[
  {
    "path": ".github/FUNDING.yml",
    "content": "# These are supported funding model platforms\n\n# github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]\n# patreon: # Replace with a single Patreon username\n# open_collective: # Replace with a single Open Collective username\n# ko_fi: # Replace with a single Ko-fi username\n# tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel\n# community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry\n# liberapay: # Replace with a single Liberapay username\n# issuehunt: # Replace with a single IssueHunt username\n# otechie: # Replace with a single Otechie username\n# custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/bug_report.yml",
    "content": "name: 🐞 Bug report\ndescription: Report an issue with naive-ui\nlabels: [untriaged]\nbody:\n  - type: markdown\n    attributes:\n      value: |\n        Thanks for taking the time to fill out this bug report!\n  - type: textarea\n    id: bug-description\n    attributes:\n      label: Describe the bug\n      description: A clear and concise description of what the bug is. If you intend to submit a PR for this issue, tell us in the description. Thanks!\n      placeholder: Bug description\n    validations:\n      required: true\n  - type: textarea\n    id: steps\n    attributes:\n      label: Steps to reproduce\n      description: Clear and concise steps to reproduce this bug.\n      placeholder: |\n        1. apply magic\n        2. wait 3.1415 seconds\n        3. 🧙🏽‍♂️\n    validations:\n      required: true\n  - type: input\n    id: reproduction\n    attributes:\n      label: Link to minimal reproduction\n      description: Please provide a  [minimal reproduction](https://stackoverflow.com/help/minimal-reproducible-example). Provide a streamlined [Playground](https://play-naive.pro-components.cn)/CodePen/CodeSandbox or GitHub repository link. Please don't fill in a link randomly.\n      placeholder: Reproduction\n    validations:\n      required: true\n  - type: textarea\n    id: system-info\n    attributes:\n      label: System Info\n      description: Output of `npx envinfo --system --npmPackages 'naive-ui,vue' --binaries --browsers`\n      render: Shell\n      placeholder: System, Binaries, Browsers\n    validations:\n      required: true\n  - type: dropdown\n    id: package-manager\n    attributes:\n      label: Used Package Manager\n      description: Select the used package manager\n      options:\n        - npm\n        - yarn\n        - pnpm\n    validations:\n      required: true\n  - type: checkboxes\n    id: checkboxes\n    attributes:\n      label: Validations\n      description: Before submitting the issue, please make sure you do the following\n      options:\n        - label: Read the [Contributing Guidelines](https://github.com/tusen-ai/naive-ui/blob/main/CONTRIBUTING.md).\n          required: true\n        - label: Read the [docs](https://www.naiveui.com/en-US/).\n          required: true\n        - label: Check that there isn't [already an issue](https://github.com/tusen-ai/naive-ui/issues) that reports the same bug to avoid creating a duplicate.\n          required: true\n        - label: Check that this is a concrete bug. For Q&A open a [GitHub Discussion](https://github.com/tusen-ai/naive-ui/discussions).\n          required: true\n        - label: The provided reproduction is a [minimal reproducible example](https://stackoverflow.com/help/minimal-reproducible-example) of the bug.\n          required: true\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/bug_report.zh-CN.yml",
    "content": "name: 🐞 错误报告\ndescription: 报告 naive-ui 的问题\nlabels: [untriaged]\nbody:\n  - type: markdown\n    attributes:\n      value: |\n        感谢您抽出时间填写此错误报告！\n  - type: textarea\n    id: bug-description\n    attributes:\n      label: 描述错误\n      description: 对错误的清晰而简明的描述。如果您打算为此问题提交 PR，请在描述中告诉我们。谢谢！\n      placeholder: 错误描述\n    validations:\n      required: true\n  - type: textarea\n    id: steps\n    attributes:\n      label: 复现步骤\n      description: 复现此错误的清晰而简明的步骤。\n      placeholder: |\n        1. 应用魔法\n        2. 等待 3.1415 秒\n        3. 🧙🏽‍♂️\n    validations:\n      required: true\n  - type: input\n    id: reproduction\n    attributes:\n      label: 最小复现链接\n      description: 请提供[最小复现](https://stackoverflow.com/help/minimal-reproducible-example)链接。提供一个简化的 [Playground](https://play.pro-components.cn)/CodePen/CodeSandbox 或 GitHub 仓库链接。请不要随机填写链接。\n      placeholder: 复现链接\n    validations:\n      required: true\n  - type: textarea\n    id: system-info\n    attributes:\n      label: 系统信息\n      description: \"`npx envinfo --system --npmPackages 'naive-ui,vue' --binaries --browsers` 命令的输出\"\n      render: Shell\n      placeholder: 系统信息，二进制文件，浏览器\n    validations:\n      required: true\n  - type: dropdown\n    id: package-manager\n    attributes:\n      label: 使用的包管理器\n      description: 选择所使用的包管理器\n      options:\n        - npm\n        - yarn\n        - pnpm\n    validations:\n      required: true\n  - type: checkboxes\n    id: checkboxes\n    attributes:\n      label: 验证\n      description: 在提交问题之前，请确保完成以下步骤\n      options:\n        - label: 阅读 [贡献指南](https://github.com/tusen-ai/naive-ui/blob/main/CONTRIBUTING.zh-CN.md)。\n          required: true\n        - label: 阅读 [文档](https://www.naiveui.com/zh-CN/)。\n          required: true\n        - label: 检查是否已经存在[相同问题的问题](https://github.com/tusen-ai/naive-ui/issues)，以避免创建重复的问题。\n          required: true\n        - label: 确保这是一个具体的 bug。有关问题和答案，请打开 [GitHub 讨论](https://github.com/tusen-ai/naive-ui/discussions)。\n          required: true\n        - label: 提供的复现是[最小可复现的示例](https://stackoverflow.com/help/minimal-reproducible-example)。\n          required: true\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/config.yml",
    "content": "blank_issues_enabled: false\ncontact_links:\n  - name: 💬 Discord Chat\n    url: https://discord.gg/Pqv7Mev5Dd\n    about: Ask questions and discuss with other Naive UI users in real time.\n  - name: ❓ Questions & Discussions\n    url: https://github.com/tusen-ai/naive-ui/discussions\n    about: Use GitHub discussions for message-board style questions and discussions.\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/feature_request.yml",
    "content": "name: 🚀 New feature request\ndescription: Propose a new feature to be added to Naive UI\nlabels: [feature request]\nbody:\n  - type: markdown\n    attributes:\n      value: |\n        Thanks for your interest in the project and taking the time to fill out this feature request!\n\n  - type: textarea\n    id: feature-description\n    attributes:\n      label: Clear and concise description of the problem\n      description: 'As a developer using Naive UI I want [goal / wish] so that [benefit]. If you intend to submit a PR for this issue, tell us in the description. Thanks!'\n    validations:\n      required: true\n  - type: textarea\n    id: suggested-solution\n    attributes:\n      label: Suggested solution\n      description: 'In module [xy] we could provide following implementation...'\n    validations:\n      required: true\n  - type: textarea\n    id: alternative\n    attributes:\n      label: Alternative\n      description: Clear and concise description of any alternative solutions or features you've considered.\n  - type: textarea\n    id: additional-context\n    attributes:\n      label: Additional context\n      description: Any other context or screenshots about the feature request here.\n  - type: checkboxes\n    id: checkboxes\n    attributes:\n      label: Validations\n      description: Before submitting the issue, please make sure you do the following\n      options:\n        - label: Read the [Contributing Guidelines](https://github.com/tusen-ai/naive-ui/blob/main/CONTRIBUTING.md).\n          required: true\n        - label: Read the [docs](https://www.naiveui.com/en-US).\n          required: true\n        - label: Check that there isn't already an issue that request the same feature to avoid creating a duplicate.\n          required: true\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/feature_request.zh-CN.yml",
    "content": "name: 🚀 新功能请求\ndescription: 提议将新功能添加到 Naive UI\nlabels: [feature request]\nbody:\n  - type: markdown\n    attributes:\n      value: |\n        感谢您对该项目的关注，并抽出时间填写此功能请求！\n\n  - type: textarea\n    id: feature-description\n    attributes:\n      label: 问题的清晰而简明的描述\n      description: '作为使用 Naive UI 的开发者，我希望 [目标/愿望]，以便 [好处]。如果您打算为此问题提交 PR，请在描述中告诉我们。谢谢！'\n    validations:\n      required: true\n  - type: textarea\n    id: suggested-solution\n    attributes:\n      label: 建议的解决方案\n      description: '在模块 [xy] 中，我们可以提供以下实现...'\n    validations:\n      required: true\n  - type: textarea\n    id: alternative\n    attributes:\n      label: 备选方案\n      description: 对您考虑过的任何备选解决方案或功能的清晰而简明的描述。\n  - type: textarea\n    id: additional-context\n    attributes:\n      label: 附加上下文\n      description: 在这里提供有关功能请求的任何其他上下文或截图。\n  - type: checkboxes\n    id: checkboxes\n    attributes:\n      label: 验证\n      description: 在提交问题之前，请确保完成以下步骤\n      options:\n        - label: 阅读 [贡献指南](https://github.com/tusen-ai/naive-ui/blob/main/CONTRIBUTING.md)。\n          required: true\n        - label: 阅读 [文档](https://www.naiveui.com/en-US)。\n          required: true\n        - label: 检查是否已经存在请求相同功能的问题，以避免创建重复的问题。\n          required: true\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 all configuration options:\n# https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates\n\nversion: 2\nupdates:\n  - package-ecosystem: npm # See documentation for possible values\n    directory: \"/\" # Location of package manifests\n    schedule:\n      interval: \"daily\"\n"
  },
  {
    "path": ".github/pull_request_template.md",
    "content": "<!--\n!!! Please read the following content if this is your first pull request !!!\n\n1. If you are working on docs, please set `docs` branch as the target branch.\n2. If you are working on bug fixes or new features, please set `main` branch as the target branch.\n\nFor people who are working on 2, please add changelog to `CHANGELOG.zh-CN.md` & `CHANGELOG.en-US.md` in the PR. You need to add changelog to both files. You can use English in both file. The develop team will translate it later.\n\nAbout docs & changelog's format and other tips, see in `CONTRIBUTING.md`.\n-->\n<!--\n!!! 如果这是你第一次提交 PR，请阅读下面的内容 !!!\n\n1. 如果你在修改文档，请提交到 `docs` 分支\n2. 如果你在修复 Bug 或者开发新的特性，请提交到 `main` 分支\n\n对于进行工作 2 的人，请在 `CHANGELOG.zh-CN.md` & `CHANGELOG.en-US.md` 中添加变更日志，你需要在两个文件中都添加变更日志。你可以只使用中文，开发团队会在之后进行翻译。\n\n关于文档和变更日志的格式以及其他的帮助信息，请参考 `CONTRIBUTING.md`。\n-->\n"
  },
  {
    "path": ".github/workflows/node.js.yml",
    "content": "# This workflow will do a clean install of node dependencies, build the source code and run tests across different versions of node\n# For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions\n\nname: Node.js CI\n\non:\n  push:\n    branches: [main, feat, docs]\n  pull_request:\n    branches: [main, feat, docs]\n\njobs:\n  lint:\n    environment: test\n\n    runs-on: ubuntu-latest\n\n    strategy:\n      matrix:\n        node-version: [22]\n        # See supported Node.js release schedule at https://nodejs.org/en/about/releases/\n    steps:\n      - uses: actions/checkout@v3\n\n      - name: Install pnpm\n        run: corepack enable\n\n      - name: Use Node.js ${{ matrix.node-version }}\n        uses: actions/setup-node@v3\n        with:\n          node-version: ${{ matrix.node-version }}\n\n      - run: pnpm install\n\n      - name: Lint\n        run: pnpm run lint\n\n  test:\n    environment: test\n\n    runs-on: ubuntu-latest\n\n    strategy:\n      matrix:\n        node-version: [22]\n    steps:\n      - uses: actions/checkout@v3\n\n      - name: Install pnpm\n        run: corepack enable\n\n      - name: Use Node.js ${{ matrix.node-version }}\n        uses: actions/setup-node@v3\n        with:\n          node-version: ${{ matrix.node-version }}\n\n      - name: Setup timezone\n        uses: szenius/set-timezone@v2.0\n        with:\n          timezoneLinux: Asia/Shanghai\n          timezoneMacos: Asia/Shanghai\n          timezoneWindows: Asia/Shanghai\n\n      - run: pnpm install\n\n      - name: Test\n        run: pnpm run test:cov\n\n      - name: Code coverage\n        uses: codecov/codecov-action@v3\n        with:\n          token: ${{ secrets.CODECOV_TOKEN }}\n          files: coverage/lcov.info\n"
  },
  {
    "path": ".github/workflows/publish-to-pkg.pr.new.yml",
    "content": "name: Publish to pkg.pr.new\non:\n  push:\n    branches: [main]\n  pull_request:\n    types: [labeled]\n\n# Cancel all previous workflows on main.\nconcurrency:\n  group: ${{ github.workflow }}-${{ github.ref }}\n  cancel-in-progress: ${{ github.event_name == 'push' && github.ref == 'refs/heads/main' }}\n\njobs:\n  publish:\n    runs-on: ubuntu-latest\n    if: github.event_name == 'push' || (github.event_name == 'pull_request' && contains(github.event.label.name, 'preview'))\n    steps:\n      - name: Checkout code\n        uses: actions/checkout@v4\n\n      - run: corepack enable\n      - uses: actions/setup-node@v4\n        with:\n          node-version: 22\n          cache: \"pnpm\"\n          cache-dependency-path: \"package.json\"\n\n      - name: Install dependencies\n        run: pnpm install\n\n      - name: Build\n        run: pnpm build:package\n\n      - name: Publish preview\n        run: pnpx pkg-pr-new publish --compact"
  },
  {
    "path": ".gitignore",
    "content": "node_modules\ndist\ndocDist\nbuild-doc/deploy-doc.sh\nbuild-doc/dist\ntest-size\ntest-bundle\ntest/unit/coverage\npackage-lock.json\nplayground/temp\nyarn.lock\n.DS_Store\n.vscode\n.idea\n.pulsar\n*.swp\n*.tgz\ncoverage\n/fonts\n/site\n/package\nlib\nes\n*.tsbuildinfo\npnpm-lock.yaml\nweb-types.json\n~*\n.pnpm-debug.log\n.history\n"
  },
  {
    "path": ".husky/pre-commit",
    "content": "pnpm exec lint-staged\n"
  },
  {
    "path": ".npmrc",
    "content": "shell-emulator=true"
  },
  {
    "path": ".nvmrc",
    "content": "22\n"
  },
  {
    "path": ".pnpmfile.cjs",
    "content": "// We will lock vue version if there's regression\nconst lockVueVersion = false\n\nconst vueVersion = '3.2.36'\n\nconst isSameVersionVuePackage = (pkgName) =>\n  [\n    'vue',\n    '@vue/shared',\n    '@vue/compiler-sfc',\n    '@vue/server-renderer',\n    '@vue/reactivity',\n    '@vue/reactivity-transform',\n    '@vue/compiler-dom',\n    '@vue/compiler-ssr',\n    '@vue/compiler-core'\n  ].some((name) => name === pkgName)\n\nfunction readPackage(pkg) {\n  if (isSameVersionVuePackage(pkg.name)) {\n    pkg.version = vueVersion\n  }\n\n  ;['dependencies', 'peerDependencies'].forEach((depsType) => {\n    const deps = { ...pkg[depsType] }\n    for (dep in pkg[depsType]) {\n      if (isSameVersionVuePackage(dep)) {\n        deps[dep] = vueVersion\n      }\n    }\n    pkg[depsType] = deps\n  })\n\n  return pkg\n}\n\nmodule.exports = lockVueVersion\n  ? {\n      hooks: {\n        readPackage\n      }\n    }\n  : {}\n"
  },
  {
    "path": ".prettierignore",
    "content": "*.cssr.js\n*.cssr.ts\n"
  },
  {
    "path": ".prettierrc",
    "content": "{\n  \"semi\": false,\n  \"singleQuote\": true,\n  \"printWidth\": 80,\n  \"trailingComma\": \"none\",\n  \"proseWrap\": \"never\"\n}\n"
  },
  {
    "path": "CHANGELOG.en-US.md",
    "content": "# CHANGELOG\n\n## NEXT_VERSION\n\n### Fixes\n\n- Fix `n-color-picker` passed `style` and `click` (onClick) not applied to trigger, closes [#7528](https://github.com/tusen-ai/naive-ui/issues/7528).\n\n## 2.44.1\n\n`2026-03-08`\n\n### Feats\n\n- `n-config-provider` adds per-component `size` options in `component-options` (`AutoComplete`, `Cascader`, `ColorPicker`, `DatePicker`, `InputNumber`, `InputOtp`, `Mention`, `Select`, `TimePicker`, `Transfer`, `TreeSelect`).\n\n### Fixes\n\n- `n-config-provider` fixes `size` prop doesn't work for some components.\n\n## 2.44.0\n\n`2026-03-08`\n\n### Breaking Changes\n\n- `n-color-picker` refactor DOM structure & trigger class names.\n- `n-card`'s `n-card__content` class name is renamed to `n-card-content`.\n- `n-select` will clear options created by `tag` prop by default when clear button is clicked.\n\n### Feats\n\n- `n-color-picker` adds `trigger` slot, closes [#7192](https://github.com/tusen-ai/naive-ui/issues/7192).\n- `n-select` adds `clear-created-options-on-clear` prop to control whether created options are cleared when clearing while `tag` and clearable are enabled.\n- `n-select`, `n-auto-complete`, `n-mention`, `n-popselect`, `n-cascader`, `n-pagination` add `scrollbar-props` prop.\n- `n-config-provider` adds component-level `renderEmpty` options (`Cascader`, `DataTable`, `Select`, `Transfer`, `Tree`, `TreeSelect`).\n- `n-config-provider` adds per-component `size` options in `component-options` (`Button`, `Card`, `Checkbox`, `DataTable`, `Descriptions`, `Dropdown`, `DynamicTags`, `Form`, `Input`, `Pagination`, `Popselect`, `Radio`, `Rate`, `Result`, `Skeleton`, `Space`, `Switch`, `Table`, `Tabs`, `Tag`), closes [#356](https://github.com/tusen-ai/naive-ui/issues/356).\n- `n-upload`'s `submit` method adds `retry` option.\n- `n-breadcrumb-item` adds `show-separator` prop for controlling separator visibility when used with `transition-group`, closes [#3614](https://github.com/tusen-ai/naive-ui/issues/3614).\n- `n-card` adds `content-scrollable` prop, closes [#4848](https://github.com/tusen-ai/naive-ui/issues/4848), [#6759](https://github.com/tusen-ai/naive-ui/pull/6759).\n- `n-date-picker` adds `fast-year-select` prop.\n- `n-date-picker` adds `fast-month-select` prop.\n- `n-button` adds `spin-props` prop.\n- `n-cascader` adds `spin-props` prop.\n- `n-log` adds `spin-props` prop.\n- `n-message` adds `spin-props` prop.\n- `n-switch` adds `spin-props` prop.\n- `n-tree` adds `spin-props` prop.\n- `n-spin` adds `radius` and `scale` props.\n- `n-tree-select` adds `show-line` prop.\n\n### Fixes\n\n- Fix `katex` type compatibility by upgrading to `0.16.28` and removing `@types/katex` dependency, closes [#7423](https://github.com/tusen-ai/naive-ui/issues/7423).\n- Fix `n-select`'s created option is not cleared when clearing dynamic options while `tag` and `clearable` are enabled, closes [#7405](https://github.com/tusen-ai/naive-ui/issues/7405).\n- Fix `n-modal` event listeners not removed, closes [#7341](https://github.com/tusen-ai/naive-ui/issues/7341) by [@lu-han](https://github.com/lu-han).\n- Fix `n-marquee` component Non-function value encountered for default slot warning.\n- Fix `n-data-table`'s empty slot is not shown in a `display: flex` container.\n- Fix `n-data-table` missing header scrollbar in `n-data-table` when in empty state with `max-height` or `flex-height`, closes [#7479](https://github.com/tusen-ai/naive-ui/pull/7479).\n- Fix `n-input`, `n-select`, `n-date-picker`, `n-auto-complete`, `n-cascader`, `n-color-picker`, `n-input-number`, `n-input-otp`, `n-mention`, `n-time-picker`, `n-transfer`, `n-tree-select` not reading global `size` config from `n-config-provider`.\n- Fix `n-data-table` and `n-tag` `size` prop default value preventing global config from taking effect.\n\n## 2.43.2\n\n`2025-11-16`\n\n### Fixes\n\n- Fix seemly dependency version range allows incompatible versions.\n- Fix `n-progress` style is incorrect after using the dashboard mode exceeding 100%, closes [#6627](https://github.com/tusen-ai/naive-ui/issues/6627).\n- Fix `n-modal`'s outside content can't be interacted with when `show-mask` is set to `false`.\n\n### Feats\n\n- `n-date-picker` prop `defaultTime` can also accept a function that will return a formatted string.\n- `n-steps` adds `content-placement` prop, closes [#7044](https://github.com/tusen-ai/naive-ui/issues/7044).\n\n## 2.43.1\n\n`2025-09-14`\n\n### Fixes\n\n- Fix esm format files are importing `lodash` rather than `lodash-es`.\n\n## 2.43.0\n\n`2025-09-13`\n\n### Breaking Changes\n\n- Modal's inner close button won't be focusable using keyboard and it'll no longer be focused first by default.\n\n### i18n\n\n- Add daDK locale.\n\n### Fixes\n\n- Fix `n-color-picker` black and white effect of text is not obvious, closes [#7074](https://github.com/tusen-ai/naive-ui/issues/7074).\n- Fix `n-image` zoom in & out locale text in `da-DK` `sv-SE`.\n- Fix `n-popover`'s `themeOverrides` property does not have the `Scrollbar` style configuration.\n- Fix `n-input`'s `themeOverrides` property does not have the `Scrollbar` style configuration.\n- Fix `n-anchor` can't activate link in the bottom of the page by click, closes [#7033](https://github.com/tusen-ai/naive-ui/issues/7033), closes [#6918](https://github.com/tusen-ai/naive-ui/issues/6918), [#6844](https://github.com/tusen-ai/naive-ui/issues/6844), [#6782](https://github.com/tusen-ai/naive-ui/issues/6782).\n- Fix `n-upload` component `'Non-function value encountered for default slot'` warning.\n- Fix `n-input`'s `tabindex` property setting of `input-props` does not take effect.\n- Fix `n-tab` scroll shadow pseudo-class style conflicts in multi-layer tab nesting scenarios, closes [#6854](https://github.com/tusen-ai/naive-ui/issues/6854).\n- Fix `n-menu`'s disabled style not working when parent node is set to `disabled` and child node has `type: \"group\"`, closes [#6792](https://github.com/tusen-ai/naive-ui/issues/6792).\n- Fix `n-input-group-label` not injecting `formItemInjectionKey`, causing the `size` property to fail, and close [#7066](https://github.com/tusen-ai/naive-ui/issues/7066).\n- Fix the issue of style confusion in `n-carousel` when there is only one image, close [#6476](https://github.com/tusen-ai/naive-ui/issues/6476).\n- Fix `n-marquee` component 'Non-function value encountered for default slot' warning.\n- Fix memory leak caused by `n-upload` icon.\n\n### Features\n\n- `n-data-table`'s column adds `customNextSortOrder` attribute, closes [#6850](https://github.com/tusen-ai/naive-ui/issues/6850).\n- Add `n-avatar-group`'s corresponding generic component `NGAvatarGroup`, closes [#6909](https://github.com/tusen-ai/naive-ui/issues/6909).\n- `n-avatar-group` adds `size` prop.\n- `n-popover` supports RTL.\n- `n-tooltip` supports RTL.\n- `n-upload` supports RTL.\n- `n-tree-select` supports RTL.\n- `useDialog`'s option supports `z-index`, closes [#4349](https://github.com/tusen-ai/naive-ui/issues/4349).\n- Add `n-heatmap` component.\n- - `n-image` adds showPreview methods, closes [#6695](https://github.com/tusen-ai/naive-ui/issues/6695).\n- Add `n-image-preview` component.\n- `n-image-group` can be used without `n-image`.\n- `n-input-otp` adds `focusOnChar` util method, closes [#7073](https://github.com/tusen-ai/naive-ui/issues/7073).\n- `n-form-item` adds `content-class`、`content-style` props.\n- `n-message` adds `border` theme variable, closes [#7105](https://github.com/tusen-ai/naive-ui/issues/7105).\n- `n-modal` adds `show-mask` prop.\n- `useModal` add `render` function, closes [#5857](https://github.com/tusen-ai/naive-ui/issues/5857).\n- `n-card` add `close-focusable` prop.\n- `n-dialog` add `close-focusable` prop.\n- `n-form-item` adds `invalidateLabelWidth` method，`n-form` adds `invalidateLabelWidths` method，closes [#5939](https://github.com/tusen-ai/naive-ui/issues/5939).\n\n## 2.42.0\n\n`2025-06-17`\n\n### Breaking Changes\n\n- Fix `n-date-picker`'s `time-picker-format` prop doesn't work, the prop is misspelled as `timer-picker-format` before, closes [#6820](https://github.com/tusen-ai/naive-ui/issues/6820).\n\n### Fixes\n\n- Fix `n-input-otp` event bindings not removed when elements are disabled (disabled/readonly), fix width style specificity conflict.\n- Fix `n-date-picker`'s `shortcuts`' time value will be overrided if `default-time` is set in with `type=\"datetimerange\"`, closes [#6902](https://github.com/tusen-ai/naive-ui/pull/6902), [#6901](https://github.com/tusen-ai/naive-ui/pull/6901).\n- Fix `n-radio`, `n-radio-button` can't use `n-popover` inside, closes [#6837](https://github.com/tusen-ai/naive-ui/pull/6837), [#6832](https://github.com/tusen-ai/naive-ui/pull/6832).\n- Fix scrolling performance issue caused by too many layers, closes [#6887](https://github.com/tusen-ai/naive-ui/issues/6887).\n\n### Features\n\n- `n-anchor-link` adds `title` slot, closes [#6845](https://github.com/tusen-ai/naive-ui/issues/6845).\n\n## 2.41.1\n\n`2025-06-08`\n\n### Fixes\n\n- Fix `n-tabs`'s type exception of the tab slots in TabPane.\n- Fix `n-data-table` missing css variable of sorting cells, closes [#6521](https://github.com/tusen-ai/naive-ui/issues/6521).\n\n### Features\n\n- 🌟 Adds `n-input-otp` component, closes [#1385](https://github.com/tusen-ai/naive-ui/issues/1385), [#5681](https://github.com/tusen-ai/naive-ui/issues/5681), [#6222](https://github.com/tusen-ai/naive-ui/issues/6222).\n- `n-upload` adds `custom-download`, closes [#5946](https://github.com/tusen-ai/naive-ui/issues/5946), [#6800](https://github.com/tusen-ai/naive-ui/issues/6800).\n- `n-upload` adds `uploadDownload` util method.\n- `n-tree-select` adds `indent` prop.\n\n## 2.41.0\n\n`2025-01-05`\n\n### Breaking Changes\n\n- (**Vue 3.3+ required**) Add slot type for all components.\n\n### i18n\n\n- Add kmKH locale.\n- Add ugCN locale.\n\n### Features\n\n- `n-modal` adds `draggable` prop, closes [#6525](https://github.com/tusen-ai/naive-ui/issues/6525), [#5792](https://github.com/tusen-ai/naive-ui/issues/5792), [#5711](https://github.com/tusen-ai/naive-ui/issues/5711), [#5501](https://github.com/tusen-ai/naive-ui/issues/5501) and [#2152](https://github.com/tusen-ai/naive-ui/issues/2152).\n- `useDialog` supports `draggable` option.\n- `useModal` supports `draggable` option.\n\n### Fixes\n\n- Fix `n-data-table` may have multiple expand trigger with tree data.\n- Fix `n-date-picker`'s `confirm`, `now`, `clear` slots doesn't work with `'month'`, `'monthrange'`, `'quarter'`, `'quarterrange'`, `'year'` and `'yearrange'` type.\n- Fix `n-input`'s `render-count` prop doesn't work when type is not `'textarea'`.\n\n## 2.40.4\n\n`2024-12-20`\n\n### Fixes\n\n- Fix `inset` CSS property caused compatibility issues in some browsers, closes [#6604](https://github.com/tusen-ai/naive-ui/issues/6604)，close [#6602](https://github.com/tusen-ai/naive-ui/issues/6602).\n- Fix memory leak problem when used with new version of vue. Note: After the fix you may still find memory leak in Chrome >= 129, since they introduced a bug, see https://github.com/vuejs/core/issues/12306, https://issues.chromium.org/issues/376777343.\n\n## 2.40.3\n\n`2024-12-02`\n\n- Fix marquee is not exported with correct name.\n\n## 2.40.2\n\n`2024-11-26`\n\n### Fixes\n\n- Fix `n-time-picker`'s `use-12-hours` type error warning, closes [#4308](https://github.com/tusen-ai/naive-ui/issues/4308).\n- Fix `input-number` the problem that the negative sign is replaced when the negative sign is entered.\n- Fix `n-data-table`'s header will show scrollbar in some old browsers, closes [#6557](https://github.com/tusen-ai/naive-ui/issues/6557).\n\n### Features\n\n- 🌟 Adds `n-marquee` component.\n- `n-image` adds `error` slot, closes [#5649](https://github.com/tusen-ai/naive-ui/issues/5649).\n- `n-date-picker` adds `date-format` prop.\n- `n-date-picker` adds `calendar-day-format` prop.\n- `n-date-picker` adds `calendar-header-year-format` prop.\n- `n-date-picker` adds `calendar-header-month-format` prop.\n- `n-date-picker` adds `calendar-header-month-before-year` prop.\n- `n-date-picker` adds `calendar-header-month-year-separator` prop.\n- `n-progress`'s `color` prop supports gradient config.\n- `n-select` adds `font-weight` theme variable.\n- `n-input` adds `font-weight` theme variable.\n- `n-data-table` adds `get-csv-header` and `get-csv-cell` props, closes [#6542](https://github.com/tusen-ai/naive-ui/issues/6542).\n\n## 2.40.1\n\n`2024-09-26`\n\n### Fixes\n\n- Fix `n-data-table` in virtual-x mode, when all column objects do not have the `fixed` attribute configured, it cannot be displayed normally.\n- Fix `css-render` dependency version is not high enough to affect the `style-mount-target` attribute of `n-config-provider`.\n- Fix `n-data-table`'s `rowProps` generated `class` will override the original row DOM's class.\n\n## 2.40.0\n\n`2024-09-26`\n\n### Breaking Changes\n\n- Fix `n-config-provider` doesn't inherit the class prefix from it's ascendant `n-config-provider`, closes [#5970](https://github.com/tusen-ai/naive-ui/issues/5970).\n- Fix `n-date-picker`'s `weekFormat` uses different standards for year and week formatting. Now it uses local week and local year for year and week formatting.\n- Dependency `date-fns` is upgraded to V3.\n- `n-cascader`'s `filter` prop is now case insensitive.\n\n### Fixes\n\n- Fix `n-infinite-scroll` reaching bottom check is not correct, closes [#6133](https://github.com/tusen-ai/naive-ui/issues/6133).\n- Fix `n-slider`'s rail may have styling issue in `vertical` mode when global CSS box-sizing is overrided, closes [#6114](https://github.com/tusen-ai/naive-ui/issues/6114).\n- Fix `n-tabs` has style issue when using `prefix` slot, `suffix` slot or `addable` prop with vertical placement, closes [#6059](https://github.com/tusen-ai/naive-ui/issues/6059), [#6060](https://github.com/tusen-ai/naive-ui/pull/6060).\n- Fix `n-upload` can only upload a maximum of 100 files in some old browsers when uploading directories, closes [#6027](https://github.com/tusen-ai/naive-ui/issues/6027).\n- Fix `n-date-picker`'s `input-readonly` prop not working in the panel's inner input for `'datetime'` or `'datetimerange'`.\n- Fix `n-menu` can't apply HTML attributes correctly on the component when `responsive` is set.\n- Fix `n-float-button` throws error when used with `popover` component, closes [#5933](https://github.com/tusen-ai/naive-ui/issues/5933).\n- Fix `n-badge` can't mask focus element's border, closes [#5929](https://github.com/tusen-ai/naive-ui/issues/5929).\n- Fix `n-button` font-weight CSS variable's name is not correct, closes [#5922](https://github.com/tusen-ai/naive-ui/issues/5922).\n- Fix `n-icon`'s `component` prop doesn't accept functional component.\n- Fix `n-mention`'s panel is misplaced if `placement` is set to `'top'` or padding is set in component's style, closes [#6241](https://github.com/tusen-ai/naive-ui/issues/6241).\n- Fix `n-carousel`'s transition doesn't work as expected, closes [#5993](https://github.com/tusen-ai/naive-ui/issues/5993).\n\n### Features\n\n- 🌟 `n-data-table` adds `virtual-scroll-x`, `virtual-scroll-header`, `height-for-row`, `header-height` and `min-row-height` props for supporting horizontal virtual scrolling when there are massive columns.\n- 🌟 Adds `n-highlight` component.\n- `n-scrollbar` adds `x-placement` and `y-placement` props, closes [#6089](https://github.com/tusen-ai/naive-ui/issues/6089).\n- `n-date-picker` adds `clear`, `now` and `confirm` slots, closes [#6013](https://github.com/tusen-ai/naive-ui/issues/6013).\n- `n-upload` adds `on-retry` prop, closes [#6031](https://github.com/tusen-ai/naive-ui/issues/6031).\n- `n-slider`'s `marks` prop supports render function, closes [#5967](https://github.com/tusen-ai/naive-ui/issues/5967).\n- `n-transfer`'s `source-title` and `target-title` props support render function, closes [#6004](https://github.com/tusen-ai/naive-ui/issues/6004).\n- `n-data-table` add `rowData` params for `render-expand-icon` prop, closes [#6108](https://github.com/tusen-ai/naive-ui/issues/6108).\n- `n-empty`'s `size` prop supports `'tiny'` size.\n- `n-config-provider` adds `style-mount-target` prop to control where to mount components' style.\n- `n-data-table` adds `allowExport` prop for column object.\n- `n-date-picker` adds `year-range` prop.\n- `n-tree-select` adds `header` slot, closes [#5915](https://github.com/tusen-ai/naive-ui/issues/5915).\n- `n-select` adds `menu-size` prop.\n\n## 2.39.0\n\n`2024-07-15`\n\n### Breaking Changes\n\n- Fix `n-input-number` Exception when the value is a string in precision mode, closes [#6091](https://github.com/tusen-ai/naive-ui/issues/6091).\n\n### Fixes\n\n- Fix `n-form-item` validation state is not correctly updated [#6068](https://github.com/tusen-ai/naive-ui/issues/6068).\n- Fix `n-select`'s header make inner input unavailable, closes [#6030](https://github.com/tusen-ai/naive-ui/issues/6030).\n- Fix `n-tree` may have incorrect node selection status when `show-irrelevant-nodes` is disabled, close [#6115](https://github.com/tusen-ai/naive-ui/issues/6115).\n\n### Features\n\n- `n-data-table` adds `filter-icon-popover-props` prop, closes [#6111](https://github.com/tusen-ai/naive-ui/issues/6111).\n- `n-input-number` adds `round` prop, closes [#6097](https://github.com/tusen-ai/naive-ui/issues/6097).\n- `n-color-picker` add `on-clear` props.\n- `n-upload`'s `on-preview` prop adds `detail.event` parameter. You can use `preventDefault` to prevent default anchor link open behavior. Closes [#6036](https://github.com/tusen-ai/naive-ui/issues/6036).\n- `n-data-table` adds `thColorSorting`, `thColorSortingModal`, `thColorSortingPopover`, `tdColorSorting`, `tdColorSortingModal` and `tdColorSortingPopover` theme variables, closes [#6118](https://github.com/tusen-ai/naive-ui/issues/6118), [#6120](https://github.com/tusen-ai/naive-ui/issues/6120).\n\n### i18n\n\n- Add azAZ locale.\n- Add uzUZ locale.\n\n## 2.38.2\n\n`2024-05-03`\n\n### Fixes\n\n- Fix `n-menu` Submenu's wai-aria role is not correct, closes [#5729](https://github.com/tusen-ai/naive-ui/issues/5729).\n- Fix `n-tabs` style bug with type is `segment`，closes [#5728](https://github.com/tusen-ai/naive-ui/issues/5728).\n- Fix the get\\*String() methods for UTC/locale mismatch, closes [#5702](https://github.com/tusen-ai/naive-ui/issues/5702).\n- Fix `n-dialog` / `n-modal` calling `destroy` method may throw error.\n- Fix `useModal` setting `card` preset without corresponding props in `n-card` slots, closes [#5746](https://github.com/tusen-ai/naive-ui/issues/5746).\n- Fix `Submenu` component's wai-aria role setting error of `n-menu`，closes [#5729](https://github.com/tusen-ai/naive-ui/issues/5729).\n- Fix the `common` type error in the `theme-overrides` prop when modifying components' themes.\n- Fix `n-split` may emit value less than `0`.\n\n### Features\n\n- `n-watermark` support multi-lines in content.\n- Adds `n-infinite-scroll` component.\n- `n-watermark` adds `text-align` prop.\n- `n-qr-code` adds `type` prop, Customize rendering output by setting `type`, providing two options: `canvas` and `svg`.\n- `n-card` adds `action`, `content`, `cover`, `footer` and `header-extra` props.\n- `n-card`'s `title` prop supports render function.\n- `n-upload` expose the `index` arg in `on-remove` function, closes [#5747](https://github.com/tusen-ai/naive-ui/issues/5747).\n- `n-upload` exports `UploadOnDownload`, `UploadOnRemove`, `UploadOnFinish` and `UploadOnChange` types.\n- `n-dialog` adds `action-class`, `action-style`, `content-class`, `content-style`, `title-class` and `title-style` props.\n- `n-split` adds `pane1-class`, `pane1-style`, `pane2-class` and `pane2-style` props.\n- `n-mention` adds `filter` method, closes [#5721](https://github.com/tusen-ai/naive-ui/pull/5721).\n- `n-slider` adds wai-aria support.\n- `n-date-picker` adds `time-picker-format` prop.\n- `n-form-item` adds `feedback-class` and `feedback-style` props.\n- `n-split` supports using pixel unit string as `value`.\n- `n-scrollbar` adds `content-style` and `content-class` props, closes [#4497](https://github.com/tusen-ai/naive-ui/issues/4497).\n- `n-image` adds `render-toolbar` prop.\n- `n-cascader` adds `get-column-style` prop.\n- `n-cascader` adds `get-render-prefix` prop.\n- `n-cascader` adds `get-render-suffix` prop.\n- `n-image` optimizes download icon style.\n- `n-scrollbar` adds `height`, `width`, `radius`, `railInsetHorizontal`, `railInsetVertical` and `railColor` theme variables.\n\n### i18n\n\n- Add csCZ locale.\n- Add missing itIT locale translations.\n\n## 2.38.1\n\n`2024-02-26`\n\n### Fixes\n\n- Fix `n-split`'s `min` attribute does not take effect.\n- Fix `n-result` built-in icons not re-rendered after hydration.\n- Fix `n-tabs` whose `type` is `'segment'` has capsule with wrong width and position after resize, closes [#5705](https://github.com/tusen-ai/naive-ui/issues/5705).\n- Fix `n-tabs`'s capsule wrong width and position after resize within `n-modal`, closes [#5569](https://github.com/tusen-ai/naive-ui/issues/5569).\n- Fix `n-split` doesn't work with `inline-theme-disabled` prop.\n- Fix `n-float-button` doesn't work with `inline-theme-disabled` prop.\n\n### Features\n\n- `n-date-picker` adds `default-calendar-start-time` props when `type` is `'date'`/`'datetime'` or `'week'`, closes [#4493](https://github.com/tusen-ai/naive-ui/issues/4493).\n- `n-tree-select` adds `get-children` prop.\n\n## 2.38.0\n\n`2024-02-22`\n\n### Breaking Changes\n\n- Fix `n-scrollbar`'s `scrollTo(x: number, y: number)` error where the order of method parameters does not match the document.\n\n### Fixes\n\n- Fix `n-tree`'s `override-default-node-click-behavior` prop may conflict with default switcher click or checkbox click behavior.\n- Fix `n-scrollbar`'s typo on `aria-hidden` attribute.\n- Fix `n-form-item`'s feedback may hide and show again, closes [#5583](https://github.com/tusen-ai/naive-ui/issues/5583).\n- Fix `n-popselect`'s header make inner input unavailable, closes [#5494](https://github.com/tusen-ai/naive-ui/pull/5494).\n- Fix `n-qr-code`'s style of size.\n- Fix `n-badge` affects child elements' text color.\n\n### Features\n\n- 🌟 Adds `n-modal-provider` component and `useModal` method.\n- 🌟 Adds `n-float-button` and `n-float-button-group` component.\n- 🌟 Provides ES module bundle at `/dist/index.mjs` and `/dist/index.prod.mjs`.\n- `n-auto-complete` adds `append` prop.\n- `n-select` add native `title` attribute when `filterable` and blur input.\n- `n-split` adds `size` prop and `on-update:size` prop.\n- `n-split` adds `watch-props` prop, closes [#5526](https://github.com/tusen-ai/naive-ui/issues/5526).\n- `n-drawer` adds `borderRadius` theme variable.\n- adds `n-float-button` component.\n- Provides ES module bundle.\n\n### i18n\n\n- Add `etEE` locale.\n\n## 2.37.3\n\n`2024-01-09`\n\n### Fixes\n\n- Fix `n-split` has no color if it's not used in a card.\n\n## 2.37.2\n\n`2024-01-09`\n\n### Fixes\n\n- `n-data-table`'s `downloadCsv` method will export selection & expand column.\n\n## 2.37.1\n\n`2024-01-08`\n\n### Fixes\n\n- Click clear button on components with popup may trigger reopen behaviors.\n- Fix `n-form`'s `validate` returned `Promise` may not `resolve`.\n\n### Features\n\n- `n-collapse` adds `trigger-areas` prop.\n- `n-date-picker`'s `is-date-disabled` callback prop supports get detail info of date/year/month/quarter button as parameter, closes [#4649](https://github.com/tusen-ai/naive-ui/issues/4649).\n- `n-auto-complete` adds `empty` slot.\n- `n-auto-complete` adds `show-empty` prop.\n\n## 2.37.0\n\n`2024-01-07`\n\n### Breaking Changes\n\n- `module` prop in `package.json` is changed from `es/index.js` to `es/index.mjs`.\n\n### Fixes\n\n- Fix `n-space` vnode reuse problem caused by filtering out comment nodes of slot, closes [#5136](https://github.com/tusen-ai/naive-ui/issues/5136).\n- Fix `n-data-table`'s prop `pagination`'s `default-page-size` and `default-page` not work in uncontrolled mode, closes [#5201](https://github.com/tusen-ai/naive-ui/issues/5201).\n- Fix `n-time-picker` formatting (format=\"HH: mm: ss. SSS\") preventing modification of milliseconds in the edit box, closes [#5224](https://github.com/tusen-ai/naive-ui/issues/5224).\n- Fix `n-notification` notification clips out of screen when screen width is less than 400px wide.\n- Fix `n-carousel` transition effect incorrect when using the `slide` effect in loop mode with only two elements, closes [#4323](https://github.com/tusen-ai/naive-ui/issues/4323).\n- Fix `n-carousel` trigger incorrect `current-index` value on arrow button click with single image, closes [#5130](https://github.com/tusen-ai/naive-ui/issues/5130).\n- Fix `n-upload-trigger` in directory drag mode with a lot of files, some of the files are not read.\n- Fix `n-dynamic-tags`'s abnormal behavior when using keyboard to trigger add button, closes [#5077](https://github.com/tusen-ai/naive-ui/issues/5077).\n- Fix `n-tree` leaf node line color.\n- Fix `n-collapse-item` cursor pointer to correct element, closes [#5482](https://github.com/tusen-ai/naive-ui/issues/5482).\n- Fix `n-data-table` throws error if summary config has empty column.\n- Fix `n-drawer`'s `on-mask-click` may be called multiple times.\n- Fix `n-tree`'s `data` When the data source 'data' switches several times according to a certain scene, some logic of animation processing can cause errors in rendering the displayed data, closes [#5217](https://github.com/tusen-ai/naive-ui/issues/5217).\n- Fix `n-radio` value's native input element's checked value is not updated, closes [#5184](https://github.com/tusen-ai/naive-ui/issues/5184).\n- Fix `n-data-table` height incorrect when set `min-height` in empty state，closes [#5108](https://github.com/tusen-ai/naive-ui/issues/5108).\n- Fix `n-tabs`'s bar not hidden when `value` is set manually to the value other than the children `n-tab`s, closes [#5100](https://github.com/tusen-ai/naive-ui/issues/5100).\n- Fix `n-spin` abnormal animation, closes [#3556](https://github.com/tusen-ai/naive-ui/issues/3556).\n- Fix `n-avatar`'s lazy loading and `fallback-src` prop not working when load error in lazy, closes [#5007](https://github.com/tusen-ai/naive-ui/issues/5007).\n- <del>Fix `n-split` has no color if it's not used in a card.</del>\n- Fix `n-card` `footer-class` prop not working.\n- Fix `n-input` click clear icon to trigger twice when using the `clearable`, closes [#5510](https://github.com/tusen-ai/naive-ui/issues/5510).\n- Fix `n-tabs` may miss over-scroll shadow if `placement` is `'left'` or `'right'`.\n- Fix `n-date-picker` with range type can input start time that is later than end time, closes [#5544](https://github.com/tusen-ai/naive-ui/issues/5544).\n\n### Features\n\n- 🌟 Adds `n-flex` component.\n- 🌟 `n-date-picker`'s `type` prop supports `'week'`.\n- 🌟 `n-data-table` adds `downloadCsv` method, closes [#4260](https://github.com/tusen-ai/naive-ui/issues/4260).\n- 🌟 `n-date-picker` adds `month-format`, `year-format` and `quarter-format` props, closes [#4891](https://github.com/tusen-ai/naive-ui/issues/4891).\n- 🌟 `n-tree` adds `override-default-node-click-behavior` prop.\n- 🌟 `n-tree-select` adds `override-default-node-click-behavior` prop.\n- `n-space` adds `reverse` prop.\n- `n-input` adds `clear` method, closes [#5423](https://github.com/tusen-ai/naive-ui/issues/5423).\n- `n-time-picker` adds `'clear'` action, closes [#5334](https://github.com/tusen-ai/naive-ui/issues/5334).\n- `n-select` supports RTL.\n- `n-data-table` supports RTL.\n- `n-dialog` supports RTL.\n- `n-date-picker` adds `on-prev-month` `on-next-month` `on-prev-year` `on-next-year` prop, closes [#5350](https://github.com/tusen-ai/naive-ui/issues/5350).\n- `n-input-number` adds `input-props` prop, closes [#5450](https://github.com/tusen-ai/naive-ui/issues/5450).\n- Update `ruRU` locale.\n- `n-drawer` adds `content-class` prop.\n- `n-drawer-content` adds `body-class` `body-content-class` `footer-class` and `header-class` props.\n- `n-tree` adds multiple `scrollTo` configurations.\n- `n-form` adds `level` property from `FormItemRule` to show abnormal values but not block submit.\n- `n-cascader` adds `ellipsis-tag-popover-props` prop.\n- `n-select` adds `ellipsis-tag-popover-props` prop.\n- `n-tree-select` adds `ellipsis-tag-popover-props` prop.\n- `n-avatar-group` adds `expand-on-hover` prop.\n- `n-tabs` adds `tab-class`, `add-tab-style` and `add-tab-class` props.\n- `n-tree` adds `override-default-node-click-behavior` prop.\n- `n-tree-select` adds `override-default-node-click-behavior` prop.\n- Adds `n-flex` component.\n- `n-pagination` adds `show-quick-jump-dropdown` prop, closes [#5251](https://github.com/tusen-ai/naive-ui/issues/5251).\n\n## 2.36.0\n\n`2023-12-18`\n\n### Fixes\n\n- Fix `n-tree` unexposed line color variable `--n-line-color`, closes [#5339](https://github.com/tusen-ai/naive-ui/issues/5339).\n- Fix `n-tree` The style of the selected node is not displayed in the case of 'disabled'.\n- Fix `n-tree` on `virtual-scroll` empty data placeholder lost problem.\n- Fix `n-watermark` won't clear it's content when `content` prop is set to empty.\n- Fix `n-tree` use `render-switcher-icon` prop to customize switcher icon will cause node selection, closes [#5380](https://github.com/tusen-ai/naive-ui/issues/5380).\n- Fix `n-input` will display the password reveal button by default when the `type` is set to `password`. Starting with Microsoft Edge browser Version 87. closes [#5384](https://github.com/tusen-ai/naive-ui/issues/5384).\n- Fix `n-radio-button` css var `buttonColor` not working.\n- Fix `n-input` not display vertical scrollbar when `type` is `textarea` and the inline theme is disabled, closes [#5418](https://github.com/tusen-ai/naive-ui/issues/5418).\n- Fix if `inline-theme-disabled` is set, custom color whose params include decimal won't work in `n-tag`, `n-avatar`, `n-badge`, `n-button`, `n-rate`.\n- Fix `n-tabs`'s border height in `vertical` mode.\n- Fix `n-tree`'s node's hover color has higher priority than selected color in `block-line` mode.\n- Fix `n-tree` click expand switch causes checkbox being checked.\n- Fix `n-progress` multiple `type=\"circle\"` cases style override issue, closes [#7172](https://github.com/tusen-ai/naive-ui/issues/7172).\n\n### Features\n\n- `n-tree` adds `treeGetClickTarget` method to get click target of node click event, closes [#5375](https://github.com/tusen-ai/naive-ui/issues/5375).\n- `n-space` adds `item-class` prop.\n- `n-layout` adds `content-class` prop.\n- `n-layout-sider` adds `collapsed-trigger-class` and `trigger-class` props.\n- `n-spin` adds `content-class` and `content-style` props.\n- `n-popover` adds `arrow-class`, `arrow-wrapper-class`, `arrow-wrapper-style`, `content-class`, `footer-class` and `header-class` props.\n- `n-notification-provider` adds `container-class` prop.\n- `n-message-provider` adds `container-class` prop.\n- `n-loading-bar-provider` adds `container-class` prop.\n- `n-thing` adds `content-class` and `description-class` props.\n- `n-card` adds `content-class`, `footer-class`, `header-class` and `header-extra-class` props.\n- `n-descriptions` adds `content-class` and `label-class` props.\n- `n-upload` adds `file-list-class` and `trigger-class` props.\n- `n-dynamic-tags` adds `input-class` and `tag-class` props.\n- `n-dynamic-input` adds `item-class` prop.\n- `n-slider` adds `on-dragstart` `on-dragend` prop, closes [#5365](https://github.com/tusen-ai/naive-ui/issues/5365).\n- `n-dialog` adds `close` slot.\n- `n-equation` export the `EquationProps` type.\n- `n-popselect` adds `header` slot.\n- `n-tree-select` adds `watch-props` prop.\n- Adds `n-split` component, closes [#3557](https://github.com/tusen-ai/naive-ui/issues/3557).\n- Adds `n-virtual-list` component.\n- Adds `n-qr-code` component, closes [#2535](https://github.com/tusen-ai/naive-ui/issues/2535).\n- `n-menu` add `responsive` prop, it will collapse overflow menu items in horizontal mode.\n- `n-menu` add `deriveResponsiveState` method.\n\n## 2.35.0\n\n`2023-10-02`\n\n### Breaking Changes\n\n- `n-input`'s `suffix` to the back of `loading`, close [#4685](https://github.com/tusen-ai/naive-ui/issues/4685).\n- Fix `n-log`'s `silent` attribute spelling problem, closes [#4875](https://github.com/tusen-ai/naive-ui/issues/4875).\n\n### Fixes\n\n- Fix `n-radio` export `radioProps` dosen't not includes `theme-overrides`.\n- Fix `n-description-item`'s `span` doesn't work when `n-descriptions`'s `label-placement` is `'top'` if there's only single line, closes [#4874](https://github.com/tusen-ai/naive-ui/issues/4874).\n- Fix `n-upload`'s `data` prop type can't include `Blob` element.\n- Fix `n-select` allows option to be created with existed label, closes [#4703](https://github.com/tusen-ai/naive-ui/issues/4703).\n- Fix `n-upload`'s `render-icon` prop's type.\n- Fix `n-auto-complete`'s `onSelect` type, closes [#4617](https://github.com/tusen-ai/naive-ui/issues/4617).\n- Fix `n-grid-item`'s suffix prop won't work with responsive config, closes [#4635](https://github.com/tusen-ai/naive-ui/issues/4635).\n- Fix `n-tabs`'s `paneWrapperStyle` prop missing height after animation.\n- Fix `n-tree` should check all items instead of uncheck all if indeterminate checkbox is clicked, closes [#4941](https://github.com/tusen-ai/naive-ui/issues/4941).\n- Fix the Popover was not displayed when the `n-internal-selection` was disabled and the mouse was moved over the '+n' tag, closes [#4789](https://github.com/tusen-ai/naive-ui/issues/4789).\n- Fix `n-input` doesn't display the vertical scroll bar when `type` is `textarea`, closes [#4570](https://github.com/tusen-ai/naive-ui/issues/4570).\n- Fix `n-alert`'s content style problem, when there is no title and use closable, closes [#4588](https://github.com/tusen-ai/naive-ui/issues/4588).\n- Fix `n-select`'s `empty` slot action then it is an interactive component, closes [#4700](https://github.com/tusen-ai/naive-ui/issues/4700).\n- Fix `n-data-table` header and body's scrolling are not sync when using the keyboard, closes [#3941](https://github.com/tusen-ai/naive-ui/issues/3941).\n- Fix `n-data-table` drag column causing text selection in Safari, closes [#4957](https://github.com/tusen-ai/naive-ui/issues/4957).\n- Fix `n-data-table` ellipsis content in table cell would wrap with expand button when using tree data, closes [#3755](https://github.com/tusen-ai/naive-ui/issues/3755).\n- Fix `useLoadingBar` can't finish loading when called `finish` method, closes [#4965](https://github.com/tusen-ai/naive-ui/issues/4965).\n- Fix `n-select` can still trigger focus and blur event in the disabled state, closes [#4454](https://github.com/tusen-ai/naive-ui/issues/4454).\n- Fix `n-steps` may have line wrap issue if step is more than 9.\n- Fix `n-grid` v-show reports errors when switching multiple times, closes [#4422](https://github.com/tusen-ai/naive-ui/issues/4422).\n- Fix `n-tree`'s `TreeOption`'s `checkboxDisabled` prop doesn't work when `check-on-click` is `true`.\n- Fix rapid clicks on `n-date-input`'s buttons triggering a text select for the rest of the website.\n- Fix `n-auto-complete`'s autocomplete menu's unexpected open when clicking the clear icon with the input not focused, closes [#4658](https://github.com/tusen-ai/naive-ui/issues/4658).\n- Fix `n-input`'s `on-keyup` prop type, closes [#5101](https://github.com/tusen-ai/naive-ui/issues/5101).\n- Fix `n-data-table`'s default sorter to place null values at the very top or bottom, closes [#5281](https://github.com/tusen-ai/naive-ui/issues/5281).\n- Fix `n-popconfirm`'s action button should not be triggered multiple times，closes [#4687](https://github.com/tusen-ai/naive-ui/issues/4687).\n\n### Features\n\n- `n-drawer` adds `max-height`, `min-height`, `max-width` and `max-width` props.\n- `n-progress` supports indicator slot when the `indicator-placement` is set to `'inside'` in the `'line'` type, closes [#4888](https://github.com/tusen-ai/naive-ui/issues/4888).\n- `n-image-preview` adds `downaload` button, closes [#4302](https://github.com/tusen-ai/naive-ui/issues/4302).\n- `n-transfer` adds `select-all-text` and `clear-text` prop, closes [#4910](https://github.com/tusen-ai/naive-ui/issues/4910).\n- `n-tree` adds `scrollbar-props` prop, closes [#4021](https://github.com/tusen-ai/naive-ui/issues/4666).\n- `n-select` adds `focusInput` `blurInput` methods.\n- `n-tree-select` adds `focusInput` `blurInput` methods.\n- `n-image-group` adds `on-preview-prev` `on-preview-next` prop.\n- `n-tree` adds `show-line` prop, closes [#3796](https://github.com/tusen-ai/naive-ui/issues/3796), [#4554](https://github.com/tusen-ai/naive-ui/pull/4554).\n- `n-tree` adds node information for `render-switcher-icon` props, closes [#4815](https://github.com/tusen-ai/naive-ui/issues/4815).\n- `n-input-number` export the `select` method.\n- `n-data-table` adds `n-data-table-tr--expanded` class to expanded rows, and `n-data-table-tr n-data-table-tr--expand` class to the additional row, closes [#4420](https://github.com/tusen-ai/naive-ui/issues/4420).\n- `n-spin` adds `delay` prop.\n- Adds `n-performant-ellipsis` component.\n- `DataTableBaseColumn` adds `ellipsisComponent` prop.\n\n### i18n\n\n- Update `zhTW` locale.\n- Add `svSE` locale.\n- Update `jaJP` locale.\n\n## 2.34.4\n\n`2023-05-21`\n\n### Fixes\n\n- Fix `n-notification`'s `description` does not wrap when there is English, closes [#4609](https://github.com/tusen-ai/naive-ui/issues/4609).\n- Fix `n-dynamic-input` can't access `value[index]` by `index` passed in `on-remove` prop.\n- Fix `n-dynamic-input` doesn't return correct `index` in `on-create` callback.\n- Fix `trTR` i18n, closes [#4231](https://github.com/tusen-ai/naive-ui/issues/4231).\n- Fix `n-input`'s show password icon is offset when use both `password` and `disabled`, closes [#4364](https://github.com/tusen-ai/naive-ui/issues/4364).\n- Fix `n-image` set `fallback-src` prop and lazy loading dosen't work, closes[#4480](https://github.com/tusen-ai/naive-ui/issues/4480).\n- Fix `n-upload` warning cause by extraneous non-props attributes were passed to vue component `TransitionGroup` but could not be automatically inherited, closes [#4447](https://github.com/tusen-ai/naive-ui/issues/4447).\n- Fix `n-menu` `show` `default` attribute spelling problem, closes [#4750](https://github.com/tusen-ai/naive-ui/issues/4750).\n- Fix `n-icon-wrapper`'s theme error, closes [#4768](https://github.com/tusen-ai/naive-ui/issues/4768).\n\n### Feats\n\n- `n-dynamic-input` adds `action` slot, closes [#3981](https://github.com/tusen-ai/naive-ui/issues/3981).\n- `n-dynamic-input` add `disabled` prop, closes [#4055](https://github.com/tusen-ai/naive-ui/issues/4055).\n- `n-data-table` adds `titleAlign` prop, closes [#3954](https://github.com/tusen-ai/naive-ui/issues/3954).\n- `n-rate` exposes `index` in the default slot, closes [#4413](https://github.com/tusen-ai/naive-ui/issues/4413).\n- `n-scrollbar` adds `size` prop, closes [#3896](https://github.com/tusen-ai/naive-ui/issues/3896).\n- `n-data-table`'s `render-expand-icon` add `expanded` param, closes [#4439](https://github.com/tusen-ai/naive-ui/issues/4439).\n- `n-tabs` adds `pane-wrapper-class` `pane-wrapper-style` prop.\n- `n-collapse` adds `titlePadding` theme variable, closes [#4728](https://github.com/tusen-ai/naive-ui/issues/4728).\n- `n-tabs` adds `placement` prop.\n\n### i18n\n\n- Update `zhTW` locale.\n- Add `faIR` locale.\n\n## 2.34.3\n\n`2022-12-24`\n\n### Fixes\n\n- Fix `n-progress`'s `indicator-text-color` prop doesn't work when `indicator-placement` is `'inside'`.\n- Fix `n-image` error while operating the previewed image, closes [#4157](https://github.com/tusen-ai/naive-ui/issues/4157).\n- Fix `n-tree` cannot access `mergedFilterRef` before initialization error, closes [#4134](https://github.com/tusen-ai/naive-ui/issues/4134).\n- Fix `n-menu` can't override submenu dropdown's `trigger` by `dropdown-props`, closes [#4147](https://github.com/tusen-ai/naive-ui/issues/4147).\n- Fix `n-ellipsis` cannot be closed when using `keep-alive`, closes [#4079](https://github.com/tusen-ai/naive-ui/issues/4079).\n- Fix `n-upload` doesn't show thumbnail for file with image type file name, closes [#4198](https://github.com/tusen-ai/naive-ui/issues/4198).\n- Fix `n-input` style bug of tiny size with autosize prop, closes [#4167](https://github.com/tusen-ai/naive-ui/issues/4167).\n- Fix `n-image` & `n-avatar` in `lazy` mode, after setting the `intersection-observer-options` `rootMargin` attribute, the preload does not take effect.\n\n### Feats\n\n- `n-tree` adds `get-children` prop, closes [#4128](https://github.com/tusen-ai/naive-ui/issues/4128).\n- `n-badge` adds `offset` prop, closes [#4149](https://github.com/tusen-ai/naive-ui/issues/4149).\n- `n-card` adds `tag` prop.\n- demos can now use `<script setup />`.\n- `n-pagination` adds `select-props` prop, closes [#4199](https://github.com/tusen-ai/naive-ui/issues/4199).\n- `n-select` adds `show-on-focus` prop, closes [#4191](https://github.com/tusen-ai/naive-ui/issues/4191).\n- `n-pagination` adds `goto` prop, closes [#4133](https://github.com/tusen-ai/naive-ui/issues/4133).\n- `n-upload` won't set `file` field of file info to `null` after file is uploaded, closes [#3868](https://github.com/tusen-ai/naive-ui/issues/3868).\n- `n-form` adds `labelFontWeight` theme variable, closes [#3516](https://github.com/tusen-ai/naive-ui/issues/3516).\n- `n-radio` adds `labelFontWeight` theme variable, closes [#3516](https://github.com/tusen-ai/naive-ui/issues/3516).\n- `n-checkbox` adds `labelFontWeight` theme variable, closes [#3516](https://github.com/tusen-ai/naive-ui/issues/3516).\n- `n-tree`'s `on-load` prop allows returned promise to resolve `false` to finish loading effect, closes [#4038](https://github.com/tusen-ai/naive-ui/issues/4038).\n\n### i18n\n\n- Update koKr locale.\n\n## 2.34.2\n\n`2022-11-22`\n\n### Fixes\n\n- Fix `n-config-provider`'s katex type issue.\n- Fix `n-image` error in toolbar operation during preview, closes [#4144](https://github.com/tusen-ai/naive-ui/issues/4144).\n\n## 2.34.1\n\n`2022-11-21`\n\n### Fixes\n\n- Fix `n-select` will print useless content in console in multiple select mode.\n- Fix `n-tree` misses `getCheckedData` and `getIndeterminateData` methods, closes [#4064](https://github.com/tusen-ai/naive-ui/issues/4064).\n- Fix `n-data-table`'s column's `align` doesn't work for table header, closes [#4063](https://github.com/tusen-ai/naive-ui/issues/4063).\n\n## 2.34.0\n\n`2022-11-21`\n\n### Breaking Changes\n\n- Wrap a `div` container around the columns of `n-data-table` to optimize the layout of filter button, closes [#3853](https://github.com/tusen-ai/naive-ui/issues/3853).\n\n### Feats\n\n- 'themeOverRides' provide `labelFontWeight` for `n-form`, `n-radio`, `n-checkbox`, closes [#3516](https://github.com/tusen-ai/naive-ui/issues/3516).\n- `n-avatar-group` exports `AvatarGroupOption` type, closes [#3879](https://github.com/tusen-ai/naive-ui/issues/3879).\n- `n-transfer` adds `show-selected` prop, closes [#3711](https://github.com/tusen-ai/naive-ui/issues/3711).\n- `n-data-table` adds `loading` slot, closes [#3865](https://github.com/tusen-ai/naive-ui/issues/3865).\n- `n-mention` adds `on-update:show` prop, closes [#3882](https://github.com/tusen-ai/naive-ui/issues/3882).\n- `n-tree` adds trigger node information for `on-update:expanded-keys`, `on-update:checked-keys` and `on-update:selected-keys` props, closes [#3885](https://github.com/tusen-ai/naive-ui/issues/3885).\n- `n-tree-select` adds trigger node information for `on-update:expanded-keys` and `on-update:value` props, closes [#3885](https://github.com/tusen-ai/naive-ui/issues/3885).\n- `n-tree` adds `getCheckedData` method.\n- `n-tree` adds `getIndeterminateData` method.\n- `n-tree-select` adds `getCheckedData` method.\n- `n-tree-select` adds `getIndeterminateData` method.\n- `n-tree-select` adds `focus` method.\n- `n-tree-select` adds `blur` method.\n- `n-cascader` adds `getCheckedData` method.\n- `n-cascader` adds `getIndeterminateData` method.\n- `n-input` adds `count-graphemes` prop, closes [#3967](https://github.com/tusen-ai/naive-ui/issues/3967).\n- `n-cascader` adds `not-found` slot, closes [#3862](https://github.com/tusen-ai/naive-ui/issues/3862).\n- `n-avatar` adds `img-props` prop, closes [#3963](https://github.com/tusen-ai/naive-ui/issues/3963).\n- `n-data-table` adds `spin-props` prop, closes [#3649](https://github.com/tusen-ai/naive-ui/issues/3649).\n- `n-button` adds `render-icon` prop, closes [#4007](https://github.com/tusen-ai/naive-ui/issues/4007).\n- Add `n-equation` component.\n- `n-image` adds `previewed-img-props` prop.\n- `n-data-table` adds `scrollbar-props` prop, closes [#4021](https://github.com/tusen-ai/naive-ui/issues/4021).\n- `n-upload` adds `should-use-thumbnail-url` prop, closes [#3861](https://github.com/tusen-ai/naive-ui/issues/3861).\n- `n-upload` adds `render-icon` prop.\n- `n-tree`'s `render-switcher-icon` prop is passed with `expanded` & `selected` state.\n- `useDialog`'s option support `transformOrigin`, closes [#3901](https://github.com/tusen-ai/naive-ui/issues/3901).\n\n### Fixes\n\n- Fix `n-image` can be dragged by any button on mouse in preview mode, closes [#3950](https://github.com/tusen-ai/naive-ui/issues/3950).\n- Fix `n-form-item`'s label text is in wrong position when `label-align=\"left\"` and `require-mark-placement=\"left\"` and `label-placement=\"left\"`, closes [#3871](https://github.com/tusen-ai/naive-ui/issues/3871).\n- Fix `n-tree`'s dragging causes partial white screen in Chrome and Edge with version 106, closes [#3909](https://github.com/tusen-ai/naive-ui/issues/3909).\n- Fix `n-select` shows wrong value in select box after `value-field` is set and `max-tag-count=\"responsive\"` and remove selected option in overflow tag's popover, closes [#3869](https://github.com/tusen-ai/naive-ui/issues/3869).\n- Fix `n-ellipsis` won't overflow in `n-card`'s title, closes [#3935](https://github.com/tusen-ai/naive-ui/issues/3935).\n- Fix `n-timeline-item`'s `line-type=\"dashed\"` not working when `n-timeline`'s `horizontal` is set, closes [#4014](https://github.com/tusen-ai/naive-ui/issues/4014).\n- Fix `n-popover` doesn't wrap line if word is too long.\n- Fix `n-date-picker` can't delete all input content in some cases, closes [#3922](https://github.com/tusen-ai/naive-ui/issues/3922).\n- Fix `n-input`'s `autosize` prop doesn't work properly if there are multiple spaces, closes [#4027](https://github.com/tusen-ai/naive-ui/issues/4027).\n- Fix `n-pagination`'s `endIndex` maybe incorrect in last page, closes [#4057](https://github.com/tusen-ai/naive-ui/issues/4057).\n- Fix `n-image` doesn't prevent space pressing scroll behavior in preview mode, closes [#3919](https://github.com/tusen-ai/naive-ui/issues/3919).\n\n### i18n\n\n- Add arDZ locale.\n- Add trTR locale.\n\n## 2.33.5\n\n`2022-10-12`\n\n### Fixes\n\n- Fix `n-data-table` throws error on tree data check action, closes [#3832](https://github.com/tusen-ai/naive-ui/issues/3832).\n\n## 2.33.4\n\n`2022-10-06`\n\n### Fixes\n\n- Fix `n-timeline-item`'s `title`'s `margin-bottom` can't be set by theme variable, closes [#3722](https://github.com/tusen-ai/naive-ui/issues/3722).\n- Fix `n-timeline-item`'s `meta` part's `margin-bottom` is overrided when nested in horizontal and vertical mode.\n- Fix `n-tree-select` would remove selected first option if it's clicked when placed in `label` tag, closes [#3715](https://github.com/tusen-ai/naive-ui/issues/3715).\n- Fix `n-popover` will show after `disabled` is set to `true` then `false` if it's shown at first.\n- Fix `n-select`'s overflow popover won't hide after removing all options in it when `maxTagCount=\"responsive\"`, closes [#3801](https://github.com/tusen-ai/naive-ui/issues/3801).\n- Fix `n-upload` may only allow selecting directory in Firefox, closes [#3798](https://github.com/tusen-ai/naive-ui/issues/3798).\n- Remove `package.json`'s `exports` field due to its poor compatibility, closes [#3786](https://github.com/tusen-ai/naive-ui/issues/3786).\n- Fix `createDiscreteApi` throws error in SSR environment, closes [#3813](https://github.com/tusen-ai/naive-ui/issues/3813).\n- Fix `n-tree-select` has wrong focus behavior when `filterable` and in single select mode.\n- Fix `n-input-number` may not update input when value is set in `on-blur` callback.\n\n### Feats\n\n- `n-collapse-item`'s `header-extra` & `header` slots support `collapsed` param, closes [#3723](https://github.com/tusen-ai/naive-ui/issues/3723).\n- `n-loading-bar-provider` adds `to` prop, closes [#3724](https://github.com/tusen-ai/naive-ui/issues/3724).\n- `n-data-table`'s `on-update:checked-row-keys` will pass current row data and state, closes [#3626](https://github.com/tusen-ai/naive-ui/issues/3626).\n- `n-data-table` column adds `resizable` prop, closes [#3165](https://github.com/tusen-ai/naive-ui/issues/3165).\n- `createDiscreteApi` contains Vue app in returned value.\n- Export `LayoutContentInst` type, closes [#3743](https://github.com/tusen-ai/naive-ui/issues/3743).\n- Export `CarouselInst` type, closes [#3742](https://github.com/tusen-ai/naive-ui/issues/3742).\n- `n-collapse` adds `itemMargin` theme variable, closes [#3788](https://github.com/tusen-ai/naive-ui/issues/3788).\n- `n-select` adds `ignore-composition` prop, closes [#3789](https://github.com/tusen-ai/naive-ui/issues/3789).\n- `n-card` exports `CardSegmented` type, closes [#3775](https://github.com/tusen-ai/naive-ui/issues/3775).\n- `n-date-picker` adds `next-month` slot, closes [#3570](https://github.com/tusen-ai/naive-ui/issues/3570).\n- `n-date-picker` adds `next-year` slot, closes [#3570](https://github.com/tusen-ai/naive-ui/issues/3570).\n- `n-date-picker` adds `prev-month` slot, closes [#3570](https://github.com/tusen-ai/naive-ui/issues/3570).\n- `n-date-picker` adds `prev-year` slot, closes [#3570](https://github.com/tusen-ai/naive-ui/issues/3570).\n- `n-pagination` adds `to` prop, closes [#3773](https://github.com/tusen-ai/naive-ui/issues/3773).\n- `n-avatar` adds `render-placeholder` prop, closes [#3751](https://github.com/tusen-ai/naive-ui/issues/3751).\n- `n-avatar` adds `render-fallback` prop, closes [#3751](https://github.com/tusen-ai/naive-ui/issues/3751).\n- `n-avatar` adds `fallback` slot.\n- `n-transfer` adds `render-target-list` prop.\n- `n-select` adds `show-checkmark` prop, closes [#3749](https://github.com/tusen-ai/naive-ui/issues/3749).\n- `n-tree` adds `animated` prop, closes [#3784](https://github.com/tusen-ai/naive-ui/issues/3784).\n- `n-slider` adds `markFontSize` theme variable, closes [#3820](https://github.com/tusen-ai/naive-ui/issues/3820).\n- `n-avatar-group` adds `gap` theme variable, closes [#3819](https://github.com/tusen-ai/naive-ui/issues/3819).\n\n## 2.33.3\n\n`2022-09-13`\n\n### Feats\n\n- `n-dialog` adds `onAfterLeave` in DialogOptions Properties, closes [#3662](https://github.com/tusen-ai/naive-ui/issues/3662).\n- `n-dynamic-tags` export `DynamicTagsOption` type, closes [#3677](https://github.com/tusen-ai/naive-ui/issues/3677).\n- `n-upload` adds `responseType` prop, closes [#3666](https://github.com/tusen-ai/naive-ui/issues/3666).\n- `n-dropdown`'s `DropdownOption` adds `show` prop, closes [#3703](https://github.com/tusen-ai/naive-ui/issues/3703).\n- `n-data-table` adds `summary-placement` prop, closes [#3681](https://github.com/tusen-ai/naive-ui/issues/3681).\n- `n-tabs` will scroll to active tab, closes [#3683](https://github.com/tusen-ai/naive-ui/issues/3683).\n\n### Performance\n\n- Fix `n-menu`'s `value` will cause useless rendering of menu item, closes [#3670](https://github.com/tusen-ai/naive-ui/issues/3670).\n\n### Fixes\n\n- Fix `n-date-picker`'s style is unexpected in `inline-theme-disabled` mode, closes [#3655](https://github.com/tusen-ai/naive-ui/issues/3655).\n- Fix `n-data-table` can't set `n-dropdown`'s `theme-overrides`, closes [#3613](https://github.com/tusen-ai/naive-ui/issues/3613).\n- Fix `n-carousel` displays abnoramlly if `transform: scale` style is set, closes [#3684](https://github.com/tusen-ai/naive-ui/issues/3684).\n- Fix `n-tree`'s node is disabled after `checkboxDisabled` is set, closes [#3620](https://github.com/tusen-ai/naive-ui/issues/3620).\n- Fix `n-tree`'s switcher won't work when `:show-irrelevant-nodes=\"false\"` is set & being searched, closes [#3647](https://github.com/tusen-ai/naive-ui/issues/3647).\n- Fix `n-progress`'s graph may overflow if `type=\"circle\"` and `stroke-width` is too large, closes [#3638](https://github.com/tusen-ai/naive-ui/issues/3638).\n\n## 2.33.2\n\n`2022-09-01`\n\n### Fixes\n\n- Fix UMD bundle doesn't work, closes [#3642](https://github.com/tusen-ai/naive-ui/issues/3642).\n- Fix `n-calendar`'s displayed month doesn't follow `default-value`, closes [#3645](https://github.com/tusen-ai/naive-ui/issues/3645).\n- Fix `n-form-item`'s `require-mark-placement` prop not working when set to `left`, closes [#3628](https://github.com/tusen-ai/naive-ui/issues/3628).\n- Fix `n-upload`'s `OnBeforeUpload` return type can only be `Promise<boolean>`.\n\n### Feats\n\n- `n-radio` adds `colorActive` theme variable, closes [#3610](https://github.com/tusen-ai/naive-ui/issues/3610).\n\n## 2.33.1\n\n`2022-08-29`\n\n### Fixes\n\n- Fix could not resolve \"@vicons/ionicons5\" error, closes [#3616](https://github.com/tusen-ai/naive-ui/issues/3616).\n\n## 2.33.0\n\n`2022-08-29`\n\n### Breaking Changes\n\n- `n-rate`'s `default-value` prop's default value is changed from `0` to `null`.\n\n### Fixes\n\n- Fix `n-select`'s menu missing option check mark in SSR mode, closes <https://github.com/07akioni/naive-ui-nuxt-demo/issues/4>.\n- Fix `n-card`'s `embedded` prop not work in `n-dialog`, closes [#3592](https://github.com/tusen-ai/naive-ui/issues/3592).\n- Fix `n-radio` warning when value prop type is boolean, closes [#3540](https://github.com/tusen-ai/naive-ui/issues/3540).\n- Fix `n-tree` content width may overflow container, closes [#3561](https://github.com/tusen-ai/naive-ui/issues/3561).\n- Fix `n-form-item` label text may overflow when it's left placement, closes [#3593](https://github.com/tusen-ai/naive-ui/issues/3593).\n\n### Feats\n\n- `n-menu` adds `disabled-field` prop.\n- `n-rate` adds `clearable` prop.\n- `n-slider` adds `keyboard` prop, closes [#3528](https://github.com/tusen-ai/naive-ui/issues/3528).\n- Add `useDialogReactiveList` method, closes [#2041](https://github.com/tusen-ai/naive-ui/issues/2041).\n- `DialogReactive` supports `onAfterEnter` prop, closes [#3569](https://github.com/tusen-ai/naive-ui/issues/3569).\n- `DialogOptions` supports `class` prop, closes [#3591](https://github.com/tusen-ai/naive-ui/issues/3591).\n\n## 2.32.2\n\n`2022-08-19`\n\n### Fixes\n\n- Fix `n-menu` extra not working in submenu, closes [#3390](https://github.com/tusen-ai/naive-ui/issues/3390).\n- Fix `n-tree` can't expand node with `type='group'`, closes [#3388](https://github.com/tusen-ai/naive-ui/issues/3388).\n- Fix `n-pagination`'s' `default-page-size` prop doesn't follows `page-sizes` prop, closes [#3369](https://github.com/tusen-ai/naive-ui/issues/3369).\n- Added `exports` field in package.json [#3410](https://github.com/tusen-ai/naive-ui/pull/3410).\n- Fix `n-dropdown` option prefix & suffix's z-index, closes [#3433](https://github.com/tusen-ai/naive-ui/issues/3433).\n- Fix `n-input-number`'s peers theme can't be configured, closes [#3422](https://github.com/tusen-ai/naive-ui/issues/3422).\n- Fix `n-tag` pointer should be not allow when disabled, closes [#3494](https://github.com/tusen-ai/naive-ui/issues/3494).\n- Fix `n-transfer` throws error if value has no corresponding option, closes [#3406](https://github.com/tusen-ai/naive-ui/issues/3406).\n- Fix `n-data-table` column `onSelect`'s type, closes [#3430](https://github.com/tusen-ai/naive-ui/issues/3430).\n- Fix `n-pagination` don't trigger quick jumper on quick jumper blur, closes [#3387](https://github.com/tusen-ai/naive-ui/issues/3387).\n- Fix some components works abnormally in open mode shadow DOM, closes [#3281](https://github.com/tusen-ai/naive-ui/issues/3281).\n- Fix `n-carousel` in `loop='true'` and `effect='slide'`, When there are only two elements, the transition switching effect of the rotation is opposite, closes [#3414](https://github.com/tusen-ai/naive-ui/issues/3413).\n- Fix `n-input` can't input value after compositing is interrupted by rerender, closes [#3503](https://github.com/tusen-ai/naive-ui/issues/3503).\n- Fix `n-layout`'s `embedded` prop not working after `n-config-provider` has set `inline-theme-disabled`, closes [#3500](https://github.com/tusen-ai/naive-ui/issues/3500).\n- Fix `n-input` has duplicate placeholder if disabled, closes [#3467](https://github.com/tusen-ai/naive-ui/issues/3467).\n- Fix `n-date-picker`'s `iconColor` theme variable not working, closes [#3501](https://github.com/tusen-ai/naive-ui/issues/3501).\n- Fix `n-time-picker`'s `iconColor` theme variable not working, closes [#3501](https://github.com/tusen-ai/naive-ui/issues/3501).\n- Fix `n-select`'s `node-props` prop doesn't work.\n- Fix Nuxt report `CSSRender is not a function` error on preview, closes [#3506](https://github.com/tusen-ai/naive-ui/issues/3506).\n- Fix `n-data-table`'s rows disabled by `column.expandable` can still be expanded, closes [#3373](https://github.com/tusen-ai/naive-ui/issues/3373).\n- Fix `n-input-number` click add or minus button quickly may trigger value change loop, closes [#3329](https://github.com/tusen-ai/naive-ui/issues/3329).\n- Fix `n-switch` some theme variables can't use non-px value, closes [#2938](https://github.com/tusen-ai/naive-ui/issues/2938).\n- Fix `n-input` with `resize` & `type=\"textarea\"` set can't be resized in some cases, closes [#3479](https://github.com/tusen-ai/naive-ui/issues/3479).\n- Fix `n-countdown`'s `reset` method doesn't work in `onFinish` callback, closes [#3536](https://github.com/tusen-ai/naive-ui/issues/3536).\n\n### Feats\n\n- `n-menu`'s `MenuOption` add `show` prop to set whether the Menu option is displayed, closes [#3334](https://github.com/tusen-ai/naive-ui/issues/3334).\n- `n-alert` adds `bordered` prop, closes [#3358](https://github.com/tusen-ai/naive-ui/issues/3358).\n- `n-tag` add `trigger-click-on-close` prop, closes [#3343](https://github.com/tusen-ai/naive-ui/issues/3343).\n- `n-cascader` adds `disabled-field` prop, closes [#3338](https://github.com/tusen-ai/naive-ui/issues/3338).\n- `n-list` adds `clickable` prop.\n- `n-list` adds `hoverable` prop.\n- `n-list` adds `show-divider` prop.\n- `n-thing` adds `content-style` prop.\n- `n-thing` adds `description-style` prop.\n- `n-data-table` adds `render-expand-icon` prop.\n- `n-tree` adds `disabled-field` prop.\n- `n-tree` adds `keyboard` prop, closes [#3438](https://github.com/tusen-ai/naive-ui/issues/3438).\n- `n-tree-select` adds `disabled-field` prop.\n- `n-collapse-item` adds `disabled` prop, closes [#3408](https://github.com/tusen-ai/naive-ui/issues/3408).\n- `n-pagination` adds `simple` prop.\n- `n-cascader` adds `arrow` slot, closes [#3459](https://github.com/tusen-ai/naive-ui/issues/3459).\n- `n-transfer` adds `source-filterable` prop, closes [#3407](https://github.com/tusen-ai/naive-ui/issues/3407).\n- `n-transfer` adds `target-filterable` prop, closes [#3407](https://github.com/tusen-ai/naive-ui/issues/3407).\n- `n-transfer`'s `filter` prop adds `from` param.\n- `n-list` supports RTL.\n- `n-drawer` supports RTL.\n- `n-input` adds `render-count` prop.\n- `n-input` adds `countTextColorDisabled` theme variable, closes [#3481](https://github.com/tusen-ai/naive-ui/issues/3481).\n- `n-statistic` adds `valueFontSize` theme variable, closes [#3510](https://github.com/tusen-ai/naive-ui/issues/3510).\n- `n-data-table` adds `sticky-expanded-rows` to allow expanded content remains sticky, closes [#3485](https://github.com/tusen-ai/naive-ui/issues/3485).\n- `n-tree` adds `scrollTo` method, closes [#3480](https://github.com/tusen-ai/naive-ui/issues/3480).\n- `n-pagination` adds `display-order` prop, closes [#3466](https://github.com/tusen-ai/naive-ui/issues/3466).\n- `n-grid` adds `layout-shift-disabled` prop, closes [#3301](https://github.com/tusen-ai/naive-ui/issues/3301).\n\n## 2.32.1\n\n`2022-07-30`\n\n### Fixes\n\n- Fix `n-drawer`'s warning when using `string` in `default-height` prop, closes [#3377](https://github.com/tusen-ai/naive-ui/issues/3377).\n- Fix `n-transfer`'s `on-update:value` is not triggered when uncheck options, closes [#3393](https://github.com/tusen-ai/naive-ui/issues/3393).\n\n### Feats\n\n- `n-steps` supports RTL.\n\n## 2.32.0\n\n`2022-07-28`\n\n### Breaking Changes\n\n- `n-transfer`'s UI is totally refactored. The original transfer component is renamed as `n-legacy-transfer` and will be removed in next major version.\n\n### Fixes\n\n- Fix `n-date-picker` will cancel selecting in range mode if click at disabled confirm button, closes [#3254](https://github.com/tusen-ai/naive-ui/issues/3254).\n- Fix `n-button`'s `focusable` prop doesn't work, closes [#3292](https://github.com/tusen-ai/naive-ui/issues/3292).\n- Fix `n-upload`'s `on-error` & `on-finish` props don't allow `() => void` type, closes [#3290](https://github.com/tusen-ai/naive-ui/issues/3290).\n- Fix `n-select`'s placeholder may overflow if it's long.\n- Fix `n-input` has is no indent at the prefix if `type=\"textarea\"` and `:autosize=\"true\"`, closes [#3238](https://github.com/tusen-ai/naive-ui/issues/3238).\n- Fix `n-select` focus loss when click `action` slot in `filterable` and `multiple`, closes [#3247](https://github.com/tusen-ai/naive-ui/issues/3247).\n- Fix `n-carousel`'s `autoplay` prop be `true` `hover` can't stop the play, closes [#3304](https://github.com/tusen-ai/naive-ui/issues/3304).\n- Fix `n-tree` may throw error on node selection `expanded-keys`, closes [#3319](https://github.com/tusen-ai/naive-ui/issues/3319).\n- Fix `n-avatar` shows placeholder after load fails, closes [#3315](https://github.com/tusen-ai/naive-ui/issues/3315).\n- Fix `n-input-number` register `mouseup` event multiple times when hold on button.\n- Fix all components' exported props type's prop is `readonly`.\n- Fix `n-tree`'s `check-on-click` prop sometimes doesn't work.\n- Fix `n-progress`'s `offset-degree` prop behaves incorrectly.\n\n### Feats\n\n- `n-checkbox-group`'s `on-update:value` prop adds trigger checkbox's value to params, closes [#3277](https://github.com/tusen-ai/naive-ui/issues/3277).\n- `n-tree` supports RTL.\n- `n-input` adds `scrollTo` method, closes [#3280](https://github.com/tusen-ai/naive-ui/issues/3280).\n- `n-legacy-grid` supports RTL.\n- `n-statistic` supports RTL.\n- `n-thing` supports RTL.\n- `n-transfer` add `render-source-label` prop.\n- `n-transfer` add `render-target-label` prop.\n- `n-transfer` add `render-source-list` prop.\n- `n-scrollbar` supports RTL.\n- `useDialog` supports `onEsc` prop.\n- `n-watermark` adds `global-rotate` prop.\n- `n-notification` add `keepAliveOnHover` props to control whether the notification will be closed when mouse hover, closes [#3249](https://github.com/tusen-ai/naive-ui/issues/3249).\n\n## 2.31.0\n\n`2022-07-07`\n\n### Breaking Changes\n\n- `n-date-picker`'s `clearable` will control visibility of clear button if no `action` is set, closes [#1196](https://github.com/tusen-ai/naive-ui/issues/1196).\n- `n-button`'s `native-focus-behavior` prop default value is changed to 'not on Safari'.\n\n### Fixes\n\n- Fix `n-data-table`'s column `render` prop's `index` param sequence exception when in expandable row, closes [#3153](https://github.com/tusen-ai/naive-ui/issues/3153).\n- Fix `n-data-table` column's `colSpan` doesn't work correctly in virtual scroll mode, closes [#3052](https://github.com/tusen-ai/naive-ui/issues/3052).\n- Fix `n-data-table` doesn't show `summary` row in virtual scroll mode, closes [#3202](https://github.com/tusen-ai/naive-ui/issues/3202).\n- Fix `n-carousel` has wrong hierarchical relationship between when `effect` is `fade`, closes [#3227](https://github.com/tusen-ai/naive-ui/issues/3227).\n- Fix `n-carousel` cannot slide under IOS, closes [#3106](https://github.com/tusen-ai/naive-ui/issues/3106).\n- Fix `n-carousel` losing the size of content elements when rendering, closes [#3078](https://github.com/tusen-ai/naive-ui/issues/3078).\n- Fix `n-cascader`'s filter menu doesn't show option path, closes [#3220](https://github.com/tusen-ai/naive-ui/issues/3220).\n- Fix `n-cascader`'s `filter` prop may not get correct `path`.\n- Fix `n-date-picker` menu's quarter text isn't same having `type=\"quarterrange\"` and `type=\"quarter\"`, closes [#3217](https://github.com/tusen-ai/naive-ui/issues/3217).\n- Fix `n-notification`'s leave animation if content height overflows screen.\n- Fix `n-dropdown`'s disabled option has hover style.\n- Fix `n-dropdown`'s menu may shift when it's entering.\n- Fix `n-dropdown`'s transform origin may not be correct in Chrome.\n- Fix `n-radio-button` may not have correct cursor style, closes [#3243](https://github.com/tusen-ai/naive-ui/issues/3243).\n- Fix `n-input`'s text color is too shallow with disabled state in Safari, closes [#3241](https://github.com/tusen-ai/naive-ui/issues/3241).\n- Fix `n-input`'s separator may have line wrap.\n- Fix all components' `user-select` style prop's effect on Safari.\n- Fix `n-data-table` will prevent page scroll in virtual scroll mode.\n- Fix `n-button` doesn't have pressed effect on Firefox.\n\n### Feats\n\n- `n-avatar` adds `lazy` prop.\n- `n-avatar` adds `intersection-observer-options` prop.\n- `n-number-animation` adds `on-finish` prop.\n- `n-notification` supports RTL.\n- Export all components' props object.\n- `n-popover` adds `footer-style` prop.\n- `n-popover` adds `footer` slot, closes [#3188](https://github.com/tusen-ai/naive-ui/issues/3188).\n- `n-dropdown` adds `menu-props` prop, closes [#2885](https://github.com/tusen-ai/naive-ui/issues/2885).\n- `n-data-table` adds `multiple` prop, closes [#3056](https://github.com/tusen-ai/naive-ui/issues/3056).\n- `n-date-picker` would disable confirm button if end date is not selected, closes [#3226](https://github.com/tusen-ai/naive-ui/issues/3226).\n- `n-tree` adds `check-on-click` prop to control `checked` status, closes [#2968](https://github.com/tusen-ai/naive-ui/issues/2968).\n- `n-tree` adds `accrodion` prop, closes [#3129](https://github.com/tusen-ai/naive-ui/issues/3129).\n- `n-countdown` adds `reset` method, closes [#3228](https://github.com/tusen-ai/naive-ui/issues/3228).\n- `n-drawer` adds `resizable` prop.\n- `n-drawer` adds `default-width` prop.\n- `n-drawer` adds `default-height` prop.\n- `n-drawer` adds `on-update:width` prop.\n- `n-drawer` adds `on-update:height` prop.\n- Update ukUA locale.\n- `n-message` supports RTL.\n\n## 2.30.8\n\n`2022-06-29`\n\n### Fixes\n\n- Fix `n-select`'s menu transition style, closes [#3211](https://github.com/tusen-ai/naive-ui/issues/3211).\n\n## 2.30.7\n\n`2022-06-29`\n\n### Fixes\n\n- Fix `n-tabs`'s `bar-width` props invalid when `0` set, closes [#3171](https://github.com/tusen-ai/naive-ui/issues/3171).\n- Fix `n-drawer` has log warnings of console when use `show-mask` prop, closes [#3172](https://github.com/tusen-ai/naive-ui/issues/3172).\n- Fix `n-button` doesn't omit content if content is wrapped in ellipsis container, closes [#3178](https://github.com/tusen-ai/naive-ui/issues/3178).\n- Fix `n-select` will remove select value in multiple mode in `form` if Enter key is pressed in input element. Closes [#3169](https://github.com/tusen-ai/naive-ui/issues/3169).\n- Fix `n-select`'s filter prop not working, closes [#3175](https://github.com/tusen-ai/naive-ui/issues/3175).\n- Fix `n-modal`'s mask may overlay over content if no preset is used, closes [#3204](https://github.com/tusen-ai/naive-ui/issues/3204).\n- Fix `n-button`'s icon doesn't align correctly if it's too big or small.\n- Fix `n-select`'s created options may repeat multiple times in menu, closes [#3206](https://github.com/tusen-ai/naive-ui/issues/3206).\n\n### Feats\n\n- `n-date-picker`'s `type` prop supports `'quarterrange'` and `'yearrange'`.\n- `n-tree-select` adds `render-prefix` prop.\n- `n-tree-select` adds `render-suffix` prop.\n- `n-tree-select` adds `render-switcher-icon` prop.\n- `n-tree-select` adds `node-props` prop.\n- `n-tree-select` adds `render-label` prop, closes [#3197](https://github.com/tusen-ai/naive-ui/issues/3197).\n- `n-tree-select` adds `render-tag` prop.\n- `n-notification` adds `titleFontSize`, `metaFontSize`, `descriptionFontSize` theme variables.\n\n## 2.30.6\n\n`2022-06-22`\n\n### Fixes\n\n- Fix `n-color-picker` can't input alpha value correctly manually.\n- Fix some components don't work correctly if `__VUE_OPTIONS_API__` is set to `false`, closes [#3146](https://github.com/tusen-ai/naive-ui/issues/3146).\n- Fix `n-grid` doesn't adjust it's content to fit responsive config in SSR page, closes [#2462](https://github.com/tusen-ai/naive-ui/issues/2462).\n- Fix `n-modal` when many instances are activated at same time, `on-mask-click` will be triggered on every modal even only one mask is clicked [#3147](https://github.com/tusen-ai/naive-ui/issues/3147).\n- Fix `n-data-table`'s column `ellipsis` prop's type doesn't allow `style` prop.\n- Fix `n-data-table`'s column will lose box shadow when set to `ellipsis` & `fixed` simultaneously, closes [#3145](https://github.com/tusen-ai/naive-ui/issues/3145).\n- Fix `n-image`'s `lazy` prop doesn't work on Safari & Firefox.\n\n## 2.30.5\n\n`2022-06-20`\n\n### Fixes\n\n- Fix `n-input-group-label`'s content is abnormal in `n-drawer-content`, closes [#3115](https://github.com/tusen-ai/naive-ui/issues/3115).\n- Fix `n-back-top` has log warnings of console when use `show` prop, closes [#3122](https://github.com/tusen-ai/naive-ui/issues/3122).\n- Fix `volar.d.ts` components' type is `any`.\n- Fix `n-grid-item` may not display correctly if `v-show` is used, closes [#3123](https://github.com/tusen-ai/naive-ui/issues/3123).\n- Fix `n-select` clears input value on mouse enter when it's clearable and using IME.\n\n### Feats\n\n- 🌟 `n-image` adds `lazy` prop, closes [#3055](https://github.com/tusen-ai/naive-ui/issues/3055).\n- `n-image` adds `intersection-observer-options` prop.\n- `n-image` adds `placeholder` slot.\n- Exports `NTooltipInst` type.\n- `n-data-table` adds `render-cell` prop, closes [#3095](https://github.com/tusen-ai/naive-ui/issues/3095).\n- `n-space` adds `wrap-item` prop.\n- `n-data-table`'s `on-update:checked-row-keys` will pass row data, closes [#2215](https://github.com/tusen-ai/naive-ui/issues/2215), closes [#2265](https://github.com/tusen-ai/naive-ui/pull/2265).\n\n## 2.30.4\n\n`2022-06-15`\n\n### Fixes\n\n- Fix `n-button` is focused after click with `:focusable=\"false\"`, closes [#3071](https://github.com/tusen-ai/naive-ui/issues/3071).\n- Fix `n-data-table` fixed selection may overlap with other fixed columns if it's width is not default, closes [#3067](https://github.com/tusen-ai/naive-ui/issues/3067).\n- Fix `n-popselect` doesn't trigger `on-update:show` when it select value then menu is closed.\n- Fix `n-popselect`'s width can't be set via `style`.\n- Fix `n-date-picker`'s year & month quick jump may be disabled after `is-date-disabled` is set, closes [#3068](https://github.com/tusen-ai/naive-ui/issues/3068).\n- Fix `n-layout` won't keep scroll state in `keep-alive` component, closes [#3054](https://github.com/tusen-ai/naive-ui/issues/3054).\n- Fix `n-layout-sider` won't keep scroll state in `keep-alive` component.\n- Fix `n-tree` may trigger loading multiple times.\n- Fix `n-tree` throws error on async expanding data with `:expand-on-click=\"true\"`, closes [#3089](https://github.com/tusen-ai/naive-ui/issues/3089).\n- Fix `n-slider`'s tooltip has no enter transition when it's triggered by keyboard.\n- Fix `n-slider` mark text's line wrap isn't correct when it appears at right-most position.\n- Fix `n-upload`'s inner anchor element may show focus-visible outline style.\n- Fix `n-upload` shows slot warning when `list-type=\"image-card\"`.\n- Fix `n-upload` image's corner may overflow item when `list-type=\"image-card\"`.\n- Fix `n-dynamic-tags`'s `on-create` prop not working.\n- Fix virtual scroll stucking issue introduced by Chrome 102, closes [#3048](https://github.com/tusen-ai/naive-ui/issues/3048).\n- Fix `n-upload-dragger` is almost transparent if disabled.\n\n### Feats\n\n- 🌟 `n-pagination` adds dropdown menu for fast jump button.\n- 🌟 `n-input` adds `allow-input` prop.\n- 🌟 `n-data-table` adds `default-expand-all` prop, closes [#3073](https://github.com/tusen-ai/naive-ui/issues/3073).\n- 🌟 `n-modal` with inner popup component like `n-select` can handle esc key pressing correctly, closes [#2973](https://github.com/tusen-ai/naive-ui/issues/2973).\n- `n-tree-select` adds `arrow` slot, closes [#3084](https://github.com/tusen-ai/naive-ui/issues/3084).\n- `n-cascader` will show corresponding submenu after checkbox is clicked, closes [#3079](https://github.com/tusen-ai/naive-ui/issues/3079).\n- `n-upload` will disable dragger when maximum number of files was reached.\n- `n-select` adds `node-props` prop.\n- `n-popselect` adds `node-props` prop.\n- `n-popselect` adds `virtual-scroll` prop.\n- `n-data-table` adds `scrollTo` method, closes [#2570](https://github.com/tusen-ai/naive-ui/issues/2570).\n- `n-slider` adds `thumb` slot.\n\n## 2.30.3\n\n`2022-06-09`\n\n### Fixes\n\n- Fix `n-cascader`'s overflow count tag's popover can't scroll after `filterable` is set, closes [#3061](https://github.com/tusen-ai/naive-ui/issues/3061).\n- Fix `n-drawer`'s `show-mask` prop will warn if `'transparent'` is passed.\n- Fix `n-calendar` doesn't call `on-panel-change` when date of other months is clicked, closes [#3063](https://github.com/tusen-ai/naive-ui/issues/3063).\n\n### Feats\n\n- 🌟 UMD usage is supported.\n- `n-cascader` will expand menu to selected value, closes [#3058](https://github.com/tusen-ai/naive-ui/issues/3058).\n- `n-space` will use `gap` CSS property if possible, closes [#3053](https://github.com/tusen-ai/naive-ui/issues/3053).\n\n## 2.30.2\n\n`2022-06-07`\n\n### Fixes\n\n- Fix `n-select` recomputed options on menu close, improves performance.\n\n## 2.30.1\n\n`2022-06-07`\n\n### Feats\n\n- `n-menu` adds `arrowColorChildActiveHover`, `itemIconColorChildActiveHoverHorizontal`, `itemIconColorChildActiveHover`,`itemTextColorChildActiveHoverHorizontal`, `itemTextColorChildActiveHover`, `arrowColorChildActiveHoverInverted`, `itemIconColorChildActiveHoverHorizontalInverted`, `itemIconColorChildActiveHoverInverted`,`itemTextColorChildActiveHoverHorizontalInverted`, `itemTextColorChildActiveHoverInverted` theme variables, closes [#2929](https://github.com/tusen-ai/naive-ui/issues/2929).\n\n### Fixes\n\n- Fix `n-menu` `node-props` is not applied to element with `role=\"menuitem\"` but a inner element.\n- Fix `n-menu` `node-props` doesn't work with `type=\"group\"` option.\n\n## 2.30.0\n\n`2022-06-06`\n\n### Breaking Changes\n\n- Theme variable `closeColor`, `closeColorHover`, `closeColorPressed` are renamed to `closeIconColor`, `closeIconColorHover`,`closeIconColorPressed`. `closeColorHover`, `closeColorPressed` still exist, controlling background color of close button.\n- `n-tag`'s `colorXxx` theme variables are renamed to `colorBorderedXxx`. `colorXxx` still exists, controlling background color of borderless tag.\n\n### Fixes\n\n- Fix `createDiscreteApi` not working with `'loadingBar'`.\n- Fix `n-popover` background color shifts when closed on theme changing.\n- Fix `n-select`'s menu position doesn't sync with select box when select box's size is changed.\n- Fix `n-scrollbar` can't show horizontal scrollbar, closes [#3047](https://github.com/tusen-ai/naive-ui/issues/3047).\n- Fix `n-tree` node's pressed style is prior to selected style when `:block-line=\"true\"` and `:selectable=\"true\"`.\n- Fix `n-slider` may leak event handler on edga case.\n- Fix `n-data-table` doesn't restore scroll state when it's reactivated inside `keep-alive` component, closes [#2522](https://github.com/tusen-ai/naive-ui/issues/2522).\n- Fix `n-image` zoom level doesn't fit ultra large image.\n- Fix `n-menu`'s dropdown option text style when some of it's descendants is activated.\n- Fix `n-input`'s `input-props` prop's `class` & `style` not working.\n\n### Feats\n\n- 🌟 `n-time-picker` adds `time-zone` prop, closes [#293](https://github.com/tusen-ai/naive-ui/issues/293).\n- 🌟 `n-input-number` adds `parse` prop.\n- 🌟 `n-input-number` adds `format` prop.\n- 🌟 `n-input-number` adds `precision` prop, closes [#2068](https://github.com/tusen-ai/naive-ui/issues/2068), [#1859](https://github.com/tusen-ai/naive-ui/issues/1859).\n- 🌟 `n-image` adds a switch to display the original size of the picture, closes [#3023](https://github.com/tusen-ai/naive-ui/issues/3023).\n- 🌟 All components' close buttons use new style and are focusable.\n- All components' select menu & dropdown menu's options use new style.\n- `n-tag` adds `icon` slot.\n- `n-tag` adds `strong` prop.\n- `n-tag` adds background color in dark theme when `:bordered=\"false\"`, closes [#1699](https://github.com/tusen-ai/naive-ui/issues/1699).\n- `n-time` adds `time-zone` prop.\n- `n-breadcrumb-item` adds `clickable` prop.\n- `n-breadcrumb-item` uses new style, adds `itemLineHeight`, `itemBorderRadius`, `itemColorHover`, `itemColorPressed` theme variables.\n- `n-notification` optimizes title style when it's too long.\n- `n-drawer` optimizes title style when it's too long.\n- `n-dialog` optimizes title style when it's too long.\n- `n-card` optimizes title style when it's too long.\n\n## 2.29.1\n\n`2022-06-03`\n\n### Fixes\n\n- Fix `n-tree` throw error when use `pattern` prop filter the tree node, closes [#2960](https://github.com/tusen-ai/naive-ui/issues/2960).\n- Fix `n-watermark` not working when `cls-prefix` is set.\n- Fix `n-dropdown`'s incorrect render arrow when `:show-arrow=\"true\"`, closes [#2977](https://github.com/tusen-ai/naive-ui/issues/2977).\n- Fix `n-upload-dragger` doesn't take full width.\n- Fix `n-global-style` doesn't clear body element's padding and margin.\n- Fix `n-modal` won't clear document body's overflow style if it's unmounted when it is shown, closes [#3015](https://github.com/tusen-ai/naive-ui/issues/3015).\n- Fix keyboard operation doesn't work in some specific old browsers.\n- Fix `n-tabs` lacks tab padding when `justify-content` is `'start'`, `'end'` or `'center'`.\n- Fix `n-tabs` doesn't update bar's position after `justify-content` or `size` is updated.\n- Fix `n-switch` has no transition effect when toggle `disabled`.\n- Fix `n-modal` & `n-drawer` will be closed on esc pressed during IME input, closes [#2989](https://github.com/tusen-ai/naive-ui/issues/2989).\n- Fix `n-date-picker` can select time when is selecting date in date time range picker, closes [#3004](https://github.com/tusen-ai/naive-ui/issues/3004).\n- Fix `n-pagination` has display issue when `:page-count=\"0\"`, closes [#2970](https://github.com/tusen-ai/naive-ui/issues/2970).\n- Fix `n-date-picker`'s `shortcuts` will be overrided by `default-time` when `type=\"datetimerange\"`, closes [#3020](https://github.com/tusen-ai/naive-ui/issues/3020).\n- Fix `n-image-group` switch pictures doesn't work in SSR mode.\n- Fix `n-tabs`'s height transition sometimes not applied when `display-directive=\"show\"` and `:animated=\"true\"`, closes [#3035](https://github.com/tusen-ai/naive-ui/issues/3035).\n- Fix `n-select`'s filter font size is a bit small in single select mode.\n- Fix `n-select`'s count tag's popover is too high when overflow tag's count is small.\n- Fix `n-date-picker`'s first time scroll state of items is not aligned when `type=\"monthrange\"`.\n- Fix `n-form-item`'s asterisk in required mode can be selected.\n- Fix `n-list`'s color is incorrect inside `n-popover` in dark mode.\n\n### Feats\n\n- 🌟 `n-select` adds `label-field` prop, closes [#3018](https://github.com/tusen-ai/naive-ui/issues/3018).\n- 🌟 `n-select` adds `value-field` prop, closes [#3018](https://github.com/tusen-ai/naive-ui/issues/3018).\n- 🌟 `n-steps` adds `on-update:current` prop.\n- 🌟 `n-date-picker` adds `panel` prop.\n- 🌟 `n-data-table` adds `on-scroll` prop, closes [#3025](https://github.com/tusen-ai/naive-ui/issues/3025).\n- 🌟 `FormItemRule` adds `renderMessage` prop, closes [#2525](https://github.com/tusen-ai/naive-ui/issues/2525).\n- 🌟 Add `createDiscreteApi` to create message, notification, dialog, loading bar outside setup.\n- `n-scrollbar` adds `trigger` prop.\n- `n-input-number` adds `button-placement` prop.\n- `n-select` adds `children-field` prop, closes [#3018](https://github.com/tusen-ai/naive-ui/issues/3018).\n- `n-upload` adds `trigger-style` prop.\n- `n-dropdown` adds `node-props` prop.\n- `n-dropdown` adds `render-option` prop.\n- `n-upload` adds `is-error-state` prop, closes [#2975](https://github.com/tusen-ai/naive-ui/issues/2975).\n- `n-date-picker`'s `shortcuts` prop supports readonly tuple type.\n- `n-step` adds `disabled` prop.\n- `n-calendar` adds `header` slot, closes [#3036](https://github.com/tusen-ai/naive-ui/issues/3036).\n- `n-tree` adds `expand-on-click` prop， [#2949](https://github.com/tusen-ai/naive-ui/issues/2949).\n\n## 2.29.0\n\n`2022-05-18`\n\n### Breaking Changes\n\n- Since `n-pagination` supports `size` prop, some theme variables of `n-pagination` are changed.\n\n### Fixes\n\n- Fix `n-menu` use `render-icon` function render incorrect when returns `true`.\n- Fix `n-tabs`'s `tabFontWeightActive` theme varialbe applies to all tabs, closes [#2926](https://github.com/tusen-ai/naive-ui/issues/2926).\n- Fix `n-tree-select`'s `default-expand-all` not working.\n- Fix `n-upload`'s `accept` prop doesn't work in drag & drop mode, closes [#2919](https://github.com/tusen-ai/naive-ui/issues/2919).\n- Fix `n-calendar`'s `on-panel-change` returning wrong month value when clicking Today.\n- Fix `n-time` throws error caused by `getTimezoneOffset` in SSR mode, closes [#2545](https://github.com/tusen-ai/naive-ui/issues/2545).\n- Fix `n-transfer`'s search box's box-shadow is truncated.\n- Fix `n-time-picker`'s input box's invalid value won't be cleared after blur.\n\n### Feats\n\n- `n-notification-provider`'s `placement` prop supports `'top'` and `'bottom'`, closes [#2930](https://github.com/tusen-ai/naive-ui/issues/2930).\n- `n-pagination` add `size` prop, closes [#2888](https://github.com/tusen-ai/naive-ui/issues/2888).\n- `n-config-provider` adds `preflight-style-disabled` prop.\n- `n-pagination`'s quick jumper only allow integer input, closes [#2928](https://github.com/tusen-ai/naive-ui/issues/2928).\n- `n-pagination` will jump to the first / last page when its value is out of range, closes [#2928](https://github.com/tusen-ai/naive-ui/issues/2928).\n- `n-color-picker` adds `on-confirm` prop.\n- `n-input` adds `clear-icon` slot.\n- `n-date-picker` adds `date-icon` slot, closes [#2668](https://github.com/tusen-ai/naive-ui/issues/2668).\n- `n-date-picker` adds `separator` slot, closes [#2668](https://github.com/tusen-ai/naive-ui/issues/2668).\n\n### i18n\n\n- Add nlNL locale.\n\n## 2.28.4\n\n`2022-05-11`\n\n### Fixes\n\n- Fix `n-theme-editor`'s content can't be scrolled.\n\n## 2.28.3\n\n`2022-05-11`\n\n### Fixes\n\n- Fix `n-menu`'s `dropdown-props` prop can't override `n-dropdown`'s `size` prop, closes [#2868](https://github.com/tusen-ai/naive-ui/issues/2868).\n- Fix `n-switch` abnormal loading animation when switching state, closes [#2870](https://github.com/tusen-ai/naive-ui/issues/2870).\n- Fix `n-data-table` doesn't show content when page is more than data's page, closes [#2840](https://github.com/tusen-ai/naive-ui/issues/2840).\n- Fix `n-data-table`'s `cellProps` doesn't has correct generic type.\n- Fix `n-data-table`'s `work-break` isn't `break-word`.\n- Fix `n-list`'s css variable `n-merged-color` is not correct.\n- Fix `MessageReactive`'s `destroy` method throws error if message has disappeared.\n- Fix `n-ellpisis` can't show tooltip if content width is very close to container width, closes [#1393](https://github.com/tusen-ai/naive-ui/issues/1393), [#2899](https://github.com/tusen-ai/naive-ui/issues/2899).\n- Fix `n-tree` can't use `width: fit-content;` style, closes [#2875](https://github.com/tusen-ai/naive-ui/issues/2875).\n- Fix `n-dropdown`'s `on-update:show` prop will be triggered twice, closes [#2905](https://github.com/tusen-ai/naive-ui/issues/2905).\n- Fix `n-select` can select option by pressing enter after options are cleared.\n- Fix `n-data-table`'s `selection` and `expand` column can't set width.\n- Fix `n-checkbox` contains selectable whitespace.\n- Fix `DescriptionsProps` is misspelled as `DescriptionProps`.\n- Fix `n-icon` misses `IconProps`.\n- Fix `n-icon-wrapper` misses `IconWrapperProps`.\n- Fix `n-countdown`'s display value is 1s faster than actual left time when `precision=0`, closes [#2910](https://github.com/tusen-ai/naive-ui/issues/2910).\n\n### Feats\n\n- `n-menu` adds `node-props` prop.\n- `n-switch` adds `rubber-band` prop.\n- `n-space`'s `justify` prop supports `'space-evenly'`.\n- `n-popover` adds `content-style` prop.\n- `n-popover` adds `header-style` prop.\n- `n-popover` adds `scrollable` prop.\n- `n-select` & `n-cascader` & `n-tree-select`'s overflow count tag's popover is scrollable.\n- `n-data-table` adds `pagination-behavior-on-filter` prop.\n- `n-date-picker`'s `type` prop supports `monthrange` option.\n- `n-date-picker` adds `on-clear` prop.\n- `n-date-picker` adds `on-confirm` prop, closes [#2852](https://github.com/tusen-ai/naive-ui/issues/2852).\n- `n-data-table`'s `columns`'s element supports `minWidth` prop.\n- `n-tree` adds `checkbox-placement` prop.\n- `n-tree-select` adds `loading` prop, closes [#2857](https://github.com/tusen-ai/naive-ui/issues/2857).\n- `n-modal` adds `block-scroll` prop, closes [#2556](https://github.com/tusen-ai/naive-ui/issues/2556).\n- `n-drawer` adds `block-scroll` prop, closes [#2556](https://github.com/tusen-ai/naive-ui/issues/2556).\n- `n-drawer` adds `show-mask` prop, closes [#2556](https://github.com/tusen-ai/naive-ui/issues/2846).\n- `useDialog().xxx` supports `blockScroll` option, closes [#2556](https://github.com/tusen-ai/naive-ui/issues/2556).\n- `useDialog().xxx` supports `autoFocus` option.\n- `n-button` adds `native-focus-behavior` prop, closes [#2882](https://github.com/tusen-ai/naive-ui/issues/2882).\n- `n-time-picker` adds `on-confirm` prop.\n- `n-time-picker` adds `on-clear` prop.\n- `n-time-picker` adds `on-update:show` prop.\n- `n-time-picker` adds `show` prop.\n- `n-date-picker` adds `on-update:show` prop.\n- `n-date-picker` adds `show` prop.\n- `n-date-picker` adds `default-calendar-start-time` prop, closes [#2732](https://github.com/tusen-ai/naive-ui/issues/2732).\n- `n-date-picker` adds `default-calendar-end-time` prop, closes [#2732](https://github.com/tusen-ai/naive-ui/issues/2732).\n- `n-date-picker` adds `bind-calendar-months` prop, closes [#2751](https://github.com/tusen-ai/naive-ui/issues/2751).\n- `n-upload` adds `directory` prop.\n- `n-upload` adds `directory-dnd` prop.\n- `UploadFileInfo` adds `fullPath` and `batchId` attrs.\n- `DataTableBaseColumn` adds `tree` attr, closes [#2757](https://github.com/tusen-ai/naive-ui/issues/2757).\n\n## 2.28.2\n\n`2022-04-22`\n\n### Fixes\n\n- Fix `date-picker` `actions`'s type can't be `null`.\n- Fix `time-picker` `actions`'s type can't be `null`.\n- Fix `n-tree-select`'s meaningless warning.\n- Fix `n-tree-select`'s `allow-checking-not-loaded` prop doesn't work.\n- Fix `n-tree-select`'s menu position may not sync with trigger box if `:allow-checking-not-loaded=\"true\"`.\n- Fix `n-cascader`'s menu position may not sync with trigger box if `:allow-checking-not-loaded=\"true\"`.\n\n## 2.28.1\n\n`2022-04-20`\n\n### Fixes\n\n- Fix `notification` icon won't show after first notification is emitted in SSR mode, closes [#2793](https://github.com/tusen-ai/naive-ui/issues/2793).\n- Fix `dialog` icon won't show after first dialog is displayed in SSR mode.\n- Fix `n-drawer` & `n-modal` may overflow screen on opening if `:autofocus=\"true\"`.\n- Fix `n-tree-select`'s filter not working correctly when `children-field` is not set, closed [#2789](https://github.com/tusen-ai/naive-ui/issues/2789).\n- Fix `n-tree-select`'s matched style is not cleared after filter value is cleared.\n- Fix `n-tree-select`'s parent items in tree are selectable when `check-strategy=\"child\"` and `:cascade=\"false\"`, closes [#2780](https://github.com/tusen-ai/naive-ui/issues/2780).\n- Fix `n-select`'s `empty` slot can't let `n-input` focus inside, closes [#2812](https://github.com/tusen-ai/naive-ui/issues/2812).\n- Fix `n-select`'s menu is invisible in fullscreen mode, closes [#2722](https://github.com/tusen-ai/naive-ui/issues/2722).\n- Fix `n-color-picker`'s `value` prop can't be `null`.\n- Fix `n-table`'s border color shifts when switch bewteen different props.\n\n### Feats\n\n- `n-input-number` adds `add-icon` and `minus-icon` slots, closes [#2668](https://github.com/tusen-ai/naive-ui/issues/2668).\n- `n-dynamic-input` adds `RTL` support.\n- `n-table` adds `RTL` support.\n- `n-collapse-transition` adds `RTL` support.\n- `n-tree` adds `show-irrelevant-nodes` prop, closes [#2764](https://github.com/tusen-ai/naive-ui/issues/2764).\n- `n-tree-select` adds `allow-checking-not-loaded` prop.\n- `n-cascader` adds `allow-checking-not-loaded` prop.\n- `n-tree` adds `allow-checking-not-loaded` prop.\n- `n-button-group` adds `RTL` support.\n\n### i18n\n\n- Add ptBR locale.\n- Add koKR locale.\n\n## 2.28.0\n\n`2022-04-11`\n\n### Breaking Changes\n\n- `n-time` uses `formatDistanceStrict` rather than `formatDistance` in `date-fns`, closes [#2703](https://github.com/tusen-ai/naive-ui/issues/2703).\n\n### Fixes\n\n- Fix `n-tabs` has unexpected line animation when nested with `n-tabs`, closes [#2689](https://github.com/tusen-ai/naive-ui/issues/2689).\n- Fix `n-popconfirm` with no body content has wrong margin top, closes [#2690](https://github.com/tusen-ai/naive-ui/issues/2690).\n- Fix `n-tree-select` unexpected warning.\n- Fix `n-calendar`'s disabled cells are clickable, closes [#2686](https://github.com/tusen-ai/naive-ui/issues/2686).\n- Fix message icon won't show after first message is emitted in SSR mode, closes [#2721](https://github.com/tusen-ai/naive-ui/issues/2721).\n- Fix `n-popconfirm`'s `positive-button-props` and `negative-button-props` props lack reactivity, closes [#2753](https://github.com/tusen-ai/naive-ui/issues/2753).\n- Fix `n-step` has unexpected theme variable class.\n- Fix `n-steps` displays uncorrectly when nested in vertical & horizontal mode.\n- Fix `n-popconfirm`'s `positive-text` & `negetive-text` props don't allow `null` type.\n- Fix `n-color-picker` can't be closed if mousedown.stop is set when click outside, closes [#2709](https://github.com/tusen-ai/naive-ui/issues/2709).\n- Fix `n-tabs` switch animation is incorrect when `display-directive='show'`, closes [#2718](https://github.com/tusen-ai/naive-ui/issues/2718).\n\n### Feats\n\n- `n-radio` adds `label` prop, closes [#2707](https://github.com/tusen-ai/naive-ui/issues/2707).\n- `n-drawer` adds `on-after-enter` and `on-after-leave` props, closes [#2698](https://github.com/tusen-ai/naive-ui/issues/2698).\n- `n-data-table` adds `paginate-single-page` prop , closes [#2043](https://github.com/tusen-ai/naive-ui/issues/2043).\n- `n-pagination` add `RTL` support.\n- `n-alert` add `RTL` support.\n- `n-data-table` adds `allow-checking-not-loaded` prop, closes [#2758](https://github.com/tusen-ai/naive-ui/issues/2758).\n\n## 2.27.0\n\n`2022-03-27`\n\n### Breaking Changes\n\n- `n-menu` has some style changes.\n\n### Fixes\n\n- Fix `n-data-table`‘s row disorder when using `expand` type, closes [#2631](https://github.com/tusen-ai/naive-ui/issues/2631).\n- Fix `n-popconfirm` doesn't has `setShow` & `syncPosition` methods.\n- Fix `n-popselect` doesn't has `setShow` & `syncPosition` methods.\n- Fix `n-menu` theme's peers missing `Dropdown`.\n- Fix `n-color-picker` can't input 0 as unit's value, closes [#2680](https://github.com/tusen-ai/naive-ui/issues/2680).\n- Fix `n-tree`'s scrollbar overflows in virtual scroll mode, closes [#2673](https://github.com/tusen-ai/naive-ui/issues/2673).\n- Fix `n-layout-sider`'s `content-style` can't override `overflow: auto` prop, closes [#2671](https://github.com/tusen-ai/naive-ui/issues/2671).\n- Fix `n-date-picker` displays panel item abnormally with `month` and `quarter` type in dark mode.\n- Fix `n-dropdown` `onUpdateShow` not working.\n- Fix `n-auto-complete` `onSelect` is triggered after `onUpdate:value`.\n- Fix `n-data-table` `initiatorColumn` in `onUpdate:filters`'s type is an optional parameter.\n\n### Feats\n\n- `n-tree-select` adds `on-load` prop, closes [#2550](https://github.com/tusen-ai/naive-ui/issues/2550).\n- `n-data-table` adds `on-load` prop.\n- `n-cascader` adds `menu-props` prop, closes [#2600](https://github.com/tusen-ai/naive-ui/issues/2600).\n- `n-cascader` adds `filter-menu-props` prop, closes [#2600](https://github.com/tusen-ai/naive-ui/issues/2600).\n- `n-badge` adds `value` slot.\n- `n-form` adds `validate-messages` prop.\n- `n-data-table`'s column supports `cellProps` prop, closes [#2625](https://github.com/tusen-ai/naive-ui/issues/2625).\n- `n-step` adds class to distinguish status.\n- `n-popconfirm` adds `negative-button-props` props, closes [#2642](https://github.com/tusen-ai/naive-ui/issues/2642).\n- `n-popconfirm` adds `positive-button-props` props, closes [#2642](https://github.com/tusen-ai/naive-ui/issues/2642).\n- `n-pagination` adds `goto` slot.\n- `n-input` adds `password-visible-icon` slot.\n- `n-input` adds `password-invisible-icon` slot.\n- `n-select` adds `status` prop.\n- `n-input-number` adds `status` prop.\n- `n-auto-complete` adds `status` prop.\n- `n-cascader` adds `status` prop.\n- `n-date-picker` adds `status` prop.\n- `n-time-picker` adds `status` prop.\n- `n-mention` adds `status` prop.\n- `n-tree-select` adds `status` prop.\n- `n-menu` adds `showOption` method, closes [#2562](https://github.com/tusen-ai/naive-ui/issues/2562).\n- `n-dynamic-tags`'s `value` support object typed option.\n- `n-dynamic-tags` adds `render-tag` prop, closes [#2526](https://github.com/tusen-ai/naive-ui/issues/2526).\n- `n-dynamic-tags` adds `on-create` prop, closes [#2576](https://github.com/tusen-ai/naive-ui/issues/2576).\n- `n-date-picker` adds `time-picker-props` props, closes [#2660](https://github.com/tusen-ai/naive-ui/issues/2660).\n- `n-tabs` adds `trigger` prop, closes [#2679](https://github.com/tusen-ai/naive-ui/issues/2679).\n- `n-menu` adds `itemColorHover`, `itemColorActiveHover`, `itemTextColorActiveHover`, `itemTextColorHorizontal`, `itemTextColorHoverHorizontal`, `itemTextColorActiveHorizontal`, `itemTextColorActiveHoverHorizontal`, `itemTextColorChildActiveHorizontal`, `itemIconColorActiveHover`, `itemIconColorHorizontal`, `itemIconColorHoverHorizontal`, `itemIconColorActiveHorizontal`, `itemIconColorActiveHoverHorizontal`, `itemIconColorChildActiveHorizontal`, `arrowColorActiveHover`, `itemColorHoverInverted`, `itemColorActiveHoverInverted`, `itemTextColorActiveHoverInverted`, `itemTextColorHorizontalInverted`, `itemTextColorHoverHorizontalInverted`, `itemTextColorChildActiveHorizontalInverted`, `itemTextColorActiveHorizontalInverted`, `itemTextColorActiveHoverHorizontalInverted`, `itemIconColorActiveHoverInverted`, `itemIconColorHorizontalInverted`, `itemIconColorHoverHorizontalInverted`, `itemIconColorActiveHorizontalInverted`, `itemIconColorActiveHoverHorizontalInverted`, `itemIconColorChildActiveHorizontalInverted`, `arrowColorActiveHoverInverted` theme variables, closes [#2598](https://github.com/tusen-ai/naive-ui/issues/2598).\n- `n-carousel` adds `next-slide-style` and `prev-slide-style` props, closes [#2340](https://github.com/tusen-ai/naive-ui/issues/2340).\n- `n-dialog` adds `negative-button-props` prop.\n- `n-dialog` adds `positive-button-props` prop.\n- `n-tabs` adds `animated` prop.\n\n### i18n\n\n- Add thTH locale.\n\n## 2.26.4\n\n`2022-03-11`\n\n### Fixes\n\n- Fix `n-tree-select`s in `multiple` mode cannot delete options whose `default-value` attribute contains parent node, closes [#2605](https://github.com/tusen-ai/naive-ui/issues/2605).\n- Fix `n-tree` may throw error when node is removed, closes [#2597](https://github.com/tusen-ai/naive-ui/issues/2597).\n- Fix `useDialog` renders component with popup content with unexpected focus management behavior, closes [#2612](https://github.com/tusen-ai/naive-ui/issues/2612).\n- Fix `n-tree-select`'s node sometimes can't be clicked when `check-strategy` is `'child'`.\n- Fix `n-tree-select`'s emitted value can be not corresponding to `check-strategy` when delete option in select box with `check-strategy` is not `'all'`.\n\n### Feats\n\n- `useDialog` supports `closeOnEsc` prop.\n- `n-data-table` exports `DataTableFilterState` type.\n- `n-data-table` exports `DataTableSortState` type.\n\n## 2.26.3\n\n`2022-03-09`\n\n### Fixes\n\n- Fix `n-button`'s loading icon shifts.\n\n## 2.26.2\n\n`2022-03-09`\n\n### Fixes\n\n- Fix `n-cascader` arrow's loading animation last for too long time.\n- Fix `n-select` menu doesn't follow theme.\n- Fix `n-tabs` throws error without child, closes [#809](https://github.com/tusen-ai/naive-ui/issues/809).\n- Fix `n-menu`'s font color is not changed after theme is changed in chrome 99, closes [#2563](https://github.com/tusen-ai/naive-ui/issues/2563). This is actual a bug of chrome, however we used a workaround and fixed it.\n- Fix `n-date-picker`'s date item click trigger area is as large as cell size only in `'date'` mode.\n\n### Feats\n\n- `n-dynamic-tags` `input` slot add `deactivate` prop, closes [#2575](https://github.com/tusen-ai/naive-ui/issues/2575).\n- `n-space` add `RTL` support.\n- `n-avatar-group` add `RTL` support.\n- `n-badge` add `RTL` support.\n- `n-radio` add `RTL` support.\n- `n-auto-complete` adds `focus` method.\n- `n-auto-complete` adds `blur` method.\n\n## 2.26.1\n\n`2022-03-06`\n\n### Fixes\n\n- Fix `base-loading` use css transition rather than svg animateTrantion to prevent js blocking, close [#2506](https://github.com/tusen-ai/naive-ui/issues/2506).\n- Fix `n-time` throws error caused by `getTimezoneOffset`, closes [#2545](https://github.com/tusen-ai/naive-ui/issues/2545).\n- Fix `n-modal`'s mask doesn't have enter & leave transition.\n- Fix `n-timeline` has style conflict when vertical & horizontal `n-timeline` are nested, closes [#2549](https://github.com/tusen-ai/naive-ui/issues/2549).\n- Fix `n-tree`'s arrow & loading switch animation isn't complete.\n\n### Feats\n\n- `n-time-line-item` adds `line-type` prop, closes [#2548](https://github.com/tusen-ai/naive-ui/issues/2548).\n- `n-step` adds `icon` slot, closes [#2547](https://github.com/tusen-ai/naive-ui/issues/2547).\n- `n-input-number` adds `autofocus` prop, closes [#2551](https://github.com/tusen-ai/naive-ui/issues/2551).\n- `n-date-picker`'s date item click trigger area is as large as cell size, closes [#2552](https://github.com/tusen-ai/naive-ui/issues/2552).\n\n## 2.26.0\n\n`2022-03-02`\n\n### Breaking Changes\n\n- Fix `n-tooltip`'s gap between arrow and body. `n-tooltip` can't be translucent anymore.\n\n### Feats\n\n- `n-popover` adds `arrow-point-to-center` prop.\n- `n-config-provider` adds `inline-theme-disabled` prop.\n\n## 2.25.8\n\n`2022-03-01`\n\n### Fixes\n\n- Fix `useMessage` loses styles.\n\n## 2.25.7\n\n`2022-03-01`\n\n### Fixes\n\n- Fix `n-time-picker` still shows action bar when `:actions=\"null\"`.\n- Fix `n-input`'s content may overflow when `type=\"text\"` and `autosize` is enabled, closes [#2505](https://github.com/tusen-ai/naive-ui/issues/2505).\n- Fix `n-upload` put `file` field before other `FormData` fields, closes [#2504](https://github.com/tusen-ai/naive-ui/issues/2504).\n- Fix `n-button` rtl support.\n- Fix `n-form-item-row` can't call `n-form-item`'s methods.\n\n### Feats\n\n- `n-collapse` add `RTL` support.\n- `useMessage` adds `create` methods.\n- `useMessage` adds `showIcon` prop, closes [#2495](https://github.com/tusen-ai/naive-ui/issues/2495).\n- `useMessage` supports `'default'` `type`.\n- `n-checkbox` supports label line wrap, closes [#2419](https://github.com/tusen-ai/naive-ui/issues/2419).\n- `n-radio` supports label line wrap, closes [#2419](https://github.com/tusen-ai/naive-ui/issues/2419).\n- `n-checkbox` add `RTL` support.\n- `n-input` add `RTL` support.\n- `n-input-number` add `RTL` support.\n\n## 2.25.5\n\n`2022-02-24`\n\n### Fixes\n\n- Fix `n-col` can't be wrapped correctly when `span=6`, closes [#2497](https://github.com/tusen-ai/naive-ui/issues/2497).\n- Fix `n-tabs` doesn't display border-bottom in scroll area on large number of tabs, closes [#2500](https://github.com/tusen-ai/naive-ui/issues/2500).\n\n## 2.25.3\n\n`2022-02-23`\n\n### Fixes\n\n- Fix `n-switch` can't use keyboard operation when checked value is customized.\n- Fix `n-data-table`'s fixed column is covered by scroll content when placed inside popover.\n- Fix `n-data-table` when the `filterOptions` value is 0, the filter will not take effect, closes [#2392](https://github.com/tusen-ai/naive-ui/issues/2392).\n- Fix `n-data-table` cannot click selection checkbox if the selection column is a column's child.\n- Fix `n-table`'s `border-color` abnormal style when this added dynamically, closes [#2403](https://github.com/tusen-ai/naive-ui/issues/2403).\n- Fix `n-tree`'s `default-expand-all` prop doesn't work for dynamic data.\n- Fix `n-form` when `model.xxx` is `undefined`, validator will use `null` as validation value, closes [#2486](https://github.com/tusen-ai/naive-ui/issues/2486).\n- Fix `n-input` focus style's priority is lower than hover style, closes [#2480](https://github.com/tusen-ai/naive-ui/issues/2480).\n- Fix `n-data-table` display issue when placed inside keep-alive component with virtual scroll, closes [#2183](https://github.com/tusen-ai/naive-ui/issues/2183).\n- Fix `notification` enter & leave animation.\n\n### Feats\n\n- `n-tree-select` adds `clear-filter-after-select` prop.\n- `n-cascader` adds `clear-filter-after-select` prop.\n- `n-switch` adds `icon` slot.\n- `n-switch` adds `checked-icon` slot.\n- `n-switch` adds `unchecked-icon` slot.\n- `n-tabs` uses `n` as CSS vars prefix.\n- Add `n-watermark` component, closes [#1745](https://github.com/tusen-ai/naive-ui/issues/1745).\n- `n-scrollbar` adds `scrollBy` method, closes [#2435](https://github.com/tusen-ai/naive-ui/issues/2435).\n- `n-data-table`'s `summary`'s `value` supports `VNodeChild`, closes [#2339](https://github.com/tusen-ai/naive-ui/issues/2339).\n- `n-input-number` adds hold click to increment, closes [#1293](https://github.com/tusen-ai/naive-ui/issues/1293).\n- `n-description` adds `titleTextColor` theme variable.\n\n### i18n\n\n- Add skSK locale.\n- Fix frFR locale.\n\n## 2.25.2\n\n`2022-02-11`\n\n### Fixes\n\n- Remove useless `console.log` in `resolveSlot`.\n- Fix `n-tag` misses background color when `checkable=true`.\n- Fix `n-tree` throws `Image` error in `happydom` testing environment.\n- Fix `n-select` `max-tag-count` tag size doesn't follow select size.\n\n### Feats\n\n- `n-progress` props `type` add type `dashboard`.\n- `n-progress` adds `gap-degree` prop.\n- `n-progress` adds `gap-offset-degree` prop.\n- `n-select` adds `clear-filter-after-select` prop, closes [#2352](https://github.com/tusen-ai/naive-ui/issues/2352).\n\n### i18n\n\n- Add plPL locale, closes [#2354](https://github.com/tusen-ai/naive-ui/issues/2354).\n- Add eo locale.\n\n## 2.25.1\n\n`2022-02-06`\n\n### i18n\n\n- Add enGB locale.\n- Fix deDE locale.\n\n## 2.25.0\n\n`2022-02-04`\n\n### Breaking Changes\n\n- Refactor `n-carousel`'s style when `show-arrow` is true.\n\n### Fixes\n\n- Fix `n-color-picker`'s hue & alpha slider handle are influenced by rail's box-shadow.\n- Fix `n-form-item` prevent feedback padding when empty.\n- Fix `n-button` has extra margin in safari.\n- Fix `n-form`'s rules and `n-form-item`'s rule about `validator` and `asyncValidator`'s `rule` type is not `FormItemRule`, closes [#2299](https://github.com/tusen-ai/naive-ui/issues/2299).\n- Fix `n-log` doesn't break line when line is too long, closes [#2298](https://github.com/tusen-ai/naive-ui/issues/2298).\n- Fix `n-log` doesn't export `LogInst` type.\n- Fix `n-popselect` action slot & empty slot now working.\n- Fix `n-data-table` can't use percent as column width.\n- Fix `n-select` trigger shows blank for a while when `filterable=true` and menu is closing.\n- Fix `n-select`'s being created option is not cleared after menu is closed.\n- Fix `n-select` can't input content when `show=false` and `filterable=true`, closes [#1723](https://github.com/tusen-ai/naive-ui/issues/1723).\n- Fix `n-dropdown` has extra margin when `trigger=\"manual\"`.\n- Fix `web-types.json`'s `n-h1` ~ `n-h6` name.\n- Fix `n-select` deletes option on backspace pressed while compisiting.\n- Fix `n-select` uses disabled option as pending option after menu is opened.\n\n### Feats\n\n- `n-tabs` props `justify-content` add types `start` `center` `end`.\n- `n-auto-complete` adds `placement` prop.\n- `n-cascader` adds `placement` prop.\n- `n-color-picker` adds `placement` prop.\n- `n-date-picker` adds `placement` prop.\n- `n-mention` adds `placement` prop.\n- `n-select` adds `placement` prop.\n- `n-slider` adds `placement` prop.\n- `n-time-picker` adds `placement` prop.\n- `n-tree-select` adds `placement` prop.\n- `n-card` adds `header-extra-style` prop.\n- `n-popover` adds `keep-alive-on-hover` prop, closes [#2326](https://github.com/tusen-ai/naive-ui/issues/2326).\n- `n-input` adds `status` prop.\n- Add `n-icon-wrapper` component.\n- `n-popover` exports `PopoverPlacement` type.\n- `n-drawer` exports `DrawerPlacement` type.\n- `n-dynamic-tags` adds `input-props` prop.\n- `n-notification-provider` adds `container-style` prop.\n- `n-notification-provider` exports `NotificationPlacement` type.\n- `n-notification-provider` exports `NotificationType` type.\n- `n-tabs` add `bar-width` prop.\n- `n-dynamic-input` adds `create-button-props` props.\n- `n-dynamic-input` adds `create-button-default` slot.\n- `n-dynamic-input` adds `create-button-icon` slot.\n- `n-dynamic-input` adds `show-sort-button` prop, closes [#2121](https://github.com/tusen-ai/naive-ui/issues/2121).\n- `n-select` can be used as tag input.\n- `n-select` exports `SelectRenderLabel` type.\n- `n-select` exports `SelectRenderOption` type.\n- `n-select` exports `SelectRenderTag` type.\n- `n-tree` adds `node-props` prop.\n\n## 2.24.7\n\n`2022-01-28`\n\n### Fixes\n\n- `n-popselect` doesn't work with `width=\"trigger\"`.\n\n### i18n\n\n- Update jaJP locale.\n- Update deDE locale.\n\n## 2.24.6\n\n`2022-01-26`\n\n### Feats\n\n- `n-icon` add `component` prop.\n\n### Fixes\n\n- Fix `n-dynamic-input` can add item when max is 0, closes [#2271](https://github.com/tusen-ai/naive-ui/issues/2271).\n- Fix `n-dialog` useless `console.log`.\n\n## 2.24.5\n\n`2022-01-25`\n\n### Fixes\n\n- `n-input` placeholder has no line-wrap in `textarea` type.\n- `n-date-picker` lacks space between panel year & month.\n\n### Feats\n\n- `n-color-picker` adds `disabled` prop.\n- `n-date-picker` adds trigger area for year & month quick jump.\n\n## 2.24.4\n\n`2022-01-24`\n\n### Fixes\n\n- Update vueuc version.\n\n## 2.24.3\n\n`2022-01-24`\n\n### Fixes\n\n- Fix `n-layout-sider` has no border transition.\n\n## 2.24.2\n\n`2022-01-24`\n\n### Fixes\n\n- Fix `n-layout-sider` still occupies 1px after collapsed.\n- Fix `n-code` doesn't break word when `word-wrap=true`.\n- Fix `n-tab-pane`'s tab label area inherits `attrs`, closes [#2221](https://github.com/tusen-ai/naive-ui/issues/2221).\n- Fix `n-image` preview popup background can still be scrolled, closes [#2241](https://github.com/tusen-ai/naive-ui/issues/2241).\n- Fix `n-input` shows placeholder when browser auto completes it, closes [#2234](https://github.com/tusen-ai/naive-ui/issues/2234).\n- Fix `n-input` placeholder word break issue with `type=\"textarea\"`.\n- Fix `n-avatar-group` extra count not correct after `max` is set, closes [#2244](https://github.com/tusen-ai/naive-ui/issues/2244).\n- Fix `n-calendar` doesn't trigger `on-panel-change` on today button clicked.\n- Fix `n-drawer` can't be closed by esc key when `mask-closable=false`, closes [#2233](https://github.com/tusen-ai/naive-ui/issues/2233).\n\n### Feats\n\n- `n-page-header` adds `back` slot, closes [#2176](https://github.com/tusen-ai/naive-ui/issues/2176).\n- `n-select` adds `reset-menu-on-options-change` prop, closes [#2168](https://github.com/tusen-ai/naive-ui/issues/2168).\n- `n-select` adds `arrow` slot, closes [#2201](https://github.com/tusen-ai/naive-ui/issues/2201).\n- `n-carousel` effect supports `'card'`.\n- `n-input` doesn't use native scrollbar when `type=\"textarea\"`, closes [#2242](https://github.com/tusen-ai/naive-ui/issues/2242), [#1172](https://github.com/tusen-ai/naive-ui/issues/1172).\n- `n-number-animation` add `locale` prop, closes [#2181](https://github.com/tusen-ai/naive-ui/issues/2181).\n- `n-number-animation`'s locale follows config provider.\n- Expose `lightTheme`.\n- `n-time-picker` adds `icon` slot, closes [#2228](https://github.com/tusen-ai/naive-ui/issues/2228).\n- `n-tab-pane` adds `tab-props` prop, closes [#2221](https://github.com/tusen-ai/naive-ui/issues/2221).\n- Add `CustomThemeCommonVars` to customize `useThemeVars`.\n- `n-slider` adds `show-tooltip` prop, closes [#2212](https://github.com/tusen-ai/naive-ui/issues/2212).\n- `n-select` adds `on-update:show` prop.\n- `n-select` adds `focus` method, closes [#2202](https://github.com/tusen-ai/naive-ui/issues/2202).\n- `n-select` adds `blur` method, closes [#2202](https://github.com/tusen-ai/naive-ui/issues/2202).\n- `n-date-picker` adds `focus` method, closes [#2202](https://github.com/tusen-ai/naive-ui/issues/2202).\n- `n-date-picker` adds `blur` method, closes [#2202](https://github.com/tusen-ai/naive-ui/issues/2202).\n- `n-time-picker` adds `focus` method, closes [#2202](https://github.com/tusen-ai/naive-ui/issues/2202).\n- `n-time-picker` adds `blur` method, closes [#2202](https://github.com/tusen-ai/naive-ui/issues/2202).\n- `n-checkbox` adds `focus` method, closes [#2202](https://github.com/tusen-ai/naive-ui/issues/2202).\n- `n-checkbox` adds `blur` method, closes [#2202](https://github.com/tusen-ai/naive-ui/issues/2202).\n- `n-cascader` adds `focus` method, closes [#2202](https://github.com/tusen-ai/naive-ui/issues/2202).\n- `n-cascader` adds `blur` method, closes [#2202](https://github.com/tusen-ai/naive-ui/issues/2202).\n- `n-upload` adds `input-props` prop, closes [#2204](https://github.com/tusen-ai/naive-ui/issues/2204).\n- `n-data-table` col adds `render-sorter-icon` prop, closes [#1785](https://github.com/tusen-ai/naive-ui/issues/1785).\n- `n-data-table` col adds `render-sorter` prop, closes [#1785](https://github.com/tusen-ai/naive-ui/issues/1785).\n- `n-date-picker` easy navigation to specific month and year for `date` and `datetime` and `daterange` and `datetimerange` type.\n- `n-modal` adds `close-on-esc` prop.\n- `n-modal` adds `auto-focus` prop.\n- `n-modal` adds `trap-focus` prop.\n- `n-modal` adds `on-esc` prop.\n- `n-drawer` adds `close-on-esc` prop.\n- `n-drawer` adds `auto-focus` prop.\n- `n-drawer` adds `trap-focus` prop.\n- `n-drawer` adds `on-esc` prop.\n- `n-upload` adds `clear` method, closes [#2247](https://github.com/tusen-ai/naive-ui/issues/2247).\n- Add volar types.\n\n### i18n\n\n- Add esAR locale.\n- Add itIT locale.\n\n## 2.24.1\n\n`2022-01-12`\n\n### Fixes\n\n- Fix install error.\n\n## 2.24.0\n\n`2022-01-12`\n\n### Breaking Changes\n\n- Fix `type PageHeaderProps` name. It was mispelled as `PageHeaderPorps` before.\n- `n-image`'s `iconColor` theme variable is renamed as `toolbarIconColor`.\n\n### Fixes\n\n- Fix `n-carousel` when Carousel is a single picture dot still existence, closes [#1777](https://github.com/tusen-ai/naive-ui/issues/1777).\n- Fix `n-upload` `on-finish` prop's `event` parameter type should be `ProgressEvent`.\n- Fix `n-upload` doesn't allow 2xx status code except 200.\n- Fix `n-form` when `validate` use `validateCallback`, cannot call Promise method.\n- Fix `n-input-number` input integer end with 0 cannot update, closes [#2115](https://github.com/tusen-ai/naive-ui/issues/2115).\n- Fix `n-back-top` allow document to be passed to `listen-to` prop.\n- Fix `n-data-table`'s content can be clicked when loading, closes [#2134](https://github.com/tusen-ai/naive-ui/issues/2134).\n- Fix `n-checkbox` doesn't show indeterminate icon in safari.\n- Fix `n-progress`'s inner text of `line` type not aligned in center, closes[#2138](https://github.com/tusen-ai/naive-ui/issues/2138).\n- Fix `n-message`'s `MessageReactive` type lacks `type` parameter.\n- Fix `n-select` has different `padding` with `n-input`, closes [#2149](https://github.com/tusen-ai/naive-ui/issues/2149).\n- Fix `n-tooltip` log errors in console when used in `n-select`'s `render-option`, closes [#1436](https://github.com/tusen-ai/naive-ui/issues/1436).\n- Fix `n-select` log ResizeObserver errors when using `render-option` in safari, closes [#1671](https://github.com/tusen-ai/naive-ui/issues/1671).\n- Fix `n-carousel` can't respond quickly and repeatedly on touch, closes [#1892](https://github.com/tusen-ai/naive-ui/issues/1892).\n- Fix `n-carousel` style of boundary, closes [#1866](https://github.com/tusen-ai/naive-ui/issues/1866).\n- Fix `n-carousel` cannot be clicked on the touchscreen, closes [#1882](https://github.com/tusen-ai/naive-ui/issues/1882).\n- Fix `n-color-picker` default mode can only be rgb is default value is empty.\n\n### Feats\n\n- `n-code` adds `word-wrap` prop, closes [#2111](https://github.com/tusen-ai/naive-ui/issues/2111).\n- `n-modal` adds `z-index` prop, closes [#2088](https://github.com/tusen-ai/naive-ui/issues/2088).\n- `n-drawer` adds `z-index` closes.\n- `n-drawer` adds wai-aria support.\n- `useMessage`'s option support `render` prop.\n- `n-data-table` `TableColumn` supports `string` typed `width`, closes [#2102](https://github.com/tusen-ai/naive-ui/issues/2102).\n- `n-calendar` adds `on-panel-change` prop, closes [#2082](https://github.com/tusen-ai/naive-ui/issues/2082).\n- `n-upload` adds `on-error` prop.\n- `n-pagination` adds `label` slot.\n- `n-tabs` adds `syncBarPosition` method, closes [#2120](https://github.com/tusen-ai/naive-ui/issues/2120).\n- `n-form`, `n-form-item`'s `label-width` prop support `auto` option, closes [#2087](https://github.com/tusen-ai/naive-ui/issues/2087).\n- `n-result` adds `icon` slot, closes [#2130](https://github.com/tusen-ai/naive-ui/issues/2130).\n- `n-date-picker` adds `value-format` prop, closes [#2076](https://github.com/tusen-ai/naive-ui/issues/2076).\n- `n-date-picker` adds `formatted-value` prop.\n- `n-date-picker` adds `default-formatted-value` prop.\n- `n-date-picker` adds `on-update:formatted-value` prop.\n- `n-date-picker`'s `on-update:value` prop will pass formatted value out.\n- `n-image` adds `show-toolbar-tooltip` prop.\n- `n-image` adds more theme variables, closes [#1531](https://github.com/tusen-ai/naive-ui/issues/1531).\n- `n-upload` adds `image-group-props` prop.\n- `n-progress` adds `offset-degree` prop, closes [#2010](https://github.com/tusen-ai/naive-ui/issues/2010).\n- `n-form-item` adds `feedback` slot, closes [#1142](https://github.com/tusen-ai/naive-ui/issues/1142).\n- `n-form-item`'s `require-mark-placement` prop adds `'right-hanging'` option, closes [#2094](https://github.com/tusen-ai/naive-ui/issues/2094).\n- `n-cascader` adds `render-label` prop, closes [#2048](https://github.com/tusen-ai/naive-ui/issues/2048).\n- `n-auto-complete` adds `render-option` prop, closes [#1629](https://github.com/tusen-ai/naive-ui/issues/1629).\n- `n-auto-complete` adds `render-label` prop, closes [#1629](https://github.com/tusen-ai/naive-ui/issues/1629).\n- `n-tree` adds `render-switcher-icon` prop, closes [#1551](https://github.com/tusen-ai/naive-ui/issues/1551).\n- `n-message` exports `MessageType` type.\n- `n-time-picker` adds `value-format` prop.\n- `n-time-picker` adds `formatted-value` prop.\n- `n-time-picker` adds `on-update:formatted-value` prop.\n- `n-time-picker` adds `default-formatted-value` prop.\n- `n-carousel` adds `default-index` prop.\n- `n-carousel` adds `current-index` prop.\n- `n-carousel` adds `show-arrow` prop.\n- `n-carousel` adds `dot-type` prop, closes [#1931](https://github.com/tusen-ai/naive-ui/issues/1931).\n- `n-carousel` adds `dot-placement` prop, closes [#1462](https://github.com/tusen-ai/naive-ui/issues/1462).\n- `n-carousel` adds `slides-per-view` prop.\n- `n-carousel` adds `space-between` prop.\n- `n-carousel` adds `centered-slides` prop.\n- `n-carousel` adds `direction` prop, closes [#1931](https://github.com/tusen-ai/naive-ui/issues/1931).\n- `n-carousel` adds `loop` prop.\n- `n-carousel` adds `effect` prop, closes [#1159](https://github.com/tusen-ai/naive-ui/issues/1159).\n- `n-carousel` adds `transition-props` prop, closes [#1159](https://github.com/tusen-ai/naive-ui/issues/1159).\n- `n-carousel` adds `transition-style` prop, closes [#1159](https://github.com/tusen-ai/naive-ui/issues/1159).\n- `n-carousel` adds `draggable` prop.\n- `n-carousel` adds `touchable` prop.\n- `n-carousel` adds `mousewheel` prop.\n- `n-carousel` adds `keyboard` prop.\n- `n-carousel` adds `show-dots` prop.\n- `n-carousel` adds `on-update:current-index` prop.\n- `n-carousel` adds `arrow` slot.\n- `n-carousel` adds `dots` slot.\n- `n-form-item` adds `for` prop.\n- `n-color-picker` adds `label` slot.\n- `n-color-picker` adds `render-label` prop.\n- `n-form-item` adds `label-props` prop.\n\n## 2.23.2\n\n`2021-12-29`\n\n### Feats\n\n- `<meta name=\"naive-ui-style\" />` can be used to controll the component style's position.\n- `n-empty` adds `show-icon` prop.\n- `n-modal` adds a11y support, closes [#1877](https://github.com/tusen-ai/naive-ui/issues/1877).\n- Add `n-avatar-group` component.\n- `n-input-number` supports `loading` state.\n- Add `n-countdown` component.\n- Add `n-number-animation` component, closes [#1465](https://github.com/tusen-ai/naive-ui/issues/1465).\n- `n-statistic` adds `tabular-nums` prop.\n- `n-pagination` will give `itemCount` a approximate value derived from `pageSize` and `pageCount` if it's not set, closes [#2044](https://github.com/tusen-ai/naive-ui/issues/2044).\n- `n-cascader` adds `on-update:show` prop, closes [#2049](https://github.com/tusen-ai/naive-ui/issues/2049).\n- `n-scrollbar` uses `n` as CSS vars prefix.\n- `n-popconfirm` uses `n` as CSS vars prefix.\n- `n-gradient-text` uses `n` as CSS vars prefix.\n- `n-form` uses `n` as CSS vars prefix.\n- `n-pagination` uses `n` as CSS vars prefix.\n- `n-loading-bar` uses `n` as CSS vars prefix.\n- `n-empty` uses `n` as CSS vars prefix.\n- `n-list` uses `n` as CSS vars prefix.\n- `n-layout` uses `n` as CSS vars prefix.\n- `n-message` uses `n` as CSS vars prefix.\n- `n-mention` uses `n` as CSS vars prefix.\n- `n-menu` uses `n` as CSS vars prefix.\n- `n-popover` uses `n` as CSS vars prefix.\n- `n-transfer` uses `n` as CSS vars prefix.\n- `n-table` uses `n` as CSS vars prefix.\n- `n-statistic` uses `n` as CSS vars prefix.\n- `n-code` uses `n` as CSS vars prefix.\n- `n-breadcrumb` uses `n` as CSS vars prefix.\n- `n-slider` uses `n` as CSS vars prefix.\n- `n-spin` uses `n` as CSS vars prefix.\n- `n-select` uses `n` as CSS vars prefix.\n- `n-result` uses `n` as CSS vars prefix.\n- `n-calendar` uses `n` as CSS vars prefix.\n- `n-card` uses `n` as CSS vars prefix.\n- `n-cascader` uses `n` as CSS vars prefix.\n- `n-color-picker` uses `n` as CSS vars prefix.\n- `n-checkbox` uses `n` as CSS vars prefix.\n- `n-data-table` uses `n` as CSS vars prefix.\n- `n-date-picker` uses `n` as CSS vars prefix.\n- `n-descriptions` uses `n` as CSS vars prefix.\n- `n-drawer` uses `n` as CSS vars prefix.\n- `n-dropdown` uses `n` as CSS vars prefix.\n- `n-rate` uses `n` as CSS vars prefix.\n- `n-radio` uses `n` as CSS vars prefix.\n- `n-progress` uses `n` as CSS vars prefix.\n- `n-skeleton` uses `n` as CSS vars prefix.\n- `n-collapse` uses `n` as CSS vars prefix.\n- `n-collapse-transition` uses `n` as CSS vars prefix.\n- `n-thing` uses `n` as CSS vars prefix.\n- `n-carousel` uses `n` as CSS vars prefix.\n- `n-page-header` uses `n` as CSS vars prefix.\n- `n-image` uses `n` as CSS vars prefix.\n- `n-input` uses `n` as CSS vars prefix.\n- `n-icon` uses `n` as CSS vars prefix.\n- `n-modal` uses `n` as CSS vars prefix.\n- `n-notification` uses `n` as CSS vars prefix.\n\n### Fixes\n\n- Fix `n-form-item-gi` 's `validate` doesn't work, closes [#1901](https://github.com/tusen-ai/naive-ui/issues/1901).\n- Fix `n-card` action's border-radius style.\n- Fix `n-code`'s content is repeatly appended if language is not set, closes [#2034](https://github.com/tusen-ai/naive-ui/issues/2034).\n- Fix `n-tabs`'s `tabTextColorActiveSegment` and `tabTextColorHoverSegment` theme variables not working, closes [#2038](https://github.com/tusen-ai/naive-ui/issues/2038).\n- Fix `n-image` may keep keyboard handler after mounted.\n- Fix `n-image` can't exit preview after esc is pressed when there's only 1 image, closes [#2042](https://github.com/tusen-ai/naive-ui/issues/2042).\n- Fix `n-drawer-content`'s content doesn't scroll by default, ref [#2003](https://github.com/tusen-ai/naive-ui/issues/2003).\n- Fix `n-popover` log warnings to console when manually set same zindex on multile instances and closes them, closes [#2050](https://github.com/tusen-ai/naive-ui/issues/2050).\n- Fix `n-transfer` has no scrollbar in virtual scroll mode.\n- Fix `n-input-number` cannot input decimals end with 0.\n\n## 2.23.1\n\n`2021-12-20`\n\n### Fixes\n\n- Fix `n-transfer` list doesn't follow container height when style.height is set, closes [#1879](https://github.com/tusen-ai/naive-ui/issues/1879).\n- Fix `n-skeleton` & `n-gradient-text` cause runtime error in some old browsers, closes [#1867](https://github.com/tusen-ai/naive-ui/issues/1867).\n- Fix `n-data-table` `ellipsis` prop in column doesn't support all `n-ellipsis`'s props, closes [#1891](https://github.com/tusen-ai/naive-ui/issues/1891).\n- Fix `n-form`'s `blankHeightXxx` theme var doesn't follow `common.heightXxx`, closes [#1880](https://github.com/tusen-ai/naive-ui/issues/1880).\n- Fix `n-date-picker`'s panel doesn't use `dateFormat` in locale, closes [#1793](https://github.com/tusen-ai/naive-ui/issues/1793).\n- Fix `n-log` text color transition in theme switching.\n\n### Feats\n\n- `n-back-top` uses `n` as CSS vars prefix.\n- `n-steps` uses `n` as CSS vars prefix.\n- `n-switch` uses `n` as CSS vars prefix.\n- `n-auto-complete` uses `n` as CSS vars prefix.\n- `n-log` uses `n` as CSS vars prefix.\n- `n-timeline` uses `n` as CSS vars prefix.\n- `n-time-picker` uses `n` as CSS vars prefix.\n- `n-avatar` uses `n` as CSS vars prefix.\n- `n-dynamic-tags` uses `n` as CSS vars prefix.\n- `n-tag` uses `n` as CSS vars prefix.\n- `n-dialog` uses `n` as CSS vars prefix.\n- `n-upload` uses `n` as CSS vars prefix.\n- `n-tree` uses `n` as CSS vars prefix.\n- `n-tree-select` uses `n` as CSS vars prefix.\n\n## 2.23.0\n\n`2021-12-17`\n\n### Breaking Changes\n\n- `n-switch` can no longer be clicked under `loading` status, closes [#1853](https://github.com/tusen-ai/naive-ui/issues/1853).\n\n### Fixes\n\n- Fix `n-data-table` 's horizontal scrollbar disappears when max-height is not set, closes [#1857](https://github.com/tusen-ai/naive-ui/issues/1857).\n- Fix `n-input-number` cannot input negative decimals value, closes [#1858](https://github.com/tusen-ai/naive-ui/issues/1858).\n- Fix `n-dialog` open new dialog again when pressing `enter` key, closes [#1559](https://github.com/tusen-ai/naive-ui/issues/1559).\n\n### Feats\n\n- `n-divider` uses `n` as CSS vars prefix.\n- `n-typography` uses `n` as CSS vars prefix.\n- `n-badge` uses `n` as CSS vars prefix.\n\n## 2.22.0\n\n`2021-12-15`\n\n### Breaking Changes\n\n- `n-button` can no longer be clicked under `loading` status, closes [#1628](https://github.com/tusen-ai/naive-ui/issues/1628).\n\n### Fixes\n\n- Fix `n-alert`'s `header` slot unable to display normally.\n- Fix `n-data-table`'s pagination `onUpdatePageSize` prop does't trigger, closes [#1774](https://github.com/tusen-ai/naive-ui/issues/1774).\n- Fix `n-data-table` can select rows when table is loading, closes [#1812](https://github.com/tusen-ai/naive-ui/issues/1812).\n- Fix `n-tag` line-height is too low that clamps the content.\n- Fix `n-select` displays with mistake in input if `filterable` is `true`, closes [#1823](https://github.com/tusen-ai/naive-ui/issues/1823).\n- Fix `n-page-header`'s content has margin-top when header is not displayed, closes [#1795](https://github.com/tusen-ai/naive-ui/issues/1795).\n- Fix `n-avatar` `color` prop not working.\n- Fix `n-avatar`'s inner icon has wrong size.\n- Fix `n-image` lacks scoped style's scope-id, closes [#1788](https://github.com/tusen-ai/naive-ui/issues/1788).\n- Fix `n-radio` click event will be triggered twice, closes [#1680](https://github.com/tusen-ai/naive-ui/issues/1680).\n- Fix `n-data-table` layout display incorrect when the table is empty and min-height set, closes [#1809](https://github.com/tusen-ai/naive-ui/issues/1809).\n- Fix `n-data-table`'s summary has hover style.\n- Fix `n-data-table` fixed group column box-shadow error and right fixed column order error, closes [#1832](https://github.com/tusen-ai/naive-ui/issues/1832).\n- Fix `n-anchor`'s hover & active style.\n- Fix `n-data-table`'s header fixed column style on data is empty.\n\n### Feats\n\n- `n-tree-select` adds `menu-props` prop.\n- `n-tree-select` adds `action` slot, closes [#1765](https://github.com/tusen-ai/naive-ui/issues/1765).\n- `n-tree-select` adds `empty` slot.\n- `n-cascader` adds `empty` slot.\n- `n-popselect` adds `action` slot.\n- `n-popselect` adds `empty` slot.\n- `n-data-table` will check all if indeterminate header checkbox is clicked, closes [#1827](https://github.com/tusen-ai/naive-ui/issues/1827).\n- `n-button` uses `n` as CSS vars prefix, closes [#1808](https://github.com/tusen-ai/naive-ui/issues/1808).\n- `n-date-picker` adds `default-time` prop.\n- `n-alert` uses `n` as CSS vars prefix.\n- `n-date-picker`'s `type` prop support `quarter` option.\n- `n-anchor` uses `n` as CSS vars prefix.\n\n### i18n\n\n- Add zhTW locale.\n\n## 2.21.5\n\n`2021-12-07`\n\n### Fixes\n\n- Fix `n-input` click clear icon does't trigger `change` event, closes [#1754](https://github.com/tusen-ai/naive-ui/issues/1754).\n- Fix `n-input-number` the cursor moves when press arrow keys to change value, closes [#1759](https://github.com/tusen-ai/naive-ui/issues/1759).\n\n### Feats\n\n- `n-date-picker`'s default format follows i18n.\n\n### i18n\n\n- Add frFR locale.\n\n## 2.21.4\n\n`2021-12-06`\n\n### Fixes\n\n- Fix `n-date-picker` has no placeholder when `type` is `year`.\n- Fix `n-element` doesn't export `NEl` alias name.\n- Fix `n-upload` still shows upload trigger when max limit is reached in `image-card` mode, closes [#1744](https://github.com/tusen-ai/naive-ui/issues/1744).\n- Fix `n-form`'s `FormValidate` type lacks `shouldRuleBeApplied` parameter, closes [#1747](https://github.com/tusen-ai/naive-ui/issues/1747).\n- Fix `n-upload` is displayed vertically in `n-form` in `image-card` mode, closes [#1746](https://github.com/tusen-ai/naive-ui/issues/1746).\n- Fix `n-upload`'s file list's top margin if trigger is hidden.\n- Fix `n-upload` shows normal file status when response has 4xx status, closes [#1741](https://github.com/tusen-ai/naive-ui/issues/1741).\n\n### Feats\n\n- `n-upload` adds `show-trigger` prop.\n- `n-data-table` will ignore `children` with length 0 in tree data mode, closes [#1703](https://github.com/tusen-ai/naive-ui/issues/1703).\n\n## 2.21.3\n\n`2021-12-03`\n\n### Fixes\n\n- Fix `n-theme-editor` throw error when click button component, closes [#1708](https://github.com/tusen-ai/naive-ui/issues/1708).\n- Fix `n-input`'s color is abnormal in Android WeChat, closes [#1705](https://github.com/tusen-ai/naive-ui/issues/1705).\n- Fix `n-input` 's `borderHover` theme variable doesn't work, closes [#1704](https://github.com/tusen-ai/naive-ui/issues/1704).\n- Fix `n-dialog`'s `content` word-break.\n- Fix `n-input-number` cannot input decimals value.\n- Fix `n-data-table`'s header & body may have wrong border radius, closes [#1712](https://github.com/tusen-ai/naive-ui/issues/1712).\n- Fix `n-button`'s `colorOpacityXxx` theme vars are not string typed.\n\n### Feats\n\n- `n-switch` adds `rail-style` prop, closes [#1718](https://github.com/tusen-ai/naive-ui/issues/1718).\n- `n-image` adds `preview-disabled` props, closes [#1647](https://github.com/tusen-ai/naive-ui/issues/1647).\n- `n-image` adds `on-load` & `on-error` prop.\n- `n-image` adds `fallback-src` prop.\n- `n-data-table` adds `on-update:expanded-row-keys` prop.\n- `n-tree` adds `watch-props` prop.\n\n## 2.21.2\n\n`2021-11-29`\n\n### Fixes\n\n- Fix `n-slider` disabled tooltip at the wrong time.\n- Fix `n-slider` incorrect fill color style, closes [#1670](https://github.com/tusen-ai/naive-ui/issues/1670).\n- Fix `n-data-table`'s pagination `onUpdatePage` prop trigger twice, closes [#1666](https://github.com/tusen-ai/naive-ui/issues/1666).\n- Fix `n-log`'s `trim` prop not being independent when used.\n- Fix `n-slider` processing of step value precision.\n- Fix `n-date-picker` throw error when `time-picker` input is empty, closes [#1678](https://github.com/tusen-ai/naive-ui/issues/1678).\n- Fix `n-popover` not working when `trigger` is `focus`.\n- Fix `n-scrollbar`'s scrollbar will vanish if clicked.\n- Fix `n-popover` has an invalid line in style.\n- Fix `n-popover` `flip=false` doesn't work.\n- Fix `n-input-number` can't accept indeterminate input value when `max` or `min` is set, closes [#1664](https://github.com/tusen-ai/naive-ui/issues/1664).\n- Fix `n-input-number`'s input value is not changed to a valid value if it's input exceeds min or max multiple times.\n\n### Feats\n\n- `n-input-number` adds `keyboard` prop.\n- Add `tableColorStriped` theme variable, closes [#1686](https://github.com/tusen-ai/naive-ui/issues/1686).\n- `n-notification-provider` adds `max` & `placement` prop.\n- `n-notification` adds `destroyAll` method, closes [#333](https://github.com/tusen-ai/naive-ui/issues/333).\n- `n-layout-sider` adds `on-after-enter` and `on-after-leave` props, closes [#1241](https://github.com/tusen-ai/naive-ui/issues/1241).\n- `n-upload` adds `custom-request` prop, closes [#1389](https://github.com/tusen-ai/naive-ui/issues/1389).\n- `n-data-table` adds `expanded-row-keys` prop.\n- `n-popover` provides better auto position adjustment, closes [#1520](https://github.com/tusen-ai/naive-ui/issues/1520), [#1643](https://github.com/tusen-ai/naive-ui/issues/1643).\n- `n-input-number` adds `update-value-on-input` prop, closes [#1662](https://github.com/tusen-ai/naive-ui/issues/1662).\n- `n-auto-complete` adds `prefix` & `suffix` slot.\n\n## 2.21.1\n\n`2021-11-23`\n\n### Fixes\n\n- Fix `n-image` drag the picture to move the position incorrectly when the zoom is large.\n- Fix `n-data-table` style glitches after some rows are expanded.\n- Fix `n-data-table` doesn't expand tree data correctly, closes [#1644](https://github.com/tusen-ai/naive-ui/issues/1644).\n\n## 2.21.0\n\n`2021-11-21`\n\n### Breaking Changes\n\n- `NButton.fontWeightText` & `NButton.fontWeightGhost` theme vars are removed. If you want to change font weight, you can use `strong` prop of `n-button` instead.\n\n### Feats\n\n- `n-tag` adds `avatar` slot.\n- `n-data-table` adds `striped` prop, closes [#1552](https://github.com/tusen-ai/naive-ui/issues/1552).\n- `n-table` adds `striped` prop, closes [#1552](https://github.com/tusen-ai/naive-ui/issues/1552).\n- `n-slider` adds `vertical` prop, closes [#1468](https://github.com/tusen-ai/naive-ui/issues/1468).\n- `n-slider` adds `reverse` prop.\n- `n-slider`'s `step` prop support `mark` option.\n- Bypass Vitejs bug on string extrapolation, ref [#636](https://github.com/tusen-ai/naive-ui/issues/636).\n- `n-button` adds `strong` prop.\n- `n-button` adds `secondary` prop.\n- `n-button` adds `tertiary` prop.\n- `n-button` adds `quaternary` prop.\n- `n-auto-complete` adds `input-props` prop, closes [#1610](https://github.com/tusen-ai/naive-ui/issues/1610).\n- `n-avatar` adds `fallback-src` prop, closes [#702](https://github.com/tusen-ai/naive-ui/issues/702).\n- `n-avatar` adds `on-error` prop.\n- `n-input` adds `select` methods, closes [#1328](https://github.com/tusen-ai/naive-ui/issues/1328).\n- Add `n-tab` component, closes [#1630](https://github.com/tusen-ai/naive-ui/issues/1630).\n- `n-switch` adds `round` prop, closes [#1469](https://github.com/tusen-ai/naive-ui/issues/1469).\n- `n-step` adds `title` slot.\n- `n-menu` support `divider` type option.\n\n### Fixes\n\n- Fix the default value of the `suffix` internal component's `loading` property.\n- Fix `n-space` is shown when it has no children, closes [#1605](https://github.com/tusen-ai/naive-ui/issues/1605).\n- Fix `n-radio` has no `onUpdateChecked` prop.\n- Fix `n-dropdown` animation flicker problem, closes [#1600](https://github.com/tusen-ai/naive-ui/issues/1600).\n- Fix `n-data-table`’s `clearSorter` method isn't exported properly.\n- Fix `n-global-style` throws error in SSR.\n- Fix `n-button` will trigger click event twice if pressed, closes [#1626](https://github.com/tusen-ai/naive-ui/issues/1626).\n\n## 2.20.3\n\n`2021-11-15`\n\n### Fixes\n\n- Fix `n-grid` suffix NGridItem does not set right span when collapsed, closes [#1530](https://github.com/tusen-ai/naive-ui/issues/1530).\n- Fix `n-button` to shrink abnormally in certain scenarios when using the `circle` prop, closes [#1557](https://github.com/tusen-ai/naive-ui/issues/1557).\n- Fix `input-props` does affect `type` prop, closes [#1553](https://github.com/tusen-ai/naive-ui/issues/1553).\n\n### Feats\n\n- `n-menu` adds a color distinction between selected and unselected arrow, closes [#1535](https://github.com/tusen-ai/naive-ui/issues/1535).\n- `n-menu` adds `watch-props` prop, closes [#1536](https://github.com/tusen-ai/naive-ui/issues/1536).\n- `n-date-picker`'s `type` prop support `year` option.\n\n### i18n\n\n- Add `createLocale` to make locale customizable, closes [#1525](https://github.com/tusen-ai/naive-ui/issues/1525).\n\n## 2.20.2\n\n`2021-11-05`\n\n### Feats\n\n- `n-modal` adds `transform-origin` prop, closes [#1498](https://github.com/tusen-ai/naive-ui/issues/1498).\n- `n-tabs` adds `pane-class` prop, closes [#1500](https://github.com/tusen-ai/naive-ui/issues/1500).\n\n### Fixes\n\n- Fix `n-alert` `contentTextColor` and `titleTextColor` type theme variable not working, closes [#1495](https://github.com/tusen-ai/naive-ui/issues/1495).\n- Fix `n-time-picker` not trigger blur event when the panel is closed by ok button, closes [#1499](https://github.com/tusen-ai/naive-ui/issues/1499).\n- Fix `n-upload` `UploadFileInfo`'s `thumbnailUrl` field not working, closes [#1495](https://github.com/tusen-ai/naive-ui/issues/1245).\n- Fix `n-button` `keyboard` prop does not work, closes [#1508](https://github.com/tusen-ai/naive-ui/issues/1508).\n- Fix `n-upload` instance misses `openOpenFileDialog` method.\n\n### i18n\n\n- Add deDE locale.\n- Add nbNO locale.\n\n## 2.20.1\n\n`2021-11-01`\n\n### Fixes\n\n- Fix `n-tabs` switch tab does not work when adding a new tab, closes [#1417](https://github.com/tusen-ai/naive-ui/issues/1417).\n- Fix `n-tree`'s `filter` prop does not work when assigned `children-field` , closes [#1477](https://github.com/tusen-ai/naive-ui/issues/1477).\n- Fix `n-cascader` can't remove options when using customized fields in multiple mode.\n- Fix `n-select`'s option created by `on-create` doesn't show correct label in trigger, closes [#1482](https://github.com/tusen-ai/naive-ui/issues/1482).\n- Fix `n-select` menu height shifts on close in `filterable` mode.\n\n### Feats\n\n- `n-select` adds `menu-props` prop, closes [#1475](https://github.com/tusen-ai/naive-ui/issues/1475).\n- `n-image`'s `toolbar` adds close icon, closes [#1412](https://github.com/tusen-ai/naive-ui/issues/1412).\n- `n-tree`'s `on-load` prop is triggered when the `expanded-keys` prop changes in `remote` mode, closes [#1339](https://github.com/tusen-ai/naive-ui/issues/1339).\n\n## 2.20.0\n\n`2021-10-28`\n\n### Breaking Changes\n\n- `n-collapsed-transition`'s `collapsed` prop is deprecated, please use `show` instead, closes [#1407](https://github.com/tusen-ai/naive-ui/issues/1407).\n\n### Fixes\n\n- Fix `n-log` `font-size` prop not working, closes [#1416](https://github.com/tusen-ai/naive-ui/issues/1416).\n- Fix `n-loading-bar` will show once even if `start` is not called when `loading-bar-style` is set.\n- Fix `n-date-picker` `separator` prop not working, closes [#1456](https://github.com/tusen-ai/naive-ui/issues/1456).\n\n### Feats\n\n- `n-data-table` optimize the logic of underlying rendering and improve component performance.\n- `n-date-picker`'s `shortcuts` prop supports functional value.\n- `n-tab-pane`'s `display-directive` props supports the `show:lazy` option, closes [#1374](https://github.com/tusen-ai/naive-ui/issues/1374).\n- `n-input` of text type supports `count` slots, closes [#1440](https://github.com/tusen-ai/naive-ui/issues/1440).\n\n### i18n\n\n- Add idID locale.\n\n## 2.19.11\n\n`2021-10-21`\n\n### Fixes\n\n- Fix `n-upload`'s file can't be removed when file count limit is reached, closes [#1401](https://github.com/tusen-ai/naive-ui/issues/1401).\n\n### Feats\n\n- `n-tabs` adds `on-before-leave` prop, closes [#1337](https://github.com/tusen-ai/naive-ui/issues/1337).\n- `n-color-picker` adds `show-preview` prop, closes [#1281](https://github.com/tusen-ai/naive-ui/issues/1281).\n- `n-tab-pane`'s `display-directive` prop support `show:lazy` option, closes [#1374](https://github.com/tusen-ai/naive-ui/issues/1374).\n\n## 2.19.9\n\n`2021-10-18`\n\n### Fixes\n\n- Fix `n-collapse`'s expanded status is lost when using `v-if` with `n-collapse-item`, closes [#1387](https://github.com/tusen-ai/naive-ui/issues/1387).\n- Fix `n-dialog`'s close button will be overlayed with content, closes [#1381](https://github.com/tusen-ai/naive-ui/issues/1381).\n- Fix `n-upload` file is set to `null` after upload failure, closes [#1316](https://github.com/tusen-ai/naive-ui/issues/1316).\n- Fix `n-cascader`'s `filter` prop not working.\n- Fix `n-cascader`'s `label-field` prop breaks filter.\n- Fix `n-cascader`'s `separator` prop isn't appiled to filter select menu.\n\n### Feats\n\n- `n-menu` adds `dropdown-props` prop, closes [#1345](https://github.com/tusen-ai/naive-ui/issues/1345).\n- `n-input` adds `count` slot, closes [#1314](https://github.com/tusen-ai/naive-ui/issues/1314).\n- `n-time-picker` adds `use-12-hours` prop, closes [#547](https://github.com/tusen-ai/naive-ui/issues/547).\n- `n-input-number` adds `focus` & `blur` methods.\n\n## 2.19.8\n\n`2021-10-14`\n\n### Fixes\n\n- Fix `n-data-table` fixed style does not work in group header table, closes [#1341](https://github.com/tusen-ai/naive-ui/issues/1341).\n- Fix `n-data-table` has duplicate right border when it has multiple level headers.\n- Fix `n-scrollbar` doesn't support `scrollTo`, closes [#1346](https://github.com/tusen-ai/naive-ui/issues/1346).\n- Fix `n-ellipsis`'s `expand-trigger` prop not show `pointer` cursor when content is short when `tooltip = false`, closes [#1299](https://github.com/tusen-ai/naive-ui/issues/1299).\n- Fix `n-upload`'s `disabled` prop's style not working, closes [#1237](https://github.com/tusen-ai/naive-ui/issues/1237).\n- `n-config-provider` adds `breakpoints` prop, closes [#1379](https://github.com/tusen-ai/naive-ui/issues/1379).\n\n### Feats\n\n- `n-auto-complete` adds `get-show` prop, closes [#1292](https://github.com/tusen-ai/naive-ui/issues/1292).\n- `n-select` adds `input-props` prop, closes [#1351](https://github.com/tusen-ai/naive-ui/issues/1351).\n- `n-color-picker` adds `swatches` prop, ref [#1281](https://github.com/tusen-ai/naive-ui/issues/1281).\n- `n-upload` adds `max` prop.\n\n### i18n\n\n- Add jaJP locale.\n\n## 2.19.7\n\n`2021-10-12`\n\n### Fixes\n\n- Fix `n-ellipsis`'s `expand-trigger` prop not show `pointer` cursor when content is short, closes [#1299](https://github.com/tusen-ai/naive-ui/issues/1299).\n- Fix `n-select`'s `fallback-option` prop's type, closes [#1327](https://github.com/tusen-ai/naive-ui/issues/1327).\n- Fix `n-modal`'s `on-after-enter` prop not working.\n\n## 2.19.6\n\n`2021-10-10`\n\n### Fixes\n\n- Fix `n-menu`'s incorrect warning on `default-expanded-keys`.\n- Fix `useThemeVars` is sometimes unusable, closes [#1309](https://github.com/tusen-ai/naive-ui/issues/1309).\n- Fix the `list-style` style of the `<ul>` element.\n\n### Feats\n\n- `n-cascader` provide all options paths in `update:value` callback function, closes [#1235](https://github.com/tusen-ai/naive-ui/issues/1235).\n- `n-layout` and `n-layout-sider` adds `on-scroll` prop, closes [#1232](https://github.com/tusen-ai/naive-ui/issues/1232).\n- `n-config-provider` adds `preflight-style-disabled` prop.\n\n## 2.19.5\n\n`2021-10-07`\n\n### Fixes\n\n- Fix `n-form-item`'s content is too long and the width is incorrect.\n- Fix `n-layout-sider`'s `arrow-circle`'s icon style.\n- Fix `n-upload`'s `show-preview-button` prop not working, closes [#1238](https://github.com/tusen-ai/naive-ui/issues/1238).\n- Fix `n-date-picker`'s `date` type of `action` validate error.\n- Fix `n-data-table` throws error when using `selection` and `summary` together, closes [#1276](https://github.com/tusen-ai/naive-ui/issues/1276).\n- Fix `n-data-table` selection column's width is collapsed when it is set to fixed, closes [#1283](https://github.com/tusen-ai/naive-ui/issues/1283).\n- Fix `n-popconfirm` can't be nested in `n-tooltip`, closes [#872](https://github.com/tusen-ai/naive-ui/issues/872).\n- Fix `n-popselect` checkmark overlays on option text, closes [#1282](https://github.com/tusen-ai/naive-ui/issues/1282).\n- Fix `n-pagination` `buttonColor` theme variable not working.\n\n### Feats\n\n- `n-breadcrumb-item` adds `href` prop.\n- `n-descriptions` adds `separator` prop, closes [#1263](https://github.com/tusen-ai/naive-ui/issues/1263).\n- `n-dropdown` adds `key-field` prop.\n- `n-dropdown` adds `label-field` prop.\n- `n-dropdown` adds `children-field` prop.\n- `n-menu` adds `key-field` prop.\n- `n-menu` adds `label-field` prop.\n- `n-menu` adds `children-field` prop.\n- `n-data-table` supports using path of the property to get as column key, closes [#1271](https://github.com/tusen-ai/naive-ui/issues/1271).\n- `n-switch` adds `checked-value` prop, closes [#1234](https://github.com/tusen-ai/naive-ui/issues/1234).\n- `n-switch` adds `unchecked-value` prop, closes [#1234](https://github.com/tusen-ai/naive-ui/issues/1234).\n- `n-checkbox` adds `checked-value` prop, closes [#1234](https://github.com/tusen-ai/naive-ui/issues/1234).\n- `n-checkbox` adds `unchecked-value` prop, closes [#1234](https://github.com/tusen-ai/naive-ui/issues/1234).\n- Add `n-collapse-transition` component, closes [#829](https://github.com/tusen-ai/naive-ui/issues/829).\n- Add `n-scrollbar` component.\n- `n-dropdown` support options with `type='render'`.\n- `n-data-table` supports multiple column sorting.\n- `n-date-picker` adds `first-day-of-week` prop.\n- `n-date-picker`'s `type` prop support `month` option.\n- `n-popover` adds `to` prop.\n- `n-tree`'s `on-update:indeterminateKeys` prop adds option info.\n- `n-tree`'s `on-update:expandedKeys` prop adds option info.\n- `n-tree`'s `on-update:checkedKeys` prop adds option info.\n- `n-tree`'s `on-update:selectedKeys` prop adds option info.\n\n## 2.19.3\n\n`2021-09-28`\n\n### Fixes\n\n- Fix `n-data-table` ellipsis not show when last column not set ellipsis, closes [#934](https://github.com/tusen-ai/naive-ui/issues/934).\n- Fix `n-grid-item` won't work with responsive config.\n- Fix `n-tabs`'s scroll shadow is not updated when it's resized, closes [#1224](https://github.com/tusen-ai/naive-ui/issues/1224).\n\n### Feats\n\n- `n-grid-item` won't display when `span` is 0, closes [#1220](https://github.com/tusen-ai/naive-ui/issues/1220).\n- `n-grid` adds `item-responsive` prop.\n\n## 2.19.2\n\n`2021-09-26`\n\n### i18n\n\n- Add ukUA locale.\n\n### Fixes\n\n- Fix `n-global-style` applies style transition on first mount.\n- Fix `n-drawer` border transition, closes [#1211](https://github.com/tusen-ai/naive-ui/issues/1211).\n- Fix `n-input-number`'s `value` prop can't be `null` type.\n- Fix components with rtl support throws error in SSR.\n- Fix components with popover throws error in SSR.\n- Fix global theme overrides not working for `n-select` trigger, closes [#1229](https://github.com/tusen-ai/naive-ui/issues/1229).\n\n### Feats\n\n- `n-checkbox` adds aria support.\n- `n-alert` aria support.\n\n## 2.19.1\n\n`2021-09-21`\n\n### Fixes\n\n- Fix `DialogReactive` props are readonly.\n- Fix `n-tree-select` sets `check-strategy='child'` not working in single select mode.\n- Fix `n-upload`'s trigger is compressed in `image-card` mode when it's the only item in the row.\n- Fix `n-upload-dragger` has no border transition.\n- Fix `n-upload` can't upload files.\n- Fix `n-tree`'s `checkable` prop doesn't work when `cascade` is `false`.\n- Fix `n-tree-select`'s `checkable` prop doesn't work when `cascade` or `multiple` is `false`.\n\n## 2.19.0\n\n`2021-09-19`\n\n### Breaking Changes\n\n- `n-layout-sider`'s `arrow-circle` trigger is changed into new style.\n\n### Feats\n\n- `n-layout-sider` adds `collapsed-trigger-style` prop.\n- `n-menu` adds `accordion` prop , closes [#917](https://github.com/tusen-ai/naive-ui/issues/917).\n- `n-input-number` adds `readonly` prop , closes [#1198](https://github.com/tusen-ai/naive-ui/issues/1198).\n- `n-spin` adds `description` prop and slot.\n- `n-anchor` adds `type` prop.\n- `n-upload` adds `abstract` prop, adds `n-upload-trigger` 和 `n-upload-file-list` component, closes [#1102](https://github.com/tusen-ai/naive-ui/issues/1102).\n- `n-tree` adds `indeterminate-keys` prop.\n- `n-tree-select` adds `indeterminate-keys` prop.\n- `n-tree` adds `on-update:indeterminate-keys` prop.\n- `n-tree-select` adds `on-update:indeterminate-keys` prop.\n- `n-tabs` `type` prop adds `'segment'` option, closes [#1133](https://github.com/tusen-ai/naive-ui/issues/1133).\n- `n-popover` adds `z-index` prop, closes [#764](https://github.com/tusen-ai/naive-ui/issues/764).\n- `n-modal` adds `on-after-enter` prop.\n- `n-modal` adds `on-after-leave` prop.\n\n### Fixes\n\n- Fix `n-select` focus input when closing tag with `filterable` , closes [#1170](https://github.com/tusen-ai/naive-ui/issues/1170).\n- Fix `n-button` border on hover conflicts with `n-badge`, closes [#1195](https://github.com/tusen-ai/naive-ui/issues/1195).\n- Fix `n-upload` prop `v-model:file-list` dosen't work well when prop `multiple` is `true`, closes [#418](https://github.com/tusen-ai/naive-ui/issues/418).\n- Fix `useThemeVars` doesn't apply theme overrides, closes [#1194](https://github.com/tusen-ai/naive-ui/issues/1194), [#1176](https://github.com/tusen-ai/naive-ui/issues/1176).\n- Fix `n-tabs`'s left shadow isn't displayed in card type.\n\n## 2.18.2\n\n`2021-09-14`\n\n### Feats\n\n- `n-cascader` show `Empty` component when `options` prop is empty, closes [#1092](https://github.com/tusen-ai/naive-ui/issues/1092).\n- `n-cascader`'s `on-update:value` prop adds option info.\n- `n-tree` adds `check-strategy` prop.\n- `n-date-picker` adds `input-readonly` prop, closes [#1120](https://github.com/tusen-ai/naive-ui/issues/1120).\n- `n-time-picker` adds `input-readonly` prop, closes [#1120](https://github.com/tusen-ai/naive-ui/issues/1120).\n- `n-config-provider` adds global config of the `Empty` component, closes [#1092](https://github.com/tusen-ai/naive-ui/issues/1092).\n- `n-select` adds `on-update:show` prop.\n- `n-auto-complete` exports `AutoCompleteOption` and `AutoCompleteGroupOption` types.\n- `n-page-header` adds `RTL` support.\n- `n-select` support variadic height option rendering.\n- `n-tree-select`'s `on-update:value` prop adds option info.\n- `n-select`'s `on-update:value` prop adds option info.\n- `n-popselect`'s `on-update:value` prop adds option info.\n- `n-card` adds `embedded` prop.\n\n### Fixes\n\n- Fix `n-p` warns when `depth` is number.\n- Fix `n-date-picker`‘s type of `actions` prop.\n- Fix `n-select` can't override `n-empty`'s theme variables.\n- Fix `n-dynamic-tags` adds button is not disabled when it is disabled.\n- Fix `n-select` closes menu when enter key is pressed in filterable mode without options data.\n- Fix `n-auto-complete`'s `children` prop can't use `AutoCompleteOption` type.\n- Fix `n-gi`'s `collapsed` does not work in `n-form-item-gi`, closes [#1160](https://github.com/tusen-ai/naive-ui/issues/1160).\n\n## 2.18.1\n\n`2021-09-08`\n\n### Feats\n\n- `useDialog` option adds `style` prop, closes [#1054](https://github.com/tusen-ai/naive-ui/issues/1054).\n- `n-timeline` adds `icon` slot, closes [#1096](https://github.com/tusen-ai/naive-ui/issues/1096).\n- `n-timeline` adds `icon-size` prop.\n\n### Fixes\n\n- Fix `n-step` doesn't work with `v-for` children.\n- Fix `n-input-number` cannot enter decimals when `step` is not a decimal.\n\n## 2.18.0\n\n`2021-09-07`\n\n### Breaking Changes\n\n- `n-form` & `n-form-item` split `show-require-mark` into `show-require-mark` and `require-mark-placement`.\n\n### Feats\n\n- `n-drawer` adds `on-mask-click` prop.\n- `n-for` adds `require-mark-placement` prop, closes [#1055](https://github.com/tusen-ai/naive-ui/issues/1055).\n- `n-form-item` adds `require-mark-placement` prop, closes [#1055](https://github.com/tusen-ai/naive-ui/issues/1055).\n\n### Fixes\n\n- Fix `n-step` must be passed with `internal-index`.\n- Fix `n-radio-group`'s `on-update:value` and `on-update-value` can't be array.\n- Fix `n-cascader` `check-strategy=\"child\"` doesn't behaves the same as previous `leaf-only`.\n\n## 2.17.2\n\n`2021-09-06`\n\n### Fixes\n\n- Fix `n-tree-select` shows key not label when `show-path=true`, closes [#1095](https://github.com/tusen-ai/naive-ui/issues/1095).\n\n## 2.17.1\n\n`2021-09-06`\n\n### Fixes\n\n- Fix `n-cascader` menu not showing correct checked keys.\n\n## 2.17.0\n\n`2021-09-05`\n\n### Breaking Changes\n\n- `n-tree-select`'s `leaf-only` prop is deprecated, please use `check-strategy=\"child\"` instead.\n- `n-cascader`'s `leaf-only` prop is deprecated, please use `check-strategy=\"child\"` instead.\n- `n-input`'s `show-password-toggle` is deprecated, please use `show-password-on=\"click\"` instead.\n\n### Fixes\n\n- Fix `n-cascader` click tag to delete the sub option in multi selection mode, and the tree option is not updated.\n- Fix `n-input` chinese input method not correct while mouse leave the input in `clearable` is true, closes [#905](https://github.com/tusen-ai/naive-ui/issues/905).\n- Fix `n-description`'s warning caused by `v-if` that should not appear, closes [#1083](https://github.com/tusen-ai/naive-ui/issues/1083).\n- Fix `n-layout`'s `sider-placement` doesn't work after build, closes [#978](https://github.com/tusen-ai/naive-ui/issues/978).\n- Fix `n-input-number`'s `step` calculate error when the value is decimal, closes [#1007](https://github.com/tusen-ai/naive-ui/issues/1007).\n- Fix `n-popselect`' s default placement and padding.\n- Fix `n-calendar`'s text color of disabled date.\n\n### Feats\n\n- `n-cascader` adds `onUpdateValue` prop.\n- `n-auto-complete` adds `onUpdateValue` prop.\n- `n-data-table`'s column's `renderFilterMenu` adds `hide` param.\n- `n-tree` adds `key-field` prop.\n- `n-tree` adds `label-field` prop.\n- `n-tree` adds `children-field` prop.\n- `n-tree-select` adds `key-field` prop.\n- `n-tree-select` adds `label-field` prop.\n- `n-tree-select` adds `children-field` prop.\n- `n-cascader` adds `key-field` prop.\n- `n-cascader`adds `label-field` prop.\n- `n-cascader` adds `children-field` prop.\n- `n-dropdown` option adds `props` prop, closes [#813](https://github.com/tusen-ai/naive-ui/issues/813).\n- `n-data-table` supports multi-selection by holding down `shift`, closes [#554](https://github.com/tusen-ai/naive-ui/issues/554).\n- `n-tree-select` adds `check-strategy` prop, closes [#624](https://github.com/tusen-ai/naive-ui/issues/624).\n- `n-cascader` adds `check-strategy` prop.\n- `n-message` option adds `keepAliveOnHover`, closes [#1036](https://github.com/tusen-ai/naive-ui/issues/1036).\n- `n-message-provider` adds `keep-alive-on-hover` prop, closes [#1036](https://github.com/tusen-ai/naive-ui/issues/1036).\n- `n-upload` export `UploadFile` type.\n- `n-cascader` export `CascaderOption` type.\n- `n-mention` export `MentionOption` type.\n- `n-transfer` export `TransferOption` type.\n- `n-pagination` export `PaginationInfo` type.\n- `n-data-table` export `DataTableCreateSummary` type.\n- `n-code` adds `inline` prop, closes [#834](https://github.com/tusen-ai/naive-ui/issues/834).\n- `n-collapse` adds `header-extra` slot, closes [#1046](https://github.com/tusen-ai/naive-ui/issues/1046).\n- `n-input` adds `show-password-on` prop.\n- `n-upload` adds `list-type`, `show-preview-button`, `on-preview` and `create-thumbnail-url` prop.\n\n## 2.16.7\n\n`2021-08-27`\n\n### Feats\n\n- `n-mention` adds `focus` and `blur` methods.\n\n### Fixes\n\n- Fix `n-mention`'s menu is too far from text in input mode.\n- Fix `n-tree` node can not expanded.\n\n## 2.16.6\n\n`2021-08-26`\n\n### Feats\n\n- `n-timeline` adds `horizontal` prop, closes [#887](https://github.com/tusen-ai/naive-ui/issues/887).\n- `n-image` adds `preview-src` prop, closes [#922](https://github.com/tusen-ai/naive-ui/issues/922).\n- `n-dynamic-tags` adds `input` and `add` slot, closes [#499](https://github.com/tusen-ai/naive-ui/issues/499).\n- `n-timeline-item` adds `color` prop.\n\n### Fixes\n\n- Fix `n-image` not initializing `rotate` after switching images, closes [#921](https://github.com/tusen-ai/naive-ui/issues/921).\n- Fix `n-data-table`'s loading is not centered, closes [#929](https://github.com/tusen-ai/naive-ui/issues/929).\n- Fix `n-tree` throws an exception when onLoad callback does not adds children, closes [#772](https://github.com/tusen-ai/naive-ui/issues/772).\n- Fix `n-input` will show placeholder and 0 simultaneously while passing `value=ref(0)` in n-input, closes [#914](https://github.com/tusen-ai/naive-ui/issues/914).\n- Fix `n-data-table` `flex-height` not working without `scroll-x`, closes [#952](https://github.com/tusen-ai/naive-ui/issues/952).\n\n## 2.16.5\n\n`2021-08-20`\n\n### Feats\n\n- `n-input-number` adds `clearable` prop.\n- `n-form` adds `show-label` prop, closes [#858](https://github.com/tusen-ai/naive-ui/issues/858).\n\n### Fixes\n\n- Fix `n-notification`'s exported `NotificationReactive` type is not writable, closes [#876](https://github.com/tusen-ai/naive-ui/issues/876).\n- Fix `n-tabs` style glitches when different types tabs are nested, closes [#850](https://github.com/tusen-ai/naive-ui/issues/850).\n- Fix `n-dropdown`'s inner link click trigger area is not the entire option, closes [#823](https://github.com/tusen-ai/naive-ui/issues/823).\n- Fix `n-popover` arrow's misplacement when placed in nested popovers with different placement, closes [#916](https://github.com/tusen-ai/naive-ui/issues/916).\n- Fix `n-ellpisis` doesn't work after content is updated, closes [#776](https://github.com/tusen-ai/naive-ui/issues/776).\n\n## 2.16.4\n\n`2021-08-16`\n\n### Fixes\n\n- Fix ruRU locale exports.\n\n## 2.16.3\n\n`2021-08-16`\n\n### i18n\n\n- Add ruRU locale [#852](https://github.com/tusen-ai/naive-ui/pull/852).\n\n### Feats\n\n- `n-message-provider` adds `container-style` prop.\n- `n-message-provider` adds `placement` prop.\n- `n-message` adds class to distinguish type.\n- `n-date-picker` adds `shortcuts` props, closes [#280](https://github.com/tusen-ai/naive-ui/issues/280).\n\n### Fixes\n\n- Fix `n-rate` half star overlays star background in dark mode.\n- Fix `n-menu` renders unexpectly when `render-icon` returns `true`.\n- Fix `n-space` render empty placeholder while use `v-if`, closes [#824](https://github.com/tusen-ai/naive-ui/issues/824).\n\n## 2.16.2\n\n`2021-08-09`\n\n### Feats\n\n- `n-message-provider` adds `closable` prop, closes [#795](https://github.com/tusen-ai/naive-ui/issues/795).\n- `n-tree-select` adds `show-path` prop, closes[#625](https://github.com/tusen-ai/naive-ui/issues/623).\n- `n-layout` adds `sider-placement` prop, closes [#566](https://github.com/tusen-ai/naive-ui/issues/566).\n\n### Fixes\n\n- Fix `n-avatar`'s scale value is incorrect while use v-show, closes [#779](https://github.com/tusen-ai/naive-ui/issues/779).\n- Fix `n-menu` show a blue background when click the menu on mobile phone, closes [#799](https://github.com/tusen-ai/naive-ui/issues/799).\n- Fix `n-select` filterable select breaks, closes [#510](https://github.com/tusen-ai/naive-ui/issues/510).\n- Fix `n-data-table` When selectAll is selected, the state display of selectAll should not contain disabled rows, closes [#778](https://github.com/tusen-ai/naive-ui/issues/778).\n- Fix `n-color-picker`'s `on-complete` callback's argument `value` is incorrect, closes [#748](https://github.com/tusen-ai/naive-ui/issues/748).\n\n## 2.16.1\n\n`2021-08-06`\n\n### Feats\n\n- `n-loading-bar-provider` adds `loading-bar-style` props, closes [#457](https://github.com/tusen-ai/naive-ui/issues/457).\n- `n-button` adds `text-color` prop.\n- `n-form` export `FormValidationError` type.\n- `n-popconfirm` support not show action components, closes [#770](https://github.com/tusen-ai/naive-ui/issues/770).\n\n### Fixes\n\n- Fix `n-slider` loss floating point decimal precision, closes [#751](https://github.com/tusen-ai/naive-ui/issues/751).\n- Fix `n-data-table` `onUpdatePage` and `onUpdatePageSize` not triggered while using jsx.\n- Fix `n-progress`'s `percentage` prop default value doesn't work with different types.\n- Fix `n-select` hide close icon when option is disabled.\n- Fix `n-modal` can't be closed when using custom content, closes [#788](https://github.com/tusen-ai/naive-ui/issues/788).\n\n## 2.16.0\n\n`2021-08-02`\n\n### Breaking Changes\n\n- `useLoadingBar`'s `finish` method won't work if no `start` is called.\n- `n-input`'s `type='input'` is renamed to `type='text'`.\n\n### Feats\n\n- `n-scrollbar` adds `scrollbarWidth`, `scrollbarHeight` and `scrollbarBorderRadius` common theme variables, closes [#649](https://github.com/tusen-ai/naive-ui/issues/649).\n- `n-menu` doesn't should icon placeholder when `render-icon` returns falsy value, closes [#722](https://github.com/tusen-ai/naive-ui/issues/722).\n- `n-menu` adds `render-extra` prop.\n- `n-select` adds `on-clear` prop.\n- `n-form` adds `disabled` prop, closes [#538](https://github.com/tusen-ai/naive-ui/issues/538).\n- `n-dynamic-tags` adds `max` prop.\n\n### Fixes\n\n- Fix `n-dropdown` click exception when using v-for.\n- Fix `n-modal` cannot customize classes when use preset, closes [#744](https://github.com/tusen-ai/naive-ui/issues/744).\n- Fix `n-cascader` menu width shifts in virtual scroll mode, closes [#728](https://github.com/tusen-ai/naive-ui/issues/728).\n\n## 2.15.11\n\n`2021-07-29`\n\n### Fixes\n\n- Fix `n-data-table` pagination's error.\n\n## 2.15.10\n\n`2021-07-29`\n\n### Feats\n\n- `n-pagination` adds `prev` and `next` slots, ref [#648](https://github.com/tusen-ai/naive-ui/issues/648).\n- `n-tag` adds `color` prop, closes [#693](https://github.com/tusen-ai/naive-ui/issues/693).\n- `n-dynamic-tags` adds `color`, closes [#693](https://github.com/tusen-ai/naive-ui/issues/693).\n- `n-time-picker` optimization the now button logic, closes [#401](https://github.com/tusen-ai/naive-ui/issues/401).\n- `n-pagination` `PaginationInfo` adds `itemCount` prop, closes [#585](https://github.com/tusen-ai/naive-ui/issues/585).\n- `n-select` adds `on-clear` prop.\n\n### Fixes\n\n- Fix `n-message`'s `destroyAll` method doesn't work.\n- Fix `n-timeline`'s header slot is invalid when using alone.\n- Fix `n-select` incorrect style when props has `disabled` and `filterable`, closes [#698](https://github.com/tusen-ai/naive-ui/issues/698).\n- Fix `n-upload` operation buttons displayed when has `file-list` & `disabled` props, closes [#668](https://github.com/tusen-ai/naive-ui/issues/668).\n\n## 2.15.9\n\n`2021-07-28`\n\n### Feats\n\n- `n-message` adds `destroyAll` method.\n- `n-input-number` adds `prefix`, `suffix` slots, closes [#609](https://github.com/tusen-ai/naive-ui/issues/609).\n\n### Fixes\n\n- Fix `n-message` options' `duration` prop doesn't work.\n\n## 2.15.8\n\n`2021-07-27`\n\n### Feats\n\n- `n-menu` adds `expand-icon` prop, closes [#414](https://github.com/tusen-ai/naive-ui/issues/414).\n- `n-descriptions`, `n-descriptions-item` adds `label-style` and `content-style` props, closes [#536](https://github.com/tusen-ai/naive-ui/issues/536).\n\n### Fixes\n\n- Fix `n-data-table` the style penetration of the `n-spin`, closes [#663](https://github.com/tusen-ai/naive-ui/issues/663).\n\n## 2.15.7\n\n`2021-07-25`\n\n### Feats\n\n- `n-dropdown` adds `show-arrow` prop, closes [#647](https://github.com/tusen-ai/naive-ui/issues/647).\n- `n-time-picker` adds `actions` prop, closes [#401](https://github.com/tusen-ai/naive-ui/issues/401).\n- `n-mention` adds `render-label` prop.\n- `n-switch` adds `checked`, `unchecked` slots.\n- `n-switch` adds `loading` prop, closes [#301](https://github.com/tusen-ai/naive-ui/issues/301).\n- `n-select` pressing arrow down can open menu, ref [#300](https://github.com/tusen-ai/naive-ui/issues/300).\n- `n-tree-select` pressing arrow down can open menu, ref [#300](https://github.com/tusen-ai/naive-ui/issues/300).\n- `n-cascader` pressing arrow down can open menu, ref [#300](https://github.com/tusen-ai/naive-ui/issues/300).\n- `n-popover`'s `trigger` prop support `'focus'`, closes [#477](https://github.com/tusen-ai/naive-ui/issues/477).\n- `n-message-provider` adds `duration` and `max` props.\n- `n-data-table` adds `flex-height` prop, closes [#596](https://github.com/tusen-ai/naive-ui/issues/596).\n\n### Fixes\n\n- Fix `n-carousel` arrow buttons cannot be displayed in a specific browser, closes [#625](https://github.com/tusen-ai/naive-ui/issues/625).\n- Fix `n-layout-sider`'s `width` prop can't be string, closes [#607](https://github.com/tusen-ai/naive-ui/issues/607).\n- Fix `n-slider` prop `disabled` doesn't work, closes [#641](https://github.com/tusen-ai/naive-ui/issues/641).\n- Fix `n-input` show clear button when readonly.\n- Fix `n-data-table` doesn't show scrollbar when table-layout is auto, closes [#518](https://github.com/tusen-ai/naive-ui/issues/518).\n- Fix `n-data-table`'s header checkbox always displays checked when data is empty.\n- Fix `n-data-table` header and body's scrollings are not sync.\n\n## 2.15.6\n\n`2021-07-23`\n\n### Feats\n\n- `n-menu` adds `render-icon` prop.\n- `n-upload` adds `show-file-list` prop.\n- `n-dropdown` adds `render-icon` prop.\n- `n-checkbox-group` adds `min` and `max` prop.\n- `n-mention` adds `empty` slot.\n- `useDialog` option adds `on-mask-click` prop, closes [#419](https://github.com/tusen-ai/naive-ui/issues/419).\n- `n-space` `justify` prop supports `center`, `space-around` and `space-between`.\n- `n-date-picker` adds `close-on-select` prop, closes [#541](https://github.com/tusen-ai/naive-ui/issues/541).\n- `n-dialog` adds `action` prop, closes [#550](https://github.com/tusen-ai/naive-ui/issues/550).\n- `n-mention`’s `option.label` support render function.\n- `n-color-picker` adds `actions` prop, closes [#319](https://github.com/tusen-ai/naive-ui/issues/319).\n\n### Fixes\n\n- Fix `n-space`'s inner `display: grid` element breaks item height, closes `https://github.com/tusen-ai/naive-ui/issues/546`.\n- Fix `n-dropdown`'s `render-label` prop is invalid for group type option.\n- Fix `n-datatable`'s `scroll-x` prop is setted, the table content width is not full of the container width, closes [#518](https://github.com/tusen-ai/naive-ui/issues/518).\n- Fix `n-descriptions` doesn't work with `v-for` children.\n- Fix `n-dialog` display an empty button when `positive-text` is not set, closes [#549](https://github.com/tusen-ai/naive-ui/issues/549).\n- Fix `n-pagination` `PaginationInfo`'s `endIndex` data error, closes [#584](https://github.com/tusen-ai/naive-ui/issues/584).\n- Fix `n-data-table` `rowClassName` doesn't work when type is string, closes [#582](https://github.com/tusen-ai/naive-ui/issues/582).\n\n## 2.15.5\n\n`2021-07-16`\n\n### Feats\n\n- `n-tree` adds `render-label`, `render-prefix` and `render-suffix` props.\n- `n-rate` adds `allow-half` prop.\n- `n-carousel` adds `show-arrow` prop.\n- `n-slider` adds `format-tooltip` prop.\n- `n-upload` adds `event` in `on-finish` callback params.\n- `n-rate` adds `readonly` prop.\n- `n-time-picker` adds `seconds`, `minutes`, `hours` props.\n- `n-notification` export `NotificationApi`, `NotificationOptions` and `NotificationReactive` type.\n- `n-avatar` adds `on-error` prop, closes [#394](https://github.com/tusen-ai/naive-ui/issues/394).\n- `n-image` adds `on-error` prop, closes [#394](https://github.com/tusen-ai/naive-ui/issues/394).\n- `n-image` adds `object-fit` prop, closes [#394](https://github.com/tusen-ai/naive-ui/issues/394).\n- `n-avatar` adds `object-fit` prop, closes [#394](https://github.com/tusen-ai/naive-ui/issues/394).\n- `n-menu` expands all the ascendant of selected item by default, closes [#481](https://github.com/tusen-ai/naive-ui/issues/481).\n\n### Fixes\n\n- Fix `n-calendar`'s `default-value` prop cannot be used.\n- Fix `n-pagination` page count is not correct when `item-count` is 0.\n- Fix `n-scrollbar` `content-style` can not override the default width of style.\n- Fix `n-select` placeholder transition.\n- Fix `n-loading-bar` `useLoadingBar`'s return type can be undefined.\n- Fix `n-tag`'s `type` prop adds `primary` type.\n- Fix `n-dynamic-tags`'s `type` prop adds `primary` type.\n\n## 2.15.4\n\n`2021-07-09`\n\n### Feats\n\n- `n-steps` adds icon customization in `'finish'` and `'error'` status.\n- `n-tree` exports `TreeDragInfo` & `TreeDropInfo` type.\n- `n-empty` export `icon` slot.\n- `useDialog` option adds `maskClosable` prop, closes [#420](https://github.com/tusen-ai/naive-ui/issues/420).\n\n### Fixes\n\n- Fix `n-data-table` fixed column box-shadow doesn't update when there is only on side fixed.\n- Fix `n-data-table` fixed column box-shadow doesn't update when `props.scrollX` is not set but each column's width is set.\n- Fix `n-result` image doesn't show on Safari and mobile phone.\n- Fix `n-drawer-content`'s `header-style` style not applied to header.\n- Fix `n-dialog` instance throws error when calling `destroy`.\n- Fix `n-image-group` initialize zoom scale when switching a picture [#423](https://github.com/tusen-ai/naive-ui/issues/423).\n- Fix `n-select` bug in using custom label, closes [#352](https://github.com/tusen-ai/naive-ui/issues/352).\n- Fix `n-carousel` when `autoplay` dot active status isn't displayed correctly, closes [#434](https://github.com/tusen-ai/naive-ui/issues/434).\n- Fix `n-input` fixed clearable position, closes [#428](https://github.com/tusen-ai/naive-ui/issues/428).\n- Fix `n-image` doesn't accept attributes.\n- Fix `n-image` set border-radius not working, closes [#427](https://github.com/tusen-ai/naive-ui/issues/427).\n- Fix `n-tab-pane` throws error when there's no children.\n- Fix `n-select` clear button is too big in `n-spin`, closes [#454](https://github.com/tusen-ai/naive-ui/issues/454).\n- Fix `n-select` options are not updated properly, closes [#441](https://github.com/tusen-ai/naive-ui/issues/441).\n\n## 2.15.3\n\n`2021-07-05`\n\n### Feats\n\n- `n-loading-bar` export `LoadingBarApi` type.\n- `n-image` adds `img-props` prop.\n- Add native `title` attributes to some components to enhance the experience.\n- `n-tree` adds `prefix` and `suffix` in TreeOption.\n- `n-carousel` adds `dot-placement` prop.\n- `n-auto-complete` adds `loading` prop, closes [#241](https://github.com/tusen-ai/naive-ui/issues/241).\n- `n-slider` adds `tooltip` prop, closes [#362](https://github.com/tusen-ai/naive-ui/issues/362).\n- `n-input` adds `loading` prop.\n\n### Fixes\n\n- Fix `n-upload` `multiple=false` doesn't work for drag & drop, closes [#363](https://github.com/tusen-ai/naive-ui/issues/363).\n- Fix `n-dropdown`'s inner `<a />`'s style.\n- Fix `n-menu` tooltip's inner `<a />`'s style, closes [#338](https://github.com/tusen-ai/naive-ui/issues/338).\n- Fix `n-carousel` doesn't work with `v-for` children.\n- Fix `n-form` `label-align` prop not working, closes [#213](https://github.com/tusen-ai/naive-ui/issues/213).\n- Fix `n-data-table` fixed column shadow doesn't work when `max-height` is set, closes [#376](https://github.com/tusen-ai/naive-ui/issues/376).\n\n## 2.15.2\n\n`2021-07-02`\n\n### Feats\n\n- `n-carousel` adds `trigger` prop.\n- `n-menu` adds `dropdown-placement` prop.\n- `n-upload` adds `before-upload` prop.\n- `n-image` adds `alt` prop.\n- Support the enter key on the numeric keypad.\n- `n-spin` support `icon` slot for icon customizing, closes[#260](https://github.com/tusen-ai/naive-ui/issues/260).\n- `n-spin` adds `rotate` prop fro slot icon to rotate.\n- `n-form` export `FormItemRule` & `FormRules` type.\n- `n-select` adds `render-tag` prop.\n\n### Fixes\n\n- Fix `n-log` warn on highlight.js when no language is set, closes [#327](https://github.com/tusen-ai/naive-ui/issues/327).\n- Remove `n-calendar`'s useless `console.log`.\n- Fix loading-bar disappears unexpectl, closes [#343](https://github.com/tusen-ai/naive-ui/issues/343).\n- Fix `n-select` doesn't scroll to selected item when menu is opened, closes [#346](https://github.com/tusen-ai/naive-ui/issues/346).\n- Fix `n-tab-pane` throws error when using v-if.\n- Fix `n-modal` still closes when `on-negative-click` returns `false`.\n- Fix `n-collapse` `defaultExpandedNames` does not work in accordion mode, closes [#350](https://github.com/tusen-ai/naive-ui/issues/350).\n- Fix `n-tag` lacks `on-update-checked` prop.\n- Fix `n-menu` `render-label` not working for dropdown in collapsed mode.\n\n## 2.15.1\n\n`2021-06-30`\n\n- Fix no `web-types.json`.\n\n## 2.15.0\n\n`2021-06-29`\n\n### Breaking Changes\n\n- `n-select`'s `SelectOption`'s `render` no longer render label but the entire option.\n\n### Feats\n\n- `n-carousel` supports touch operation, closes [#271](https://github.com/tusen-ai/naive-ui/issues/271).\n- `n-input` adds `input-props` prop.\n- `n-message` optimize the error message of `useMessage` when there is no `n-message-provider`, adds the related document link.\n- Add `web-types.json` for webstorm, however I recommend using VSCode and Volar. `web-types.json` only provides limited information for coding.\n- `n-tree-select` adds `leaf-only` prop.\n- `n-tree` adds `leaf-only` prop.\n- `n-select`'s `SelectOption`'s `label` supports render function.\n- `n-select` adds `render-option` prop.\n- `n-select` export `SelectOption` & `SelectGroupOption` type.\n- `n-popover` adds `header` slot.\n- `n-dropdown` adds `render-label` prop.\n\n### Fixes\n\n- Fix `n-date-picker` `n-provider` pass `date-locale` not work, closes [#250](https://github.com/tusen-ai/naive-ui/issues/250).\n- Fix `n-input` clear button placeholder prevent clicking on actual component, closes [#288](https://github.com/tusen-ai/naive-ui/issues/288).\n- Fix `n-carousel` click the at current item button, the component behaves abnormally.\n- Fix `n-menu` `render-label` not working for tooltip in collapsed mode.\n- Fix `n-dropdown` can't render `n-popover` in option.\n\n## 2.14.0\n\n`2021-06-23`\n\n### Breaking Changes\n\n- `n-element` removes `abstract` prop.\n- `n-element` doesn't return theme variables in default slot. Please use `useThemeVars` instead.\n\n### Feats\n\n- Add `n-carousel` component.\n- Add `useThemeVars` composable to provide theme variables.\n- `n-upload` adds `on-update:file-list` prop, closes [#135](https://github.com/tusen-ai/naive-ui/issues/135).\n- `n-date-picker` adds `update-value-on-close` prop.\n\n### Fixes\n\n- Fix `n-select` can't input in filterable mode in single mode in iOS Safari, closes [#230](https://github.com/tusen-ai/naive-ui/issues/230).\n- Fix `n-input-number` lacks `on-update-value` prop.\n- Fix `n-input-number`'s value can't be null.\n- Fix `n-input-number`'s button doesn't work after value is cleared, closes [#251](https://github.com/tusen-ai/naive-ui/issues/251).\n- Fix `n-data-table` expand trigger's cursor is not pointer, closes [#261](https://github.com/tusen-ai/naive-ui/issues/261).\n\n## Refactors\n\n- `n-input-number` will focus directly, closes [#244](https://github.com/tusen-ai/naive-ui/issues/244).\n\n## 2.13.0\n\n`2021-06-21`\n\n### Feats\n\n- `n-dropdown` adds `on-clickoutside` prop, closes [#123](https://github.com/tusen-ai/naive-ui/issues/123).\n- `n-menu` adds `render-label` prop, closes [#84](https://github.com/tusen-ai/naive-ui/issues/84).\n- `n-tree` supports keyboard operations.\n- Add `n-tree-select` component.\n\n### Fixes\n\n- Fix `n-tree` drag over leaf node causes error, closes [#200](https://github.com/tusen-ai/naive-ui/issues/200).\n- Fix `n-tree` misses `on-update-expanded-keys`, `on-update-selected-keys`, `on-update-checked-keys` prop.\n- Fix `n-tree`'s `selected-keys` prop influences original array.\n- Fix `n-select`'s input has useless empty row in multiple filterable mode.\n- Fix `n-button`'s loading icon doesn't show on iOS Safari, closes [#219](https://github.com/tusen-ai/naive-ui/issues/219).\n- Fix `n-date-picker` doesn't show icon when clearable.\n- Fix `n-time-picker` icon mis-aligned when clearable, closes [#222](https://github.com/tusen-ai/naive-ui/issues/222).\n\n## 2.12.2\n\n`2021-06-19`\n\n### Fixes\n\n- Fix `n-form-item` always show require mark.\n\n## 2.12.1\n\n`2021-06-19`\n\n### Feats\n\n- `n-form`, `n-form-item` enhance `show-require-mark` prop, closes [#171](https://github.com/tusen-ai/naive-ui/issues/171).\n- `n-dropdown` support class attr, closes [#180](https://github.com/tusen-ai/naive-ui/issues/180).\n- `n-input` adds `show-password-toggle` prop.\n- `n-popselect` support class attr.\n- `n-select` adds `render-label` prop.\n- `n-popselect` adds `render-label` prop.\n\n### Fixes\n\n- Fix `n-input` baseline shifts when mix Chinese and English characters in input, closes [#174](https://github.com/tusen-ai/naive-ui/issues/174).\n- Fix `n-icon` use setup script, `$parent` is an empty object by default, and access `$parent.$options` will be `undefined`.\n- Fix `n-notification` position not correct.\n- Fix `n-message` content & option type not correct.\n\n## 2.12.0\n\n`2021-06-16`\n\n### Breaking Changes\n\n- `n-a`'s `to` prop is removed. Now if you want to use `n-a` like a router link, you can follow the doc site.\n\n### Feats\n\n- `n-tree` support `disabled` & `checkboxDisabled` on option.\n- `n-input-number` support keyboard events ArrowUp and ArrowDown operations.\n\n### Fixes\n\n- Fix `n-cascader` text blur in win10 Chrome.\n- Fix `n-tree` click on indent won't trigger select in block line mode.\n\n## 2.11.12\n\n`2021-06-16`\n\n### Feats\n\n- `n-drawer-content` adds `closable` prop, closes [#139](https://github.com/tusen-ai/naive-ui/issues/139).\n- `n-element` pass `themeVars` to default slot.\n- `n-element` adds `abstract` prop.\n\n### Fixes\n\n- Fix `n-radio-group` doesn't trigger form item validation.\n- Fix `n-auto-complete` customizing input not working.\n\n## 2.11.11\n\n`2021-06-15`\n\n### Feats\n\n- `n-tag` adds `RTL` support.\n\n### Fixes\n\n- Move `vue` & `vue-router` to peer dependencies to avoid redundant bundle.\n\n## 2.11.9\n\n`2021-06-15`\n\n### Feats\n\n- `n-space` supports wai-aria.\n- `n-button-group` supports wai-aria.\n- `n-progress` supports wai-aria.\n- `n-menu` supports use `<a />` and `<router-link />` as label, closes [#84](https://github.com/tusen-ai/naive-ui/issues/84).\n- `n-input-number` adds `show-button` prop.\n- `n-rate` support `default` slot for icon customizing.\n- `n-rate` adds color prop.\n- `n-rate` adds size prop.\n\n### Fixes\n\n- Fix `n-card`'s `header-style` it not applied to header, closes [#103](https://github.com/tusen-ai/naive-ui/issues/103).\n- Fix `n-dialog` misses `destroyAll` method.\n- Fix `n-data-table` misses `on-update-sorter`, `on-update-filters`, `on-update-page` and `on-update-page-size` props.\n\n## 2.11.8\n\n`2021-06-13`\n\n### Feats\n\n- `n-data-table` exports `DataTableCreateRowClassName`, `DataTableCreateRowKey` and `DataTableCreateRowProps` type.\n\n### Fixes\n\n- Fix `n-calendar`'s `on-update:value` prop type.\n- Fix `n-form-item`'s style attribute `grid-template-columns` influence on the layout of child elements, closes [#93](https://github.com/tusen-ai/naive-ui/pull/93).\n- Fix `n-data-table`'s prop types of `rowKey`, `rowClassName`, `rowProps`, `summary` aren't compatible with expected value.\n\n## 2.11.7\n\n`2021-06-12`\n\n### Fixes\n\n- Fix `n-slider` doesn't prevent scrolling when touchstart.\n- Fix `n-color-picker`'s default value doesn't follow modes.\n- Fix not `lodash` & `lodash-es` type.\n\n## 2.11.6\n\n`2021-06-11`\n\n### Feats\n\n- `n-spin`'s `size` prop support number.\n- `n-date-picker` adds `footer` slot.\n\n### Fixes\n\n- Fix `n-slider` doesn't support touch events.\n- Fix `n-button` causes crash when it's imported in script inside head tag, closes [#68](https://github.com/tusen-ai/naive-ui/pull/68).\n- Fix `n-spin` animation shifts.\n- Fix `n-menu` lack `on-update-value` and `on-update-expanded-keys` props.\n- Fix `n-popconfirm` icon slot not working.\n- Fix `n-tabs` logs useless info.\n- Fix `n-color-picker` set `modes` not working, closes [#77](https://github.com/tusen-ai/naive-ui/issues/77).\n\n## 2.11.5\n\n`2021-06-10`\n\n### Feats\n\n- `n-dropdown` adds `disabled` prop.\n- `n-card` adds `:target` style.\n\n### Fixes\n\n- Fix `n-popover` sometimes won't sync position in manual mode.\n- Fix `n-transfer`'s empty icon is no toggling transition.\n- Fix `n-message` API option is not optional.\n- Fix `n-calendar` date calculate incorrectly.\n- Fix `n-input` misses the `password` type declaration.\n- Fix `n-menu` the type definition of `extra` property of menu and submenu.\n- Fix `n-dropdown` mouse cursor is not pointer.\n\n## 2.11.4\n\n`2021-06-07`\n\n### Feats\n\n- `n-button` supports wai-aria.\n- `n-card` supports wai-aria.\n- `n-switch` supports wai-aria.\n- `n-menu` supports basic wai-aria.\n- `n-divider` supports basic wai-aria.\n- `n-data-table` adds `row-props` prop.\n- `n-date-picker` adds `ranges` prop.\n\n### Fixes\n\n- Fix `n-tab-pane` `display-directive` not working.\n- Fix `n-drawer` animation.\n- Fix `n-scrollbar`'s track may be overlayed in chrome windows.\n\n## 2.11.3\n\n`2021-06-05`\n\n- Fix `n-collapse` `default-expanded-names` not working.\n\n## 2.11.2\n\n`2021-06-05`\n\n### Fixes\n\n- Fix `n-dropdown` default placement is not `bottom`.\n- Fix `n-date-picker`'s input theme is not set in `date` & `datetime` type.\n- Fix `n-config-provider` doesn't merge inherited theme.\n\n### Feats\n\n- `n-collapse` adds `arrow` slot.\n\n## 2.11.1\n\n`2021-06-05`\n\nUpdate package.json & README.md.\n\n## 2.11.0\n\n`2021-06-05`\n\n### Breaking Changes\n\n- `n-affix`'s `listen-to` prop is `document` by default (first scrollable parent before).\n\n### Feats\n\n- `n-affix`'s `listen-to` prop support `Window | Document | HTMLElement`.\n- `n-anchor` adds `offset-target` prop.\n- `n-select` adds `virtual-scroll` prop.\n- `n-select` adds `consistent-menu-width` prop.\n- `n-date-picker` update value after confirm is clicked.\n\n### Fixes\n\n- Fix `n-date-picker` doesn't disable start date correctly when value is empty.\n- Fix `n-input-number` not restore valid value after blur.\n- Fix `n-date-picker` display selected date when value is null in date mode.\n\n### Deprecated\n\n- `n-affix`'s `offset-top` prop is deprecated, please use `trigger-top` instead.\n- `n-affix`'s `offset-bottom` prop is deprecated, please use `trigger-bottom` instead.\n- `n-anchor`'s `listen-to` prop is removed.\n\n## 2.10.0\n\n`2021-05-26`\n\n### Breaking Changes\n\n- `n-popover`'s `placement` prop default value is set to `'top'`.\n\n### Feats\n\n- `n-tabs` adds `on-close` prop.\n- `n-tabs` adds `on-add` prop.\n- `n-tabs` adds `tab` slot.\n- `n-tab-pane`'s `tab` prop support render function & VNode.\n- `n-tabs`'s `type` prop support `'line'` option.\n- `n-tabs` adds box shadow to indicate scroll status.\n- `n-tabs` adds `pane-style` prop.\n\n### Fixes\n\n- Fix `n-layout`'s `scrollTo` not working when using native scrollbar.\n\n### Deprecated\n\n- `n-tab-pane`'s `label` prop is deprecated. Please use `tab` prop instead.\n\n## 2.9.0\n\n`2021-05-25`\n\n### Breaking Changes\n\n- `n-layout-sider` removed `show-content` prop. Please use `show-collapsed-content` instead.\n\n### Feats\n\n- `n-data-table` support tree data.\n- `n-data-table` adds `cascade` prop.\n- `n-data-table` adds `children-key` prop.\n- `n-data-table` adds `indent` prop.\n- `n-button` adds `tag` prop.\n- `n-data-table` adds `table-layout` prop.\n- `n-tree` adds `block-line` prop.\n- `n-tree` support drag & drop.\n- `n-menu` adds `inverted` prop.\n- `n-dropdown` adds `inverted` prop.\n- `n-tabs` adds `addable` prop.\n- `n-tabs` adds `tab-style` prop.\n- `n-tabs` adds `tabs-padding` prop.\n- `n-tabs` adds `default-value` prop.\n- `n-layout-sider` & `n-layout-footer` & `n-layout-header` adds `inverted` prop.\n- `n-data-table`'s `max-height` & `min-height` prop accept CSS value.\n- `n-layout` & `n-layout-content` adds `embedded` prop.\n\n### Fixes\n\n- `n-layout` & `n-layout-sider`'s `scrollTo` not working with native scrollbar.\n- `n-layout-sider`'s `collapse-mode` not working.\n- Internal selection component's theme peers has wrong key for popover.\n\n## 2.8.0\n\n`2021-05-19`\n\n### Perf\n\n- Optimize `n-data-table` init render count.\n- Optimize `n-select` open duration after first opening.\n- Optimize `n-anchor` scroll performance.\n\n### Feats\n\n- `n-tree` adds `virtual-scroll` prop.\n- `n-data-table` adds `virtual-scroll` prop.\n- `n-cascader` adds `virtual-scroll` prop.\n- `n-pagination` adds `item-count` prop.\n- `n-pagination` adds `prefix` prop.\n- `n-pagination` adds `prefix` slot.\n- `n-pagination` adds `suffix` prop.\n- `n-pagination` adds `suffix` slot.\n- `n-input` adds `show-count` prop.\n\n### Fixes\n\n- Fix `n-layout-sider` doesn't show menu after collapsed.\n- Fix `n-input-number` doesn't reset to origin value when blur with invalid value.\n- Fix `n-pagination` doesn't update page in uncontrolled mode.\n\n## 2.7.4\n\n`2021-04-25`\n\n### Feats\n\n- `n-form-item` works without `n-form`.\n\n### Fixes\n\n- Fix `n-checkbox` check mark not displayed.\n- Fix `n-date-picker` icon transition style in trigger.\n- Fix `n-p`, `n-ol`, `n-ul` margin bottom is not 0 when they are last child.\n- Fix `n-checkbox-group` not working in uncontrolled mode.\n- Fix `n-data-table` clear check all in table now working.\n\n## 2.7.3\n\n`2021-04-22`\n\n### Feats\n\n- `n-data-table` highlight sorted col.\n- `n-data-table` col adds `render-filter` prop.\n- `n-data-table` col adds `render-filter-icon` prop.\n\n### Fixes\n\n- `n-data-table` fixed column box-shadow more clear in dark theme.\n- Fix `n-color-picker` value has line wrap.\n- Fix `n-form` FormRuleItem.trigger types.\n\n## 2.7.2\n\n`2021-04-21`\n\n### Feats\n\n- `n-data-table` adds `summary` prop.\n- `n-data-table` adds `options` on `'type=selection'` column.\n\n### Fixes\n\n- Fix `n-layout` overflow on horizontal direction.\n\n## 2.7.1\n\n`2021-04-20`\n\n### Feats\n\n- `n-checkbox` adds `focusable` prop.\n- `n-cascader` adds `action` slot.\n\n### Fixes\n\n- Fix `n-cascader` loading triggered when click checkbox.\n- Fix `n-cascader` menu mask style.\n\n## 2.7.0\n\n`2021-04-19`\n\n### Breaking Changes\n\n- `n-drawer` doesn't have padding by default. `n-drawer-content` is provided to fill the drawer.\n\n## 2.6.0\n\n`2021-04-19`\n\n### Feats\n\n- `n-drawer` adds `content-style` prop.\n- `n-layout` adds `content-style` prop.\n- `n-layout-sider` adds `content-style` prop.\n\n### Feats\n\n- `n-config-provider` Add `cls-prefix` prop.\n\n### Fixes\n\n- Fix `n-popover` may influence other popover when static props is hoisted.\n\n## 2.5.1\n\n`2021-04-14`\n\n### Feats\n\n- `n-color-picker` adds `show-alpha` prop.\n\n### Fixes\n\n- Fix `n-select` default `fallback-option` breaks the component.\n\n## 2.5.0\n\n`2021-04-13`\n\n### Feats\n\n- Add `n-skeleton` component.\n- Add `n-calendar` component.\n- Add `n-color-picker` component.\n- `n-date-picker` locale adds `firstDayOfWeek`.\n- `n-select` adds `showArrow` prop.\n\n### Fixes\n\n- Fix `n-date-picker` trigger has no focus style in focus is in panel.\n- Fix `n-button` loading's fade-in transtion drifts.\n- Fix `n-time-picker` close animation drifts in `n-date-picker`.\n- Fix detached components in popover should stay in popover.\n\n## 2.4.2\n\n`2021-04-08`\n\n### Feats\n\n- Add `n-form-item-gi` component.\n\n### Fixes\n\n- Fix `n-ellipsis` & `n-data-table` ellpisis cell mis-vertical-aligned.\n- Fix `n-select` filterable doesn't work with composite events.\n\n## 2.4.1\n\n`2021-04-07`\n\n### Fixes\n\n- Fix `n-select` caret color in single filter mode.\n- Fix `n-select` menu action part can't be focused.\n\n## 2.4.0\n\n`2021-04-07`\n\n### Feats\n\n- Add `n-image` component.\n- Add `n-global-style` component.\n- Add `n-theme-editor` component.\n- Add `n-page-header` component.\n- `n-statistic` adds `label` slot.\n- `n-breadcrumb-item` adds `separator` slot & prop.\n- `n-button` adds `bordered` prop.\n- `n-card` adds `footer-style` prop.\n\n### Refactors\n\n- Refactor `n-statistic`'s style.\n- `n-menu` adds `options` prop to replace `items` prop, `items` prop is deprecated.\n\n### Fixes\n\n- Fix `n-anchor` `ignore-gap` not working.\n- Fix `n-collapse` content is truncated by `overflow: hidden`.\n- Fix `n-select` tag text overflow.\n- Fix `n-popover` doesn't hide as expected in mobile phone.\n\n## 2.3.1\n\n`2021-03-29`\n\n### Fixes\n\n- Fix `n-layout-sider` horizontal content overflows.\n\n## 2.3.0\n\n`2021-03-29`\n\n### Breaking Changes\n\n- Collapsing won't work for `n-layout-sider` with `position=\"absolute\"`.\n- For `n-layout` contains `n-layout-sider` as a direct child `has-sider` must be set.\n\n## 2.2.0\n\n`2021-03-29`\n\n### Feats\n\n- Add `n-mention` component.\n- `n-data-table` supports expanding rows.\n\n### Fixes\n\n- Fix `n-input` focused background color not correct in warning & error status in dark theme.\n- Fix `n-input` caret color not correct in warning & error status.\n- Fix `n-select`'s namespace not correct.\n- Fix `n-cascader`'s namespace not correct.\n- Fix `n-input` in textarea mode can't select text.\n- Fix `n-input` in textarea mode has no box-shadow.\n- Fix `n-input` in textarea mode `autosize` line not correct due to inconsistant font family.\n- Fix `n-input` in textarea mode `autosize` rows not changed if props.value is changed from outside.\n\n### Refactors\n\n- Change `n-empty`'s icon and make it size larger.\n\n## 2.1.3\n\n`2021-03-25`\n\n### Fixes\n\n- Fix `n-data-table` has no right border of non-last td.\n- Fix `n-data-table` header has no enough width when table width is more than `scroll-x`.\n\n## 2.1.2\n\n`2021-03-24`\n\n### Feats\n\n- `n-data-table`'s column adds `colSpan` and `rowSpan` prop.\n- `n-data-table`'s column adds `titleColSpan` prop.\n\n### Fixes\n\n- Fix `n-dropdown` with `x` and `y` set logs errors when mouse move outside it.\n\n## 2.1.1\n\n`2021-03-22`\n\n### Fixes\n\n- Fix `n-select` selection overflow counter wrong popover trigger area.\n\n## 2.1.0\n\n`2021-03-22`\n\n### Breaking Changes\n\n- `n-popover` default `duration` is set to `100`.\n- `n-popover` default `delay` is set to `100`.\n- `n-tooltip` default `showArrow` is set to `true`.\n\n### Feats\n\n- `n-config-provider` prop `theme-overrides` support inheritance.\n- `n-card` adds `hoverable` prop.\n- `n-select` adds `max-tag-count` prop.\n- `n-cascader` adds `max-tag-count` prop.\n- `n-popover` adds `get-disabled` prop.\n- adds `n-ellipsis` component.\n- `n-popover`'s `width` prop adds `'trigger'` option.\n- `n-data-table`'s columns's `ellipsis` prop can be set as props of `n-ellipsis`.\n\n### Fixes\n\n- Fix `n-cascader` menu appears after click clear button.\n- Fix `n-card`'s action not placed at bottom after style height is set.\n- Fix `n-popover`'s `duration` and `delay` prop works unexpectly.\n\n## 2.0.1\n\n`2021-03-17`\n\n### Feats\n\n- `n-layout-sider` adds `default-collapsed` prop.\n- `n-modal` support custom position.\n\n### Fixes\n\n- Fix `n-menu` tooltip of `n-menu-item` won't show when vertical collapsed.\n- Fix `n-menu` `collapsed-icon-size` not working.\n- Fix `n-menu` callback props validate array with error.\n- Fix `n-layout-sider` toggle button is covered.\n\n## 2.0.0\n\n`2021-03-15`\n\nSee vue3.md\n\n## 1.6.0\n\n`2020-10-23`\n\n### Fixes\n\n- Fix the problem that `n-auto-complete`'s menu can't be closed when use `textarea` as input.\n- Fix the problem that nested `n-icon` is not flattened.\n- Fix the problem that `n-date-picker` has no year in panel when type is `date` and `datetime`.\n\n### Feats\n\n- `n-button` adds `dashed` props.\n- Add `n-space` component.\n- Make `n-drawer` content scrollable.\n\n### i18n\n\n- Add zhCN for `n-log`.\n\n## 1.5.5\n\n`2020-08-15`\n\n### Breaking Changes\n\n- Fix all typos of `separator` (originally it was `seperator`).\n\n### Fixes\n\n- Fix the problem that when theme is not set, style errors will be logged.\n- Fix the text color of `n-select`'s placeholder when `single` `filterable`.\n\n## 1.5.4\n\n`2020-08-08`\n\n### Fixes\n\n- Fix the problem that Message, Notification, Confirm doesn't follow theme change.\n\n## 1.5.3\n\n`2020-07-23`\n\n### Fixes\n\n- Fix the problem that `n-select` display with mistakes when `placeholder` is empty.\n\n## 1.5.2\n\n`2020-07-22`\n\n### Fixes\n\n- Fix the problem that `n-radio` can not be focused.\n- Fix the problem that `n-data-table`'s `max-height` style is broken, see <https://bugs.chromium.org/p/chromium/issues/detail?id=1107223>.\n\n### Refactors\n\n- Refactor `n-tag` styles.\n\n## 1.5.1\n\n`2020-07-20`\n\n### Feats\n\n- Add `disabled` for `n-time-picker`.\n\n### Fixes\n\n- Fix the child elements of `n-radio` cannot focus.\n\n## 1.5.0\n\n`2020-07-09`\n\n### Breaking Changes\n\n- Refactor experimental setting primary color feature.\n\n### Fixes\n\n- Fix some style glitches.\n\n## 1.4.1\n\n`2020-06-23`\n\n### Feats\n\n- Add `autofocus` for `n-select`.\n\n## 1.4.0\n\n`2020-06-19`\n\n### Breaking Changes\n\n- `n-menu` doesn't support slot API anymore.\n\n### Feats\n\n- Add experimental setting primary color feature.\n\n## 1.3.5\n\n`2020-06-06`\n\n### Feats\n\n- Add `attr-type` for `n-button`.\n\n### Fixes\n\n- Fix the problem that if `n-input` is too width, its inner input elements' width won't expand.\n- Fix style glitches of border of a `n-input-number` inside a `n-input-group`.\n\n## 1.3.4\n\n`2020-06-05`\n\n### Fixes\n\n- Fix the problem that `n-a`'s `to` prop can't be a object.\n\n## 1.3.3\n\n`2020-06-03`\n\n### Feats\n\n- Add `$NOs.theme` to get the current theme of the OS.\n\n## 1.3.2\n\n`2020-06-02`\n\n### Fixes\n\n- Fix the problem that `n-log`'s loading indicator uses monospace font.\n- Fix the problem that icon-related class name isn't applied properly.\n\n## 1.3.1\n\n`2020-06-01`\n\n### Fixes\n\n- Fix the problem that checkbox in the selection column of `n-data-table` is not center aligned.\n- Fix the problem that header of `n-data-table` has no border-color transition.\n- Fix the problem that `show-icon` & `closable` & `bordered` props of `$NConfirm` don't work.\n\n### Feats\n\n- Add and adjust some colors in the style scheme of `n-config-consumer`.\n\n## 1.3.0\n\n`2020-06-01`\n\n### Breaking Changes\n\n- Default UI CSS bundle won't include external font files. If you need using it you should import it explicitly.\n\n### Feats\n\n- Add `themed-style` prop on `n-layout`.\n\n### Fixes\n\n- Fix the problem that round toggle button won't rotate `n-layout-sider` when collapsed status is changed.\n- Fix the problem that `n-form-item`'s feedback has no leave animation if it is set at first.\n- Fix the problem that max-height related styles of `n-data-table` are applied all the time.\n- Fix some style glitches.\n\n### Refactors\n\n- Refactor some components' styles in the light theme.\n\n## 1.2.1\n\n`2020-05-29`\n\n### Fixes\n\n- Fix the problem that `n-slider` tooltip has no z-index.\n\n## 1.2.0\n\n`2020-05-29`\n\n### Feats\n\n- Add `feedback` and `validation-status` props for `n-form-item`.\n\n## 1.1.5\n\n`2020-05-28`\n\n### Feats\n\n- Add `display-directive` prop for `n-collapse` and `n-collapse-item`.\n- Add `class` and `style` prop for `n-select`'s `option`.\n- Add `debug` prop for `n-select`.\n\n### Fixes\n\n- Fix the problem that `n-select` can still be cleared when disabled.\n\n## 1.1.4\n\n`2020-05-28`\n\n### Fixes\n\n- Fix the problem that the input value of `n-select` may be modified directly.\n\n### Refactors\n\n- An UI instance can be install to a Vue instance for no more than once.\n\n## 1.1.3\n\n`2020-05-20`\n\n### Chores\n\n- Update css-render dependencies.\n\n### Fixes\n\n- Fix the problem that `n-transfer`'s animation disorder when value changes.\n\n## 1.1.2\n\n`2020-05-19`\n\n### Feats\n\n- Add content slot for `n-step`.\n- Add `label` prop for `n-checkbox`.\n\n### Performance Improvements\n\n- All placeable components register listeners on demand.\n- Use cache when finding scrollable parent node.\n- Imporve performance of `n-button`'s beforeDestroy.\n- Reduce the useless re-rendering of `n-checkbox` when checked status isn't changed.\n- Imporve performance of text typed `n-avatar`.\n\n## 1.1.1\n\n`2020-05-18`\n\n### Fixes\n\n- Update css-render dependencies.\n- Color of default typed button icon.\n\n### Performance Improvements\n\n- Reduce useless re-renders of `n-menu-item`.\n- Reduce useless re-renders of doc page.\n\n### Refactors\n\n- Refactor the codes of `n-nimbus-service-layout` for performance reason, may be there will be some bugs.\n\n## 1.1.0\n\n`2020-05-16`\n\n### Feats\n\n- `n-button` now accepts custom color.\n\n### Refactors\n\n- Replace all $slots by $scopedSlots for better robustness.\n- Move some static button styles inside button component to create dynamically.\n\n## 1.0.14\n\n`2020-05-15`\n\n### Fixes\n\n- Fix the problem that `line` typed `n-tabs`'s line position stays still when `activeName` changes.\n- Fix the problem that `n-tabs` scroll button is not triggered when tabs' width changes.\n- Fix the problem that height change of `n-tabs` will unexpectly trigger some re-render callbacks.\n\n## 1.0.13\n\n`2020-05-14`\n\n### Fixes\n\n- Fix the problem that label slot of the `n-form-item-col` & `n-form-item-row` cannot display.\n\n## 1.0.12\n\n`2020-04-30`\n\n### Fixes\n\n- Fix the problem that some CSS length props are badly formated.\n\n## 1.0.11\n\n`2020-04-30`\n\n### Feats\n\n- Add `fallback-option` prop for `n-select` to deal with the value with no corresponding option.\n\n### Fixes\n\n- Fix the problem that `max-height` and `min-height` are ill displayed on `n-data-table`.\n\n### Breaking Changes\n\n- `n-data-table`'s `max-height` and `min-height` will be applied to the entire table part, not only body.\n- `n-select` will display value with no corrensponding option.\n\n## 1.0.10\n\n`2020-04-28`\n\n### Feats\n\n- Add `arrow-placement` prop on `n-collapse`.\n- Add `arrow` slot on `n-collapse-item`.\n\n### Fixes\n\n- Fix the problem that detachable components detached in wrong place when nested like `modal > drawer > component`.\n\n## 1.0.9\n\n`2020-04-23`\n\n### Feats\n\n- Add `autofocus` prop on `n-input`.\n- Add `closable` option on `NMessage`.\n\n### Fixes\n\n- Fix the problem that the default value of `n-tag` `closable` is set to `true`.\n- Fix the problem that `n-data-table` can't use all `pagination`'s props.\n- Fix the problem that `n-pagination`'s `on-page-size-change` prop doesn't work.\n\n## 1.0.8\n\n`2020-04-22`\n\n### Feats\n\n- Add `n-dynamic-tags`.\n- Add `tableHeaderOverlayBackgroundColor` & `inputOverlayBackgroundColor` to `styleScheme`.\n\n## 1.0.7\n\n`2020-04-10`\n\n### Feats\n\n- Add `filter-option-value` prop for `n-data-table`'s `column` to better deal with single filter mode.\n\n### Fixes\n\n- Fix the problem that `n-collpase-item` don't support `number` typed `name`.\n\n## 1.0.6\n\n`2020-04-03`\n\n### Fixes\n\n- Fix the problem that all the `console` statements are striped in the bundle.\n\n## 1.0.5\n\n`2020-03-27`\n\n### Feats\n\n- Change the data type of `n-data-table`'s filters from Array to Object.\n\n### Fixes\n\n- `n-data-table` cannot be filtered correctly when there are multiple filtered columns.\n\n## 1.0.4\n\n`2020-03-26`\n\n### Feats\n\n- Filter menu in `n-data-table` is scrollable when there are too many items.\n\n## 1.0.3\n\n`2020-03-25`\n\n### Feats\n\n- `$NMessage`, `$NNotification`, `$NConfirm`'s theme will be applied on their children components.\n\n### Fixes\n\n- View measuring element will confict when multiple naive-ui exist.\n- `validate` method of `n-form-item` won't be resolved for some validator.\n- `$NConfirm`'s theme doesn't follow `n-config-provider`'s theme.\n\n## 1.0.2\n\n`2020-03-23`\n\n### Fixes\n\n- `n-transfer`'s options are not reinitialized after value changes.\n- `n-nimbus-service-layout` (deprecated) doesn't deal with the compatibility of Vue Router(under 3.1)'s `push` method.\n\n## 1.0.1\n\n`2020-03-21`\n\n### Feats\n\n- Add `'bar'` & `'arrow-circle'` on `show-trigger` prop of `n-layout-sider`.\n\n### Fixes\n\n- Rails of `n-scrollbar` shadow mouse event.\n\n### Feats\n\n- `n-date-table` adds `empty` slot, closes [#86](https://github.com/tusen-ai/naive-ui/issues/86).\n"
  },
  {
    "path": "CHANGELOG.zh-CN.md",
    "content": "# CHANGELOG\n\n## NEXT_VERSION\n\n### Fixes\n\n- 修复 `n-color-picker` 传入的 style、click 事件不生效，关闭 [#7528](https://github.com/tusen-ai/naive-ui/issues/7528)\n\n## 2.44.1\n\n`2026-03-08`\n\n### Feats\n\n- `n-config-provider` 在 `component-options` 中新增按组件配置 `size`（`AutoComplete`、`Cascader`、`ColorPicker`、`DatePicker`、`InputNumber`、`InputOtp`、`Mention`、`Select`、`TimePicker`、`Transfer`、`TreeSelect`）\n\n### Fixes\n\n- 修复 `n-config-provider` 部分组件的 `size` 全局配置不生效\n\n## 2.44.0\n\n`2026-03-08`\n\n### Breaking Changes\n\n- `n-color-picker` 重构 DOM 结构和 trigger 相关的类名\n- `n-card` 中 `n-card__content` 类名改为 `n-card-content`\n- `n-select` 点击清空按钮时默认会删除通过 `tag` 属性创建的选项\n\n### Feats\n\n- `n-color-picker` 新增 `trigger` slot，关闭 [#7192](https://github.com/tusen-ai/naive-ui/issues/7192)\n- `n-select` 新增 `clear-created-options-on-clear` 属性，用于在开启 `tag` 且可清空时控制点击清空是否同时清空通过 tag 创建的选项\n- `n-select` `n-auto-complete` `n-mention` `n-popselect` `n-cascader` `n-pagination` 新增 `scrollbar-props` 属性\n- `n-config-provider` 新增组件级 `renderEmpty` 配置（`Cascader`、`DataTable`、`Select`、`Transfer`、`Tree`、`TreeSelect`）\n- `n-config-provider` 在 `component-options` 中新增按组件配置 `size`（`Button`、`Card`、`Checkbox`、`DataTable`、`Descriptions`、`Dropdown`、`DynamicTags`、`Form`、`Input`、`Pagination`、`Popselect`、`Radio`、`Rate`、`Result`、`Skeleton`、`Space`、`Switch`、`Table`、`Tabs`、`Tag`），关闭 [#356](https://github.com/tusen-ai/naive-ui/issues/356)\n- `n-upload` 的 `submit` 方法新增 `retry` 属性。\n- `n-breadcrumb-item` 新增 `show-separator` 属性，用于配合 `transition-group` 使用时手动控制分隔符显隐，关闭 [#3614](https://github.com/tusen-ai/naive-ui/issues/3614)\n- `n-card` 新增 `content-scrollable` 属性，关闭 [#4848](https://github.com/tusen-ai/naive-ui/issues/4848)、[#6759](https://github.com/tusen-ai/naive-ui/pull/6759)\n- `n-date-picker` 新增 `fast-year-select` 参数\n- `n-date-picker` 新增 `fast-month-select` 参数\n- `n-button` 增加 `spin-props` 属性\n- `n-cascader` 增加 `spin-props` 属性\n- `n-log` 增加 `spin-props` 属性\n- `n-message` 增加 `spin-props` 属性\n- `n-switch` 增加 `spin-props` 属性\n- `n-tree` 增加 `spin-props` 属性\n- `n-spin` 增加 `radius` 和 `scale` 属性\n- `n-tree-select` 增加 `show-line` 属性\n\n### Fixes\n\n- 修复 `katex` 类型兼容问题，升级到 `0.16.28` 并移除 `@types/katex` 依赖，关闭 [#7423](https://github.com/tusen-ai/naive-ui/issues/7423)\n- 修复 `n-select` 清除动态创建的选项时，同时启用 `tag` 和 `clearable` 属性时清除不生效的问题，关闭 [#7405](https://github.com/tusen-ai/naive-ui/issues/7405)\n- 修复 `n-modal` 监听事件未移除，关闭 [#7341](https://github.com/tusen-ai/naive-ui/issues/7341)\n- 修复 `n-marquee` 组件 Non-function value encountered for default slot 警告\n- 修复 `n-data-table` 的 empty 状态在 `display: flex` 的容器中不展示\n- 修复 `n-data-table` 的在 empty 状态下，配合 `max-height` 或者 `flex-height`，header 部分没有滚动条，关闭 [#7479](https://github.com/tusen-ai/naive-ui/pull/7479)\n- 修复 `n-input`、`n-select`、`n-date-picker`、`n-auto-complete`、`n-cascader`、`n-color-picker`、`n-input-number`、`n-input-otp`、`n-mention`、`n-time-picker`、`n-transfer`、`n-tree-select` 未读取 `n-config-provider` 的全局 `size` 配置\n- 修复 `n-data-table`、`n-tag` 的 `size` 属性默认值导致全局配置无法生效\n\n## 2.43.2\n\n`2025-11-16`\n\n### Fixes\n\n- 修复 seemly 依赖的版本未更新到最新\n- 修复 `n-progress` 使用仪表盘模式超过 100% 之后样式不正确，关闭 [#6627](https://github.com/tusen-ai/naive-ui/issues/6627)\n- 修复 `n-modal` 在 `show-mask` 为 `false` 的情况下，外部内容不能被操作\n\n### Feats\n\n- `n-date-picker` 的 `defaultTime` 属性可以接受返回格式化字符串的函数\n- `n-steps` 增加 `content-placement` 属性，关闭 [#7044](https://github.com/tusen-ai/naive-ui/issues/7044)\n\n## 2.43.1\n\n`2025-09-14`\n\n- 修复 esm 格式的产物使用 `lodash` 而非 `lodash-es`\n\n## 2.43.0\n\n`2025-09-13`\n\n### Breaking Changes\n\n- Modal 内部的关闭按钮将无法通过键盘聚焦，并且不再是默认的焦点\n\n### i18n\n\n- Add daDK locale.\n\n### Fixes\n\n- 修复 `n-color-picker` 的 trigger 文字黑白颜色效果不明显问题，关闭 [#7074](https://github.com/tusen-ai/naive-ui/issues/7074)\n- 修复 `n-image` 放大缩小在 `da-DK` `sv-SE` 本地化的文案\n- 修复 `n-popover` 的 `themeOverrides` 属性没有 `Scrollbar` 样式配置\n- 修复 `n-input` 的 `themeOverrides` 属性没有 `Scrollbar` 样式配置\n- 修复 `n-anchor` 对页面底部的 link 无法通过点击激活，关闭 [#7033](https://github.com/tusen-ai/naive-ui/issues/7033)，关闭 [#6918](https://github.com/tusen-ai/naive-ui/issues/6918)、[#6844](https://github.com/tusen-ai/naive-ui/issues/6844)、[#6782](https://github.com/tusen-ai/naive-ui/issues/6782)\n- 修复 `n-upload` 组件 `'Non-function value encountered for default slot'` 警告\n- 修复 `n-input` 的 `input-props` 属性设置 `tabindex` 不生效的问题\n- 修复 `n-tab` 在多层 tab 嵌套的场景下，阴影的伪类样式冲突，关闭 [#6854](https://github.com/tusen-ai/naive-ui/issues/6854)\n- 修复 `n-menu` 在父节点设置 `disabled`，子节点为 `type: \"group\"` 的禁用样式失效，关闭 [#6792](https://github.com/tusen-ai/naive-ui/issues/6792)\n- 修复 `n-input-group-label` 没有注入 `formItemInjectionKey`，导致 `size` 属性失效的问题，关闭 [#7066](https://github.com/tusen-ai/naive-ui/issues/7066)\n- 修复 `n-carousel` 只有一张图的情況下样式错乱的问题，关闭 [#6476](https://github.com/tusen-ai/naive-ui/issues/6476)\n- 修复 `n-progress` 多个 `type=\"circle\"`情况下样式覆盖问题，关闭 [#7172](https://github.com/tusen-ai/naive-ui/issues/7172)\n- 修复 `n-marquee` 组件 'Non-function value encountered for default slot' 警告\n- 修复 `n-upload` icon 导致的内存泄露问题\n\n### Features\n\n- `n-data-table` 的列增加 `customNextSortOrder` 属性，关闭 [#6850](https://github.com/tusen-ai/naive-ui/issues/6850)\n- 新增 `n-avatar-group` 对应的泛型组件 `NGAvatarGroup`，关闭 [#6909](https://github.com/tusen-ai/naive-ui/issues/6909)\n- `n-avatar-group` 新增 `size` 属性\n- `n-popover` 支持 RTL\n- `n-tooltip` 支持 RTL\n- `n-upload` 支持 RTL\n- `n-tree-select` 支持 RTL\n- `useDialog` 的选项支持 `z-index`，关闭 [#4349](https://github.com/tusen-ai/naive-ui/issues/4349)\n- 新增组件 `n-heatmap`\n- `n-image` 增加 `showPreview` 方法，关闭 [#6695](https://github.com/tusen-ai/naive-ui/issues/6695)\n- 新增 `n-image-preview` 组件\n- `n-image-group` 可以脱离 `n-image` 使用\n- `n-input-otp` 增加 `focusOnChar` 方法，关闭 [#7073](https://github.com/tusen-ai/naive-ui/issues/7073)\n- `n-form-item` 新增 `content-class`、`content-style` 属性\n- `n-message` 增加 `border` 主题变量，关闭 [#7105](https://github.com/tusen-ai/naive-ui/issues/7105)\n- `n-modal` 增加 `mask-visible` 属性\n- `useModal` 新增 `render` 函数，关闭 [#5857](https://github.com/tusen-ai/naive-ui/issues/5857)\n- `n-card` 新增 `close-focusable` 属性\n- `n-dialog` 新增 `close-focusable` 属性\n- `n-form-item` 增加 `invalidateLabelWidth` 方法，`n-form` 增加 `invalidateLabelWidths` 方法，关闭 [#5939](https://github.com/tusen-ai/naive-ui/issues/5939)\n\n## 2.42.0\n\n`2025-06-17`\n\n### Breaking Changes\n\n- 修复 `n-date-picker` 的 `time-picker-format` 属性不生效的问题，这个属性之前被错误的拼写为 `timer-picker-format`，关闭 [#6820](https://github.com/tusen-ai/naive-ui/issues/6820)\n\n### Fixes\n\n- 修复 `n-input-otp` 组件，当被禁用（disabled、readonly）时移除事件绑定，防止禁用状态下仍可触发交互行为，修复宽度样式权重冲突问题\n- 修复 `n-date-picker` 在 `type=\"datetimerange\"` 情况下，设定 `default-time` 会影响 `shortcuts` 选项选中的值，关闭 [#6902](https://github.com/tusen-ai/naive-ui/pull/6902)、[#6901](https://github.com/tusen-ai/naive-ui/pull/6901)\n- 修复 `n-radio`、`n-radio-button` 中无法正常使用 `n-popover`，关闭 [#6837](https://github.com/tusen-ai/naive-ui/pull/6837)、[#6832](https://github.com/tusen-ai/naive-ui/pull/6832)\n- 优化图层过多导致的滚动性能问题，关闭 [#6887](https://github.com/tusen-ai/naive-ui/issues/6887)\n\n### Features\n\n- `n-anchor-link` 新增 `title` slot，关闭 [#6845](https://github.com/tusen-ai/naive-ui/issues/6845)\n\n## 2.41.1\n\n`2025-06-08`\n\n### Fixes\n\n- 修复 `n-tabs` TabPane tab slots 的类型异常\n- 修复 `n-data-table` 可排序表格背景颜色变量丢失，关闭 [#6521](https://github.com/tusen-ai/naive-ui/issues/6521)\n\n### Features\n\n- 🌟 新增 `n-input-otp` 组件，关闭 [#1385](https://github.com/tusen-ai/naive-ui/issues/1385)、[#5681](https://github.com/tusen-ai/naive-ui/issues/5681)、[#6222](https://github.com/tusen-ai/naive-ui/issues/6222)\n- `n-upload` 新增 `custom-download` 属性，关闭 [#5946](https://github.com/tusen-ai/naive-ui/issues/5946)、[#6800](https://github.com/tusen-ai/naive-ui/issues/6800)\n- `n-upload` 新增 `uploadDownload` 工具方法\n- `n-tree-select` 新增 `indent` 属性\n\n## 2.41.0\n\n`2025-01-05`\n\n### Breaking Changes\n\n- （需要 Vue 3.3+）为所有的组件增加插槽的类型标注\n\n### i18n\n\n- 添加 kmKH 国际化\n- 添加 ugCN 国际化\n\n### Features\n\n- `n-modal` 新增 `draggable` 属性，关闭 [#6525](https://github.com/tusen-ai/naive-ui/issues/6525)、[#5792](https://github.com/tusen-ai/naive-ui/issues/5792)、[#5711](https://github.com/tusen-ai/naive-ui/issues/5711)、[#5501](https://github.com/tusen-ai/naive-ui/issues/5501)、[#2152](https://github.com/tusen-ai/naive-ui/issues/2152)\n- `useDialog` 支持 `draggable` 参数\n- `useModal` 支持 `draggable` 参数\n\n### Fixes\n\n- 修复 `n-data-table` 在使用树形数据的时候出现多个展开 icon\n- 修复 `n-date-picker` 的 `confirm`、`now`、`clear` 插槽对 `'month'`、`'monthrange'`、`'quarter'`、`'quarterrange'`、`'year'` 和 `'yearrange'` 类型不生效\n- 修复 `n-input` 的 `render-count` 属性在类型非 `'textarea'` 时不生效\n\n## 2.40.4\n\n`2024-12-20`\n\n### Fixes\n\n- 修复 `n-scrollbar`、`n-float-button`、`n-float-button-group`、`n-popover` 组件中的 `inset` 属性在部分浏览器中有兼容性问题，关闭 [#6604](https://github.com/tusen-ai/naive-ui/issues/6604)，关闭 [#6602](https://github.com/tusen-ai/naive-ui/issues/6602)\n- 修复和较新版本 vue 配合使用时的内存泄露问题。注意：修复后你可能仍然会在 Chrome >= 129 中发现内存泄漏，因为他们引入了一个 bug，参考：https://github.com/vuejs/core/issues/12306 https://issues.chromium.org/issues/376777343\n\n## 2.40.3\n\n`2024-12-02`\n\n- 修复 marquee 没有被用正确的名字导出\n\n## 2.40.2\n\n`2024-11-26`\n\n### Fixes\n\n- `n-time-picker` 的 `use-12-hours` 类型错误警告，关闭 [#4308](https://github.com/tusen-ai/naive-ui/issues/4308)\n- 修复 `input-number` 存在负号时被替换的问题\n- 修复 `n-data-table` 的 header 在部分浏览器中会出现滚动条，关闭 [#6557](https://github.com/tusen-ai/naive-ui/issues/6557)\n\n### Features\n\n- 🌟 新增 `n-marquee` 组件\n- `n-image` 新增 `error` 插槽，关闭 [#5649](https://github.com/tusen-ai/naive-ui/issues/5649)\n- `n-date-picker` 新增 `date-format` 属性\n- `n-date-picker` 新增 `calendar-day-format` 属性\n- `n-date-picker` 新增 `calendar-header-year-format` 属性\n- `n-date-picker` 新增 `calendar-header-month-format` 属性\n- `n-date-picker` 新增 `calendar-header-month-before-year` 属性\n- `n-date-picker` 新增 `calendar-header-month-year-separator` 属性\n- `n-progress` 的 `color` 属性支持渐变色配置\n- `n-select` 新增 `font-weight` 主题变量\n- `n-input` 新增 `font-weight` 主题变量\n- `n-data-table` 新增 `get-csv-header` 和 `get-csv-cell` 属性，关闭 [#6542](https://github.com/tusen-ai/naive-ui/issues/6542)\n\n## 2.40.1\n\n`2024-09-26`\n\n### Fixes\n\n- 修复 `n-data-table` 在设定 `virtual-x`，且所有的 column 对象均没有配置 `fixed` 属性的时候无法正常显示\n- 修复 `css-render` 依赖版本不够高可能会影响 `n-config-provider` 的 `style-mount-target` 属性的问题\n- 修复 `n-data-table` 的 `rowProps` 产生的 `class` 会覆盖原本行 DOM 的 class\n\n## 2.40.0\n\n`2024-09-26`\n\n### Breaking Changes\n\n- 修复 `n-config-provider` 默认继承父级的类前缀 `cls-prefix`，关闭 [#5970](https://github.com/tusen-ai/naive-ui/issues/5970)\n- 修复 `n-date-picker` 默认 `weekFormat` 中 year 和 week 标准不同，现在使用 local year 和 local week\n- 依赖 `date-fns` 升级到 V3\n- `n-cascader` 过滤算法现在忽略大小写\n\n### Fixes\n\n- 修复 `n-infinite-scroll` 组件触底判断错误，关闭 [#6133](https://github.com/tusen-ai/naive-ui/issues/6133)\n- 修复 `n-slider` 在垂直模式下的宽度样式可能会被全局 CSS box-sizing override 影响，关闭[#6114](https://github.com/tusen-ai/naive-ui/issues/6114)\n- 修复 `n-tabs` 在垂直模式下使用 `prefix` slot、`suffix` slot 和 `addable` 属性的时候可能出现样式问题，关闭 [#6059](https://github.com/tusen-ai/naive-ui/issues/6059)，[#6060](https://github.com/tusen-ai/naive-ui/pull/6060)\n- 修复 `n-upload` 在某些老浏览器下目录上传最多只能上传 100 个文件，关闭 [#6027](https://github.com/tusen-ai/naive-ui/issues/6027)\n- 修复 `n-date-picker` 的 `input-readonly` 属性在 `'datetime'`、`'datetimerange'` 类型的面板输入框中不生效\n- 修复 `n-menu` 在 `responsive` 被设定的情况下，HTML 属性无法正确的应用到组件上\n- 修复 `n-float-button` 和 `popover` 一起使用会报错，关闭 [#5933](https://github.com/tusen-ai/naive-ui/issues/5933)\n- 修复 `n-badge` 中无法遮盖聚焦元素边框问题，关闭 [#5929](https://github.com/tusen-ai/naive-ui/issues/5929)\n- 修复 `n-button` font-weight CSS 变量名错误的问题，关闭 [#5922](https://github.com/tusen-ai/naive-ui/issues/5922)\n- 修复 `n-icon` 的 `component` 属性不接受 FunctionalComponent\n- 修复 `n-mention` 的面板在 `placement` 设为 `'top'` 或者组件设定的 padding 的时候位置有问题，关闭 [#6241](https://github.com/tusen-ai/naive-ui/issues/6241)\n- 修复 `n-carousel` 中轮播图的过渡行为不符合预期，关闭 [#5993](https://github.com/tusen-ai/naive-ui/issues/5993)\n\n### Features\n\n- 🌟 `n-data-table` 新增 `virtual-scroll-x`、`virtual-scroll-header`、`height-for-row`、`header-height`、`min-row-height` 属性，用于支持大量列数据的虚拟滚动\n- 🌟 新增 `n-highlight` 组件\n- `n-scrollbar` 新增 `x-placement` 和 `y-placement` 属性，关闭 [#6089](https://github.com/tusen-ai/naive-ui/issues/6089)\n- `n-date-picker` 新增 `clear`、`now` 和 `confirm` 插槽，关闭 [#6013](https://github.com/tusen-ai/naive-ui/issues/6013)\n- `n-upload` 新增 `on-retry`属性，关闭 [#6031](https://github.com/tusen-ai/naive-ui/issues/6031)\n- `n-slider` 的 `marks` 属性支持渲染函数，关闭 [#5967](https://github.com/tusen-ai/naive-ui/issues/5967)\n- `n-transfer` 的 `source-title` 和 `target-title` 属性支持渲染函数，关闭 [#6004](https://github.com/tusen-ai/naive-ui/issues/6004)\n- `n-data-table` 的 `render-expand-icon` 属性新增 `rowData` 参数，关闭 [#6108](https://github.com/tusen-ai/naive-ui/issues/6108)\n- `n-empty` 的 `size` 属性支持 `tiny` 尺寸\n- `n-config-provider` 新增 `style-mount-target` 属性，用于控制样式的挂载位置\n- `n-data-table` 在列的配置中新增 `allowExport` 属性\n- `n-date-picker` 新增 `year-range` 属性\n- `n-tree-select` 新增 `header` 插槽，关闭 [#5915](https://github.com/tusen-ai/naive-ui/issues/5915)\n- `n-select` 新增 `menu-size` 属性\n\n## 2.39.0\n\n`2024-07-15`\n\n### Breaking Changes\n\n- 修复 `n-input-number` precision 模式下 value 为字符串时的异常问题，关闭 [#6091](https://github.com/tusen-ai/naive-ui/issues/6091)\n\n### Fixes\n\n- 修复 `n-form-item` 状态更新不正常 [#6068](https://github.com/tusen-ai/naive-ui/issues/6068)\n- 修复 `n-select` 组件的 header 插槽里 input 无法输入，关闭 [#6030](https://github.com/tusen-ai/naive-ui/issues/6030)\n- 修复 `n-tree` 组件在禁用 `show-irrelevant-nodes` 时，节点的选中状态可能不正确，关闭 [#6115](https://github.com/tusen-ai/naive-ui/issues/6115)\n\n### Features\n\n- `n-data-table` 新增 `filter-icon-popover-props` 属性，关闭 [#6111](https://github.com/tusen-ai/naive-ui/issues/6111)\n- `n-input-number` 新增 `round` 属性，关闭 [#6097](https://github.com/tusen-ai/naive-ui/issues/6097)\n- `n-color-picker` 新增 `on-clear` 属性\n- `n-upload` 的 `on-preview` 属性新增 `detail.event` 参数，你可以通过 `preventDefault` 来取消默认的链接打开行为，关闭 [#6036](https://github.com/tusen-ai/naive-ui/issues/6036)\n- `n-data-table` 新增 `thColorSorting`、`thColorSortingModal`、`thColorSortingPopover`、`tdColorSorting`、`tdColorSortingModal` 和 `tdColorSortingPopover` 主题变量，关闭 [#6118](https://github.com/tusen-ai/naive-ui/issues/6118)、 [#6120](https://github.com/tusen-ai/naive-ui/issues/6120)\n\n### i18n\n\n- 新增 azAZ 国际化\n- 新增 uzUZ 国际化\n\n## 2.38.2\n\n`2024-05-03`\n\n### Fixes\n\n- 修复 `n-menu` 中 Submenu 组件的 wai-aria role 设置错误，关闭 [#5729](https://github.com/tusen-ai/naive-ui/issues/5729)\n- 修复 `n-tabs` type 为 `segment` 时样式存在问题，关闭 [#5728](https://github.com/tusen-ai/naive-ui/issues/5728)\n- 修复 get\\*String() 方法中 UTC/区域设置不匹配的问题，关闭 [#5702](https://github.com/tusen-ai/naive-ui/issues/5702)\n- 修复 `n-dialog` / `n-modal` 调用 `destroy` 方法时可能会报错\n- 修复 `useModal` 设置 `card` 预设时 `n-card` 插槽缺少相应属性，关闭 [#5746](https://github.com/tusen-ai/naive-ui/issues/5746)\n- 修复组件调整主题时 `theme-overrides` 属性中的 `common` 类型报错\n- 修复 `n-split` 可能产生小与 `0` 的值\n\n### Features\n\n- `n-watermark` 支持多行文本\n- 新增 `n-infinite-scroll` 组件\n- `n-watermark` 新增 `text-align` 属性\n- `n-qr-code` 新增 `type` 属性，设置 `type` 自定义渲染结果，提供 `canvas` 和 `svg` 两个选项\n- `n-card` 新增 `action`、`content`、`cover`、`footer`、`header-extra` 属性\n- `n-card` 的 `title` 属性支持渲染函数\n- `n-upload` 导出 `on-remove` 方法的 `index` 属性，关闭 [#5747](https://github.com/tusen-ai/naive-ui/issues/5747)\n- `n-upload` 导出 `UploadOnDownload`、`UploadOnRemove`、`UploadOnFinish` 和 `UploadOnChange` 类型\n- `n-dialog` 新增 `action-class`、`action-style`、`content-class`、`content-style`、`title-class` 和 `title-style` 属性\n- `n-split` 新增 `pane1-class`、`pane1-style`、`pane2-class` 和 `pane2-style` 属性\n- `n-mention` 新增 `filter` 方法，关闭 [#5721](https://github.com/tusen-ai/naive-ui/pull/5721)\n- `n-slider` 新增 wai-aria 支持\n- `n-date-picker` 新增 `time-picker-format` 属性\n- `n-form-item` 新增 `feedback-class` 和 `feedback-style` 属性\n- `n-split` 支持设置像素值大小\n- `n-scrollbar` 新增 `content-style` 和 `content-class` 属性，关闭 [#4497](https://github.com/tusen-ai/naive-ui/issues/4497)\n- `n-image` 新增 `render-toolbar` 属性\n- `n-cascader` 新增 `get-column-width` 属性\n- `n-cascader` 新增 `render-prefix` 属性\n- `n-cascader` 新增 `render-suffix` 属性\n- `n-image` 优化下载按钮图标\n- `n-scrollbar` 新增 `height`、`width`、`radius`、`railInsetHorizontal`、`railInsetVertical`、`railColor` 主题变量\n\n### i18n\n\n- 新增 csCZ locale\n- 增加缺少的 itIT locale\n\n## 2.38.1\n\n`2024-02-26`\n\n### Fixes\n\n- 修复 `n-split` 的 `min` 属性未生效\n- 修复 `n-result` 内置的 icon 无法在 hydration 之后重渲染\n- 修复 `n-tabs` 在 `type` 为 `'segment'` 时候，胶囊在 tabs 大小改变后有错误的位置和宽度，关闭 [#5705](https://github.com/tusen-ai/naive-ui/issues/5705)\n- 修复 `n-tabs` 在 `n-modal` 内部时，胶囊在 tabs 大小改变后有错误的位置和宽度，关闭 [#5569](https://github.com/tusen-ai/naive-ui/issues/5569)\n- 修复 `n-split` 不支持 `inline-theme-disabled` 属性\n- 修复 `n-float-button` 不支持 `inline-theme-disabled` 属性\n\n### Features\n\n- `n-date-picker` 在 `type` 为 `'date'`、`'datetime'` 或 `'week'` 时新增 `default-calendar-start-time` 属性，关闭 [#4493](https://github.com/tusen-ai/naive-ui/issues/4493)\n- `n-tree-select` 新增 `get-children` 属性\n\n## 2.38.0\n\n`2024-02-22`\n\n### Breaking Changes\n\n- 修复 `n-scrollbar` 组件的 `scrollTo(x: number, y: number)`方法参数顺序与文档不符的错误\n\n### Fixes\n\n- 修复 `n-tree` 的 `override-default-node-click-behavior` 属性可能覆盖掉默认展开按钮和选中按钮的行为\n- 修复 `n-scrollbar` `aria-hidden` 拼写错误\n- 修复 `n-form-item` 校验结果可能会闪烁的问题，关闭 [#5583](https://github.com/tusen-ai/naive-ui/issues/5583)\n- 修复 `n-popselect` 组件的 header 插槽里 input 无法输入，关闭 [#5494](https://github.com/tusen-ai/naive-ui/pull/5494)\n- 修复 `n-qr-code` 大小样式问题\n- 修复 `n-badge` 会影响子元素的文字颜色\n\n### Features\n\n- 🌟 新增 `n-modal-provider` 组件和 `useModal` 方法\n- 🌟 新增 `n-float-button` 和 `n-float-button-group` 组件\n- 🌟 提供 ES module 打包（在 `/dist/index.mjs` 和 `/dist/index.prod.mjs`）\n- `n-auto-complete` 新增 `append` 属性\n- `n-select` 在组件可过滤且输入失焦时，添加原生 `title` 属性\n- `n-split` 新增 `size` 和 `on-update:size` 属性\n- `n-split` 新增 `watch-props` 属性，关闭 [#5526](https://github.com/tusen-ai/naive-ui/issues/5526)\n- `n-drawer` 新增 `borderRadius` 主题变量\n- 新增 `n-float-button` 组件\n- 提供 ES module 打包\n\n### i18n\n\n- 新增 `etEE` locale\n\n## 2.37.3\n\n`2024-01-09`\n\n### Fixes\n\n- 修复 `n-split` 不在卡片中使用没有颜色\n\n## 2.37.2\n\n`2024-01-09`\n\n### Fixes\n\n- `n-data-table` 的 `downloadCsv` 方法会导出选择列、展开列\n\n## 2.37.1\n\n`2024-01-08`\n\n### Fixes\n\n- 点击具有弹出菜单的组件的清空按钮时，可能会触发菜单的重复出现\n- `n-form` 的 `validate` 方法返回的 `Promise` 可能不会 `resolve`\n\n### Features\n\n- `n-collapse` 新增 `trigger-areas` 属性\n- `n-date-picker` 的 `is-date-disabled` 回调函数支持获取对应年、月、日、季度按钮的具体信息，关闭 [#4649](https://github.com/tusen-ai/naive-ui/issues/4649)\n- `n-auto-complete` 新增 `empty` 插槽\n- `n-auto-complete` 新增 `show-empty` 属性\n\n## 2.37.0\n\n`2024-01-07`\n\n### Breaking Changes\n\n- `package.json` 中的 `module` 属性由 `es/index.js` 改为 `es/index.mjs`\n\n### Fixes\n\n- 修复 `n-space` 插槽过滤了注释节点导致节点复用问题，关闭 [#5136](https://github.com/tusen-ai/naive-ui/issues/5136)\n- 修复 `n-data-table` 属性 `pagination` 在非受控模式下的默认分页大小 `default-page-size` 和当前页数 `default-page` 不生效，关闭 [#5201](https://github.com/tusen-ai/naive-ui/issues/5201)\n- 修复 `n-time-picker` 时间选择器格式化（`format=\"HH:mm:ss.SSS\"`）后无法在编辑框内修改毫秒数的问题，关闭 [#5224](https://github.com/tusen-ai/naive-ui/issues/5224)\n- 修复 `n-notification` 通知在屏幕宽度小于 400px 的时候溢出屏幕\n- 修复 `n-carousel` 在只有两个元素时，过渡效果为 `slide` 且循环播放时过渡效果有问题，关闭 [#4323](https://github.com/tusen-ai/naive-ui/issues/4323)\n- 修复 `n-carousel` 在只有一张图片时点击箭头切换按钮触发的 `current-index` 值不正确，关闭 [#5130](https://github.com/tusen-ai/naive-ui/issues/5130)\n- 修复 `n-upload-trigger` 在拖拽文件夹场景下当文件夹内文件较多时，部分文件不会被正确读取的问题\n- 修复 `n-dynamic-tags` 使用键盘触发新增时行为异常，关闭 [#5077](https://github.com/tusen-ai/naive-ui/issues/5077)\n- 修复 `n-tree` 叶子节点连接线颜色\n- 修复 `n-collapse-item` 光标样式和实际点击生效的位置不对应，关闭 [#5482](https://github.com/tusen-ai/naive-ui/issues/5482).\n- 修复 `n-data-table` 总结栏有未设定的列时，会抛出异常\n- 修复 `n-drawer` 的 `on-mask-click` 属性可能被触发多次\n- 修复 `n-tree` 属性 `data` 当数据源 `data` 按一定场景多次发生切换时，动画处理的一些逻辑会导致渲染展示的数据出错，关闭 [#5217](https://github.com/tusen-ai/naive-ui/issues/5217)\n- 修复 `n-radio` value 值取消更新后，input 原生 checked 值未更新，关闭 [#5184](https://github.com/tusen-ai/naive-ui/issues/5184)\n- 修复 `n-data-table` 空表格在设置 `min-height` 时高度不正确，关闭 [#5108](https://github.com/tusen-ai/naive-ui/issues/5108)\n- 修复 `n-tabs` 在 `value` 被设为没有对应标签页的值的时候指示条仍然展示，关闭 [#5100](https://github.com/tusen-ai/naive-ui/issues/5100)\n- 修复 `n-spin` 动画异常问题，关闭 [#3556](https://github.com/tusen-ai/naive-ui/issues/3556)\n- 修复 `n-avatar` 懒加载和懒加载失败时 `fallback-src` 属性都不生效，关闭 [#5007](https://github.com/tusen-ai/naive-ui/issues/5007)\n- <del>修复 `n-split` 不在卡片中使用没有颜色</del>\n- 修复 `n-card` 的 `footer-class` 属性不生效\n- 修复 `n-input` 在使用 `clearable` 时点击触发两次的问题，关闭 [#5510](https://github.com/tusen-ai/naive-ui/issues/5510)\n- 修复 `n-tabs` 在 `placement` 为 `'left'` 和 `'right'` 时初始化滚动阴影可能不正确\n- 修复 `n-date-picker` 在范围类型下，可以通过输入框使开始时间大于结束时间，关闭 [#5544](https://github.com/tusen-ai/naive-ui/issues/5544)\n\n### Features\n\n- 🌟 新增 `n-flex` 组件\n- 🌟 `n-date-picker` 的 `type` 属性支持 `'week'`\n- 🌟 `n-data-table` 新增 `downloadCsv` 方法，关闭 [#4260](https://github.com/tusen-ai/naive-ui/issues/4260)\n- 🌟 `n-date-picker` 新增 `month-format`、`year-format` 和 `quarter-format` 属性，关闭 [#4891](https://github.com/tusen-ai/naive-ui/issues/4891)\n- 🌟 `n-tree` 新增 `override-default-node-click-behavior` 属性\n- 🌟 `n-tree-select` 新增 `override-default-node-click-behavior` 属性\n- `n-space` 新增 `reverse` 属性\n- `n-input` 新增 `clear` 方法，关闭 [#5423](https://github.com/tusen-ai/naive-ui/issues/5423)\n- `n-time-picker` 新增 `'clear'` `action`，关闭 [#5334](https://github.com/tusen-ai/naive-ui/issues/5334)\n- `n-select` 支持 RTL\n- `n-data-table` 支持 RTL\n- `n-dialog` 支持 RTL\n- `n-select` 新增 `header` 插槽，关闭 [#5448](https://github.com/tusen-ai/naive-ui/issues/5448)\n- `n-date-picker` 新增 `on-prev-month` `on-next-month` `on-prev-year` `on-next-year` 属性，关闭 [#5350](https://github.com/tusen-ai/naive-ui/issues/5350)\n- `n-input-number` 新增 `input-props` 属性，关闭 [#5450](https://github.com/tusen-ai/naive-ui/issues/5450)\n- 更新 ruRU locale\n- `n-drawer` 新增 `content-class` 属性\n- `n-drawer-content` 新增 `body-class` `body-content-class` `footer-class` 和 `header-class` 属性\n- `n-tree` 新增多种 `scrollTo` 配置\n- `n-form` 为 `FormItemRule` 增加 `level` 属性，`level: 'warning'` 用于显示表单异常值，但不会阻塞提交\n- `n-cascader` 新增 `ellipsis-tag-popover-props` 属性\n- `n-select` 新增 `ellipsis-tag-popover-props` 属性\n- `n-tree-select` 新增 `ellipsis-tag-popover-props` 属性\n- `n-avatar-group` 新增 `expand-on-hover` 属性\n- `n-tabs` 新增 `tab-class`、`add-tab-style`、`add-tab-class` 属性\n- `n-tree` 新增 `override-default-node-click-behavior` 属性\n- `n-tree-select` 新增 `override-default-node-click-behavior` 属性\n- 新增 `n-flex` 组件\n- `n-pagination` 新增 `show-quick-jump-dropdown` 属性，关闭 [#5251](https://github.com/tusen-ai/naive-ui/issues/5251)\n\n## 2.36.0\n\n`2023-12-18`\n\n### Fixes\n\n- 修复 `n-tree` 未暴露连接线颜色变量 `--n-line-color`，关闭[#5339](https://github.com/tusen-ai/naive-ui/issues/5339)\n- 修复 `n-tree` 在 `disabled` 的情况下不显示选中节点的样式\n- 修复 `n-tree` `virtual-scroll` 空数据占位符丢失\n- 修复 `n-watermark` 组件中的 `content` 属性为空时，无法清空水印内容\n- 修复 `n-tree` 自定义不同的展开开关图标时会导致节点选中，关闭[#5380](https://github.com/tusen-ai/naive-ui/issues/5380)\n- 修复 `n-input` 从 Edge 浏览器 87 版本开始，`type` 为 `password` 时默认样式会多出一个显示密码按钮，关闭[#5384](https://github.com/tusen-ai/naive-ui/issues/5384)\n- 修复 `n-radio-button` 主题变量 `buttonColor` 设置不生效\n- 修复 `n-input` 当 `type` 为 `textarea` 且禁用 inline 主题时不显示纵向滚动条，关闭 [#5418](https://github.com/tusen-ai/naive-ui/issues/5418)\n- 修复在 `inline-theme-disabled` 设定后，带小数点的自定义颜色在 `n-tag`、`n-avatar`、`n-badge`、`n-button`、`n-rate` 使用会出问题\n- 修复 `n-tabs` 在 `vertical` 模式下的边界高度不正常\n- 修复 `n-tree` 节点在 `block-line` 模式下的悬浮颜色比选种颜色有更高的优先级\n- 修复 `n-tree` 点击展开开关会导致选中勾选框\n\n### Features\n\n- `n-tree` 导出 `treeGetClickTarget` 函数，判断点击位置，关闭 [#5375](https://github.com/tusen-ai/naive-ui/issues/5375)\n- `n-space` 新增 `item-class` 属性\n- `n-layout` 新增 `content-class` 属性\n- `n-layout-sider` 新增 `collapsed-trigger-class` 和 `trigger-class` 属性\n- `n-spin` 新增 `content-class`、`content-style` 属性\n- `n-popover` 新增 `arrow-class`、`arrow-wrapper-class`、`arrow-wrapper-style`、`content-class`、`footer-class` 和 `header-class` 属性\n- `n-notification-provider` 新增 `container-class` 属性\n- `n-message-provider` 新增 `container-class` 属性\n- `n-loading-bar-provider` 新增 `container-class` 属性\n- `n-thing` 新增 `content-class` 和 `description-class` 属性\n- `n-card` 新增 `content-class`、`footer-class`、`header-class` 和 `header-extra-class` 属性\n- `n-descriptions` 新增 `content-class` 和 `label-class` 属性\n- `n-upload` 新增 `file-list-class` 和 `trigger-class` 属性\n- `n-dynamic-tags` 新增 `input-class` 和 `tag-class` 属性\n- `n-dynamic-input` 新增 `item-class` 属性\n- `n-slider` 新增 `on-dragstart` `on-dragend` 属性，关闭 [#5365](https://github.com/tusen-ai/naive-ui/issues/5365)\n- `n-dialog` 新增 `close` 插槽\n- `n-equation` 导出 `EquationProps` 类型\n- `n-popselect` 新增 `header` 插槽\n- `n-tree-select` 新增 `watch-props` 属性\n- 新增 `n-split` 组件，关闭 [#3557](https://github.com/tusen-ai/naive-ui/issues/3557)\n- 新增 `n-virtual-list` 组件\n- 新增 `n-qr-code` 组件，关闭 [#2535](https://github.com/tusen-ai/naive-ui/issues/2535)\n- `n-menu` 新增 `responsive` 属性，在水平状态会收起溢出的菜单项\n- `n-menu` 新增 `deriveResponsiveState` 方法\n\n## 2.35.0\n\n`2023-10-02`\n\n### Breaking Changes\n\n- `n-input` 的 `suffix` 移动到 `loading` 之后，关闭 [#4685](https://github.com/tusen-ai/naive-ui/issues/4685)\n- 修复 `n-log` 的 `silent` 拼写问题，关闭 [#4875](https://github.com/tusen-ai/naive-ui/issues/4875)\n- 修复 `n-affix` 的 `position` 默认值与文档一不致\n\n### Fixes\n\n- 修复 `n-radio` 导出的 `radioProps` 未包含 `theme-overrides`\n- 修复 `n-descriptions` 当 `label-placement` 为 `'top'` 的时候并且只有一列的时候，生成的 table 缺少对应的列导致 `n-description-item` 的 `span` 属性失效，关闭 [#4874](https://github.com/tusen-ai/naive-ui/issues/4874)\n- 修复 `n-upload` 的 `data` 属性类型不能包含 `Blob` 元素\n- 修复 `n-select` 动态添加选项时，可以添加已存在的选项，关闭 [#4703](https://github.com/tusen-ai/naive-ui/issues/4703)\n- 修复 `n-upload` `render-icon` 属性的类型\n- 修复 `n-auto-complete` 的 `onSelect` 类型，关闭[#4617](https://github.com/tusen-ai/naive-ui/issues/4617)\n- 修复 `n-grid-item` 属性 suffix 响应式设置不生效，关闭[#4635](https://github.com/tusen-ai/naive-ui/issues/4635)\n- 修复 `n-tabs` 的 `paneWrapperStyle` 属性在动画后丢失高度\n- 修复 `n-tree` 在级联选择下点击半选状态勾选框时应选中全部而不是清空已选，关闭 [#4941](https://github.com/tusen-ai/naive-ui/issues/4941)\n- 修复 `n-internal-selection` 在 `disabled` 时，鼠标移动到 `+n` 标签上时，未展示 popover，关闭 [#4789](https://github.com/tusen-ai/naive-ui/issues/4789)\n- 修复 `n-input` 当 `type` 为 `textarea` 时不显示纵向滚动条的问题，关闭 [#4570](https://github.com/tusen-ai/naive-ui/issues/4570)\n- 修复 `n-alert` 在没有标题且可关闭时，内容样式出现的问题，关闭 [#4588](https://github.com/tusen-ai/naive-ui/issues/4588)\n- 修复 `n-select` 的 `empty` slot 为可交互组件时的行为，关闭 [#4700](https://github.com/tusen-ai/naive-ui/issues/4700)\n- 修复 `n-data-table` 使用按键滚动时 header 和 body 不同步，关闭 [#3941](https://github.com/tusen-ai/naive-ui/issues/3941)\n- 修复 `n-data-table` 在 Safari 中拖拽列时文本会被选中, 关闭 [#4957](https://github.com/tusen-ai/naive-ui/issues/4957)\n- 修复 `n-data-table` 当使用树形表格时，某一列设置了固定宽度且 ellipsis: true 后，如果文字溢出，不会显示省略号，而是换行[#3755](https://github.com/tusen-ai/naive-ui/issues/3755)\n- 修复 `useLoadingBar` 调用 `finish` 方法无法结束加载，关闭 [#4965](https://github.com/tusen-ai/naive-ui/issues/4965)\n- 修复 `n-select` 在 `disabled` 的情况下还可以触发 `focus` 和 `blur`，关闭 [#4454](https://github.com/tusen-ai/naive-ui/issues/4454)\n- 修复 `n-steps` 在超过 9 个步数的时候换行可能存在问题\n- 修复 `n-form-item-gi` v-show 多次切换报错，关闭 [#4422](https://github.com/tusen-ai/naive-ui/issues/4422)\n- 修复 `n-tree` `check-on-click` 为 `true` 时，`TreeOption` `checkboxDisabled` 不生效\n- 修复 `n-date-input` 的按钮快速点击时网站其余文本会被选中\n- 修复 `n-auto-complete` 在未聚焦状态下点击清除按钮时补全菜单意外打开的问题，关闭 [#4658](https://github.com/tusen-ai/naive-ui/issues/4658)\n- 修复 `n-input` 属性 `on-keyup` 类型，关闭 [#5101](https://github.com/tusen-ai/naive-ui/issues/5101)\n- Fix `n-data-table`'s default sorter to place null values at the very top or bottom, closes [#5281](https://github.com/tusen-ai/naive-ui/issues/5281).\n- 修复 `n-popconfirm` 操作按钮不应该被多次触发，关闭 [#4687](https://github.com/tusen-ai/naive-ui/issues/4687)\n\n### Features\n\n- `n-drawer` 新增 `max-height`、`min-height`、`max-width`、`max-width` 属性\n- `n-progress` 在 `'line'` 类型下设置指标位置为 `'inside'` 时支持指示标插槽，关闭 [#4888](https://github.com/tusen-ai/naive-ui/issues/4888)\n- `n-image-preview` 新增 `downaload` 按钮，关闭 [#4302](https://github.com/tusen-ai/naive-ui/issues/4302)\n- `n-transfer` 新增 `select-all-text` 和 `clear-text` 属性，关闭 [#4910](https://github.com/tusen-ai/naive-ui/issues/4910)\n- `n-tree` 新增 `scrollbar-props` 属性，关闭 [#4021](https://github.com/tusen-ai/naive-ui/issues/4666)\n- `n-select` 新增 `focusInput` `blurInput` 方法\n- `n-tree-select` 新增 `focusInput` `blurInput` 方法\n- `n-image-group` 新增 `on-preview-prev` `on-preview-next` 属性\n- `n-tree` 新增 `show-line` 属性，关闭 [#3796](https://github.com/tusen-ai/naive-ui/issues/3796)， [#4554](https://github.com/tusen-ai/naive-ui/issues/4554)\n- `n-tree` 为 `render-switcher-icon` 属性添加节点信息，关闭 [#4815](https://github.com/tusen-ai/naive-ui/issues/4815)\n- `n-input-number` 导出 `select` 方法\n- `n-data-table` 新增 `n-data-table-tr--expanded` class 到展开行，新增 `n-data-table-tr n-data-table-tr--expand` class 到附加行，关闭 [#4420](https://github.com/tusen-ai/naive-ui/issues/4420)\n- `n-spin` 新增 `delay` 属性\n- 新增 `n-performant-ellipsis` 组件\n- `DataTableBaseColumn` 新增 `ellipsisComponent` 属性\n\n### i18n\n\n- 更新 zhTW locale\n- 新增 svSE locale\n- 更新 jaJP locale\n\n## 2.34.4\n\n`2023-05-21`\n\n### Fixes\n\n- 修复 `n-notification` 的 `description` 有英文时没有自动换行，关闭 [#4609](https://github.com/tusen-ai/naive-ui/issues/4609)\n- 修复 `n-dynamic-input` 的 `on-remove` 方法返回被删除的数据下标 `index` 时 `value[index]` 已经不存在\n- 修复 `n-dynamic-input` 在点击添加按钮后 `on-create` 返回的 `index` 不正确\n- 修复 `trTR` 国际化，关闭 [#4231](https://github.com/tusen-ai/naive-ui/issues/4231)\n- 修复 `n-input` 同时使用 `password` 和 `disabled` 时，显示密码图标偏移的问题，关闭 [#4364](https://github.com/tusen-ai/naive-ui/issues/4364)\n- 修复 `n-image` 设置 `fallback-src` 属性和懒加载无效，关闭 [#4480](https://github.com/tusen-ai/naive-ui/issues/4480)\n- 修复 `n-upload` 内部使用 vue `TransitionGroup` 组件时，传递了未声明的 prop 且未被自动继承导致警告，关闭[#4447](https://github.com/tusen-ai/naive-ui/issues/4447)\n- 修复 `n-menu` `show` `default` 属性拼写问题，关闭 [#4750](https://github.com/tusen-ai/naive-ui/issues/4750)\n- 修复 `n-icon-wrapper` 的主题异常，关闭 [#4768](https://github.com/tusen-ai/naive-ui/issues/4768)\n\n### Feats\n\n- `n-dynamic-input` 新增 `action` slot，关闭 [#3981](https://github.com/tusen-ai/naive-ui/issues/3981)\n- `n-dynamic-input` 新增 `disabled` 属性，关闭 [#4055](https://github.com/tusen-ai/naive-ui/issues/4055)\n- `n-data-table` 新增 `titleAlign` 属性，关闭 [#3954](https://github.com/tusen-ai/naive-ui/issues/3954)\n- `n-rate` 默认 slot 提供 `index` 序号，关闭 [#4413](https://github.com/tusen-ai/naive-ui/issues/4413)\n- `n-scrollbar` 新增 `size` 属性，关闭 [#3896](https://github.com/tusen-ai/naive-ui/issues/3896)\n- `n-select` 新增 `keyboard` 属性，[#4340](https://github.com/tusen-ai/naive-ui/issues/4340)\n- `n-data-table` 的 `render-expand-icon` 属性新增 `expanded` 参数，关闭 [#4439](https://github.com/tusen-ai/naive-ui/issues/4439)\n- `n-tabs` 新增 `pane-wrapper-class` `pane-wrapper-style` 属性\n- `n-collapse` 新增 `titlePadding` 主题变量，关闭 [#4728](https://github.com/tusen-ai/naive-ui/issues/4728)\n- `n-tabs` 新增 `placement` 属性\n\n### i18n\n\n- 更新 `zhTW` 国际化\n- 新增 `faIR` 国际化\n\n## 2.34.3\n\n`2022-12-24`\n\n### Fixes\n\n- 修复 `n-progress` `indicator-placement` 为 `inside` 时，`indicator-text-color` 不生效\n- 修复 `n-image` 操作预览图片时报错，关闭 [#4157](https://github.com/tusen-ai/naive-ui/issues/4157)\n- 修复 `n-tree` 的`cannot access 'mergedFilterRef' before initialization`报错，关闭 [#4134](https://github.com/tusen-ai/naive-ui/issues/4134)\n- 修复 `n-menu` 无法通过 `dropdown-props` 覆盖子菜单 dropdown 的 `trigger`，关闭 [#4147](https://github.com/tusen-ai/naive-ui/issues/4147)\n- 修复 `n-ellipsis` 在使用 `keep-alive` 的情况下关闭异常，关闭 [#4079](https://github.com/tusen-ai/naive-ui/issues/4079)\n- 修复 `n-upload` 对于名称为图片的文件不显示预览图，关闭 [#4198](https://github.com/tusen-ai/naive-ui/issues/4198)\n- 修复 `n-input` 在 size 为 tiny 和 autosize 属性下，input 对齐样式异常，关闭 [#4167](https://github.com/tusen-ai/naive-ui/issues/4167)\n- 修复 `n-image` 和 `n-avatar` 在 `lazy` 模式，设定 `intersection-observer-options` `rootMargin` 属性后，预加载不生效\n\n### Feats\n\n- `n-tree` 新增 `get-children` 属性，关闭 [#4128](https://github.com/tusen-ai/naive-ui/issues/4128)\n- `n-badge` 新增 `offset` 属性，关闭 [#4149](https://github.com/tusen-ai/naive-ui/issues/4149)\n- `n-card` 新增 `tag` 属性\n- demos 可以使用 `<script setup />`\n- `n-pagination` 新增 `select-props` 属性，关闭 [#4199](https://github.com/tusen-ai/naive-ui/issues/4199)\n- `n-select` 新增 `show-on-focus` 属性，关闭 [#4191](https://github.com/tusen-ai/naive-ui/issues/4191)\n- `n-pagination` 新增 `goto` 属性，关闭 [#4133](https://github.com/tusen-ai/naive-ui/issues/4133)\n- `n-upload` 上传后不再将 `file` 字段置为 `null`，关闭 [#3868](https://github.com/tusen-ai/naive-ui/issues/3868)\n- `n-form` 新增 `labelFontWeight` 主题变量，关闭 [#3516](https://github.com/tusen-ai/naive-ui/issues/3516)\n- `n-radio` 新增 `labelFontWeight` 主题变量，关闭 [#3516](https://github.com/tusen-ai/naive-ui/issues/3516)\n- `n-checkbox` 新增 `labelFontWeight` 主题变量，关闭 [#3516](https://github.com/tusen-ai/naive-ui/issues/3516)\n- `n-tree` 的 `on-load` 属性支持返回值 resolve false 来关闭加载动画，关闭 [#4038](https://github.com/tusen-ai/naive-ui/issues/4038)\n\n### i18n\n\n- 更新 koKr 国际化\n\n## 2.34.2\n\n`2022-11-22`\n\n### Fixes\n\n- 修复 `n-config-provider` 的 katex 的类型问题\n- 修复 `n-image` 预览工具栏操作报错，关闭 [#4144](https://github.com/tusen-ai/naive-ui/issues/4144)\n\n## 2.34.1\n\n`2022-11-21`\n\n### Fixes\n\n- 修复 `n-select` 在多选模式下会在控制台打印无用内容\n- 修复 `n-tree` 缺少 `getCheckedData` 和 `getIndeterminateData` 方法，关闭 [#4064](https://github.com/tusen-ai/naive-ui/issues/4064)\n- 修复 `n-data-table` 列的 `align` 配置对表头不生效，关闭 [#4063](https://github.com/tusen-ai/naive-ui/issues/4063)\n\n## 2.34.0\n\n`2022-11-21`\n\n### Breaking Changes\n\n- 在 `n-data-table` 的列外包裹一层 `div` 容器用以优化过滤按钮的布局，关闭 [#3853](https://github.com/tusen-ai/naive-ui/issues/3853)\n\n### Feats\n\n- `n-avatar-group` 导出 `AvatarGroupOption` 类型，关闭 [#3879](https://github.com/tusen-ai/naive-ui/issues/3879)\n- `n-transfer` 新增 `show-selected` 属性，关闭 [#3711](https://github.com/tusen-ai/naive-ui/issues/3711)\n- `n-data-table` 新增 `loading` 插槽，关闭 [#3865](https://github.com/tusen-ai/naive-ui/issues/3865)\n- `n-mention` 新增 `on-update:show` 属性，关闭 [#3882](https://github.com/tusen-ai/naive-ui/issues/3882)\n- `n-tree` 为 `on-update:expanded-keys`、`on-update:checked-keys`、`on-update:selected-keys` 属性添加触发节点信息，关闭 [#3885](https://github.com/tusen-ai/naive-ui/issues/3885)\n- `n-tree-select` 为 `on-update:expanded-keys`、`on-update:value` 属性添加触发节点信息，关闭 [#3885](https://github.com/tusen-ai/naive-ui/issues/3885)\n- `n-tree` 新增 `getCheckedData` 方法\n- `n-tree` 新增 `getIndeterminateData` 方法\n- `n-tree-select` 新增 `getCheckedData` 方法\n- `n-tree-select` 新增 `getIndeterminateData` 方法\n- `n-tree-select` 新增 `focus` 方法\n- `n-tree-select` 新增 `blur` 方法\n- `n-cascader` 新增 `getCheckedData` 方法\n- `n-cascader` 新增 `getIndeterminateData` 方法\n- `n-input` 新增 `count-graphemes` 属性，关闭 [#3967](https://github.com/tusen-ai/naive-ui/issues/3967)\n- `n-cascader` 新增 `not-found` slot，关闭 [#3862](https://github.com/tusen-ai/naive-ui/issues/3862)\n- `n-avatar` 新增 `img-props` 属性，关闭 [#3963](https://github.com/tusen-ai/naive-ui/issues/3963)\n- `n-data-table` 新增 `spin-props` 属性，关闭 [#3649](https://github.com/tusen-ai/naive-ui/issues/3649)\n- `n-button` 新增 `render-icon` 属性，关闭 [#4007](https://github.com/tusen-ai/naive-ui/issues/4007)\n- 新增 `n-equation` 组件\n- `n-image` 新增 `previewed-img-props` 属性\n- `n-data-table` 新增 `scrollbar-props` 属性，关闭 [#4021](https://github.com/tusen-ai/naive-ui/issues/4021)\n- `n-upload` 新增 `should-use-thumbnail-url` 属性，关闭 [#3861](https://github.com/tusen-ai/naive-ui/issues/3861)\n- `n-upload` 新增 `render-icon` 属性\n- `n-tree` 的 `render-switcher-icon` 属性传入 `expanded` 和 `selected` 字段\n- `useDialog` 的选项 option 支持 `transformOrigin`，关闭 [#3901](https://github.com/tusen-ai/naive-ui/issues/3901)\n\n### Fixes\n\n- 修复 `n-image` 在预览时可以被鼠标的任何按键拖动，关闭 [#3950](https://github.com/tusen-ai/naive-ui/issues/3950)\n- 修复 `n-form-item` 在 `label-align=\"left\"` 并且 `require-mark-placement=\"left\"` 并且 `label-placement=\"left\"` 时标签文本显示位置有问题，关闭 [#3871](https://github.com/tusen-ai/naive-ui/issues/3871)\n- 修复 `n-tree` 在谷歌、edge 浏览器 106 版本下拖动 tree，出现白屏现象，关闭 [#3909](https://github.com/tusen-ai/naive-ui/issues/3909)\n- 修复 `n-select` 在设定了 `value-field` 和 `max-tag-count=\"responsive\"` 之后在溢出标签的弹框中移除选中选项之后选框会显示错误的值，关闭 [#3869](https://github.com/tusen-ai/naive-ui/issues/3869)\n- 修复 `n-ellipsis` 在 `n-card` 标题中使用不会溢出，关闭 [#3935](https://github.com/tusen-ai/naive-ui/issues/3935)\n- 修复 `n-timeline-item` 在 `n-timeline` 设定 `horizontal` 之后，`line-type=\"dashed\"` 不生效，关闭 [#4014](https://github.com/tusen-ai/naive-ui/issues/4014)\n- 修复 `n-popover` 在英文和数字过长时不断行\n- 修复 `n-input` 的属性 `autosize` 在输入包含多个空格的时候表现不正确，关闭 [#4027](https://github.com/tusen-ai/naive-ui/issues/4027)\n- 修复 `n-pagination` 的 `endIndex` 在最后一页计算错误，关闭 [#4057](https://github.com/tusen-ai/naive-ui/issues/4057)\n- 修复 `n-image` 在预览时按空格会使页面滚动，关闭 [#3919](https://github.com/tusen-ai/naive-ui/issues/3919)\n\n### i18n\n\n- 新增 arDZ locale\n- 新增 trTR locale\n\n## 2.33.5\n\n`2022-10-12`\n\n### Fixes\n\n- 修复 `n-data-table` 树形数据勾选时报错，关闭 [#3832](https://github.com/tusen-ai/naive-ui/issues/3832)\n\n## 2.33.4\n\n`2022-10-06`\n\n### Fixes\n\n- 修复 `n-timeline-item` 的 `title` 的 `margin-bottom` 无法通过主题变量设置，关闭 [#3722](https://github.com/tusen-ai/naive-ui/issues/3722)\n- 修复 `n-timeline-item` 的 `meta` 在水平垂直嵌套时 `margin-bottom` 被覆盖\n- 修复 `n-tree-select` 在放置于 `label` 标签内时点击会删除掉第一个选中的选项，关闭 [#3715](https://github.com/tusen-ai/naive-ui/issues/3715)\n- 修复 `n-popover` 在已经弹出的状态下 `disabled` 被置为 `true`，之后又被置为 `false` 时，错误地重新弹出的行为\n- 修复 `n-select` 在 `maxTagCount=\"responsive\"` 的情况下，在弹层删除掉所有已选中项后，弹层不会消失，关闭 [#3801](https://github.com/tusen-ai/naive-ui/issues/3801)\n- 修复 `n-upload` 在 Firefox 浏览器可能只能选择目录，关闭 [#3798](https://github.com/tusen-ai/naive-ui/issues/3798)\n- 移除 `package.json` 中的 `exports` 字段，因为其兼容性还比较差，关闭 [#3786](https://github.com/tusen-ai/naive-ui/issues/3786)\n- 修复 `createDiscreteApi` 在 SSR 环境下报错，关闭 [#3813](https://github.com/tusen-ai/naive-ui/issues/3813)\n- 修复 `n-tree-select` 在单选并且 `filterable` 的情况下菜单关闭时聚焦状态有问题\n- 修复 `n-input-number` 在 `on-blur` 回调中设定值输入框可能不会更新\n\n### Feats\n\n- `n-collapse-item` 的 `header-extra` 和 `header` 插槽支持 `collapsed` 参数，关闭 [#3723](https://github.com/tusen-ai/naive-ui/issues/3723)\n- `n-loading-bar-provider` 新增 `container-style` 属性\n- `n-loading-bar-provider` 新增 `to` 属性，关闭 [#3724](https://github.com/tusen-ai/naive-ui/issues/3724)\n- `n-data-table` 新增 `on-update:checked-row-keys` 传递当前行数据和状态，关闭 [#3626](https://github.com/tusen-ai/naive-ui/issues/3626)\n- `n-data-table` column 新增 `resizable` 属性，关闭 [#3165](https://github.com/tusen-ai/naive-ui/issues/3165)\n- `createDiscreteApi` 会返回 Vue app\n- 导出 `LayoutContentInst` 类型，关闭 [#3743](https://github.com/tusen-ai/naive-ui/issues/3743)\n- 导出 `CarouselInst` 类型，关闭 [#3742](https://github.com/tusen-ai/naive-ui/issues/3742)\n- `n-collapse` 新增 `itemMargin` 主题变量，关闭 [#3788](https://github.com/tusen-ai/naive-ui/issues/3788)\n- `n-select` 新增 `ignore-composition` 属性，关闭 [#3789](https://github.com/tusen-ai/naive-ui/issues/3789)\n- `n-card` 导出 `CardSegmented` 类型，关闭 [#3775](https://github.com/tusen-ai/naive-ui/issues/3775)\n- `n-date-picker` 新增 `next-month` 插槽，关闭 [#3570](https://github.com/tusen-ai/naive-ui/issues/3570)\n- `n-date-picker` 新增 `next-year` 插槽，关闭 [#3570](https://github.com/tusen-ai/naive-ui/issues/3570)\n- `n-date-picker` 新增 `prev-month` 插槽，关闭 [#3570](https://github.com/tusen-ai/naive-ui/issues/3570)\n- `n-date-picker` 新增 `prev-year` 插槽，关闭 [#3570](https://github.com/tusen-ai/naive-ui/issues/3570)\n- `n-pagination` 新增 `to` 属性，关闭 [#3773](https://github.com/tusen-ai/naive-ui/issues/3773)\n- `n-avatar` 新增 `render-placeholder` 属性，关闭 [#3751](https://github.com/tusen-ai/naive-ui/issues/3751)\n- `n-avatar` 新增 `render-fallback` 属性，关闭 [#3751](https://github.com/tusen-ai/naive-ui/issues/3751)\n- `n-avatar` 新增 `fallback` slot\n- `n-transfer` 新增 `render-target-list` 属性\n- `n-select` 新增 `show-checkmark` 属性，关闭 [#3749](https://github.com/tusen-ai/naive-ui/issues/3749)\n- `n-tree` 新增 `animated` 属性，关闭 [#3784](https://github.com/tusen-ai/naive-ui/issues/3784)\n- `n-slider` 新增 `markFontSize` 主题变量，关闭 [#3820](https://github.com/tusen-ai/naive-ui/issues/3820)\n- `n-avatar-group` 新增 `gap` 主题变量，关闭 [#3819](https://github.com/tusen-ai/naive-ui/issues/3819)\n\n## 2.33.3\n\n`2022-09-13`\n\n### Feats\n\n- `n-dialog` 新增 `onAfterLeave` 在 DialogOptions Properties 中，关闭 [#3662](https://github.com/tusen-ai/naive-ui/issues/3662)\n- `n-dynamic-tags` 导出类型 `DynamicTagsOption`，关闭 [#3677](https://github.com/tusen-ai/naive-ui/issues/3677)\n- `n-upload` 新增 `responseType` 属性，关闭 [#3666](https://github.com/tusen-ai/naive-ui/issues/3666)\n- `n-dropdown` `DropdownOption` 新增 `show` 属性，关闭 [#3703](https://github.com/tusen-ai/naive-ui/issues/3703)\n- `n-data-table` 新增 `summary-placement` 属性，关闭 [#3681](https://github.com/tusen-ai/naive-ui/issues/3681)\n- `n-tabs` 会滚动到激活的标签，关闭 [#3683](https://github.com/tusen-ai/naive-ui/issues/3683)\n\n### Performance\n\n- 修复 `n-menu` 在 `value` 改变时会引发菜单项无用的渲染，关闭 [#3670](https://github.com/tusen-ai/naive-ui/issues/3670)\n\n### Fixes\n\n- 修复 `n-date-picker` 在 `inline-theme-disabled` 模式下样式不正常，关闭 [#3655](https://github.com/tusen-ai/naive-ui/issues/3655)\n- 修复 `n-data-table` 无法设定 `n-dropdown` 的 `theme-overrides`，关闭 [#3613](https://github.com/tusen-ai/naive-ui/issues/3613)\n- 修复 `n-carousel` 在设定了 `transform: scale` 后显示不正常，关闭 [#3684](https://github.com/tusen-ai/naive-ui/issues/3684)\n- 修复 `n-tree` 的节点在设定 `checkboxDisabled` 后会被整体禁用，关闭 [#3620](https://github.com/tusen-ai/naive-ui/issues/3620)\n- 修复 `n-tree` 在设定 `:show-irrelevant-nodes=\"false\"` 并搜索后展开关闭按钮失效，关闭 [#3647](https://github.com/tusen-ai/naive-ui/issues/3647)\n- 修复 `n-progress` 在 `type=\"circle\"` 并且 `stroke-width` 过大时，圆圈可能溢出，关闭 [#3638](https://github.com/tusen-ai/naive-ui/issues/3638)\n\n## 2.33.2\n\n`2022-09-01`\n\n### Fixes\n\n- 修复 UMD 构建产物不能正常工作，关闭 [#3642](https://github.com/tusen-ai/naive-ui/issues/3642)\n- 修复 `n-calendar` 在设定了 `default-value` 后默认显示月份没有跟随，关闭 [#3645](https://github.com/tusen-ai/naive-ui/issues/3645)\n- 修复 `n-form-item` 属性 `require-mark-placement` 值为 `left` 时不生效，关闭 [#3628](https://github.com/tusen-ai/naive-ui/issues/3628).\n- 修复 `n-upload` `OnBeforeUpload` 类型返回值只能为 `Promise<boolean>`\n\n### Feats\n\n- `n-radio` 新增 `colorActive` 主题变量，关闭 [#3610](https://github.com/tusen-ai/naive-ui/issues/3610)\n\n## 2.33.1\n\n`2022-08-29`\n\n### Fixes\n\n- 修复 Could not resolve \"@vicons/ionicons5\" 异常，关闭 [#3616](https://github.com/tusen-ai/naive-ui/issues/3616)\n\n## 2.33.0\n\n`2022-08-29`\n\n### Breaking Changes\n\n- `n-rate` 的 `default-value` 默认值从 `0` 设为 `null`\n\n### Fixes\n\n- 修复 `n-select` 菜单在 SSR 情况下缺少勾选图标，关闭 <https://github.com/07akioni/naive-ui-nuxt-demo/issues/4>\n- 修复 `n-card` 的 `embedded` 属性在 `n-dialog` 中不生效，关闭 [#3592](https://github.com/tusen-ai/naive-ui/issues/3592)\n- 修复 `n-radio` 当 `value` 属性为布尔值时报警告，关闭 [#3540](https://github.com/tusen-ai/naive-ui/issues/3540)\n- 修复 `n-pagination` 被禁用时，快速跳转菜单还会触发并可进行分页跳转\n- 修复 `n-tree` 节点的内容长度可能超过容器溢出，关闭 [#3561](https://github.com/tusen-ai/naive-ui/issues/3561)\n- 修复 `n-form-item` 标签在放在左侧时文字可能溢出，关闭 [#3593](https://github.com/tusen-ai/naive-ui/issues/3593)\n\n### Feats\n\n- `n-menu` 新增 `disabled-field` 属性\n- `n-rate` 新增 `clearable` 属性\n- `n-slider` 新增 `keyboard` 属性，关闭 [#3528](https://github.com/tusen-ai/naive-ui/issues/3528)\n- 新增 `useDialogReactiveList` 方法，关闭 [#2041](https://github.com/tusen-ai/naive-ui/issues/2041)\n- `DialogReactive` 支持 `onAfterEnter` 属性，关闭 [#3569](https://github.com/tusen-ai/naive-ui/issues/3569)\n- `DialogOptions` 支持 `class` 属性，关闭 [#3591](https://github.com/tusen-ai/naive-ui/issues/3591)\n\n## 2.32.2\n\n`2022-08-19`\n\n### Fixes\n\n- 修复 `n-menu` extra 在 submenu 中无效，关闭 [#3390](https://github.com/tusen-ai/naive-ui/issues/3390)\n- 修复 `n-tree` 在传入的节点数据中包含 `type='group'` 时无法展开，关闭 [#3388](https://github.com/tusen-ai/naive-ui/issues/3388)\n- 修复 `n-pagination` 的 `default-page-size` 没有跟随 `page-sizes` prop，关闭 [#3369](https://github.com/tusen-ai/naive-ui/issues/3369)\n- 在 package.json 中新增 `exports` 字段\n- 修复 `n-dropdown` 选项 prefix & suffix 的 z-index，关闭 [#3433](https://github.com/tusen-ai/naive-ui/issues/3433)\n- 修复 `n-input-number` 中配置 peers 主题不生效，关闭 [#3422](https://github.com/tusen-ai/naive-ui/issues/3422)\n- 修复 `n-tag` 当 tag 为 disabled 时，pointer 应该为 not allow，关闭 [#3494](https://github.com/tusen-ai/naive-ui/issues/3494)\n- 修复 `n-transfer` 中初始值不在选项列表报错，关闭 [#3406](https://github.com/tusen-ai/naive-ui/issues/3406)\n- 修复 `n-data-table` column `onSelect` 的类型，关闭 [#3430](https://github.com/tusen-ai/naive-ui/issues/3430)\n- 修复 `n-pagination` 的快速跳转在失焦时不会触发，关闭 [#3387](https://github.com/tusen-ai/naive-ui/issues/3387)\n- 修复部分组件在 open 模式的 shadow DOM 内运行不正常，关闭 [#3281](https://github.com/tusen-ai/naive-ui/issues/3281)\n- 修复 `n-carousel` 在 `loop='true'` 和 `effect='slide'` 下，只有两个元素时轮播过渡切换效果相反，关闭 [#3414](https://github.com/tusen-ai/naive-ui/issues/3413)\n- 修复 `n-input` 在中文输入过程中如果被重渲染打断可能无法输入，关闭 [#3503](https://github.com/tusen-ai/naive-ui/issues/3503)\n- 修复 `n-layout` 的 `embedded` 属性在 `n-config-provider` 设置 `inline-theme-disabled` 后不生效，关闭 [#3500](https://github.com/tusen-ai/naive-ui/issues/3500)\n- 修复 `n-input` 在禁用状态下有两层 placeholder，关闭 [#3467](https://github.com/tusen-ai/naive-ui/issues/3467)\n- 修复 `n-date-picker` 的 `iconColor` 主题变量不生效，关闭 [#3501](https://github.com/tusen-ai/naive-ui/issues/3501)\n- 修复 `n-time-picker` 的 `iconColor` 主题变量不生效，关闭 [#3501](https://github.com/tusen-ai/naive-ui/issues/3501)\n- 修复 `n-select` 的 `node-props` 属性不生效\n- 修复 Nuxt 的 `CSSRender is not a function` 报错，关闭 [#3506](https://github.com/tusen-ai/naive-ui/issues/3506)\n- 修复 `n-data-table` 用 `column.expandable` 禁用展开后依然可以渲染展开的行，关闭 [#3373](https://github.com/tusen-ai/naive-ui/issues/3373)\n- 修复 `n-input-number` 快速点击按钮可能触发变化无限循环，关闭 [#3329](https://github.com/tusen-ai/naive-ui/issues/3329)\n- 修复 `n-switch` 部分主题变量不能使用非 `px` 单位的值，关闭 [#2938](https://github.com/tusen-ai/naive-ui/issues/2938)\n- 修复 `n-input` 在 `resizable` 和 `type=\"textarea\"` 时某些情况不能调整大小，关闭 [#3479](https://github.com/tusen-ai/naive-ui/issues/3479)\n- 修复 `n-countdown` 在 `onFinish` 回调中使用 `reset` 方法时不生效，关闭 [#3536](https://github.com/tusen-ai/naive-ui/issues/3536)\n\n### Feats\n\n- `n-menu` 的 `MenuOption` 新增 `show` 属性，用于是否显示菜单，关闭 [#3334](https://github.com/tusen-ai/naive-ui/issues/3334)\n- `n-alert` 新增 `bordered` 属性，关闭 [#3358](https://github.com/tusen-ai/naive-ui/issues/3358)\n- `n-tag` 新增 `trigger-click-on-close` 属性，关闭 [#3343](https://github.com/tusen-ai/naive-ui/issues/3343)\n- `n-cascader` 新增 `disabled-field` 属性，关闭 [#3338](https://github.com/tusen-ai/naive-ui/issues/3338)\n- `n-list` 新增 `clickable` 属性\n- `n-list` 新增 `hoverable` 属性\n- `n-list` 新增 `show-divider` 属性\n- `n-thing` 新增 `content-style` 属性\n- `n-thing` 新增 `description-style` 属性\n- `n-data-table` 新增 `render-expand-icon`属性\n- `n-tree` 新增 `keyboard` 属性，关闭 [#3438](https://github.com/tusen-ai/naive-ui/issues/3438)\n- `n-tree` 新增 `disabled-field` 属性\n- `n-tree-select` 新增 `disabled-field` 属性\n- `n-collapse-item` 新增 `disabled` 属性，关闭 [#3408](https://github.com/tusen-ai/naive-ui/issues/3408)\n- `n-pagination` 新增 `simple` 属性\n- `n-cascader` 新增 `arrow` 插槽，关闭 [#3459](https://github.com/tusen-ai/naive-ui/issues/3459)\n- `n-transfer` 新增 `source-filterable` 属性，关闭 [#3407](https://github.com/tusen-ai/naive-ui/issues/3407)\n- `n-transfer` 新增 `target-filterable` 属性，关闭 [#3407](https://github.com/tusen-ai/naive-ui/issues/3407)\n- `n-transfer` 的 `filter` 属性新增 `from` 参数\n- `n-list` 支持 RTL\n- `n-drawer` 支持 RTL\n- `n-input` 新增 `render-count` 属性\n- `n-input` 新增 `countTextColorDisabled` 主题变量，关闭 [#3481](https://github.com/tusen-ai/naive-ui/issues/3481)\n- `n-statistic` 新增 `valueFontSize` 主题变量，关闭 [#3510](https://github.com/tusen-ai/naive-ui/issues/3510)\n- `n-tree` 新增 `scrollTo` 方法，关闭 [#3480](https://github.com/tusen-ai/naive-ui/issues/3480)\n- `n-pagination` 新增 `display-order` 属性，关闭 [#3466](https://github.com/tusen-ai/naive-ui/issues/3466)\n- `n-grid` 新增 `layout-shift-disabled` 属性，关闭 [#3301](https://github.com/tusen-ai/naive-ui/issues/3301)\n- `n-data-table` 新增 `sticky-expanded-rows` 属性，支持固定展开内容，关闭 [#3485](https://github.com/tusen-ai/naive-ui/issues/3485).\n\n## 2.32.1\n\n`2022-07-30`\n\n### Fixes\n\n- 修复 `n-drawer` 的 `default-height` 属性在使用 `string` 传参时控制台出现 warning，关闭 [#3377](https://github.com/tusen-ai/naive-ui/issues/3377)\n- 修复 `n-transfer` 的 `on-update:value` 在取消选择时不会触发，关闭 [#3393](https://github.com/tusen-ai/naive-ui/issues/3393)\n\n### Feats\n\n- `n-steps` 支持 RTL\n\n## 2.32.0\n\n`2022-07-28`\n\n### Breaking Changes\n\n- `n-transfer` 的 UI 完全重构，原本的 transfer 组件被重命名为 `n-legacy-transfer`，并将在下个主版本被移除。\n\n### Fixes\n\n- 修复 `n-date-picker` 在范围模式下点击禁用的确认按钮会取消选择中的状态，关闭 [#3254](https://github.com/tusen-ai/naive-ui/issues/3254)\n- 修复 `n-button` 的 `focusable` 属性不生效，关闭 [#3292](https://github.com/tusen-ai/naive-ui/issues/3292)\n- 修复 `n-upload` 的 `on-error` 和 `on-finish` 属性不允许 `() => void` 类型，关闭 [#3290](https://github.com/tusen-ai/naive-ui/issues/3290)\n- 修复 `n-select` 的 placeholder 过长时可能溢出\n- 修复 `n-input` 在 `type=\"textarea\"` 并且 `:autosize=\"true\"` 时添加 prefix 后内容没有对齐，关闭 [#3238](https://github.com/tusen-ai/naive-ui/issues/3238)\n- 修复 `n-select` 当在同时设置 `filterable` 和 `multiple` 时点击 `action` 焦点丢失的问题，关闭 [#3247](https://github.com/tusen-ai/naive-ui/issues/3247)\n- 修复 `n-carousel` 在 `autoplay` 为 `true` 时 `hover` 不停止播放，关闭 [#3304](https://github.com/tusen-ai/naive-ui/issues/3304)\n- 修复 `n-tree` 在选中节点时设定 `expanded-keys` 时可能会抛出异常，关闭 [#3319](https://github.com/tusen-ai/naive-ui/issues/3319)\n- 修复 `n-avatar` 加载失败时依然显示 placeholder，关闭 [#3315](https://github.com/tusen-ai/naive-ui/issues/3315)\n- 修复 `n-input-number` 按住按钮时重复注册 `mouseup` 事件\n- 修复所有组件导出的 props 类型属性都是 `readonly` 的\n- 修复 `n-tree` 的 `check-on-click` 属性有时不生效\n- 修复 `n-progress` 的 `offset-degree` 表现不正确\n- 修复 `n-date-picker` 在某些情况下不能删除全部输入，关闭 [#3922](https://github.com/tusen-ai/naive-ui/issues/3922)\n\n### Feats\n\n- `n-checkbox-group` 的 `on-update:value` 属性增加触发变更的 checkbox 的值到参数中，关闭 [#3277](https://github.com/tusen-ai/naive-ui/issues/3277)\n- `n-tree` 支持 RTL\n- `n-input` 新增 `scrollTo` 方法，关闭 [#3280](https://github.com/tusen-ai/naive-ui/issues/3280)\n- `n-legacy-grid` 支持 RTL\n- `n-statistic` 支持 RTL\n- `n-thing` 支持 RTL\n- `n-transfer` 新增 `render-source-label` 属性\n- `n-transfer` 新增 `render-target-label` 属性\n- `n-transfer` 新增 `render-source-list` 属性\n- `n-scrollbar` 支持 RTL\n- `useDialog` 支持 `onEsc` 属性\n- `n-watermark` 新增 `global-rotate` 属性\n- `n-notification` 新增 `keepAliveOnHover` 属性，用于设置鼠标移入时是否保持通知框显示，关闭 [#3249](https://github.com/tusen-ai/naive-ui/issues/3249)\n\n## 2.31.0\n\n`2022-07-07`\n\n### Breaking Changes\n\n- `n-date-picker` 的 `clearable` 属性在 `action` 属性没有设置时，会控面板清空按钮的显隐，关闭 [#1196](https://github.com/tusen-ai/naive-ui/issues/1196)\n- `n-button` 的 `native-focus-behavior` 属性默认值改为“不是 Safari”\n\n### Fixes\n\n- 修复 `n-data-table` 的列的 `render` 属性的 `index` 参数当使用产开行时序列异常，关闭 [#3153](https://github.com/tusen-ai/naive-ui/issues/3153)\n- 修复 `n-data-table` 在虚拟滚动模式下列 `colSpan` 没有正确生效，关闭 [#3052](https://github.com/tusen-ai/naive-ui/issues/3052)\n- 修复 `n-data-table` 在虚拟滚动模式下 `summary` 行不显示，关闭 [#3202](https://github.com/tusen-ai/naive-ui/issues/3202)\n- 修复 `n-carousel` 在 `effect` 为 `fade` 时幻灯片之间的层级关系错误问题，关闭 [#3227](https://github.com/tusen-ai/naive-ui/issues/3227)\n- 修复 `n-carousel` 在 IOS 下无法滑动问题，关闭 [#3106](https://github.com/tusen-ai/naive-ui/issues/3106)\n- 修复 `n-carousel` 在渲染时丢失内容元素大小问题，关闭 [#3078](https://github.com/tusen-ai/naive-ui/issues/3078)\n- 修复 `n-cascader` 的搜索菜单没有显示节点路径，关闭 [#3220](https://github.com/tusen-ai/naive-ui/issues/3220)\n- 修复 `n-cascader` 的 `filter` 属性接收到的 `path` 可能有误\n- 修复 `n-date-picker` 在 `type=\"quarterrange\"` 和 `type=\"quarter\"` 时菜单季度文案不一致，关闭 [#3217](https://github.com/tusen-ai/naive-ui/issues/3217)\n- 修复 `n-notification` 在内容高度超过屏幕后的关闭动画\n- 修复 `n-dropdown` 禁用的选项有 hover 样式\n- 修复 `n-dropdown` 菜单出现可能会闪\n- 修复 `n-dropdown` 菜单的 transform origin 在 Chrome 上可能不正确\n- 修复 `n-radio-button` 光标样式可能不正确，关闭 [#3243](https://github.com/tusen-ai/naive-ui/issues/3243)\n- 修复 `n-input` 在 disabled 状态下在 Safari 上文本颜色过浅，关闭 [#3241](https://github.com/tusen-ai/naive-ui/issues/3241)\n- 修复 `n-input` 的分割符可能折行\n- 修复所有组件的 `user-select` 样式属性在 Safari 的效果\n- 修复 `n-data-table` 在虚拟滚动模式下会阻止页面滚动\n- 修复 `n-button` 在 Firefox 下没有按下的效果\n\n### Feats\n\n- `n-avatar` 新增 `lazy` 属性\n- `n-avatar` 新增 `intersection-observer-options` 属性\n- `n-number-animation` 新增 `on-finish` 属性\n- `n-notification` 支持 RTL\n- 导出所有组件的 props 对象\n- `n-popover` 新增 `footer-style` 属性，用于设置底部内容的样式\n- `n-popover` 新增 `footer` 插槽，用于设置底部内容，关闭 [#3188](https://github.com/tusen-ai/naive-ui/issues/3188)\n- `n-dropdown` 新增 `menu-props`，关闭 [#2885](https://github.com/tusen-ai/naive-ui/issues/2885)\n- `n-data-table` 的列属性增加 `multiple` 属性使得表格选择支持单选模式，关闭 [#3056](https://github.com/tusen-ai/naive-ui/issues/3056)\n- `n-date-picker` 在选择结束日期过程中禁止点击确认按钮，关闭 [#3226](https://github.com/tusen-ai/naive-ui/issues/3226)\n- `n-tree` 新增 `check-on-click` 属性来控制可选状态下的选中交互方式，关闭 [#2968](https://github.com/tusen-ai/naive-ui/issues/2968)\n- `n-tree` 新增 `accrodion` 属性，关闭 [#3129](https://github.com/tusen-ai/naive-ui/issues/3129)\n- `n-countdown` 新增 `reset` 方法，关闭 [#3228](https://github.com/tusen-ai/naive-ui/issues/3228)\n- `n-drawer` 新增 `resizable` 属性\n- `n-drawer` 新增 `default-height` 属性\n- `n-drawer` 新增 `default-width` 属性\n- `n-drawer` 新增 `on-update:height` 属性\n- `n-drawer` 新增 `on-update:width` 属性\n- 更新 ukUA locale\n- `n-message` 支持 RTL\n\n## 2.30.8\n\n`2022-06-29`\n\n### Fixes\n\n- 修复 `n-select` 菜单的 transition 样式，关闭 [#3211](https://github.com/tusen-ai/naive-ui/issues/3211)\n\n## 2.30.7\n\n`2022-06-29`\n\n### Fixes\n\n- 修复 `n-tabs` 的 `bar-width` 属性在设置 `0` 时失效，关闭 [#3171](https://github.com/tusen-ai/naive-ui/issues/3171)\n- 修复 `n-drawer` 使用 `show-mask` 属性时控制台出现 warning，关闭 [#3172](https://github.com/tusen-ai/naive-ui/issues/3172)\n- 修复 `n-button` 放入 ellipsis 的容器中时不能正确显示，关闭 [#3178](https://github.com/tusen-ai/naive-ui/issues/3178).\n- 修复 `n-select` 在 `form` 中，多选的情况下，在 input 元素中按下 Enter 键会导致选项被清除，关闭 [#3169](https://github.com/tusen-ai/naive-ui/issues/3169)\n- 修复 `n-select` 的 `filter` 属性不生效，关闭 [#3175](https://github.com/tusen-ai/naive-ui/issues/3175)\n- 修复 `n-modal` 在不使用任何 preset 的时候遮罩可能覆盖住内容，关闭 [#3204](https://github.com/tusen-ai/naive-ui/issues/3204)\n- 修复 `n-button` 在图标过大或者过小时未对齐\n- 修复 `n-select` 创建的选项可能出现多次，关闭 [#3206](https://github.com/tusen-ai/naive-ui/issues/3206)\n\n### Feats\n\n- `n-date-picker` `type` 属性支持 `'quarterrange'` 和 `'yearrange'`\n- `n-tree-select` 新增 `render-prefix` 属性\n- `n-tree-select` 新增 `render-suffix` 属性\n- `n-tree-select` 新增 `render-switcher-icon` 属性\n- `n-tree-select` 新增 `node-props` 属性\n- `n-tree-select` 新增 `render-label` 属性，关闭 [#3197](https://github.com/tusen-ai/naive-ui/issues/3197)\n- `n-tree-select` 新增 `render-tag` 属性\n- `n-notification` 新增 `titleFontSize`、`metaFontSize`、`descriptionFontSize` 主题变量\n\n## 2.30.6\n\n`2022-06-22`\n\n### Fixes\n\n- 修复 `n-color-picker` 手动输入 alpha 值时不生效\n- 修复某些组件在 `__VUE_OPTIONS_API__` 设为 `false` 时工作不正常的问题，关闭 [#3146](https://github.com/tusen-ai/naive-ui/issues/3146)\n- 修复 `n-grid` 在 SSR 页面挂载后不会正确的适配响应式，关闭 [#2462](https://github.com/tusen-ai/naive-ui/issues/2462)\n- 修复 `n-modal` 在同时打开多个的时候点击某个遮罩，`on-mask-click` 会对每一个都触发，关闭 [#3147](https://github.com/tusen-ai/naive-ui/issues/3147)\n- 修复 `n-data-table` 的列的 `ellipsis` 属性类型不接受 `style` 属性\n- 修复 `n-data-table` 在列同时设为 `ellipsis` 和 `fixed` 时会丢失固定列的阴影\n- 修复 `n-image` 的 `lazy` 属性在 Safari 和 Firefox 上工作不正常\n\n## 2.30.5\n\n`2022-06-20`\n\n### Fixes\n\n- 修复 `n-input-group-label` 的内容在 `n-drawer-content` 嵌套中异常，关闭 [#3115](https://github.com/tusen-ai/naive-ui/issues/3115)\n- 修复 `n-back-top` 在使用 `show` 时控制台报警告，关闭 [#3122](https://github.com/tusen-ai/naive-ui/issues/3122)\n- 修复 `volar.d.ts` 组件全局类型为 `any`\n- 修复 `n-grid-item` 使用 `v-show` 可能存在显示状态不正确的问题，关闭 [#3123](https://github.com/tusen-ai/naive-ui/issues/3123)\n- 修复 `n-select` 在可清空状态下使用输入法输入，移入鼠标后输入文字会消失\n\n### Feats\n\n- 🌟 `n-image` 新增 `lazy` 属性，关闭 [#3055](https://github.com/tusen-ai/naive-ui/issues/3055)\n- `n-image` 新增 `intersection-observer-options` 属性\n- `n-image` 新增 `placeholder` slot\n- 导出 `NTooltipInst` 类型\n- `n-data-table` 新增 `render-cell` 属性，关闭 [#3095](https://github.com/tusen-ai/naive-ui/issues/3095)\n- `n-space` 新增 `wrap-item` 属性\n- `n-data-table` 的 `on-update:checked-row-keys` 会传出行数据，关闭 [#2215](https://github.com/tusen-ai/naive-ui/issues/2215)，关闭 [#2265](https://github.com/tusen-ai/naive-ui/pull/2265)\n\n## 2.30.4\n\n`2022-06-15`\n\n### Fixes\n\n- 修复 `n-button` 在设定 `:focusable=\"false\"` 后点击仍然会聚焦，关闭 [#3071](https://github.com/tusen-ai/naive-ui/issues/3071)\n- 修复 `n-data-table` 固定的选择列在设定了非默认宽度的情况下可能和其他列重叠，关闭 [#3067](https://github.com/tusen-ai/naive-ui/issues/3067)\n- 修复 `n-popselect` 在选择完关闭菜单后没有触发 `on-update:show`\n- 修复 `n-popselect` 的宽度不能通过 `style` 配置\n- 修复 `n-date-picker` 在设定了 `is-date-disabled` 后年月的快速跳转可能会被禁用，关闭 [#3068](https://github.com/tusen-ai/naive-ui/issues/3068)\n- 修复 `n-layout` 在 `keep-alive` 中使用的时候不会维持滚动状态\n- 修复 `n-layout-sider` 在 `keep-alive` 中使用的时候不会维持滚动状态\n- 修复 `n-tree` 可能重复发送异步数据请求\n- 修复 `n-tree` 在设定 `expand-on-click` 之后异步展开报错，关闭 [#3089](https://github.com/tusen-ai/naive-ui/issues/3089)\n- 修复 `n-slider` 使用键盘聚焦触发 tooltip 的时候没有动画\n- 修复 `n-slider` 在 mark 出现在最右侧的时候换行不正常\n- 修复 `n-upload` 内部的链接会出现原生 focus-visible 的 outline 样式\n- 修复 `n-upload` 在 `list-type=\"image-card\"` 时会出现 slot 相关 warning\n- 修复 `n-upload` 在 `list-type=\"image-card\"` 图片的边角会溢出列表项\n- 修复 `n-dynamic-tags` 的 `on-create` 属性不生效\n- 修复 Chrome 102 版本引入的虚拟滚动卡顿问题，关闭 [#3048](https://github.com/tusen-ai/naive-ui/issues/3048)\n- 修复 `n-upload-dragger` 在禁用状态下过于透明\n\n### Feats\n\n- 🌟 `n-pagination` 新增快速跳转的下拉菜单\n- 🌟 `n-input` 新增 `allow-input` 属性\n- 🌟 `n-data-table` 新增 `default-expand-all` 属性，关闭 [#3073](https://github.com/tusen-ai/naive-ui/issues/3073)\n- 🌟 `n-modal` 在内部带有弹出层组件例如 `n-select` 的时候可以正确处理 esc 键按下的情况，关闭 [#2973](https://github.com/tusen-ai/naive-ui/issues/2973)\n- `n-tree-select` 新增 `arrow` slot，关闭 [#3084](https://github.com/tusen-ai/naive-ui/issues/3084)\n- `n-cascader` 在点击 checkbox 后会显示对应的子菜单，关闭 [#3079](https://github.com/tusen-ai/naive-ui/issues/3079)\n- `n-upload` 在达到最大文件数量限制后会禁用 dragger\n- `n-select` 新增 `node-props` 属性\n- `n-popselect` 新增 `node-props` 属性\n- `n-popselect` 新增 `virtual-scroll` 属性\n- `n-data-table` 新增 `scrollTo` 方法，关闭 [#2570](https://github.com/tusen-ai/naive-ui/issues/2570)\n- `n-slider` 新增 `thumb` 插槽\n\n## 2.30.3\n\n`2022-06-09`\n\n### Fixes\n\n- 修复 `n-cascader` 溢出标签的 popover 在设定 `filterable` 后无法滚动，关闭 [#3061](https://github.com/tusen-ai/naive-ui/issues/3061)\n- 修复 `n-drawer` 的 `show-mask` 传入 `'transparent'` 会报 warning\n- 修复 `n-calendar` 点击不在当前月份的日期不会调用 `on-panel-change`，关闭 [#3063](https://github.com/tusen-ai/naive-ui/issues/3063)\n\n### Feats\n\n- 🌟 提供 UMD 打包\n- `n-cascader` 在单选状态下会展开选中的值，关闭 [#3058](https://github.com/tusen-ai/naive-ui/issues/3058)\n- `n-space` 在可能的情况下会使用 `gap` CSS 属性，关闭 [#3053](https://github.com/tusen-ai/naive-ui/issues/3053)\n\n## 2.30.2\n\n`2022-06-07`\n\n### Fixes\n\n- 修复 `n-select` 每次关闭菜单时会重新计算选项，提升了性能\n\n## 2.30.1\n\n`2022-06-07`\n\n### Feats\n\n- `n-menu` 新增 `arrowColorChildActiveHover`, `itemIconColorChildActiveHoverHorizontal`, `itemIconColorChildActiveHover`,`itemTextColorChildActiveHoverHorizontal`, `itemTextColorChildActiveHover`, `arrowColorChildActiveHoverInverted`, `itemIconColorChildActiveHoverHorizontalInverted`, `itemIconColorChildActiveHoverInverted`,`itemTextColorChildActiveHoverHorizontalInverted`, `itemTextColorChildActiveHoverInverted` 主题变量，关闭 [#2929](https://github.com/tusen-ai/naive-ui/issues/2929)\n\n### Fixes\n\n- 修复 `n-menu` `node-props` 属性没有添加到 `role=\"menuitem\"` 的元素上，而是添加到了里层元素\n- 修复 `n-menu` `node-props` 对 `type=\"group\"` 的选项不生效\n\n## 2.30.0\n\n`2022-06-06`\n\n### Breaking Changes\n\n- 主题变量 `closeColor`、`closeColorHover`、`closeColorPressed` 重命名为 `closeIconColor`、`closeIconColorHover`、`closeIconColorPressed`，`closeColorHover`、`closeColorPressed` 仍然保留，控制关闭按钮的背景颜色\n- `n-tag` 的 `colorXxx` 主题变量重命名为 `colorBorderedXxx`，`colorXxx` 仍然保留，控制不带边框标签的颜色\n\n### Fixes\n\n- 修复 `createDiscreteApi` 中传入 `'loadingBar'` 不生效\n- 修复 `n-popover` 在切换主题时关闭背景颜色突变\n- 修复 `n-select` 多选时选框大小改变时菜单位置没有同步\n- 修复 `n-scrollbar` 无法显示横向滚动条，关闭 [#3047](https://github.com/tusen-ai/naive-ui/issues/3047)\n- 修复 `n-tree` 在 `:block-line=\"true\"` 并且 `:selectable=\"true\"` 时节点的点击样式优先级高于激活样式\n- 修复 `n-slider` 在边界情况下可能泄露事件监听器\n- 修复 `n-data-table` 在 `keep-alive` 组件中使用重新激活时不会恢复滚动位置，关闭 [#2522](https://github.com/tusen-ai/naive-ui/issues/2522)\n- 修复 `n-image` 在图像过大时缩放比例不够大\n- 修复 `n-menu` 下拉菜单选项在选项后代被激活的状况下的文字样式\n- 修复 `n-input` 的 `input-props` 属性设定 `class` 和 `style` 不生效\n\n### Feats\n\n- 🌟 `n-time-picker` 新增 `time-zone` 属性，关闭 [#293](https://github.com/tusen-ai/naive-ui/issues/293)\n- 🌟 `n-input-number` 新增 `parse` 属性\n- 🌟 `n-input-number` 新增 `format` 属性\n- 🌟 `n-input-number` 新增 `precision` 属性，关闭 [#2068](https://github.com/tusen-ai/naive-ui/issues/2068)、[#1859](https://github.com/tusen-ai/naive-ui/issues/1859)\n- 🌟 `n-image` 新增展示图片原始大小的开关，关闭 [#3023](https://github.com/tusen-ai/naive-ui/issues/3023)\n- 🌟 所有组件的关闭按钮使用了新样式、并且可以聚焦\n- 所有组件的选择菜单或下拉菜单使用了新的选项样式\n- `n-tag` 新增 `icon` 插槽\n- `n-tag` 新增 `strong` 属性\n- `n-tag` 在暗色背景下 `:bordered=\"false\"` 时增加背景颜色，关闭 [#1699](https://github.com/tusen-ai/naive-ui/issues/1699)\n- `n-time` 新增 `time-zone` 属性\n- `n-breadcrumb-item` 新增 `clickable` 属性\n- `n-breadcrumb-item` 使用新样式，新增 `itemLineHeight`、`itemBorderRadius`、`itemColorHover`、`itemColorPressed` 主题变量\n- `n-notification` 优化标题过长时的样式\n- `n-drawer` 优化标题过长时的样式\n- `n-dialog` 优化标题过长时的样式\n- `n-card` 优化标题过长时的样式\n\n## 2.29.1\n\n`2022-06-03`\n\n### Fixes\n\n- 修复 `n-tree` 使用 `pattern` 属性过滤树节点时报错，关闭 [#2960](https://github.com/tusen-ai/naive-ui/issues/2960)\n- 修复 `n-watermark` 在全局配置了 `cls-prefix` 时失效\n- 修复 `n-dropdown` 在 `:show-arrow=\"true\"` 情况下不显示箭头的问题，关闭[#2977](https://github.com/tusen-ai/naive-ui/issues/2977)\n- 修复 `n-upload-dragger` 没有占据满宽度\n- 修复 `n-global-style` 没有清空 body 的 padding 和 margin\n- 修复 `n-modal` 在显示时被卸载不会清除 body 的 overflow，关闭 [#3015](https://github.com/tusen-ai/naive-ui/issues/3015)\n- 修复键盘操作在特定的老旧浏览器无法使用\n- 修复 `n-tabs` 的 `justify-content` 为 `'start'`、 `'end'` 和 `'center'` 时缺少 padding\n- 修复 `n-tabs` 在 `justify-content`、`size` 切换时指示条的位置没有更新\n- 修复 `n-switch` 在 `disabled` 切换时没有过渡效果\n- 修复 `n-modal` & `n-drawer` 在输入法输入过程中按 Esc 会关闭，关闭 [#2989](https://github.com/tusen-ai/naive-ui/issues/2989)\n- 修复 `n-date-picker` 在选择日期时间范围的过程中还可以选择时间，关闭 [#3004](https://github.com/tusen-ai/naive-ui/issues/3004)\n- 修复 `n-pagination` 在 `:page-count=\"0\"` 是显示有问题，关闭 [#2970](https://github.com/tusen-ai/naive-ui/issues/2970)\n- 修复 `n-date-picker` 在 `type=\"datetimerange\"` 时 `shortcuts` 会被 `default-time` 覆盖，关闭 [#3020](https://github.com/tusen-ai/naive-ui/issues/3020)\n- 修复 `n-image-group` 在 SSR 下无法切换图片\n- 修复 `n-tabs` 在 `display-directive=\"show\"` 和 `:animated=\"true\"` 的时候动画切换高度有时没有过渡，关闭 [#3035](https://github.com/tusen-ai/naive-ui/issues/3035)\n- 修复 `n-select` 在单选时搜索时字体略小\n- 修复 `n-select` 的计数标签在溢出内容少的时候弹出内容过高\n- 修复 `n-date-picker` 在 `type=\"monthrange\"` 时第一次选中时滚动状态没有对齐\n- 修复 `n-form-item` 的必填星号可以被选中\n- 修复 `n-list` 在暗色模式下的 `n-popover` 中颜色不正确\n\n### Feats\n\n- 🌟 `n-select` 新增 `label-field` 属性，关闭 [#3018](https://github.com/tusen-ai/naive-ui/issues/3018)\n- 🌟 `n-select` 新增 `value-field` 属性，关闭 [#3018](https://github.com/tusen-ai/naive-ui/issues/3018)\n- 🌟 `n-steps` 新增 `on-update:current` 属性\n- 🌟 `n-date-picker` 新增 `panel` 属性\n- 🌟 `n-data-table` 新增 `on-scroll` 属性，关闭 [#3025](https://github.com/tusen-ai/naive-ui/issues/3025)\n- 🌟 `FormItemRule` 新增 `renderMessage` 属性，关闭 [#2525](https://github.com/tusen-ai/naive-ui/issues/2525)\n- 🌟 新增 `createDiscreteApi` 在 setup 外使用 message、notification、dialog、loading bar\n- `n-scrollbar` 新增 `trigger` 属性\n- `n-input-number` 新增 `button-placement` 属性\n- `n-select` 新增 `children-field` 属性，关闭 [#3018](https://github.com/tusen-ai/naive-ui/issues/3018)\n- `n-upload` 新增 `trigger-style` 属性\n- `n-dropdown` 新增 `node-props` 属性\n- `n-dropdown` 新增 `render-option` 属性\n- `n-upload` 新增 `is-error-state` 属性，关闭 [#2975](https://github.com/tusen-ai/naive-ui/issues/2975)\n- `n-date-picker` 的 `shortcuts` 属性支持 readonly tuple 类型\n- `n-step` 新增 `disabled` 属性\n- `n-calendar` 新增 `header` slot，关闭 [#3036](https://github.com/tusen-ai/naive-ui/issues/3036)\n- `n-tree` 新增 `expand-on-click` 属性， [#2949](https://github.com/tusen-ai/naive-ui/issues/2949)\n\n## 2.29.0\n\n`2022-05-18`\n\n### Breaking Changes\n\n- 由于 `n-pagination` 支持了 `size` 属性，因此 `n-pagination` 的部分主题变量名称进行了调整\n\n### Fixes\n\n- 修复 `n-menu` 使用 `render-icon` 函数返回值为 `true` 时渲染不正确\n- 修复 `n-tabs` 的 `tabFontWeightActive` 主题变量应用在全部 tab 上了，关闭 [#2926](https://github.com/tusen-ai/naive-ui/issues/2926)\n- 修复 `n-tree-select` 的 `default-expand-all` 不生效\n- 修复 `n-upload` 的 `accept` 属性对拖拽场景不生效，关闭 [#2919](https://github.com/tusen-ai/naive-ui/issues/2919)\n- 修复 `n-calendar` 的 `on-panel-change` 在点击“今天”的时候返回的 `month` 不正确\n- 修复 `n-time` 在 SSR 下由于无法导入 `getTimezoneOffset` 报错的问题，关闭 [#2545](https://github.com/tusen-ai/naive-ui/issues/2545)\n- 修复 `n-transfer` 搜索框的 box-shadow 被切断\n- 修复 `n-time-picker` 在 blur 后输入框不合法的值不会被清除\n\n### Feats\n\n- `n-notification-provider` 的 `placement` 属性支持 `'top'` 和 `'bottom'`，关闭 [#2930](https://github.com/tusen-ai/naive-ui/issues/2930)\n- `n-pagination` 新增 `size` 属性，关闭 [#2888](https://github.com/tusen-ai/naive-ui/issues/2888)\n- `n-config-provider` 新增 `preflight-style-disabled` 属性\n- `n-pagination` 快速跳转的页码超出范围时取最大值、最小值，关闭 [#2928](https://github.com/tusen-ai/naive-ui/issues/2928)\n- `n-pagination` 中快速跳转的输入字符只允许纯数字，关闭 [#2928](https://github.com/tusen-ai/naive-ui/issues/2928)\n- `n-color-picker` 新增 `on-confirm` 属性\n- `n-input` 新增 `clear-icon` slot\n- `n-date-picker` 新增 `date-icon` 插槽，关闭 [#2668](https://github.com/tusen-ai/naive-ui/issues/2668)\n- `n-date-picker` 新增 `separator` 插槽，关闭 [#2668](https://github.com/tusen-ai/naive-ui/issues/2668)\n\n### i18n\n\n- 新增 nlNL locale\n\n## 2.28.4\n\n`2022-05-11`\n\n### Fixes\n\n- 修复 `n-theme-editor` 内容不能滚动\n\n## 2.28.3\n\n`2022-05-11`\n\n### Fixes\n\n- 修复 `n-menu` 的 `dropdown-props` 无法覆盖 `n-dropdown` 的 `size` 属性，关闭 [#2868](https://github.com/tusen-ai/naive-ui/issues/2868)\n- 修复 `n-switch` 切换状态时 loading 动画异常，关闭 [#2870](https://github.com/tusen-ai/naive-ui/issues/2870)\n- 修复 `n-data-table` 在页数设定超过数据内容时，不显示内容，关闭 [#2840](https://github.com/tusen-ai/naive-ui/issues/2840)\n- 修复 `n-data-table` 的 `cellProps` 泛型类型不正确\n- 修复 `n-data-table` 的 `work-break` 样式为 `break-word`\n- 修复 `n-list` 的 `n-merged-color` 样式不正常\n- 修复 `MessageReactive` 的 `destroy` 方法在 message 消失后调用会抛错\n- 修复 `n-ellpisis` 在恰好触发省略的时候无法弹出 tooltip，关闭 [#1393](https://github.com/tusen-ai/naive-ui/issues/1393)、[#2899](https://github.com/tusen-ai/naive-ui/issues/2899)\n- 修复 `n-tree` 无法使用 `width: fit-content;` 的样式，关闭 [#2875](https://github.com/tusen-ai/naive-ui/issues/2875)\n- 修复 `n-dropdown` 的 `on-update:show` 会被触发两次，关闭 [#2905](https://github.com/tusen-ai/naive-ui/issues/2905)\n- 修复 `n-select` 在选框清空后依然可以通过 enter 键选中值\n- 修复 `n-data-table` 的 `selection` 和 `expand` 列不能设置宽度\n- 修复 `n-checkbox` 中有可以被选中的空格\n- 修复 `DescriptionsProps` 拼错成了 `DescriptionProps`\n- 修复 `n-icon` 缺少 `IconProps`\n- 修复 `n-icon-wrapper` 缺少 `IconWrapperProps`\n- 修复 `n-countdown` 在 `precision=0` 时显示比实际快一秒，关闭 [#2910](https://github.com/tusen-ai/naive-ui/issues/2910)\n\n### Feats\n\n- `n-menu` 新增 `node-props` 属性\n- `n-switch` 新增 `rubber-band` 属性\n- `n-space` 的 `justify` 支持 `'space-evenly'`\n- `n-popover` 新增 `content-style` 属性\n- `n-popover` 新增 `header-style` 属性\n- `n-popover` 新增 `scrollable` 属性\n- `n-select` 和 `n-cascader` 和 `n-tree-select` 的溢出计数 tag 弹出内容可以滚动\n- `n-data-table` 新增 `pagination-behavior-on-filter` 属性\n- `n-date-picker` 属性 `type` 支持 `monthrange` 选项\n- `n-date-picker` 新增 `on-clear` 属性\n- `n-date-picker` 新增 `on-confirm` 属性，关闭 [#2852](https://github.com/tusen-ai/naive-ui/issues/2852)\n- `n-data-table` 的 `columns` 的元素支持 `minWidth` 属性\n- `n-tree` 新增 `checkbox-placement` 属性\n- `n-tree-select` 新增 `loading` 属性，关闭 [#2857](https://github.com/tusen-ai/naive-ui/issues/2857)\n- `n-modal` 新增 `block-scroll` 属性\n- `n-modal` 新增 `block-scroll` 属性，关闭 [#2556](https://github.com/tusen-ai/naive-ui/issues/2556)\n- `n-drawer` 新增 `block-scroll` 属性，关闭 [#2556](https://github.com/tusen-ai/naive-ui/issues/2556)\n- `n-drawer` 新增 `show-mask` 属性，关闭 [#2556](https://github.com/tusen-ai/naive-ui/issues/2556)\n- `useDialog().xxx` 支持 `blockScroll` 属性，关闭 [#2556](https://github.com/tusen-ai/naive-ui/issues/2556)\n- `useDialog().xxx` 支持 `autoFocus` 属性\n- `n-button` 新增 `native-focus-behavior` 属性，关闭 [#2882](https://github.com/tusen-ai/naive-ui/issues/2882)\n- `n-time-picker` 新增 `on-confirm` 属性\n- `n-time-picker` 新增 `on-clear` 属性\n- `n-time-picker` 新增 `on-update:show` 属性\n- `n-time-picker` 新增 `show` 属性\n- `n-date-picker` 新增 `on-update:show` 属性\n- `n-date-picker` 新增 `show` 属性\n- `n-date-picker` 新增 `default-calendar-start-time` 属性，关闭 [#2732](https://github.com/tusen-ai/naive-ui/issues/2732)\n- `n-date-picker` 新增 `default-calendar-end-time` 属性，关闭 [#2732](https://github.com/tusen-ai/naive-ui/issues/2732)\n- `n-date-picker` 新增 `bind-calendar-months` 属性，关闭 [#2751](https://github.com/tusen-ai/naive-ui/issues/2751)\n- `n-upload` 新增 `directory` 属性\n- `n-upload` 新增 `directory-dnd` 属性\n- `UploadFileInfo` 新增 `fullPath` 和 `batchId` 属性\n- `DataTableBaseColumn` 新增 `tree` 属性，关闭 [#2757](https://github.com/tusen-ai/naive-ui/issues/2757)\n\n## 2.28.2\n\n`2022-04-22`\n\n### Fixes\n\n- 修复 `date-picker` `actions` 的类型不能为 `null`\n- 修复 `time-picker` `actions` 的类型不能为 `null`\n- 修复 `n-tree-select` 的无意义 warning\n- 修复 `n-tree-select` 的 `allow-checking-not-loaded` 属性不生效\n- 修复 `n-tree-select` 在 `:allow-checking-not-loaded=\"true\"` 的情况下菜单可能和选框位置不同步\n- 修复 `n-cascader` 在 `:allow-checking-not-loaded=\"true\"` 的情况下菜单可能和选框位置不同步\n\n## 2.28.1\n\n`2022-04-20`\n\n### Fixes\n\n- 修复 `notification` 在 SSR 模式下第一个之后的 icon 都不会展示，关闭 [#2793](https://github.com/tusen-ai/naive-ui/issues/2793)\n- 修复 `dialog` 在 SSR 模式下第一个之后的 icon 都不会展示\n- 修复 `n-drawer` 和 `n-modal` 在 `:autofocus=\"true\"` 情况下打开时可能溢出屏幕\n- 修复 `n-tree-select` 在使用 `children-field` 时过滤器不生效，关闭 [#2789](https://github.com/tusen-ai/naive-ui/issues/2789)\n- 修复 `n-tree-select` 清空搜索值时搜索命中样式未更新\n- 修复 `n-tree-select` 在 `check-strategy=\"child\"` 和 `:cascade=\"false\"` 时非叶节点依然可以被选择，关闭 [#2780](https://github.com/tusen-ai/naive-ui/issues/2780)\n- 修复 `n-select` 的 `empty` slot 中 `n-input` 无法聚焦，关闭 [#2812](https://github.com/tusen-ai/naive-ui/issues/2812)\n- 修复 `n-select` 菜单在全屏模式下不可见，关闭 [#2722](https://github.com/tusen-ai/naive-ui/issues/2722)\n- 修复 `n-color-picker` 的 `value` 属性类型不能为 `null`\n- 修复 `n-table` 在不同属性切换时边框颜色突变\n\n### Feats\n\n- `n-input-number` 新增 `add-icon` 和 `minus-icon` 插槽，关闭 [#2668](https://github.com/tusen-ai/naive-ui/issues/2668)\n- `n-dynamic-input` 添加 `RTL` 支持\n- `n-table` 添加 `RTL` 支持\n- `n-collapse-transition` 添加 `RTL` 支持\n- `n-tree` 新增 `show-irrelevant-nodes` 属性，关闭 [#2764](https://github.com/tusen-ai/naive-ui/issues/2764)\n- `n-tree-select` 新增 `allow-checking-not-loaded` 属性\n- `n-cascader` 新增 `allow-checking-not-loaded` 属性\n- `n-tree` 新增 `allow-checking-not-loaded` 属性\n- `n-button-group` 添加 `RTL` 支持\n\n### i18n\n\n- 新增 ptBR locale\n- 新增 koKR locale\n\n## 2.28.0\n\n`2022-04-11`\n\n### Breaking Changes\n\n- `n-time` 使用 `date-fns` 的 `formatDistanceStrict` 代替 `formatDistance`，关闭 [#2703](https://github.com/tusen-ai/naive-ui/issues/2703)\n\n### Fixes\n\n- 修复 `n-tabs` 中嵌套 `n-tabs`，内部的线条会有一次多余的动画，关闭 [#2689](https://github.com/tusen-ai/naive-ui/issues/2689)\n- 修复 `n-popconfirm` body 没有内容时外边距的异常，关闭 [#2690](https://github.com/tusen-ai/naive-ui/issues/2690)\n- 修复 `n-tree-select` 无意义 warning\n- 修复 `n-calendar` 的禁用单元格可以被点击，关闭 [#2686](https://github.com/tusen-ai/naive-ui/issues/2686)\n- 修复 message 在 SSR 模式下第一个之后的 icon 都不会展示，关闭 [#2721](https://github.com/tusen-ai/naive-ui/issues/2721)\n- 修复 `n-popconfirm` 的 `positive-button-props` 和 `negative-button-props` 属性缺乏响应式，关闭 [#2753](https://github.com/tusen-ai/naive-ui/issues/2753)\n- 修复 `n-step` 有多余的主题变量类名\n- 修复 `n-steps` 垂直水平相互嵌套样式错乱\n- 修复 `n-popconfirm` 的 `positive-text` & `negetive-text` 不允许 `null` 类型\n- 修复 `n-color-picker` 的面板关闭会被 `mousedown.stop` 阻止，关闭 [#2709](https://github.com/tusen-ai/naive-ui/issues/2709)\n- 修复 `n-tabs` 切换动画在 `display-directive='show'` 的时候不正常，关闭 [#2718](https://github.com/tusen-ai/naive-ui/issues/2718)\n\n### Feats\n\n- `n-radio` 新增 `label` 属性，关闭 [#2707](https://github.com/tusen-ai/naive-ui/issues/2707)\n- `n-drawer` 新增 `on-after-enter` 和 `on-after-leave` 属性，关闭 [#2698](https://github.com/tusen-ai/naive-ui/issues/2698)\n- `n-date-table` 新增 `paginate-single-page` 属性，关闭 [#2043](https://github.com/tusen-ai/naive-ui/issues/2043)\n- `n-pagination` 添加 `RTL` 支持\n- `n-alert` 添加 `RTL` 支持\n- `n-data-table` 新增 `allow-checking-not-loaded` 属性，关闭 [#2758](https://github.com/tusen-ai/naive-ui/issues/2758)\n\n## 2.27.0\n\n`2022-03-27`\n\n### Breaking Changes\n\n- `n-menu` 进行了一些样式改动\n\n### Fixes\n\n- 修复 `n-data-table` 使用 `expand` 类型时，行错乱的问题，关闭 [#2631](https://github.com/tusen-ai/naive-ui/issues/2631)\n- 修复 `n-popconfirm` 缺少 `setShow` 和 `syncPosition` 方法\n- 修复 `n-popselect` 缺少 `setShow` 和 `syncPosition` 方法\n- 修复 `n-menu` 主题 peers 缺少 `Dropdown`\n- 修复 `n-color-picker` 不能输入 0 作为单位的值，关闭 [#2680](https://github.com/tusen-ai/naive-ui/issues/2680)\n- 修复 `n-tree` 在使用虚拟滚动时滚动条长度存在问题，关闭 [#2673](https://github.com/tusen-ai/naive-ui/issues/2673)\n- 修复 `n-layout-sider` 的 `content-style` 不能覆盖 `overflow: auto` 属性，关闭 [#2671](https://github.com/tusen-ai/naive-ui/issues/2671)\n- 修复 `n-date-picker` 在 `month` 和 `quarter` 模式下暗黑模式的 disabled 的面板时间显示有问题\n- 修复 `n-dropdown` `onUpdateShow` 不生效\n- 修复 `n-auto-complete` `onSelect` 在 `onUpdate:value` 后被触发\n- 修复 `n-data-table` `onUpdate:filters` 的类型中 `initiatorColumn` 是可选选参数\n\n### Feats\n\n- `n-tree-select` 新增 `on-load` 属性，关闭 [#2550](https://github.com/tusen-ai/naive-ui/issues/2550)\n- `n-data-table` 新增 `on-load` 属性\n- `n-cascader` 添加 `menu-props` 属性，关闭 [#2600](https://github.com/tusen-ai/naive-ui/issues/2600)\n- `n-cascader` 添加 `filter-menu-props` 属性，关闭 [#2600](https://github.com/tusen-ai/naive-ui/issues/2600)\n- `n-badge` 新增 `value` slot\n- `n-form` 新增 `validate-messages` 属性\n- `n-data-table` 的 column 支持 `cellProps` 属性，关闭 [#2625](https://github.com/tusen-ai/naive-ui/issues/2625)\n- `n-step` 增加类名用于区分状态\n- `n-popconfirm` 新增 `negative-button-props` 属性，关闭 [#2642](https://github.com/tusen-ai/naive-ui/issues/2642)\n- `n-popconfirm` 新增 `positive-button-props` 属性，关闭 [#2642](https://github.com/tusen-ai/naive-ui/issues/2642)\n- `n-pagination` 新增 `goto` slot\n- `n-input` 新增 `password-visible-icon` slot\n- `n-input` 新增 `password-invisible-icon` slot\n- `n-select` 新增 `status` 属性\n- `n-input-number` 新增 `status` 属性\n- `n-auto-complete` 新增 `status` 属性\n- `n-cascader` 新增 `status` 属性\n- `n-date-picker` 新增 `status` 属性\n- `n-time-picker` 新增 `status` 属性\n- `n-mention` 新增 `status` 属性\n- `n-tree-select` 新增 `status` 属性\n- `n-menu` 新增 `showOption` 方法，关闭 [#2562](https://github.com/tusen-ai/naive-ui/issues/2562)\n- `n-dynamic-tags` 的 `value` 属性支持对象类型的选项\n- `n-dynamic-tags` 新增 `render-tag` 属性，关闭 [#2526](https://github.com/tusen-ai/naive-ui/issues/2526)\n- `n-dynamic-tags` 新增 `on-create` 属性，关闭 [#2576](https://github.com/tusen-ai/naive-ui/issues/2576)\n- `n-date-picker` 新增 `time-picker-props` 属性，关闭 [#2660](https://github.com/tusen-ai/naive-ui/issues/2660)\n- `n-tabs` 新增 `trigger` 属性，关闭 [#2679](https://github.com/tusen-ai/naive-ui/issues/2679)\n- `n-menu` 新增 `itemColorHover`, `itemColorActiveHover`, `itemTextColorActiveHover`, `itemTextColorHorizontal`, `itemTextColorHoverHorizontal`, `itemTextColorActiveHorizontal`, `itemTextColorActiveHoverHorizontal`, `itemTextColorChildActiveHorizontal`, `itemIconColorActiveHover`, `itemIconColorHorizontal`, `itemIconColorHoverHorizontal`, `itemIconColorActiveHorizontal`, `itemIconColorActiveHoverHorizontal`, `itemIconColorChildActiveHorizontal`, `arrowColorActiveHover`, `itemColorHoverInverted`, `itemColorActiveHoverInverted`, `itemTextColorActiveHoverInverted`, `itemTextColorHorizontalInverted`, `itemTextColorHoverHorizontalInverted`, `itemTextColorChildActiveHorizontalInverted`, `itemTextColorActiveHorizontalInverted`, `itemTextColorActiveHoverHorizontalInverted`, `itemIconColorActiveHoverInverted`, `itemIconColorHorizontalInverted`, `itemIconColorHoverHorizontalInverted`, `itemIconColorActiveHorizontalInverted`, `itemIconColorActiveHoverHorizontalInverted`, `itemIconColorChildActiveHorizontalInverted`, `arrowColorActiveHoverInverted` 主题变量，关闭 [#2598](https://github.com/tusen-ai/naive-ui/issues/2598)\n- `n-carousel` 新增 `next-slide-style` 和 `prev-slide-style` 属性，关闭 [#2340](https://github.com/tusen-ai/naive-ui/issues/2340)\n- `n-dialog` 新增 `negative-button-props` 属性\n- `n-dialog` 新增 `positive-button-props` 属性\n- `n-tabs` 新增 `animated` 属性\n\n### i18n\n\n- 新增 thTH locale.\n\n## 2.26.4\n\n`2022-03-11`\n\n### Fixes\n\n- 修复 `n-tree-select` 在 multiple 模式下不能删除 default-value 属性包含父节点的选项，关闭 [#2605](https://github.com/tusen-ai/naive-ui/issues/2605)\n- 修复 `n-tree` 在移除节点时可能抛出异常，关闭 [#2597](https://github.com/tusen-ai/naive-ui/issues/2597)\n- 修复 `useDialog` 中使用带有弹出层的元素有异常的焦点管理行为，关闭 [#2612](https://github.com/tusen-ai/naive-ui/issues/2612)\n- 修复 `n-tree-select` 当 `check-strategy` 为 `'child'` 时有的节点不能被点击\n- 修复 `n-tree-select` 在 `check-strategy` 不为 `'all'` 的时候从选框中删除时发出的值可能和 `check-strategy` 不对应\n\n### Feats\n\n- `useDialog` 支持 `closeOnEsc` 属性\n- `n-data-table` 导出 `DataTableFilterState` 类型\n- `n-data-table` 导出 `DataTableSortState` 类型\n\n## 2.26.3\n\n`2022-03-09`\n\n### Fixes\n\n- 修复 `n-button` loading 图标漂移\n\n## 2.26.2\n\n`2022-03-09`\n\n### Fixes\n\n- 修复 `n-cascader` 节点箭头 loading 显示过久\n- 修复 `n-select` 菜单不随主题变化\n- 修复 `n-tabs` 不能没有子节点，关闭 [#809](https://github.com/tusen-ai/naive-ui/issues/809)\n- 修复 `n-menu` 切换主题时在 chrome 99 内字体颜色异常，关闭 [#2563](https://github.com/tusen-ai/naive-ui/issues/2563)，这实际上是一个 chrome 的问题，我们进行了临时的修复\n- 修复 `n-date-picker` 仅 `'date'` 类型的扩大日期点击触发范围\n\n### Feats\n\n- `n-dynamic-tags` 的 `input` slot 新增 `deactivate` 属性，关闭 [#2575](https://github.com/tusen-ai/naive-ui/issues/2575)\n- `n-space` 添加 `RTL` 支持\n- `n-avatar-group` 添加 `RTL` 支持\n- `n-badge` 添加 `RTL` 支持\n- `n-radio` 添加 `RTL` 支持\n- `n-auto-complete` 新增 `focus` 方法\n- `n-auto-complete` 新增 `blur` 方法\n\n## 2.26.1\n\n`2022-03-06`\n\n### Fixes\n\n- 修复 `base-loading` 动画会被 js 堵塞，关闭 [#2506](https://github.com/tusen-ai/naive-ui/issues/2506)\n- 修复 `n-time` 由于无法导入 `getTimezoneOffset` 报错的问题，关闭 [#2545](https://github.com/tusen-ai/naive-ui/issues/2545)\n- 修复 `n-modal` 遮罩出现没有动画\n- 修复 `n-timeline` 在水平和非水平嵌套时的样式冲突，关闭 [#2549](https://github.com/tusen-ai/naive-ui/issues/2549)\n- 修复 `n-tree` 箭头和 loading 切换时动画不完整\n\n### Feats\n\n- `n-time-line-item` 新增 `line-type` 属性，关闭 [#2548](https://github.com/tusen-ai/naive-ui/issues/2548)\n- `n-step` 新增 `icon` slot，关闭 [#2547](https://github.com/tusen-ai/naive-ui/issues/2547)\n- `n-input-number` 新增 `autofocus` 属性，关闭 [#2551](https://github.com/tusen-ai/naive-ui/issues/2551)\n- `n-date-picker` 扩大日期点击触发范围，关闭 [#2552](https://github.com/tusen-ai/naive-ui/issues/2552)\n\n## 2.26.0\n\n`2022-03-02`\n\n### Breaking Changes\n\n- 修复 `n-tooltip` 箭头和主体之间的间隙，`n-tooltip` 不再能使用半透明的颜色\n\n### Feats\n\n- `n-popover` 新增 `arrow-point-to-center` 属性\n- `n-config-provider` 新增 `inline-theme-disabled` 属性\n\n## 2.25.8\n\n`2022-03-01`\n\n### Fixes\n\n- 修复 `useMessage` 丢失样式\n\n## 2.25.7\n\n`2022-03-01`\n\n### Fixes\n\n- 修复 `n-time-picker` 在 `\"actions=\"null\"` 时依然显示操作栏\n- 修复 `n-input` 在 `type=\"text\"` 并且 `autosize` 被设定时文字内容可能溢出，关闭 [#2505](https://github.com/tusen-ai/naive-ui/issues/2505)\n- 修复 `n-upload` 将 `file` 字段放于其他 `FormData` 字段之前，关闭 [#2504](https://github.com/tusen-ai/naive-ui/issues/2504)\n- 修复 `n-button` rtl 支持\n- 修复 `n-form-item-row` 不能调用 `n-form-item` 的方法\n\n### Feats\n\n- `n-collapse` 添加 `RTL` 支持\n- `useMessage` 新增 `create` 方法\n- `useMessage` 新增 `showIcon` 属性，关闭 [#2495](https://github.com/tusen-ai/naive-ui/issues/2495)\n- `useMessage` 支持 `'default'` 的 `type`\n- `n-checkbox` 支持内容折行，关闭 [#2419](https://github.com/tusen-ai/naive-ui/issues/2419)\n- `n-radio` 支持内容折行，关闭 [#2419](https://github.com/tusen-ai/naive-ui/issues/2419)\n- `n-checkbox` 添加 `RTL` 支持\n- `n-input` 添加 `RTL` 支持\n- `n-input-number` 添加 `RTL` 支持\n\n## 2.25.5\n\n`2022-02-24`\n\n### Fixes\n\n- 修复 `n-col` 在 `span=6` 时不能正确的换行，关闭 [#2497](https://github.com/tusen-ai/naive-ui/issues/2497)\n- 修复 `n-tabs` 在内容过多时底部边框在滚动区域不显示，关闭 [#2500](https://github.com/tusen-ai/naive-ui/issues/2500)\n\n## 2.25.3\n\n`2022-02-23`\n\n### Fixes\n\n- 修复 `n-switch` 在自定义选中值的时候无法使用键盘操作\n- 修复 `n-data-table` 放在 popover 内使用固定列滚动内容覆盖\n- 修复 `n-data-table` 当 `filterOptions` 值为 0 时过滤不生效，关闭 [#2392](https://github.com/tusen-ai/naive-ui/issues/2392)\n- 修复 `n-data-table` 当 selection column 为某个 column 的子 column 时无法点击全选复选框\n- 修复 `n-table` 动态增加时 `border-color` 的样式异常，关闭 [#2403](https://github.com/tusen-ai/naive-ui/issues/2403)\n- 修复 `n-tree` 的 `default-expand-all` 对于动态数据不生效\n- 修复 `n-form` 当 `model.xxx` 为 `undefined` 的时候会使用 `null` 作为验证值，关闭 [#2486](https://github.com/tusen-ai/naive-ui/issues/2486)\n- 修复 `n-input` focus 样式优先级低于 hover，关闭 [#2480](https://github.com/tusen-ai/naive-ui/issues/2480)\n- 修复 `n-data-table` 在使用 keep-alive 组件中使用虚拟滚动的显示问题，关闭 [#2183](https://github.com/tusen-ai/naive-ui/issues/2183)\n- 修复 `notification` 出现的动画\n\n### Feats\n\n- `n-tree-select` 新增 `clear-filter-after-select` 属性\n- `n-cascader` 新增 `clear-filter-after-select` 属性\n- `n-switch` 新增 `icon` 插槽\n- `n-switch` 新增 `checked-icon` 插槽\n- `n-switch` 新增 `unchecked-icon` 插槽\n- `n-tabs` 的 CSS 变量使用 `n` 作为前缀\n- 新增 `n-watermark` 组件，关闭 [#1745](https://github.com/tusen-ai/naive-ui/issues/1745)\n- `n-scrollbar` 新增 `scrollBy` 方法，关闭 [#2435](https://github.com/tusen-ai/naive-ui/issues/2435)\n- `n-data-table` 的 `summary` 属性的 value 值支持 `VNodeChild`，关闭 [#2339](https://github.com/tusen-ai/naive-ui/issues/2339)\n- `n-input-number` 可以使用长按来改变值，关闭 [#1293](https://github.com/tusen-ai/naive-ui/issues/1293)\n- `n-description` 新增 `titleTextColor` 主题变量\n\n### i18n\n\n- 新增 skSK locale\n- 完善 frFR locale\n\n## 2.25.2\n\n`2022-02-11`\n\n### Fixes\n\n- 移除 `resolveSlot` 中无用的 `console.log`\n- 修复 `n-tag` 在 `checkable=true` 时缺少背景色\n- 修复 `n-tree` 在 `happydom` 测试环境下由于 `Image` 对象报错\n- 修复 `n-select` `max-tag-count` 标签尺寸和 `n-select` size 不同\n\n### Feats\n\n- `n-progress` 的 `type` 属性新增 `dashboard` 类型\n- `n-progress` 新增 `gap-degree` 属性\n- `n-progress` 新增 `gap-offset-degree` 属性\n- `n-select` 新增 `clear-filter-after-select` 属性，关闭 [#2352](https://github.com/tusen-ai/naive-ui/issues/2352)\n\n### i18n\n\n- 新增 plPL locale，关闭 [#2354](https://github.com/tusen-ai/naive-ui/issues/2354)\n- 新增 eo locale\n\n## 2.25.1\n\n`2022-02-06`\n\n### i18n\n\n- 新增 enGB locale\n- 完善 deDE locale\n\n## 2.25.0\n\n`2022-02-04`\n\n### Breaking Changes\n\n- 重构了 `n-carousel` 带箭头时的样式\n\n### Fixes\n\n- 修复 `n-color-picker` 色阶和不透明度调整滑块 box-shadow 被轨道 box-shadow 影响\n- 修复 `n-form-item` feedback DOM 内容为空依然有 padding\n- 修复 `n-button` 在 safari 下显示有多余 margin\n- 修复 `n-form` 的 rules 和 `n-form-item` 的 rule 中的 `validator` 与 `asyncValidator` 函数的 `rule` 类型不为 `FormItemRule` 类型， 关闭 [#2299](https://github.com/tusen-ai/naive-ui/issues/2299)\n- 修复 `n-log` 在内容过长时不折行，关闭 [#2298](https://github.com/tusen-ai/naive-ui/issues/2298)\n- 修复 `n-log` 未导出 `LogInst` 类型\n- 修复 `n-popselect` action slot & empty slot 不生效\n- 修复 `n-data-table` 不能使用百分比列宽\n- 修复 `n-select` 在可过滤，关闭菜单并且没有选中任何值的时候选框会空一下\n- 修复 `n-select` 在动态创建选项时关闭菜单后创建中的选项未清空\n- 修复 `n-select` 在 `show=false` 和 `filterable=true` 时无法输入内容，关闭 [#1723](https://github.com/tusen-ai/naive-ui/issues/1723)\n- 修复 `n-dropdown` 在 `trigger=\"manual\"` 时有额外 margin\n- 修复 `web-types.json` 中 `n-h1` ~ `n-h6` 的名称\n- 修复 `n-select` 在输入法激活时按退格键会删除选项\n- 修复 `n-select` 在特定情况下打开菜单后会将禁用的选项作为待选选项\n\n### Feats\n\n- `n-tabs` 的 `justify-content` 新增类型 `start` `center` `end`\n- `n-auto-complete` 新增 `placement` 属性\n- `n-cascader` 新增 `placement` 属性\n- `n-color-picker` 新增 `placement` 属性\n- `n-date-picker` 新增 `placement` 属性\n- `n-mention` 新增 `placement` 属性\n- `n-select` 新增 `placement` 属性\n- `n-slider` 新增 `placement` 属性\n- `n-time-picker` 新增 `placement` 属性\n- `n-tree-select` 新增 `placement` 属性\n- `n-card` 新增 `header-extra-style` 属性\n- `n-popover` 新增 `keep-alive-on-hover` 属性，关闭 [#2326](https://github.com/tusen-ai/naive-ui/issues/2326)\n- `n-input` 新增 `status` 属性\n- 新增 `n-icon-wrapper` 组件\n- `n-popover` 导出 `PopoverPlacement` 类型\n- `n-drawer` 导出 `DrawerPlacement` 类型\n- `n-dynamic-tags` 新增 `input-props` 属性\n- `n-notification-provider` 新增 `container-style` 属性\n- `n-notification-provider` 导出 `NotificationPlacement` 类型\n- `n-notification-provider` 导出 `NotificationType` 类型\n- `n-tabs` 新增 `bar-width` 属性\n- `n-dynamic-input` 新增 `create-button-props` 属性\n- `n-dynamic-input` 新增 `create-button-default` slot\n- `n-dynamic-input` 新增 `create-button-icon` slot\n- `n-dynamic-input` 新增 `show-sort-button` 属性，关闭 [#2121](https://github.com/tusen-ai/naive-ui/issues/2121)\n- `n-select` 可以作为标签输入框使用\n- `n-select` 导出 `SelectRenderLabel` 类型\n- `n-select` 导出 `SelectRenderOption` 类型\n- `n-select` 导出 `SelectRenderTag` 类型\n- `n-tree` 新增 `node-props` 属性\n\n## 2.24.7\n\n`2022-01-28`\n\n### Fixes\n\n- `n-popselect` 设定 `width=\"trigger\"` 不生效\n\n### i18n\n\n- 更新 jaJP locale\n- 更新 deDE locale\n\n## 2.24.6\n\n`2022-01-26`\n\n### Feats\n\n- `n-icon` 新增 `component` 属性\n\n### Fixes\n\n- 修复 `n-dynamic-input` 当 max 为 0 时可以添加子项， 关闭 [#2271](https://github.com/tusen-ai/naive-ui/issues/2271)\n- 修复 `n-dialog` 有无用的 `console.log`\n\n## 2.24.5\n\n`2022-01-25`\n\n### Fixes\n\n- `n-input` 在类型为 `textarea` 时 placeholder 无法换行\n- `n-date-picker` 面板年和月之前缺少空格\n\n### Feats\n\n- `n-color-picker` 新增 `disabled` 属性\n- `n-date-picker` 快速跳转面板增加触发背景区域\n\n## 2.24.4\n\n`2022-01-24`\n\n### Fixes\n\n- 更新 vueuc 版本\n\n## 2.24.3\n\n`2022-01-24`\n\n### Fixes\n\n- 修复 `n-layout-sider` 边框没有 transition\n\n## 2.24.2\n\n`2022-01-24`\n\n### Fixes\n\n- 修复 `n-layout-sider` 在折叠时仍占据 1px 宽度\n- 修复 `n-code` 在 `word-wrap=true` 时不切分单词\n- 修复 `n-tab-pane` 的 tab 区会继承 `attrs`， 关闭 [#2221](https://github.com/tusen-ai/naive-ui/issues/2221)\n- 修复 `n-image` 在预览时仍可滚动背景，关闭 [#2241](https://github.com/tusen-ai/naive-ui/issues/2241)\n- 修复 `n-input` 在被浏览器自动填充的时候仍然展示 placeholder，关闭 [#2234](https://github.com/tusen-ai/naive-ui/issues/2234)\n- 修复 `n-input` 在 `type=\"textarea\"` 时 placeholder 换行问题\n- 修复 `n-avatar-group` 超出 max 之后显示少一人，关闭 [#2244](https://github.com/tusen-ai/naive-ui/issues/2244)\n- 修复 `n-calendar` 再点击今天按钮后不触发 `on-panel-change`\n- 修复 `n-drawer` 在设定 `mask-closable=false` 时无法被 esc 键关闭，关闭 [#2233](https://github.com/tusen-ai/naive-ui/issues/2233)\n\n### Feats\n\n- `n-page-header` 新增 `back` 插槽，关闭 [#2176](https://github.com/tusen-ai/naive-ui/issues/2176)\n- `n-select` 新增 `reset-menu-on-options-change` 属性，关闭 [#2168](https://github.com/tusen-ai/naive-ui/issues/2168)\n- `n-select` 新增 `arrow` 插槽，关闭 [#2201](https://github.com/tusen-ai/naive-ui/issues/2201)\n- `n-carousel` `effect` 属性支持 `'card'`\n- `n-input` 在 `type=\"textarea\"` 不再使用原生滚动条，关闭 [#2242](https://github.com/tusen-ai/naive-ui/issues/2242)，关闭 [#1172](https://github.com/tusen-ai/naive-ui/issues/1172)\n- `n-number-animation` 新增 `locale` 属性，用于设置国际化语言，关闭 [#2181](https://github.com/tusen-ai/naive-ui/issues/2181)\n- `n-number-animation` 跟随 config provider 国际化\n- 导出 `lightTheme`\n- `n-time-picker` 新增 `icon` 插槽，关闭 [#2228](https://github.com/tusen-ai/naive-ui/issues/2228)\n- `n-tab-pane` 新增 `tab-props` 属性，关闭 [#2221](https://github.com/tusen-ai/naive-ui/issues/2221)\n- 新增 `CustomThemeCommonVars` 用于拓展 `useThemeVars`\n- `n-slider` 新增 `show-tooltip` 属性，关闭 [#2212](https://github.com/tusen-ai/naive-ui/issues/2212)\n- `n-select` 新增 `on-update:show` 属性\n- `n-select` 新增 `focus` 方法，关闭 [#2202](https://github.com/tusen-ai/naive-ui/issues/2202)\n- `n-select` 新增 `blur` 方法，关闭 [#2202](https://github.com/tusen-ai/naive-ui/issues/2202)\n- `n-date-picker` 新增 `focus` 方法，关闭 [#2202](https://github.com/tusen-ai/naive-ui/issues/2202)\n- `n-date-picker` 新增 `blur` 方法，关闭 [#2202](https://github.com/tusen-ai/naive-ui/issues/2202)\n- `n-time-picker` 新增 `focus` 方法，关闭 [#2202](https://github.com/tusen-ai/naive-ui/issues/2202)\n- `n-time-picker` 新增 `blur` 方法，关闭 [#2202](https://github.com/tusen-ai/naive-ui/issues/2202)\n- `n-checkbox` 新增 `focus` 方法，关闭 [#2202](https://github.com/tusen-ai/naive-ui/issues/2202)\n- `n-checkbox` 新增 `blur` 方法，关闭 [#2202](https://github.com/tusen-ai/naive-ui/issues/2202)\n- `n-cascader` 新增 `focus` 方法，关闭 [#2202](https://github.com/tusen-ai/naive-ui/issues/2202)\n- `n-cascader` 新增 `blur` 方法，关闭 [#2202](https://github.com/tusen-ai/naive-ui/issues/2202)\n- `n-upload` 新增 `input-props` 属性，关闭 [#2204](https://github.com/tusen-ai/naive-ui/issues/2204)\n- `n-data-table` 列增加 `render-sorter-icon` 属性，关闭 [#1785](https://github.com/tusen-ai/naive-ui/issues/1785)\n- `n-data-table` 列增加 `render-sorter` 属性，关闭 [#1785](https://github.com/tusen-ai/naive-ui/issues/1785)\n- `n-date-picker` 在 `date`、`datetime`、`daterange`、`datetimerange` 类型下可以快速导航到特定的年和月\n- `n-modal` 新增 `close-on-esc` 属性\n- `n-modal` 新增 `auto-focus` 属性\n- `n-modal` 新增 `trap-focus` 属性\n- `n-modal` 新增 `on-esc` 属性\n- `n-drawer` 新增 `close-on-esc` 属性\n- `n-drawer` 新增 `auto-focus` 属性\n- `n-drawer` 新增 `trap-focus` 属性\n- `n-drawer` 新增 `on-esc` 属性\n- `n-upload` 新增 `clear` 方法，关闭 [#2247](https://github.com/tusen-ai/naive-ui/issues/2247)\n\n### i18n\n\n- 新增 esAR locale\n- 新增 itIT locale\n\n## 2.24.1\n\n`2022-01-12`\n\n### Fixes\n\n- 修复安装错误\n\n## 2.24.0\n\n`2022-01-12`\n\n### Breaking Changes\n\n- 修复 `type PageHeaderProps` 命名，原先错拼为 `PageHeaderPorps`\n- `n-image` 主题变量的 `iconColor` 重命名为 `toolbarIconColor`\n\n### Fixes\n\n- 修复 `n-carousel` 只有一张图片仍显示 `dot` 的问题，关闭 [#1777](https://github.com/tusen-ai/naive-ui/issues/1777)\n- 修复 `n-upload` `on-finish` 回调中 `event` 的类型应为 `ProgressEvent`\n- 修复 `n-upload` 不允许 200 之外的 2xx 响应状态码\n- 修复 `n-form` 当 `validate` 使用了 `validateCallback` 时调用 Promise 方法无效\n- 修复 `n-input-number` 输入以 0 结尾的整数不更新，关闭 [#2115](https://github.com/tusen-ai/naive-ui/issues/2115)\n- 修复 `n-back-top` 允许 `listen-to` 为 `document`\n- 修复 `n-data-table` 在 loading 时可以点击内容，关闭 [#2134](https://github.com/tusen-ai/naive-ui/issues/2134)\n- 修复 `n-checkbox` 在 safari 显示 indeterminate 图标\n- 修复 `n-progress` `line` 类型的进度条中的文字未居中，关闭 [#2138](https://github.com/tusen-ai/naive-ui/issues/2138)\n- 修复 `n-message` 的 `MessageReactive` 类型缺少 `type` 参数\n- 修复 `n-select` 与 `n-input` `padding` 不一致，关闭 [#2149](https://github.com/tusen-ai/naive-ui/issues/2149)\n- 修复 `n-tooltip` 用于 `n-select` `render-option` 时控制台报错，关闭 [#1436](https://github.com/tusen-ai/naive-ui/issues/1436)\n- 修复 `n-select` 在 safari 中使用 `render-option` 时 ResizeObserver 报错，关闭 [#1671](https://github.com/tusen-ai/naive-ui/issues/1671)\n- 修复 `n-carousel` 无法快速响应多次滑动，关闭 [#1892](https://github.com/tusen-ai/naive-ui/issues/1892)\n- 修复 `n-carousel` 边界样式，关闭 [#1866](https://github.com/tusen-ai/naive-ui/issues/1866)\n- 修复 `n-carousel` 触屏下轮播内容无法点击问题，关闭 [#1882](https://github.com/tusen-ai/naive-ui/issues/1882)\n- 修复 `n-color-picker` 在空值的情况下默认模式只能为 rgb\n\n### Feats\n\n- `n-code` 新增 `word-wrap` 属性，关闭 [#2111](https://github.com/tusen-ai/naive-ui/issues/2111)\n- `n-modal` 新增 `z-index` 属性，关闭 [#2088](https://github.com/tusen-ai/naive-ui/issues/2088)\n- `n-drawer` 新增 `z-index` 属性\n- `n-drawer` 新增 wai-aria 支持\n- `useMessage` 新增 `render` 选项\n- `n-data-table` `TableColumn` 支持 `string` 类型的 `width`，关闭 [#2102](https://github.com/tusen-ai/naive-ui/issues/2102)\n- `n-calendar` 新增 `on-panel-change` 属性，关闭 [#2082](https://github.com/tusen-ai/naive-ui/issues/2082)\n- `n-upload` 新增 `on-error` 属性\n- `n-pagination` 新增 `label` 插槽\n- `n-tabs` 新增 `syncBarPosition` 方法，关闭 [#2120](https://github.com/tusen-ai/naive-ui/issues/2120)\n- `n-form`、`n-form-item` 的 `label-width` 选项支持 `auto` 属性，关闭 [#2087](https://github.com/tusen-ai/naive-ui/issues/2087)\n- `n-result` 新增 `icon` 插槽，关闭 [#2130](https://github.com/tusen-ai/naive-ui/issues/2130)\n- `n-date-picker` 新增 `value-format` 属性，关闭 [#2076](https://github.com/tusen-ai/naive-ui/issues/2076)\n- `n-date-picker` 新增 `formatted-value` 属性\n- `n-date-picker` 新增 `default-formatted-value` 属性\n- `n-date-picker` 新增 `on-update:formatted-value` 属性\n- `n-date-picker` `on-update:value` 属性会传出格式化后的值\n- `n-image` 新增 `show-toolbar-tooltip` 属性\n- `n-image` 新增更多主题变量，关闭 [#1531](https://github.com/tusen-ai/naive-ui/issues/1531)\n- `n-upload` 新增 `image-group-props` 属性\n- `n-progress` 新增 `offset-degree` 属性，关闭 [#2010](https://github.com/tusen-ai/naive-ui/issues/2010)\n- `n-form-item` 新增 `feedback` 插槽，关闭 [#1142](https://github.com/tusen-ai/naive-ui/issues/1142)\n- `n-form-item` `require-mark-placement` 新增 `'right-hanging'` 选项，关闭 [#2094](https://github.com/tusen-ai/naive-ui/issues/2094)\n- `n-cascader` 新增 `render-label` 属性，关闭 [#2048](https://github.com/tusen-ai/naive-ui/issues/2048)\n- `n-auto-complete` 新增 `render-option` 属性，关闭 [#1629](https://github.com/tusen-ai/naive-ui/issues/1629)\n- `n-auto-complete` 新增 `render-label` 属性，关闭 [#1629](https://github.com/tusen-ai/naive-ui/issues/1629)\n- `n-tree` 新增 `render-switcher-icon` 属性，关闭 [#1551](https://github.com/tusen-ai/naive-ui/issues/1551)\n- `n-message` 导出 `MessageType` 类型\n- `n-time-picker` 新增 `value-format` 属性\n- `n-time-picker` 新增 `formatted-value` 属性\n- `n-time-picker` 新增 `on-update:formatted-value` 属性\n- `n-time-picker` 新增 `default-formatted-value` 属性\n- `n-carousel` 新增 `default-index` 属性\n- `n-carousel` 新增 `current-index` 属性\n- `n-carousel` 新增 `show-arrow` 属性\n- `n-carousel` 新增 `dot-type` 属性，关闭 [#1931](https://github.com/tusen-ai/naive-ui/issues/1931)\n- `n-carousel` 新增 `dot-placement` 属性，关闭 [#1462](https://github.com/tusen-ai/naive-ui/issues/1462)\n- `n-carousel` 新增 `slides-per-view` 属性\n- `n-carousel` 新增 `space-between` 属性\n- `n-carousel` 新增 `centered-slides` 属性\n- `n-carousel` 新增 `direction` 属性，关闭 [#1931](https://github.com/tusen-ai/naive-ui/issues/1931)\n- `n-carousel` 新增 `loop` 属性\n- `n-carousel` 新增 `effect` 属性，关闭 [#1159](https://github.com/tusen-ai/naive-ui/issues/1159)\n- `n-carousel` 新增 `transition-props` 属性，关闭 [#1159](https://github.com/tusen-ai/naive-ui/issues/1159)\n- `n-carousel` 新增 `transition-style` 属性，关闭 [#1159](https://github.com/tusen-ai/naive-ui/issues/1159)\n- `n-carousel` 新增 `draggable` 属性\n- `n-carousel` 新增 `touchable` 属性\n- `n-carousel` 新增 `mousewheel` 属性\n- `n-carousel` 新增 `keyboard` 属性\n- `n-carousel` 新增 `show-dots` 属性\n- `n-carousel` 新增 `on-update:current-index` 属性\n- `n-carousel` 新增 `arrow` 插槽\n- `n-carousel` 新增 `dots` 插槽\n- `n-color-picker` 新增 `label` 插槽\n- `n-color-picker` 新增 `render-label` 属性\n- `n-form-item` 新增 `label-props` 属性\n- 新增 volar 类型支持\n\n## 2.23.2\n\n`2021-12-29`\n\n### Feats\n\n- 可以通过 `<meta name=\"naive-ui-style\" />` 控制组件样式的位置\n- `n-empty` 新增 `show-icon` 属性\n- `n-modal` 增加可访问性支持，关闭 [#1877](https://github.com/tusen-ai/naive-ui/issues/1877)\n- 新增 `n-avatar-group`\n- `n-input-number` 支持 `loading` 状态\n- 新增`n-countdown` 组件\n- 新增`n-number-animation` 组件，关闭 [#1465](https://github.com/tusen-ai/naive-ui/issues/1465)\n- `n-pagination` 在不传 itemCount 时会根据 pageSize 和 pageCount 估计一个，关闭 [#2044](https://github.com/tusen-ai/naive-ui/issues/2044)\n- `n-statistic` 新增 `tabular-nums` 属性\n- `n-cascader` 新增 `on-update:show` 属性，关闭 [#2049](https://github.com/tusen-ai/naive-ui/issues/2049)\n- `n-scrollbar` 的 CSS 变量使用 `n` 作为前缀\n- `n-popconfirm` 的 CSS 变量使用 `n` 作为前缀\n- `n-gradient-text` 的 CSS 变量使用 `n` 作为前缀\n- `n-form` 的 CSS 变量使用 `n` 作为前缀\n- `n-pagination` 的 CSS 变量使用 `n` 作为前缀\n- `n-loading-bar` 的 CSS 变量使用 `n` 作为前缀\n- `n-empty` 的 CSS 变量使用 `n` 作为前缀\n- `n-list` 的 CSS 变量使用 `n` 作为前缀\n- `n-layout` 的 CSS 变量使用 `n` 作为前缀\n- `n-message` 的 CSS 变量使用 `n` 作为前缀\n- `n-mention` 的 CSS 变量使用 `n` 作为前缀\n- `n-menu` 的 CSS 变量使用 `n` 作为前缀\n- `n-popover` 的 CSS 变量使用 `n` 作为前缀\n- `n-transfer` 的 CSS 变量使用 `n` 作为前缀\n- `n-table` 的 CSS 变量使用 `n` 作为前缀\n- `n-statistic` 的 CSS 变量使用 `n` 作为前缀\n- `n-code` 的 CSS 变量使用 `n` 作为前缀\n- `n-breadcrumb` 的 CSS 变量使用 `n` 作为前缀\n- `n-slider` 的 CSS 变量使用 `n` 作为前缀\n- `n-spin` 的 CSS 变量使用 `n` 作为前缀\n- `n-select` 的 CSS 变量使用 `n` 作为前缀\n- `n-result` 的 CSS 变量使用 `n` 作为前缀\n- `n-calendar` 的 CSS 变量使用 `n` 作为前缀\n- `n-card` 的 CSS 变量使用 `n` 作为前缀\n- `n-cascader` 的 CSS 变量使用 `n` 作为前缀\n- `n-color-picker` 的 CSS 变量使用 `n` 作为前缀\n- `n-checkbox` 的 CSS 变量使用 `n` 作为前缀\n- `n-data-table` 的 CSS 变量使用 `n` 作为前缀\n- `n-date-picker` 的 CSS 变量使用 `n` 作为前缀\n- `n-descriptions` 的 CSS 变量使用 `n` 作为前缀\n- `n-drawer` 的 CSS 变量使用 `n` 作为前缀\n- `n-dropdown` 的 CSS 变量使用 `n` 作为前缀\n- `n-rate` 的 CSS 变量使用 `n` 作为前缀\n- `n-radio` 的 CSS 变量使用 `n` 作为前缀\n- `n-progress` 的 CSS 变量使用 `n` 作为前缀\n- `n-skeleton` 的 CSS 变量使用 `n` 作为前缀\n- `n-collapse` 的 CSS 变量使用 `n` 作为前缀\n- `n-collapse-transition` 的 CSS 变量使用 `n` 作为前缀\n- `n-thing` 的 CSS 变量使用 `n` 作为前缀\n- `n-carousel` 的 CSS 变量使用 `n` 作为前缀\n- `n-page-header` 的 CSS 变量使用 `n` 作为前缀\n- `n-image` 的 CSS 变量使用 `n` 作为前缀\n- `n-input` 的 CSS 变量使用 `n` 作为前缀\n- `n-icon` 的 CSS 变量使用 `n` 作为前缀\n- `n-modal` 的 CSS 变量使用 `n` 作为前缀\n- `n-notification` 的 CSS 变量使用 `n` 作为前缀\n\n### Fixes\n\n- 修复 `n-form-item-gi` 的 `validate` 不生效，关闭 [#1901](https://github.com/tusen-ai/naive-ui/issues/1901)\n- 修复 `n-card` action 部分的 border-radius 样式\n- 修复 `n-code` 不设定 language 时内容重复添加，关闭 [#2034](https://github.com/tusen-ai/naive-ui/issues/2034)\n- 修复 `n-tabs` `tabTextColorActiveSegment` 和 `tabTextColorHoverSegment` 主题变量不生效，关闭 [#2038](https://github.com/tusen-ai/naive-ui/issues/2038)\n- 修复 `n-image` 卸载时可能未解绑键盘事件监听器\n- 修复 `n-image` 在仅有一张图片时按 esc 无法退出预览，关闭 [#2042](https://github.com/tusen-ai/naive-ui/issues/2042)\n- 修复 `n-drawer-content` 的内容区域默认无法滚动，关于 [#2003](https://github.com/tusen-ai/naive-ui/issues/2003)\n- 修复 `n-popover` 手动指定多个 popover 有 相同 zindex 并关闭时控制台打印错误，关闭 [#2050](https://github.com/tusen-ai/naive-ui/issues/2050)\n- 修复 `n-transfer` 在虚拟滚动模式下没有滚动条\n- 修复 `n-input-number` 不能输入以 0 结尾的小数\n\n## 2.23.1\n\n`2021-12-20`\n\n### Fixes\n\n- 修复 `n-transfer` 在自定义高度后内部列表和容器高度不一致，关闭 [#1879](https://github.com/tusen-ai/naive-ui/issues/1879)\n- 修复 `n-skeleton` 和 `n-gradient-text` 在某些较老的浏览器导致运行错误，关闭 [#1867](https://github.com/tusen-ai/naive-ui/issues/1867)\n- 修复 `n-data-table` 中列的 ellipsis 属性对于 `n-ellipsis` 的属性支持不全，关闭 [#1891](https://github.com/tusen-ai/naive-ui/issues/1891)\n- 修复 `n-form` 的 `blankHeightXxx` 主题变量没有跟随 `common.heightXxx`，关闭 [#1880](https://github.com/tusen-ai/naive-ui/issues/1880)\n- 修复 `n-date-picker` 面板中的日期输入未使用国际化的 `dateFormat`，关闭 [#1793](https://github.com/tusen-ai/naive-ui/issues/1793)\n- 修复 `n-log` 主题切换文字颜色 transition\n\n### Feats\n\n- `n-back-top` 的 CSS 变量使用 `n` 作为前缀\n- `n-steps` 的 CSS 变量使用 `n` 作为前缀\n- `n-switch` 的 CSS 变量使用 `n` 作为前缀\n- `n-auto-complete` 的 CSS 变量使用 `n` 作为前缀\n- `n-log` 的 CSS 变量使用 `n` 作为前缀\n- `n-timeline` 的 CSS 变量使用 `n` 作为前缀\n- `n-time-picker` 的 CSS 变量使用 `n` 作为前缀\n- `n-avatar` 的 CSS 变量使用 `n` 作为前缀\n- `n-dynamic-tags` 的 CSS 变量使用 `n` 作为前缀\n- `n-tag` 的 CSS 变量使用 `n` 作为前缀\n- `n-dialog` 的 CSS 变量使用 `n` 作为前缀\n- `n-upload` 的 CSS 变量使用 `n` 作为前缀\n- `n-tree` 的 CSS 变量使用 `n` 作为前缀\n- `n-tree-select` 的 CSS 变量使用 `n` 作为前缀\n\n## 2.23.0\n\n`2021-12-17`\n\n### Breaking Changes\n\n- `n-switch` 在 `loading` 状态不可再被点击，关闭 [#1853](https://github.com/tusen-ai/naive-ui/issues/1853)\n\n### Fixes\n\n- 修复 `n-data-table` 在未设置 max-height 的情况下横向滚动条消失，关闭 [#1857](https://github.com/tusen-ai/naive-ui/issues/1857)\n- 修复 `n-input-number` 不能输入为负数的小数，关闭 [#1858](https://github.com/tusen-ai/naive-ui/issues/1858)\n- 修复 `n-dialog` 点击回车键反复弹出新弹窗，关闭 [#1559](https://github.com/tusen-ai/naive-ui/issues/1559)\n\n### Feats\n\n- `n-divider` 的 CSS 变量使用 `n` 作为前缀\n- `n-typography` 的 CSS 变量使用 `n` 作为前缀\n- `n-badge` 的 CSS 变量使用 `n` 作为前缀\n\n## 2.22.0\n\n`2021-12-15`\n\n### Breaking Changes\n\n- `n-button` 在 `loading` 状态不可再被点击，关闭 [#1628](https://github.com/tusen-ai/naive-ui/issues/1628)\n\n### Fixes\n\n- 修复 `n-alert` 的 `header` 插槽 无法正常显示\n- 修复 `n-data-table` 的分页器 `onUpdatePageSize` 属性未被触发，关闭 [#1774](https://github.com/tusen-ai/naive-ui/issues/1774)\n- 修复 `n-data-table` loading 时可以选中行，关闭 [#1812](https://github.com/tusen-ai/naive-ui/issues/1812)\n- 修复 `n-tag` 行高过低导致内容截断\n- 修复 `n-select` 设定 `filterable` 后选项过长显示出错，关闭 [#1823](https://github.com/tusen-ai/naive-ui/issues/1823)\n- 修复 `n-page-header` 在不显示头部时内容有 margin-top，关闭 [#1795](https://github.com/tusen-ai/naive-ui/issues/1795)\n- 修复 `n-avatar` `color` 属性不生效\n- 修复 `n-avatar` 内部图标尺寸不正确\n- 修复 `n-image` 缺少 scoped style 的 scope-id，关闭 [#1788](https://github.com/tusen-ai/naive-ui/issues/1788)\n- 修复 `n-radio` 的点击事件会被触发两次，关闭 [#1680](https://github.com/tusen-ai/naive-ui/issues/1680)\n- 修复 `n-data-table` 当表格为空表格并且设置 min-height 时布局显示错乱，关闭 [#1809](https://github.com/tusen-ai/naive-ui/issues/1809)\n- 修复 `n-data-table` 总结行有 hover 样式\n- 修复 `n-data-table` 固定 group column box-shadow 错误和 right fixed column 的渲染顺序错误，关闭 [#1832](https://github.com/tusen-ai/naive-ui/issues/1832)\n- 修复 `n-anchor` 的 hover & active 的样式\n- 修复 `n-data-table` 在无数据时头部固定列的样式\n\n### Feats\n\n- `n-tree-select` 新增 `menu-props` 属性\n- `n-tree-select` 新增 `action` 插槽，关闭 [#1765](https://github.com/tusen-ai/naive-ui/issues/1765)\n- `n-tree-select` 新增 `empty` 插槽\n- `n-cascader` 新增 `empty` 插槽\n- `n-popselect` 新增 `action` 插槽\n- `n-popselect` 新增 `empty` 插槽\n- `n-data-table` 点击表头半选的勾选框之后会全选，关闭 [#1827](https://github.com/tusen-ai/naive-ui/issues/1827)\n- `n-button` 的 CSS 变量使用 `n` 作为前缀，关闭 [#1808](https://github.com/tusen-ai/naive-ui/issues/1808)\n- `n-date-picker` 新增 `default-time` 属性\n- `n-alert` 的 CSS 变量使用 `n` 作为前缀\n- `n-date-picker` 属性 `type` 支持 `quarter` 选项\n- `n-anchor` 的 CSS 变量使用 `n` 作为前缀\n\n### i18n\n\n- 新增 zhTW locale\n\n## 2.21.5\n\n`2021-12-07`\n\n### Fixes\n\n- 修复 `n-input` 点击清除按钮时不触发 `change` 事件，关闭 [#1754](https://github.com/tusen-ai/naive-ui/issues/1754)\n- 修复 `n-input-number` 按压上、下方向键改变数值时光标移动的问题，关闭 [#1759](https://github.com/tusen-ai/naive-ui/issues/1759)\n\n### Feats\n\n- `n-date-picker` 跟随国际化变化默认日期格式\n\n### i18n\n\n- 新增 frFR locale\n\n## 2.21.4\n\n`2021-12-06`\n\n### Fixes\n\n- 修复 `n-date-picker` 在 `type` 为 `year` 时没有正确的 placeholder\n- 修复 `n-element` 未导出 `NEl` 别名\n- 修复 `n-upload` 在 `image-card` 模式下，达到最大上传数量后仍然展示上传按钮，关闭 [#1744](https://github.com/tusen-ai/naive-ui/issues/1744)\n- 修复 `n-form` 的 `FormValidate` 类型缺少 `shouldRuleBeApplied` 参数，关闭 [#1747](https://github.com/tusen-ai/naive-ui/issues/1747)\n- 修复 `n-upload` 在 `image-card` 模式时在表格中被展示为垂直的样式，关闭 [#1746](https://github.com/tusen-ai/naive-ui/issues/1746).\n- 修复 `n-upload` 文件列表在不显示触发区域的时候的 margin-top\n- 修复 `n-upload` 在响应为 4xx 的情况下文件显示正常状态，关闭 [#1741](https://github.com/tusen-ai/naive-ui/issues/1741)\n\n### Feats\n\n- `n-upload` 新增 `show-trigger` 属性\n- `n-data-table` 展示树形数据时会忽略长度为 0 的 `children`，关闭 [#1703](https://github.com/tusen-ai/naive-ui/issues/1703)\n\n## 2.21.3\n\n`2021-12-03`\n\n### Fixes\n\n- 修复 `n-theme-editor` 点击 button 组件时报错，关闭 [#1708](https://github.com/tusen-ai/naive-ui/issues/1708)\n- 修复 `n-input` 的颜色在安卓微信浏览器下异常，关闭 [#1705](https://github.com/tusen-ai/naive-ui/issues/1705)\n- 修复 `n-input` 的 `borderHover` 主题变量不生效， 关闭 [#1704](https://github.com/tusen-ai/naive-ui/issues/1704)\n- 修复 `n-dialog` 的 `content` 内容为英文时的换行问题\n- 修复 `n-input-number` 不能输入小数值\n- 修复 `n-data-table` 的表头和主体可能有错误的圆角，关闭 [#1712](https://github.com/tusen-ai/naive-ui/issues/1712)\n- 修复 `n-button` `colorOpacityXxx` 主题变量不为 string 类型\n\n### Feats\n\n- `n-switch` 新增 `rail-style` 属性，关闭 [#1718](https://github.com/tusen-ai/naive-ui/issues/1718)\n- `n-image` 新增 `preview-disabled` 属性，关闭 [#1647](https://github.com/tusen-ai/naive-ui/issues/1647)\n- `n-image` 新增 `on-load` & `on-error` 属性\n- `n-image` 新增 `fallback-src` 属性\n- `n-data-table` 新增 `on-update:expanded-row-keys` 属性\n- `n-tree` 新增 `watch-props` 属性\n\n## 2.21.2\n\n`2021-11-29`\n\n### Fixes\n\n- 修复 `n-slider` tooltip 禁用时机错误问题\n- 修复 `n-slider` 填充色样式错误问题，关闭 [#1670](https://github.com/tusen-ai/naive-ui/issues/1670)\n- 修复 `n-data-table` 的分页器 `onUpdatePage` 属性会被触发两次，关闭 [#1666](https://github.com/tusen-ai/naive-ui/issues/1666)\n- 修复 `n-log` 的 `trim` 属性不能独立使用\n- 修复 `n-slider` 对于数值精度的处理问题\n- 修复 `n-date-picker` 当 `time-picker` 输入为空时报错，关闭 [#1678](https://github.com/tusen-ai/naive-ui/issues/1678)\n- 修复 `n-popover` `trigger` 为 `focus` 时不生效\n- 修复 `n-scrollbar` 点击在滚动条上时会消失一次\n- 修复 `n-popover` 样式中有不合法的行\n- 修复 `n-popover` `flip=false` 不生效\n- 修复 `n-input-number` 在设定 `max` 或 `min` 后在输入过程中无法输入中间值，关闭 [#1664](https://github.com/tusen-ai/naive-ui/issues/1664)\n- 修复 `n-input-number` 在连读多次输入超过 `min` 或 `max` 范围的数字后，显示的值不转化为合法值\n\n### Feats\n\n- `n-input-number` 新增 `keyboard` 属性\n- 新增 `tableColorStriped` 主题变量，关闭 [#1686](https://github.com/tusen-ai/naive-ui/issues/1686)\n- `n-notification-provider` 新增 `max` & `placement` 属性\n- `n-notification` 新增 `detroyAll` 方法，关闭 [#333](https://github.com/tusen-ai/naive-ui/issues/333)\n- `n-layout-sider` 新增 `on-after-enter` 和 `on-after-leave` 属性，关闭 [#1241](https://github.com/tusen-ai/naive-ui/issues/1241)\n- `n-upload` 新增 `custom-request` 属性，关闭 [#1389](https://github.com/tusen-ai/naive-ui/issues/1389)\n- `n-data-table` 新增 `expanded-row-keys` 属性\n- `n-popover` 提供更强的自动位置调整能力，关闭 [#1520](https://github.com/tusen-ai/naive-ui/issues/1520)、[#1643](https://github.com/tusen-ai/naive-ui/issues/1643)\n- `n-input-number` 新增 `update-value-on-input` 属性，关闭 [#1662](https://github.com/tusen-ai/naive-ui/issues/1662)\n- `n-auto-complete` 新增 `prefix` & `suffix` 插槽\n\n## 2.21.1\n\n`2021-11-23`\n\n### Fixes\n\n- 修复 `n-image` 当放大很大的时候拖动图片移动位置不正确\n- 修复 `n-data-table` 在某些行展开后出现的样式问题\n- 修复 `n-data-table` 未能正确展开树形数据，关闭 [#1644](https://github.com/tusen-ai/naive-ui/issues/1644)\n\n## 2.21.0\n\n`2021-11-21`\n\n### Breaking Changes\n\n- 移除了 `NButton.fontWeightText` & `NButton.fontWeightGhost` 主题变量，如果你需要调整字重，可以使用 `n-button` 的 `strong` 属性\n\n### Feats\n\n- `n-tag` 新增 `avatar` 插槽\n- `n-data-table` 新增 `striped` 属性，关闭 [#1552](https://github.com/tusen-ai/naive-ui/issues/1552)\n- `n-table` 新增 `striped` 属性，关闭 [#1552](https://github.com/tusen-ai/naive-ui/issues/1552)\n- `n-slider` 新增 `vertical` 属性，关闭 [#1468](https://github.com/tusen-ai/naive-ui/issues/1468)\n- `n-slider` 新增 `reverse` 属性\n- `n-slider` 的 `step` 属性支持 `mark` 选项\n- 绕过 Vitejs SSR 渲染问题，关于 [#636](https://github.com/tusen-ai/naive-ui/issues/636)\n- `n-button` 新增 `strong` 属性\n- `n-button` 新增 `secondary` 属性\n- `n-button` 新增 `tertiary` 属性\n- `n-button` 新增 `quaternary` 属性\n- `n-auto-complete` 新增 `input-props` 属性，关闭 [#1610](https://github.com/tusen-ai/naive-ui/issues/1610)\n- `n-avatar` 新增 `fallback-src` 属性，关闭 [#702](https://github.com/tusen-ai/naive-ui/issues/702)\n- `n-avatar` 新增 `on-error` 属性\n- `n-input` 新增 `select` 方法，关闭[#1328](https://github.com/tusen-ai/naive-ui/issues/1328)\n- 新增 `n-tab` 组件，关闭 [#1630](https://github.com/tusen-ai/naive-ui/issues/1630)\n- `n-switch` 新增 `round` 属性，关闭 [#1469](https://github.com/tusen-ai/naive-ui/issues/1469)\n- `n-step` 新增 `title` 插槽\n- `n-menu` 支持 `divider` 类型的选项\n\n### Fixes\n\n- 修复 `suffix` 内部组件 `loading` 属性的默认值\n- 修复 `n-space` 没有子节点的时候还被展示，关闭 [#1605](https://github.com/tusen-ai/naive-ui/issues/1605)\n- 修复 `n-radio` 缺少 `onUpdateChecked` 属性\n- 修复 `n-dropdown` 动画闪烁问题，关闭 [#1600](https://github.com/tusen-ai/naive-ui/issues/1600)\n- 修复 `n-data-table` 的 `clearSorter` 方法没有被正常导出\n- 修复 `n-global-style` SSR 报错\n- 修复 `n-button` 按下 Enter 会出发两次 click 时间 [#1626](https://github.com/tusen-ai/naive-ui/issues/1626)\n\n## 2.20.3\n\n`2021-11-15`\n\n### Fixes\n\n- 修复 `n-grid` 收缩时后缀 girdItem 设置的 span 不起作用，关闭 [#1530](https://github.com/tusen-ai/naive-ui/issues/1530)\n- 修复 `n-button` 使用 `circle` 属性时在特定场景异常收缩的问题，关闭 [#1557](https://github.com/tusen-ai/naive-ui/issues/1557)\n- 修复 `input-props` 对于 `type` 属性无法生效的问题，关闭 [#1553](https://github.com/tusen-ai/naive-ui/issues/1553)\n\n### Feats\n\n- `n-menu` 添加箭头颜色区分选中未选中，关闭 [#1535](https://github.com/tusen-ai/naive-ui/issues/1535)\n- `n-menu` 新增 `watch-props` 属性，关闭 [#1536](https://github.com/tusen-ai/naive-ui/issues/1536)\n- `n-date-picker` 属性 `type` 支持 `year` 选项\n\n### i18n\n\n- 新增 `createLocale` 方法允许用户自定义国际化，关闭 [#1525](https://github.com/tusen-ai/naive-ui/issues/1525)\n\n## 2.20.2\n\n`2021-11-05`\n\n### Feats\n\n- `n-modal` 新增 `transform-origin` 属性，关闭 [#1498](https://github.com/tusen-ai/naive-ui/issues/1498)\n- `n-tabs` 新增 `pane-class` 属性，关闭 [#1500](https://github.com/tusen-ai/naive-ui/issues/1500)\n\n### Fixes\n\n- 修复 `n-alert` `contentTextColor` 和 `titleTextColor` 的类型主题变量不起作用，关闭 [#1495](https://github.com/tusen-ai/naive-ui/issues/1495)\n- 修复 `n-time-picker` 当选择面板通过确认按钮关闭时不会触发 blur 事件，closes [#1499](https://github.com/tusen-ai/naive-ui/issues/1499)\n- 修复 `n-upload` `UploadFileInfo` 的 `thumbnailUrl` 字段不起作用，关闭 [#1495](https://github.com/tusen-ai/naive-ui/issues/1245)\n- 修复 `n-button` `keyboard` 属性不起作用，关闭 [#1508](https://github.com/tusen-ai/naive-ui/issues/1508)\n- 修复 `n-upload` 实例缺少 `openOpenFileDialog` 方法\n\n### i18n\n\n- 新增 deDE locale\n- 新增 nbNO locale\n\n## 2.20.1\n\n`2021-11-01`\n\n### Fixes\n\n- 修复 `n-tabs` 在新增 tab 后切换 tab 无法生效，关闭 [#1417](https://github.com/tusen-ai/naive-ui/issues/1417)\n- 修复 `n-tree` 当指定`children-field`时过滤不生效，关闭 [#1477](https://github.com/tusen-ai/naive-ui/issues/1477)\n- 修复 `n-cascader` 在自定义字段和 `multiple` 一起使用时无法删除选项\n- 修复 `n-select` 使用 `on-create` 创建的选项字段不正确，关闭 [#1482](https://github.com/tusen-ai/naive-ui/issues/1482)\n- 修复 `n-select` 在过滤状态下点击选项菜单闪动\n\n### Feats\n\n- `n-select` 新增 `menu-props` 属性，关闭 [#1475](https://github.com/tusen-ai/naive-ui/issues/1475)\n- `n-image` 的 `toolbar` 增加关闭图标，关闭 [#1412](https://github.com/tusen-ai/naive-ui/issues/1412)\n- `n-tree` 的 `on-load` 属性在 `remote` 模式下 `expanded-keys` 属性改变时被触发，关闭 [#1339](https://github.com/tusen-ai/naive-ui/issues/1339)\n\n## 2.20.0\n\n`2021-10-28`\n\n### Breaking Changes\n\n- `n-collapsed-transition` 的 `collapsed` 属性被废弃，请使用 `show` 属性代替，关闭 [#1407](https://github.com/tusen-ai/naive-ui/issues/1407)\n\n### Fixes\n\n- 修复 `n-log` `font-size` 属性不生效，关闭 [#1416](https://github.com/tusen-ai/naive-ui/issues/1416)\n- 修复 `n-loading-bar` 设定 `loading-bar-style` 后不调用 `start` 也会显示一次\n- 修复 `n-date-picker` `separator` 不生效，关闭 [#1456](https://github.com/tusen-ai/naive-ui/issues/1456)\n\n### Feats\n\n- `n-data-table` 优化底层渲染的逻辑，提升组件性能\n- `n-date-picker` 的 `shortcuts` 属性支持传入回调函数\n- `n-tab-pane` 属性 `display-directive` 支持 `show:lazy` 选项，关闭 [#1374](https://github.com/tusen-ai/naive-ui/issues/1374)\n- `n-input` 的 `count` 插槽 s 支持 text 类型，关闭 [#1440](https://github.com/tusen-ai/naive-ui/issues/1440)\n\n### i18n\n\n- 新增 idID locale\n\n## 2.19.11\n\n`2021-10-21`\n\n### Fixes\n\n- 修复 `n-upload` 在达到最大文件数量后无法删除文件，关闭 [#1401](https://github.com/tusen-ai/naive-ui/issues/1401)\n\n### Feats\n\n- `n-tabs` 新增 `on-before-leave` 属性，关闭 [#1337](https://github.com/tusen-ai/naive-ui/issues/1337)\n- `n-color-picker` 新增 `show-preview` 属性，关闭 [#1281](https://github.com/tusen-ai/naive-ui/issues/1281)\n\n## 2.19.9\n\n`2021-10-18`\n\n### Fixes\n\n- 修复 `n-collapse` 在 `n-collapse-item` 使用 `v-if` 时展开状态丢失，关闭 [#1387](https://github.com/tusen-ai/naive-ui/issues/1387)\n- 修复 `n-dialog` 的关闭按钮会被内容遮盖，关闭 [#1381](https://github.com/tusen-ai/naive-ui/issues/1381)\n- 修复 `n-upload` 上传失败后重试时文件为 `null`，关闭 [#1316](https://github.com/tusen-ai/naive-ui/issues/1316)\n- 修复 `n-cascader` 的 `filter` 属性不生效\n- 修复 `n-cascader` 的 `label-field` 属性使 `filter` 失效\n- 修复 `n-cascader` 的 `separator` 属性对于过滤菜单无效\n\n### Feats\n\n- `n-menu` 新增 `dropdown-props` 属性，关闭 [#1345](https://github.com/tusen-ai/naive-ui/issues/1345)\n- `n-input` 新增 `count` 插槽，关闭 [#1314](https://github.com/tusen-ai/naive-ui/issues/1314)\n- `n-time-picker` 新增 `use-12-hours` 属性，关闭 [#547](https://github.com/tusen-ai/naive-ui/issues/547)\n- `n-input-number` 新增 `focus` 和 `blur` 方法\n- `n-config-provider` 新增 `breakpoints` 属性，关闭 [#1379](https://github.com/tusen-ai/naive-ui/issues/1379)\n\n## 2.19.8\n\n`2021-10-14`\n\n### Fixes\n\n- 修复 `n-data-table` `fixed` 样式在表头分组不生效的问题，关闭 [#1341](https://github.com/tusen-ai/naive-ui/issues/1341)\n- 修复 `n-data-table` 多级表头右侧边框重复\n- 修复 `n-scrollbar` 不支持 `scrollTo`，关闭 [#1346](https://github.com/tusen-ai/naive-ui/issues/1346)\n- 修复 `n-ellipsis` 的 `expand-trigger` 属性在内容不显示提示并且 `tooltip = false` 的时候禁用鼠标样式的问题，关闭 [#1299](https://github.com/tusen-ai/naive-ui/issues/1299)\n- 修复 `n-upload` 的 `disabled` 属性的样式问题，关闭 [#1237](https://github.com/tusen-ai/naive-ui/issues/1237)\n\n### Feats\n\n- `n-auto-complete` 新增 `get-show` 属性，关闭 [#1292](https://github.com/tusen-ai/naive-ui/issues/1292)\n- `n-select` 新增 `input-props` 属性，关闭 [#1351](https://github.com/tusen-ai/naive-ui/issues/1351)\n- `n-color-picker` 新增 `swatches` 属性，有关 [#1281](https://github.com/tusen-ai/naive-ui/issues/1281)\n- `n-upload` 新增 `max` 属性\n\n### i18n\n\n- 新增 jaJP locale\n\n## 2.19.7\n\n`2021-10-12`\n\n### Fixes\n\n- 修复 `n-ellipsis` 的 `expand-trigger` 属性在内容不显示提示的时候禁用鼠标样式的问题，关闭 [#1299](https://github.com/tusen-ai/naive-ui/issues/1299)\n- 修复 `n-select` `fallback-option` 属性类型，关闭 [#1327](https://github.com/tusen-ai/naive-ui/issues/1327)\n- 修复 `n-modal` `on-after-enter` 不生效\n\n## 2.19.6\n\n`2021-10-10`\n\n### Fixes\n\n- 修复 `n-menu` 对于 `default-expanded-keys` 的错误警报\n- 修复 `useThemeVars` 有时无法使用，关闭 [#1309](https://github.com/tusen-ai/naive-ui/issues/1309)\n- 修复 `<ul>` 元素的 `list-style` 样式\n\n### Feats\n\n- `n-cascader` 值改变时回调函数提供上层节点的全部 options 值，关闭 [#1235](https://github.com/tusen-ai/naive-ui/issues/1235)\n- `n-layout` 和 `n-layout-sider` 增加 `on-scroll` 属性，关闭 [#1232](https://github.com/tusen-ai/naive-ui/issues/1232)\n\n## 2.19.5\n\n`2021-10-07`\n\n### Fixes\n\n- 修复 `n-form-item` 中组件内容过长影响 `n-form-item` 宽度\n- 修复 `n-layout-sider` 中 `arrow-circle` 的 icon 样式\n- 修复 `n-upload` 的 `show-preview-button` 属性失效，关闭 [#1238](https://github.com/tusen-ai/naive-ui/issues/1238)\n- 修复 `n-date-picker` 的 `date` 类型的 `action` 验证错误\n- 修复 `n-data-table` 在 `selection` 和 `summary` 一起使用时报错，关闭 [#1276](https://github.com/tusen-ai/naive-ui/issues/1276)\n- 修复 `n-data-table` 勾选列的宽度在设为 fixed 时候塌陷，关闭 [#1283](https://github.com/tusen-ai/naive-ui/issues/1283)\n- 修复 `n-popconfirm` 不能被嵌套于 `n-tooltip` 内，关闭 [#872](https://github.com/tusen-ai/naive-ui/issues/872).\n- 修复 `n-popselect` 勾选图标覆盖了文本，关闭 [#1282](https://github.com/tusen-ai/naive-ui/issues/1282)\n- 修复 `n-pagination` `buttonColor` 主题变量不生效\n\n### Feats\n\n- `n-breadcrumb-item` 新增 `href` 属性\n- `n-descriptions` 新增 `separator` 属性，关闭 [#1263](https://github.com/tusen-ai/naive-ui/issues/1263)\n- `n-dropdown` 新增 `key-field` 属性\n- `n-dropdown` 新增 `label-field` 属性\n- `n-dropdown` 新增 `children-field` 属性\n- `n-menu` 新增 `key-field` 属性\n- `n-menu` 新增 `label-field` 属性\n- `n-menu` 新增 `children-field` 属性\n- `n-data-table` 支持使用访问属性路径作为列的 key，关闭 [#1271](https://github.com/tusen-ai/naive-ui/issues/1271)\n- `n-switch` 新增 `checked-value` 属性，关闭 [#1234](https://github.com/tusen-ai/naive-ui/issues/1234)\n- `n-switch` 新增 `unchecked-value` 属性，关闭 [#1234](https://github.com/tusen-ai/naive-ui/issues/1234)\n- `n-checkbox` 新增 `checked-value` 属性，关闭 [#1234](https://github.com/tusen-ai/naive-ui/issues/1234)\n- `n-checkbox` 新增 `unchecked-value` 属性，关闭 [#1234](https://github.com/tusen-ai/naive-ui/issues/1234)\n- 新增 `n-collapse-transition` 组件，关闭 [#829](https://github.com/tusen-ai/naive-ui/issues/829)\n- 新增 `n-scrollbar` 组件\n- `n-dropdown` 支持 `type='render'` 的选项\n- `n-data-table` 支持多列排序\n- `n-date-picker` 新增 `first-day-of-week` 属性\n- `n-date-picker` 属性 `type` 支持 `month` 选项\n- `n-popover` 新增 `to` 属性\n- `n-tree` 的 `on-update:indeterminateKeys` 回调新增选项信息\n- `n-tree` 的 `on-update:expandedKeys` 回调新增选项信息\n- `n-tree` 的 `on-update:checkedKeys` 回调新增选项信息\n- `n-tree` 的 `on-update:selectedKeys` 回调新增选项信息\n\n## 2.19.3\n\n`2021-09-28`\n\n### Fixes\n\n- 修复 `n-data-table` 当最后一列未设置 `ellipsis` 时省略失效，关闭 [#934](https://github.com/tusen-ai/naive-ui/issues/934)\n- 修复 `n-grid-item` 响应式不生效\n- 修复 `n-tabs` 在尺寸改变后没有更新滚动阴影状态，关闭 [#1224](https://github.com/tusen-ai/naive-ui/issues/1224)\n\n### Feats\n\n- `n-grid-item` 在 `span` 为 0 的时候隐藏，关闭 [#1220](https://github.com/tusen-ai/naive-ui/issues/1220)\n- `n-grid` 新增 `item-responsive` 属性\n\n## 2.19.2\n\n`2021-09-26`\n\n### i18n\n\n- 新增 ukUA locale\n\n### Fixes\n\n- 修复 `n-global-style` 在首次挂载时应用样式过渡\n- 修复 `n-drawer` 边界缺少 transition，关闭 [#1211](https://github.com/tusen-ai/naive-ui/issues/1211)\n- 修复 `n-input-number` 的 `value` 属性不能为 null 类型\n- 修复支持 rtl 的组件 SSR 报错\n- 修复有弹出层组件的 SSR 报错\n- 修复全局样式覆盖对 select 触发器不生效，关闭 [#1229](https://github.com/tusen-ai/naive-ui/issues/1229)\n\n### Feats\n\n- `n-checkbox` 增加 aria 支持\n- `n-alert` 增加 aria 支持\n\n## 2.19.1\n\n`2021-09-21`\n\n### Fixes\n\n- 修复 `DialogReactive` 属性不可修改\n- 修复 `n-tree-select` 设定 `check-strategy='child'` 在单选时不生效\n- 修复 `n-upload` 在 `image-card` 模式下触发区域作为一行唯一元素时被压缩\n- 修复 `n-upload-dragger` 边框缺乏过渡\n- 修复 `n-upload` 无法上传文件\n- 修复 `n-tree` 在 `cascade` 设置为 `false` 时 `checkable` 无法显示勾选框\n- 修复 `n-tree-select` 在 `cascade` 或 `multiple` 设置为 `false` 时 `checkable` 无法显示勾选框\n\n## 2.19.0\n\n`2021-09-19`\n\n### Breaking Changes\n\n- `n-layout-sider` 的 `arrow-circle` 类型触发按钮采用了新样式\n\n### Feats\n\n- `n-layout-sider` 新增 `collapsed-trigger-style` 属性\n- `n-menu` 添加 `accordion` 属性，关闭 [#917](https://github.com/tusen-ai/naive-ui/issues/917)\n- `n-input-number` 新增 `readonly` 属性，关闭 [#1198](https://github.com/tusen-ai/naive-ui/issues/1198)\n- `n-spin` 新增 `description` prop 和 插槽\n- `n-anchor` 新增 `type` 属性\n- `n-upload` 新增 `abstract` 属性，新增 `n-upload-trigger` 和 `n-upload-file-list` 组件，关闭 [#1102](https://github.com/tusen-ai/naive-ui/issues/1102)\n- `n-tree` 新增 `indeterminate-keys` 属性\n- `n-tree-select` 新增 `indeterminate-keys` 属性\n- `n-tree` 新增 `on-update:indeterminate-keys` 属性\n- `n-tree-select` 新增 `on-update:indeterminate-keys` 属性\n- `n-tabs` 的 `type` 属性新增 `'segment'` 选项，关闭 [#1133](https://github.com/tusen-ai/naive-ui/issues/1133)\n- `n-popover` 新增 `z-index` 属性，关闭 [#764](https://github.com/tusen-ai/naive-ui/issues/764).\n- `n-modal` 新增 `on-after-enter` 属性\n- `n-modal` 新增 `on-after-leave` 属性\n\n### Fixes\n\n- 修复 `n-select` `filterable` 下关闭标签 input 光标聚焦问题，关闭 [#1170](https://github.com/tusen-ai/naive-ui/issues/1170)\n- 修复 `n-button` 在 hover 状态下边框与 `n-badge` 冲突，关闭 [#1195](https://github.com/tusen-ai/naive-ui/issues/1195)\n- 修复 `n-upload` 的 `v-model:file-list` 属性在 `multiple` 属性设为 `true` 的时候没有正确更新，关闭 [#418](https://github.com/tusen-ai/naive-ui/issues/418)\n- 修复 `useThemeVars` 未应用覆盖的变量值，关闭 [#1194](https://github.com/tusen-ai/naive-ui/issues/1194)、[#1176](https://github.com/tusen-ai/naive-ui/issues/1176)\n- Fix `n-tabs` 在 card 类型时左侧滚动的阴影不显示\n\n## 2.18.2\n\n`2021-09-14`\n\n### Feats\n\n- `n-cascader` 当 `options` 为空时显示 `Empty` 组件，关闭 [#1092](https://github.com/tusen-ai/naive-ui/issues/1092)\n- `n-cascader` 的 `on-update:value` 属性新增选项参数\n- `n-tree` 增加 `check-strategy` 文档属性\n- `n-date-picker` 新增 `input-readonly` 属性，关闭 [#1120](https://github.com/tusen-ai/naive-ui/issues/1120)\n- `n-time-picker` 新增 `input-readonly` 属性，关闭 [#1120](https://github.com/tusen-ai/naive-ui/issues/1120)\n- `n-config-provider` 新增 `Empty` 组件的全局配置，关闭 [#1092](https://github.com/tusen-ai/naive-ui/issues/1092)\n- `n-select` 新增 `on-update:show` 属性\n- `n-auto-complete` 导出 `AutoCompleteOption` 以及 `AutoCompleteGroupOption` 类型\n- `n-page-header` 添加 `RTL` 支持\n- `n-select` 支持可变高度选项渲染\n- `n-tree-select` 的 `on-update:value` 属性新增选项参数\n- `n-select` 的 `on-update:value` 属性新增选项参数\n- `n-popselect` 的 `on-update:value` 属性新增选项参数\n- `n-card` 新增 `embedded` 属性\n\n### Fixes\n\n- 修复 `n-p` `depth` 传入 number 报错\n- 修复 `n-date-picker` 的 `actions` 属性类型\n- 修复 `n-select` 无法重写 empty 的主题变量\n- 修复 `n-dynamic-tags` 禁用时 add 按钮未被禁用\n- 修复 `n-select` 在 filterable 并且菜单无数据是按下 enter 导致菜单关闭\n- 修复 `n-auto-complete` 的 `children` 属性不允许使用 `AutoCompleteOption` 类型\n- 修复 `n-gi` 的 `collapsed` 在 `n-form-item-gi` 中切换无法生效问题，关闭 [#1160](https://github.com/tusen-ai/naive-ui/issues/1160)\n\n## 2.18.1\n\n`2021-09-08`\n\n### Feats\n\n- `useDialog` 选项新增 `style` 属性，关闭 [#1054](https://github.com/tusen-ai/naive-ui/issues/1054)\n- `n-timeline` 新增 `icon` 插槽，关闭 [#1096](https://github.com/tusen-ai/naive-ui/issues/1096)\n- `n-timeline` 新增 `icon-size` 属性\n\n### Fixes\n\n- 修复 `n-step` 无法使用 `v-for` 的子元素\n- 修复 `n-input-number` 在 `step` 不为小数时不能输入小数\n\n## 2.18.0\n\n`2021-09-07`\n\n### Breaking Changes\n\n- `n-form` & `n-form-item` 拆分 `show-require-mark` 为 `show-require-mark` 和 `require-mark-placement`\n\n### Feats\n\n- `n-drawer` 新增 `on-mask-click` 属性\n- `n-form` 新增 `require-mark-placement` 属性，关闭 [#1055](https://github.com/tusen-ai/naive-ui/issues/1055)\n- `n-form-item` 新增 `require-mark-placement` 属性，关闭 [#1055](https://github.com/tusen-ai/naive-ui/issues/1055)\n\n### Fixes\n\n- 修复 `n-step` 必须传 `internal-index`\n- 修复 `n-radio-group` 的 `on-update:value` 和 `on-update-value` 类型不能为数组\n- 修复 `n-cascader` `check-strategy=\"child\"` 和原有 `leaf-only` 表现不一致\n\n## 2.17.2\n\n`2021-09-06`\n\n### Fixes\n\n- 修复 `n-tree-select` 显示路径是展示 key 而不是 label，关闭 [#1095](https://github.com/tusen-ai/naive-ui/issues/1095)\n\n## 2.17.1\n\n`2021-09-06`\n\n### Fixes\n\n- 修复 `n-cascader` 菜单未展示正确的选中 key\n\n## 2.17.0\n\n`2021-09-05`\n\n### Breaking Changes\n\n- `n-tree-select` 的 `leaf-only` 属性被废弃，请使用 `check-strategy=\"child\"`\n- `n-cascader` 的 `leaf-only` 属性被废弃，请使用 `check-strategy=\"child\"`\n- `n-input` 的 `show-password-toggle` 属性被废弃，请使用 `show-password-on=\"click\"`\n\n### Fixes\n\n- 修复 `n-cascader` 多选模式下点击 tag 删除子选项未更新选中项\n- 修复 `n-input` 在 `clearable` 为 `true` 时鼠标离开输入框时中文输入法不正确，关闭 [#905](https://github.com/tusen-ai/naive-ui/issues/905)\n- 修复 `n-description` 中因 `v-if` 导致的不该出现的警告，关闭 [#1083](https://github.com/tusen-ai/naive-ui/issues/1083)\n- 修复 `n-layout` 的 `sider-placement` 属性在打包之后不生效，关闭 [#978](https://github.com/tusen-ai/naive-ui/issues/978)\n- 修复 `n-input-number` 的 `step` 值为小数时计算错误，关闭 [#1007](https://github.com/tusen-ai/naive-ui/issues/1007)\n- 修复 `n-popselect` 的默认位置和 padding\n- 修复 `n-calendar` 禁用日期的字体颜色\n\n### Feats\n\n- `n-cascader` 新增 `onUpdateValue` 方法\n- `n-auto-complete` 新增 `onUpdateValue` 方法\n- `n-data-table` 的列的 `renderFilterMenu` 新增 hide 参数\n- `n-tree` 新增 `key-field` 属性\n- `n-tree` 新增 `label-field` 属性\n- `n-tree` 新增 `children-field` 属性\n- `n-tree-select` 新增 `key-field` 属性\n- `n-tree-select` 新增 `label-field` 属性\n- `n-tree-select` 新增 `children-field` 属性\n- `n-cascader` 新增 `key-field` 属性\n- `n-cascader` 新增 `label-field` 属性\n- `n-cascader` 新增 `children-field` 属性\n- `n-dropdown` 选项新增 `props` 属性，关闭 [#813](https://github.com/tusen-ai/naive-ui/issues/813)\n- `n-data-table` 支持按住 `shift` 进行多选操作，关闭 [#554](https://github.com/tusen-ai/naive-ui/issues/554)\n- `n-tree-select` 增加 `check-strategy` 属性，关闭 [#624](https://github.com/tusen-ai/naive-ui/issues/624)\n- `n-cascader` 增加 `check-strategy` 属性\n- `n-message` 选项增加 `keepAliveOnHover` 属性，关闭 [#1036](https://github.com/tusen-ai/naive-ui/issues/1036).\n- `n-message-provider` 新增 `keep-alive-on-hover` 属性，关闭 [#1036](https://github.com/tusen-ai/naive-ui/issues/1036).\n- `n-upload` 导出 `UploadFile` 类型\n- `n-cascader` 导出 `CascaderOption` 类型\n- `n-mention` 导出 `MentionOption` 类型\n- `n-transfer` 导出 `TransferOption` 类型\n- `n-pagination` 导出 `PaginationInfo` 类型\n- `n-data-table` 导出 `DataTableCreateSummary` 类型\n- `n-code` 新增 `inline` 属性，关闭 [#834](https://github.com/tusen-ai/naive-ui/issues/834)\n- `n-collapse` 新增 `header-extra` 插槽，关闭 [#1046](https://github.com/tusen-ai/naive-ui/issues/1046)\n- `n-input` 新增 `show-password-on` 属性\n- `n-upload` 增加 `list-type`、 `show-preview-button`、 `on-preview` 和 `create-thumbnail-url` 属性\n\n## 2.16.7\n\n`2021-08-27`\n\n### Feats\n\n- `n-mention` 新增 `focus`、`blur` 方法\n\n### Fixes\n\n- 修复 `n-mention` 在 input 模式下菜单距离文字太远\n- 修复 `n-tree` 节点无法展开的问题\n\n## 2.16.6\n\n`2021-08-26`\n\n### Feats\n\n- `n-timeline` 新增 `horizontal` 属性，关闭 [#887](https://github.com/tusen-ai/naive-ui/issues/887)\n- `n-image` 新增 `preview-src` 属性，关闭 [#922](https://github.com/tusen-ai/naive-ui/issues/922)\n- `n-dynamic-tags` 新增 `input` 和 `add` 插槽，关闭 [#499](https://github.com/tusen-ai/naive-ui/issues/499)\n- `n-timeline-item` 新增 `color` 属性\n\n### Fixes\n\n- 修复 `n-image` 切换图像后没有初始化 `rotate`，关闭 [#921](https://github.com/tusen-ai/naive-ui/issues/921)\n- 修复 `n-data-table` 的 loading 不在中间，关闭 [#929](https://github.com/tusen-ai/naive-ui/issues/929)\n- 修复 `n-tree` 当 onLoad 回调没有添加 children 时抛出错误，关闭 [#772](https://github.com/tusen-ai/naive-ui/issues/772)\n- 修复 `n-input` 当传递 `value=ref(0)` 时，同时显示 0 和占位符问题，关闭 [#914](https://github.com/tusen-ai/naive-ui/issues/914)\n- 修复 `n-data-table` `flex-height` 在不设定 `scroll-x` 的时候不生效，关闭 [#952](https://github.com/tusen-ai/naive-ui/issues/952)\n\n## 2.16.5\n\n`2021-08-20`\n\n### Feats\n\n- `n-input-number` 新增 `clearable` 属性\n- `n-form` 新增 `show-label` 属性，关闭 [#858](https://github.com/tusen-ai/naive-ui/issues/858)\n\n### Fixes\n\n- 修复 `n-notification` 导出的 `NotificationReactive` 类型不可变，关闭 [#876](https://github.com/tusen-ai/naive-ui/issues/876)\n- 修复 `n-tabs` 不同类型嵌套样式错乱，关闭 [#850](https://github.com/tusen-ai/naive-ui/issues/850)\n- 修复 `n-dropdown` 内部的链接点击触发区域不是整个选项，关闭 [#823](https://github.com/tusen-ai/naive-ui/issues/823)\n- 修复 `n-popover` 嵌套于不同 placement 的 popover 中箭头位置错乱，关闭 [#916](https://github.com/tusen-ai/naive-ui/issues/916)\n- 修复 `n-ellpisis` 在更新内容后失效，关闭 [#776](https://github.com/tusen-ai/naive-ui/issues/776)\n\n## 2.16.4\n\n`2021-08-16`\n\n### Fixes\n\n- 修复 ruRU locale 导出\n\n## 2.16.3\n\n`2021-08-16`\n\n### i18n\n\n- 新增 ruRU locale [#852](https://github.com/tusen-ai/naive-ui/pull/852)\n\n### Feats\n\n- `n-message-provider` 新增 `container-style` 属性\n- `n-message-provider` 新增 `placement` 属性\n- `n-message` 增加类用于区分类型\n- `n-date-picker` 新增 `shortcuts` 属性，关闭 [#280](https://github.com/tusen-ai/naive-ui/issues/280)\n\n### Fixes\n\n- 修复 `n-rate` 在深色模式下半个星星重叠\n- 修复 `n-menu` 使用 `render-icon` 在返回值为 `true` 时渲染有误\n- 修复 `n-space` 在使用 `v-if` 时渲染空的占位，关闭 [#824](https://github.com/tusen-ai/naive-ui/issues/824)\n\n## 2.16.2\n\n`2021-08-09`\n\n### Feats\n\n- `n-message-provider` 新增 `closable` 属性，关闭 [#795](https://github.com/tusen-ai/naive-ui/issues/795)\n- `n-tree-select` 新增 `show-path` 属性，关闭[#625](https://github.com/tusen-ai/naive-ui/issues/623)\n- `n-layout` 增加 `sider-placement` 属性，关闭 [#566](https://github.com/tusen-ai/naive-ui/issues/566)\n\n### Fixes\n\n- 修复 `n-avatar` 的缩放在使用 `v-show` 时不正确，关闭 [#779](https://github.com/tusen-ai/naive-ui/issues/779)\n- 修复 `n-menu` 在手机端点击菜单的时候出现蓝色背景问题，关闭 [#799](https://github.com/tusen-ai/naive-ui/issues/799)\n- 修复 `n-select` 可过滤的选择器失效，关闭 [#510](https://github.com/tusen-ai/naive-ui/issues/510)\n- 修复 `n-data-table` 当全选选中时，全选的状态显示不应该包含被禁用的行，关闭 [#778](https://github.com/tusen-ai/naive-ui/issues/778)\n- 修复 `n-color-picker` 的 `on-complete` 回调参数 `value` 值不正确，关闭 [#748](https://github.com/tusen-ai/naive-ui/issues/748)\n\n## 2.16.1\n\n`2021-08-06`\n\n### Feats\n\n- `n-loading-bar-provider` 新增 `loading-bar-style` 属性，关闭 [#457](https://github.com/tusen-ai/naive-ui/issues/457)\n- `n-button` 新增 `text-color` 属性\n- `n-form` 导出 `FormValidationError` 类型\n- `n-popconfirm` 支持不显示操作组件，关闭 [#770](https://github.com/tusen-ai/naive-ui/issues/770)\n\n### Fixes\n\n- 修复 `n-slider` 丢失浮点数小数精度，关闭 [#751](https://github.com/tusen-ai/naive-ui/issues/751)\n- 修复 `n-data-table` `onUpdatePage` 和 `onUpdatePageSize` 在使用 jsx 时不触发的问题\n- 修复 `n-progress` 的 `percentage` 属性默认值不能适应多种类型\n- 修复 `n-select` 当选项禁用时未隐藏关闭图标\n- 修复 `n-modal` 使用自定义内容无法正常关闭，关闭 [#788](https://github.com/tusen-ai/naive-ui/issues/788)\n\n## 2.16.0\n\n`2021-08-02`\n\n### Breaking Changes\n\n- `useLoadingBar` 中 `finish` 方法只有在调用过 `start` 后才生效\n- `n-input` 的 `type='input'` 被重命名为 `type='text'`\n\n### Feats\n\n- `n-scrollbar` 增加 `scrollbarWidth`、`scrollbarHeight` 和　`scrollbarBorderRadius`　公共主题变量，关闭 [#649](https://github.com/tusen-ai/naive-ui/issues/649)\n- `n-menu` 在 `render-icon` 返回 falsy 值的时候不渲染 icon 的占位符，关闭 [#722](https://github.com/tusen-ai/naive-ui/issues/722)\n- `n-menu` 新增 `render-extra` 属性\n- `n-select` 新增 `on-clear` 属性\n- `n-form` 增加 `disabled` 属性，关闭 [#538](https://github.com/tusen-ai/naive-ui/issues/538)\n- `n-dynamic-tags` 新增 `max` 属性\n\n### Fixes\n\n- 修复 `n-dropdown` 循环渲染时点击异常\n- 修复 `n-modal` 使用预设时无法自定义类，关闭 [#744](https://github.com/tusen-ai/naive-ui/issues/744)\n- 修复 `n-cascader` 的菜单虚拟滚动时宽度展示不一致问题，关闭 [#728](https://github.com/tusen-ai/naive-ui/issues/728)\n\n## 2.15.11\n\n`2021-07-29`\n\n### Fixes\n\n- 修复 `n-data-table` pagination 的报错\n\n## 2.15.10\n\n`2021-07-29`\n\n### Feats\n\n- `n-pagination` 新增 `prev`、`next` 插槽，有关 [#648](https://github.com/tusen-ai/naive-ui/issues/648)\n- `n-tag` 新增 `color`，关闭 [#693](https://github.com/tusen-ai/naive-ui/issues/693)\n- `n-dynamic-tags` 新增 `color`，关闭 [#693](https://github.com/tusen-ai/naive-ui/issues/693)\n- `n-time-picker` 优化 now 按钮的逻辑，关闭 [#401](https://github.com/tusen-ai/naive-ui/issues/401)\n- `n-pagination` `PaginationInfo` 增加 `itemCount` 属性，关闭 [#585](https://github.com/tusen-ai/naive-ui/issues/585)\n\n### Fixes\n\n- 修复 `n-message` 的 `destroyAll` 方法不生效\n- 修复 `n-timeline` 的 header 插槽 单独使用无效的问题\n- 修复 `n-select` 当属性是 `disabled` 和 `filterable` 时样式错误，关闭 [#698](https://github.com/tusen-ai/naive-ui/issues/698)\n- 修复 `n-upload` 拥有 `file-list` & `disabled` 属性时操作按钮仍然显示，关闭 [#668](https://github.com/tusen-ai/naive-ui/issues/668)\n\n## 2.15.9\n\n`2021-07-28`\n\n### Feats\n\n- `n-message` 增加 `destroyAll` 方法\n- `n-input-number` 增加 `prefix`、`suffix` 插槽 s，关闭 [#609](https://github.com/tusen-ai/naive-ui/issues/609)\n\n### Fixes\n\n- 修复 `n-message` 的 options 中 `duration` 配置无效\n\n## 2.15.8\n\n`2021-07-27`\n\n### Feats\n\n- `n-menu` 新增 `expand-icon` 属性，关闭 [#414](https://github.com/tusen-ai/naive-ui/issues/414)\n- `n-descriptions`，`n-descriptions-item` 增加 `label-style` 和 `content-style` 属性，关闭 [#536](https://github.com/tusen-ai/naive-ui/issues/536)\n\n### Fixes\n\n- 修复 `n-data-table` `n-spin`的样式穿透问题，关闭 [#663](https://github.com/tusen-ai/naive-ui/issues/663)\n\n## 2.15.7\n\n`2021-07-25`\n\n### Feats\n\n- `n-dropdown` 选项新增 `show-arrow`属性，关闭 [#647](https://github.com/tusen-ai/naive-ui/issues/647)\n- `n-time-picker` 增加 `actions` 属性，关闭 [#401](https://github.com/tusen-ai/naive-ui/issues/401)\n- `n-mention` 新增 `render-label` 属性\n- `n-switch` 增加 `checked`、`unchecked` 插槽\n- `n-switch` 增加 `loading` 属性，关闭 [#301](https://github.com/tusen-ai/naive-ui/issues/301)\n- `n-select` 按下箭头会打开菜单，有关 [#300](https://github.com/tusen-ai/naive-ui/issues/300)\n- `n-tree-select` 按下箭头会打开菜单，有关 [#300](https://github.com/tusen-ai/naive-ui/issues/300)\n- `n-cascader` 按下箭头会打开菜单，有关 [#300](https://github.com/tusen-ai/naive-ui/issues/300)\n- `n-popover` 的 `trigger` 属性支持 `'focus'`，关闭 [#477](https://github.com/tusen-ai/naive-ui/issues/477)\n- `n-message-provider` 新增 `duration` 和 `max` 属性\n- `n-data-table` 新增 `flex-height` 属性，关闭 [#596](https://github.com/tusen-ai/naive-ui/issues/596)\n\n### Fixes\n\n- 修复 `n-carousel` 中箭头按钮在特定浏览器下无法显示问题，关闭 [#625](https://github.com/tusen-ai/naive-ui/issues/625)\n- 修复 `n-layout-sider` `width` 不能为字符串，关闭 [#607](https://github.com/tusen-ai/naive-ui/issues/607)\n- 修复 `n-slider` `disabled` 属性不生效，关闭 [#641](https://github.com/tusen-ai/naive-ui/issues/641)\n- 修复 `n-input` 在只读时仍展示清除按钮\n- 修复 `n-data-table` 在 table-layout 为 auto 时不展示滚动条，关闭 [#518](https://github.com/tusen-ai/naive-ui/issues/518)\n- 修复 `n-data-table` 无数据时头部 checkbox 显示状态不正确\n- 修复 `n-data-table` header 和 body 滚动不同步\n\n## 2.15.6\n\n`2021-07-23`\n\n### Feats\n\n- `n-menu` 新增 `render-icon` 属性\n- `n-upload` 新增 `show-file-list` 属性\n- `n-dropdown` 新增 `render-icon` 属性\n- `n-checkbox-group` 新增 `min` 和 `max` 属性\n- `n-mention` 新增 `empty` 插槽\n- `useDialog` 选项新增 `on-mask-click`属性，关闭 [#419](https://github.com/tusen-ai/naive-ui/issues/419)\n- `n-space` `justify` 属性支持 `center`、`space-around` 和 `space-between`\n- `n-date-picker` 新增 `close-on-select` 属性，关闭 [#541](https://github.com/tusen-ai/naive-ui/issues/541)\n- `n-dialog` 新增 `action` 属性，关闭 [#550](https://github.com/tusen-ai/naive-ui/issues/550)\n- `n-mention` 的 `option.label` 支持使用渲染函数\n- `n-color-picker` 新增 `actions` 属性，关闭 [#319](https://github.com/tusen-ai/naive-ui/issues/319)\n\n### Fixes\n\n- 修复 `n-space` 中 `display: grid` 的元素显示不正确，关闭 `https://github.com/tusen-ai/naive-ui/issues/546`\n- 修复 `n-dropdown` 的 `render-label` 属性对 group 类型 option 失效\n- 修复 `n-datatable` 的 `scroll-x` 属性设置后 table 内容宽度未占满容器宽度，关闭 [#518](https://github.com/tusen-ai/naive-ui/issues/518)\n- 修复 `n-descriptions` 无法使用 `v-for` 的子元素\n- 修复 `n-dialog` `positive-text` 为空仍然显示按钮，关闭 [#549](https://github.com/tusen-ai/naive-ui/issues/549)\n- 修复 `n-pagination` `PaginationInfo` 的 `endIndex` 数据错误，关闭 [#584](https://github.com/tusen-ai/naive-ui/issues/584)\n- 修复 `n-data-table` `rowClassName` 的类型是 string 的时候不生效问题，关闭 [#582](https://github.com/tusen-ai/naive-ui/issues/582)\n\n## 2.15.5\n\n`2021-07-16`\n\n### Feats\n\n- `n-tree` 新增 `render-label`、`render-prefix` 和 `render-suffix` 属性\n- `n-rate` 新增 `allow-half` 属性\n- `n-carousel` 新增 `show-arrow` 属性\n- `n-slider` 新增 `format-tooltip` 属性\n- `n-upload` 在 `on-finish` 回调参数中新增 `event`\n- `n-rate` 新增 `readonly` 属性\n- `n-time-picker` 新增 `seconds`、`minutes`、`hours`属性\n- `n-notification` 导出 `NotificationApi`、`NotificationOptions` 和 `NotificationReactive` 类型\n- `n-avatar` 新增 `on-error` 属性，关闭[#394](https://github.com/tusen-ai/naive-ui/issues/394)\n- `n-image` 新增 `on-error` 属性，关闭[#394](https://github.com/tusen-ai/naive-ui/issues/394)\n- `n-image` 新增 `object-fit` 属性，关闭[#394](https://github.com/tusen-ai/naive-ui/issues/394)\n- `n-avatar` 新增 `object-fit` 属性，关闭[#394](https://github.com/tusen-ai/naive-ui/issues/394)\n- `n-menu` 默认展开选中项的全部父级，关闭[#481](https://github.com/tusen-ai/naive-ui/issues/481)\n\n### Fixes\n\n- 修复 `n-calendar` 的 `default-value` 属性无法使用\n- 修复 `n-pagination` `item-count` 为 0 时页数不对\n- 修复 `n-scrollbar` `content-style` 无法覆盖默认样式的宽度\n- 修复 `n-select` placeholder transition\n- 修复 `n-loading-bar` `useLoadingBar` 返回类型可能为 undefined\n- 修复 `n-tag` 的 `type` 增加 `primary`　类型\n- 修复 `n-dynamic-tags` 的 `type` 增加 `primary`　类型\n\n## 2.15.4\n\n`2021-07-09`\n\n### Feats\n\n- `n-steps` 新增 `'finish'` 和 `'error'` 状态下的图标定制\n- `n-tree` 导出 `TreeDragInfo` & `TreeDropInfo` 类型\n- `n-empty` 导出 `icon` 插槽\n- `useDialog` 选项增加 `maskClosable` 属性，关闭 [#420](https://github.com/tusen-ai/naive-ui/issues/420)\n\n### Fixes\n\n- 修复 `n-data-table` 在只有一侧固定列时固定列阴影不更新\n- 修复 `n-data-table` 在未设定 `props.scrollX` 但为每个列设定宽度后固定列阴影不更新\n- 修复 `n-result` 图片在 Safari 和手机端不显示\n- 修复 `n-drawer-content` 的 `header-style` 样式未应用于头部\n- 修复 `n-dialog` 实例调用 `destroy` 函数错误\n- 修复 `n-select` 自定义 label 的显示问题，关闭 [#352](https://github.com/tusen-ai/naive-ui/issues/352)\n- 修复 `n-image-group` 当切换图片预览时，初始化缩放比例 [#423](https://github.com/tusen-ai/naive-ui/issues/423)\n- 修复 `n-carousel` 设定 `autoplay` 点击后 dot active 状态不正常，关闭 [#434](https://github.com/tusen-ai/naive-ui/issues/434)\n- 修复 `n-input` 清空按钮位置引起的样式问题，关闭 [#428](https://github.com/tusen-ai/naive-ui/issues/428)\n- 修复 `n-image` 不接受 attributes\n- 修复 `n-image` 设定 border-radius 无效，关闭 [#427](https://github.com/tusen-ai/naive-ui/issues/427)\n- 修复 `n-tab-pane` 再没有子节点时报错\n- 修复 `n-select` clear 按钮在 `n-spin` 内过大，关闭 [#454](https://github.com/tusen-ai/naive-ui/issues/454)\n- 修复 `n-select` 选项没有被正常更新，关闭 [#441](https://github.com/tusen-ai/naive-ui/issues/441)\n\n## 2.15.3\n\n`2021-07-05`\n\n### Feats\n\n- `n-loading-bar` 导出 `LoadingBarApi` 类型\n- `n-image` 增加 `img-props` 属性\n- 在部分组件上添加原生 `title` 属性，以提高用户体验\n- `n-tree` 在 TreeOption 中增加 `prefix` 和 `suffix` 属性\n- `n-carousel` 增加 `dot-placement` 属性\n- `n-auto-complete` 新增 `loading` 属性，关闭 [#241](https://github.com/tusen-ai/naive-ui/issues/241)\n- `n-slider` 增加 `tooltip` 属性，关闭 [#362](https://github.com/tusen-ai/naive-ui/issues/362)\n- `n-input` 新增 `loading` 属性\n\n### Fixes\n\n- 修复 `n-upload` `multiple=false` 对于拖拽不生效，关闭 [#363](https://github.com/tusen-ai/naive-ui/issues/363)\n- 修复 `n-dropdown` 中 `<a />` 的样式\n- 修复 `n-menu` tooltip 中 `<a />` 的样式，关闭 [#338](https://github.com/tusen-ai/naive-ui/issues/338)\n- 修复 `n-carousel` 无法使用 `v-for` 的子元素\n- 修复 `n-form` `label-align` 属性失效，关闭 [#213](https://github.com/tusen-ai/naive-ui/issues/213)\n- 修复 `n-data-table` 在不设定 `max-height` 时固定列阴影失效，关闭 [#376](https://github.com/tusen-ai/naive-ui/issues/376)\n\n## 2.15.2\n\n`2021-07-02`\n\n### Feats\n\n- `n-carousel` 增加 `trigger` 属性增加触发切换的方式\n- `n-menu` 新增 `dropdown-placement` 属性\n- `n-upload` 新增 `before-upload` 属性\n- `n-image` 新增 `alt` 属性.\n- 支持小键盘的 enter 键\n- `n-spin` 支持 `icon` 插槽为了自定义加载图标，closes[#260](https://github.com/tusen-ai/naive-ui/issues/260)\n- `n-spin` 新增 `rotate` 属性控制自定义加载图标是否有旋转动画\n- `n-form` 导出 `FormItemRule` & `FormRules` 类型\n- `n-select` 新增 `render-tag` 属性\n\n### Fixes\n\n- 修复 `n-log` 在未设定语言时仍然对缺少 highlight.js 报错，关闭 [#327](https://github.com/tusen-ai/naive-ui/issues/327)\n- 移除 `n-calendar` 无用的 console.log\n- 修复 loading-bar 自动消失，关闭 [#343](https://github.com/tusen-ai/naive-ui/issues/343)\n- 修复 `n-select` 打开菜单时没有自动滚动到选中项，关闭 [#346](https://github.com/tusen-ai/naive-ui/issues/346)\n- 修复 `n-tab-pane` 在使用 v-if 时报错\n- 修复 `n-modal` `on-negative-click` 返回 false 时 modal 依然关闭\n- 修复 `n-collapse` 在 accordion 模式下默认指定展开属性无效，关闭 [#350](https://github.com/tusen-ai/naive-ui/issues/350)\n- 修复 `n-tag` 缺少 `on-update-checked` 属性\n- 修复 `n-menu` 折叠时 `render-label` 对于 dropdown 不生效\n\n## 2.15.1\n\n`2021-06-30`\n\n- 修复缺少 `web-types.json`\n\n## 2.15.0\n\n`2021-06-29`\n\n### Breaking Changes\n\n- `n-select` 的 `SelectOption` `render` 属性不再渲染 label 而是整个选项\n\n### Feats\n\n- `n-carousel` 支持触控操作，关闭 [#271](https://github.com/tusen-ai/naive-ui/issues/271)\n- `n-input` 新增 `input-props` 属性\n- `n-message` 优化 `useMessage` 当没有 `n-message-provider` 时的报错信息，增加关联的文档链接\n- 为 webstorm 添加 `web-types.json`，但是我还是推荐使用 VSCode 和 Volar，`web-types.json` 只能为编码提供很有限的信息\n- `n-tree-select` 新增 `leaf-only` 属性\n- `n-tree` 新增 `leaf-only` 属性\n- `n-select` 的 `SelectOption` 的 `label` 属性支持渲染函数\n- `n-select` 新增 `render-option` 属性\n- `n-select` 导出 `SelectOption` & `SelectGroupOption` 类型\n- `n-popover` 支持使用 `header` 插槽\n- `n-dropdown` 新增 `render-label` 属性\n\n### Fixes\n\n- 修复 `n-date-picker` `n-provider` 传递 `date-locale` 属性无效，关闭 [#250](https://github.com/tusen-ai/naive-ui/issues/250)\n- 修复 `n-input` clear button placeholder prevent clicking on actual component [#288](https://github.com/tusen-ai/naive-ui/issues/288)\n- 修复 `n-carousel` 点击当前页对应的控制按钮时，组件显示异常\n- 修复 `n-menu` 折叠时 `render-label` 对于 tooltip 不生效\n- 修复 `n-dropdown` 不能在选项中渲染 `n-popover`\n\n## 2.14.0\n\n`2021-06-23`\n\n### Breaking Changes\n\n- `n-element` 移除了 `abstract` 属性\n- `n-element` 不再在 default 插槽 返回主题变量，请使用 `useThemeVars` 代替\n\n### Feats\n\n- 新增 `n-carousel` 组件\n- 新增 `useThemeVars` 函数提供主题变量\n- `n-upload` 新增 `on-update:file-list` 属性，关闭 [#135](https://github.com/tusen-ai/naive-ui/issues/135)\n- `n-date-picker` 新增 `update-value-on-close` 属性\n\n### Fixes\n\n- 修复 `n-select` 在可过滤单选模式下在 iOS Safari 无法输入，关闭 [#230](https://github.com/tusen-ai/naive-ui/issues/230)\n- 修复 `n-input-number` 缺少 `on-update-value` 属性\n- 修复 `n-input-number` 值无法为 `null`\n- 修复 `n-input-number` 的按钮在值清空后无法使用，关闭 [#251](https://github.com/tusen-ai/naive-ui/issues/251)\n- 修复 `n-data-table` 展开图标光标样式不是 pointer，关闭 [#261](https://github.com/tusen-ai/naive-ui/issues/261)\n\n## Refactors\n\n- `n-input-number` 会直接聚焦，关闭 [#244](https://github.com/tusen-ai/naive-ui/issues/244)\n\n## 2.13.0\n\n`2021-06-21`\n\n### Feats\n\n- `n-dropdown` 新增 `on-clickoutside` 属性，关闭 [#123](https://github.com/tusen-ai/naive-ui/issues/123)\n- `n-menu` 新增 `render-label` 属性，关闭 [#84](https://github.com/tusen-ai/naive-ui/issues/84)\n- `n-tree` 支持键盘操作\n- 新增 `n-tree-select` 组件\n\n### Fixes\n\n- 修复 `n-tree` 缺少 `on-update-expanded-keys`、`on-update-selected-keys`、`on-update-checked-keys` 属性\n- 修复 `n-tree` 拖拽悬浮叶节点报错，关闭 [#200](https://github.com/tusen-ai/naive-ui/issues/200)\n- 修复 `n-tree` 对 `selected-keys` 属性影响原数组\n- 修复 `n-select` 在 multiple filterable 模式下输入框有无用的空行\n- 修复 `n-button` 的 loading 图标在 iOS Safari 上不显示，关闭 [#219](https://github.com/tusen-ai/naive-ui/issues/219)\n- 修复 `n-date-picker` 非 clearable 不显示图标\n- 修复 `n-time-picker` clearable 状态下图标位置不正确，关闭 [#222](https://github.com/tusen-ai/naive-ui/issues/222)\n\n## 2.12.2\n\n`2021-06-19`\n\n### Fixes\n\n- 修复 `n-form-item` 始终展示必需的星号\n\n## 2.12.1\n\n`2021-06-19`\n\n### Feats\n\n- `n-form`、`n-form-item` 增强 `show-require-mark` 属性，关闭 [#171](https://github.com/tusen-ai/naive-ui/issues/171)\n- `n-dropdown` 支持 class 属性，关闭 [#180](https://github.com/tusen-ai/naive-ui/issues/180)\n- `n-input` 新增 `show-password-toggle` 属性\n- `n-popselect` 支持 class 属性\n- `n-select` 新增 `render-label` 属性\n- `n-popselect` 新增 `render-label` 属性\n\n### Fixes\n\n- 修复 `n-input` 中英文字符切换输入时抖动，关闭[#174](https://github.com/tusen-ai/naive-ui/issues/174)\n- 修复 `n-icon` 在使用 setup script 时，`$parent` 默认是一个空对象，访问 `$parent.$options` 会是 `undefined`\n- 修复 `n-notification` 位置不正确\n- 修复 `n-message` 的 content & option 类型不正确\n\n## 2.12.0\n\n`2021-06-16`\n\n### Breaking Changes\n\n- 移除了 `n-a` 的 `to` 属性。现在如果你需要把 `n-a` 用作 router-link，你可以参考文档网站\n\n### Feats\n\n- `n-tree` 选项支持 `disabled` & `checkboxDisabled` 属性\n- `n-input-number` 支持键盘的上键和下键操作\n\n### Fixes\n\n- 修复 `n-cascader` 在 win10 Chrome 环境下文字模糊的问题\n- 修复 `n-tree` 在 block line 模式下点击缩进空白无法触发选择\n\n## 2.11.12\n\n`2021-06-16`\n\n### Feats\n\n- `n-drawer-content` 新增 `closable` 属性，关闭 [#139](https://github.com/tusen-ai/naive-ui/issues/139)\n- `n-element` 向 default 插槽 传递 `themeVars`\n- `n-element` 新增 `abstract` 属性\n\n### Fixes\n\n- 修复 `n-radio-group` 不触发 form-item 验证\n- 修复 `n-auto-complete` 无法自定义元素\n\n## 2.11.11\n\n`2021-06-15`\n\n### Feats\n\n- `n-tag` 添加 `RTL` 支持\n\n### Fixes\n\n- 将 `vue` 和 `vue-router` 移至 peer dependencies 避免重复打包\n\n## 2.11.9\n\n`2021-06-15`\n\n### Feats\n\n- `n-space` 支持 wai-aria\n- `n-button-group` 支持 wai-aria\n- `n-progress` 支持 wai-aria\n- `n-menu` 支持使用 `<a />` 和 `<router-link />` 作为 label，关闭 [#84](https://github.com/tusen-ai/naive-ui/issues/84)\n- `n-input-number` 新增 `show-button` 属性\n- `n-rate` 支持使用 default 插槽 自定义图标\n- `n-rate` 新增 color 属性\n- `n-rate` 新增 size 属性\n\n### Fixes\n\n- 修复 `n-card` 的 `header-style` 没有应用于 header 上 [#103](https://github.com/tusen-ai/naive-ui/issues/103)\n- 修复 `n-dialog` 的 `destroyAll` 方法缺失\n- 修复 `n-data-table` 缺少 `on-update-sorter`、`on-update-filters`、`on-update-page`、`on-update-page-size` 属性\n\n## 2.11.8\n\n`2021-06-13`\n\n### Feats\n\n- `n-data-table` 导出 `DataTableCreateRowClassName`、`DataTableCreateRowKey`、`DataTableCreateRowProps` 类型\n\n### Fixes\n\n- 修复 `n-calendar` 的 `on-update:value` 属性类型\n- 修复 `n-form-item` 的 `grid-template-columns` 样式属性对子元素布局的影响 [#93](https://github.com/tusen-ai/naive-ui/pull/93)\n- 修复 `n-data-table` 的 `rowKey`、`rowClassName`、`rowProps`、`summary` 属性类型和期望值不兼容\n\n## 2.11.7\n\n`2021-06-12`\n\n### Fixes\n\n- 修复 `n-slider` 在 touchstart 发生时没有阻止滚动\n- 修复 `n-color-picker` 默认值不跟随模式设定\n- 修复缺少 `lodash` & `lodash-es` 类型\n\n## 2.11.6\n\n`2021-06-11`\n\n### Feats\n\n- `n-spin` 的 `size` 属性支持 number 类型\n- `n-date-picker` 支持 `footer` 插槽\n\n### Fixes\n\n- 修正 `n-slider` 不支持触摸事件\n- 修正 `n-button` 在 head 内部的 script 被引入造成崩溃 [#68](https://github.com/tusen-ai/naive-ui/pull/68)\n- 修正 `n-spin` 动画闪烁\n- 修正 `n-menu` 缺少 `on-update-value` 和 `on-update-expanded-keys` 属性\n- 修正 `n-popconfirm` icon 插槽 不生效\n- 修正 `n-tabs` 在控制台输出无用信息\n- 修正 `n-color-picker` 设定 `modes` 无效 [#77](https://github.com/tusen-ai/naive-ui/issues/77)\n\n## 2.11.5\n\n`2021-06-10`\n\n### Feats\n\n- `n-dropdown` 新增 `disabled` 属性\n- `n-card` 增加 `:target` 的样式\n\n### Fixes\n\n- 修复 `n-popover` 有时在手动模式不会同步位置\n- 修复 `n-transfer` 的无数据 Icon 没有开关动画\n- 修复 `n-message` API 的 option 不是可选的\n- 修复 `n-calendar` 展示日期计算错误\n- 修复 `n-input` 缺失 `password` 的声明\n- 修复 `n-menu` 的菜单和子菜单的 `extra` 属性的类型定义\n- 修复 `n-dropdown` 选项鼠标形状不是 pointer\n\n## 2.11.4\n\n`2021-06-07`\n\n### Feats\n\n- `n-button` 支持 wai-aria\n- `n-card` 支持 wai-aria\n- `n-switch` 支持 wai-aria\n- `n-menu` 部分支持 wai-aria\n- `n-divider` 部分支持 wai-aria\n- `n-data-table` 新增 `row-props` 属性\n- `n-date-picker` 新增 `ranges` 属性\n\n### Fixes\n\n- 修正 `n-tab-pane` `display-directive` 不生效\n- 修正 `n-drawer` 动画\n- 修正 `n-scrollbar` 在 windows chrome 有重叠轨道\n\n## 2.11.3\n\n`2021-06-05`\n\n### Fixes\n\n- 修复 `n-collapse` `default-expanded-names` 不生效\n\n## 2.11.2\n\n`2021-06-05`\n\n### Fixes\n\n- 修复 `n-dropdown` 默认位置不是 `bottom`\n- 修复 `n-date-picker` 输入组件在 `date` & `datetime` 类型下未设定主题\n- 修复 `n-config-provider` 没有合并继承的主题\n\n### Feats\n\n- `n-collapse` 新增 `arrow` 插槽\n\n## 2.11.1\n\n`2021-06-05`\n\n更新 package.json & README.md\n\n## 2.11.0\n\n`2021-06-05`\n\n### Breaking Changes\n\n- `n-affix` 的 `listen-to` 属性默认为 `document` (曾为首个可滚动的父节点)\n\n### Feats\n\n- `n-affix` 的 `listen-to` 属性支持 `Window | Document | HTMLElement`\n- `n-anchor` 新增 `offset-target` 属性\n- `n-select` 新增 `virtual-scroll` 属性\n- `n-select` 新增 `consistent-menu-width` 属性\n- `n-date-picker` 在确认后再更新值\n\n### Fixes\n\n- 修正 `n-date-picker` 在没有值的状态下起始日期 disabled 状态不正确\n- 修正 `n-input-number` 在 blur 后不会恢复有效的值\n- 修正 `n-date-picker` 在值为 null 的时候仍然显示选中日期\n\n### Deprecated\n\n- 废弃了 `n-affix` 的 `offset-top` 属性，请使用 `trigger-top` 代替\n- 废弃了 `n-affix` 的 `offset-bottom` 属性，请使用 `trigger-bottom` 代替\n- 移除了 `n-anchor` 的 `listen-to` 属性\n\n## 2.10.0\n\n`2021-05-26`\n\n### Breaking Changes\n\n- `n-popover` 的 `placement` 属性默认值设为 `'top'`\n\n### Feats\n\n- `n-tabs` 新增 `on-close` 属性\n- `n-tabs` 新增 `on-add` 属性\n- `n-tab-pane` 新增 `tab` 插槽\n- `n-tab-pane` 的 `tab` 属性支持渲染函数和 VNode\n- `n-tabs` 的 `type` 新增 `'line'` 选项\n- `n-tabs` 添加阴影来展示滚动状态\n- `n-tabs` 新增 `pane-style` 属性\n\n### Fixes\n\n- 修正 `n-layout` `scrollTo` 方法在原生滚动时不生效\n\n### Deprecated\n\n- `n-tab-pane` 的 `label` 属性被废弃，请使用 `tab` 属性代替\n\n## 2.9.0\n\n`2021-05-25`\n\n### Breaking Changes\n\n- `n-layout-sider` 移除了 `show-content`，使用 `show-collapsed-content` 代替\n\n### Feats\n\n- `n-data-table` 支持树形数据\n- `n-data-table` 新增 `cascade` 属性\n- `n-data-table` 新增 `children-key` 属性\n- `n-data-table` 新增 `indent` 属性\n- `n-button` 新增 `tag` 属性\n- `n-data-table` 新增 `table-layout` 属性\n- `n-tree` 新增 `block-line` 属性\n- `n-tree` 支持拖放\n- `n-menu` 新增 `inverted` 属性\n- `n-dropdown` 新增 `inverted` 属性\n- `n-tabs` 新增 `addable` 属性\n- `n-tabs` 新增 `tab-style` 属性\n- `n-tabs` 新增 `tabs-padding` 属性\n- `n-tabs` 新增 `default-value` 属性\n- `n-layout-sider` & `n-layout-footer` & `n-layout-header` 新增 `inverted` 属性\n- `n-data-table` 的 `max-height` & `min-height` 属性接受 CSS 属性\n- `n-layout` & `n-layout-content` 新增 `embedded` 属性\n\n### Fixes\n\n- `n-layout` & `n-layout-sider` 的 `scrollTo` 在使用原生滚动条时不生效\n- `n-layout-sider` 的 `collapse-mode` 属性不生效\n- 内部 selection 组件的主题 peers 中 popover 的 key 不正确\n\n## 2.8.0\n\n`2021-05-19`\n\n### Perf\n\n- 优化 `n-data-table` 初始渲染次数\n- 优化 `n-select` 首次打开后打开用时\n- 优化 `n-anchor` 滚动性能\n\n### Feats\n\n- `n-tree` 新增 `virtual-scroll` 属性\n- `n-data-table` 新增 `virtual-scroll` 属性\n- `n-cascader` 新增 `virtual-scroll` 属性\n- `n-pagination` 新增 `item-count` 属性\n- `n-pagination` 新增 `prefix` 属性\n- `n-pagination` 新增 `prefix` 插槽\n- `n-pagination` 新增 `suffix` 属性\n- `n-pagination` 新增 `suffix` 插槽\n- `n-input` 新增 `show-count` 属性\n\n### Fixes\n\n- 修正 `n-layout-sider` 折叠后不显示菜单\n- 修正 `n-input-number` 在输入不合法 blur 时没有重设回原始值\n- 修正 `n-pagination` 在非受控模式下不更新页数\n\n## 2.7.4\n\n`2021-04-25`\n\n### Feats\n\n- `n-form-item` 可以在 `n-form` 外使用\n\n### Fixes\n\n- 修正 `n-checkbox` 勾选图标不显示\n- 修正 `n-date-picker` 触发器的图标 transition 效果\n- 修正 `n-p`、`n-ol`、`n-ul` 作为最后一个子元素 margin bottom 不是 0\n- 修正 `n-checkbox-group` 在非受控模式不工作\n- 修正 `n-data-table` 取消全部选择不工作\n\n## 2.7.3\n\n`2021-04-22`\n\n### Feats\n\n- `n-data-table` 高亮排序列\n- `n-data-table` 列增加 `render-filter` 属性\n- `n-data-table` 列增加 `render-filter-icon` 属性\n\n### Fixes\n\n- `n-data-table` 固定列 box-shadow 在暗色模式更明显\n- 修正 `n-color-picker` 值折行\n- 修正 `n-form` FormRuleItem.trigger 类型\n\n## 2.7.2\n\n`2021-04-21`\n\n### Feats\n\n- `n-data-table` 增加 `summary` 属性\n- `n-data-table` 在 `'type=selection'` 的列增加 `options` 选项\n\n### Fixes\n\n- Fix `n-layout` 横向溢出的问题\n\n## 2.7.1\n\n`2021-04-20`\n\n### Feats\n\n- `n-checkbox` 增加 `focusable` 属性\n- `n-cascader` 增加 `action` 插槽\n\n### Fixes\n\n- 修正 `n-cascader` 点击 checkbox 会触发 loading\n- 修正 `n-cascader` 菜单遮罩样式\n\n## 2.7.0\n\n`2021-04-19`\n\n### Breaking Changes\n\n- `n-drawer` 默认不再包含 padding，填充 drawer 的内容可以使用 `n-drawer-content`\n\n### Feats\n\n- `n-drawer` 增加 `content-style` 属性\n- `n-layout` 增加 `content-style` 属性\n- `n-layout-sider` 增加 `content-style` 属性\n\n## 2.6.0\n\n`2021-04-19`\n\n### Feats\n\n- `n-config-provider` 增加 `cls-prefix` 属性\n\n### Fixes\n\n- 修正 `n-popover` 在静态提升时可能影响别的 popover 的问题\n\n## 2.5.1\n\n`2021-04-14`\n\n### Feats\n\n- `n-color-picker` 增加 `show-alpha` 属性\n\n### Fixes\n\n- 修正 `n-select` 默认 `fallback-option` 属性使组件崩溃\n\n## 2.5.0\n\n`2021-04-13`\n\n### Feats\n\n- 添加 `n-skeleton` 组件\n- 添加 `n-calendar` 组件\n- 添加 `n-color-picker` 组件\n- `n-date-picker` locale 增加 `firstDayOfWeek`\n- `n-select` 增加 `showArrow` 属性\n\n### Fixes\n\n- 修正 `n-date-picker` 触发器在焦点在面板内的时候没有 focus 样式\n- 修正 `n-button` 加载状态宽度闪烁的问题\n- 修正 `n-time-picker` 在 `n-date-picker` 内部关闭动画闪烁的问题\n- 修正 popover 内部的卸载组件应卸载于 popover 内部\n\n## 2.4.2\n\n`2021-04-08`\n\n### Feats\n\n- 添加 `n-form-item-gi` 组件\n\n### Fixes\n\n- 修正 `n-ellipsis` & `n-data-table` ellpisis 单元格文本垂直排列错位\n- 修正 `n-select` 在输入法输入过程中就进行过滤\n\n## 2.4.1\n\n`2021-04-07`\n\n### Fixes\n\n- 修正 `n-select` 单选过滤模式的光标颜色\n- 修正 `n-select` 菜单的 action 部分不能 focus\n\n## 2.4.0\n\n`2021-04-07`\n\n### Feats\n\n- 添加 `n-image` 组件\n- 添加 `n-global-style` 组件\n- 添加 `n-theme-editor` 组件\n- 添加 `n-page-header` 组件\n- `n-statistic` 增加 `label` 插槽\n- `n-breadcrumb-item` 增加 `separator` 插槽 & prop\n- `n-button` 增加 `bordered` prop\n- `n-card` 增加 `footer-style` prop\n\n### Refactors\n\n- 重构 `n-statistic` 样式\n- `n-menu` 增加 `options` prop 去替代 `items` prop，`items` prop 被废弃\n\n### Fixes\n\n- 修正 `n-anchor` `ignore-gap` 不生效的问题\n- 修正 `n-collapse` 内容被 `overflow: hidden` 截断\n- 修正 `n-select` tag 文本溢出\n- 修正 `n-popover` 在移动端无法正常关闭的问题\n\n## 2.3.1\n\n`2021-03-29`\n\n### Fixes\n\n- 修正 `n-layout-sider` 横向宽度溢出\n\n## 2.3.0\n\n`2021-03-29`\n\n### Breaking Changes\n\n- 折叠对于 `position=\"absolute\"` 的 `n-layout-sider` 不再生效\n- 对于包含 `n-layout-sider` 的 `n-layout` 必须设定 `has-sider`\n\n## 2.2.0\n\n`2021-03-29`\n\n### Feats\n\n- 新增 `n-mention` 组件\n- `n-data-table` 支持行展开\n\n### Fixes\n\n- 修正 `n-input` 在暗色主题 focus 状态下的背景颜色在 warning 和 error 的状态不正确\n- 修正 `n-input` 在 warning 和 error 状态下光标颜色不正确\n- 修正 `n-select` 的 namespace 不正确\n- 修正 `n-cascader` 的 namespace 不正确\n- 修正 `n-input` 在 textarea 模式无法选中\n- 修正 `n-input` 在 textarea 模式没有 box-shadow\n- 修正 `n-input` 在 textarea 模式 `autosize` 由于字体不一致导致行数有误\n- 修正 `n-input` 在 textarea 模式 `autosize` 在外部使 props.value 改变的时候行数不会变化\n\n### Refactors\n\n- 替换了 `n-empty` 的图标 & 增大了它的尺寸\n\n## 2.1.3\n\n`2021-03-25`\n\n### Fixes\n\n- 修正 `n-data-table` 对于不是最后一个的 td 没有右侧边框\n- 修正 `n-data-table` 头部在表格宽度大于 `scroll-x` 的时候不够宽\n\n## 2.1.2\n\n`2021-03-24`\n\n### Feats\n\n- `n-data-table` column 新增 `colSpan` 和 `rowSpan` 属性\n- `n-data-table` column 新增 `titleColSpan` 属性\n\n### Fixes\n\n- 修正 `n-dropdown` 在设定 `x` 和 `y` 之后鼠标在外面移动会报错\n\n## 2.1.1\n\n`2021-03-22`\n\n### Fixes\n\n- 修正 `n-select` 选择器溢出计数器 popover 触发区域有误\n\n## 2.1.0\n\n`2021-03-22`\n\n### Breaking Changes\n\n- `n-popover` 默认 `duration` 设为 `100`\n- `n-popover` 默认 `delay` 设为 `100`\n- `n-tooltip` 默认 `showArrow` 设为 `true`\n\n### Feats\n\n- `n-config-provider` 的 `theme-overrides` 支持继承\n- `n-card` 新增 `hoverable` 属性\n- `n-select` 新增 `max-tag-count` 属性\n- `n-cascader` 新增 `max-tag-count` 属性\n- `n-popover` 新增 `get-disabled` 属性\n- 新增 `n-ellipsis` 文本省略组件\n- `n-popover` `width` prop 新增 `'trigger'` 的值\n- `n-data-table` 的列的 `ellipsis` 属性可设为 `n-ellipsis` 的 props\n\n### Fixes\n\n- 修正 `n-cascader` 再点击清除按钮后菜单出现\n- 修正 `n-card` 设定高度后 action 不在底部的问题\n- 修正 `n-popover` 的 `duration` 和 `delay` 属性执行有问题\n\n## 2.0.1\n\n`2021-03-17`\n\n### Feats\n\n- `n-layout-sider` 新增 `default-collapsed` 属性\n- `n-modal` 支持自定义位置\n\n### Fixes\n\n- 修正 `n-menu` 垂直折叠时 `n-menu-item` tooltip 不显示的问题\n- 修正 `n-menu` `collapsed-icon-size` 不生效的问题\n- 修正 `n-menu` 回调类 prop 不接受数组\n- 修正 `n-layout-sider` 按钮被遮挡的问题\n\n## 2.0.0\n\n`2021-03-15`\n\n参考 vue3.md\n\n## 1.6.0\n\n`2020-10-23`\n\n### Fixes\n\n- 修正了 `n-auto-complete` 使用 `textarea` 作为输入元素时菜单无法关闭的问题\n- 修正了嵌套 `n-icon` 没有被打平的问题\n- 修正了 `n-date-picker` 在类型为 `date` 和 `datetime` 时面板不显示年的问题\n\n### Feats\n\n- `n-button` 增加 `dashed` 属性\n- 增加 `n-space` 组件\n- `n-drawer` 内容可滚动\n\n### i18n\n\n- `n-log` 添加 zhCN 本地化\n\n## 1.5.5\n\n`2020-08-15`\n\n### Breaking Changes\n\n- 修正了所有 `separator` 的拼写（原来错拼为 `seperator`）\n\n### Fixes\n\n- 修正了未设定主题时样式报错的问题\n- 修正了 `n-select` `single` `filterable` 时 placeholder 的样式问题\n\n## 1.5.4\n\n`2020-08-08`\n\n### Fixes\n\n- 修正了 Message、Notification、Confirm 不随主题切换的问题\n\n## 1.5.3\n\n`2020-07-23`\n\n### Fixes\n\n- 修正了 `n-select` 在 `placeholder` 为空的时候显示出错的问题\n\n## 1.5.2\n\n`2020-07-22`\n\n### Fixes\n\n- 修正了 `n-radio` 无法聚焦的问题\n- 修正了 `n-data-table` 的 `max-height` 样式失效的问题 <https://bugs.chromium.org/p/chromium/issues/detail?id=1107223>\n\n### Refactors\n\n- 重构了 `n-tag` 的样式\n\n## 1.5.1\n\n`2020-07-20`\n\n### Feats\n\n- 为 `n-time-picker` 增加了 `disabled` 属性\n\n### Fixes\n\n- 修正了 `n-radio` 下的子元素无法获取焦点的问题\n\n## 1.5.0\n\n`2020-07-09`\n\n### Breaking Changes\n\n- 重构了试验性的设定主色功能\n\n### Fixes\n\n- 修正了一些零碎的样式错误\n\n## 1.4.1\n\n`2020-06-23`\n\n### Feats\n\n- 为 `n-select` 增加了 `autofocus` 属性\n\n## 1.4.0\n\n`2020-06-19`\n\n### Breaking Changes\n\n- `n-menu` 不再支持 插槽 API\n\n### Feats\n\n- 增加了试验性的设定主色功能\n\n## 1.3.5\n\n`2020-06-06`\n\n### Feats\n\n- 为 `n-button` 增加了 `attr-type` 属性\n\n### Fixes\n\n- 修正了 `n-input` 如果太宽里面的 input 元素宽度不会展开的问题\n- 修正了 `n-input-group` 中 `n-input-number` 边框的样式瑕疵\n\n## 1.3.4\n\n`2020-06-05`\n\n### Fixes\n\n- 修正了 `n-a` 的 `to` 属性不能为对象的问题\n\n## 1.3.3\n\n`2020-06-03`\n\n### Feats\n\n- 增加了 `$NOs.theme` 来获取当前操作系统的主题\n\n## 1.3.2\n\n`2020-06-02`\n\n### Fixes\n\n- 修正了 `n-log` 的加载器显示等宽字体的问题\n- 修正了 `n-button` icon 有关的类名没有被正确应用的问题\n\n## 1.3.1\n\n`2020-06-01`\n\n### Fixes\n\n- 修正了 `n-data-table` 选框列的选框没有垂直居中的问题\n- 修正了 `n-data-table` 表头没 border-color transition 的问题\n- 修正了 `$NConfirm` 的 `show-icon` & `closable` & `bordered` 属性设置无效的问题\n\n### Feats\n\n- 增加并调整了一些 `n-config-consumer` 样式方案中的颜色\n\n## 1.3.0\n\n`2020-06-01`\n\n### Breaking Changes\n\n- UI 默认样式不再包含外部字体文件，如果需要使用 UI 提供的字体需要明确引入\n\n### Feats\n\n- 为 `n-layout` 增加了 `themed-style` 属性\n\n### Fixes\n\n- 修正了 `n-layout-sider` 圆形按钮没有随着折叠状态滚动的问题\n- 修正了 `n-form-item` feedback 如果在一开始被设定则消失没有动画的问题\n- 修正了 `n-data-table` max-height 相关属性在所有情况下都会被应用的问题\n- 修正了一些组件的样式瑕疵\n\n### Refactors\n\n- 调整了一些组件亮色主题下的样式\n\n## 1.2.1\n\n`2020-05-29`\n\n### Fixes\n\n- 修正了 `n-slider` 弹框没有 z-index 的问题\n\n## 1.2.0\n\n`2020-05-29`\n\n### Feats\n\n- 为 `n-form-item` 增加了 `feedback` 和 `validation-status` 属性\n\n## 1.1.5\n\n`2020-05-28`\n\n### Feats\n\n- 为 `n-collapse` 和 `n-collapse-item` 增加了 `display-directive` 属性\n- 为 `n-select` 的 `option` 增加了 `class` 和 `style` 属性\n- 为 `n-select` 增加 `debug` 模式\n\n### Fixes\n\n- 修正了 `n-select` 在 disabled 状态下能被清除的问题\n\n## 1.1.4\n\n`2020-05-28`\n\n### Fixes\n\n- 修正了 `n-select` 在多选情况下传入值被直接修改的问题\n\n### Refactors\n\n- 一个 UI 实例最多在一个 Vue 上安装一次\n\n## 1.1.3\n\n`2020-05-20`\n\n### Chores\n\n- 更新 css-render 的依赖\n\n### Fixes\n\n- 修正了 `n-transfer` 在值改变时动画出错的问题\n\n## 1.1.2\n\n`2020-05-19`\n\n### Feats\n\n- 为 `n-step` 增加内容的 插槽\n- 为 `n-checkbox` 增加了 `label` prop\n\n### Performance Improvements\n\n- 所有定位组件按需注册监听器\n- 在寻找可滚动节点的过程中使用缓存\n- 提升了 `n-button` beforeDestroy 的性能\n- 减少了 `n-checkbox` 在值未改变时的重复渲染\n- 提升了文字内容的 `n-avatar` 的性能\n\n## 1.1.1\n\n`2020-05-18`\n\n### Fixes\n\n- 更新 css-render 的依赖\n- 默认类型的按钮的 icon 的颜色\n\n### Performance Improvements\n\n- 减少了 `n-menu-item` 没用的重复渲染\n- 减少了文档页面没用的重复渲染\n\n### Refactors\n\n- 为了性能重构了 `n-nimbus-service-layout` 的部分代码\n\n## 1.1.0\n\n`2020-05-16`\n\n### Feats\n\n- `n-button` 接受自定义颜色\n\n### Refactors\n\n- 将内部所有使用 $插槽 s 的地方换为 $scopedSlots 来获得更好的鲁棒性\n- 将部分按钮样式生成转移到组件内动态进行\n\n## 1.0.14\n\n`2020-05-15`\n\n### Fixes\n\n- 修正了 `line` 型 `n-tabs` 线不随 `activeName` 属性改变的问题\n- 修正了 `n-tabs` 滚动按钮没有随着宽度改变触发的问题\n- 修正了 `n-tabs` 高度变化会导致一些不期望的调用的问题\n\n## 1.0.13\n\n`2020-05-14`\n\n### Fixes\n\n- 修正 `n-form-item-col` & `n-form-item-row` 的 label 插槽 不显示的问题\n\n## 1.0.12\n\n`2020-04-30`\n\n### Fixes\n\n- 修正了一些 CSS 长度属性格式化错误的问题\n\n## 1.0.11\n\n`2020-04-30`\n\n### Feats\n\n- 为 `n-select` 增加了 `fallback-option` 属性用于控制无对应选项时的回退选项\n\n### Fixes\n\n- 解决了 `n-data-table` 在没有数据时 `max-height` 和 `min-height` 错误显示的问题\n\n### Breaking Changes\n\n- `n-data-table` 的 `max-height` 和 `min-height` 会对表格部分的整体生效，不只是表格的内容部分\n- `n-select` 在默认情况下会显示选项中不存在的值\n\n## 1.0.10\n\n`2020-04-28`\n\n### Feats\n\n- 为 `n-collapse` 增加了 `arrow-placement` 属性\n- 为 `n-collapse-item` 增加了`arrow` 插槽\n\n### Fixes\n\n- 解决了可卸载组件在嵌套成 `modal > drawer > component` 样子的时候会被卸载到错误位置的问题\n\n## 1.0.9\n\n`2020-04-23`\n\n### Feats\n\n- 为 `n-input` 增加了 `autofocus` 选项\n- 为 `NMessage` 增加了 `closable` 选项\n\n### Fixes\n\n- 解决了 `n-tag` `closable` 默认值被设为 `true` 的问题\n- 解决了 `n-data-table` 不能使用全部 `pagination` prop 的问题\n- 解决了 `n-pagination` `on-page-size-change` 不生效的问题\n\n## 1.0.8\n\n`2020-04-22`\n\n### Feats\n\n- 增加 `n-dynamic-tags` 组件\n- `styleScheme` 新增暴露颜色 `tableHeaderOverlayBackgroundColor` & `inputOverlayBackgroundColor`\n\n## 1.0.7\n\n`2020-04-10`\n\n### Feats\n\n- 为 `n-data-table` 的 `column` 增加了 `filter-option-value` 的属性来应对单选的情况\n\n### Fixes\n\n- 解决了 `n-collpase-item` 不支持 `number` 的问题\n\n## 1.0.6\n\n`2020-04-03`\n\n### Fixes\n\n- 解决了所有的 `console` 语句都在打包中被删除了的问题\n\n## 1.0.5\n\n`2020-03-27`\n\n### Feats\n\n- 改变 `n-data-table` 的 filters 的数据类型从数组改变成对象\n\n### Fixes\n\n- `n-data-table` 在有多列筛选的情况下数据不能被正确筛选\n\n## 1.0.4\n\n`2020-03-26`\n\n### Feats\n\n- 当选项过多时，`n-data-table` 过滤菜单的内容可以滚动\n\n## 1.0.3\n\n`2020-03-25`\n\n### Feats\n\n- `$NMessage`、`$NNotification`、`$NConfirm` 的获取到的主题会应用到他们的内部组件\n\n### Fixes\n\n- 多个 naive-ui 共存时定位元素会产生冲突\n- `n-form-item` 的 validate 方法在某些 validator 的返回值下不会 resolve\n- `$NConfirm` 主题未随 `n-config-provider` 切换\n\n## 1.0.2\n\n`2020-03-23`\n\n### Fixes\n\n- `n-transfer` 的选项在值变化之后没有重置\n- `n-nimbus-service-layout` (deprecated) 没有兼容 Vue Router(3.1 版本以下) `push` 方法的返回值\n\n## 1.0.1\n\n`2020-03-21`\n\n### Feats\n\n- `n-layout-sider` 的 `show-trigger` 增加了 `'bar'` & `'arrow-circle'` 选项\n\n### Fixes\n\n- `n-scrollbar` 的轨道会挡住鼠标事件\n\n### Feats\n\n- `n-data-table` 增加了 empty 插槽 [#86](https://github.com/tusen-ai/naive-ui/issues/86)\n"
  },
  {
    "path": "CONTRIBUTING.md",
    "content": "# Contributing\n\n- For new features & bug fixes, please create pull request to `main` branch.\n- For documentation, please create pull request to `docs` branch.\n\n## Useful Commands\n\n```bash\n# open the dev server, please note that hot module reload doesn't work well\n# if you find anything doesn't work, just refresh the page\n# if you aren't able to open the page at the first time, try to refresh a couple of times\n# pnpm version 7.0.0 and above is required\npnpm run dev\n\n# testing\npnpm run test\n\n# testing some component\npnpm run test -- src/xxx\n\n# testing with coverage\npnpm run test:cov\n\n# lint code\npnpm run lint:code\n\n# check type\npnpm run lint:type\n\n# lint code & type\npnpm run lint\n\n# build site (if site build failed, you might need to run `git clean -fdx` first)\npnpm run build:site\n```\n\n## About Docs and Changelog Format\n\n- Add period `.` to each description in English API tables (and each log of changelogs).\n- Don't add period `。` in any description in Chinese API tables (and any log of changelogs).\n- Add space between Chinese and Latin charactors.\n- Don't use Chinese punctuation in English docs.\n- Don't write changelogs in a released version.\n- When rebase the branch, pay attention to whether it is placed in the released version.\n- Add NEXT_VERSION to the version of the API table.\n\nFor Example:\n\n```\nEnglish API table:\n| Name | Type | Default | Description | Version |\n| --- | --- | --- | --- | --- |\n| example | `any` | `undefined` | Need period. | NEXT_VERSION |\n\nChinese API table:\n| 名称 | 类型 | 默认值 | 说明 | 版本 |\n| --- | --- | --- | --- | --- |\n| example | `any` | `undefined` | 描述不要加句号 | NEXT_VERSION |\n\nEnglish Changelog:\n- Some changes, period needed.\n\nChinese Changelog:\n- 一些变更，不要加句号\n\nSpace between Chinese and Latin charactors:\n星之 star 卡比 kirby\n\nChangelog position:\n\n# CHANGELOG\n\n## NEXT_VERSION\n\n### Feats\n\nyour changelog\n\n### Fixes\n```\n"
  },
  {
    "path": "CONTRIBUTING.zh-CN.md",
    "content": "# 贡献代码\n\n- 对于新特性和 bug fix，请对 `main` 分支提交 Pull Request\n- 对于文档更新，请对 `docs` 分支提交 Pull Request\n\n## 有用的指令\n\n```bash\n# 开启开发服务器，注意热更新不是很好用\n# 如果你觉得哪里有问题，刷新页面即可\n# 第一次运行打不开时，你可以试试刷新几次浏览器\n# 需要 pnpm 在 7.0.0 及以上版本\npnpm run dev\n\n# 测试\npnpm run test\n\n# 测试某个组件\npnpm run test -- src/xxx\n\n# 生成覆盖率报告\npnpm run test:cov\n\n# 检查代码风格\npnpm run lint:code\n\n# 检查类型\npnpm run lint:type\n\n# 上面俩个都检查\npnpm run lint\n\n# 构建文档网站（如果网站构建失败了，你可能需要先运行一下 `git clean -fdx`）\npnpm run build:site\n```\n\n## 关于文档和变更日志的格式\n\n- 每一条英文的变更日志和英文的 API 表中的 description 都需要加英文句号 `.`\n- 不要在中文 API 表和中文的变更日志中加句号\n- 在每一个中文和拉丁字母（数字）之间要加空格\n- 不要在英文文档中使用中文标点\n- 不要写在已经发布的版本中\n- rebase 分支时注意是否放到已发布的版本中\n- 添加 NEXT_VERSION 到 API 表格的版本上\n\n例如:\n\n```\n英文 API 表格：\n| Name | Type | Default | Description | Version |\n| --- | --- | --- | --- | --- |\n| example | `any` | `undefined` | Need period. | NEXT_VERSION |\n\n中文 API 表格：\n| 名称 | 类型 | 默认值 | 说明 | 版本 |\n| --- | --- | --- | --- | --- |\n| example | `any` | `undefined` | 描述不要加句号 | NEXT_VERSION |\n\nEnglish Changelog:\n- Some changes, period needed.\n\nChinese Changelog:\n- 一些变更，不要加句号\n\n中英文之间要加空格：\n星之 star 卡比 kirby\n\nChangelog 位置：\n\n# CHANGELOG\n\n## NEXT_VERSION\n\n### Feats\n\n你的 changelog\n\n### Fixes\n```\n"
  },
  {
    "path": "LICENSE",
    "content": "MIT License\n\nCopyright (c) 2021 TuSimple\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": "<p align=\"center\">\n  <img width=\"144px\" src=\"https://naiveui.oss-cn-hongkong.aliyuncs.com/naivelogo.svg\" />\n</p>\n\n<h1 align=\"center\">Naive UI</h1>\n<p align=\"center\">A Vue 3 Component Library</p>\n<p align=\"center\"><b>Fairly Complete, Theme Customizable, Uses TypeScript, Fast</b></p>\n<p align=\"center\">Kinda Interesting</p>\n\n<p align=\"center\">\n  <a href=\"https://npmjs.com/package/naive-ui\">\n    <img src=\"https://img.shields.io/npm/v/naive-ui.svg\" alt=\"npm\">\n  </a>\n  <a href=\"https://pkg.pr.new/~/tusen-ai/naive-ui\">\n    <img src=\"https://pkg.pr.new/badge/tusen-ai/naive-ui\" alt=\"pkg.pr.new\">\n  </a>\n</p>\n\n<p align=\"center\">English | <a href=\"README.zh-CN.md\">中文</a></p>\n\n## Documentation\n\n[www.naiveui.com](http://www.naiveui.com)\n\n## Community\n\n- [Discord](https://discord.gg/Pqv7Mev5Dd)\n- DingTalk Group 1 (Member limit reached) 33482509\n- DingTalk Group 2 (Member limit reached) 35886835\n- DingTalk Group 3 (Member limit reached) 32377370\n- DingTalk Group 4 (Member limit reached) 8165002788\n- DingTalk Group 5 (Member limit reached) 31205022250\n- DingTalk Group 6 (Member limit reached) 62720001971\n- DingTalk Group 7 172000005810\n\n- [Awesome Naive UI](https://github.com/naive-ui/awesome-naive)\n\n## Features\n\n### Fairly Complete\n\nThere are more than 90 components. Hope they can help you write less code.\n\nWhat's more, they are all treeshakable.\n\n### Theme Customizable\n\nWe provide an advanced type safe theme system built using TypeScript. All you need is to provide a theme overrides object in JS. Then all the stuff will be done by us.\n\nWhat's more, no less/sass/css variables, no webpack loaders are required.\n\n### Uses TypeScript\n\nAll the stuff in Naive UI is written in TypeScript. It can work with your typescript project seamlessly.\n\nWhat's more, you don't need to import any CSS to use the components.\n\n### Fast\n\nI try to make it not rather slow. All data components works with virtual list by default.\n\nWhat's more, ..., no more. Just enjoy it.\n\n## Installation\n\n### npm\n\nUse npm to install.\n\n```bash\nnpm i -D naive-ui\n```\n\n### Fonts\n\n```bash\nnpm i -D vfonts\n```\n\n### Icons\n\nNaive UI recommends using [xicons](https://www.xicons.org) as icon library.\n\n### Design Resources\n\n[Naive UI (Sketch)](https://naive-ui.oss-accelerate.aliyuncs.com/NaiveUI-Design-Library-en-US.sketch).\n\n## Contributing\n\nPlease see [CONTRIBUTING.md](https://github.com/tusen-ai/naive-ui/blob/main/CONTRIBUTING.md).\n\n## License\n\nNaive UI is licensed under the [MIT license](https://opensource.org/licenses/MIT).\n\nGraphics resources of `result` component is licensed under the [CC-BY 4.0](https://creativecommons.org/licenses/by/4.0/). The graphics resources come from [Twemoji](https://github.com/twitter/twemoji).\n"
  },
  {
    "path": "README.zh-CN.md",
    "content": "<p align=\"center\">\n  <img width=\"144px\" src=\"https://naiveui.oss-cn-hongkong.aliyuncs.com/naivelogo.svg\" />\n</p>\n\n<h1 align=\"center\">Naive UI</h1>\n<p align=\"center\">一个 Vue 3 组件库</p>\n<p align=\"center\"><b>比较完整，主题可调，使用 TypeScript，快</b></p>\n<p align=\"center\">有点意思</p>\n\n<p align=\"center\">\n  <a href=\"https://npmjs.com/package/naive-ui\">\n    <img src=\"https://img.shields.io/npm/v/naive-ui.svg\" alt=\"npm\">\n  </a>\n  <a href=\"https://pkg.pr.new/~/tusen-ai/naive-ui\">\n    <img src=\"https://pkg.pr.new/badge/tusen-ai/naive-ui\" alt=\"pkg.pr.new\">\n  </a>\n</p>\n\n<p align=\"center\"><a href=\"README.md\">English</a> | 中文</p>\n\n## 文档\n\n[www.naiveui.com](http://www.naiveui.com)\n\n## 社区\n\n- [Discord](https://discord.gg/Pqv7Mev5Dd)\n- 钉钉一群 33482509 (已满)\n- 钉钉二群 35886835 (已满)\n- 钉钉三群 32377370 (已满)\n- 钉钉四群 8165002788 (已满)\n- 钉钉五群 31205022250 (已满)\n- 钉钉六群 62720001971 (已满)\n- 钉钉七群 172000005810\n\n- [Awesome Naive UI](https://github.com/naive-ui/awesome-naive)\n\n钉钉群加入方法：在**搜索框**中搜索群号，点击下拉框中更多分组内的**网络查找公开群组**\n\n## 特性\n\n### 比较完整\n\n有超过 90 个组件，希望能帮你少写点代码。\n\n顺便一提，它们全都可以 treeshaking。\n\n### 主题可调\n\n我们提供了一个使用 TypeScript 构建的先进的类型安全主题系统。你只需要提供一个样式覆盖的对象，剩下的都交给我们。\n\n顺便一提，不用 less、sass、css 变量，也不用 webpack 的 loaders。以及你可以试试右下角的主题编辑器。\n\n### 使用 TypeScript\n\nNaive UI 全量使用 TypeScript 编写，和你的 TypeScript 项目无缝衔接。\n\n顺便一提，你不需要导入任何 CSS 就能让组件正常工作。\n\n### 快\n\n我尽力让它不要太慢。任何数据组件均可使用虚拟列表。\n\n顺便一提，...，没有顺便了。祝你使用愉快。\n\n## 安装\n\n### npm\n\n使用 npm 安装。\n\n```bash\nnpm i -D naive-ui\n```\n\n### 字体\n\n```bash\nnpm i -D vfonts\n```\n\n### 图标\n\nnaive-ui 建议使用 [xicons](https://www.xicons.org) 作为图标库。\n\n### 设计资源\n\n[Naive UI (Sketch)](https://naive-ui.oss-accelerate.aliyuncs.com/NaiveUI-Design-Library-zh-CN.sketch)\n\n## 贡献\n\n请参考 [CONTRIBUTING.zh-CN.md](https://github.com/tusen-ai/naive-ui/blob/main/CONTRIBUTING.zh-CN.md)\n\n## 许可\n\nNaive UI 使用 [MIT license](https://opensource.org/licenses/MIT) 许可证书。\n\n`result` 组件的图像资源来自于 [Twemoji](https://github.com/twitter/twemoji)，遵守 [CC-BY 4.0](https://creativecommons.org/licenses/by/4.0/) 许可。\n"
  },
  {
    "path": "babel.config.js",
    "content": "// the file is used for site building and other tooling builds\n// > 2%, make template string not compiled to concat, since it's not fast\nconst process = require('node:process')\n\nmodule.exports = {\n  presets:\n    process.env.NODE_ENV === 'test'\n      ? [['@babel/preset-env', { targets: { node: 'current' } }]]\n      : [\n          [\n            '@babel/preset-env',\n            {\n              targets: '>2%, not IE 11'\n            }\n          ]\n        ]\n}\n"
  },
  {
    "path": "build/loaders/ComponentDemoTemplate.vue",
    "content": "<template>\n  <component-demo\n    demo-file-name=\"<!-- DEMO_FILE_NAME -->\"\n    relative-url=\"<!-- URL -->\"\n    title=\"<!-- TITLE_SLOT -->\"\n    ts-code=\"<!-- TS_CODE_SLOT -->\"\n    js-code=\"<!-- JS_CODE_SLOT -->\"\n    language-type=\"<!-- LANGUAGE_TYPE_SLOT -->\"\n  >\n    <template #title>\n      <!-- TITLE_SLOT -->\n    </template>\n    <template #content>\n      <!-- CONTENT_SLOT -->\n    </template>\n    <template #demo>\n      <div class=\"demo-card__view\">\n        <!-- DEMO_SLOT -->\n      </div>\n    </template>\n  </component-demo>\n</template>\n\n<!-- SCRIPT_SLOT -->\n\n<!-- STYLE_SLOT -->\n"
  },
  {
    "path": "build/loaders/convert-md-to-doc.ts",
    "content": "import type { Token, Tokens } from 'marked'\nimport path from 'node:path'\nimport fse from 'fs-extra'\nimport camelCase from 'lodash/camelCase'\nimport { marked } from 'marked'\nimport { createRenderer } from './md-renderer'\nimport projectPath from './project-path'\n\nconst mdRenderer = createRenderer()\n\ninterface DemoInfo {\n  id: string\n  title: string\n  debug: boolean\n  variable?: string\n  fileName?: string\n  tag?: string\n}\n\ninterface ComponentInfo {\n  ids: string[]\n  importStmt: string\n}\n\nasync function resolveDemoTitle(\n  fileName: string,\n  demoEntryPath: string\n): Promise<string> {\n  const demoStr = await fse.readFile(\n    path.resolve(projectPath, demoEntryPath, '..', fileName),\n    'utf-8'\n  )\n  const match = demoStr.match(/# ([^\\n]+)/)\n  if (!match)\n    throw new Error('No demo title found')\n  return match[1]\n}\n\nasync function resolveDemoInfos(\n  literal: string,\n  url: string,\n  env: string\n): Promise<DemoInfo[]> {\n  const ids = literal\n    .split('\\n')\n    .map(line => line.trim())\n    .filter(id => id.length)\n  const infos: DemoInfo[] = []\n  for (const id of ids) {\n    const debug = id.includes('debug') || id.includes('Debug')\n    if (env === 'production' && debug) {\n      continue\n    }\n    let fileName\n    if (id.includes('.vue')) {\n      fileName = `${id.slice(0, -4)}.demo.vue`\n    }\n    else {\n      fileName = `${id}.demo.md`\n    }\n    const variable = `${camelCase(id)}Demo`\n    infos.push({\n      id,\n      variable,\n      fileName,\n      title: await resolveDemoTitle(fileName, url),\n      tag: `<${variable} />`,\n      debug\n    })\n  }\n  return infos\n}\n\nfunction genDemosTemplate(demoInfos: DemoInfo[], colSpan: number): string {\n  return `<component-demos :span=\"${colSpan}\">${demoInfos\n    .map(({ tag }) => tag)\n    .join('\\n')}</component-demos>`\n}\n\nfunction genAnchorTemplate(\n  children: string,\n  options: { ignoreGap: boolean } = {\n    ignoreGap: false\n  }\n): string {\n  return `\n    <n-anchor\n      internal-scrollable\n      :bound=\"16\"\n      type=\"block\"\n      style=\"width: 192px; position: sticky; top: 32px; max-height: calc(100vh - 32px - 64px); height: auto;\"\n      offset-target=\"#doc-layout\"\n      :ignore-gap=\"${options.ignoreGap}\"\n    >\n      ${children}\n    </n-anchor>\n  `\n}\n\nfunction genDemosApiAnchorTemplate(\n  tokens: Token[]\n): (DemoInfo | { id: string, title: string, debug: boolean })[] {\n  const api: DemoInfo[] = [\n    {\n      id: 'API',\n      title: 'API',\n      debug: false\n    }\n  ]\n  return api.concat(\n    tokens\n      .filter(\n        (token): token is Tokens.Heading =>\n          token.type === 'heading' && token.depth === 3\n      )\n      .map(token => ({\n        id: token.text.replace(/ /g, '-'),\n        title: token.text,\n        debug: false\n      }))\n  )\n}\n\nfunction genDemosAnchorTemplate(\n  demoInfos: DemoInfo[],\n  hasApi: boolean,\n  tokens: Token[]\n): string {\n  const links = (\n    hasApi\n      ? demoInfos.concat(genDemosApiAnchorTemplate(tokens) as DemoInfo[])\n      : demoInfos\n  ).map(\n    ({ id, title, debug }) => `<n-anchor-link\n      v-if=\"(displayMode === 'debug') || ${!debug}\"\n      title=\"${title}\"\n      href=\"#${id}\"\n    />`\n  )\n  return genAnchorTemplate(links.join('\\n'), {\n    ignoreGap: hasApi\n  })\n}\n\nfunction genPageAnchorTemplate(tokens: Token[]): string {\n  const titles = tokens\n    .filter(\n      (token): token is Tokens.Heading =>\n        token.type === 'heading' && token.depth === 2\n    )\n    .map(token => token.text)\n  const links = titles.map((title) => {\n    const href = title.replace(/ /g, '-')\n    return `<n-anchor-link title=\"${title}\" href=\"#${href}\"/>`\n  })\n  return genAnchorTemplate(links.join('\\n'), { ignoreGap: true })\n}\n\nfunction genScript(\n  demoInfos: DemoInfo[],\n  components: ComponentInfo[] = [],\n  url: string,\n  forceShowAnchor: boolean\n): string {\n  const showAnchor = !!(demoInfos.length || forceShowAnchor)\n  const importStmts = demoInfos\n    .map(({ variable, fileName }) => `import ${variable} from './${fileName}'`)\n    .concat(components.map(({ importStmt }) => importStmt))\n    .join('\\n')\n  const componentStmts = demoInfos\n    .map(({ variable }) => variable)\n    .concat(components.map(({ ids }) => ids).flat())\n    .join(',\\n')\n  const script = `<script>\n${importStmts}\nimport { computed } from 'vue'\nimport { useMemo } from 'vooks'\nimport { useDisplayMode } from '/demo/store'\nimport { useIsMobile } from '/demo/utils/composables'\n\nexport default {\n  components: {\n    ${componentStmts}\n  },\n  setup () {\n    const isMobileRef = useIsMobile()\n    const showAnchorRef = useMemo(() => {\n      if (isMobileRef.value) return false\n      return ${showAnchor}\n    })\n    const useSmallPaddingRef = isMobileRef\n    return {\n      showAnchor: showAnchorRef,\n      displayMode: useDisplayMode(),\n      wrapperStyle: computed(() => {\n        return !useSmallPaddingRef.value\n          ? 'display: flex; flex-wrap: nowrap; padding: 32px 24px 56px 56px;'\n          : 'padding: 16px 16px 24px 16px;'\n      }),\n      contentStyle: computed(() => {\n        return showAnchorRef.value\n          ? 'width: calc(100% - 228px); margin-right: 36px;'\n          : 'width: 100%; padding-right: 12px;';\n      }),\n      url: ${JSON.stringify(url)}\n    }\n  }\n}\n</script>`\n  return script\n}\n\nexport async function convertMd2ComponentDocumentation(\n  text: string,\n  url: string,\n  env: string = 'development'\n): Promise<string> {\n  const forceShowAnchor = !!~text.search('<!--anchor:on-->')\n  const colSpan = ~text.search('<!--single-column-->') ? 1 : 2\n  const hasApi = !!~text.search('## API')\n  const tokens = marked.lexer(text)\n  // resolve external components\n  const componentsIndex = tokens.findIndex(\n    token =>\n      token.type === 'code' && (token as Tokens.Code).lang === 'component'\n  )\n  let components: ComponentInfo[] = []\n  if (~componentsIndex) {\n    const token = tokens[componentsIndex] as Tokens.Code\n    components = token.text\n      .split('\\n')\n      .map((component) => {\n        const [ids, importStmt] = component.split(':')\n        if (!ids.trim())\n          throw new Error('No component id')\n        if (!importStmt.trim())\n          throw new Error('No component source url')\n        return {\n          ids: ids.split(',').map(id => id.trim()),\n          importStmt: importStmt.trim()\n        }\n      })\n      .filter(({ ids, importStmt }) => ids && importStmt)\n    tokens.splice(componentsIndex, 1)\n  }\n  // add edit on github button on title\n  const titleIndex = tokens.findIndex(\n    token => token.type === 'heading' && token.depth === 1\n  )\n  if (titleIndex > -1) {\n    const titleText = JSON.stringify(\n      (tokens[titleIndex] as Tokens.Heading).text\n    )\n    const btnTemplate = `<edit-on-github-header relative-url=\"${url}\" text=${titleText}><\\/edit-on-github-header>`\n    tokens.splice(titleIndex, 1, {\n      type: 'html',\n      pre: false,\n      text: btnTemplate\n    } as Tokens.HTML)\n  }\n  // resolve demos, debug demos are removed from production build\n  const demosIndex = tokens.findIndex(\n    token => token.type === 'code' && (token as Tokens.Code).lang === 'demo'\n  )\n  let demoInfos: DemoInfo[] = []\n  if (~demosIndex) {\n    demoInfos = await resolveDemoInfos(\n      (tokens[demosIndex] as Tokens.Code).text,\n      url,\n      env\n    )\n    tokens.splice(demosIndex, 1, {\n      type: 'html',\n      pre: false,\n      text: genDemosTemplate(demoInfos, colSpan)\n    } as any)\n  }\n  const docMainTemplate = marked.parser(tokens, {\n    gfm: true,\n    renderer: mdRenderer\n  })\n  // generate page\n  const docTemplate = `\n<template>\n  <div\n    class=\"doc\"\n    :style=\"wrapperStyle\"\n  >\n    <div :style=\"contentStyle\">\n      ${docMainTemplate}\n    </div>\n    <div style=\"width: 192px;\" v-if=\"showAnchor\">\n      ${\n        demoInfos.length\n          ? genDemosAnchorTemplate(demoInfos, hasApi, tokens)\n          : genPageAnchorTemplate(tokens)\n      }\n    </div>\n  </div>\n</template>`\n  const docScript = await genScript(demoInfos, components, url, forceShowAnchor)\n  return `${docTemplate}\\n\\n${docScript}`\n}\n"
  },
  {
    "path": "build/loaders/convert-vue-to-demo.ts",
    "content": "import type { Token } from 'marked'\nimport fs from 'node:fs'\nimport path from 'node:path'\nimport process from 'node:process'\nimport { fileURLToPath } from 'node:url'\nimport { marked } from 'marked'\nimport { handleMergeCode } from '../utils/handle-merge-code'\nimport { createRenderer } from './md-renderer'\n\ninterface Parts {\n  template?: string\n  script?: string\n  style?: string\n  title: string\n  content: string\n  language: 'ts' | 'js'\n  api: 'composition' | 'options'\n}\n\ninterface MergedParts extends Parts {\n  tsCode: string\n  jsCode: string\n}\n\ninterface MergePartsOptions {\n  parts: Parts\n  isVue: boolean\n}\n\ninterface ConvertVue2DemoOptions {\n  content: string\n  resourcePath: string\n  relativeUrl: string\n  isVue?: boolean\n}\n\nconst __filename = fileURLToPath(import.meta.url)\nconst __dirname = path.dirname(__filename)\n\nconst mdRenderer = createRenderer()\n\nconst __HTTP__ = process.env.NODE_ENV !== 'production' ? 'http' : 'https'\n\nconst demoBlock = fs\n  .readFileSync(path.resolve(__dirname, 'ComponentDemoTemplate.vue'))\n  .toString()\n\nfunction mergeParts({ parts, isVue }: MergePartsOptions): MergedParts {\n  const mergedParts: Partial<MergedParts> = {\n    ...parts,\n    title: parts.title,\n    content: parts.content,\n    tsCode: '',\n    jsCode: ''\n  }\n  handleMergeCode({ parts, mergedParts: mergedParts as MergedParts, isVue })\n  mergedParts.tsCode = encodeURIComponent(mergedParts.tsCode!)\n  mergedParts.jsCode = encodeURIComponent(mergedParts.jsCode!)\n  return mergedParts as MergedParts\n}\n\nconst cssRuleRegex = /([^{}]*)(\\{[^}]*\\})/g\n\n// simulate scss style\n// to remove dep of sass\n// xxx {\n//   mystyle\n// }\nfunction genStyle(sourceStyle: string): string | null {\n  let match\n  let matched = false\n  const rules: string[] = []\n\n  let matchResult = cssRuleRegex.exec(sourceStyle)\n  while (matchResult !== null) {\n    match = matchResult\n    matchResult = cssRuleRegex.exec(sourceStyle)\n    matched = true\n    const selector = match[1]\n    const body = match[2]\n    rules.push(\n      selector\n        .split(',')\n        .map(part => `.demo-card__view ${part}, .naive-ui-doc ${part}`)\n        .join(',') + body\n    )\n  }\n  if (!matched)\n    return null\n  return `<style scoped>\\n${rules.join('\\n')}</style>`\n}\n\nfunction genVueComponent(\n  parts: MergedParts,\n  fileName: string,\n  relativeUrl: string\n): string {\n  const demoFileNameReg = /<!-- DEMO_FILE_NAME -->/g\n  const relativeUrlReg = /<!-- URL -->/g\n  const titleReg = /<!-- TITLE_SLOT -->/g\n  const contentReg = /<!-- CONTENT_SLOT -->/\n  const tsCodeReg = /<!-- TS_CODE_SLOT -->/\n  const jsCodeReg = /<!-- JS_CODE_SLOT -->/\n  const scriptReg = /<!-- SCRIPT_SLOT -->/\n  const styleReg = /<!-- STYLE_SLOT -->/\n  const demoReg = /<!-- DEMO_SLOT -->/\n  const languageTypeReg = /<!-- LANGUAGE_TYPE_SLOT -->/\n  let src = demoBlock\n  src = src.replace(demoFileNameReg, fileName)\n  src = src.replace(relativeUrlReg, relativeUrl)\n  if (parts.content) {\n    src = src.replace(contentReg, parts.content)\n  }\n  if (parts.title) {\n    src = src.replace(titleReg, parts.title)\n  }\n  if (parts.tsCode) {\n    src = src.replace(tsCodeReg, parts.tsCode)\n  }\n  if (parts.jsCode) {\n    src = src.replace(jsCodeReg, parts.jsCode)\n  }\n  if (parts.script) {\n    const attributes = `${parts.api === 'composition' ? ' setup' : ''}${\n      parts.language === 'ts' ? ' lang=\"ts\"' : ''\n    }`\n    const startScriptTag = `<script${attributes}>\\n`\n    src = src.replace(scriptReg, `${startScriptTag + parts.script}\\n</script>`)\n  }\n  if (parts.language) {\n    src = src.replace(languageTypeReg, parts.language)\n  }\n  if (parts.style) {\n    const style = genStyle(parts.style)\n    if (style !== null) {\n      src = src.replace(styleReg, style)\n    }\n  }\n  if (parts.template) {\n    src = src.replace(demoReg, parts.template)\n  }\n  if (/__HTTP__/.test(src)) {\n    src = src.replace(/__HTTP__/g, __HTTP__)\n  }\n  return src.trim()\n}\n\nfunction getFileName(resourcePath: string): [string, string] {\n  const dirs = resourcePath.split('/')\n  const fileNameWithExtension = dirs[dirs.length - 1]\n  return [fileNameWithExtension.split('.')[0], fileNameWithExtension]\n}\n\nfunction getPartsOfDemo(text: string): Parts {\n  // slot template\n  const firstIndex = text.indexOf('<template>')\n  let template = text.slice(firstIndex + 10)\n  const lastIndex = template.lastIndexOf('</template>')\n  template = template.slice(0, lastIndex)\n  const script = text.match(/<script[\\s\\S]*?>([\\s\\S]*?)<\\/script>/)?.[1]?.trim()\n  const style = text.match(/<style>([\\s\\S]*?)<\\/style>/)?.[1]\n  const markdownText\n    = text.match(/<markdown>([\\s\\S]*?)<\\/markdown>/)?.[1]?.trim() ?? ''\n  const tokens = marked.lexer(markdownText)\n  const contentTokens: Token[] = []\n  let title = ''\n  for (const token of tokens) {\n    if (token.type === 'heading' && token.depth === 1) {\n      title = token.text\n    }\n    else {\n      contentTokens.push(token)\n    }\n  }\n  const scriptAttributes\n    = text.match(/<script([\\s\\S]*?)>[\\s\\S]*?<\\/script>/)?.[1].trim() ?? ''\n  const languageType = scriptAttributes?.includes('lang=\"ts\"') ? 'ts' : 'js'\n  const apiType = scriptAttributes?.includes('setup')\n    ? 'composition'\n    : 'options'\n  return {\n    template,\n    script,\n    style,\n    title,\n    content: marked.parser(contentTokens, {\n      renderer: mdRenderer\n    }),\n    language: languageType,\n    api: apiType\n  }\n}\n\nexport function convertVue2Demo(options: ConvertVue2DemoOptions): string {\n  const { content, resourcePath, relativeUrl, isVue = true } = options\n  const parts = getPartsOfDemo(content)\n  const mergedParts = mergeParts({ parts, isVue })\n  const [fileName] = getFileName(resourcePath)\n  const vueComponent = genVueComponent(\n    mergedParts,\n    `${fileName}.vue`,\n    relativeUrl\n  )\n  return vueComponent\n}\n"
  },
  {
    "path": "build/loaders/md-renderer.ts",
    "content": "import hljs from 'highlight.js'\nimport { Renderer } from 'marked'\n\nexport function createRenderer(wrapCodeWithCard = true): Renderer {\n  const renderer = new Renderer()\n  const overrides: any = {\n    table(header: string, body: string): string {\n      if (body)\n        body = `<tbody>${body}</tbody>`\n      return (\n        `<div class=\"md-table-wrapper\"><n-table single-column class=\"md-table\">\\n`\n        + `<thead>\\n${header}</thead>\\n${body}</n-table>\\n`\n        + `</div>`\n      )\n    },\n\n    tablerow(content: string): string {\n      return `<tr>\\n${content}</tr>\\n`\n    },\n\n    tablecell(\n      content: string,\n      flags: { header: boolean, align: 'center' | 'left' | 'right' | null }\n    ): string {\n      const type = flags.header ? 'th' : 'td'\n      const tag = flags.align ? `<${type} align=\"${flags.align}\">` : `<${type}>`\n      return `${tag + content}</${type}>\\n`\n    },\n\n    code: (code: string, language: string): string => {\n      if (language.startsWith('__')) {\n        language = language.replace('__', '')\n      }\n      const isLanguageValid = !!(language && hljs.getLanguage(language))\n      if (!isLanguageValid) {\n        throw new Error(\n          `MdRendererError: ${language} is not valid for code - ${code}`\n        )\n      }\n      const highlighted = hljs.highlight(code, { language }).value\n      const content = `<n-code><pre v-pre>${highlighted}</pre></n-code>`\n      return wrapCodeWithCard\n        ? `<n-card embedded :bordered=\"false\" class=\"md-card\" content-style=\"padding: 0;\">\n            <n-scrollbar x-scrollable content-style=\"padding: 16px;\">\n              ${content}\n            </n-scrollbar>\n          </n-card>`\n        : content\n    },\n    heading: (text: string, level: number): string => {\n      const id = text.replace(/ /g, '-')\n      return `<n-h${level} id=\"${id}\">${text}</n-h${level}>`\n    },\n    blockquote: (quote: string): string => {\n      return `<n-blockquote>${quote}</n-blockquote>`\n    },\n    hr: (): string => '<n-hr />',\n    paragraph: (text: string): string => {\n      return `<n-p>${text}</n-p>`\n    },\n    link(href: string, title: string | null | undefined, text: string): string {\n      if (/^(http:|https:)/.test(href)) {\n        return `<n-a href=\"${href}\" target=\"_blank\">${text}</n-a>`\n      }\n      return `<router-link to=\"${href}\" #=\"{ navigate, href }\" custom><n-a :href=\"href\" @click=\"navigate\">${text}</n-a></router-link>`\n    },\n    list(body: string, ordered: boolean, start: number): string {\n      const type = ordered ? 'n-ol' : 'n-ul'\n      const startatt = ordered && start !== 1 ? ` start=\"${start}\"` : ''\n      return `<${type}${startatt}>\\n${body}</${type}>\\n`\n    },\n    listitem(text: string): string {\n      return `<n-li>${text}</n-li>`\n    },\n    codespan(code: string): string {\n      return `<n-text code>${code}</n-text>`\n    },\n    strong(text: string): string {\n      return `<n-text strong>${text}</n-text>`\n    },\n    checkbox(checked: boolean): string {\n      return `<n-checkbox :checked=\"${checked}\" style=\"vertical-align: -2px; margin-right: 8px;\" />`\n    }\n  }\n\n  Object.assign(renderer, overrides)\n  return renderer\n}\n"
  },
  {
    "path": "build/loaders/naive-ui-demo-loader.ts",
    "content": "import { convertVue2Demo } from './convert-vue-to-demo'\nimport projectPath from './project-path'\n\nexport default function (content: string, path: string): string {\n  const relativeUrl = path.replace(`${projectPath}/`, '')\n  return convertVue2Demo({\n    content,\n    relativeUrl,\n    resourcePath: path,\n    isVue: true\n  })\n}\n"
  },
  {
    "path": "build/loaders/naive-ui-doc-loader.ts",
    "content": "import process from 'node:process'\nimport { convertMd2ComponentDocumentation } from './convert-md-to-doc'\nimport projectPath from './project-path'\n\nexport default async function (content: string, path: string): Promise<string> {\n  const env = process.env.NODE_ENV\n  const relativeUrl = path.replace(`${projectPath}/`, '')\n  return await convertMd2ComponentDocumentation(content, relativeUrl, env)\n}\n"
  },
  {
    "path": "build/loaders/project-path.ts",
    "content": "import path from 'node:path'\nimport { fileURLToPath } from 'node:url'\n\nconst __filename = fileURLToPath(import.meta.url)\nconst __dirname = path.dirname(__filename)\n\nconst projectPath = path.resolve(__dirname, '..', '..')\n\nexport default projectPath\n"
  },
  {
    "path": "build/loaders/test/basic.test.md",
    "content": "# Style Scheme\n\n```html\n<n-element tag=\"div\" class=\"myel\">\n  <template #=\"{ styleScheme }\">\n    <pre\n      :style=\"{\n        color: styleScheme.secondaryTextColor,\n        transition: `color .3s ${styleScheme.easeInOutCubicBezier}`\n      }\"\n    >\n{{ JSON.stringify(styleScheme, 0, 2) }}</pre\n    >\n  </template>\n</n-element>\n```\n"
  },
  {
    "path": "build/loaders/test/component.test.md",
    "content": "# 按钮\n\n按钮需要一些说明\n\n## 演示\n\n```demo\ndemo1\n```\n\n## API\n\n| 属性 | 说明     | 类型   | 默认值      | 版本 |\n| ---- | -------- | ------ | ----------- | ---- |\n| type | 按钮类型 | string | `'default'` |      |\n"
  },
  {
    "path": "build/loaders/test/test.md",
    "content": "# Get Started\n\n## Installation\n\nFirst install it.\n\n```bash\nnpm install --save-dev naive-ui\n```\n\n## Usage\n\nAdd the following lines in you entry point js file.\n\n```js\nimport naive from 'naive-ui'\nimport 'naive-ui/dist/lib/index.css'\n\nVue.use(naive)\n```\n"
  },
  {
    "path": "build/loaders/test/testDemoLoader.js",
    "content": "const fs = require('node:fs')\nconst path = require('node:path')\nconst demoLoader = require('../NaiveUIDemoLoader')\n\nconst demoMd = fs\n  .readFileSync(path.resolve(__dirname, 'basic.test.md'))\n  .toString()\n// eslint-disable-next-line no-console\nconsole.log(demoLoader(demoMd))\n"
  },
  {
    "path": "build/loaders/test/testMdLoader.js",
    "content": "// const mdLoader = require('./NaiveUIMdLoader')\n// const { marked } = require('marked')\nconst fs = require('node:fs')\nconst path = require('node:path')\n\nconst content = fs\n  .readFileSync(path.resolve(__dirname, '../../../CHANGELOG.zh-CN.md'))\n  .toString()\n// console.log('rendered', mdLoader(content))\n\nconst mdLoader = require('../NaiveUIMdLoader')\n\n// function parseMdAsAnchor (content) {\n//   const tokens = marked.lexer(content)\n//   const titles = tokens.filter(token => token.type === 'heading' && token.depth === 2).map(token => token.text)\n//   const linkTags = titles.map(title => {\n//     const href = title.replace(/ /g, '-')\n//     return `<n-anchor-link title=\"${title}\" href=\"#${href}\"/>`\n//   })\n//   return `<n-anchor :top=\"32\" position=\"absolute\" affix style=\"width: 132px;\">${linkTags.join('\\n')}</n-anchor>`\n// }\n\n// eslint-disable-next-line no-console\nconsole.log(mdLoader.call({ resourcePath: 'xxx' }, content, 'xxx'))\n"
  },
  {
    "path": "build/utils/get-demo-by-path.ts",
    "content": "import fs from 'fs-extra'\nimport demoLoader from '../loaders/naive-ui-demo-loader'\nimport docLoader from '../loaders/naive-ui-doc-loader'\n\nexport async function getTransformedVueSrc(\n  path: string\n): Promise<string | undefined> {\n  if (path.endsWith('.demo.vue')) {\n    const code = await fs.readFile(path, 'utf-8')\n    return demoLoader(code, path)\n  }\n  else if (path.endsWith('.md')) {\n    const code = await fs.readFile(path, 'utf-8')\n    return await docLoader(code, path)\n  }\n}\n"
  },
  {
    "path": "build/utils/handle-merge-code.ts",
    "content": "import { tsToJs } from './tsToJs'\n\ninterface Parts {\n  api?: 'composition' | 'options'\n  language?: 'ts' | 'js'\n  template?: string\n  script?: string\n  style?: string\n}\n\ninterface MergedParts {\n  tsCode: string\n  jsCode: string\n}\n\ninterface MergeCodeOptions {\n  parts: Parts\n  mergedParts: MergedParts\n  isVue: boolean\n}\n\nexport function handleMergeCode(options: MergeCodeOptions): void {\n  const { parts, mergedParts, isVue } = options\n  const isCompositionApi = parts.api === 'composition'\n  if (isVue && parts.language === 'ts') {\n    // ts and js\n    if (parts.template) {\n      mergedParts.tsCode += `<template>${parts.template}</template>`\n      mergedParts.jsCode += `<template>${parts.template}</template>`\n    }\n    if (parts.script) {\n      if (parts.template) {\n        mergedParts.tsCode += '\\n\\n'\n        mergedParts.jsCode += '\\n\\n'\n      }\n      mergedParts.tsCode += `<script${\n        isCompositionApi ? ' setup' : ''\n      } lang=\"ts\">\n${parts.script}\n</script>`\n      mergedParts.jsCode += `<script${isCompositionApi ? ' setup' : ''}>\n${tsToJs(parts.script)}\n</script>`\n    }\n    if (parts.style) {\n      if (parts.template || parts.script) {\n        mergedParts.tsCode += '\\n\\n'\n        mergedParts.jsCode += '\\n\\n'\n      }\n      const style = `<style scoped>${parts.style}</style>`\n      mergedParts.tsCode += style\n      mergedParts.jsCode += style\n    }\n  }\n  else {\n    // only js when md or vue file\n    if (parts.template) {\n      mergedParts.jsCode += isVue\n        ? `<template>${parts.template}</template>`\n        : `<template>\\n${parts.template\n          .split('\\n')\n          .map((line: string) => (line.length ? `  ${line}` : line))\n          .join('\\n')}\\n</template>`\n    }\n    if (parts.script) {\n      if (parts.template) {\n        mergedParts.jsCode += '\\n\\n'\n      }\n      mergedParts.jsCode += `<script${isCompositionApi ? ' setup' : ''}>\\n${parts.script}\\n</script>`\n    }\n    if (parts.style) {\n      if (parts.template || parts.script) {\n        mergedParts.jsCode += '\\n\\n'\n      }\n      const style = isVue\n        ? `<style scoped>${parts.style}</style>`\n        : `<style scoped>\\n${parts.style}\\n</style>`\n      mergedParts.jsCode += style\n    }\n  }\n}\n"
  },
  {
    "path": "build/utils/terse-cssr.ts",
    "content": "import { generate } from '@babel/generator'\nimport { parse } from '@babel/parser'\nimport _traverse from '@babel/traverse'\n\nexport function terseCssr(code: string): string {\n  // https://github.com/babel/babel/discussions/13093\n  const traverse = (_traverse as any)?.default ?? _traverse\n  const patternSpace = / +/g\n  const patternEnter = /\\n+/g\n\n  const ast: any = parse(code, {\n    sourceType: 'module'\n  })\n\n  traverse(ast, {\n    TemplateElement(path: any) {\n      ;(['raw', 'cooked'] as const).forEach((type) => {\n        path.node.value[type] = path.node.value[type]\n          .replace(patternSpace, ' ')\n          .replace(patternEnter, '\\n')\n      })\n    }\n  })\n\n  return generate(ast).code\n}\n"
  },
  {
    "path": "build/utils/tsToJs.ts",
    "content": "import { transformSync } from 'esbuild'\n\nexport function tsToJs(content: string | null): string {\n  if (!content) {\n    return ''\n  }\n  // esbuild will remove blank line\n  const beforeTransformContent = content.replace(\n    /\\n(\\s)*\\n/g,\n    '\\n__blankline\\n'\n  )\n  const { code } = transformSync(beforeTransformContent, {\n    loader: 'ts',\n    minify: false,\n    minifyWhitespace: false,\n    charset: 'utf8'\n  })\n  return code.trim().replace(/__blankline;/g, '')\n}\n"
  },
  {
    "path": "build/vite-plugin-css-render.ts",
    "content": "import type { Plugin } from 'vite'\nimport { terseCssr } from './utils/terse-cssr'\n\nexport function cssRenderPlugin(): Plugin {\n  return {\n    name: 'css-render-vite',\n    transform(src: string, id: string) {\n      if (id.endsWith('.cssr.ts') || id.endsWith('.cssr.js')) {\n        return terseCssr(src)\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "build/vite-plugin-demo.ts",
    "content": "import type { Plugin } from 'vite'\nimport vue from '@vitejs/plugin-vue'\nimport { getTransformedVueSrc } from './utils/get-demo-by-path'\nimport { cssRenderPlugin } from './vite-plugin-css-render'\nimport { demoIndexTransFormPlugin } from './vite-plugin-index-tranform'\n\nconst fileRegex = /\\.(md|vue)$/\n\nconst vuePlugin = vue({\n  include: [/\\.vue$/, /\\.md$/]\n})\n\nexport function createDemoPlugin(): Plugin[] {\n  const naiveDemoVitePlugin: Plugin = {\n    name: 'demo-vite',\n    async transform(_, id) {\n      if (fileRegex.test(id)) {\n        return await getTransformedVueSrc(id)\n      }\n    },\n    async handleHotUpdate(ctx) {\n      const { file } = ctx\n      if (fileRegex.test(file)) {\n        const code = await getTransformedVueSrc(file)\n        if (code === undefined)\n          return []\n\n        const { handleHotUpdate } = vuePlugin\n        if (typeof handleHotUpdate === 'function') {\n          return handleHotUpdate({\n            ...ctx,\n            read: () => code\n          })\n        }\n        else if (handleHotUpdate?.handler) {\n          return handleHotUpdate.handler({\n            ...ctx,\n            read: () => code\n          })\n        }\n        return []\n      }\n    }\n  }\n\n  const cssrPlugin = cssRenderPlugin()\n\n  return [demoIndexTransFormPlugin, naiveDemoVitePlugin, vuePlugin, cssrPlugin]\n}\n"
  },
  {
    "path": "build/vite-plugin-index-tranform.ts",
    "content": "import type { Plugin } from 'vite'\nimport { env } from 'node:process'\n\nfunction transformIndexHtml(code: string): string {\n  switch (env.NODE_ENV) {\n    case 'production':\n      return code.replace(/__INDEX__/, 'demo/index.prod.js')\n    default:\n      return code.replace(/__INDEX__/, 'demo/index.dev.js')\n  }\n}\n\nexport const demoIndexTransFormPlugin: Plugin = {\n  name: 'demo-transform',\n  transformIndexHtml: {\n    order: 'pre',\n    handler: (code: string) => {\n      return transformIndexHtml(code)\n    }\n  }\n}\n"
  },
  {
    "path": "demo/Caveat.md",
    "content": "# Caveat\n\nCode is messy here because I've no time to refactor it.\n\nIt works matter.\n"
  },
  {
    "path": "demo/Site.vue",
    "content": "<script lang=\"ts\">\nimport { useLoadingBar } from 'naive-ui'\nimport { defineComponent, onMounted } from 'vue'\nimport { loadingBarApiRef } from './routes/router'\nimport SiteHeader from './SiteHeader.vue'\nimport { useIsMobile } from './utils/composables'\n\nexport default defineComponent({\n  name: 'Site',\n  components: {\n    SiteHeader\n  },\n  setup() {\n    const loadingBar = useLoadingBar()\n    const isMobileRef = useIsMobile()\n    onMounted(() => {\n      loadingBarApiRef.value = loadingBar\n      loadingBar.finish()\n    })\n    return {\n      isMobile: isMobileRef\n    }\n  }\n})\n</script>\n\n<template>\n  <n-layout :position=\"isMobile ? 'static' : 'absolute'\" class=\"root-layout\">\n    <SiteHeader />\n    <router-view />\n  </n-layout>\n</template>\n"
  },
  {
    "path": "demo/SiteHeader.vue",
    "content": "<script lang=\"ts\">\nimport { MenuOutline } from '@vicons/ionicons5'\nimport { useMessage, version } from 'naive-ui'\nimport { computed, defineComponent, ref } from 'vue'\nimport { useRoute, useRouter } from 'vue-router'\nimport {\n  useComponentOptions,\n  useConfigProviderName,\n  useDisplayMode,\n  useDocOptions,\n  useFlattenedDocOptions,\n  useLocaleName,\n  useThemeName\n} from './store'\nimport { renderMenuLabel } from './store/menu-options'\nimport { i18n, useIsMobile, useIsTablet } from './utils/composables'\nimport { repoUrl } from './utils/github-url'\nimport { findMenuValue } from './utils/route'\n\n// match substr\nfunction match(pattern, string) {\n  if (!pattern.length)\n    return true\n  if (!string.length)\n    return false\n  if (pattern[0] === string[0])\n    return match(pattern.slice(1), string.slice(1))\n  return match(pattern, string.slice(1))\n}\n\nconst locales = {\n  'zh-CN': {\n    dark: '深色',\n    light: '浅色',\n    searchPlaceholder: '搜索',\n    home: '首页',\n    doc: '文档',\n    component: '组件',\n    common: '常规',\n    debug: '调试',\n    alreadyHome: '别点了，你已经在首页了',\n    tusimpleTheme: '图森主题',\n    defaultTheme: '默认主题'\n  },\n  'en-US': {\n    dark: 'Dark',\n    light: 'Light',\n    searchPlaceholder: 'Search',\n    home: 'Home',\n    doc: 'Docs',\n    component: 'Components',\n    common: 'Common',\n    debug: 'Debug',\n    alreadyHome: 'You are already in home page. No clicking anymore.',\n    tusimpleTheme: 'TuSimple Theme',\n    defaultTheme: 'Default Theme'\n  }\n}\n\nexport default defineComponent({\n  name: 'SiteHeader',\n  components: {\n    MenuOutline\n  },\n  setup() {\n    const message = useMessage()\n    const route = useRoute()\n    const router = useRouter()\n\n    const mobilePopoverRef = ref(null)\n    const themeAndLocaleReg = /^(\\/[^/]+){2}/\n\n    // i18n\n    const { t } = i18n(locales)\n\n    // theme\n    const themeNameRef = useThemeName()\n    const themeLabelMapRef = computed(() => ({\n      dark: t('light'),\n      light: t('dark')\n    }))\n\n    // locale\n    const localeNameRef = useLocaleName()\n\n    // menu\n    const menuOptionsRef = computed(() => {\n      return [\n        {\n          key: 'home',\n          label: t('home'),\n          path: themeAndLocaleReg.exec(route.path)[0]\n        },\n        {\n          key: 'doc',\n          label: t('doc'),\n          path: `${themeAndLocaleReg.exec(route.path)[0]}/docs/introduction`\n        },\n        {\n          key: 'component',\n          label: t('component'),\n          path: `${themeAndLocaleReg.exec(route.path)[0]}/components/button`\n        }\n      ]\n    })\n    const menuValueRef = computed(() => {\n      if (/\\/docs\\//.test(route.path))\n        return 'doc'\n      if (/\\/components\\//.test(route.path))\n        return 'component'\n      else if (route.name === 'home')\n        return 'home'\n      return null\n    })\n\n    // mobile options\n    const docOptionsRef = useDocOptions()\n    const componentOptionsRef = useComponentOptions()\n    const mobileMenuOptionsRef = computed(() => {\n      return [\n        {\n          key: 'theme',\n          label: themeLabelMapRef.value[themeNameRef.value]\n        },\n        {\n          key: 'locale',\n          label: localeNameRef.value === 'zh-CN' ? 'English' : '中文'\n        },\n        {\n          key: 'home',\n          label: t('home'),\n          path: themeAndLocaleReg.exec(route.path)[0]\n        },\n        {\n          key: 'doc',\n          label: t('doc'),\n          children: docOptionsRef.value,\n          path: `${themeAndLocaleReg.exec(route.path)[0]}/docs/introduction`\n        },\n        {\n          key: 'component',\n          label: t('component'),\n          path: `${themeAndLocaleReg.exec(route.path)[0]}/components/button`,\n          children: componentOptionsRef.value\n        },\n        {\n          key: 'github',\n          label: 'GitHub'\n        }\n      ]\n    })\n    const mobileMenuValueRef = computed(() => {\n      if (route.name === 'home')\n        return 'home'\n      return findMenuValue(mobileMenuOptionsRef.value, route.path)\n    })\n    function handleUpdateMobileMenu(value, { path }) {\n      if (value === 'theme') {\n        handleThemeUpdate()\n      }\n      else if (value === 'locale') {\n        if (localeNameRef.value === 'zh-CN') {\n          localeNameRef.value = 'en-US'\n        }\n        else {\n          localeNameRef.value = 'zh-CN'\n        }\n      }\n      else if (path) {\n        router.push(path)\n      }\n      else {\n        window.open(repoUrl, '_blank')\n      }\n      mobilePopoverRef.value.setShow(false)\n    }\n\n    function handleThemeUpdate() {\n      if (themeNameRef.value === 'dark') {\n        themeNameRef.value = 'light'\n      }\n      else {\n        themeNameRef.value = 'dark'\n      }\n    }\n\n    const localeLabelMap = {\n      'zh-CN': 'English',\n      'en-US': '中文'\n    }\n    function handleLocaleUpdate() {\n      if (localeNameRef.value === 'zh-CN') {\n        localeNameRef.value = 'en-US'\n      }\n      else {\n        localeNameRef.value = 'zh-CN'\n      }\n    }\n\n    // display mode\n    const displayModeRef = useDisplayMode()\n    const displayModeLabelMap = {\n      common: 'Debug',\n      debug: 'Prod'\n    }\n    function handleDisplayModeUpdate() {\n      if (displayModeRef.value === 'common') {\n        displayModeRef.value = 'debug'\n      }\n      else {\n        displayModeRef.value = 'common'\n      }\n    }\n\n    // config provider\n    const configProviderNameRef = useConfigProviderName()\n    const cfgProviderLabelMapRef = computed(() => ({\n      tusimple: t('defaultTheme'),\n      default: t('tusimpleTheme')\n    }))\n    function handleConfigProviderUpdate() {\n      if (configProviderNameRef.value === 'tusimple') {\n        configProviderNameRef.value = 'default'\n      }\n      else {\n        configProviderNameRef.value = 'tusimple'\n      }\n    }\n\n    // search\n    const searchableOptionsRef = useFlattenedDocOptions()\n    const searchPatternRef = ref('')\n    const searchOptionsRef = computed(() => {\n      // function getLabel(item) {\n      //   if (item.label) {\n      //     return typeof item.extra === 'function'\n      //       ? () => [item.label, ' ', item.extra()]\n      //       : item.label + (item.extra ? ' ' + item.extra : '')\n      //   }\n      //   return item.key\n      // }\n      function getSearchableContent(item) {\n        if (item.label) {\n          return item.label + (item.extraString ? ` ${item.extraString}` : '')\n        }\n        return item.key\n      }\n      if (!searchPatternRef.value)\n        return []\n      const replaceRegex = / |-/g\n      return searchableOptionsRef.value\n        .filter((item) => {\n          const pattern = searchPatternRef.value\n            .toLowerCase()\n            .replace(replaceRegex, '')\n            .slice(0, 20)\n          const label = getSearchableContent(item)\n            .toLowerCase()\n            .replace(replaceRegex, '')\n          return match(pattern, label)\n        })\n        .map(item => ({\n          label: getSearchableContent(item),\n          value: item.path\n        }))\n    })\n    function handleSearch(value) {\n      router.push(value)\n    }\n\n    // common\n    const isMobileRef = useIsMobile()\n    const isTabletRef = useIsTablet()\n    function handleLogoClick() {\n      if (/^(\\/[^/]+){2}$/.test(route.path)) {\n        message.info(t('alreadyHome'))\n        return\n      }\n      router.push(/^(\\/[^/]+){2}/.exec(route.path)[0])\n    }\n\n    // responsive menu\n    const menuInstRef = ref()\n    let lastWindowInnerWidth = window.innerWidth\n    window.addEventListener('resize', () => {\n      if (window.innerWidth > lastWindowInnerWidth) {\n        menuInstRef.value?.deriveResponsiveState()\n      }\n      lastWindowInnerWidth = window.innerWidth\n    })\n\n    return {\n      menuInstRef,\n      renderMenuLabel,\n      mobilePopoverRef,\n      tusimple: process.env.TUSIMPLE,\n      dev: __DEV__,\n      message,\n      t,\n      version,\n      isMobile: isMobileRef,\n      isTablet: isTabletRef,\n      repoUrl,\n      // theme\n      theme: themeNameRef,\n      handleThemeUpdate,\n      themeLabelMap: themeLabelMapRef,\n      // displayMode\n      displayMode: displayModeRef,\n      displayModeLabelMap,\n      handleDisplayModeUpdate,\n      // locale\n      locale: localeNameRef,\n      localeLabelMap,\n      handleLocaleUpdate,\n      // configProvider\n      configProviderName: configProviderNameRef,\n      cfgProviderLabelMap: cfgProviderLabelMapRef,\n      handleConfigProviderUpdate,\n      // search\n      searchPattern: searchPatternRef,\n      searchOptions: searchOptionsRef,\n      handleSearch,\n      // menu\n      menuOptions: menuOptionsRef,\n      menuValue: menuValueRef,\n      // mobile & tablet menu\n      mobileMenuOptions: mobileMenuOptionsRef,\n      handleUpdateMobileMenu,\n      mobileMenuValue: mobileMenuValueRef,\n      // common\n      handleLogoClick,\n      style: computed(() => {\n        return isMobileRef.value\n          ? {\n              '--side-padding': '16px',\n              'grid-template-columns': 'auto 1fr auto'\n            }\n          : {\n              '--side-padding': '32px',\n              'grid-template-columns':\n                'calc(272px - var(--side-padding)) 1fr auto'\n            }\n      })\n    }\n  }\n})\n</script>\n\n<template>\n  <n-layout-header bordered class=\"nav\" :style=\"style\">\n    <n-text tag=\"div\" class=\"ui-logo\" :depth=\"1\" @click=\"handleLogoClick\">\n      <img src=\"./assets/images/naivelogo.svg\">\n      <span v-if=\"!isMobile\">Naive UI</span>\n    </n-text>\n    <div\n      :style=\"\n        !isMobile ? 'display: flex; align-items: center; overflow: hidden;' : ''\n      \"\n    >\n      <div v-if=\"!(isMobile || isTablet)\" class=\"nav-menu\">\n        <n-menu\n          ref=\"menuInstRef\"\n          responsive\n          mode=\"horizontal\"\n          :value=\"menuValue\"\n          :options=\"menuOptions\"\n          :render-label=\"renderMenuLabel\"\n        />\n      </div>\n      <n-auto-complete\n        v-model:value=\"searchPattern\"\n        :style=\"\n          !isMobile\n            ? 'width: 216px; margin-left: 24px; margin-right: 12px; flex-shrink: 0;'\n            : undefined\n        \"\n        :placeholder=\"t('searchPlaceholder')\"\n        :options=\"searchOptions\"\n        clear-after-select\n        blur-after-select\n        @select=\"handleSearch\"\n      />\n      <!-- TODO: add it -->\n      <!-- template #suffix>\n        <span style=\"color: var(--placeholder-color)\">⌘ + K</span>\n      </template -->\n    </div>\n    <n-popover\n      v-if=\"isMobile || isTablet\"\n      ref=\"mobilePopoverRef\"\n      style=\"padding: 0; width: 288px\"\n      placement=\"bottom-end\"\n      display-directive=\"show\"\n      trigger=\"click\"\n    >\n      <template #trigger>\n        <n-icon size=\"20\" style=\"margin-left: 12px\">\n          <MenuOutline />\n        </n-icon>\n      </template>\n      <div style=\"overflow: auto; max-height: 79vh\">\n        <n-menu\n          :value=\"mobileMenuValue\"\n          :options=\"mobileMenuOptions\"\n          :indent=\"18\"\n          :render-label=\"renderMenuLabel\"\n          @update:value=\"handleUpdateMobileMenu\"\n        />\n      </div>\n    </n-popover>\n    <div v-else class=\"nav-end\">\n      <n-button\n        size=\"small\"\n        quaternary\n        class=\"nav-picker\"\n        @click=\"handleLocaleUpdate\"\n      >\n        {{ localeLabelMap[locale] }}\n      </n-button>\n      <n-button\n        size=\"small\"\n        quaternary\n        class=\"nav-picker\"\n        @click=\"handleThemeUpdate\"\n      >\n        {{ themeLabelMap[theme] }}\n      </n-button>\n      <n-button\n        size=\"small\"\n        tag=\"a\"\n        quaternary\n        class=\"nav-picker\"\n        :href=\"repoUrl\"\n        target=\"_blank\"\n      >\n        GitHub\n      </n-button>\n      <n-text class=\"nav-picker padded\">\n        {{ version }}\n      </n-text>\n      <n-button\n        v-if=\"dev\"\n        size=\"small\"\n        quaternary\n        class=\"nav-picker\"\n        @click=\"handleDisplayModeUpdate\"\n      >\n        {{ displayModeLabelMap[displayMode] }}\n      </n-button>\n      <n-button\n        v-if=\"tusimple || dev\"\n        size=\"small\"\n        quaternary\n        class=\"nav-picker\"\n        @click=\"handleConfigProviderUpdate\"\n      >\n        {{ cfgProviderLabelMap[configProviderName] }}\n      </n-button>\n    </div>\n  </n-layout-header>\n</template>\n\n<style scoped>\n.nav {\n  display: grid;\n  grid-template-rows: calc(var(--header-height) - 1px);\n  align-items: center;\n  padding: 0 var(--side-padding);\n}\n\n.ui-logo {\n  cursor: pointer;\n  display: flex;\n  align-items: center;\n  font-size: 18px;\n}\n\n.ui-logo > img {\n  margin-right: 12px;\n  height: 32px;\n  width: 32px;\n}\n\n.nav-menu {\n  padding-left: 36px;\n  overflow: hidden;\n  flex-grow: 0;\n  flex-shrink: 1;\n}\n\n.nav-picker {\n  margin-right: 4px;\n}\n\n.nav-picker.padded {\n  padding: 0 10px;\n}\n\n.nav-picker:last-child {\n  margin-right: 0;\n}\n\n.nav-end {\n  display: flex;\n  align-items: center;\n}\n</style>\n\n<style>\n.nav-menu .n-menu-item,\n.nav-menu .n-submenu,\n.nav-menu .n-menu-item-content {\n  height: calc(var(--header-height) - 1px) !important;\n}\n</style>\n"
  },
  {
    "path": "demo/SiteRoot.vue",
    "content": "<script lang=\"ts\">\nimport { defineComponent } from 'vue'\nimport { useRoute, useRouter } from 'vue-router'\nimport Site from './Site.vue'\nimport { initRouter, siteSetup } from './store'\n\nexport default defineComponent({\n  name: 'SiteProvider',\n  components: {\n    Site\n  },\n  setup() {\n    initRouter(useRouter(), useRoute())\n    return siteSetup()\n  }\n})\n</script>\n\n<template>\n  <component\n    :is=\"configProvider\"\n    class=\"demo\"\n    namespace=\"naive-ui-doc\"\n    preflight-style-disabled\n    :theme-name=\"themeName\"\n    :theme=\"theme\"\n    :locale=\"locale\"\n    :date-locale=\"dateLocale\"\n    :hljs=\"hljs\"\n  >\n    <n-theme-editor :style=\"themeEditorStyle\">\n      <n-loading-bar-provider>\n        <n-message-provider>\n          <n-notification-provider>\n            <n-modal-provider>\n              <n-dialog-provider>\n                <Site />\n              </n-dialog-provider>\n            </n-modal-provider>\n          </n-notification-provider>\n        </n-message-provider>\n      </n-loading-bar-provider>\n      <n-global-style />\n    </n-theme-editor>\n  </component>\n</template>\n"
  },
  {
    "path": "demo/index.dev.js",
    "content": "import { createApp } from 'vue'\nimport naive, { NThemeEditor } from '../src/index'\nimport createDemoRouter from './routes/router'\nimport { routes } from './routes/routes'\nimport { installDemoComponents } from './setup'\nimport SiteRoot from './SiteRoot.vue'\n\nconst app = createApp(SiteRoot)\n\nconst router = createDemoRouter(app, routes)\n\napp.use(router)\napp.use(naive)\napp.component('NThemeEditor', NThemeEditor)\ninstallDemoComponents(app)\n\nrouter.isReady().then(() => {\n  app.mount('#app')\n})\n"
  },
  {
    "path": "demo/index.prod.js",
    "content": "import naive, { NThemeEditor } from 'naive-ui'\nimport { createApp } from 'vue'\nimport createDemoRouter from './routes/router'\nimport { routes } from './routes/routes'\nimport { installDemoComponents } from './setup'\nimport SiteRoot from './SiteRoot.vue'\n\nconst app = createApp(SiteRoot)\n\nconst router = createDemoRouter(app, routes)\n\napp.use(router)\napp.use(naive)\napp.component('NThemeEditor', NThemeEditor)\ninstallDemoComponents(app)\n\nrouter.isReady().then(() => {\n  app.mount('#app')\n})\n"
  },
  {
    "path": "demo/pages/Layout.vue",
    "content": "<script lang=\"ts\">\nimport { useMemo } from 'vooks'\n// Frame component for components & docs page\nimport { computed, defineComponent, ref, toRef, watch } from 'vue'\nimport { useRoute } from 'vue-router'\nimport { useComponentOptions, useDocOptions } from '../store'\nimport { renderMenuLabel } from '../store/menu-options'\nimport { useIsMobile, useIsTablet } from '../utils/composables'\nimport { findMenuValue } from '../utils/route'\nimport SiteFooter from './home/Footer.vue'\n\nexport default defineComponent({\n  components: {\n    SiteFooter\n  },\n  setup() {\n    const route = useRoute()\n    const layoutInstRef = ref(null)\n    const docOptionsRef = useDocOptions()\n    const componentOptionsRef = useComponentOptions()\n    const optionsRef = computed(() =>\n      route.path.includes('/docs/')\n        ? docOptionsRef.value\n        : componentOptionsRef.value\n    )\n\n    const menuValueRef = computed(() => {\n      return findMenuValue(optionsRef.value, route.path)\n    })\n    watch(toRef(route, 'path'), (value, oldValue) => {\n      const langAndThemeReg = /\\/(zh-CN|en-US)\\/(light|dark|os-theme)/g\n      // only theme & lang change do not restore the scroll status\n      if (\n        value.replace(langAndThemeReg, '')\n        !== oldValue.replace(langAndThemeReg, '')\n      ) {\n        layoutInstRef.value.scrollTo(0, 0)\n      }\n    })\n    const isMobileRef = useIsMobile()\n    const isTabletRef = useIsTablet()\n\n    return {\n      layoutScrollbarProps: {\n        containerClass: 'document-scroll-container'\n      },\n      renderMenuLabel,\n      showSider: useMemo(() => {\n        return !isMobileRef.value && !isTabletRef.value\n      }),\n      layoutInstRef,\n      options: optionsRef,\n      menuValue: menuValueRef,\n      isMobile: isMobileRef\n    }\n  }\n})\n</script>\n\n<template>\n  <n-layout\n    id=\"doc-layout\"\n    :has-sider=\"showSider\"\n    :position=\"isMobile ? 'static' : 'absolute'\"\n    :style=\"{\n      top: isMobile ? '' : 'var(--header-height)',\n    }\"\n  >\n    <n-layout-sider\n      v-if=\"showSider\"\n      :native-scrollbar=\"false\"\n      :collapsed-width=\"0\"\n      collapse-mode=\"transform\"\n      trigger-style=\"top: 240px;\"\n      collapsed-trigger-style=\"top: 240px; right: -20px;\"\n      bordered\n      show-trigger=\"arrow-circle\"\n    >\n      <n-menu\n        :value=\"menuValue\"\n        :options=\"options\"\n        :render-label=\"renderMenuLabel\"\n      />\n    </n-layout-sider>\n    <n-layout\n      ref=\"layoutInstRef\"\n      :scrollbar-props=\"layoutScrollbarProps\"\n      :native-scrollbar=\"false\"\n      :position=\"isMobile || showSider ? 'static' : 'absolute'\"\n      content-style=\"min-height: calc(100vh - var(--header-height)); display: flex; flex-direction: column;\"\n    >\n      <router-view />\n      <SiteFooter />\n    </n-layout>\n  </n-layout>\n</template>\n"
  },
  {
    "path": "demo/pages/docs/changelog/enUS/index.vue",
    "content": "<script>\nimport Changelog from '../../../../../CHANGELOG.en-US.md'\n\nexport default {\n  components: {\n    Changelog\n  }\n}\n</script>\n\n<template>\n  <Changelog />\n</template>\n"
  },
  {
    "path": "demo/pages/docs/changelog/zhCN/index.vue",
    "content": "<script>\nimport Changelog from '../../../../../CHANGELOG.zh-CN.md'\n\nexport default {\n  components: {\n    Changelog\n  }\n}\n</script>\n\n<template>\n  <Changelog />\n</template>\n"
  },
  {
    "path": "demo/pages/docs/common-issues/enUS/index.md",
    "content": "# Common Issues\n\n## 1. The difference between @update:xxx and on-update:xxx\n\n### Case 1\n\nIf you are not using `v-model:xxx` with `on-update:xxx` on the same component, there is no difference between `@update:xxx` and `on-update:xxx` when used in templates.\n\nIn Naive UI, all API documents use the `on-update:xxx` format, because `@` is just a shorthand provided by Vue.\n\nIf you prefer camelCase, you can use `onUpdate:xxx`.\n\nIf you are using JSX, you can use `onUpdateXxx` (all `onUpdate:xxx` have an equivalent implementation of `onUpdateXxx`).\n\n### Case 2\n\nIf you are using `v-model:xxx`, you should use `@update:xxx` on the same component.\n\n✅ example `<n-input v-model:value=\"xxx\" @update:value=\"yyy\" />`.\n\n❌ example `<n-input v-model:value=\"xxx\" :on-update:value=\"yyy\" />`.\n\nThat is because `v-model:value=\"xxx\"` will be transformed to `:onUpdate:value=\"xxx\"`. If you are using `@update:value=\"yyy\"` together, it will be `:onUpdate:value=\"[xxx, yyy]\"`, and then Naive UI would take care of if.\n\nHowever if you are using `on-update:value=\"yyy\"`, Vue would generate code like `:onUpdate:value=\"xxx\" :on-update-value=\"yyy\"` and the second one would override the first one in Vue runtime. The `v-model:value` would be broken.\n\nIf you have any problems, feel free to create a PR or issue on GitHub.\n\n## 2. How to use in Single File Component(SFC)?\n\nplease see [Usage in SFC](usage-sfc)\n"
  },
  {
    "path": "demo/pages/docs/common-issues/zhCN/index.md",
    "content": "# 常见问题\n\n## 1. @update:xxx 和 on-update:xxx 的区别\n\n### 情况 1\n\n如果你没有在同一个组件上同时使用 `v-model:xxx` 和 `on-update:xxx`，`@update:xxx` 和 `on-update:xxx` 在模版中使用时没有任何区别。\n\n在 Naive UI 中，全部的 API 文档使用 `on-update:xxx` 格式，因为 `@` 只是 Vue 提供的一种简写。\n\n如果你偏爱 camelCase，可以使用 `onUpdate:xxx`。\n\n如果你在使用 JSX，可以使用 `onUpdateXxx`（所有的 `onUpdate:xxx` 都有一个 `onUpdateXxx` 的对等实现）。\n\n### 情况 2\n\n如果你在一个组件上使用了 `v-model:xxx`，你应该使用 `@update:xxx`。\n\n✅ 例子 `<n-input v-model:value=\"xxx\" @update:value=\"yyy\" />`。\n\n❌ 例子 `<n-input v-model:value=\"xxx\" :on-update:value=\"yyy\" />`。\n\n这是因为 `v-model:value=\"xxx\"` 会被转化为 `:onUpdate:value=\"xxx\"`。如果你同时使用了 `@update:value=\"yyy\"`，他们会被转化为 `:onUpdate:value=\"[xxx, yyy]\"`，然后 Naive UI 会来处理这种情况。\n\n然而如果你使用了 `on-update:value=\"yyy\"`，Vue 会生成类似于 `:onUpdate:value=\"xxx\" :on-update:value=\"yyy\"` 的代码，然后第二个属性会在运行时覆盖掉第一个，`v-model:value` 会崩掉。\n\n如果你发现任何问题，欢迎在 GitHub 上提交 issue 和 PR。\n\n## 2. 如何在单文件组件（SFC - Single File Component）中使用？\n\n详见 [在 SFC 中使用](usage-sfc)\n"
  },
  {
    "path": "demo/pages/docs/community/enUS/index.md",
    "content": "<!--anchor:on-->\n\n# Third-Party Libraries\n\nNaive UI is a high-quality Vue component library of unified design specifications. We prefer to provide only UI components with a unified specification and visual presentation. So we recommend the following great resources from the community that complement Naive UI.\n\nIf you want to contribute excellent resources, you can create a pull request of this page in naive-ui's github repo.\n\n| Resources | Descriptions |\n| --- | --- |\n| [Naive UI Admin](https://github.com/jekip/naive-ui-admin) | A free open source out-of-box UI solution for enterprise applications. |\n| [Admin Work](https://github.com/qingqingxuan/admin-work) | A free open source, powerful, easy to use, beautiful back-office management system solution. |\n| [Soybean Admin](https://github.com/honghuangdc/soybean-admin) | A beautiful vue admin template, based on Vue3 + Vite + Naive UI + TypeScript. |\n| [Rengar Admin](https://github.com/RengarJS/rengar-admin) | A mid-backend management system template based on Vue 3.5 + Vite 7 + TypeScript + Naive UI + Pinia + UnoCSS, which is concise without excessive encapsulation and has simple and easy-to-understand code. |\n| [GoView](https://github.com/dromara/go-view) | A free open source and powerful yet accessible data visualization tool. |\n| [Vue Naive Admin](https://github.com/zclzone/vue-naive-admin) | A lightweight backend management template base on Vue3 + Vite4 + Pinia + Unocss + Naive UI. |\n| [Vue Bag Admin](https://vite.itnavs.com/admin/) | 🎉vue-bag-admin，Using Vite4, Vue3, TypeScript, JavaScript construction, support a variety of writing and call, a complete framework system, responsive background management system |\n| [Celeris Web](https://github.com/kirklin/celeris-web) | Celeris Web, based on Vue 3 and Vite, is a free and open-source front-end framework with Naive UI components and TypeScript support, featuring a Monorepo structure. It also integrates with OpenAI, providing natural language processing capabilities for modern web development. |\n| [Nova admin](https://github.com/chansee97/nova-admin) | a clean and concise back-end management template based on Vue3, Vite5, Typescript, and Naive UI. It implements complete functionality in a simple way, while also considering code standards, readability, and avoiding excessive encapsulation to facilitate secondary development. |\n| [chatgpt-web](https://github.com/Chanzhaoyu/chatgpt-web) | ChatGPT demo web page built with Express and Vue3 |\n| [pro-naive-ui](https://github.com/Zheng-Changfu/pro-naive-ui) | Based on Naive UI secondary encapsulation, more functions are extended on the original components |\n| [vue3-dynamic-form](https://github.com/yayaluoya/vue3-dynamic-form) | A dynamic form designer based on Vue3, Naive UI, to implement a lot of basic controls, can be very convenient to customize the control. |\n| [astral-3d-editor](https://github.com/mlt131220/Astral3DEditor) | 3D scene building tool based on Vue3 + Naive UI + ThreeJS + Vite5 + Typescript, supporting CAD & BIM analysis, including weather system, particle system, plug-in center... |\n| [it-tools](https://github.com/CorentinTh/it-tools) | Developed based on Vue3 and the Naive UI component library, it brings together a variety of practical online tools |\n| [Lithe Admin](https://github.com/tenianon/lithe-admin) | A lightweight and elegant backend management template, built using Vue3 + Naive UI + Vite + TypeScript + Pinia, featuring a Tailwind CSS Color color scheme and a frosted texture design. |\n"
  },
  {
    "path": "demo/pages/docs/community/zhCN/index.md",
    "content": "<!--anchor:on-->\n\n# 社区精选资源\n\nNaive UI 是统一设计规范的高质量 Vue 组件库，我们倾向于只提供符合统一规范且带有视觉展现的 UI 组件。所以我们推荐以下社区已有的优秀资源，与 Naive UI 形成互补。\n\n想贡献优秀资源，可直接在项目中 PR 此页面。\n\n| 资源 | 描述 |\n| --- | --- |\n| [Naive UI Admin](https://github.com/jekip/naive-ui-admin) | 免费开源的中后台模板 |\n| [Admin Work](https://github.com/qingqingxuan/admin-work) | 一款免费开源、功能强大、方便易用、漂亮的中后台管理系统模板 |\n| [Soybean Admin](https://github.com/honghuangdc/soybean-admin) | 一个基于 Vue3 + Vite + Naive UI + TypeScript 的漂亮清爽的中后台模版 |\n| [Rengar Admin](https://github.com/RengarJS/rengar-admin) | 基于 Vue 3.5 + Vite 7 + TypeScript + Naive UI + Pinia + UnoCSS 的中后台管理系统模板，简洁不过度封装，代码简单易懂 |\n| [GoView](https://gitee.com/dromara/go-view) | 开源、精美、便捷的「数据可视化」低代码开发平台 |\n| [Vue Naive Admin](https://github.com/zclzone/vue-naive-admin) | 基于 Vue3 + Vite4 + Pinia + Unocss + Naive UI 的轻量级后台管理模板 |\n| [Vue Bag Admin](https://vite.itnavs.com/admin/) | 🎉vue-bag-admin，采用Vite4、Vue3、TypeScript、JavaScript构建，支持多种写法和调用，完整的框架体系，响应式中后台管理系统 |\n| [Celeris Web](https://github.com/kirklin/celeris-web) | 一个基于 Vue 3 和 Vite 的免费开源前端框架，具有 Naive UI 组件和 TypeScript 支持，采用 Monorepo 结构。它还集成了 OpenAI，为现代 Web 开发提供自然语言处理能力。 |\n| [Nova admin](https://github.com/chansee97/nova-admin) | 一个基于Vue3、Vite5、Typescript、Naive UI, 简洁干净后台管理模板，用简单的方式实现完整功能，并尽可能的考虑代码规范，易读易理解无过度封装，方便二次开发。 |\n| [chatgpt-web](https://github.com/Chanzhaoyu/chatgpt-web) | 使用 Express 和 Vue3 搭建的 ChatGPT 演示网页 |\n| [pro-naive-ui](https://github.com/Zheng-Changfu/pro-naive-ui) | 基于 Naive UI 二次封装, 基于原有组件扩展了更多功能 |\n| [vue3-dynamic-form](https://github.com/yayaluoya/vue3-dynamic-form) | 一个基于 Vue3、Naive UI 的动态表单设计器，实现了很多基础控件，能非常方便的自定义控件。 |\n| [astral-3d-editor](https://github.com/mlt131220/Astral3DEditor) | 基于 Vue3 + Naive UI + ThreeJS + Vite5 + Typescript 的三维场景构建工具，支持 CAD & BIM 解析，内含天气系统、粒子系统、插件中心... |\n| [it-tools](https://github.com/CorentinTh/it-tools) | 基于 Vue3 和 Naive UI 组件库开发，汇集了多种实用的在线工具 |\n| [Lithe Admin](https://github.com/tenianon/lithe-admin) | 一个轻盈而优雅的后台管理模板，基于 Vue3 + Naive UI + Vite + TypeScript + Pinia 构建，采用 Tailwind CSS Color 配色方案和磨砂纹理质感的设计 |\n| [DVHA Pro](https://github.com/duxweb/dvha) | 一款基于 Vue 3 的无头（Headless）中后台前端开发框架，搭配了 Naive UI 封装了开箱即用的异步能力，同时增加了异步渲染基座模式，无需编译即可集成到任何后端使用。 |\n"
  },
  {
    "path": "demo/pages/docs/controlled-uncontrolled/enUS/index.md",
    "content": "<!--anchor:on-->\n\n# Controlled manner & uncontrolled manner\n\nA component's manner can be controlled or uncontrolled. Uncontrolled manner means you only listen to its change but not control its value. Controlled manner means you control the component's value.\n\n## Uncontrolled manner\n\nIn this situation, you don't set `<n-input />`'s `value` but only listen to its change. Component's value will be controlled by itself.\n\n```html\n<n-input @update:value=\"handleUpdateValue\" />\n```\n\n## Controlled manner\n\nIn the situation, you listen to component's value & change at the same time. If you don't update `value`, component's value won't be changed. Its value is controlled by you.\n\n```html\n<n-input :value=\"value\" @update:value=\"handleUpdateValue\" />\n```\n\n### `v-model`\n\nA component with `v-model` works in controlled manner, since `v-model` is the same as `:model-value` and `@update:model-value`.\n\n## Uncontrolled manner in naive-ui\n\nDifferent library has different behavior on how to distinguish controlled or uncontrolled manner. In naive-ui, if `value` is `undefined` or not passed, it will be uncontrolled. That is to say, if you set a component's value to `undefined` won't clear it but transform it from controlled manner to uncontrolled manner. If you need to clear it, at most time you can use `null`.\n\n### Not only `value`\n\nAny props pair like `xxx` & `@update:xxx` can work both in controlled manner or uncontrolled manner.\n"
  },
  {
    "path": "demo/pages/docs/controlled-uncontrolled/zhCN/index.md",
    "content": "<!--anchor:on-->\n\n# 受控模式与非受控模式\n\n一个组件的行为可以分为受控模式和非受控模式两种。非受控模式指的是只监听组件的变化，而不去控制组件的 value，受控模式指的是控制组件的值。\n\n## 非受控模式\n\n在这种情况下，你不能控制 `<n-input />` 的 `value`，而只能监听它的变化，组件值的变化由组件自身控制。\n\n```html\n<n-input @update:value=\"handleUpdateValue\" />\n```\n\n## 受控模式\n\n在这种情况下，你既监听了组件的变化，然后也控制了组件的值。如果你不更新 `value`，那么组件的值不会改变，组件值的变化由你控制。\n\n```html\n<n-input :value=\"value\" @update:value=\"handleUpdateValue\" />\n```\n\n### `v-model`\n\n`v-model` 控制的组件在受控模式下，因为 `v-model` 等同于 `:model-value` 和 `@update:model-value` 的组合。\n\n## naive-ui 中的受控模式\n\n不同的组件库区分受控与非受控模式的区别是不同的。在 naive-ui 中，只要 `value` 是 `undefined` 或者根本没有传，那么组件的值会是非受控的。也就是说你将一个组件的值设为 `undefined` 并不能清空它，只会改变它的控制模式。一般情况下清空可以使用 `null`。\n\n### 不止 `value`\n\n任何 `xxx` 与 `@update:xxx` 的属性对都可以有受控和非受控模式。\n"
  },
  {
    "path": "demo/pages/docs/customize-theme/enUS/index.md",
    "content": "<!--anchor:on-->\n\n# Customizing theme\n\nNaive-ui provides `n-config-provider` to customize the theme.\n\nBy default all of the components are light themed, without any configuration.\n\nTo learn more about `n-config-provider`, see [Config Provider](../components/config-provider).\n\n## Use dark theme\n\nSet `n-config-provider`'s `theme` prop to `darkTheme` imported from naive-ui to set dark theme inside `n-config-provider`.\n\nIf `theme` is `undefined` it won't affect the theme of components inside.\n\n```html\n<template>\n  <n-config-provider :theme=\"darkTheme\">\n    <app />\n  </n-config-provider>\n</template>\n\n<script>\n  import { defineComponent } from 'vue'\n  import { darkTheme } from 'naive-ui'\n\n  export default defineComponent({\n    setup() {\n      return {\n        darkTheme\n      }\n    }\n  })\n</script>\n```\nYou may need to include `<n-global-style />` if you want to apply the dark theme globally, not just to the components.\n\nTo learn more, see [n-global-style](../docs/customize-theme#Sync-style-of-the-body-element).\n\n## Get theme vars\n\nWhether it's the default light theme (`lightTheme`), the modified dark theme (`darkTheme`), or the custom theme we adjusted, you can get theme variables within the scope of the theme using [useThemeVars](./theme#use-theme-vars).\n\n## Customizing theme vars (design tokens)\n\nNo CSS (Scss, Less) needed.\n\nThe configured global theme variables will overwrite the theme variables that take effect on descendant components.\n\nSet `n-config-provider`'s `theme-overrides` to customize theme vars. Naive-ui exports type `GlobalThemeOverrides` to help you define `theme-overrides`.\n\nFor available vars please follow the type hint of `GlobalThemeOverrides`.\n\nIf you want to view more theme variables, you can view them in the edit button at the bottom right corner of the Naive UI homepage.\n\nYou can modify the corresponding theme variable, you can get the themeOverrides object after export.\n\n```html\n<script>\n  import { NConfigProvider } from 'naive-ui'\n\n  /**\n   * Use this for type hints under js file\n   * @type import('naive-ui').GlobalThemeOverrides\n   */\n  const themeOverrides = {\n    common: {\n      primaryColor: '#FF0000'\n    },\n    Button: {\n      textColor: '#FF0000'\n    },\n    Select: {\n      peers: {\n        InternalSelection: {\n          textColor: '#FF0000'\n        }\n      }\n    }\n    // ...\n  }\n\n  // ...\n</script>\n\n<template>\n  <n-config-provider :theme-overrides=\"themeOverrides\">\n    <my-app />\n  </n-config-provider>\n</template>\n```\n\n## Customizing theme vars in TypeScript\n\nIf you are using ts to write code, this one is more suitable for you.\n\n```html\n<script lang=\"ts\">\n  import { NConfigProvider, GlobalThemeOverrides } from 'naive-ui'\n\n  const themeOverrides: GlobalThemeOverrides = {\n    common: {\n      primaryColor: '#FF0000'\n    },\n    Button: {\n      textColor: '#FF0000'\n    }\n  }\n\n  // ...\n</script>\n\n<template>\n  <n-config-provider :theme-overrides=\"themeOverrides\">\n    <my-app />\n  </n-config-provider>\n</template>\n```\n\n## Customizing component theme vars\n\nThe use of component theme variables is the same as the use of global theme variables, and the component theme variables will override the global theme variables.\n\n```html\n<script lang=\"ts\">\n  import { SelectProps, ButtonProps } from 'naive-ui'\n\n  type SelectThemeOverrides = NonNullable<SelectProps['themeOverrides']>\n  type ButtonThemeOverrides = NonNullable<ButtonProps['themeOverrides']>\n\n  const selectThemeOverrides: SelectThemeOverrides = {\n    menuBoxShadow:\n      '0 6px 16px -9px rgba(0, 0, 0, .08), 0 9px 28px 0 rgba(0, 0, 0, .05), 0 12px 48px 16px rgba(0, 0, 0, .03)',\n    peers: {\n      InternalSelection: {\n        textColor: '#FF0000',\n        heightMedium: '42px'\n      }\n    }\n  }\n  const buttonThemeOverrides: ButtonThemeOverrides = {\n    heightMedium: '40px',\n    textColor: 'rgba(24, 127, 231, 1)'\n  }\n\n  // ...\n</script>\n\n<template>\n  <n-select\n    v-model:value=\"value\"\n    :options=\"options\"\n    :theme-overrides=\"selectThemeOverrides\"\n  />\n  <n-button :theme-overrides=\"buttonThemeOverrides\">theme</n-button>\n</template>\n```\n\n## Customizing theme vars under different themes\n\nIf you want to use different theme variables on light and dark theme at the same time, you can take a look at this.\n\n```html\n<script>\n  import { NConfigProvider, darkTheme } from 'naive-ui'\n\n  /**\n   * @type import('naive-ui').GlobalThemeOverrides\n   */\n  const lightThemeOverrides = {\n    common: {\n      primaryColor: '#000000'\n    }\n    // ...\n  }\n\n  const darkThemeOverrides = {\n    common: {\n      primaryColor: '#FFFFFF'\n    }\n    // ...\n  }\n\n  const theme = null\n  // ...\n</script>\n\n<template>\n  <n-config-provider\n    :theme=\"theme\"\n    :theme-overrides=\"theme === null ? lightThemeOverrides : darkThemeOverrides\"\n  >\n    <my-app />\n  </n-config-provider>\n</template>\n```\n\n## Use the peers vars\n\nIn many cases, another component will be reused inside a component, so the theme variable of peers appears.\n\nThe theme variables related to peers have not been exposed yet. Use `GlobalThemeOverrides` to view the peers variables of the corresponding component.\n\nThe specific available peers will be updated later.\n\n```html\n<script lang=\"ts\">\n  import { NConfigProvider, GlobalThemeOverrides } from 'naive-ui'\n\n  const themeOverrides: GlobalThemeOverrides = {\n    Select: {\n      peers: {\n        InternalSelection: {\n          textColor: '#FF0000'\n        },\n        InternalSelectMenu: {\n          borderRadius: '6px'\n        }\n      }\n    },\n    DataTable: {\n      paginationMargin: '40px 0 0 0',\n      peers: {\n        Empty: {\n          textColor: '#ccc'\n        },\n        Pagination: {\n          itemTextColor: '#ccc'\n        }\n      }\n    }\n    // ...\n  }\n  // ...\n</script>\n\n<template>\n  <n-config-provider :theme-overrides=\"themeOverrides\">\n    <my-app />\n  </n-config-provider>\n</template>\n```\n\n## Sync style of the body element\n\nFor the following reasons, you may need to set some styles on `document.body`.\n\n1. Naive-ui will mount some global style that is unresponsive (to theme, not media query). For example `font-family`. The style works fine by default, however they won't change when theme is changed.\n2. `n-config-provider` can't sync global style (for example, body's background color) outside it.\n\nYou can use `n-global-style` to sync common global style to the body element. In the following example, `n-global-style` will sync the theme provided by `n-config-provider` to `document.body`.\n\n```html\n<template>\n  <n-config-provider ...>\n    <app />\n    <n-global-style />\n  </n-config-provider>\n</template>\n```\n\n## Theme editor\n\nNaive-ui provides a theme editor to help you edit theme and export the corresponding configuration. It can be placed inside `n-config-provider`.\n\nThe theme editor is not included in global installation (`app.use(naive)`). You need to import it explicitly to use it.\n\n```html\n<template>\n  <n-theme-editor>\n    <app />\n  </n-theme-editor>\n</template>\n\n<script>\n  import { defineComponent } from 'vue'\n  import { NThemeEditor } from 'naive-ui'\n\n  export default defineComponent({\n    components: {\n      NThemeEditor\n    }\n  })\n</script>\n```\n"
  },
  {
    "path": "demo/pages/docs/customize-theme/zhCN/index.md",
    "content": "<!--anchor:on-->\n\n# 调整主题\n\nNaive UI 通过使用 `n-config-provider` 调整主题。\n\n默认情况下所有组件均为亮色主题，无需任何配置。\n\n了解更多关于 `n-config-provider` 的信息，参见 [全局化配置](../components/config-provider)。\n\n## 使用暗色主题\n\n将 `n-config-provider` 的 `theme` 设为从 naive-ui 导入的 `darkTheme` 来设定暗色主题。\n\n若 `theme` 为 `undefined` 则不会影响内部组件的主题。\n\n```html\n<template>\n  <n-config-provider :theme=\"darkTheme\">\n    <app />\n  </n-config-provider>\n</template>\n\n<script>\n  import { defineComponent } from 'vue'\n  import { darkTheme } from 'naive-ui'\n\n  export default defineComponent({\n    setup() {\n      return {\n        darkTheme\n      }\n    }\n  })\n</script>\n```\n\n如果你需要给 body 元素也应用 dark theme，而不仅仅是组件，你可能需要使用 `<n-global-style />`。更多细节请参考 [n-global-style](../docs/customize-theme#Sync-style-of-the-body-element)。\n\n## 获取主题变量\n\n无论是默认的亮色主题(`lightTheme`)，还是修改后的暗色主题(`darkTheme`)，亦或我们通过调整得到的自定义主题，在该主题生效范围内的组件中都可以通过 [useThemeVars](./theme#use-theme-vars) 来获取主题变量。\n\n## 调整主题变量\n\n你不需要写任何 CSS（Scss、Less...）。\n\n配置的全局主题变量会对后代组件生效的主题变量覆盖。\n\n通过设定 `n-config-provider` 的 `theme-overrides` 来调整主题变量。naive-ui 导出了 `GlobalThemeOverrides` 类型帮助你定义主题。\n\n具体可使用变量请参考 `GlobalThemeOverrides` 类型提示。\n\n如果想要查看更多的主题变量，可在 Naive UI 主页的右下角的 edit 按钮查看。\n\n可以修改对应的主题变量，导出后可以拿到 themeOverrides 对象。\n\n```html\n<script>\n  import { NConfigProvider } from 'naive-ui'\n\n  /**\n   * js 文件下使用这个做类型提示\n   * @type import('naive-ui').GlobalThemeOverrides\n   */\n  const themeOverrides = {\n    common: {\n      primaryColor: '#FF0000'\n    },\n    Button: {\n      textColor: '#FF0000'\n    },\n    Select: {\n      peers: {\n        InternalSelection: {\n          textColor: '#FF0000'\n        }\n      }\n    }\n    // ...\n  }\n\n  // ...\n</script>\n\n<template>\n  <n-config-provider :theme-overrides=\"themeOverrides\">\n    <my-app />\n  </n-config-provider>\n</template>\n```\n\n## TS 下使用主题变量\n\n如果你正在使用 ts 写代码，这块比较适合你。\n\n```html\n<script lang=\"ts\">\n  import { NConfigProvider, GlobalThemeOverrides } from 'naive-ui'\n\n  const themeOverrides: GlobalThemeOverrides = {\n    common: {\n      primaryColor: '#FF0000'\n    },\n    Button: {\n      textColor: '#FF0000'\n    }\n  }\n\n  // ...\n</script>\n\n<template>\n  <n-config-provider :theme-overrides=\"themeOverrides\">\n    <my-app />\n  </n-config-provider>\n</template>\n```\n\n## 调整组件主题变量\n\n组件主题变量使用方法同全局主题变量使用方法，并且组件主题变量会覆盖全局主题变量。\n\n```html\n<script lang=\"ts\">\n  import { SelectProps, ButtonProps } from 'naive-ui'\n\n  type SelectThemeOverrides = NonNullable<SelectProps['themeOverrides']>\n  type ButtonThemeOverrides = NonNullable<ButtonProps['themeOverrides']>\n\n  const selectThemeOverrides: SelectThemeOverrides = {\n    menuBoxShadow:\n      '0 6px 16px -9px rgba(0, 0, 0, .08), 0 9px 28px 0 rgba(0, 0, 0, .05), 0 12px 48px 16px rgba(0, 0, 0, .03)',\n    peers: {\n      InternalSelection: {\n        textColor: '#FF0000',\n        heightMedium: '42px'\n      }\n    }\n  }\n  const buttonThemeOverrides: ButtonThemeOverrides = {\n    heightMedium: '40px',\n    textColor: 'rgba(24, 127, 231, 1)'\n  }\n\n  // ...\n</script>\n\n<template>\n  <n-select\n    v-model:value=\"value\"\n    :options=\"options\"\n    :theme-overrides=\"selectThemeOverrides\"\n  />\n  <n-button :theme-overrides=\"buttonThemeOverrides\">theme</n-button>\n</template>\n```\n\n## 不同主题下调整主题变量\n\n如果你想要在亮色和暗色上同时使用不同的主题变量，可以来看看这个。\n\n```html\n<script>\n  import { NConfigProvider, darkTheme } from 'naive-ui'\n\n  /**\n   * @type import('naive-ui').GlobalThemeOverrides\n   */\n  const lightThemeOverrides = {\n    common: {\n      primaryColor: '#000000'\n    }\n    // ...\n  }\n\n  const darkThemeOverrides = {\n    common: {\n      primaryColor: '#FFFFFF'\n    }\n    // ...\n  }\n\n  const theme = null\n  // ...\n</script>\n\n<template>\n  <n-config-provider\n    :theme=\"theme\"\n    :theme-overrides=\"theme === null ? lightThemeOverrides : darkThemeOverrides\"\n  >\n    <my-app />\n  </n-config-provider>\n</template>\n```\n\n## 使用 peers 主题变量\n\n很多时候组件内部都会复用另一个组件，因此出现了 peers 的主题变量。\n\npeers 相关的主题变量还没有暴露，使用 `GlobalThemeOverrides` 可以查看对应组件的 peers 变量。\n\n具体哪些可使用的 peers 后续会更新。\n\n```html\n<script lang=\"ts\">\n  import { NConfigProvider, GlobalThemeOverrides } from 'naive-ui'\n\n  const themeOverrides: GlobalThemeOverrides = {\n    Select: {\n      peers: {\n        InternalSelection: {\n          textColor: '#FF0000'\n        },\n        InternalSelectMenu: {\n          borderRadius: '6px'\n        }\n      }\n    },\n    DataTable: {\n      paginationMargin: '40px 0 0 0',\n      peers: {\n        Empty: {\n          textColor: '#ccc'\n        },\n        Pagination: {\n          itemTextColor: '#ccc'\n        }\n      }\n    }\n    // ...\n  }\n  // ...\n</script>\n\n<template>\n  <n-config-provider :theme-overrides=\"themeOverrides\">\n    <my-app />\n  </n-config-provider>\n</template>\n```\n\n## 同步 body 元素的样式\n\n出于以下原因，你可能需要将某些样式设定在 `document.body` 上。\n\n1. naive-ui 会设定一些非响应式的全局样式（例如字体），它们在默认状况下工作良好，但是不能响应主题的变化。\n2. `n-config-provider` 无法将全局样式同步到它以外的地方（例如 body 背景色）。\n\n通过使用 `n-global-style` 可以将常见的全局样式同步到 body 上。在下面的例子中，`n-global-style` 会将 `n-config-provider` 提供的主题同步到 `document.body` 上。\n\n```html\n<template>\n  <n-config-provider>\n    <app />\n    <n-global-style />\n  </n-config-provider>\n</template>\n```\n\n## 主题编辑器\n\nnaive-ui 提供主题编辑器帮助你方便的编辑主题并导出对应配置。它可以被嵌套于 `n-config-provider` 中。\n\n主题编辑器不包含在全局安装中（`app.use(naive)`）。你需要显式引入来使用它。\n\n```html\n<template>\n  <n-theme-editor>\n    <app />\n  </n-theme-editor>\n</template>\n\n<script>\n  import { defineComponent } from 'vue'\n  import { NThemeEditor } from 'naive-ui'\n\n  export default defineComponent({\n    components: {\n      NThemeEditor\n    }\n  })\n</script>\n```\n"
  },
  {
    "path": "demo/pages/docs/experimental-features/enUS/index.md",
    "content": "<!--anchor:on-->\n\n# Experimental Features\n\n<n-alert type=\"warning\" title=\"Caveats\" :bordered=\"false\">\n  The following features are <n-text strong>unstable</n-text>. Use them if you really need and perpare to follow the API changes.\n</n-alert>\n\n## Use TuSimple Theme\n\n```html\n<script>\n  import { TsConfigProvider, useDialog, useMessage } from '@naive-ui/tusimple-theme'\n\n  // danger typed api\n  const dialog = useDialog()\n  dialog.danger(...)\n\n  const message = useMessage()\n  message.danger(...)\n</script>\n\n<template>\n  <ts-config-provider>\n    <my-app />\n  </ts-config-provider>\n</template>\n```\n"
  },
  {
    "path": "demo/pages/docs/experimental-features/zhCN/index.md",
    "content": "<!--anchor:on-->\n\n# 试验性特性\n\n<n-alert type=\"warning\" title=\"注意\" :bordered=\"false\">\n  下列的所有功能都是<n-text strong>不稳定</n-text>的。只在真的需要的时候再使用他们，API 有可能在未来被改变。\n</n-alert>\n\n## 使用图森主题\n\n```html\n<script>\n  import { TsConfigProvider, useDialog, useMessage } from '@naive-ui/tusimple-theme'\n\n  // danger typed api\n  const dialog = useDialog()\n  dialog.danger(...)\n\n  const message = useMessage()\n  message.danger(...)\n</script>\n\n<template>\n  <ts-config-provider>\n    <my-app />\n  </ts-config-provider>\n</template>\n```\n"
  },
  {
    "path": "demo/pages/docs/fonts/enUS/index.md",
    "content": "# Configuring Fonts\n\nNaive UI works with [vfonts](https://github.com/07akioni/vfonts). You can use fonts from `vfonts` easily which includes general fonts and monospace fonts.\n\nJust import fonts from in your app's entry file. Then it will work.\n\n```js\n// entry js file of your app\n// ...\n\n// General Font\nimport 'vfonts/Lato.css'\n// Monospace Font\nimport 'vfonts/FiraCode.css'\n// then it works\n\n// ...\n```\n\nNote: Different fonts from vfonts have different font weights. If you want to use `Lato` or `OpenSans` you need to configure the global font weight of naive-ui.\n\n```html\n<!-- configuring the global font weight -->\n<n-config-provider :theme-overrides=\"{ common: { fontWeightStrong: '600' } }\">\n  <app />\n</n-config-provider>\n```\n\n## Change Global Fonts by Customizing Theme\n\nIf you don't use `vfont` and want change global fonts by customzing theme, you need to use `n-global-style` to achieve that. Components' font won't be responsive to `theme-overrides` without `n-global-style`.\n\nNote: Make `vfont` work without `n-global-style` is a compromised design (I think this is a correct behavior). In the next major version, global reset style won't contain font related style. They'll be all put inside `n-global-style` component.\n"
  },
  {
    "path": "demo/pages/docs/fonts/zhCN/index.md",
    "content": "# 配置字体\n\nNaive UI 可以和 [vfonts](https://github.com/07akioni/vfonts) 配合，你可以简单的引入 `vfonts` 中的字体，包含常规字体和等宽字体。\n\n只需要在你 App 的入口文件导入字体，即可调整 Naive UI 的字体。\n\n```js\n// 你 App 的入口 js 文件\n// ...\n\n// 通用字体\nimport 'vfonts/Lato.css'\n// 等宽字体\nimport 'vfonts/FiraCode.css'\n\nconst app = createApp()\napp.use(naive)\n\n// ...\n```\n\n注意：不同 vfonts 字体提供的字重不同，在使用 `Lato`、`OpenSans` 的时候你需要全局调整 naive-ui 的字重配置。\n\n```html\n<!-- 调整 naive-ui 的字重配置 -->\n<n-config-provider :theme-overrides=\"{ common: { fontWeightStrong: '600' } }\">\n  <app />\n</n-config-provider>\n```\n\n## 通过定制主题修改全局字体\n\n如果你不打算使用 `vfonts` 并且想要通过主题调整修改其为别的字体，你需要使用 `n-global-style` 来做到这一点。在不使用 `n-global-style` 的情况下组件不会响应 `theme-overrides` 中的字体变更。\n\n题外话：不使用 `n-global-style` 就能让 `vfonts` 直接生效是一个设计上的妥协，在下个大的版本默认的全局 reset 样式将不再带有字体相关的样式，而是全部置于 `n-global-style` 组件中。\n"
  },
  {
    "path": "demo/pages/docs/i18n/enUS/index.md",
    "content": "<!--anchor:on-->\n\n# Internationalization\n\nNaive-ui provides `n-config-provider` to customize the internationalization. By default, all components are in English.\n\nTo learn more about `n-config-provider`, see [Config Provider](../components/config-provider).\n\n## Configure\n\nSet `n-config-provider`'s `locale` prop to `enUS` imported from naive-ui to set Chinese theme inside `n-config-provider`.\n\nSet `n-config-provider`'s `date-locale` prop to `dateEnUS` imported from naive-ui to set Chinese theme's date inside `n-config-provider`.\n\n```html\n<template>\n  <n-config-provider :locale=\"enUS\" :date-locale=\"dateEnUS\">\n    <app />\n  </n-config-provider>\n</template>\n\n<script>\n  import { defineComponent } from 'vue'\n  import { NConfigProvider } from 'naive-ui'\n  import { enUS, dateEnUS } from 'naive-ui'\n\n  export default defineComponent({\n    components: {\n      NConfigProvider\n    },\n    setup() {\n      return {\n        enUS,\n        dateEnUS\n      }\n    }\n  })\n</script>\n```\n\n## Supported languages\n\nPRs are welcomed for locales that are not supported yet!\n\nThe following list is sorted by 'Config' column.\n\n| Language                   | Config | Date config | Version |\n| -------------------------- | ------ | ----------- | ------- |\n| Arabic (العربية)           | arDZ   | dateArDZ    | 2.34.0  |\n| Azerbaijani (Azərbaycanca) | azAZ   | dateAzAZ    | 2.39.0  |\n| Czech (Czechia)            | csCZ   | dateCsCz    | 2.38.2  |\n| Danish (Denmark)           | daDK   | dateDaDK    | 2.43.0  |\n| German (Germany)           | deDE   | dateDeDE    |         |\n| English (British)          | enGB   | dateEnGB    | 2.25.1  |\n| English                    | enUS   | dateEnUS    |         |\n| Esperanto                  | eo     | dateEo      | 2.25.2  |\n| Spanish (Argentina)        | esAR   | dateEsAR    | 2.24.2  |\n| Estonian                   | etEE   | dateEtEE    | 2.38.0  |\n| Persian                    | faIR   | dateFaIR    | 2.34.4  |\n| French                     | frFR   | dateFrFR    |         |\n| Bahasa Indonesia           | idID   | dateIdID    |         |\n| Italiano                   | itIT   | dateItIT    | 2.24.2  |\n| Japanese                   | jaJP   | dateJaJP    |         |\n| Khmer (Cambodia)           | kmKH   | dateKmKH    | 2.41.0  |\n| Korean (South Korea)       | koKR   | dateKoKR    | 2.28.1  |\n| Norwegian Bokmål (Norway)  | nbNO   | dateNbNO    |         |\n| Dutch (Netherlands)        | nlNL   | dateNlNL    | 2.29.0  |\n| Polish (Poland)            | plPL   | datePlPL    | 2.25.2  |\n| Portuguese (Brazil)        | ptBR   | datePtBR    | 2.28.1  |\n| Russian                    | ruRU   | dateRuRU    |         |\n| Slovak                     | skSK   | dateSkSK    | 2.25.3  |\n| Swedish                    | svSE   | dateSvSE    | 2.35.0  |\n| Thai (Thailand)            | thTH   | dateThTH    | 2.27.0  |\n| Turkish                    | trTR   | dateTrTR    | 2.34.0  |\n| Uyghur (China)             | ugCN   | dateUgCN    |         |\n| Ukrainian                  | ukUA   | dateUkUA    |         |\n| Uzbek (Uzbekistan)         | uzUZ   | dateUzUZ    | 2.39.0  |\n| Vietnamese (Vietnam)       | viVN   | dateViVN    | 2.30.7  |\n| Chinese (Simplified)       | zhCN   | dateZhCN    |         |\n| Chinese (Traditional)      | zhTW   | dateZhTW    |         |\n\n## Customize the existing locale\n\nYou can use `createLocale` to customize the existing locale.\n\n```html\n<template>\n  <n-config-provider :locale=\"locale\" :date-locale=\"dateEnUS\">\n    <app />\n  </n-config-provider>\n</template>\n\n<script>\n  import { defineComponent } from 'vue'\n  import { NConfigProvider, createLocale, enUS } from 'naive-ui'\n  import { enUS, dateEnUS } from 'naive-ui'\n\n  const customizedLocale = createLocale(\n    {\n      Input: {\n        placeholder: 'Okay'\n      }\n    },\n    enUS\n  )\n\n  export default defineComponent({\n    components: {\n      NConfigProvider\n    },\n    setup() {\n      return {\n        locale: customizedLocale,\n        dateEnUS\n      }\n    }\n  })\n</script>\n```\n"
  },
  {
    "path": "demo/pages/docs/i18n/zhCN/index.md",
    "content": "<!--anchor:on-->\n\n# 国际化\n\nNaive-ui 通过使用 `n-config-provider` 调整语言，默认情况下所有组件均为英语。\n\n了解更多关于 `n-config-provider` 的信息，参见 [全局化配置](../components/config-provider)。\n\n## 配置\n\n将 `n-config-provider` 的 `locale` 设为从 naive-ui 导入的 `zhCN` 来设定全局中文。\n\n将 `n-config-provider` 的 `date-locale` 设为从 naive-ui 导入的 `dateZhCN` 来设定全局日期中文。\n\n```html\n<template>\n  <n-config-provider :locale=\"zhCN\" :date-locale=\"dateZhCN\">\n    <app />\n  </n-config-provider>\n</template>\n\n<script>\n  import { defineComponent } from 'vue'\n  import { NConfigProvider } from 'naive-ui'\n  import { zhCN, dateZhCN } from 'naive-ui'\n\n  export default defineComponent({\n    components: {\n      NConfigProvider\n    },\n    setup() {\n      return {\n        zhCN,\n        dateZhCN\n      }\n    }\n  })\n</script>\n```\n\n## 支持语言\n\n欢迎提交 PR 来支持尚未支持的语言。\n\n以下列表依据“配置”列排序。\n\n| 语言               | 配置 | 日期配置 | 版本   |\n| ------------------ | ---- | -------- | ------ |\n| 阿拉伯语           | arDZ | dateArDZ | 2.34.0 |\n| 阿塞拜疆语         | azAZ | dateAzAZ | 2.39.0 |\n| 捷克语（捷克）     | csCZ | dateCsCz | 2.38.2 |\n| 丹麦               | daDK | dateDaDK | 2.43.0 |\n| 德语               | deDE | dateDeDE |        |\n| 英国英语           | enGB | dateEnGB | 2.25.1 |\n| 英语               | enUS | dateEnUS |        |\n| 世界语             | eo   | dateEo   | 2.25.2 |\n| 西班牙语（阿根廷） | esAR | dateEsAR | 2.24.2 |\n| 爱沙尼亚语         | etEE | dateEtEE | 2.38.0 |\n| 波斯语             | faIR | dateFaIR | 2.34.4 |\n| 法语               | frFR | dateFrFR |        |\n| 印度尼西亚语       | idID | dateIdID |        |\n| 意大利语           | itIT | dateItIT | 2.24.2 |\n| 日语               | jaJP | dateJaJP |        |\n| 高棉语（柬埔寨）   | kmKH | dateKmKH | 2.41.0 |\n| 韩语               | koKR | dateKoKR | 2.28.1 |\n| 书面挪威语         | nbNO | dateNbNO |        |\n| 荷兰语（荷兰）     | nlNL | dateNlNL | 2.29.0 |\n| 波兰语（波兰）     | plPL | datePlPL | 2.25.2 |\n| 葡萄牙语 (巴西)    | ptBR | datePtBR | 2.28.1 |\n| 俄罗斯语           | ruRU | dateRuRU |        |\n| 斯洛伐克语         | skSK | dateSkSK | 2.25.3 |\n| 瑞典語             | svSE | dateSvSE | 2.35.0 |\n| 泰语（泰国）       | thTH | dateThTH | 2.27.0 |\n| 土耳其语           | trTR | dateTrTR | 2.34.0 |\n| 维吾尔语           | ugCN | dateUgCN | 2.41.0 |\n| 乌克兰语           | ukUA | dateUkUA |        |\n| 乌兹别克语         | uzUZ | dateUzUZ | 2.39.0 |\n| 越南语（越南）     | viVN | dateViVN | 2.30.7 |\n| 简体中文           | zhCN | dateZhCN |        |\n| 繁体中文           | zhTW | dateZhTW |        |\n\n## 在现有国际化基础上调整\n\n你可以使用 `createLocale` 在现有国际化基础上调整。\n\n```html\n<template>\n  <n-config-provider :locale=\"locale\" :date-locale=\"dateZhCN\">\n    <app />\n  </n-config-provider>\n</template>\n\n<script>\n  import { defineComponent } from 'vue'\n  import { NConfigProvider, createLocale, zhCN } from 'naive-ui'\n  import { zhCN, dateZhCN } from 'naive-ui'\n\n  const customizedLocale = createLocale(\n    {\n      Input: {\n        placeholder: '不提申请不构成加班'\n      }\n    },\n    zhCN\n  )\n\n  export default defineComponent({\n    components: {\n      NConfigProvider\n    },\n    setup() {\n      return {\n        locale: customizedLocale,\n        dateZhCN\n      }\n    }\n  })\n</script>\n```\n"
  },
  {
    "path": "demo/pages/docs/import-on-demand/enUS/index.md",
    "content": "# Import on Demand (Tree Shaking)\n\nNaive UI supports tree shaking for components, locales and themes.\n\nBy default the component theme is light, locale is enUS, and no extra imports are needed.\n\nFor more info about theming, see [Customizing Theme](customize-theme).\n\n## Import Directly\n\n```html\n<script>\n  import { defineComponent } from 'vue'\n  import { NConfigProvider, NInput, NDatePicker, NSpace } from 'naive-ui'\n  // theme\n  import { createTheme, inputDark, datePickerDark } from 'naive-ui'\n  // locale & dateLocale\n  import { zhCN, dateZhCN } from 'naive-ui'\n\n  export default defineComponent({\n    components: {\n      NConfigProvider,\n      NInput,\n      NDatePicker,\n      NSpace\n    },\n    setup() {\n      return {\n        darkTheme: createTheme([inputDark, datePickerDark]),\n        zhCN,\n        dateZhCN\n      }\n    }\n  })\n</script>\n\n<template>\n  <n-config-provider :theme=\"darkTheme\" :locale=\"zhCN\" :date-locale=\"dateZhCN\">\n    <n-space vertical>\n      <n-input />\n      <n-date-picker />\n    </n-space>\n  </n-config-provider>\n</template>\n\n<style>\n  body {\n    background: black;\n  }\n</style>\n```\n\n## Auto Import\n\nYou can use the `unplugin-auto-import` plugin to automatically import APIs.\n\nIf you develop using SFC, you can use the `unplugin-vue-components` plugin to automatically import components on demand.The plugin will automatically parse the components used in the template and import the components.\n\n```ts\nimport vue from '@vitejs/plugin-vue'\nimport AutoImport from 'unplugin-auto-import/vite'\nimport { NaiveUiResolver } from 'unplugin-vue-components/resolvers'\nimport Components from 'unplugin-vue-components/vite'\n// vite.config.ts\nimport { defineConfig } from 'vite'\n\n// https://vitejs.dev/config/\nexport default defineConfig({\n  plugins: [\n    vue(),\n    AutoImport({\n      imports: [\n        'vue',\n        {\n          'naive-ui': [\n            'useDialog',\n            'useMessage',\n            'useNotification',\n            'useLoadingBar'\n          ]\n        }\n      ]\n    }),\n    Components({\n      resolvers: [NaiveUiResolver()]\n    })\n  ]\n})\n```\n\n## Install on Demand Globally\n\n```js\nimport {\n  // create naive ui\n  create,\n  // component\n  NButton\n} from 'naive-ui'\nimport { createApp } from 'vue'\n\nconst naive = create({\n  components: [NButton]\n})\n\nconst app = createApp()\napp.use(naive)\n```\n\nAfter the installation, you can use the components you installed in SFC like this.\n\n```html\n<template>\n  <n-button>naive-ui</n-button>\n</template>\n```\n"
  },
  {
    "path": "demo/pages/docs/import-on-demand/zhCN/index.md",
    "content": "# 按需引入（Tree Shaking）\n\nNaive UI 支持 tree shaking，组件、语言、主题均可 tree-shaking。\n\n默认情况组件主题为亮色，语言为英文，无需额外导入。\n\n了解更多关于主题设定的信息，参见[调整主题](customize-theme)。\n\n## 手动引入\n\n```html\n<script>\n  import { defineComponent } from 'vue'\n  import { NConfigProvider, NInput, NDatePicker, NSpace } from 'naive-ui'\n  // theme\n  import { createTheme, inputDark, datePickerDark } from 'naive-ui'\n  // locale & dateLocale\n  import { zhCN, dateZhCN } from 'naive-ui'\n\n  export default defineComponent({\n    components: {\n      NConfigProvider,\n      NInput,\n      NDatePicker,\n      NSpace\n    },\n    setup() {\n      return {\n        darkTheme: createTheme([inputDark, datePickerDark]),\n        zhCN,\n        dateZhCN\n      }\n    }\n  })\n</script>\n\n<template>\n  <n-config-provider :theme=\"darkTheme\" :locale=\"zhCN\" :date-locale=\"dateZhCN\">\n    <n-space vertical>\n      <n-input />\n      <n-date-picker />\n    </n-space>\n  </n-config-provider>\n</template>\n\n<style>\n  body {\n    background: black;\n  }\n</style>\n```\n\n## 自动引入\n\n可以使用 `unplugin-auto-import` 插件来自动导入 API。\n\n如果使用模板方式进行开发，可以使用 `unplugin-vue-components` 插件来按需自动加载组件，插件会自动解析模板中的使用到的组件，并导入组件。\n\n```ts\nimport vue from '@vitejs/plugin-vue'\nimport AutoImport from 'unplugin-auto-import/vite'\nimport { NaiveUiResolver } from 'unplugin-vue-components/resolvers'\nimport Components from 'unplugin-vue-components/vite'\n// vite.config.ts\nimport { defineConfig } from 'vite'\n\n// https://vitejs.dev/config/\nexport default defineConfig({\n  plugins: [\n    vue(),\n    AutoImport({\n      imports: [\n        'vue',\n        {\n          'naive-ui': [\n            'useDialog',\n            'useMessage',\n            'useNotification',\n            'useLoadingBar'\n          ]\n        }\n      ]\n    }),\n    Components({\n      resolvers: [NaiveUiResolver()]\n    })\n  ]\n})\n```\n\n## 按需全局安装组件（手动）\n\n```js\nimport {\n  // create naive ui\n  create,\n  // component\n  NButton\n} from 'naive-ui'\nimport { createApp } from 'vue'\n\nconst naive = create({\n  components: [NButton]\n})\n\nconst app = createApp()\napp.use(naive)\n```\n\n安装后，你可以这样在 SFC 中使用你安装的组件。\n\n```html\n<template>\n  <n-button>naive-ui</n-button>\n</template>\n```\n"
  },
  {
    "path": "demo/pages/docs/installation/enUS/index.md",
    "content": "<!--anchor:on-->\n\n# Installation\n\n> Please note that naive-ui only supports Vue3. If you are using Vue2, you may look at other libraries.\n\n## npm\n\nUse npm to install.\n\n```bash\nnpm i -D naive-ui\n```\n\n## UMD\n\nPlease refer to [Using UMD](umd).\n\n## Fonts\n\n```bash\nnpm i -D vfonts\n```\n\n## Icons\n\nnaive-ui recommends using [xicons](https://www.xicons.org) as icon library.\n\n## Design Resources\n\n<n-card size=\"small\" footer-style=\"text-align: center;\" style=\"width: 420px; max-width: 100%;\">\n  <template #cover>\n    <img src=\"https://naive-ui.oss-accelerate.aliyuncs.com/naive-design.png\">\n  </template>\n  <template #footer>\n    <n-button\n      tag=\"a\"\n      href=\"https://naive-ui.oss-accelerate.aliyuncs.com/NaiveUI-Design-Library-en-US.sketch\"\n      text\n      target=\"_blank\"\n      icon-placement=\"right\"\n    >\n      Naive UI (Sketch)\n      <template #icon>\n        <n-icon >\n          <ArrowDownload16Regular />\n        </n-icon>\n      </template>\n    </n-button>\n  </template>\n</n-card>\n\n```component\nArrowDownload16Regular: import ArrowDownload16Regular from '@vicons/fluent/ArrowDownload16Regular'\n```\n"
  },
  {
    "path": "demo/pages/docs/installation/zhCN/index.md",
    "content": "<!--anchor:on-->\n\n# 安装\n\n> 注意，naive-ui 仅支持 Vue3。如果你在使用 Vue2，可以去看看别的库。\n\n## npm\n\n使用 npm 安装。\n\n```bash\nnpm i -D naive-ui\n```\n\n## UMD\n\n参考 [使用 UMD](umd)。\n\n## 字体\n\n```bash\nnpm i -D vfonts\n```\n\n## 图标\n\nnaive-ui 建议使用 [xicons](https://www.xicons.org) 作为图标库。\n\n## 设计资源\n\n<n-card size=\"small\"  footer-style=\"text-align: center;\" style=\"width: 420px; max-width: 100%;\">\n  <template #cover>\n    <img src=\"https://naive-ui.oss-accelerate.aliyuncs.com/naive-design.png\">\n  </template>\n  <template #footer>\n    <n-button\n      tag=\"a\"\n      href=\"https://naive-ui.oss-accelerate.aliyuncs.com/NaiveUI-Design-Library-zh-CN.sketch\"\n      text\n      target=\"_blank\"\n      icon-placement=\"right\"\n    >\n      Naive UI (Sketch)\n      <template #icon>\n        <n-icon >\n          <ArrowDownload16Regular />\n        </n-icon>\n      </template>\n    </n-button>\n  </template>\n</n-card>\n\n```component\nArrowDownload16Regular: import ArrowDownload16Regular from '@vicons/fluent/ArrowDownload16Regular'\n```\n"
  },
  {
    "path": "demo/pages/docs/introduction/enUS/index.md",
    "content": "<!--anchor:on-->\n\n# Naive UI\n\nNaive UI is a Vue 3 component library.\n\nTo know how to install it, see [Installation](installation).\n\nIt is fairly complete, themeable, written in typescript, not too slow.\n\n## Fairly Complete\n\nThere are more than 90 components. Hope they can help you write less code.\n\nWhat's more, they are all treeshakable.\n\n## Theme Customizable\n\nWe provide an advanced type safe theme system that is built with typescript. All you need is to provide a theme overrides object in JS. Then all the stuffs will be done by us.\n\nWhat's more, no less/sass/css variables, no webpack loaders are required. And you can try the theme editor on the bottom right of the page.\n\n## Uses TypeScript\n\nAll the stuff in Naive UI is written in TypeScript. It can work with your typescript project seamlessly.\n\nWhat's more, you don't need to import any CSS to use the components.\n\n## Fast\n\nI try to make it not rather slow. At least select, tree, transfer, table and cascader work with virtual list.\n\nWhat's more, ..., no more. Just enjoy it.\n\n## Community\n\n- [Discord](https://discord.gg/Pqv7Mev5Dd)\n- 钉钉一群 33482509 (已满)\n- 钉钉二群 35886835 (已满)\n- 钉钉三群 32377370 (已满)\n- 钉钉四群 8165002788 (已满)\n- 钉钉五群 31205022250 (已满)\n- 钉钉六群 62720001971 (已满)\n- 钉钉七群 172000005810\n\n## Contributing\n\nPlease see [CONTRIBUTING.md](https://github.com/tusen-ai/naive-ui/blob/main/CONTRIBUTING.md).\n\n## License\n\nNaive UI is licensed under the [MIT license](https://opensource.org/licenses/MIT).\n"
  },
  {
    "path": "demo/pages/docs/introduction/zhCN/index.md",
    "content": "<!--anchor:on-->\n\n# Naive UI\n\nNaive UI 是一个 Vue3 的组件库。\n\n要了解如何安装，参见[安装](installation)。\n\n它比较完整，主题可调，用 TypeScript 写的，快。\n\n## 比较完整\n\n有超过 90 个组件，希望能帮你少写点代码。\n\n顺便一提，它们全都可以 treeshaking。\n\n## 主题可调\n\n我们提供了一个使用 TypeScript 构建的先进的类型安全主题系统。你只需要提供一个样式覆盖的对象，剩下的都交给我们。\n\n顺便一提，不用 less、sass、css 变量，也不用 webpack 的 loaders。以及你可以试试右下角的主题编辑器。\n\n## 使用 TypeScript\n\nNaive UI 全量使用 TypeScript 编写，和你的 TypeScript 项目无缝衔接。\n\n顺便一提，你不需要导入任何 CSS 就能让组件正常工作。\n\n## 快\n\n我尽力让它不要太慢。至少 select、tree、transfer、table、cascader 都可以用虚拟列表。\n\n顺便一提，...，没有顺便了。祝你使用愉快。\n\n## 社区\n\n- [Discord](https://discord.gg/Pqv7Mev5Dd)\n- 钉钉一群 33482509 (已满)\n- 钉钉二群 35886835 (已满)\n- 钉钉三群 32377370 (已满)\n- 钉钉四群 8165002788 (已满)\n- 钉钉五群 31205022250 (已满)\n- 钉钉六群 62720001971 (已满)\n- 钉钉七群 172000005810\n\n## 贡献\n\n请参考 [CONTRIBUTING.md](https://github.com/tusen-ai/naive-ui/blob/main/CONTRIBUTING.md)。\n\n## 许可\n\nNaive UI 使用 [MIT license](https://opensource.org/licenses/MIT) 许可证书。\n"
  },
  {
    "path": "demo/pages/docs/jsx/enUS/index.md",
    "content": "<!--anchor:on-->\n\n# JSX & TSX\n\n## Enable JSX & TSX\n\nFor how to enable JSX & TSX, please look at your toolchain's docs.\n\n## Use Component\n\nWe recommend importing components directly when using JSX.\n\n```js\nimport { NButton } from 'naive-ui'\nimport { defineComponent } from 'vue'\n\nexport default defineComponent({\n  render() {\n    return <NButton>{{ default: () => 'Star Kirby' }}</NButton>\n  }\n})\n```\n\n## Props look like @update:\\*\n\nIn naive-ui, all props look like `on-update:*` has a corresponding `onUpdate*` prop (since in JSX `on-update:*` and `onUpdate:*` are not valid prop names).\n\nIf you find it doesn't exist, I must have forgotten to make it. Please create an issue or PR.\n\nFor example, `<n-select @update:value=\"...\" />` in template can be written in `<NSelect onUpdateValue={...} />`.\n"
  },
  {
    "path": "demo/pages/docs/jsx/zhCN/index.md",
    "content": "<!--anchor:on-->\n\n# JSX & TSX\n\n## 启用 JSX & TSX\n\n关于启用 JSX 和 TSX，请参考你使用的工具链的相关文档。\n\n## 使用组件\n\n在 JSX 中，推荐以直接引入的形式使用组件。\n\n```js\nimport { NButton } from 'naive-ui'\nimport { defineComponent } from 'vue'\n\nexport default defineComponent({\n  render() {\n    return <NButton>{{ default: () => 'Star Kirby' }}</NButton>\n  }\n})\n```\n\n## 形如 @update:\\* 的 prop\n\nnaive-ui 中，所有形如 `on-update:*` 的 prop 都有一个对应的 `onUpdate*` 属性可供使用（由于 JSX 自身的规定，`on-update:*` 和 `onUpdate:*` 不是合法的 prop 名称）。\n\n如果你发现没有，那一定是我忘了写了，请提交一个 Issue 或者 PR。\n\n例如，在模板中 `<n-select @update:value=\"...\" />` 在 JSX 中可以写为 `<NSelect onUpdateValue={...} />`。\n"
  },
  {
    "path": "demo/pages/docs/nuxtjs/enUS/index.md",
    "content": "# Nuxt.js\n\n## Caveat\n\nThis document pertains to SSR (Server-Side Rendering). Please familiarize yourself with the [SSR Caveats](ssr#Caveat) before proceeding.\n\n## Nuxt.js Demo\n\nYou can refer to [example](https://github.com/07akioni/naive-ui-nuxt-demo).\n\n## Using Nuxt Module\n\nThis is the same approach which previous demo uses.\n\nInstall the [module](https://github.com/07akioni/nuxtjs-naive-ui) to your Nuxt application with one command:\n\n```bash\n# npm\nnpx nuxi module add nuxtjs-naive-ui\n\n# pnpm\npnpm dlx nuxi module add nuxtjs-naive-ui\n```\n\n## Using Auto Import in Nuxt\n\nYou can also use the `unplugin-auto-import` plugin to automatically import APIs and the `unplugin-vue-components` plugin to automatically import components on demand. In this case, the `nuxt.config.ts` file will have a few additional configuration lines compared to the example above.\n\n```ts\nimport AutoImport from 'unplugin-auto-import/vite'\nimport { NaiveUiResolver } from 'unplugin-vue-components/resolvers'\nimport Components from 'unplugin-vue-components/vite'\n\n// https://nuxt.com/docs/api/configuration/nuxt-config\nexport default defineNuxtConfig({\n  modules: ['nuxtjs-naive-ui'],\n  vite: {\n    plugins: [\n      AutoImport({\n        imports: [\n          {\n            'naive-ui': [\n              'useDialog',\n              'useMessage',\n              'useNotification',\n              'useLoadingBar'\n            ]\n          }\n        ]\n      }),\n      Components({\n        resolvers: [NaiveUiResolver()]\n      })\n    ]\n  }\n})\n```\n"
  },
  {
    "path": "demo/pages/docs/nuxtjs/zhCN/index.md",
    "content": "# Nuxt.js\n\n## 注意\n\n本文档涉及到 SSR，请先了解[SSR 的注意事项](ssr#注意)。\n\n## Nuxt.js 示例\n\n参考[例子](https://github.com/07akioni/naive-ui-nuxt-demo)。\n\n## 使用 Nuxt Module\n\n这和上一个示例使用的是同样的方式。\n\n在你的 Nuxt 应用中使用下列命令安装此[模块](https://github.com/07akioni/nuxtjs-naive-ui)：\n\n```bash\n# npm\nnpx nuxi module add nuxtjs-naive-ui\n\n# pnpm\npnpm dlx nuxi module add nuxtjs-naive-ui\n```\n\n## 在 Nuxt 中使用自动引入\n\n同样可以使用 `unplugin-auto-import` 插件来自动导入 API，使用 `unplugin-vue-components` 插件来按需自动加载组件。在这种情况下，`nuxt.config.ts` 会比上面的例子多几行配置。\n\n```ts\nimport AutoImport from 'unplugin-auto-import/vite'\nimport { NaiveUiResolver } from 'unplugin-vue-components/resolvers'\nimport Components from 'unplugin-vue-components/vite'\n\n// https://nuxt.com/docs/api/configuration/nuxt-config\nexport default defineNuxtConfig({\n  modules: ['nuxtjs-naive-ui'],\n  vite: {\n    plugins: [\n      AutoImport({\n        imports: [\n          {\n            'naive-ui': [\n              'useDialog',\n              'useMessage',\n              'useNotification',\n              'useLoadingBar'\n            ]\n          }\n        ]\n      }),\n      Components({\n        resolvers: [NaiveUiResolver()]\n      })\n    ]\n  }\n})\n```\n"
  },
  {
    "path": "demo/pages/docs/ssr/enUS/index.md",
    "content": "# Server-Sider Rendering\n\nSince naive-ui is using CSS in JS, in SSR mode it needs some extra configuration.\n\n## Caveat\n\nWhen using SSR under any framework, it is essential to ensure that the project meets the following conditions:\n\n1. During the build process, any direct or indirect references to the `@css-render/*` and `css-render` packages must have a version of `>=0.15.14`.\n2. During the build process, each direct or indirect reference to any `@css-render/*` and `css-render` package should ultimately point to a single target (a package should not have multiple versions or multiple copies of the same version).\n\nYou can search for `css-render` in the lock file to check for duplicate packages.\n\nFailure to meet these conditions may result in SSR build failures.\n\nIf you encounter issues due to this, you can resolve the problem by directing all related packages to the same version using the `resolution` field in the `package.json` file.\n\n## Nuxt.js\n\nSee [Nuxt.js](nuxtjs).\n\n## Vitepress\n\nSee [Vitepress](vitepress).\n\n## Vite SSG/SSE\n\nSee [Vite SSG/SSE](vite-ssge).\n\n## Vite Example\n\nIf you are using Vite, please see [example](https://github.com/07akioni/naive-ui-vite-ssr).\n\n## Webpack Example\n\nIf you are using Webpack, please see [example](https://github.com/tusen-ai/naive-ui/tree/main/playground/ssr).\n\n## Inline Style Optimization\n\nBy default, naive-ui bind inline theme style on components, it may increase SSR rendered HTML size. You may use `inline-theme-disabled` prop on `n-config-provider` to disable it. For pros & cons see `n-config-provider`'s doc.\n\n## Known Issues\n\nThe following components has some bugs in SSR scene, please avoid using them if possible. We will fix them gradually.\n\n- `n-scrollbar`, `n-data-table` (It works after vue >= 3.2.36)\n- `n-anchor`\n- `n-avatar-group`\n- `n-watermark`\n- `n-affix`\n- `n-transfer`\n"
  },
  {
    "path": "demo/pages/docs/ssr/zhCN/index.md",
    "content": "# 服务端渲染 Server-Sider Rendering\n\n由于 naive-ui 在使用 CSS in JS，在 SSR 的情况下需要一些额外的配置。\n\n## 注意\n\n无论在任何框架下使用 SSR，需要确保项目满足以下条件：\n\n1. 构建时，任何被直接和间接引用的 `@css-render/*` 和 `css-render` 包版本都 `>=0.15.14`\n2. 构建时，任何被直接和间接引用的每个 `@css-render/*` 和 `css-render` 包最终只都指向一个目标（一个包不会有多个版本，也不会有同一个版本的多个副本）\n\n你可以在 lock file 中搜索 `css-render` 去检查是否有重复的包。\n\n如果上述条件没有满足，可能会导致 SSR 构建失败。\n\n如果因为这个原因遇到问题，你可以通过 `package.json` 中的 `resolution` 字段来让所有相关包指向同一个版本来解决问题。\n\n## Nuxt.js\n\n参考 [Nuxt.js](nuxtjs)。\n\n## Vitepress\n\n参考 [Vitepress](vitepress)。\n\n## Vite SSG/SSE\n\n参考 [Vite SSG/SSE](vite-ssge)。\n\n## Vite 示例\n\n如果你是用的是 Vite，请参考[例子](https://github.com/07akioni/naive-ui-vite-ssr)。\n\n## Webpack 示例\n\n如果你使用的是 Webpack，请参考[例子](https://github.com/tusen-ai/naive-ui/tree/main/playground/ssr)。\n\n## 内联样式优化\n\n默认情况下，naive-ui 会在组件上绑定 inline 主题样式，这可能会影响 SSR 的尺寸。你可以使用 `n-config-provider` 的 `inline-theme-disabled` 属性来优化，详细的优劣请参考 `n-config-provider` 的文档。\n\n## 已知问题\n\n下列组件在 SSR 场景中存在一些 Bug，使用时请尽量规避，我们会逐步修复。\n\n- `n-scrollbar`, `n-data-table`（vue 版本 >= 3.2.36 后没有问题)\n- `n-anchor`\n- `n-avatar-group`\n- `n-watermark`\n- `n-affix`\n- `n-transfer`\n"
  },
  {
    "path": "demo/pages/docs/style-conflict/enUS/index.md",
    "content": "# Potential Style Conflict\n\n## Style Element Position\n\nSometimes you want to control where the style element should be inserted.\n\nFor example. If you have a tailwind reset style, you don't want it to be inserted after naive-ui's style. Since it may override button's style, etc.\n\nYou can create a `<meta name=\"naive-ui-style\" />` element inside `head` element, then naive-ui's style will be inserted right before it.\n\nAlso, naive-ui uses [vueuc](https://github.com/07akioni/vueuc). If you need, its style can be controlled by `<meta name=\"vueuc-style\" />` (generally it's not needed).\n\n```html\n<head>\n  <xxx />\n  <!-- naive-ui's style will be inserted here -->\n  <meta name=\"naive-ui-style\" />\n  <!-- vueuc's style will be inserted here -->\n  <meta name=\"vueuc-style\" />\n  <xxx />\n</head>\n```\n\n## About Tailwind's Preflight Style Override\n\nYou may find adding a meta tag to your static html files doesn't work (naive's style would still be overriden), since your toolchain may always insert tailwind's style at the end of the head tag. In this situation, you need to insert the meta tag dynamically right before the app is mounted.\n\n```ts\nconst meta = document.createElement('meta')\nmeta.name = 'naive-ui-style'\ndocument.head.appendChild(meta)\n\nvueApp.mount('#app')\n```\n\n## Disable Preflight Style (CSS Reset)\n\nTo make naive-ui work for most users out of box, mounting any component of naive would create global preflight style. However it may not be expected. If you want to disable it, using `n-config-provider` like this.\n\n```html\n<n-config-provider preflight-style-disabled>\n  <your-app />\n</n-config-provider>\n```\n"
  },
  {
    "path": "demo/pages/docs/style-conflict/zhCN/index.md",
    "content": "# 潜在的样式冲突\n\n## 样式元素的位置\n\n有时你可能希望控制样式元素插入的位置。\n\n例如，如果你使用了 tailwind 的 reset 样式，你不希望它被插入 naive-ui 样式的后面，因为这可能会覆盖按钮等组件的样式。\n\n你可以在 `head` 元素中加入一个 `<meta name=\"naive-ui-style\" />` 元素，naive-ui 会把所有的样式刚好插入这个元素的前面。\n\n同时，naive-ui 依赖 [vueuc](https://github.com/07akioni/vueuc)。如果你需要（通常应该不会），它的样式位置可以通过 `<meta name=\"vueuc-style\" />` 控制。\n\n```html\n<head>\n  <xxx />\n  <!-- naive-ui 的样式会出现在这里 -->\n  <meta name=\"naive-ui-style\" />\n  <!-- vueuc 的样式会出现在这里 -->\n  <meta name=\"vueuc-style\" />\n  <xxx />\n</head>\n```\n\n## 关于 tailwind 的 preflight 样式\n\n你可能会发现在静态 HTML 文件中加入 meta 标签没用（naive 的样式仍然可能被覆盖），因为你的工具链可能永远会把 tailwind 的样式插入 head 的尾部。这种情况下，你需要在 app 挂载之前动态的插入 meta 标签。\n\n```ts\nconst meta = document.createElement('meta')\nmeta.name = 'naive-ui-style'\ndocument.head.appendChild(meta)\n\nvueApp.mount('#app')\n```\n\n## 禁用 preflight 样式\n\n为了让多数用户直接无配置的使用 naive-ui，挂载任何一个组件都会创建全局的 CSS 样式。但是这样可能不是期望的行为，你可以使用 `n-config-provider` 来禁用这个行为。\n\n```html\n<n-config-provider preflight-style-disabled>\n  <your-app />\n</n-config-provider>\n```\n"
  },
  {
    "path": "demo/pages/docs/supported-platforms/enUS/index.md",
    "content": "<!--anchor:on-->\n\n# Supported Platforms\n\n## Browsers\n\nIE is not supported.\n\nModern browsers such as `Edge`, `Firefox`, `Chrome`, `Safari` are tested on the latest 2 versions.\n\nNo strict tests are being implemented on other versions due to the constraint of development resources, but naive-ui is expected to work on those browsers whose version is not too old (eg. in 2 years). If you find any problems please feel free to create an issue.\n\n## Vue\n\nOnly Vue 3 (>3.0.5) is supported.\n\n## TypeScript\n\nRequires version > 4.1.\n"
  },
  {
    "path": "demo/pages/docs/supported-platforms/zhCN/index.md",
    "content": "<!--anchor:on-->\n\n# 支持的平台\n\n## 浏览器\n\n不支持 IE 浏览器。\n\n`Edge`、`Firefox`、`Chrome`、`Safari` 等现代浏览器的最新的 2 个版本确保会被支持。\n\n对于这些浏览器的其他版本中，由于开发资源的限制并没有做过严格的测试。但是我们预期 naive-ui 应该在这些浏览器不算太老的版本上能正常的运行（比如 2 年之内的版本）。如果你发现了任何问题欢迎来提 issue。\n\n## Vue\n\n只支持 Vue 3（>3.0.5）。\n\n## TypeScript\n\n需要版本 > 4.1。\n"
  },
  {
    "path": "demo/pages/docs/theme/enUS/element.demo.vue",
    "content": "<markdown>\n# Use Naive Element\n\nNaive UI has `n-element` component. See [Element](../components/element).\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { darkTheme } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst theme = ref<typeof darkTheme | null>(null)\n</script>\n\n<template>\n  <n-space vertical>\n    <n-space>\n      <n-button @click=\"theme = darkTheme\">\n        Dark\n      </n-button>\n      <n-button @click=\"theme = null\">\n        Light\n      </n-button>\n    </n-space>\n    <n-config-provider :theme=\"theme\">\n      <n-card>\n        <n-el\n          tag=\"span\"\n          style=\"\n            color: var(--primary-color);\n            transition: 0.3s var(--cubic-bezier-ease-in-out);\n          \"\n        >\n          I am a Span.\n        </n-el>\n      </n-card>\n    </n-config-provider>\n  </n-space>\n</template>\n"
  },
  {
    "path": "demo/pages/docs/theme/enUS/index.demo-entry.md",
    "content": "# Create Themed Component\n\nYou may not want to use only the provided components and want to write themed components.\n\nNaive UI provides some tools for developers to create themed components easier.\n\n## Demos\n\n```demo\nprovide-theme.vue\nelement.vue\nuse-theme-vars.vue\n```\n"
  },
  {
    "path": "demo/pages/docs/theme/enUS/provide-theme.demo.vue",
    "content": "<markdown>\n# Provide Theme\n\nUse `n-config-provider` to set the theme of all its descendant components.\n</markdown>\n\n<script setup lang=\"ts\">\nimport { darkTheme } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst theme = ref<typeof darkTheme | null>(null)\n</script>\n\n<template>\n  <n-config-provider :theme=\"theme\">\n    <n-card>\n      <n-space>\n        <n-button @click=\"theme = darkTheme\">\n          Dark\n        </n-button>\n        <n-button @click=\"theme = null\">\n          Light\n        </n-button>\n      </n-space>\n    </n-card>\n  </n-config-provider>\n</template>\n"
  },
  {
    "path": "demo/pages/docs/theme/enUS/use-theme-vars.demo.vue",
    "content": "<markdown>\n# useThemeVars\n\nNaive UI provides `useThemeVars`. It contains common theme variables.\n</markdown>\n\n<script setup lang=\"ts\">\nimport { useThemeVars } from 'naive-ui'\n\nconst themeVars = useThemeVars()\n</script>\n\n<template>\n  <pre style=\"overflow: auto\">{{ themeVars }}</pre>\n</template>\n"
  },
  {
    "path": "demo/pages/docs/theme/zhCN/element.demo.vue",
    "content": "<markdown>\n# 使用元素组件\n\nNaive UI 提供 `n-element` 组件，参考 [Element](../components/element)。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { darkTheme } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst theme = ref<typeof darkTheme | null>(null)\n</script>\n\n<template>\n  <n-space vertical>\n    <n-space>\n      <n-button @click=\"theme = darkTheme\">\n        深色\n      </n-button>\n      <n-button @click=\"theme = null\">\n        浅色\n      </n-button>\n    </n-space>\n    <n-config-provider :theme=\"theme\">\n      <n-card>\n        <n-el\n          tag=\"span\"\n          style=\"\n            color: var(--primary-color);\n            transition: 0.3s var(--cubic-bezier-ease-in-out);\n          \"\n        >\n          我是个 span 标签\n        </n-el>\n      </n-card>\n    </n-config-provider>\n  </n-space>\n</template>\n"
  },
  {
    "path": "demo/pages/docs/theme/zhCN/index.demo-entry.md",
    "content": "# 创建适配主题的组件\n\n你可能觉得只用内置的组件不够爽，想自己也写适配主题的组件。\n\nNaive UI 提供一些工具帮助开发者简单的创建支持主题的组件。\n\n## 演示\n\n```demo\nprovide-theme.vue\nelement.vue\nuse-theme-vars.vue\n```\n"
  },
  {
    "path": "demo/pages/docs/theme/zhCN/provide-theme.demo.vue",
    "content": "<markdown>\n# 提供主题\n\n使用 `n-config-provider` 来设定它全部的后代组件主题。\n</markdown>\n\n<script setup lang=\"ts\">\nimport { darkTheme } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst theme = ref<typeof darkTheme | null>(null)\n</script>\n\n<template>\n  <n-config-provider :theme=\"theme\">\n    <n-card>\n      <n-space>\n        <n-button @click=\"theme = darkTheme\">\n          Dark\n        </n-button>\n        <n-button @click=\"theme = null\">\n          Light\n        </n-button>\n      </n-space>\n    </n-card>\n  </n-config-provider>\n</template>\n"
  },
  {
    "path": "demo/pages/docs/theme/zhCN/use-theme-vars.demo.vue",
    "content": "<markdown>\n# useThemeVars\n\nNaive UI 提供 `useThemeVars`，它包含了常见的主题变量。\n</markdown>\n\n<script setup lang=\"ts\">\nimport { useThemeVars } from 'naive-ui'\n\nconst themeVars = useThemeVars()\n</script>\n\n<template>\n  <pre style=\"overflow: auto\">{{ themeVars }}</pre>\n</template>\n"
  },
  {
    "path": "demo/pages/docs/umd/enUS/index.md",
    "content": "# Using UMD\n\n<n-alert title=\"Warning\" type=\"warning\" :bordered=\"false\">\n  There is a self-closing bug in UMD version of naive. Please close tags explicitly like <n-text code>&lt;n-input>&lt;/n-input></n-text>.\n</n-alert>\n\nAfter version `2.30.3`, you can use UMD version of naive.\n\nIf you want to use a minified version of naive, use `https://unpkg.com/naive-ui@version/dist/index.prod.js` as `src`. `version` is the version of naive-ui you want to use. If you don't specify a version, latest version would be used.\n\nIt's preferable to link to a specific version of the package, as always relying on the latest version may lead to breaking changes.\n\nHere's a basic [demo](https://jsbin.com/saxubitaki/1/edit?html,output):\n\n```html\n<!DOCTYPE html>\n<html>\n  <head>\n    <meta charset=\"utf-8\" />\n    <script src=\"https://unpkg.com/vue\"></script>\n    <!-- Would use latest version, you'd better specify a version -->\n    <script src=\"https://unpkg.com/naive-ui\"></script>\n  </head>\n  <body>\n    <div id=\"app\">\n      <n-button>{{ message }}</n-button>\n    </div>\n    <script>\n      const App = {\n        setup() {\n          return {\n            message: 'naive'\n          }\n        }\n      }\n      const app = Vue.createApp(App)\n      app.use(naive)\n      app.mount('#app')\n    </script>\n  </body>\n</html>\n```\n"
  },
  {
    "path": "demo/pages/docs/umd/zhCN/index.md",
    "content": "# 使用 UMD\n\n<n-alert title=\"警告\" type=\"warning\" :bordered=\"false\">\n  目前 UMD 版本的 naive 标签自闭合存在问题。请显式进行标签闭合。如：<n-text code>&lt;n-input>&lt;/n-input></n-text>。\n</n-alert>\n\n在 `2.30.3` 版本后，你可以使用 UMD 版本的 naive。\n\n如果你要使用 minify 版本的包，将 `https://unpkg.com/naive-ui@version/dist/index.prod.js` 作为 `src`，`version` 是你期望使用的版本，如果不指定 `version` 则会使用最新的版本。\n\n你最好锁定包的版本，不然可能会有不兼容变更。\n\n下面是个基本 [demo](https://jsbin.com/saxubitaki/1/edit?html,output)：\n\n```html\n<!DOCTYPE html>\n<html>\n  <head>\n    <meta charset=\"utf-8\" />\n    <script src=\"https://unpkg.com/vue\"></script>\n    <!-- 会使用最新版本，你最好指定一个版本 -->\n    <script src=\"https://unpkg.com/naive-ui\"></script>\n  </head>\n  <body>\n    <div id=\"app\">\n      <n-button>{{ message }}</n-button>\n    </div>\n    <script>\n      const App = {\n        setup() {\n          return {\n            message: 'naive'\n          }\n        }\n      }\n      const app = Vue.createApp(App)\n      app.use(naive)\n      app.mount('#app')\n    </script>\n  </body>\n</html>\n```\n"
  },
  {
    "path": "demo/pages/docs/usage-sfc/enUS/index.md",
    "content": "<!--anchor:on-->\n\n# Usage in SFC\n\nIf you want to use the Single File Component(SFC) style, you can directly import components from Naive UI or install it globally to a Vue app.\n\n## Import Directly (Recommended)\n\nYou can import a component directly and use it. In this form, only components imported will be bundled.\n\nIf you want to know how to import themes and locales, please see [Import on Demand](import-on-demand).\n\n```html\n<template>\n  <n-button>naive-ui</n-button>\n</template>\n\n<script>\n  import { defineComponent } from 'vue'\n  import { NButton } from 'naive-ui'\n\n  export default defineComponent({\n    components: {\n      NButton\n    }\n  })\n</script>\n```\n\nIf you can use vue setup script, you can use it like this.\n\n```html\n<template>\n  <n-button>naive-ui</n-button>\n</template>\n\n<script setup>\n  import { NButton } from 'naive-ui'\n</script>\n```\n\n## Install Globally (Not Recommended)\n\n### Install All Components\n\nNo tree-shaking. Bundle will have redundant codes.\n\nIf you want to install globally but don't want all components, please see [Import on Demand](import-on-demand).\n\n```js\nimport naive from 'naive-ui'\nimport { createApp } from 'vue'\n\nconst app = createApp(App)\napp.use(naive)\n```\n\nAfter the installation, you can use all the components in your SFC like this.\n\n```html\n<template>\n  <n-button>naive-ui</n-button>\n</template>\n```\n\n### Volar support (2.24.2)\n\nIf you are using Volar, you can specify global component types by configuring `compilerOptions.types` in `tsconfig.json`.\n\n```json\n// tsconfig.json\n{\n  \"compilerOptions\": {\n    // ...\n    \"types\": [\"naive-ui/volar\"]\n  }\n}\n```\n"
  },
  {
    "path": "demo/pages/docs/usage-sfc/zhCN/index.md",
    "content": "<!--anchor:on-->\n\n# 在 SFC 中使用\n\n如果你想使用单文件组件风格（SFC - Single File Component），可以选择直接引入或全局安装在 Vue App 中。\n\n## 直接引入（推荐）\n\n你可以直接导入组件并使用它。这种情况下，只有导入的组件才会被打包。\n\n如果你想知道如何按需引入主题和语言包，请参考[按需引入](import-on-demand)。\n\n```html\n<template>\n  <n-button>naive-ui</n-button>\n</template>\n\n<script>\n  import { defineComponent } from 'vue'\n  import { NButton } from 'naive-ui'\n\n  export default defineComponent({\n    components: {\n      NButton\n    }\n  })\n</script>\n```\n\n如果你可以使用 setup script，你可以用下面的方式使用组件。\n\n```html\n<template>\n  <n-button>naive-ui</n-button>\n</template>\n\n<script setup>\n  import { NButton } from 'naive-ui'\n</script>\n```\n\n## 全局安装（不推荐）\n\n### 安装全部组件\n\n失去 tree-shaking 的能力，打包有冗余代码。\n\n如果你想全局安装但是不想安装全部组件，请参考[按需引入](import-on-demand)。\n\n```js\nimport naive from 'naive-ui'\nimport { createApp } from 'vue'\n\nconst app = createApp(App)\napp.use(naive)\n```\n\n安装后，你可以这样在 SFC 中使用全部组件。\n\n```html\n<template>\n  <n-button>naive-ui</n-button>\n</template>\n```\n\n### Volar 支持（2.24.2）\n\n如果你在使用 Volar，那么可以在 `tsconfig.json` 中配置 `compilerOptions.types` 来指定全局组件类型。\n\n```json\n// tsconfig.json\n{\n  \"compilerOptions\": {\n    // ...\n    \"types\": [\"naive-ui/volar\"]\n  }\n}\n```\n"
  },
  {
    "path": "demo/pages/docs/vite-ssge/enUS/index.md",
    "content": "# Vite SSG/SSE\n\n## Caveat\n\nThis document pertains to SSR (Server-Side Rendering). Please familiarize yourself with the [SSR Caveats](ssr#Caveat) before proceeding.\n\n## Setup Guide\n\nIf you are using `vite-sse` or `vite-ssg`. Follow the following steps to setup `naive-ui`.\n\n### 1. Install `naive-ui`, `@css-render/vue3-ssr`\n\n```bash\n# pnpm\npnpm i naive-ui @css-render/vue3-ssr\n\n# npm\nnpm i naive-ui @css-render/vue3-ssr\n```\n\n### 2. Modify `vite.config.ts`\n\nAdd following content. If there exists content already, merge them.\n\n```ts\nimport { setup } from '@css-render/vue3-ssr'\n\ndefineConfig({\n  ssr: {\n    noExternal: ['naive-ui', 'vueuc', 'date-fns']\n  },\n  ssgOptions: {\n    async onBeforePageRender(_, __, appCtx) {\n      const { collect } = setup(appCtx.app)\n      ;(appCtx as any).__collectStyle = collect\n      return undefined\n    },\n    async onPageRendered(_, renderedHTML, appCtx) {\n      return renderedHTML.replace(\n        /<\\/head>/,\n        `${(appCtx as any).__collectStyle()}</head>`\n      )\n    }\n  }\n})\n```\n\nThen you can using naive-ui in `vite-ssg` or `vite-sse` project.\n"
  },
  {
    "path": "demo/pages/docs/vite-ssge/zhCN/index.md",
    "content": "# Vite SSG/SSE\n\n## 注意\n\n本文档涉及到 SSR，请先了解[SSR 的注意事项](ssr#注意)。\n\n## 配置指南\n\n如果你正在使用 `vite-sse` 或者 `vite-ssg`，通过下面的步骤设定 `naive-ui`。\n\n### 1. 安装 `naive-ui`、`@css-render/vue3-ssr`\n\n```bash\n# pnpm\npnpm i naive-ui @css-render/vue3-ssr\n\n# npm\nnpm i naive-ui @css-render/vue3-ssr\n```\n\n### 2. 修改 `vite.config.ts`\n\n增加下列内容，如果已经存在一些内容，则合并他们。\n\n```ts\nimport { setup } from '@css-render/vue3-ssr'\n\ndefineConfig({\n  ssr: {\n    noExternal: ['naive-ui', 'vueuc', 'date-fns']\n  },\n  ssgOptions: {\n    async onBeforePageRender(_, __, appCtx) {\n      const { collect } = setup(appCtx.app)\n      ;(appCtx as any).__collectStyle = collect\n      return undefined\n    },\n    async onPageRendered(_, renderedHTML, appCtx) {\n      return renderedHTML.replace(\n        /<\\/head>/,\n        `${(appCtx as any).__collectStyle()}</head>`\n      )\n    }\n  }\n})\n```\n\n现在你可以在 `vite-ssg` 或 `vite-sse` 项目中使用 `naive-ui` 了。\n"
  },
  {
    "path": "demo/pages/docs/vitepress/enUS/index.md",
    "content": "# Vitepress\n\n## Caveat\n\nThis document pertains to SSR (Server-Side Rendering). Please familiarize yourself with the [SSR Caveats](ssr#Caveat) before proceeding.\n\n## Example\n\nThis is a [demo](https://github.com/07akioni/naive-ui-vitepress-demo) for using `naive-ui` in `vitepress` with SSR enabled.\n\nYou can directly use the demo.\n\n## Key process from scratch\n\nIf you want to build your own demo from scratch, follow the next steps:\n\n### 0. Install `@css-render/vue3-ssr`\n\nMake sure its version `>=0.15.14`.\n\n```bash\n# npm\nnpm install --save-dev @css-render/vue3-ssr\n\n# pnpm\npnpm install --save-dev @css-render/vue3-ssr\n```\n\n### 1. Add this content to `.vitepress/theme/index.js`\n\n```js\n// .vitepress/theme/index.js\n\nimport { setup } from '@css-render/vue3-ssr'\nimport { NConfigProvider } from 'naive-ui'\nimport { useRoute } from 'vitepress'\nimport DefaultTheme from 'vitepress/theme'\nimport { defineComponent, h, inject } from 'vue'\n\nconst { Layout } = DefaultTheme\n\nconst CssRenderStyle = defineComponent({\n  setup() {\n    const collect = inject('css-render-collect')\n    return {\n      style: collect()\n    }\n  },\n  render() {\n    return h('css-render-style', {\n      innerHTML: this.style\n    })\n  }\n})\n\nconst VitepressPath = defineComponent({\n  setup() {\n    const route = useRoute()\n    return () => {\n      return h('vitepress-path', null, [route.path])\n    }\n  }\n})\n\nconst NaiveUIProvider = defineComponent({\n  render() {\n    return h(\n      NConfigProvider,\n      { abstract: true, inlineThemeDisabled: true },\n      {\n        default: () => [\n          h(Layout, null, { default: this.$slots.default?.() }),\n          import.meta.env.SSR ? [h(CssRenderStyle), h(VitepressPath)] : null\n        ]\n      }\n    )\n  }\n})\n\nexport default {\n  extends: DefaultTheme,\n  Layout: NaiveUIProvider,\n  enhanceApp: ({ app }) => {\n    if (import.meta.env.SSR) {\n      const { collect } = setup(app)\n      app.provide('css-render-collect', collect)\n    }\n  }\n}\n```\n\n### 2. Add this content to `.vitepress/config.mts`\n\n```ts\nimport { defineConfig } from 'vitepress'\n\nconst fileAndStyles: Record<string, string> = {}\n\nexport default defineConfig({\n  // ...\n  vite: {\n    ssr: {\n      noExternal: ['naive-ui', 'date-fns', 'vueuc']\n    }\n  },\n  postRender(context) {\n    const styleRegex = /<css-render-style>((.|\\s)+)<\\/css-render-style>/\n    const vitepressPathRegex = /<vitepress-path>(.+)<\\/vitepress-path>/\n    const style = styleRegex.exec(context.content)?.[1]\n    const vitepressPath = vitepressPathRegex.exec(context.content)?.[1]\n    if (vitepressPath && style) {\n      fileAndStyles[vitepressPath] = style\n    }\n    context.content = context.content.replace(styleRegex, '')\n    context.content = context.content.replace(vitepressPathRegex, '')\n  },\n  transformHtml(code, id) {\n    const html = id.split('/').pop()\n    if (!html)\n      return\n    const style = fileAndStyles[`/${html}`]\n    if (style) {\n      return code.replace(/<\\/head>/, `${style}</head>`)\n    }\n  }\n})\n```\n\n### 3. Start using naive-ui in your markdown file\n\n```md\n...\n\n<script setup>\nimport { NButton } from 'naive-ui'\n</script>\n\n<NButton>Hello World</NButton>\n\n...\n```\n"
  },
  {
    "path": "demo/pages/docs/vitepress/zhCN/index.md",
    "content": "# Vitepress\n\n## 注意\n\n本文档涉及到 SSR，请先了解[SSR 的注意事项](ssr#注意)。\n\n## 例子\n\n这是一个使用 `naive-ui`、`vitepress` 的[样例](https://github.com/07akioni/naive-ui-vitepress-demo)，支持 SSR。\n\n你可以直接使用这个样例。\n\n## 从零开始的关键步骤\n\n如果你希望从头开始改造一个 vitepress 项目，遵循下列步骤\n\n### 0. 安装 `@css-render/vue3-ssr`\n\n确保其版本 `>=0.15.14`。\n\n```bash\n# npm\nnpm install --save-dev @css-render/vue3-ssr\n\n# pnpm\npnpm install --save-dev @css-render/vue3-ssr\n```\n\n### 1. 把下面的内容增加到 `.vitepress/theme/index.js`\n\n```js\n// .vitepress/theme/index.js\n\nimport { setup } from '@css-render/vue3-ssr'\nimport { NConfigProvider } from 'naive-ui'\nimport { useRoute } from 'vitepress'\nimport DefaultTheme from 'vitepress/theme'\nimport { defineComponent, h, inject } from 'vue'\n\nconst { Layout } = DefaultTheme\n\nconst CssRenderStyle = defineComponent({\n  setup() {\n    const collect = inject('css-render-collect')\n    return {\n      style: collect()\n    }\n  },\n  render() {\n    return h('css-render-style', {\n      innerHTML: this.style\n    })\n  }\n})\n\nconst VitepressPath = defineComponent({\n  setup() {\n    const route = useRoute()\n    return () => {\n      return h('vitepress-path', null, [route.path])\n    }\n  }\n})\n\nconst NaiveUIProvider = defineComponent({\n  render() {\n    return h(\n      NConfigProvider,\n      { abstract: true, inlineThemeDisabled: true },\n      {\n        default: () => [\n          h(Layout, null, { default: this.$slots.default?.() }),\n          import.meta.env.SSR ? [h(CssRenderStyle), h(VitepressPath)] : null\n        ]\n      }\n    )\n  }\n})\n\nexport default {\n  extends: DefaultTheme,\n  Layout: NaiveUIProvider,\n  enhanceApp: ({ app }) => {\n    if (import.meta.env.SSR) {\n      const { collect } = setup(app)\n      app.provide('css-render-collect', collect)\n    }\n  }\n}\n```\n\n### 2. 把下面的内容增加到 `.vitepress/config.mts`\n\n```ts\nimport { defineConfig } from 'vitepress'\n\nconst fileAndStyles: Record<string, string> = {}\n\nexport default defineConfig({\n  // ...\n  vite: {\n    ssr: {\n      noExternal: ['naive-ui', 'date-fns', 'vueuc']\n    }\n  },\n  postRender(context) {\n    const styleRegex = /<css-render-style>((.|\\s)+)<\\/css-render-style>/\n    const vitepressPathRegex = /<vitepress-path>(.+)<\\/vitepress-path>/\n    const style = styleRegex.exec(context.content)?.[1]\n    const vitepressPath = vitepressPathRegex.exec(context.content)?.[1]\n    if (vitepressPath && style) {\n      fileAndStyles[vitepressPath] = style\n    }\n    context.content = context.content.replace(styleRegex, '')\n    context.content = context.content.replace(vitepressPathRegex, '')\n  },\n  transformHtml(code, id) {\n    const html = id.split('/').pop()\n    if (!html)\n      return\n    const style = fileAndStyles[`/${html}`]\n    if (style) {\n      return code.replace(/<\\/head>/, `${style}</head>`)\n    }\n  }\n})\n```\n\n### 3. 在 markdown 文件中开始使用 naive-ui\n\n```md\n...\n\n<script setup>\nimport { NButton } from 'naive-ui'\n</script>\n\n<NButton>Hello World</NButton>\n\n...\n```\n"
  },
  {
    "path": "demo/pages/docs/vue3/enUS/index.vue",
    "content": "<script>\nimport Vue3 from '../../../../../vue3.md'\n\nexport default {\n  components: {\n    Vue3\n  }\n}\n</script>\n\n<template>\n  <Vue3 />\n</template>\n"
  },
  {
    "path": "demo/pages/docs/vue3/zhCN/index.vue",
    "content": "<script>\nimport Vue3 from '../../../../../vue3.md'\n\nexport default {\n  components: {\n    Vue3\n  }\n}\n</script>\n\n<template>\n  <Vue3 />\n</template>\n"
  },
  {
    "path": "demo/pages/home/Footer.vue",
    "content": "<script lang=\"ts\">\nimport { version } from 'naive-ui'\nimport { defineComponent } from 'vue'\nimport { push } from '../../store'\nimport { i18n } from '../../utils/composables'\nimport { repoUrl } from '../../utils/github-url'\n\nexport default defineComponent({\n  props: {\n    centered: Boolean\n  },\n  setup() {\n    return {\n      version,\n      repoUrl,\n      push,\n      ...i18n({\n        'zh-CN': {\n          resources: '资源',\n          designResources: '设计资源',\n          help: '帮助',\n          community: '社区',\n          contact: '联系我们',\n          changelog: '更新日志',\n          commonIssues: '常见问题',\n          tusimple: '图森未来',\n          icons: '图标库',\n          libraries: '社区精选资源',\n          dingTalk: '钉钉',\n          dingTalkGroupChat: '钉钉交流群',\n          memberLimitReached: '（已满）',\n          reportBug: '报告 Bug',\n          sketchLink:\n            'https://naive-ui.oss-accelerate.aliyuncs.com/NaiveUI-Design-Library-zh-CN.sketch',\n          joinUsLink: 'https://app.mokahr.com/campus_apply/tusenweilai/3232#/'\n        },\n        'en-US': {\n          resources: 'Resources',\n          designResources: 'Design Resources',\n          help: 'Help',\n          community: 'Community',\n          contact: 'Contact Us',\n          changelog: 'Change Log',\n          commonIssues: 'Common Issues',\n          tusimple: 'TuSimple',\n          icons: 'Icon Library',\n          libraries: 'Third-Party Libraries',\n          dingTalk: 'DingTalk',\n          dingTalkGroupChat: 'DingTalk Group Chat',\n          memberLimitReached: '(Member limit reached)',\n          reportBug: 'Report Bug',\n          sketchLink:\n            'https://naive-ui.oss-accelerate.aliyuncs.com/NaiveUI-Design-Library-en-US.sketch',\n          joinUsLink:\n            'https://boards.greenhouse.io/tusimplerelocationjobs/jobs/5137805002?gh_src=7908a9242us'\n        }\n      })\n    }\n  }\n})\n</script>\n\n<template>\n  <n-layout-footer\n    bordered\n    class=\"footer\"\n    :class=\"{\n      ['footer--centered']: centered,\n    }\"\n  >\n    <div class=\"footer-links\">\n      <div class=\"footer-links-col\">\n        <n-text depth=\"1\" class=\"col-header\">\n          {{ t('resources') }}\n        </n-text>\n        <n-button text tag=\"a\" :href=\"t('sketchLink')\" download>\n          {{ t('designResources') }}\n        </n-button>\n        <n-button text tag=\"a\" target=\"_blank\" href=\"https://www.xicons.org\">\n          {{ t('icons') }}\n        </n-button>\n        <n-button text @click=\"push('/docs/community')\">\n          {{ t('libraries') }}\n        </n-button>\n      </div>\n      <div class=\"footer-links-col\">\n        <n-text depth=\"1\" class=\"col-header\">\n          {{ t('help') }}\n        </n-text>\n        <n-button text @click=\"push('/docs/common-issues')\">\n          {{ t('commonIssues') }}\n        </n-button>\n        <n-button text @click=\"push('/docs/changelog')\">\n          {{ t('changelog') }}\n        </n-button>\n        <n-button\n          text\n          tag=\"a\"\n          target=\"_blank\"\n          href=\"https://naive-ui.github.io/issue-helper/\"\n        >\n          {{ t('reportBug') }}\n        </n-button>\n      </div>\n      <div class=\"footer-links-col\">\n        <n-text depth=\"1\" class=\"col-header\">\n          {{ t('community') }}\n        </n-text>\n        <n-button text tag=\"a\" target=\"_blank\" :href=\"repoUrl\">\n          GitHub\n        </n-button>\n        <n-button\n          text\n          tag=\"a\"\n          href=\"https://discord.gg/Pqv7Mev5Dd\"\n          target=\"_blank\"\n        >\n          Discord\n        </n-button>\n        <n-tooltip>\n          <template #trigger>\n            <n-button text>\n              {{ t('dingTalk') }}\n            </n-button>\n          </template>\n          {{ t('dingTalkGroupChat') }} 1\n          {{ t('memberLimitReached') }} 33482509<br>\n          {{ t('dingTalkGroupChat') }} 2\n          {{ t('memberLimitReached') }} 35886835<br>\n          {{ t('dingTalkGroupChat') }} 3\n          {{ t('memberLimitReached') }} 32377370<br>\n          {{ t('dingTalkGroupChat') }} 4\n          {{ t('memberLimitReached') }} 8165002788<br>\n          {{ t('dingTalkGroupChat') }} 5\n          {{ t('memberLimitReached') }} 31205022250<br>\n          {{ t('dingTalkGroupChat') }} 6\n          {{ t('memberLimitReached') }} 62720001971<br>\n          {{ t('dingTalkGroupChat') }} 7 172000005810\n        </n-tooltip>\n      </div>\n      <div class=\"footer-links-col footer-links-col--last\">\n        <n-text depth=\"1\" class=\"col-header\">\n          {{ t('contact') }}\n        </n-text>\n        <n-button text tag=\"a\" target=\"_blank\" href=\"https://www.tusimple.com/\">\n          {{ t('tusimple') }}\n        </n-button>\n      </div>\n    </div>\n    <n-divider class=\"footer-divider\" />\n    <div style=\"text-align: center; padding: 20px\">\n      <n-text depth=\"3\">\n        Naive UI {{ version }} · Made by TuSimple\n      </n-text>\n    </div>\n  </n-layout-footer>\n</template>\n\n<style scoped>\n.footer {\n  --x-padding: 56px;\n  margin-top: auto;\n}\n\n.footer.footer--centered .footer-links {\n  margin: auto;\n  max-width: 960px;\n  --x-padding: 36px;\n}\n\n.footer-links {\n  box-sizing: border-box;\n  display: flex;\n  flex-wrap: wrap;\n  justify-content: space-between;\n  padding: var(--x-padding);\n  padding-bottom: 0;\n  padding-top: 32px;\n}\n\n.footer-links-col {\n  flex: 1 0 0;\n  display: flex;\n  flex-direction: column;\n  align-items: flex-start;\n  padding-right: 24px;\n  padding-bottom: 24px;\n}\n\n.col-header {\n  white-space: nowrap;\n}\n\n@media only screen and (min-width: 1024px) {\n  .footer.footer--centered .footer-links-col.footer-links-col--last {\n    flex: 0 0 0;\n  }\n}\n\n.footer.footer--centered .footer-links-col {\n  width: initial;\n}\n\n.footer-divider {\n  margin: 0;\n  padding: 0 var(--x-padding);\n}\n\n.footer-links-col > * {\n  line-height: 2;\n}\n\n.col-header {\n  font-weight: 500;\n}\n\n.link {\n  text-decoration: none;\n}\n</style>\n"
  },
  {
    "path": "demo/pages/home/Left.vue",
    "content": "<template>\n  <n-el>\n    <svg\n      xmlns=\"http://www.w3.org/2000/svg\"\n      xmlns:xlink=\"http://www.w3.org/1999/xlink\"\n      viewBox=\"30 0 579.43 484.77\"\n    >\n      <defs>\n        <filter\n          id=\"filter-1\"\n          x=\"-80.0%\"\n          y=\"-80.0%\"\n          width=\"260.0%\"\n          height=\"260.0%\"\n          filterUnits=\"objectBoundingBox\"\n        >\n          <feGaussianBlur stdDeviation=\"12\" in=\"SourceGraphic\" />\n        </filter>\n      </defs>\n      <g style=\"opacity: 0.9\">\n        <g>\n          <image\n            width=\"609\"\n            height=\"226\"\n            transform=\"translate(0.43 148.18)\"\n            xlink:href=\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAmEAAADiCAYAAAAGThAUAAAACXBIWXMAAAsSAAALEgHS3X78AAAT2klEQVR4Xu3d7XKjOBqAUXlq7/+Sx/sjo25ZefUF2Nj4nCoKITDJpLfKTwkne7vf7wkAgNf6Z3QBAADHE2EAACcQYQAAJxBhAAAnEGEAACcQYQAAJxBhAAAnEGEAACcQYQAAJxBhAAAn+N/ogme43W630TUAwHPc/X8WvoXbK/4dRBcAvD9x9lpPjbDJ+Jq5BgDYb/lNX5g9z1MibBBfW88BAOtm3+iH1wmyYx0aYZ34qudnYmvmGgDg0eobe+/67r1E2T6HRVgjwMq50fnI6DwA8GP1DX01vgTZwQ6JsCDAevE1CrPePAAwbzW0WvOzc2Jswe4ImwywVnhteUwJAKyZDa6Z2Bod/z2xNzIubleEdQKsF2LRNdFxaw4AaFtd/RpFVXm8cu3fyT2xcWFHRtgotkb7THgBwLFW42t1PDr3M7knOi5oc4QtBNjMXG8MAGzzzPganW8di7H/PCPCeuNekJXzrWMAoK/3xr4aYHvmeuOfia0RchGbImxiFawVYKMoq8fRMQAQe0aAzZwTYxscFWGzAdY6n4p9PY6OAYBHKwFWz83EVLRfub43/pnYEiUfbG+EtWJqZavvU+4jggwA+tFVq68dhdHMfuaaaN8bf1WILUfY5CrYli0F+4gIA+Abrb1hPzoiwvbMRfvW3M/EaqB8oP+NLugYxVArtv6pjlMwLu8BAGx/T7ynx9dGx+V8b5+vK+fq8+W4p75/nksppXS73W5XD7E9EVaKYis6VwdYL8byMQCwTR1ceS46P1q56sVXbxxpfV8P30t++nbVGNsbYa1IaoXWzJaKfT0GAMbKVal6vpyrg6y1L8OqnBvFVyvGoteUAVZ+rcuuii1FWPB/UxSJAiqKrZXHkqWZ7wEArmYlQqL3yijAovAp51rxVUbUTHy1YqzW+j4uuSq2FGGFOrRGMTW71a/NxwDw7ba8H5bB8hA11XF9bhRf5Vx03Iuv8h6lVoA9XH+lVbGtEdYTxVdrvhdi5R4AWFe+j0bxlY/rcWufX1fOtY5bMdYKsjrOWl//MiH2jAiLjMJrNsJEGQDERlFSR04ZY/W4nsv7OraiuOrFWHQ+EgXYw/dzhceTeyIsCqIoonpxJcIA4Bh1ZLWuSSmOonLcirKZEGvN9cKr/t5b/y3lvX8u/OBVsT0RVhsFUy+86gBrRRgA0Lb1fTMKsdH5UYjVrx1tLeX9631K6XND7MgIy8r/AUQhFgVWFGj1OQBgnzKkZtRB1oqhOtBmAysSRWB2qRDbG2GtFas6olphVUdZK75m/8cCAMRyuKyey1oBVp4bxdjs1lN/D3nu40Jsb4Tt0frHrsMMANhvT4D17Imxf9Oc3vdYRtlHhdgzIyz6YdWrXeVcbyUsOgYA5rXCpH5/nYmy3mpYOR7F0D/Fda1Ai+5Vfu1f38unhNjRETb6R8t6K13iCwCO11tJKpXXlUHWGufXjGJstNWrYmWgRT4+xI6IsF4k1atbs7a8BgBYV0dX69yMVozl43+L+V50Red7PjLEjoiwI7T+kVf/8QGA7er33Tqi8lxrRay8NloNy6GVUvwosgyvfL4XY9H38jEh9qoI27oiFjnqPgDwTbaESBk40dwoxlrKMIvCq5yP5lo+KsReFWGR+h9r5h9v5hoA4LfoPXQ2TMrXlitc+Xg2xsr4ylqPIaOVsH/S7xCrv+bHhNiZEQYAnKv3+LGlXh3bEmM9dXyNjlP60BATYQBAFq14tczEWOlPDFXH9daLr95nxj4uxEQYABCpI6tlFGP1fqQXX6NHlL3v4Y93CTERBgD0zK6OtWIs8iuMAmVwjVbFWo9Vb43xW/hndAEAwH9uabyaVZ+/dfbl9k8wV8/PjMstBeOfwe02+u94OithAMCqHDCtlaX6/Gzw9H5TcjRufY16JSzvT38sKcIAgK3+BE3nfErtEBrF2Up8RX++ohR9Ru3UEBNhAMAeo1WxfM2zQqx1PhJ+UP8sIgwAOMIoxuoQy2aCbGUVrL5Hfd9fH9Q/azVMhAEAR+qtNI0+K7YaYlF81a+vv5/yezg1xPx2JABwtFvqP2Ysz5XxVI/rLfqNyNa+da+sFW0vYyUMAHiWehWqdS6PZ4Kot/rV2kd+fT7s1athVsIAgGfqhVBvZSpaCau30WrY6O+HZX/Gr/z7YVbCAIBne1hx6pzL43ouek09Hu1TCj6UX4x73+NTiDAA4BVyDEWh04qiVI3L67P6Q/qtCGs97jztsaTHkQDAK7Ue97VWt+rxLbUfM47O1Vsq9g/jVzyWFGEAwKttDbH62t7Wi7HyHtH4JTyOBADOcEvzjybzuKVe1YoCLu97jyXzdS/522EiDAA4y2yIpdT/ExZ5PvpcWCvQUpr4I67PJMIAgDMdEWL1Y8UyuFof2K/vFa2+PXU1zGfCAICzjVa4ouMovPK28uH8OtrKez6VCAMA3sEoxMp9Pe7NjbasGWDP+k1JjyMBgHdxS/3PYpXnozDKc/lRYyvc7tW+Fj6aPJqVMADg3dWrVK3jPF59HBl5+mqYlTAA4J20Vp/q+XLVqzzOc72VsHJc7ktPXw2zEgYAvJvR6lR5frTK1Vv96kXYr/mjV8OshAEA72i0ApWDqLVqVu/z/VZC7KmrYVbCAIBPUsfS7ErXzDWRp62GiTAA4F2Ngqc8X4ZVedwKr9F8KvZPIcIAgHcWhVA914qvVO1n46t8Xet4NxEGALy7XoiNAmw2vOr50sPxUY8kRRgAcAVROLUCa0uk5bnDiDAA4BNEAVRHVh7PhFYrvMp96dAAS0mEAQDXUYdSK7CiFa7edb8C7IhHkiIMAPgUvRWqVlSVx73AikIssju+MhEGAFzJTHzV53rnSw/He1fDRBgA8ElmV8Pq41Zc9UIsOn8YEQYAXE1vdaucax2X10YOCTIRBgB8mpXVsNb5Vnj1VsXy3CFEGABwVbMrXqO56JqfEzs+FybCAIBPNHpcGK1grcZYz+x1TSIMALiKmTCaCa8o2Orzu4kwAOBTjWLoVm31fO+66Jpy//fExkeSIgwAuJJmLKVxjLWuica7iTAA4Bu1VsKia1rxtSvKRBgA8MlmQih61FjOt66vr62v2UWEAQBXNrO6dau2+tr6eHeApSTCAIDrGcXSykpYPo7Gfyc3fDhfhAEAn242gHrXRStheb5ndL5JhAEAV9f7jNeW1bBDiDAA4IpGq17RNaPVsNVVsi4RBgBcQSuIZuZbq2H1ddHxZiIMAPhmMytm0Xh3jIkwAOCbjOKp9UhyaPU3JEUYAPAteo8WVx5JHkKEAQBX1Xuc2Lqu1nvdaL5LhAEAVxdF0q3aRzbF1SwRBgDwV+szYa1o2xxqIgwAuIrNQfSfva9fIsIAgG8183mv0bnNRBgA8O1WI2v1+pAIAwDYZleMiTAA4NusxNPKtUtEGADAnEODTIQBAPzW+wv6hxBhAAAnEGEAwDc5anVr931EGADACUQYAMAJRBgAwAlEGADwTe6jCybtvo8IAwA4gQgDAPjtng5Y7eoRYQAAcw6NMhEGAHyblZhauXaJCAMA2GZXoIkwAODbrcbU6vUhEQYAfKsypnphdUh01UQYAHAVe2Np7+uXiDAAgL/uxVbPl/t6fpkIAwCuLgqlVlRF1zyFCAMArqr1ma+V1ayZz41tijURBgB8i1589f5C/qbIGhFhAMA3GQVV6zNhQ/f7fek1IgwA+GZbHkVuirSaCAMArmA1imajauXzY0tEGABwRb3ffmydaz2K7F2/mQgDAK6uDKvZkKpjbFdwRUQYAPAtRp/x6q2atYzON4kwAODTrYZQuSo280hyuCK2+puRKYkwAOB6RpFV7svrRo8qW480NxFhAMDV1ZHVi6nZa3eHmAgDAD7Z3hi6p9/hVZ4r94cSYQDAlcyscpXjKLzKuV6A7YozEQYAfKpRBLVWuVrHq9f8nNjwofyURBgAcB0zMTQKq9FxnttNhAEAn2j0mDAKp3s17gXZKLRG54dEGABwVVFYjeIrz5X78roHWx9FpiTCAIBrGK1g1ed7QRZdV15zCBEGAHyaUQhtCavWdU8jwgCATxKF0czjwyjA7tVWz5WvPXw1TIQBAFdSB1IUWOV45nz2cO89nwdLSYQBAJ8jip57tc/jXlDNBFjLrvAqiTAA4CrqQIrCqrXC1bvusPAqiTAA4BMcsQrWO5eCfelhbu+jyJREGABwDXUUzaxu9YKsfF3reBcRBgC8u97KVB1NrbCaOde7xx9HrIKlJMIAgPfWC7DecR1po9Aq9y8hwgCAdzWKovL8zErXli0bfS/LRBgA8EnqGJpd4WoFVr2vPcwf9SgyJREGALynUez0VqpG0TW7lfc7nAgDAN7NaFVqJrhGW+t+pYf5I1fBUhJhAMB7mQqiFK9W1YG1Zyvv+xQiDAB4d1FsRcd5/G8xntkiD/NHr4KlJMIAgPcxCp0ovuqYqoNsy3XZ6PvZRYQBAO9gtCJVR1M53rNlzfh6xipYSiIMADjfKMCi43pcbquPI/O9miH2DCIMADjTTIDVobSytYKsvlf28P08axUsJREGAJzn6ABbXQEr1V/n6UQYAHCG2QArx0dsrXtlf8bPXAVLSYQBAK+3EmB1JJXne1tvVay8RzR+CREGALzS1gCbDayVR5Kp2D+Mn70KllJK/xtdAABwgF7UrARYK7pG8dW6Tyr2PwcvCLCUrIQBAM+3JcDKuaO28p71+CXhVRJhAMAzbQ2wUVDd0+9VsNY+irEwyl61CpaSx5EAwPNsCbBRhI0eO85uqdj/HLwwwFISYQDA8UYxc0SAzax+RffKwhB7JREGABypFzX1uWhVakuAjbZS9DVfvgqWkggDAI4xipjeKtSWAGudjwIsCrJTAywlEQYA7DMTMKMA60VYK8Ci1bDRylgq9qcTYQDAFjMxU1/TCrBWhI0CrHXtKMD+fF9nrYKlJMIAgHWjcJmJr7wvI6kVUisxFsVXKsZvEWApiTAAYM5ssGwJsN42E2Cjvwf2dgGWkggDAPpmY2U1vsrxSnz1oqu8d75/NH4LIgwAiMxGSyu+ynEUXfXxTHCNPguW1V/jwTusgqUkwgCAv1biZEt8lePRNlr9qo/re6dg/zYBlpIIA4BvtiVIZuIrj+s4KsdHxddHBlhK50bYPaV06xxHZq4BAH7bEyDRa8u5aNwKpHpu5jcie3P1/VOwf7sAS+l1EZZ/MEcE1Nv9EAHgoqL33HIuGrdiaGabDa9yS8G43L9lgKX0uggbuac40FrzAMDxWrFSz5fHUfzU4yiaRnE1Ot/6euX+bQMspWMi7J7aoZR/MKshteU1AMC6XqSU50bjXhjNbDPRVW+ps3/rAEvpmAgr3dNcPOXrouvrufwDnLkvABCbCZLomnKuHkcBVI+3bjnKWvdKnf3bB1hKx0dY6Z7iwKrn6x9SPje6DgDYJ3pvrefK4178RMFUH9fbyupXCsbR/iMCLKXnRtjIPbU/B5bS35WyPAYAtuuFSX2uPI7GrShqHe/dWvfP/ow/JcBS2h9h9xQ/ViyPyx9avcqVf1BRcEXnAIDtWu+n9XwUOL19K5a2bNE9UjAu9z8HHxRgKe2PsMg99R8p5rnouvqHJ8AA4HjRe2sUNvU4iqBWOM2cm31N6ux/Dj4swFI6NsLuqb0aVh5HP9BsFF0eSwJA22yI1NeVx/W4F0FRMI3mZ65NwTja/xx8YICltC/C7qn9m43l/t6YHwUXADBv5j01uqacG0VPK5B6QTV7vp5Pwb4ef2yApbQvwlaMfqCztrwGAPj9HtoKm9b7dR1K5Xg1sKL5aBztfw4+OL6yZ0TYPT2ucpXH9XwtX9M6BgDmtd5rW8e9AJodl1s0X89F98nCZrhCgKW0PcLKOKp/ENFvPfZ+sOVx9IH+6P4A8G32hkf0vluPZ/ajkFo9Tp19Pb5MgKW0GGH3+/1+u91GERTFVPRD/fe/c+UWvSb63BkA0NZ6r6zne9EziqWVwOrdo5yrz/+dvFB8ZUsRFsjBFM2PxrV8r2glDQBYF72Hjt6je/st49596vl67ufgggGW0v4Iy6IfTvQ48d+U0j/VdXV8lVE3WnUDAPrq9+jW8cp+dTyzr8eXja9sT4TVwRSdj8w8hmx9HiwlYQbAd9oTJL0Qm4miVlTNzkX71tzPxMUDLKUNERZ8LmwUTSPl6+t9RIQBwNp77kyElePefuaa3r43/or4ypYjrFIHWB1nPfn6cvUrv6YOrZX7AsA36r0/Rudm4iuPW9euXN8b/0x8UYCltD/CsjqiUnBcXxs9hoxe17oPAPBoJcRGcdQKrJn97Phn4sviK7tt/e+uHkmWjxF74+ixY3Sf1jEA0PfqEGvNta75O7E1Qi7iqJWw0j21V7byufr6+rpylQwA2CZ6H50NpVFkzYyj46+Pr2zzSlhK3dWwLfvM6hcAHGsUY3vCbObcz+Se6LigI1fCyhWwlc9x9Va/BBkArOm9/45irD4erWqNjn8mxVdo10pYSr9Ww1KKP+PV+tyXVTAAeL7Wm/1MRI2uaYaE+OrbHWEpTYfYzLnRPAAwb3VVrDUvvJ7gkAhLKQyxlMbBNYqt0XkA4MfqG/pqoAmvgx0WYSk1QyylbY8dZ64BAB6tvrGvrIg9XnBkRHyhQyMs68RYSv24El4AcKzZN/rhdaLrWE+JsGwQY9nMNQDAfstv+sLreZ4aYdlkjAEAJxJcr/WSCKuJMgA4j9h6D6dEGADAt/tndAEAAMcTYQAAJxBhAAAnEGEAACcQYQAAJxBhAAAnEGEAACcQYQAAJxBhAAAnEGEAACf4PzCIE6JAXnWaAAAAAElFTkSuQmCC\"\n          />\n          <path\n            d=\"M.24,161.44h471a88,88,0,0,1,0,176H.24Z\"\n            transform=\"translate(25.34 9.79)\"\n            :style=\"{\n              transition: `fill .3s var(--cubic-bezier-ease-in-out)`,\n              fill: 'var(--info-color)',\n              fillRule: 'evenodd',\n            }\"\n          />\n        </g>\n        <g>\n          <image\n            width=\"373\"\n            height=\"212\"\n            transform=\"translate(0.14 246.43)\"\n            xlink:href=\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAXUAAADUCAYAAABjyrM3AAAACXBIWXMAAAsSAAALEgHS3X78AAARaklEQVR4Xu3d4Y7buq5AYaY47//I9fmRrQ7DIUVKlhPbWR8QWJadTO8Us8rjFvs+tm0TAMA9/MluAABcB1EHgBsh6gBwI0QdAG6EqAPAjRB1ALgRog4AN0LUAeBGiDoA3AhRB4Ab+V92w2qPx+OR3QPgHjb+OyRv9zj6e07EAVjE/jiHRb0Y88o9AK5nOCyEfo3lUU9iPnsNwPlVY5LeR+DnLYt6J+Z2vxLvyj0APms0HtH93c8h8GOWRD0Iut7Lrnuy6wA+YzQavfu9a+H9BD63O+pO0Hsxz0Lf2wdwXqPhjvbtHoEftCvqxaBHIZ95LAPg3KoBnwm6+9nE/dV01DtB74Xdu8c7j/YAnMfodN6LdBbw7Jy4/2dV1LN4Z8eGkAPXlsW8GvbK2jv/+rhPRX0g6JW93hrANWQxt+fZOrveWz83ZuJ2A6uj3lv3Aq/3o3MA59KLx2jQezGfDf1zYyZyFzYc9cKUHgU9i7xde+cAzuHIoI8EPvvsn43R2F3UiqhXgx5dF3W0a+8cwGeNBN3uZVHO4p0de+vnxmj0LmbPf6UxC3HlJZ2jh8AD72cj2Ps5tPdu8nO/Xdvjw5zrPX2tJ/t68ng8HncO+9CkXpzSZ17iHD1EHThePQq/eVG365Fjtpd9RrT33BgJ4EXMTupZXKN4/zHn4qz1ZwB4v9mfPT0ZR+fVY3uvXUtn7dHvfag9EZFbTu2zUdeiydtes0Hvxb2dA7gGG/C2512fibldizq36x77B8S/JxB3ifueqEfRjcJdeYk62jWA89FRtft6T4f7Ia/XbdSjtQ17FvrGfk3va99mai9HPfnvpDdekL14jzyG0Sq/BgD7jITN+5n0gu4FXF/Tx7ZfCbn+tXpB77Ff8xZhL0ddseHO4lx92fe2cwDvNfNzZ+Oq9/R5L+7tWA253asEXn+WPrZrl38cMxP1Hi/m0X4v7PoI4Pz0z6sX83Zu19HRrkWtK3GvBF7TX09E5LJT++qoe7KQV6NO5IFzyEJnI6rjbtejYc8C3tj7PL2vLSLXDPts1L3AelHuxZqoA9dkox3dIxJPzFnQo7B759FrxG3CPht1KwtwL+Q26FHUAZzHyp/PmbDb946+PPZrt71LhX1V1Bv9G+2F3Qu2F3x7DcC1tAD2foZbQPXaHr1rlUBX6YBH1y4V9j1RjyZqG+Uo1DbyUcwJO3AtvVCO6kV+9vVXfU5bN94fLJcK+56o7xH9htvQA7ge72dXB1nvefeGUTVre38Ub+uPuqettUuH/aioR79Rdv9hXnrf3gfgGrzg2Z9hG/Qo8JoX9038ryfyGu8s9JHLhX1l1LPfkKY3iRNz4Pp6k7p3z2jg7bQeTepeyHXoe4HXv4ZLhX1v1LNv/EyUZ94D4Ny8Sd275sW0xwbeYyf2FvNq4EUuFPa9UV8h+k3LfjMBXJcNubevr0f/y34z6+q0biPu7dmve4mwvyPqsxO7Z9XnADjOaOCqga9M7hE7lXtT+h9zLnLBsL8j6h77G1P5jarcA+Dzomm7Qj96sXtNFndvaveeq+uY9yb59muxj4VOGfZPRR3Ad/HC3LMi7lo0mUdTevY45iXoZ0LUAXyCF21PFPeRoFvVmEdhF3kN+qmmdaIO4JOi5+mWjXv0KMTzEP8vRisx98Iu0pnaPx12og7gLCrTuxf3ytTe+2eN2Tr6bO/X8PGwE3UAZ1ON+8zU3ozEPJrWG/t1PxLzhqgDOKss7r2pfUXYK49hml9B/9S0TtQBnF02/XpTu0gt8NmUrt9nP1uzv4aPPYYh6gCuYGZq10bD7k3rUeBFTvR8nagDuJLRqV3HvBp2O6VnU7v28efqRB3A1VSm9ijsPdGUnk3t1kcfwxB1AFfVm4ijsGeBb9dsyHtTu/d8ve2/fWon6gCubDbsbc97j10/JI67XYs4k7rI+6Z1og7g6nqPY3qPYrypPYp6O9q49yb/jzyG+ZPdAAAXEcU1CrVdj7z+mGP2taPryxF1AHeSxVWvvRj3wv3HXK+8RB2fJ4/HoYHn8QuAu3lI/VFMW0dsmG2se38B6z3DP/TRiwiTOoB7ikKt922goym79/Km9yZaHzqtM6kDuKtoMrb7dprW+3bdQm7/JUxbR39x+rZpnUkdwJ1FE/HDOdp7sym99/K87B81rTOpA7i7bDrW17Mge38I2LU+am+Z1pnUAXwDL7J6z4t0by+azr3Qay97R0zrTOoAvpmdmr0p2sa/Hdu9UdijfxHT7jlkWmdSB/Atoqk4mrIrk3j0b9fFrLWXvdXTOpM6gG+STcj2ujd162M0qXvvaw6d1pnUAXybdHqW31O2N41XJnT7Oc3L3sppnagDwJOdxNvai7a+5t0Xhd5GflnMG6IO4BtVYhpN2NlLnPXbEHUA3yqKtr0WRVtfs/eNXHtuLHoEQ9QBwPcrvGY/e9l79fu1JTFviDqAbxZF29vzgq2veffa+6ylQRch6gDQ05vW7bE3oXv7vz53xSMYog7g21Un6Eq4bay9sHt2x7wh6gCQB9de92Ku19l1bVnQRYg6AER607q9ZyTs9p4Xex/BEHUAeMpi6kVZzNGbwr0/BDzZ1y8h6gAQs+HOrntTut63a319CaIOAD8qcbXR9sLfi7td//qaex7BEHUAqOlN2L0p3O5HkV+CqANAXxbemUk9+szsa6WIOgC8qoS1F+vqpB5N/bsQdQAY403k0X4Uf3u+JOgiRB0AKrL4jkzq7dxb/2xO/mUpUQeA36aCaniTetvvya53EXUAmGOjvWdaX4aoA0DNzLPxbFofneJTRB0AfFFgK/vRtG7v8853IeoAsFYv0tG03/tDYAhRB4B9shhHj2BSM/8ChqgDwLzeo5SRRzDLEHUAqOs9Ponus3rvy/ZTRB0AxnnRfZijZzrWVUQdAI4VPVOP/hDYFX6iDgCxXYGV/e8fRtQBYJ3K8/Ls2i5EHQDWG4326P0hog4A57E77kQdAN5rd7h7iDoA7Dcb6tn3hYg6ALzP8ohbRB0A3uPwoIsQdQC4FaIOADdC1AHgRog6ALzHlt2wAlEHgPc5POxEHQD2m4317PtCRB0A3mt5yDWiDgDnsTv4RB0A1huN8+j9IaIOAOvoOPdCvSziFlEHgNje+O59/zCiDgDH2tTL7uuj3Z9C1AFgnBfeKNLePYch6gBQFz0zH5m2K8/dp+NP1AFgXi/m3iMX776liDoA7JMFOnqmntq2bfg9RB0A1pp59DIVfQ9RBwDf6KOTaqRHnr8PI+oAUFP5i1Fv3wt87/5diDoAzLHB1kcvznZ/d8A9RB0AflsR3GxKj2TXu4g6AOSixyXe9dEp3f3MmX/5IkLUAWCUDbIX/M289L6W/WExjKgDwKtKYKNYVyb1KOSVr5si6gDQl8V2ZlKPPjP7WimiDgA13hTuTd/VSd2ulyDqAPCjElk7gc9M6nr962vO/iWpCFEHgJ7q4xI7qXsx703z0xG3iDoAPGVh7UXa7nn36Xs92dcvIeoA4PMiG0Xam8R707k3zT8v7Hj0IkLUAUAkn6B7E/hI0KPPWoaoA/h20UTu7UUB9871nsjrvrUs7EQdAGLeZN327TELvt3/9bl7H72IEHUA321mSo9C7d1r77N2R9wi6gDg603plZe9V79fWxp2og7gW/Um52jy9qbvKODVa8+NBY9eRIg6gO9UCWgU/ewlzvptiDoAPHkRjoKtr3n3RZHXe21/KaIO4Nt4IbV7XnwrL/te+znNy96qRy8iRB3Ad8ni2Yt7FvHq9Sb7tUwh6gC+RRTRzTn2Aq3v+Zvc633Nl72VU7oIUQfw3WxQowhnoa9ea5aGXCPqAL5BNjFnIe6F3d5nP0972Vs9pYsQdQD3l4XTi/sRL/01DkPUAdxZFNDNOdp7s0hXAq697B8xpYsQdQD3VYqrOc9ivUn8l6Ptc3qRPyTkGlEHcEeVoFdCPBP4Joz5UVO6CFEHcD/VoOv17EvMMbpm14ch6gDuZCToOr76Wnv9DY4jL1HH58mBU7oIUQdwH7NBz8LsvbzQe9ywH+l/2Q0AcHK9YK4Oup3We5/R/FsfPaWLMKkDuLaZoOu96mvk0Yv+/J+TNwRdhKgDuK7ZoGdR1hGvxNzS+28JucbjFwBXk4UyCnoW9egvRkcC733tt03pIkzqAK4li+PeoO99iTp+BJM6gCvIQhnF3B6zoK+azv/tvXNKF2FSB3B+WRRXB73ysrxfw9uDLsKkDuC8siDa61HI9boSdG9Kz4Iv6vg8+UDQRYg6gPOpxNCbjEeingU9ujcLeuXXfiiiDuAsKkG092RBz14jcfdiLmr9b+9TU7oIUQfwWdX4RTHX681ZV2I+E3dx1s/FB4MuQtQBfEY1fNWYt2Ml6r1oZ0Fv3PWngy5C1AG8x2jsvPu9iNujDXAU517Me0G369P5VNQ3EXl0zj2VewB83p7YVWJu96KoR69sGrd7jRf0f9fPMKWLvCfq7RuxIsin+KYBWCr6uf4VTrPXW/ciPbJnP1Oc42mCLvKeqGc28YMf7QO4viiCXsD1uhry6BX9xefoX4j++7WdKegi+6O+SRze9o0YDfPMewCcWy989po+j2Iahbca7Oo/WbRrfTxd0EX2R13bpBbjdp93v91r37DK5wI4h0ro7D3RuXe06+qrEnLv88U5njLoImujrm3iB9vu229Ku5bdB+BavJ9hu6fPvZjadW9vJODeSzrH0wZd5LioZzaJn6OL/EzybQ3gOnrBs9f0eRZTL7rVVy/y0Wd7x1MHXWRf1DfxH6Poc/2NslN4+8Z4AfeuAbiO6OfW7utzL6S99aqX9/ne8fRBF9kXdc8m/Ucobc+7z36zCDpwffZnWJ97a+9o1zbIf4Pr0b73GXbd/FtfIegi66K+STyt6/PoGyeSR5zHMMB5VANn7/OC2TvadW+v+rLvlc7xeXKRoIvMR32T+F+u6OMW7GcBB3BelZ9d7x69l8U0C3D15d0vzto7Pk8uFHSR+aiP6H3zRsy8B8D72Z9Vfe6tvaMXZHvei3Xvml23c318nlws6CLro77J6xSuz+2+1e6JzgGcV/QzHZ3bFvTCGwXb26u8X5zjy/qKMW9moq5ja/8P9/5VS/ebp869v2D1Ph/AsfYGzfv5tuvKsRLo6n1SOD5PLhx0kYGob9u2PR6PLKpenL1v3N//rumX9x7vuT2A84h+Ju1+L6RRgLNQZ/fofbvXvPw6rx50kYGoO1qAvf1sbbXP8iZ9AOfn/axmLcgC3FtX7xN11OvbxbzZE/XG+2Z4j0/+isgfc5+Nuf5DIvtfBQDOxbYgOq8c96x7R7u+VdBF5qNuA+xd91Qeu0TP00UIPfAOeyLXC3sW3Czu3l72GdHec+NmQRcZjLrzXD2LcEa/3x49RB14v5Gf7UrU9XpP0HvH3vqWMW+Gom7YoNvY97T79XTe3mPDPfK5AI7X+zn0rlVi3tZZrLNjb33rmDd7ot7YKItzbu/1Hrt474s+B8BnjYQ9C252HL3Hrp8bXxB0EZHHzP+d5hGMfmzSW3uPWbzPic4BnMuRYa9e662fGzORu7AVk7q2STx5t2v2fnufnuIBXIP38zoadr3OrvfWz40vi3kzNamLdKf1mWPDdA5cWxb3PaG3a+/8a2PerJrU9YQ+8hy8N50TeODcej/nWdzteRbr7PzrY95MT+oiv6Z1Ef8ZefTcnCkduJ8oKGmUC/e4n03MX+2Kukg57JVr2T6A8xqd2qP9UshFiHlkd9RF3LCL5AHP4p1dB/AZo9EYDT4h32FJ1EXCsIvMPWap3APgs0bjMTKx/1xcFakvsSzqTfKf5529BuD8qjFJ7yPk85ZHvSn8t9dFCDlwV8NhIeRrHBb1phh3AF+EgB/n8KhbRB74HsT7/d4edQDAcez/JyIAwIURdQC4EaIOADdC1AHgRog6ANwIUQeAGyHqAHAjRB0AboSoA8CNEHUAuJH/AwlpSZI6+jazAAAAAElFTkSuQmCC\"\n          />\n          <path\n            d=\"M-.34,259.64h242a81,81,0,1,1,0,162H-.34Z\"\n            transform=\"translate(25.34 9.79)\"\n            :style=\"{\n              transition: `fill .3s var(--cubic-bezier-ease-in-out)`,\n              fill: 'var(--error-color)',\n              fillRule: 'evenodd',\n            }\"\n          />\n        </g>\n        <g>\n          <image\n            width=\"510\"\n            height=\"162\"\n            transform=\"translate(0.06 78.37)\"\n            xlink:href=\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAf4AAACiCAYAAACgVK8dAAAACXBIWXMAAAsSAAALEgHS3X78AAAOGElEQVR4Xu3d2W7juBZAUTq4///J8X1Is4o5dThosJ1YawGGJEpWhgZ6k3LQfbvf7wUAuIaP2QUAwPsQfgC4EOEHgAsRfgC4EOEHgAsRfgC4EOEHgAsRfgC4EOEHgAv53+yCs91ut9vsGgA46u4/TZu6Pfr3IvQA/BQmAw8M/2LwV64BgC2Ww3bFicDp4Z8Ef+85AOhZDdnwuqtMAk4L/yD4cXwl8CvXAHBNW8PVu757n3eeBJwS/k7027HZ+czsPADXsyVaW4KfXvuOE4DD4U+iPwr+bDIwGgeAaBSx1cC3Y28/ATgU/sXo92K/5yMAAMisru5Hx7Nr32ICsDv8g+iP4p9dkx33xgCglPXQZ2P3sB1dk5371ROAs8I/C/xsW4k9AHvMgj/bn52P+18DeyP6QrvCvyH6K2OjfQAYmQU/HsfQbz0X939d/M8O/2h/NAlox3vHAFD14tWL/krgZ9vR/q+ZAGwO/8Jqvxf92UQg7mfHADAK1yzSo+3KNVU29ivif0b4V6PfO1+abdzPjgG4rq0r/XZ/a/RX3lf9mgnAkf873yzWK68y2GZMAgCuJQa014Gt4b+Xr3u123a/hP0qvi+Ofb3xdrv91PhvWvEvrvb3vEqyzQg/wHtbj9J3vdV33O9NAtr90XH2nnb7bf8nxn/vin8W4F7gP8JxSfbbewBwLXv+3d+uvutx3I+r8nsYq+Oz40z79b99nbpg/kkTgL3hb/VW8PFcjP5oAlCPAWAkRr+Oxf1e8NuxbDLQ3qt9T6Z977drf9Kj/yPh74W5F/eVV2m2cR8AWr3o3zr7veDH0Gexj+NRFv0fGf/l8A/+t7utLNpZ4Lc88m+tfA8A/F5bwjiKfj1ux0fBL+F4FvtvUQ9+dPyXw9+IcZ8FfPUV31uPAbiOrf/ej6vzdqyNbx3vTQKy49lr5MfGf0/4R7Lg98ZH8W+3ANDTtqINfj1uo5sF/9bsZzG+lVI+k/EtflT8zw5/Zhb71fCbCAAwiuW3uDbH2USgDX4Jx/H1MTj3mdyr6n3tUsrr4r83/FmEs3CPgi78AJytF//eNVsmADX0rTop6Plx8d8b/mgW6VHsY/R74QeAI20YTQriBKCO9ULfmwhkhvF/trPCX7X/QLL4Z1HPJgXxHACsaCO7qjcBuJf8MX8b+49yMP7PXvUfCX9vZR7D3Yt5nAj0gr/1HyAA17Ql+jW8WfTbaz6bbdVOBj6b49kEIH6dl8T/SPiP6P2DiZMBAFiVdWN1MtBb9X+EbVz1f4T91QnAy+L/qPBnv+S4qm/HRiv+7BgAoiyabT+yx+17tZGPj/tXHv/Hpw1Pc2b4V3+BoxW94AOwV2/FH8+PJgAxxu3qP672S/kb+Rj7lacP8ft4yqr/aPhHYc5W+Cv2vAcAMjG07Vg2AVh5EhAf6Wfxz1b9vUnFt/1Hx/9o+M/Q+wXPfvEAsMW31XU47j2FHgU4C3071lvdt2P1uqc9+n9G+Peu/DNn3QeA97MazdkEYOvqvxf/3iQg+if6j1z1PyP8mfgLmP1iS1m7BoDr6q2oe3oTgJlb6f8xXy/+sz/4e9oj/1eFHwAeLT5q78kmALNV/+gv+W+TbSn59/OUR/4fswsA4A2sfOzcns+ifQvHH2H8NhmP7++N/3G73Wbf82ZW/ABcSQ1pb0XdrrbjCryNcPbxQFz11+NsEhHFlX67fyrhB+CKRmFtJwcx9rMVeBb53gSglDz03763sz/rF34Armrr6r9eO4p/PZfFPoa/d6+HrvqFH4Crm63+t8S/HY+xz54GlDL+Q7+vgxNX/cIPAOvxb4+z+I/Cv/Uz/3rulOBX/qofAL6sPMLPYp3Fvr7av/AvyX4ca30bO+sv/K34AeCvlcfvccWfrf7jdbP49+5Rrzlt1W/FDwD/mq2uR6v8ra8S9lvfxs5Y9VvxA8C6dvXdrtZ753qr/HptO/6UVb8VPwDkeqvrOJ5FvRf+3mq/3T6U8ANA3yz+7fks6FnoR+d61/49OPi4X/gBYGwltPGa3op+a/C7E4C9hB8A5rLoxrDX/V7QZ7HP7ledEv1ShB8AzhBX53FsdWUfr2vH/r7hwON+4QeANasr8V7YV8babdzPjjcTfgBYNwvvKO4rE4DuKv8swg8Ax6zEemW1P4v/KZMB4QeAbWYBvoVXHM+ua8da2TVfJ3Z+zi/8AHDcaNUfV/N7JgCtXcGvhB8AttsT31ns43V7vsaU8APA+W6lH/de0OOTgezaw5MB4QeAc8we98dzvcnB6bFvCT8A7LM1yG38R6v+3v7Wr5cSfgB4rd5HAlN7/rJf+AHgcUaP8VdX/nvOdwk/ADzG3s/tR+87TPgB4DzZH/GtnIvXPIzwA8Br9T7j700UDk0OhB8A9tsa4VMjvofwA8BrbHnkf9oEQfgB4PlOC/lWwg8Av8fhCYPwA8CFCD8A/CyHV/Ujwg8AFyL8APCz3GcXHCH8AHAhwg8Av8fhpwHCDwDPdzjgewk/ALzGKP7x3GkTBeEHgP22BvlhQV8l/ADwWvfmFcfbbRzfRfgB4Dy9WM/OxWseRvgB4DHaiG9ZtY/ed5jwA8DjxEf4cb8X9lnwZ+e7hB8AXqv3Gf/U/X7f/B7hB4B9tka3/Yx/ZaW/+nRgE+EHgHNs/cO+e3jFa3vHhwg/AJyvF/V6LtNe25tEHJ4ECD8AbLcnwL3Vfu+6PV9jSvgB4LjZY/572J9NAkbRPzQhEH4A2GYW3t5j/j3B7z4Z2PMX/aUIPwActfJofiX48T7ZJOAw4QeAdbP4jgI/Cv4s+qcRfgBYk8W4N7a6wo9j7TbuZ8ebCT8AHBcjHsdWVv3Zde3Y3zfs/Hy/FOEHgBWj1f5oJX/vvHrXttvW7tBHwg8AYyvRjdeMVvErk4B4j3p8mPADQF8vttnqfBTzXtRXJwB/Dw485i9F+AGgZxb99rgX7tEkILvm4YQfANZlq/bRudErXpe9r73fKYQfAP41C+3WyK9OAKJvY0cf85dSyv9mFwDAhYzCek+2o5V679ws/nEScDj2LSt+APiyNfrxXN1vX5/Nfkn241jr29gZq/1ShB8ASlmLfjzurd57r8/J+fZVnRL7lvADcHWr0W+jPAv3llfm2/hZq/1SfMYPwHXNYnok+iur+969qtn3t4vwA3BFo6hm8d0S/S2TgKob/DNX+6UIPwDXMovoavTba3qBX1n1t/frxv9Mwg/AFayEdEv0R2GfBT/erxf/01f7pQg/AO9rNZrxulH069iR1X3v+0rjf7ZXhf9eSrkNjjMr1wBwXVuDuRL8uh29PpP93nY2Efiz/4jVfinPCX/9oc6I9kN+CQBcSi/47f6Z0Z+9SrP9OnhQ9Et5TvhnepOCsyYLAFDKvuC3+1ui34t7HKvj7fahjoZ/FOf6g22N9573AEAmi2kW3XZ/Fuze5/vZRKAX+3rff/Yfudov5Xj4W6vBrtdl18ex+sOv3BeAa5sFczX47f7sNVvpt6943xL2Hx79Us4Nf+te8qjH8fgD1nOz6wBgRexHe3xPtlmgs9dodb9lEvB0jwr/TAx7O17K3ycCdR8AZnohzWLf7veCX8pXxOt26wRgJfp/vp9nrPZLORb+Gu8Y8fa4/UHjar7+gFnks3MAMJM1ox3rhTdGefTas8IffQ9Pi34px8KfuZfx4/o6ll0Xf2jRB2CP2I5RdO/Jfjs2i/rsfHb/0myfGv1Szgv/vfRX/e1x+kP/ZxZ6j/wBWIlkvCbrThbk7Di+VkPfu2dpti+xN/z30v+L/HZ774zPIg8AmVk74vn2OIa3F+ctr/o3AL3zJdn/49mr/VL2h3+L7Afe84PueQ8A1xE7kTWnF+NRuFdX+fFeJdn/4xXRL+X88N/L99V8exzHo3pN7xgAol5PevuxQ6Nwb3317tduvw5eFP1S9oW/DXL8xrO/1s9+6Pi+eM/R/QF4X0eCmLWltx2FeuWVXVuS/Xb7dfDC6JeyIfz3+/1+u91m4c0Cnv3gn/+da1/Ze7K/IwCAUvImtGNxPwtyL+J7zpXB9uvgxdEvZUP4EzXS2fhsP6r3yp4YAEBP1omsPb3Yt2Oz2Mfxkuxn26+DHxD9Uo6Fv8p+kOxR/Wcp5SNcF4PfTiRmTxcAoJR/OzQLf93OYj47jvv1uN1+HfyQ6JeyP/wx0tn5zMoj/t7n+6WYDAC8u72BzOKb7R+dAGTvabff9n9S8KtN4U8+55+FeqZ9f9xmhB/gWlbbEq/LQjwL99b9Khv7kdEvZWP4gxj9OCEYqde3q/z6nhj3LfcF4L31OrA1/HG7OpZt4/6PjX4px8JfxXCX5Dhemz3iz97Xuw8A1zXqQi/Gs3jvDf2vCX512/M9hsf97SP60X72SD+7T+8YAKpevOL4SrRXt6P9XxH9Us5Z8bfupb+Cr+fi9fG69mkAAIxkrejFv93fMiEY7f+a4Fe7VvylDFf9e7aVVT4Ae8wmALP92fm4/zWwN6IvdNaKv13pb/lcfrTKNwkAoKfXmdkEoD0eRf3tgl/tXvGX8s+qv5T8M/ve5/hW+wCcZXUisCXwbxX86lD4S1mO/8q52TgARKOIraz+41h6v3cIfnU4/KWk8S9lHvlZ4GfnAbieLdFafQrQG3ur4FenhL+UbvxL2fdIf+UaAK5pa7i2TAC+TpwVxx/otPBXk/91795zANCzGrLhde8c+9bp4a8mE4Bq5RoA2GI5bFeJfeth4a8WJwAA8HBXDH308PBHJgIAPIPI554efgDgdT5mFwAA70P4AeBChB8ALkT4AeBChB8ALkT4AeBChB8ALkT4AeBChB8ALkT4AeBChB8ALuT/3MQqo/aC3uoAAAAASUVORK5CYII=\"\n          />\n          <path\n            d=\"M-.44,91.54h404a56,56,0,1,1,0,112H-.44Z\"\n            transform=\"translate(25.34 9.79)\"\n            :style=\"{\n              transition: `fill .3s var(--cubic-bezier-ease-in-out)`,\n              fill: 'var(--warning-color)',\n              fillRule: 'evenodd',\n            }\"\n          />\n        </g>\n        <g>\n          <image\n            width=\"206\"\n            height=\"127\"\n            transform=\"translate(0.38 357.77)\"\n            xlink:href=\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAM4AAAB/CAYAAACnif0UAAAACXBIWXMAAAsSAAALEgHS3X78AAAJ2UlEQVR4Xu2d25KjOgxFxdT5/08ezkPK3cqOZMk3MJm9qijbsiEhaEWkpzN9nOcphJA2/kQLCCGfUBxCOqA4hHRAcQjpgOIQ0gHFIaQDikNIBxSHkA4oDiEdUBxCOvgvWjCb4ziOaA35Ds4v/n2uY/W5URSi+RaZlomTFCazhjyPVFI9WaLp4gTC9M6RvckkUXXN0ySaJk5FGIxnBMmsIfeSTRxvnRl/ikBTxHGk0bFo3iKaJ/eRTRprXSq2u0DD4hjS1ISJZKrFyb5kq0rreFuBhsRJSuPJ0nMLR/YlI4/Xj+a2E6hbnIo0NXmsNdbYi5F9yIhSG2eE2lagWeJEgkRtgbI8l9pnl0iM7LrXoDdpJ9IlToM0mVitT55B9rbLEyUj0FbyzP6VG0+QSCId98ZkL3Ti6mt1qnHpl7WHEauh1+pj/rx53yVQc8VJVBtPmkgk7Ftjsgde0rRUmii2dfWZIU5WGm9eVIt9a0zuJSONHtda7EdrrPY1aE3kQUZu1aJkz2xSaS0o0fVgQnrXoEWcU17H0WLgWKPXY/va+TiOK+VpEifx7za9mxitBcW5Bp2A2ddc71MSW8dbhHmTAkB5SuxSeZrEUUQvpifIHxiL0dfHIPfQ+trrJC5jHUdhdN8SqCX536rPVfL0iqOxBLHmUJqaQGVM9gelKTGv9eRpSXZLyB+ukGdEHC+xPTkym6gW+2Q/vEqjk7rELVkseWqbBuUpMRFZL09anMrXBjRW0luCtNyyaTLPgYyTTTiUxpIIq0JNhlbw2Lq/lLQ4CpQjEiC74b5lTK6n5XXXSYtjrAo4F21/JQYrzs/jrKw6PeLUsITx4jV5dEv2xhKmjD15PIFQlD9OHPFkXSbPbHEsIlmy4lCkPfCS0BIokgePVURBkf5ILI+I/ThL5OkVx0piK/FrQlCc7+QnYVX/I5lV39osYXrkWUavOEiU5DVZUBpPHLIHM65LlNj6Fi2SB49jyTm96swSp6BfVEseSwpLKpwjz6G84yOeLFh5tBhFlJo8+FhetZvKiDheZcDE92TwKo1eg32yLzphdczKj4+KoMAfCFjyZPLjQ5qZVWdEnBG8k0WZyHOw3vktibyKhFhVJpKogNJMrzqrxLFOBquKjtUqjjUm+2F91tBzPdfQEsRrRWxRllSdmeJkX5haRaEwz8WqODjnVaEaZb5I5InjHWtJ1RkVp3bSVoXJ0LMP2Q+vEpRx9jpj1YkqjyXH9KozKs4MvBcw+8KS/cGkLoms2xpajqjyXFJ1rhCnt/JYzDoOmU8mIXXitshjyaH7eJzlVecKcSzwRcoIkVlD7gOvj5eUuvrofWryROJcXnX4pwzJKqI7De/N84DNilkbHmMpFIesJiNPLeEzskRxfazfQe47ZiYUh1wBJjDOYVuTAdeI00dhXIF6oDjkSqKExXkr+bPy6HY6FIdcjZXMljCRILhZ+2FMx4egOOQOavJYVSazJrvujd7PORSH7IonR62SmHI4ZNeZUBxyF9mqY4Hy4HoUDImOH0JxyJ1kEtiqNLr11uHazGOloThkN6zEx3FUcfQajE0RiOKQu/ESOYrXxKjJ90HPDwgoDnkKUSXKVp2WeReKQ55AVGUsmqpOKxSH7Eg26TPSLIHikJ2pVRjvdi0r05BcFId8O0OCeFAcsgOtyT21evRAccg3s0woikOezjI5alAc8nSG//+AHigO+WaWSUVxyA60Jjiub91/GIpDvp0lUlEcsjNW0p/Q6njZLKZWKYpDdkQndS3Bs5JMh+KQJ+BVGS+G8ekiURzyFGoieLdokTDRvAvFIXeTqRhW3BMFJQrl6PnP1ykO2Y2osmDbUm28tc1QHHInmSRGObyKU6s204QpUBxyF7UqESV5VHEs0XB+CIpDdgUrh1V5vDUZsutMKA65g2y1qd164Zrsujd6fjAgQnHI9WRunazKYo29ORE7puNDUBxyJVHSWgLpfkYoMdrp3PU3QMm/RS2BvQrhVRRcI07fkk6Ph2DFIatplcZaE8kUxfWxfgedn29EWHHIOqKkxHlPBCtWk0W3y7hLnFPevyuOY4vMGnIf2WS1KkCLIL1bIfs8q1whTnniM5J+ykmT21gljXU85C0+cpsmssdnnNSJkkfjvev3SPM3sQa3wrScGq04p/iVpDzp1krTsw/ZDytJMYkz4rSKYvEWH602IuPiaLIJX9ZZ6zFWTjBzXHIvtWREYbDNbJFA3rEKw7JoZoqj8aTwxCiUuWgd2R+8ZpYwpe2VJSPJ2/OYUW1E1okTYYlV4iK/Fan0yf5YCVmTJxLnr9HHtiaQK88MRsQpyY8S6LE+GawmWgzdL2twjjwDvF6YwGelb0mRlQU3Ue1rMKnaiIyJY2EJoudKzFqHJ0Vpnou+bpjElizeZkkTCVTAx5vKLHEsSayxPrlWUXjLtgeZRKwlMOZATZiMNIj12FOrjUi/OCiGjqEkVjyShOxLdN0iaUqb2SJprE0/zjJ6xWnBOqGeE+vZh1wHXp+MNDj25OiR5uf5zK42IvPFOeW9mugxxpGyxhuTPcFrqcdWMmO/trUIU46p2yXSiPSJoxMan5T107KPk5HP/fCYteOT9fQkm3VNvXbmJkb/1VkkjUiDOOd5nsdxRIlrCfBxQvJ6Jzlgs/axPkeRfcDrocfYxyS3xq2bqBb7S0mLY6AlwXjUR8qxrIpF9sa6RpjUM6Tx9tfxH1ZWG5ExcQrWE7Rutf7K529jozBaxKi6kX3AHIjE0f2sSNb+uv1htTQi/eJgklvzFplbNO/zjQhluoqexNP7WH1PEBxnYqLat/4V0og0imN8zokSPULvj60Fxbme7HXFdZjgrQJ5Y6t9DS6SRqRRHAClQaFqlPW6ypR9UI6W45L1eNegRZzSZgSJjvMaXCiNyJg4BUx8Mca41rpFs/bzjkPuJSOP1Y+EqM3j2t/gxdKIiBw9jwm3a/oWq9a3bsms43hjshct8ngxS55ai/1bpBGZU3E0p/gVpMzhelynqxF5BnitvESPxIhE+w3eJEyhq+KIVKtOT1tglXkuViJFFSMjDPZvl0ZkXsXRlablc0mtylCivfGuca366HFGko/H2EEakYGKI/JRdUTszyze5xhWm+8iI1JNikcIUxgSRyQtT2YuipN9yUjTM95OmMKwOCKmPCKxJJEg0Ty5j2zSWOtSsV2FKUwRR8SVR6TvliyzhtxLNnGy1egVnJWQi5kmTiH46kHvHNmbTBJV1zxFmMJ0cQqJ7+6IUJZvJZVUT5NFs0ycQlIg8o/wZFk0y8VBKNK/w7dIYnG5OIR8Azv8fRxCHgfFIaQDikNIBxSHkA4oDiEdUBxCOqA4hHRAcQjpgOIQ0gHFIaSD/wHNyPt3U4v5hgAAAABJRU5ErkJggg==\"\n          />\n          <path\n            d=\"M0,371H117.5a38.5,38.5,0,0,1,0,77H0Z\"\n            transform=\"translate(25.34 9.79)\"\n            :style=\"{\n              transition: `fill .3s var(--cubic-bezier-ease-in-out)`,\n              fill: 'var(--warning-color)',\n              fillRule: 'evenodd',\n            }\"\n          />\n        </g>\n        <g>\n          <image\n            width=\"142\"\n            height=\"77\"\n            transform=\"translate(308.86 25.74)\"\n            xlink:href=\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAI4AAABNCAYAAABwgVwSAAAACXBIWXMAAAsSAAALEgHS3X78AAAFzUlEQVR4Xu2c65KbMAxGxU7f/5GX/thqq3z5ZMkXSCA6M4xl2dCATkVme9n2fZei6OUr2lAUjBKnGKLEKYYocYohSpxiiBKnGKLEKYYocYohSpxiiBKnGOJPtOFMtm3boj2fzP5Gfz60veqzlCRreJVMp4rTIUt236eQKtKZEp0iTiBMJEm0fleiwrjrZwh0qDgNYVg+I0hmz5XJFIPtoecdKdBh4jjS2Fy07pHZc0UyhYikeVo/Sp5DxCHStISJ5l7uzkSCRPOHtSPkWSpOhzCZmM0/jawcmXipQMvESUqDo5djcy93J3o6DROktfYzWVTwo34AGAkSrVvuLovF3qsWWHNY8E2eBdnMiLmlLOk40G287tISpyUSxp9A9OphY2vNjku6zrQ4HdJgHMnDZLm7QK1XVSRNj0TT8kyJ0ylNNPfORe4qT680kTiHynPGdxw8WF5IrHyCPLs835PNoRSbiRXNWezepQyLE3QbjVsH2yMQ67xFtP6uYNFb6xlhPDk0r/t+Rdq2bRvtOsPiEDwZsoeQ2I4Zeva+gkgWi+0yVg4bt4RBlnafIXGcboOxzfUcArHO70D2PvA15XWbFrjPSvMbj3adIXEIWGRPBHt8BXvFjBjfGZTGCmNjPb6Da9icyKNAw8yKwwrLJMlIwwSyI8Z3xJPGCoN8ybM87Dnhq2pKoFlxEPzAKAJKk+k6Os+Q3fcqokKhNBpH3cbKg+cqU6Ig3eIEfyZlcygBHq2uI2TE+IpEn9/rBl7RrTD4vDyBdM9vbuR7Trc4BlZQW3iW7znw/E8Ai46vFwZ7Vuy1JE6+SxhlRhwEhWEysXFWnKtKNVQwgAm2Qaz7xOSnWSkOA2XSMXPgOXdjxT3Z57Osm2SYFYfdPCu6F9sck8Zef8WDvgK2U7A55lmXQZGYRFNizYqD4A16hUd5ECYY23MHWEE1b2OESeHFbD7FanEiWiJhh2FE61cEu4sH29cS5VCO+rfjPQXOdqlPo/Ucep5Lz940R4nTYz7utfOe69yN1nPoeS49e9Oc/arC9zZ7h7d+h2T3XYlsYXdz2ByLD2e1OFYGnLMY99vzxOzRmO25GyiDd587jK2YzaeYFYcVHqXYG7H3hQ7zp37xewNQip0cbJ3FdrRMPc9ZcSKsWCiPyOSH/8dVX1mte8+I0xIJ4+WsFAclEWl3mVVdZMU13o2sOK29GNs908yIg6Kw7yM2790owxPsqt0lCytyJE8klD2X5YfoFmff9x3+aoUVyOZEHouO47fwHwfg9ew8utF3Fyv6/Eqr6Pb4Jjm2H3nI9f6VCpEBcQJY0UUeBbLCfP9bw8Nep6fjdD+ANwOFwdE7rEACsbL02cyKYwuscWi4xN3Ge00tvfk3xZPHE6jVdexhr4dxN7PiKCiQxSt41G0+URoFC+xJE0mCOc1PMyQOfM9BafB1kv2gKAx7VUVEr7JXk70PkUcBdOwRCKHyjHy/ERkUx0GLnf0gVpSo27Sw69lf+x2IPisW2pOG5TyRol8zzbA4TtfRUXMMKwfL2WsIxCy37GG8EHYPKI6OvQKxa/wEg91GZEKcACsSy+OcvZ50xGv0dLUr0ZKHjUwWb76cqf/mRESi/3zAjhi39trRwnJ3olceHZk4rXOmuo3IAnFEuuTRMdrTij8BWxQWRx2oNU5LI7JIHJFQHsxF65ZPk0bBwrBXT0scXP8JFhX8rO84G8nZfRZ7jp3b3F1hRe0VyFtbyrKOI/LUdURyr57WK+nuokR40ozEy7qNyGJxlA6BMnMvd2d6Og+bHyaMcog4IlQekbZAXg7J7LkimUJEQj2tHyGNyIHiiLjyiJQ0HpliRPL8Tx5Y3EPFURoCicQyROt3JSqMu36kMMop4iiBQJbsvk8hVaQzhFFOFcfSIVHR4ExZLC8Th1EytXmVJIy3Eqe4Dkf92/Hi5pQ4xRAlTjFEiVMMUeIUQ5Q4xRAlTjFEiVMMUeIUQ5Q4xRB/AelwFo4tukdPAAAAAElFTkSuQmCC\"\n          />\n          <path\n            d=\"M322.05,39h65a13.51,13.51,0,0,1,13.5,13.5h0A13.5,13.5,0,0,1,387.05,66h-65a13.49,13.49,0,0,1-13.5-13.5h0A13.5,13.5,0,0,1,322.05,39Z\"\n            transform=\"translate(25.34 9.79)\"\n            :style=\"{\n              transition: `fill .3s var(--cubic-bezier-ease-in-out)`,\n              fill: 'var(--error-color)',\n              fillRule: 'evenodd',\n            }\"\n          />\n        </g>\n        <g>\n          <image\n            width=\"175\"\n            height=\"77\"\n            transform=\"translate(236.67 341.14)\"\n            xlink:href=\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAK8AAABNCAYAAADQHjT8AAAACXBIWXMAAAsSAAALEgHS3X78AAAF20lEQVR4Xu2c7W7bMAxF6WLv/8j1frTqmBtSpD4TrfcAhiiK9hL7lNW2INd930LIiXxEBYS8K5SXHAvlJcdCecmxUF5yLJSXHAvlJcdCecmxUF5yLJSXHMufqGAn13VdUQ15LfcbfZ7getVroaj/D68Sequ8DcJm68g+UqLsFHmLvIG0kajROllHJIe7vkPipfJWpLXyGUkzNWSMjBBWjXneSomXyeuIq3PRukemhvSRkSES92l9lcBL5DXErUkbzb0cWUskaTR/WFsh8FR5G6TNxNac7CcraCaeKvE0eZPi4ujlrLmXI3Np6biWpLW1r8kk6Vb9J0UkabSuobB70fe7SFZyKN0lz5JeasTcVKZ0Xui6XpetyVuTGWOyh2gbYI21NT1O6b7D8jaIi3EksCUsJV5PbdsQidsi8rDAQ/I2ihvNvXMRCryOVnEjeZcKvGPPi4eVFyMuUOA93PJ8X3UOxbxUXCg5ja6dSre8Qdctce2wagTiMq8RrRMfFK+2npHWE7TkS92PzNd1Xb3dt1teA0/I7CFGrMcMLbW/lUhYje62WlAd16RFpnbhLnmdrouxzrUcAnGZkzlk7yVuGbyuWwPrtLg/cW/37ZLXAEXzZNTHR1ArasSYrAXF1dLquByfwTV0TuRR4m5G5bXkskTNiGtJrEeMyRo8cbW0yIc8C2w9K9w2DEk8Ki+CLxhlRHEz3bfMM2TrfjORLChuiaOuqwXGcwtDsiLN8gafYdA5FBGPWvcVY8SY9BHdQ68reuJpafGZeRKXmp9cz763WV6FJZWWz8q3HHg+2QOKh7/qLaznZW0RxMk3SVsYkRdBaS2hrXFUXordT5c0gCX5BXGpE5UfZqa8Fih0GTMHnkPmM+O+6mc0ratmGJXXevOWeF6sc5a4+vozbjTJoTumNce81W1RZkvkIblH5UXwDXryocCIJblVQ+ZgSVXyOkYsMb3Ymg8xW96ImszYaS2iddIHdlkPq64m61JWfVdZi2TZbk32U3sWLc+mpTbNKnlbfvqwVs9brkPmU3sWLc+mpTbN7m0D7qGs/VTtpzRbR9rIynWrQ+eseDmz5dVC4tyKsV6fJ6qmxFYNmQ8K6d3rG8ZabM2HGJXXkg/FvCuxt8HH/Na/CBAReRbzNg5r3Yr1qBl6pqPyRmi5UWCRwRf/DbcP/dTuf0bemswYT2emvCiqSL3bzuqmM65BnsnKW6vFWNcMMyIvymrtT3Xee6MWnuTssuuxRIsEjqTW51r5Lprlve/7ho9Faol1TuRRPBw/xf6nOryenkdvlHLHRPewUBNPH59GzqpHHnKtH4cU6ZA3wBJP5FFiLe3n9xoe+jotnbf5BpAnUFocvUNLLBAXpj6fUXm1ZCUOf8ok7rrelmHqmycunsCexLXuqw99PYybGZW3gBJrPOmirktxXwtK5okbiYq5kh+mS17Y96K4+Ks9+0JRWmvbEBFtK0j+Xoo8SljGFokRU+Ce/a5Ip7wORbjsC9GyRl23hl7P/tnki+h+oWyeuFbOkzn6M9N0y+t03zKWnIUW1MrpawjEVm7azfjlWPcR5S1jq8TWNb6Czq4rMiBvgJbZyuPc2iqUEa/R0t1JGzWBrdES1ptPZ+grTkUk+sI9PWJcq9WjxsqRubQKXEZL3to5Q11XZIK8Ik0ClzGqqcVkD1oMK446cW0cFldkkrwiocCYi9Y1FPd1oBzWNqAmL65/BZOk27XnvYycrtPoc/Rc58g6LLFaJfbWpjKt84o8dV+R3Dagtj2grK/HE7cnntZ1RSbLW2iQODP3cmQtLR3Ymi+TtrBEXhFTYJG6xF4OydSQPjIyRFI/ra8QV2ShvCKuwCIU953JCBEJ/C+5ULCl8hYqEovEQkbrZB2RHO76SmkLW+QtBBJrsnVkHylRdkhb2CqvpkFk8ubsFFbzMnktKPT78ypRLd5KXkJaWPVdZYQsh/KSY6G85FgoLzkWykuOhfKSY6G85FgoLzkWykuOhfKSY/kL3icWjo4FIT4AAAAASUVORK5CYII=\"\n          />\n          <path\n            d=\"M249.83,354.35h98a13.49,13.49,0,0,1,13.5,13.5h0a13.49,13.49,0,0,1-13.5,13.5h-98a13.49,13.49,0,0,1-13.5-13.5h0A13.49,13.49,0,0,1,249.83,354.35Z\"\n            transform=\"translate(25.34 9.79)\"\n            :style=\"{\n              transition: `fill .3s var(--cubic-bezier-ease-in-out)`,\n              fill: 'var(--success-color)',\n              fillRule: 'evenodd',\n            }\"\n          />\n        </g>\n        <g>\n          <image\n            width=\"323\"\n            height=\"162\"\n            xlink:href=\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAUMAAACiCAYAAADbXK+UAAAACXBIWXMAAAsSAAALEgHS3X78AAANT0lEQVR4Xu3d227jyA5AUTqY///kaB7cldAMWWRdJDvxXoAhqSS7kx5og0pw+tyO4xAAeHcf2QUA8A6IIQAIMQQAESGGACAixBAARIQYAoCIEEMAEBFiCAAiQgwBQERE/ssuOMPtdrtl1wA4z8H/9OyH2xV/J8QPeH3vHshTY1iMYOUaAHuUb/h3i+MpMUwiOHsOwLjqDd697h3CuDWGnQja9Ur0KtcAeDR6Q0fXh5/zV8O4LYZBCPVadt6TnQfwbeRmHomge+1fi+KWGDoh7EUwC2RvHUBd7+auRk+v/ekoLsewGMIogDOPzwDGVKfA3nF27a+P4lIMOyHsBdG7xjuO1gD0VePnrR1m27vGO/dro7gzhln0sm1DAIG9sghm+9l5u39fWInLE0zHcCCElbXePoA5WQTtsY3f6Dm7/6uCeEYMe/u9MOr16BhALrqpoxBWopdte/u/IopTMSxMhVEIszjafe8YQKx3Q2fh6m0r1zTe2ssHcVcMqyGMzova2n3vGMBPoxOh3h8NYeV9za+I4uq/WpMFrPKSztZDGIE7G5Xo3hiN4SH3z9JbvS9mv7Hvs2v3N95ut1cM4vBkWJwKZ17ibD3EEO9q7Gb9Fk1pdj8Ko97vHXvv0duH/VcL4spkmEUpit6HORZnX38GgLuZ+0FPae3Y7tvp7TBrbT079ug//+HPaYPVq0RxJYZaNOnZczaEvSi2YwBzbAjbmt2PIqjXvEDqz9Lv8ej3Plz7Ko/NqzGMYhUFr/IStbX7AGqiEN6C/SiCNn5eAO265YXw5YI4FMPk3ylsvJB50Rt5XNYqXwPwF43EohfCdqzXexEUc5wF8CF0xssGcSiGig1eFrXqy763HQMYvxfsFKfXdJDaehRG7zh79bxkEGdj2ONFMFrvBVFvAYzT94+OYDvWIfIieFP7XqBuIvLprI94mSCeEUNPFsBqDIkjEOsF5CE46tiLo46gmGP7+uic+3Q+q4n+bBF5ThBXYuiFyYtZL3LEELhOFMTompEotvhpLZSRlwriSgytLFy9ANoQRjEEEFu5X3qhtFFsa1H8ojh6ukG80s4YNvo/iBdEL3ReKO05AGt0eKqiKB7iPyLrAH7IYhCvnA5XYxhNcDZmUeBsHKMIjv4HBPBoJIQtRl4I9TWfatvoQH6q4yyK9s+5PIirMVwR/YexgQSwzruXqoGMpsMPs7XT4YfZr0bxKUE8M4beX7Kd/vRabzL0jgHUeSHR95T3qDpLh88+Klcene1UeondMaz+BfYmPyII7BdNhvZ8L4o2UHpKtFOhyHf4bAArU6r9Ok6fDnfEsBcrbxKsmHkPgDE2PnrNi2JlYrSPw14QvekwCu3D/plB3BHDHaK/4OwvHsAeD1OYOY6e4HpR8uKn16IpUK+16y55bL4qhrMTomfX5wDvpBqSLIqjU2IUxCiM1o8QnjUdXhVDj/0LyP5iRWrXAPgpmrwiURQzN4l/YRIFMfulyiWPy8+MIYDnsY+pES+K2XTY+w3yLdmK+F/P6Y/LH9kFAP68yo+x9HkvZDdz/GHWb8m6fX+0/qX476uWMRkCaFpcoslLT2V2UtNh8h6t7XTYjr2wWnYi1PvbEEMAVi82Opg2gNmk5oUviqKIH7+Hr23nzw6JIQDP6JTYru0FsZ3zAmhjGH3WadMhMQTQk02JI0HU6zaA3tQo0v9lyv1g03RIDAFkqkHUx14QezEc/RliO7ccwYbfJgOoqDz+egHzAthe+jfL4uzbNe1hbcdvlpkMAVRVHl3tZOhNifa6LIjRZ7RrtkyHTIYARmVTWG8aHH2J2dce1lanQyZDALvoKU1PddG5aBps1+r106dDJkMAM6IpzK57oYtiGE2FensaYghgVhZEfd6LnBe/3rno2u+DhUdlYghgRSU+9ppo8huNYBjFGcQQwCovRDZ2bT+KXBZA7/Oa5RCKEEMA57NTnF2rToD2Or32/YbJR2ViCGCH6sQWxa6yprd23zseQgwB7JLFqBe8ShTDaXAHYgjgTJWAVabCLIjLgSSGAHbKonQzL7vuXafXNO+a+4mJnxsSQwBn602HduqbiaI2HMGGGALYbSZIWQDtdTN/RhcxBHC1m8TBiyJnJ0jv2qVAEkMAV8gele25KJhbA6gRQwBnGI2UDmJvOoz2R/+8H4ghgFcWPU6nRn+jTAwBPEvvEbg6Ic6cdxFDAM8w+3PA3vuWEEMAV/F+UVI5Z685BTEE8MqinxlG8ZwOJjEEcJbRMG0L2wxiCOAVjTwub4kmMQTwarbEbRQxBPBXLEWUGAKAEEMAv8vS9NdDDAFAiCGA3+XILphFDAFAiCGAv2NpaiSGAF7NUtRmEUMAr6gXRHtuSzyJIYCzjEbqlMhVEUMAr+xQL7uut3Z9GDEEcJUoYNk5e80piCGAZ9BhG5nueu9bQgwBPIt9/LX7UeyyCGbnXcQQwCuLfmaYOo5j6D3EEMAZhkIkjz8zrEyE1SmyjBgCuMLoL08O87LXRsfTiCGAq0Wha+c8+toorEthJIYAdpuJUjQVRtfN/BldxBDA2bJH5MPsZ2HshXA6ksQQwE5ZjKJH5JkIhhPk6G+SRYghgHNVHmsrEbSf44VxCTEEsEsWpF70ehHMQrgFMQSwgxeoaK06Cdo1vbX73vEQYgjgbDZsdq0yHXrX6bXvN0z8vFCEGAJY15sKexPfEbyia/VWm4qfRQwBrKiEyF7Tm/YqYbSf0Y6XEEMAs6IAeVNcL3BR6KpR/D6YfEQWIYYA5mQh1MdRzHph9K45FTEEsIs33fXO9V72Ou99+vOWEUMAo7L4jIavGkXrYW3lEVlE5L/sAgD4pxebw9n2JrroXBZEG8alAGpMhgAqRkNoz7V9/fpU++Ls2zXtYW11KhQhhgBylRDa42jKi16fyXn9apYDqBFDAD3VEOpQZTEbeXke1ndMhSL8zBCALwvMSggrU2D0WU329Q0jhgCsXmi8II2EcCSMTRjBXVOhCDEE8C0LSzWE+pooepXpUH9eGMRdiCGASlxGQtiLXRZB+3lRELdOhSLEEHhX1ZDY63ohbGsrU2D0dblB3OmZMTxE5NY59lSuAfDTaEQqEWzb3uvT2Y+2WRy/9ndPhSLXxbB9UztCtv0vAcCXKIJ6f2cIs5eo7f3ghBCKXBfDTBTKXQEF0DcTQb0/EsIoeHatrevtaXbEsBes9o2NBm3mPQDGeIHxQqT3s4hFPy/04hgFsH3uj/2zpkKRPTHUqhFr13nX27X2zVc+F4Avi0g1gno/e2UToX7ZzxWzf2oIRfbHUDvED51dt99gO5ddB2CNvaf08eFsvWh5r94UOBLGS50Zw4yNnV4X+Z4c2z6AeVFcvADq/SiCIvewte1oFCsh/Pp6zp4KRdZj2IJmw6aP9Tdqp772DXrh884BmOfdR3otipENVe81Mwn2voZLQiiyHkPPIf1H3bbmXWe/aUII7GXvp16IDmdfr2Why857ny9qe1kIRfbG8JB4OtTH7jf9TxY/HpeBWCUc9hrvXvQi5R3bVzV+0WeK2l5uJYaHxL8J1tsjWM/CB2BMdj/Z8/rYxigK1sir/UwxOi/O/pcrp0KRtRiO8L7hmW905j0Aft473n0YBaoXs+o0aD9LnP0vV4dQ5JwYHvI49elju261a6JjAHXRPRbt23uzF7PRV/R5ens/eEIIReZjqCNlv3Dvt8TeN23fZz+z9/nAO1qJhHe/RdtevCov71px9vX2fvCkEIoMxvA4juN2u2Ux8qLmfeOf/87pl/ce7+eSAPq8+0Sv2X0vUlHYZs5JZ3s/eGIIRQZj6Gjh8tazfat9ljdZAhjn3Tve/RgFUK9lAbTr4ux72/vBk0Mosh7DxvtGvMfcT/n5/8hnI6jjmk2hAPrsvZnFsG2zwGXHdr8d6+394AVCKLIWQxsu77yn8ngc/bxQhEDifc1GwwuSt78aRe89evuw/yoRbIZj6PzcMItXRr/fbj3EELir3m/2Oi9OWcxG9xtv7eVCKDIRQ8OG0Eayp12vp8H2Hhu8kc8F3lV0b4zG0G6ra97W7r9kCEXWY9jYmIlzbK/1Ho+990WfA+Cn3r0SBSoL2mz8fkUEm9vs12celfXjbW/fexz2Pic6BpCLbmq7XglZddvbf/kQiuybDLVD4kmvnbPX2+v01Ahgjnf/REHU+yOR7O3/igg205OhSHc6nNk2TIPAXlkUs/3svN2/L6zE5Ql2ToZ6Ihz5OV9vGiSMwLjo3suiqI97oftTEWyWJkORH9OhiP8zwOjngkyFwPmqcRyJ3p+JYLMcQ5FyECvnsnUAdb2buzIl2jX38357BJstMRRxgyiShy+LXnYewLeRm7k6LUZrfyaCzbYYioRBFJl7HK5cA+DR6A09EsX7iZ3ReCFbY9gk/8zX7DkA46o3ePe6vxpA7ZQYNoV/+1CEAAJXKt/w7xBA7dQYNsUoAniid4ufdUkMLeIIPNe7h8/zlBgCwKux/+o0ALwlYggAQgwBQESIIQCICDEEABEhhgAgIsQQAESEGAKAiBBDABARYggAIkIMAUBERP4HZiAqo1QvVeIAAAAASUVORK5CYII=\"\n          />\n          <path\n            d=\"M-.23,13.17h217a56,56,0,0,1,0,112H-.23Z\"\n            transform=\"translate(25.34 9.79)\"\n            :style=\"{\n              transition: `fill .3s var(--cubic-bezier-ease-in-out)`,\n              fill: 'var(--success-color)',\n              fillRule: 'evenodd',\n            }\"\n          />\n        </g>\n        <circle\n          fill-opacity=\"0.3\"\n          fill=\"#000000\"\n          filter=\"url(#filter-1)\"\n          cx=\"477.54\"\n          cy=\"66.09\"\n          r=\"20\"\n        />\n        <circle\n          cx=\"477.54\"\n          cy=\"66.09\"\n          r=\"22.5\"\n          :style=\"{\n            transition: `fill .3s var(--cubic-bezier-ease-in-out)`,\n            fill: 'var(--info-color)',\n          }\"\n        />\n      </g>\n    </svg>\n  </n-el>\n</template>\n"
  },
  {
    "path": "demo/pages/home/Right.vue",
    "content": "<template>\n  <n-el>\n    <svg\n      xmlns=\"http://www.w3.org/2000/svg\"\n      xmlns:xlink=\"http://www.w3.org/1999/xlink\"\n      viewBox=\"0 0 575.08 485.98\"\n    >\n      <defs>\n        <filter\n          id=\"filter-1\"\n          x=\"-80.0%\"\n          y=\"-80.0%\"\n          width=\"260.0%\"\n          height=\"260.0%\"\n          filterUnits=\"objectBoundingBox\"\n        >\n          <feGaussianBlur stdDeviation=\"12\" in=\"SourceGraphic\" />\n        </filter>\n      </defs>\n      <g style=\"opacity: 0.9\">\n        <g>\n          <image\n            width=\"605\"\n            height=\"226\"\n            transform=\"translate(0 103.89)\"\n            xlink:href=\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAl0AAADiCAYAAAB0gXKiAAAACXBIWXMAAAsSAAALEgHS3X78AAATjUlEQVR4Xu3d2ZLcOJJAUQ9Z//8nV85DNachT8fCJfZzzMIIgiBTNfOQ18CQ+vbz8xMAANzXn9kCAADOE10AAA8gugAAHkB0AQA8gOgCAHgA0QUA8ACiCwDgAUQXAMADiC4AgAcQXQAAD/Cf2QLu73a73WZrAIBr/DzpfwPx9qSf+5XEFQC8nkdFmOi6k4OBdeQeAGBuGjz3ji/RdaHF0FpZE7G+DgCojSKne+1e8SW6TliIrNH12b3Z3vUA8I1WwiavKe+5Or5E104HQ0t8AcD9zaKmut7O/bp+ZXiJrkWD2FqNrD33r1wDAGq9uBkFVvfaVeElugYmu1r52ux8dc1oHgBYtxpWP+mYx5eEl+gq7NjVGp3vWTuaW7kGAMxfH7bnvWNv7nR4+cdRG4uxtRpaK+PqvDcHAIy1vz+3QNrmVoPpJ/69pz1ewk5XdGNrb1zNro/G1XlvDgAYW3mNWO10TXfBzux2ffVO10JszcZn5vK4Ol+9BgDUu1u9na52Fyuvu3SHa/OVO10XxlbvuHotj6vz1WsA8M1y0Ix2uKrz0Zr2eHi366t2ug7G1iyeVtfNrrWEFwCsa3eq8nneudrGVTj1nnMosrKvia4iuI7GVnVcWdMeR+PqfGTPWgD4FG0I5d+F+bVhe5wFVH5ujrXDPj66Jrtbe2PrzFx7HI2r8z3O3AsA72IUQNWrwSPBVAbX7Xa7HXnF+NHRtbi7tXLcO95z3MzOAYD/qX5P5ki6FXPb559fd/9rFFN/xddeHxldF8fWSmQdia/ReDQHANTaINriqo2t1p/4O7zaOMsOh1br46JrEFy98FqNrVFk9Z6R59pjHlfns3kA4F9bYLXj2WvF3u/k6p7teYd9THSd2N2axdXe84h6Ls/nud75XmfvB4B3kANo+/2357Xi7J6uI9/r+ojo2rG71Yui6rw3N7q3nc9z7TGPq/PeHADw+3dkFUzteFP9Lt7WbefteLMcZD1vH10LwdWLod55b27l/lg4jsbVOQAwl2Mon7fzEX/vbrW/x/Ou12XeNroWYmsb98JoFlMr12My3ozmWtVctrIGAL7BkTDKv5Nvcew5u71ldC0E1yiIRnO9z+z+atweR+PqvGd1HQDwW97dane5qvnq1eThQHu76DoQXL1omn1G90QxznN5Ps+1qjkAYGz0+7P6Xlb7e7kKq9n5KW8VXYvBNQqm3vzqJ98fC8fROBtdAwD6el9+v8XvL8Hf4u/59loeX+ZtoisF1yh0qjg6+8nPi2LcHkfj6nz1GgDwW/6bh5HO87hdcyvmqhjL87u9RXTtDK7qPH/+TK73nhPFuDqOxqM5AGC/7XdqFV953alwOuPlo+tAcN3jE5PxpjeuzntW1wEA41eEo3Xt2nb+blH20tF1p+Ba3eXKz6/Gm5VxNroGAKzZfp/OvgC/zVXXKqvrlr1sdC0EVx73PqPIqq7lZ0Yxbo+jcTa6BgCcd4v9sbT9nu/dd+SZv7xkdF0QXL3QOrvL1R5H49EcAHC9W7zg97haLxddi8FVnfeianVu9PxojqPxaG7VmXsB4FtcEVLb7/krnjX1UtF1IrhWwmpll6v3czbVXL62x5F7AIBYiqW8ZuWeu3mZ6DoYXEdj60/x3Cq0qsjKobQnnPasBQA+yEtE10XBtfe8euY9Ymt1HQDwwZ4eXcX/tE/E7xhq52dBtRpbs9Cqwqs671ldBwB8gadHV1JFUDs/i6pRfB2Nrs1KRK2sAQC+0FOjq/NasR3PYmk1uNrz/NwYHPO4Z2UNAPDFnhZdg+9xjYJrFlkrrxbzs6M4bmYxNbsOABART4quyRfnt/HoczS4cnRFcczjnpU1AAAR8aToKuQYmoXW0eDqhdae4JpdBwD45eHRVexyrQTXSmjtCa4qtqrz1WsAAEMPja6FL863VkNq9W8sRjHezIJqdh0AYOhh0XXB97jaqKp2u2b/REQUxzzOxBYAcIk/swV31AbQ2Y/gAgBe2kOia/Jacfbp7W7NQktwAQAv4yHR1ajiJ1/f+1n5Hld7zONMcAEAl7v7d7qK/23FNoJ6kTQLrNku12ZPcIktAOBu7rrTdfK1YhVbK58oxhvBBQA8xV2jqzCKnqOx1XtWxN/XBRcA8DR3i66du1x5fs+/Pj963kZwAQBPdbfoauSoytf2fkb3tc+txi3BBQA8zF2ia/Dl+W2857Oys5VjbCO4AICXcJfoasxiqzc/+0Qab+ctwQUAvIzLo2uyy5Xnz3zyc6I4ZoILAHiKy6OrUYVRjqb2OPuMntM+q2d2HQDgbi6NrgfucuXYmsWX4AIAnurS6GpUUXT0E2m86c0BALycy6Jr5y5XPh759J6XCTEA4Okui65GDqLVz2h9+7x2PAuq2XUAgIe4JLrusMvVWxNpvKl+nuACAF7GJdHVqHaizn7yszY5zgAAXtbV0TWSI6kXVtWa1kpkrawBAHiY09HVebU4C6uV+d4ztrn22BJcAMDLOR1djdGO1N7Iate0BBUA8JZORdfiF+h7MbUaYDm+8vNaogwAeEmnoqtjz+7V6rreHADAW7gqukYxVIXUyq5Wtcu1WZ0DAHgJh6Nr8mqxF1D52uh6S1ABAG/tcHQ1qtjK53uCK9/bnuc1+RoAwEu6Irp6ciTl2GrnqnXtmpHZdQCAp7squo6EVG9dZXYdAOClHYqu4vtcEWuvA0e7XTnQBBYA8DEORVdjFkajkOrFVmsWX7OfDwDwEs5GV8Q8lGaxtc3NrKwBAHhJu6Nr8mrxSGz11swia3YdAOBl7I6uxuprvyqgclj1IuuWjgAAb+lMdPX0QmnPLtbM2fsBAB7qbHRVYZWPq7tYVwUZAMDLORtdEeOdrXyeo2q2K1ZdAwB4O7uiq/Ml+og6pLZxtXt1Jqr2rgcAeLpd0dWYhU/vdWJvpyuPAQA+ytHo6ql2uWbr2vPRPQAAb+tMdI3CKc/3XjG2x9VrAABv50x0tXpBlY1eL67Yux4A4CWcja6j39ESTwDAV1mOrsHfXBzpvVqs1gEAfKzl6Nrh6KtF4QUAfKwj0TWKqtma6tqR15MAAG/lSHStWgmvao3YAgA+ztHo6u1WVfMr3+kCAPhoR6PriLPhdfZ+AICnuUd0rbxWzGMAgI92RXTtjae96wEA3t6Z6BJPAACLzkTXyJ4g27MWAOAtXRld4gkAoOPK6Mr8UxEAAP91z+gCAOC/zkbXVTtZVz0HAOAlnY0uAAAWiC4AgAcQXQAAD3A2un5mCxZd9RwAgJd0NroAAFhwz+j6CTtYAAARcW10CSwAgI4ro6u1J8D2rAUAeEtnokssAQAsOhNdm73xtXc9AMDbuyK6slFUtdfEFwDwNe4RXT1nI+vs/QAAT3M0unIA/aRjO++fjgAAvt7R6Fqx8pqxWiPQAICPcyS6elG0+n2t3i7ZaAwA8NaORNfMKMpGUSWyAICPtRxdPz8/R6Jo9Ttds+sAAG9tObo6RrtXe14xAgB8tLPRtVl9VTh7xXh0HgDgpZ2Jrl5oVfPVK8be+moNAMBbOxNdlbyLVUVTO18dhRYA8HGORtcsjFZ3u/KaFavrAABexq7oGvwNxt73tPbsdlVrRtcBAN7Grujq6MVRFV85wlbuBQB4e2ejqxdLs+9oVTtdVZT1rKwBAHgZZ6Jr72vB0U4XAMBHOxNdWS+mqt2rKr56O2LtEQDgLe2Ors6X6as4yq8Qeztd1Xkvwlqz6wAAL2N3dBVGu1ijXa4cWzMrawAAXtLZ6FoNodEu10qg9az+fACApzoUXYNXjFVEjUJr9T4AgLd2KLoKox2q1dBqj9noujgDAF7eFdG1+vpvtqOV5/MYAOBtXRFdrdGu1ur1dr5ltwsAeFuHo6v4Xld1Ptq9Wrm+EVUAwFs7HF3JKIpmYTWLrSq+7HYBAG/lVHQt/C3GHEm9qJqta68BALydU9FVGO1A9Xa5ep+8dpOf1xJmAMBLujK6ZjtYq2GV51uiCgB4S6ej68AX6tu5I1G2zbXHljADAF7O6ehKRgG2N7Sqe9prvfPeHADA01wdXa1eOI1Cq3etvd6ej8yuAwA8zCXRtfCKMc+vhNbKmo3AAgBe2n9mCw74iYhbM66u5+N2Ty+8tue1RtfaNaPrAAAPcclOV8Rddrtmn97zst48AMDD3GOnK+LvHaYqenrhVY1v8fcz8nPbnaz257Z68wAAD3HZTldE7N3tWv3804wjjXvnAAAv5V47XRF/7y5VIbTtYLXf5YpifEvnWfszfL8LAHhJl+50RUx3u6odqtVPdU8U4/aY9eYBAO7q8uhKquCaxVX+/FPM5WfmcXU+mwcAuJu7vF78+fn5ud1uvS+4t9FTvTrcQutPmhsFVsTfz5q9cuzNAwDcxV2iK9kCJwfRdi2Pq9BqQyzf1xJeAMBLult0pd2u3k7XprfjVc21x0rvZwovAOBp7v2drqz3ivCn86m+z5U/WRVredwaBRwAwCXuGl3pbzJW41lQrcRXvhbFeCO8AICnuNvrxc3gS/VV6PReM27H7Xtd7fe72jWb/N2u7WdGGrfa9QAAl7p7dCVtcM2+7zWKr97aVn7+SnjNrgEAHHLX14ubg68Z/1k8zj7552yqUFu5BgCw28N2una+ZmzXrBzz68YeO14AwFOshMo99Haeqh2qaner2u0a7XxFMd7Mom90HQBgycN2uiKi9293bVGTd8Fy7ORgqr5UP9rxqnbV8nfJ7HoBAHfx0OiK6IbXNt5UgZRjqze3El75+auvG9u1AADLHh5dHVUIZVVY9WJr5TteOcBWwmu7HpM1AAB/eUp0DV4z7gmv2S7X2fDarvesrAEAiIgnRVfENLy2ucqe2Pon/n3e9plF2GZvfAkvAGDoadEVMQyvSOPWamxVgbVFWKva7cohNQur6vthAAD/76nRVeh9tyrHV3te7Wz9SeORWVDt2fWKWF8HAHyRp0dX8Y+mRtS7Xtt8xO+drBxYvRCb6e16bdeiOO9ZXQcAfIGnR1fE9Ptd+dVdG145pkaxlb/f1X42vV2vK+IrYr4WAPhQLxFdEYfDK6IfV0d2uio5uI7GV8Tv16Qr9wAAH+BloiviVHhFrL1ybHe32rXbzxhF0Gp8tXMz+b8hYv1eAPhm1e/QLK9ZueduXiq6InaFV6UNqyq2qiibxVZ+5TiLr+2ePLdq9t8IAFzjJx74e/floitiObxmEdb7ztctfdp/bDVfGxn9Wdo/e2v2TADgmF4TPCyqZl4yuiKWw2vF7B9Iba9n7S5X3vHq6e1+Rfz95155FgCwz55G2Mx2vI4885eXja6IpfAaBdh2fRRZK5/2We243RmrdryqP1sbWr0/txgDgHXV79PR3GpAra5b9tLRFXEovNoYihhH1uxvNOZnVbtdR3bA2rns8v8nA8CXyD3QfvK61Vi7zMtHV8QwvCqja9nKrlfEWnyN5D9T+5xqLQCwroqt2bqHe4voiijDK6K/21Vpw+nIJz+jPc/Ho1b+OwCA30a7WXmc1+S5VnXfIW8TXRG/wiuijp7KkRjqRVq+1guu9rwdV3/Odh0AcMxKZOXr+VoeX+atoitiObxmO0a9oJoFVvuZhVf7Z2wdCcDN0fsA4BP1winHVfVp121m56e8XXRFTMPr1/Lo70BV6/bE1yi8coC159WfaVs3cibYAODT7I2u2ZrqeutUhL1ldEX8G14REQvf8+rF2HZPjqtqvoqsPeGV/xx5vFmJqlP/DweADzaLrt7nId42ujaLrxvztTxuz9sAqyIrz0dn3AuvKMbbfe15OwcAjOXf97PwiqjXtPOXevvoipiGV8Tv+MlGAZbPc1y1z85xNTr2Yiv/OfYSagB8g97vyBxS7Xj0md2zOfK7OSI+JLoiYs/rxpFRbOXw6p1HMZd/fhVf1Xk7v2r23wgAn6gKo1lo5cjK93dt3bHHx0TX5sCuVxtL+Z4cX/laXtcLsHzM8ZXn27ko5gGA33I47Y2v9p7s9O/ij4uuiFjZ9Wr1dpci+oE1G8fisf25bYBV1wGAsRxd27GKr3/SeXvfSoTt9pHRtensekX8HUgr/8dsY6q9rxdb1fN78bWNc4Ct/LkqOd4A4BONfk/+FMfVz8js+tDtwCvJt5TiK+J39OTxkePKmk1vXJ2P7FkLAJ9ib3Rtxz2fKMaHvs8V8UXRFVGGV8RaCLVB1V6rQmu2vlqbjUJKZAHA33LMtOe9eFoJrepe0bXHyfhaOa5ey+PqfPUaAHyzPeHVi6/emvYouo7YGV/t+SiuqjnBBQD3NwuvKqR6O1rV+sPBFfHl0bVZiK98PhvPrudxdd6bAwDGql2udjwKsDzXHkXXVTrxFbEeSyvj2bXeHACwrrfrdfR4KrgiRFdpMb72ns/W9uZWrgEAv0OrmpvGVWdOdN3TIL4i5hG1ElWrcQcA7NcLrt64d/10cEWIrmUnA6w3N5qfXQMAar246UbV6NoVwRUhug7ZGWC9uZVrlb3rAeBbzKJm9vrx1/WrgitCdJ0yia/NkR2uyt71APCNVsJmtMv1v8mLI0l0XehkhGWr6wCA2ihyuteujq2N6LqTxQDLjtwDAMxNg+desbURXQ90MMQAgDu6d2xtRNcLEGMA8DiPiqxMdAEAPMCf2QIAAM4TXQAADyC6AAAeQHQBADyA6AIAeADRBQDwAKILAOABRBcAwAOILgCABxBdAAAP8H9VKE5I+SV7owAAAABJRU5ErkJggg==\"\n          />\n          <path\n            d=\"M104,118H571V294H104a88,88,0,0,1,0-176Z\"\n            transform=\"translate(8.97 8.95)\"\n            :style=\"{\n              transition: `fill .3s var(--cubic-bezier-ease-in-out)`,\n              fill: 'var(--success-color)',\n              fillRule: 'evenodd',\n            }\"\n          />\n        </g>\n        <g>\n          <image\n            width=\"476\"\n            height=\"185\"\n            transform=\"translate(128.84 202)\"\n            xlink:href=\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAdwAAAC5CAYAAACC7Y6oAAAACXBIWXMAAAsSAAALEgHS3X78AAAPYklEQVR4Xu3d247buBJA0XIw///J8XlIeFJdXTdSlCy79wIMURTl9GAAb1DuyTyez6cAAIBz/aoWAACA4wguAAAXILgAAFyA4AIAcAGCCwDABQguAAAXILgAAFyA4AIAcAGCCwDABf6rFiD2eDwe1RoAwP08X/DXLD5e8Ge+JeIKAJ/rigAT3MBkYGfWAgBeowzemeEluH81A9tZI9JfBwA4Vxa58NoZ4f3RwW1ENrpe3WfNrgcArOuEza5x79kZ3h8Z3CK09trM2szMWgDAmipq3nU99+36ruj+mOBuiGx3rnMNAHCuKG5ZXMNrO6L78cFNQltFdva8mgcAXK8b1ac52vHh6H5scJuhzSLaXeedd68BAPaqHhnr8+gYzR2K7sf9xRcLofXG3djOPmYGAJxLfwaPOI65biyf8ucefTzso3a4QWxX4tqdi86jOQDANTqPjr0dbrn7Xd3lfsQOdyK02Vx0rOai82oeALCft6uNdrh692rXbdvZDm+9wz0htDPrs7FFdAHgfDZo2c7WO8/W6OPSLvdtd7hObDuhzWI7s2bIfgaL6ALAefQO1Z7bHesYe9GM3mc6sNZbBjeJbRTdbliryB6NrtZdBwDw6Qjaz1T7qFgfq3ja97WhXvJWwZ3c1UYhnR1nRzv2zrtW7wOAnyqLn/c4eCWWbmwfj8dj9rHy2wS3sautgludV2PvaMfZHABgL++z1gby4cyN1+9vd/+RhfRLeGe8RXBNbL1xJ5jd8GbvaeftnEZ0AeB6OoYjrDq02i/5Gl0dZmspstqtg9vY1Y7xSmSr2Hrh1cdsnM0BAM4x4qrH1aPk6HPcu2e835LbBrcR2yqy9rwKbfZ+oo56HP2MK47cCwA/kY3f+BydeZRc3ROa/R73lsFdiG0UUO8VrYveLzsO9jyaAwDsYz9nvVjq8aDv05/r3g5Za8fYc7vgNmM7E87Oy94jjaMde+cAgOvYENpzPS/ydVerP//tbneLWwU3+OUo7+hFcvVl30caRzv2zq3qOgBg3koUvc/2lfeZcpvgTsbWO9evX8m17F6R79eHzjjTXQcAOI/d1erdrTfvPY5eivMtgrsQ290vccbe0Y69cwDAdbLPYO97WP257kW1Ol/28uCeFNtqhzte9r3FOWbjbA4AcK3oF50e8v0Xnh7ydV5fs+MtXhrcjbGNAmvno/eT5GjH3nk1DwA4l/0NYzHndqzXPJw5L8R2fsrLgrshtl5kuztb+/6SHO04mwMAvMb4TPbCa9ctR/OIlwTX+U9/RPzgea9uaL05+76SHLNxpLMGALBX9lg4W6fX6vlTgvyS4BpR/LyXjWh17r3EGXvHwZ5X8wCAa43P4+qXncacd83TXddyeXCb/yMC7/UrGHvnes57T0mOdpzNAQDuZyWUow/RfSvv+cWlwU2+t43C6AV1Nrze+4tztONsDgBwP1EUD8dyh8uCW/yS1BivxnbmUXJ2HFYju3ofAGDejoiORux4r9RlwVW82J0d2zNCO7MWALBfJ5R2TeeeU1wS3OJ/SNB5eYHNHifb95bkOHQC2lkDAMA3pwe38UtSWhTQLLar//nP0IloZw0AAKFTg3vge9sqsllsbXDFOdpxpLMGAIDSqcF12BiuvLIAZ5GdiW11HQCAKacFt3iUXL1sVDuRtbH1Quudd68BALDstOAqUfj09dnX7KNkO/ZU1wEAWHZKcDf8VrKOand3K854yGJKaAEAp/tVLZi18Cg5u9Z9iTMeiC0A4OW2B9cRRc1Gs7uT9d6P2AIAbm3rI+XJ3W00fyTCndgSWgDA5c7e4Xpxq8LZDawO7Xhfb6wRWwDAS2wL7sTu1purXtE9Ysbj3ENsAQAvsy24Di+Eu176PTViCwC4pS3BTXa349zbjVZRjSLrvY8+WsQWAPByW4LriMJqz7O4ZuuHKqbVdQAALrE7uN5OVI+jsHbi672XPreILQDgNg4HN/lbpfS5Dqee68Z3sOdjDgCAWzscXMULo7dD7QQ2uj48zNEiwgCAWzkU3MbuVs9lcc0CrUXzdg0AALdyKLiBKKD6ml3n3RfFeIiCDADA7ewKbha6mdjq9R6CCgB4S8vBbTxOzoI6u7Ot/qxoDgCAW1gObiCLafc8kq0htgCAW9sR3Ch23q60E9tqdwsAwNvZEVwRP656bMOZxdbT2fkCAHBbS8F1vr8VqXew3blsZ0tcAQBvaSm4SjeAM6H17ot0/3wAAF7qaHBF8p1oFlEb30pnDQAAt7QjuJrdsdr5aJdbrfNU1wEAuI3p4Bbf3+pzb15fz8Kr5/URAIC3NB1cpYpgtHON1sxYvQ8AgJc4EtyIt9O116M1nUfJAAC8naPBjXas0e42imsWYQAA3t7R4IrE37NG0ezuYmffFwCA29oRXJG1R8RRUAEA+DhTwQ1+Q7nDe6TsrQEA4CNNBVep4tgNq93lVu8LAMBbWg1uZPZxcnWNAAMAPsLu4Hqq6HrXCS0A4KMcCW7028NRQIkoAODHOhLcFVGku2bXAwBwC7uCOxNSogkA+HGOBnc1nqv3AQDwlo4GN0NUAQD468zgziDOAICPtju4hBMAAMfu4FoEGAAAOT+4AABACC4AAJc4O7jPagEAAD/B7uASWAAAHLuDu4pQAwA+2pnBJaIAAPx1NLirUV29DwCAt3Q0uIMNaBZUYgsA+HF2BbdrJsye2fUAANzCkeBG8fSi+AzmAQD4EY4EtysKbRVoAAA+xu7g6lBmu9rud7yEFwDwEVaDW4VwNqjZbhcAgLc3Fdzn87kaxKd6ZWsAAPhIU8FNRI+BO4+VCS0A4OPtCG4Uziy0ncjOvi8AALd1NLhRDL1drg2tPveuAQDwMY4G11OFM4trd/cLAMBbORLcKozRLjdaM2P1PgAAXmI6uMFvKke71mjHmj1etuv0EQCAtzQd3IL9XtbOV6GN1nmq6wAA3MaO4FY7U+8xcrQjznTWAABwS0eD241gtrvtxDnS/fMBAHippeAW3+PagGaR7d6n1wIA8HaWguvwdqZ63ImsvU9jlwsAeGs7gtuNZLWT9eajnS4AAG9lR3C1TlSr80i2higDAG5tObjO97jRjjYaZzta76URXQDAW1kOrtHdmVbR1es9RBUA8Jb+qxYssFF8/J0bRzu25957DA81Hvdp3hwAAC93aIfbeKys5+wj4uglZqxF83YNAAC3cii4hg5dFlBvXIXXhvZpjhbRBQDcyuHgNna5NqB6rgqsF9rqzwMA4HYOB9fIYjgbWW+NfS99bhFiAMBtnPFLUyL/YveQr+HT51FQn2qdvX8Yvxj1lPyXpKrrAABcYssO1zxWtoHMwjrz0uz76KMVzQMAcJmzdrgi/0Knd6P2Whbi6B6ReIdrz6t5AAAusS24z+fz+Xg8vBDaHaZ9rDyOWXCzR8te2IkuAOBWtgU34EUu2unq8W/587jb2+laUeSJLgDgNrYGd2KXK5L/AtU4jvCOY0b/opWYsWZ3xAAAnK6K2A7R7vRpXr/NMXtF7yXy9Xq2M86uAQCw1dYdrsj0Llek952uPtqxyPfvcjs73eoaAADbbA+uyLfoivwLW7Q7teOx0/3lHO09w5HoSnIdAIDDTgmuoWObfaeqx9Ux+k63iu6Y97DbBQCc5rTgLjxa1tei3W21yxWJd9LsdgEAL3NacAPZo+Vx3Y6j3e3sby53HzGP61KsAQCg7dTgBrvcbLfrBTfb3R6N7rge6awBAKB0anBFykfLNmQ6uFlg9bXf8ud9qvBahBcAcJnTgyvyLboi9aNlvU7ke2BHdHVox/l4ad4u1wa/esw81gzVWgAA/u+S4Bpe+CJeaLPxqpnd7uD93J37AAB7VJs2kfyry0tdFtyF73OHTmhnHitHu91xTeTrzzIT0Zf9iwQALHnKRZ/dlwVXJI2umLHVDa1+rKy///UeM1teeCWYAwDcT9SQS4JauTS4ImF09bgbXS+0eoer46tV39XanyHagRNgALinlcBWO92V9/zi8uA67A63G91xXu1wtSq2VrTrFfF/xpn3BgDs4X0eZ3PdeHbXtbwkuM5vLYt8jW0V3Wg3G+1w9Wuo4mtj29nhbv2XAwCYpj+Hn+Zl13VDvcVLgivyLbpebLPoivi7WRtZu8sd72vjOyv62Y68JwBgnRfaat2lXhZckS3RHaLQertcTQe4K9vtdn5WAMA5sl2sHds1dk7z7pv20uCKbI2uFj1O9l4iX8Nr/+zKys8HADhHJ7D2ur1mx1u8PLgiy9HVkbSv6r/H9e7V8za2+rwbYmvlHgBArtqNPpOXXjdU58tuEVyR5ehGOjvcwcbXi649t+OxBgBwrdngVmu861q3Q9/cJrgibnRX2IB2XlV0vQjrsXdurf7zAAD6quBGr9PdKrgi36Ir4kfPo6OZiYK8Gl1xzvUcAOAa+jNYhzSLrLdGz29zu+CKtKObxVff472i6zbaXnzHvD7aeT3XRaABYE70OWsjqsfZq7pnmP18F5GbBlekHd3IWOPNVeF9OmMxRy+w3s80E9Glf4EAgP/zolhF1gbW3h96Pp/lGu22wRX59w+z+D88GHRAvTkbWS+0XmSrn6PzswEA9rLRnA2vvsc69Jn+mAz0yzh/FaS384yOj8Z5NfaOdpzNAQDO5+1So/D+NufZvH2/z9rhasUj5o6xXo8fjbEkRzse592fSSPSADAn+6z1Itl9ZarrobfZ4WqN3a6d84LZncuOduydR7rrAAC+2eCO48xLnPH07lbkTYMrkkZXj+1cFdDummEmtgQWAM5jY6bPo3B2Iuvd+7OCK+JGV6QX3ug4sz4bW8QWAM43E90ovNEaffx5wR1OCG+11o6982oeALBfFV0votFO1lu/FFuRDwnuMBFePT4yF51HcwCAa3i7Wz3O4mvn9JHgDkF0Rerw6nE3roQWAO4r2u2uHpdjK/KBwR0Wwptdq3a0WWQJMABcx4vabHijOYKbaYZ3x3k1DwC4XhTbaBxdPxRbkR8Q3CEJr0gvpt25zjUAwLmiuIVBza4dja3IDwqutiG+nWvWzFoAwJoqatUj52/Xd8RW5IcGdyjCK7LvsfHsegDAuk7Yst3tv8mNkfzRwdUa8RXph7O7DgBwrixy4bWdoR0IbqAZ4GFmLQDgNcrgnRHageA2TQYYAPBGzgztQHAPIMIA8J6uCKxFcAEAuMCvagEAADiO4AIAcAGCCwDABQguAAAXILgAAFyA4AIAcAGCCwDABQguAAAXILgAAFyA4AIAcAGCCwDABf4HTmXXxp0OkSUAAAAASUVORK5CYII=\"\n          />\n          <path\n            d=\"M212.5,216H571V351H212.5a67.5,67.5,0,0,1,0-135Z\"\n            transform=\"translate(8.97 8.95)\"\n            :style=\"{\n              transition: `fill .3s var(--cubic-bezier-ease-in-out)`,\n              fill: 'var(--error-color)',\n              fillRule: 'evenodd',\n            }\"\n          />\n        </g>\n        <g>\n          <image\n            width=\"312\"\n            height=\"122\"\n            transform=\"translate(293.08 304.98)\"\n            xlink:href=\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAATgAAAB6CAYAAAArmE+5AAAACXBIWXMAAAsSAAALEgHS3X78AAAKJElEQVR4Xu3d227bSgxAUao4///J8XkIJmFocsi5SHaUvQBhdBk7bQFtjJw2PR6PhwDAHf3LJgDAb0XgANwWgQNwWwQOwG0ROAC3ReAA3BaBA3BbBA7AbRE4ALf1XzbhNzmO48jmALje40X/ZOp40dddRsyA3+uq4P2qwA1ErToPwHnSuJwdurcPXCFq2XWR2hwA63pBCa+dFbq3DVwnbKPnreo8ADWViNg57mt2h+7tAjcQNm9eNV7VeQD6soB41/W5p+s7I/c2gQvClkUtO65eA7AmCkkvZuG1XZF7i8A5cdPH1WvVlR+A81Qj9jCj3d8SuZcGLlm1ZSHLVm8EDzhf9giqj6MxOrccuZf9Rd/iqq13LptvrwHYT99fLUbtXDVOD/l8jR63uHwFNxm27Lx3TSNywLkqj6LeCi5d3a2s4i5dwXXiFkUuWrVlo93XiB2wj7dqi1ZwenVm521duTWXreAKcfPGLHZZ2IgccB4bj97KzTvuzdHj9CrukhXcYNzs/kjw9NgQOWA/vQKzx3ZF1va9SEXvMxU06/TAmbh5+5WozYSuqYasOg/4q3R07P1iHz31mMXKvq8N47RTAxfEzRujoI2EzhvtftXMa4C768XGe7yciZMbt+M4jpnH1NMCNxi3XuCy4Nn302NDsIB13n1kg3Q459r28fTqT71w/QjdqFMCNxG3yua9Rpz9hsgB59PxaSHTYdP+yc/I6RBa01HTtgeu+K8TsphVNnH29Wj3vWMA81rM9H72aBrdn95r2vtN2x44w/vNZOE65LP01bj1AucdV8y8Brg7GxsvbqL2vUfT7DWhmc/htgau82jqRWkkbO0/x/GuiTPafe8YwBh7D3lx8kIVdcFbAWrl+EW2BS753K3tR5sNW7aCa5t0xsYeA9jDhicKkY1YG73zW20LnOIFp7dlcfNiJ86+Hpte3HrXAPhmIuTdpzPvM2xL4JJ/qVCNW7QfbWL227EeeypzAKyxqza9evPOe4+30zFcDlzhXypoUax6cdPH9j3EGRsCBuzXu6+8z9H0/elFLDteshw4xQtNFDQvZPZctIoTZ1+PGpEDzhN9Y0BHSoetF7OtYWuWAhf8nTeRftiiqNmxt4kz2v3eOQBr7HdAxRzbfT3ncM554bPnhy0FTtGxsUHZFTW9iRp7+wDOYQPW9r15S5FaMR24wk/mtTGqbN7nb9H7eaOH4AF79R4ze/O82J0awOnAKTZsbVzdWuzs+4kzagQNOFe7x7JvDrRz1YhV55X9kwmF1Zve9yLlhcyu3ux7ZHGzrwNwjZn7LrtfZ97zyVTgAl7Iescrn7vp33z2BwXgHNF99zb34+ojqv2NeOHJglXZxOy344rqPAB9Ox4f2328471Swyu45PG0Heso6XPViK3Gzb4ewLrK/ZT14VIrKzgbnChCWcBGY9b7A3vpHyaA97ISuJ4sbtk177oeLcIG4MnwI6rhra4qATuK59p5PVrEDYBrKHCdH0dejVnv2IrO2zkA4BoKnFINi7cas3Gz56PYVc4BwJfZwIn0o5OFzc61stUbcQOQWgmc5QXLC5W3govm2jkAULYauGgVFkUtWsF55yPZdQAQkYHAJT/7LdrPHj+z9yRmAKaVA6dk0ams3mbteA8Af8RM4CKVx8zeIyrxArDVzsBZlcj1rhE8AEvODJxIvDrrfcZG2ABsMRu4kWABwEvMBu4ViCeAIVcGLlr1AcAprgwcAFzqysDZH1F8yY8sBvB3XRm4VQQRwJDZwEWrMSIE4G3MBq7qoTZ7Xo/eNQBYcmbgolD1AqavEToAS3YGrhInb060ygOAJTOBy0LkPY7uCtiO9wDwR5QD93g8RlZlbT/6jC37pkR2HQBS5cAFohBVVnH2EdWej2TXAUBE1gOnebHzVnHRCq634gOAYSuB68XIW5X1VnBWFDt9HQC6ZgNXDUwWOhvEkVVc9dcA4I8aClzwjQYvWjPHVraKa3MAwDUUOIcNTBSuXuR659p5PVpEDoBrNXCRkch517zrerTsawFgKXBejKKVV7RKs5ud3461XsgIHYAvw4FzPofzjr2VV7ZF88Tst+Me+3oA6yr3U9aHS/2XTUg85OePHtfHXuTa2ObZiEXaXO84+9HnL/0DBvDDpQuP1cBpOlqNPrZR+5DPFWQlcCLfr9WjSD10APaK7tnsXr7M8COqiGSPqXbfrtzs9mFGW3h7LgqifR2Aa8zcd9n9OvOeT3as4Oxqyq7i2vmRUeR7hVdhH5OjawDWefHpnavGqjqvbDpwj8fjcRxH9vmbyPNjam+0UfsQ/78bjELarmvb/9AAfNH318Nsdl41jNtMB86wwYlWVDZkdrTzK+zXZQUHnM8LWzbvckuBc1ZxX5ecc/Z8L3aHxI+neqWoRXF76R8wcGO9VZrdt3O8Ftjj5Xt3KXCGXsV5j6r22Fu16XNe6KK4eYgbcL5K0Ox1e83ub7McOLOKs3HLPg+LwuZ9Dte2xr6/Pq7ErRpKAN+y1dajs+l5TXa8ZDlwIk+RE/mOTfaLjVZsOmreo2o1pEQM2Gs0cNkc77qWNaRrS+AMHbfRyEXHh7OJ+F+rt8rTsl8XgFwWuGi7xLbABY+qOjC935T9vM1Grf2LBy90UVDt12U1B+yl72kdrl7UvDn6/FbbAifSjZyY/Uj0HVT79+Fs7HpBrQTWIobAs+gestHS+70te00zcu/+sDVwDhucSuRE4sdSL2rt/e3Y9vXXq4ar8msE/jovQlnUbNDs60Od/7o0tD1wwd+N03GrRs7SQfMiZ9/bi9vM1wUQs5EaDZ1+jbV8v24PnMhT5Ly4ebHxAmY3b147FjMSN+B8NnBt9EJX+YEaveANOyVwItOR83jh0+ekM7b9ytfR9OsBfOrdRw9nrG492fWuY+Kxdoh5XPX2baii4958ccamGqvqPOCvGg1cG0c2cfanPn8TOXEF1zgrOZGfqzDvF96u2eMj2BdnbKJw2fNTf4DAH2XvF30chaoXNftauz/l9BVc43zjIQrTyErNi1q0r7FaA9ZV4mRD5sXNO9bj9ArussCJlCJnz1Ui6I12XyNuwD5Z5LxoeXGL5k/HTeTiwIl0I6f37bnsvHdNI2rAubzVm97vxc6e0+PvClwzGbrqNY24AdeIVnOz41LcRF4YOBE3ciL542YUs+w4Ow9gnBeQ0dBF53534Jriai67RtCA14viFu1H15fjJvImgRNJV3Ozx9VrANZEIQkD1ru2I24ibxS4JgidSC1m1YhV5wHoywKSPcI+Xd8VN5E3DFwzELrsvFWdB6CmEpHe6u375OYgvW3gmk7ovqYk10VqcwCs6wUlvLY7bM3bB04rxK6pzgNwnjQuZ4Wt+VWB0wZiB+DNnB225tcGzkP0gPd0VdCsWwUOADTv/xwFgFsgcABui8ABuC0CB+C2CByA2yJwAG6LwAG4LQIH4LYIHIDbInAAbovAAbit/wFfjkiNiPaWiwAAAABJRU5ErkJggg==\"\n          />\n          <path\n            d=\"M345,319H571v72H345a36,36,0,0,1,0-72Z\"\n            transform=\"translate(8.97 8.95)\"\n            :style=\"{\n              transition: `fill .3s var(--cubic-bezier-ease-in-out)`,\n              fill: 'var(--warning-color)',\n              fillRule: 'evenodd',\n            }\"\n          />\n        </g>\n        <g>\n          <image\n            width=\"264\"\n            height=\"122\"\n            transform=\"translate(340.94 363.98)\"\n            xlink:href=\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAQgAAAB6CAYAAABDa82BAAAACXBIWXMAAAsSAAALEgHS3X78AAAKHElEQVR4Xu2d7Y7bOAwA6eLe/5Gb+1Go5bKkSMmyLW9nAEGfdnYX4oTy5dLj8/kIAIDHj2wBAPy7IAgACEEQABCCIAAgBEEAQAiCAIAQBAEAIQgCAEIQBACE/JcteBvHcRzZGoA38nngY8/HA6+5DGQA/zJ3CON1ghiQQnUdwM6kAXqlKF4hiIIUsnmR2hqAHegFZTh3hSi2FkRHDKPjluo6gLuoBKJd416zUhRbCmJADN66avBX1wFcTRaE3rwe+2t+lSS2EkQghkwKWb86B/A0UTD2ZBDOrZDENoJw5KD71blq5gGwM1UJfExt26cl8bggkqwhE0GWPSAMeAPZEUL3ozoaOyWJRz8oVcwaemPZejsHsCN6f7ZgbmPV4P7Ir2t0fZpHMohJMWTj3pwGScDuVI4SXgaRZhezWcTtGURHDpEkoqwhq21bgyxgJ7ysIcogdHZg1y3LHBq3ZhAFOXh1JotMDEgCdsYGYC9z8Pq9NbqeyiJuyyAG5WDbI8LQdQNJwI7oDMD2bUbQ2l6QR/cZFoLlFkEYOXjtihRmRNGoiqC6DmAWHbR2v9mjg66zYLf3tWKZ4nJBBHLw6kgII6LwatuuMnMNQEYvWL3jwUxwu3I4juMYPWZcKohBOfQEkQnD3k/XDQIedsDbhzagD2eslZ9/Xf2LXuB/EcUIlwliQg6V4l0jTruBJOAN6OBtItBi0PyQr5LQIrFMSUFziSCKn47MZFAp4rR1bdteH+BJmgx0OztaRPvbu6bdb4pLBGHwfpks8A/5ZcqqHHqC8PoVZq4ByLDB6slBVNs7WmTXhIw+h1guiM7RwgvqETG0L9j15sSpbdvrA9yN3YNecHuBHsWVl4FoyvLwWCqI5LlDa0fFiiHLIFqRTt2wfYBdsIEbBbKVQKu98WUsFYTCC9heyeTgyUKctq4bPTn05gCuYiaIvX0+c58hlgki+aRkVQ5ROypi2q2v6x6VNQBPY7MGnT14497xZEomSwRR+KSkJgr2nhx0395DnLqBAGBHevvSe46g97cngaw/zRJBKLxAjYTgicCORVmEOG1da5AE7Ez0YFEHuRZDTwbLxNA4LYjgMw8ifTFEUrB1r4hT23ZvDOBp7H+BENO3bb3mcMY8cdjxIU4LQqGD1QbkKinoIqrutQF2xQqgtb1100F+hlOCKHwzlA3mSvGeP0T382oPhAG70Tsm9NZ5srhMIKcEobBiaPXZ0mRh7ydOrUEIsDttj2YPF9tYVQLVdSV+yCSF7EG3vSD3RGCzB3uPTA72OoC3MLNvs/0+c88vTAsiwBNBr3/muYP+5bM/FMCuRPt2i/284ohhfxEvcLOArxQx7davUF0HcDUr0v8WByvu1WUqg0iOF62vg1qPVSVwVg72eoAdqOzHLL5u42wGYQM2CuJMAKMy6P3BHvtjAnw3zgqiRyaHbM6b17UFMQAsZuqIYfDe3SsCOIpjbVzXFuQAcAHDguh8nVxVBr2+JRq3awDgAoYFoagGppcNWDnY8UgWlTEAWMQZQYj0gzYTg11rybIH5ABwMWcFYfEC3gt0L4OI1to1AHATKwQRZQGRFKIMwhuPyOYBYAFDgki++yFqZ8eH7J7IAOAhhgShyIK2kj3MsuIeAFBgVhARlWNC74hB8ANsxGpBWCqS6M0hDIAHuVoQInF20HvGgBgANuCMIEYCHgBeyBlBPAHyAbiRuwURZR0AsCF3CwIAXsTdgrBfkXX5V2YBwDx3C+IsCAXgRs4IIsoGCGKAb8IZQVT5qGLHde3NAcCDXC2IKNB7AtBziALgQVYLohLc3pooywCAB5kVRBbI3nFilQBW3AMACgwJ4vP5jGQFrR09Y8geambzAHAxQ4IIiAK5kkXYI4Ydj8jmAWABKwSh8WThZRFRBtHLOADgZs4KohfMXlbQyyAskSz0PABcyBlBVAM0E4UVykgWUf0ZAGCCYUEEDyq9oJ/pW7Isoq0BgAsYFoSDDdAo8HuS6I21cV1bkATABawQRMSIJLw5b17XFnstAJzkrCC8YI7e+aMswRa7vvU1PREgCoBFTAnCeQ7h9b13/qxE68S0W7+HvR5gByr7MYuv2/gvW1DgI1+/Ok73PUm0uq2zEohoa71+9tV1j/2BAS7gtje+FYLQ6KBv6L6Vwk/5lcVUBCHy51pdi9RFAbAb0Z7PYuEWpo4YIpIdM2zbZg62/DS1NaQdi4RirwN4CzP7NtvvM/f8wqoMwr6b2yyijY/UIn8yjAr2mBPNAeyAF7y9sWqwV9eVOCWIz+fzMf/itxVFwx4zerWVwk/xvy4/ElGb1yz9owEsRu/Pjyl2XVUsSzglCIMN2Ogd3YrA1nZ9Bfu6ZBDwBjwxZOtu5bQgnCzi95QzZsd7sjgkPl7oTEUTyeGxPzBAQi9LsG27xosl2z+1908LwqCzCO+oYfte1qDHPFFEcvBADvAGKkKw83bOtpewRBAmi7ByyJ4HRGLwnkO00rD31/2KHKqiAVhJ9m7/6RS9rpH1p1kiCJG/JCHyJ1izHzbKGLQUvKNGVURIAHZjVBDZGm9ek8VgyDJBGLQcRiUR9Q+niPiv1csyNNnPBXAHmSCicjlLBREcNXSA9n4p+7zBSqF94tITRSQk+7pkE7AbOiZ04Pek4K3R48tYKgiRriTEtCOi/4JhPw9hZdETUkVQFmQCVxDtQRv0ut0r2TWNkb3/m+WCcLABW5GESHys8KTQ7m/r1tavVw38ys8IcBYviDMpWCHY60M6/3SFyyWCCD4boeVQlYRFC8GThL23J4eZ1wW4Ehvko6LQ11hO7fdLBCHylyQ8OXjB6gnAFm9d64upkQO8ASuIVnuiqPwPjT1hDHGZIESmJeHhiUOPSadu7crraPT1AKvo7cOPU1dLj2w+5Bg8kkxhjhte2wZ61O+tF6duVIO9ug5gllFBtHqkiNMefv4gcnEG0XAyCZGvWYD3g7c52z+Ctjh1Iwp8Oz78BwQ4gd1vuh8Fek8K9lrbHuaWDKLhPLiMAnskU/CkELU1ZAuwA5XgtiLw5OD1dT2VQdwqCJGSJOxYRSJebdsa5AA7kUnCC3pPDtH6KTmIPCAIka4kdNuOZePenAYpwO542YNu92Rhx3T9LkE0JkVRndMgB3gLUTYxW0/LQeRhQYi4khDJjwuRDLJ+Ng7wBF4QjooiGnu3IBrFbCKbQwjwHYjkELWj+VNyENlIECJpNjHbr84BPE0UjKEAenNn5SCymSAagShEajKoSqC6DuBqsiDMjiB/za+Qg8imgmgMiCIbt1TXAdxFJRB72cOfwYVBvbUgGh1R/F6SzIvU1gDsQC8ow7mVYmi8QhCagiwa1XUAO5MG6BViaLxOEJoBWQB8O64UQ+PVgvBAGvBduUMIlm8nCABYR/VfzgaAfxAEAQAhCAIAQhAEAIQgCAAIQRAAEIIgACAEQQBACIIAgBAEAQAhCAIAQv4HvkZIjVufyEEAAAAASUVORK5CYII=\"\n          />\n          <path\n            d=\"M393,378H571v72H393a36,36,0,0,1,0-72Z\"\n            transform=\"translate(8.97 8.95)\"\n            :style=\"{\n              transition: `fill .3s var(--cubic-bezier-ease-in-out)`,\n              fill: 'var(--info-color)',\n              fillRule: 'evenodd',\n            }\"\n          />\n        </g>\n        <g>\n          <image\n            width=\"390\"\n            height=\"185\"\n            transform=\"translate(214.81)\"\n            xlink:href=\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAYYAAAC5CAYAAAAs25gpAAAACXBIWXMAAAsSAAALEgHS3X78AAAPJUlEQVR4Xu3c247cuA5GYVZjv/8jp/ZFRgjN5kmyXMf1AYZlWXbXIBj+RbuT2/1+FwAAhp9qAQDguxAMAIADggEAcEAwAAAOCAYAwAHBAAA4IBgAAAcEAwDggGAAABz8r1qA2O12u1VrAOCM+xP+eYrbE37mWyIEALyCRwQFwRCYDIKZtQBQKQvzlQFBMPynGQSdNSL9dQAwZMU4PHdFQHx1MDTCIDpfXWfNrgfwHToF2K5xr9kZEF8ZDEUg2HMzazMzawF8vqr4euf13K/zu8Lha4JhQxh05zrnAGCIinAWAuG5HeHw8cGQBEIVBrPH1TwAZLrF/272dnw6HD42GJqBkBX77jrvuHsOwPeqHhXp42gfzZ0Kh4/7C24LgeCNu6Ew+3gJAAZdK0YRH3Pdon6Xv9fo/Wkf1TEEobASAt256DiaAwCr88jI6xjKbmK1a/iIjmEiELK5aF/NRcfVPIDv5nUJUceguwG7blunMLx1x3BBIMysz8YW4QBAs4U36xS842yN3i91DW/bMTih0AmELBRm1gzZZ7AIBwAix2/89th2AGPsFffoPtNBYL1lMCShEIVDNwCqMDgbDlp3HYD3p4u1/X/fPiLS+6rI2/vaQFnyVsEw2SVEBX92nO3t2DvuWr0OwOvLirT3GGilqLuhcLvdbrOPk94mGBpdQhUM1XE19vZ2nM0B+F5eTbCF/ObMje3Pr6v/ygr+ISBmvEUwmFDwxp3C3g2I7J523s5phAOAjC7aIwB0IGg/cgwHHSDWUhhoLx0MjS5hjFfCoAoFLyD0PhtncwAwQkCPq0dIUb3xrhn3W/KywdAIhSoM7HEVCNn9RO31OPqMK85cC+C12SI9/n+feYRUXROafc/wksGwEApRofe2aF10v2w/2ONoDsB3svXAK+p6POjrdP3xOg6tHRqelwuGZijMFPjOZq+Rxt6OvWMA8NiCbY/1vMixS9B1ynYPW7xUMAQvmb29V8xXN3sfaezt2Du2qvMAPttK8fZq0Mp9prxMMEyGgnest5/kXHatyO/zQ2ec6a4DAJHfXYLuFrx57zHUUoi8RDAshMLuTZyxt7dj7xgAPFmt8N4T6PrjFf/qeNnTg+GiUKg6hrHZe4uzz8bZHABEohfGN/n94vgmx3l9zo63eGowbAyFKAjsfHQ/SfZ27B1X8wAw2N8oEnNsx3rNzZnzAsPOT3laMGwIBS8Mup2Cvb8kezvO5gCgMmqHFxB23XJxP+MpweD8SqqIX5i9rRsI3py9ryT7bBzprAHwvbLHQdk6vVbPXxIcTwkGIyrS3maLfXXsbeKMvf1gj6t5AIiMulG9NB5z3jlPd13Lw4Oh+Q/iedtPMPaO9Zx3T0n2dpzNAcAZKwV91LHoupV7Hjw0GJL3ClEB9wr/bEB49xdnb8fZHACcERXv00V9h4cFQ/GyeYxXQ2HmEVK2H1bDYPU6AJ9tR7EftWzHvVIPCwbFK8pXh8IVgTCzFsB36xR0u6ZzzSUeEgzFP4zX2bwgyB4j2XtLsh86hb6zBgDe2uXB0HjZrEWFPguF1V9LHTrFvrMGAD7CpcFw4r1CFQZZKNhgEGdvx5HOGgD4KJcGg8MW7ZUtC4osDGZCoToPAB/rsmAoHiFVmy3+nTCwoeAFgnfcPQcAX+GyYFCiAq3Pz26zj5Ds2FOdB4CvcEkwbPgtJF38u92COOMhK/oEAgAoP9WCWQuPkLJz3U2c8UAoAMCE7cHgiIqvLe7dzsC7H6EAAJtsfZQ02S1E82fCohMKBAIAJK7uGLwiXBX4bhDoQBj39cYaoQAAhW3BMNEteHPVFl0jZjyOPYQCADRsCwaHV7B3bfqeGqEAACdtCYakWxjH3rf7qvhHYeDdR+8tQgEAJmwJBkcUAPY4C4Fs/VAV/eo8AMDYHQzeN3s9jgKgExLevfSxRSgAwILTwZD8LWd9rAu8nuuGxGCPxxwAYJPTwaB4Bdz7xt8Jguj8cDN7i7AAgEWngqHRLei5LASyINGiebsGALDoVDAEokKvz9l13nVRaAxRcAAATtgVDFlBngkFvd5D4QeAiy0HQ+MxUlb4ZzuF6mdFcwCAScvBEMiKfvc4kq0hFABgkx3BEBVl71t+JxSqbgEAcKEdwSDih4Ae2wKfhYKn00kAADZYCgbn/YJI3RF057JOgRAAgIstBYPSLdQzgeBdF+n+fABA09lgEMm/2WfF3oZEpbMGAHDSjmDQbAdg56OuoVrnqc4DABZMB0PxfkEfe/P6fBYQel7vAQAXmw4GpSrWUScQrZmxeh0AoHAmGCJe52DPR2s6j5AAABc6GwxRBxB1C1EIZGEBAHigs8EgEr8HiIp7tyuYvS8AYIMdwSCy9mgoKvwAgCeaCobgN5I6vEdJ3hoAwJNNBYNSFfFuANiuobovAOBiq8EQmX2MVJ0jKADgwXYHg6cKB+88gQAAT3ImGKLfFooKPcUeAN7AmWBYEYVJ1+x6AMCkXcEwU/Ap7gDwws4Gw2qRX70OAHCxs8GQofgDwBu6MhhmECIA8CJ2BwMFHgDe3O5gsAgKAHgzVwcDAODNEAwAgIOrg+FeLQAAvJbdwUAQAMCb2x0MqwgUAHgRVwYDxR4A3tDZYFgt/qvXAQAudjYYBlvos8JPKADAC9sVDF0zAeKZXQ8AmHQmGKIi7xXvezAPAHgxZ4KhKwqEKkgAAE+wOxh0Qc+6hO47CAICAB5sNRiqgj1b+LPuAQDwQFPBcL/fVwv3XW3ZGgDAk00FQyJ6/NN5nEQgAMAL2REMUYHPAqETBrP3BQBscDYYoqLtdQ02EPSxdw4A8ARng8FTFfgsBLrdBADgImeCoSrgUdcQrZmxeh0AoDAdDMFvJkVdQNQBZI+V7Dq9BwBcbDoYCva9gZ2vAiFa56nOAwAW7AiG6pu+9/go6jAynTUAgJPOBkO3WGfdQidEIt2fDwBoWgqG4j2DLfRZGHSv02sBABdaCgaH901fjzthYK/T6BoA4EF2BEO3mFedgTcfdQ4AgIvsCAatU/yr40i2hvAAgE2Wg8F5zxB1CNE46xC8TSMcAOAiy8FgdL/pV+Gg13so/gBwsf9VCxbY4n37b27s7dgee/cYbmo8rtO8OQDAhFMdQ+Nxkp6zj4aiTcxYi+btGgDAolPBYOiCnBV6b1wFhA2Eu9lbhAMALDodDI2uwRZ6PVcFgRcI1c8DAJxwOhiMrGjPhoG3xt5LH1sEBgAsuOLls8i/onyTY4HWx1Hhv6t19vphvGC+S/6yuToPADC2dAzmcZIt5FkAzGyavY/eW9E8AMBxVccg8q8g62/39lwWGNE1InHHYI+reQCAsS0Y7vf7/Xa7eQXbfmO3j5PGPguG7JGSF0CEAwAs2hYMAa8YR52DHv+Rv4+5vM7BisKIcACABVuDYaJrEMlfRI/9CIixz+gX1mLGmu0wAABKVWx3iL7t3832x+yzLbqXyPF81mlk5wDga23tGESmuwaR3jsHvbdjkd/vGjqdQ3UOAL7S9mAQ+RUOIv8KcPRt345H5/Dj7O01w5lwkOQ8AHyVS4LB0KGQPfPX42ofvXOowmHMe+geAEAuDIaFR0r6XNQtVF2DSNyZ0D0AQMNlwRDIHimN83YcdQuzv6nUfbQ0zkuxBgA+0qXBEHQNWffgBUPWLZwNh3E+0lkDAB/l0mAQKR8p2YKrgyELAn3uj/y9TxUQFgEBAI7Lg0HkVziI1I+U9DqR30EwwkEHwjgem+Z1DTaYqsdLY81QrQWAt/SQYDC8Ah3xAiEbr5rpHgbvc3euA/B9qi/BIvmj9Yd6WDAsvG8YOoEw8zgp6h7GOZHjZ5kp9k/7gwTw8e7yoBrzsGAQScNBzNjqBoJ+nKTfT3iPlywvICSYA4Azolr3kMJfeWgwiIThoMfdcPACQXcMOiS06l2C/QxRR0NQADhrJQiqzmHlngcPDwaH7Ri64TCOq45Bq0LBiroIEf8zztwbwPfx6kY21y3y3XUtTwkG57eURI6hUIVD1B1EHYPehiokbCh0OoatfzgAPpquF3ez2XXdQNniKcEg8iscvFDIwkHE7w5sGNiuYdzXhsSs6LOduSeA7+AFQrXuoZ4WDCJbwmGIAsHrGjQdFF1Z99D5rACQdQV2bNfYOc27btpTg0Fkazho0WMkbxM5BoT92ZWVzwcAnSCw5+05O97i6cEgshwOupjbrfr7DN61et6Ggj7uBoa1cg2Az1F9u78nm143VMfLXiIYRJbDIdLpGAYbEl442GM7HmsAIDIbDNUa77zWrZe/vEwwiLjhsMIW+s5WhYMXFnrsHVur/z0APlMVDNF2uZcKBpFf4SDiF2ePLu6ZKDhWw0GcYz0HAJauFbrgZ2HgrdHz27xcMIi0wyELCX2Nt0Xnbbh4ITHm9d7O67kuggT4XFE9sMVej7OtumaYrUMi8qLBINIOh8hY481VAXF3xmL2XhB4n2mm2C/9AQJ4S17xrsLABoG9PnS/38s12ssGg8i//5jFf3hv0IXem7Nh4AWCFwbV5+h8NgDfyxb32YDQ11inas9tMkiexvknNLxv8tH+1jiuxt7ejrM5ANC8b/1RQPwxx9m8vd9ndQxa8WipY6zX41tjLMnejsdx9zNphAnwubKa4BXz7papzofepmPQGt2DnfMKe3cu29uxdxzprgPw/maDYexnNnHG092CyJsGg0gaDnps56pC310zzIQCQQBA5HdI6OOowHfCwLv2u4JBxA0HkV5ARPuZ9dnYIhQAaDPhEAVEtEbvvy8YhgsColprx95xNQ/gu1Xh4BX7qDPw1i+FgsiHBMMwERB6fGYuOo7mAMDyugU9zkLCzuk9wTAE4SBSB4Qed0OAQACwQ9Q9rO6XQ0HkA4NhWAiI7FzVIWRhQFAA8HjFdzYgojmCIdMMiB3H1TwAZKJQiMbR+VOhIPIFwTAkASHSK/rduc45ABiiIhwW/uzc2VAQ+aJg0DaEROecNbMWwOerim/1qOnX+R2hIPKlwTAUASGy73HR7HoA36FTgLNu4d/kxmL+1cGgNUJCpF/gu+sAYMiKcXhuZyAMBEOgGRTDzFoAqJSF+YpAGAiGpsmgAIBLXBkIA8FwAmEB4GqPCAKLYAAAHPxUCwAA34VgAAAcEAwAgAOCAQBwQDAAAA4IBgDAAcEAADggGAAABwQDAOCAYAAAHBAMAICD/wOJkNfGLqBVggAAAABJRU5ErkJggg==\"\n          />\n          <path\n            d=\"M298.5,14H571V149H298.5a67.5,67.5,0,0,1,0-135Z\"\n            transform=\"translate(8.97 8.95)\"\n            :style=\"{\n              transition: `fill .3s var(--cubic-bezier-ease-in-out)`,\n              fill: 'var(--warning-color)',\n              fillRule: 'evenodd',\n            }\"\n          />\n        </g>\n        <g>\n          <image\n            width=\"142\"\n            height=\"77\"\n            transform=\"translate(69.89 44.75)\"\n            xlink:href=\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAI4AAABNCAYAAABwgVwSAAAACXBIWXMAAAsSAAALEgHS3X78AAAFzUlEQVR4Xu2c65KbMAxGxU7f/5GX/thqq3z5ZMkXSCA6M4xl2dCATkVme9n2fZei6OUr2lAUjBKnGKLEKYYocYohSpxiiBKnGKLEKYYocYohSpxiiBKnGOJPtOFMtm3boj2fzP5Gfz60veqzlCRreJVMp4rTIUt236eQKtKZEp0iTiBMJEm0fleiwrjrZwh0qDgNYVg+I0hmz5XJFIPtoecdKdBh4jjS2Fy07pHZc0UyhYikeVo/Sp5DxCHStISJ5l7uzkSCRPOHtSPkWSpOhzCZmM0/jawcmXipQMvESUqDo5djcy93J3o6DROktfYzWVTwo34AGAkSrVvuLovF3qsWWHNY8E2eBdnMiLmlLOk40G287tISpyUSxp9A9OphY2vNjku6zrQ4HdJgHMnDZLm7QK1XVSRNj0TT8kyJ0ylNNPfORe4qT680kTiHynPGdxw8WF5IrHyCPLs835PNoRSbiRXNWezepQyLE3QbjVsH2yMQ67xFtP6uYNFb6xlhPDk0r/t+Rdq2bRvtOsPiEDwZsoeQ2I4Zeva+gkgWi+0yVg4bt4RBlnafIXGcboOxzfUcArHO70D2PvA15XWbFrjPSvMbj3adIXEIWGRPBHt8BXvFjBjfGZTGCmNjPb6Da9icyKNAw8yKwwrLJMlIwwSyI8Z3xJPGCoN8ybM87Dnhq2pKoFlxEPzAKAJKk+k6Os+Q3fcqokKhNBpH3cbKg+cqU6Ig3eIEfyZlcygBHq2uI2TE+IpEn9/rBl7RrTD4vDyBdM9vbuR7Trc4BlZQW3iW7znw/E8Ai46vFwZ7Vuy1JE6+SxhlRhwEhWEysXFWnKtKNVQwgAm2Qaz7xOSnWSkOA2XSMXPgOXdjxT3Z57Osm2SYFYfdPCu6F9sck8Zef8WDvgK2U7A55lmXQZGYRFNizYqD4A16hUd5ECYY23MHWEE1b2OESeHFbD7FanEiWiJhh2FE61cEu4sH29cS5VCO+rfjPQXOdqlPo/Ucep5Lz940R4nTYz7utfOe69yN1nPoeS49e9Oc/arC9zZ7h7d+h2T3XYlsYXdz2ByLD2e1OFYGnLMY99vzxOzRmO25GyiDd587jK2YzaeYFYcVHqXYG7H3hQ7zp37xewNQip0cbJ3FdrRMPc9ZcSKsWCiPyOSH/8dVX1mte8+I0xIJ4+WsFAclEWl3mVVdZMU13o2sOK29GNs908yIg6Kw7yM2790owxPsqt0lCytyJE8klD2X5YfoFmff9x3+aoUVyOZEHouO47fwHwfg9ew8utF3Fyv6/Eqr6Pb4Jjm2H3nI9f6VCpEBcQJY0UUeBbLCfP9bw8Nep6fjdD+ANwOFwdE7rEACsbL02cyKYwuscWi4xN3Ge00tvfk3xZPHE6jVdexhr4dxN7PiKCiQxSt41G0+URoFC+xJE0mCOc1PMyQOfM9BafB1kv2gKAx7VUVEr7JXk70PkUcBdOwRCKHyjHy/ERkUx0GLnf0gVpSo27Sw69lf+x2IPisW2pOG5TyRol8zzbA4TtfRUXMMKwfL2WsIxCy37GG8EHYPKI6OvQKxa/wEg91GZEKcACsSy+OcvZ50xGv0dLUr0ZKHjUwWb76cqf/mRESi/3zAjhi39trRwnJ3olceHZk4rXOmuo3IAnFEuuTRMdrTij8BWxQWRx2oNU5LI7JIHJFQHsxF65ZPk0bBwrBXT0scXP8JFhX8rO84G8nZfRZ7jp3b3F1hRe0VyFtbyrKOI/LUdURyr57WK+nuokR40ozEy7qNyGJxlA6BMnMvd2d6Og+bHyaMcog4IlQekbZAXg7J7LkimUJEQj2tHyGNyIHiiLjyiJQ0HpliRPL8Tx5Y3EPFURoCicQyROt3JSqMu36kMMop4iiBQJbsvk8hVaQzhFFOFcfSIVHR4ExZLC8Th1EytXmVJIy3Eqe4Dkf92/Hi5pQ4xRAlTjFEiVMMUeIUQ5Q4xRAlTjFEiVMMUeIUQ5Q4xRB/AelwFo4tukdPAAAAAElFTkSuQmCC\"\n          />\n          <path\n            d=\"M99.43,58.8h65a13.49,13.49,0,0,1,13.5,13.5h0a13.49,13.49,0,0,1-13.5,13.5h-65a13.5,13.5,0,0,1-13.5-13.5h0A13.5,13.5,0,0,1,99.43,58.8Z\"\n            transform=\"translate(8.97 8.95)\"\n            :style=\"{\n              transition: `fill .3s var(--cubic-bezier-ease-in-out)`,\n              fill: 'var(--error-color)',\n              fillRule: 'evenodd',\n            }\"\n          />\n        </g>\n        <g>\n          <image\n            width=\"142\"\n            height=\"73\"\n            transform=\"translate(188.95 374.52)\"\n            xlink:href=\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAI4AAABJCAYAAADrEB4EAAAACXBIWXMAAAsSAAALEgHS3X78AAAFYElEQVR4Xu2b607zSgxFHXTe/5HJ+fHJsLtre5y5lHbiJUVz8wQSL5yowHGepxTFVb5aAUVhUeIUXZQ4RRclTtFFiVN0UeIUXZQ4RRclTtFFiVN08V8r4BUcx3G0Yopfzjf4uP/4i++hRJnLX4j0MnGSsmRi7kwzWa+SaLk4DWF61+5ElCB3bbVAy8QJhOH5rCDZuE8nmxCOM/etEmiJOI40ONda98jEfDKZZFgxOPe0vkKeqeJcFCZTeXYXpUVLEh6/TKBp4hjSZIQ5qEXuLo0SyZOR5mH/LHmmiJOUxmujPnIXkbyEtMTwWu5PkWfFB4AtUUYF2h2+bk3y4fRbnHItPsVwxaFqE8nREscSyRrfBe9dJtO2YoarzpA4ndJckQi5i0BWQloinHCI0bfaIXlWPKpEYlGiMe9ldpdHHyvWHK6hGBG4dyrd4jSqjfY9Sbw16xzIHcThMcqCrQoR7bHif0Q6juPorTrd4hh4goj8/vmGJ48lkI49dpEIE8fXhGsqiSeMcojIt9jn+pFmlC5xnGrDfZ475J9AGWm4bZGNexciWRCsMigM9vH4pnUE5376vVWnSxwDlsc6PGksgax2JzLXhAJw6yX6S/7JY/EkzQij4rAw2mYPlEmMvpK50TuhkmhfW5bHksS7V1yJhgQaFYfhbxolwXFUfcRold0FwqTq+JBnYZQveRQIhdOxMiQKc1mcxq8XcI5luXIItNzfGRRGx947C2LdM6tqKQ/n63nPuSwOYCUWE2/NZ4XivciuEvVWBxQERcFzRPPZr/PAiDiMl2CrzRy4B9lVHEaT2kquJYW3t3WuNDPFQSJpuG1Jcwd5+N0E56w1LyYjzxRGxbmSwIw8GMvjnfGkwTHHjUpyJfaJUXEs+CZYAnjVhIXxYnYkeqToNVsxljTW/m5JLFb+J+dIgr29I+d8d1Zc88jekJXijBju7R0557uz4ppH9oaseFRZz+eD+t6LX/Qs55id4Ws8nTmr5b41HmZUHE5qhCcNP4s1Fuf4wrNf81OwEusJgRJF8rS4EvvEqDgekSSeNEgUM/1F701oyWMdHBO1U5kpjiaax54s0QXxnjvA98MSIDq8Pcg0iUbEwaSyFN48rmcvwhJyd/AaW+JYa9Y5vPkuLotznudJv+jkxOqcyLMg3k8CgrLxO8/u1YfvC98vT56WUMzD3NVfcIp0iNOAJcJvCCXSP23EjwN0r/VYY4F2x/th4/439C25kKn3blQcFIWTbcUyKhALI9ROvegP4QzangPPwf3LjIqjsEAW3+J/4Kj7udpkpfm0R1jmmkR8abCPB1cgFgfPNUSXOPSew9JY7zsqAFcYq9pYjygLXJtyM/6I6HvnhEfS8DpjytPzfiPSKY4DCoIcYv+7hsLCYBzv2UUWD74mK9kZgaw1PMcwq/4FmPvZsc5hi0QVaAeiSsESeZJEY4G2u9qIzK04yCl29bHQWJHHqsN7s+f7dDLyWG1TlJkMVRyRsOpwG61ZrbJ7lfHgxGTk0bYVM1RtRCaII3JJnqiN+ncGE2T1r7bD0oiseVSdcu2xovFWH7mLSN596xWI+1OYUnFEnqqOSK6SeI8nb+6OWAlqyeFKM6PaiEwUR8SUR6QtjTf25u5EJI01DqvMLGlEJoujXBQommMyMZ9MJhktmZYKoywRR8SVRyRXaSyycZ9ONiFR5fmdXJTgZeIogUAisQx3EaVFlCB3bZUwynJxlIZASibmzjSTtVoY5WXiIEmJiiSvkgX5E3GYEukafyEK8xbiFJ/Hyv/kLDamxCm6KHGKLkqcoosSp+iixCm6KHGKLkqcoosSp+iixCm6KHGKLv4Hoce3hmt0vV8AAAAASUVORK5CYII=\"\n          />\n          <path\n            :style=\"{\n              transition: `fill .3s var(--cubic-bezier-ease-in-out)`,\n              fill: 'var(--success-color)',\n              fillRule: 'evenodd',\n            }\"\n            d=\"M216.5,388.57h69a11.5,11.5,0,0,1,11.5,11.5h0a11.5,11.5,0,0,1-11.5,11.5h-69a11.5,11.5,0,0,1-11.5-11.5h0A11.5,11.5,0,0,1,216.5,388.57Z\"\n            transform=\"translate(8.97 8.95)\"\n          />\n        </g>\n        <circle\n          fill-opacity=\"0.3\"\n          fill=\"#000000\"\n          filter=\"url(#filter-1)\"\n          transform=\"translate(106.010000, 376.700000) scale(-1, 1) translate(-106.010000, -376.700000) \"\n          cx=\"106.01\"\n          cy=\"376.7\"\n          r=\"20\"\n        />\n        <circle\n          cx=\"106.01\"\n          cy=\"376.7\"\n          r=\"22.5\"\n          :style=\"{\n            transition: `fill .3s var(--cubic-bezier-ease-in-out)`,\n            fill: 'var(--info-color)',\n            fillRule: 'evenodd',\n          }\"\n        />\n      </g>\n    </svg>\n  </n-el>\n</template>\n"
  },
  {
    "path": "demo/pages/home/index.vue",
    "content": "<script lang=\"ts\">\nimport { computed, defineComponent } from 'vue'\nimport { useThemeName } from '../../store'\nimport { i18n, useIsMobile, useIsTablet } from '../../utils/composables'\nimport LandingFooter from './Footer.vue'\nimport leftImage from './Left.vue'\nimport rightImage from './Right.vue'\n\nexport default defineComponent({\n  components: {\n    LandingFooter,\n    LeftImage: leftImage,\n    RightImage: rightImage\n  },\n  setup() {\n    const isMobileRef = useIsMobile()\n    return {\n      isMobile: isMobileRef,\n      isTablet: useIsTablet(),\n      theme: useThemeName(),\n      titleStyle: computed(() => {\n        if (isMobileRef.value) {\n          return 'margin-top: 0; font-size: 64px !important'\n        }\n        else {\n          return 'margin-top: 0; font-size: 80px !important'\n        }\n      }),\n      ...i18n({\n        'zh-CN': {\n          start: '开始使用',\n          intro1: '一个 Vue 3 组件库',\n          intro2: '比较完整，主题可调，使用 TypeScript，快',\n          intro3: '有点意思',\n          intro4: '换个主题'\n        },\n        'en-US': {\n          start: 'Get Started',\n          intro1: 'A Vue 3 Component Library',\n          intro2: 'Fairly Complete, Theme Customizable, Uses TypeScript, Fast',\n          intro3: 'Kinda Interesting',\n          intro4: 'Change Theme'\n        }\n      })\n    }\n  },\n  data() {\n    return {\n      hover: false,\n      themeOptions: {\n        dark: {\n          next: 'light'\n        },\n        light: {\n          next: 'dark'\n        }\n      }\n    }\n  },\n  methods: {\n    handleStartClick() {\n      this.$router.push(`${this.$route.path}/docs/installation`)\n    },\n    handleTitleMouseEnter() {\n      this.hover = true\n    },\n    handleTitleMouseLeave() {\n      this.hover = false\n    },\n    handleThemeChangeClick() {\n      this.theme = this.themeOptions[this.theme].next\n    }\n  }\n})\n</script>\n\n<template>\n  <n-layout\n    :native-scrollbar=\"false\"\n    :position=\"isMobile ? 'static' : 'absolute'\"\n    :style=\"isMobile ? undefined : 'top: var(--header-height);'\"\n  >\n    <div class=\"banner\" style=\"overflow: hidden\">\n      <RightImage v-if=\"!(isMobile || isTablet)\" class=\"right-image\" />\n      <n-h1 :style=\"titleStyle\" class=\"naive-title\">\n        <span\n          @mouseenter=\"handleTitleMouseEnter\"\n          @mouseleave=\"handleTitleMouseLeave\"\n        >Na{{ hover ? 'ï' : 'i' }}ve UI</span>\n      </n-h1>\n      <n-p style=\"font-size: 16px; margin-top: 0; margin-bottom: 0\">\n        {{ t('intro1') }}\n      </n-p>\n      <n-p\n        style=\"\n          font-size: 16px;\n          margin-bottom: 4px;\n          margin-top: 4px;\n          font-weight: 500;\n        \"\n      >\n        {{ t('intro2') }}\n      </n-p>\n      <n-p style=\"font-size: 16px; margin-top: 0\">\n        {{ t('intro3') }}\n      </n-p>\n      <div>\n        <n-button\n          type=\"default\"\n          size=\"large\"\n          style=\"margin-right: 12px\"\n          @click=\"handleThemeChangeClick\"\n        >\n          {{ t('intro4') }}\n        </n-button>\n        <n-button\n          type=\"primary\"\n          :ghost=\"theme === 'dark'\"\n          size=\"large\"\n          @click=\"handleStartClick\"\n        >\n          {{ t('start') }}\n        </n-button>\n      </div>\n      <LeftImage class=\"left-image\" />\n    </div>\n    <n-layout-footer>\n      <LandingFooter centered />\n    </n-layout-footer>\n  </n-layout>\n</template>\n\n<style scoped>\n.banner {\n  height: calc(100vh - 64px);\n  display: flex;\n  flex-direction: column;\n  position: relative;\n  text-align: center;\n  justify-content: center;\n}\n\n.banner::after {\n  content: '';\n  width: 100%;\n  height: 64px;\n}\n\n.naive-title {\n  line-height: 1;\n  font-family: Metropolis, sans-serif;\n  margin-bottom: 18px !important;\n}\n\n@media only screen and (max-width: 1920px) {\n  .left-image {\n    right: calc(50% + 270px);\n    width: calc(50% - 270px);\n    min-width: 440px;\n  }\n  .right-image {\n    left: calc(50% + 270px);\n    width: calc(50% - 270px);\n    min-width: 440px;\n  }\n}\n\n@media only screen and (min-width: 1920px) {\n  .left-image {\n    left: 0;\n    width: 700px;\n  }\n  .right-image {\n    right: 0;\n    width: 700px;\n  }\n}\n\n.left-image {\n  position: absolute;\n  top: 50%;\n  transform: translateY(-50%);\n}\n\n.right-image {\n  position: absolute;\n  top: 50%;\n  transform: translateY(-50%);\n}\n\n@media only screen and (max-width: 1023px) {\n  .banner {\n    position: static;\n    text-align: left;\n    padding-left: 16px;\n    transform: none;\n    padding-top: 60px;\n    padding-right: 16px;\n    min-height: 550px;\n    height: calc(100vh - 124px);\n  }\n  .left-image {\n    position: relative;\n    left: -16px;\n    min-width: unset;\n    width: 300px;\n    top: 8px;\n    transform: none;\n  }\n}\n</style>\n"
  },
  {
    "path": "demo/routes/router.js",
    "content": "import { nextTick } from 'vue'\nimport { createRouter, createWebHistory } from 'vue-router'\nimport { useLocaleName } from '../store'\n\nexport const loadingBarApiRef = {}\n\nexport default function createDemoRouter(app, routes) {\n  const router = createRouter({\n    history: createWebHistory(),\n    routes\n  })\n\n  router.beforeEach((to, from, next) => {\n    if (!from || to.path !== from.path) {\n      if (loadingBarApiRef.value) {\n        loadingBarApiRef.value.start()\n      }\n    }\n    next()\n  })\n\n  router.afterEach((to, from) => {\n    if (!from || to.path !== from.path) {\n      if (loadingBarApiRef.value) {\n        loadingBarApiRef.value.finish()\n      }\n      if (to.hash && to.hash !== from.hash) {\n        nextTick(() => {\n          const el = document.querySelector(to.hash)\n          if (el)\n            el.scrollIntoView()\n        })\n      }\n      nextTick(() => {\n        const h1s = document.getElementsByTagName('h1')\n        if (to.name !== 'home' && h1s.length !== 0) {\n          document.title = `${h1s[0].textContent} - Naive UI`\n        }\n        else {\n          // defined in index.html\n          window.deriveTitleFromLocale(useLocaleName().value)\n        }\n      })\n    }\n  })\n\n  return router\n}\n"
  },
  {
    "path": "demo/routes/routes.js",
    "content": "export const enDocRoutes = [\n  // basic docs\n  {\n    path: 'introduction',\n    component: () => import('../pages/docs/introduction/enUS/index.md')\n  },\n  {\n    path: 'installation',\n    component: () => import('../pages/docs/installation/enUS/index.md')\n  },\n  {\n    path: 'usage-sfc',\n    component: () => import('../pages/docs/usage-sfc/enUS/index.md')\n  },\n  {\n    path: 'supported-platforms',\n    component: () => import('../pages/docs/supported-platforms/enUS/index.md')\n  },\n  // {\n  //   path: 'from-v1',\n  //   component: () => import('../pages/docs/vue3/enUS/index.vue')\n  // },\n  // {\n  //   path: 'experimental-features',\n  //   component: () => import('../pages/docs/experimental-features/enUS/index.md')\n  // },\n  {\n    path: 'customize-theme',\n    component: () => import('../pages/docs/customize-theme/enUS/index.md')\n  },\n  {\n    path: 'community',\n    component: () => import('../pages/docs/community/enUS/index.md')\n  },\n  {\n    path: 'i18n',\n    component: () => import('../pages/docs/i18n/enUS/index.md')\n  },\n  {\n    path: 'changelog',\n    component: () => import('../pages/docs/changelog/enUS/index.vue')\n  },\n  {\n    path: 'theme',\n    component: () => import('../pages/docs/theme/enUS/index.demo-entry.md')\n  },\n  {\n    path: 'jsx',\n    component: () => import('../pages/docs/jsx/enUS/index.md')\n  },\n  {\n    path: 'ssr',\n    component: () => import('../pages/docs/ssr/enUS/index.md')\n  },\n  {\n    path: 'nuxtjs',\n    component: () => import('../pages/docs/nuxtjs/enUS/index.md')\n  },\n  {\n    path: 'vitepress',\n    component: () => import('../pages/docs/vitepress/enUS/index.md')\n  },\n  {\n    path: 'vite-ssge',\n    component: () => import('../pages/docs/vite-ssge/enUS/index.md')\n  },\n  {\n    path: 'common-issues',\n    component: () => import('../pages/docs/common-issues/enUS/index.md')\n  },\n  {\n    path: 'fonts',\n    component: () => import('../pages/docs/fonts/enUS/index.md')\n  },\n  {\n    path: 'import-on-demand',\n    component: () => import('../pages/docs/import-on-demand/enUS/index.md')\n  },\n  {\n    path: 'style-conflict',\n    component: () => import('../pages/docs/style-conflict/enUS/index.md')\n  },\n  {\n    path: 'controlled-uncontrolled',\n    component: () =>\n      import('../pages/docs/controlled-uncontrolled/enUS/index.md')\n  },\n  {\n    path: 'umd',\n    component: () => import('../pages/docs/umd/enUS/index.md')\n  }\n]\n\nexport const zhDocRoutes = [\n  // basic docs\n  {\n    path: 'introduction',\n    component: () => import('../pages/docs/introduction/zhCN/index.md')\n  },\n  {\n    path: 'installation',\n    component: () => import('../pages/docs/installation/zhCN/index.md')\n  },\n  {\n    path: 'usage-sfc',\n    component: () => import('../pages/docs/usage-sfc/zhCN/index.md')\n  },\n  {\n    path: 'supported-platforms',\n    component: () => import('../pages/docs/supported-platforms/zhCN/index.md')\n  },\n  {\n    path: 'from-v1',\n    component: () => import('../pages/docs/vue3/zhCN/index.vue')\n  },\n  {\n    path: 'customize-theme',\n    component: () => import('../pages/docs/customize-theme/zhCN/index.md')\n  },\n  {\n    path: 'community',\n    component: () => import('../pages/docs/community/zhCN/index.md')\n  },\n  {\n    path: 'i18n',\n    component: () => import('../pages/docs/i18n/zhCN/index.md')\n  },\n  // {\n  //   path: 'experimental-features',\n  //   component: () => import('../pages/docs/experimental-features/zhCN/index.md')\n  // },\n  {\n    path: 'changelog',\n    component: () => import('../pages/docs/changelog/zhCN/index.vue')\n  },\n  {\n    path: 'theme',\n    component: () => import('../pages/docs/theme/zhCN/index.demo-entry.md')\n  },\n  {\n    path: 'jsx',\n    component: () => import('../pages/docs/jsx/zhCN/index.md')\n  },\n  {\n    path: 'ssr',\n    component: () => import('../pages/docs/ssr/zhCN/index.md')\n  },\n  {\n    path: 'nuxtjs',\n    component: () => import('../pages/docs/nuxtjs/zhCN/index.md')\n  },\n  {\n    path: 'vitepress',\n    component: () => import('../pages/docs/vitepress/zhCN/index.md')\n  },\n  {\n    path: 'vite-ssge',\n    component: () => import('../pages/docs/vite-ssge/zhCN/index.md')\n  },\n  {\n    path: 'common-issues',\n    component: () => import('../pages/docs/common-issues/zhCN/index.md')\n  },\n  {\n    path: 'fonts',\n    component: () => import('../pages/docs/fonts/zhCN/index.md')\n  },\n  {\n    path: 'import-on-demand',\n    component: () => import('../pages/docs/import-on-demand/zhCN/index.md')\n  },\n  {\n    path: 'style-conflict',\n    component: () => import('../pages/docs/style-conflict/zhCN/index.md')\n  },\n  {\n    path: 'controlled-uncontrolled',\n    component: () =>\n      import('../pages/docs/controlled-uncontrolled/zhCN/index.md')\n  },\n  {\n    path: 'umd',\n    component: () => import('../pages/docs/umd/zhCN/index.md')\n  }\n]\n\nexport const enComponentRoutes = [\n  // components\n  {\n    path: 'layout',\n    component: () => import('../../src/layout/demos/enUS/index.demo-entry.md')\n  },\n  {\n    path: 'gradient-text',\n    component: () =>\n      import('../../src/gradient-text/demos/enUS/index.demo-entry.md')\n  },\n  {\n    path: 'icon',\n    component: () => import('../../src/icon/demos/enUS/index.demo-entry.md')\n  },\n  {\n    path: 'checkbox',\n    component: () => import('../../src/checkbox/demos/enUS/index.demo-entry.md')\n  },\n  {\n    path: 'button',\n    component: () => import('../../src/button/demos/enUS/index.demo-entry.md')\n  },\n  {\n    path: 'switch',\n    component: () => import('../../src/switch/demos/enUS/index.demo-entry.md')\n  },\n  {\n    path: 'data-table',\n    component: () =>\n      import('../../src/data-table/demos/enUS/index.demo-entry.md')\n  },\n  {\n    path: 'input',\n    component: () => import('../../src/input/demos/enUS/index.demo-entry.md')\n  },\n  {\n    path: 'input-otp',\n    component: () =>\n      import('../../src/input-otp/demos/enUS/index.demo-entry.md')\n  },\n  {\n    path: 'select',\n    component: () => import('../../src/select/demos/enUS/index.demo-entry.md')\n  },\n  {\n    path: 'cascader',\n    component: () => import('../../src/cascader/demos/enUS/index.demo-entry.md')\n  },\n  {\n    path: 'dynamic-input',\n    component: () =>\n      import('../../src/dynamic-input/demos/enUS/index.demo-entry.md')\n  },\n  {\n    path: 'modal',\n    component: () => import('../../src/modal/demos/enUS/index.demo-entry.md')\n  },\n  {\n    path: 'message',\n    component: () => import('../../src/message/demos/enUS/index.demo-entry.md')\n  },\n  {\n    path: 'tooltip',\n    component: () => import('../../src/tooltip/demos/enUS/index.demo-entry.md')\n  },\n  {\n    path: 'popover',\n    component: () => import('../../src/popover/demos/enUS/index.demo-entry.md')\n  },\n  {\n    path: 'notification',\n    component: () =>\n      import('../../src/notification/demos/enUS/index.demo-entry.md')\n  },\n  {\n    path: 'pagination',\n    component: () =>\n      import('../../src/pagination/demos/enUS/index.demo-entry.md')\n  },\n  {\n    path: 'alert',\n    component: () => import('../../src/alert/demos/enUS/index.demo-entry.md')\n  },\n  {\n    path: 'date-picker',\n    component: () =>\n      import('../../src/date-picker/demos/enUS/index.demo-entry.md')\n  },\n  {\n    path: 'input-number',\n    component: () =>\n      import('../../src/input-number/demos/enUS/index.demo-entry.md')\n  },\n  {\n    path: 'radio',\n    component: () => import('../../src/radio/demos/enUS/index.demo-entry.md')\n  },\n  {\n    path: 'form',\n    component: () => import('../../src/form/demos/enUS/index.demo-entry.md')\n  },\n  {\n    path: 'tabs',\n    component: () => import('../../src/tabs/demos/enUS/index.demo-entry.md')\n  },\n  {\n    path: 'time-picker',\n    component: () =>\n      import('../../src/time-picker/demos/enUS/index.demo-entry.md')\n  },\n  {\n    path: 'dialog',\n    component: () => import('../../src/dialog/demos/enUS/index.demo-entry.md')\n  },\n  {\n    path: 'badge',\n    component: () => import('../../src/badge/demos/enUS/index.demo-entry.md')\n  },\n  {\n    path: 'steps',\n    component: () => import('../../src/steps/demos/enUS/index.demo-entry.md')\n  },\n  {\n    path: 'collapse',\n    component: () => import('../../src/collapse/demos/enUS/index.demo-entry.md')\n  },\n  {\n    path: 'progress',\n    component: () => import('../../src/progress/demos/enUS/index.demo-entry.md')\n  },\n  {\n    path: 'tag',\n    component: () => import('../../src/tag/demos/enUS/index.demo-entry.md')\n  },\n  {\n    path: 'menu',\n    component: () => import('../../src/menu/demos/enUS/index.demo-entry.md')\n  },\n  {\n    path: 'timeline',\n    component: () => import('../../src/timeline/demos/enUS/index.demo-entry.md')\n  },\n  {\n    path: 'back-top',\n    component: () => import('../../src/back-top/demos/enUS/index.demo-entry.md')\n  },\n  {\n    path: 'divider',\n    component: () => import('../../src/divider/demos/enUS/index.demo-entry.md')\n  },\n  {\n    path: 'popconfirm',\n    component: () =>\n      import('../../src/popconfirm/demos/enUS/index.demo-entry.md')\n  },\n  {\n    path: 'anchor',\n    component: () => import('../../src/anchor/demos/enUS/index.demo-entry.md')\n  },\n  {\n    path: 'dropdown',\n    component: () => import('../../src/dropdown/demos/enUS/index.demo-entry.md')\n  },\n  {\n    path: 'popselect',\n    component: () =>\n      import('../../src/popselect/demos/enUS/index.demo-entry.md')\n  },\n  {\n    path: 'config-provider',\n    component: () =>\n      import('../../src/config-provider/demos/enUS/index.demo-entry.md')\n  },\n  {\n    path: 'transfer',\n    component: () => import('../../src/transfer/demos/enUS/index.demo-entry.md')\n  },\n  {\n    path: 'legacy-transfer',\n    component: () =>\n      import('../../src/legacy-transfer/demos/enUS/index.demo-entry.md')\n  },\n  {\n    path: 'spin',\n    component: () => import('../../src/spin/demos/enUS/index.demo-entry.md')\n  },\n  {\n    path: 'drawer',\n    component: () => import('../../src/drawer/demos/enUS/index.demo-entry.md')\n  },\n  {\n    path: 'loading-bar',\n    component: () =>\n      import('../../src/loading-bar/demos/enUS/index.demo-entry.md')\n  },\n  {\n    path: 'time',\n    component: () => import('../../src/time/demos/enUS/index.demo-entry.md')\n  },\n  {\n    path: 'slider',\n    component: () => import('../../src/slider/demos/enUS/index.demo-entry.md')\n  },\n  {\n    path: 'tree',\n    component: () => import('../../src/tree/demos/enUS/index.demo-entry.md')\n  },\n  {\n    path: 'affix',\n    component: () => import('../../src/affix/demos/enUS/index.demo-entry.md')\n  },\n  {\n    path: 'statistic',\n    component: () =>\n      import('../../src/statistic/demos/enUS/index.demo-entry.md')\n  },\n  {\n    path: 'legacy-grid',\n    component: () =>\n      import('../../src/legacy-grid/demos/enUS/index.demo-entry.md')\n  },\n  {\n    path: 'grid',\n    component: () => import('../../src/grid/demos/enUS/index.demo-entry.md')\n  },\n  {\n    path: 'breadcrumb',\n    component: () =>\n      import('../../src/breadcrumb/demos/enUS/index.demo-entry.md')\n  },\n  {\n    path: 'descriptions',\n    component: () =>\n      import('../../src/descriptions/demos/enUS/index.demo-entry.md')\n  },\n  {\n    path: 'list',\n    component: () => import('../../src/list/demos/enUS/index.demo-entry.md')\n  },\n  {\n    path: 'card',\n    component: () => import('../../src/card/demos/enUS/index.demo-entry.md')\n  },\n  {\n    path: 'avatar',\n    component: () => import('../../src/avatar/demos/enUS/index.demo-entry.md')\n  },\n  {\n    path: 'result',\n    component: () => import('../../src/result/demos/enUS/index.demo-entry.md')\n  },\n  {\n    path: 'thing',\n    component: () => import('../../src/thing/demos/enUS/index.demo-entry.md')\n  },\n  {\n    path: 'auto-complete',\n    component: () =>\n      import('../../src/auto-complete/demos/enUS/index.demo-entry.md')\n  },\n  {\n    path: 'empty',\n    component: () => import('../../src/empty/demos/enUS/index.demo-entry.md')\n  },\n  {\n    path: 'element',\n    component: () => import('../../src/element/demos/enUS/index.demo-entry.md')\n  },\n  {\n    path: 'log',\n    component: () => import('../../src/log/demos/enUS/index.demo-entry.md')\n  },\n  {\n    path: 'code',\n    component: () => import('../../src/code/demos/enUS/index.demo-entry.md')\n  },\n  {\n    path: 'typography',\n    component: () =>\n      import('../../src/typography/demos/enUS/index.demo-entry.md')\n  },\n  {\n    path: 'upload',\n    component: () => import('../../src/upload/demos/enUS/index.demo-entry.md')\n  },\n  {\n    path: 'table',\n    component: () => import('../../src/table/demos/enUS/index.demo-entry.md')\n  },\n  {\n    path: 'space',\n    component: () => import('../../src/space/demos/enUS/index.demo-entry.md')\n  },\n  {\n    path: 'flex',\n    component: () => import('../../src/flex/demos/enUS/index.demo-entry.md')\n  },\n  {\n    path: 'rate',\n    component: () => import('../../src/rate/demos/enUS/index.demo-entry.md')\n  },\n  {\n    path: 'dynamic-tags',\n    component: () =>\n      import('../../src/dynamic-tags/demos/enUS/index.demo-entry.md')\n  },\n  {\n    path: 'ellipsis',\n    component: () => import('../../src/ellipsis/demos/enUS/index.demo-entry.md')\n  },\n  {\n    path: 'mention',\n    component: () => import('../../src/mention/demos/enUS/index.demo-entry.md')\n  },\n  {\n    path: 'page-header',\n    component: () =>\n      import('../../src/page-header/demos/enUS/index.demo-entry.md')\n  },\n  {\n    path: 'global-style',\n    component: () =>\n      import('../../src/global-style/demos/enUS/index.demo-entry.md')\n  },\n  {\n    path: 'image',\n    component: () => import('../../src/image/demos/enUS/index.demo-entry.md')\n  },\n  {\n    path: 'skeleton',\n    component: () => import('../../src/skeleton/demos/enUS/index.demo-entry.md')\n  },\n  {\n    path: 'calendar',\n    component: () => import('../../src/calendar/demos/enUS/index.demo-entry.md')\n  },\n  {\n    path: 'color-picker',\n    component: () =>\n      import('../../src/color-picker/demos/enUS/index.demo-entry.md')\n  },\n  {\n    path: 'tree-select',\n    component: () =>\n      import('../../src/tree-select/demos/enUS/index.demo-entry.md')\n  },\n  {\n    path: 'carousel',\n    component: () => import('../../src/carousel/demos/enUS/index.demo-entry.md')\n  },\n  {\n    path: 'collapse-transition',\n    component: () =>\n      import('../../src/collapse-transition/demos/enUS/index.demo-entry.md')\n  },\n  {\n    path: 'scrollbar',\n    component: () =>\n      import('../../src/scrollbar/demos/enUS/index.demo-entry.md')\n  },\n  {\n    path: 'countdown',\n    component: () =>\n      import('../../src/countdown/demos/enUS/index.demo-entry.md')\n  },\n  {\n    path: 'number-animation',\n    component: () =>\n      import('../../src/number-animation/demos/enUS/index.demo-entry.md')\n  },\n  {\n    path: 'watermark',\n    component: () =>\n      import('../../src/watermark/demos/enUS/index.demo-entry.md')\n  },\n  {\n    path: 'discrete',\n    component: () => import('../../src/discrete/demos/enUS/index.demo-entry.md')\n  },\n  {\n    path: 'equation',\n    component: () => import('../../src/equation/demos/enUS/index.demo-entry.md')\n  },\n  {\n    path: 'qr-code',\n    component: () => import('../../src/qr-code/demos/enUS/index.demo-entry.md')\n  },\n  {\n    path: 'virtual-list',\n    component: () =>\n      import('../../src/virtual-list/demos/enUS/index.demo-entry.md')\n  },\n  {\n    path: 'split',\n    component: () => import('../../src/split/demos/enUS/index.demo-entry.md')\n  },\n  {\n    path: 'infinite-scroll',\n    component: () =>\n      import('../../src/infinite-scroll/demos/enUS/index.demo-entry.md')\n  },\n  {\n    path: 'float-button',\n    component: () =>\n      import('../../src/float-button/demos/enUS/index.demo-entry.md')\n  },\n  {\n    path: 'highlight',\n    component: () =>\n      import('../../src/highlight/demos/enUS/index.demo-entry.md')\n  },\n  {\n    path: 'marquee',\n    component: () => import('../../src/marquee/demos/enUS/index.demo-entry.md')\n  },\n  {\n    path: 'heatmap',\n    component: () => import('../../src/heatmap/demos/enUS/index.demo-entry.md')\n  }\n]\n\nexport const zhComponentRoutes = [\n  // components\n  {\n    path: 'layout',\n    component: () => import('../../src/layout/demos/zhCN/index.demo-entry.md')\n  },\n  {\n    path: 'gradient-text',\n    component: () =>\n      import('../../src/gradient-text/demos/zhCN/index.demo-entry.md')\n  },\n  {\n    path: 'icon',\n    component: () => import('../../src/icon/demos/zhCN/index.demo-entry.md')\n  },\n  {\n    path: 'checkbox',\n    component: () => import('../../src/checkbox/demos/zhCN/index.demo-entry.md')\n  },\n  {\n    path: 'button',\n    component: () => import('../../src/button/demos/zhCN/index.demo-entry.md')\n  },\n  {\n    path: 'switch',\n    component: () => import('../../src/switch/demos/zhCN/index.demo-entry.md')\n  },\n  {\n    path: 'data-table',\n    component: () =>\n      import('../../src/data-table/demos/zhCN/index.demo-entry.md')\n  },\n  {\n    path: 'input',\n    component: () => import('../../src/input/demos/zhCN/index.demo-entry.md')\n  },\n  {\n    path: 'input-otp',\n    component: () =>\n      import('../../src/input-otp/demos/zhCN/index.demo-entry.md')\n  },\n  {\n    path: 'select',\n    component: () => import('../../src/select/demos/zhCN/index.demo-entry.md')\n  },\n  {\n    path: 'cascader',\n    component: () => import('../../src/cascader/demos/zhCN/index.demo-entry.md')\n  },\n  {\n    path: 'dynamic-input',\n    component: () =>\n      import('../../src/dynamic-input/demos/zhCN/index.demo-entry.md')\n  },\n  {\n    path: 'modal',\n    component: () => import('../../src/modal/demos/zhCN/index.demo-entry.md')\n  },\n  {\n    path: 'message',\n    component: () => import('../../src/message/demos/zhCN/index.demo-entry.md')\n  },\n  {\n    path: 'tooltip',\n    component: () => import('../../src/tooltip/demos/zhCN/index.demo-entry.md')\n  },\n  {\n    path: 'popover',\n    component: () => import('../../src/popover/demos/zhCN/index.demo-entry.md')\n  },\n  {\n    path: 'notification',\n    component: () =>\n      import('../../src/notification/demos/zhCN/index.demo-entry.md')\n  },\n  {\n    path: 'pagination',\n    component: () =>\n      import('../../src/pagination/demos/zhCN/index.demo-entry.md')\n  },\n  {\n    path: 'alert',\n    component: () => import('../../src/alert/demos/zhCN/index.demo-entry.md')\n  },\n  {\n    path: 'date-picker',\n    component: () =>\n      import('../../src/date-picker/demos/zhCN/index.demo-entry.md')\n  },\n  {\n    path: 'input-number',\n    component: () =>\n      import('../../src/input-number/demos/zhCN/index.demo-entry.md')\n  },\n  {\n    path: 'radio',\n    component: () => import('../../src/radio/demos/zhCN/index.demo-entry.md')\n  },\n  {\n    path: 'form',\n    component: () => import('../../src/form/demos/zhCN/index.demo-entry.md')\n  },\n  {\n    path: 'tabs',\n    component: () => import('../../src/tabs/demos/zhCN/index.demo-entry.md')\n  },\n  {\n    path: 'time-picker',\n    component: () =>\n      import('../../src/time-picker/demos/zhCN/index.demo-entry.md')\n  },\n  {\n    path: 'dialog',\n    component: () => import('../../src/dialog/demos/zhCN/index.demo-entry.md')\n  },\n  {\n    path: 'badge',\n    component: () => import('../../src/badge/demos/zhCN/index.demo-entry.md')\n  },\n  {\n    path: 'steps',\n    component: () => import('../../src/steps/demos/zhCN/index.demo-entry.md')\n  },\n  {\n    path: 'collapse',\n    component: () => import('../../src/collapse/demos/zhCN/index.demo-entry.md')\n  },\n  {\n    path: 'progress',\n    component: () => import('../../src/progress/demos/zhCN/index.demo-entry.md')\n  },\n  {\n    path: 'tag',\n    component: () => import('../../src/tag/demos/zhCN/index.demo-entry.md')\n  },\n  {\n    path: 'menu',\n    component: () => import('../../src/menu/demos/zhCN/index.demo-entry.md')\n  },\n  {\n    path: 'timeline',\n    component: () => import('../../src/timeline/demos/zhCN/index.demo-entry.md')\n  },\n  {\n    path: 'back-top',\n    component: () => import('../../src/back-top/demos/zhCN/index.demo-entry.md')\n  },\n  {\n    path: 'divider',\n    component: () => import('../../src/divider/demos/zhCN/index.demo-entry.md')\n  },\n  {\n    path: 'popconfirm',\n    component: () =>\n      import('../../src/popconfirm/demos/zhCN/index.demo-entry.md')\n  },\n  {\n    path: 'anchor',\n    component: () => import('../../src/anchor/demos/zhCN/index.demo-entry.md')\n  },\n  {\n    path: 'dropdown',\n    component: () => import('../../src/dropdown/demos/zhCN/index.demo-entry.md')\n  },\n  {\n    path: 'popselect',\n    component: () =>\n      import('../../src/popselect/demos/zhCN/index.demo-entry.md')\n  },\n  {\n    path: 'config-provider',\n    component: () =>\n      import('../../src/config-provider/demos/zhCN/index.demo-entry.md')\n  },\n  {\n    path: 'transfer',\n    component: () => import('../../src/transfer/demos/zhCN/index.demo-entry.md')\n  },\n  {\n    path: 'legacy-transfer',\n    component: () =>\n      import('../../src/legacy-transfer/demos/zhCN/index.demo-entry.md')\n  },\n  {\n    path: 'spin',\n    component: () => import('../../src/spin/demos/zhCN/index.demo-entry.md')\n  },\n  {\n    path: 'drawer',\n    component: () => import('../../src/drawer/demos/zhCN/index.demo-entry.md')\n  },\n  {\n    path: 'loading-bar',\n    component: () =>\n      import('../../src/loading-bar/demos/zhCN/index.demo-entry.md')\n  },\n  {\n    path: 'time',\n    component: () => import('../../src/time/demos/zhCN/index.demo-entry.md')\n  },\n  {\n    path: 'slider',\n    component: () => import('../../src/slider/demos/zhCN/index.demo-entry.md')\n  },\n  {\n    path: 'tree',\n    component: () => import('../../src/tree/demos/zhCN/index.demo-entry.md')\n  },\n  {\n    path: 'affix',\n    component: () => import('../../src/affix/demos/zhCN/index.demo-entry.md')\n  },\n  {\n    path: 'statistic',\n    component: () =>\n      import('../../src/statistic/demos/zhCN/index.demo-entry.md')\n  },\n  {\n    path: 'legacy-grid',\n    component: () =>\n      import('../../src/legacy-grid/demos/zhCN/index.demo-entry.md')\n  },\n  {\n    path: 'grid',\n    component: () => import('../../src/grid/demos/zhCN/index.demo-entry.md')\n  },\n  {\n    path: 'breadcrumb',\n    component: () =>\n      import('../../src/breadcrumb/demos/zhCN/index.demo-entry.md')\n  },\n  {\n    path: 'descriptions',\n    component: () =>\n      import('../../src/descriptions/demos/zhCN/index.demo-entry.md')\n  },\n  {\n    path: 'list',\n    component: () => import('../../src/list/demos/zhCN/index.demo-entry.md')\n  },\n  {\n    path: 'card',\n    component: () => import('../../src/card/demos/zhCN/index.demo-entry.md')\n  },\n  {\n    path: 'avatar',\n    component: () => import('../../src/avatar/demos/zhCN/index.demo-entry.md')\n  },\n  {\n    path: 'result',\n    component: () => import('../../src/result/demos/zhCN/index.demo-entry.md')\n  },\n  {\n    path: 'thing',\n    component: () => import('../../src/thing/demos/zhCN/index.demo-entry.md')\n  },\n  {\n    path: 'auto-complete',\n    component: () =>\n      import('../../src/auto-complete/demos/zhCN/index.demo-entry.md')\n  },\n  {\n    path: 'empty',\n    component: () => import('../../src/empty/demos/zhCN/index.demo-entry.md')\n  },\n  {\n    path: 'element',\n    component: () => import('../../src/element/demos/zhCN/index.demo-entry.md')\n  },\n  {\n    path: 'log',\n    component: () => import('../../src/log/demos/zhCN/index.demo-entry.md')\n  },\n  {\n    path: 'code',\n    component: () => import('../../src/code/demos/zhCN/index.demo-entry.md')\n  },\n  {\n    path: 'typography',\n    component: () =>\n      import('../../src/typography/demos/zhCN/index.demo-entry.md')\n  },\n  {\n    path: 'upload',\n    component: () => import('../../src/upload/demos/zhCN/index.demo-entry.md')\n  },\n  {\n    path: 'table',\n    component: () => import('../../src/table/demos/zhCN/index.demo-entry.md')\n  },\n  {\n    path: 'space',\n    component: () => import('../../src/space/demos/zhCN/index.demo-entry.md')\n  },\n  {\n    path: 'flex',\n    component: () => import('../../src/flex/demos/zhCN/index.demo-entry.md')\n  },\n  {\n    path: 'rate',\n    component: () => import('../../src/rate/demos/zhCN/index.demo-entry.md')\n  },\n  {\n    path: 'dynamic-tags',\n    component: () =>\n      import('../../src/dynamic-tags/demos/zhCN/index.demo-entry.md')\n  },\n  {\n    path: 'ellipsis',\n    component: () => import('../../src/ellipsis/demos/zhCN/index.demo-entry.md')\n  },\n  {\n    path: 'mention',\n    component: () => import('../../src/mention/demos/zhCN/index.demo-entry.md')\n  },\n  {\n    path: 'page-header',\n    component: () =>\n      import('../../src/page-header/demos/zhCN/index.demo-entry.md')\n  },\n  {\n    path: 'global-style',\n    component: () =>\n      import('../../src/global-style/demos/zhCN/index.demo-entry.md')\n  },\n  {\n    path: 'image',\n    component: () => import('../../src/image/demos/zhCN/index.demo-entry.md')\n  },\n  {\n    path: 'skeleton',\n    component: () => import('../../src/skeleton/demos/zhCN/index.demo-entry.md')\n  },\n  {\n    path: 'calendar',\n    component: () => import('../../src/calendar/demos/zhCN/index.demo-entry.md')\n  },\n  {\n    path: 'color-picker',\n    component: () =>\n      import('../../src/color-picker/demos/zhCN/index.demo-entry.md')\n  },\n  {\n    path: 'tree-select',\n    component: () =>\n      import('../../src/tree-select/demos/zhCN/index.demo-entry.md')\n  },\n  {\n    path: 'carousel',\n    component: () => import('../../src/carousel/demos/zhCN/index.demo-entry.md')\n  },\n  {\n    path: 'collapse-transition',\n    component: () =>\n      import('../../src/collapse-transition/demos/zhCN/index.demo-entry.md')\n  },\n  {\n    path: 'scrollbar',\n    component: () =>\n      import('../../src/scrollbar/demos/zhCN/index.demo-entry.md')\n  },\n  {\n    path: 'countdown',\n    component: () =>\n      import('../../src/countdown/demos/zhCN/index.demo-entry.md')\n  },\n  {\n    path: 'number-animation',\n    component: () =>\n      import('../../src/number-animation/demos/zhCN/index.demo-entry.md')\n  },\n  {\n    path: 'watermark',\n    component: () =>\n      import('../../src/watermark/demos/zhCN/index.demo-entry.md')\n  },\n  {\n    path: 'discrete',\n    component: () => import('../../src/discrete/demos/zhCN/index.demo-entry.md')\n  },\n  {\n    path: 'equation',\n    component: () => import('../../src/equation/demos/zhCN/index.demo-entry.md')\n  },\n  {\n    path: 'qr-code',\n    component: () => import('../../src/qr-code/demos/zhCN/index.demo-entry.md')\n  },\n  {\n    path: 'virtual-list',\n    component: () =>\n      import('../../src/virtual-list/demos/zhCN/index.demo-entry.md')\n  },\n  {\n    path: 'split',\n    component: () => import('../../src/split/demos/zhCN/index.demo-entry.md')\n  },\n  {\n    path: 'infinite-scroll',\n    component: () =>\n      import('../../src/infinite-scroll/demos/zhCN/index.demo-entry.md')\n  },\n  {\n    path: 'float-button',\n    component: () =>\n      import('../../src/float-button/demos/zhCN/index.demo-entry.md')\n  },\n  {\n    path: 'highlight',\n    component: () =>\n      import('../../src/highlight/demos/zhCN/index.demo-entry.md')\n  },\n  {\n    path: 'marquee',\n    component: () => import('../../src/marquee/demos/zhCN/index.demo-entry.md')\n  },\n  {\n    path: 'heatmap',\n    component: () => import('../../src/heatmap/demos/zhCN/index.demo-entry.md')\n  }\n]\n\nexport const routes = [\n  {\n    name: 'home',\n    path: '/:lang/:theme',\n    component: () => import('../pages/home/index.vue')\n  },\n  {\n    name: 'enDocs',\n    path: '/en-US/:theme/docs',\n    component: () => import('../pages/Layout.vue'),\n    children: enDocRoutes\n  },\n  {\n    name: 'zhDocs',\n    path: '/zh-CN/:theme/docs',\n    component: () => import('../pages/Layout.vue'),\n    children: zhDocRoutes\n  },\n  {\n    name: 'enComponents',\n    path: '/en-US/:theme/components',\n    component: () => import('../pages/Layout.vue'),\n    children: enComponentRoutes\n  },\n  {\n    name: 'zhComponents',\n    path: '/zh-CN/:theme/components',\n    component: () => import('../pages/Layout.vue'),\n    children: zhComponentRoutes\n  },\n  {\n    name: 'not-found',\n    path: '/:pathMatch(.*)*',\n    redirect: {\n      name: 'home',\n      params: {\n        lang: navigator.language === 'zh-CN' ? 'zh-CN' : 'en-US',\n        theme: 'os-theme'\n      }\n    }\n  }\n]\n"
  },
  {
    "path": "demo/setup.js",
    "content": "import ComponentDemo from './utils/ComponentDemo.vue'\nimport ComponentDemos from './utils/ComponentDemos'\nimport EditOnGithubHeader from './utils/EditOnGithubHeader.vue'\nimport './styles/demo.css'\nimport 'vfonts/Inter.css'\nimport 'vfonts/FiraCode.css'\nimport 'katex/dist/katex.css'\n\nexport function installDemoComponents(app) {\n  app.component('ComponentDemo', ComponentDemo)\n  app.component('ComponentDemos', ComponentDemos)\n  app.component('EditOnGithubHeader', EditOnGithubHeader)\n}\n"
  },
  {
    "path": "demo/store/hljs.js",
    "content": "import hljs from 'highlight.js/lib/core'\nimport cpp from 'highlight.js/lib/languages/cpp'\nimport javascript from 'highlight.js/lib/languages/javascript'\nimport python from 'highlight.js/lib/languages/python'\nimport xml from 'highlight.js/lib/languages/xml'\n\nhljs.registerLanguage('javascript', javascript)\nhljs.registerLanguage('python', python)\nhljs.registerLanguage('cpp', cpp)\nhljs.registerLanguage('html', xml)\nhljs.registerLanguage('naive-log', () => ({\n  contains: [\n    {\n      className: 'number',\n      begin: /\\d+/\n    }\n  ]\n}))\n\nexport default hljs\n"
  },
  {
    "path": "demo/store/index.js",
    "content": "import {\n  darkTheme,\n  dateEnUS,\n  dateZhCN,\n  enUS,\n  NConfigProvider,\n  useOsTheme,\n  zhCN\n} from 'naive-ui'\nimport { useMemo } from 'vooks'\nimport { computed, ref } from 'vue'\nimport { TsConfigProvider } from '../../themes/tusimple/src'\nimport { i18n, useIsMobile } from '../utils/composables'\nimport hljs from './hljs'\nimport {\n  createComponentMenuOptions,\n  createDocumentationMenuOptions\n} from './menu-options'\n\nlet route = null\nlet router = null\n// locale\nlet localeNameRef = null\n// useMemo\nlet dateLocaleRef = null\n// theme\nconst osThemeRef = useOsTheme()\nlet themeNameRef = null\nlet rawThemeNameRef = null // could be `os-theme`\n\nexport function initRouter(_router, _route) {\n  route = _route\n  router = _router\n  localeNameRef = useMemo({\n    get() {\n      return route.path.startsWith('/zh-CN') ? 'zh-CN' : 'en-US'\n    },\n    set(locale) {\n      router.push(changeLangInPath(route.fullPath, locale))\n    }\n  })\n  dateLocaleRef = useMemo(() => {\n    return route.path.startsWith('/zh-CN') ? dateZhCN : dateEnUS\n  })\n  rawThemeNameRef = useMemo(() => route.params.theme)\n  themeNameRef = useMemo({\n    get() {\n      switch (route.params.theme) {\n        case 'os-theme':\n          return osThemeRef.value\n        case 'dark':\n          return 'dark'\n        default:\n          return 'light'\n      }\n    },\n    set(theme) {\n      router.push(changeThemeInPath(route.fullPath, theme))\n    }\n  })\n}\n\n// display mode\nconst _displayModeRef = ref(window.localStorage.getItem('mode') ?? 'debug')\nconst displayModeRef = computed({\n  get() {\n    return _displayModeRef.value\n  },\n  set(value) {\n    _displayModeRef.value = value\n    window.localStorage.setItem('mode', value)\n  }\n})\n\nconst localeRef = computed(() => {\n  return localeNameRef.value === 'zh-CN' ? zhCN : enUS\n})\n\nconst themeRef = computed(() => {\n  const { value } = themeNameRef\n  return value === 'dark' ? darkTheme : null\n})\n\n// config provider\n// eslint-disable-next-line node/prefer-global/process\nconst configProviderNameRef = ref(process.env.TUSIMPLE ? 'tusimple' : 'default')\n\nconst configProviderRef = computed(() => {\n  return configProviderNameRef.value === 'tusimple'\n    ? TsConfigProvider\n    : NConfigProvider\n})\n\n// options\nconst docOptionsRef = computed(() =>\n  createDocumentationMenuOptions({\n    theme: rawThemeNameRef.value,\n    lang: localeNameRef.value,\n    mode: displayModeRef.value\n  })\n)\nconst componentOptionsRef = computed(() =>\n  createComponentMenuOptions({\n    theme: rawThemeNameRef.value,\n    lang: localeNameRef.value,\n    mode: displayModeRef.value\n  })\n)\nconst flattenedDocOptionsRef = computed(() => {\n  const flattenedItems = []\n  const traverse = (items) => {\n    if (!items)\n      return\n    items.forEach((item) => {\n      if (item.children)\n        traverse(item.children)\n      else flattenedItems.push(item)\n    })\n  }\n  traverse(docOptionsRef.value)\n  traverse(componentOptionsRef.value)\n  return flattenedItems\n})\n\nexport function siteSetup() {\n  i18n.provide(computed(() => localeNameRef.value))\n  const isMobileRef = useIsMobile()\n  return {\n    themeEditorStyle: computed(() => {\n      return isMobileRef.value ? 'right: 18px; bottom: 24px;' : undefined\n    }),\n    configProvider: configProviderRef,\n    hljs,\n    themeName: themeNameRef,\n    theme: themeRef,\n    locale: localeRef,\n    dateLocale: dateLocaleRef\n  }\n}\n\nfunction changeLangInPath(path, lang) {\n  const langReg = /^\\/(zh-CN|en-US)\\//\n  return path.replace(langReg, `/${lang}/`)\n}\n\nfunction changeThemeInPath(path, theme) {\n  const themeReg = /(^\\/[^/]+\\/)([^/]+)/\n  return path.replace(themeReg, `$1${theme}`)\n}\n\nexport function push(partialPath) {\n  const { fullPath } = route\n  router.push(\n    fullPath.replace(/(^\\/[^/]+\\/[^/]+)((\\/.*)|$)/, `$1${partialPath}`)\n  )\n}\n\nexport function useDisplayMode() {\n  return displayModeRef\n}\n\nexport function useLocaleName() {\n  return localeNameRef\n}\n\nexport function useThemeName() {\n  return themeNameRef\n}\n\nexport function useDocOptions() {\n  return docOptionsRef\n}\n\nexport function useComponentOptions() {\n  return componentOptionsRef\n}\n\nexport function useFlattenedDocOptions() {\n  return flattenedDocOptionsRef\n}\n\nexport function useConfigProviderName() {\n  return configProviderNameRef\n}\n"
  },
  {
    "path": "demo/store/menu-options.js",
    "content": "// rubbish code here\n\nimport { NSpace, NTag } from 'naive-ui'\nimport { h } from 'vue'\nimport { RouterLink } from 'vue-router'\n\nexport function renderMenuLabel(option) {\n  if (!('path' in option) || option.label === '--Debug') {\n    return option.label\n  }\n  return h(\n    RouterLink,\n    {\n      to: option.path\n    },\n    { default: () => option.label }\n  )\n}\n\nfunction renderNewTag(isZh) {\n  return h(\n    NTag,\n    {\n      type: 'success',\n      size: 'small',\n      round: true,\n      bordered: false,\n      style: { pointerEvents: 'none' }\n    },\n    { default: isZh ? () => '新' : () => 'New' }\n  )\n}\n\nfunction renderItemExtra(rawItem, isZh) {\n  if (!rawItem.enSuffix || !isZh) {\n    return rawItem.isNew ? renderNewTag : undefined\n  }\n  const renderEn = () =>\n    h(\n      NSpace,\n      { inline: true, size: 6, wrapItem: false, align: 'center' },\n      { default: () => [rawItem.en, renderNewTag(isZh)] }\n    )\n  return rawItem.isNew ? renderEn : rawItem.en\n}\nfunction getItemExtraString(rawItem, isZh) {\n  if (!rawItem.enSuffix || !isZh) {\n    return ''\n  }\n  else {\n    return rawItem.en\n  }\n}\n\nfunction appendCounts(item) {\n  if (!item.children) {\n    item.count = 1\n    return item\n  }\n  if (item.children) {\n    item.children.forEach(appendCounts)\n    item.count = item.children.reduce((sum, item) => sum + item.count, 0)\n    if (item.type === 'group') {\n      item.en += ` (${item.count})`\n      item.zh += ` (${item.count})`\n    }\n    return item\n  }\n}\n\nfunction createItems(lang, theme, prefix, items) {\n  const isZh = lang === 'zh-CN'\n  const langKey = isZh ? 'zh' : 'en'\n  return items.map((rawItem) => {\n    const item = {\n      ...rawItem,\n      key: rawItem.en,\n      label: rawItem[langKey] || rawItem.en,\n      extra: renderItemExtra(rawItem, isZh),\n      extraString: getItemExtraString(rawItem, isZh),\n      path: rawItem.path\n        ? `/${lang}/${theme}${prefix}${rawItem.path}`\n        : undefined\n    }\n    if (rawItem.children) {\n      item.children = createItems(lang, theme, prefix, rawItem.children)\n    }\n    return item\n  })\n}\n\nexport function createDocumentationMenuOptions({ lang, theme }) {\n  return createItems(lang, theme, '/docs', [\n    {\n      en: 'Introduction',\n      zh: '介绍',\n      type: 'group',\n      children: [\n        {\n          en: 'Naive UI',\n          zh: 'Naive UI',\n          path: '/introduction'\n        }\n      ]\n    },\n    {\n      en: 'Getting Started',\n      zh: '快速上手',\n      type: 'group',\n      children: [\n        {\n          en: 'Installation',\n          zh: '安装',\n          path: '/installation'\n        },\n        {\n          en: 'Usage in SFC',\n          zh: '在 SFC 中使用',\n          path: '/usage-sfc'\n        },\n        {\n          en: 'Using UMD',\n          zh: '使用 UMD',\n          path: '/umd'\n        },\n        {\n          en: 'Configuring Fonts',\n          zh: '配置字体',\n          path: '/fonts'\n        },\n        {\n          en: 'Import on Demand',\n          zh: '按需引入',\n          path: '/import-on-demand'\n        },\n        {\n          en: 'Supported Platforms',\n          zh: '支持的平台',\n          path: '/supported-platforms'\n        },\n        {\n          en: 'Common Issues',\n          zh: '常见问题',\n          path: '/common-issues'\n        },\n        {\n          en: 'Controlled & Uncontrolled',\n          zh: '受控与非受控',\n          path: '/controlled-uncontrolled'\n        }\n      ]\n    },\n    {\n      en: 'Guides',\n      zh: '指南',\n      type: 'group',\n      children: [\n        {\n          en: 'JSX & TSX',\n          zh: 'JSX & TSX',\n          path: '/jsx'\n        },\n        {\n          en: 'Server-Sider Rendering',\n          zh: '服务端渲染 SSR',\n          path: '/ssr'\n        },\n        {\n          en: 'Nuxt.js',\n          zh: 'Nuxt.js',\n          path: '/nuxtjs'\n        },\n        {\n          en: 'Vitepress',\n          zh: 'Vitepress',\n          path: '/vitepress'\n        },\n        {\n          en: 'Vite SSG/SSE',\n          zh: 'Vite SSG/SSE',\n          path: '/vite-ssge'\n        },\n        {\n          en: 'Customizing Theme',\n          zh: '调整主题',\n          path: '/customize-theme'\n        },\n        {\n          en: 'Internationalization',\n          zh: '国际化',\n          path: '/i18n'\n        },\n        {\n          en: 'Create Themed Component',\n          zh: '创建适配主题的组件',\n          path: '/theme'\n        },\n        {\n          en: 'Potential Style Conflict',\n          zh: '潜在的样式冲突',\n          path: '/style-conflict'\n        },\n        {\n          en: 'Third-Party Libraries',\n          zh: '社区精选资源',\n          path: '/community'\n        }\n      ]\n    },\n    {\n      en: 'Version',\n      zh: '版本',\n      type: 'group',\n      children: [\n        {\n          en: 'Change Log',\n          zh: '变更日志',\n          path: '/changelog'\n        }\n      ]\n    }\n  ])\n}\n\nexport function createComponentMenuOptions({ lang, theme }) {\n  return createItems(lang, theme, '/components', [\n    appendCounts({\n      zh: '通用组件',\n      en: 'Common Components',\n      type: 'group',\n      children: [\n        {\n          en: 'Avatar',\n          zh: '头像',\n          enSuffix: true,\n          path: '/avatar'\n        },\n        {\n          en: 'Button',\n          zh: '按钮',\n          enSuffix: true,\n          path: '/button'\n        },\n        {\n          en: 'Card',\n          zh: '卡片',\n          enSuffix: true,\n          path: '/card'\n        },\n        {\n          en: 'Carousel',\n          zh: '轮播图',\n          enSuffix: true,\n          path: '/carousel'\n        },\n        {\n          en: 'Collapse',\n          zh: '折叠面板',\n          enSuffix: true,\n          path: '/collapse'\n        },\n        {\n          en: 'Divider',\n          zh: '分割线',\n          enSuffix: true,\n          path: '/divider'\n        },\n        {\n          en: 'Dropdown',\n          zh: '下拉菜单',\n          enSuffix: true,\n          path: '/dropdown'\n        },\n        {\n          en: 'Ellipsis',\n          zh: '文本省略',\n          enSuffix: true,\n          path: '/ellipsis'\n        },\n        {\n          en: 'Gradient Text',\n          zh: '渐变文字',\n          enSuffix: true,\n          path: '/gradient-text'\n        },\n        {\n          en: 'Icon',\n          zh: '图标',\n          enSuffix: true,\n          path: '/icon'\n        },\n        {\n          en: 'PageHeader',\n          zh: '页头',\n          enSuffix: true,\n          path: '/page-header'\n        },\n        {\n          en: 'Tag',\n          zh: '标签',\n          enSuffix: true,\n          path: '/tag'\n        },\n        {\n          en: 'Typography',\n          zh: '排印',\n          enSuffix: true,\n          path: '/typography'\n        },\n        {\n          en: 'Watermark',\n          zh: '水印',\n          enSuffix: true,\n          path: '/watermark'\n        },\n        {\n          en: 'Float Button',\n          zh: '浮动按钮',\n          enSuffix: true,\n          path: '/float-button',\n          isNew: true\n        }\n      ]\n    }),\n    appendCounts({\n      zh: '数据录入组件',\n      en: 'Data Input Components',\n      type: 'group',\n      children: [\n        {\n          en: 'Auto Complete',\n          zh: '自动填充',\n          enSuffix: true,\n          path: '/auto-complete'\n        },\n        {\n          en: 'Cascader',\n          zh: '级联选择',\n          enSuffix: true,\n          path: '/cascader'\n        },\n        {\n          en: 'Color Picker',\n          zh: '颜色选择器',\n          enSuffix: true,\n          path: '/color-picker'\n        },\n        {\n          en: 'Checkbox',\n          zh: '复选框',\n          enSuffix: true,\n          path: '/checkbox'\n        },\n        {\n          en: 'Date Picker',\n          zh: '日期选择器',\n          enSuffix: true,\n          path: '/date-picker'\n        },\n        {\n          en: 'Dynamic Input',\n          zh: '动态录入',\n          enSuffix: true,\n          path: '/dynamic-input'\n        },\n        {\n          en: 'Dynamic Tags',\n          zh: '动态标签',\n          enSuffix: true,\n          path: '/dynamic-tags'\n        },\n        {\n          en: 'Form',\n          zh: '表单',\n          enSuffix: true,\n          path: '/form'\n        },\n        {\n          en: 'Input',\n          zh: '文本输入',\n          enSuffix: true,\n          path: '/input'\n        },\n        {\n          en: 'Input Number',\n          zh: '数字输入',\n          enSuffix: true,\n          path: '/input-number'\n        },\n        {\n          en: 'Input OTP',\n          zh: '验证码',\n          enSuffix: true,\n          path: '/input-otp',\n          isNew: true\n        },\n        {\n          en: 'Mention',\n          zh: '提及',\n          enSuffix: true,\n          path: '/mention'\n        },\n        {\n          en: 'Radio',\n          zh: '单选',\n          enSuffix: true,\n          path: '/radio'\n        },\n        {\n          en: 'Rate',\n          zh: '评分',\n          enSuffix: true,\n          path: '/rate'\n        },\n        {\n          en: 'Select',\n          zh: '选择器',\n          enSuffix: true,\n          path: '/select'\n        },\n        {\n          en: 'Slider',\n          zh: '滑动选择',\n          enSuffix: true,\n          path: '/slider'\n        },\n        {\n          en: 'Switch',\n          zh: '开关',\n          enSuffix: true,\n          path: '/switch'\n        },\n        {\n          en: 'Time Picker',\n          zh: '时间选择器',\n          enSuffix: true,\n          path: '/time-picker'\n        },\n        {\n          en: 'Transfer',\n          zh: '穿梭框',\n          enSuffix: true,\n          path: '/transfer'\n        },\n        {\n          en: 'Tree Select',\n          zh: '树型选择',\n          enSuffix: true,\n          path: '/tree-select'\n        },\n        {\n          en: 'Upload',\n          zh: '上传',\n          enSuffix: true,\n          path: '/upload'\n        }\n      ]\n    }),\n    appendCounts({\n      zh: '数据展示组件',\n      en: 'Data Display Components',\n      type: 'group',\n      children: [\n        {\n          en: 'Calendar',\n          zh: '日历',\n          enSuffix: true,\n          path: '/calendar'\n        },\n        {\n          en: 'Countdown',\n          zh: '倒计时',\n          enSuffix: true,\n          path: '/countdown'\n        },\n        {\n          en: 'Code',\n          zh: '代码',\n          enSuffix: true,\n          path: '/code'\n        },\n        {\n          en: 'Data Table',\n          zh: '数据表格',\n          enSuffix: true,\n          path: '/data-table'\n        },\n        {\n          en: 'Descriptions',\n          zh: '描述',\n          enSuffix: true,\n          path: '/descriptions'\n        },\n        {\n          en: 'Empty',\n          zh: '无内容',\n          enSuffix: true,\n          path: '/empty'\n        },\n        {\n          en: 'Equation',\n          zh: '公式',\n          enSuffix: true,\n          path: '/equation'\n        },\n        {\n          en: 'Image',\n          zh: '图像',\n          enSuffix: true,\n          path: '/image'\n        },\n        {\n          en: 'List',\n          zh: '列表',\n          enSuffix: true,\n          path: '/list'\n        },\n        {\n          en: 'Log',\n          zh: '日志',\n          enSuffix: true,\n          path: '/log'\n        },\n        {\n          en: 'Number Animation',\n          zh: '数值动画',\n          enSuffix: true,\n          path: '/number-animation'\n        },\n        {\n          en: 'QR Code',\n          zh: '二维码',\n          enSuffix: true,\n          path: '/qr-code',\n          isNew: true\n        },\n        {\n          en: 'Statistic',\n          zh: '统计数据',\n          enSuffix: true,\n          path: '/statistic'\n        },\n        {\n          en: 'Table',\n          zh: '表格',\n          enSuffix: true,\n          path: '/table'\n        },\n        {\n          en: 'Thing',\n          zh: '东西',\n          enSuffix: true,\n          path: '/thing'\n        },\n        {\n          en: 'Time',\n          zh: '时间',\n          enSuffix: true,\n          path: '/time'\n        },\n        {\n          en: 'Timeline',\n          zh: '时间线',\n          enSuffix: true,\n          path: '/timeline'\n        },\n        {\n          en: 'Tree',\n          zh: '树',\n          enSuffix: true,\n          path: '/tree'\n        },\n        {\n          en: 'Infinite Scroll',\n          zh: '无限滚动',\n          enSuffix: true,\n          path: '/infinite-scroll',\n          isNew: true\n        },\n        {\n          en: 'Highlight',\n          zh: '高亮文本',\n          enSuffix: true,\n          path: '/highlight',\n          isNew: true\n        },\n        {\n          en: 'Heatmap',\n          zh: '热力图',\n          enSuffix: true,\n          path: '/heatmap',\n          isNew: true\n        }\n      ]\n    }),\n    appendCounts({\n      zh: '导航组件',\n      en: 'Navigation Components',\n      type: 'group',\n      children: [\n        {\n          en: 'Affix',\n          zh: '固钉',\n          enSuffix: true,\n          path: '/affix'\n        },\n        {\n          en: 'Anchor',\n          zh: '侧边导航',\n          enSuffix: true,\n          path: '/anchor'\n        },\n        {\n          en: 'Back Top',\n          zh: '回到顶部',\n          enSuffix: true,\n          path: '/back-top'\n        },\n        {\n          en: 'Breadcrumb',\n          zh: '面包屑',\n          enSuffix: true,\n          path: '/breadcrumb'\n        },\n        {\n          en: 'Loading Bar',\n          zh: '加载条',\n          enSuffix: true,\n          path: '/loading-bar'\n        },\n        {\n          en: 'Menu',\n          zh: '菜单',\n          enSuffix: true,\n          path: '/menu'\n        },\n        {\n          en: 'Pagination',\n          zh: '分页',\n          enSuffix: true,\n          path: '/pagination'\n        },\n        {\n          en: 'Steps',\n          zh: '步骤',\n          enSuffix: true,\n          path: '/steps'\n        },\n        {\n          en: 'Tabs',\n          zh: '标签页',\n          enSuffix: true,\n          path: '/tabs'\n        }\n      ]\n    }),\n    appendCounts({\n      zh: '反馈组件',\n      en: 'Feedback Components',\n      type: 'group',\n      children: [\n        {\n          en: 'Alert',\n          zh: '警告信息',\n          enSuffix: true,\n          path: '/alert'\n        },\n        {\n          en: 'Badge',\n          zh: '标记',\n          enSuffix: true,\n          path: '/badge'\n        },\n        {\n          en: 'Dialog',\n          zh: '对话框',\n          enSuffix: true,\n          path: '/dialog'\n        },\n        {\n          en: 'Drawer',\n          zh: '抽屉',\n          enSuffix: true,\n          path: '/drawer'\n        },\n        {\n          en: 'Marquee',\n          zh: '跑马灯',\n          enSuffix: true,\n          path: '/marquee',\n          isNew: true\n        },\n        {\n          en: 'Message',\n          zh: '信息',\n          enSuffix: true,\n          path: '/message'\n        },\n        {\n          en: 'Modal',\n          zh: '模态框',\n          enSuffix: true,\n          path: '/modal'\n        },\n        {\n          en: 'Notification',\n          zh: '通知',\n          enSuffix: true,\n          path: '/notification'\n        },\n        {\n          en: 'Popconfirm',\n          zh: '弹出确认',\n          enSuffix: true,\n          path: '/popconfirm'\n        },\n        {\n          en: 'Popover',\n          zh: '弹出信息',\n          enSuffix: true,\n          path: '/popover'\n        },\n        {\n          en: 'Popselect',\n          zh: '弹出选择',\n          enSuffix: true,\n          path: '/popselect'\n        },\n        {\n          en: 'Progress',\n          zh: '进度',\n          enSuffix: true,\n          path: '/progress'\n        },\n        {\n          en: 'Result',\n          zh: '结果页',\n          enSuffix: true,\n          path: '/result'\n        },\n        {\n          en: 'Skeleton',\n          zh: '骨架屏',\n          enSuffix: true,\n          path: '/skeleton'\n        },\n        {\n          en: 'Spin',\n          zh: '加载',\n          enSuffix: true,\n          path: '/spin'\n        },\n        {\n          en: 'Tooltip',\n          zh: '弹出提示',\n          enSuffix: true,\n          path: '/tooltip'\n        }\n      ]\n    }),\n    appendCounts({\n      zh: '布局组件',\n      en: 'Layout Components',\n      type: 'group',\n      children: [\n        {\n          en: 'Flex',\n          zh: '弹性布局',\n          enSuffix: true,\n          path: '/flex',\n          isNew: true\n        },\n        {\n          en: 'Layout',\n          zh: '布局',\n          enSuffix: true,\n          path: '/layout'\n        },\n        {\n          en: 'Legacy Grid',\n          zh: '旧版栅格',\n          enSuffix: true,\n          path: '/legacy-grid'\n        },\n        {\n          en: 'Grid',\n          zh: '栅格',\n          enSuffix: true,\n          path: '/grid'\n        },\n        {\n          en: 'Space',\n          zh: '间距',\n          enSuffix: true,\n          path: '/space'\n        },\n        {\n          en: 'Split',\n          zh: '面板分割',\n          enSuffix: true,\n          path: '/split',\n          isNew: true\n        }\n      ]\n    }),\n    appendCounts({\n      zh: '工具组件',\n      en: 'Utility Components',\n      type: 'group',\n      children: [\n        {\n          en: 'Collapse Transition',\n          zh: '折叠渐变',\n          enSuffix: true,\n          path: '/collapse-transition'\n        },\n        {\n          en: 'Discrete API',\n          zh: '独立 API',\n          enSuffix: true,\n          path: '/discrete'\n        },\n        {\n          en: 'Scrollbar',\n          zh: '滚动条',\n          enSuffix: true,\n          path: '/scrollbar'\n        },\n        {\n          en: 'Virtual List',\n          zh: '虚拟列表',\n          enSuffix: true,\n          path: '/virtual-list',\n          isNew: true\n        }\n      ]\n    }),\n    appendCounts({\n      zh: '配置组件',\n      en: 'Config Components',\n      type: 'group',\n      children: [\n        {\n          en: 'Config Provider',\n          zh: '全局化配置',\n          enSuffix: true,\n          path: '/config-provider'\n        },\n        {\n          en: 'Element',\n          zh: '元素',\n          enSuffix: true,\n          path: '/element'\n        },\n        {\n          en: 'Global Style',\n          zh: '全局样式',\n          enSuffix: true,\n          path: '/global-style'\n        }\n      ]\n    }),\n    appendCounts({\n      zh: '废弃的组件',\n      en: 'Deprecated Components',\n      type: 'group',\n      children: [\n        {\n          en: 'Legacy Transfer',\n          zh: '旧版穿梭框',\n          enSuffix: true,\n          path: '/legacy-transfer'\n        }\n      ]\n    })\n  ])\n}\n"
  },
  {
    "path": "demo/styles/Metropolis.css",
    "content": "@font-face {\n  font-family: 'Metropolis';\n  font-weight: 600;\n  src: url('./Metropolis-Bold.woff2');\n}"
  },
  {
    "path": "demo/styles/demo.css",
    "content": "@import 'Metropolis.css';\n\nbody {\n  overflow: hidden;\n  --header-height: 64px;\n}\n\n.demo-card .demo-card__view:not(:first-child) {\n  margin-top: 16px;\n}\n\n.demo-card .demo-card__view pre {\n  font-family: v-mono, monospace;\n}\n\n.demo-card .demo-card__view code {\n  font-family: v-mono, monospace;\n}\n\n.demo-card code.n-text {\n  white-space: nowrap;\n}\n\n.doc .n-p,\n.n-blockquote {\n  max-width: 680px;\n}\n\n.md-table-wrapper {\n  margin-bottom: 16px;\n}\n\n.md-table-wrapper:last-child,\n.md-card:last-child {\n  margin-bottom: 0;\n}\n\n.md-table td:first-child {\n  font-size: 0.93em !important;\n  font-family: v-mono, monospace;\n}\n\n.md-table .n-text.n-text--code {\n  font-size: 0.93em !important;\n}\n\n.md-card {\n  margin-bottom: 16px;\n}\n\n.ts-dark-theme .demo-card {\n  background-color: #141414;\n}\n\n.md-table td {\n  word-break: normal;\n}\n\n@media only screen and (max-width: 1280px) {\n  .md-table td {\n    word-break: break-word;\n  }\n}\n\n@media only screen and (max-width: 639px) {\n  body {\n    overflow: visible;\n  }\n  .md-table td {\n    word-break: normal;\n  }\n  .md-table-wrapper {\n    overflow: auto;\n    margin: 0 -16px;\n    display: flex;\n    flex-wrap: nowrap;\n  }\n  .md-table-wrapper::before,\n  .md-table-wrapper::after {\n    content: '';\n    width: 16px;\n    flex-shrink: 0;\n  }\n}\n"
  },
  {
    "path": "demo/utils/ComponentDemo.vue",
    "content": "<script lang=\"ts\">\nimport { CodeOutline } from '@vicons/ionicons5'\nimport { computed, defineComponent, nextTick, ref, watch } from 'vue'\nimport { useDisplayMode } from '../store'\nimport { i18n } from '../utils/composables'\nimport CopyCodeButton from './CopyCodeButton.vue'\nimport EditInCodeSandboxButton from './EditInCodeSandboxButton.vue'\nimport EditInPlaygroundButton from './EditInPlaygroundButton.vue'\nimport EditOnGithubButton from './EditOnGithubButton.vue'\n\nexport default defineComponent({\n  components: {\n    CodeOutline,\n    EditOnGithubButton,\n    EditInCodeSandboxButton,\n    CopyCodeButton,\n    EditInPlaygroundButton\n  },\n  props: {\n    title: {\n      type: String,\n      required: true\n    },\n    tsCode: {\n      type: String,\n      required: true\n    },\n    demoFileName: {\n      type: String,\n      required: true\n    },\n    relativeUrl: {\n      type: String,\n      required: true\n    },\n    jsCode: {\n      type: String,\n      required: true\n    },\n    languageType: {\n      type: String,\n      default: 'js'\n    }\n  },\n  setup(props) {\n    const displayModeRef = useDisplayMode()\n    const isDebugDemo = /(d|D)ebug/.test(props.demoFileName)\n    const showDemoRef = computed(() => {\n      return !(isDebugDemo && displayModeRef.value !== 'debug')\n    })\n    const showCodeRef = ref(false)\n    const showTsRef = ref(props.languageType === 'ts')\n    const expandCodeButtonRef = ref(null)\n    watch(showCodeRef, () => {\n      nextTick(() => {\n        expandCodeButtonRef.value.syncPosition()\n      })\n    })\n    return {\n      expandCodeButtonRef,\n      showDemo: showDemoRef,\n      showCode: showCodeRef,\n      showTs: showTsRef,\n      sfcTsCode: decodeURIComponent(props.tsCode),\n      sfcJsCode: decodeURIComponent(props.jsCode),\n      toggleCodeDisplay() {\n        showCodeRef.value = !showCodeRef.value\n      },\n      handleTitleClick: () => {\n        window.location.hash = `#${props.demoFileName}`\n      },\n      toggleLanguageChange() {\n        showTsRef.value = !showTsRef.value\n      },\n      ...i18n({\n        'zh-CN': {\n          show: '显示代码',\n          hide: '收起代码',\n          editOnGithub: '在 GitHub 中编辑',\n          editInCodeSandbox: '在 CodeSandbox 中编辑',\n          editInPlayground: '在 Playground 中编辑',\n          copyCode: '复制代码',\n          copySuccess: '复制成功'\n        },\n        'en-US': {\n          show: 'Show Code',\n          hide: 'Hide Code',\n          editOnGithub: 'Edit on GitHub',\n          editInCodeSandbox: 'Edit in CodeSandbox',\n          editInPlayground: 'Edit in Playground',\n          copyCode: 'Copy Code',\n          copySuccess: 'Successfully Copied'\n        }\n      })\n    }\n  }\n})\n</script>\n\n<template>\n  <n-card\n    v-if=\"showDemo\"\n    :id=\"demoFileName\"\n    class=\"demo-card\"\n    :segmented=\"{\n      footer: true,\n    }\"\n    footer-style=\"padding: 0;\"\n  >\n    <template #header>\n      <span style=\"cursor: pointer\" @click=\"handleTitleClick\">\n        <slot name=\"title\" />\n      </span>\n    </template>\n    <template #header-extra>\n      <n-tooltip>\n        <template #trigger>\n          <EditInPlaygroundButton\n            style=\"padding: 0; margin-right: 6px\"\n            size=\"tiny\"\n            :code=\"showTs ? sfcTsCode : sfcJsCode\"\n          />\n        </template>\n        {{ t('editInPlayground') }}\n      </n-tooltip>\n      <n-tooltip>\n        <template #trigger>\n          <EditInCodeSandboxButton\n            style=\"padding: 0; margin-right: 6px\"\n            size=\"tiny\"\n            :code=\"showTs ? sfcTsCode : sfcJsCode\"\n          />\n        </template>\n        {{ t('editInCodeSandbox') }}\n      </n-tooltip>\n      <n-tooltip>\n        <template #trigger>\n          <EditOnGithubButton\n            depth=\"3\"\n            style=\"padding: 0; margin-right: 6px\"\n            size=\"tiny\"\n            :relative-url=\"relativeUrl\"\n          />\n        </template>\n        {{ t('editOnGithub') }}\n      </n-tooltip>\n      <n-tooltip>\n        <template #trigger>\n          <CopyCodeButton\n            depth=\"3\"\n            style=\"padding: 0; margin-right: 6px\"\n            size=\"tiny\"\n            :code=\"showTs ? sfcTsCode : sfcJsCode\"\n            :success-text=\"t('copySuccess')\"\n          />\n        </template>\n        {{ t('copyCode') }}\n      </n-tooltip>\n      <n-tooltip ref=\"expandCodeButtonRef\">\n        <template #trigger>\n          <n-button\n            style=\"padding: 0\"\n            size=\"tiny\"\n            text\n            depth=\"3\"\n            @click=\"toggleCodeDisplay\"\n          >\n            <template #icon>\n              <n-icon>\n                <CodeOutline />\n              </n-icon>\n            </template>\n          </n-button>\n        </template>\n        {{ !showCode ? t('show') : t('hide') }}\n      </n-tooltip>\n    </template>\n    <slot name=\"content\" />\n    <slot name=\"demo\" />\n    <template v-if=\"showCode\" #footer>\n      <n-tabs\n        v-if=\"languageType === 'ts'\"\n        size=\"small\"\n        type=\"segment\"\n        style=\"padding: 12px 24px 0 24px\"\n        :value=\"showTs ? 'ts' : 'js'\"\n        @update:value=\"($e) => (showTs = $e === 'ts')\"\n      >\n        <n-tab name=\"ts\">\n          TypeScript\n        </n-tab>\n        <n-tab name=\"js\">\n          JavaScript\n        </n-tab>\n      </n-tabs>\n      <n-scrollbar\n        x-scrollable\n        content-style=\"padding: 20px 24px;\"\n        style=\"height: auto\"\n      >\n        <n-code v-if=\"showTs\" language=\"html\" :code=\"sfcTsCode\" />\n        <n-code v-else language=\"html\" :code=\"sfcJsCode\" />\n      </n-scrollbar>\n    </template>\n  </n-card>\n</template>\n"
  },
  {
    "path": "demo/utils/ComponentDemos.tsx",
    "content": "import { computed, defineComponent, Fragment, h } from 'vue'\nimport { useIsMobile, useIsSmallDesktop, useIsTablet } from './composables'\n\nexport default defineComponent({\n  name: 'ComponentDemos',\n  props: {\n    span: {\n      type: Number,\n      default: 2\n    }\n  },\n  setup(props) {\n    const isMobileRef = useIsMobile()\n    const isTabletRef = useIsTablet()\n    const isSmallDesktop = useIsSmallDesktop()\n    const mergedColsRef = computed(() => {\n      return isMobileRef.value || isTabletRef.value || isSmallDesktop.value\n        ? 1\n        : props.span\n    })\n    return {\n      mergedCols: mergedColsRef\n    }\n  },\n  render() {\n    const children = this.$slots.default?.() ?? []\n    const { mergedCols } = this\n    return (\n      <div\n        style={{\n          display: 'grid',\n          gap: '16px',\n          gridTemplateColumns:\n            mergedCols === 1 ? '100%' : 'minmax(0, 1fr) minmax(0, 1fr)',\n          alignItems: 'flex-start'\n        }}\n      >\n        {mergedCols === 1 ? (\n          children\n        ) : (\n          <>\n            <div\n              style={{\n                display: 'grid',\n                gap: '16px',\n                gridTemplateColumns: '100%'\n              }}\n            >\n              {children.filter((_, index) => index % 2 === 0)}\n            </div>\n            <div\n              style={{\n                display: 'grid',\n                gap: '16px',\n                gridTemplateColumns: '100%'\n              }}\n            >\n              {children.filter((_, index) => index % 2 === 1)}\n            </div>\n          </>\n        )}\n      </div>\n    )\n  }\n})\n"
  },
  {
    "path": "demo/utils/CopyCodeButton.vue",
    "content": "<script lang=\"ts\">\nimport { useMessage } from 'naive-ui'\nimport { defineComponent } from 'vue'\n\nexport default defineComponent({\n  name: 'CopyCodeButton',\n  props: {\n    code: {\n      type: String,\n      required: true\n    },\n    successText: {\n      type: String,\n      required: true\n    },\n    text: Boolean,\n    size: String,\n    depth: String\n  },\n  setup(props) {\n    const message = useMessage()\n    return {\n      handleClick() {\n        navigator.clipboard.writeText(props.code).then(() => {\n          message.success(props.successText)\n        })\n      }\n    }\n  }\n})\n</script>\n\n<template>\n  <n-button\n    class=\"edit-button\"\n    text\n    :size=\"size\"\n    :depth=\"depth\"\n    @click=\"handleClick\"\n  >\n    <template #icon>\n      <n-icon size=\"14\">\n        <svg\n          viewBox=\"0 0 544 560\"\n          fill=\"none\"\n          xmlns=\"http://www.w3.org/2000/svg\"\n        >\n          <path\n            d=\"M399.503 143.667C399.319 152.501 406.332 159.812 415.167 159.997C424.001 160.181 431.312 153.168 431.497 144.333L399.503 143.667ZM416 120L431.997 120.333C431.999 120.207 432 120.081 432 119.954L416 120ZM360 64L360.046 48.0001C360.03 48 360.015 48 360 48L360 64ZM144 64V48C143.984 48 143.968 48 143.953 48.0001L144 64ZM80 128L64.0001 127.953C64 127.968 64 127.984 64 128L80 128ZM80 344H64C64 344.015 64 344.03 64.0001 344.046L80 344ZM136 400L135.954 416C135.97 416 135.985 416 136 416L136 400ZM160 416C168.837 416 176 408.837 176 400C176 391.163 168.837 384 160 384V416ZM217 160H439V128H217V160ZM439 160C461.644 160 480 178.356 480 201H512C512 160.683 479.317 128 439 128V160ZM480 201V423H512V201H480ZM480 423C480 445.644 461.644 464 439 464V496C479.317 496 512 463.317 512 423H480ZM439 464H217V496H439V464ZM217 464C194.356 464 176 445.644 176 423H144C144 463.317 176.683 496 217 496V464ZM176 423V201H144V423H176ZM176 201C176 178.356 194.356 160 217 160V128C176.683 128 144 160.683 144 201H176ZM431.497 144.333L431.997 120.333L400.003 119.667L399.503 143.667L431.497 144.333ZM432 119.954C431.946 100.888 424.347 82.6173 410.865 69.1349L388.238 91.7624C395.741 99.2658 399.97 109.434 400 120.046L432 119.954ZM410.865 69.1349C397.383 55.6526 379.112 48.0543 360.046 48.0001L359.954 79.9999C370.566 80.0301 380.734 84.2589 388.238 91.7624L410.865 69.1349ZM360 48H144V80H360V48ZM143.953 48.0001C122.767 48.0627 102.467 56.5064 87.4868 71.4868L110.114 94.1142C119.117 85.1118 131.316 80.0376 144.047 79.9999L143.953 48.0001ZM87.4868 71.4868C72.5064 86.4673 64.0627 106.767 64.0001 127.953L95.9999 128.047C96.0376 115.316 101.112 103.117 110.114 94.1142L87.4868 71.4868ZM64 128V344H96V128H64ZM64.0001 344.046C64.0543 363.112 71.6526 381.383 85.1349 394.865L107.762 372.238C100.259 364.734 96.0301 354.566 95.9999 343.954L64.0001 344.046ZM85.1349 394.865C98.6173 408.347 116.888 415.946 135.954 416L136.046 384C125.434 383.97 115.266 379.741 107.762 372.238L85.1349 394.865ZM136 416H160V384H136V416Z\"\n            fill=\"currentColor\"\n          />\n        </svg>\n      </n-icon>\n    </template>\n  </n-button>\n</template>\n"
  },
  {
    "path": "demo/utils/EditInCodeSandboxButton.vue",
    "content": "<script lang=\"ts\">\nimport { computed, defineComponent } from 'vue'\nimport { getCodeSandboxParams } from './codesandbox'\n\nexport default defineComponent({\n  name: 'EditInCodeSandboxButton',\n  props: {\n    code: String,\n    size: String\n  },\n  setup(props) {\n    return {\n      parameters: computed(() => getCodeSandboxParams(props.code))\n    }\n  }\n})\n</script>\n\n<template>\n  <form\n    action=\"https://codesandbox.io/api/v1/sandboxes/define\"\n    method=\"POST\"\n    target=\"_blank\"\n    style=\"display: flex\"\n  >\n    <input type=\"hidden\" name=\"parameters\" :value=\"parameters\">\n    <n-button\n      class=\"edit-button\"\n      text\n      :size=\"size\"\n      attr-type=\"submit\"\n      depth=\"3\"\n    >\n      <template #icon>\n        <n-icon>\n          <svg\n            width=\"512\"\n            height=\"512\"\n            viewBox=\"0 0 512 512\"\n            fill=\"none\"\n            xmlns=\"http://www.w3.org/2000/svg\"\n          >\n            <path\n              d=\"M69 153.99L256 263.99M256 263.99L443 153.99M256 263.99V463.99M448 341.37V170.61C447.993 165.021 446.523 159.531 443.735 154.687C440.947 149.843 436.939 145.814 432.11 143L280.11 54.54C272.787 50.2765 264.464 48.0303 255.99 48.0303C247.516 48.0303 239.193 50.2765 231.87 54.54L79.89 143C75.0609 145.814 71.053 149.843 68.2652 154.687C65.4773 159.531 64.0068 165.021 64 170.61V341.37C64.0033 346.962 65.4722 352.456 68.2602 357.304C71.0482 362.152 75.058 366.185 79.89 369L231.89 457.46C239.215 461.718 247.537 463.96 256.01 463.96C264.483 463.96 272.805 461.718 280.13 457.46L432.13 369C436.958 366.182 440.964 362.148 443.748 357.301C446.533 352.453 447.999 346.96 448 341.37Z\"\n              stroke=\"currentColor\"\n              stroke-width=\"32\"\n              stroke-linecap=\"round\"\n              stroke-linejoin=\"round\"\n            />\n          </svg>\n        </n-icon>\n      </template>\n    </n-button>\n  </form>\n</template>\n"
  },
  {
    "path": "demo/utils/EditInPlaygroundButton.vue",
    "content": "<script lang=\"ts\">\nimport type { PropType } from 'vue'\nimport { strFromU8, strToU8, zlibSync } from 'fflate'\nimport { defineComponent } from 'vue'\nimport { appCode, playgroundUrl } from './playground'\n\nfunction utoa(data: string): string {\n  const buffer = strToU8(data)\n  const zipped = zlibSync(buffer, { level: 9 })\n  const binary = strFromU8(zipped, true)\n  return btoa(binary)\n}\n\nfunction serialized(data: string): string {\n  const originCode = {\n    'App.vue': appCode,\n    'Demo.vue': data\n  }\n  return utoa(JSON.stringify(originCode))\n}\n\nexport default defineComponent({\n  name: 'PlaygroundButton',\n  props: {\n    code: {\n      type: String,\n      required: true\n    },\n    size: String as PropType<any>,\n    depth: String\n  },\n  setup(props) {\n    return {\n      handleClick() {\n        const serializedState = serialized(props.code)\n        window.open(`${playgroundUrl}/#${serializedState}`, '_blank')\n      }\n    }\n  }\n})\n</script>\n\n<template>\n  <n-button\n    class=\"edit-button\"\n    text\n    :size=\"size\"\n    :depth=\"depth\"\n    @click=\"handleClick\"\n  >\n    <template #icon>\n      <n-icon size=\"14\">\n        <svg\n          xmlns=\"http://www.w3.org/2000/svg\"\n          xmlns:xlink=\"http://www.w3.org/1999/xlink\"\n          viewBox=\"0 0 16 16\"\n        >\n          <g fill=\"none\">\n            <path\n              d=\"M5.745 3.064A.5.5 0 0 0 5 3.5v9a.5.5 0 0 0 .745.436l8-4.5a.5.5 0 0 0 0-.871l-8-4.5zM4 3.5a1.5 1.5 0 0 1 2.235-1.307l8 4.5a1.5 1.5 0 0 1 0 2.615l-8 4.5A1.5 1.5 0 0 1 4 12.5v-9z\"\n              fill=\"currentColor\"\n            />\n          </g>\n        </svg>\n      </n-icon>\n    </template>\n  </n-button>\n</template>\n"
  },
  {
    "path": "demo/utils/EditOnGithubButton.vue",
    "content": "<script lang=\"ts\">\nimport type { ButtonProps } from 'naive-ui'\nimport type { PropType } from 'vue'\nimport EditIcon from '@vicons/fluent/Compose16Regular.js'\nimport { defineComponent } from 'vue'\nimport { blobUrl } from './github-url'\n\nexport default defineComponent({\n  name: 'EditOnGithubButton',\n  components: {\n    EditIcon\n  },\n  props: {\n    relativeUrl: {\n      type: String,\n      required: true\n    },\n    text: Boolean,\n    quaternary: Boolean,\n    size: {\n      type: String as PropType<ButtonProps['size']>,\n      default: 'tiny'\n    }\n  },\n  setup(props) {\n    return {\n      url: blobUrl + props.relativeUrl\n    }\n  }\n})\n</script>\n\n<template>\n  <n-button\n    class=\"edit-button\"\n    :theme-overrides=\"\n      quaternary\n        ? {\n          paddingTiny: '4px',\n          heightTiny: '14px',\n        }\n        : undefined\n    \"\n    :quaternary=\"quaternary\"\n    :text=\"!quaternary\"\n    :size=\"size\"\n    tag=\"a\"\n    :href=\"url\"\n    target=\"_blank\"\n  >\n    <template #icon>\n      <n-icon>\n        <EditIcon />\n      </n-icon>\n    </template>\n  </n-button>\n</template>\n"
  },
  {
    "path": "demo/utils/EditOnGithubHeader.vue",
    "content": "<script lang=\"ts\">\nimport { defineComponent } from 'vue'\nimport { i18n } from '../utils/composables'\nimport EditOnGithubButton from './EditOnGithubButton.vue'\n\nexport default defineComponent({\n  name: 'EditOnGithubHeader',\n  components: {\n    EditOnGithubButton\n  },\n  props: {\n    relativeUrl: {\n      type: String,\n      required: true\n    },\n    text: {\n      type: String,\n      required: true\n    }\n  },\n  setup() {\n    return {\n      ...i18n({\n        'zh-CN': {\n          editOnGithub: '在 GitHub 上编辑'\n        },\n        'en-US': {\n          editOnGithub: 'Edit on GitHub'\n        }\n      })\n    }\n  },\n  computed: {\n    id() {\n      return this.text.replace(/ /g, '-')\n    }\n  }\n})\n</script>\n\n<template>\n  <n-h1 :id=\"id\" class=\"naive-doc-title\">\n    <span>{{ text }}</span>\n    <span class=\"edit-button\">\n      <n-tooltip placement=\"right\" :show-arrow=\"false\">\n        <template #trigger>\n          <EditOnGithubButton\n            text\n            class=\"edit-button\"\n            quaternary\n            :relative-url=\"relativeUrl\"\n          />\n        </template>\n        {{ t('editOnGithub') }}\n      </n-tooltip>\n    </span>\n  </n-h1>\n</template>\n\n<style scoped>\n.naive-doc-title {\n  display: flex;\n}\n\n.naive-doc-title .edit-button {\n  margin-left: 2px;\n  display: inline-flex;\n  align-items: center;\n}\n</style>\n"
  },
  {
    "path": "demo/utils/codesandbox.js",
    "content": "import { getParameters } from 'codesandbox/lib/api/define'\n\nconst indexHtml = `<!DOCTYPE html>\n<html lang=\"en\">\n  <head>\n    <title>Naive UI Demo</title>\n    <style>\n      body {\n        padding: 24px;\n      }\n    </style>\n  </head>\n  <body>\n    <div id=\"app\"></div>\n  </body>\n</html>\n`\n\nconst appVue = `<template>\n<n-loading-bar-provider>\n  <n-message-provider>\n    <n-notification-provider>\n      <n-modal-provider>\n        <n-dialog-provider>\n          <demo />\n        </n-dialog-provider>\n      </n-modal-provider>\n    </n-notification-provider>\n  </n-message-provider>\n</n-loading-bar-provider>\n</template>\n\n<script>\nimport { defineComponent } from \"vue\";\nimport Demo from \"./Demo.vue\";\n\nexport default defineComponent({\ncomponents: {\n  Demo,\n},\n});\n</script>`\n\nconst mainJs = `import { createApp } from \"vue\";\nimport naive from \"naive-ui\";\nimport App from \"./App.vue\";\n\nconst app = createApp(App);\n\napp.use(naive);\n\napp.mount(\"#app\");\n`\n\nfunction getDeps(code) {\n  return (code.match(/from '([^']+)'\\n/g) || [])\n    .map(v => v.slice(6, v.length - 2))\n    .reduce((prevV, dep) => {\n      prevV[dep] = 'latest'\n      return prevV\n    }, {})\n}\n\nexport function getCodeSandboxParams(code) {\n  return getParameters({\n    files: {\n      'package.json': {\n        content: {\n          dependencies: {\n            ...getDeps(code),\n            vue: 'latest',\n            'vue-router': 'latest',\n            'naive-ui': 'latest'\n          },\n          devDependencies: {\n            '@vue/cli-plugin-babel': '~4.5.0',\n            typescript: '~4.6.3'\n          }\n        }\n      },\n      'index.html': {\n        content: indexHtml\n      },\n      'src/Demo.vue': {\n        content: code\n      },\n      'src/App.vue': {\n        content: appVue\n      },\n      'src/main.js': {\n        content: mainJs\n      }\n    }\n  })\n}\n"
  },
  {
    "path": "demo/utils/composables.js",
    "content": "import { useBreakpoint, useMemo } from 'vooks'\nimport { inject, provide, reactive, toRef, watchEffect } from 'vue'\n\nexport function useIsMobile() {\n  const breakpointRef = useBreakpoint()\n  return useMemo(() => {\n    return breakpointRef.value === 'xs'\n  })\n}\n\nexport function useIsTablet() {\n  const breakpointRef = useBreakpoint()\n  return useMemo(() => {\n    return breakpointRef.value === 's'\n  })\n}\n\nexport function useIsSmallDesktop() {\n  const breakpointRef = useBreakpoint()\n  return useMemo(() => {\n    return breakpointRef.value === 'm'\n  })\n}\n\nexport function i18n(data) {\n  const localeReactive = inject('i18n', null)\n  return {\n    locale: toRef(localeReactive, 'locale'),\n    t(key) {\n      const { locale } = localeReactive\n      return data[locale][key]\n    }\n  }\n}\n\ni18n.provide = function (localeRef) {\n  const localeReactive = reactive({})\n  watchEffect(() => {\n    localeReactive.locale = localeRef.value\n  })\n  provide('i18n', localeReactive)\n}\n"
  },
  {
    "path": "demo/utils/composables.ts",
    "content": "import { useBreakpoint, useMemo } from 'vooks'\nimport { inject, provide, reactive, toRef, watchEffect } from 'vue'\n\nexport function useIsMobile() {\n  const breakpointRef = useBreakpoint()\n  return useMemo(() => {\n    return breakpointRef.value === 'xs'\n  })\n}\n\nexport function useIsTablet() {\n  const breakpointRef = useBreakpoint()\n  return useMemo(() => {\n    return breakpointRef.value === 's'\n  })\n}\n\nexport function useIsSmallDesktop() {\n  const breakpointRef = useBreakpoint()\n  return useMemo(() => {\n    return breakpointRef.value === 'm'\n  })\n}\n\nexport function i18n(data: Record<string, Record<string, string>>) {\n  const localeReactive = inject<{ locale: string } | null>('i18n', null)\n  if (!localeReactive) {\n    throw new Error('i18n context not provided')\n  }\n  return {\n    locale: toRef(localeReactive, 'locale'),\n    t(key) {\n      const { locale } = localeReactive\n      return data[locale][key]\n    }\n  }\n}\n\ni18n.provide = function (localeRef) {\n  const localeReactive = reactive<{ locale: string }>({ locale: '' })\n  watchEffect(() => {\n    localeReactive.locale = localeRef.value\n  })\n  provide('i18n', localeReactive)\n}\n"
  },
  {
    "path": "demo/utils/github-url.js",
    "content": "export const repoUrl = 'https://github.com/tusen-ai/naive-ui'\nexport const blobUrl = `${repoUrl}/blob/main/`\n"
  },
  {
    "path": "demo/utils/playground.js",
    "content": "export const playgroundUrl = 'https://play-naive.pro-components.cn'\nexport const appCode = `<template>\n  <n-config-provider>\n    <n-loading-bar-provider>\n      <n-message-provider>\n        <n-notification-provider>\n          <n-modal-provider>\n            <n-dialog-provider>\n              <Demo />\n            </n-dialog-provider>\n          </n-modal-provider>\n        </n-notification-provider>\n      </n-message-provider>\n    </n-loading-bar-provider>\n  </n-config-provider>\n</template>\n\n<script setup lang=\"ts\">\nimport Demo from './Demo.vue'\n</script>\n`\n"
  },
  {
    "path": "demo/utils/route.js",
    "content": "export function findMenuValue(options, path) {\n  for (const option of options) {\n    if (option.children) {\n      const value = findMenuValue(option.children, path)\n      if (value)\n        return value\n    }\n    if (option.path === path) {\n      return option.key\n    }\n  }\n  return undefined\n}\n"
  },
  {
    "path": "design-notes/design-token-status.md",
    "content": "## Color\n\n--color --color-hover --color-pressed --color-active --color-active-hover --color-active-pressed --color-focus --color-focus-hover --color-focus-active --color-focus-pressed --color-disabled --color-disabled-active\n\ndisabled-active > disabled > active-hover > active > pressed > hover > default\n"
  },
  {
    "path": "design-notes/how-to-name-a-style-var.md",
    "content": "# How to Name a Style Var\n\nFor example, you have a button, which has `default` and `error` type. How will you name the background color of the button.\n\n```\nbuttonColor\nerrorButtonColor\n```\n\nor\n\n```\nbuttonColor\nbuttonColorError\n```\n\nThe second is the better (The second is easy to extend and read. Also it follow the css pattern for example `padding-right` and `padding-left`).\n\nWhen it comes to hover style?\n\n```\nbuttonColor\nbuttonColorHover\nbuttonColorError\nbuttonColorErrorHover <-\n```\n\nor\n\n```\nbuttonColor\nbuttonColorHover\nbuttonColorError\nbuttonColorHoverError <-\n```\n\nThe second is the better since if you want write a map entity, you always loop on types. For example:\n\n```js\n// better\n;['Default', 'Error'].map((type) => [\n  'buttonColor' + type,\n  'buttonColorHover' + type\n])\n// worse, hard to maintain\n;['Default', 'Error'].map((type) => [\n  'button' + type + 'Color',\n  'buttonHover' + type + 'Color'\n])\n```\n"
  },
  {
    "path": "design-notes/maintaining.md",
    "content": "# 这个文档是为仓库维护者提供的\n\n## 关于 PR 合并\n\n1. docs、main 的 PR 都要 squash 合并。\n2. 分支间的合并使用最普通的 merge 合并（一定不要 squash，不要 rebase）\n\n## 发版流程\n\n1. 将 docs 合并到 main（发起一个 PR，CI 过了就合并）\n2. 拉下最新的 main\n3. 从 main checkout 到 release 分支\n4. 修改 package.json 版本号\n5. npm run gen-version\n6. 修改两个语言的 changelog 版本号（还有日期）\n7. 把改动提交到 release 分支，git commit -m \"x.x.x\"\n8. 将 release 分支合并到 main（发起一个 PR，CI 过了就合并）\n9. 回到 main 分支拉回最新的代码\n10. git clean -fdx && pnpm i && npm run release:package\n11. 将 main 合并到 docs（发起一个 PR，CI 过了就合并）\n\n## 提交信息\n\n### Commit Message\n\n使用 Angular Style，`feat(xxx): yyy`\n\n#### 注意事项\n\n- `feat(xxx)` 必须是组件，不能加 `n`，`feat(input)` ✅，`feat(n-input)` ❌\n- feat 或者是 fix 的话如果有对应的 issue 的话需要自己增加 comment 如 fix #514 或者 close #514\n\n## Changelog\n\n- 新增属性\n\n```\n- `n-xxx` add `xxx` prop.\n- `n-xxx` 新增 `xxx` 属性\n\n注意 `xxx` 属性必须是 kebab-case，不能是 camelCase。\n```\n\n- 修复 Bug\n\n```\n- Fix `n-xxx` ...\n- 修复 `n-xxx` ...\n```\n\n## PR checklist\n\n- [ ] 我在中文文档中使用了中文的标点符号（`（`、`，`、`、`）\n- [ ] 我在英文文档中使用了英文的标点符号\n- [ ] 我没有在中文 API Table 的描述中使用句号\n- [ ] 我在英文文档的 API Table description 中增加了句号\n- [ ] 我在中文和英文以及中文和数字之间添加了空格\n- [ ] 我在文档中的 prop 使用了 kebab-case\n- [ ] 文档的 API 表格按照字母顺序\n- [ ] feat 或者 fix 要注意有没有加 CHANGELOG\n- [ ] feat 尽量增加测试\n- [ ] 文档要精简，可读性好，没用的空格删除\n- [ ] 代码要精简，没用的代码删除\n- [ ] 测试代码不要牵扯太多无关代码，测试的方式要准确、灵活\n"
  },
  {
    "path": "design-notes/think.md",
    "content": "## git problem...\n\n我的锅...远程分支没设定好，推得哪个自己都不知道。\n\n## test 时候 vue v-model 产生的效果必须在 \\$nextTick() 之后才会产生，虽然它声称自己是同步的...\n\n我的锅，忘了为啥了。确实是同步的，是我没有考虑到 v-model 这东西应该用什么方法测试。\n\n## Vue loader 编译深度选择器出了问题\n\na >>> b 被编译成了 a > > > b\n\n## input 的 change 不随外界 props value 的改变改变\n\n其他的我还没想好\n\n## 2019.7.17 There may be a bug of chrome\n\n在一个 single filterable select 中，会出现一个 bug...，这个 bug 会让溢出屏幕的 item 不再显示。感觉可能是 Chrome 为了性能优化没有渲染一些在屏幕外面的东西，暂时通过 translateZ(0) 解决了。\n\n## 2019.7.17 Popover\n\npopover 的 hover 有问题，哎...一大堆东西闪来闪去就可能 mouseleave 没触发就一直留在那了\n\n## 2019.7.31 Margin 没有撑开元素\n\noverflow: hidden 可以解决，这是 BFC 的问题\n\n## 2019.8.1\n\nwidth: fit-content, min-content, max-content, intrinsic, extrinsic flex, flex-grow\n\n```\nrender (h) {\n    console.log(this.$props)\n    return h('div', {\n      staticClass: 'n-steps'\n    }, mapSteps({ ...this.$props }, this.$slots.default))\n  }\n```\n\n为什么 \\$props 不一样？解构赋值做了什么 document.querySelector('\\*[n-id=888d3] .simulate-transparent-text') 不合法？\n\n## 2019.8.8\n\n函数节流别忘了加上@scroll\n\n## 2019.8.27\n\nactivator 外面不应该包元素检查内存泄露可能性考虑级联异步 api placement \\$refs 变化更改\n\n## 2019.8.28\n\npicker 在 input 聚焦的时候，esc 按钮不符合预期\n\n## 2019.8.29\n\nblock transition for date picker in range not via :key\n\n## 2019.9.2\n\nselect menu 更加自治一点 比如 isSelected，可能最后要加到 vmodel 为止 tooltip css max-content 兼容性 popover z-index 问题\n\n## 2019.9.3\n\npopover 停止追踪的时机\n\n## 2019.9.24\n\npopover 可能 activator 和 content 不同步，在 beforeRouteEnter locale change 的时候！！！\n\n## 2019.9.28\n\nconfirm 有 bug = =...和 button 颜色相关，之后检查吧\n\n## 2019.10.21\n\nRadio Button 默认主题下是否 hollow out，这是个问题\n\n## 2019.11.14\n\nbase picker focus 问题\n\n## 2019.12.3\n\nDropdown Submenu 定位问题还有那个... Modal + border 的问题，怎么解决\n\n## 2019.12.20\n\nAnchor Bug 复现 at typography\n\n## 2019.12.23\n\nDamn eslint\n\n```\nWhat fixed it for me was using double quotes and an escaping slash like so:\n\"lint\": \"eslint \\\"**/*.{js,jsx}\\\" --quiet\",\n\nPreviously, it would not work with single quotes:\n\"lint\": \"eslint '**/*.{js,jsx}' --quiet\",\n```\n\n## 2019.12.30\n\n为了按需引入打包大小依旧可控，需要用某种方式让互相的依赖变为外部依赖。或者就维持原本的文件结构，这样的话需要的是 babel。看起来还是有点麻烦，之后再解决吧。\n\n## 2019.2.26\n\n虽然没啥用了，还是留着吧\n\n```\n/**\n* In Chrome, Firefox, Safari, this only happens when devtool opened\n* However only Chrome and Firefox will refocus at input element\n*/\nconst devtoolIsOpened = e.target === document.activeElement\n```\n\n## 2020.3.7\n\n主体差不多做完了，好累\n\n## 2020.3.8\n\nzindex 有点问题\n\n## 2020.3.11\n\nzindex 的问题解决了，虽然很简单，在 static 元素上设定 zindex 没用，😅\n\n## 2020.3.15\n\n在搞响应式页面的时候，我意识到存粹依赖 css 是一种不可靠的方式。虽然从布局层面 grid layout 已经给出了一种近乎完美的解决方案，但是涉及到一切内联样式的... 都需要从 js 的层面来解决。目前想来最 trival 的方式就是让每个 config consumer 都能拿到这个值。\n\n## 2020.3.20\n\n一想到到了 1.0 就要写 changelog，就感觉 🥚 在隐隐作痛\n\n## 2020.3.25\n\n一个有趣的事情是，blur 到 document.body 之后，document.activeElement 是 body，但是 blurEvent.relatedTarget 会被设为 null\n\n## 2020.5.18\n\nrerender 报警了\n\n```\nh('NLayout', {\n  ref: 'body',\n  style: { ...this.contentStyle },\n  props: {\n    'use-native-scrollbar': false,\n    'scroll-content-style': {\n      width: '100%',\n      boxSizing: 'border-box',\n      padding: this.paddingBody ? '21px 48px' : null\n    }\n  }\n}, null)\n```\n\n一个是 computed 导致重复渲染，还有一个是 getScrollParent 缓存的问题\n\n## 2020.5.19\n\n我在想要不要帮用户检查值，比如说一些不存在的值...现在这个问题就出现在 checkbox 里面，这是个哲学问题\n\n## 2020.5.19\n\n得看懂 vue 究竟是怎么更新组件的...\n\n## 2020.5.28\n\n目前看来，对于动态样式，有两种情况，一种是像直接通过 prop 生效，另一种是通过组合才生效，比如 error 的 formitem 与 input，判断是否要生成样式是个比较麻烦的事，目前看来比较凑巧的是这个样式的体积不是很大，其实放在哪边都差不多= =\n\n## 2020.5.29\n\n主题变量有两种组织方式：\n\n```\nlight {\n  error: {\n    backgroundColor: {\n      hover\n    }\n  }\n}\n或者\nlight {\n  backgroundColor: {\n    error: {\n      default\n    }\n  }\n}\n```\n\n我目前觉得第一种好点，因为扩展一般是按照种类扩展，每次插入一个同样结构的块。而第二种是每次扩展的时候在每个块里同样的位置插入一行，这样扩展的时候写起来很别扭。\n\n## 2020.7.1\n\nshouldMount 可以加到 withCssr\n\n## 2020.7.8\n\nstyle overrides RFC\n\n## 2020.8.2\n\n颜色命名的方式\n\n```\n1.\n{\n  xColor,\n  xActiveColor,\n  xDisabledColor,\n  secondaryTextColor,\n  tertiaryTextColor\n},\n{ // 这种拒绝，因为只有一个状态也需要 default\n  xColor: {\n    default,\n    active,\n    disabled\n  }\n}\n// 现在感觉第三种比较好\n{\n  xColor,\n  xColorActive,\n  xColorDisabled,\n  textColor2, // 暂时可以先不改\n  textColor3, //\n  textColorDisabled,\n  textColor1,\n  textColor2,\n  textColor3,\n  textColorQ...\n}\n// 还有一点是去掉 backgroundColor 中的 background，因为 color & textColor 区分度已经够了\n```\n\n```js\n// no import on demand\nimport naive from 'naive-ui'\n\nnaive.Button.overrideStyles({\n  light: {\n    borderRadius: 8\n  },\n  dark: {\n    borderRadius: 8\n  }\n})\n\nnaive.InputNumber.overrideStyles({\n  light: {\n    borderRadius: 8\n  },\n  dark: {\n    borderRadius: 8\n  }\n})\n\nnaive.themes.light.overrideStyles({\n  primaryColor: '1234'\n})\n\nVue.use(naive)\n```\n\n```js\n// import on demand\n\n// essential\nimport create from 'naive-ui/create'\nimport lightStyle from 'naive-ui/styles/light'\nimport darkStyle from 'naive-ui/styles/dark'\n\n// components\nimport Button from 'naive-ui/button'\n\n// styles\nimport buttonLightStyle from 'naive-ui/button/styles/light'\nimport buttonDarkStyle from 'naive-ui/button/styles/dark'\n\ncreate({\n  components: [Button],\n  styles: [\n    // base styles, required for each theme\n    lightStyle,\n    darkStyle,\n    // component styles\n    buttonLightStyle,\n    buttonDarkStyle\n  ]\n})\n```\n\n## 2020.10.22\n\n```js\n// extend Element.prototype.scrollTo\n// override 1 (xCoord, yCoord) keep it\n// overried 2 ScrollOptions\n// ScrollOptions {\n//   x: number,\n//   y: number,\n//   behavior: 'auto' | 'smooth'\n//   index?: number\n//   key?: number\n//   el?: Element\n//   position?: 'bottom' | 'top',\n//   slient?: boolean\n// }\n```\n\n## TODO 排序不分先后\n\n1. <del>Focus Detector on Time Selector</del>\n2. <del>Menu Root Indent = 0 可能造成问题</del>\n3. <del>用 RAF 优化 scrollbar 性能（不一定需要）</del>为了有时候滚动同步的一致性，决定不做了\n4. <del>Anchor 切换有 bug，忽然闪现第一个</del>\n5. <del>Safari select lightbar container overflow 边角（或许是 webkit 的问题）</del>默认选中第一个可以装作这个问题不存在\n6. <del>Chrome lightbar offset @table fitler</del> select menu 始终存在这个问题，不知道原因是什么\n7. <del>cascader 数据结构重构，维持原选项！</del> 这个不做了，对 Children 的处理过于边角，Patch 那块也会从声明式变成命令式\n8. <del>排查 render 函数是否每个地方都支持数组</del> 我现在明白了，只要套上数组，vue 就能完美的渲染\n9. <del>form async validation</del>\n10. <del>table filter 重构支持异步</del>\n11. <del>tabs resize bug</del>\n12. <del>CSS 整理</del> 暂且算做完了\n13. <del>落地页</del>\n14. <del>按需引入 babel plugin</del> 这个不做了，收益不大，工作量不小\n15. <del>form table 需要 size</del>\n16. <del>input number 需要一个小型的</del> 目前看来也不是很必要，input number 其实可以很小\n17. <del>layout scroll api</del>\n18. <del>cascader select menu disabled 选项</del>\n19. <del>icon 的默认 stroke</del>\n20. <del>tree 组件</del>\n21. <del>文件上传组件</del>\n22. <del>custom-input 废弃或者重构</del>\n23. <del>Date 键盘操作 Time 键盘操作</del> 先把能做的做了\n24. <del>Time 格式化</del>\n25. <del>Date 格式化</del>\n26. <del>base cancel mark rename suffix</del>\n27. <del>base picker => base selection</del>\n28. <del>base lightbar => base tracking rect</del>\n29. <del>loader 区分 debug 和 非 debug</del>\n30. <del>逐步放宽对宽度必需传 number 的现实，尤其是对于 table</del>\n31. <del>BaseLoading 代替 Log 里的 Spin</del>\n32. <del>Modal 内部组件的卸载方式</del>\n33. <del>Anchor 的另一种模式，追踪内容按照的是中间范围而不是自身大小</del>\n34. <del>bug md-loader alert 内的 code 不显示</del> 不是 bug，md 就这么渲染\n35. <del>backtop mounted blink</del>\n36. <del>Tab keep alive</del>\n37. <del>Cascader submenu 的 lightbar 用 base tracking rect 代替</del>\n38. <del>Dropdown 样式微调</del>\n39. <del>Card 用 padding 代替 margin 来避免 margin 折叠的问题</del> 不做了，要是想避免折叠让用户自己写 bfc 吧\n40. <del>检查 Icon 在 button 中切换有没有问题，直觉来说应该没问题</del>\n41. <del>Radio Group 和 Steps 的镂空效果在 mounted 的时候 transition 没有关闭</del>\n42. <del>Typography 文档待更新</del>\n43. <del>Tab 文档待更新</del>\n44. <del>Icon 文档待更新</del>\n45. <del>把 Upload 的回调 API 从 promise 改成 callback 格式的，文档也要对应修改</del> 我决定全面提供 Promise API 而不是 callback 风格的\n46. <del>Date Picker 的 format 文档内容</del>s\n47. <del>Button Group 样式</del>\n48. <del>text button icon</del>\n49. <del>tab scroll 计算有潜在 bug</del>\n50. <del>data-table 的 header height 为啥要固定？因为固定列的问题，sticky 解决了就没事</del>\n51. <del>scrollbar 在平时不显示用不到的 rail</del>\n52. <del>placeholder transition 对 firefox 做兼容</del>\n53. <del>调整 date picker 的尺寸</del>s\n54. <del>Select option 右侧 padding 调整</del>\n55. <del>Popover arrow shadow 调整</del>\n56. <del>Input number 按钮样式调整</del>\n57. <del>一部分组件在 Modal 内部的样式</del> 还差 data table 的选项们\n58. <del>更新 Progress 文档</del>\n59. <del>为所有的数据录入组件的尺寸</del>\n60. <del>审核文档</del> 就这样吧，凑活\n61. <del>调整 transfer 的样式</del>\n62. <del>Table cascader 差一点国际化</del>\n63. <del>Anchor 初次滚动的逻辑是不是要手动调整一下，现在位置实际上不一致</del>\n64. <del>将所有的 Typography 组件改为非 Functional 的，因为获取不到 context 本身的主题</del>\n65. <del>搞明白 table layout 这个 css 属性是在干什么</del>\n66. <del>Icon 颜色</del> 原来我早就解决了，都忘了...\n67. <del>Modal 滚动之后的 transform origin</del>\n68. <del>Slider 对于 modal 适配</del>\n69. <del>table fixed scroll checkbox, not sync</del>\n70. <del>Transfer no data</del>\n71. <del>Metropolis 从自带字体去掉<del>\n72. <del>Input Group</del>\n73. <del>Dropdown API 修改为 label + value，目前为止 UI 并没有出现过 key，不能只为了它搞特殊，value 可以，key 甚至会另有作用，现在占用实际是个危险的事情</del>\n74. <del>card slot</del>\n75. <del>table fixed computed left right</del>\n76. <del>gradient text 的切换能解决？</del>目前我想不出解决办法，希望未来 CSS 能增加 gradient 的渐变\n77. <del>Auto Complete Group</del>\n78. <del>select add tag</del>\n79. <del>dynamic input</del> 还差英文文档\n80. <del>input 严格受控</del>\n81. <del>搞明白 vue 的 scoped 和 普通的关系</del>\n82. <del>Form Item 不返回 true 的时候... 错误信息不会消失，这似乎不太合理?</del> async-validator 的特性\n83. <del>Form Item 应该和 Input Group 也契合良好</del> 能用\n84. <del>Notification 主题切换需要工作良好</del>\n85. <del>Notification 这个东西很特殊...</del>感觉也没那么特殊\n86. <del>文件上传的回调方式改成传对象</del>\n87. 抵御外界 CSS 变化，比如 line-height 之类的，需要一个良好的测试机制\n88. <del>CSS Font 选择</del> 对英文应该没有那么麻烦，走系统字体就好了，然而对中文又没什么好的解决方案，so 先这个样子，之后再琢磨琢磨\n89. <del>把所有用 $slots 判断的地方都改成 $scopedSlots，[原因](https://vuejs.org/v2/api/#vm-scopedSlots)<del> done\n90. <del>调整默认状态下 button, input 的 icon 的颜色</del>\n91. <del>优化 button 的样式，现在太冗余了，关键是怎么同步按钮的主题变量呢...</del>\n92. <del>placeable 按需注册</del>\n93. steps 列表优化\n94. tabs 列表优化\n95. tree 列表优化\n96. <del>cascader 列表优化</del>\n97. 更多的 tabs 选择\n98. <del>下拉菜单应该给 icon 留空间</del>\n99. <del>Form item feedback 好像有点问题，消失的时候，自定义时候</del>\n100. <del>Confim 重命名 Dialog</del> 算了不换了，牵扯的地方太多不好改了，confirm 也就凑活吧\n101. Dark Debug 3，Safari 你可太秀了......\n102. <del>close-outline icon</del>\n103. <del>input + icon 主题切换 transition 有问题!!!</del>\n104. <del>auto-complete 自定义元素 demo 有问题</del> 有 pendingData 的时候 preventDefault\n105. <del>markdown 渲染缺少空格，修正了 n-select single filterable 时 placeholder 的样式问题</del> caused by vue compiler `preserveWhitespace: false`, change it to `whitespace: 'condense'`\n106. <del>drawer 加上滚动条，以及 overflow auto 的样式</del>\n107. <del>所有弹出的东西改成 body-style</del>\n108. <del>size 切换的时候... transfer 动画问题</del>\n109. 利用了公用组件的组件样式没办法特殊调教，比如 select 组件自身是没有命名空间的，这个想要单独定制就比较麻烦。先不出来怎么解决\n110. <del>treemate 重构 cascader，异步 api 需要更改</del>\n111. 样式不能被 cloned，因为 peers 机制\n\n```\nDone\n// modal transform scale\n// Notification content close\n// form required css\n// Md Loader 对于 strong 的处理\n// pref hollowout, cache next bg color\n// issue fix, add delay prop\n// add trigger to tooltip\n// outside click delegate select\n// DatePicker range Bug\n// Scrollbar Firefox...\n// scrollbar 在 resize 之后滚动会有问题\n// ResizeObserver Polyfill\n// Select 需要进一步重构，现在这种状况 collector 在 corner case 中不会调 updated 钩子，要把 key 换成 value\n```\n\n```cache\n需要注意的是，以 Base 开头的 CSS 文件并不会确保随着版本的更新保持稳定（我会尽力的保持）。因为它是内部实现的一部分。如果你维持按需引入时升级后样式出现了错误，可以来这里检查一下。虽然把这些公共样式各自打包进每个用到他们的组件是可行的，但是相比于升级的繁琐，我更不喜欢重复的代码。（这不意味着这种解决方案是“更好的”，它只是种选择而已）\n\nWhat should be noted is the CSS files start with 'Base' are not guaranteed to be stable (I'll try not to change them). Because they are parts of internal implementation of the library. If you find import mistakes after upgrade the package, you may have a look at here. It is possible to pack these common styles inside every component using it. However, compared to add routines when upgrading package, I perfer not to import duplicate codes. (It doesn't mean this is a better solution. It is only a choice.)\n```\n\nHow I want to use styling API ?\n\n```js\n// index.js\nimport { createApp } from 'vue'\nimport { create, enUS, buttonLight, inputLight } from 'naive-ui'\n\nconst app = createApp()\nconst naive = create({\n  // install components globally or import it in other component are both ok\n  // components: [\n  //   Button,\n  //   Input\n  // ],\n  styles: [buttonLight, inputLight],\n  locales: [enUS]\n})\n\napp.use(naive)\n```\n\n## 2020.11.14 是否要给 icon 加上默认的 color transition?\n\n否。前提条件是 svg 在合适的地方用到了 currentColor。\n\nfor example:\n\n```\n<n-icon>\n  <svg>\n    <line stroke=\"currentColor\">\n  </svg>\n</n-icon>\n```\n\n我期望的是 n-icon 一直跟着外部走，如果外面有 transtion 了那内部其实不需要 transition，不然的话会重叠。如果一定需要 transition 的话应该去保证样式带 color transition。\n"
  },
  {
    "path": "design-notes/todo.md",
    "content": "# TODO\n\n## Urgent\n\n- message fullscreen\n- use resolve slot!!!\n- manual trigger style\n\n## DataTable\n\n## Form\n\n- (easy) message support render function\n\n## Popover\n\n## Radio\n\n- (easy) Button custom align & width\n\n## Select\n\n## Tabs\n\n- (moderate) Left, right tabs\n\n## Tree\n\n- (moderate) Use set to check if node is checked or selected internally\n\n## TreeSelect\n\n- (moderate) Async\n\n## DatePicker\n\n- Do not allow start > end\n\nhttps://github.com/tusen-ai/naive-ui/pull/4853 Later-\n"
  },
  {
    "path": "eslint.config.mjs",
    "content": "import antfu from '@antfu/eslint-config'\n\nexport default antfu(\n  {\n    languageOptions: {\n      ecmaVersion: 'latest',\n    },\n    regexp: false,\n    ignores: [\n      'node_modules',\n      'lib',\n      'test/unit/coverage',\n      'src/_deprecated/icons',\n      'dist',\n      'es'\n    ]\n  },\n  {\n    files: ['**/*.demo.vue'],\n    rules: {\n      'no-console': 'off',\n      'vue/one-component-per-file': 'off'\n    }\n  },\n  {\n    files: ['**/*.tsx'],\n    rules: {\n      'unused-imports/no-unused-imports': 'off'\n    }\n  },\n  {\n    files: ['**/*'],\n    rules: {\n      'style/multiline-ternary': 'off',\n      'style/max-statements-per-line': 'off',\n      'style/comma-dangle': 'off',\n      'style/quote-props': 'off',\n      'jsdoc/require-returns-description': 'off',\n      'jsdoc/check-param-names': 'off'\n    }\n  }\n)\n"
  },
  {
    "path": "esm-test/index.spec.js",
    "content": "import { NDataTable } from '../dist/index.prod.mjs'\nimport { createApp } from 'vue'\n\n// eslint-disable-next-line n/no-exports-assign\nexports = undefined\n\ndescribe('esm', () => {\n  it('works', () => {\n    const div = document.createElement('div')\n    document.body.appendChild(div)\n    createApp(NDataTable).mount(div)\n    expect(div.innerHTML).toContain('n-data-table')\n  })\n})\n"
  },
  {
    "path": "generic/AvatarGroup.vue",
    "content": "<script\n  lang=\"ts\"\n  setup\n  generic=\"T extends AvatarGroupOption = AvatarGroupOption\"\n>\nimport type {\n  AvatarGroupOption,\n  GAvatarGroupProps,\n  GAvatarGroupSlots\n} from 'naive-ui'\nimport { NAvatarGroup } from 'naive-ui'\n\ndefineProps<GAvatarGroupProps<T>>()\ndefineSlots<GAvatarGroupSlots<T>>()\n</script>\n\n<template>\n  <NAvatarGroup v-bind=\"$props\">\n    <template #avatar=\"props\">\n      <slot name=\"avatar\" v-bind=\"props as any\" />\n    </template>\n    <template #rest=\"props\">\n      <slot name=\"rest\" v-bind=\"props as any\" />\n    </template>\n  </NAvatarGroup>\n</template>\n"
  },
  {
    "path": "generic/index.ts",
    "content": "export { default as NGAvatarGroup } from './AvatarGroup.vue'\n"
  },
  {
    "path": "index.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n  <head>\n    <!-- Google tag (gtag.js) -->\n    <script\n      async\n      src=\"https://www.googletagmanager.com/gtag/js?id=G-15QSS7T6SH\"\n    ></script>\n    <script>\n      window.dataLayer = window.dataLayer || []\n      function gtag() {\n        dataLayer.push(arguments)\n      }\n      gtag('js', new Date())\n\n      gtag('config', 'G-15QSS7T6SH')\n    </script>\n    <meta charset=\"utf-8\" />\n    <meta\n      name=\"viewport\"\n      content=\"width=device-width, initial-scale=1, maximum-scale=1\"\n    />\n    <title>Naive UI</title>\n    <meta name=\"naive-ui-style\" />\n    <meta name=\"vueuc-style\" />\n    <link\n      rel=\"icon\"\n      type=\"image/svg+xml\"\n      href=\"/demo/assets/images/naivelogo.svg\"\n    />\n  </head>\n  <body>\n    <script>\n      const path = window.location.pathname\n      const pathLocale = path.startsWith('/en-US')\n        ? 'en-US'\n        : path.startsWith('/zh-CN')\n          ? 'zh-CN'\n          : undefined\n      function deriveTitleFromLocale(locale = navigator.language) {\n        if (locale === 'zh-CN') {\n          document.title = 'Naive UI: 一个 Vue 3 组件库'\n        } else {\n          document.title = 'Naive UI: A Vue 3 Component Library'\n        }\n      }\n      deriveTitleFromLocale(pathLocale)\n    </script>\n    <div id=\"app\"></div>\n    <script type=\"module\" src=\"__INDEX__\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "package.json",
    "content": "{\n  \"name\": \"naive-ui\",\n  \"version\": \"2.44.1\",\n  \"packageManager\": \"pnpm@10.29.2\",\n  \"description\": \"A Vue 3 Component Library. Fairly Complete, Theme Customizable, Uses TypeScript, Fast\",\n  \"author\": \"07akioni\",\n  \"license\": \"MIT\",\n  \"homepage\": \"https://www.naiveui.com\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/tusen-ai/naive-ui\"\n  },\n  \"keywords\": [\n    \"naive-ui\",\n    \"component library\",\n    \"ui framework\",\n    \"ui\",\n    \"vue\"\n  ],\n  \"sideEffects\": false,\n  \"main\": \"lib/index.js\",\n  \"module\": \"es/index.mjs\",\n  \"unpkg\": \"dist/index.js\",\n  \"jsdelivr\": \"dist/index.js\",\n  \"types\": \"es/index.d.ts\",\n  \"files\": [\n    \"README.md\",\n    \"dist\",\n    \"es\",\n    \"generic\",\n    \"lib\",\n    \"volar.d.ts\",\n    \"web-types.json\"\n  ],\n  \"engines\": {\n    \"node\": \">=20\"\n  },\n  \"scripts\": {\n    \"start\": \"pnpm run dev\",\n    \"dev\": \"pnpm run clean && pnpm run gen-version && pnpm run gen-volar-dts && NODE_ENV=development vite\",\n    \"build:package\": \"pnpm run gen-version && pnpm run clean && pnpm run gen-volar-dts && tsc -b --force tsconfig.esm.json && tsx scripts/pre-build/pre-cjs-build.ts && tsc -b --force tsconfig.cjs.json && rollup -c && pnpm run test:umd && pnpm run test:esm && pnpm run post-build && rimraf {es,lib}/*.tsbuildinfo\",\n    \"build:themes\": \"tsc -b --force themes/tusimple/tsconfig.esm.json && tsc -b --force themes/tusimple/tsconfig.cjs.json\",\n    \"build:site\": \"bash ./scripts/pre-build-site/pre-build-site.sh && NODE_ENV=production NODE_OPTIONS=--max-old-space-size=4096 vite build && bash ./scripts/post-build-site/post-build-site.sh\",\n    \"clean\": \"rimraf site lib es dist node_modules/naive-ui themes/tusimple/es themes/tusimple/lib\",\n    \"release:package\": \"pnpm run test && pnpm run build:package && pnpm publish --no-git-checks\",\n    \"release:changelog\": \"tsx scripts/release-changelog.ts\",\n    \"lint\": \"pnpm run lint:code && pnpm run lint:type\",\n    \"lint:type\": \"pnpm run lint:src-type && pnpm run lint:demo-type\",\n    \"lint:code\": \"eslint \\\"{src,build,scripts,demo}/**/*.{ts,tsx,js,vue,md}\\\"\",\n    \"lint:fix\": \"eslint --fix \\\"{src,build,scripts,demo}/**/*.{ts,tsx,js,vue,md}\\\"\",\n    \"lint:src-type\": \"tsc -b --force tsconfig.esm.json\",\n    \"lint:demo-type\": \"NODE_OPTIONS=--max-old-space-size=4096 vue-tsc -p src/tsconfig.demo.json\",\n    \"format\": \"pnpm run format:code && pnpm run format:md && pnpm run lint:fix\",\n    \"format:code\": \"prettier --write \\\"{src,demo,scripts,build}/**/*.{vue,js,ts,tsx}\\\"\",\n    \"format:md\": \"prettier --write --parser markdown --prose-wrap never \\\"(src|demo)/**/*.md\\\"\",\n    \"test\": \"vitest run\",\n    \"test:update\": \"vitest --run --update\",\n    \"test:cov\": \"vitest run --coverage\",\n    \"test:watch\": \"vitest --watch\",\n    \"test:umd\": \"vitest run umd-test/index.spec.js\",\n    \"test:esm\": \"vitest run esm-test/index.spec.js\",\n    \"gen-version\": \"tsx scripts/gen-version.ts\",\n    \"gen-volar-dts\": \"tsx scripts/gen-component-declaration.ts\",\n    \"post-build\": \"tsx scripts/post-build/index.ts\",\n    \"build:site:ts\": \"bash ./scripts/pre-build-site/pre-build-site.sh && TUSIMPLE=true NODE_ENV=production NODE_OPTIONS=--max-old-space-size=4096 vite build && bash ./scripts/post-build-site/post-build-site.sh\",\n    \"prepare\": \"husky\",\n    \"transpile-docs\": \"tsx scripts/md-to-vue.ts\",\n    \"release:site\": \"TUSIMPLE=true pnpm run build:site && node build-doc/generate-deploy-sh.js && sudo bash build-doc/deploy-doc.sh\"\n  },\n  \"web-types\": \"./web-types.json\",\n  \"peerDependencies\": {\n    \"vue\": \"^3.0.0\"\n  },\n  \"dependencies\": {\n    \"@css-render/plugin-bem\": \"^0.15.14\",\n    \"@css-render/vue3-ssr\": \"^0.15.14\",\n    \"@types/lodash\": \"^4.17.20\",\n    \"@types/lodash-es\": \"^4.17.12\",\n    \"async-validator\": \"^4.2.5\",\n    \"css-render\": \"^0.15.14\",\n    \"csstype\": \"^3.1.3\",\n    \"date-fns\": \"^4.1.0\",\n    \"date-fns-tz\": \"^3.2.0\",\n    \"evtd\": \"^0.2.4\",\n    \"highlight.js\": \"^11.8.0\",\n    \"lodash\": \"^4.17.21\",\n    \"lodash-es\": \"^4.17.21\",\n    \"seemly\": \"^0.3.10\",\n    \"treemate\": \"^0.3.11\",\n    \"vdirs\": \"^0.1.8\",\n    \"vooks\": \"^0.2.12\",\n    \"vueuc\": \"^0.4.65\"\n  },\n  \"devDependencies\": {\n    \"@antfu/eslint-config\": \"^5.3.0\",\n    \"@babel/core\": \"^7.28.0\",\n    \"@babel/generator\": \"^7.28.0\",\n    \"@babel/parser\": \"^7.28.0\",\n    \"@babel/preset-env\": \"^7.28.0\",\n    \"@babel/traverse\": \"^7.28.0\",\n    \"@lylajs/web\": \"^2.1.0\",\n    \"@rollup/plugin-babel\": \"^6.0.4\",\n    \"@rollup/plugin-commonjs\": \"^28.0.6\",\n    \"@rollup/plugin-node-resolve\": \"^16.0.1\",\n    \"@rollup/plugin-replace\": \"^6.0.2\",\n    \"@rollup/plugin-terser\": \"^0.4.4\",\n    \"@types/babel__core\": \"^7.20.5\",\n    \"@types/babel__generator\": \"^7.27.0\",\n    \"@types/babel__traverse\": \"^7.28.0\",\n    \"@types/estree\": \"^1.0.1\",\n    \"@types/fs-extra\": \"^11.0.4\",\n    \"@types/node\": \"^24.0.12\",\n    \"@types/superagent\": \"^8.1.9\",\n    \"@vicons/fluent\": \"^0.13.0\",\n    \"@vicons/ionicons4\": \"^0.13.0\",\n    \"@vicons/ionicons5\": \"^0.13.0\",\n    \"@vitejs/plugin-vue\": \"^6.0.0\",\n    \"@vitest/coverage-v8\": \"^3.2.4\",\n    \"@vue/compiler-sfc\": \"^3.5.21\",\n    \"@vue/server-renderer\": \"^3.5.21\",\n    \"@vue/test-utils\": \"^2.4.6\",\n    \"autoprefixer\": \"^10.4.21\",\n    \"codesandbox\": \"^2.2.3\",\n    \"cssnano\": \"^7.1.0\",\n    \"deepmerge\": \"^4.3.1\",\n    \"esbuild\": \"0.25.10\",\n    \"eslint\": \"^9.6.0\",\n    \"express\": \"^5.1.0\",\n    \"fast-glob\": \"^3.3.1\",\n    \"fflate\": \"^0.8.2\",\n    \"fs-extra\": \"^11.3.0\",\n    \"grapheme-splitter\": \"^1.0.4\",\n    \"husky\": \"^9.1.7\",\n    \"inquirer\": \"^12.7.0\",\n    \"jsdom\": \"^27.0.0\",\n    \"katex\": \"^0.16.28\",\n    \"lint-staged\": \"^16.1.6\",\n    \"marked\": \"^12.0.2\",\n    \"prettier\": \"^3.6.2\",\n    \"rimraf\": \"^6.0.1\",\n    \"rollup\": \"^4.45.1\",\n    \"rollup-plugin-esbuild\": \"^6.2.1\",\n    \"superagent\": \"^10.2.2\",\n    \"tsx\": \"^4.20.3\",\n    \"typescript\": \"^5.9.2\",\n    \"vfonts\": \"^0.0.3\",\n    \"vite\": \"^7.0.4\",\n    \"vitest\": \"^3.2.4\",\n    \"vue\": \"^3.5.21\",\n    \"vue-router\": \"^4.5.1\",\n    \"vue-tsc\": \"^3.0.7\"\n  },\n  \"pnpm\": {\n    \"overrides\": {\n      \"cssstyle\": \"5.2.1\"\n    },\n    \"peerDependencyRules\": {\n      \"ignoreMissing\": [\n        \"@babel/core\",\n        \"postcss\",\n        \"rollup\",\n        \"webpack\"\n      ]\n    }\n  },\n  \"lint-staged\": {\n    \"*.js\": [\n      \"prettier --write\",\n      \"eslint --fix\"\n    ],\n    \"*.ts\": [\n      \"prettier --write\",\n      \"eslint --fix\"\n    ],\n    \"*.tsx\": [\n      \"prettier --write\",\n      \"eslint --fix\"\n    ],\n    \"*.vue\": [\n      \"prettier --parser=vue --write\",\n      \"eslint --fix\"\n    ],\n    \"*.css\": [\n      \"prettier --write\"\n    ],\n    \"*.md\": [\n      \"prettier --write --parser markdown --prose-wrap never\",\n      \"eslint --fix\"\n    ]\n  }\n}\n"
  },
  {
    "path": "playground/collect-vars.js",
    "content": "const varRegex = /var\\(--([^)]+)\\)/g\n\nfunction getVars (input) {\n  console.log(\n    Array.from(\n      new Set(Array.from(input.matchAll(varRegex)).map((v) => '// --' + v[1]))\n    )\n      .sort()\n      .join('\\n')\n  )\n}\n\ngetVars(document.body.textContent)\n"
  },
  {
    "path": "playground/ssr/app.js",
    "content": "import { h, defineComponent, ref } from 'vue'\nimport { NButton } from 'naive-ui'\n\nconst App = defineComponent({\n  setup () {\n    return {\n      count: ref(0)\n    }\n  },\n  render () {\n    return [\n      h(\n        NButton,\n        {\n          onClick: () => this.count++\n        },\n        { default: () => this.count }\n      )\n    ]\n  }\n})\n\nexport default App\n"
  },
  {
    "path": "playground/ssr/build.sh",
    "content": "webpack ./client.js --mode=development --output-filename=client.js\nwebpack --config ./webpack.config.server.js"
  },
  {
    "path": "playground/ssr/client.js",
    "content": "import { createApp } from 'vue'\nimport App from './app'\n\ncreateApp(App).mount('#app')\n"
  },
  {
    "path": "playground/ssr/pre-build.sh",
    "content": "# make sure cwd is the sh's dir\n\ncd ./../../\n\n./scripts/pre-build-site/pre-build-site.sh\n"
  },
  {
    "path": "playground/ssr/readme.md",
    "content": "You need to install `webpack` & `webpack-cli` globally.\n\n```\n./pre-build.sh\n./build.sh\n\nnode dist/server.js\n\n# browse localhost:8086\n```\n"
  },
  {
    "path": "playground/ssr/server.js",
    "content": "const fs = require('fs')\nconst path = require('path')\nconst express = require('express')\nconst { createSSRApp } = require('vue')\nconst { renderToString } = require('@vue/server-renderer')\nconst { setup } = require('@css-render/vue3-ssr')\nconst { default: App } = require('./app')\n\nconst server = express()\n\n// serve js\nserver.use((req, res, next) => {\n  if (req.path.endsWith('.js')) {\n    // the file will be in dist folder after build\n    // so no `dist` is required in path.resolve\n    res.send(fs.readFileSync(path.resolve(__dirname, 'client.js'), 'utf8'))\n  } else {\n    next()\n  }\n})\n\n// serve html\nserver.use((req, res, next) => {\n  if (req.path.endsWith('.js')) {\n    next()\n    return\n  }\n  const ssrApp = createSSRApp(App)\n  res.write('<!DOCTYPE html><html><head><title>SSR Test</title></head><body>')\n  const { collect } = setup(ssrApp)\n  renderToString(ssrApp).then((html) => {\n    res.write(collect())\n    res.write(`<div id=\"app\">${html}</div>`)\n    res.write('<script src=\"dist/client.js\"></script></body></html>')\n    res.end()\n  })\n})\n\nserver.listen(8086)\n"
  },
  {
    "path": "playground/ssr/webpack.config.server.js",
    "content": "module.exports = {\n  mode: 'development',\n  externalsPresets: { node: true },\n  externals: [/^[@/a-z\\-0-9]+$/],\n  target: 'node',\n  entry: './server.js',\n  output: {\n    filename: 'server.js',\n    library: {\n      type: 'commonjs2'\n    }\n  }\n}\n"
  },
  {
    "path": "playground/testAsyncValidator.js",
    "content": "const Schema = require('async-validator')\n\nconst descriptor = {\n  value: {\n    type: 'string',\n    required: true,\n    validator: () => true\n  }\n}\n\nconst validator = new Schema(descriptor)\n\nvalidator.validate({\n  value: '123'\n}, (errors, fields) => {\n  console.log('wtf')\n})\n"
  },
  {
    "path": "playground/testColor.js",
    "content": "const tinyColor = require('tinycolor2')\n\nconst red = tinyColor('#ce347c').getBrightness()\nconst green = tinyColor('#00c060').getBrightness()\nconst orange = tinyColor('#EF8745').getBrightness()\nconst blue = tinyColor('#2090f0').getBrightness()\nconsole.log(red, green, orange, blue)\n"
  },
  {
    "path": "playground/uploadServer.js",
    "content": "const express = require('express')\nconst multer = require('multer')\nconst cors = require('cors')\nconst path = require('path')\nconst fs = require('fs')\n\nconst app = express()\nconst dest = path.resolve(__dirname, 'temp')\nconst upload = multer({ dest })\n\napp.options('/upload-test', cors())\napp.post(\n  '/upload-test',\n  cors(),\n  function (req, res, next) {\n    req.on('close', () => {\n      console.log('文件上传取消')\n    })\n    req.on('error', () => {\n      console.log('文件上传出错')\n    })\n    next()\n  },\n  upload.any(),\n  function (req, res, next) {\n    if (!fs.existsSync(dest)) fs.mkdirSync(dest)\n    console.log(req.headers)\n    console.log(req.body)\n    res.send('very good')\n  }\n)\n\napp.listen(3000)\n"
  },
  {
    "path": "postcss.config.js",
    "content": "// this file is used by vite, keep it here\nmodule.exports = {\n  plugins: [\n    require('autoprefixer'),\n    require('cssnano')({\n      preset: [\n        'default',\n        {\n          normalizeWhitespace: false,\n          colormin: false\n        }\n      ]\n    })\n  ]\n}\n"
  },
  {
    "path": "rollup.config.mjs",
    "content": "import path from 'node:path'\nimport { fileURLToPath } from 'node:url'\nimport babel from '@rollup/plugin-babel'\nimport commonjs from '@rollup/plugin-commonjs'\nimport nodeResolve from '@rollup/plugin-node-resolve'\nimport replace from '@rollup/plugin-replace'\nimport terser from '@rollup/plugin-terser'\nimport merge from 'deepmerge'\nimport { defineConfig } from 'rollup'\nimport esbuild from 'rollup-plugin-esbuild'\n\nconst __filename = fileURLToPath(import.meta.url)\nconst __dirname = path.dirname(__filename)\n\nconst extensions = ['.mjs', '.js', '.json', '.ts']\n\nconst baseConfig = defineConfig({\n  input: path.resolve('./src/index.ts'),\n  external: ['vue'],\n  plugins: [\n    nodeResolve({ extensions }),\n    esbuild({\n      tsconfig: path.resolve(__dirname, 'tsconfig.esbuild.json'),\n      target: 'esnext',\n      sourceMap: true\n    }),\n    babel({\n      extensions,\n      babelHelpers: 'bundled'\n    }),\n    commonjs()\n  ]\n})\n\nconst umdConfig = defineConfig({\n  output: {\n    name: 'naive',\n    format: 'umd',\n    exports: 'named',\n    globals: {\n      vue: 'Vue'\n    }\n  }\n})\n\nconst esmConfig = defineConfig({\n  output: {\n    format: 'esm'\n  }\n})\n\nconst devConfig = defineConfig({\n  plugins: [\n    replace({\n      values: {\n        __DEV__: JSON.stringify(true),\n        'process.env.NODE_ENV': JSON.stringify('development')\n      },\n      preventAssignment: true\n    })\n  ]\n})\n\nconst umdDevOutputConfig = defineConfig({\n  output: {\n    file: path.resolve('dist/index.js')\n  }\n})\n\nconst esmDevOutputConfig = defineConfig({\n  output: {\n    file: path.resolve('dist/index.mjs')\n  }\n})\n\nconst prodConfig = defineConfig({\n  plugins: [\n    replace({\n      values: {\n        __DEV__: JSON.stringify(false),\n        'process.env.NODE_ENV': JSON.stringify('production')\n      },\n      preventAssignment: true\n    }),\n    terser()\n  ]\n})\n\nconst umdProdOutputConfig = defineConfig({\n  output: {\n    file: path.resolve('dist/index.prod.js')\n  }\n})\n\nconst esmProdOutputConfig = defineConfig({\n  output: {\n    file: path.resolve('dist/index.prod.mjs')\n  }\n})\n\nexport default [\n  // umd dev\n  merge.all([baseConfig, umdConfig, devConfig, umdDevOutputConfig]),\n  // umd prod\n  merge.all([baseConfig, umdConfig, prodConfig, umdProdOutputConfig]),\n  // esm dev\n  merge.all([baseConfig, esmConfig, devConfig, esmDevOutputConfig]),\n  // esm prod\n  merge.all([baseConfig, esmConfig, prodConfig, esmProdOutputConfig])\n]\n"
  },
  {
    "path": "scripts/gen-component-declaration.ts",
    "content": "import { existsSync } from 'node:fs'\nimport { readFile, writeFile } from 'node:fs/promises'\nimport path from 'node:path'\nimport process from 'node:process'\nimport * as globalComponents from '../src/components'\n\nconst TYPE_ROOT = process.cwd()\n\n// XButton is for tsx type checking, shouldn't be exported\nconst excludeComponents: string[] = ['NxButton']\n\nfunction exist(path: string): boolean {\n  return existsSync(path)\n}\n\nfunction parseComponentsDeclaration(code: string): Record<string, string> {\n  if (!code) {\n    return {}\n  }\n  return Object.fromEntries(\n    Array.from(code.matchAll(/(?<!\\/\\/)\\s+\\s+['\"]?(.+?)['\"]?:\\s(.+?)\\n/g)).map(\n      (i: string[]) => [i[1], i[2]]\n    )\n  )\n}\n\nasync function generateComponentsType(): Promise<void> {\n  const components: Record<string, string> = {}\n  Object.keys(globalComponents).forEach((key: string) => {\n    const entry = `(typeof import('naive-ui'))['${key}']`\n    if (key.startsWith('N') && !excludeComponents.includes(key)) {\n      components[key] = entry\n    }\n  })\n  const originalContent = exist(path.resolve(TYPE_ROOT, 'volar.d.ts'))\n    ? await readFile(path.resolve(TYPE_ROOT, 'volar.d.ts'), 'utf-8')\n    : ''\n  const originImports = parseComponentsDeclaration(originalContent)\n  const lines = Object.entries({\n    ...originImports,\n    ...components\n  })\n    .filter(([name]: [string, string]) => {\n      return components[name]\n    })\n    .map(([name, v]: [string, string]) => {\n      if (!/^\\w+$/.test(name)) {\n        name = `'${name}'`\n      }\n      return `${name}: ${v}`\n    })\n  const code = `// Auto generated component declarations\ndeclare module 'vue' {\n  export interface GlobalComponents {\n    ${lines.join('\\n    ')}\n  }\n}\nexport {}\n`\n\n  if (code !== originalContent) {\n    await writeFile(path.resolve(TYPE_ROOT, 'volar.d.ts'), code, 'utf-8')\n  }\n}\n\ngenerateComponentsType()\n"
  },
  {
    "path": "scripts/gen-css-vars-dts.ts",
    "content": "import { promises as fs } from 'node:fs'\nimport path from 'node:path'\nimport process from 'node:process'\nimport { walk } from './utils'\nimport { collectVars, genDts } from './utils/collect-vars'\n\nconst srcPath = path.resolve(process.cwd(), 'src')\n\n;(async () => {\n  for await (const p of walk(srcPath)) {\n    if (p.endsWith('.cssr.ts')) {\n      const dts = genDts(collectVars(await fs.readFile(p, 'utf-8')))\n      console.log(p, dts)\n    }\n  }\n})()\n"
  },
  {
    "path": "scripts/gen-version.ts",
    "content": "import { writeFileSync } from 'node:fs'\nimport { resolve } from 'node:path'\nimport { cwd } from 'node:process'\nimport packageJson from '../package.json' with { type: 'json' }\n\nwriteFileSync(\n  resolve(cwd(), 'src', 'version.ts'),\n  `export default '${packageJson.version}'\\n`\n)\n"
  },
  {
    "path": "scripts/md-to-vue.ts",
    "content": "import { argv } from 'node:process'\nimport { convertFilesByComponentName } from './utils/loader'\n\nasync function translateMdToVue(): Promise<void> {\n  const componentName = argv[2]\n  await convertFilesByComponentName(componentName)\n}\n\ntranslateMdToVue()\n"
  },
  {
    "path": "scripts/post-build/complete-path.ts",
    "content": "import path from 'node:path'\nimport process from 'node:process'\nimport * as babel from '@babel/core'\nimport glob from 'fast-glob'\nimport fs from 'fs-extra'\n\ninterface FormatConfig {\n  root: string\n  parse: (code: string, filePath: string, currentDir: string) => Promise<void>\n}\n\nconst formatConfigs: Record<string, FormatConfig> = {\n  es: {\n    root: path.join(process.cwd(), 'es'),\n    async parse(code: string, filePath: string, currentDir: string) {\n      const suffix = '.mjs'\n      const result = await babel.transformAsync(code, {\n        root: this.root,\n        babelrc: false,\n        filename: filePath,\n        sourceType: 'module',\n        plugins: [\n          {\n            visitor: {\n              ImportDeclaration: ({ node }) => {\n                const source = node.source.value\n                const parsedSource = parseSource(source, currentDir, suffix)\n                if (parsedSource) {\n                  node.source.value = parsedSource\n                }\n              },\n              ExportNamedDeclaration: ({ node }) => {\n                if (node.source) {\n                  const source = node.source.value\n                  const parsedSource = parseSource(source, currentDir, suffix)\n                  if (parsedSource) {\n                    node.source.value = parsedSource\n                  }\n                }\n              },\n              ExportAllDeclaration: ({ node }) => {\n                const source = node.source.value\n                const parsedSource = parseSource(source, currentDir, suffix)\n                if (parsedSource) {\n                  node.source.value = parsedSource\n                }\n              }\n            }\n          }\n        ]\n      })\n      const newFilePath = replaceExtname(filePath, suffix)\n      await fs.writeFile(newFilePath, result?.code || code)\n      await fs.unlink(filePath)\n    }\n  },\n  lib: {\n    root: path.join(process.cwd(), 'lib'),\n    async parse(code: string, filePath: string, currentDir: string) {\n      const suffix = '.js'\n      const result = await babel.transformAsync(code, {\n        root: this.root,\n        babelrc: false,\n        filename: filePath,\n        plugins: [\n          {\n            visitor: {\n              CallExpression: ({ node }) => {\n                if (\n                  node.callee.type === 'Identifier'\n                  && node.callee.name === 'require'\n                ) {\n                  const firstArg = node.arguments[0]\n                  if (firstArg.type === 'StringLiteral') {\n                    const source = firstArg.value\n                    const parsedSource = parseSource(source, currentDir, suffix)\n                    if (parsedSource) {\n                      firstArg.value = parsedSource\n                    }\n                  }\n                }\n              }\n            }\n          }\n        ]\n      })\n      await fs.writeFile(filePath, result?.code || code)\n    }\n  }\n}\n\nexport async function completePath(formats: ('es' | 'lib')[]): Promise<void> {\n  await Promise.all(\n    formats.map(async (format) => {\n      const config = formatConfigs[format]\n      const files = await glob('**/*.js', {\n        cwd: config.root,\n        absolute: true,\n        onlyFiles: true\n      })\n      await Promise.all(\n        files.map(async (filePath) => {\n          const code = await fs.readFile(filePath, 'utf-8')\n          await config.parse(code, filePath, path.dirname(filePath))\n        })\n      )\n    })\n  )\n}\n\nfunction parseSource(\n  source: string,\n  currentDir: string,\n  suffix: string\n): string | null {\n  if (source.startsWith('.')) {\n    const fullPath = joinPath(currentDir, source)\n    return fs.existsSync(fullPath)\n      ? path.extname(fullPath)\n        ? source\n        : joinPath(source, `index${suffix}`)\n      : source + suffix\n  }\n  else {\n    return source\n  }\n}\n\nfunction replaceExtname(filePath: string, ext: string): string {\n  const oldExt = path.extname(filePath)\n  if (!oldExt)\n    return filePath + ext\n  return joinPath(path.dirname(filePath), path.basename(filePath, oldExt) + ext)\n}\n\nconst normalizePath = (p: string): string => p.replace(/\\\\/g, '/')\n\nfunction joinPath(firstPath: string, ...restPath: string[]): string {\n  const joinedPath = normalizePath(path.join(firstPath, ...restPath))\n  return firstPath.startsWith('./') ? `./${joinedPath}` : joinedPath\n}\n"
  },
  {
    "path": "scripts/post-build/gen-web-types.ts",
    "content": "import fs from 'node:fs'\nimport path from 'node:path'\nimport process, { argv } from 'node:process'\nimport { kebabCase } from 'lodash'\nimport * as components from '../../src/components'\nimport version from '../../src/version'\n\nconst baseDir = path.resolve(process.cwd())\n\ninterface WebTypesScaffold {\n  $schema: string\n  framework: string\n  name: string\n  version: string\n  'js-types-syntax': string\n  contributions: {\n    html: {\n      'vue-components': VueComponent[]\n    }\n  }\n}\n\ninterface VueComponent {\n  name: string\n  description?: string\n  'doc-url'?: string\n  source: {\n    symbol: string\n  }\n  slots: Slot[]\n  attributes: any[]\n  props: Prop[]\n  js: {\n    events: Event[]\n  }\n}\n\ninterface Slot {\n  name: string\n  'doc-url'?: string\n  description?: string\n  type?: string\n  'description-sections'?: {\n    since: string\n  }\n}\n\ninterface Prop {\n  name: string\n  'doc-url'?: string\n  type?: string\n  description?: string\n  default?: string\n  'description-sections'?: {\n    since: string\n  }\n}\n\ninterface Event {\n  name: string\n  'doc-url'?: string\n  description?: string\n  type?: string\n  'description-sections'?: {\n    since: string\n  }\n}\n\nexport function genWebTypes(): void {\n  const vueComponents: VueComponent[] = []\n\n  const scaffold: WebTypesScaffold = {\n    $schema:\n      'https://raw.githubusercontent.com/JetBrains/web-types/master/schema/web-types.json',\n    framework: 'vue',\n    name: 'naive-ui',\n    version,\n    'js-types-syntax': 'typescript',\n    contributions: {\n      html: {\n        'vue-components': vueComponents\n      }\n    }\n  }\n\n  const ignoredPropNames = ['theme', 'themeOverrides', 'builtinThemeOverrides']\n\n  Object.entries(components).forEach(\n    ([exportName, component]: [string, any]) => {\n      if (exportName[0] !== 'N')\n        return\n      if (exportName.startsWith('Nx'))\n        return\n\n      const {\n        props: docProps,\n        slots: docSlots,\n        description,\n        docUrl\n      } = loadDocs(component.name)\n\n      const { props: componentProps } = component\n      const name = exportName\n      const slots: Slot[] = []\n      const attributes: any[] = []\n      const props: Prop[] = []\n      const events: Event[] = []\n      componentProps\n      && Object.entries(componentProps).forEach(\n        ([propName, prop]: [string, any]) => {\n          if (propName.startsWith('internal'))\n            return\n          if (ignoredPropNames.includes(propName))\n            return\n          if (propName.startsWith('on') && /[A-Z]/.test(propName[2])) {\n            // is event\n            const event: Event = {\n              name: kebabCase(propName.slice(2)),\n              'doc-url': docUrl\n            }\n            assignDocs(event, docProps[kebabCase(propName)])\n            delete docProps[kebabCase(propName)]\n            events.push(event)\n          }\n          else {\n            const resultProp: Prop = {\n              name: kebabCase(propName),\n              'doc-url': docUrl\n            }\n            const type = prop ? getType(prop) : null\n            if (type !== null) {\n              resultProp.type = type\n            }\n            assignDocs(resultProp, docProps[resultProp.name])\n            delete docProps[resultProp.name]\n            props.push(resultProp)\n          }\n        }\n      )\n\n      // Add the rest of the props and events from docs\n      for (const name in docProps) {\n        const prop: Prop = {\n          name,\n          'doc-url': docUrl\n        }\n        assignDocs(prop, docProps[name])\n        if (prop.name.startsWith('on-')) {\n          ;(prop as any).name = prop.name.substring(3)\n          events.push(prop as any)\n        }\n        else {\n          props.push(prop)\n        }\n      }\n\n      for (const name in docSlots) {\n        const slot: Slot = {\n          name,\n          'doc-url': docUrl\n        }\n        assignDocs(slot, docSlots[name])\n        slots.push(slot)\n      }\n\n      vueComponents.push({\n        name,\n        description,\n        'doc-url': docUrl,\n        source: {\n          symbol: exportName\n        },\n        slots,\n        attributes,\n        props,\n        js: {\n          events\n        }\n      })\n    }\n  )\n\n  fs.writeFileSync(\n    path.resolve(process.cwd(), 'web-types.json'),\n    JSON.stringify(scaffold, null, 2),\n    {\n      encoding: 'utf-8'\n    }\n  )\n\n  function getType(prop: any): string | null {\n    if (typeof prop !== 'object' && typeof prop !== 'function') {\n      console.error(`invalid prop: ${prop}`)\n      return null\n    }\n    if ('type' in prop) {\n      return _getType(prop.type)\n    }\n    if ('validator' in prop) {\n      return null\n    }\n    return _getType(prop)\n  }\n\n  function _getType(propType: any): string | null {\n    if (Array.isArray(propType)) {\n      const types = propType.map(mapType)\n      if (types.includes(null))\n        return null\n      return types.join(' | ')\n    }\n    return mapType(propType)\n  }\n\n  function mapType(type: any): string | null {\n    const typeMap = new Map<any, string>([\n      [String, 'string'],\n      [Number, 'number'],\n      [Boolean, 'boolean'],\n      [Array, 'Array'],\n      [Object, 'object'],\n      [Function, 'Function'],\n      [Date, 'Date']\n    ])\n\n    if (typeMap.has(type)) {\n      return typeMap.get(type)!\n    }\n\n    console.error(`unknown type ${type}`)\n    return null\n  }\n\n  function loadDocs(componentName: string): {\n    props: Record<string, any>\n    slots: Record<string, any>\n    description?: string\n    docUrl?: string\n  } {\n    let componentPath = kebabCase(componentName)\n    switch (componentPath) {\n      case 'row':\n      case 'col':\n        componentPath = 'legacy-grid'\n        break\n      case 'step':\n        componentPath = 'steps'\n        break\n      case 'h-1':\n      case 'h-2':\n      case 'h-3':\n      case 'h-4':\n      case 'h-5':\n      case 'h-6':\n      case 'text':\n      case 'p':\n      case 'ul':\n      case 'ol':\n      case 'li':\n      case 'hr':\n      case 'a':\n      case 'blockquote':\n        componentPath = 'typography'\n        break\n      case 'th':\n      case 'tr':\n      case 'td':\n      case 'thead':\n      case 'tbody':\n        componentPath = 'table'\n        break\n      case 'tab-pane':\n      case 'tab':\n        componentPath = 'tabs'\n        break\n    }\n    let docsPath: string | undefined\n    do {\n      docsPath = path.resolve(\n        baseDir,\n        `src/${componentPath}/demos/enUS/index.demo-entry.md`\n      )\n      if (fs.existsSync(docsPath))\n        break\n      componentPath = componentPath.substring(\n        0,\n        Math.max(0, componentPath.lastIndexOf('-'))\n      )\n    } while (componentPath)\n\n    if (!componentPath || !docsPath) {\n      console.log(`Docs not found for ${componentName}`)\n      return {\n        props: {},\n        slots: {}\n      }\n    }\n    const docsFile = fs.readFileSync(docsPath).toString()\n    const props = extractSectionTable('Props')\n    const slots = extractSectionTable('Slots')\n    const description = extractComponentDescription()\n\n    return {\n      props,\n      slots,\n      description,\n      docUrl: `https://www.naiveui.com/en-US/os-theme/components/${componentPath}`\n    }\n\n    function extractComponentDescription(): string | undefined {\n      const description = docsFile.match(\n        new RegExp(`#.*${componentName}\\n(.*)## Demos`, 's')\n      )\n      if (description) {\n        return description[1].trim()\n      }\n    }\n\n    function extractSectionTable(sectionName: string): Record<string, any> {\n      const result: Record<string, any> = {}\n      try {\n        const sectionHeaderRegex = new RegExp(\n          `##.*${componentName}[, ].*${sectionName}\\n`\n        )\n        const location = docsFile.match(sectionHeaderRegex)\n        if (!location || location.index === undefined || location.index < 0)\n          return result\n        let end = docsFile.indexOf('##', location.index + 3)\n        if (end < 0)\n          end = docsFile.length\n\n        const rowRegex = /\\|((?:\\\\\\||[^|])+)/g\n        const sectionContents = docsFile.substring(\n          location.index + location[0].length,\n          end\n        )\n        const table = sectionContents\n          .split('\\n')\n          .map(it => it.trim())\n          .filter(it => !!it && !it.includes('| ---') && it.startsWith('|'))\n          .map((it) => {\n            const row = it.match(rowRegex)\n            if (row === null)\n              throw new Error(`Failed to match: ${it}`)\n            return row.map(it => it.substring(1).trim())\n          })\n\n        if (table.length > 0) {\n          if (table[0][0] !== 'Name') {\n            throw new Error(`Bad table ${sectionName} in ${componentName}`)\n          }\n          for (let i = 1; i < table.length; i++) {\n            const row = table[i]\n            const name = row[0]\n            const info: Record<string, any> = {}\n            for (let j = 1; j < row.length; j++) {\n              info[table[0][j].toLowerCase()] = row[j]\n            }\n            result[name] = info\n          }\n        }\n      }\n      catch (e) {\n        console.error(\n          `Failed to build table info for section ${sectionName} of ${componentName} under ${docsPath}`,\n          e\n        )\n      }\n      return result\n    }\n  }\n\n  function assignDocs(target: any, docs: any): void {\n    if (!docs)\n      return\n    if (docs.parameters) {\n      // For slot\n      const type = strip(strip(docs.parameters, '`'), '(', ')')\n      const objDefStart = type ? type.indexOf('{') : -1\n      if (objDefStart >= 0) {\n        target.type = type.substring(objDefStart).replaceAll('\\\\|', '|')\n      }\n    }\n    if (docs.type) {\n      // For props and events\n      target.type = strip(docs.type, '`').replaceAll('\\\\|', '|')\n    }\n    if (docs.description) {\n      target.description = docs.description\n    }\n    if (docs.default) {\n      target.default = strip(docs.default, '`')\n    }\n    if (docs.version) {\n      target['description-sections'] = { since: docs.version }\n    }\n  }\n\n  function strip(str: string, prefix: string, suffix?: string): string {\n    if (!str)\n      return str\n    if (!suffix)\n      suffix = prefix\n    if (str.startsWith(prefix) && str.endsWith(suffix)) {\n      return str.substring(1, str.length - 1).trim()\n    }\n    return str\n  }\n}\n\nif (import.meta.url === `file://${argv[1]}`) {\n  genWebTypes()\n}\n"
  },
  {
    "path": "scripts/post-build/index.ts",
    "content": "import { outDirs, replaceDefine, srcDir } from '../utils'\nimport { completePath } from './complete-path'\nimport { genWebTypes } from './gen-web-types'\nimport { terseCssr } from './terse-cssr'\n\n;\n\n(async () => {\n  await terseCssr()\n  await replaceDefine(outDirs, {\n    __DEV__: 'process.env.NODE_ENV !== \\'production\\''\n  })\n  await replaceDefine([srcDir], {\n    // the sequence is crucial\n    '\\'lodash\\'': '\\'lodash-es\\''\n  })\n\n  // complete require and import source path\n  await completePath(['es'])\n\n  // generate web-types.json for webstorm & vetur\n  // web-types.json is only a very loose description for auto-complete\n  // vscode is a much better choice\n  genWebTypes()\n})()\n"
  },
  {
    "path": "scripts/post-build/terse-cssr.ts",
    "content": "import { promises as fs } from 'node:fs'\nimport { argv } from 'node:process'\nimport { terseCssr as terseCssrUtil } from '../../build/utils/terse-cssr'\nimport { outDirs, walk } from '../utils'\n\nexport async function terseCssr(): Promise<void> {\n  for (const dir of outDirs) {\n    for await (const p of walk(dir)) {\n      if (p.includes('.cssr.js')) {\n        const code = await fs.readFile(p, 'utf-8')\n        await fs.writeFile(p, terseCssrUtil(code))\n      }\n    }\n  }\n}\n\nif (import.meta.url === `file://${argv[1]}`) {\n  terseCssr()\n}\n"
  },
  {
    "path": "scripts/post-build-site/post-build-site.sh",
    "content": "cp site/index.html site/404.html\n\nrm -rf node_modules/naive-ui\n"
  },
  {
    "path": "scripts/pre-build/pre-cjs-build.ts",
    "content": "import { replaceDefine, srcDir } from '../utils'\n\n;\n\n(async () => {\n  await replaceDefine([srcDir], {\n    '\\'lodash-es\\'': '\\'lodash\\''\n  })\n})()\n"
  },
  {
    "path": "scripts/pre-build-site/pre-build-site.sh",
    "content": "if ! [[ -x $(command -v pnpm) ]]; then\n  curl -f https://get.pnpm.io/v6.16.js | node - add --global pnpm@6\nfi\n\npnpm run build:package\n\npnpm pack\nUI_PACKAGE_NAME=$(ls | grep naive-ui)\ntar -xzvf $UI_PACKAGE_NAME\nmv package node_modules/naive-ui\nrm $UI_PACKAGE_NAME\n"
  },
  {
    "path": "scripts/release-changelog.ts",
    "content": "import fs from 'node:fs'\nimport path from 'node:path'\nimport { env } from 'node:process'\nimport url from 'node:url'\nimport inquirer from 'inquirer'\nimport request from 'superagent'\n\nconst __dirname = url.fileURLToPath(new URL('.', import.meta.url))\n\nconst {\n  DINGTALK_TOKEN,\n  DINGTALK_TOKEN_2,\n  DINGTALK_TOKEN_3,\n  DINGTALK_TOKEN_4,\n  DINGTALK_TOKEN_5,\n  DINGTALK_TOKEN_6,\n  DINGTALK_TOKEN_7\n} = env\n\nconst { DISCORD_TOKEN } = env\n\nasync function releaseChangelogToDingTalk(): Promise<void> {\n  const allLog = fs\n    .readFileSync(path.resolve(__dirname, '../CHANGELOG.zh-CN.md'), 'utf-8')\n    .split(/^## /gm)[1]\n\n  const changelog = allLog\n    .replace(/(^.*?\\n)/g, '')\n    .replace(/^##/gm, '')\n    .replace(/\\[([^\\]]+)\\]\\([^)]+\\)/g, '[$1]')\n\n  const number = allLog.split(/^(.*)$/m)[1]\n\n  const title = `变更日志 ${number.trim()}`\n\n  const text = `${changelog.trim()}\\n\\n完整信息见 https://github.com/tusen-ai/naive-ui/blob/main/CHANGELOG.zh-CN.md\\n`\n\n  await inquirer\n    .prompt([\n      {\n        type: 'confirm',\n        name: 'release-changelog',\n        message: `发布以下变更日志到钉钉群：\\n\\n${title}\\n\\n${text}`\n      }\n    ])\n    .then(async (ans) => {\n      if (ans['release-changelog']) {\n        for (const token of [\n          DINGTALK_TOKEN,\n          DINGTALK_TOKEN_2,\n          DINGTALK_TOKEN_3,\n          DINGTALK_TOKEN_4,\n          DINGTALK_TOKEN_5,\n          DINGTALK_TOKEN_6,\n          DINGTALK_TOKEN_7\n        ]) {\n          if (token) {\n            await request\n              .post('https://oapi.dingtalk.com/robot/send')\n              .query({\n                access_token: token\n              })\n              .type('application/json')\n              .send({\n                msgtype: 'markdown',\n                markdown: {\n                  title,\n                  text: `${title}\\n\\n${text}`\n                }\n              })\n              .then((res) => {\n                console.log(res.text)\n              })\n          }\n        }\n      }\n    })\n}\n\nasync function releaseChangelogToDiscord(): Promise<void> {\n  const changelog = fs\n    .readFileSync(path.resolve(__dirname, '../CHANGELOG.en-US.md'), 'utf-8')\n    .split(/^## /gm)[1]\n    .replace(/^##/gm, '')\n    .replace(/\\[([^\\]]+)\\]\\([^)]+\\)/g, '[$1]')\n\n  const message = `Changelog ${changelog.trim()}\\n\\nSee https://github.com/tusen-ai/naive-ui/blob/main/CHANGELOG.en-US.md for details.\\n`\n\n  await inquirer\n    .prompt([\n      {\n        type: 'confirm',\n        name: 'release-changelog',\n        message: `发布以下变更日志到 Discord：\\n\\n${message}`\n      }\n    ])\n    .then((ans) => {\n      if (ans['release-changelog']) {\n        ;(async () => {\n          if (DISCORD_TOKEN) {\n            for (let i = 0; i < message.length; i += 1800) {\n              const part = message.slice(i, i + 1800)\n              await request\n                .post(`https://discord.com/api/webhooks/${DISCORD_TOKEN}`)\n                .type('application/json')\n                .send({\n                  content: part\n                })\n                .then(() => {\n                  console.log('done')\n                })\n                .catch((e) => {\n                  console.error(e)\n                  console.log('Error happens.')\n                })\n            }\n          }\n        })()\n      }\n    })\n}\n\n;(async () => {\n  await releaseChangelogToDingTalk()\n  await releaseChangelogToDiscord()\n})()\n"
  },
  {
    "path": "scripts/utils/collect-vars.ts",
    "content": "const pattern = /var\\(([^)]+)\\)/g\nconst patternDetail = /var\\(([^)]+)\\)/\nconst commentPattern = /^( *)(\\*|(\\S\\S)|(\\S\\*))/g\n\nexport function collectVars(code: string): string[] {\n  const vars = new Set<string>()\n  const lines = code.split('\\n')\n  lines.forEach((line) => {\n    if (line.match(commentPattern)) {\n      return\n    }\n    const result = line.match(pattern)\n    if (result) {\n      result.forEach((varExpr) => {\n        const match = varExpr.match(patternDetail)\n        if (match)\n          vars.add(match[1])\n      })\n    }\n  })\n  return Array.from(vars).sort()\n}\n\nexport function genDts(vars: string[]): string {\n  console.log(vars)\n  return `interface CssVars {\n${vars.map(v => `  '${v}': string`).join('\\n')}\n}`\n}\n"
  },
  {
    "path": "scripts/utils/index.ts",
    "content": "import { promises as fs } from 'node:fs'\nimport { join, resolve } from 'node:path'\nimport process from 'node:process'\n\nexport async function* walk(dir: string): AsyncGenerator<string> {\n  for await (const d of await fs.opendir(dir)) {\n    const entry = join(dir, d.name)\n    if (d.isDirectory()) {\n      yield* walk(entry)\n    }\n    else if (d.isFile()) {\n      yield entry\n    }\n  }\n}\n\nexport const outDirs = ['es', 'lib'].map(d => resolve(process.cwd(), d))\n\nexport const srcDir = resolve(process.cwd(), 'src')\n\nexport { replaceDefine } from './replace-define'\n"
  },
  {
    "path": "scripts/utils/loader.ts",
    "content": "import type { TokensList } from 'marked'\nimport path from 'node:path'\nimport process from 'node:process'\nimport fs from 'fs-extra'\nimport { marked } from 'marked'\n\nconst fileRegex = /\\.demo\\.md$/\n\ninterface DemoParts {\n  template: string | null\n  script: string | null\n  style: string | null\n  title: string | null\n  content: string | null\n}\n\ninterface FileInfo {\n  path: string\n  dir: string\n  file: string\n  name: string\n}\n\nfunction getPartsOfMdDemo(tokens: TokensList): DemoParts {\n  let template = null\n  let script = null\n  let style = null\n  let title = null\n  let content = null\n  for (const token of tokens) {\n    if (token.type === 'heading' && token.depth === 1) {\n      title = token.text\n    }\n    else if (\n      token.type === 'code'\n      && (token.lang === 'template' || token.lang === 'html')\n    ) {\n      template = token.text\n    }\n    else if (\n      token.type === 'code'\n      && (token.lang === 'script' || token.lang === 'js' || token.lang === 'ts')\n    ) {\n      script = token.text\n    }\n    else if (\n      token.type === 'code'\n      && (token.lang === 'style' || token.lang === 'css')\n    ) {\n      style = token.text\n    }\n    else if (token.type === 'paragraph') {\n      content = token.text\n    }\n  }\n  return {\n    template,\n    script,\n    style,\n    title,\n    content\n  }\n}\n\nfunction createBlockTemplate(\n  tag: string,\n  content: string,\n  attrs?: Record<string, string>\n): string {\n  const attrsStr = attrs\n    ? Object.keys(attrs).reduce((attrsStr, key) => {\n        return `${attrsStr} ${key}=\"${attrs[key]}\"`\n      }, '')\n    : ''\n  return `<${tag}${attrsStr}>\\n${content}\\n</${tag}>`\n}\n\nasync function loadFile(filepath: string): Promise<string | undefined> {\n  if (fs.existsSync(filepath)) {\n    return await fs.readFile(filepath, 'utf-8')\n  }\n  return undefined\n}\n\nasync function loadAllMdFile(filePathArr: string[]): Promise<FileInfo[]> {\n  const filesArr: FileInfo[] = []\n  for (let i = 0; i < filePathArr.length; i++) {\n    const filePath = filePathArr[i]\n    if (fs.existsSync(filePath)) {\n      const files = await fs.readdir(filePath)\n      const filesObjArr = files\n        .filter(file => fileRegex.test(file))\n        .map((file) => {\n          const index = file.lastIndexOf('.')\n          return {\n            path: `${filePath}/${file}`,\n            dir: filePath,\n            file,\n            name: file.slice(0, index)\n          }\n        })\n      filesArr.push(...filesObjArr)\n    }\n  }\n  return filesArr\n}\n\nasync function updateIndexEntryDemo(file: FileInfo): Promise<void> {\n  let indexFileContent = await loadFile(\n    path.resolve(file.dir, './index.demo-entry.md')\n  )\n  if (indexFileContent) {\n    const index = file.name.indexOf('.')\n    const name = file.name.slice(0, index)\n    indexFileContent = indexFileContent.replace(name, `${name}.vue`)\n    fs.writeFileSync(\n      path.resolve(file.dir, './index.demo-entry.md'),\n      indexFileContent\n    )\n  }\n}\n\nconst LINE_SPACE = '\\n\\n'\nasync function transformMdToVueAndUpdateEntryFile(\n  files: FileInfo[]\n): Promise<void> {\n  for (const file of files) {\n    const fileString = await loadFile(file.path)\n    if (fileString) {\n      const tokens = marked.lexer(fileString)\n      const parts = getPartsOfMdDemo(tokens)\n      const vueDemoBlocks: string[] = []\n      if (parts.title || parts.content) {\n        vueDemoBlocks.push(\n          createBlockTemplate(\n            'markdown',\n            `# ${parts.title}${parts.content ? `${LINE_SPACE}${parts.content}` : ''}`\n          )\n        )\n      }\n      if (parts.template) {\n        vueDemoBlocks.push(createBlockTemplate('template', parts.template))\n      }\n      if (parts.script) {\n        vueDemoBlocks.push(\n          createBlockTemplate('script', parts.script, {\n            lang: 'ts'\n          })\n        )\n      }\n      if (parts.style) {\n        vueDemoBlocks.push(createBlockTemplate('style', parts.style))\n      }\n      await fs.remove(file.path)\n      await fs.ensureDir(file.dir)\n      fs.writeFileSync(\n        path.resolve(file.dir, `./${file.name}.vue`),\n        `${vueDemoBlocks.join(LINE_SPACE)}\\n`\n      )\n      // should be able to be modified together\n      await updateIndexEntryDemo(file)\n    }\n  }\n}\n\nconst COMPONENT_ROOT = path.resolve(process.cwd(), 'src')\n\nexport async function convertFilesByComponentName(\n  componentName: string\n): Promise<void> {\n  const folders = ['zhCN', 'enUS'].map(item =>\n    path.resolve(COMPONENT_ROOT, `${componentName}/demos/${item}`)\n  )\n  if (folders.length) {\n    const files = await loadAllMdFile(folders)\n    transformMdToVueAndUpdateEntryFile(files)\n  }\n}\n"
  },
  {
    "path": "scripts/utils/replace-define.ts",
    "content": "import { promises as fs } from 'node:fs'\nimport { walk } from '.'\n\nexport async function replaceDefine(\n  dirs: string[],\n  defines: Record<string, string>\n): Promise<void> {\n  const defineKeys = Object.keys(defines)\n  const patterns: Record<string, RegExp> = {}\n  defineKeys.forEach((key) => {\n    patterns[key] = new RegExp(key, 'g')\n  })\n  for (const dir of dirs) {\n    for await (const p of walk(dir)) {\n      if (p.endsWith('.vue'))\n        continue\n      let code = await fs.readFile(p, 'utf-8')\n      for (const key of defineKeys) {\n        const pattern = patterns[key]\n        if (pattern.test(code)) {\n          code = code.replace(pattern, defines[key])\n        }\n      }\n      await fs.writeFile(p, code)\n    }\n  }\n}\n"
  },
  {
    "path": "src/_internal/README.md",
    "content": "Themeable components:\n\n- selection\n- select-menu\n- clear\n"
  },
  {
    "path": "src/_internal/clear/index.ts",
    "content": "export { default } from './src/Clear'\n"
  },
  {
    "path": "src/_internal/clear/src/Clear.tsx",
    "content": "import type { PropType } from 'vue'\nimport { defineComponent, h, toRef } from 'vue'\nimport { useStyle } from '../../../_mixins'\nimport { resolveSlot } from '../../../_utils'\nimport { NBaseIcon } from '../../icon'\nimport NIconSwitchTransition from '../../icon-switch-transition'\nimport { ClearIcon } from '../../icons'\nimport style from './styles/index.cssr'\n\nexport default defineComponent({\n  name: 'BaseClear',\n  props: {\n    clsPrefix: {\n      type: String,\n      required: true\n    },\n    show: Boolean,\n    onClear: Function as PropType<(e: MouseEvent) => void>\n  },\n  setup(props) {\n    useStyle('-base-clear', style, toRef(props, 'clsPrefix'))\n    return {\n      handleMouseDown(e: MouseEvent) {\n        e.preventDefault()\n      }\n    }\n  },\n  render() {\n    const { clsPrefix } = this\n    return (\n      <div class={`${clsPrefix}-base-clear`}>\n        <NIconSwitchTransition>\n          {{\n            default: () => {\n              return this.show ? (\n                <div\n                  key=\"dismiss\"\n                  class={`${clsPrefix}-base-clear__clear`}\n                  onClick={this.onClear}\n                  onMousedown={this.handleMouseDown}\n                  data-clear\n                >\n                  {resolveSlot(this.$slots.icon, () => [\n                    <NBaseIcon clsPrefix={clsPrefix}>\n                      {{\n                        default: () => <ClearIcon />\n                      }}\n                    </NBaseIcon>\n                  ])}\n                </div>\n              ) : (\n                <div key=\"icon\" class={`${clsPrefix}-base-clear__placeholder`}>\n                  {this.$slots.placeholder?.()}\n                </div>\n              )\n            }\n          }}\n        </NIconSwitchTransition>\n      </div>\n    )\n  }\n})\n"
  },
  {
    "path": "src/_internal/clear/src/styles/index.cssr.ts",
    "content": "import { iconSwitchTransition } from '../../../../_styles/transitions/icon-switch.cssr'\nimport { c, cB, cE } from '../../../../_utils/cssr'\n\n// vars:\n// --n-bezier\n// --n-clear-color\n// --n-clear-size\n// --n-clear-color-hover\n// --n-clear-color-pressed\nexport default cB('base-clear', `\n  flex-shrink: 0;\n  height: 1em;\n  width: 1em;\n  position: relative;\n`, [\n  c('>', [\n    cE('clear', `\n      font-size: var(--n-clear-size);\n      height: 1em;\n      width: 1em;\n      cursor: pointer;\n      color: var(--n-clear-color);\n      transition: color .3s var(--n-bezier);\n      display: flex;\n    `, [\n      c('&:hover', `\n        color: var(--n-clear-color-hover)!important;\n      `),\n      c('&:active', `\n        color: var(--n-clear-color-pressed)!important;\n      `)\n    ]),\n    cE('placeholder', `\n      display: flex;\n    `),\n    cE('clear, placeholder', `\n      position: absolute;\n      left: 50%;\n      top: 50%;\n      transform: translateX(-50%) translateY(-50%);\n    `, [\n      iconSwitchTransition({\n        originalTransform: 'translateX(-50%) translateY(-50%)',\n        left: '50%',\n        top: '50%'\n      })\n    ])\n  ])\n])\n"
  },
  {
    "path": "src/_internal/close/index.ts",
    "content": "export { default as NBaseClose } from './src/Close'\n"
  },
  {
    "path": "src/_internal/close/src/Close.tsx",
    "content": "import type { PropType } from 'vue'\nimport { defineComponent, h, toRef } from 'vue'\nimport { useStyle } from '../../../_mixins'\nimport { NBaseIcon } from '../../icon'\nimport { CloseIcon } from '../../icons'\nimport style from './styles/index.cssr'\n\nexport default defineComponent({\n  name: 'BaseClose',\n  props: {\n    isButtonTag: {\n      type: Boolean,\n      default: true\n    },\n    clsPrefix: {\n      type: String,\n      required: true\n    },\n    disabled: {\n      type: Boolean,\n      default: undefined\n    },\n    focusable: {\n      type: Boolean,\n      default: true\n    },\n    round: Boolean,\n    onClick: Function as PropType<(e: MouseEvent) => void>,\n    absolute: Boolean\n  },\n  setup(props) {\n    useStyle('-base-close', style, toRef(props, 'clsPrefix'))\n    return () => {\n      const { clsPrefix, disabled, absolute, round, isButtonTag } = props\n      const Tag = isButtonTag ? 'button' : 'div'\n      return (\n        <Tag\n          type={isButtonTag ? 'button' : undefined}\n          tabindex={disabled || !props.focusable ? -1 : 0}\n          aria-disabled={disabled}\n          aria-label=\"close\"\n          role={isButtonTag ? undefined : 'button'}\n          disabled={disabled}\n          class={[\n            `${clsPrefix}-base-close`,\n            absolute && `${clsPrefix}-base-close--absolute`,\n            disabled && `${clsPrefix}-base-close--disabled`,\n            round && `${clsPrefix}-base-close--round`\n          ]}\n          onMousedown={(e) => {\n            if (!props.focusable) {\n              e.preventDefault()\n            }\n          }}\n          onClick={props.onClick}\n        >\n          <NBaseIcon clsPrefix={clsPrefix}>\n            {{\n              default: () => <CloseIcon />\n            }}\n          </NBaseIcon>\n        </Tag>\n      )\n    }\n  }\n})\n"
  },
  {
    "path": "src/_internal/close/src/styles/index.cssr.ts",
    "content": "import { c, cB, cM, cNotM } from '../../../../_utils/cssr'\n\n// vars:\n// --n-close-border-radius\n// --n-close-color-hover\n// --n-close-color-pressed\n// --n-close-icon-color\n// --n-close-icon-color-hover\n// --n-close-icon-color-pressed\n// --n-close-icon-color-disabled\nexport default cB('base-close', `\n  display: flex;\n  align-items: center;\n  justify-content: center;\n  cursor: pointer;\n  background-color: transparent;\n  color: var(--n-close-icon-color);\n  border-radius: var(--n-close-border-radius);\n  height: var(--n-close-size);\n  width: var(--n-close-size);\n  font-size: var(--n-close-icon-size);\n  outline: none;\n  border: none;\n  position: relative;\n  padding: 0;\n`, [\n  cM('absolute', `\n    height: var(--n-close-icon-size);\n    width: var(--n-close-icon-size);\n  `),\n  c('&::before', `\n    content: \"\";\n    position: absolute;\n    width: var(--n-close-size);\n    height: var(--n-close-size);\n    left: 50%;\n    top: 50%;\n    transform: translateY(-50%) translateX(-50%);\n    transition: inherit;\n    border-radius: inherit;\n  `),\n  cNotM('disabled', [\n    c('&:hover', `\n      color: var(--n-close-icon-color-hover);\n    `),\n    c('&:hover::before', `\n      background-color: var(--n-close-color-hover);\n    `),\n    c('&:focus::before', `\n      background-color: var(--n-close-color-hover);\n    `),\n    c('&:active', `\n      color: var(--n-close-icon-color-pressed);\n    `),\n    c('&:active::before', `\n      background-color: var(--n-close-color-pressed);\n    `)\n  ]),\n  cM('disabled', `\n    cursor: not-allowed;\n    color: var(--n-close-icon-color-disabled);\n    background-color: transparent;\n  `),\n  cM('round', [\n    c('&::before', `\n      border-radius: 50%;\n    `)\n  ])\n])\n"
  },
  {
    "path": "src/_internal/fade-in-expand-transition/index.ts",
    "content": "export { default } from './src/FadeInExpandTransition'\n"
  },
  {
    "path": "src/_internal/fade-in-expand-transition/src/FadeInExpandTransition.ts",
    "content": "import type { PropType, TransitionProps } from 'vue'\nimport { defineComponent, h, Transition, TransitionGroup } from 'vue'\n\nexport default defineComponent({\n  name: 'FadeInExpandTransition',\n  props: {\n    appear: Boolean,\n    group: Boolean,\n    mode: String as PropType<'in-out' | 'out-in' | 'default'>,\n    onLeave: Function,\n    onAfterLeave: Function,\n    onAfterEnter: Function,\n    width: Boolean,\n    // reverse mode is only used in tree\n    // it make it from expanded to collapsed after mounted\n    reverse: Boolean\n  },\n  setup(props, { slots }) {\n    function handleBeforeLeave(el: HTMLElement): void {\n      if (props.width) {\n        el.style.maxWidth = `${el.offsetWidth}px`\n      }\n      else {\n        el.style.maxHeight = `${el.offsetHeight}px`\n      }\n      void el.offsetWidth\n    }\n    function handleLeave(el: HTMLElement): void {\n      if (props.width) {\n        el.style.maxWidth = '0'\n      }\n      else {\n        el.style.maxHeight = '0'\n      }\n      void el.offsetWidth\n      const { onLeave } = props\n      if (onLeave)\n        onLeave()\n    }\n    function handleAfterLeave(el: HTMLElement): void {\n      if (props.width) {\n        el.style.maxWidth = ''\n      }\n      else {\n        el.style.maxHeight = ''\n      }\n      const { onAfterLeave } = props\n      if (onAfterLeave)\n        onAfterLeave()\n    }\n    function handleEnter(el: HTMLElement): void {\n      el.style.transition = 'none'\n      if (props.width) {\n        const memorizedWidth = el.offsetWidth\n        el.style.maxWidth = '0'\n        void el.offsetWidth\n        el.style.transition = ''\n        el.style.maxWidth = `${memorizedWidth}px`\n      }\n      else {\n        if (props.reverse) {\n          el.style.maxHeight = `${el.offsetHeight}px`\n          void el.offsetHeight\n          el.style.transition = ''\n          el.style.maxHeight = '0'\n        }\n        else {\n          const memorizedHeight = el.offsetHeight\n          el.style.maxHeight = '0'\n          void el.offsetWidth\n          el.style.transition = ''\n          el.style.maxHeight = `${memorizedHeight}px`\n        }\n      }\n      void el.offsetWidth\n    }\n    function handleAfterEnter(el: HTMLElement): void {\n      if (props.width) {\n        el.style.maxWidth = ''\n      }\n      else {\n        if (!props.reverse) {\n          el.style.maxHeight = ''\n        }\n      }\n      props.onAfterEnter?.()\n    }\n    return () => {\n      const { group, width, appear, mode } = props\n      const type = group ? TransitionGroup : Transition\n      const resolvedProps = {\n        name: width\n          ? 'fade-in-width-expand-transition'\n          : 'fade-in-height-expand-transition',\n        appear,\n        onEnter: handleEnter,\n        onAfterEnter: handleAfterEnter,\n        onBeforeLeave: handleBeforeLeave,\n        onLeave: handleLeave,\n        onAfterLeave: handleAfterLeave\n      }\n      if (!group) {\n        ;(resolvedProps as unknown as TransitionProps).mode = mode\n      }\n      return h(type as any, resolvedProps, slots)\n    }\n  }\n})\n"
  },
  {
    "path": "src/_internal/focus-detector/index.tsx",
    "content": "import FocusDetector from './src/FocusDetector'\n\nexport default FocusDetector\n"
  },
  {
    "path": "src/_internal/focus-detector/src/FocusDetector.tsx",
    "content": "import type { PropType } from 'vue'\nimport { defineComponent, h } from 'vue'\n\nexport default defineComponent({\n  props: {\n    onFocus: Function as PropType<(e: FocusEvent) => void>,\n    onBlur: Function as PropType<(e: FocusEvent) => void>\n  },\n  setup(props) {\n    return () => (\n      <div\n        style=\"width: 0; height: 0\"\n        tabindex={0}\n        onFocus={props.onFocus}\n        onBlur={props.onBlur}\n      />\n    )\n  }\n})\n"
  },
  {
    "path": "src/_internal/icon/index.ts",
    "content": "export { default as NBaseIcon } from './src/Icon'\n"
  },
  {
    "path": "src/_internal/icon/src/Icon.tsx",
    "content": "import type { PropType } from 'vue'\nimport { defineComponent, h, toRef } from 'vue'\nimport { useStyle } from '../../../_mixins'\nimport style from './styles/index.cssr'\n\nexport default defineComponent({\n  name: 'BaseIcon',\n  props: {\n    role: String,\n    ariaLabel: String,\n    ariaDisabled: {\n      type: Boolean,\n      default: undefined\n    },\n    ariaHidden: {\n      type: Boolean,\n      default: undefined\n    },\n    clsPrefix: {\n      type: String,\n      required: true\n    },\n    onClick: Function as PropType<(e: MouseEvent) => void>,\n    onMousedown: Function as PropType<(e: MouseEvent) => void>,\n    onMouseup: Function as PropType<(e: MouseEvent) => void>\n  },\n  setup(props) {\n    useStyle('-base-icon', style, toRef(props, 'clsPrefix'))\n  },\n  render() {\n    return (\n      <i\n        class={`${this.clsPrefix}-base-icon`}\n        onClick={this.onClick}\n        onMousedown={this.onMousedown}\n        onMouseup={this.onMouseup}\n        role={this.role}\n        aria-label={this.ariaLabel}\n        aria-hidden={this.ariaHidden}\n        aria-disabled={this.ariaDisabled}\n      >\n        {this.$slots}\n      </i>\n    )\n  }\n})\n"
  },
  {
    "path": "src/_internal/icon/src/styles/index.cssr.ts",
    "content": "import { c, cB } from '../../../../_utils/cssr'\n\nexport default cB('base-icon', `\n  height: 1em;\n  width: 1em;\n  line-height: 1em;\n  text-align: center;\n  display: inline-block;\n  position: relative;\n  fill: currentColor;\n`, [\n  c('svg', `\n    height: 1em;\n    width: 1em;\n  `)\n])\n"
  },
  {
    "path": "src/_internal/icon-switch-transition/index.ts",
    "content": "export { default } from './src/IconSwitchTransition'\n"
  },
  {
    "path": "src/_internal/icon-switch-transition/src/IconSwitchTransition.tsx",
    "content": "import { useIsMounted } from 'vooks'\nimport { defineComponent, h, Transition } from 'vue'\n\nexport default defineComponent({\n  name: 'BaseIconSwitchTransition',\n  setup(_, { slots }) {\n    const isMountedRef = useIsMounted()\n    return () => (\n      <Transition name=\"icon-switch-transition\" appear={isMountedRef.value}>\n        {slots}\n      </Transition>\n    )\n  }\n})\n"
  },
  {
    "path": "src/_internal/icons/Add.tsx",
    "content": "import { defineComponent, h } from 'vue'\n\nexport default defineComponent({\n  name: 'Add',\n  render() {\n    return (\n      <svg\n        width=\"512\"\n        height=\"512\"\n        viewBox=\"0 0 512 512\"\n        fill=\"none\"\n        xmlns=\"http://www.w3.org/2000/svg\"\n      >\n        <path\n          d=\"M256 112V400M400 256H112\"\n          stroke=\"currentColor\"\n          stroke-width=\"32\"\n          stroke-linecap=\"round\"\n          stroke-linejoin=\"round\"\n        />\n      </svg>\n    )\n  }\n})\n"
  },
  {
    "path": "src/_internal/icons/ArrowBack.tsx",
    "content": "import { defineComponent, h } from 'vue'\n\nexport default defineComponent({\n  name: 'ArrowBack',\n  render() {\n    return (\n      <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\">\n        <path d=\"M0 0h24v24H0V0z\" fill=\"none\"></path>\n        <path d=\"M19 11H7.83l4.88-4.88c.39-.39.39-1.03 0-1.42-.39-.39-1.02-.39-1.41 0l-6.59 6.59c-.39.39-.39 1.02 0 1.41l6.59 6.59c.39.39 1.02.39 1.41 0 .39-.39.39-1.02 0-1.41L7.83 13H19c.55 0 1-.45 1-1s-.45-1-1-1z\"></path>\n      </svg>\n    )\n  }\n})\n"
  },
  {
    "path": "src/_internal/icons/ArrowDown.tsx",
    "content": "import { defineComponent, h } from 'vue'\n\nexport default defineComponent({\n  name: 'ArrowDown',\n  render() {\n    return (\n      <svg viewBox=\"0 0 28 28\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n        <g stroke=\"none\" stroke-width=\"1\" fill-rule=\"evenodd\">\n          <g fill-rule=\"nonzero\">\n            <path d=\"M23.7916,15.2664 C24.0788,14.9679 24.0696,14.4931 23.7711,14.206 C23.4726,13.9188 22.9978,13.928 22.7106,14.2265 L14.7511,22.5007 L14.7511,3.74792 C14.7511,3.33371 14.4153,2.99792 14.0011,2.99792 C13.5869,2.99792 13.2511,3.33371 13.2511,3.74793 L13.2511,22.4998 L5.29259,14.2265 C5.00543,13.928 4.53064,13.9188 4.23213,14.206 C3.93361,14.4931 3.9244,14.9679 4.21157,15.2664 L13.2809,24.6944 C13.6743,25.1034 14.3289,25.1034 14.7223,24.6944 L23.7916,15.2664 Z\" />\n          </g>\n        </g>\n      </svg>\n    )\n  }\n})\n"
  },
  {
    "path": "src/_internal/icons/ArrowUp.tsx",
    "content": "import { defineComponent, h } from 'vue'\n\nexport default defineComponent({\n  name: 'ArrowUp',\n  render() {\n    return (\n      <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 20 20\">\n        <g fill=\"none\">\n          <path\n            d=\"M3.13 9.163a.5.5 0 1 0 .74.674L9.5 3.67V17.5a.5.5 0 0 0 1 0V3.672l5.63 6.165a.5.5 0 0 0 .738-.674l-6.315-6.916a.746.746 0 0 0-.632-.24a.746.746 0 0 0-.476.24L3.131 9.163z\"\n            fill=\"currentColor\"\n          >\n          </path>\n        </g>\n      </svg>\n    )\n  }\n})\n"
  },
  {
    "path": "src/_internal/icons/Attach.tsx",
    "content": "import { h } from 'vue'\nimport { replaceable } from './replaceable'\n\nexport default replaceable('attach', () => (\n  <svg viewBox=\"0 0 16 16\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n    <g stroke=\"none\" stroke-width=\"1\" fill=\"none\" fill-rule=\"evenodd\">\n      <g fill=\"currentColor\" fill-rule=\"nonzero\">\n        <path d=\"M3.25735931,8.70710678 L7.85355339,4.1109127 C8.82986412,3.13460197 10.4127766,3.13460197 11.3890873,4.1109127 C12.365398,5.08722343 12.365398,6.67013588 11.3890873,7.64644661 L6.08578644,12.9497475 C5.69526215,13.3402718 5.06209717,13.3402718 4.67157288,12.9497475 C4.28104858,12.5592232 4.28104858,11.9260582 4.67157288,11.5355339 L9.97487373,6.23223305 C10.1701359,6.0369709 10.1701359,5.72038841 9.97487373,5.52512627 C9.77961159,5.32986412 9.4630291,5.32986412 9.26776695,5.52512627 L3.96446609,10.8284271 C3.18341751,11.6094757 3.18341751,12.8758057 3.96446609,13.6568542 C4.74551468,14.4379028 6.01184464,14.4379028 6.79289322,13.6568542 L12.0961941,8.35355339 C13.4630291,6.98671837 13.4630291,4.77064094 12.0961941,3.40380592 C10.7293591,2.0369709 8.51328163,2.0369709 7.14644661,3.40380592 L2.55025253,8 C2.35499039,8.19526215 2.35499039,8.51184464 2.55025253,8.70710678 C2.74551468,8.90236893 3.06209717,8.90236893 3.25735931,8.70710678 Z\" />\n      </g>\n    </g>\n  </svg>\n))\n"
  },
  {
    "path": "src/_internal/icons/Backward.tsx",
    "content": "import { defineComponent, h } from 'vue'\n\nexport default defineComponent({\n  name: 'Backward',\n  render() {\n    return (\n      <svg viewBox=\"0 0 20 20\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n        <path\n          d=\"M12.2674 15.793C11.9675 16.0787 11.4927 16.0672 11.2071 15.7673L6.20572 10.5168C5.9298 10.2271 5.9298 9.7719 6.20572 9.48223L11.2071 4.23177C11.4927 3.93184 11.9675 3.92031 12.2674 4.206C12.5673 4.49169 12.5789 4.96642 12.2932 5.26634L7.78458 9.99952L12.2932 14.7327C12.5789 15.0326 12.5673 15.5074 12.2674 15.793Z\"\n          fill=\"currentColor\"\n        />\n      </svg>\n    )\n  }\n})\n"
  },
  {
    "path": "src/_internal/icons/Cancel.tsx",
    "content": "import { h } from 'vue'\nimport { replaceable } from './replaceable'\n\nexport default replaceable('cancel', () => (\n  <svg viewBox=\"0 0 16 16\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n    <g stroke=\"none\" stroke-width=\"1\" fill=\"none\" fill-rule=\"evenodd\">\n      <g fill=\"currentColor\" fill-rule=\"nonzero\">\n        <path d=\"M2.58859116,2.7156945 L2.64644661,2.64644661 C2.82001296,2.47288026 3.08943736,2.45359511 3.2843055,2.58859116 L3.35355339,2.64644661 L8,7.293 L12.6464466,2.64644661 C12.8417088,2.45118446 13.1582912,2.45118446 13.3535534,2.64644661 C13.5488155,2.84170876 13.5488155,3.15829124 13.3535534,3.35355339 L8.707,8 L13.3535534,12.6464466 C13.5271197,12.820013 13.5464049,13.0894374 13.4114088,13.2843055 L13.3535534,13.3535534 C13.179987,13.5271197 12.9105626,13.5464049 12.7156945,13.4114088 L12.6464466,13.3535534 L8,8.707 L3.35355339,13.3535534 C3.15829124,13.5488155 2.84170876,13.5488155 2.64644661,13.3535534 C2.45118446,13.1582912 2.45118446,12.8417088 2.64644661,12.6464466 L7.293,8 L2.64644661,3.35355339 C2.47288026,3.17998704 2.45359511,2.91056264 2.58859116,2.7156945 L2.64644661,2.64644661 L2.58859116,2.7156945 Z\"></path>\n      </g>\n    </g>\n  </svg>\n))\n"
  },
  {
    "path": "src/_internal/icons/Checkmark.tsx",
    "content": "import { defineComponent, h } from 'vue'\n\nexport default defineComponent({\n  name: 'Checkmark',\n  render() {\n    return (\n      <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 16 16\">\n        <g fill=\"none\">\n          <path\n            d=\"M14.046 3.486a.75.75 0 0 1-.032 1.06l-7.93 7.474a.85.85 0 0 1-1.188-.022l-2.68-2.72a.75.75 0 1 1 1.068-1.053l2.234 2.267l7.468-7.038a.75.75 0 0 1 1.06.032z\"\n            fill=\"currentColor\"\n          >\n          </path>\n        </g>\n      </svg>\n    )\n  }\n})\n"
  },
  {
    "path": "src/_internal/icons/ChevronDown.tsx",
    "content": "import { defineComponent, h } from 'vue'\n\nexport default defineComponent({\n  name: 'ChevronDown',\n  render() {\n    return (\n      <svg viewBox=\"0 0 16 16\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n        <path\n          d=\"M3.14645 5.64645C3.34171 5.45118 3.65829 5.45118 3.85355 5.64645L8 9.79289L12.1464 5.64645C12.3417 5.45118 12.6583 5.45118 12.8536 5.64645C13.0488 5.84171 13.0488 6.15829 12.8536 6.35355L8.35355 10.8536C8.15829 11.0488 7.84171 11.0488 7.64645 10.8536L3.14645 6.35355C2.95118 6.15829 2.95118 5.84171 3.14645 5.64645Z\"\n          fill=\"currentColor\"\n        />\n      </svg>\n    )\n  }\n})\n"
  },
  {
    "path": "src/_internal/icons/ChevronDownFilled.tsx",
    "content": "import { defineComponent, h } from 'vue'\n\nexport default defineComponent({\n  name: 'ChevronDownFilled',\n  render() {\n    return (\n      <svg viewBox=\"0 0 16 16\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n        <path\n          d=\"M3.20041 5.73966C3.48226 5.43613 3.95681 5.41856 4.26034 5.70041L8 9.22652L11.7397 5.70041C12.0432 5.41856 12.5177 5.43613 12.7996 5.73966C13.0815 6.0432 13.0639 6.51775 12.7603 6.7996L8.51034 10.7996C8.22258 11.0668 7.77743 11.0668 7.48967 10.7996L3.23966 6.7996C2.93613 6.51775 2.91856 6.0432 3.20041 5.73966Z\"\n          fill=\"currentColor\"\n        />\n      </svg>\n    )\n  }\n})\n"
  },
  {
    "path": "src/_internal/icons/ChevronLeft.tsx",
    "content": "import { defineComponent, h } from 'vue'\n\nexport default defineComponent({\n  name: 'ChevronLeft',\n  render() {\n    return (\n      <svg viewBox=\"0 0 16 16\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n        <path\n          d=\"M10.3536 3.14645C10.5488 3.34171 10.5488 3.65829 10.3536 3.85355L6.20711 8L10.3536 12.1464C10.5488 12.3417 10.5488 12.6583 10.3536 12.8536C10.1583 13.0488 9.84171 13.0488 9.64645 12.8536L5.14645 8.35355C4.95118 8.15829 4.95118 7.84171 5.14645 7.64645L9.64645 3.14645C9.84171 2.95118 10.1583 2.95118 10.3536 3.14645Z\"\n          fill=\"currentColor\"\n        />\n      </svg>\n    )\n  }\n})\n"
  },
  {
    "path": "src/_internal/icons/ChevronRight.tsx",
    "content": "import { defineComponent, h } from 'vue'\n\nexport default defineComponent({\n  name: 'ChevronRight',\n  render() {\n    return (\n      <svg viewBox=\"0 0 16 16\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n        <path\n          d=\"M5.64645 3.14645C5.45118 3.34171 5.45118 3.65829 5.64645 3.85355L9.79289 8L5.64645 12.1464C5.45118 12.3417 5.45118 12.6583 5.64645 12.8536C5.84171 13.0488 6.15829 13.0488 6.35355 12.8536L10.8536 8.35355C11.0488 8.15829 11.0488 7.84171 10.8536 7.64645L6.35355 3.14645C6.15829 2.95118 5.84171 2.95118 5.64645 3.14645Z\"\n          fill=\"currentColor\"\n        />\n      </svg>\n    )\n  }\n})\n"
  },
  {
    "path": "src/_internal/icons/Clear.tsx",
    "content": "import { h } from 'vue'\nimport { replaceable } from './replaceable'\n\nexport default replaceable('clear', () => (\n  <svg viewBox=\"0 0 16 16\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n    <g stroke=\"none\" stroke-width=\"1\" fill=\"none\" fill-rule=\"evenodd\">\n      <g fill=\"currentColor\" fill-rule=\"nonzero\">\n        <path d=\"M8,2 C11.3137085,2 14,4.6862915 14,8 C14,11.3137085 11.3137085,14 8,14 C4.6862915,14 2,11.3137085 2,8 C2,4.6862915 4.6862915,2 8,2 Z M6.5343055,5.83859116 C6.33943736,5.70359511 6.07001296,5.72288026 5.89644661,5.89644661 L5.89644661,5.89644661 L5.83859116,5.9656945 C5.70359511,6.16056264 5.72288026,6.42998704 5.89644661,6.60355339 L5.89644661,6.60355339 L7.293,8 L5.89644661,9.39644661 L5.83859116,9.4656945 C5.70359511,9.66056264 5.72288026,9.92998704 5.89644661,10.1035534 L5.89644661,10.1035534 L5.9656945,10.1614088 C6.16056264,10.2964049 6.42998704,10.2771197 6.60355339,10.1035534 L6.60355339,10.1035534 L8,8.707 L9.39644661,10.1035534 L9.4656945,10.1614088 C9.66056264,10.2964049 9.92998704,10.2771197 10.1035534,10.1035534 L10.1035534,10.1035534 L10.1614088,10.0343055 C10.2964049,9.83943736 10.2771197,9.57001296 10.1035534,9.39644661 L10.1035534,9.39644661 L8.707,8 L10.1035534,6.60355339 L10.1614088,6.5343055 C10.2964049,6.33943736 10.2771197,6.07001296 10.1035534,5.89644661 L10.1035534,5.89644661 L10.0343055,5.83859116 C9.83943736,5.70359511 9.57001296,5.72288026 9.39644661,5.89644661 L9.39644661,5.89644661 L8,7.293 L6.60355339,5.89644661 Z\" />\n      </g>\n    </g>\n  </svg>\n))\n"
  },
  {
    "path": "src/_internal/icons/Close.tsx",
    "content": "import { h } from 'vue'\nimport { replaceable } from './replaceable'\n\nexport default replaceable('close', () => (\n  <svg\n    viewBox=\"0 0 12 12\"\n    version=\"1.1\"\n    xmlns=\"http://www.w3.org/2000/svg\"\n    aria-hidden\n  >\n    <g stroke=\"none\" stroke-width=\"1\" fill=\"none\" fill-rule=\"evenodd\">\n      <g fill=\"currentColor\" fill-rule=\"nonzero\">\n        <path d=\"M2.08859116,2.2156945 L2.14644661,2.14644661 C2.32001296,1.97288026 2.58943736,1.95359511 2.7843055,2.08859116 L2.85355339,2.14644661 L6,5.293 L9.14644661,2.14644661 C9.34170876,1.95118446 9.65829124,1.95118446 9.85355339,2.14644661 C10.0488155,2.34170876 10.0488155,2.65829124 9.85355339,2.85355339 L6.707,6 L9.85355339,9.14644661 C10.0271197,9.32001296 10.0464049,9.58943736 9.91140884,9.7843055 L9.85355339,9.85355339 C9.67998704,10.0271197 9.41056264,10.0464049 9.2156945,9.91140884 L9.14644661,9.85355339 L6,6.707 L2.85355339,9.85355339 C2.65829124,10.0488155 2.34170876,10.0488155 2.14644661,9.85355339 C1.95118446,9.65829124 1.95118446,9.34170876 2.14644661,9.14644661 L5.293,6 L2.14644661,2.85355339 C1.97288026,2.67998704 1.95359511,2.41056264 2.08859116,2.2156945 L2.14644661,2.14644661 L2.08859116,2.2156945 Z\" />\n      </g>\n    </g>\n  </svg>\n))\n"
  },
  {
    "path": "src/_internal/icons/Date.tsx",
    "content": "import { h } from 'vue'\nimport { replaceable } from './replaceable'\n\nexport default replaceable('date', () => (\n  <svg\n    width=\"28px\"\n    height=\"28px\"\n    viewBox=\"0 0 28 28\"\n    version=\"1.1\"\n    xmlns=\"http://www.w3.org/2000/svg\"\n  >\n    <g stroke=\"none\" stroke-width=\"1\" fill-rule=\"evenodd\">\n      <g fill-rule=\"nonzero\">\n        <path d=\"M21.75,3 C23.5449254,3 25,4.45507456 25,6.25 L25,21.75 C25,23.5449254 23.5449254,25 21.75,25 L6.25,25 C4.45507456,25 3,23.5449254 3,21.75 L3,6.25 C3,4.45507456 4.45507456,3 6.25,3 L21.75,3 Z M23.5,9.503 L4.5,9.503 L4.5,21.75 C4.5,22.7164983 5.28350169,23.5 6.25,23.5 L21.75,23.5 C22.7164983,23.5 23.5,22.7164983 23.5,21.75 L23.5,9.503 Z M21.75,4.5 L6.25,4.5 C5.28350169,4.5 4.5,5.28350169 4.5,6.25 L4.5,8.003 L23.5,8.003 L23.5,6.25 C23.5,5.28350169 22.7164983,4.5 21.75,4.5 Z\" />\n      </g>\n    </g>\n  </svg>\n))\n"
  },
  {
    "path": "src/_internal/icons/Download.tsx",
    "content": "import { h } from 'vue'\nimport { replaceable } from './replaceable'\n\nexport default replaceable('download', () => (\n  <svg viewBox=\"0 0 16 16\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n    <g stroke=\"none\" stroke-width=\"1\" fill=\"none\" fill-rule=\"evenodd\">\n      <g fill=\"currentColor\" fill-rule=\"nonzero\">\n        <path d=\"M3.5,13 L12.5,13 C12.7761424,13 13,13.2238576 13,13.5 C13,13.7454599 12.8231248,13.9496084 12.5898756,13.9919443 L12.5,14 L3.5,14 C3.22385763,14 3,13.7761424 3,13.5 C3,13.2545401 3.17687516,13.0503916 3.41012437,13.0080557 L3.5,13 L12.5,13 L3.5,13 Z M7.91012437,1.00805567 L8,1 C8.24545989,1 8.44960837,1.17687516 8.49194433,1.41012437 L8.5,1.5 L8.5,10.292 L11.1819805,7.6109127 C11.3555469,7.43734635 11.6249713,7.4180612 11.8198394,7.55305725 L11.8890873,7.6109127 C12.0626536,7.78447906 12.0819388,8.05390346 11.9469427,8.2487716 L11.8890873,8.31801948 L8.35355339,11.8535534 C8.17998704,12.0271197 7.91056264,12.0464049 7.7156945,11.9114088 L7.64644661,11.8535534 L4.1109127,8.31801948 C3.91565056,8.12275734 3.91565056,7.80617485 4.1109127,7.6109127 C4.28447906,7.43734635 4.55390346,7.4180612 4.7487716,7.55305725 L4.81801948,7.6109127 L7.5,10.292 L7.5,1.5 C7.5,1.25454011 7.67687516,1.05039163 7.91012437,1.00805567 L8,1 L7.91012437,1.00805567 Z\" />\n      </g>\n    </g>\n  </svg>\n))\n"
  },
  {
    "path": "src/_internal/icons/Empty.tsx",
    "content": "import { defineComponent, h } from 'vue'\n\nexport default defineComponent({\n  name: 'Empty',\n  render() {\n    return (\n      <svg viewBox=\"0 0 28 28\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n        <path\n          d=\"M26 7.5C26 11.0899 23.0899 14 19.5 14C15.9101 14 13 11.0899 13 7.5C13 3.91015 15.9101 1 19.5 1C23.0899 1 26 3.91015 26 7.5ZM16.8536 4.14645C16.6583 3.95118 16.3417 3.95118 16.1464 4.14645C15.9512 4.34171 15.9512 4.65829 16.1464 4.85355L18.7929 7.5L16.1464 10.1464C15.9512 10.3417 15.9512 10.6583 16.1464 10.8536C16.3417 11.0488 16.6583 11.0488 16.8536 10.8536L19.5 8.20711L22.1464 10.8536C22.3417 11.0488 22.6583 11.0488 22.8536 10.8536C23.0488 10.6583 23.0488 10.3417 22.8536 10.1464L20.2071 7.5L22.8536 4.85355C23.0488 4.65829 23.0488 4.34171 22.8536 4.14645C22.6583 3.95118 22.3417 3.95118 22.1464 4.14645L19.5 6.79289L16.8536 4.14645Z\"\n          fill=\"currentColor\"\n        >\n        </path>\n        <path\n          d=\"M25 22.75V12.5991C24.5572 13.0765 24.053 13.4961 23.5 13.8454V16H17.5L17.3982 16.0068C17.0322 16.0565 16.75 16.3703 16.75 16.75C16.75 18.2688 15.5188 19.5 14 19.5C12.4812 19.5 11.25 18.2688 11.25 16.75L11.2432 16.6482C11.1935 16.2822 10.8797 16 10.5 16H4.5V7.25C4.5 6.2835 5.2835 5.5 6.25 5.5H12.2696C12.4146 4.97463 12.6153 4.47237 12.865 4H6.25C4.45507 4 3 5.45507 3 7.25V22.75C3 24.5449 4.45507 26 6.25 26H21.75C23.5449 26 25 24.5449 25 22.75ZM4.5 22.75V17.5H9.81597L9.85751 17.7041C10.2905 19.5919 11.9808 21 14 21L14.215 20.9947C16.2095 20.8953 17.842 19.4209 18.184 17.5H23.5V22.75C23.5 23.7165 22.7165 24.5 21.75 24.5H6.25C5.2835 24.5 4.5 23.7165 4.5 22.75Z\"\n          fill=\"currentColor\"\n        >\n        </path>\n      </svg>\n    )\n  }\n})\n"
  },
  {
    "path": "src/_internal/icons/Error.tsx",
    "content": "import { h } from 'vue'\nimport { replaceable } from './replaceable'\n\nexport default replaceable('error', () => (\n  <svg viewBox=\"0 0 48 48\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n    <g stroke=\"none\" stroke-width=\"1\" fill-rule=\"evenodd\">\n      <g fill-rule=\"nonzero\">\n        <path d=\"M24,4 C35.045695,4 44,12.954305 44,24 C44,35.045695 35.045695,44 24,44 C12.954305,44 4,35.045695 4,24 C4,12.954305 12.954305,4 24,4 Z M17.8838835,16.1161165 L17.7823881,16.0249942 C17.3266086,15.6583353 16.6733914,15.6583353 16.2176119,16.0249942 L16.1161165,16.1161165 L16.0249942,16.2176119 C15.6583353,16.6733914 15.6583353,17.3266086 16.0249942,17.7823881 L16.1161165,17.8838835 L22.233,24 L16.1161165,30.1161165 L16.0249942,30.2176119 C15.6583353,30.6733914 15.6583353,31.3266086 16.0249942,31.7823881 L16.1161165,31.8838835 L16.2176119,31.9750058 C16.6733914,32.3416647 17.3266086,32.3416647 17.7823881,31.9750058 L17.8838835,31.8838835 L24,25.767 L30.1161165,31.8838835 L30.2176119,31.9750058 C30.6733914,32.3416647 31.3266086,32.3416647 31.7823881,31.9750058 L31.8838835,31.8838835 L31.9750058,31.7823881 C32.3416647,31.3266086 32.3416647,30.6733914 31.9750058,30.2176119 L31.8838835,30.1161165 L25.767,24 L31.8838835,17.8838835 L31.9750058,17.7823881 C32.3416647,17.3266086 32.3416647,16.6733914 31.9750058,16.2176119 L31.8838835,16.1161165 L31.7823881,16.0249942 C31.3266086,15.6583353 30.6733914,15.6583353 30.2176119,16.0249942 L30.1161165,16.1161165 L24,22.233 L17.8838835,16.1161165 L17.7823881,16.0249942 L17.8838835,16.1161165 Z\" />\n      </g>\n    </g>\n  </svg>\n))\n"
  },
  {
    "path": "src/_internal/icons/Eye.tsx",
    "content": "import { defineComponent, h } from 'vue'\n\nexport default defineComponent({\n  name: 'Eye',\n  render() {\n    return (\n      <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 512 512\">\n        <path\n          d=\"M255.66 112c-77.94 0-157.89 45.11-220.83 135.33a16 16 0 0 0-.27 17.77C82.92 340.8 161.8 400 255.66 400c92.84 0 173.34-59.38 221.79-135.25a16.14 16.14 0 0 0 0-17.47C428.89 172.28 347.8 112 255.66 112z\"\n          fill=\"none\"\n          stroke=\"currentColor\"\n          stroke-linecap=\"round\"\n          stroke-linejoin=\"round\"\n          stroke-width=\"32\"\n        />\n        <circle\n          cx=\"256\"\n          cy=\"256\"\n          r=\"80\"\n          fill=\"none\"\n          stroke=\"currentColor\"\n          stroke-miterlimit=\"10\"\n          stroke-width=\"32\"\n        />\n      </svg>\n    )\n  }\n})\n"
  },
  {
    "path": "src/_internal/icons/EyeOff.tsx",
    "content": "import { defineComponent, h } from 'vue'\n\nexport default defineComponent({\n  name: 'EyeOff',\n  render() {\n    return (\n      <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 512 512\">\n        <path\n          d=\"M432 448a15.92 15.92 0 0 1-11.31-4.69l-352-352a16 16 0 0 1 22.62-22.62l352 352A16 16 0 0 1 432 448z\"\n          fill=\"currentColor\"\n        />\n        <path\n          d=\"M255.66 384c-41.49 0-81.5-12.28-118.92-36.5c-34.07-22-64.74-53.51-88.7-91v-.08c19.94-28.57 41.78-52.73 65.24-72.21a2 2 0 0 0 .14-2.94L93.5 161.38a2 2 0 0 0-2.71-.12c-24.92 21-48.05 46.76-69.08 76.92a31.92 31.92 0 0 0-.64 35.54c26.41 41.33 60.4 76.14 98.28 100.65C162 402 207.9 416 255.66 416a239.13 239.13 0 0 0 75.8-12.58a2 2 0 0 0 .77-3.31l-21.58-21.58a4 4 0 0 0-3.83-1a204.8 204.8 0 0 1-51.16 6.47z\"\n          fill=\"currentColor\"\n        />\n        <path\n          d=\"M490.84 238.6c-26.46-40.92-60.79-75.68-99.27-100.53C349 110.55 302 96 255.66 96a227.34 227.34 0 0 0-74.89 12.83a2 2 0 0 0-.75 3.31l21.55 21.55a4 4 0 0 0 3.88 1a192.82 192.82 0 0 1 50.21-6.69c40.69 0 80.58 12.43 118.55 37c34.71 22.4 65.74 53.88 89.76 91a.13.13 0 0 1 0 .16a310.72 310.72 0 0 1-64.12 72.73a2 2 0 0 0-.15 2.95l19.9 19.89a2 2 0 0 0 2.7.13a343.49 343.49 0 0 0 68.64-78.48a32.2 32.2 0 0 0-.1-34.78z\"\n          fill=\"currentColor\"\n        />\n        <path\n          d=\"M256 160a95.88 95.88 0 0 0-21.37 2.4a2 2 0 0 0-1 3.38l112.59 112.56a2 2 0 0 0 3.38-1A96 96 0 0 0 256 160z\"\n          fill=\"currentColor\"\n        />\n        <path\n          d=\"M165.78 233.66a2 2 0 0 0-3.38 1a96 96 0 0 0 115 115a2 2 0 0 0 1-3.38z\"\n          fill=\"currentColor\"\n        />\n      </svg>\n    )\n  }\n})\n"
  },
  {
    "path": "src/_internal/icons/FastBackward.tsx",
    "content": "import { defineComponent, h } from 'vue'\n\nexport default defineComponent({\n  name: 'FastBackward',\n  render() {\n    return (\n      <svg viewBox=\"0 0 20 20\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n        <g stroke=\"none\" stroke-width=\"1\" fill=\"none\" fill-rule=\"evenodd\">\n          <g fill=\"currentColor\" fill-rule=\"nonzero\">\n            <path d=\"M8.73171,16.7949 C9.03264,17.0795 9.50733,17.0663 9.79196,16.7654 C10.0766,16.4644 10.0634,15.9897 9.76243,15.7051 L4.52339,10.75 L17.2471,10.75 C17.6613,10.75 17.9971,10.4142 17.9971,10 C17.9971,9.58579 17.6613,9.25 17.2471,9.25 L4.52112,9.25 L9.76243,4.29275 C10.0634,4.00812 10.0766,3.53343 9.79196,3.2325 C9.50733,2.93156 9.03264,2.91834 8.73171,3.20297 L2.31449,9.27241 C2.14819,9.4297 2.04819,9.62981 2.01448,9.8386 C2.00308,9.89058 1.99707,9.94459 1.99707,10 C1.99707,10.0576 2.00356,10.1137 2.01585,10.1675 C2.05084,10.3733 2.15039,10.5702 2.31449,10.7254 L8.73171,16.7949 Z\" />\n          </g>\n        </g>\n      </svg>\n    )\n  }\n})\n"
  },
  {
    "path": "src/_internal/icons/FastForward.tsx",
    "content": "import { defineComponent, h } from 'vue'\n\nexport default defineComponent({\n  name: 'FastForward',\n  render() {\n    return (\n      <svg viewBox=\"0 0 20 20\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n        <g stroke=\"none\" stroke-width=\"1\" fill=\"none\" fill-rule=\"evenodd\">\n          <g fill=\"currentColor\" fill-rule=\"nonzero\">\n            <path d=\"M11.2654,3.20511 C10.9644,2.92049 10.4897,2.93371 10.2051,3.23464 C9.92049,3.53558 9.93371,4.01027 10.2346,4.29489 L15.4737,9.25 L2.75,9.25 C2.33579,9.25 2,9.58579 2,10.0000012 C2,10.4142 2.33579,10.75 2.75,10.75 L15.476,10.75 L10.2346,15.7073 C9.93371,15.9919 9.92049,16.4666 10.2051,16.7675 C10.4897,17.0684 10.9644,17.0817 11.2654,16.797 L17.6826,10.7276 C17.8489,10.5703 17.9489,10.3702 17.9826,10.1614 C17.994,10.1094 18,10.0554 18,10.0000012 C18,9.94241 17.9935,9.88633 17.9812,9.83246 C17.9462,9.62667 17.8467,9.42976 17.6826,9.27455 L11.2654,3.20511 Z\" />\n          </g>\n        </g>\n      </svg>\n    )\n  }\n})\n"
  },
  {
    "path": "src/_internal/icons/File.tsx",
    "content": "import { defineComponent, h } from 'vue'\n\nexport default defineComponent({\n  name: 'File',\n  render() {\n    return (\n      <svg viewBox=\"0 0 24 24\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n        <g\n          fill=\"none\"\n          stroke=\"currentColor\"\n          stroke-width=\"2\"\n          stroke-linecap=\"round\"\n          stroke-linejoin=\"round\"\n        >\n          <path d=\"M14 3v4a1 1 0 0 0 1 1h4\"></path>\n          <path d=\"M17 21H7a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h7l5 5v11a2 2 0 0 1-2 2z\"></path>\n        </g>\n      </svg>\n    )\n  }\n})\n"
  },
  {
    "path": "src/_internal/icons/Filter.tsx",
    "content": "import { defineComponent, h } from 'vue'\n\nexport default defineComponent({\n  name: 'Filter',\n  render() {\n    return (\n      <svg viewBox=\"0 0 28 28\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n        <g stroke=\"none\" stroke-width=\"1\" fill-rule=\"evenodd\">\n          <g fill-rule=\"nonzero\">\n            <path d=\"M17,19 C17.5522847,19 18,19.4477153 18,20 C18,20.5522847 17.5522847,21 17,21 L11,21 C10.4477153,21 10,20.5522847 10,20 C10,19.4477153 10.4477153,19 11,19 L17,19 Z M21,13 C21.5522847,13 22,13.4477153 22,14 C22,14.5522847 21.5522847,15 21,15 L7,15 C6.44771525,15 6,14.5522847 6,14 C6,13.4477153 6.44771525,13 7,13 L21,13 Z M24,7 C24.5522847,7 25,7.44771525 25,8 C25,8.55228475 24.5522847,9 24,9 L4,9 C3.44771525,9 3,8.55228475 3,8 C3,7.44771525 3.44771525,7 4,7 L24,7 Z\" />\n          </g>\n        </g>\n      </svg>\n    )\n  }\n})\n"
  },
  {
    "path": "src/_internal/icons/Forward.tsx",
    "content": "import { defineComponent, h } from 'vue'\n\nexport default defineComponent({\n  name: 'Forward',\n  render() {\n    return (\n      <svg viewBox=\"0 0 20 20\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n        <path\n          d=\"M7.73271 4.20694C8.03263 3.92125 8.50737 3.93279 8.79306 4.23271L13.7944 9.48318C14.0703 9.77285 14.0703 10.2281 13.7944 10.5178L8.79306 15.7682C8.50737 16.0681 8.03263 16.0797 7.73271 15.794C7.43279 15.5083 7.42125 15.0336 7.70694 14.7336L12.2155 10.0005L7.70694 5.26729C7.42125 4.96737 7.43279 4.49264 7.73271 4.20694Z\"\n          fill=\"currentColor\"\n        />\n      </svg>\n    )\n  }\n})\n"
  },
  {
    "path": "src/_internal/icons/Info.tsx",
    "content": "import { h } from 'vue'\nimport { replaceable } from './replaceable'\n\nexport default replaceable('info', () => (\n  <svg viewBox=\"0 0 28 28\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n    <g stroke=\"none\" stroke-width=\"1\" fill-rule=\"evenodd\">\n      <g fill-rule=\"nonzero\">\n        <path d=\"M14,2 C20.6274,2 26,7.37258 26,14 C26,20.6274 20.6274,26 14,26 C7.37258,26 2,20.6274 2,14 C2,7.37258 7.37258,2 14,2 Z M14,11 C13.4477,11 13,11.4477 13,12 L13,12 L13,20 C13,20.5523 13.4477,21 14,21 C14.5523,21 15,20.5523 15,20 L15,20 L15,12 C15,11.4477 14.5523,11 14,11 Z M14,6.75 C13.3096,6.75 12.75,7.30964 12.75,8 C12.75,8.69036 13.3096,9.25 14,9.25 C14.6904,9.25 15.25,8.69036 15.25,8 C15.25,7.30964 14.6904,6.75 14,6.75 Z\" />\n      </g>\n    </g>\n  </svg>\n))\n"
  },
  {
    "path": "src/_internal/icons/More.tsx",
    "content": "import { defineComponent, h } from 'vue'\n\nexport default defineComponent({\n  name: 'More',\n  render() {\n    return (\n      <svg viewBox=\"0 0 16 16\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n        <g stroke=\"none\" stroke-width=\"1\" fill=\"none\" fill-rule=\"evenodd\">\n          <g fill=\"currentColor\" fill-rule=\"nonzero\">\n            <path d=\"M4,7 C4.55228,7 5,7.44772 5,8 C5,8.55229 4.55228,9 4,9 C3.44772,9 3,8.55229 3,8 C3,7.44772 3.44772,7 4,7 Z M8,7 C8.55229,7 9,7.44772 9,8 C9,8.55229 8.55229,9 8,9 C7.44772,9 7,8.55229 7,8 C7,7.44772 7.44772,7 8,7 Z M12,7 C12.5523,7 13,7.44772 13,8 C13,8.55229 12.5523,9 12,9 C11.4477,9 11,8.55229 11,8 C11,7.44772 11.4477,7 12,7 Z\" />\n          </g>\n        </g>\n      </svg>\n    )\n  }\n})\n"
  },
  {
    "path": "src/_internal/icons/Photo.tsx",
    "content": "import { defineComponent, h } from 'vue'\n\nexport default defineComponent({\n  name: 'Photo',\n  render() {\n    return (\n      <svg viewBox=\"0 0 24 24\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n        <g\n          fill=\"none\"\n          stroke=\"currentColor\"\n          stroke-width=\"2\"\n          stroke-linecap=\"round\"\n          stroke-linejoin=\"round\"\n        >\n          <path d=\"M15 8h.01\"></path>\n          <rect x=\"4\" y=\"4\" width=\"16\" height=\"16\" rx=\"3\"></rect>\n          <path d=\"M4 15l4-4a3 5 0 0 1 3 0l5 5\"></path>\n          <path d=\"M14 14l1-1a3 5 0 0 1 3 0l2 2\"></path>\n        </g>\n      </svg>\n    )\n  }\n})\n"
  },
  {
    "path": "src/_internal/icons/Remove.tsx",
    "content": "import { defineComponent, h } from 'vue'\n\nexport default defineComponent({\n  name: 'Remove',\n  render() {\n    return (\n      <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 512 512\">\n        <line\n          x1=\"400\"\n          y1=\"256\"\n          x2=\"112\"\n          y2=\"256\"\n          style=\"\n        fill: none;\n        stroke: currentColor;\n        stroke-linecap: round;\n        stroke-linejoin: round;\n        stroke-width: 32px;\n      \"\n        />\n      </svg>\n    )\n  }\n})\n"
  },
  {
    "path": "src/_internal/icons/ResizeSmall.tsx",
    "content": "import { defineComponent, h } from 'vue'\n\nexport default defineComponent({\n  name: 'ResizeSmall',\n  render() {\n    return (\n      <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 20 20\">\n        <g fill=\"none\">\n          <path\n            d=\"M5.5 4A1.5 1.5 0 0 0 4 5.5v1a.5.5 0 0 1-1 0v-1A2.5 2.5 0 0 1 5.5 3h1a.5.5 0 0 1 0 1h-1zM16 5.5A1.5 1.5 0 0 0 14.5 4h-1a.5.5 0 0 1 0-1h1A2.5 2.5 0 0 1 17 5.5v1a.5.5 0 0 1-1 0v-1zm0 9a1.5 1.5 0 0 1-1.5 1.5h-1a.5.5 0 0 0 0 1h1a2.5 2.5 0 0 0 2.5-2.5v-1a.5.5 0 0 0-1 0v1zm-12 0A1.5 1.5 0 0 0 5.5 16h1.25a.5.5 0 0 1 0 1H5.5A2.5 2.5 0 0 1 3 14.5v-1.25a.5.5 0 0 1 1 0v1.25zM8.5 7A1.5 1.5 0 0 0 7 8.5v3A1.5 1.5 0 0 0 8.5 13h3a1.5 1.5 0 0 0 1.5-1.5v-3A1.5 1.5 0 0 0 11.5 7h-3zM8 8.5a.5.5 0 0 1 .5-.5h3a.5.5 0 0 1 .5.5v3a.5.5 0 0 1-.5.5h-3a.5.5 0 0 1-.5-.5v-3z\"\n            fill=\"currentColor\"\n          />\n        </g>\n      </svg>\n    )\n  }\n})\n"
  },
  {
    "path": "src/_internal/icons/Retry.tsx",
    "content": "import { h } from 'vue'\nimport { replaceable } from './replaceable'\n\nexport default replaceable('retry', () => (\n  <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 512 512\">\n    <path\n      d=\"M320,146s24.36-12-64-12A160,160,0,1,0,416,294\"\n      style=\"fill: none; stroke: currentcolor; stroke-linecap: round; stroke-miterlimit: 10; stroke-width: 32px;\"\n    />\n    <polyline\n      points=\"256 58 336 138 256 218\"\n      style=\"fill: none; stroke: currentcolor; stroke-linecap: round; stroke-linejoin: round; stroke-width: 32px;\"\n    />\n  </svg>\n))\n"
  },
  {
    "path": "src/_internal/icons/RotateClockwise.tsx",
    "content": "import { h } from 'vue'\nimport { replaceable } from './replaceable'\n\nexport default replaceable('rotateClockwise', () => (\n  <svg viewBox=\"0 0 20 20\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n    <path\n      d=\"M3 10C3 6.13401 6.13401 3 10 3C13.866 3 17 6.13401 17 10C17 12.7916 15.3658 15.2026 13 16.3265V14.5C13 14.2239 12.7761 14 12.5 14C12.2239 14 12 14.2239 12 14.5V17.5C12 17.7761 12.2239 18 12.5 18H15.5C15.7761 18 16 17.7761 16 17.5C16 17.2239 15.7761 17 15.5 17H13.8758C16.3346 15.6357 18 13.0128 18 10C18 5.58172 14.4183 2 10 2C5.58172 2 2 5.58172 2 10C2 10.2761 2.22386 10.5 2.5 10.5C2.77614 10.5 3 10.2761 3 10Z\"\n      fill=\"currentColor\"\n    >\n    </path>\n    <path\n      d=\"M10 12C11.1046 12 12 11.1046 12 10C12 8.89543 11.1046 8 10 8C8.89543 8 8 8.89543 8 10C8 11.1046 8.89543 12 10 12ZM10 11C9.44772 11 9 10.5523 9 10C9 9.44772 9.44772 9 10 9C10.5523 9 11 9.44772 11 10C11 10.5523 10.5523 11 10 11Z\"\n      fill=\"currentColor\"\n    >\n    </path>\n  </svg>\n))\n"
  },
  {
    "path": "src/_internal/icons/RotateCounterclockwise.tsx",
    "content": "import { h } from 'vue'\nimport { replaceable } from './replaceable'\n\nexport default replaceable('rotateClockwise', () => (\n  <svg viewBox=\"0 0 20 20\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n    <path\n      d=\"M17 10C17 6.13401 13.866 3 10 3C6.13401 3 3 6.13401 3 10C3 12.7916 4.63419 15.2026 7 16.3265V14.5C7 14.2239 7.22386 14 7.5 14C7.77614 14 8 14.2239 8 14.5V17.5C8 17.7761 7.77614 18 7.5 18H4.5C4.22386 18 4 17.7761 4 17.5C4 17.2239 4.22386 17 4.5 17H6.12422C3.66539 15.6357 2 13.0128 2 10C2 5.58172 5.58172 2 10 2C14.4183 2 18 5.58172 18 10C18 10.2761 17.7761 10.5 17.5 10.5C17.2239 10.5 17 10.2761 17 10Z\"\n      fill=\"currentColor\"\n    >\n    </path>\n    <path\n      d=\"M10 12C8.89543 12 8 11.1046 8 10C8 8.89543 8.89543 8 10 8C11.1046 8 12 8.89543 12 10C12 11.1046 11.1046 12 10 12ZM10 11C10.5523 11 11 10.5523 11 10C11 9.44772 10.5523 9 10 9C9.44772 9 9 9.44772 9 10C9 10.5523 9.44772 11 10 11Z\"\n      fill=\"currentColor\"\n    >\n    </path>\n  </svg>\n))\n"
  },
  {
    "path": "src/_internal/icons/Search.tsx",
    "content": "import { defineComponent, h } from 'vue'\n\nexport default defineComponent({\n  name: 'Search',\n  render() {\n    return (\n      <svg\n        version=\"1.1\"\n        xmlns=\"http://www.w3.org/2000/svg\"\n        viewBox=\"0 0 512 512\"\n        style=\"enable-background: new 0 0 512 512\"\n      >\n        <path\n          d=\"M443.5,420.2L336.7,312.4c20.9-26.2,33.5-59.4,33.5-95.5c0-84.5-68.5-153-153.1-153S64,132.5,64,217s68.5,153,153.1,153\n  c36.6,0,70.1-12.8,96.5-34.2l106.1,107.1c3.2,3.4,7.6,5.1,11.9,5.1c4.1,0,8.2-1.5,11.3-4.5C449.5,437.2,449.7,426.8,443.5,420.2z\n   M217.1,337.1c-32.1,0-62.3-12.5-85-35.2c-22.7-22.7-35.2-52.9-35.2-84.9c0-32.1,12.5-62.3,35.2-84.9c22.7-22.7,52.9-35.2,85-35.2\n  c32.1,0,62.3,12.5,85,35.2c22.7,22.7,35.2,52.9,35.2,84.9c0,32.1-12.5,62.3-35.2,84.9C279.4,324.6,249.2,337.1,217.1,337.1z\"\n        />\n      </svg>\n    )\n  }\n})\n"
  },
  {
    "path": "src/_internal/icons/Success.tsx",
    "content": "import { h } from 'vue'\nimport { replaceable } from './replaceable'\n\nexport default replaceable('success', () => (\n  <svg viewBox=\"0 0 48 48\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n    <g stroke=\"none\" stroke-width=\"1\" fill-rule=\"evenodd\">\n      <g fill-rule=\"nonzero\">\n        <path d=\"M24,4 C35.045695,4 44,12.954305 44,24 C44,35.045695 35.045695,44 24,44 C12.954305,44 4,35.045695 4,24 C4,12.954305 12.954305,4 24,4 Z M32.6338835,17.6161165 C32.1782718,17.1605048 31.4584514,17.1301307 30.9676119,17.5249942 L30.8661165,17.6161165 L20.75,27.732233 L17.1338835,24.1161165 C16.6457281,23.6279612 15.8542719,23.6279612 15.3661165,24.1161165 C14.9105048,24.5717282 14.8801307,25.2915486 15.2749942,25.7823881 L15.3661165,25.8838835 L19.8661165,30.3838835 C20.3217282,30.8394952 21.0415486,30.8698693 21.5323881,30.4750058 L21.6338835,30.3838835 L32.6338835,19.3838835 C33.1220388,18.8957281 33.1220388,18.1042719 32.6338835,17.6161165 Z\" />\n      </g>\n    </g>\n  </svg>\n))\n"
  },
  {
    "path": "src/_internal/icons/Switcher.tsx",
    "content": "import { defineComponent, h } from 'vue'\n\nexport default defineComponent({\n  name: 'Switcher',\n  render() {\n    return (\n      <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 32 32\">\n        <path d=\"M12 8l10 8l-10 8z\" />\n      </svg>\n    )\n  }\n})\n"
  },
  {
    "path": "src/_internal/icons/Time.tsx",
    "content": "import { h } from 'vue'\nimport { replaceable } from './replaceable'\n\nexport default replaceable('time', () => (\n  <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 512 512\">\n    <path\n      d=\"M256,64C150,64,64,150,64,256s86,192,192,192,192-86,192-192S362,64,256,64Z\"\n      style=\"\n        fill: none;\n        stroke: currentColor;\n        stroke-miterlimit: 10;\n        stroke-width: 32px;\n      \"\n    />\n    <polyline\n      points=\"256 128 256 272 352 272\"\n      style=\"\n        fill: none;\n        stroke: currentColor;\n        stroke-linecap: round;\n        stroke-linejoin: round;\n        stroke-width: 32px;\n      \"\n    />\n  </svg>\n))\n"
  },
  {
    "path": "src/_internal/icons/To.tsx",
    "content": "import { h } from 'vue'\nimport { replaceable } from './replaceable'\n\nexport default replaceable('to', () => (\n  <svg viewBox=\"0 0 20 20\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n    <g stroke=\"none\" stroke-width=\"1\" fill=\"none\" fill-rule=\"evenodd\">\n      <g fill=\"currentColor\" fill-rule=\"nonzero\">\n        <path d=\"M11.2654,3.20511 C10.9644,2.92049 10.4897,2.93371 10.2051,3.23464 C9.92049,3.53558 9.93371,4.01027 10.2346,4.29489 L15.4737,9.25 L2.75,9.25 C2.33579,9.25 2,9.58579 2,10.0000012 C2,10.4142 2.33579,10.75 2.75,10.75 L15.476,10.75 L10.2346,15.7073 C9.93371,15.9919 9.92049,16.4666 10.2051,16.7675 C10.4897,17.0684 10.9644,17.0817 11.2654,16.797 L17.6826,10.7276 C17.8489,10.5703 17.9489,10.3702 17.9826,10.1614 C17.994,10.1094 18,10.0554 18,10.0000012 C18,9.94241 17.9935,9.88633 17.9812,9.83246 C17.9462,9.62667 17.8467,9.42976 17.6826,9.27455 L11.2654,3.20511 Z\" />\n      </g>\n    </g>\n  </svg>\n))\n"
  },
  {
    "path": "src/_internal/icons/Trash.tsx",
    "content": "import { h } from 'vue'\nimport { replaceable } from './replaceable'\n\nexport default replaceable('trash', () => (\n  <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 512 512\">\n    <path\n      d=\"M432,144,403.33,419.74A32,32,0,0,1,371.55,448H140.46a32,32,0,0,1-31.78-28.26L80,144\"\n      style=\"fill: none; stroke: currentcolor; stroke-linecap: round; stroke-linejoin: round; stroke-width: 32px;\"\n    >\n    </path>\n    <rect\n      x=\"32\"\n      y=\"64\"\n      width=\"448\"\n      height=\"80\"\n      rx=\"16\"\n      ry=\"16\"\n      style=\"fill: none; stroke: currentcolor; stroke-linecap: round; stroke-linejoin: round; stroke-width: 32px;\"\n    >\n    </rect>\n    <line\n      x1=\"312\"\n      y1=\"240\"\n      x2=\"200\"\n      y2=\"352\"\n      style=\"fill: none; stroke: currentcolor; stroke-linecap: round; stroke-linejoin: round; stroke-width: 32px;\"\n    >\n    </line>\n    <line\n      x1=\"312\"\n      y1=\"352\"\n      x2=\"200\"\n      y2=\"240\"\n      style=\"fill: none; stroke: currentcolor; stroke-linecap: round; stroke-linejoin: round; stroke-width: 32px;\"\n    >\n    </line>\n  </svg>\n))\n"
  },
  {
    "path": "src/_internal/icons/Warning.tsx",
    "content": "import { h } from 'vue'\nimport { replaceable } from './replaceable'\n\nexport default replaceable('warning', () => (\n  <svg viewBox=\"0 0 24 24\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n    <g stroke=\"none\" stroke-width=\"1\" fill-rule=\"evenodd\">\n      <g fill-rule=\"nonzero\">\n        <path d=\"M12,2 C17.523,2 22,6.478 22,12 C22,17.522 17.523,22 12,22 C6.477,22 2,17.522 2,12 C2,6.478 6.477,2 12,2 Z M12.0018002,15.0037242 C11.450254,15.0037242 11.0031376,15.4508407 11.0031376,16.0023869 C11.0031376,16.553933 11.450254,17.0010495 12.0018002,17.0010495 C12.5533463,17.0010495 13.0004628,16.553933 13.0004628,16.0023869 C13.0004628,15.4508407 12.5533463,15.0037242 12.0018002,15.0037242 Z M11.99964,7 C11.4868042,7.00018474 11.0642719,7.38637706 11.0066858,7.8837365 L11,8.00036004 L11.0018003,13.0012393 L11.00857,13.117858 C11.0665141,13.6151758 11.4893244,14.0010638 12.0021602,14.0008793 C12.514996,14.0006946 12.9375283,13.6145023 12.9951144,13.1171428 L13.0018002,13.0005193 L13,7.99964009 L12.9932303,7.8830214 C12.9352861,7.38570354 12.5124758,6.99981552 11.99964,7 Z\" />\n      </g>\n    </g>\n  </svg>\n))\n"
  },
  {
    "path": "src/_internal/icons/ZoomIn.tsx",
    "content": "import { h } from 'vue'\nimport { replaceable } from './replaceable'\n\nexport default replaceable('zoomIn', () => (\n  <svg viewBox=\"0 0 20 20\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n    <path\n      d=\"M11.5 8.5C11.5 8.22386 11.2761 8 11 8H9V6C9 5.72386 8.77614 5.5 8.5 5.5C8.22386 5.5 8 5.72386 8 6V8H6C5.72386 8 5.5 8.22386 5.5 8.5C5.5 8.77614 5.72386 9 6 9H8V11C8 11.2761 8.22386 11.5 8.5 11.5C8.77614 11.5 9 11.2761 9 11V9H11C11.2761 9 11.5 8.77614 11.5 8.5Z\"\n      fill=\"currentColor\"\n    >\n    </path>\n    <path\n      d=\"M8.5 3C11.5376 3 14 5.46243 14 8.5C14 9.83879 13.5217 11.0659 12.7266 12.0196L16.8536 16.1464C17.0488 16.3417 17.0488 16.6583 16.8536 16.8536C16.68 17.0271 16.4106 17.0464 16.2157 16.9114L16.1464 16.8536L12.0196 12.7266C11.0659 13.5217 9.83879 14 8.5 14C5.46243 14 3 11.5376 3 8.5C3 5.46243 5.46243 3 8.5 3ZM8.5 4C6.01472 4 4 6.01472 4 8.5C4 10.9853 6.01472 13 8.5 13C10.9853 13 13 10.9853 13 8.5C13 6.01472 10.9853 4 8.5 4Z\"\n      fill=\"currentColor\"\n    >\n    </path>\n  </svg>\n))\n"
  },
  {
    "path": "src/_internal/icons/ZoomOut.tsx",
    "content": "import { h } from 'vue'\nimport { replaceable } from './replaceable'\n\nexport default replaceable('zoomOut', () => (\n  <svg viewBox=\"0 0 20 20\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n    <path\n      d=\"M11 8C11.2761 8 11.5 8.22386 11.5 8.5C11.5 8.77614 11.2761 9 11 9H6C5.72386 9 5.5 8.77614 5.5 8.5C5.5 8.22386 5.72386 8 6 8H11Z\"\n      fill=\"currentColor\"\n    >\n    </path>\n    <path\n      d=\"M14 8.5C14 5.46243 11.5376 3 8.5 3C5.46243 3 3 5.46243 3 8.5C3 11.5376 5.46243 14 8.5 14C9.83879 14 11.0659 13.5217 12.0196 12.7266L16.1464 16.8536L16.2157 16.9114C16.4106 17.0464 16.68 17.0271 16.8536 16.8536C17.0488 16.6583 17.0488 16.3417 16.8536 16.1464L12.7266 12.0196C13.5217 11.0659 14 9.83879 14 8.5ZM4 8.5C4 6.01472 6.01472 4 8.5 4C10.9853 4 13 6.01472 13 8.5C13 10.9853 10.9853 13 8.5 13C6.01472 13 4 10.9853 4 8.5Z\"\n      fill=\"currentColor\"\n    >\n    </path>\n  </svg>\n))\n"
  },
  {
    "path": "src/_internal/icons/index.ts",
    "content": "export { default as AddIcon } from './Add'\nexport { default as ArrowBackIcon } from './ArrowBack'\nexport { default as ArrowDownIcon } from './ArrowDown'\nexport { default as ArrowUpIcon } from './ArrowUp'\nexport { default as AttachIcon } from './Attach'\nexport { default as BackwardIcon } from './Backward'\nexport { default as CancelIcon } from './Cancel'\nexport { default as CheckmarkIcon } from './Checkmark'\nexport { default as ChevronDownIcon } from './ChevronDown'\nexport { default as ChevronDownFilledIcon } from './ChevronDownFilled'\nexport { default as ChevronLeftIcon } from './ChevronLeft'\nexport { default as ChevronRightIcon } from './ChevronRight'\nexport { default as ClearIcon } from './Clear'\nexport { default as CloseIcon } from './Close'\nexport { default as DateIcon } from './Date'\nexport { default as DownloadIcon } from './Download'\nexport { default as EmptyIcon } from './Empty'\nexport { default as ErrorIcon } from './Error'\nexport { default as EyeIcon } from './Eye'\nexport { default as EyeOffIcon } from './EyeOff'\nexport { default as FastBackwardIcon } from './FastBackward'\nexport { default as FastForwardIcon } from './FastForward'\nexport { default as FileIcon } from './File'\nexport { default as FilterIcon } from './Filter'\nexport { default as ForwardIcon } from './Forward'\nexport { default as InfoIcon } from './Info'\nexport { default as MoreIcon } from './More'\nexport { default as PhotoIcon } from './Photo'\nexport { default as RemoveIcon } from './Remove'\nexport { default as ResizeSmallIcon } from './ResizeSmall'\nexport { default as RetryIcon } from './Retry'\nexport { default as RotateClockwiseIcon } from './RotateClockwise'\nexport { default as RotateCounterclockwiseIcon } from './RotateCounterclockwise'\nexport { default as SearchIcon } from './Search'\nexport { default as SuccessIcon } from './Success'\nexport { default as SwitcherIcon } from './Switcher'\nexport { default as TimeIcon } from './Time'\nexport { default as ToIcon } from './To'\nexport { default as TrashIcon } from './Trash'\nexport { default as WarningIcon } from './Warning'\nexport { default as ZoomInIcon } from './ZoomIn'\nexport { default as ZoomOutIcon } from './ZoomOut'\n"
  },
  {
    "path": "src/_internal/icons/replaceable.tsx",
    "content": "import type { VNode } from 'vue'\nimport type { GlobalIconConfig } from '../../config-provider/src/internal-interface'\nimport { upperFirst } from 'lodash-es'\nimport { defineComponent, h, inject } from 'vue'\nimport { configProviderInjectionKey } from '../../config-provider/src/context'\n\nexport function replaceable(name: keyof GlobalIconConfig, icon: () => VNode) {\n  const IconComponent = defineComponent({\n    render() {\n      return icon()\n    }\n  })\n  return defineComponent({\n    name: upperFirst(name),\n    setup() {\n      const mergedIconsRef = inject(\n        configProviderInjectionKey,\n        null\n      )?.mergedIconsRef\n      return () => {\n        const iconOverride = mergedIconsRef?.value?.[name]\n        return iconOverride ? iconOverride() : <IconComponent />\n      }\n    }\n  })\n}\n"
  },
  {
    "path": "src/_internal/index.ts",
    "content": "export { default as NBaseClear } from './clear'\nexport { NBaseClose } from './close'\nexport { default as NFadeInExpandTransition } from './fade-in-expand-transition'\nexport { default as NBaseFocusDetector } from './focus-detector'\nexport { NBaseIcon } from './icon'\nexport { default as NIconSwitchTransition } from './icon-switch-transition'\nexport { default as NBaseLoading } from './loading'\nexport type { SharedSpinProps } from './loading'\nexport { default as NBaseMenuMask } from './menu-mask'\nexport { NScrollbar, NxScrollbar } from './scrollbar'\nexport type { ScrollbarInst, ScrollbarProps } from './scrollbar'\nexport { default as NInternalSelectMenu } from './select-menu'\nexport type { InternalSelectMenuRef } from './select-menu'\nexport { default as NInternalSelection } from './selection'\nexport type { InternalSelectionInst } from './selection'\nexport { default as NBaseSlotMachine } from './slot-machine'\nexport { default as NBaseSuffix } from './suffix'\nexport { default as NBaseWave } from './wave'\nexport type { BaseWaveRef } from './wave'\n"
  },
  {
    "path": "src/_internal/loading/index.ts",
    "content": "export { default } from './src/Loading'\nexport type { SharedSpinProps } from './src/Loading'\n"
  },
  {
    "path": "src/_internal/loading/src/Loading.tsx",
    "content": "import type { ExtractPublicPropTypes } from '../../../_utils'\nimport { defineComponent, h, toRef } from 'vue'\nimport { useStyle } from '../../../_mixins'\nimport NIconSwitchTransition from '../../icon-switch-transition'\nimport style from './styles/index.cssr'\n\nconst duration = '1.6s'\n\nexport const exposedLoadingProps = {\n  strokeWidth: {\n    type: Number,\n    default: 28\n  },\n  stroke: {\n    type: String,\n    default: undefined\n  },\n  scale: {\n    type: Number,\n    default: 1\n  },\n  radius: {\n    type: Number,\n    default: 100\n  }\n}\n\nexport type SharedSpinProps = ExtractPublicPropTypes<typeof exposedLoadingProps>\n\nexport default defineComponent({\n  name: 'BaseLoading',\n  props: {\n    clsPrefix: {\n      type: String,\n      required: true\n    },\n    show: {\n      type: Boolean,\n      default: true\n    },\n    ...exposedLoadingProps\n  },\n  setup(props) {\n    useStyle('-base-loading', style, toRef(props, 'clsPrefix'))\n  },\n  render() {\n    const { clsPrefix, radius, strokeWidth, stroke, scale } = this\n    const scaledRadius = radius / scale\n    return (\n      <div class={`${clsPrefix}-base-loading`} role=\"img\" aria-label=\"loading\">\n        <NIconSwitchTransition>\n          {{\n            default: () =>\n              this.show ? (\n                <div\n                  key=\"icon\"\n                  class={`${clsPrefix}-base-loading__transition-wrapper`}\n                >\n                  <div class={`${clsPrefix}-base-loading__container`}>\n                    <svg\n                      class={`${clsPrefix}-base-loading__icon`}\n                      viewBox={`0 0 ${2 * scaledRadius} ${2 * scaledRadius}`}\n                      xmlns=\"http://www.w3.org/2000/svg\"\n                      style={{ color: stroke }}\n                    >\n                      <g>\n                        <animateTransform\n                          attributeName=\"transform\"\n                          type=\"rotate\"\n                          values={`0 ${scaledRadius} ${scaledRadius};270 ${scaledRadius} ${scaledRadius}`}\n                          begin=\"0s\"\n                          dur={duration}\n                          fill=\"freeze\"\n                          repeatCount=\"indefinite\"\n                        />\n                        <circle\n                          class={`${clsPrefix}-base-loading__icon`}\n                          fill=\"none\"\n                          stroke=\"currentColor\"\n                          stroke-width={strokeWidth}\n                          stroke-linecap=\"round\"\n                          cx={scaledRadius}\n                          cy={scaledRadius}\n                          r={radius - strokeWidth / 2}\n                          stroke-dasharray={5.67 * radius}\n                          stroke-dashoffset={18.48 * radius}\n                        >\n                          <animateTransform\n                            attributeName=\"transform\"\n                            type=\"rotate\"\n                            values={`0 ${scaledRadius} ${scaledRadius};135 ${scaledRadius} ${scaledRadius};450 ${scaledRadius} ${scaledRadius}`}\n                            begin=\"0s\"\n                            dur={duration}\n                            fill=\"freeze\"\n                            repeatCount=\"indefinite\"\n                          />\n                          <animate\n                            attributeName=\"stroke-dashoffset\"\n                            values={`${5.67 * radius};${1.42 * radius};${\n                              5.67 * radius\n                            }`}\n                            begin=\"0s\"\n                            dur={duration}\n                            fill=\"freeze\"\n                            repeatCount=\"indefinite\"\n                          />\n                        </circle>\n                      </g>\n                    </svg>\n                  </div>\n                </div>\n              ) : (\n                <div\n                  key=\"placeholder\"\n                  class={`${clsPrefix}-base-loading__placeholder`}\n                >\n                  {this.$slots}\n                </div>\n              )\n          }}\n        </NIconSwitchTransition>\n      </div>\n    )\n  }\n})\n"
  },
  {
    "path": "src/_internal/loading/src/styles/index.cssr.ts",
    "content": "import { iconSwitchTransition } from '../../../../_styles/transitions/icon-switch.cssr'\nimport { c, cB, cE } from '../../../../_utils/cssr'\n\nexport default c([\n  c('@keyframes rotator', `\n    0% {\n      -webkit-transform: rotate(0deg);\n      transform: rotate(0deg);\n    }\n    100% {\n      -webkit-transform: rotate(360deg);\n      transform: rotate(360deg);\n    }`),\n  cB('base-loading', `\n    position: relative;\n    line-height: 0;\n    width: 1em;\n    height: 1em;\n  `, [\n    cE('transition-wrapper', `\n      position: absolute;\n      width: 100%;\n      height: 100%;\n    `, [\n      iconSwitchTransition()\n    ]),\n    cE('placeholder', `\n      position: absolute;\n      left: 50%;\n      top: 50%;\n      transform: translateX(-50%) translateY(-50%);\n    `, [\n      iconSwitchTransition({\n        left: '50%',\n        top: '50%',\n        originalTransform: 'translateX(-50%) translateY(-50%)'\n      })\n    ]),\n    cE('container', `\n      animation: rotator 3s linear infinite both;\n    `, [\n      cE('icon', `\n        height: 1em;\n        width: 1em;\n      `)\n    ])\n  ])\n])\n"
  },
  {
    "path": "src/_internal/menu-mask/index.ts",
    "content": "export type { MenuMaskRef } from './src/interface'\nexport { default } from './src/MenuMask'\n"
  },
  {
    "path": "src/_internal/menu-mask/src/MenuMask.tsx",
    "content": "import type { MenuMaskRef } from './interface'\nimport {\n  defineComponent,\n  h,\n  onBeforeUnmount,\n  ref,\n  toRef,\n  Transition\n} from 'vue'\nimport { useStyle } from '../../../_mixins'\nimport style from './styles/index.cssr'\n\nexport default defineComponent({\n  name: 'BaseMenuMask',\n  props: {\n    clsPrefix: {\n      type: String,\n      required: true\n    }\n  },\n  setup(props) {\n    useStyle('-base-menu-mask', style, toRef(props, 'clsPrefix'))\n    const messageRef = ref<string | null>(null)\n    let timerId: number | null = null\n    const uncontrolledShowRef = ref(false)\n    onBeforeUnmount(() => {\n      if (timerId !== null) {\n        window.clearTimeout(timerId)\n      }\n    })\n    const exposedRef: MenuMaskRef = {\n      showOnce(message: string, duration = 1500) {\n        if (timerId)\n          window.clearTimeout(timerId)\n        uncontrolledShowRef.value = true\n        messageRef.value = message\n        timerId = window.setTimeout(() => {\n          uncontrolledShowRef.value = false\n          messageRef.value = null\n        }, duration)\n      }\n    }\n    return {\n      message: messageRef,\n      show: uncontrolledShowRef,\n      ...exposedRef\n    }\n  },\n  render() {\n    return (\n      <Transition name=\"fade-in-transition\">\n        {{\n          default: () =>\n            this.show ? (\n              <div class={`${this.clsPrefix}-base-menu-mask`}>\n                {this.message}\n              </div>\n            ) : null\n        }}\n      </Transition>\n    )\n  }\n})\n"
  },
  {
    "path": "src/_internal/menu-mask/src/interface.ts",
    "content": "export interface MenuMaskRef {\n  showOnce: (message: string, duration?: number) => void\n}\n"
  },
  {
    "path": "src/_internal/menu-mask/src/styles/index.cssr.ts",
    "content": "import { fadeInTransition } from '../../../../_styles/transitions/fade-in.cssr'\nimport { cB } from '../../../../_utils/cssr'\n\nexport default cB('base-menu-mask', `\n  position: absolute;\n  left: 0;\n  right: 0;\n  top: 0;\n  bottom: 0;\n  display: flex;\n  align-items: center;\n  justify-content: center;\n  text-align: center;\n  padding: 14px;\n  overflow: hidden;\n`, [\n  fadeInTransition()\n])\n"
  },
  {
    "path": "src/_internal/scrollbar/index.ts",
    "content": "export {\n  default as NScrollbar,\n  XScrollbar as NxScrollbar\n} from './src/Scrollbar'\nexport type { ScrollbarInst, ScrollbarProps } from './src/Scrollbar'\n"
  },
  {
    "path": "src/_internal/scrollbar/src/Scrollbar.tsx",
    "content": "import type { CSSProperties, HTMLAttributes, PropType, VNode } from 'vue'\nimport type { ThemeProps } from '../../../_mixins'\nimport type {\n  ExtractInternalPropTypes,\n  ExtractPublicPropTypes\n} from '../../../_utils'\nimport type { ScrollbarTheme } from '../styles'\nimport { off, on } from 'evtd'\nimport { depx, getPadding, getPreciseEventTarget, pxfy } from 'seemly'\nimport { useIsIos } from 'vooks'\nimport {\n  computed,\n  defineComponent,\n  Fragment,\n  h,\n  mergeProps,\n  onBeforeUnmount,\n  onMounted,\n  ref,\n  Transition,\n  watchEffect\n} from 'vue'\nimport { VResizeObserver } from 'vueuc'\nimport { useConfig, useRtl, useTheme, useThemeClass } from '../../../_mixins'\nimport { rtlInset, useReactivated, Wrapper } from '../../../_utils'\nimport { scrollbarLight } from '../styles'\nimport style from './styles/index.cssr'\n\ninterface MergedScrollOptions {\n  left?: number\n  top?: number\n  el?: HTMLElement\n  position?: 'top' | 'bottom'\n  behavior?: ScrollBehavior\n  debounce?: boolean\n  index?: number\n  elSize?: number\n}\n\nexport interface ScrollTo {\n  (x: number, y: number): void\n  (options: {\n    left?: number\n    top?: number\n    behavior?: ScrollBehavior\n    debounce?: boolean\n  }): void\n  (options: {\n    el: HTMLElement\n    behavior?: ScrollBehavior\n    debounce?: boolean\n  }): void\n  (options: {\n    index: number\n    elSize: number\n    behavior?: ScrollBehavior\n    debounce?: boolean\n  }): void\n  (options: {\n    position: 'top' | 'bottom'\n    behavior?: ScrollBehavior\n    debounce?: boolean\n  }): void\n}\n\nexport interface ScrollBy {\n  (x: number, y: number): void\n  (options: { left?: number, top?: number, behavior?: ScrollBehavior }): void\n}\n\nexport interface ScrollbarInstMethods {\n  syncUnifiedContainer: () => void\n  scrollTo: ScrollTo\n  scrollBy: ScrollBy\n  sync: () => void\n  handleMouseEnterWrapper: () => void\n  handleMouseLeaveWrapper: () => void\n}\n\nexport interface ScrollbarInst extends ScrollbarInstMethods {\n  $el: HTMLElement\n  containerRef: HTMLElement | null\n  contentRef: HTMLElement | null\n  containerScrollTop: number\n}\n\nconst scrollbarProps = {\n  ...(useTheme.props as ThemeProps<ScrollbarTheme>),\n  duration: {\n    type: Number,\n    default: 0\n  },\n  scrollable: {\n    type: Boolean,\n    default: true\n  },\n  xScrollable: Boolean,\n  trigger: {\n    type: String as PropType<'none' | 'hover'>,\n    default: 'hover'\n  },\n  useUnifiedContainer: Boolean,\n  triggerDisplayManually: Boolean,\n  // If container is set, resize observer won't not attached\n  container: Function as PropType<() => HTMLElement | null | undefined>,\n  content: Function as PropType<() => HTMLElement | null | undefined>,\n  containerClass: String,\n  containerStyle: [String, Object] as PropType<string | CSSProperties>,\n  contentClass: [String, Array] as PropType<string | Array<string | undefined>>,\n  contentStyle: [String, Object] as PropType<string | CSSProperties>,\n  horizontalRailStyle: [String, Object] as PropType<string | CSSProperties>,\n  verticalRailStyle: [String, Object] as PropType<string | CSSProperties>,\n  onScroll: Function as PropType<(e: Event) => void>,\n  onWheel: Function as PropType<(e: WheelEvent) => void>,\n  onResize: Function as PropType<(e: ResizeObserverEntry) => void>,\n  internalOnUpdateScrollLeft: Function as PropType<\n    (scrollLeft: number) => void\n  >,\n  internalHoistYRail: Boolean,\n  internalExposeWidthCssVar: Boolean,\n  yPlacement: {\n    type: String as PropType<'left' | 'right'>,\n    default: 'right'\n  },\n  xPlacement: {\n    type: String as PropType<'top' | 'bottom'>,\n    default: 'bottom'\n  }\n} as const\n\nexport type ScrollbarProps = ExtractPublicPropTypes<typeof scrollbarProps>\nexport type ScrollbarInternalProps = ExtractInternalPropTypes<\n  typeof scrollbarProps\n>\n\nconst Scrollbar = defineComponent({\n  name: 'Scrollbar',\n  props: scrollbarProps,\n  inheritAttrs: false,\n  setup(props) {\n    const { mergedClsPrefixRef, inlineThemeDisabled, mergedRtlRef }\n      = useConfig(props)\n    const rtlEnabledRef = useRtl('Scrollbar', mergedRtlRef, mergedClsPrefixRef)\n\n    // dom ref\n    const wrapperRef = ref<HTMLElement | null>(null)\n    const containerRef = ref<HTMLElement | null>(null)\n    const contentRef = ref<HTMLElement | null>(null)\n    const yRailRef = ref<HTMLElement | null>(null)\n    const xRailRef = ref<HTMLElement | null>(null)\n\n    // data ref\n    const contentHeightRef = ref<number | null>(null)\n    const contentWidthRef = ref<number | null>(null)\n    const containerHeightRef = ref<number | null>(null)\n    const containerWidthRef = ref<number | null>(null)\n    const yRailSizeRef = ref<number | null>(null)\n    const xRailSizeRef = ref<number | null>(null)\n    const containerScrollTopRef = ref(0)\n    const containerScrollLeftRef = ref(0)\n    const isShowXBarRef = ref(false)\n    const isShowYBarRef = ref(false)\n\n    let yBarPressed = false\n    let xBarPressed = false\n    let xBarVanishTimerId: number | undefined\n    let yBarVanishTimerId: number | undefined\n    let memoYTop: number = 0\n    let memoXLeft: number = 0\n    let memoMouseX: number = 0\n    let memoMouseY: number = 0\n    const isIos = useIsIos()\n\n    const themeRef = useTheme(\n      'Scrollbar',\n      '-scrollbar',\n      style,\n      scrollbarLight,\n      props,\n      mergedClsPrefixRef\n    )\n\n    const yBarSizeRef = computed(() => {\n      const { value: containerHeight } = containerHeightRef\n      const { value: contentHeight } = contentHeightRef\n      const { value: yRailSize } = yRailSizeRef\n      if (\n        containerHeight === null\n        || contentHeight === null\n        || yRailSize === null\n      ) {\n        return 0\n      }\n      else {\n        return Math.min(\n          containerHeight,\n          (yRailSize * containerHeight) / contentHeight\n          + depx(themeRef.value.self.width) * 1.5\n        )\n      }\n    })\n    const yBarSizePxRef = computed(() => {\n      return `${yBarSizeRef.value}px`\n    })\n    const xBarSizeRef = computed(() => {\n      const { value: containerWidth } = containerWidthRef\n      const { value: contentWidth } = contentWidthRef\n      const { value: xRailSize } = xRailSizeRef\n      if (\n        containerWidth === null\n        || contentWidth === null\n        || xRailSize === null\n      ) {\n        return 0\n      }\n      else {\n        return (\n          (xRailSize * containerWidth) / contentWidth\n          + depx(themeRef.value.self.height) * 1.5\n        )\n      }\n    })\n    const xBarSizePxRef = computed(() => {\n      return `${xBarSizeRef.value}px`\n    })\n    const yBarTopRef = computed(() => {\n      const { value: containerHeight } = containerHeightRef\n      const { value: containerScrollTop } = containerScrollTopRef\n      const { value: contentHeight } = contentHeightRef\n      const { value: yRailSize } = yRailSizeRef\n      if (\n        containerHeight === null\n        || contentHeight === null\n        || yRailSize === null\n      ) {\n        return 0\n      }\n      else {\n        const heightDiff = contentHeight - containerHeight\n        if (!heightDiff)\n          return 0\n        return (\n          (containerScrollTop / heightDiff) * (yRailSize - yBarSizeRef.value)\n        )\n      }\n    })\n    const yBarTopPxRef = computed(() => {\n      return `${yBarTopRef.value}px`\n    })\n    const xBarLeftRef = computed(() => {\n      const { value: containerWidth } = containerWidthRef\n      const { value: containerScrollLeft } = containerScrollLeftRef\n      const { value: contentWidth } = contentWidthRef\n      const { value: xRailSize } = xRailSizeRef\n      if (\n        containerWidth === null\n        || contentWidth === null\n        || xRailSize === null\n      ) {\n        return 0\n      }\n      else {\n        const widthDiff = contentWidth - containerWidth\n        if (!widthDiff)\n          return 0\n        return (\n          (containerScrollLeft / widthDiff) * (xRailSize - xBarSizeRef.value)\n        )\n      }\n    })\n    const xBarLeftPxRef = computed(() => {\n      return `${xBarLeftRef.value}px`\n    })\n    const needYBarRef = computed(() => {\n      const { value: containerHeight } = containerHeightRef\n      const { value: contentHeight } = contentHeightRef\n      return (\n        containerHeight !== null\n        && contentHeight !== null\n        && contentHeight > containerHeight\n      )\n    })\n    const needXBarRef = computed(() => {\n      const { value: containerWidth } = containerWidthRef\n      const { value: contentWidth } = contentWidthRef\n      return (\n        containerWidth !== null\n        && contentWidth !== null\n        && contentWidth > containerWidth\n      )\n    })\n    const mergedShowXBarRef = computed(() => {\n      const { trigger } = props\n      return trigger === 'none' || isShowXBarRef.value\n    })\n    const mergedShowYBarRef = computed(() => {\n      const { trigger } = props\n      return trigger === 'none' || isShowYBarRef.value\n    })\n    const mergedContainerRef = computed(() => {\n      const { container } = props\n      if (container)\n        return container()\n      return containerRef.value\n    })\n    const mergedContentRef = computed(() => {\n      const { content } = props\n      if (content)\n        return content()\n      return contentRef.value\n    })\n\n    const scrollTo: ScrollTo = (\n      options: MergedScrollOptions | number,\n      y?: number\n    ): void => {\n      if (!props.scrollable)\n        return\n      if (typeof options === 'number') {\n        scrollToPosition(options, y ?? 0, 0, false, 'auto')\n        return\n      }\n      const {\n        left,\n        top,\n        index,\n        elSize,\n        position,\n        behavior,\n        el,\n        debounce = true\n      } = options\n      if (left !== undefined || top !== undefined) {\n        scrollToPosition(left ?? 0, top ?? 0, 0, false, behavior)\n      }\n      if (el !== undefined) {\n        scrollToPosition(0, el.offsetTop, el.offsetHeight, debounce, behavior)\n      }\n      else if (index !== undefined && elSize !== undefined) {\n        scrollToPosition(0, index * elSize, elSize, debounce, behavior)\n      }\n      else if (position === 'bottom') {\n        scrollToPosition(0, Number.MAX_SAFE_INTEGER, 0, false, behavior)\n      }\n      else if (position === 'top') {\n        scrollToPosition(0, 0, 0, false, behavior)\n      }\n    }\n\n    const activateState = useReactivated(() => {\n      // Only restore for builtin container & content\n      if (!props.container) {\n        // remount\n        scrollTo({\n          top: containerScrollTopRef.value,\n          left: containerScrollLeftRef.value\n        })\n      }\n    })\n\n    // methods\n    const handleContentResize = (): void => {\n      if (activateState.isDeactivated)\n        return\n      sync()\n    }\n    const handleContainerResize = (e: ResizeObserverEntry): void => {\n      if (activateState.isDeactivated)\n        return\n      const { onResize } = props\n      if (onResize)\n        onResize(e)\n      sync()\n    }\n    const scrollBy: ScrollBy = (\n      options: ScrollOptions | number,\n      y?: number\n    ): void => {\n      if (!props.scrollable)\n        return\n      const { value: container } = mergedContainerRef\n      if (!container)\n        return\n      if (typeof options === 'object') {\n        container.scrollBy(options)\n      }\n      else {\n        container.scrollBy(options, y || 0)\n      }\n    }\n    function scrollToPosition(\n      left: number,\n      top: number,\n      elSize: number,\n      debounce: boolean,\n      behavior?: ScrollBehavior\n    ): void {\n      const { value: container } = mergedContainerRef\n      if (!container)\n        return\n      if (debounce) {\n        const { scrollTop, offsetHeight } = container\n        if (top > scrollTop) {\n          if (top + elSize <= scrollTop + offsetHeight) {\n            // do nothing\n          }\n          else {\n            container.scrollTo({\n              left,\n              top: top + elSize - offsetHeight,\n              behavior\n            })\n          }\n          return\n        }\n      }\n      container.scrollTo({\n        left,\n        top,\n        behavior\n      })\n    }\n    function handleMouseEnterWrapper(): void {\n      showXBar()\n      showYBar()\n      sync()\n    }\n    function handleMouseLeaveWrapper(): void {\n      hideBar()\n    }\n    function hideBar(): void {\n      hideYBar()\n      hideXBar()\n    }\n    function hideYBar(): void {\n      if (yBarVanishTimerId !== undefined) {\n        window.clearTimeout(yBarVanishTimerId)\n      }\n      yBarVanishTimerId = window.setTimeout(() => {\n        isShowYBarRef.value = false\n      }, props.duration)\n    }\n    function hideXBar(): void {\n      if (xBarVanishTimerId !== undefined) {\n        window.clearTimeout(xBarVanishTimerId)\n      }\n      xBarVanishTimerId = window.setTimeout(() => {\n        isShowXBarRef.value = false\n      }, props.duration)\n    }\n    function showXBar(): void {\n      if (xBarVanishTimerId !== undefined) {\n        window.clearTimeout(xBarVanishTimerId)\n      }\n      isShowXBarRef.value = true\n    }\n    function showYBar(): void {\n      if (yBarVanishTimerId !== undefined) {\n        window.clearTimeout(yBarVanishTimerId)\n      }\n      isShowYBarRef.value = true\n    }\n    function handleScroll(e: Event): void {\n      const { onScroll } = props\n      if (onScroll)\n        onScroll(e)\n      syncScrollState()\n    }\n    function syncScrollState(): void {\n      // only collect scroll state, do not trigger any dom event\n      const { value: container } = mergedContainerRef\n      if (container) {\n        containerScrollTopRef.value = container.scrollTop\n        containerScrollLeftRef.value\n          = container.scrollLeft * (rtlEnabledRef?.value ? -1 : 1)\n      }\n    }\n    function syncPositionState(): void {\n      // only collect position state, do not trigger any dom event\n      // Don't use getClientBoundingRect because element may be scale transformed\n      const { value: content } = mergedContentRef\n      if (content) {\n        contentHeightRef.value = content.offsetHeight\n        contentWidthRef.value = content.offsetWidth\n      }\n      const { value: container } = mergedContainerRef\n      if (container) {\n        containerHeightRef.value = container.offsetHeight\n        containerWidthRef.value = container.offsetWidth\n      }\n      const { value: xRailEl } = xRailRef\n      const { value: yRailEl } = yRailRef\n      if (xRailEl) {\n        xRailSizeRef.value = xRailEl.offsetWidth\n      }\n      if (yRailEl) {\n        yRailSizeRef.value = yRailEl.offsetHeight\n      }\n    }\n    /**\n     * Sometimes there's only one element that we can scroll,\n     * For example for textarea, there won't be a content element.\n     */\n    function syncUnifiedContainer(): void {\n      const { value: container } = mergedContainerRef\n      if (container) {\n        containerScrollTopRef.value = container.scrollTop\n        containerScrollLeftRef.value\n          = container.scrollLeft * (rtlEnabledRef?.value ? -1 : 1)\n        containerHeightRef.value = container.offsetHeight\n        containerWidthRef.value = container.offsetWidth\n        contentHeightRef.value = container.scrollHeight\n        contentWidthRef.value = container.scrollWidth\n      }\n      const { value: xRailEl } = xRailRef\n      const { value: yRailEl } = yRailRef\n      if (xRailEl) {\n        xRailSizeRef.value = xRailEl.offsetWidth\n      }\n      if (yRailEl) {\n        yRailSizeRef.value = yRailEl.offsetHeight\n      }\n    }\n    function sync(): void {\n      if (!props.scrollable)\n        return\n      if (props.useUnifiedContainer) {\n        syncUnifiedContainer()\n      }\n      else {\n        syncPositionState()\n        syncScrollState()\n      }\n    }\n    function isMouseUpAway(e: MouseEvent): boolean {\n      return !wrapperRef.value?.contains(\n        getPreciseEventTarget(e) as Node | null\n      )\n    }\n    function handleXScrollMouseDown(e: MouseEvent): void {\n      e.preventDefault()\n      e.stopPropagation()\n      xBarPressed = true\n      on('mousemove', window, handleXScrollMouseMove, true)\n      on('mouseup', window, handleXScrollMouseUp, true)\n      memoXLeft = containerScrollLeftRef.value\n      memoMouseX = rtlEnabledRef?.value\n        ? window.innerWidth - e.clientX\n        : e.clientX\n    }\n    function handleXScrollMouseMove(e: MouseEvent): void {\n      if (!xBarPressed)\n        return\n      if (xBarVanishTimerId !== undefined) {\n        window.clearTimeout(xBarVanishTimerId)\n      }\n      if (yBarVanishTimerId !== undefined) {\n        window.clearTimeout(yBarVanishTimerId)\n      }\n      const { value: containerWidth } = containerWidthRef\n      const { value: contentWidth } = contentWidthRef\n      const { value: xBarSize } = xBarSizeRef\n      if (containerWidth === null || contentWidth === null)\n        return\n      const dX = rtlEnabledRef?.value\n        ? window.innerWidth - e.clientX - memoMouseX\n        : e.clientX - memoMouseX\n\n      const dScrollLeft\n        = (dX * (contentWidth - containerWidth)) / (containerWidth - xBarSize)\n      const toScrollLeftUpperBound = contentWidth - containerWidth\n      let toScrollLeft = memoXLeft + dScrollLeft\n      toScrollLeft = Math.min(toScrollLeftUpperBound, toScrollLeft)\n      toScrollLeft = Math.max(toScrollLeft, 0)\n      const { value: container } = mergedContainerRef\n      if (container) {\n        container.scrollLeft = toScrollLeft * (rtlEnabledRef?.value ? -1 : 1)\n        const { internalOnUpdateScrollLeft } = props\n        if (internalOnUpdateScrollLeft)\n          internalOnUpdateScrollLeft(toScrollLeft)\n      }\n    }\n    function handleXScrollMouseUp(e: MouseEvent): void {\n      e.preventDefault()\n      e.stopPropagation()\n      off('mousemove', window, handleXScrollMouseMove, true)\n      off('mouseup', window, handleXScrollMouseUp, true)\n      xBarPressed = false\n      sync()\n      if (isMouseUpAway(e)) {\n        hideBar()\n      }\n    }\n    function handleYScrollMouseDown(e: MouseEvent): void {\n      e.preventDefault()\n      e.stopPropagation()\n      yBarPressed = true\n      on('mousemove', window, handleYScrollMouseMove, true)\n      on('mouseup', window, handleYScrollMouseUp, true)\n      memoYTop = containerScrollTopRef.value\n      memoMouseY = e.clientY\n    }\n    function handleYScrollMouseMove(e: MouseEvent): void {\n      if (!yBarPressed)\n        return\n      if (xBarVanishTimerId !== undefined) {\n        window.clearTimeout(xBarVanishTimerId)\n      }\n      if (yBarVanishTimerId !== undefined) {\n        window.clearTimeout(yBarVanishTimerId)\n      }\n      const { value: containerHeight } = containerHeightRef\n      const { value: contentHeight } = contentHeightRef\n      const { value: yBarSize } = yBarSizeRef\n      if (containerHeight === null || contentHeight === null)\n        return\n      const dY = e.clientY - memoMouseY\n      const dScrollTop\n        = (dY * (contentHeight - containerHeight)) / (containerHeight - yBarSize)\n      const toScrollTopUpperBound = contentHeight - containerHeight\n      let toScrollTop = memoYTop + dScrollTop\n      toScrollTop = Math.min(toScrollTopUpperBound, toScrollTop)\n      toScrollTop = Math.max(toScrollTop, 0)\n      const { value: container } = mergedContainerRef\n      if (container) {\n        container.scrollTop = toScrollTop\n      }\n    }\n    function handleYScrollMouseUp(e: MouseEvent): void {\n      e.preventDefault()\n      e.stopPropagation()\n      off('mousemove', window, handleYScrollMouseMove, true)\n      off('mouseup', window, handleYScrollMouseUp, true)\n      yBarPressed = false\n      sync()\n      if (isMouseUpAway(e)) {\n        hideBar()\n      }\n    }\n    watchEffect(() => {\n      const { value: needXBar } = needXBarRef\n      const { value: needYBar } = needYBarRef\n      const { value: mergedClsPrefix } = mergedClsPrefixRef\n      const { value: xRailEl } = xRailRef\n      const { value: yRailEl } = yRailRef\n      if (xRailEl) {\n        if (!needXBar) {\n          xRailEl.classList.add(`${mergedClsPrefix}-scrollbar-rail--disabled`)\n        }\n        else {\n          xRailEl.classList.remove(\n            `${mergedClsPrefix}-scrollbar-rail--disabled`\n          )\n        }\n      }\n      if (yRailEl) {\n        if (!needYBar) {\n          yRailEl.classList.add(`${mergedClsPrefix}-scrollbar-rail--disabled`)\n        }\n        else {\n          yRailEl.classList.remove(\n            `${mergedClsPrefix}-scrollbar-rail--disabled`\n          )\n        }\n      }\n    })\n    onMounted(() => {\n      // if container exist, it always can't be resolved when scrollbar is mounted\n      // for example:\n      // - component\n      //   - scrollbar\n      //     - inner\n      // if you pass inner to scrollbar, you may use a ref inside component\n      // however, when scrollbar is mounted, ref is not ready at component\n      // you need to init by yourself\n      if (props.container)\n        return\n      sync()\n    })\n    onBeforeUnmount(() => {\n      if (xBarVanishTimerId !== undefined) {\n        window.clearTimeout(xBarVanishTimerId)\n      }\n      if (yBarVanishTimerId !== undefined) {\n        window.clearTimeout(yBarVanishTimerId)\n      }\n      off('mousemove', window, handleYScrollMouseMove, true)\n      off('mouseup', window, handleYScrollMouseUp, true)\n    })\n    const cssVarsRef = computed(() => {\n      const {\n        common: { cubicBezierEaseInOut },\n        self: {\n          color,\n          colorHover,\n          height,\n          width,\n          borderRadius,\n          railInsetHorizontalTop,\n          railInsetHorizontalBottom,\n          railInsetVerticalRight,\n          railInsetVerticalLeft,\n          railColor\n        }\n      } = themeRef.value\n\n      const {\n        top: railTopHorizontalTop,\n        right: railRightHorizontalTop,\n        bottom: railBottomHorizontalTop,\n        left: railLeftHorizontalTop\n      } = getPadding(railInsetHorizontalTop)\n\n      const {\n        top: railTopHorizontalBottom,\n        right: railRightHorizontalBottom,\n        bottom: railBottomHorizontalBottom,\n        left: railLeftHorizontalBottom\n      } = getPadding(railInsetHorizontalBottom)\n\n      const {\n        top: railTopVerticalRight,\n        right: railRightVerticalRight,\n        bottom: railBottomVerticalRight,\n        left: railLeftVerticalRight\n      } = getPadding(\n        rtlEnabledRef?.value\n          ? rtlInset(railInsetVerticalRight)\n          : railInsetVerticalRight\n      )\n\n      const {\n        top: railTopVerticalLeft,\n        right: railRightVerticalLeft,\n        bottom: railBottomVerticalLeft,\n        left: railLeftVerticalLeft\n      } = getPadding(\n        rtlEnabledRef?.value\n          ? rtlInset(railInsetVerticalLeft)\n          : railInsetVerticalLeft\n      )\n\n      return {\n        '--n-scrollbar-bezier': cubicBezierEaseInOut,\n        '--n-scrollbar-color': color,\n        '--n-scrollbar-color-hover': colorHover,\n        '--n-scrollbar-border-radius': borderRadius,\n        '--n-scrollbar-width': width,\n        '--n-scrollbar-height': height,\n        '--n-scrollbar-rail-top-horizontal-top': railTopHorizontalTop,\n        '--n-scrollbar-rail-right-horizontal-top': railRightHorizontalTop,\n        '--n-scrollbar-rail-bottom-horizontal-top': railBottomHorizontalTop,\n        '--n-scrollbar-rail-left-horizontal-top': railLeftHorizontalTop,\n        '--n-scrollbar-rail-top-horizontal-bottom': railTopHorizontalBottom,\n        '--n-scrollbar-rail-right-horizontal-bottom': railRightHorizontalBottom,\n        '--n-scrollbar-rail-bottom-horizontal-bottom':\n          railBottomHorizontalBottom,\n        '--n-scrollbar-rail-left-horizontal-bottom': railLeftHorizontalBottom,\n        '--n-scrollbar-rail-top-vertical-right': railTopVerticalRight,\n        '--n-scrollbar-rail-right-vertical-right': railRightVerticalRight,\n        '--n-scrollbar-rail-bottom-vertical-right': railBottomVerticalRight,\n        '--n-scrollbar-rail-left-vertical-right': railLeftVerticalRight,\n        '--n-scrollbar-rail-top-vertical-left': railTopVerticalLeft,\n        '--n-scrollbar-rail-right-vertical-left': railRightVerticalLeft,\n        '--n-scrollbar-rail-bottom-vertical-left': railBottomVerticalLeft,\n        '--n-scrollbar-rail-left-vertical-left': railLeftVerticalLeft,\n        '--n-scrollbar-rail-color': railColor\n      }\n    })\n    const themeClassHandle = inlineThemeDisabled\n      ? useThemeClass('scrollbar', undefined, cssVarsRef, props)\n      : undefined\n    const exposedMethods: ScrollbarInstMethods = {\n      scrollTo,\n      scrollBy,\n      sync,\n      syncUnifiedContainer,\n      handleMouseEnterWrapper,\n      handleMouseLeaveWrapper\n    }\n    return {\n      ...exposedMethods,\n      mergedClsPrefix: mergedClsPrefixRef,\n      rtlEnabled: rtlEnabledRef,\n      containerScrollTop: containerScrollTopRef,\n      wrapperRef,\n      containerRef,\n      contentRef,\n      yRailRef,\n      xRailRef,\n      needYBar: needYBarRef,\n      needXBar: needXBarRef,\n      yBarSizePx: yBarSizePxRef,\n      xBarSizePx: xBarSizePxRef,\n      yBarTopPx: yBarTopPxRef,\n      xBarLeftPx: xBarLeftPxRef,\n      isShowXBar: mergedShowXBarRef,\n      isShowYBar: mergedShowYBarRef,\n      isIos,\n      handleScroll,\n      handleContentResize,\n      handleContainerResize,\n      handleYScrollMouseDown,\n      handleXScrollMouseDown,\n      containerWidth: containerWidthRef,\n      cssVars: inlineThemeDisabled ? undefined : cssVarsRef,\n      themeClass: themeClassHandle?.themeClass,\n      onRender: themeClassHandle?.onRender\n    }\n  },\n  render() {\n    const {\n      $slots,\n      mergedClsPrefix,\n      triggerDisplayManually,\n      rtlEnabled,\n      internalHoistYRail,\n      yPlacement,\n      xPlacement,\n      xScrollable\n    } = this\n    if (!this.scrollable)\n      return $slots.default?.()\n    const triggerIsNone = this.trigger === 'none'\n    const createYRail = (\n      className: string | undefined,\n      style: CSSProperties | undefined\n    ): VNode => {\n      return (\n        <div\n          ref=\"yRailRef\"\n          class={[\n            `${mergedClsPrefix}-scrollbar-rail`,\n            `${mergedClsPrefix}-scrollbar-rail--vertical`,\n            `${mergedClsPrefix}-scrollbar-rail--vertical--${yPlacement}`,\n            className\n          ]}\n          data-scrollbar-rail\n          style={[style || '', this.verticalRailStyle as CSSProperties]}\n          aria-hidden\n        >\n          {h(\n            (triggerIsNone ? Wrapper : Transition) as any,\n            triggerIsNone ? null : { name: 'fade-in-transition' },\n            {\n              default: () =>\n                this.needYBar && this.isShowYBar && !this.isIos ? (\n                  <div\n                    class={`${mergedClsPrefix}-scrollbar-rail__scrollbar`}\n                    style={{\n                      height: this.yBarSizePx,\n                      top: this.yBarTopPx\n                    }}\n                    onMousedown={this.handleYScrollMouseDown}\n                  />\n                ) : null\n            }\n          )}\n        </div>\n      )\n    }\n    const createChildren = (): VNode => {\n      this.onRender?.()\n      return h(\n        'div',\n        mergeProps(this.$attrs, {\n          role: 'none',\n          ref: 'wrapperRef',\n          class: [\n            `${mergedClsPrefix}-scrollbar`,\n            this.themeClass,\n            rtlEnabled && `${mergedClsPrefix}-scrollbar--rtl`\n          ],\n          style: this.cssVars,\n          onMouseenter: triggerDisplayManually\n            ? undefined\n            : this.handleMouseEnterWrapper,\n          onMouseleave: triggerDisplayManually\n            ? undefined\n            : this.handleMouseLeaveWrapper\n        }),\n        [\n          this.container ? (\n            $slots.default?.()\n          ) : (\n            <div\n              role=\"none\"\n              ref=\"containerRef\"\n              class={[\n                `${mergedClsPrefix}-scrollbar-container`,\n                this.containerClass\n              ]}\n              style={[\n                this.containerStyle,\n                this.internalExposeWidthCssVar\n                  ? { '--n-scrollbar-current-width': pxfy(this.containerWidth) }\n                  : undefined\n              ]}\n              onScroll={this.handleScroll}\n              onWheel={this.onWheel}\n            >\n              <VResizeObserver onResize={this.handleContentResize}>\n                {{\n                  default: () => (\n                    <div\n                      ref=\"contentRef\"\n                      role=\"none\"\n                      style={\n                        [\n                          {\n                            width: this.xScrollable ? 'fit-content' : null\n                          },\n                          this.contentStyle\n                        ] as any\n                      }\n                      class={[\n                        `${mergedClsPrefix}-scrollbar-content`,\n                        this.contentClass\n                      ]}\n                    >\n                      {$slots}\n                    </div>\n                  )\n                }}\n              </VResizeObserver>\n            </div>\n          ),\n          internalHoistYRail ? null : createYRail(undefined, undefined),\n          xScrollable && (\n            <div\n              ref=\"xRailRef\"\n              class={[\n                `${mergedClsPrefix}-scrollbar-rail`,\n                `${mergedClsPrefix}-scrollbar-rail--horizontal`,\n                `${mergedClsPrefix}-scrollbar-rail--horizontal--${xPlacement}`\n              ]}\n              style={this.horizontalRailStyle}\n              data-scrollbar-rail\n              aria-hidden\n            >\n              {h(\n                (triggerIsNone ? Wrapper : Transition) as any,\n                triggerIsNone ? null : { name: 'fade-in-transition' },\n                {\n                  default: () =>\n                    this.needXBar && this.isShowXBar && !this.isIos ? (\n                      <div\n                        class={`${mergedClsPrefix}-scrollbar-rail__scrollbar`}\n                        style={{\n                          width: this.xBarSizePx,\n                          right: rtlEnabled ? this.xBarLeftPx : undefined,\n                          left: rtlEnabled ? undefined : this.xBarLeftPx\n                        }}\n                        onMousedown={this.handleXScrollMouseDown}\n                      />\n                    ) : null\n                }\n              )}\n            </div>\n          )\n        ]\n      )\n    }\n    const scrollbarNode = this.container ? (\n      createChildren()\n    ) : (\n      <VResizeObserver onResize={this.handleContainerResize}>\n        {{\n          default: createChildren\n        }}\n      </VResizeObserver>\n    )\n    if (internalHoistYRail) {\n      return (\n        <Fragment>\n          {scrollbarNode}\n          {createYRail(this.themeClass, this.cssVars)}\n        </Fragment>\n      )\n    }\n    else {\n      return scrollbarNode\n    }\n  }\n})\n\ntype NativeScrollbarProps = Omit<HTMLAttributes, keyof ScrollbarInternalProps>\ntype MergedProps = Partial<ScrollbarInternalProps & NativeScrollbarProps>\n\nexport default Scrollbar\nexport const XScrollbar: new () => { $props: MergedProps } = Scrollbar as any\n"
  },
  {
    "path": "src/_internal/scrollbar/src/styles/index.cssr.ts",
    "content": "import { fadeInTransition } from '../../../../_styles/transitions/fade-in.cssr'\nimport { c, cB, cE, cM } from '../../../../_utils/cssr'\n\n// vars:\n// --n-scrollbar-bezier\n// --n-scrollbar-color\n// --n-scrollbar-color-hover\n// --n-scrollbar-width\n// --n-scrollbar-height\n// --n-scrollbar-border-radius\n// --n-scrollbar-rail-inset-horizontal\n// --n-scrollbar-rail-inset-vertical\n// --n-scrollbar-rail-color\nexport default cB('scrollbar', `\n  overflow: hidden;\n  position: relative;\n  z-index: auto;\n  height: 100%;\n  width: 100%;\n`, [\n  c('>', [\n    cB('scrollbar-container', `\n      width: 100%;\n      overflow: scroll;\n      height: 100%;\n      min-height: inherit;\n      max-height: inherit;\n      scrollbar-width: none;\n    `, [\n      c('&::-webkit-scrollbar, &::-webkit-scrollbar-track-piece, &::-webkit-scrollbar-thumb', `\n        width: 0;\n        height: 0;\n        display: none;\n      `),\n      c('>', [\n        // We can't set overflow hidden since it affects positioning.\n        cB('scrollbar-content', `\n          box-sizing: border-box;\n          min-width: 100%;\n        `)\n      ])\n    ])\n  ]),\n  c('>, +', [\n    cB('scrollbar-rail', `\n      position: absolute;\n      pointer-events: none;\n      user-select: none;\n      background: var(--n-scrollbar-rail-color);\n      -webkit-user-select: none;\n    `, [\n      cM('horizontal', `\n        height: var(--n-scrollbar-height);\n      `, [\n        c('>', [\n          cE('scrollbar', `\n            height: var(--n-scrollbar-height);\n            border-radius: var(--n-scrollbar-border-radius);\n            right: 0;\n          `)\n        ])\n      ]),\n      cM('horizontal--top', `\n        top: var(--n-scrollbar-rail-top-horizontal-top);  \n        right: var(--n-scrollbar-rail-right-horizontal-top);  \n        bottom: var(--n-scrollbar-rail-bottom-horizontal-top);  \n        left: var(--n-scrollbar-rail-left-horizontal-top);  \n      `),\n      cM('horizontal--bottom', `\n        top: var(--n-scrollbar-rail-top-horizontal-bottom);  \n        right: var(--n-scrollbar-rail-right-horizontal-bottom);  \n        bottom: var(--n-scrollbar-rail-bottom-horizontal-bottom);  \n        left: var(--n-scrollbar-rail-left-horizontal-bottom);  \n      `),\n      cM('vertical', `\n        width: var(--n-scrollbar-width);\n      `, [\n        c('>', [\n          cE('scrollbar', `\n            width: var(--n-scrollbar-width);\n            border-radius: var(--n-scrollbar-border-radius);\n            bottom: 0;\n          `)\n        ])\n      ]),\n      cM('vertical--left', `\n        top: var(--n-scrollbar-rail-top-vertical-left);  \n        right: var(--n-scrollbar-rail-right-vertical-left);  \n        bottom: var(--n-scrollbar-rail-bottom-vertical-left);  \n        left: var(--n-scrollbar-rail-left-vertical-left);  \n      `),\n      cM('vertical--right', `\n        top: var(--n-scrollbar-rail-top-vertical-right);  \n        right: var(--n-scrollbar-rail-right-vertical-right);  \n        bottom: var(--n-scrollbar-rail-bottom-vertical-right);  \n        left: var(--n-scrollbar-rail-left-vertical-right);  \n      `),\n      cM('disabled', [\n        c('>', [\n          cE('scrollbar', 'pointer-events: none;')\n        ])\n      ]),\n      c('>', [\n        cE('scrollbar', `\n          z-index: 1;\n          position: absolute;\n          cursor: pointer;\n          pointer-events: all;\n          background-color: var(--n-scrollbar-color);\n          transition: background-color .2s var(--n-scrollbar-bezier);\n        `, [\n          fadeInTransition(),\n          c('&:hover', 'background-color: var(--n-scrollbar-color-hover);')\n        ])\n      ])\n    ])\n  ])\n])\n"
  },
  {
    "path": "src/_internal/scrollbar/src/styles/rtl.cssr.ts",
    "content": "import { c, cB, cE, cM } from '../../../../_utils/cssr'\n\nexport default cB('scrollbar', [\n  cM('rtl', `\n    direction: rtl;\n  `, [\n    c('>', [\n      cB('scrollbar-rail', [\n        cM('horizontal', [\n          c('>', [\n            cE('scrollbar', `\n              left: 0;\n              right: unset;\n            `)\n          ])\n        ])\n      ])\n    ])\n  ])\n])\n"
  },
  {
    "path": "src/_internal/scrollbar/styles/common.ts",
    "content": "export const commonVars = {\n  railInsetHorizontalBottom: 'auto 2px 4px 2px',\n  railInsetHorizontalTop: '4px 2px auto 2px',\n  railInsetVerticalRight: '2px 4px 2px auto',\n  railInsetVerticalLeft: '2px auto 2px 4px',\n  railColor: 'transparent'\n}\n"
  },
  {
    "path": "src/_internal/scrollbar/styles/dark.ts",
    "content": "import type { ScrollbarTheme } from './light'\nimport { commonDark } from '../../../_styles/common'\nimport { self } from './light'\n\nconst scrollbarDark: ScrollbarTheme = {\n  name: 'Scrollbar',\n  common: commonDark,\n  self\n}\n\nexport default scrollbarDark\n"
  },
  {
    "path": "src/_internal/scrollbar/styles/index.ts",
    "content": "export { default as scrollbarDark } from './dark'\nexport { default as scrollbarLight } from './light'\nexport type { ScrollbarTheme, ScrollbarThemeVars } from './light'\nexport { default as scrollbarRtl } from './rtl'\n"
  },
  {
    "path": "src/_internal/scrollbar/styles/light.ts",
    "content": "import type { Theme } from '../../../_mixins'\nimport type { ThemeCommonVars } from '../../../_styles/common'\nimport { commonLight } from '../../../_styles/common'\nimport { commonVars } from './common'\n\nexport function self(vars: ThemeCommonVars) {\n  const {\n    scrollbarColor,\n    scrollbarColorHover,\n    scrollbarHeight,\n    scrollbarWidth,\n    scrollbarBorderRadius\n  } = vars\n  return {\n    ...commonVars,\n    height: scrollbarHeight,\n    width: scrollbarWidth,\n    borderRadius: scrollbarBorderRadius,\n    color: scrollbarColor,\n    colorHover: scrollbarColorHover\n  }\n}\n\nexport type ScrollbarThemeVars = ReturnType<typeof self>\n\nconst scrollbarLight: Theme<'Scrollbar', ScrollbarThemeVars> = {\n  name: 'Scrollbar',\n  common: commonLight,\n  self\n}\n\nexport default scrollbarLight\nexport type ScrollbarTheme = typeof scrollbarLight\n"
  },
  {
    "path": "src/_internal/scrollbar/styles/rtl.ts",
    "content": "import type { RtlItem } from '../../../config-provider/src/internal-interface'\nimport rtlStyle from '../src/styles/rtl.cssr'\n\nexport const scrollbarRtl: RtlItem = {\n  name: 'Scrollbar',\n  style: rtlStyle\n}\n\nexport default scrollbarRtl\n"
  },
  {
    "path": "src/_internal/scrollbar/tests/Scrollbar.spec.ts",
    "content": "import { mount } from '@vue/test-utils'\nimport { NScrollbar } from '../index'\n\ndescribe('n-scrollbar', () => {\n  it('should work with import on demand', () => {\n    mount(NScrollbar)\n  })\n})\n"
  },
  {
    "path": "src/_internal/scrollbar/tests/server.spec.tsx",
    "content": "import { setup } from '@css-render/vue3-ssr'\nimport { renderToString } from '@vue/server-renderer'\n/**\n * @vitest-environment node\n */\nimport { createSSRApp, h } from 'vue'\nimport { NScrollbar } from '../index'\n\ndescribe('server side rendering', () => {\n  it('works', async () => {\n    const app = createSSRApp(() => <NScrollbar />)\n    setup(app)\n    try {\n      await renderToString(app)\n    }\n    catch (e) {\n      expect(e).not.toBeTruthy()\n    }\n  })\n})\n"
  },
  {
    "path": "src/_internal/select-menu/index.ts",
    "content": "export type { InternalSelectMenuRef } from './src/interface'\nexport { default } from './src/SelectMenu'\n"
  },
  {
    "path": "src/_internal/select-menu/src/SelectGroupHeader.tsx",
    "content": "import type { TreeNode } from 'treemate'\nimport type { PropType, Ref } from 'vue'\nimport type { SelectGroupOption } from '../../../select/src/interface'\nimport type { RenderLabelImpl, RenderOptionImpl } from './interface'\nimport { defineComponent, h, inject } from 'vue'\nimport { render } from '../../../_utils'\nimport { internalSelectionMenuInjectionKey } from './interface'\n\nexport default defineComponent({\n  name: 'NBaseSelectGroupHeader',\n  props: {\n    clsPrefix: {\n      type: String,\n      required: true\n    },\n    tmNode: {\n      type: Object as PropType<TreeNode<SelectGroupOption>>,\n      required: true\n    }\n  },\n  setup() {\n    const { renderLabelRef, renderOptionRef, labelFieldRef, nodePropsRef }\n      = inject(internalSelectionMenuInjectionKey)!\n    return {\n      labelField: labelFieldRef,\n      nodeProps: nodePropsRef,\n      renderLabel: renderLabelRef as Ref<RenderLabelImpl | undefined>,\n      renderOption: renderOptionRef as Ref<RenderOptionImpl | undefined>\n    }\n  },\n  render() {\n    const {\n      clsPrefix,\n      renderLabel,\n      renderOption,\n      nodeProps,\n      tmNode: { rawNode }\n    } = this\n    const attrs = nodeProps?.(rawNode)\n    const children = renderLabel\n      ? renderLabel(rawNode, false)\n      : render(rawNode[this.labelField], rawNode, false)\n    const node = (\n      <div\n        {...attrs}\n        class={[`${clsPrefix}-base-select-group-header`, attrs?.class]}\n      >\n        {children}\n      </div>\n    )\n    return rawNode.render\n      ? rawNode.render({ node, option: rawNode })\n      : renderOption\n        ? renderOption({ node, option: rawNode, selected: false })\n        : node\n  }\n})\n"
  },
  {
    "path": "src/_internal/select-menu/src/SelectMenu.tsx",
    "content": "import type { TreeNode } from 'treemate'\nimport type { CSSProperties, PropType, WatchStopHandle } from 'vue'\nimport type { VirtualListInst } from 'vueuc'\nimport type { ThemeProps } from '../../../_mixins'\nimport type {\n  SelectGroupOption,\n  SelectIgnoredOption,\n  SelectOption,\n  SelectTreeMate,\n  Value\n} from '../../../select/src/interface'\nimport type { ScrollbarInst } from '../../scrollbar'\nimport type { ScrollbarProps } from '../../scrollbar/src/Scrollbar'\nimport type { InternalSelectMenuTheme } from '../styles'\nimport type {\n  InternalExposedProps,\n  NodeProps,\n  RenderLabel,\n  RenderOption,\n  Size\n} from './interface'\nimport { depx, getPadding, happensIn } from 'seemly'\nimport { createIndexGetter } from 'treemate'\nimport {\n  computed,\n  defineComponent,\n  h,\n  nextTick,\n  onBeforeUnmount,\n  onMounted,\n  provide,\n  ref,\n  toRef,\n  watch\n} from 'vue'\nimport { VirtualList } from 'vueuc'\nimport { useConfig, useRtl, useTheme, useThemeClass } from '../../../_mixins'\nimport { resolveSlot, resolveWrappedSlot, useOnResize } from '../../../_utils'\nimport { createKey } from '../../../_utils/cssr'\nimport { NEmpty } from '../../../empty'\nimport NFocusDetector from '../../focus-detector'\nimport NInternalLoading from '../../loading'\nimport { NScrollbar } from '../../scrollbar'\nimport { internalSelectMenuLight } from '../styles'\nimport {\n  internalSelectionMenuBodyInjectionKey,\n  internalSelectionMenuInjectionKey\n} from './interface'\nimport NSelectGroupHeader from './SelectGroupHeader'\nimport NSelectOption from './SelectOption'\nimport style from './styles/index.cssr'\n\nexport default defineComponent({\n  name: 'InternalSelectMenu',\n  props: {\n    ...(useTheme.props as ThemeProps<InternalSelectMenuTheme>),\n    clsPrefix: {\n      type: String,\n      required: true\n    },\n    scrollable: {\n      type: Boolean,\n      default: true\n    },\n    treeMate: {\n      type: Object as PropType<SelectTreeMate>,\n      required: true\n    },\n    multiple: Boolean,\n    size: {\n      type: String as PropType<Size>,\n      default: 'medium'\n    },\n    value: {\n      type: [String, Number, Array] as PropType<Value | null>,\n      default: null\n    },\n    autoPending: Boolean,\n    virtualScroll: {\n      type: Boolean,\n      default: true\n    },\n    // show is used to toggle pending state initialization\n    show: {\n      type: Boolean,\n      default: true\n    },\n    labelField: {\n      type: String,\n      default: 'label'\n    },\n    valueField: {\n      type: String,\n      default: 'value'\n    },\n    loading: Boolean,\n    focusable: Boolean,\n    renderLabel: Function as PropType<RenderLabel>,\n    renderOption: Function as PropType<RenderOption>,\n    nodeProps: Function as PropType<NodeProps>,\n    showCheckmark: { type: Boolean, default: true },\n    onMousedown: Function as PropType<(e: MouseEvent) => void>,\n    onScroll: Function as PropType<(e: Event) => void>,\n    onFocus: Function as PropType<(e: FocusEvent) => void>,\n    onBlur: Function as PropType<(e: FocusEvent) => void>,\n    onKeyup: Function as PropType<(e: KeyboardEvent) => void>,\n    onKeydown: Function as PropType<(e: KeyboardEvent) => void>,\n    onTabOut: Function as PropType<() => void>,\n    onMouseenter: Function as PropType<(e: MouseEvent) => void>,\n    onMouseleave: Function as PropType<(e: MouseEvent) => void>,\n    onResize: Function as PropType<() => void>,\n    resetMenuOnOptionsChange: {\n      type: Boolean,\n      default: true\n    },\n    inlineThemeDisabled: Boolean,\n    scrollbarProps: Object as PropType<ScrollbarProps>,\n    // deprecated\n    onToggle: Function as PropType<(tmNode: TreeNode<SelectOption>) => void>\n  },\n  setup(props) {\n    const { mergedClsPrefixRef, mergedRtlRef, mergedComponentPropsRef }\n      = useConfig(props)\n    const rtlEnabledRef = useRtl(\n      'InternalSelectMenu',\n      mergedRtlRef,\n      mergedClsPrefixRef\n    )\n    const themeRef = useTheme(\n      'InternalSelectMenu',\n      '-internal-select-menu',\n      style,\n      internalSelectMenuLight,\n      props,\n      toRef(props, 'clsPrefix')\n    )\n    const selfRef = ref<HTMLElement | null>(null)\n    const virtualListRef = ref<VirtualListInst | null>(null)\n    const scrollbarRef = ref<ScrollbarInst | null>(null)\n    const flattenedNodesRef = computed(() => props.treeMate.getFlattenedNodes())\n    const fIndexGetterRef = computed(() =>\n      createIndexGetter(flattenedNodesRef.value)\n    )\n    const pendingNodeRef = ref<TreeNode<SelectOption> | null>(null)\n    function initPendingNode(): void {\n      const { treeMate } = props\n      let defaultPendingNode: TreeNode<SelectOption> | null = null\n      const { value } = props\n      if (value === null) {\n        defaultPendingNode = treeMate.getFirstAvailableNode()\n      }\n      else {\n        if (props.multiple) {\n          defaultPendingNode = treeMate.getNode(\n            ((value as Array<string | number> | null) || [])[\n              ((value as Array<string | number> | null) || []).length - 1\n            ]\n          )\n        }\n        else {\n          defaultPendingNode = treeMate.getNode(value as string | number)\n        }\n        if (!defaultPendingNode || defaultPendingNode.disabled) {\n          defaultPendingNode = treeMate.getFirstAvailableNode()\n        }\n      }\n      if (defaultPendingNode) {\n        setPendingTmNode(defaultPendingNode)\n      }\n      else {\n        setPendingTmNode(null)\n      }\n    }\n    function clearPendingNodeIfInvalid(): void {\n      const { value: pendingNode } = pendingNodeRef\n      if (pendingNode && !props.treeMate.getNode(pendingNode.key)) {\n        pendingNodeRef.value = null\n      }\n    }\n\n    let initPendingNodeWatchStopHandle: WatchStopHandle | undefined\n    watch(\n      () => props.show,\n      (show) => {\n        if (show) {\n          initPendingNodeWatchStopHandle = watch(\n            () => props.treeMate,\n            () => {\n              if (props.resetMenuOnOptionsChange) {\n                if (props.autoPending) {\n                  initPendingNode()\n                }\n                else {\n                  clearPendingNodeIfInvalid()\n                }\n                void nextTick(scrollToPendingNode)\n              }\n              else {\n                clearPendingNodeIfInvalid()\n              }\n            },\n            {\n              immediate: true\n            }\n          )\n        }\n        else {\n          initPendingNodeWatchStopHandle?.()\n        }\n      },\n      {\n        immediate: true\n      }\n    )\n    onBeforeUnmount(() => {\n      initPendingNodeWatchStopHandle?.()\n    })\n\n    const itemSizeRef = computed(() => {\n      return depx(themeRef.value.self[createKey('optionHeight', props.size)])\n    })\n    const paddingRef = computed(() => {\n      return getPadding(themeRef.value.self[createKey('padding', props.size)])\n    })\n    const valueSetRef = computed(() => {\n      if (props.multiple && Array.isArray(props.value)) {\n        return new Set(props.value)\n      }\n      return new Set<string | number>()\n    })\n    const emptyRef = computed(() => {\n      const tmNodes = flattenedNodesRef.value\n      return tmNodes && tmNodes.length === 0\n    })\n    const mergedRenderEmptyRef = computed(() => {\n      return mergedComponentPropsRef?.value?.Select?.renderEmpty\n    })\n    function doToggle(tmNode: TreeNode<SelectOption>): void {\n      const { onToggle } = props\n      if (onToggle)\n        onToggle(tmNode)\n    }\n    function doScroll(e: Event): void {\n      const { onScroll } = props\n      if (onScroll)\n        onScroll(e)\n    }\n    // required, scroller sync need to be triggered manually\n    function handleVirtualListScroll(e: Event): void {\n      scrollbarRef.value?.sync()\n      doScroll(e)\n    }\n    function handleVirtualListResize(): void {\n      scrollbarRef.value?.sync()\n    }\n    function getPendingTmNode(): TreeNode<SelectOption> | null {\n      const { value: pendingTmNode } = pendingNodeRef\n      if (pendingTmNode)\n        return pendingTmNode\n      return null\n    }\n    function handleOptionMouseEnter(\n      e: MouseEvent,\n      tmNode: TreeNode<SelectOption>\n    ): void {\n      if (tmNode.disabled)\n        return\n      setPendingTmNode(tmNode, false)\n    }\n    function handleOptionClick(\n      e: MouseEvent,\n      tmNode: TreeNode<SelectOption>\n    ): void {\n      if (tmNode.disabled)\n        return\n      doToggle(tmNode)\n    }\n    // keyboard related methods\n    function handleKeyUp(e: KeyboardEvent): void {\n      if (happensIn(e, 'action'))\n        return\n      props.onKeyup?.(e)\n    }\n    function handleKeyDown(e: KeyboardEvent): void {\n      if (happensIn(e, 'action'))\n        return\n      props.onKeydown?.(e)\n    }\n    function handleMouseDown(e: MouseEvent): void {\n      props.onMousedown?.(e)\n      if (props.focusable)\n        return\n      e.preventDefault()\n    }\n    function next(): void {\n      const { value: pendingTmNode } = pendingNodeRef\n      if (pendingTmNode) {\n        setPendingTmNode(pendingTmNode.getNext({ loop: true }), true)\n      }\n    }\n    function prev(): void {\n      const { value: pendingTmNode } = pendingNodeRef\n      if (pendingTmNode) {\n        setPendingTmNode(pendingTmNode.getPrev({ loop: true }), true)\n      }\n    }\n    function setPendingTmNode(\n      tmNode: TreeNode<SelectOption> | null,\n      doScroll = false\n    ): void {\n      pendingNodeRef.value = tmNode\n      if (doScroll)\n        scrollToPendingNode()\n    }\n    function scrollToPendingNode(): void {\n      const tmNode = pendingNodeRef.value\n      if (!tmNode)\n        return\n      const fIndex = fIndexGetterRef.value(tmNode.key)\n      if (fIndex === null)\n        return\n      if (props.virtualScroll) {\n        virtualListRef.value?.scrollTo({ index: fIndex })\n      }\n      else {\n        scrollbarRef.value?.scrollTo({\n          index: fIndex,\n          elSize: itemSizeRef.value\n        })\n      }\n    }\n    function handleFocusin(e: FocusEvent): void {\n      if (selfRef.value?.contains(e.target as Node | null)) {\n        props.onFocus?.(e)\n      }\n    }\n    function handleFocusout(e: FocusEvent): void {\n      if (!selfRef.value?.contains(e.relatedTarget as Node | null)) {\n        props.onBlur?.(e)\n      }\n    }\n    provide(internalSelectionMenuInjectionKey, {\n      handleOptionMouseEnter,\n      handleOptionClick,\n      valueSetRef,\n      pendingTmNodeRef: pendingNodeRef,\n      nodePropsRef: toRef(props, 'nodeProps'),\n      showCheckmarkRef: toRef(props, 'showCheckmark'),\n      multipleRef: toRef(props, 'multiple'),\n      valueRef: toRef(props, 'value'),\n      renderLabelRef: toRef(props, 'renderLabel'),\n      renderOptionRef: toRef(props, 'renderOption'),\n      labelFieldRef: toRef(props, 'labelField'),\n      valueFieldRef: toRef(props, 'valueField')\n    })\n    provide(internalSelectionMenuBodyInjectionKey, selfRef)\n    onMounted(() => {\n      const { value } = scrollbarRef\n      if (value)\n        value.sync()\n    })\n    const cssVarsRef = computed(() => {\n      const { size } = props\n      const {\n        common: { cubicBezierEaseInOut },\n        self: {\n          height,\n          borderRadius,\n          color,\n          groupHeaderTextColor,\n          actionDividerColor,\n          optionTextColorPressed,\n          optionTextColor,\n          optionTextColorDisabled,\n          optionTextColorActive,\n          optionOpacityDisabled,\n          optionCheckColor,\n          actionTextColor,\n          optionColorPending,\n          optionColorActive,\n          loadingColor,\n          loadingSize,\n          optionColorActivePending,\n          [createKey('optionFontSize', size)]: fontSize,\n          [createKey('optionHeight', size)]: optionHeight,\n          [createKey('optionPadding', size)]: optionPadding\n        }\n      } = themeRef.value\n      return {\n        '--n-height': height,\n        '--n-action-divider-color': actionDividerColor,\n        '--n-action-text-color': actionTextColor,\n        '--n-bezier': cubicBezierEaseInOut,\n        '--n-border-radius': borderRadius,\n        '--n-color': color,\n        '--n-option-font-size': fontSize,\n        '--n-group-header-text-color': groupHeaderTextColor,\n        '--n-option-check-color': optionCheckColor,\n        '--n-option-color-pending': optionColorPending,\n        '--n-option-color-active': optionColorActive,\n        '--n-option-color-active-pending': optionColorActivePending,\n        '--n-option-height': optionHeight,\n        '--n-option-opacity-disabled': optionOpacityDisabled,\n        '--n-option-text-color': optionTextColor,\n        '--n-option-text-color-active': optionTextColorActive,\n        '--n-option-text-color-disabled': optionTextColorDisabled,\n        '--n-option-text-color-pressed': optionTextColorPressed,\n        '--n-option-padding': optionPadding,\n        '--n-option-padding-left': getPadding(optionPadding, 'left'),\n        '--n-option-padding-right': getPadding(optionPadding, 'right'),\n        '--n-loading-color': loadingColor,\n        '--n-loading-size': loadingSize\n      }\n    })\n    const { inlineThemeDisabled } = props\n    const themeClassHandle = inlineThemeDisabled\n      ? useThemeClass(\n          'internal-select-menu',\n          computed(() => props.size[0]),\n          cssVarsRef,\n          props\n        )\n      : undefined\n    const exposedProps: InternalExposedProps = {\n      selfRef,\n      next,\n      prev,\n      getPendingTmNode\n    }\n    useOnResize(selfRef, props.onResize)\n    return {\n      mergedTheme: themeRef,\n      mergedClsPrefix: mergedClsPrefixRef,\n      rtlEnabled: rtlEnabledRef,\n      virtualListRef,\n      scrollbarRef,\n      itemSize: itemSizeRef,\n      padding: paddingRef,\n      flattenedNodes: flattenedNodesRef,\n      empty: emptyRef,\n      mergedRenderEmpty: mergedRenderEmptyRef,\n      virtualListContainer() {\n        const { value } = virtualListRef\n        return value?.listElRef\n      },\n      virtualListContent() {\n        const { value } = virtualListRef\n        return value?.itemsElRef\n      },\n      doScroll,\n      handleFocusin,\n      handleFocusout,\n      handleKeyUp,\n      handleKeyDown,\n      handleMouseDown,\n      handleVirtualListResize,\n      handleVirtualListScroll,\n      cssVars: inlineThemeDisabled ? undefined : cssVarsRef,\n      themeClass: themeClassHandle?.themeClass,\n      onRender: themeClassHandle?.onRender,\n      ...exposedProps\n    }\n  },\n  render() {\n    const {\n      $slots,\n      virtualScroll,\n      clsPrefix,\n      mergedTheme,\n      themeClass,\n      onRender\n    } = this\n    onRender?.()\n    return (\n      <div\n        ref=\"selfRef\"\n        tabindex={this.focusable ? 0 : -1}\n        class={[\n          `${clsPrefix}-base-select-menu`,\n          `${clsPrefix}-base-select-menu--${this.size}-size`,\n          this.rtlEnabled && `${clsPrefix}-base-select-menu--rtl`,\n          themeClass,\n          this.multiple && `${clsPrefix}-base-select-menu--multiple`\n        ]}\n        style={this.cssVars as CSSProperties}\n        onFocusin={this.handleFocusin}\n        onFocusout={this.handleFocusout}\n        onKeyup={this.handleKeyUp}\n        onKeydown={this.handleKeyDown}\n        onMousedown={this.handleMouseDown}\n        onMouseenter={this.onMouseenter}\n        onMouseleave={this.onMouseleave}\n      >\n        {resolveWrappedSlot(\n          $slots.header,\n          children =>\n            children && (\n              <div\n                class={`${clsPrefix}-base-select-menu__header`}\n                data-header\n                key=\"header\"\n              >\n                {children}\n              </div>\n            )\n        )}\n        {this.loading ? (\n          <div class={`${clsPrefix}-base-select-menu__loading`}>\n            <NInternalLoading clsPrefix={clsPrefix} strokeWidth={20} />\n          </div>\n        ) : !this.empty ? (\n          <NScrollbar\n            ref=\"scrollbarRef\"\n            theme={mergedTheme.peers.Scrollbar}\n            themeOverrides={mergedTheme.peerOverrides.Scrollbar}\n            scrollable={this.scrollable}\n            container={virtualScroll ? this.virtualListContainer : undefined}\n            content={virtualScroll ? this.virtualListContent : undefined}\n            onScroll={virtualScroll ? undefined : this.doScroll}\n            {...this.scrollbarProps}\n          >\n            {{\n              default: () => {\n                return virtualScroll ? (\n                  <VirtualList\n                    ref=\"virtualListRef\"\n                    class={`${clsPrefix}-virtual-list`}\n                    items={this.flattenedNodes}\n                    itemSize={this.itemSize}\n                    showScrollbar={false}\n                    paddingTop={this.padding.top}\n                    paddingBottom={this.padding.bottom}\n                    onResize={this.handleVirtualListResize}\n                    onScroll={this.handleVirtualListScroll}\n                    itemResizable\n                  >\n                    {{\n                      default: ({\n                        item: tmNode\n                      }: {\n                        item: TreeNode<\n                          SelectGroupOption | SelectOption | SelectIgnoredOption\n                        >\n                      }) => {\n                        return tmNode.isGroup ? (\n                          <NSelectGroupHeader\n                            key={tmNode.key}\n                            clsPrefix={clsPrefix}\n                            tmNode={\n                              tmNode as unknown as TreeNode<SelectGroupOption>\n                            }\n                          />\n                        ) : tmNode.ignored ? null : (\n                          <NSelectOption\n                            clsPrefix={clsPrefix}\n                            key={tmNode.key}\n                            tmNode={tmNode as unknown as TreeNode<SelectOption>}\n                          />\n                        )\n                      }\n                    }}\n                  </VirtualList>\n                ) : (\n                  <div\n                    class={`${clsPrefix}-base-select-menu-option-wrapper`}\n                    style={{\n                      paddingTop: this.padding.top,\n                      paddingBottom: this.padding.bottom\n                    }}\n                  >\n                    {this.flattenedNodes.map(tmNode =>\n                      tmNode.isGroup ? (\n                        <NSelectGroupHeader\n                          key={tmNode.key}\n                          clsPrefix={clsPrefix}\n                          tmNode={\n                            tmNode as unknown as TreeNode<SelectGroupOption>\n                          }\n                        />\n                      ) : (\n                        <NSelectOption\n                          clsPrefix={clsPrefix}\n                          key={tmNode.key}\n                          tmNode={tmNode as unknown as TreeNode<SelectOption>}\n                        />\n                      )\n                    )}\n                  </div>\n                )\n              }\n            }}\n          </NScrollbar>\n        ) : (\n          <div class={`${clsPrefix}-base-select-menu__empty`} data-empty>\n            {resolveSlot($slots.empty, () => {\n              return [\n                this.mergedRenderEmpty?.() || (\n                  <NEmpty\n                    theme={mergedTheme.peers.Empty}\n                    themeOverrides={mergedTheme.peerOverrides.Empty}\n                    size={this.size}\n                  />\n                )\n              ]\n            })}\n          </div>\n        )}\n        {resolveWrappedSlot(\n          $slots.action,\n          children =>\n            children && [\n              <div\n                class={`${clsPrefix}-base-select-menu__action`}\n                data-action\n                key=\"action\"\n              >\n                {children}\n              </div>,\n              <NFocusDetector onFocus={this.onTabOut} key=\"focus-detector\" />\n            ]\n        )}\n      </div>\n    )\n  }\n})\n"
  },
  {
    "path": "src/_internal/select-menu/src/SelectOption.tsx",
    "content": "import type { TreeNode } from 'treemate'\nimport type { PropType, Ref, VNode } from 'vue'\nimport type { SelectOption } from '../../../select/src/interface'\nimport type { RenderLabelImpl, RenderOptionImpl } from './interface'\nimport { useMemo } from 'vooks'\nimport { defineComponent, h, inject, Transition } from 'vue'\nimport { mergeEventHandlers, render } from '../../../_utils'\nimport { NBaseIcon } from '../../icon'\nimport { CheckmarkIcon } from '../../icons'\nimport { internalSelectionMenuInjectionKey } from './interface'\n\nfunction renderCheckMark(show: boolean, clsPrefix: string): VNode {\n  return (\n    <Transition name=\"fade-in-scale-up-transition\">\n      {{\n        default: () =>\n          show ? (\n            <NBaseIcon\n              clsPrefix={clsPrefix}\n              class={`${clsPrefix}-base-select-option__check`}\n            >\n              {{\n                default: () => h(CheckmarkIcon)\n              }}\n            </NBaseIcon>\n          ) : null\n      }}\n    </Transition>\n  )\n}\n\nexport default defineComponent({\n  name: 'NBaseSelectOption',\n  props: {\n    clsPrefix: {\n      type: String,\n      required: true\n    },\n    tmNode: {\n      type: Object as PropType<TreeNode<SelectOption>>,\n      required: true\n    }\n  },\n  setup(props) {\n    const {\n      valueRef,\n      pendingTmNodeRef,\n      multipleRef,\n      valueSetRef,\n      renderLabelRef,\n      renderOptionRef,\n      labelFieldRef,\n      valueFieldRef,\n      showCheckmarkRef,\n      nodePropsRef,\n      handleOptionClick,\n      handleOptionMouseEnter\n    } = inject(internalSelectionMenuInjectionKey)!\n    const isPendingRef = useMemo(() => {\n      const { value: pendingTmNode } = pendingTmNodeRef\n      if (!pendingTmNode)\n        return false\n      return props.tmNode.key === pendingTmNode.key\n    })\n    function handleClick(e: MouseEvent): void {\n      const { tmNode } = props\n      if (tmNode.disabled)\n        return\n      handleOptionClick(e, tmNode)\n    }\n    function handleMouseEnter(e: MouseEvent): void {\n      const { tmNode } = props\n      if (tmNode.disabled)\n        return\n      handleOptionMouseEnter(e, tmNode)\n    }\n    function handleMouseMove(e: MouseEvent): void {\n      const { tmNode } = props\n      const { value: isPending } = isPendingRef\n      if (tmNode.disabled || isPending)\n        return\n      handleOptionMouseEnter(e, tmNode)\n    }\n    return {\n      multiple: multipleRef,\n      isGrouped: useMemo(() => {\n        const { tmNode } = props\n        const { parent } = tmNode\n        return parent && parent.rawNode.type === 'group'\n      }),\n      showCheckmark: showCheckmarkRef,\n      nodeProps: nodePropsRef,\n      isPending: isPendingRef,\n      isSelected: useMemo(() => {\n        const { value } = valueRef\n        const { value: multiple } = multipleRef\n        if (value === null)\n          return false\n        const optionValue = props.tmNode.rawNode[\n          valueFieldRef.value\n        ] as NonNullable<SelectOption['value']>\n        if (multiple) {\n          const { value: valueSet } = valueSetRef\n          return valueSet.has(optionValue)\n        }\n        else {\n          return value === optionValue\n        }\n      }),\n      labelField: labelFieldRef,\n      renderLabel: renderLabelRef as Ref<RenderLabelImpl | undefined>,\n      renderOption: renderOptionRef as Ref<RenderOptionImpl | undefined>,\n      handleMouseMove,\n      handleMouseEnter,\n      handleClick\n    }\n  },\n  render() {\n    const {\n      clsPrefix,\n      tmNode: { rawNode },\n      isSelected,\n      isPending,\n      isGrouped,\n      showCheckmark,\n      nodeProps,\n      renderOption,\n      renderLabel,\n      handleClick,\n      handleMouseEnter,\n      handleMouseMove\n    } = this\n    const checkmark = renderCheckMark(isSelected, clsPrefix)\n    const children = renderLabel\n      ? [renderLabel(rawNode, isSelected), showCheckmark && checkmark]\n      : [\n          render(\n            rawNode[this.labelField] as SelectOption['label'],\n            rawNode,\n            isSelected\n          ),\n          showCheckmark && checkmark\n        ]\n    const attrs = nodeProps?.(rawNode)\n    const node = (\n      <div\n        {...attrs}\n        class={[\n          `${clsPrefix}-base-select-option`,\n          rawNode.class,\n          attrs?.class,\n          {\n            [`${clsPrefix}-base-select-option--disabled`]: rawNode.disabled,\n            [`${clsPrefix}-base-select-option--selected`]: isSelected,\n            [`${clsPrefix}-base-select-option--grouped`]: isGrouped,\n            [`${clsPrefix}-base-select-option--pending`]: isPending,\n            [`${clsPrefix}-base-select-option--show-checkmark`]: showCheckmark\n          }\n        ]}\n        style={[attrs?.style || '', rawNode.style || '']}\n        onClick={mergeEventHandlers([handleClick, attrs?.onClick])}\n        onMouseenter={mergeEventHandlers([\n          handleMouseEnter,\n          attrs?.onMouseenter\n        ])}\n        onMousemove={mergeEventHandlers([handleMouseMove, attrs?.onMousemove])}\n      >\n        <div class={`${clsPrefix}-base-select-option__content`}>{children}</div>\n      </div>\n    )\n    return rawNode.render\n      ? rawNode.render({ node, option: rawNode, selected: isSelected })\n      : renderOption\n        ? renderOption({ node, option: rawNode, selected: isSelected })\n        : node\n  }\n})\n"
  },
  {
    "path": "src/_internal/select-menu/src/interface.ts",
    "content": "import type { TreeNode } from 'treemate'\nimport type { HTMLAttributes, Ref, UnwrapRef, VNode, VNodeChild } from 'vue'\nimport type {\n  SelectBaseOption,\n  SelectGroupOption,\n  SelectIgnoredOption\n} from '../../../select/src/interface'\nimport { createInjectionKey } from '../../../_utils/vue/create-injection-key'\n\nexport type Size = 'tiny' | 'small' | 'medium' | 'large' | 'huge'\n\nexport type RenderLabel = (\n  option: SelectBaseOption & SelectGroupOption & SelectIgnoredOption,\n  selected: boolean\n) => VNodeChild\n\nexport type RenderLabelImpl = (\n  option: SelectBaseOption | SelectGroupOption | SelectIgnoredOption,\n  selected: boolean\n) => VNodeChild\n\nexport type RenderOption = (info: {\n  node: VNode\n  option: SelectBaseOption & SelectGroupOption & SelectIgnoredOption\n  selected: boolean\n}) => VNodeChild\n\nexport type RenderOptionImpl = (info: {\n  node: VNode\n  option: SelectBaseOption | SelectGroupOption | SelectIgnoredOption\n  selected: boolean\n}) => VNodeChild\n\nexport type NodeProps = (\n  option: SelectBaseOption | SelectGroupOption\n) => HTMLAttributes & Record<string, unknown>\n\nexport interface InternalSelectMenuInjection {\n  handleOptionMouseEnter: (\n    e: MouseEvent,\n    tmNode: TreeNode<SelectBaseOption>\n  ) => void\n  handleOptionClick: (e: MouseEvent, tmNode: TreeNode<SelectBaseOption>) => void\n  showCheckmarkRef: Ref<boolean>\n  valueSetRef: Ref<Set<number | string>>\n  pendingTmNodeRef: Ref<TreeNode<SelectBaseOption> | null>\n  multipleRef: Ref<boolean>\n  valueRef: Ref<string | number | Array<string | number> | null>\n  renderLabelRef: Ref<RenderLabel | undefined>\n  renderOptionRef: Ref<RenderOption | undefined>\n  labelFieldRef: Ref<string>\n  valueFieldRef: Ref<string>\n  nodePropsRef: Ref<NodeProps | undefined>\n}\n\nexport interface InternalExposedProps {\n  selfRef: Ref<HTMLElement | null>\n  getPendingTmNode: () => TreeNode<SelectBaseOption> | null\n  prev: () => void\n  next: () => void\n}\n\nexport const internalSelectionMenuInjectionKey\n  = createInjectionKey<InternalSelectMenuInjection>('n-internal-select-menu')\n\nexport const internalSelectionMenuBodyInjectionKey = createInjectionKey<\n  Ref<HTMLElement | null>\n>('n-internal-select-menu-body')\n\nexport type InternalSelectMenuRef = UnwrapRef<InternalExposedProps>\n"
  },
  {
    "path": "src/_internal/select-menu/src/styles/index.cssr.ts",
    "content": "import { fadeInScaleUpTransition } from '../../../../_styles/transitions/fade-in-scale-up.cssr'\nimport { c, cB, cE, cM, cNotM } from '../../../../_utils/cssr'\n\n// --n-loading-color\n// --n-loading-size\n// --n-option-padding-right\nexport default cB('base-select-menu', `\n  line-height: 1.5;\n  outline: none;\n  z-index: 0;\n  position: relative;\n  border-radius: var(--n-border-radius);\n  transition:\n    background-color .3s var(--n-bezier),\n    box-shadow .3s var(--n-bezier);\n  background-color: var(--n-color);\n`, [\n  cB('scrollbar', `\n    max-height: var(--n-height);\n  `),\n  cB('virtual-list', `\n    max-height: var(--n-height);\n  `),\n  cB('base-select-option', `\n    min-height: var(--n-option-height);\n    font-size: var(--n-option-font-size);\n    display: flex;\n    align-items: center;\n  `, [\n    cE('content', `\n      z-index: 1;\n      white-space: nowrap;\n      text-overflow: ellipsis;\n      overflow: hidden;\n    `)\n  ]),\n  cB('base-select-group-header', `\n    min-height: var(--n-option-height);\n    font-size: .93em;\n    display: flex;\n    align-items: center;\n  `),\n  cB('base-select-menu-option-wrapper', `\n    position: relative;\n    width: 100%;\n  `),\n  cE('loading, empty', `\n    display: flex;\n    padding: 12px 32px;\n    flex: 1;\n    justify-content: center;\n  `),\n  cE('loading', `\n    color: var(--n-loading-color);\n    font-size: var(--n-loading-size);\n  `),\n  cE('header', `\n    padding: 8px var(--n-option-padding-left);\n    font-size: var(--n-option-font-size);\n    transition: \n      color .3s var(--n-bezier),\n      border-color .3s var(--n-bezier);\n    border-bottom: 1px solid var(--n-action-divider-color);\n    color: var(--n-action-text-color);\n  `),\n  cE('action', `\n    padding: 8px var(--n-option-padding-left);\n    font-size: var(--n-option-font-size);\n    transition: \n      color .3s var(--n-bezier),\n      border-color .3s var(--n-bezier);\n    border-top: 1px solid var(--n-action-divider-color);\n    color: var(--n-action-text-color);\n  `),\n  cB('base-select-group-header', `\n    position: relative;\n    cursor: default;\n    padding: var(--n-option-padding);\n    color: var(--n-group-header-text-color);\n  `),\n  cB('base-select-option', `\n    cursor: pointer;\n    position: relative;\n    padding: var(--n-option-padding);\n    transition:\n      color .3s var(--n-bezier),\n      opacity .3s var(--n-bezier);\n    box-sizing: border-box;\n    color: var(--n-option-text-color);\n    opacity: 1;\n  `, [\n    cM('show-checkmark', `\n      padding-right: calc(var(--n-option-padding-right) + 20px);\n    `),\n    c('&::before', `\n      content: \"\";\n      position: absolute;\n      left: 4px;\n      right: 4px;\n      top: 0;\n      bottom: 0;\n      border-radius: var(--n-border-radius);\n      transition: background-color .3s var(--n-bezier);\n    `),\n    c('&:active', `\n      color: var(--n-option-text-color-pressed);\n    `),\n    cM('grouped', `\n      padding-left: calc(var(--n-option-padding-left) * 1.5);\n    `),\n    cM('pending', [\n      c('&::before', `\n        background-color: var(--n-option-color-pending);\n      `)\n    ]),\n    cM('selected', `\n      color: var(--n-option-text-color-active);\n    `, [\n      c('&::before', `\n        background-color: var(--n-option-color-active);\n      `),\n      cM('pending', [\n        c('&::before', `\n          background-color: var(--n-option-color-active-pending);\n        `)\n      ])\n    ]),\n    cM('disabled', `\n      cursor: not-allowed;\n    `, [\n      cNotM('selected', `\n        color: var(--n-option-text-color-disabled);\n      `),\n      cM('selected', `\n        opacity: var(--n-option-opacity-disabled);\n      `)\n    ]),\n    cE('check', `\n      font-size: 16px;\n      position: absolute;\n      right: calc(var(--n-option-padding-right) - 4px);\n      top: calc(50% - 7px);\n      color: var(--n-option-check-color);\n      transition: color .3s var(--n-bezier);\n    `, [\n      fadeInScaleUpTransition({\n        enterScale: '0.5'\n      })\n    ])\n  ])\n])\n"
  },
  {
    "path": "src/_internal/select-menu/src/styles/rtl.cssr.ts",
    "content": "import { cB, cE, cM } from '../../../../_utils/cssr'\n\nexport default cB('base-select-menu', [\n  cM('rtl', `\n    direction: rtl;\n  `, [\n    cB('base-select-option', [\n      cE('check', `\n        right: unset;\n        left: calc(var(--n-option-padding-right) - 4px);\n      `),\n      cM('show-checkmark', `\n        padding-left: calc(var(--n-option-padding-right) + 20px);\n        padding-right: var(--n-option-padding-left);\n      `)\n    ])\n  ])\n])\n"
  },
  {
    "path": "src/_internal/select-menu/styles/_common.ts",
    "content": "export default {\n  height: 'calc(var(--n-option-height) * 7.6)',\n  paddingTiny: '4px 0',\n  paddingSmall: '4px 0',\n  paddingMedium: '4px 0',\n  paddingLarge: '4px 0',\n  paddingHuge: '4px 0',\n  optionPaddingTiny: '0 12px',\n  optionPaddingSmall: '0 12px',\n  optionPaddingMedium: '0 12px',\n  optionPaddingLarge: '0 12px',\n  optionPaddingHuge: '0 12px',\n  loadingSize: '18px'\n}\n"
  },
  {
    "path": "src/_internal/select-menu/styles/dark.ts",
    "content": "import type { InternalSelectMenuTheme } from './light'\nimport { commonDark } from '../../../_styles/common'\nimport { emptyDark } from '../../../empty/styles'\nimport { scrollbarDark } from '../../scrollbar/styles'\nimport { self } from './light'\n\nconst internalSelectMenuDark: InternalSelectMenuTheme = {\n  name: 'InternalSelectMenu',\n  common: commonDark,\n  peers: {\n    Scrollbar: scrollbarDark,\n    Empty: emptyDark\n  },\n  self\n}\n\nexport default internalSelectMenuDark\n"
  },
  {
    "path": "src/_internal/select-menu/styles/index.ts",
    "content": "export { default as internalSelectMenuDark } from './dark'\nexport { default as internalSelectMenuLight } from './light'\nexport type {\n  InternalSelectMenuTheme,\n  InternalSelectMenuThemeVars\n} from './light'\nexport { internalSelectMenuRtl } from './rtl'\n"
  },
  {
    "path": "src/_internal/select-menu/styles/light.ts",
    "content": "import type { ThemeCommonVars } from '../../../_styles/common'\nimport { createTheme } from '../../../_mixins'\nimport { commonLight } from '../../../_styles/common'\nimport { emptyLight } from '../../../empty/styles'\nimport { scrollbarLight } from '../../scrollbar/styles'\nimport commonVariables from './_common'\n\nexport function self(vars: ThemeCommonVars) {\n  const {\n    borderRadius,\n    popoverColor,\n    textColor3,\n    dividerColor,\n    textColor2,\n    primaryColorPressed,\n    textColorDisabled,\n    primaryColor,\n    opacityDisabled,\n    hoverColor,\n    fontSizeTiny,\n    fontSizeSmall,\n    fontSizeMedium,\n    fontSizeLarge,\n    fontSizeHuge,\n    heightTiny,\n    heightSmall,\n    heightMedium,\n    heightLarge,\n    heightHuge\n  } = vars\n  return {\n    ...commonVariables,\n    optionFontSizeTiny: fontSizeTiny,\n    optionFontSizeSmall: fontSizeSmall,\n    optionFontSizeMedium: fontSizeMedium,\n    optionFontSizeLarge: fontSizeLarge,\n    optionFontSizeHuge: fontSizeHuge,\n    optionHeightTiny: heightTiny,\n    optionHeightSmall: heightSmall,\n    optionHeightMedium: heightMedium,\n    optionHeightLarge: heightLarge,\n    optionHeightHuge: heightHuge,\n    borderRadius,\n    color: popoverColor,\n    groupHeaderTextColor: textColor3,\n    actionDividerColor: dividerColor,\n    optionTextColor: textColor2,\n    optionTextColorPressed: primaryColorPressed,\n    optionTextColorDisabled: textColorDisabled,\n    optionTextColorActive: primaryColor,\n    optionOpacityDisabled: opacityDisabled,\n    optionCheckColor: primaryColor,\n    optionColorPending: hoverColor,\n    optionColorActive: 'rgba(0, 0, 0, 0)',\n    optionColorActivePending: hoverColor,\n    actionTextColor: textColor2,\n    loadingColor: primaryColor\n  }\n}\n\nexport type InternalSelectMenuThemeVars = ReturnType<typeof self>\n\nconst internalSelectMenuLight = createTheme({\n  name: 'InternalSelectMenu',\n  common: commonLight,\n  peers: {\n    Scrollbar: scrollbarLight,\n    Empty: emptyLight\n  },\n  self\n})\n\nexport default internalSelectMenuLight\nexport type InternalSelectMenuTheme = typeof internalSelectMenuLight\n"
  },
  {
    "path": "src/_internal/select-menu/styles/rtl.ts",
    "content": "import type { RtlItem } from '../../../config-provider/src/internal-interface'\nimport rtlStyle from '../src/styles/rtl.cssr'\n\nexport const internalSelectMenuRtl: RtlItem = {\n  name: 'InternalSelectMenu',\n  style: rtlStyle\n}\n"
  },
  {
    "path": "src/_internal/selection/index.ts",
    "content": "export { default } from './src/Selection'\nexport type { InternalSelectionInst } from './src/Selection'\n"
  },
  {
    "path": "src/_internal/selection/src/Selection.tsx",
    "content": "import type { CSSProperties, InputHTMLAttributes, PropType, VNode } from 'vue'\nimport type { VOverflowInst } from 'vueuc'\nimport type { ThemeProps } from '../../../_mixins'\nimport type { FormValidationStatus } from '../../../form/src/public-types'\nimport type { PopoverProps } from '../../../popover'\nimport type { SelectBaseOption } from '../../../select/src/interface'\nimport type { TagRef } from '../../../tag/src/Tag'\nimport type {\n  RenderLabel,\n  RenderLabelImpl\n} from '../../select-menu/src/interface'\nimport type { InternalSelectionTheme } from '../styles'\nimport type { RenderTag } from './interface'\nimport { getPadding } from 'seemly'\nimport {\n  computed,\n  defineComponent,\n  Fragment,\n  h,\n  nextTick,\n  onMounted,\n  ref,\n  toRef,\n  watch,\n  watchEffect\n} from 'vue'\nimport { VOverflow } from 'vueuc'\nimport { useConfig, useRtl, useTheme, useThemeClass } from '../../../_mixins'\nimport {\n  createKey,\n  getTitleAttribute,\n  render,\n  useOnResize,\n  Wrapper\n} from '../../../_utils'\nimport { NPopover } from '../../../popover'\nimport { NTag } from '../../../tag'\nimport Suffix from '../../suffix'\nimport { internalSelectionLight } from '../styles'\nimport style from './styles/index.cssr'\n\nexport interface InternalSelectionInst {\n  isComposing: boolean\n  focus: () => void\n  focusInput: () => void\n  blur: () => void\n  blurInput: () => void\n  $el: HTMLElement\n}\n\nexport default defineComponent({\n  name: 'InternalSelection',\n  props: {\n    ...(useTheme.props as ThemeProps<InternalSelectionTheme>),\n    clsPrefix: {\n      type: String,\n      required: true\n    },\n    bordered: {\n      type: Boolean as PropType<boolean | undefined>,\n      default: undefined\n    },\n    active: Boolean,\n    pattern: {\n      type: String,\n      default: ''\n    },\n    placeholder: String,\n    selectedOption: {\n      type: Object as PropType<SelectBaseOption | null>,\n      default: null\n    },\n    selectedOptions: {\n      type: Array as PropType<SelectBaseOption[] | null>,\n      default: null\n    },\n    labelField: { type: String, default: 'label' },\n    valueField: {\n      type: String,\n      default: 'value'\n    },\n    multiple: Boolean,\n    filterable: Boolean,\n    clearable: Boolean,\n    disabled: Boolean,\n    size: {\n      type: String as PropType<'tiny' | 'small' | 'medium' | 'large'>,\n      default: 'medium'\n    },\n    loading: Boolean,\n    autofocus: Boolean,\n    showArrow: {\n      type: Boolean,\n      default: true\n    },\n    inputProps: Object as PropType<InputHTMLAttributes>,\n    focused: Boolean,\n    renderTag: Function as PropType<RenderTag>,\n    onKeydown: Function as PropType<(e: KeyboardEvent) => void>,\n    onClick: Function as PropType<(e: MouseEvent) => void>,\n    onBlur: Function as PropType<(e: FocusEvent) => void>,\n    onFocus: Function as PropType<(e: FocusEvent) => void>,\n    onDeleteOption: Function as PropType<(option: SelectBaseOption) => void>,\n    maxTagCount: [String, Number] as PropType<number | 'responsive'>,\n    ellipsisTagPopoverProps: Object as PropType<PopoverProps>,\n    onClear: Function as PropType<(e: MouseEvent) => void>,\n    onPatternInput: Function as PropType<(e: InputEvent) => void>,\n    onPatternFocus: Function as PropType<(e: FocusEvent) => void>,\n    onPatternBlur: Function as PropType<(e: FocusEvent) => void>,\n    renderLabel: Function as PropType<RenderLabel>,\n    status: String as PropType<FormValidationStatus>,\n    inlineThemeDisabled: Boolean,\n    ignoreComposition: { type: Boolean, default: true },\n    onResize: Function as PropType<() => void>\n  },\n  setup(props) {\n    const { mergedClsPrefixRef, mergedRtlRef } = useConfig(props)\n    const rtlEnabledRef = useRtl(\n      'InternalSelection',\n      mergedRtlRef,\n      mergedClsPrefixRef\n    )\n    const patternInputMirrorRef = ref<HTMLElement | null>(null)\n    const patternInputRef = ref<HTMLElement | null>(null)\n    const selfRef = ref<HTMLElement | null>(null)\n    const multipleElRef = ref<HTMLElement | null>(null)\n    const singleElRef = ref<HTMLElement | null>(null)\n    const patternInputWrapperRef = ref<HTMLElement | null>(null)\n    const counterRef = ref<TagRef | null>(null)\n    const counterWrapperRef = ref<HTMLElement | null>(null)\n    const overflowRef = ref<VOverflowInst | null>(null)\n    const inputTagElRef = ref<HTMLElement | null>(null)\n\n    const showTagsPopoverRef = ref<boolean>(false)\n    const patternInputFocusedRef = ref(false)\n    const hoverRef = ref(false)\n    const themeRef = useTheme(\n      'InternalSelection',\n      '-internal-selection',\n      style,\n      internalSelectionLight,\n      props,\n      toRef(props, 'clsPrefix')\n    )\n    const mergedClearableRef = computed(() => {\n      return (\n        props.clearable && !props.disabled && (hoverRef.value || props.active)\n      )\n    })\n    const filterablePlaceholderRef = computed(() => {\n      return props.selectedOption\n        ? props.renderTag\n          ? props.renderTag({\n              option: props.selectedOption,\n              handleClose: () => {}\n            })\n          : props.renderLabel\n            ? props.renderLabel(props.selectedOption as never, true)\n            : render(\n                props.selectedOption[props.labelField],\n                props.selectedOption,\n                true\n              )\n        : props.placeholder\n    })\n    const labelRef = computed(() => {\n      const option = props.selectedOption\n      if (!option)\n        return undefined\n      return option[props.labelField]\n    })\n    const selectedRef = computed(() => {\n      if (props.multiple) {\n        return !!(\n          Array.isArray(props.selectedOptions) && props.selectedOptions.length\n        )\n      }\n      else {\n        return props.selectedOption !== null\n      }\n    })\n    function syncMirrorWidth(): void {\n      const { value: patternInputMirrorEl } = patternInputMirrorRef\n      if (patternInputMirrorEl) {\n        const { value: patternInputEl } = patternInputRef\n        if (patternInputEl) {\n          patternInputEl.style.width = `${patternInputMirrorEl.offsetWidth}px`\n          if (props.maxTagCount !== 'responsive') {\n            overflowRef.value?.sync({\n              showAllItemsBeforeCalculate: false\n            })\n          }\n        }\n      }\n    }\n    function hideInputTag(): void {\n      const { value: inputTagEl } = inputTagElRef\n      if (inputTagEl)\n        inputTagEl.style.display = 'none'\n    }\n    function showInputTag(): void {\n      const { value: inputTagEl } = inputTagElRef\n      if (inputTagEl)\n        inputTagEl.style.display = 'inline-block'\n    }\n    watch(toRef(props, 'active'), (value) => {\n      if (!value)\n        hideInputTag()\n    })\n    watch(toRef(props, 'pattern'), () => {\n      if (props.multiple) {\n        void nextTick(syncMirrorWidth)\n      }\n    })\n    function doFocus(e: FocusEvent): void {\n      const { onFocus } = props\n      if (onFocus)\n        onFocus(e)\n    }\n    function doBlur(e: FocusEvent): void {\n      const { onBlur } = props\n      if (onBlur)\n        onBlur(e)\n    }\n    function doDeleteOption(value: SelectBaseOption): void {\n      const { onDeleteOption } = props\n      if (onDeleteOption)\n        onDeleteOption(value)\n    }\n    function doClear(e: MouseEvent): void {\n      const { onClear } = props\n      if (onClear)\n        onClear(e)\n    }\n    function doPatternInput(value: InputEvent): void {\n      const { onPatternInput } = props\n      if (onPatternInput)\n        onPatternInput(value)\n    }\n    function handleFocusin(e: FocusEvent): void {\n      if (\n        !e.relatedTarget\n        || !selfRef.value?.contains(e.relatedTarget as Node)\n      ) {\n        doFocus(e)\n      }\n    }\n    function handleFocusout(e: FocusEvent): void {\n      if (selfRef.value?.contains(e.relatedTarget as Node))\n        return\n      doBlur(e)\n    }\n    function handleClear(e: MouseEvent): void {\n      doClear(e)\n    }\n    function handleMouseEnter(): void {\n      hoverRef.value = true\n    }\n    function handleMouseLeave(): void {\n      hoverRef.value = false\n    }\n    function handleMouseDown(e: MouseEvent): void {\n      if (!props.active || !props.filterable)\n        return\n      if (e.target === patternInputRef.value)\n        return\n      e.preventDefault()\n    }\n    function handleDeleteOption(option: SelectBaseOption): void {\n      doDeleteOption(option)\n    }\n    const isComposingRef = ref(false)\n    function handlePatternKeyDown(e: KeyboardEvent): void {\n      if (e.key === 'Backspace' && !isComposingRef.value) {\n        if (!props.pattern.length) {\n          const { selectedOptions } = props\n          if (selectedOptions?.length) {\n            handleDeleteOption(selectedOptions[selectedOptions.length - 1])\n          }\n        }\n      }\n    }\n    // the composition end is later than its input so we can cached the event\n    // and return the input event\n    let cachedInputEvent: InputEvent | null = null\n    function handlePatternInputInput(e: InputEvent): void {\n      // we should sync mirror width here\n      const { value: patternInputMirrorEl } = patternInputMirrorRef\n      if (patternInputMirrorEl) {\n        const inputText: string = (e.target as any).value\n        patternInputMirrorEl.textContent = inputText\n        syncMirrorWidth()\n      }\n      if (props.ignoreComposition) {\n        if (!isComposingRef.value) {\n          doPatternInput(e)\n        }\n        else {\n          cachedInputEvent = e\n        }\n      }\n      else {\n        doPatternInput(e)\n      }\n    }\n    function handleCompositionStart(): void {\n      isComposingRef.value = true\n    }\n    function handleCompositionEnd(): void {\n      isComposingRef.value = false\n      if (props.ignoreComposition) {\n        doPatternInput(cachedInputEvent!)\n      }\n      cachedInputEvent = null\n    }\n    function handlePatternInputFocus(e: FocusEvent): void {\n      patternInputFocusedRef.value = true\n      props.onPatternFocus?.(e)\n    }\n    function handlePatternInputBlur(e: FocusEvent): void {\n      patternInputFocusedRef.value = false\n      props.onPatternBlur?.(e)\n    }\n    function blur(): void {\n      if (props.filterable) {\n        patternInputFocusedRef.value = false\n        patternInputWrapperRef.value?.blur()\n        patternInputRef.value?.blur()\n      }\n      else if (props.multiple) {\n        const { value: multipleEl } = multipleElRef\n        multipleEl?.blur()\n      }\n      else {\n        const { value: singleEl } = singleElRef\n        singleEl?.blur()\n      }\n    }\n    function focus(): void {\n      if (props.filterable) {\n        patternInputFocusedRef.value = false\n        patternInputWrapperRef.value?.focus()\n      }\n      else if (props.multiple) {\n        multipleElRef.value?.focus()\n      }\n      else {\n        singleElRef.value?.focus()\n      }\n    }\n    function focusInput(): void {\n      const { value: patternInputEl } = patternInputRef\n      if (patternInputEl) {\n        showInputTag()\n        patternInputEl.focus()\n      }\n    }\n    function blurInput(): void {\n      const { value: patternInputEl } = patternInputRef\n      if (patternInputEl) {\n        patternInputEl.blur()\n      }\n    }\n    function updateCounter(count: number): void {\n      const { value } = counterRef\n      if (value) {\n        value.setTextContent(`+${count}`)\n      }\n    }\n    function getCounter(): HTMLElement | null {\n      const { value } = counterWrapperRef\n      return value\n    }\n    function getTail(): HTMLElement | null {\n      return patternInputRef.value\n    }\n    let enterTimerId: number | null = null\n    function clearEnterTimer(): void {\n      if (enterTimerId !== null)\n        window.clearTimeout(enterTimerId)\n    }\n    function handleMouseEnterCounter(): void {\n      if (props.active)\n        return\n      clearEnterTimer()\n      enterTimerId = window.setTimeout(() => {\n        if (selectedRef.value) {\n          showTagsPopoverRef.value = true\n        }\n      }, 100)\n    }\n    function handleMouseLeaveCounter(): void {\n      clearEnterTimer()\n    }\n    function onPopoverUpdateShow(show: boolean): void {\n      if (!show) {\n        clearEnterTimer()\n        showTagsPopoverRef.value = false\n      }\n    }\n    watch(selectedRef, (value) => {\n      if (!value) {\n        showTagsPopoverRef.value = false\n      }\n    })\n    onMounted(() => {\n      watchEffect(() => {\n        const patternInputWrapperEl = patternInputWrapperRef.value\n        if (!patternInputWrapperEl)\n          return\n        if (props.disabled) {\n          patternInputWrapperEl.removeAttribute('tabindex')\n        }\n        else {\n          patternInputWrapperEl.tabIndex = patternInputFocusedRef.value ? -1 : 0\n        }\n      })\n    })\n    useOnResize(selfRef, props.onResize)\n    const { inlineThemeDisabled } = props\n    const cssVarsRef = computed(() => {\n      const { size } = props\n      const {\n        common: { cubicBezierEaseInOut },\n        self: {\n          fontWeight,\n          borderRadius,\n          color,\n          placeholderColor,\n          textColor,\n          paddingSingle,\n          paddingMultiple,\n          caretColor,\n          colorDisabled,\n          textColorDisabled,\n          placeholderColorDisabled,\n          colorActive,\n          boxShadowFocus,\n          boxShadowActive,\n          boxShadowHover,\n          border,\n          borderFocus,\n          borderHover,\n          borderActive,\n          arrowColor,\n          arrowColorDisabled,\n          loadingColor,\n          // form warning\n          colorActiveWarning,\n          boxShadowFocusWarning,\n          boxShadowActiveWarning,\n          boxShadowHoverWarning,\n          borderWarning,\n          borderFocusWarning,\n          borderHoverWarning,\n          borderActiveWarning,\n          // form error\n          colorActiveError,\n          boxShadowFocusError,\n          boxShadowActiveError,\n          boxShadowHoverError,\n          borderError,\n          borderFocusError,\n          borderHoverError,\n          borderActiveError,\n          // clear\n          clearColor,\n          clearColorHover,\n          clearColorPressed,\n          clearSize,\n          // arrow\n          arrowSize,\n          [createKey('height', size)]: height,\n          [createKey('fontSize', size)]: fontSize\n        }\n      } = themeRef.value\n\n      const paddingSingleDiscrete = getPadding(paddingSingle)\n      const paddingMultipleDiscrete = getPadding(paddingMultiple)\n\n      return {\n        '--n-bezier': cubicBezierEaseInOut,\n        '--n-border': border,\n        '--n-border-active': borderActive,\n        '--n-border-focus': borderFocus,\n        '--n-border-hover': borderHover,\n        '--n-border-radius': borderRadius,\n        '--n-box-shadow-active': boxShadowActive,\n        '--n-box-shadow-focus': boxShadowFocus,\n        '--n-box-shadow-hover': boxShadowHover,\n        '--n-caret-color': caretColor,\n        '--n-color': color,\n        '--n-color-active': colorActive,\n        '--n-color-disabled': colorDisabled,\n        '--n-font-size': fontSize,\n        '--n-height': height,\n        '--n-padding-single-top': paddingSingleDiscrete.top,\n        '--n-padding-multiple-top': paddingMultipleDiscrete.top,\n        '--n-padding-single-right': paddingSingleDiscrete.right,\n        '--n-padding-multiple-right': paddingMultipleDiscrete.right,\n        '--n-padding-single-left': paddingSingleDiscrete.left,\n        '--n-padding-multiple-left': paddingMultipleDiscrete.left,\n        '--n-padding-single-bottom': paddingSingleDiscrete.bottom,\n        '--n-padding-multiple-bottom': paddingMultipleDiscrete.bottom,\n        '--n-placeholder-color': placeholderColor,\n        '--n-placeholder-color-disabled': placeholderColorDisabled,\n        '--n-text-color': textColor,\n        '--n-text-color-disabled': textColorDisabled,\n        '--n-arrow-color': arrowColor,\n        '--n-arrow-color-disabled': arrowColorDisabled,\n        '--n-loading-color': loadingColor,\n        // form warning\n        '--n-color-active-warning': colorActiveWarning,\n        '--n-box-shadow-focus-warning': boxShadowFocusWarning,\n        '--n-box-shadow-active-warning': boxShadowActiveWarning,\n        '--n-box-shadow-hover-warning': boxShadowHoverWarning,\n        '--n-border-warning': borderWarning,\n        '--n-border-focus-warning': borderFocusWarning,\n        '--n-border-hover-warning': borderHoverWarning,\n        '--n-border-active-warning': borderActiveWarning,\n        // form error\n        '--n-color-active-error': colorActiveError,\n        '--n-box-shadow-focus-error': boxShadowFocusError,\n        '--n-box-shadow-active-error': boxShadowActiveError,\n        '--n-box-shadow-hover-error': boxShadowHoverError,\n        '--n-border-error': borderError,\n        '--n-border-focus-error': borderFocusError,\n        '--n-border-hover-error': borderHoverError,\n        '--n-border-active-error': borderActiveError,\n        // clear\n        '--n-clear-size': clearSize,\n        '--n-clear-color': clearColor,\n        '--n-clear-color-hover': clearColorHover,\n        '--n-clear-color-pressed': clearColorPressed,\n        // arrow-size\n        '--n-arrow-size': arrowSize,\n        // font-weight\n        '--n-font-weight': fontWeight\n      }\n    })\n    const themeClassHandle = inlineThemeDisabled\n      ? useThemeClass(\n          'internal-selection',\n          computed(() => {\n            return props.size[0]\n          }),\n          cssVarsRef,\n          props\n        )\n      : undefined\n    return {\n      mergedTheme: themeRef,\n      mergedClearable: mergedClearableRef,\n      mergedClsPrefix: mergedClsPrefixRef,\n      rtlEnabled: rtlEnabledRef,\n      patternInputFocused: patternInputFocusedRef,\n      filterablePlaceholder: filterablePlaceholderRef,\n      label: labelRef,\n      selected: selectedRef,\n      showTagsPanel: showTagsPopoverRef,\n      isComposing: isComposingRef,\n      // dom ref\n      counterRef,\n      counterWrapperRef,\n      patternInputMirrorRef,\n      patternInputRef,\n      selfRef,\n      multipleElRef,\n      singleElRef,\n      patternInputWrapperRef,\n      overflowRef,\n      inputTagElRef,\n      handleMouseDown,\n      handleFocusin,\n      handleClear,\n      handleMouseEnter,\n      handleMouseLeave,\n      handleDeleteOption,\n      handlePatternKeyDown,\n      handlePatternInputInput,\n      handlePatternInputBlur,\n      handlePatternInputFocus,\n      handleMouseEnterCounter,\n      handleMouseLeaveCounter,\n      handleFocusout,\n      handleCompositionEnd,\n      handleCompositionStart,\n      onPopoverUpdateShow,\n      focus,\n      focusInput,\n      blur,\n      blurInput,\n      updateCounter,\n      getCounter,\n      getTail,\n      renderLabel: props.renderLabel as RenderLabelImpl,\n      cssVars: inlineThemeDisabled ? undefined : cssVarsRef,\n      themeClass: themeClassHandle?.themeClass,\n      onRender: themeClassHandle?.onRender\n    }\n  },\n  render() {\n    const {\n      status,\n      multiple,\n      size,\n      disabled,\n      filterable,\n      maxTagCount,\n      bordered,\n      clsPrefix,\n      ellipsisTagPopoverProps,\n      onRender,\n      renderTag,\n      renderLabel\n    } = this\n    onRender?.()\n    const maxTagCountResponsive = maxTagCount === 'responsive'\n    const maxTagCountNumeric = typeof maxTagCount === 'number'\n    const useMaxTagCount = maxTagCountResponsive || maxTagCountNumeric\n    const suffix = (\n      <Wrapper>\n        {{\n          default: () => (\n            <Suffix\n              clsPrefix={clsPrefix}\n              loading={this.loading}\n              showArrow={this.showArrow}\n              showClear={this.mergedClearable && this.selected}\n              onClear={this.handleClear}\n            >\n              {{\n                default: () => this.$slots.arrow?.()\n              }}\n            </Suffix>\n          )\n        }}\n      </Wrapper>\n    )\n    let body: JSX.Element\n    if (multiple) {\n      const { labelField } = this\n      const createTag = (option: SelectBaseOption): JSX.Element => (\n        <div\n          class={`${clsPrefix}-base-selection-tag-wrapper`}\n          key={option.value}\n        >\n          {renderTag ? (\n            renderTag({\n              option,\n              handleClose: () => {\n                this.handleDeleteOption(option)\n              }\n            })\n          ) : (\n            <NTag\n              size={size}\n              closable={!option.disabled}\n              disabled={disabled}\n              onClose={() => {\n                this.handleDeleteOption(option)\n              }}\n              internalCloseIsButtonTag={false}\n              internalCloseFocusable={false}\n            >\n              {{\n                default: () =>\n                  renderLabel\n                    ? renderLabel(option, true)\n                    : render(option[labelField], option, true)\n              }}\n            </NTag>\n          )}\n        </div>\n      )\n      const createOriginalTagNodes = (): VNode[] =>\n        (maxTagCountNumeric\n          ? this.selectedOptions!.slice(0, maxTagCount)\n          : this.selectedOptions!\n        ).map(createTag)\n      const input = filterable ? (\n        <div\n          class={`${clsPrefix}-base-selection-input-tag`}\n          ref=\"inputTagElRef\"\n          key=\"__input-tag__\"\n        >\n          <input\n            {...this.inputProps}\n            ref=\"patternInputRef\"\n            tabindex={-1}\n            disabled={disabled}\n            value={this.pattern}\n            autofocus={this.autofocus}\n            class={`${clsPrefix}-base-selection-input-tag__input`}\n            onBlur={this.handlePatternInputBlur}\n            onFocus={this.handlePatternInputFocus}\n            onKeydown={this.handlePatternKeyDown}\n            onInput={this.handlePatternInputInput as any}\n            onCompositionstart={this.handleCompositionStart}\n            onCompositionend={this.handleCompositionEnd}\n          />\n          <span\n            ref=\"patternInputMirrorRef\"\n            class={`${clsPrefix}-base-selection-input-tag__mirror`}\n          >\n            {this.pattern}\n          </span>\n        </div>\n      ) : null\n      // May Overflow\n      const renderCounter = maxTagCountResponsive\n        ? () => (\n            <div\n              class={`${clsPrefix}-base-selection-tag-wrapper`}\n              ref=\"counterWrapperRef\"\n            >\n              <NTag\n                size={size}\n                ref=\"counterRef\"\n                onMouseenter={this.handleMouseEnterCounter}\n                onMouseleave={this.handleMouseLeaveCounter}\n                disabled={disabled}\n              />\n            </div>\n          )\n        : undefined\n      let counter: JSX.Element | undefined\n      if (maxTagCountNumeric) {\n        const rest = this.selectedOptions!.length - maxTagCount\n        if (rest > 0) {\n          counter = (\n            <div\n              class={`${clsPrefix}-base-selection-tag-wrapper`}\n              key=\"__counter__\"\n            >\n              <NTag\n                size={size}\n                ref=\"counterRef\"\n                onMouseenter={this.handleMouseEnterCounter}\n                disabled={disabled}\n              >\n                {{\n                  default: () => `+${rest}`\n                }}\n              </NTag>\n            </div>\n          )\n        }\n      }\n      const tags = maxTagCountResponsive ? (\n        filterable ? (\n          <VOverflow\n            ref=\"overflowRef\"\n            updateCounter={this.updateCounter}\n            getCounter={this.getCounter}\n            getTail={this.getTail}\n            style={{\n              width: '100%',\n              display: 'flex',\n              overflow: 'hidden'\n            }}\n          >\n            {{\n              default: createOriginalTagNodes,\n              counter: renderCounter,\n              tail: () => input\n            }}\n          </VOverflow>\n        ) : (\n          <VOverflow\n            ref=\"overflowRef\"\n            updateCounter={this.updateCounter}\n            getCounter={this.getCounter}\n            style={{\n              width: '100%',\n              display: 'flex',\n              overflow: 'hidden'\n            }}\n          >\n            {{\n              default: createOriginalTagNodes,\n              counter: renderCounter\n            }}\n          </VOverflow>\n        )\n      ) : maxTagCountNumeric && counter ? (\n        createOriginalTagNodes().concat(counter)\n      ) : (\n        createOriginalTagNodes()\n      )\n      const renderPopover = useMaxTagCount\n        ? (): JSX.Element => (\n            <div class={`${clsPrefix}-base-selection-popover`}>\n              {maxTagCountResponsive\n                ? createOriginalTagNodes()\n                : this.selectedOptions!.map(createTag)}\n            </div>\n          )\n        : undefined\n      const popoverProps = useMaxTagCount\n        ? ({\n            show: this.showTagsPanel,\n            trigger: 'hover',\n            overlap: true,\n            placement: 'top',\n            width: 'trigger',\n            onUpdateShow: this.onPopoverUpdateShow,\n            theme: this.mergedTheme.peers.Popover,\n            themeOverrides: this.mergedTheme.peerOverrides.Popover,\n            ...ellipsisTagPopoverProps\n          } as const)\n        : null\n      const showPlaceholder = this.selected\n        ? false\n        : this.active\n          ? !this.pattern && !this.isComposing\n          : true\n      const placeholder = showPlaceholder ? (\n        <div\n          class={`${clsPrefix}-base-selection-placeholder ${clsPrefix}-base-selection-overlay`}\n        >\n          <div class={`${clsPrefix}-base-selection-placeholder__inner`}>\n            {this.placeholder}\n          </div>\n        </div>\n      ) : null\n      const popoverTrigger = filterable ? (\n        <div\n          ref=\"patternInputWrapperRef\"\n          class={`${clsPrefix}-base-selection-tags`}\n        >\n          {tags}\n          {maxTagCountResponsive ? null : input}\n          {suffix}\n        </div>\n      ) : (\n        <div\n          ref=\"multipleElRef\"\n          class={`${clsPrefix}-base-selection-tags`}\n          tabindex={disabled ? undefined : 0}\n        >\n          {tags}\n          {suffix}\n        </div>\n      )\n      body = (\n        <>\n          {useMaxTagCount ? (\n            <NPopover\n              {...popoverProps}\n              scrollable\n              style=\"max-height: calc(var(--v-target-height) * 6.6);\"\n            >\n              {{\n                trigger: () => popoverTrigger,\n                default: renderPopover\n              }}\n            </NPopover>\n          ) : (\n            popoverTrigger\n          )}\n          {placeholder}\n        </>\n      )\n    }\n    else {\n      if (filterable) {\n        const hasInput = this.pattern || this.isComposing\n        const showPlaceholder = this.active ? !hasInput : !this.selected\n        const showSelectedLabel = this.active ? false : this.selected\n        body = (\n          <div\n            ref=\"patternInputWrapperRef\"\n            class={`${clsPrefix}-base-selection-label`}\n            title={\n              this.patternInputFocused\n                ? undefined\n                : getTitleAttribute(this.label)\n            }\n          >\n            <input\n              {...this.inputProps}\n              ref=\"patternInputRef\"\n              class={`${clsPrefix}-base-selection-input`}\n              value={this.active ? this.pattern : ''}\n              placeholder=\"\"\n              readonly={disabled}\n              disabled={disabled}\n              tabindex={-1}\n              autofocus={this.autofocus}\n              onFocus={this.handlePatternInputFocus}\n              onBlur={this.handlePatternInputBlur}\n              onInput={this.handlePatternInputInput as any}\n              onCompositionstart={this.handleCompositionStart}\n              onCompositionend={this.handleCompositionEnd}\n            />\n            {showSelectedLabel ? (\n              <div\n                class={`${clsPrefix}-base-selection-label__render-label ${clsPrefix}-base-selection-overlay`}\n                key=\"input\"\n              >\n                <div class={`${clsPrefix}-base-selection-overlay__wrapper`}>\n                  {renderTag\n                    ? renderTag({\n                        option: this.selectedOption!,\n                        handleClose: () => {}\n                      })\n                    : renderLabel\n                      ? renderLabel(this.selectedOption!, true)\n                      : render(this.label, this.selectedOption, true)}\n                </div>\n              </div>\n            ) : null}\n            {showPlaceholder ? (\n              <div\n                class={`${clsPrefix}-base-selection-placeholder ${clsPrefix}-base-selection-overlay`}\n                key=\"placeholder\"\n              >\n                <div class={`${clsPrefix}-base-selection-overlay__wrapper`}>\n                  {this.filterablePlaceholder}\n                </div>\n              </div>\n            ) : null}\n            {suffix}\n          </div>\n        )\n      }\n      else {\n        body = (\n          <div\n            ref=\"singleElRef\"\n            class={`${clsPrefix}-base-selection-label`}\n            tabindex={this.disabled ? undefined : 0}\n          >\n            {this.label !== undefined ? (\n              <div\n                class={`${clsPrefix}-base-selection-input`}\n                title={getTitleAttribute(this.label)}\n                key=\"input\"\n              >\n                <div class={`${clsPrefix}-base-selection-input__content`}>\n                  {renderTag\n                    ? renderTag({\n                        option: this.selectedOption!,\n                        handleClose: () => {}\n                      })\n                    : renderLabel\n                      ? renderLabel(this.selectedOption!, true)\n                      : render(this.label, this.selectedOption, true)}\n                </div>\n              </div>\n            ) : (\n              <div\n                class={`${clsPrefix}-base-selection-placeholder ${clsPrefix}-base-selection-overlay`}\n                key=\"placeholder\"\n              >\n                <div class={`${clsPrefix}-base-selection-placeholder__inner`}>\n                  {this.placeholder}\n                </div>\n              </div>\n            )}\n            {suffix}\n          </div>\n        )\n      }\n    }\n    return (\n      <div\n        ref=\"selfRef\"\n        class={[\n          `${clsPrefix}-base-selection`,\n          this.rtlEnabled && `${clsPrefix}-base-selection--rtl`,\n          this.themeClass,\n          status && `${clsPrefix}-base-selection--${status}-status`,\n          {\n            [`${clsPrefix}-base-selection--active`]: this.active,\n            [`${clsPrefix}-base-selection--selected`]:\n              this.selected || (this.active && this.pattern),\n            [`${clsPrefix}-base-selection--disabled`]: this.disabled,\n            [`${clsPrefix}-base-selection--multiple`]: this.multiple,\n            // focus is not controlled by selection itself since it always need\n            // to be managed together with menu. provide :focus style will cause\n            // many redundant codes.\n            [`${clsPrefix}-base-selection--focus`]: this.focused\n          }\n        ]}\n        style={this.cssVars as CSSProperties}\n        onClick={this.onClick}\n        onMouseenter={this.handleMouseEnter}\n        onMouseleave={this.handleMouseLeave}\n        onKeydown={this.onKeydown}\n        onFocusin={this.handleFocusin}\n        onFocusout={this.handleFocusout}\n        onMousedown={this.handleMouseDown}\n      >\n        {body}\n        {bordered ? (\n          <div class={`${clsPrefix}-base-selection__border`} />\n        ) : null}\n        {bordered ? (\n          <div class={`${clsPrefix}-base-selection__state-border`} />\n        ) : null}\n      </div>\n    )\n  }\n})\n"
  },
  {
    "path": "src/_internal/selection/src/interface.ts",
    "content": "import type { VNodeChild } from 'vue'\nimport type { SelectOption } from '../../../select/src/interface'\n\nexport type RenderTag = (props: {\n  option: SelectOption\n  handleClose: () => void\n}) => VNodeChild\n"
  },
  {
    "path": "src/_internal/selection/src/styles/index.cssr.ts",
    "content": "import {\n  c,\n  cB,\n  cE,\n  cM,\n  cNotM\n} from '../../../../_utils/cssr'\n\n// vars:\n// --n-bezier\n// --n-border\n// --n-border-active\n// --n-border-focus\n// --n-border-hover\n// --n-border-radius\n// --n-box-shadow-active\n// --n-box-shadow-focus\n// --n-box-shadow-hover\n// --n-caret-color\n// --n-color\n// --n-color-active\n// --n-color-disabled\n// --n-font-size\n// --n-height\n// --n-padding-single\n// --n-padding-multiple\n// --n-placeholder-color\n// --n-placeholder-color-disabled\n// --n-text-color\n// --n-text-color-disabled\n// --n-arrow-color\n// --n-arrow-size\n// --n-loading-color\n// --n-font-weight\n// ...clear vars\n// ...form item vars\nexport default c([\n  cB('base-selection', `\n    --n-padding-single: var(--n-padding-single-top) var(--n-padding-single-right) var(--n-padding-single-bottom) var(--n-padding-single-left);\n    --n-padding-multiple: var(--n-padding-multiple-top) var(--n-padding-multiple-right) var(--n-padding-multiple-bottom) var(--n-padding-multiple-left);\n    position: relative;\n    z-index: auto;\n    box-shadow: none;\n    width: 100%;\n    max-width: 100%;\n    display: inline-block;\n    vertical-align: bottom;\n    border-radius: var(--n-border-radius);\n    min-height: var(--n-height);\n    line-height: 1.5;\n    font-size: var(--n-font-size);\n  `, [\n    cB('base-loading', `\n      color: var(--n-loading-color);\n    `),\n    cB('base-selection-tags', 'min-height: var(--n-height);'),\n    cE('border, state-border', `\n      position: absolute;\n      left: 0;\n      right: 0;\n      top: 0;\n      bottom: 0;\n      pointer-events: none;\n      border: var(--n-border);\n      border-radius: inherit;\n      transition:\n        box-shadow .3s var(--n-bezier),\n        border-color .3s var(--n-bezier);\n    `),\n    cE('state-border', `\n      z-index: 1;\n      border-color: #0000;\n    `),\n    cB('base-suffix', `\n      cursor: pointer;\n      position: absolute;\n      top: 50%;\n      transform: translateY(-50%);\n      right: 10px;\n    `, [\n      cE('arrow', `\n        font-size: var(--n-arrow-size);\n        color: var(--n-arrow-color);\n        transition: color .3s var(--n-bezier);\n      `)\n    ]),\n    cB('base-selection-overlay', `\n      display: flex;\n      align-items: center;\n      white-space: nowrap;\n      pointer-events: none;\n      position: absolute;\n      top: 0;\n      right: 0;\n      bottom: 0;\n      left: 0;\n      padding: var(--n-padding-single);\n      transition: color .3s var(--n-bezier);\n    `, [\n      cE('wrapper', `\n        flex-basis: 0;\n        flex-grow: 1;\n        overflow: hidden;\n        text-overflow: ellipsis;\n      `)\n    ]),\n    cB('base-selection-placeholder', `\n      color: var(--n-placeholder-color);\n    `, [\n      cE('inner', `\n        max-width: 100%;\n        overflow: hidden;\n      `)\n    ]),\n    cB('base-selection-tags', `\n      cursor: pointer;\n      outline: none;\n      box-sizing: border-box;\n      position: relative;\n      z-index: auto;\n      display: flex;\n      padding: var(--n-padding-multiple);\n      flex-wrap: wrap;\n      align-items: center;\n      width: 100%;\n      vertical-align: bottom;\n      background-color: var(--n-color);\n      border-radius: inherit;\n      transition:\n        color .3s var(--n-bezier),\n        box-shadow .3s var(--n-bezier),\n        background-color .3s var(--n-bezier);\n    `),\n    cB('base-selection-label', `\n      height: var(--n-height);\n      display: inline-flex;\n      width: 100%;\n      vertical-align: bottom;\n      cursor: pointer;\n      outline: none;\n      z-index: auto;\n      box-sizing: border-box;\n      position: relative;\n      transition:\n      color .3s var(--n-bezier),\n      box-shadow .3s var(--n-bezier),\n      background-color .3s var(--n-bezier);\n      border-radius: inherit;\n      background-color: var(--n-color);\n      align-items: center;\n    `, [\n      cB('base-selection-input', `\n        font-size: inherit;\n        line-height: inherit;\n        outline: none;\n        cursor: pointer;\n        box-sizing: border-box;\n        border:none;\n        width: 100%;\n        padding: var(--n-padding-single);\n        background-color: #0000;\n        color: var(--n-text-color);\n        transition: color .3s var(--n-bezier);\n        caret-color: var(--n-caret-color);\n      `, [\n        cE('content', `\n          text-overflow: ellipsis;\n          overflow: hidden;\n          white-space: nowrap;  \n        `)\n      ]),\n      cE('render-label', `\n        color: var(--n-text-color);\n      `)\n    ]),\n    cNotM('disabled', [\n      c('&:hover', [\n        cE('state-border', `\n          box-shadow: var(--n-box-shadow-hover);\n          border: var(--n-border-hover);\n        `)\n      ]),\n      cM('focus', [\n        cE('state-border', `\n          box-shadow: var(--n-box-shadow-focus);\n          border: var(--n-border-focus);\n        `)\n      ]),\n      cM('active', [\n        cE('state-border', `\n          box-shadow: var(--n-box-shadow-active);\n          border: var(--n-border-active);\n        `),\n        cB('base-selection-label', 'background-color: var(--n-color-active);'),\n        cB('base-selection-tags', 'background-color: var(--n-color-active);')\n      ])\n    ]),\n    cM('disabled', 'cursor: not-allowed;', [\n      cE('arrow', `\n        color: var(--n-arrow-color-disabled);\n      `),\n      cB('base-selection-label', `\n        cursor: not-allowed;\n        background-color: var(--n-color-disabled);\n      `, [\n        cB('base-selection-input', `\n          cursor: not-allowed;\n          color: var(--n-text-color-disabled);\n        `),\n        cE('render-label', `\n          color: var(--n-text-color-disabled);\n        `)\n      ]),\n      cB('base-selection-tags', `\n        cursor: not-allowed;\n        background-color: var(--n-color-disabled);\n      `),\n      cB('base-selection-placeholder', `\n        cursor: not-allowed;\n        color: var(--n-placeholder-color-disabled);\n      `)\n    ]),\n    cB('base-selection-input-tag', `\n      height: calc(var(--n-height) - 6px);\n      line-height: calc(var(--n-height) - 6px);\n      outline: none;\n      display: none;\n      position: relative;\n      margin-bottom: 3px;\n      max-width: 100%;\n      vertical-align: bottom;\n    `, [\n      cE('input', `\n        font-size: inherit;\n        font-family: inherit;\n        min-width: 1px;\n        padding: 0;\n        background-color: #0000;\n        outline: none;\n        border: none;\n        max-width: 100%;\n        overflow: hidden;\n        width: 1em;\n        line-height: inherit;\n        cursor: pointer;\n        color: var(--n-text-color);\n        caret-color: var(--n-caret-color);\n      `),\n      cE('mirror', `\n        position: absolute;\n        left: 0;\n        top: 0;\n        white-space: pre;\n        visibility: hidden;\n        user-select: none;\n        -webkit-user-select: none;\n        opacity: 0;\n      `)\n    ]),\n    ['warning', 'error'].map(status => cM(`${status}-status`, [\n      cE('state-border', `border: var(--n-border-${status});`),\n      cNotM('disabled', [\n        c('&:hover', [\n          cE('state-border', `\n            box-shadow: var(--n-box-shadow-hover-${status});\n            border: var(--n-border-hover-${status});\n          `)\n        ]),\n        cM('active', [\n          cE('state-border', `\n            box-shadow: var(--n-box-shadow-active-${status});\n            border: var(--n-border-active-${status});\n          `),\n          cB('base-selection-label', `background-color: var(--n-color-active-${status});`),\n          cB('base-selection-tags', `background-color: var(--n-color-active-${status});`)\n        ]),\n        cM('focus', [\n          cE('state-border', `\n            box-shadow: var(--n-box-shadow-focus-${status});\n            border: var(--n-border-focus-${status});\n          `)\n        ])\n      ])\n    ]))\n  ]),\n  cB('base-selection-popover', `\n    margin-bottom: -3px;\n    display: flex;\n    flex-wrap: wrap;\n    margin-right: -8px;\n  `),\n  cB('base-selection-tag-wrapper', `\n    max-width: 100%;\n    display: inline-flex;\n    padding: 0 7px 3px 0;\n  `, [\n    c('&:last-child', 'padding-right: 0;'),\n    cB('tag', `\n      font-size: 14px;\n      max-width: 100%;\n    `, [\n      cE('content', `\n        line-height: 1.25;\n        text-overflow: ellipsis;\n          overflow: hidden;\n      `)\n    ])\n  ])\n])\n"
  },
  {
    "path": "src/_internal/selection/src/styles/rtl.cssr.ts",
    "content": "import { cB, cM } from '../../../../_utils/cssr'\n\nexport default cB('base-selection', [\n  cM('rtl', `\n    direction: rtl;\n    --n-padding-single: var(--n-padding-single-top) var(--n-padding-single-left) var(--n-padding-single-bottom) var(--n-padding-single-right);\n    --n-padding-multiple: var(--n-padding-multiple-top) var(--n-padding-multiple-left) var(--n-padding-multiple-bottom) var(--n-padding-multiple-right);\n  `, [\n    cB('base-suffix', `\n      right: unset;\n      left: 10px;\n    `)\n  ])\n])\n"
  },
  {
    "path": "src/_internal/selection/styles/_common.ts",
    "content": "export default {\n  paddingSingle: '0 26px 0 12px',\n  paddingMultiple: '3px 26px 0 12px',\n  clearSize: '16px',\n  arrowSize: '16px'\n}\n"
  },
  {
    "path": "src/_internal/selection/styles/dark.ts",
    "content": "import type { InternalSelectionTheme } from './light'\nimport { changeColor } from 'seemly'\nimport { commonDark } from '../../../_styles/common'\nimport { popoverDark } from '../../../popover/styles'\nimport commonVars from './_common'\n\nconst internalSelectionDark: InternalSelectionTheme = {\n  name: 'InternalSelection',\n  common: commonDark,\n  peers: {\n    Popover: popoverDark\n  },\n  self(vars) {\n    const {\n      borderRadius,\n      textColor2,\n      textColorDisabled,\n      inputColor,\n      inputColorDisabled,\n      primaryColor,\n      primaryColorHover,\n      warningColor,\n      warningColorHover,\n      errorColor,\n      errorColorHover,\n      iconColor,\n      iconColorDisabled,\n      clearColor,\n      clearColorHover,\n      clearColorPressed,\n      placeholderColor,\n      placeholderColorDisabled,\n      fontSizeTiny,\n      fontSizeSmall,\n      fontSizeMedium,\n      fontSizeLarge,\n      heightTiny,\n      heightSmall,\n      heightMedium,\n      heightLarge,\n      fontWeight\n    } = vars\n    return {\n      ...commonVars,\n      fontWeight,\n      fontSizeTiny,\n      fontSizeSmall,\n      fontSizeMedium,\n      fontSizeLarge,\n      heightTiny,\n      heightSmall,\n      heightMedium,\n      heightLarge,\n      borderRadius,\n      // default\n      textColor: textColor2,\n      textColorDisabled,\n      placeholderColor,\n      placeholderColorDisabled,\n      color: inputColor,\n      colorDisabled: inputColorDisabled,\n      colorActive: changeColor(primaryColor, { alpha: 0.1 }),\n      border: '1px solid #0000',\n      borderHover: `1px solid ${primaryColorHover}`,\n      borderActive: `1px solid ${primaryColor}`,\n      borderFocus: `1px solid ${primaryColorHover}`,\n      boxShadowHover: 'none',\n      boxShadowActive: `0 0 8px 0 ${changeColor(primaryColor, {\n        alpha: 0.4\n      })}`,\n      boxShadowFocus: `0 0 8px 0 ${changeColor(primaryColor, {\n        alpha: 0.4\n      })}`,\n      caretColor: primaryColor,\n      arrowColor: iconColor,\n      arrowColorDisabled: iconColorDisabled,\n      loadingColor: primaryColor,\n      // warning\n      borderWarning: `1px solid ${warningColor}`,\n      borderHoverWarning: `1px solid ${warningColorHover}`,\n      borderActiveWarning: `1px solid ${warningColor}`,\n      borderFocusWarning: `1px solid ${warningColorHover}`,\n      boxShadowHoverWarning: 'none',\n      boxShadowActiveWarning: `0 0 8px 0 ${changeColor(warningColor, {\n        alpha: 0.4\n      })}`,\n      boxShadowFocusWarning: `0 0 8px 0 ${changeColor(warningColor, {\n        alpha: 0.4\n      })}`,\n      colorActiveWarning: changeColor(warningColor, { alpha: 0.1 }),\n      caretColorWarning: warningColor,\n      // error\n      borderError: `1px solid ${errorColor}`,\n      borderHoverError: `1px solid ${errorColorHover}`,\n      borderActiveError: `1px solid ${errorColor}`,\n      borderFocusError: `1px solid ${errorColorHover}`,\n      boxShadowHoverError: 'none',\n      boxShadowActiveError: `0 0 8px 0 ${changeColor(errorColor, {\n        alpha: 0.4\n      })}`,\n      boxShadowFocusError: `0 0 8px 0 ${changeColor(errorColor, {\n        alpha: 0.4\n      })}`,\n      colorActiveError: changeColor(errorColor, { alpha: 0.1 }),\n      caretColorError: errorColor,\n      clearColor,\n      clearColorHover,\n      clearColorPressed\n    }\n  }\n}\n\nexport default internalSelectionDark\n"
  },
  {
    "path": "src/_internal/selection/styles/index.ts",
    "content": "export { default as internalSelectionDark } from './dark'\nexport { default as internalSelectionLight } from './light'\nexport type {\n  InternalSelectionTheme,\n  InternalSelectionThemeVars\n} from './light'\nexport { internalSelectionRtl } from './rtl'\n"
  },
  {
    "path": "src/_internal/selection/styles/light.ts",
    "content": "import type { ThemeCommonVars } from '../../../_styles/common'\nimport { changeColor } from 'seemly'\nimport { createTheme } from '../../../_mixins'\nimport { commonLight } from '../../../_styles/common'\nimport { popoverLight } from '../../../popover/styles'\nimport commonVariables from './_common'\n\nfunction self(vars: ThemeCommonVars) {\n  const {\n    borderRadius,\n    textColor2,\n    textColorDisabled,\n    inputColor,\n    inputColorDisabled,\n    primaryColor,\n    primaryColorHover,\n    warningColor,\n    warningColorHover,\n    errorColor,\n    errorColorHover,\n    borderColor,\n    iconColor,\n    iconColorDisabled,\n    clearColor,\n    clearColorHover,\n    clearColorPressed,\n    placeholderColor,\n    placeholderColorDisabled,\n    fontSizeTiny,\n    fontSizeSmall,\n    fontSizeMedium,\n    fontSizeLarge,\n    heightTiny,\n    heightSmall,\n    heightMedium,\n    heightLarge,\n    fontWeight\n  } = vars\n  return {\n    ...commonVariables,\n    fontSizeTiny,\n    fontSizeSmall,\n    fontSizeMedium,\n    fontSizeLarge,\n    heightTiny,\n    heightSmall,\n    heightMedium,\n    heightLarge,\n    borderRadius,\n    fontWeight,\n    // default\n    textColor: textColor2,\n    textColorDisabled,\n    placeholderColor,\n    placeholderColorDisabled,\n    color: inputColor,\n    colorDisabled: inputColorDisabled,\n    colorActive: inputColor,\n    border: `1px solid ${borderColor}`,\n    borderHover: `1px solid ${primaryColorHover}`,\n    borderActive: `1px solid ${primaryColor}`,\n    borderFocus: `1px solid ${primaryColorHover}`,\n    boxShadowHover: 'none',\n    boxShadowActive: `0 0 0 2px ${changeColor(primaryColor, {\n      alpha: 0.2\n    })}`,\n    boxShadowFocus: `0 0 0 2px ${changeColor(primaryColor, {\n      alpha: 0.2\n    })}`,\n    caretColor: primaryColor,\n    arrowColor: iconColor,\n    arrowColorDisabled: iconColorDisabled,\n    loadingColor: primaryColor,\n    // warning\n    borderWarning: `1px solid ${warningColor}`,\n    borderHoverWarning: `1px solid ${warningColorHover}`,\n    borderActiveWarning: `1px solid ${warningColor}`,\n    borderFocusWarning: `1px solid ${warningColorHover}`,\n    boxShadowHoverWarning: 'none',\n    boxShadowActiveWarning: `0 0 0 2px ${changeColor(warningColor, {\n      alpha: 0.2\n    })}`,\n    boxShadowFocusWarning: `0 0 0 2px ${changeColor(warningColor, {\n      alpha: 0.2\n    })}`,\n    colorActiveWarning: inputColor,\n    caretColorWarning: warningColor,\n    // error\n    borderError: `1px solid ${errorColor}`,\n    borderHoverError: `1px solid ${errorColorHover}`,\n    borderActiveError: `1px solid ${errorColor}`,\n    borderFocusError: `1px solid ${errorColorHover}`,\n    boxShadowHoverError: 'none',\n    boxShadowActiveError: `0 0 0 2px ${changeColor(errorColor, {\n      alpha: 0.2\n    })}`,\n    boxShadowFocusError: `0 0 0 2px ${changeColor(errorColor, {\n      alpha: 0.2\n    })}`,\n    colorActiveError: inputColor,\n    caretColorError: errorColor,\n    clearColor,\n    clearColorHover,\n    clearColorPressed\n  }\n}\n\nexport type InternalSelectionThemeVars = ReturnType<typeof self>\n\nconst internalSelectionLight = createTheme({\n  name: 'InternalSelection',\n  common: commonLight,\n  peers: {\n    Popover: popoverLight\n  },\n  self\n})\n\nexport default internalSelectionLight\nexport type InternalSelectionTheme = typeof internalSelectionLight\n"
  },
  {
    "path": "src/_internal/selection/styles/rtl.ts",
    "content": "import type { RtlItem } from '../../../config-provider/src/internal-interface'\nimport rtlStyle from '../src/styles/rtl.cssr'\n\nexport const internalSelectionRtl: RtlItem = {\n  name: 'InternalSelection',\n  style: rtlStyle\n}\n"
  },
  {
    "path": "src/_internal/slot-machine/index.ts",
    "content": "export { default } from './src/SlotMachine'\n"
  },
  {
    "path": "src/_internal/slot-machine/src/SlotMachine.tsx",
    "content": "import {\n  computed,\n  defineComponent,\n  h,\n  ref,\n  toRef,\n  TransitionGroup,\n  watch\n} from 'vue'\nimport { useStyle } from '../../../_mixins'\nimport NFadeInExpandTransition from '../../fade-in-expand-transition'\nimport SlotMachineNumber from './SlotMachineNumber'\nimport style from './styles/index.cssr'\n\nexport default defineComponent({\n  name: 'BaseSlotMachine',\n  props: {\n    clsPrefix: {\n      type: String,\n      required: true\n    },\n    value: {\n      type: [Number, String],\n      default: 0\n    },\n    max: {\n      type: Number,\n      default: undefined\n    },\n    appeared: {\n      type: Boolean,\n      required: true\n    }\n  },\n  setup(props) {\n    useStyle('-base-slot-machine', style, toRef(props, 'clsPrefix'))\n    const oldValueRef = ref<number>()\n    const newValueRef = ref<number>()\n    const numbersRef = computed(() => {\n      if (typeof props.value === 'string')\n        return []\n      if (props.value < 1)\n        return [0]\n      const numbers: number[] = []\n      let value = props.value\n      if (props.max !== undefined) {\n        value = Math.min(props.max, value)\n      }\n      while (value >= 1) {\n        numbers.push(value % 10)\n        value /= 10\n        value = Math.floor(value)\n      }\n      numbers.reverse()\n      return numbers\n    })\n    watch(toRef(props, 'value'), (value, oldValue) => {\n      if (typeof value === 'string') {\n        newValueRef.value = undefined\n        oldValueRef.value = undefined\n      }\n      else {\n        if (typeof oldValue === 'string') {\n          newValueRef.value = value\n          oldValueRef.value = undefined\n        }\n        else {\n          newValueRef.value = value\n          oldValueRef.value = oldValue\n        }\n      }\n    })\n    return () => {\n      const { value, clsPrefix } = props\n      return typeof value === 'number' ? (\n        <span class={`${clsPrefix}-base-slot-machine`}>\n          <TransitionGroup name=\"fade-up-width-expand-transition\" tag=\"span\">\n            {{\n              default: () =>\n                numbersRef.value.map((number, i) => (\n                  <SlotMachineNumber\n                    clsPrefix={clsPrefix}\n                    key={numbersRef.value.length - i - 1}\n                    oldOriginalNumber={oldValueRef.value}\n                    newOriginalNumber={newValueRef.value}\n                    value={number}\n                  />\n                ))\n            }}\n          </TransitionGroup>\n          <NFadeInExpandTransition key=\"+\" width>\n            {{\n              default: () =>\n                props.max !== undefined && props.max < value ? (\n                  <SlotMachineNumber clsPrefix={clsPrefix} value=\"+\" />\n                ) : null\n            }}\n          </NFadeInExpandTransition>\n        </span>\n      ) : (\n        <span class={`${clsPrefix}-base-slot-machine`}>{value}</span>\n      )\n    }\n  }\n})\n"
  },
  {
    "path": "src/_internal/slot-machine/src/SlotMachineNumber.tsx",
    "content": "import type { PropType } from 'vue'\nimport { computed, defineComponent, h, nextTick, ref, toRef, watch } from 'vue'\n\nexport default defineComponent({\n  name: 'SlotMachineNumber',\n  props: {\n    clsPrefix: {\n      type: String,\n      required: true\n    },\n    value: {\n      // could be '+', 1, 2, ...\n      type: [Number, String] as PropType<string | number>,\n      required: true\n    },\n    oldOriginalNumber: {\n      type: Number,\n      default: undefined\n    },\n    newOriginalNumber: {\n      type: Number,\n      default: undefined\n    }\n  },\n  setup(props) {\n    const numberRef = ref<HTMLElement | null>(null)\n    const oldNumberRef = ref<number | string>(props.value)\n    const newNumberRef = ref<number | string>(props.value)\n    const scrollAnimationDirectionRef = ref<'up' | 'down'>('up')\n    const activeRef = ref(false)\n    const newNumberScrollAnimationClassRef = computed(() => {\n      return activeRef.value\n        ? `${props.clsPrefix}-base-slot-machine-current-number--${scrollAnimationDirectionRef.value}-scroll`\n        : null\n    })\n    const oldNumberScrollAnimationClassRef = computed(() => {\n      return activeRef.value\n        ? `${props.clsPrefix}-base-slot-machine-old-number--${scrollAnimationDirectionRef.value}-scroll`\n        : null\n    })\n    // BUG: may be typescript bug\n    watch(toRef(props, 'value'), (value, oldValue) => {\n      oldNumberRef.value = oldValue\n      newNumberRef.value = value\n      void nextTick(scroll)\n    })\n    function scroll(): void {\n      const newOriginalNumber = props.newOriginalNumber\n      const oldOriginalNumber = props.oldOriginalNumber\n      if (oldOriginalNumber === undefined || newOriginalNumber === undefined) {\n        return\n      }\n      if (newOriginalNumber > oldOriginalNumber) {\n        scrollByDir('up')\n      }\n      else if (oldOriginalNumber > newOriginalNumber) {\n        scrollByDir('down')\n      }\n    }\n    function scrollByDir(dir: 'up' | 'down'): void {\n      scrollAnimationDirectionRef.value = dir\n      activeRef.value = false\n      void nextTick(() => {\n        void numberRef.value?.offsetWidth\n        activeRef.value = true\n      })\n    }\n    return () => {\n      const { clsPrefix } = props\n      return (\n        <span ref={numberRef} class={`${clsPrefix}-base-slot-machine-number`}>\n          {oldNumberRef.value !== null ? (\n            <span\n              class={[\n                `${clsPrefix}-base-slot-machine-old-number ${clsPrefix}-base-slot-machine-old-number--top`,\n                oldNumberScrollAnimationClassRef.value\n              ]}\n            >\n              {oldNumberRef.value}\n            </span>\n          ) : null}\n          <span\n            class={[\n              `${clsPrefix}-base-slot-machine-current-number`,\n              newNumberScrollAnimationClassRef.value\n            ]}\n          >\n            <span\n              ref=\"numberWrapper\"\n              class={[\n                `${clsPrefix}-base-slot-machine-current-number__inner`,\n                typeof props.value !== 'number'\n                && `${clsPrefix}-base-slot-machine-current-number__inner--not-number`\n              ]}\n            >\n              {newNumberRef.value}\n            </span>\n          </span>\n          {oldNumberRef.value !== null ? (\n            <span\n              class={[\n                `${clsPrefix}-base-slot-machine-old-number ${clsPrefix}-base-slot-machine-old-number--bottom`,\n                oldNumberScrollAnimationClassRef.value\n              ]}\n            >\n              {oldNumberRef.value}\n            </span>\n          ) : null}\n        </span>\n      )\n    }\n  }\n})\n"
  },
  {
    "path": "src/_internal/slot-machine/src/styles/index.cssr.ts",
    "content": "import { fadeInWidthExpandTransition } from '../../../../_styles/transitions/fade-in-width-expand.cssr'\nimport { fadeUpWidthExpandTransition } from '../../../../_styles/transitions/fade-up-width-expand.cssr'\nimport { c, cB, cE, cM } from '../../../../_utils/cssr'\n\n// ease-out: cubic-bezier(0, 0, .2, 1)\nexport default c([\n  c('@keyframes n-base-slot-machine-fade-up-in', `\n    from {\n      transform: translateY(60%);\n      opacity: 0;\n    }\n    to {\n      transform: translateY(0);\n      opacity: 1;\n    }\n  `),\n  c('@keyframes n-base-slot-machine-fade-down-in', `\n    from {\n      transform: translateY(-60%);\n      opacity: 0;\n    }\n    to {\n      transform: translateY(0);\n      opacity: 1;\n    }\n  `),\n  c('@keyframes n-base-slot-machine-fade-up-out', `\n    from {\n      transform: translateY(0%);\n      opacity: 1;\n    }\n    to {\n      transform: translateY(-60%);\n      opacity: 0;\n    }\n  `),\n  c('@keyframes n-base-slot-machine-fade-down-out', `\n    from {\n      transform: translateY(0%);\n      opacity: 1;\n    }\n    to {\n      transform: translateY(60%);\n      opacity: 0;\n    }\n  `),\n  cB('base-slot-machine', `\n    overflow: hidden;\n    white-space: nowrap;\n    display: inline-block;\n    height: 18px;\n    line-height: 18px;\n  `, [\n    cB('base-slot-machine-number', `\n      display: inline-block;\n      position: relative;\n      height: 18px;\n      width: .6em;\n      max-width: .6em;\n    `, [\n      fadeUpWidthExpandTransition({ duration: '.2s' }),\n      // use 0s, not 0\n      fadeInWidthExpandTransition({ duration: '.2s', delay: '0s' }),\n      cB('base-slot-machine-old-number', `\n        display: inline-block;\n        opacity: 0;\n        position: absolute;\n        left: 0;\n        right: 0;\n      `, [\n        cM('top', {\n          transform: 'translateY(-100%)'\n        }),\n        cM('bottom', {\n          transform: 'translateY(100%)'\n        }),\n        cM('down-scroll', {\n          animation: 'n-base-slot-machine-fade-down-out .2s cubic-bezier(0, 0, .2, 1)',\n          animationIterationCount: 1\n        }),\n        cM('up-scroll', {\n          animation: 'n-base-slot-machine-fade-up-out .2s cubic-bezier(0, 0, .2, 1)',\n          animationIterationCount: 1\n        })\n      ]),\n      cB('base-slot-machine-current-number', `\n        display: inline-block;\n        position: absolute;\n        left: 0;\n        top: 0;\n        bottom: 0;\n        right: 0;\n        opacity: 1;\n        transform: translateY(0);\n        width: .6em;\n      `, [\n        cM('down-scroll', {\n          animation: 'n-base-slot-machine-fade-down-in .2s cubic-bezier(0, 0, .2, 1)',\n          animationIterationCount: 1\n        }),\n        cM('up-scroll', {\n          animation: 'n-base-slot-machine-fade-up-in .2s cubic-bezier(0, 0, .2, 1)',\n          animationIterationCount: 1\n        }),\n        cE('inner', `\n            display: inline-block;\n            position: absolute;\n            right: 0;\n            top: 0;\n            width: .6em;\n          `, [\n          cM('not-number', `\n            right: unset;\n            left: 0;\n          `)\n        ])\n      ])\n    ])\n  ])\n])\n"
  },
  {
    "path": "src/_internal/suffix/index.ts",
    "content": "export { default } from './src/Suffix'\n"
  },
  {
    "path": "src/_internal/suffix/src/Suffix.tsx",
    "content": "import type { PropType } from 'vue'\nimport { defineComponent, h } from 'vue'\nimport { resolveSlot } from '../../../_utils/vue'\nimport NBaseClear from '../../clear'\nimport { NBaseIcon } from '../../icon'\nimport { ChevronDownIcon } from '../../icons'\nimport NBaseLoading from '../../loading'\n\nexport default defineComponent({\n  name: 'InternalSelectionSuffix',\n  props: {\n    clsPrefix: {\n      type: String,\n      required: true\n    },\n    showArrow: {\n      type: Boolean,\n      default: undefined\n    },\n    showClear: {\n      type: Boolean,\n      default: undefined\n    },\n    loading: {\n      type: Boolean,\n      default: false\n    },\n    onClear: Function as PropType<(e: MouseEvent) => void>\n  },\n  setup(props, { slots }) {\n    return () => {\n      const { clsPrefix } = props\n      return (\n        <NBaseLoading\n          clsPrefix={clsPrefix}\n          class={`${clsPrefix}-base-suffix`}\n          strokeWidth={24}\n          scale={0.85}\n          show={props.loading}\n        >\n          {{\n            default: () =>\n              props.showArrow ? (\n                <NBaseClear\n                  clsPrefix={clsPrefix}\n                  show={props.showClear}\n                  onClear={props.onClear}\n                >\n                  {{\n                    placeholder: () => (\n                      <NBaseIcon\n                        clsPrefix={clsPrefix}\n                        class={`${clsPrefix}-base-suffix__arrow`}\n                      >\n                        {{\n                          default: () =>\n                            resolveSlot(slots.default, () => [\n                              <ChevronDownIcon />\n                            ])\n                        }}\n                      </NBaseIcon>\n                    )\n                  }}\n                </NBaseClear>\n              ) : null\n          }}\n        </NBaseLoading>\n      )\n    }\n  }\n})\n"
  },
  {
    "path": "src/_internal/wave/index.ts",
    "content": "export { default } from './src/Wave'\nexport type { BaseWaveRef } from './src/Wave'\n"
  },
  {
    "path": "src/_internal/wave/src/Wave.tsx",
    "content": "import { defineComponent, h, nextTick, onBeforeUnmount, ref, toRef } from 'vue'\nimport { useStyle } from '../../../_mixins'\nimport style from './styles/index.cssr'\n\nexport interface BaseWaveRef {\n  play: () => void\n}\n\nexport default defineComponent({\n  name: 'BaseWave',\n  props: {\n    clsPrefix: {\n      type: String,\n      required: true\n    }\n  },\n  setup(props) {\n    useStyle('-base-wave', style, toRef(props, 'clsPrefix'))\n    const selfRef = ref<HTMLElement | null>(null)\n    const activeRef = ref(false)\n    let animationTimerId: number | null = null\n    onBeforeUnmount(() => {\n      if (animationTimerId !== null) {\n        window.clearTimeout(animationTimerId)\n      }\n    })\n    return {\n      active: activeRef,\n      selfRef,\n      play() {\n        if (animationTimerId !== null) {\n          window.clearTimeout(animationTimerId)\n          activeRef.value = false\n          animationTimerId = null\n        }\n        void nextTick(() => {\n          void selfRef.value?.offsetHeight\n          activeRef.value = true\n          animationTimerId = window.setTimeout(() => {\n            activeRef.value = false\n            animationTimerId = null\n          }, 1000)\n        })\n      }\n    }\n  },\n  render() {\n    const { clsPrefix } = this\n    return (\n      <div\n        ref=\"selfRef\"\n        aria-hidden\n        class={[\n          `${clsPrefix}-base-wave`,\n          this.active && `${clsPrefix}-base-wave--active`\n        ]}\n      />\n    )\n  }\n})\n"
  },
  {
    "path": "src/_internal/wave/src/styles/index.cssr.ts",
    "content": "import { cB } from '../../../../_utils/cssr/index'\n\nexport default cB('base-wave', `\n  position: absolute;\n  left: 0;\n  right: 0;\n  top: 0;\n  bottom: 0;\n  border-radius: inherit;\n`)\n"
  },
  {
    "path": "src/_mixins/common.ts",
    "content": "export const cssrAnchorMetaName = 'naive-ui-style'\n"
  },
  {
    "path": "src/_mixins/index.ts",
    "content": "export { defaultClsPrefix, default as useConfig } from './use-config'\nexport { useThemeClass } from './use-css-vars-class'\nexport { default as useFormItem } from './use-form-item'\nexport { default as useHljs } from './use-hljs'\nexport type { Hljs } from './use-hljs'\nexport { default as useLocale } from './use-locale'\nexport { useRtl } from './use-rtl'\nexport { default as useStyle } from './use-style'\nexport { createTheme, default as useTheme } from './use-theme'\nexport type {\n  MergedTheme,\n  Theme,\n  ThemeProps,\n  ThemePropsReactive\n} from './use-theme'\n"
  },
  {
    "path": "src/_mixins/use-config.ts",
    "content": "import type { ComputedRef, Ref } from 'vue'\nimport type {\n  Breakpoints,\n  GlobalComponentConfig,\n  RtlEnabledState\n} from '../config-provider/src/internal-interface'\nimport { computed, inject, shallowRef } from 'vue'\nimport { configProviderInjectionKey } from '../config-provider/src/context'\n\ntype UseConfigProps = Readonly<{\n  bordered?: boolean\n  [key: string]: unknown\n}>\n\nexport const defaultClsPrefix = 'n'\n\nexport default function useConfig(\n  props: UseConfigProps = {},\n  options: {\n    defaultBordered?: boolean\n  } = {\n    defaultBordered: true\n  }\n): {\n  inlineThemeDisabled: boolean | undefined\n  mergedRtlRef: Ref<RtlEnabledState | undefined> | undefined\n  mergedBorderedRef: ComputedRef<boolean>\n  mergedClsPrefixRef: Ref<string>\n  mergedBreakpointsRef: Ref<Breakpoints> | undefined\n  mergedComponentPropsRef: Ref<GlobalComponentConfig | undefined> | undefined\n  namespaceRef: ComputedRef<string | undefined>\n} {\n  const NConfigProvider = inject(configProviderInjectionKey, null)\n  return {\n    // NConfigProvider,\n    inlineThemeDisabled: NConfigProvider?.inlineThemeDisabled,\n    mergedRtlRef: NConfigProvider?.mergedRtlRef,\n    mergedComponentPropsRef: NConfigProvider?.mergedComponentPropsRef,\n    mergedBreakpointsRef: NConfigProvider?.mergedBreakpointsRef,\n    mergedBorderedRef: computed(() => {\n      const { bordered } = props\n      if (bordered !== undefined)\n        return bordered\n      return (\n        NConfigProvider?.mergedBorderedRef.value\n        ?? options.defaultBordered\n        ?? true\n      )\n    }),\n    mergedClsPrefixRef: NConfigProvider\n      ? NConfigProvider.mergedClsPrefixRef\n      : shallowRef(defaultClsPrefix),\n    namespaceRef: computed(() => NConfigProvider?.mergedNamespaceRef.value)\n  }\n}\n\nexport function useMergedClsPrefix(): Ref<string> {\n  const NConfigProvider = inject(configProviderInjectionKey, null)\n  return NConfigProvider\n    ? NConfigProvider.mergedClsPrefixRef\n    : shallowRef(defaultClsPrefix)\n}\n"
  },
  {
    "path": "src/_mixins/use-css-vars-class.ts",
    "content": "import type { ComputedRef, Ref } from 'vue'\nimport { useSsrAdapter } from '@css-render/vue3-ssr'\nimport { hash } from 'css-render'\nimport { inject, ref, watchEffect } from 'vue'\nimport { throwError } from '../_utils'\nimport { c } from '../_utils/cssr'\nimport { configProviderInjectionKey } from '../config-provider/src/context'\n\nexport function useThemeClass(\n  componentName: string,\n  hashRef: Ref<string> | undefined,\n  cssVarsRef: ComputedRef<Record<string, string>> | undefined,\n  props: { themeOverrides?: unknown, builtinThemeOverrides?: unknown }\n): {\n  themeClass: Ref<string>\n  onRender: () => void\n} {\n  if (!cssVarsRef)\n    throwError('useThemeClass', 'cssVarsRef is not passed')\n\n  const NConfigProvider = inject(configProviderInjectionKey, null)\n\n  const mergedThemeHashRef = NConfigProvider?.mergedThemeHashRef\n  const styleMountTarget = NConfigProvider?.styleMountTarget\n\n  const themeClassRef = ref('')\n\n  const ssrAdapter = useSsrAdapter()\n\n  let renderCallback: (() => void) | undefined\n\n  const hashClassPrefix = `__${componentName}`\n  const mountStyle = (): void => {\n    let finalThemeHash = hashClassPrefix\n    const hashValue = hashRef ? hashRef.value : undefined\n    const themeHash = mergedThemeHashRef?.value\n    if (themeHash)\n      finalThemeHash += `-${themeHash}`\n    if (hashValue)\n      finalThemeHash += `-${hashValue}`\n    const { themeOverrides, builtinThemeOverrides } = props\n    if (themeOverrides) {\n      finalThemeHash += `-${hash(JSON.stringify(themeOverrides))}`\n    }\n    if (builtinThemeOverrides) {\n      finalThemeHash += `-${hash(JSON.stringify(builtinThemeOverrides))}`\n    }\n    themeClassRef.value = finalThemeHash\n    renderCallback = () => {\n      const cssVars = cssVarsRef.value\n      let style = ''\n      for (const key in cssVars) {\n        style += `${key}: ${cssVars[key]};`\n      }\n      c(`.${finalThemeHash}`, style).mount({\n        id: finalThemeHash,\n        ssr: ssrAdapter,\n        parent: styleMountTarget\n      })\n      renderCallback = undefined\n    }\n  }\n\n  watchEffect(() => {\n    mountStyle()\n  })\n\n  return {\n    themeClass: themeClassRef,\n    onRender: () => {\n      renderCallback?.()\n    }\n  }\n}\n"
  },
  {
    "path": "src/_mixins/use-form-item.ts",
    "content": "import type { ComputedRef, Ref } from 'vue'\nimport type {\n  FormItemSize,\n  FormValidationStatus\n} from '../form/src/public-types'\nimport { computed, inject, onBeforeUnmount, provide } from 'vue'\nimport { createInjectionKey } from '../_utils'\n\ntype AllowedSize = 'tiny' | 'small' | 'medium' | 'large' | 'huge' | number\n\nexport interface FormItemInjection {\n  path: Ref<string | undefined>\n  disabled: Ref<boolean>\n  mergedSize: ComputedRef<FormItemSize>\n  mergedValidationStatus: ComputedRef<FormValidationStatus | undefined>\n  restoreValidation: () => void\n  handleContentBlur: () => void\n  handleContentFocus: () => void\n  handleContentInput: () => void\n  handleContentChange: () => void\n}\n\nexport const formItemInjectionKey\n  = createInjectionKey<FormItemInjection | null>('n-form-item')\n\ninterface UseFormItemOptions<T> {\n  defaultSize?: FormItemSize\n  mergedSize?: (formItem: FormItemInjection | null) => T\n  mergedDisabled?: (formItem: FormItemInjection | null) => boolean\n}\n\ninterface UseFormItemProps<T> {\n  size?: T\n  disabled?: boolean\n  status?: FormValidationStatus\n}\n\nexport interface UseFormItem<T> {\n  mergedSizeRef: ComputedRef<T>\n  mergedDisabledRef: ComputedRef<boolean>\n  mergedStatusRef: ComputedRef<FormValidationStatus | undefined>\n  nTriggerFormBlur: () => void\n  nTriggerFormChange: () => void\n  nTriggerFormFocus: () => void\n  nTriggerFormInput: () => void\n}\n\nexport default function useFormItem<T extends AllowedSize = FormItemSize>(\n  props: UseFormItemProps<T>,\n  {\n    defaultSize = 'medium',\n    mergedSize,\n    mergedDisabled\n  }: UseFormItemOptions<T> = {}\n): UseFormItem<T> {\n  const NFormItem = inject(formItemInjectionKey, null)\n  provide(formItemInjectionKey, null)\n  const mergedSizeRef = computed(\n    mergedSize\n      ? () => mergedSize(NFormItem)\n      : () => {\n          const { size } = props\n          if (size)\n            return size\n          if (NFormItem) {\n            const { mergedSize } = NFormItem\n            if (mergedSize.value !== undefined) {\n              return mergedSize.value as T\n            }\n          }\n          return defaultSize as T\n        }\n  )\n  const mergedDisabledRef = computed(\n    mergedDisabled\n      ? () => mergedDisabled(NFormItem)\n      : () => {\n          const { disabled } = props\n          if (disabled !== undefined) {\n            return disabled\n          }\n          if (NFormItem) {\n            return NFormItem.disabled.value\n          }\n          return false\n        }\n  )\n  const mergedStatusRef = computed<FormValidationStatus | undefined>(() => {\n    const { status } = props\n    if (status)\n      return status\n    return NFormItem?.mergedValidationStatus.value\n  })\n  onBeforeUnmount(() => {\n    if (NFormItem) {\n      NFormItem.restoreValidation()\n    }\n  })\n  return {\n    mergedSizeRef,\n    mergedDisabledRef,\n    mergedStatusRef,\n    nTriggerFormBlur() {\n      if (NFormItem) {\n        NFormItem.handleContentBlur()\n      }\n    },\n    nTriggerFormChange() {\n      if (NFormItem) {\n        NFormItem.handleContentChange()\n      }\n    },\n    nTriggerFormFocus() {\n      if (NFormItem) {\n        NFormItem.handleContentFocus()\n      }\n    },\n    nTriggerFormInput() {\n      if (NFormItem) {\n        NFormItem.handleContentInput()\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "src/_mixins/use-hljs.ts",
    "content": "import type { HLJSApi } from 'highlight.js'\nimport type { ComputedRef, Ref } from 'vue'\nimport { computed, inject, watchEffect } from 'vue'\nimport { warn } from '../_utils'\nimport { configProviderInjectionKey } from '../config-provider/src/context'\n\ninterface UseHljsProps {\n  hljs?: unknown\n  [key: string]: unknown\n}\n\nexport interface Hljs {\n  highlight: HLJSApi['highlight']\n  getLanguage: HLJSApi['getLanguage']\n}\nexport default function useHljs(\n  props: UseHljsProps,\n  shouldHighlightRef?: Ref<boolean>\n): ComputedRef<Hljs | undefined> {\n  const NConfigProvider = inject(configProviderInjectionKey, null)\n  if (__DEV__) {\n    const warnHljs = (): void => {\n      if (!props.hljs && !NConfigProvider?.mergedHljsRef.value) {\n        warn('code', 'hljs is not set.')\n      }\n    }\n    if (!shouldHighlightRef) {\n      warnHljs()\n    }\n    else {\n      watchEffect(() => {\n        if (shouldHighlightRef.value) {\n          warnHljs()\n        }\n      })\n    }\n  }\n  return computed(() => {\n    return (props.hljs as any) || NConfigProvider?.mergedHljsRef.value\n  })\n}\n"
  },
  {
    "path": "src/_mixins/use-locale.ts",
    "content": "import type { Ref } from 'vue'\nimport type { NLocale } from '../locales/common/enUS'\nimport type { NDateLocale } from '../locales/date/enUS'\nimport { computed, inject } from 'vue'\nimport { configProviderInjectionKey } from '../config-provider/src/context'\nimport { dateEnUS, enUS } from '../locales'\n\nexport default function useLocale<T extends keyof NLocale>(\n  ns: T\n): {\n  localeRef: Ref<NLocale[T]>\n  dateLocaleRef: Ref<NDateLocale>\n} {\n  const { mergedLocaleRef, mergedDateLocaleRef }\n    = inject(configProviderInjectionKey, null) || {}\n  const localeRef = computed(() => {\n    return mergedLocaleRef?.value?.[ns] ?? enUS[ns]\n  })\n  const dateLocaleRef = computed(() => {\n    return mergedDateLocaleRef?.value ?? dateEnUS\n  })\n  return {\n    dateLocaleRef,\n    localeRef\n  }\n}\n"
  },
  {
    "path": "src/_mixins/use-rtl.ts",
    "content": "import type { Ref } from 'vue'\nimport type {\n  RtlEnabledState,\n  RtlItem\n} from '../config-provider/src/internal-interface'\nimport { useSsrAdapter } from '@css-render/vue3-ssr'\nimport { exists } from 'css-render'\nimport { computed, inject, onBeforeMount, watchEffect } from 'vue'\nimport { configProviderInjectionKey } from '../config-provider/src/context'\nimport { cssrAnchorMetaName } from './common'\n\nexport function useRtl(\n  mountId: string,\n  rtlStateRef: Ref<RtlEnabledState | undefined> | undefined,\n  clsPrefixRef: Ref<string>\n): Ref<RtlItem | undefined> | undefined {\n  if (!rtlStateRef)\n    return undefined\n  const ssrAdapter = useSsrAdapter()\n  const componentRtlStateRef = computed(() => {\n    const { value: rtlState } = rtlStateRef\n    if (!rtlState) {\n      return undefined\n    }\n    const componentRtlState = rtlState[mountId as keyof RtlEnabledState]\n    if (!componentRtlState) {\n      return undefined\n    }\n    return componentRtlState\n  })\n  const NConfigProvider = inject(configProviderInjectionKey, null)\n  const mountStyle = (): void => {\n    watchEffect(() => {\n      const { value: clsPrefix } = clsPrefixRef\n      const id = `${clsPrefix}${mountId}Rtl`\n      // if it already exists, we only need to watch clsPrefix, although in most\n      // of time it's unnecessary... However we can at least listen less\n      // handlers, which is great.\n      if (exists(id, ssrAdapter))\n        return\n      const { value: componentRtlState } = componentRtlStateRef\n      if (!componentRtlState)\n        return\n      componentRtlState.style.mount({\n        id,\n        head: true,\n        anchorMetaName: cssrAnchorMetaName,\n        props: {\n          bPrefix: clsPrefix ? `.${clsPrefix}-` : undefined\n        },\n        ssr: ssrAdapter,\n        parent: NConfigProvider?.styleMountTarget\n      })\n    })\n  }\n  if (ssrAdapter) {\n    mountStyle()\n  }\n  else {\n    onBeforeMount(mountStyle)\n  }\n  return componentRtlStateRef\n}\n"
  },
  {
    "path": "src/_mixins/use-style.ts",
    "content": "import type { CNode } from 'css-render'\nimport type { Ref } from 'vue'\nimport { useSsrAdapter } from '@css-render/vue3-ssr'\nimport { inject, onBeforeMount } from 'vue'\nimport globalStyle from '../_styles/global/index.cssr'\nimport { throwError } from '../_utils'\nimport { configProviderInjectionKey } from '../config-provider/src/context'\nimport { cssrAnchorMetaName } from './common'\n\nexport default function useStyle(\n  mountId: string,\n  style: CNode,\n  clsPrefixRef: Ref<string | undefined>\n): void {\n  if (!style) {\n    if (__DEV__)\n      throwError('use-style', 'No style is specified.')\n    return\n  }\n  const ssrAdapter = useSsrAdapter()\n  const NConfigProvider = inject(configProviderInjectionKey, null)\n  const mountStyle = (): void => {\n    const clsPrefix = clsPrefixRef.value\n    style.mount({\n      id: clsPrefix === undefined ? mountId : clsPrefix + mountId,\n      head: true,\n      anchorMetaName: cssrAnchorMetaName,\n      props: {\n        bPrefix: clsPrefix ? `.${clsPrefix}-` : undefined\n      },\n      ssr: ssrAdapter,\n      parent: NConfigProvider?.styleMountTarget\n    })\n    if (!NConfigProvider?.preflightStyleDisabled) {\n      globalStyle.mount({\n        id: 'n-global',\n        head: true,\n        anchorMetaName: cssrAnchorMetaName,\n        ssr: ssrAdapter,\n        parent: NConfigProvider?.styleMountTarget\n      })\n    }\n  }\n  if (ssrAdapter) {\n    mountStyle()\n  }\n  else {\n    onBeforeMount(mountStyle)\n  }\n}\n"
  },
  {
    "path": "src/_mixins/use-theme.ts",
    "content": "import type { CNode } from 'css-render'\nimport type { ComputedRef, PropType, Ref } from 'vue'\nimport type { ThemeCommonVars } from '../_styles/common'\nimport type { GlobalTheme } from '../config-provider'\nimport { useSsrAdapter } from '@css-render/vue3-ssr'\nimport { merge } from 'lodash-es'\nimport { computed, inject, onBeforeMount } from 'vue'\nimport globalStyle from '../_styles/global/index.cssr'\nimport { configProviderInjectionKey } from '../config-provider/src/context'\nimport { cssrAnchorMetaName } from './common'\n\nexport interface Theme<N, T = Record<string, unknown>, R = any> {\n  name: N\n  common?: ThemeCommonVars\n  peers?: R\n  self?: (vars: ThemeCommonVars) => T\n}\n\nexport interface ThemeProps<T> {\n  theme: PropType<T>\n  themeOverrides: PropType<ExtractThemeOverrides<T>>\n  builtinThemeOverrides: PropType<ExtractThemeOverrides<T>>\n}\n\nexport interface ThemePropsReactive<T> {\n  theme?: T\n  themeOverrides?: ExtractThemeOverrides<T>\n  builtinThemeOverrides?: ExtractThemeOverrides<T>\n}\n\nexport type ExtractThemeVars<T>\n  = T extends Theme<unknown, infer U, unknown>\n    ? unknown extends U // self is undefined, ThemeVars is unknown\n      ? Record<string, unknown>\n      : U\n    : Record<string, unknown>\n\nexport type ExtractPeerOverrides<T>\n  = T extends Theme<unknown, unknown, infer V>\n    ? {\n        peers?: {\n          [k in keyof V]?: ExtractThemeOverrides<V[k]>\n        }\n      }\n    : T\n\n// V is peers theme\nexport type ExtractMergedPeerOverrides<T>\n  = T extends Theme<unknown, unknown, infer V>\n    ? {\n        [k in keyof V]?: ExtractPeerOverrides<V[k]>\n      }\n    : T\n\nexport type ExtractThemeOverrides<T> = Partial<ExtractThemeVars<T>>\n  & ExtractPeerOverrides<T> & { common?: Partial<ThemeCommonVars> }\n\nexport function createTheme<N extends string, T, R>(\n  theme: Theme<N, T, R>\n): Theme<N, T, R> {\n  return theme\n}\n\ntype UseThemeProps<T> = Readonly<{\n  theme?: T | undefined\n  themeOverrides?: ExtractThemeOverrides<T>\n  builtinThemeOverrides?: ExtractThemeOverrides<T>\n}>\n\nexport type MergedTheme<T>\n  = T extends Theme<unknown, infer V, infer W>\n    ? {\n        common: ThemeCommonVars\n        self: V\n        peers: W\n        peerOverrides: ExtractMergedPeerOverrides<T>\n      }\n    : T\n\nfunction useTheme<N, T, R>(\n  resolveId: Exclude<keyof GlobalTheme, 'common' | 'name'>,\n  mountId: string,\n  style: CNode | undefined,\n  defaultTheme: Theme<N, T, R>,\n  props: UseThemeProps<Theme<N, T, R>>,\n  clsPrefixRef: Ref<string | undefined> | undefined\n): ComputedRef<MergedTheme<Theme<N, T, R>>> {\n  const ssrAdapter = useSsrAdapter()\n  const NConfigProvider = inject(configProviderInjectionKey, null)\n  if (style) {\n    const mountStyle = (): void => {\n      const clsPrefix = clsPrefixRef?.value\n      style.mount({\n        id: clsPrefix === undefined ? mountId : clsPrefix + mountId,\n        head: true,\n        props: {\n          bPrefix: clsPrefix ? `.${clsPrefix}-` : undefined\n        },\n        anchorMetaName: cssrAnchorMetaName,\n        ssr: ssrAdapter,\n        parent: NConfigProvider?.styleMountTarget\n      })\n      if (!NConfigProvider?.preflightStyleDisabled) {\n        globalStyle.mount({\n          id: 'n-global',\n          head: true,\n          anchorMetaName: cssrAnchorMetaName,\n          ssr: ssrAdapter,\n          parent: NConfigProvider?.styleMountTarget\n        })\n      }\n    }\n    if (ssrAdapter) {\n      mountStyle()\n    }\n    else {\n      onBeforeMount(mountStyle)\n    }\n  }\n  const mergedThemeRef = computed(() => {\n    // keep props to make theme overrideable\n    const {\n      theme: { common: selfCommon, self, peers = {} } = {},\n      themeOverrides: selfOverrides = {} as ExtractThemeOverrides<\n        Theme<N, T, R>\n      >,\n      builtinThemeOverrides: builtinOverrides = {} as ExtractThemeOverrides<\n        Theme<N, T, R>\n      >\n    } = props\n    const { common: selfCommonOverrides, peers: peersOverrides } = selfOverrides\n    const {\n      common: globalCommon = undefined,\n      [resolveId]: {\n        common: globalSelfCommon = undefined,\n        self: globalSelf = undefined,\n        peers: globalPeers = {}\n      } = {}\n    } = NConfigProvider?.mergedThemeRef.value || {}\n    const {\n      common: globalCommonOverrides = undefined,\n      [resolveId]: globalSelfOverrides = {}\n    } = NConfigProvider?.mergedThemeOverridesRef.value || {}\n    const {\n      common: globalSelfCommonOverrides,\n      peers: globalPeersOverrides = {}\n    } = globalSelfOverrides\n    const mergedCommon = merge(\n      {},\n      selfCommon || globalSelfCommon || globalCommon || defaultTheme.common,\n      globalCommonOverrides,\n      globalSelfCommonOverrides,\n      selfCommonOverrides\n    )\n    const mergedSelf = merge(\n      // {}, executed every time, no need for empty obj\n      (self || globalSelf || defaultTheme.self)?.(mergedCommon) as T,\n      builtinOverrides,\n      globalSelfOverrides,\n      selfOverrides\n    )\n    return {\n      common: mergedCommon,\n      self: mergedSelf,\n      peers: merge({}, defaultTheme.peers, globalPeers, peers),\n      peerOverrides: merge(\n        {},\n        builtinOverrides.peers,\n        globalPeersOverrides,\n        peersOverrides\n      )\n    }\n  })\n  return mergedThemeRef\n}\n\nuseTheme.props = {\n  theme: Object,\n  themeOverrides: Object,\n  builtinThemeOverrides: Object\n} as const\n\n/**\n * props.theme (Theme):\n * {\n *   common: CommonThemeVars,\n *   self(): ThemeVars,\n *   peers: { Component: Theme }\n * }\n * provider.theme:\n * {\n *   common: CommonThemeVars,\n *   Button: Theme\n *   ...\n * }\n * defaultTheme:\n * {\n *   common: CommonThemeVars,\n *   self(): ThemeVars,\n *   peers: { Component: Theme }\n * }\n *\n * props.themeOverrides (ThemeOverrides):\n * {\n *   common: CommonThemeVars,\n *   peers: { Component: ThemeOverrides },\n *   ...ThemeVars\n * }\n * provider.themeOverrides:\n * {\n *   common: CommonThemeVars,\n *   Component: ThemeOverrides\n *   ...\n * }\n *\n * mergedTheme:\n * {\n *   common: CommonThemeVars,\n *   self: ThemeVars,\n *   peers: { Component: Theme },\n *   overrides: { Component: ThemeOverrides }\n * }\n */\nexport default useTheme\n"
  },
  {
    "path": "src/_styles/common/_common.ts",
    "content": "export default {\n  fontFamily:\n    'v-sans, system-ui, -apple-system, BlinkMacSystemFont, \"Segoe UI\", sans-serif, \"Apple Color Emoji\", \"Segoe UI Emoji\", \"Segoe UI Symbol\"',\n  fontFamilyMono: 'v-mono, SFMono-Regular, Menlo, Consolas, Courier, monospace',\n\n  fontWeight: '400',\n  fontWeightStrong: '500',\n\n  cubicBezierEaseInOut: 'cubic-bezier(.4, 0, .2, 1)',\n  cubicBezierEaseOut: 'cubic-bezier(0, 0, .2, 1)',\n  cubicBezierEaseIn: 'cubic-bezier(.4, 0, 1, 1)',\n\n  borderRadius: '3px',\n  borderRadiusSmall: '2px',\n\n  fontSize: '14px',\n  fontSizeMini: '12px',\n  fontSizeTiny: '12px',\n  fontSizeSmall: '14px',\n  fontSizeMedium: '14px',\n  fontSizeLarge: '15px',\n  fontSizeHuge: '16px',\n\n  lineHeight: '1.6',\n\n  heightMini: '16px', // private now, it's too small\n  heightTiny: '22px',\n  heightSmall: '28px',\n  heightMedium: '34px',\n  heightLarge: '40px',\n  heightHuge: '46px'\n}\n"
  },
  {
    "path": "src/_styles/common/dark.ts",
    "content": "import type { ThemeCommonVars } from './light'\nimport { composite, rgba, scaleColor } from 'seemly'\nimport commonVariables from './_common'\n\nconst base = {\n  neutralBase: '#000',\n  neutralInvertBase: '#fff',\n  neutralTextBase: '#fff',\n  neutralPopover: 'rgb(72, 72, 78)',\n  neutralCard: 'rgb(24, 24, 28)',\n  neutralModal: 'rgb(44, 44, 50)',\n  neutralBody: 'rgb(16, 16, 20)',\n\n  alpha1: '0.9',\n  alpha2: '0.82',\n  alpha3: '0.52',\n  alpha4: '0.38',\n  alpha5: '0.28',\n\n  alphaClose: '0.52',\n\n  alphaDisabled: '0.38',\n  alphaDisabledInput: '0.06',\n  alphaPending: '0.09',\n  alphaTablePending: '0.06',\n  alphaTableStriped: '0.05',\n  alphaPressed: '0.05',\n\n  alphaAvatar: '0.18',\n  alphaRail: '0.2',\n  alphaProgressRail: '0.12',\n  alphaBorder: '0.24',\n  alphaDivider: '0.09',\n  alphaInput: '0.1',\n  alphaAction: '0.06',\n  alphaTab: '0.04',\n  alphaScrollbar: '0.2',\n  alphaScrollbarHover: '0.3',\n  alphaCode: '0.12',\n  alphaTag: '0.2',\n\n  // primary\n  primaryHover: '#7fe7c4',\n  primaryDefault: '#63e2b7',\n  primaryActive: '#5acea7',\n  primarySuppl: 'rgb(42, 148, 125)',\n\n  // info\n  infoHover: '#8acbec',\n  infoDefault: '#70c0e8',\n  infoActive: '#66afd3',\n  infoSuppl: 'rgb(56, 137, 197)',\n\n  // error\n  errorHover: '#e98b8b',\n  errorDefault: '#e88080',\n  errorActive: '#e57272',\n  errorSuppl: 'rgb(208, 58, 82)',\n\n  // warning\n  warningHover: '#f5d599',\n  warningDefault: '#f2c97d',\n  warningActive: '#e6c260',\n  warningSuppl: 'rgb(240, 138, 0)',\n\n  // success\n  successHover: '#7fe7c4',\n  successDefault: '#63e2b7',\n  successActive: '#5acea7',\n  successSuppl: 'rgb(42, 148, 125)'\n}\n\nconst baseBackgroundRgb = rgba(base.neutralBase)\nconst baseInvertBackgroundRgb = rgba(base.neutralInvertBase)\nconst overlayPrefix = `rgba(${baseInvertBackgroundRgb.slice(0, 3).join(', ')}, `\nfunction overlay(alpha: number | string): string {\n  return `${overlayPrefix + String(alpha)})`\n}\nfunction neutral(alpha: number | string): string {\n  const overlayRgba = Array.from(baseInvertBackgroundRgb)\n  overlayRgba[3] = Number(alpha)\n  return composite(\n    baseBackgroundRgb,\n    overlayRgba as [number, number, number, number]\n  )\n}\nconst derived: ThemeCommonVars = {\n  name: 'common' as const,\n\n  ...commonVariables,\n\n  baseColor: base.neutralBase,\n\n  // primary color\n  primaryColor: base.primaryDefault,\n  primaryColorHover: base.primaryHover,\n  primaryColorPressed: base.primaryActive,\n  primaryColorSuppl: base.primarySuppl,\n  // info color\n  infoColor: base.infoDefault,\n  infoColorHover: base.infoHover,\n  infoColorPressed: base.infoActive,\n  infoColorSuppl: base.infoSuppl,\n  // success color\n  successColor: base.successDefault,\n  successColorHover: base.successHover,\n  successColorPressed: base.successActive,\n  successColorSuppl: base.successSuppl,\n  // warning color\n  warningColor: base.warningDefault,\n  warningColorHover: base.warningHover,\n  warningColorPressed: base.warningActive,\n  warningColorSuppl: base.warningSuppl,\n  // error color\n  errorColor: base.errorDefault,\n  errorColorHover: base.errorHover,\n  errorColorPressed: base.errorActive,\n  errorColorSuppl: base.errorSuppl,\n  // text color\n  textColorBase: base.neutralTextBase,\n  textColor1: overlay(base.alpha1),\n  textColor2: overlay(base.alpha2),\n  textColor3: overlay(base.alpha3),\n  // textColor4: overlay(base.alpha4), // disabled, placeholder, icon\n  // textColor5: overlay(base.alpha5),\n\n  textColorDisabled: overlay(base.alpha4),\n  placeholderColor: overlay(base.alpha4),\n  placeholderColorDisabled: overlay(base.alpha5),\n  iconColor: overlay(base.alpha4),\n  iconColorDisabled: overlay(base.alpha5),\n  iconColorHover: overlay(Number(base.alpha4) * 1.25),\n  iconColorPressed: overlay(Number(base.alpha4) * 0.8),\n\n  opacity1: base.alpha1,\n  opacity2: base.alpha2,\n  opacity3: base.alpha3,\n  opacity4: base.alpha4,\n  opacity5: base.alpha5,\n\n  dividerColor: overlay(base.alphaDivider),\n  borderColor: overlay(base.alphaBorder),\n\n  // close\n  closeIconColorHover: overlay(Number(base.alphaClose)),\n  closeIconColor: overlay(Number(base.alphaClose)),\n  closeIconColorPressed: overlay(Number(base.alphaClose)),\n  closeColorHover: 'rgba(255, 255, 255, .12)',\n  closeColorPressed: 'rgba(255, 255, 255, .08)',\n\n  // clear\n  clearColor: overlay(base.alpha4),\n  clearColorHover: scaleColor(overlay(base.alpha4), { alpha: 1.25 }),\n  clearColorPressed: scaleColor(overlay(base.alpha4), { alpha: 0.8 }),\n\n  scrollbarColor: overlay(base.alphaScrollbar),\n  scrollbarColorHover: overlay(base.alphaScrollbarHover),\n  scrollbarWidth: '5px',\n  scrollbarHeight: '5px',\n  scrollbarBorderRadius: '5px',\n\n  progressRailColor: overlay(base.alphaProgressRail),\n  railColor: overlay(base.alphaRail),\n\n  popoverColor: base.neutralPopover,\n  tableColor: base.neutralCard,\n  cardColor: base.neutralCard,\n  modalColor: base.neutralModal,\n  bodyColor: base.neutralBody,\n  tagColor: neutral(base.alphaTag),\n  avatarColor: overlay(base.alphaAvatar),\n  invertedColor: base.neutralBase,\n\n  inputColor: overlay(base.alphaInput),\n  codeColor: overlay(base.alphaCode),\n  tabColor: overlay(base.alphaTab),\n  actionColor: overlay(base.alphaAction),\n  tableHeaderColor: overlay(base.alphaAction),\n\n  hoverColor: overlay(base.alphaPending),\n  tableColorHover: overlay(base.alphaTablePending),\n  tableColorStriped: overlay(base.alphaTableStriped),\n  pressedColor: overlay(base.alphaPressed),\n\n  opacityDisabled: base.alphaDisabled,\n  inputColorDisabled: overlay(base.alphaDisabledInput),\n\n  buttonColor2: 'rgba(255, 255, 255, .08)',\n  buttonColor2Hover: 'rgba(255, 255, 255, .12)',\n  buttonColor2Pressed: 'rgba(255, 255, 255, .08)',\n\n  boxShadow1:\n    '0 1px 2px -2px rgba(0, 0, 0, .24), 0 3px 6px 0 rgba(0, 0, 0, .18), 0 5px 12px 4px rgba(0, 0, 0, .12)',\n  boxShadow2:\n    '0 3px 6px -4px rgba(0, 0, 0, .24), 0 6px 12px 0 rgba(0, 0, 0, .16), 0 9px 18px 8px rgba(0, 0, 0, .10)',\n  boxShadow3:\n    '0 6px 16px -9px rgba(0, 0, 0, .08), 0 9px 28px 0 rgba(0, 0, 0, .05), 0 12px 48px 16px rgba(0, 0, 0, .03)'\n}\n\nexport default derived\n"
  },
  {
    "path": "src/_styles/common/index.ts",
    "content": "export { default as commonDark } from './dark'\nexport { default as commonLight } from './light'\nexport type { ThemeCommonVars } from './light'\n"
  },
  {
    "path": "src/_styles/common/light.ts",
    "content": "import { composite, rgba, scaleColor } from 'seemly'\nimport commonVariables from './_common'\n\nconst base = {\n  neutralBase: '#FFF',\n  neutralInvertBase: '#000',\n  neutralTextBase: '#000',\n  neutralPopover: '#fff',\n  neutralCard: '#fff',\n  neutralModal: '#fff',\n  neutralBody: '#fff',\n\n  alpha1: '0.82',\n  alpha2: '0.72',\n  alpha3: '0.38',\n  alpha4: '0.24', // disabled text, placeholder, icon\n  alpha5: '0.18', // disabled placeholder\n\n  alphaClose: '0.6',\n\n  alphaDisabled: '0.5',\n  alphaDisabledInput: '0.02',\n  alphaPending: '0.05',\n  alphaTablePending: '0.02',\n  alphaPressed: '0.07',\n\n  alphaAvatar: '0.2',\n  alphaRail: '0.14',\n  alphaProgressRail: '.08',\n  alphaBorder: '0.12',\n  alphaDivider: '0.06',\n  alphaInput: '0',\n  alphaAction: '0.02',\n  alphaTab: '0.04',\n  alphaScrollbar: '0.25',\n  alphaScrollbarHover: '0.4',\n  alphaCode: '0.05',\n  alphaTag: '0.02',\n\n  // primary\n  primaryHover: '#36ad6a',\n  primaryDefault: '#18a058',\n  primaryActive: '#0c7a43',\n  primarySuppl: '#36ad6a',\n\n  // info\n  infoHover: '#4098fc',\n  infoDefault: '#2080f0',\n  infoActive: '#1060c9',\n  infoSuppl: '#4098fc',\n\n  // error\n  errorHover: '#de576d',\n  errorDefault: '#d03050',\n  errorActive: '#ab1f3f',\n  errorSuppl: '#de576d',\n\n  // warning\n  warningHover: '#fcb040',\n  warningDefault: '#f0a020',\n  warningActive: '#c97c10',\n  warningSuppl: '#fcb040',\n\n  // success\n  successHover: '#36ad6a',\n  successDefault: '#18a058',\n  successActive: '#0c7a43',\n  successSuppl: '#36ad6a'\n}\n\nconst baseBackgroundRgb = rgba(base.neutralBase)\nconst baseInvertBackgroundRgb = rgba(base.neutralInvertBase)\nconst overlayPrefix = `rgba(${baseInvertBackgroundRgb.slice(0, 3).join(', ')}, `\nfunction overlay(alpha: string | number) {\n  return `${overlayPrefix + String(alpha)})`\n}\nfunction neutral(alpha: string | number) {\n  const overlayRgba = Array.from(baseInvertBackgroundRgb)\n  overlayRgba[3] = Number(alpha)\n  return composite(\n    baseBackgroundRgb,\n    overlayRgba as [number, number, number, number]\n  )\n}\nconst derived = {\n  name: 'common' as const,\n\n  ...commonVariables,\n\n  baseColor: base.neutralBase,\n\n  // primary color\n  primaryColor: base.primaryDefault,\n  primaryColorHover: base.primaryHover,\n  primaryColorPressed: base.primaryActive,\n  primaryColorSuppl: base.primarySuppl,\n  // info color\n  infoColor: base.infoDefault,\n  infoColorHover: base.infoHover,\n  infoColorPressed: base.infoActive,\n  infoColorSuppl: base.infoSuppl,\n  // success color\n  successColor: base.successDefault,\n  successColorHover: base.successHover,\n  successColorPressed: base.successActive,\n  successColorSuppl: base.successSuppl,\n  // warning color\n  warningColor: base.warningDefault,\n  warningColorHover: base.warningHover,\n  warningColorPressed: base.warningActive,\n  warningColorSuppl: base.warningSuppl,\n  // error color\n  errorColor: base.errorDefault,\n  errorColorHover: base.errorHover,\n  errorColorPressed: base.errorActive,\n  errorColorSuppl: base.errorSuppl,\n  // text color\n  textColorBase: base.neutralTextBase,\n  textColor1: 'rgb(31, 34, 37)',\n  textColor2: 'rgb(51, 54, 57)',\n  textColor3: 'rgb(118, 124, 130)',\n  // textColor4: neutral(base.alpha4), // disabled, placeholder, icon\n  // textColor5: neutral(base.alpha5),\n\n  textColorDisabled: neutral(base.alpha4),\n  placeholderColor: neutral(base.alpha4),\n  placeholderColorDisabled: neutral(base.alpha5),\n  iconColor: neutral(base.alpha4),\n  iconColorHover: scaleColor(neutral(base.alpha4), { lightness: 0.75 }),\n  iconColorPressed: scaleColor(neutral(base.alpha4), { lightness: 0.9 }),\n  iconColorDisabled: neutral(base.alpha5),\n\n  opacity1: base.alpha1,\n  opacity2: base.alpha2,\n  opacity3: base.alpha3,\n  opacity4: base.alpha4,\n  opacity5: base.alpha5,\n\n  dividerColor: 'rgb(239, 239, 245)',\n  borderColor: 'rgb(224, 224, 230)',\n\n  // close\n  closeIconColor: neutral(Number(base.alphaClose)),\n  closeIconColorHover: neutral(Number(base.alphaClose)),\n  closeIconColorPressed: neutral(Number(base.alphaClose)),\n  closeColorHover: 'rgba(0, 0, 0, .09)',\n  closeColorPressed: 'rgba(0, 0, 0, .13)',\n\n  // clear\n  clearColor: neutral(base.alpha4),\n  clearColorHover: scaleColor(neutral(base.alpha4), { lightness: 0.75 }),\n  clearColorPressed: scaleColor(neutral(base.alpha4), { lightness: 0.9 }),\n\n  scrollbarColor: overlay(base.alphaScrollbar),\n  scrollbarColorHover: overlay(base.alphaScrollbarHover),\n  scrollbarWidth: '5px',\n  scrollbarHeight: '5px',\n  scrollbarBorderRadius: '5px',\n\n  progressRailColor: neutral(base.alphaProgressRail),\n  railColor: 'rgb(219, 219, 223)',\n\n  popoverColor: base.neutralPopover,\n  tableColor: base.neutralCard,\n  cardColor: base.neutralCard,\n  modalColor: base.neutralModal,\n  bodyColor: base.neutralBody,\n  tagColor: '#eee',\n  avatarColor: neutral(base.alphaAvatar),\n  invertedColor: 'rgb(0, 20, 40)',\n\n  inputColor: neutral(base.alphaInput),\n  codeColor: 'rgb(244, 244, 248)',\n  tabColor: 'rgb(247, 247, 250)',\n  actionColor: 'rgb(250, 250, 252)',\n  tableHeaderColor: 'rgb(250, 250, 252)',\n\n  hoverColor: 'rgb(243, 243, 245)',\n  // use color with alpha since it can be nested with header filter & sorter effect\n  tableColorHover: 'rgba(0, 0, 100, 0.03)',\n  tableColorStriped: 'rgba(0, 0, 100, 0.02)',\n  pressedColor: 'rgb(237, 237, 239)',\n\n  opacityDisabled: base.alphaDisabled,\n  inputColorDisabled: 'rgb(250, 250, 252)',\n\n  // secondary button color\n  // can also be used in tertiary button & quaternary button\n  buttonColor2: 'rgba(46, 51, 56, .05)',\n  buttonColor2Hover: 'rgba(46, 51, 56, .09)',\n  buttonColor2Pressed: 'rgba(46, 51, 56, .13)',\n\n  boxShadow1:\n    '0 1px 2px -2px rgba(0, 0, 0, .08), 0 3px 6px 0 rgba(0, 0, 0, .06), 0 5px 12px 4px rgba(0, 0, 0, .04)',\n  boxShadow2:\n    '0 3px 6px -4px rgba(0, 0, 0, .12), 0 6px 16px 0 rgba(0, 0, 0, .08), 0 9px 28px 8px rgba(0, 0, 0, .05)',\n  boxShadow3:\n    '0 6px 16px -9px rgba(0, 0, 0, .08), 0 9px 28px 0 rgba(0, 0, 0, .05), 0 12px 48px 16px rgba(0, 0, 0, .03)'\n}\n\nexport default derived\nexport type ThemeCommonVars = typeof derived\n"
  },
  {
    "path": "src/_styles/global/index.cssr.ts",
    "content": "import { c } from '../../_utils/cssr'\nimport commonVariables from '../common/_common'\n\nconst {\n  fontSize,\n  fontFamily,\n  lineHeight\n} = commonVariables\n\n// All the components need the style\n// It is static and won't be changed in the app's lifetime\n// If user want to overrides it they need to use `n-global-style` is provided\n//\n// Technically we can remove font-size & font-family & line-height to make\n// it pure. However the coding cost doesn't worth it.\n//\n// -webkit-tap-hilight-color:\n// https://developer.mozilla.org/en-US/docs/Web/CSS/-webkit-tap-highlight-color\n// In some android devices, there will be the style.\nexport default c('body', `\n  margin: 0;\n  font-size: ${fontSize};\n  font-family: ${fontFamily};\n  line-height: ${lineHeight};\n  -webkit-text-size-adjust: 100%;\n  -webkit-tap-highlight-color: transparent;\n`, [\n  c('input', `\n    font-family: inherit;\n    font-size: inherit;\n  `)\n])\n"
  },
  {
    "path": "src/_styles/transitions/fade-down.cssr.ts",
    "content": "import type { CNode } from 'css-render'\nimport { c } from '../../_utils/cssr'\nimport commonVariables from '../common/_common'\n\nconst { cubicBezierEaseInOut } = commonVariables\n\ninterface FadeDownTransitionOptions {\n  name?: string\n  fromOffset?: string\n  enterDuration?: string\n  leaveDuration?: string\n  enterCubicBezier?: string\n  leaveCubicBezier?: string\n}\n\nexport function fadeDownTransition({\n  name = 'fade-down',\n  fromOffset = '-4px',\n  enterDuration = '.3s',\n  leaveDuration = '.3s',\n  enterCubicBezier = cubicBezierEaseInOut,\n  leaveCubicBezier = cubicBezierEaseInOut\n}: FadeDownTransitionOptions = {}): CNode[] {\n  return [\n    c(`&.${name}-transition-enter-from, &.${name}-transition-leave-to`, {\n      opacity: 0,\n      transform: `translateY(${fromOffset})`\n    }),\n    c(`&.${name}-transition-enter-to, &.${name}-transition-leave-from`, {\n      opacity: 1,\n      transform: 'translateY(0)'\n    }),\n    c(`&.${name}-transition-leave-active`, {\n      transition: `opacity ${leaveDuration} ${leaveCubicBezier}, transform ${leaveDuration} ${leaveCubicBezier}`\n    }),\n    c(`&.${name}-transition-enter-active`, {\n      transition: `opacity ${enterDuration} ${enterCubicBezier}, transform ${enterDuration} ${enterCubicBezier}`\n    })\n  ]\n}\n"
  },
  {
    "path": "src/_styles/transitions/fade-in-height-expand.cssr.ts",
    "content": "import type { CNode } from 'css-render'\nimport { c } from '../../_utils/cssr'\nimport commonVariables from '../common/_common'\n\nconst {\n  cubicBezierEaseInOut,\n  cubicBezierEaseOut,\n  cubicBezierEaseIn\n} = commonVariables\n\ninterface FadeInHeightExpandTransitionOption {\n  overflow?: string\n  duration?: string\n  originalTransition?: string\n  leavingDelay?: string\n  foldPadding?: boolean\n  enterToProps?: Record<string, string | number> | undefined\n  leaveToProps?: Record<string, string | number> | undefined\n  reverse?: boolean\n}\n\nexport function fadeInHeightExpandTransition({\n  overflow = 'hidden',\n  duration = '.3s',\n  originalTransition = '',\n  leavingDelay = '0s',\n  foldPadding = false,\n  enterToProps = undefined,\n  leaveToProps = undefined,\n  reverse = false\n}: FadeInHeightExpandTransitionOption = {}): CNode[] {\n  const enterClass = reverse ? 'leave' : 'enter'\n  const leaveClass = reverse ? 'enter' : 'leave'\n  return [\n    c(`&.fade-in-height-expand-transition-${leaveClass}-from,\n      &.fade-in-height-expand-transition-${enterClass}-to`, {\n      ...enterToProps,\n      opacity: 1\n    }),\n    c(`&.fade-in-height-expand-transition-${leaveClass}-to,\n      &.fade-in-height-expand-transition-${enterClass}-from`, {\n      ...leaveToProps,\n      opacity: 0,\n      marginTop: '0 !important',\n      marginBottom: '0 !important',\n      paddingTop: foldPadding ? '0 !important' : undefined,\n      paddingBottom: foldPadding ? '0 !important' : undefined\n    }),\n    c(`&.fade-in-height-expand-transition-${leaveClass}-active`, `\n      overflow: ${overflow};\n      transition:\n        max-height ${duration} ${cubicBezierEaseInOut} ${leavingDelay},\n        opacity ${duration} ${cubicBezierEaseOut} ${leavingDelay},\n        margin-top ${duration} ${cubicBezierEaseInOut} ${leavingDelay},\n        margin-bottom ${duration} ${cubicBezierEaseInOut} ${leavingDelay},\n        padding-top ${duration} ${cubicBezierEaseInOut} ${leavingDelay},\n        padding-bottom ${duration} ${cubicBezierEaseInOut} ${leavingDelay}\n        ${originalTransition ? `,${originalTransition}` : ''}\n    `),\n    c(`&.fade-in-height-expand-transition-${enterClass}-active`, `\n      overflow: ${overflow};\n      transition:\n        max-height ${duration} ${cubicBezierEaseInOut},\n        opacity ${duration} ${cubicBezierEaseIn},\n        margin-top ${duration} ${cubicBezierEaseInOut},\n        margin-bottom ${duration} ${cubicBezierEaseInOut},\n        padding-top ${duration} ${cubicBezierEaseInOut},\n        padding-bottom ${duration} ${cubicBezierEaseInOut}\n        ${originalTransition ? `,${originalTransition}` : ''}\n    `)\n  ]\n}\n"
  },
  {
    "path": "src/_styles/transitions/fade-in-scale-up.cssr.ts",
    "content": "import type { CNode } from 'css-render'\nimport { c } from '../../_utils/cssr'\nimport commonVariables from '../common/_common'\n\nconst {\n  cubicBezierEaseIn,\n  cubicBezierEaseOut\n} = commonVariables\n\ninterface FadeInScaleUpTransitionOptions {\n  transformOrigin?: string\n  duration?: string\n  enterScale?: string\n  originalTransform?: string\n  originalTransition?: string\n}\n\nexport function fadeInScaleUpTransition({\n  transformOrigin = 'inherit',\n  duration = '.2s',\n  enterScale = '.9',\n  originalTransform = '',\n  originalTransition = ''\n}: FadeInScaleUpTransitionOptions = {}): CNode[] {\n  return [\n    c('&.fade-in-scale-up-transition-leave-active', {\n      transformOrigin,\n      transition: `opacity ${duration} ${cubicBezierEaseIn}, transform ${duration} ${cubicBezierEaseIn} ${\n        originalTransition && `,${originalTransition}`\n      }`\n    }),\n    c('&.fade-in-scale-up-transition-enter-active', {\n      transformOrigin,\n      transition: `opacity ${duration} ${cubicBezierEaseOut}, transform ${duration} ${cubicBezierEaseOut} ${\n        originalTransition && `,${originalTransition}`\n      }`\n    }),\n    c('&.fade-in-scale-up-transition-enter-from, &.fade-in-scale-up-transition-leave-to', {\n      opacity: 0,\n      transform: `${originalTransform} scale(${enterScale})`\n    }),\n    c('&.fade-in-scale-up-transition-leave-from, &.fade-in-scale-up-transition-enter-to', {\n      opacity: 1,\n      transform: `${originalTransform} scale(1)`\n    })\n  ]\n}\n"
  },
  {
    "path": "src/_styles/transitions/fade-in-width-expand.cssr.ts",
    "content": "import type { CNode } from 'css-render'\nimport { c } from '../../_utils/cssr'\nimport commonVariables from '../common/_common'\n\nconst { cubicBezierEaseInOut } = commonVariables\n\ninterface FadeInWidthExpandTransition {\n  duration?: string\n  delay?: string\n}\n\nexport function fadeInWidthExpandTransition({\n  duration = '.2s',\n  delay = '.1s'\n}: FadeInWidthExpandTransition = {}): CNode[] {\n  return [\n    c('&.fade-in-width-expand-transition-leave-from, &.fade-in-width-expand-transition-enter-to', {\n      opacity: 1\n    }),\n    c('&.fade-in-width-expand-transition-leave-to, &.fade-in-width-expand-transition-enter-from', `\n      opacity: 0!important;\n      margin-left: 0!important;\n      margin-right: 0!important;\n    `),\n    c('&.fade-in-width-expand-transition-leave-active', `\n      overflow: hidden;\n      transition:\n        opacity ${duration} ${cubicBezierEaseInOut},\n        max-width ${duration} ${cubicBezierEaseInOut} ${delay},\n        margin-left ${duration} ${cubicBezierEaseInOut} ${delay},\n        margin-right ${duration} ${cubicBezierEaseInOut} ${delay};\n    `),\n    c('&.fade-in-width-expand-transition-enter-active', `\n      overflow: hidden;\n      transition:\n        opacity ${duration} ${cubicBezierEaseInOut} ${delay},\n        max-width ${duration} ${cubicBezierEaseInOut},\n        margin-left ${duration} ${cubicBezierEaseInOut},\n        margin-right ${duration} ${cubicBezierEaseInOut};\n    `)\n  ]\n}\n"
  },
  {
    "path": "src/_styles/transitions/fade-in.cssr.ts",
    "content": "import type { CNode } from 'css-render'\nimport { c } from '../../_utils/cssr'\nimport commonVariables from '../common/_common'\n\nconst { cubicBezierEaseInOut } = commonVariables\n\ninterface FadeInTransitionOptions {\n  name?: string\n  enterDuration?: string\n  leaveDuration?: string\n  enterCubicBezier?: string\n  leaveCubicBezier?: string\n}\n\nexport function fadeInTransition({\n  name = 'fade-in',\n  enterDuration = '0.2s',\n  leaveDuration = '0.2s',\n  enterCubicBezier = cubicBezierEaseInOut,\n  leaveCubicBezier = cubicBezierEaseInOut\n}: FadeInTransitionOptions = {}): CNode[] {\n  return [\n    c(`&.${name}-transition-enter-active`, {\n      transition: `all ${enterDuration} ${enterCubicBezier}!important`\n    }),\n    c(`&.${name}-transition-leave-active`, {\n      transition: `all ${leaveDuration} ${leaveCubicBezier}!important`\n    }),\n    c(`&.${name}-transition-enter-from, &.${name}-transition-leave-to`, {\n      opacity: 0\n    }),\n    c(`&.${name}-transition-leave-from, &.${name}-transition-enter-to`, {\n      opacity: 1\n    })\n  ]\n}\n"
  },
  {
    "path": "src/_styles/transitions/fade-up-width-expand.cssr.ts",
    "content": "import type { CNode } from 'css-render'\nimport { c } from '../../_utils/cssr'\nimport commonVariables from '../common/_common'\n\nconst { cubicBezierEaseOut } = commonVariables\n\ninterface FadeUpWidthExpandTransition {\n  duration?: string\n}\n\nexport function fadeUpWidthExpandTransition({\n  duration = '.2s'\n}: FadeUpWidthExpandTransition = {}): CNode[] {\n  return [\n    c('&.fade-up-width-expand-transition-leave-active', {\n      transition: `\n        opacity ${duration} ${cubicBezierEaseOut},\n        max-width ${duration} ${cubicBezierEaseOut},\n        transform ${duration} ${cubicBezierEaseOut}\n      `\n    }),\n    c('&.fade-up-width-expand-transition-enter-active', {\n      transition: `\n        opacity ${duration} ${cubicBezierEaseOut},\n        max-width ${duration} ${cubicBezierEaseOut},\n        transform ${duration} ${cubicBezierEaseOut}\n      `\n    }),\n    c('&.fade-up-width-expand-transition-enter-to', {\n      opacity: 1,\n      transform: 'translateX(0) translateY(0)'\n    }),\n    c('&.fade-up-width-expand-transition-enter-from', {\n      maxWidth: '0 !important',\n      opacity: 0,\n      transform: 'translateY(60%)'\n    }),\n    c('&.fade-up-width-expand-transition-leave-from', {\n      opacity: 1,\n      transform: 'translateY(0)'\n    }),\n    c('&.fade-up-width-expand-transition-leave-to', {\n      maxWidth: '0 !important',\n      opacity: 0,\n      transform: 'translateY(60%)'\n    })\n  ]\n}\n"
  },
  {
    "path": "src/_styles/transitions/icon-switch.cssr.ts",
    "content": "import type { CNode } from 'css-render'\nimport { c } from '../../_utils/cssr'\nimport commonVariables from '../common/_common'\n\nconst {\n  cubicBezierEaseInOut\n} = commonVariables\n\ninterface IconSwitchTransitionOptions {\n  originalTransform?: string\n  left?: string | number\n  top?: string | number\n  transition?: string\n}\n\nexport function iconSwitchTransition({\n  originalTransform = '',\n  left = 0,\n  top = 0,\n  transition = `all .3s ${cubicBezierEaseInOut} !important`\n}: IconSwitchTransitionOptions = {}): CNode[] {\n  return [\n    c('&.icon-switch-transition-enter-from, &.icon-switch-transition-leave-to', {\n      transform: `${originalTransform} scale(0.75)`,\n      left,\n      top,\n      opacity: 0\n    }),\n    c('&.icon-switch-transition-enter-to, &.icon-switch-transition-leave-from', {\n      transform: `scale(1) ${originalTransform}`,\n      left,\n      top,\n      opacity: 1\n    }),\n    c('&.icon-switch-transition-enter-active, &.icon-switch-transition-leave-active', {\n      transformOrigin: 'center',\n      position: 'absolute',\n      left,\n      top,\n      transition\n    })\n  ]\n}\n"
  },
  {
    "path": "src/_styles/transitions/slide-in-from-bottom.ts",
    "content": "import type { CNode } from 'css-render'\nimport { c } from '../../_utils/cssr'\nimport commonVariables from '../common/_common'\n\nconst { cubicBezierEaseIn, cubicBezierEaseOut } = commonVariables\n\ninterface SlideInFromBottomTransitionOptions {\n  duration?: string\n  leaveDuration?: string\n  name?: string\n}\n\nexport function slideInFromBottomTransition({\n  duration = '0.3s',\n  leaveDuration = '0.2s',\n  name = 'slide-in-from-bottom'\n}: SlideInFromBottomTransitionOptions = {}): CNode[] {\n  return [\n    c(`&.${name}-transition-leave-active`, {\n      transition: `transform ${leaveDuration} ${cubicBezierEaseIn}`\n    }),\n    c(`&.${name}-transition-enter-active`, {\n      transition: `transform ${duration} ${cubicBezierEaseOut}`\n    }),\n    c(`&.${name}-transition-enter-to`, {\n      transform: 'translateY(0)'\n    }),\n    c(`&.${name}-transition-enter-from`, {\n      transform: 'translateY(100%)'\n    }),\n    c(`&.${name}-transition-leave-from`, {\n      transform: 'translateY(0)'\n    }),\n    c(`&.${name}-transition-leave-to`, {\n      transform: 'translateY(100%)'\n    })\n  ]\n}\n"
  },
  {
    "path": "src/_styles/transitions/slide-in-from-left.ts",
    "content": "import type { CNode } from 'css-render'\nimport { c } from '../../_utils/cssr'\nimport commonVariables from '../common/_common'\n\nconst { cubicBezierEaseIn, cubicBezierEaseOut } = commonVariables\n\ninterface SlideInFromLeftTransitionOptions {\n  duration?: string\n  leaveDuration?: string\n  name?: string\n}\n\nexport function slideInFromLeftTransition({\n  duration = '0.3s',\n  leaveDuration = '0.2s',\n  name = 'slide-in-from-left'\n}: SlideInFromLeftTransitionOptions = {}): CNode[] {\n  return [\n    c(`&.${name}-transition-leave-active`, {\n      transition: `transform ${leaveDuration} ${cubicBezierEaseIn}`\n    }),\n    c(`&.${name}-transition-enter-active`, {\n      transition: `transform ${duration} ${cubicBezierEaseOut}`\n    }),\n    c(`&.${name}-transition-enter-to`, {\n      transform: 'translateX(0)'\n    }),\n    c(`&.${name}-transition-enter-from`, {\n      transform: 'translateX(-100%)'\n    }),\n    c(`&.${name}-transition-leave-from`, {\n      transform: 'translateX(0)'\n    }),\n    c(`&.${name}-transition-leave-to`, {\n      transform: 'translateX(-100%)'\n    })\n  ]\n}\n"
  },
  {
    "path": "src/_styles/transitions/slide-in-from-right.ts",
    "content": "import type { CNode } from 'css-render'\nimport { c } from '../../_utils/cssr'\nimport commonVariables from '../common/_common'\n\nconst { cubicBezierEaseIn, cubicBezierEaseOut } = commonVariables\n\ninterface SlideInFromRightTransitionOptions {\n  duration?: string\n  leaveDuration?: string\n  name?: string\n}\n\nexport function slideInFromRightTransition({\n  duration = '0.3s',\n  leaveDuration = '0.2s',\n  name = 'slide-in-from-right'\n}: SlideInFromRightTransitionOptions = {}): CNode[] {\n  return [\n    c(`&.${name}-transition-leave-active`, {\n      transition: `transform ${leaveDuration} ${cubicBezierEaseIn}`\n    }),\n    c(`&.${name}-transition-enter-active`, {\n      transition: `transform ${duration} ${cubicBezierEaseOut}`\n    }),\n    c(`&.${name}-transition-enter-to`, {\n      transform: 'translateX(0)'\n    }),\n    c(`&.${name}-transition-enter-from`, {\n      transform: 'translateX(100%)'\n    }),\n    c(`&.${name}-transition-leave-from`, {\n      transform: 'translateX(0)'\n    }),\n    c(`&.${name}-transition-leave-to`, {\n      transform: 'translateX(100%)'\n    })\n  ]\n}\n"
  },
  {
    "path": "src/_styles/transitions/slide-in-from-top.ts",
    "content": "import type { CNode } from 'css-render'\nimport { c } from '../../_utils/cssr'\nimport commonVariables from '../common/_common'\n\nconst { cubicBezierEaseIn, cubicBezierEaseOut } = commonVariables\n\ninterface SlideInFromTopTransitionOptions {\n  duration?: string\n  leaveDuration?: string\n  name?: string\n}\n\nexport function slideInFromTopTransition({\n  duration = '0.3s',\n  leaveDuration = '0.2s',\n  name = 'slide-in-from-top'\n}: SlideInFromTopTransitionOptions = {}): CNode[] {\n  return [\n    c(`&.${name}-transition-leave-active`, {\n      transition: `transform ${leaveDuration} ${cubicBezierEaseIn}`\n    }),\n    c(`&.${name}-transition-enter-active`, {\n      transition: `transform ${duration} ${cubicBezierEaseOut}`\n    }),\n    c(`&.${name}-transition-enter-to`, {\n      transform: 'translateY(0)'\n    }),\n    c(`&.${name}-transition-enter-from`, {\n      transform: 'translateY(-100%)'\n    }),\n    c(`&.${name}-transition-leave-from`, {\n      transform: 'translateY(0)'\n    }),\n    c(`&.${name}-transition-leave-to`, {\n      transform: 'translateY(-100%)'\n    })\n  ]\n}\n"
  },
  {
    "path": "src/_utils/color/index.ts",
    "content": "import { composite } from 'seemly'\n\nexport function createHoverColor(rgb: string): string {\n  return composite(rgb, [255, 255, 255, 0.16])\n}\n\nexport function createPressedColor(rgb: string): string {\n  return composite(rgb, [0, 0, 0, 0.12])\n}\n"
  },
  {
    "path": "src/_utils/composable/index.ts",
    "content": "export { useAdjustedTo } from './use-adjusted-to'\nexport {\n  useInjectionCollection,\n  useInjectionElementCollection,\n  useInjectionInstanceCollection\n} from './use-collection'\nexport { useDeferredTrue } from './use-deferred-true'\nexport { useHoudini } from './use-houdini'\nexport { useIsComposing } from './use-is-composing'\nexport {\n  lockHtmlScrollRightCompensationRef,\n  useLockHtmlScroll\n} from './use-lock-html-scroll'\nexport { useReactivated } from './use-reactivated'\nexport { useOnResize } from './use-resize'\n"
  },
  {
    "path": "src/_utils/composable/use-adjusted-to.ts",
    "content": "import type { ComponentPublicInstance, ComputedRef, PropType } from 'vue'\nimport { off, on } from 'evtd'\nimport { useMemo } from 'vooks'\nimport { inject, onBeforeUnmount, onMounted, ref } from 'vue'\nimport { internalSelectionMenuBodyInjectionKey } from '../../_internal/select-menu/src/interface'\nimport { drawerBodyInjectionKey } from '../../drawer/src/interface'\nimport { modalBodyInjectionKey } from '../../modal/src/interface'\nimport { popoverBodyInjectionKey } from '../../popover/src/interface'\n\ninterface UseAdjustedToProps {\n  to?: string | HTMLElement | boolean\n  [key: string]: unknown\n}\n\nconst teleportDisabled = '__disabled__'\nfunction useAdjustedTo(\n  props: UseAdjustedToProps\n): ComputedRef<HTMLElement | string> {\n  const modal = inject(modalBodyInjectionKey, null)\n  const drawer = inject(drawerBodyInjectionKey, null)\n  const popover = inject(popoverBodyInjectionKey, null)\n  const selectMenu = inject(internalSelectionMenuBodyInjectionKey, null)\n\n  const fullscreenElementRef = ref<null | Element>()\n  if (typeof document !== 'undefined') {\n    fullscreenElementRef.value = document.fullscreenElement\n    const handleFullscreenChange = (): void => {\n      fullscreenElementRef.value = document.fullscreenElement\n    }\n    onMounted(() => {\n      on('fullscreenchange', document, handleFullscreenChange)\n    })\n    onBeforeUnmount(() => {\n      off('fullscreenchange', document, handleFullscreenChange)\n    })\n  }\n\n  return useMemo(() => {\n    const { to } = props\n    if (to !== undefined) {\n      if (to === false)\n        return teleportDisabled\n      if (to === true)\n        return fullscreenElementRef.value || 'body'\n      return to\n    }\n    if (modal?.value) {\n      return (modal.value as ComponentPublicInstance).$el ?? modal.value\n    }\n    if (drawer?.value)\n      return drawer.value\n    if (popover?.value)\n      return popover.value\n    if (selectMenu?.value)\n      return selectMenu.value\n    return to ?? (fullscreenElementRef.value || 'body')\n  })\n}\n\n// teleport disabled key\nuseAdjustedTo.tdkey = teleportDisabled\nuseAdjustedTo.propTo = {\n  type: [String, Object, Boolean] as PropType<HTMLElement | string | boolean>,\n  default: undefined\n}\n\nexport { useAdjustedTo }\n"
  },
  {
    "path": "src/_utils/composable/use-browser-location.ts",
    "content": "import type { Ref } from 'vue'\nimport { onMounted, onUnmounted, ref } from 'vue'\nimport { isBrowser } from '../env/is-browser'\n\nexport interface IWindowLocation {\n  hash?: string\n  host?: string\n  hostname?: string\n  href?: string\n  origin?: string\n  pathname?: string\n  port?: string\n  protocol?: string\n  search?: string\n}\n\nexport function useBrowserLocation(\n  customWindow = isBrowser ? window : null\n): Ref<IWindowLocation> {\n  const getWindowLocation = (): IWindowLocation => {\n    const {\n      hash,\n      host,\n      hostname,\n      href,\n      origin,\n      pathname,\n      port,\n      protocol,\n      search\n    } = customWindow?.location || {}\n\n    return {\n      hash,\n      host,\n      hostname,\n      href,\n      origin,\n      pathname,\n      port,\n      protocol,\n      search\n    }\n  }\n\n  const locationState = ref(getWindowLocation())\n\n  const updateLocation = (): void => {\n    locationState.value = getWindowLocation()\n  }\n\n  onMounted(() => {\n    if (customWindow) {\n      customWindow.addEventListener('popstate', updateLocation)\n      customWindow.addEventListener('hashchange', updateLocation)\n    }\n  })\n\n  onUnmounted(() => {\n    if (customWindow) {\n      customWindow.removeEventListener('popstate', updateLocation)\n      customWindow.removeEventListener('hashchange', updateLocation)\n    }\n  })\n\n  return locationState\n}\n"
  },
  {
    "path": "src/_utils/composable/use-collection.ts",
    "content": "import type { InjectionKey, Ref } from 'vue'\nimport {\n  getCurrentInstance,\n  inject,\n  onBeforeUnmount,\n  onMounted,\n  watch\n} from 'vue'\n\n// injection.collection {\n//   key1: [insta, instb]\n//   key2: [instc]\n// }\nexport function useInjectionInstanceCollection(\n  injectionName: string | InjectionKey<unknown>,\n  collectionKey: string,\n  registerKeyRef: Ref<string | undefined>\n): void {\n  const injection = inject<Record<string, Record<string, any>> | null>(\n    injectionName,\n    null\n  )\n  if (injection === null)\n    return\n  const vm = getCurrentInstance()?.proxy\n  watch(registerKeyRef, registerInstance)\n  registerInstance(registerKeyRef.value)\n  onBeforeUnmount(() => {\n    registerInstance(undefined, registerKeyRef.value)\n  })\n  function registerInstance(key?: string, oldKey?: string): void {\n    if (!injection)\n      return\n    const collection = injection[collectionKey]\n    if (oldKey !== undefined)\n      removeInstance(collection, oldKey)\n    if (key !== undefined)\n      addInstance(collection, key)\n  }\n  function removeInstance(\n    collection: Record<string, any[]>,\n    key: string\n  ): void {\n    if (!collection[key])\n      collection[key] = []\n    collection[key].splice(\n      collection[key].findIndex(instance => instance === vm),\n      1\n    )\n  }\n  function addInstance(collection: Record<string, any[]>, key: string): void {\n    if (!collection[key])\n      collection[key] = []\n    if (!~collection[key].findIndex(instance => instance === vm)) {\n      collection[key].push(vm)\n    }\n  }\n}\n\n// injection.collection {\n//   key1: [insta.value, instb.value]\n//   key2: [instc.value]\n// }\nexport function useInjectionCollection(\n  injectionName: string | InjectionKey<unknown>,\n  collectionKey: string,\n  valueRef: Ref<any>\n): void {\n  const injection = inject<Record<any, any[]> | null>(injectionName, null)\n  if (injection === null)\n    return\n  if (!(collectionKey in injection)) {\n    injection[collectionKey] = []\n  }\n  injection[collectionKey].push(valueRef.value)\n  watch(valueRef, (value, prevValue) => {\n    const collectionArray = injection[collectionKey]\n    const index = collectionArray.findIndex(\n      collectionValue => collectionValue === prevValue\n    )\n    if (~index)\n      collectionArray.splice(index, 1)\n    collectionArray.push(value)\n  })\n  onBeforeUnmount(() => {\n    const collectionArray = injection[collectionKey]\n    const index = collectionArray.findIndex(\n      collectionValue => collectionValue === valueRef.value\n    )\n    if (~index)\n      collectionArray.splice(index, 1)\n  })\n}\n\n// injection.collection {\n//   key1: [insta.$el, instb.$el]\n//   key2: [instc.$el]\n// }\nexport function useInjectionElementCollection(\n  injectionName: string | InjectionKey<unknown>,\n  collectionKey: string,\n  getElement: () => HTMLElement | null\n): void {\n  const injection = inject<Record<string, HTMLElement[]> | null>(\n    injectionName,\n    null\n  )\n  if (injection === null)\n    return\n  if (!(collectionKey in injection)) {\n    injection[collectionKey] = []\n  }\n  onMounted(() => {\n    const el = getElement()\n    if (!el)\n      return\n    injection[collectionKey].push(el)\n  })\n  onBeforeUnmount(() => {\n    const collectionArray = injection[collectionKey]\n    const element = getElement()\n    const index = collectionArray.findIndex(\n      collectionElement => collectionElement === element\n    )\n    if (~index)\n      collectionArray.splice(index, 1)\n  })\n}\n"
  },
  {
    "path": "src/_utils/composable/use-deferred-true.ts",
    "content": "import type { Ref } from 'vue'\nimport { ref, watch } from 'vue'\n\nexport function useDeferredTrue(\n  valueRef: Ref<any>,\n  delay: number,\n  shouldDelayRef: Ref<boolean>\n): Ref<boolean> {\n  if (!delay)\n    return valueRef\n  const delayedRef = ref(valueRef.value)\n  let timerId: number | null = null\n  watch(valueRef, (value) => {\n    if (timerId !== null)\n      window.clearTimeout(timerId)\n    if (value === true) {\n      if (shouldDelayRef && !shouldDelayRef.value) {\n        delayedRef.value = true\n      }\n      else {\n        timerId = window.setTimeout(() => {\n          delayedRef.value = true\n        }, delay)\n      }\n    }\n    else {\n      delayedRef.value = false\n    }\n  })\n  return delayedRef\n}\n"
  },
  {
    "path": "src/_utils/composable/use-houdini.ts",
    "content": "import { isBrowser } from '../env/is-browser'\n\nlet houdiniRegistered = false\n\nexport function useHoudini(): void {\n  if (!isBrowser)\n    return\n  if (!window.CSS)\n    return\n  if (!houdiniRegistered) {\n    houdiniRegistered = true\n    if ('registerProperty' in window?.CSS) {\n      try {\n        ;(CSS as any).registerProperty({\n          name: '--n-color-start',\n          syntax: '<color>',\n          inherits: false,\n          initialValue: '#0000'\n        })\n        ;(CSS as any).registerProperty({\n          name: '--n-color-end',\n          syntax: '<color>',\n          inherits: false,\n          initialValue: '#0000'\n        })\n      }\n      catch {}\n    }\n  }\n}\n"
  },
  {
    "path": "src/_utils/composable/use-is-composing.ts",
    "content": "import type { Ref } from 'vue'\nimport { onBeforeMount, onBeforeUnmount, ref } from 'vue'\nimport { isBrowser } from '../env/is-browser'\n\nconst isComposingRef = ref(false)\nfunction compositionStartHandler(): void {\n  isComposingRef.value = true\n}\nfunction compositionEndHandler(): void {\n  isComposingRef.value = false\n}\nlet mountedCount = 0\n\nexport function useIsComposing(): Ref<boolean> {\n  if (isBrowser) {\n    onBeforeMount(() => {\n      if (!mountedCount) {\n        window.addEventListener('compositionstart', compositionStartHandler)\n        window.addEventListener('compositionend', compositionEndHandler)\n      }\n      mountedCount++\n    })\n    onBeforeUnmount(() => {\n      if (mountedCount <= 1) {\n        window.removeEventListener('compositionstart', compositionStartHandler)\n        window.removeEventListener('compositionend', compositionEndHandler)\n        mountedCount = 0\n      }\n      else {\n        mountedCount--\n      }\n    })\n  }\n  return isComposingRef\n}\n"
  },
  {
    "path": "src/_utils/composable/use-lock-html-scroll.ts",
    "content": "import type { Ref, WatchStopHandle } from 'vue'\nimport { onBeforeUnmount, onMounted, ref, watch } from 'vue'\n\nlet lockCount = 0\nlet originalMarginRight: string = ''\nlet originalOverflow: string = ''\nlet originalOverflowX: string = ''\nlet originalOverflowY: string = ''\nexport const lockHtmlScrollRightCompensationRef = ref('0px')\n\nexport function useLockHtmlScroll(lockRef: Ref<boolean>): void {\n  // not browser\n  if (typeof document === 'undefined')\n    return\n  const el = document.documentElement\n  let watchStopHandle: WatchStopHandle | undefined\n  let activated = false\n  const unlock = (): void => {\n    el.style.marginRight = originalMarginRight\n    el.style.overflow = originalOverflow\n    el.style.overflowX = originalOverflowX\n    el.style.overflowY = originalOverflowY\n    lockHtmlScrollRightCompensationRef.value = '0px'\n  }\n  onMounted(() => {\n    watchStopHandle = watch(\n      lockRef,\n      (value) => {\n        if (value) {\n          if (!lockCount) {\n            const scrollbarWidth = window.innerWidth - el.offsetWidth\n            if (scrollbarWidth > 0) {\n              originalMarginRight = el.style.marginRight\n              el.style.marginRight = `${scrollbarWidth}px`\n              lockHtmlScrollRightCompensationRef.value = `${scrollbarWidth}px`\n            }\n            originalOverflow = el.style.overflow\n            originalOverflowX = el.style.overflowX\n            originalOverflowY = el.style.overflowY\n            el.style.overflow = 'hidden'\n            el.style.overflowX = 'hidden'\n            el.style.overflowY = 'hidden'\n          }\n          activated = true\n          lockCount++\n        }\n        else {\n          lockCount--\n          if (!lockCount) {\n            unlock()\n          }\n          activated = false\n        }\n      },\n      {\n        immediate: true\n      }\n    )\n  })\n  onBeforeUnmount(() => {\n    watchStopHandle?.()\n    if (activated) {\n      lockCount--\n      if (!lockCount) {\n        unlock()\n      }\n      activated = false\n    }\n  })\n}\n"
  },
  {
    "path": "src/_utils/composable/use-reactivated.ts",
    "content": "import { onActivated, onDeactivated } from 'vue'\n\nexport function useReactivated(callback: () => void): {\n  isDeactivated: boolean\n} {\n  const isDeactivatedRef = { isDeactivated: false }\n  let activateStateInitialized = false\n  onActivated(() => {\n    isDeactivatedRef.isDeactivated = false\n    if (!activateStateInitialized) {\n      activateStateInitialized = true\n      return\n    }\n    callback()\n  })\n  onDeactivated(() => {\n    isDeactivatedRef.isDeactivated = true\n    if (!activateStateInitialized) {\n      activateStateInitialized = true\n    }\n  })\n  return isDeactivatedRef\n}\n"
  },
  {
    "path": "src/_utils/composable/use-resize.ts",
    "content": "import type { Ref } from 'vue'\nimport { onBeforeUnmount, onMounted, watch } from 'vue'\nimport { resizeObserverManager } from 'vueuc'\n\nexport function useOnResize(\n  elRef: Ref<HTMLElement | null>,\n  onResize: (() => void) | undefined\n): void {\n  // it needn't be reactive since it's for internal usage\n  if (onResize) {\n    onMounted(() => {\n      const { value: el } = elRef\n      if (el) {\n        resizeObserverManager.registerHandler(el, onResize)\n      }\n    })\n\n    // avoid memory leak\n    watch(\n      elRef,\n      (_, oldEl) => {\n        if (oldEl) {\n          resizeObserverManager.unregisterHandler(oldEl)\n        }\n      },\n      {\n        deep: false\n      }\n    )\n\n    onBeforeUnmount(() => {\n      const { value: el } = elRef\n      if (el) {\n        resizeObserverManager.unregisterHandler(el)\n      }\n    })\n  }\n}\n"
  },
  {
    "path": "src/_utils/css/color-to-class.ts",
    "content": "export function color2Class(color: string): string {\n  return color.replace(/#|\\(|\\)|,|\\s|\\./g, '_')\n}\n"
  },
  {
    "path": "src/_utils/css/format-length.ts",
    "content": "const pureNumberRegex = /^(\\d|\\.)+$/\nconst numberRegex = /(\\d|\\.)+/\n\ninterface FormatLengthOptions {\n  c?: number\n  offset?: number\n  attachPx?: boolean\n}\n\nexport function formatLength<\n  T extends number | string | null | undefined | any\n>(\n  length: T,\n  { c = 1, offset = 0, attachPx = true }: FormatLengthOptions = {}\n): T extends null\n  ? null\n  : T extends undefined\n    ? undefined\n    : T extends string | number\n      ? string\n      : T {\n  if (typeof length === 'number') {\n    const result = (length + offset) * c\n    if (result === 0)\n      return '0' as any\n    return `${result}px` as any\n  }\n  else if (typeof length === 'string') {\n    if (pureNumberRegex.test(length)) {\n      const result = (Number(length) + offset) * c\n      if (attachPx) {\n        if (result === 0)\n          return '0' as any\n        return `${result}px` as any\n      }\n      else {\n        return `${result}` as any\n      }\n    }\n    else {\n      const result = numberRegex.exec(length)\n      if (!result)\n        return length as any\n      return length.replace(\n        numberRegex,\n        String((Number(result[0]) + offset) * c)\n      ) as any\n    }\n  }\n  return length as any\n}\n"
  },
  {
    "path": "src/_utils/css/index.ts",
    "content": "export { color2Class } from './color-to-class'\nexport { formatLength } from './format-length'\nexport { rtlInset } from './rtl-inset'\n"
  },
  {
    "path": "src/_utils/css/rtl-inset.ts",
    "content": "import { getPadding } from 'seemly'\n\nexport function rtlInset(inset: string): string {\n  const { left, right, top, bottom } = getPadding(inset)\n  return `${top} ${left} ${bottom} ${right}`\n}\n"
  },
  {
    "path": "src/_utils/cssr/index.ts",
    "content": "import type { CNode, CProperties } from 'css-render'\nimport { plugin as BemPlugin } from '@css-render/plugin-bem'\nimport { CssRender } from 'css-render'\n\nconst namespace = 'n'\nconst prefix = `.${namespace}-`\nconst elementPrefix = '__'\nconst modifierPrefix = '--'\n\nconst cssr = CssRender()\nconst plugin = BemPlugin({\n  blockPrefix: prefix,\n  elementPrefix,\n  modifierPrefix\n})\ncssr.use(plugin)\nconst { c, find } = cssr\nconst { cB, cE, cM, cNotM } = plugin\n\nfunction insideModal(style: CNode): CNode {\n  return c(\n    ({ props: { bPrefix } }) =>\n      `${bPrefix || prefix}modal, ${bPrefix || prefix}drawer`,\n    [style]\n  )\n}\n\nfunction insidePopover(style: CNode): CNode {\n  return c(({ props: { bPrefix } }) => `${bPrefix || prefix}popover`, [style])\n}\n\nfunction asModal(style: CProperties): CNode {\n  return c(({ props: { bPrefix } }) => `&${bPrefix || prefix}modal`, style)\n}\n\n// child block\nconst cCB: typeof cB = ((...args: any[]) => {\n  return c('>', [(cB as any)(...args)])\n}) as any\n\nfunction createKey<P extends string, S extends string>(\n  prefix: P,\n  suffix: S\n): S extends 'default' ? P : `${P}${Capitalize<S>}` {\n  return (prefix\n    + (suffix === 'default'\n      ? ''\n      : suffix.replace(/^[a-z]/, startChar =>\n          startChar.toUpperCase()))) as any\n}\n\nexport {\n  asModal,\n  c,\n  cB,\n  cCB,\n  cE,\n  cM,\n  cNotM,\n  createKey,\n  find,\n  insideModal,\n  insidePopover,\n  namespace,\n  prefix\n}\n"
  },
  {
    "path": "src/_utils/dom/download.ts",
    "content": "export function download(url: string | null, name: string | undefined): void {\n  if (!url)\n    return\n  const a = document.createElement('a')\n  a.href = url\n  if (name !== undefined) {\n    a.download = name\n  }\n  document.body.appendChild(a)\n  a.click()\n  document.body.removeChild(a)\n}\n\nexport function publicDownload(url: string, name: string | undefined): void {\n  download(url, name)\n}\n"
  },
  {
    "path": "src/_utils/dom/index.ts",
    "content": "export { download } from './download'\nexport { isDocument } from './is-document'\n"
  },
  {
    "path": "src/_utils/dom/is-document.ts",
    "content": "export function isDocument(node: Node): node is Document {\n  return node.nodeName === '#document'\n}\n"
  },
  {
    "path": "src/_utils/env/browser.ts",
    "content": "import { isBrowser } from './is-browser'\n\nexport const isChrome = isBrowser && 'chrome' in window\nexport const isFirefox = isBrowser && navigator.userAgent.includes('Firefox')\nexport const isSafari\n  = isBrowser && navigator.userAgent.includes('Safari') && !isChrome\n"
  },
  {
    "path": "src/_utils/env/is-browser.ts",
    "content": "export const isBrowser\n  = typeof document !== 'undefined' && typeof window !== 'undefined'\n"
  },
  {
    "path": "src/_utils/env/is-jsdom.ts",
    "content": "let _isJsdom: boolean | undefined\n\nexport function isJsdom(): boolean {\n  if (_isJsdom === undefined) {\n    _isJsdom\n      = navigator.userAgent.includes('Node.js')\n        || navigator.userAgent.includes('jsdom')\n  }\n  return _isJsdom\n}\n"
  },
  {
    "path": "src/_utils/env/is-native-lazy-load.ts",
    "content": "import { isBrowser } from './is-browser'\n\nexport const isImageSupportNativeLazy\n  = isBrowser && 'loading' in document.createElement('img')\n"
  },
  {
    "path": "src/_utils/event/index.ts",
    "content": "const eventSet = new WeakSet<Event>()\n\nexport function markEventEffectPerformed(event: Event): void {\n  eventSet.add(event)\n}\n\nexport function eventEffectNotPerformed(event: Event): boolean {\n  return !eventSet.has(event)\n}\n"
  },
  {
    "path": "src/_utils/index.ts",
    "content": "export * from './composable'\nexport { color2Class, formatLength, rtlInset } from './css'\nexport { createKey } from './cssr'\nexport * from './dom'\nexport { isBrowser } from './env/is-browser'\nexport { isJsdom } from './env/is-jsdom'\nexport { eventEffectNotPerformed, markEventEffectPerformed } from './event'\nexport {\n  getTitleAttribute,\n  isArrayShallowEqual,\n  largerSize,\n  smallerSize,\n  throwError,\n  warn,\n  warnOnce\n} from './naive'\nexport type {\n  ExtractInternalPropTypes,\n  ExtractPublicPropTypes,\n  Mutable\n} from './naive'\nexport type * from './ts/ts'\nexport {\n  call,\n  createDataKey,\n  createInjectionKey,\n  createRefSetter,\n  flatten,\n  getFirstSlotVNode,\n  getFirstSlotVNodeWithTypedProps,\n  getSlot,\n  getVNodeChildren,\n  isNodeVShowFalse,\n  isSlotEmpty,\n  keep,\n  keysOf,\n  mergeEventHandlers,\n  omit,\n  render,\n  resolveSlot,\n  resolveSlotWithTypedProps,\n  resolveWrappedSlot,\n  resolveWrappedSlotWithProps,\n  Wrapper\n} from './vue'\nexport type { MaybeArray } from './vue'\n"
  },
  {
    "path": "src/_utils/naive/attribute.ts",
    "content": "import type { HTMLAttributes } from 'vue'\n\nexport function getTitleAttribute(value: unknown): HTMLAttributes['title'] {\n  switch (typeof value) {\n    case 'string':\n      // The empty string should also be reset to undefined.\n      return value || undefined\n    case 'number':\n      return String(value)\n    default:\n      return undefined\n  }\n}\n"
  },
  {
    "path": "src/_utils/naive/extract-public-props.ts",
    "content": "import type { ExtractPropTypes } from 'vue'\nimport type { useTheme } from '../../_mixins'\n\ntype themePropKeys = keyof typeof useTheme.props\n\ntype RemoveReadonly<T> = {\n  -readonly [key in keyof T]: T[key]\n}\n\nexport type ExtractPublicPropTypes<T> = Omit<\n  Partial<RemoveReadonly<ExtractPropTypes<T>>>,\n  | Exclude<themePropKeys, 'themeOverrides'>\n  | Extract<keyof T, `internal${string}`>\n>\n\nexport type ExtractInternalPropTypes<T> = Partial<ExtractPropTypes<T>>\n"
  },
  {
    "path": "src/_utils/naive/index.ts",
    "content": "export { getTitleAttribute } from './attribute'\nexport type {\n  ExtractInternalPropTypes,\n  ExtractPublicPropTypes\n} from './extract-public-props'\nexport type { Mutable } from './mutable'\nexport { largerSize, smallerSize } from './prop'\nexport { isArrayShallowEqual } from './value'\nexport { throwError, warn, warnOnce } from './warn'\n"
  },
  {
    "path": "src/_utils/naive/mutable.ts",
    "content": "export type Mutable<T>\n  = T extends Record<string, unknown>\n    ? {\n        -readonly [P in keyof T]: T[P] extends ReadonlyArray<infer U>\n          ? Array<Mutable<U>>\n          : Mutable<T[P]>\n      }\n    : T\n"
  },
  {
    "path": "src/_utils/naive/prop.ts",
    "content": "const smallerSizeMap = {\n  tiny: 'mini',\n  small: 'tiny',\n  medium: 'small',\n  large: 'medium',\n  huge: 'large'\n} as const\n\nconst largerSizeMap = {\n  tiny: 'small',\n  small: 'medium',\n  medium: 'large',\n  large: 'huge'\n} as const\n\ntype SmallerSizeMap = typeof smallerSizeMap\ntype SmallerSize = keyof SmallerSizeMap\n\ntype LargerSizeMap = typeof largerSizeMap\ntype LargerSize = keyof LargerSizeMap\n\nexport function largerSize<T extends LargerSize>(size: T): LargerSizeMap[T] {\n  const result = largerSizeMap[size]\n\n  if (result === undefined) {\n    throw new Error(`${size} has no larger size.`)\n  }\n\n  return result\n}\n\nexport function smallerSize<T extends SmallerSize>(size: T): SmallerSizeMap[T] {\n  const result = smallerSizeMap[size]\n\n  if (result === undefined) {\n    throw new Error(`${size} has no smaller size.`)\n  }\n\n  return result\n}\n"
  },
  {
    "path": "src/_utils/naive/value.ts",
    "content": "export function isArrayShallowEqual<T extends Array<any>>(\n  array1: T | null,\n  array2: T | null\n): boolean {\n  if (array1 === null && array2 === null)\n    return true\n  if (array1 === null || array2 === null)\n    return false\n  if (array1.length === array2.length) {\n    for (let i = 0; i < array1.length; ++i) {\n      if (array1[i] !== array2[i]) {\n        return false\n      }\n    }\n    return true\n  }\n  return false\n}\n"
  },
  {
    "path": "src/_utils/naive/warn.ts",
    "content": "const warnedMessages = new Set()\n\nexport function warnOnce(location: string, message: string): void {\n  const mergedMessage = `[naive/${location}]: ${message}`\n  if (warnedMessages.has(mergedMessage))\n    return\n  warnedMessages.add(mergedMessage)\n  console.error(mergedMessage)\n}\n\nexport function warn(location: string, message: string): void {\n  console.error(`[naive/${location}]: ${message}`)\n}\n\nexport function error(location: string, message: string, error: unknown): void {\n  console.error(`[naive/${location}]: ${message}`, error)\n}\n\nexport function throwError(location: string, message: string): never {\n  throw new Error(`[naive/${location}]: ${message}`)\n}\n"
  },
  {
    "path": "src/_utils/tests/index.spec.ts",
    "content": "import type { VNode } from 'vue'\nimport { h, isVNode } from 'vue'\nimport { createHoverColor, createPressedColor } from '../color'\nimport {\n  call,\n  createDataKey,\n  formatLength,\n  getTitleAttribute,\n  keep,\n  keysOf,\n  largerSize,\n  omit,\n  render,\n  smallerSize\n} from '../index'\n\ndescribe('color', () => {\n  it('should work with createHoverColor', () => {\n    expect(createHoverColor('#666666')).toBe('rgba(126, 126, 126, 1)')\n    expect(createHoverColor('rgb(42, 148, 125)')).toBe('rgba(76, 165, 146, 1)')\n  })\n\n  it('should work with createPressedColor', () => {\n    expect(createPressedColor('#666666')).toBe('rgba(90, 90, 90, 1)')\n    expect(createPressedColor('rgb(42, 148, 125)')).toBe(\n      'rgba(37, 130, 110, 1)'\n    )\n  })\n})\n\ndescribe('css', () => {\n  it('should work with formatLength', () => {\n    expect(formatLength(7)).toBe('7px')\n    expect(formatLength(2, { offset: 3 })).toBe('5px')\n    expect(formatLength(3, { offset: 4, c: 2 })).toBe('14px')\n    expect(formatLength('3')).toBe('3px')\n    expect(formatLength('3', { attachPx: false })).toBe('3')\n    expect(formatLength('2', { offset: 3 })).toBe('5px')\n    expect(formatLength('3', { offset: 4, c: 2 })).toBe('14px')\n    expect(formatLength('4px')).toBe('4px')\n    expect(formatLength('2px', { offset: 3 })).toBe('5px')\n    expect(formatLength('3px', { offset: 4, c: 2 })).toBe('14px')\n  })\n})\n\ndescribe('naive', () => {\n  it('should work with getTitleAttribute', () => {\n    expect(getTitleAttribute(7)).toBe('7')\n    expect(getTitleAttribute('test')).toBe('test')\n    expect(getTitleAttribute([])).toBe(undefined)\n    expect(getTitleAttribute({})).toBe(undefined)\n    expect(getTitleAttribute(() => '')).toBe(undefined)\n  })\n\n  it('should work with largerSize', () => {\n    expect(largerSize('tiny')).toBe('small')\n    expect(largerSize('small')).toBe('medium')\n    expect(largerSize('medium')).toBe('large')\n    expect(largerSize('large')).toBe('huge')\n  })\n\n  it('should work with smallerSize', () => {\n    expect(smallerSize('huge')).toBe('large')\n    expect(smallerSize('large')).toBe('medium')\n    expect(smallerSize('medium')).toBe('small')\n    expect(smallerSize('small')).toBe('tiny')\n  })\n})\n\ndescribe('vue', () => {\n  it('should work with call', () => {\n    let testValue = 0\n    let testValue2 = 0\n    function testFunction1(): void {\n      testValue = testValue + 1\n    }\n    function testFunction2(v: number): void {\n      testValue = testValue + v + 2\n    }\n    function testFunction3(v: number): void {\n      testValue2 = testValue2 + v + 3\n    }\n    call(testFunction1)\n    expect(testValue).toBe(1)\n    testValue = 0\n    call(testFunction2, 1)\n    expect(testValue).toBe(3)\n    testValue = 0\n    call([testFunction2, testFunction3], 1)\n    expect(testValue).toBe(3)\n    expect(testValue2).toBe(4)\n  })\n\n  it('should work with createDataKey', () => {\n    expect(createDataKey('1')).toBe('s-1')\n    expect(createDataKey(1)).toBe('n-1')\n  })\n\n  it('should work with keep', () => {\n    const test = { c: 3 }\n    const test2 = { a: 1, b: 2, d: test }\n    expect(JSON.stringify(keep(test, ['c']))).toBe(JSON.stringify({ c: 3 }))\n    expect(JSON.stringify(keep(test2, ['a', 'b', 'd']))).toBe(\n      JSON.stringify({ a: 1, b: 2, d: { c: 3 } })\n    )\n    expect(JSON.stringify(keep(test2, ['a', 'b', 'd'], { a: 4, e: 5 }))).toBe(\n      JSON.stringify({ a: 4, b: 2, d: { c: 3 }, e: 5 })\n    )\n  })\n\n  it('should work with keysOf', () => {\n    const test = { c: 3 }\n    const test2 = { a: 1, b: 2, d: test }\n    expect(keysOf(test).toString()).toBe(['c'].toString())\n    expect(keysOf(test2).toString()).toBe(['a', 'b', 'd'].toString())\n  })\n\n  it('should work with omit', () => {\n    const test = { c: 3 }\n    const test2 = { a: 1, b: 2, d: test }\n\n    expect(JSON.stringify(omit(test2, ['a']))).toBe(\n      JSON.stringify({ b: 2, d: { c: 3 } })\n    )\n    expect(JSON.stringify(omit(test2, ['a', 'd']))).toBe(\n      JSON.stringify({ b: 2 })\n    )\n    expect(JSON.stringify(omit(test2, ['b'], { a: 4, b: 5 }))).toBe(\n      JSON.stringify({ a: 4, d: { c: 3 }, b: 5 })\n    )\n  })\n\n  it('should work with render', () => {\n    function testFunction(value: string): VNode {\n      return h(value, null, { default: () => 'test' })\n    }\n    expect(isVNode(render('test'))).toBe(true)\n    expect(isVNode(render(123))).toBe(true)\n    expect(isVNode(render(testFunction, 'div'))).toBe(true)\n    expect(isVNode(render({ a: 1 }))).toBe(false)\n    expect(render({ a: 1 })).toBe(null)\n    expect(isVNode(render(['1']))).toBe(false)\n    expect(render(['1'])).toBe(null)\n  })\n})\n"
  },
  {
    "path": "src/_utils/ts/ts.ts",
    "content": "export type ThemeRelatedProps\n  = | 'theme'\n    | 'themeOverrides'\n    | 'builtinThemeOverrides'\nexport type Equal<X, Y>\n  = (<T>() => T extends X ? 1 : 2) extends <T>() => T extends Y ? 1 : 2\n    ? true\n    : false\nexport type Expect<T extends true> = T\n"
  },
  {
    "path": "src/_utils/vue/call.ts",
    "content": "type AnyFunction = (...args: any[]) => any\n\nfunction call(funcs: MaybeArray<() => void>): void\nfunction call<A1>(funcs: MaybeArray<(a1: A1) => void>, a1: A1): void\nfunction call<A1, A2>(\n  funcs: MaybeArray<(a1: A1, a2: A2) => void>,\n  a1: A1,\n  a2: A2\n): void\nfunction call<A1, A2, A3>(\n  funcs: MaybeArray<(a1: A1, a2: A2, a3: A3) => void>,\n  a1: A1,\n  a2: A2,\n  a3: A3\n): void\nfunction call<A1, A2, A3, A4>(\n  funcs: MaybeArray<(a1: A1, a2: A2, a3: A3, a4: A4) => void>,\n  a1: A1,\n  a2: A2,\n  a3: A3,\n  a4: A4\n): void\nfunction call<A extends any[]>(\n  funcs: AnyFunction[] | AnyFunction,\n  ...args: A\n): void {\n  if (Array.isArray(funcs)) {\n    funcs.forEach(func => (call as any)(func, ...args))\n  }\n  else {\n    return funcs(...args)\n  }\n}\n\nexport { call }\n\nexport type MaybeArray<T> = T | T[]\n"
  },
  {
    "path": "src/_utils/vue/create-data-key.ts",
    "content": "export function createDataKey(key: string | number): string {\n  return typeof key === 'string' ? `s-${key}` : `n-${key}`\n}\n"
  },
  {
    "path": "src/_utils/vue/create-injection-key.ts",
    "content": "import type { InjectionKey } from 'vue'\n\nexport function createInjectionKey<T>(key: string): InjectionKey<T> {\n  return key as any\n}\n"
  },
  {
    "path": "src/_utils/vue/create-ref-setter.ts",
    "content": "import type { Ref } from 'vue'\n\nexport function createRefSetter(ref: Ref<HTMLElement | null>): any {\n  return (inst: { $el: HTMLElement | null } | null) => {\n    if (inst) {\n      ref.value = inst.$el\n    }\n    else {\n      ref.value = null\n    }\n  }\n}\n"
  },
  {
    "path": "src/_utils/vue/flatten.ts",
    "content": "import type { VNode, VNodeChild } from 'vue'\nimport { Comment, createTextVNode, Fragment } from 'vue'\n\n// o(n) flatten\nexport function flatten(\n  vNodes: VNodeChild[],\n  filterCommentNode: boolean = true,\n  result: VNode[] = []\n): VNode[] {\n  vNodes.forEach((vNode) => {\n    if (vNode === null)\n      return\n    if (typeof vNode !== 'object') {\n      if (typeof vNode === 'string' || typeof vNode === 'number') {\n        result.push(createTextVNode(String(vNode)))\n      }\n      return\n    }\n    if (Array.isArray(vNode)) {\n      flatten(vNode, filterCommentNode, result)\n      return\n    }\n    if (vNode.type === Fragment) {\n      if (vNode.children === null)\n        return\n      if (Array.isArray(vNode.children)) {\n        flatten(vNode.children, filterCommentNode, result)\n      }\n      // rawSlot\n    }\n    else {\n      if (vNode.type === Comment && filterCommentNode)\n        return\n      result.push(vNode)\n    }\n  })\n  return result\n}\n"
  },
  {
    "path": "src/_utils/vue/get-first-slot-vnode.ts",
    "content": "import type { Slots, VNode } from 'vue'\nimport { warn } from '../naive'\nimport { flatten } from './flatten'\n\nexport function getFirstSlotVNode(\n  slots: Slots,\n  slotName = 'default',\n  props: unknown = undefined\n): VNode | null {\n  const slot = slots[slotName]\n  if (!slot) {\n    warn('getFirstSlotVNode', `slot[${slotName}] is empty`)\n    return null\n  }\n  const slotContent = flatten(slot(props))\n  // vue will normalize the slot, so slot must be an array\n  if (slotContent.length === 1) {\n    return slotContent[0]\n  }\n  else {\n    warn('getFirstSlotVNode', `slot[${slotName}] should have exactly one child`)\n    return null\n  }\n}\n\nexport function getFirstSlotVNodeWithTypedProps<T>(\n  slotName: string,\n  slot: ((props: T) => VNode[]) | undefined,\n  props: T\n): VNode | null {\n  if (!slot) {\n    return null\n  }\n  const slotContent = flatten(slot(props))\n  // vue will normalize the slot, so slot must be an array\n  if (slotContent.length === 1) {\n    return slotContent[0]\n  }\n  else {\n    warn('getFirstSlotVNode', `slot[${slotName}] should have exactly one child`)\n    return null\n  }\n}\n"
  },
  {
    "path": "src/_utils/vue/get-slot.ts",
    "content": "import type { ComponentPublicInstance, VNodeChild } from 'vue'\n\nexport function getSlot(\n  instance: ComponentPublicInstance,\n  slotName = 'default',\n  fallback: VNodeChild[] = []\n): VNodeChild[] {\n  const slots = instance.$slots\n  const slot = slots[slotName]\n  if (slot === undefined)\n    return fallback\n  return slot()\n}\n"
  },
  {
    "path": "src/_utils/vue/get-v-node-children.ts",
    "content": "import type { VNode } from 'vue'\n\nexport function getVNodeChildren(\n  vNode: VNode,\n  slotName = 'default',\n  fallback: VNode[] = []\n): VNode[] {\n  const { children } = vNode\n  if (\n    children !== null\n    && typeof children === 'object'\n    && !Array.isArray(children)\n  ) {\n    const slot = children[slotName]\n    if (typeof slot === 'function') {\n      return slot()\n    }\n  }\n  return fallback\n}\n"
  },
  {
    "path": "src/_utils/vue/index.ts",
    "content": "export { call } from './call'\nexport type { MaybeArray } from './call'\nexport { createDataKey } from './create-data-key'\nexport { createInjectionKey } from './create-injection-key'\nexport { createRefSetter } from './create-ref-setter'\nexport { flatten } from './flatten'\nexport {\n  getFirstSlotVNode,\n  getFirstSlotVNodeWithTypedProps\n} from './get-first-slot-vnode'\nexport { getSlot } from './get-slot'\nexport { getVNodeChildren } from './get-v-node-children'\nexport { isNodeVShowFalse } from './is-node-v-show-false'\nexport { keep } from './keep'\nexport { keysOf } from './keysOf'\nexport { mergeEventHandlers } from './merge-handlers'\nexport { omit } from './omit'\nexport { render } from './render'\nexport {\n  isSlotEmpty,\n  resolveSlot,\n  resolveSlotWithTypedProps,\n  resolveWrappedSlot,\n  resolveWrappedSlotWithProps\n} from './resolve-slot'\nexport { Wrapper } from './wrapper'\n"
  },
  {
    "path": "src/_utils/vue/is-node-v-show-false.ts",
    "content": "import type { VNode } from 'vue'\nimport { vShow } from 'vue'\n\nexport function isNodeVShowFalse(vNode: VNode): boolean {\n  const showDir = vNode.dirs?.find(({ dir }) => dir === vShow)\n  return !!(showDir && showDir.value === false)\n}\n"
  },
  {
    "path": "src/_utils/vue/keep.ts",
    "content": "export function keep<T, K, R>(\n  object: T,\n  keys: K[] = [],\n  rest?: R\n): Pick<T, K & keyof T> & R {\n  const keepedObject: any = {}\n  keys.forEach((key) => {\n    keepedObject[key] = (object as any)[key]\n  })\n  return Object.assign(keepedObject, rest)\n}\n"
  },
  {
    "path": "src/_utils/vue/keysOf.ts",
    "content": "export function keysOf<T extends Record<string, unknown>>(\n  obj: T\n): Array<keyof T> {\n  return Object.keys(obj) as any\n}\n"
  },
  {
    "path": "src/_utils/vue/merge-handlers.ts",
    "content": "export function mergeEventHandlers<T>(\n  handlers: Array<undefined | ((e: T) => void)>\n): undefined | ((e: T) => void) {\n  const filteredHandlers = handlers.filter(handler => handler !== undefined)\n  if (filteredHandlers.length === 0)\n    return undefined\n  if (filteredHandlers.length === 1)\n    return filteredHandlers[0]\n  return (e) => {\n    handlers.forEach((handler) => {\n      if (handler) {\n        handler(e)\n      }\n    })\n  }\n}\n"
  },
  {
    "path": "src/_utils/vue/omit.ts",
    "content": "export function omit<T, K extends keyof T, R extends Record<string, any>>(\n  object: T,\n  keys: K[] = [],\n  rest?: R\n): Omit<T, K> & (R extends undefined ? Record<string, unknown> : R) {\n  const omitedObject: any = {}\n  const originalKeys = Object.getOwnPropertyNames(object)\n  originalKeys.forEach((originalKey) => {\n    if (!(keys as string[]).includes(originalKey)) {\n      omitedObject[originalKey] = object[originalKey as keyof T]\n    }\n  })\n  return Object.assign(omitedObject, rest)\n}\n"
  },
  {
    "path": "src/_utils/vue/render.ts",
    "content": "import type { VNodeChild } from 'vue'\nimport { createTextVNode } from 'vue'\n\nexport function render<T extends any[]>(\n  r:\n    | string\n    | number\n    | undefined\n    | null\n    | ((...args: [...T]) => VNodeChild)\n    | unknown,\n  ...args: [...T]\n): VNodeChild {\n  if (typeof r === 'function') {\n    return r(...args)\n  }\n  else if (typeof r === 'string') {\n    return createTextVNode(r)\n  }\n  else if (typeof r === 'number') {\n    return createTextVNode(String(r))\n  }\n  else {\n    return null\n  }\n}\n"
  },
  {
    "path": "src/_utils/vue/resolve-slot.ts",
    "content": "import type { Slot, VNodeArrayChildren, VNodeChild } from 'vue'\nimport { Comment, Fragment, isVNode } from 'vue'\n\nexport function ensureValidVNode(\n  vnodes: VNodeArrayChildren\n): VNodeArrayChildren | null {\n  return vnodes.some((child) => {\n    if (!isVNode(child)) {\n      return true\n    }\n    if (child.type === Comment) {\n      return false\n    }\n    if (\n      child.type === Fragment\n      && !ensureValidVNode(child.children as VNodeArrayChildren)\n    ) {\n      return false\n    }\n    return true\n  })\n    ? vnodes\n    : null\n}\n\n/**\n * We shouldn't use the following functions with slot flags `_: 1, 2, 3`\n */\nexport function resolveSlot(\n  slot: Slot | undefined,\n  fallback: () => VNodeArrayChildren\n): VNodeArrayChildren {\n  return (slot && ensureValidVNode(slot())) || fallback()\n}\n\nexport function resolveSlotWithTypedProps<T>(\n  slot: Slot<T> | undefined,\n  props: T,\n  fallback: (props: T) => VNodeArrayChildren\n): VNodeArrayChildren {\n  return (slot && ensureValidVNode(slot(props))) || fallback(props)\n}\n\n/**\n * Resolve slot with wrapper if content exists, no fallback\n */\nexport function resolveWrappedSlot(\n  slot: Slot | undefined,\n  wrapper: (children: VNodeArrayChildren | null) => VNodeChild\n): VNodeChild {\n  const children = slot && ensureValidVNode(slot())\n  return wrapper(children || null)\n}\n\n/*\n * Resolve slot with wrapper if content exists, no fallback\n */\nexport function resolveWrappedSlotWithProps(\n  slot: Slot | undefined,\n  props: any,\n  wrapper: (children: VNodeArrayChildren | null) => VNodeChild\n): VNodeChild {\n  const children = slot && ensureValidVNode(slot(props))\n  return wrapper(children || null)\n}\n\nexport function isSlotEmpty(slot: Slot | undefined): boolean {\n  return !(slot && ensureValidVNode(slot()))\n}\n"
  },
  {
    "path": "src/_utils/vue/wrapper.tsx",
    "content": "import { defineComponent } from 'vue'\n\nexport const Wrapper = defineComponent({\n  render() {\n    return this.$slots.default?.()\n  }\n})\n"
  },
  {
    "path": "src/affix/demos/enUS/basic.demo.vue",
    "content": "<markdown>\n# Basic\n\nAffix has `trigger-top`, `top`, `trigger-bottom` and `bottom`. `trigger-top` is top affixing trigger point. `top` is the style `top` value after top affixing is trigger. `trigger-bottom` and `bottom` work in similar way.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst containerRef = ref<HTMLElement | undefined>(undefined)\n</script>\n\n<template>\n  <div ref=\"containerRef\" class=\"container\">\n    <div class=\"padding\" />\n    <div class=\"content\">\n      <n-row>\n        <n-col :span=\"12\">\n          <n-affix :top=\"120\" :trigger-top=\"60\" :listen-to=\"() => containerRef\">\n            <n-tag>Affix Trigger Top 60px</n-tag>\n          </n-affix>\n        </n-col>\n        <n-col :span=\"12\">\n          <n-affix\n            :bottom=\"120\"\n            :trigger-bottom=\"60\"\n            :listen-to=\"() => containerRef\"\n          >\n            <n-tag>Affix Trigger Bottom 60px</n-tag>\n          </n-affix>\n        </n-col>\n      </n-row>\n    </div>\n  </div>\n</template>\n\n<style>\n.container {\n  width: 100%;\n  height: 200px;\n  background-color: rgba(128, 128, 128, 0.3);\n  border-radius: 3px;\n  overflow: auto;\n}\n\n.padding {\n  height: 150px;\n  width: 100%;\n  background-color: rgba(128, 128, 128, 0.15);\n}\n\n.content {\n  height: 600px;\n}\n</style>\n"
  },
  {
    "path": "src/affix/demos/enUS/index.demo-entry.md",
    "content": "# Affix\n\nAffix can make content stick to fixed places when scrolling. It's similar to `position: sticky` but can do more things.\n\n## Demos\n\n```demo\nbasic.vue\nposition.vue\n```\n\n## API\n\n### Affix Props\n\n| Name | Type | Default | Description |\n| --- | --- | --- | --- |\n| bottom | `number` | `undefined` | The css bottom property after trigger bottom affix. (if not set, use `trigger-bottom` prop) |\n| listen-to | `string \\| HTMLElement \\| Document \\| Window \\| (() => HTMLElement)` | `document` | The scrolling element to listen scrolling. |\n| trigger-bottom | `number` | `undefined` | The distance px to bottom of target to trigger bottom affix. (if not set, use `bottom` prop) |\n| trigger-top | `number` | `undefined` | The distance px to top of target to trigger top affix. (if not set, use `top` prop) |\n| position | `'fixed' \\| 'absolute'` | `'fixed'` | CSS position of the affix. |\n| top | `number` | `undefined` | The css top property after trigger top affix. (if not set, use `trigger-top` prop) |\n"
  },
  {
    "path": "src/affix/demos/enUS/position.demo.vue",
    "content": "<markdown>\n# Position\n\nAffix can be `absolute` or `fixed` positioned. You may need some css tricks to make it works as following. By default position is set to `fixed`, because in most cases scrolled element is `document`.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst containerRef = ref<HTMLElement | undefined>(undefined)\n</script>\n\n<template>\n  <div class=\"absolute-anchor-container\">\n    <div ref=\"containerRef\" class=\"container\">\n      <div class=\"padding\" />\n      <div class=\"content\">\n        <div style=\"display: inline-block; width: 50%\">\n          <n-affix\n            :trigger-top=\"50\"\n            position=\"absolute\"\n            :listen-to=\"() => containerRef\"\n          >\n            <n-tag>Affix Trigger Top 50px</n-tag>\n          </n-affix>\n        </div>\n        <div style=\"display: inline-block; width: 50%\">\n          <n-affix\n            :trigger-bottom=\"60\"\n            position=\"absolute\"\n            :listen-to=\"() => containerRef\"\n          >\n            <n-tag>Affix Trigger Bottom 60px</n-tag>\n          </n-affix>\n        </div>\n      </div>\n    </div>\n  </div>\n</template>\n\n<style>\n.absolute-anchor-container {\n  width: 100%;\n  height: 200px;\n  position: relative;\n}\n\n.container {\n  height: 200px;\n  background-color: rgba(128, 128, 128, 0.3);\n  border-radius: 3px;\n  overflow: auto;\n}\n\n.padding {\n  height: 150px;\n  width: 100%;\n  background-color: rgba(128, 128, 128, 0.15);\n}\n\n.content {\n  height: 600px;\n}\n</style>\n"
  },
  {
    "path": "src/affix/demos/zhCN/basic.demo.vue",
    "content": "<markdown>\n# 基础用法\n\nAffix 有 `trigger-top`、`top`、`trigger-bottom` 和 `bottom` 属性。`trigger-top` 是顶部固定的触发距离，`top` 是在触发顶部固定之后 CSS 的 `top` 值。`trigger-bottom` 和 `bottom` 类似。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst containerRef = ref<HTMLElement | undefined>(undefined)\n</script>\n\n<template>\n  <div ref=\"containerRef\" class=\"container\">\n    <div class=\"padding\" />\n    <div class=\"content\">\n      <n-grid :cols=\"2\">\n        <n-gi :span=\"1\">\n          <n-affix :top=\"120\" :trigger-top=\"60\" :listen-to=\"() => containerRef\">\n            <n-tag>顶部触发距离 60px</n-tag>\n          </n-affix>\n        </n-gi>\n        <n-gi :span=\"1\">\n          <n-affix\n            :bottom=\"120\"\n            :trigger-bottom=\"60\"\n            :listen-to=\"() => containerRef\"\n          >\n            <n-tag>底部触发距离 60px</n-tag>\n          </n-affix>\n        </n-gi>\n      </n-grid>\n    </div>\n  </div>\n</template>\n\n<style>\n.container {\n  width: 100%;\n  height: 200px;\n  background-color: rgba(128, 128, 128, 0.3);\n  border-radius: 3px;\n  overflow: auto;\n}\n\n.padding {\n  height: 150px;\n  width: 100%;\n  background-color: rgba(128, 128, 128, 0.15);\n}\n\n.content {\n  height: 600px;\n}\n</style>\n"
  },
  {
    "path": "src/affix/demos/zhCN/index.demo-entry.md",
    "content": "# 固钉 Affix\n\nAffix 可以让内容在页面滚动的时候固定在一个位置，它和 `position: sticky` 有那么点像不过可以做更多事。\n\n## 演示\n\n```demo\nbasic.vue\nposition.vue\n```\n\n## API\n\n### Affix Props\n\n| 名称 | 类型 | 默认值 | 描述 |\n| --- | --- | --- | --- |\n| bottom | `number` | `undefined` | 在触发底部固定后 Affix 的 CSS bottom 属性（如果没设定，会使用 `trigger-bottom` 代替) |\n| listen-to | `string \\| HTMLElement \\| Document \\| Window \\| (() => HTMLElement)` | `document` | 需要监听滚动的元素 |\n| trigger-bottom | `number` | `undefined` | 触发底部固定时，Affix 和目标元素元素的底部距离（如果没设定，会使用 `bottom` 代替) |\n| trigger-top | `number` | `undefined` | 触发顶部固定时，Affix 和目标元素元素的顶部距离（如果没设定，会使用 `top` 代替) |\n| position | `'fixed' \\| 'absolute'` | `'fixed'` | Affix 的 CSS position |\n| top | `number` | `undefined` | 在触发顶部固定后 Affix 的 CSS top 属性（如果没设定，会使用 `trigger-top` 代替) |\n"
  },
  {
    "path": "src/affix/demos/zhCN/position.demo.vue",
    "content": "<markdown>\n# 位置\n\nAffix 可以 `absolute` 或者 `fixed` 定位。你可能还需要写一些额外的 CSS 才能让达到例子的效果。 默认情况下位置是 `fixed`，因为大多数情况下，滚动的元素是 `document`。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst containerRef = ref<HTMLElement | undefined>(undefined)\n</script>\n\n<template>\n  <div class=\"absolute-anchor-container\">\n    <div ref=\"containerRef\" class=\"container\">\n      <div class=\"padding\" />\n      <div class=\"content\">\n        <div style=\"display: inline-block; width: 50%\">\n          <n-affix\n            :trigger-top=\"50\"\n            position=\"absolute\"\n            :listen-to=\"() => containerRef\"\n          >\n            <n-tag>顶部触发距离 50px</n-tag>\n          </n-affix>\n        </div>\n        <div style=\"display: inline-block; width: 50%\">\n          <n-affix\n            :trigger-bottom=\"60\"\n            position=\"absolute\"\n            :listen-to=\"() => containerRef\"\n          >\n            <n-tag>底部触发距离 60px</n-tag>\n          </n-affix>\n        </div>\n      </div>\n    </div>\n  </div>\n</template>\n\n<style>\n.absolute-anchor-container {\n  width: 100%;\n  height: 200px;\n  position: relative;\n}\n\n.container {\n  height: 200px;\n  background-color: rgba(128, 128, 128, 0.3);\n  border-radius: 3px;\n  overflow: auto;\n}\n\n.padding {\n  height: 150px;\n  width: 100%;\n  background-color: rgba(128, 128, 128, 0.15);\n}\n\n.content {\n  height: 600px;\n}\n</style>\n"
  },
  {
    "path": "src/affix/index.ts",
    "content": "export { affixProps, default as NAffix } from './src/Affix'\nexport type { AffixProps } from './src/Affix'\n"
  },
  {
    "path": "src/affix/src/Affix.tsx",
    "content": "import type { CSSProperties, PropType } from 'vue'\nimport type { ExtractPublicPropTypes } from '../../_utils'\nimport type { ScrollTarget } from './utils'\nimport { beforeNextFrameOnce, unwrapElement } from 'seemly'\nimport {\n  computed,\n  defineComponent,\n  h,\n  onBeforeUnmount,\n  onMounted,\n  ref\n} from 'vue'\nimport { useConfig, useStyle } from '../../_mixins'\nimport { keysOf, warn } from '../../_utils'\nimport style from './styles/index.cssr'\nimport { getRect, getScrollTop } from './utils'\n\nexport const affixProps = {\n  listenTo: [String, Object, Function] as PropType<\n    string | ScrollTarget | (() => HTMLElement) | undefined\n  >,\n  top: Number,\n  bottom: Number,\n  triggerTop: Number,\n  triggerBottom: Number,\n  position: {\n    type: String as PropType<'fixed' | 'absolute'>,\n    default: 'fixed'\n  },\n  // deprecated\n  offsetTop: {\n    type: Number as PropType<number | undefined>,\n    validator: () => {\n      if (__DEV__) {\n        warn(\n          'affix',\n          '`offset-top` is deprecated, please use `trigger-top` instead.'\n        )\n      }\n      return true\n    },\n    default: undefined\n  },\n  offsetBottom: {\n    type: Number as PropType<number | undefined>,\n    validator: () => {\n      if (__DEV__) {\n        warn(\n          'affix',\n          '`offset-bottom` is deprecated, please use `trigger-bottom` instead.'\n        )\n      }\n      return true\n    },\n    default: undefined\n  },\n  target: {\n    type: Function as unknown as PropType<(() => HTMLElement) | undefined>,\n    validator: () => {\n      if (__DEV__) {\n        warn('affix', '`target` is deprecated, please use `listen-to` instead.')\n      }\n      return true\n    },\n    default: undefined\n  }\n} as const\n\nexport const affixPropKeys = keysOf(affixProps)\n\nexport type AffixProps = ExtractPublicPropTypes<typeof affixProps>\n\nexport default defineComponent({\n  name: 'Affix',\n  props: affixProps,\n  setup(props) {\n    const { mergedClsPrefixRef } = useConfig(props)\n    useStyle('-affix', style, mergedClsPrefixRef)\n    let scrollTarget: ScrollTarget | null = null\n    const stickToTopRef = ref(false)\n    const stickToBottomRef = ref(false)\n    const bottomAffixedTriggerScrollTopRef = ref<number | null>(null)\n    const topAffixedTriggerScrollTopRef = ref<number | null>(null)\n    const affixedRef = computed(() => {\n      return stickToBottomRef.value || stickToTopRef.value\n    })\n    const mergedOffsetTopRef = computed(() => {\n      return props.triggerTop ?? props.offsetTop ?? props.top\n    })\n    const mergedTopRef = computed(() => {\n      return props.top ?? props.triggerTop ?? props.offsetTop\n    })\n    const mergedBottomRef = computed(() => {\n      return props.bottom ?? props.triggerBottom ?? props.offsetBottom\n    })\n    const mergedOffsetBottomRef = computed(() => {\n      return props.triggerBottom ?? props.offsetBottom ?? props.bottom\n    })\n    const selfRef = ref<Element | null>(null)\n    const init = (): void => {\n      const { target: getScrollTarget, listenTo } = props\n      if (getScrollTarget) {\n        // deprecated\n        scrollTarget = getScrollTarget()\n      }\n      else if (listenTo) {\n        scrollTarget = unwrapElement(listenTo)\n      }\n      else {\n        scrollTarget = document\n      }\n      if (scrollTarget) {\n        scrollTarget.addEventListener('scroll', handleScroll)\n        handleScroll()\n      }\n      else if (__DEV__) {\n        warn('affix', 'Target to be listened to is not valid.')\n      }\n    }\n    function handleScroll(): void {\n      beforeNextFrameOnce(_handleScroll)\n    }\n\n    function _handleScroll(): void {\n      const { value: selfEl } = selfRef\n      if (!scrollTarget || !selfEl)\n        return\n      const scrollTop = getScrollTop(scrollTarget)\n      if (affixedRef.value) {\n        if (\n          topAffixedTriggerScrollTopRef.value !== null\n          && scrollTop < topAffixedTriggerScrollTopRef.value\n        ) {\n          stickToTopRef.value = false\n          topAffixedTriggerScrollTopRef.value = null\n        }\n        if (\n          bottomAffixedTriggerScrollTopRef.value !== null\n          && scrollTop > bottomAffixedTriggerScrollTopRef.value\n        ) {\n          stickToBottomRef.value = false\n          bottomAffixedTriggerScrollTopRef.value = null\n        }\n        return\n      }\n      const containerRect = getRect(scrollTarget)\n      const affixRect = selfEl.getBoundingClientRect()\n      const pxToTop = affixRect.top - containerRect.top\n      const pxToBottom = containerRect.bottom - affixRect.bottom\n      const mergedOffsetTop = mergedOffsetTopRef.value\n      const mergedOffsetBottom = mergedOffsetBottomRef.value\n      if (mergedOffsetTop !== undefined && pxToTop <= mergedOffsetTop) {\n        stickToTopRef.value = true\n        topAffixedTriggerScrollTopRef.value\n          = scrollTop - (mergedOffsetTop - pxToTop)\n      }\n      else {\n        stickToTopRef.value = false\n        topAffixedTriggerScrollTopRef.value = null\n      }\n      if (\n        mergedOffsetBottom !== undefined\n        && pxToBottom <= mergedOffsetBottom\n      ) {\n        stickToBottomRef.value = true\n        bottomAffixedTriggerScrollTopRef.value\n          = scrollTop + mergedOffsetBottom - pxToBottom\n      }\n      else {\n        stickToBottomRef.value = false\n        bottomAffixedTriggerScrollTopRef.value = null\n      }\n    }\n    onMounted(() => {\n      init()\n    })\n    onBeforeUnmount(() => {\n      if (!scrollTarget)\n        return\n      scrollTarget.removeEventListener('scroll', handleScroll)\n    })\n    return {\n      selfRef,\n      affixed: affixedRef,\n      mergedClsPrefix: mergedClsPrefixRef,\n      mergedstyle: computed<CSSProperties>(() => {\n        const style: CSSProperties = {}\n        if (\n          stickToTopRef.value\n          && mergedOffsetTopRef.value !== undefined\n          && mergedTopRef.value !== undefined\n        ) {\n          style.top = `${mergedTopRef.value}px`\n        }\n        if (\n          stickToBottomRef.value\n          && mergedOffsetBottomRef.value !== undefined\n          && mergedBottomRef.value !== undefined\n        ) {\n          style.bottom = `${mergedBottomRef.value}px`\n        }\n        return style\n      })\n    }\n  },\n  render() {\n    const { mergedClsPrefix } = this\n    return (\n      <div\n        ref=\"selfRef\"\n        class={[\n          `${mergedClsPrefix}-affix`,\n          {\n            [`${mergedClsPrefix}-affix--affixed`]: this.affixed,\n            [`${mergedClsPrefix}-affix--absolute-positioned`]:\n              this.position === 'absolute'\n          }\n        ]}\n        style={this.mergedstyle}\n      >\n        {this.$slots}\n      </div>\n    )\n  }\n})\n"
  },
  {
    "path": "src/affix/src/styles/index.cssr.ts",
    "content": "import { cB, cM } from '../../../_utils/cssr'\n\nexport default cB('affix', [\n  cM('affixed', {\n    position: 'fixed'\n  }, [\n    cM('absolute-positioned', {\n      position: 'absolute'\n    })\n  ])\n])\n"
  },
  {
    "path": "src/affix/src/utils.ts",
    "content": "export type ScrollTarget = Window | Document | HTMLElement\n\nexport function getScrollTop(target: ScrollTarget): number {\n  return target instanceof HTMLElement ? target.scrollTop : window.scrollY\n}\n\nexport function getRect(target: ScrollTarget): { top: number, bottom: number } {\n  return target instanceof HTMLElement\n    ? target.getBoundingClientRect()\n    : { top: 0, bottom: window.innerHeight }\n}\n"
  },
  {
    "path": "src/affix/tests/Affix.spec.ts",
    "content": "import { mount } from '@vue/test-utils'\nimport { sleep } from 'seemly'\nimport { h } from 'vue'\nimport { NAffix } from '../index'\n\nasync function makeScroll(\n  dom: Element,\n  name: 'scrollTop',\n  offset: number\n): Promise<any> {\n  const eventTarget = dom === document.documentElement ? window : dom\n  dom[name] = offset\n  eventTarget.dispatchEvent(\n    new CustomEvent('scroll', {\n      detail: {\n        target: {\n          [name]: offset\n        }\n      }\n    })\n  )\n\n  await sleep(100)\n}\n\ndescribe('n-affix', () => {\n  it('should work with import on demand', () => {\n    mount(NAffix)\n  })\n\n  it('should work with `top` prop', async () => {\n    const wrapper = mount(NAffix, {\n      attachTo: document.body,\n      props: {\n        top: 120\n      },\n      slots: {\n        default: () => {\n          return h('div', {}, 'content')\n        }\n      }\n    })\n\n    expect(wrapper.find('.n-affix--fixed').exists()).toBe(false)\n    await makeScroll(document.documentElement, 'scrollTop', 200)\n    expect(wrapper.attributes('style')).toContain('top: 120px;')\n    wrapper.unmount()\n  })\n\n  it('should work with `position` prop', async () => {\n    const wrapper = mount(NAffix, {\n      props: {\n        position: 'absolute'\n      },\n      slots: {\n        default: () => {\n          return h('div', {}, 'content')\n        }\n      }\n    })\n\n    expect(wrapper.find('.n-affix--absolute-positioned').exists()).not.toBe(\n      null\n    )\n    wrapper.unmount()\n  })\n})\n"
  },
  {
    "path": "src/affix/tests/server.spec.tsx",
    "content": "import { setup } from '@css-render/vue3-ssr'\nimport { renderToString } from '@vue/server-renderer'\n/**\n * @vitest-environment node\n */\nimport { createSSRApp, h } from 'vue'\nimport { NAffix } from '../..'\n\ndescribe('server side rendering', () => {\n  it('works', async () => {\n    const app = createSSRApp(() => <NAffix />)\n    setup(app)\n    try {\n      await renderToString(app)\n    }\n    catch (e) {\n      expect(e).not.toBeTruthy()\n    }\n  })\n})\n"
  },
  {
    "path": "src/alert/demos/enUS/basic.demo.vue",
    "content": "<markdown>\n# Basic\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { IosAirplane } from '@vicons/ionicons4'\n</script>\n\n<template>\n  <n-space vertical :size=\"12\">\n    <n-alert title=\"Default Text\" type=\"default\">\n      <template #icon>\n        <n-icon>\n          <IosAirplane />\n        </n-icon>\n      </template>\n      Gee it's good to be back home\n    </n-alert>\n    <n-alert title=\"Info Text\" type=\"info\">\n      Gee it's good to be back home\n    </n-alert>\n    <n-alert title=\"Success Text\" type=\"success\">\n      Leave it till tomorrow to unpack my case\n    </n-alert>\n    <n-alert title=\"Warning Text\" type=\"warning\">\n      Honey disconnect the phone\n    </n-alert>\n    <n-alert title=\"Error Text\" type=\"error\">\n      I'm back in the U.S.S.R.\n    </n-alert>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/alert/demos/enUS/bordered.demo.vue",
    "content": "<markdown>\n# Bordered\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst bordered = ref(true)\n</script>\n\n<template>\n  <n-space vertical :size=\"12\">\n    <n-switch v-model:value=\"bordered\" />\n    <n-alert title=\"Could be no border\" type=\"info\" :bordered=\"bordered\">\n      Gee it's good to be back home\n    </n-alert>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/alert/demos/enUS/closable.demo.vue",
    "content": "<markdown>\n# Closable\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { IosAirplane } from '@vicons/ionicons4'\n</script>\n\n<template>\n  <n-alert title=\"Default Text\" type=\"default\" closable>\n    <template #icon>\n      <n-icon>\n        <IosAirplane />\n      </n-icon>\n    </template>\n    Gee it's good to be back home\n  </n-alert>\n  <n-alert title=\"Info Text\" type=\"info\" closable>\n    Gee it's good to be back home\n  </n-alert>\n  <n-alert title=\"Success Text\" type=\"success\" closable>\n    Leave it till tomorrow to unpack my case\n  </n-alert>\n  <n-alert title=\"Warning Text\" type=\"warning\" closable>\n    Honey disconnect the phone\n  </n-alert>\n  <n-alert title=\"Error Text\" type=\"error\" closable>\n    I'm back in the U.S.S.R.\n  </n-alert>\n</template>\n\n<style>\n.n-alert:not(:last-child) {\n  margin-bottom: 12px;\n}\n</style>\n"
  },
  {
    "path": "src/alert/demos/enUS/icon.demo.vue",
    "content": "<markdown>\n# Icon\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { IosAirplane } from '@vicons/ionicons4'\n</script>\n\n<template>\n  <n-alert title=\"Back in the U.S.S.R.\">\n    <template #icon>\n      <n-icon>\n        <IosAirplane />\n      </n-icon>\n    </template>\n    Well the Ukraine girls really knock me out<br>\n    They leave the West behind<br>\n    And Moscow girls make me sing and shout<br>\n    That Georgia's always on my mind<br>\n    Aw come on!\n  </n-alert>\n</template>\n"
  },
  {
    "path": "src/alert/demos/enUS/index.demo-entry.md",
    "content": "# Alert\n\nAccording to my experience, the most frequent usage of it may be requesting for disabling AdBlocks.\n\n## Demos\n\n```demo\nbasic.vue\nbordered.vue\nclosable.vue\nicon.vue\nno-icon.vue\nmarquee.vue\n```\n\n## API\n\n### Alert Props\n\n| Name | Type | Default | Description | Version |\n| --- | --- | --- | --- | --- |\n| bordered | `boolean` | `true` | Whether the alert can show border. | 2.32.2 |\n| closable | `boolean` | `false` | Whether the alert can be closed. |  |\n| show-icon | `boolean` | `true` | Whether to show the icon of alert. |  |\n| title | `string` | `undefined` | Title of the alert. |  |\n| type | `'default' \\| 'info' \\| 'success' \\| 'warning' \\| 'error'` | `'default'` | Alert type. |  |\n| on-after-leave | `Function` | `undefined` | Callback function executed when the alert disappears. |  |\n| on-close | `() => boolean \\| Promise<boolean> \\| any` | `() => true` | The callback function executed when the close icon is clicked. |  |\n\n### Alert Slots\n\n| Name    | Parameters | Description                             |\n| ------- | ---------- | --------------------------------------- |\n| default | `()`       | The content of the alert.               |\n| header  | `()`       | The content placed in the alert header. |\n| icon    | `()`       | Icon displayed in the alert.            |\n"
  },
  {
    "path": "src/alert/demos/enUS/marquee.demo.vue",
    "content": "<markdown>\n# Marquee\n\nYou can use `n-marquee` to achieve marquee effect.\n</markdown>\n\n<template>\n  <n-alert type=\"error\" title=\"Warning\">\n    <n-marquee>\n      <div style=\"margin-right: 64px\">\n        Test environment is offline again.\n      </div>\n    </n-marquee>\n  </n-alert>\n</template>\n"
  },
  {
    "path": "src/alert/demos/enUS/no-icon.demo.vue",
    "content": "<markdown>\n# No icon\n</markdown>\n\n<template>\n  <n-alert :show-icon=\"false\">\n    Yeah I'm back in the U.S.S.R.<br>\n    You don't know how lucky you are boys\n  </n-alert>\n</template>\n"
  },
  {
    "path": "src/alert/demos/zhCN/basic.demo.vue",
    "content": "<markdown>\n# 基础用法\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { IosAirplane } from '@vicons/ionicons4'\n</script>\n\n<template>\n  <n-space vertical :size=\"12\">\n    <n-alert title=\"Default 类型\" type=\"default\">\n      <template #icon>\n        <n-icon>\n          <IosAirplane />\n        </n-icon>\n      </template>\n      Gee it's good to be back home\n    </n-alert>\n    <n-alert title=\"Info 类型\" type=\"info\">\n      Gee it's good to be back home\n    </n-alert>\n    <n-alert title=\"Success 类型\" type=\"success\">\n      Leave it till tomorrow to unpack my case\n    </n-alert>\n    <n-alert title=\"Warning 类型\" type=\"warning\">\n      Honey disconnect the phone\n    </n-alert>\n    <n-alert title=\"Error 类型\" type=\"error\">\n      I'm back in the U.S.S.R.\n    </n-alert>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/alert/demos/zhCN/bordered.demo.vue",
    "content": "<markdown>\n# 无边框\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst bordered = ref(true)\n</script>\n\n<template>\n  <n-space vertical :size=\"12\">\n    <n-switch v-model:value=\"bordered\" />\n    <n-alert title=\"可以没有边框\" type=\"info\" :bordered=\"bordered\">\n      Gee it's good to be back home\n    </n-alert>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/alert/demos/zhCN/closable.demo.vue",
    "content": "<markdown>\n# 可以关掉\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { IosAirplane } from '@vicons/ionicons4'\n</script>\n\n<template>\n  <n-alert title=\"Default 类型\" type=\"default\" closable>\n    <template #icon>\n      <n-icon>\n        <IosAirplane />\n      </n-icon>\n    </template>\n    Gee it's good to be back home\n  </n-alert>\n  <n-alert title=\"Info 类型\" type=\"info\" closable>\n    Gee it's good to be back home\n  </n-alert>\n  <n-alert title=\"Success 类型\" type=\"success\" closable>\n    Leave it till tomorrow to unpack my case\n  </n-alert>\n  <n-alert title=\"Warning 类型\" type=\"warning\" closable>\n    Honey disconnect the phone\n  </n-alert>\n  <n-alert title=\"Error 类型\" type=\"error\" closable>\n    I'm back in the U.S.S.R.\n  </n-alert>\n</template>\n\n<style>\n.n-alert:not(:last-child) {\n  margin-bottom: 12px;\n}\n</style>\n"
  },
  {
    "path": "src/alert/demos/zhCN/empty-debug.demo.vue",
    "content": "<markdown>\n# Empty debug\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { IosAirplane } from '@vicons/ionicons4'\n</script>\n\n<template>\n  <n-space vertical :size=\"12\">\n    <n-alert type=\"default\">\n      <template #icon>\n        <n-icon>\n          <IosAirplane />\n        </n-icon>\n      </template>\n    </n-alert>\n    <n-alert title=\"Info 类型\" type=\"info\">\n      Gee it's good to be back home\n    </n-alert>\n    <n-alert title=\"Success 类型\" type=\"success\">\n      Leave it till tomorrow to unpack my case\n    </n-alert>\n    <n-alert title=\"Warning 类型\" type=\"warning\">\n      Honey disconnect the phone\n    </n-alert>\n    <n-alert title=\"Error 类型\" type=\"error\">\n      I'm back in the U.S.S.R.\n    </n-alert>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/alert/demos/zhCN/icon.demo.vue",
    "content": "<markdown>\n# 图标\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { IosAirplane } from '@vicons/ionicons4'\n</script>\n\n<template>\n  <n-alert title=\"Back in the U.S.S.R.\">\n    <template #icon>\n      <n-icon>\n        <IosAirplane />\n      </n-icon>\n    </template>\n    Well the Ukraine girls really knock me out<br>\n    They leave the West behind<br>\n    And Moscow girls make me sing and shout<br>\n    That Georgia's always on my mind<br>\n    Aw come on!\n  </n-alert>\n</template>\n"
  },
  {
    "path": "src/alert/demos/zhCN/index.demo-entry.md",
    "content": "# 警示信息 Alert\n\n根据我的经验，这东西使用最频繁的场景是让你关掉 AdBlocks。\n\n<!-- there is a bug of chrome rendering svg, if translateZ is not set -->\n\n## 演示\n\n```demo\nbasic.vue\nbordered.vue\nclosable.vue\nicon.vue\nno-icon.vue\nmarquee.vue\nrtl-debug.vue\nempty-debug.vue\n```\n\n## API\n\n### Alert Props\n\n| 名称 | 类型 | 默认值 | 说明 | 版本 |\n| --- | --- | --- | --- | --- |\n| bordered | `boolean` | `true` | alert 是否显示边框 | 2.32.2 |\n| closable | `boolean` | `false` | alert 信息是否可以关掉 |  |\n| show-icon | `boolean` | `true` | alert 是否展示 icon |  |\n| title | `string` | `undefined` | alert 的 title 信息 |  |\n| type | `'default' \\| 'info' \\| 'success' \\| 'warning' \\| 'error'` | `'default'` | alert 的类型 |  |\n| on-after-leave | `Function` | `undefined` | alert 消失时执行的回调函数 |  |\n| on-close | `() => boolean \\| Promise<boolean> \\| any` | `() => true` | 点击 close icon 时执行的回调函数 |  |\n\n### Alert Slots\n\n| 名称    | 参数 | 说明                           |\n| ------- | ---- | ------------------------------ |\n| default | `()` | alert 的内容                   |\n| header  | `()` | alert 的 header 部分填充的内容 |\n| icon    | `()` | alert 的 icon 部分填充的内容   |\n"
  },
  {
    "path": "src/alert/demos/zhCN/marquee.demo.vue",
    "content": "<markdown>\n# 跑马灯\n\n你可以配合 `n-marquee` 实现轮播的效果。\n</markdown>\n\n<template>\n  <n-alert type=\"error\" title=\"呵呵\">\n    <n-marquee>\n      <div style=\"margin-right: 64px\">\n        测试环境又挂了。\n      </div>\n    </n-marquee>\n  </n-alert>\n</template>\n"
  },
  {
    "path": "src/alert/demos/zhCN/no-icon.demo.vue",
    "content": "<markdown>\n# 没有图标\n</markdown>\n\n<template>\n  <n-alert :show-icon=\"false\">\n    Yeah I'm back in the U.S.S.R.<br>\n    You don't know how lucky you are boys\n  </n-alert>\n</template>\n"
  },
  {
    "path": "src/alert/demos/zhCN/rtl-debug.demo.vue",
    "content": "<markdown>\n# Rtl Debug\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { IosAirplane } from '@vicons/ionicons4'\nimport { unstableAlertRtl } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst rtlEnabled = ref(false)\nconst rtlStyles = [unstableAlertRtl]\n</script>\n\n<template>\n  <n-space vertical>\n    <n-space><n-switch v-model:value=\"rtlEnabled\" />Rtl</n-space>\n    <n-config-provider :rtl=\"rtlEnabled ? rtlStyles : undefined\">\n      <n-alert title=\"Default 类型\" type=\"default\" closable>\n        <template #icon>\n          <n-icon>\n            <IosAirplane />\n          </n-icon>\n        </template>\n        Gee it's good to be back home\n      </n-alert>\n    </n-config-provider>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/alert/index.ts",
    "content": "export { alertProps, default as NAlert } from './src/Alert'\nexport type { AlertProps, AlertSlots } from './src/Alert'\n"
  },
  {
    "path": "src/alert/src/Alert.tsx",
    "content": "import type { HTMLAttributes, PropType, SlotsType, VNode } from 'vue'\nimport type { ThemeProps } from '../../_mixins'\nimport type { ExtractPublicPropTypes } from '../../_utils'\nimport type { AlertTheme } from '../styles'\nimport { getMargin } from 'seemly'\nimport { computed, defineComponent, h, mergeProps, ref, watchEffect } from 'vue'\nimport { NBaseClose, NBaseIcon, NFadeInExpandTransition } from '../../_internal'\nimport {\n  ErrorIcon,\n  InfoIcon,\n  SuccessIcon,\n  WarningIcon\n} from '../../_internal/icons'\nimport { useConfig, useTheme, useThemeClass } from '../../_mixins'\nimport { useRtl } from '../../_mixins/use-rtl'\nimport {\n  createKey,\n  resolveSlot,\n  resolveWrappedSlot,\n  warnOnce\n} from '../../_utils'\nimport { alertLight } from '../styles'\nimport style from './styles/index.cssr'\n\nexport const alertProps = {\n  ...(useTheme.props as ThemeProps<AlertTheme>),\n  title: String,\n  showIcon: {\n    type: Boolean,\n    default: true\n  },\n  type: {\n    type: String as PropType<\n      'info' | 'warning' | 'error' | 'success' | 'default'\n    >,\n    default: 'default'\n  },\n  bordered: {\n    type: Boolean,\n    default: true\n  },\n  closable: Boolean,\n  onClose: Function,\n  onAfterLeave: Function,\n  /** @deprecated */\n  onAfterHide: Function\n}\n\nexport type AlertProps = ExtractPublicPropTypes<typeof alertProps>\n\nexport interface AlertSlots {\n  default?: () => VNode[]\n  icon?: () => VNode[]\n  header?: () => VNode[]\n}\n\nexport default defineComponent({\n  name: 'Alert',\n  inheritAttrs: false,\n  props: alertProps,\n  slots: Object as SlotsType<AlertSlots>,\n  setup(props) {\n    if (__DEV__) {\n      watchEffect(() => {\n        if (props.onAfterHide !== undefined) {\n          warnOnce(\n            'alert',\n            '`on-after-hide` is deprecated, please use `on-after-leave` instead.'\n          )\n        }\n      })\n    }\n    const {\n      mergedClsPrefixRef,\n      mergedBorderedRef,\n      inlineThemeDisabled,\n      mergedRtlRef\n    } = useConfig(props)\n    const themeRef = useTheme(\n      'Alert',\n      '-alert',\n      style,\n      alertLight,\n      props,\n      mergedClsPrefixRef\n    )\n    const rtlEnabledRef = useRtl('Alert', mergedRtlRef, mergedClsPrefixRef)\n    const cssVarsRef = computed(() => {\n      const {\n        common: { cubicBezierEaseInOut },\n        self\n      } = themeRef.value\n      const {\n        fontSize,\n        borderRadius,\n        titleFontWeight,\n        lineHeight,\n        iconSize,\n        iconMargin,\n        iconMarginRtl,\n        closeIconSize,\n        closeBorderRadius,\n        closeSize,\n        closeMargin,\n        closeMarginRtl,\n        padding\n      } = self\n      const { type } = props\n      const { left, right } = getMargin(iconMargin)\n      return {\n        '--n-bezier': cubicBezierEaseInOut,\n        '--n-color': self[createKey('color', type)],\n        '--n-close-icon-size': closeIconSize,\n        '--n-close-border-radius': closeBorderRadius,\n        '--n-close-color-hover': self[createKey('closeColorHover', type)],\n        '--n-close-color-pressed': self[createKey('closeColorPressed', type)],\n        '--n-close-icon-color': self[createKey('closeIconColor', type)],\n        '--n-close-icon-color-hover':\n          self[createKey('closeIconColorHover', type)],\n        '--n-close-icon-color-pressed':\n          self[createKey('closeIconColorPressed', type)],\n        '--n-icon-color': self[createKey('iconColor', type)],\n        '--n-border': self[createKey('border', type)],\n        '--n-title-text-color': self[createKey('titleTextColor', type)],\n        '--n-content-text-color': self[createKey('contentTextColor', type)],\n        '--n-line-height': lineHeight,\n        '--n-border-radius': borderRadius,\n        '--n-font-size': fontSize,\n        '--n-title-font-weight': titleFontWeight,\n        '--n-icon-size': iconSize,\n        '--n-icon-margin': iconMargin,\n        '--n-icon-margin-rtl': iconMarginRtl,\n        '--n-close-size': closeSize,\n        '--n-close-margin': closeMargin,\n        '--n-close-margin-rtl': closeMarginRtl,\n        '--n-padding': padding,\n        '--n-icon-margin-left': left,\n        '--n-icon-margin-right': right\n      }\n    })\n    const themeClassHandle = inlineThemeDisabled\n      ? useThemeClass(\n          'alert',\n          computed(() => {\n            return props.type[0]\n          }),\n          cssVarsRef,\n          props\n        )\n      : undefined\n    const visibleRef = ref(true)\n    const doAfterLeave = (): void => {\n      const {\n        onAfterLeave,\n        onAfterHide // deprecated\n      } = props\n      if (onAfterLeave)\n        onAfterLeave()\n      if (onAfterHide)\n        onAfterHide()\n    }\n    const handleCloseClick = (): void => {\n      void Promise.resolve(props.onClose?.()).then((result) => {\n        if (result === false)\n          return\n        visibleRef.value = false\n      })\n    }\n    const handleAfterLeave = (): void => {\n      doAfterLeave()\n    }\n    return {\n      rtlEnabled: rtlEnabledRef,\n      mergedClsPrefix: mergedClsPrefixRef,\n      mergedBordered: mergedBorderedRef,\n      visible: visibleRef,\n      handleCloseClick,\n      handleAfterLeave,\n      mergedTheme: themeRef,\n      cssVars: inlineThemeDisabled ? undefined : cssVarsRef,\n      themeClass: themeClassHandle?.themeClass,\n      onRender: themeClassHandle?.onRender\n    }\n  },\n  render() {\n    this.onRender?.()\n    return (\n      <NFadeInExpandTransition onAfterLeave={this.handleAfterLeave}>\n        {{\n          default: () => {\n            const { mergedClsPrefix, $slots } = this\n            const attrs: HTMLAttributes = {\n              class: [\n                `${mergedClsPrefix}-alert`,\n                this.themeClass,\n                this.closable && `${mergedClsPrefix}-alert--closable`,\n                this.showIcon && `${mergedClsPrefix}-alert--show-icon`,\n                // fix: https://github.com/tusen-ai/naive-ui/issues/4588\n                !this.title\n                && this.closable\n                && `${mergedClsPrefix}-alert--right-adjust`,\n                this.rtlEnabled && `${mergedClsPrefix}-alert--rtl`\n              ],\n              style: this.cssVars as any,\n              role: 'alert'\n            }\n            return this.visible ? (\n              <div {...mergeProps(this.$attrs, attrs as any)}>\n                {this.closable && (\n                  <NBaseClose\n                    clsPrefix={mergedClsPrefix}\n                    class={`${mergedClsPrefix}-alert__close`}\n                    onClick={this.handleCloseClick}\n                  />\n                )}\n                {this.bordered && (\n                  <div class={`${mergedClsPrefix}-alert__border`} />\n                )}\n                {this.showIcon && (\n                  <div\n                    class={`${mergedClsPrefix}-alert__icon`}\n                    aria-hidden=\"true\"\n                  >\n                    {resolveSlot($slots.icon, () => [\n                      <NBaseIcon clsPrefix={mergedClsPrefix}>\n                        {{\n                          default: () => {\n                            switch (this.type) {\n                              case 'success':\n                                return <SuccessIcon />\n                              case 'info':\n                                return <InfoIcon />\n                              case 'warning':\n                                return <WarningIcon />\n                              case 'error':\n                                return <ErrorIcon />\n                              default:\n                                return null\n                            }\n                          }\n                        }}\n                      </NBaseIcon>\n                    ])}\n                  </div>\n                )}\n                <div\n                  class={[\n                    `${mergedClsPrefix}-alert-body`,\n                    this.mergedBordered\n                    && `${mergedClsPrefix}-alert-body--bordered`\n                  ]}\n                >\n                  {resolveWrappedSlot($slots.header, (children) => {\n                    const mergedChildren = children || this.title\n                    return mergedChildren ? (\n                      <div class={`${mergedClsPrefix}-alert-body__title`}>\n                        {mergedChildren}\n                      </div>\n                    ) : null\n                  })}\n                  {$slots.default && (\n                    <div class={`${mergedClsPrefix}-alert-body__content`}>\n                      {$slots}\n                    </div>\n                  )}\n                </div>\n              </div>\n            ) : null\n          }\n        }}\n      </NFadeInExpandTransition>\n    )\n  }\n})\n"
  },
  {
    "path": "src/alert/src/styles/index.cssr.ts",
    "content": "import { fadeInHeightExpandTransition } from '../../../_styles/transitions/fade-in-height-expand.cssr'\nimport { c, cB, cE, cM } from '../../../_utils/cssr'\n\n// vars:\n// --n-bezier\n// --n-color\n// --n-close-color-hover\n// --n-close-color-pressed\n// --n-close-icon-color\n// --n-close-icon-color-hover\n// --n-close-icon-color-pressed\n// --n-icon-color\n// --n-border\n// --n-title-text-color\n// --n-content-text-color\n// --n-line-height\n// --n-border-radius\n// --n-font-size\n// --n-title-font-weight\n// --n-icon-size\n// --n-icon-margin\n// --n-close-size\n// --n-close-icon-size\n// --n-close-margin\n// --n-padding\n// --n-icon-margin-left\n// --n-icon-margin-right\nexport default cB('alert', `\n  line-height: var(--n-line-height);\n  border-radius: var(--n-border-radius);\n  position: relative;\n  transition: background-color .3s var(--n-bezier);\n  background-color: var(--n-color);\n  text-align: start;\n  word-break: break-word;\n`, [\n  cE('border', `\n    border-radius: inherit;\n    position: absolute;\n    left: 0;\n    right: 0;\n    top: 0;\n    bottom: 0;\n    transition: border-color .3s var(--n-bezier);\n    border: var(--n-border);\n    pointer-events: none;\n  `),\n  cM('closable', [\n    cB('alert-body', [\n      cE('title', `\n        padding-right: 24px;\n      `)\n    ])\n  ]),\n  cE('icon', {\n    color: 'var(--n-icon-color)'\n  }),\n  cB('alert-body', {\n    padding: 'var(--n-padding)'\n  }, [\n    cE('title', {\n      color: 'var(--n-title-text-color)'\n    }),\n    cE('content', {\n      color: 'var(--n-content-text-color)'\n    })\n  ]),\n  fadeInHeightExpandTransition({\n    originalTransition: 'transform .3s var(--n-bezier)',\n    enterToProps: {\n      transform: 'scale(1)'\n    },\n    leaveToProps: {\n      transform: 'scale(0.9)'\n    }\n  }),\n  cE('icon', `\n    position: absolute;\n    left: 0;\n    top: 0;\n    align-items: center;\n    justify-content: center;\n    display: flex;\n    width: var(--n-icon-size);\n    height: var(--n-icon-size);\n    font-size: var(--n-icon-size);\n    margin: var(--n-icon-margin);\n  `),\n  cE('close', `\n    transition:\n      color .3s var(--n-bezier),\n      background-color .3s var(--n-bezier);\n    position: absolute;\n    right: 0;\n    top: 0;\n    margin: var(--n-close-margin);\n  `),\n  cM('show-icon', [\n    cB('alert-body', {\n      paddingLeft: 'calc(var(--n-icon-margin-left) + var(--n-icon-size) + var(--n-icon-margin-right))'\n    })\n  ]),\n  // fix: https://github.com/tusen-ai/naive-ui/issues/4588\n  cM('right-adjust', [\n    cB('alert-body', {\n      paddingRight: 'calc(var(--n-close-size) + var(--n-padding) + 2px)'\n    })\n  ]),\n  cB('alert-body', `\n    border-radius: var(--n-border-radius);\n    transition: border-color .3s var(--n-bezier);\n  `, [\n    cE('title', `\n      transition: color .3s var(--n-bezier);\n      font-size: 16px;\n      line-height: 19px;\n      font-weight: var(--n-title-font-weight);\n    `, [\n      c('& +', [\n        cE('content', {\n          marginTop: '9px'\n        })\n      ])\n    ]),\n    cE('content', {\n      transition: 'color .3s var(--n-bezier)',\n      fontSize: 'var(--n-font-size)'\n    })\n  ]),\n  cE('icon', {\n    transition: 'color .3s var(--n-bezier)'\n  })\n])\n"
  },
  {
    "path": "src/alert/src/styles/rtl.cssr.ts",
    "content": "import { cB, cE, cM } from '../../../_utils/cssr'\n\nexport default cB('alert', [\n  cM('rtl', `\n    direction: rtl;\n  `, [\n    cE('icon', `\n      left: unset;\n      right: 0;\n      margin: var(--n-icon-margin-rtl);\n    `),\n    cM('show-icon', [\n      cB('alert-body', `\n        padding-left: var(--n-padding);\n        padding-right: calc(var(--n-icon-margin-left) + var(--n-icon-size) + var(--n-icon-margin-right));\n      `)\n    ]),\n    cE('close', `\n      position: absolute;\n      right: unset;\n      left: 0;\n      margin: var(--n-close-margin-rtl);\n    `)\n  ])\n])\n"
  },
  {
    "path": "src/alert/styles/_common.ts",
    "content": "export default {\n  iconMargin: '11px 8px 0 12px',\n  iconMarginRtl: '11px 12px 0 8px',\n  iconSize: '24px',\n  closeIconSize: '16px',\n  closeSize: '20px',\n  closeMargin: '13px 14px 0 0',\n  closeMarginRtl: '13px 0 0 14px',\n  padding: '13px'\n}\n"
  },
  {
    "path": "src/alert/styles/dark.ts",
    "content": "import type { AlertTheme } from './light'\nimport { changeColor } from 'seemly'\nimport { commonDark } from '../../_styles/common'\nimport commonVars from './_common'\n\nconst alertDark: AlertTheme = {\n  name: 'Alert',\n  common: commonDark,\n  self(vars) {\n    const {\n      lineHeight,\n      borderRadius,\n      fontWeightStrong,\n      dividerColor,\n      inputColor,\n      textColor1,\n      textColor2,\n      closeColorHover,\n      closeColorPressed,\n      closeIconColor,\n      closeIconColorHover,\n      closeIconColorPressed,\n      infoColorSuppl,\n      successColorSuppl,\n      warningColorSuppl,\n      errorColorSuppl,\n      fontSize\n    } = vars\n    return {\n      ...commonVars,\n      fontSize,\n      lineHeight,\n      titleFontWeight: fontWeightStrong,\n      borderRadius,\n      border: `1px solid ${dividerColor}`,\n      color: inputColor,\n      titleTextColor: textColor1,\n      iconColor: textColor2,\n      contentTextColor: textColor2,\n      closeBorderRadius: borderRadius,\n      closeColorHover,\n      closeColorPressed,\n      closeIconColor,\n      closeIconColorHover,\n      closeIconColorPressed,\n      borderInfo: `1px solid ${changeColor(infoColorSuppl, { alpha: 0.35 })}`,\n      colorInfo: changeColor(infoColorSuppl, { alpha: 0.25 }),\n      titleTextColorInfo: textColor1,\n      iconColorInfo: infoColorSuppl,\n      contentTextColorInfo: textColor2,\n      closeColorHoverInfo: closeColorHover,\n      closeColorPressedInfo: closeColorPressed,\n      closeIconColorInfo: closeIconColor,\n      closeIconColorHoverInfo: closeIconColorHover,\n      closeIconColorPressedInfo: closeIconColorPressed,\n      borderSuccess: `1px solid ${changeColor(successColorSuppl, {\n        alpha: 0.35\n      })}`,\n      colorSuccess: changeColor(successColorSuppl, { alpha: 0.25 }),\n      titleTextColorSuccess: textColor1,\n      iconColorSuccess: successColorSuppl,\n      contentTextColorSuccess: textColor2,\n      closeColorHoverSuccess: closeColorHover,\n      closeColorPressedSuccess: closeColorPressed,\n      closeIconColorSuccess: closeIconColor,\n      closeIconColorHoverSuccess: closeIconColorHover,\n      closeIconColorPressedSuccess: closeIconColorPressed,\n      borderWarning: `1px solid ${changeColor(warningColorSuppl, {\n        alpha: 0.35\n      })}`,\n      colorWarning: changeColor(warningColorSuppl, { alpha: 0.25 }),\n      titleTextColorWarning: textColor1,\n      iconColorWarning: warningColorSuppl,\n      contentTextColorWarning: textColor2,\n      closeColorHoverWarning: closeColorHover,\n      closeColorPressedWarning: closeColorPressed,\n      closeIconColorWarning: closeIconColor,\n      closeIconColorHoverWarning: closeIconColorHover,\n      closeIconColorPressedWarning: closeIconColorPressed,\n      borderError: `1px solid ${changeColor(errorColorSuppl, { alpha: 0.35 })}`,\n      colorError: changeColor(errorColorSuppl, { alpha: 0.25 }),\n      titleTextColorError: textColor1,\n      iconColorError: errorColorSuppl,\n      contentTextColorError: textColor2,\n      closeColorHoverError: closeColorHover,\n      closeColorPressedError: closeColorPressed,\n      closeIconColorError: closeIconColor,\n      closeIconColorHoverError: closeIconColorHover,\n      closeIconColorPressedError: closeIconColorPressed\n    }\n  }\n}\n\nexport default alertDark\n"
  },
  {
    "path": "src/alert/styles/index.ts",
    "content": "export { default as alertDark } from './dark'\nexport { default as alertLight } from './light'\nexport type { AlertTheme, AlertThemeVars } from './light'\nexport { alertRtl } from './rtl'\n"
  },
  {
    "path": "src/alert/styles/light.ts",
    "content": "import type { Theme } from '../../_mixins/use-theme'\nimport type { ThemeCommonVars } from '../../_styles/common'\nimport { changeColor, composite } from 'seemly'\nimport { commonLight } from '../../_styles/common'\nimport commonVars from './_common'\n\nfunction self(vars: ThemeCommonVars) {\n  const {\n    lineHeight,\n    borderRadius,\n    fontWeightStrong,\n    baseColor,\n    dividerColor,\n    actionColor,\n    textColor1,\n    textColor2,\n    closeColorHover,\n    closeColorPressed,\n    closeIconColor,\n    closeIconColorHover,\n    closeIconColorPressed,\n    infoColor,\n    successColor,\n    warningColor,\n    errorColor,\n    fontSize\n  } = vars\n  return {\n    ...commonVars,\n    fontSize,\n    lineHeight,\n    titleFontWeight: fontWeightStrong,\n    borderRadius,\n    border: `1px solid ${dividerColor}`,\n    color: actionColor,\n    titleTextColor: textColor1,\n    iconColor: textColor2,\n    contentTextColor: textColor2,\n    closeBorderRadius: borderRadius,\n    closeColorHover,\n    closeColorPressed,\n    closeIconColor,\n    closeIconColorHover,\n    closeIconColorPressed,\n    borderInfo: `1px solid ${composite(\n      baseColor,\n      changeColor(infoColor, { alpha: 0.25 })\n    )}`,\n    colorInfo: composite(baseColor, changeColor(infoColor, { alpha: 0.08 })),\n    titleTextColorInfo: textColor1,\n    iconColorInfo: infoColor,\n    contentTextColorInfo: textColor2,\n    closeColorHoverInfo: closeColorHover,\n    closeColorPressedInfo: closeColorPressed,\n    closeIconColorInfo: closeIconColor,\n    closeIconColorHoverInfo: closeIconColorHover,\n    closeIconColorPressedInfo: closeIconColorPressed,\n    borderSuccess: `1px solid ${composite(\n      baseColor,\n      changeColor(successColor, { alpha: 0.25 })\n    )}`,\n    colorSuccess: composite(\n      baseColor,\n      changeColor(successColor, { alpha: 0.08 })\n    ),\n    titleTextColorSuccess: textColor1,\n    iconColorSuccess: successColor,\n    contentTextColorSuccess: textColor2,\n    closeColorHoverSuccess: closeColorHover,\n    closeColorPressedSuccess: closeColorPressed,\n    closeIconColorSuccess: closeIconColor,\n    closeIconColorHoverSuccess: closeIconColorHover,\n    closeIconColorPressedSuccess: closeIconColorPressed,\n    borderWarning: `1px solid ${composite(\n      baseColor,\n      changeColor(warningColor, { alpha: 0.33 })\n    )}`,\n    colorWarning: composite(\n      baseColor,\n      changeColor(warningColor, { alpha: 0.08 })\n    ),\n    titleTextColorWarning: textColor1,\n    iconColorWarning: warningColor,\n    contentTextColorWarning: textColor2,\n    closeColorHoverWarning: closeColorHover,\n    closeColorPressedWarning: closeColorPressed,\n    closeIconColorWarning: closeIconColor,\n    closeIconColorHoverWarning: closeIconColorHover,\n    closeIconColorPressedWarning: closeIconColorPressed,\n    borderError: `1px solid ${composite(\n      baseColor,\n      changeColor(errorColor, { alpha: 0.25 })\n    )}`,\n    colorError: composite(baseColor, changeColor(errorColor, { alpha: 0.08 })),\n    titleTextColorError: textColor1,\n    iconColorError: errorColor,\n    contentTextColorError: textColor2,\n    closeColorHoverError: closeColorHover,\n    closeColorPressedError: closeColorPressed,\n    closeIconColorError: closeIconColor,\n    closeIconColorHoverError: closeIconColorHover,\n    closeIconColorPressedError: closeIconColorPressed\n  }\n}\n\nexport type AlertThemeVars = ReturnType<typeof self>\n\nconst alertLight: Theme<'Alert', AlertThemeVars> = {\n  name: 'Alert',\n  common: commonLight,\n  self\n}\n\nexport default alertLight\nexport type AlertTheme = typeof alertLight\n"
  },
  {
    "path": "src/alert/styles/rtl.ts",
    "content": "import type { RtlItem } from '../../config-provider/src/internal-interface'\nimport rtlStyle from '../src/styles/rtl.cssr'\n\nexport const alertRtl: RtlItem = {\n  name: 'Alert',\n  style: rtlStyle\n}\n"
  },
  {
    "path": "src/alert/tests/Alert.spec.ts",
    "content": "import { IosAirplane } from '@vicons/ionicons4'\nimport { mount } from '@vue/test-utils'\nimport { h } from 'vue'\nimport { NIcon } from '../../icon'\nimport { NAlert } from '../index'\n\ndescribe('n-alert', () => {\n  it('should work with import on demand', () => {\n    mount(NAlert)\n  })\n\n  it('should have a role of \"alert\"', () => {\n    const wrapper = mount(NAlert)\n    expect(wrapper.find('.n-alert').attributes('role')).toBe('alert')\n    wrapper.unmount()\n  })\n\n  it('should add the right aria', () => {\n    const wrapper = mount(NAlert)\n    expect(wrapper.find('.n-alert__icon').attributes('aria-hidden')).toBe(\n      'true'\n    )\n    wrapper.unmount()\n  })\n\n  it('shouldnt have default title', () => {\n    const wrapper = mount(NAlert)\n    expect(wrapper.find('.n-alert-body__title').exists()).toBe(false)\n    wrapper.unmount()\n  })\n\n  it('should have designated title', () => {\n    const title = 'sometimes naïve'\n    const wrapper = mount(NAlert, {\n      props: { title }\n    })\n    expect(wrapper.find('.n-alert-body__title').text()).toBe(title)\n    wrapper.unmount()\n  })\n\n  it('should work with type prop', async () => {\n    ;(['info', 'success', 'warning', 'error'] as const).forEach((type) => {\n      const wrapper = mount(NAlert, { props: { type } })\n      expect(wrapper.find('.n-alert').attributes('style')).toMatchSnapshot()\n      wrapper.unmount()\n    })\n  })\n\n  it('should work with `bordered` prop', async () => {\n    const wrapper = mount(NAlert)\n    const body = wrapper.find('.n-alert-body')\n    expect(body.classes()).toContain('n-alert-body--bordered')\n    await wrapper.setProps({ bordered: false })\n    expect(body.classes()).not.toContain('n-alert-body--bordered')\n    wrapper.unmount()\n  })\n\n  it('should work with `default` slot', () => {\n    const wrapper = mount(NAlert, {\n      slots: {\n        default: () => 'default'\n      }\n    })\n\n    expect(wrapper.find('.n-alert-body__content').exists()).toBe(true)\n    expect(wrapper.find('.n-alert-body__content').text()).toBe('default')\n    wrapper.unmount()\n  })\n\n  it('should work with `icon` slot', async () => {\n    const wrapper = mount(NAlert, {\n      slots: {\n        icon: () =>\n          h(NIcon, null, {\n            default: () => h(IosAirplane)\n          })\n      }\n    })\n\n    expect(wrapper.findComponent(NIcon).exists()).toBe(true)\n    wrapper.unmount()\n  })\n\n  it('should work with `header` slot', async () => {\n    const wrapper = mount(NAlert, {\n      slots: {\n        header: () => 'test-header'\n      }\n    })\n\n    expect(wrapper.find('.n-alert-body__title').text()).toBe('test-header')\n    wrapper.unmount()\n  })\n\n  it('shouldnt be closable by default', () => {\n    const wrapper = mount(NAlert)\n    expect(wrapper.find('.n-base-close.n-alert__close').exists()).toBe(false)\n    wrapper.unmount()\n  })\n\n  it('should be closable when designated', () => {\n    const wrapper = mount(NAlert, { props: { closable: true } })\n    expect(wrapper.find('.n-base-close.n-alert__close').exists()).toBe(true)\n    wrapper.unmount()\n  })\n\n  it('should show icon by default', () => {\n    const wrapper = mount(NAlert)\n    expect(wrapper.find('.n-alert__icon').exists()).toBe(true)\n    wrapper.unmount()\n  })\n\n  it('should hide icon when designated', () => {\n    const wrapper = mount(NAlert, { props: { showIcon: false } })\n    expect(wrapper.find('.n-alert__icon').exists()).toBe(false)\n    wrapper.unmount()\n  })\n\n  it('shouldn\\'t closed when on-close prop returns false', async () => {\n    const wrapper = mount(NAlert, {\n      props: { closable: true, onClose: () => false }\n    })\n    const closeBtn = wrapper.find('.n-base-close.n-alert__close')\n    await closeBtn.trigger('click')\n\n    expect(wrapper.find('.n-base-close.n-alert__close').exists()).toBe(true)\n    wrapper.unmount()\n  })\n\n  it('should trigger callback when closed', async () => {\n    const handleCloseClick = vi.fn()\n    const handleOnAfterLeave = vi.fn()\n    // https://github.com/vuejs/test-utils/issues/1912#issuecomment-1351054542\n    const rafSpy = vi\n      .spyOn(window, 'requestAnimationFrame')\n      .mockImplementation((cb: FrameRequestCallback): number => {\n        cb(0)\n        return 0\n      })\n    const wrapper = mount(NAlert, {\n      props: {\n        closable: true,\n        onClose: handleCloseClick,\n        onAfterLeave: handleOnAfterLeave\n      },\n      global: {\n        stubs: {\n          Transition: false,\n          TransitionGroup: false\n        }\n      }\n    })\n    const closeBtn = wrapper.find('.n-base-close.n-alert__close')\n    expect(closeBtn.exists()).toBe(true)\n\n    await closeBtn.trigger('click')\n    expect(wrapper.emitted()).toHaveProperty('click')\n\n    expect(handleCloseClick).toHaveBeenCalled()\n    expect(handleOnAfterLeave).toHaveBeenCalled()\n\n    wrapper.unmount()\n    rafSpy.mockRestore()\n  })\n})\n"
  },
  {
    "path": "src/alert/tests/__snapshots__/Alert.spec.ts.snap",
    "content": "// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html\n\nexports[`n-alert > should work with type prop 1`] = `\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-color: rgba(237, 245, 254, 1); --n-close-icon-size: 16px; --n-close-border-radius: 3px; --n-close-color-hover: rgba(0, 0, 0, .09); --n-close-color-pressed: rgba(0, 0, 0, .13); --n-close-icon-color: rgba(102, 102, 102, 1); --n-close-icon-color-hover: rgba(102, 102, 102, 1); --n-close-icon-color-pressed: rgba(102, 102, 102, 1); --n-icon-color: #2080f0; --n-border: 1px solid rgba(199, 223, 251, 1); --n-title-text-color: rgb(31, 34, 37); --n-content-text-color: rgb(51, 54, 57); --n-line-height: 1.6; --n-border-radius: 3px; --n-font-size: 14px; --n-title-font-weight: 500; --n-icon-size: 24px; --n-icon-margin: 11px 8px 0 12px; --n-icon-margin-rtl: 11px 12px 0 8px; --n-close-size: 20px; --n-close-margin: 13px 14px 0 0; --n-close-margin-rtl: 13px 0 0 14px; --n-padding: 13px; --n-icon-margin-left: 12px; --n-icon-margin-right: 8px;\"`;\n\nexports[`n-alert > should work with type prop 2`] = `\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-color: rgba(237, 247, 242, 1); --n-close-icon-size: 16px; --n-close-border-radius: 3px; --n-close-color-hover: rgba(0, 0, 0, .09); --n-close-color-pressed: rgba(0, 0, 0, .13); --n-close-icon-color: rgba(102, 102, 102, 1); --n-close-icon-color-hover: rgba(102, 102, 102, 1); --n-close-icon-color-pressed: rgba(102, 102, 102, 1); --n-icon-color: #18a058; --n-border: 1px solid rgba(197, 231, 213, 1); --n-title-text-color: rgb(31, 34, 37); --n-content-text-color: rgb(51, 54, 57); --n-line-height: 1.6; --n-border-radius: 3px; --n-font-size: 14px; --n-title-font-weight: 500; --n-icon-size: 24px; --n-icon-margin: 11px 8px 0 12px; --n-icon-margin-rtl: 11px 12px 0 8px; --n-close-size: 20px; --n-close-margin: 13px 14px 0 0; --n-close-margin-rtl: 13px 0 0 14px; --n-padding: 13px; --n-icon-margin-left: 12px; --n-icon-margin-right: 8px;\"`;\n\nexports[`n-alert > should work with type prop 3`] = `\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-color: rgba(254, 247, 237, 1); --n-close-icon-size: 16px; --n-close-border-radius: 3px; --n-close-color-hover: rgba(0, 0, 0, .09); --n-close-color-pressed: rgba(0, 0, 0, .13); --n-close-icon-color: rgba(102, 102, 102, 1); --n-close-icon-color-hover: rgba(102, 102, 102, 1); --n-close-icon-color-pressed: rgba(102, 102, 102, 1); --n-icon-color: #f0a020; --n-border: 1px solid rgba(250, 224, 181, 1); --n-title-text-color: rgb(31, 34, 37); --n-content-text-color: rgb(51, 54, 57); --n-line-height: 1.6; --n-border-radius: 3px; --n-font-size: 14px; --n-title-font-weight: 500; --n-icon-size: 24px; --n-icon-margin: 11px 8px 0 12px; --n-icon-margin-rtl: 11px 12px 0 8px; --n-close-size: 20px; --n-close-margin: 13px 14px 0 0; --n-close-margin-rtl: 13px 0 0 14px; --n-padding: 13px; --n-icon-margin-left: 12px; --n-icon-margin-right: 8px;\"`;\n\nexports[`n-alert > should work with type prop 4`] = `\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-color: rgba(251, 238, 241, 1); --n-close-icon-size: 16px; --n-close-border-radius: 3px; --n-close-color-hover: rgba(0, 0, 0, .09); --n-close-color-pressed: rgba(0, 0, 0, .13); --n-close-icon-color: rgba(102, 102, 102, 1); --n-close-icon-color-hover: rgba(102, 102, 102, 1); --n-close-icon-color-pressed: rgba(102, 102, 102, 1); --n-icon-color: #d03050; --n-border: 1px solid rgba(243, 203, 211, 1); --n-title-text-color: rgb(31, 34, 37); --n-content-text-color: rgb(51, 54, 57); --n-line-height: 1.6; --n-border-radius: 3px; --n-font-size: 14px; --n-title-font-weight: 500; --n-icon-size: 24px; --n-icon-margin: 11px 8px 0 12px; --n-icon-margin-rtl: 11px 12px 0 8px; --n-close-size: 20px; --n-close-margin: 13px 14px 0 0; --n-close-margin-rtl: 13px 0 0 14px; --n-padding: 13px; --n-icon-margin-left: 12px; --n-icon-margin-right: 8px;\"`;\n"
  },
  {
    "path": "src/alert/tests/server.spec.tsx",
    "content": "import { setup } from '@css-render/vue3-ssr'\nimport { renderToString } from '@vue/server-renderer'\n/**\n * @vitest-environment node\n */\nimport { createSSRApp, h } from 'vue'\nimport { NAlert } from '../..'\n\ndescribe('server side rendering', () => {\n  it('works', async () => {\n    const app = createSSRApp(() => <NAlert />)\n    setup(app)\n    try {\n      await renderToString(app)\n    }\n    catch (e) {\n      expect(e).not.toBeTruthy()\n    }\n  })\n})\n"
  },
  {
    "path": "src/anchor/demos/enUS/affix.demo.vue",
    "content": "<markdown>\n# Affix\n\nWhen in affix mode, Anchor can recieve addition props as same as Affix.\n</markdown>\n\n<template>\n  <div style=\"height: 200px\">\n    <n-anchor\n      affix\n      listen-to=\".document-scroll-container\"\n      :trigger-top=\"24\"\n      :top=\"88\"\n      style=\"z-index: 1\"\n      :bound=\"24\"\n    >\n      <n-anchor-link title=\"Demos\" href=\"#Demos\">\n        <n-anchor-link title=\"Basic\" href=\"#basic.vue\" />\n        <n-anchor-link title=\"Ignore-Gap\" href=\"#ignore-gap.vue\" />\n        <n-anchor-link title=\"Affix\" href=\"#affix.vue\" />\n        <n-anchor-link title=\"Scroll To\" href=\"#scrollto.vue\" />\n      </n-anchor-link>\n      <n-anchor-link title=\"API\" href=\"#API\" />\n    </n-anchor>\n  </div>\n</template>\n"
  },
  {
    "path": "src/anchor/demos/enUS/basic.demo.vue",
    "content": "<markdown>\n# Basic\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst showRail = ref(true)\nconst showBackground = ref(true)\n</script>\n\n<template>\n  <n-space style=\"margin-bottom: 12px\">\n    <n-switch v-model:value=\"showRail\" /> Show Rail\n    <n-switch v-model:value=\"showBackground\" /> Show Background\n  </n-space>\n  <n-anchor :show-rail=\"showRail\" :show-background=\"showBackground\">\n    <n-anchor-link title=\"Demos\" href=\"#Demos\">\n      <n-anchor-link title=\"Basic\" href=\"#basic.vue\" />\n      <n-anchor-link title=\"Ignore-Gap\" href=\"#ignore-gap.vue\" />\n      <n-anchor-link title=\"Affix\" href=\"#affix.vue\" />\n      <n-anchor-link title=\"Scroll To\" href=\"#scrollto.vue\" />\n    </n-anchor-link>\n    <n-anchor-link title=\"API\" href=\"#API\" />\n  </n-anchor>\n</template>\n"
  },
  {
    "path": "src/anchor/demos/enUS/ignore-gap.demo.vue",
    "content": "<markdown>\n# Ignore gap\n</markdown>\n\n<template>\n  <div style=\"height: 200px\">\n    <n-row :gutter=\"12\">\n      <n-col :span=\"6\">\n        <div />\n      </n-col>\n      <n-col :span=\"6\">\n        <div />\n      </n-col>\n      <n-col :span=\"6\">\n        <div style=\"width: 160px\">\n          <n-anchor\n            affix\n            :trigger-top=\"24\"\n            :top=\"88\"\n            style=\"z-index: 1\"\n            ignore-gap\n          >\n            <n-anchor-link title=\"Demos\" href=\"#Demos\">\n              <n-anchor-link title=\"Basic\" href=\"#basic.vue\" />\n              <n-anchor-link title=\"Ignore-Gap\" href=\"#ignore-gap.vue\" />\n              <n-anchor-link title=\"Affix\" href=\"#affix.vue\" />\n              <n-anchor-link title=\"Scroll To\" href=\"#scrollto.vue\" />\n            </n-anchor-link>\n            <n-anchor-link title=\"API\" href=\"#API\" />\n          </n-anchor>\n        </div>\n      </n-col>\n      <n-col :span=\"6\">\n        <div style=\"width: 160px\">\n          <n-anchor affix :trigger-top=\"24\" :top=\"88\" style=\"z-index: 1\">\n            <n-anchor-link title=\"Demos\" href=\"#Demos\">\n              <n-anchor-link title=\"Basic\" href=\"#basic.vue\" />\n              <n-anchor-link title=\"Ignore-Gap\" href=\"#ignore-gap.vue\" />\n              <n-anchor-link title=\"Affix\" href=\"#affix.vue\" />\n              <n-anchor-link title=\"Scroll To\" href=\"#scrollto.vue\" />\n            </n-anchor-link>\n            <n-anchor-link title=\"API\" href=\"#API\" />\n          </n-anchor>\n        </div>\n      </n-col>\n    </n-row>\n  </div>\n</template>\n"
  },
  {
    "path": "src/anchor/demos/enUS/index.demo-entry.md",
    "content": "# Anchor\n\n<!--single-column-->\n\nTell you where you are.\n\n## Demos\n\n```demo\nbasic.vue\nignore-gap.vue\naffix.vue\nscrollto.vue\n```\n\n## API\n\n### Anchor Props\n\n| Name | Type | Default | Description |\n| --- | --- | --- | --- |\n| affix | `boolean` | `false` | If it works like an affix. If set to `true`, it will receive props from [affix](affix#Affix-Props). |\n| bound | `number` | `12` | The height of the border when scrolling. |\n| ignore-gap | `boolean` | `false` | If set to `true`, it will be displayed on the exact href. |\n| offset-target | `string \\| HTMLElement \\| Window \\| Document \\| (() => HTMLElement)` | `document` | The element or selector used to calc offset of link elements. If you are not scrolling the entire document but only a part of it, you may need to set this. |\n| show-rail | `boolean` | `true` | Whether to show the sider rail. |\n| show-background | `boolean` | `true` | Whether to show background of links. |\n| type | `'rail' \\| 'block'` | `'rail'` | The type to use. |\n\n### AnchorLink Props\n\n| Name  | Type     | Default     | Description         |\n| ----- | -------- | ----------- | ------------------- |\n| href  | `string` | `undefined` | The target of link  |\n| title | `string` | `undefined` | The content of link |\n\n### AnchorLink Slots\n\n| Name  | Parameters | Description            | Version |\n| ----- | ---------- | ---------------------- | ------- |\n| title | `()`       | The title of the link. | 2.42.0  |\n\n### Anchor Methods\n\n| Name | Type | Description |\n| --- | --- | --- |\n| scrollTo | `(href: string) => void` | Manually scroll to the specific position. |\n"
  },
  {
    "path": "src/anchor/demos/enUS/scrollto.demo.vue",
    "content": "<markdown>\n# Scroll to\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { AnchorInst } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst anchorRef = ref<AnchorInst | null>(null)\nfunction scrollTo(href: string) {\n  anchorRef.value?.scrollTo(href)\n}\n</script>\n\n<template>\n  <div style=\"height: 200px; padding-left: 200px\">\n    <n-anchor\n      ref=\"anchorRef\"\n      affix\n      :trigger-top=\"24\"\n      :top=\"88\"\n      :bound=\"24\"\n      style=\"z-index: 1\"\n    >\n      <n-anchor-link title=\"Demos\" href=\"#Demos\">\n        <n-anchor-link title=\"Basic\" href=\"#basic.vue\" />\n        <n-anchor-link title=\"Ignore-Gap\" href=\"#ignore-gap.vue\" />\n        <n-anchor-link title=\"Affix\" href=\"#affix.vue\" />\n        <n-anchor-link title=\"Scroll To\" href=\"#scrollto.vue\" />\n      </n-anchor-link>\n      <n-anchor-link title=\"API\" href=\"#API\" />\n    </n-anchor>\n  </div>\n  <n-space style=\"padding-left: 400px\">\n    <n-button @click=\"scrollTo('#basic.vue')\">\n      Basic\n    </n-button>\n    <n-button @click=\"scrollTo('#affix.vue')\">\n      Affix\n    </n-button>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/anchor/demos/zhCN/affix.demo.vue",
    "content": "<markdown>\n# 固定\n\n在固定模式下，Anchor 还接受和 Affix 一样的 Props。\n</markdown>\n\n<template>\n  <div style=\"height: 200px\">\n    <n-anchor\n      affix\n      listen-to=\".document-scroll-container\"\n      :trigger-top=\"24\"\n      :top=\"88\"\n      style=\"z-index: 1\"\n      :bound=\"24\"\n    >\n      <n-anchor-link title=\"演示\" href=\"#演示\">\n        <n-anchor-link title=\"基础用法\" href=\"#basic.vue\" />\n        <n-anchor-link title=\"忽略间隔\" href=\"#ignore-gap.vue\" />\n        <n-anchor-link title=\"固定\" href=\"#affix.vue\" />\n        <n-anchor-link title=\"滚动到\" href=\"#scrollto.vue\" />\n      </n-anchor-link>\n      <n-anchor-link title=\"API\" href=\"#API\" />\n    </n-anchor>\n  </div>\n</template>\n"
  },
  {
    "path": "src/anchor/demos/zhCN/basic.demo.vue",
    "content": "<markdown>\n# 基础用法\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst showRail = ref(true)\nconst showBackground = ref(true)\n</script>\n\n<template>\n  <n-space style=\"margin-bottom: 12px\">\n    <n-switch v-model:value=\"showRail\" /> 展示轨道\n    <n-switch v-model:value=\"showBackground\" /> 展示背景\n  </n-space>\n  <n-anchor :show-rail=\"showRail\" :show-background=\"showBackground\">\n    <n-anchor-link title=\"演示\" href=\"#演示\">\n      <n-anchor-link title=\"基础用法\" href=\"#basic.vue\" />\n      <n-anchor-link title=\"忽略间隔\" href=\"#ignore-gap.vue\" />\n      <n-anchor-link title=\"固定\" href=\"#affix.vue\" />\n      <n-anchor-link title=\"滚动到\" href=\"#scrollto.vue\" />\n    </n-anchor-link>\n    <n-anchor-link title=\"API\" href=\"#API\" />\n  </n-anchor>\n</template>\n"
  },
  {
    "path": "src/anchor/demos/zhCN/ignore-gap.demo.vue",
    "content": "<markdown>\n# 忽略间隔\n</markdown>\n\n<template>\n  <div style=\"height: 200px\">\n    <n-row :gutter=\"12\">\n      <n-col :span=\"6\">\n        <div />\n      </n-col>\n      <n-col :span=\"6\">\n        <div />\n      </n-col>\n      <n-col :span=\"6\">\n        <div style=\"width: 160px; float: right\">\n          <n-anchor\n            affix\n            :trigger-top=\"24\"\n            :top=\"88\"\n            style=\"z-index: 1\"\n            ignore-gap\n          >\n            <n-anchor-link title=\"演示\" href=\"#演示\">\n              <n-anchor-link title=\"忽略间隔\" href=\"#ignore-gap.vue\" />\n              <n-anchor-link title=\"固定\" href=\"#affix.vue\" />\n              <n-anchor-link title=\"滚动到\" href=\"#scrollto.vue\" />\n            </n-anchor-link>\n            <n-anchor-link title=\"API\" href=\"#API\" />\n          </n-anchor>\n        </div>\n      </n-col>\n      <n-col :span=\"6\">\n        <div style=\"width: 160px; float: right\">\n          <n-anchor affix :trigger-top=\"24\" :top=\"88\" style=\"z-index: 1\">\n            <n-anchor-link title=\"演示\" href=\"#演示\">\n              <n-anchor-link title=\"忽略间隔\" href=\"#ignore-gap.vue\" />\n              <n-anchor-link title=\"固定\" href=\"#affix.vue\" />\n              <n-anchor-link title=\"滚动到\" href=\"#scrollto.vue\" />\n            </n-anchor-link>\n            <n-anchor-link title=\"API\" href=\"#API\" />\n          </n-anchor>\n        </div>\n      </n-col>\n    </n-row>\n  </div>\n</template>\n"
  },
  {
    "path": "src/anchor/demos/zhCN/index.demo-entry.md",
    "content": "# 侧边导航 Anchor\n\n<!--single-column-->\n\n你永远的指路明灯。\n\n## 演示\n\n```demo\nbasic.vue\nignore-gap.vue\naffix.vue\nscrollto.vue\nmax-height-debug.vue\n```\n\n## API\n\n### Anchor Props\n\n| 名称 | 类型 | 默认值 | 说明 |\n| --- | --- | --- | --- |\n| affix | `boolean` | `false` | Anchor 是否像 Affix 一样展示，如果设定为 `true`，它还会接受 [Affix](affix#Affix-Props) 的 Props |\n| bound | `number` | `12` | 元素开始触发 anchor 的偏移量 |\n| ignore-gap | `boolean` | `false` | 如果设定为 `true`, 导航将显示在准确的 href 区域 |\n| offset-target | `string \\| HTMLElement \\| Window \\| Document \\| (() => HTMLElement)` | `document` | 计算偏移位置相对的元素或选择器。如果你滚动的不是整个文档而只是其中的一部分，那你有可能要设定这个 |\n| show-rail | `boolean` | `true` | 是否展示侧面的轨道 |\n| show-background | `boolean` | `true` | 是否展示 link 的背景 |\n| type | `'rail' \\| 'block'` | `'rail'` | Anchor 的风格，`'block'` 为块状风格，`'rail'` 为轨道风格 |\n\n### AnchorLink Props\n\n| 名称  | 类型     | 默认值      | 说明     |\n| ----- | -------- | ----------- | -------- |\n| href  | `string` | `undefined` | 锚点链接 |\n| title | `stirng` | `undefined` | 锚点标题 |\n\n### AnchorLink Slots\n\n| 名称  | 参数 | 说明     | 版本   |\n| ----- | ---- | -------- | ------ |\n| title | `()` | 锚点标题 | 2.42.0 |\n\n### Anchor Methods\n\n| 名称     | 类型                     | 说明                   |\n| -------- | ------------------------ | ---------------------- |\n| scrollTo | `(href: string) => void` | 手动触发到指定滚动位置 |\n"
  },
  {
    "path": "src/anchor/demos/zhCN/max-height-debug.demo.vue",
    "content": "<markdown>\n# 高度限定\n</markdown>\n\n<template>\n  <div style=\"position: fixed; right: 0; top: 500px; z-index: 9\">\n    <n-anchor\n      :bound=\"16\"\n      type=\"block\"\n      style=\"width: 128px; max-height: 100px\"\n      internal-scrollable\n    >\n      <n-anchor-link title=\"非常长的 TOC, 固定\" href=\"#basic\" />\n      <n-anchor-link title=\"很长很长\" href=\"#basic\" />\n\n      <n-anchor-link title=\"长到放不下\" href=\"#ignore-gap\" />\n      <n-anchor-link title=\"长到放不下\" href=\"#ignore-gap\" />\n      <n-anchor-link title=\"长到放不下\" href=\"#ignore-gap\" />\n      <n-anchor-link title=\"长到放不下\" href=\"#ignore-gap\" />\n      <n-anchor-link title=\"长到放不下\" href=\"#ignore-gap\" />\n      <n-anchor-link title=\"长到放不下\" href=\"#ignore-gap\" />\n      <n-anchor-link title=\"长到放不下\" href=\"#ignore-gap\" />\n      <n-anchor-link title=\"长到放不下\" href=\"#ignore-gap\" />\n      <n-anchor-link title=\"长到放不下\" href=\"#ignore-gap\" />\n      <n-anchor-link title=\"长到放不下\" href=\"#ignore-gap\" />\n      <n-anchor-link title=\"长到放不下\" href=\"#ignore-gap\" />\n      <n-anchor-link title=\"长到放不下\" href=\"#ignore-gap\" />\n      <n-anchor-link title=\"长到放不下\" href=\"#ignore-gap\" />\n      <n-anchor-link title=\"长到放不下\" href=\"#ignore-gap\" />\n    </n-anchor>\n  </div>\n</template>\n"
  },
  {
    "path": "src/anchor/demos/zhCN/scrollto.demo.vue",
    "content": "<markdown>\n# 滚动到\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { AnchorInst } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst anchorRef = ref<AnchorInst | null>(null)\nfunction scrollTo(href: string) {\n  anchorRef.value?.scrollTo(href)\n}\n</script>\n\n<template>\n  <div style=\"height: 200px; padding-left: 200px\">\n    <n-anchor\n      ref=\"anchorRef\"\n      affix\n      :trigger-top=\"24\"\n      :top=\"88\"\n      :bound=\"24\"\n      style=\"z-index: 1\"\n    >\n      <n-anchor-link title=\"演示\" href=\"#演示\">\n        <n-anchor-link title=\"基础用法\" href=\"#basic.vue\" />\n        <n-anchor-link title=\"忽略间隔\" href=\"#ignore-gap.vue\" />\n        <n-anchor-link title=\"固定\" href=\"#affix.vue\" />\n        <n-anchor-link title=\"滚动到\" href=\"#scrollto.vue\" />\n      </n-anchor-link>\n      <n-anchor-link title=\"API\" href=\"#API\" />\n    </n-anchor>\n  </div>\n  <n-space style=\"padding-left: 400px\">\n    <n-button @click=\"scrollTo('#basic.vue')\">\n      基础用法\n    </n-button>\n    <n-button @click=\"scrollTo('#affix.vue')\">\n      固定\n    </n-button>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/anchor/index.ts",
    "content": "export { anchorProps, default as NAnchor } from './src/AnchorAdapter'\nexport type { AnchorInst, AnchorProps } from './src/AnchorAdapter'\nexport { anchorLinkProps, default as NAnchorLink } from './src/Link'\nexport type { AnchorLinkProps } from './src/Link'\nexport type * from './src/public-types'\n"
  },
  {
    "path": "src/anchor/src/AnchorAdapter.tsx",
    "content": "import type { CSSProperties } from 'vue'\nimport type { ThemeProps } from '../../_mixins'\nimport type { ExtractPublicPropTypes } from '../../_utils'\nimport type { AnchorTheme } from '../styles'\nimport type { BaseAnchorInst } from './BaseAnchor'\nimport { computed, defineComponent, h, ref } from 'vue'\nimport { useConfig, useTheme, useThemeClass } from '../../_mixins'\nimport { keep } from '../../_utils'\nimport { NAffix } from '../../affix'\nimport { affixPropKeys, affixProps } from '../../affix/src/Affix'\nimport { anchorLight } from '../styles'\nimport NBaseAnchor, { baseAnchorPropKeys, baseAnchorProps } from './BaseAnchor'\nimport style from './styles/index.cssr'\n\nexport interface AnchorInst {\n  scrollTo: (href: string) => void\n}\n\nexport const anchorProps = {\n  ...(useTheme.props as ThemeProps<AnchorTheme>),\n  affix: Boolean,\n  ...affixProps,\n  ...baseAnchorProps\n} as const\n\nexport type AnchorProps = ExtractPublicPropTypes<typeof anchorProps>\n\nexport default defineComponent({\n  name: 'Anchor',\n  props: anchorProps,\n  setup(props, { slots }) {\n    const { mergedClsPrefixRef, inlineThemeDisabled } = useConfig(props)\n    const themeRef = useTheme(\n      'Anchor',\n      '-anchor',\n      style,\n      anchorLight,\n      props,\n      mergedClsPrefixRef\n    )\n    const anchorRef = ref<BaseAnchorInst | null>(null)\n    const cssVarsRef = computed(() => {\n      const {\n        self: {\n          railColor,\n          linkColor,\n          railColorActive,\n          linkTextColor,\n          linkTextColorHover,\n          linkTextColorPressed,\n          linkTextColorActive,\n          linkFontSize,\n          railWidth,\n          linkPadding,\n          borderRadius\n        },\n        common: { cubicBezierEaseInOut }\n      } = themeRef.value\n      return {\n        '--n-link-border-radius': borderRadius,\n        '--n-link-color': linkColor,\n        '--n-link-font-size': linkFontSize,\n        '--n-link-text-color': linkTextColor,\n        '--n-link-text-color-hover': linkTextColorHover,\n        '--n-link-text-color-active': linkTextColorActive,\n        '--n-link-text-color-pressed': linkTextColorPressed,\n        '--n-link-padding': linkPadding,\n        '--n-bezier': cubicBezierEaseInOut,\n        '--n-rail-color': railColor,\n        '--n-rail-color-active': railColorActive,\n        '--n-rail-width': railWidth\n      }\n    })\n    const themeClassHandle = inlineThemeDisabled\n      ? useThemeClass('anchor', undefined, cssVarsRef, props)\n      : undefined\n    return {\n      scrollTo(href: string) {\n        anchorRef.value?.setActiveHref(href)\n      },\n      renderAnchor: () => {\n        themeClassHandle?.onRender()\n        return (\n          <NBaseAnchor\n            ref={anchorRef}\n            style={\n              inlineThemeDisabled\n                ? undefined\n                : (cssVarsRef.value as CSSProperties)\n            }\n            class={themeClassHandle?.themeClass.value}\n            {...keep(props, baseAnchorPropKeys)}\n            mergedClsPrefix={mergedClsPrefixRef.value}\n          >\n            {slots}\n          </NBaseAnchor>\n        )\n      }\n    }\n  },\n  render() {\n    return !this.affix ? (\n      this.renderAnchor()\n    ) : (\n      <NAffix {...keep(this, affixPropKeys)}>\n        {{ default: this.renderAnchor }}\n      </NAffix>\n    )\n  }\n})\n"
  },
  {
    "path": "src/anchor/src/BaseAnchor.tsx",
    "content": "import type { PropType } from 'vue'\nimport type { OffsetTarget } from './utils'\nimport { unwrapElement } from 'seemly'\nimport { onFontsReady } from 'vooks'\nimport {\n  computed,\n  defineComponent,\n  h,\n  nextTick,\n  onBeforeUnmount,\n  onMounted,\n  provide,\n  ref,\n  toRef,\n  watch\n} from 'vue'\nimport { NScrollbar } from '../../_internal'\nimport { keysOf } from '../../_utils'\nimport { anchorInjectionKey } from './Link'\nimport { getOffset } from './utils'\n\ninterface LinkInfo {\n  top: number\n  height: number\n  href: string\n}\n\nexport interface BaseAnchorInst {\n  setActiveHref: (href: string) => void\n}\n\nexport const baseAnchorProps = {\n  type: {\n    type: String as PropType<'block' | 'rail'>,\n    default: 'rail'\n  },\n  showRail: {\n    type: Boolean,\n    default: true\n  },\n  showBackground: {\n    type: Boolean,\n    default: true\n  },\n  bound: {\n    type: Number,\n    default: 12\n  },\n  internalScrollable: Boolean,\n  ignoreGap: Boolean,\n  offsetTarget: [String, Object, Function] as PropType<\n    string | OffsetTarget | (() => HTMLElement)\n  >\n} as const\n\nexport const baseAnchorPropKeys = keysOf(baseAnchorProps)\n\nexport default defineComponent({\n  name: 'BaseAnchor',\n  props: {\n    ...baseAnchorProps,\n    mergedClsPrefix: {\n      type: String,\n      required: true\n    }\n  },\n  setup(props) {\n    const collectedLinkHrefs: string[] = []\n    const titleEls: HTMLElement[] = []\n    const activeHrefRef = ref<string | null>(null)\n    const slotRef = ref<HTMLElement | null>(null)\n    const barRef = ref<HTMLElement | null>(null)\n    const selfRef = ref<HTMLElement | null>(null)\n    let skipScrollHandling = false\n    const isBlockTypeRef = computed(() => {\n      return props.type === 'block'\n    })\n    const mergedShowRailRef = computed(() => {\n      return !isBlockTypeRef.value && props.showRail\n    })\n    function disableTransitionOneTick(): void {\n      const { value: barEl } = barRef\n      const { value: slotEl } = slotRef\n      if (barEl) {\n        barEl.style.transition = 'none'\n      }\n      if (slotEl) {\n        slotEl.style.transition = 'none'\n      }\n      if (titleEls) {\n        titleEls.forEach((titleEl) => {\n          titleEl.style.transition = 'none'\n        })\n      }\n      void nextTick(() => {\n        const { value: nextBarEl } = barRef\n        const { value: nextSlotEl } = slotRef\n        if (nextBarEl) {\n          void nextBarEl.offsetWidth\n          nextBarEl.style.transition = ''\n        }\n        if (nextSlotEl) {\n          void nextSlotEl.offsetWidth\n          nextSlotEl.style.transition = ''\n        }\n        if (titleEls) {\n          titleEls.forEach((titleEl) => {\n            void titleEl.offsetWidth\n            titleEl.style.transition = ''\n          })\n        }\n      })\n    }\n    function updateBarPosition(\n      linkTitleEl: HTMLElement,\n      transition = true\n    ): void {\n      const { value: barEl } = barRef\n      const { value: slotEl } = slotRef\n      const { value: selfEl } = selfRef\n      if (!selfEl || !barEl)\n        return\n      if (!transition) {\n        barEl.style.transition = 'none'\n        if (slotEl)\n          slotEl.style.transition = 'none'\n      }\n      const { offsetHeight, offsetWidth } = linkTitleEl\n      const { top: linkTitleClientTop, left: linkTitleClientLeft }\n        = linkTitleEl.getBoundingClientRect()\n      const { top: anchorClientTop, left: anchorClientLeft }\n        = selfEl.getBoundingClientRect()\n      const offsetTop = linkTitleClientTop - anchorClientTop\n      const offsetLeft = linkTitleClientLeft - anchorClientLeft\n      barEl.style.top = `${offsetTop}px`\n      barEl.style.height = `${offsetHeight}px`\n      if (slotEl) {\n        slotEl.style.top = `${offsetTop}px`\n        slotEl.style.height = `${offsetHeight}px`\n        slotEl.style.maxWidth = `${offsetWidth + offsetLeft}px`\n      }\n      void barEl.offsetHeight\n      if (slotEl)\n        void slotEl.offsetHeight\n\n      if (!transition) {\n        barEl.style.transition = ''\n        if (slotEl)\n          slotEl.style.transition = ''\n      }\n    }\n\n    let currentThrottleTimerId: ReturnType<typeof setTimeout> | undefined\n    let hasTrailingThrottledTask = false\n    let isInThrottledPeriod = false\n    const handleScroll = () => {\n      if (isInThrottledPeriod) {\n        hasTrailingThrottledTask = true\n      }\n      else {\n        if (skipScrollHandling) {\n          return\n        }\n        _handleScroll(true)\n        isInThrottledPeriod = true\n        clearTimeout(currentThrottleTimerId)\n        currentThrottleTimerId = setTimeout(() => {\n          isInThrottledPeriod = false\n          if (hasTrailingThrottledTask) {\n            hasTrailingThrottledTask = false\n            handleScroll()\n          }\n        }, 128)\n      }\n    }\n    function setActiveHref(href: string, transition = true): void {\n      const idMatchResult = /^#([^#]+)$/.exec(href)\n      if (!idMatchResult)\n        return\n      const linkEl = document.getElementById(idMatchResult[1])\n      if (!linkEl)\n        return\n      skipScrollHandling = true\n      activeHrefRef.value = href\n      linkEl.scrollIntoView()\n      if (!transition) {\n        disableTransitionOneTick()\n      }\n      hasTrailingThrottledTask = false\n      setTimeout(() => {\n        skipScrollHandling = false\n      }, 0)\n    }\n\n    function _handleScroll(transition = true): void {\n      const links: LinkInfo[] = []\n      const offsetTarget = unwrapElement(props.offsetTarget ?? document)\n      collectedLinkHrefs.forEach((href) => {\n        const idMatchResult = /#([^#]+)$/.exec(href)\n        if (!idMatchResult)\n          return\n        const linkEl = document.getElementById(idMatchResult[1])\n        if (linkEl && offsetTarget) {\n          const { top, height } = getOffset(linkEl, offsetTarget)\n          links.push({\n            top,\n            height,\n            href\n          })\n        }\n      })\n      links.sort((a, b) => {\n        // ascend top\n        if (a.top > b.top) {\n          return 1\n          // descend height\n        }\n        else if (a.top === b.top && a.height < b.height) {\n          return -1\n        }\n        return -1\n      })\n      const currentActiveHref = activeHrefRef.value\n      const { bound, ignoreGap } = props\n      const activeLink = links.reduce((prevLink: LinkInfo | null, link) => {\n        if (link.top + link.height < 0) {\n          if (ignoreGap) {\n            return link\n          }\n          else {\n            return prevLink\n          }\n        }\n        if (link.top <= bound) {\n          if (prevLink === null) {\n            return link\n          }\n          else if (link.top === prevLink.top) {\n            if (link.href === currentActiveHref) {\n              return link\n            }\n            else {\n              return prevLink\n            }\n          }\n          else if (link.top > prevLink.top) {\n            return link\n          }\n          else {\n            return prevLink\n          }\n        }\n        return prevLink\n      }, null)\n      if (!transition)\n        disableTransitionOneTick()\n      if (activeLink) {\n        activeHrefRef.value = activeLink.href\n      }\n      else {\n        activeHrefRef.value = null\n      }\n    }\n    provide(anchorInjectionKey, {\n      activeHref: activeHrefRef,\n      mergedClsPrefix: toRef(props, 'mergedClsPrefix'),\n      updateBarPosition,\n      setActiveHref,\n      collectedLinkHrefs,\n      titleEls\n    })\n    onMounted(() => {\n      document.addEventListener('scroll', handleScroll, true)\n      setActiveHref(window.location.hash)\n      _handleScroll(false)\n    })\n    onFontsReady(() => {\n      setActiveHref(window.location.hash)\n      _handleScroll(false)\n    })\n    onBeforeUnmount(() => {\n      clearTimeout(currentThrottleTimerId)\n      document.removeEventListener('scroll', handleScroll, true)\n    })\n    watch(activeHrefRef, (value) => {\n      if (value === null) {\n        const { value: slotEl } = slotRef\n        if (slotEl && !isBlockTypeRef.value) {\n          slotEl.style.maxWidth = '0'\n        }\n      }\n    })\n    return {\n      selfRef,\n      barRef,\n      slotRef,\n      setActiveHref,\n      activeHref: activeHrefRef,\n      isBlockType: isBlockTypeRef,\n      mergedShowRail: mergedShowRailRef\n    }\n  },\n  render() {\n    const { mergedClsPrefix, mergedShowRail, isBlockType, $slots } = this\n\n    const Anchor = (\n      <div\n        class={[\n          `${mergedClsPrefix}-anchor`,\n          isBlockType && `${mergedClsPrefix}-anchor--block`,\n          mergedShowRail && `${mergedClsPrefix}-anchor--show-rail`\n        ]}\n        ref=\"selfRef\"\n      >\n        {mergedShowRail && this.showBackground ? (\n          <div\n            ref=\"slotRef\"\n            class={`${mergedClsPrefix}-anchor-link-background`}\n          />\n        ) : null}\n        {mergedShowRail ? (\n          <div class={`${mergedClsPrefix}-anchor-rail`}>\n            <div\n              ref=\"barRef\"\n              class={[\n                `${mergedClsPrefix}-anchor-rail__bar`,\n                this.activeHref !== null\n                && `${mergedClsPrefix}-anchor-rail__bar--active`\n              ]}\n            />\n          </div>\n        ) : null}\n        {$slots.default?.()}\n      </div>\n    )\n\n    return this.internalScrollable ? (\n      <NScrollbar>\n        {{\n          default: () => Anchor\n        }}\n      </NScrollbar>\n    ) : (\n      Anchor\n    )\n  }\n})\n"
  },
  {
    "path": "src/anchor/src/Link.tsx",
    "content": "import type { Ref, SlotsType } from 'vue'\nimport type { ExtractPublicPropTypes } from '../../_utils'\nimport type { AnchorLinkSlots } from './public-types'\nimport { useMemo } from 'vooks'\nimport { defineComponent, h, inject, ref, toRef, watch } from 'vue'\nimport {\n  createInjectionKey,\n  getTitleAttribute,\n  resolveSlot\n} from '../../_utils'\nimport {\n  useInjectionCollection,\n  useInjectionElementCollection\n} from '../../_utils/composable'\n\nexport interface AnchorInjection {\n  activeHref: Ref<string | null>\n  mergedClsPrefix: Ref<string>\n  updateBarPosition: (el: HTMLElement) => void\n  setActiveHref: (href: string, transition?: boolean) => void\n  collectedLinkHrefs: string[]\n  titleEls: HTMLElement[]\n}\n\nexport const anchorInjectionKey\n  = createInjectionKey<AnchorInjection>('n-anchor')\n\nexport const anchorLinkProps = {\n  title: String,\n  href: String\n} as const\n\nexport type AnchorLinkProps = ExtractPublicPropTypes<typeof anchorLinkProps>\n\nexport default defineComponent({\n  name: 'AnchorLink',\n  props: anchorLinkProps,\n  slots: Object as SlotsType<AnchorLinkSlots>,\n  setup(props, { slots }) {\n    const titleRef = ref<HTMLElement | null>(null)\n    const NAnchor = inject(anchorInjectionKey)!\n    const hrefRef = toRef(props, 'href')\n    const activeRef = useMemo(() => {\n      return hrefRef.value && hrefRef.value === NAnchor.activeHref.value\n    })\n    useInjectionCollection(anchorInjectionKey, 'collectedLinkHrefs', hrefRef)\n    useInjectionElementCollection(\n      anchorInjectionKey,\n      'titleEls',\n      () => titleRef.value\n    )\n    watch(activeRef, (value) => {\n      if (value && titleRef.value) {\n        NAnchor.updateBarPosition(titleRef.value)\n      }\n    })\n    function handleClick(): void {\n      if (props.href !== undefined) {\n        NAnchor.setActiveHref(props.href)\n      }\n    }\n    return () => {\n      const { value: mergedClsPrefix } = NAnchor.mergedClsPrefix\n      return (\n        <div\n          class={[\n            `${mergedClsPrefix}-anchor-link`,\n            activeRef.value && `${mergedClsPrefix}-anchor-link--active`\n          ]}\n        >\n          <a\n            ref={titleRef}\n            class={[`${mergedClsPrefix}-anchor-link__title`]}\n            href={props.href}\n            title={getTitleAttribute(props.title)}\n            onClick={handleClick}\n          >\n            {{\n              default: () => resolveSlot(slots.title, () => [props.title])\n            }}\n          </a>\n          {slots.default?.()}\n        </div>\n      )\n    }\n  }\n})\n"
  },
  {
    "path": "src/anchor/src/public-types.tsx",
    "content": "import type { VNode } from 'vue'\n\nexport interface AnchorLinkSlots {\n  default?: () => VNode[]\n  title?: () => VNode[]\n}\n"
  },
  {
    "path": "src/anchor/src/styles/index.cssr.ts",
    "content": "import { c, cB, cE, cM, cNotM } from '../../../_utils/cssr'\n\n// vars:\n// --n-link-color\n// --n-link-font-size\n// --n-link-text-color\n// --n-link-text-color-hover\n// --n-link-text-color-active\n// --n-link-text-color-pressed\n// --n-bezier\n// --n-rail-color\n// --n-rail-color-active\n// --n-rail-width\n// --n-link-padding\n// --n-link-border-radius\nexport default cB('anchor', `\n  position: relative;\n`, [\n  cNotM('block', `\n    padding-left: var(--n-rail-width);\n  `, [\n    cB('anchor-link', [\n      c('+, >', [\n        cB('anchor-link', `\n          margin-top: .5em;\n        `)\n      ])\n    ]),\n    cB('anchor-link-background', `\n      max-width: 0;\n      border-top-right-radius: 10.5px;\n      border-bottom-right-radius: 10.5px;\n    `),\n    cNotM('show-rail', [\n      c('>', [\n        cB('anchor-link', 'padding-left: 0;')\n      ])\n    ])\n  ]),\n  cM('block', [\n    cB('anchor-link', `\n      margin-bottom: 4px;\n      padding: 2px 8px;\n      transition: background-color .3s var(--n-bezier);\n      background-color: transparent;\n      border-radius: var(--n-link-border-radius);\n    `, [\n      cM('active', `\n        background-color: var(--n-link-color);\n      `)\n    ])\n  ]),\n  cB('anchor-link-background', `\n    position: absolute;\n    left: calc(var(--n-rail-width) / 2);\n    width: 100%;\n    background-color: var(--n-link-color);\n    transition:\n      top .15s var(--n-bezier),\n      max-width .15s var(--n-bezier),\n      background-color .3s var(--n-bezier);\n  `),\n  cB('anchor-rail', `\n    position: absolute;\n    left: 0;\n    top: 0;\n    bottom: 0;\n    width: var(--n-rail-width);\n    border-radius: calc(var(--n-rail-width) / 2);\n    overflow: hidden;\n    transition: background-color .3s var(--n-bezier);\n    background-color: var(--n-rail-color);\n  `, [\n    cE('bar', `\n      position: absolute;\n      left: 0;\n      width: var(--n-rail-width);\n      height: 21px;\n      background-color: #0000;\n      transition: \n        top .15s var(--n-bezier),\n        background-color .3s var(--n-bezier);\n    `, [\n      cM('active', {\n        backgroundColor: 'var(--n-rail-color-active)'\n      })\n    ])\n  ]),\n  cB('anchor-link', `\n    padding: var(--n-link-padding);\n    position: relative;\n    line-height: 1.5;\n    font-size: var(--n-link-font-size);\n    min-height: 1.5em;\n    display: flex;\n    flex-direction: column;\n  `, [\n    cM('active', [\n      c('>', [\n        cE('title', `\n          color: var(--n-link-text-color-active);\n        `)\n      ])\n    ]),\n    cE('title', `\n      outline: none;\n      max-width: 100%;\n      text-decoration: none;\n      white-space: nowrap;\n      text-overflow: ellipsis;\n      overflow: hidden;\n      cursor: pointer;\n      display: inline-block;\n      padding-right: 16px;\n      transition: color .3s var(--n-bezier);\n      color: var(--n-link-text-color);\n    `, [\n      c('&:hover, &:focus', `\n        color: var(--n-link-text-color-hover);\n      `),\n      c('&:active', `\n        color: var(--n-link-text-color-pressed);\n      `)\n    ])\n  ])\n])\n"
  },
  {
    "path": "src/anchor/src/utils.ts",
    "content": "export type OffsetTarget = Window | Document | HTMLElement\n\nexport function getOffset(\n  el: HTMLElement,\n  scrollTarget: OffsetTarget\n): {\n  top: number\n  height: number\n} {\n  const { top: elTop, height } = el.getBoundingClientRect()\n  const scrollTargetTop\n    = scrollTarget instanceof HTMLElement\n      ? scrollTarget.getBoundingClientRect().top\n      : 0\n  return {\n    top: elTop - scrollTargetTop,\n    height\n  }\n}\n"
  },
  {
    "path": "src/anchor/styles/_common.ts",
    "content": "export default {\n  linkFontSize: '13px',\n  linkPadding: '0 0 0 16px',\n  railWidth: '4px'\n}\n"
  },
  {
    "path": "src/anchor/styles/dark.ts",
    "content": "import type { AnchorTheme } from './light'\nimport { commonDark } from '../../_styles/common'\nimport { self } from './light'\n\nconst anchorDark: AnchorTheme = {\n  name: 'Anchor',\n  common: commonDark,\n  self\n}\n\nexport default anchorDark\n"
  },
  {
    "path": "src/anchor/styles/index.ts",
    "content": "export { default as anchorDark } from './dark'\nexport { default as anchorLight } from './light'\nexport type { AnchorTheme, AnchorThemeVars } from './light'\n"
  },
  {
    "path": "src/anchor/styles/light.ts",
    "content": "import type { Theme } from '../../_mixins'\nimport type { ThemeCommonVars } from '../../_styles/common'\nimport { changeColor } from 'seemly'\nimport { commonLight } from '../../_styles/common'\nimport commonVars from './_common'\n\nexport function self(vars: ThemeCommonVars) {\n  const {\n    borderRadius,\n    railColor,\n    primaryColor,\n    primaryColorHover,\n    primaryColorPressed,\n    textColor2\n  } = vars\n  return {\n    ...commonVars,\n    borderRadius,\n    railColor,\n    railColorActive: primaryColor,\n    linkColor: changeColor(primaryColor, { alpha: 0.15 }),\n    linkTextColor: textColor2,\n    linkTextColorHover: primaryColorHover,\n    linkTextColorPressed: primaryColorPressed,\n    linkTextColorActive: primaryColor\n  }\n}\n\nexport type AnchorThemeVars = ReturnType<typeof self>\n\nconst anchorLight: Theme<'Anchor', AnchorThemeVars> = {\n  name: 'Anchor',\n  common: commonLight,\n  self\n}\n\nexport default anchorLight\nexport type AnchorTheme = typeof anchorLight\n"
  },
  {
    "path": "src/anchor/tests/Anchor.spec.ts",
    "content": "import { mount } from '@vue/test-utils'\nimport { h } from 'vue'\nimport { NAnchor, NAnchorLink } from '../index'\n\ndescribe('n-anchor', () => {\n  it('should work with import on demand', () => {\n    mount(NAnchor)\n  })\n\n  it('should work with `showRail` and `showBackground` prop', async () => {\n    const wrapper = mount(NAnchor, {\n      props: {\n        showRail: true\n      }\n    })\n\n    expect(wrapper.find('.n-anchor-rail').exists()).toBe(true)\n\n    await wrapper.setProps({ showBackground: true })\n\n    expect(wrapper.find('.n-anchor-link-background').exists()).toBe(true)\n    wrapper.unmount()\n  })\n\n  it('should work with `affix` prop', () => {\n    const wrapper = mount(NAnchor, {\n      props: {\n        affix: true\n      }\n    })\n\n    expect(wrapper.find('.n-affix').exists()).toBe(true)\n    wrapper.unmount()\n  })\n\n  it('should work with `type` prop', async () => {\n    const wrapper = mount(NAnchor, {\n      props: {\n        type: 'rail'\n      }\n    })\n\n    expect(wrapper.find('.n-anchor--show-rail').exists()).toBe(true)\n\n    await wrapper.setProps({ type: 'block' })\n\n    expect(wrapper.find('.n-anchor--block').exists()).toBe(true)\n    wrapper.unmount()\n  })\n\n  it('should work with `title` and `href` prop', async () => {\n    const wrapper = mount(NAnchor, {\n      props: {\n        showRail: false\n      },\n      slots: {\n        default: () => {\n          return h(NAnchorLink, {\n            title: 'testTitle',\n            href: '#testHref'\n          })\n        }\n      }\n    })\n\n    expect(wrapper.find('.n-anchor-link__title').attributes('href')).toBe(\n      '#testHref'\n    )\n    expect(wrapper.find('.n-anchor-link__title').attributes('title')).toBe(\n      'testTitle'\n    )\n    wrapper.unmount()\n  })\n\n  it('should work with `naive-scrollbar` and `max-height` prop', async () => {\n    const wrapper = mount(NAnchor, {\n      props: {\n        naiveScrollbar: true,\n        style: {\n          maxHeight: '100px'\n        }\n      },\n      slots: {\n        default() {\n          return h(NAnchorLink, {\n            title: 'testTitle',\n            href: '#testHref'\n          })\n        }\n      }\n    })\n\n    expect(wrapper.find('.n-scrollbar')).toBeTruthy()\n    wrapper.unmount()\n  })\n})\n"
  },
  {
    "path": "src/anchor/tests/server.spec.tsx",
    "content": "import { setup } from '@css-render/vue3-ssr'\nimport { renderToString } from '@vue/server-renderer'\n/**\n * @vitest-environment node\n */\nimport { createSSRApp, h } from 'vue'\nimport { NAnchor } from '../..'\n\ndescribe('server side rendering', () => {\n  it('works', async () => {\n    const app = createSSRApp(() => <NAnchor />)\n    setup(app)\n    try {\n      await renderToString(app)\n    }\n    catch (e) {\n      expect(e).not.toBeTruthy()\n    }\n  })\n})\n"
  },
  {
    "path": "src/auto-complete/demos/enUS/after-select.demo.vue",
    "content": "<markdown>\n# Actions after select\n\nChoose whether the element blurs after a selection is made with `blur-after-select`.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { computed, ref } from 'vue'\n\nconst valueRef = ref('')\nconst value = valueRef\nconst options = computed(() => {\n  return ['@gmail.com', '@163.com', '@qq.com'].map((suffix) => {\n    const value = valueRef.value === null ? '' : valueRef.value\n    const prefix = value.split('@')[0]\n    return {\n      label: prefix + suffix,\n      value: prefix + suffix\n    }\n  })\n})\n</script>\n\n<template>\n  <n-space vertical>\n    <n-auto-complete\n      v-model:value=\"value\"\n      :options=\"options\"\n      clear-after-select\n      placeholder=\"Clear After Select\"\n    />\n    <n-auto-complete\n      v-model:value=\"value\"\n      :options=\"options\"\n      blur-after-select\n      placeholder=\"Blur After Select\"\n    />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/auto-complete/demos/enUS/append.demo.vue",
    "content": "<markdown>\n# Append\n\nAppend the selected option to the input box instead of directly overwriting it, and use it in conjunction with get-show.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { computed, ref } from 'vue'\n\nconst valueRef = ref('')\nconst appendValueRef = ref('')\nconst value = valueRef\nconst options = computed(() => {\n  return ['@gmail.com', '@163.com', '@qq.com'].map((suffix) => {\n    const value = valueRef.value === null ? '' : valueRef.value\n    const prefix = value.split('@')[0]\n    return {\n      label: prefix + suffix,\n      value: prefix + suffix\n    }\n  })\n})\nconst appendValue = appendValueRef\nconst appendOptions = computed(() => {\n  return ['gmail.com', '163.com', 'qq.com'].map((suffix) => {\n    return {\n      label: suffix,\n      value: suffix\n    }\n  })\n})\nfunction getShow(value: string) {\n  if (value.endsWith('@')) {\n    return true\n  }\n  return false\n}\n</script>\n\n<template>\n  <n-space vertical>\n    <n-auto-complete\n      v-model:value=\"value\"\n      :options=\"options\"\n      :append=\"false\"\n      placeholder=\"Select and overwrite\"\n    />\n    <n-auto-complete\n      v-model:value=\"appendValue\"\n      :options=\"appendOptions\"\n      :append=\"true\"\n      :get-show=\"getShow\"\n      placeholder=\"Select and append\"\n    />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/auto-complete/demos/enUS/basic.demo.vue",
    "content": "<markdown>\n# Basic\n\nStart typing to see how this works.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { computed, ref } from 'vue'\n\nconst valueRef = ref('')\nconst value = valueRef\nconst options = computed(() => {\n  return ['@gmail.com', '@163.com', '@qq.com'].map((suffix) => {\n    const prefix = valueRef.value.split('@')[0]\n    return {\n      label: prefix + suffix,\n      value: prefix + suffix\n    }\n  })\n})\n</script>\n\n<template>\n  <n-auto-complete\n    v-model:value=\"value\"\n    :input-props=\"{\n      autocomplete: 'disabled',\n    }\"\n    :options=\"options\"\n    placeholder=\"Email\"\n    clearable\n  />\n</template>\n"
  },
  {
    "path": "src/auto-complete/demos/enUS/custom-input.demo.vue",
    "content": "<markdown>\n# Customize input element\n\nYou can also replace the input element of the auto-complete component (e.g. using a textarea).\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { computed, ref } from 'vue'\n\nconst valueRef = ref('')\nconst value = valueRef\nconst options = computed(() => {\n  return ['@gmail.com', '@163.com', '@qq.com'].map((suffix) => {\n    const prefix = valueRef.value.split('@')[0]\n    return {\n      label: prefix + suffix,\n      value: prefix + suffix\n    }\n  })\n})\n</script>\n\n<template>\n  <n-auto-complete v-model:value=\"value\" :options=\"options\">\n    <template\n      #default=\"{ handleInput, handleBlur, handleFocus, value: slotValue }\"\n    >\n      <n-input\n        type=\"textarea\"\n        :value=\"slotValue\"\n        placeholder=\"Email\"\n        @input=\"handleInput\"\n        @focus=\"handleFocus\"\n        @blur=\"handleBlur\"\n      />\n    </template>\n  </n-auto-complete>\n</template>\n"
  },
  {
    "path": "src/auto-complete/demos/enUS/customized-rendering.demo.vue",
    "content": "<markdown>\n# Customized rendering\n\nUse `render-label` to customize label rendering.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { SelectOption } from 'naive-ui'\nimport type { VNodeChild } from 'vue'\nimport { NTag } from 'naive-ui'\nimport { computed, h, ref } from 'vue'\n\nconst valueRef = ref('')\nconst value = valueRef\nfunction renderLabel(option: SelectOption): VNodeChild {\n  return [\n    option.label as string,\n    ' ',\n    h(NTag, { size: 'small', type: 'info' }, { default: () => 'Email' })\n  ]\n}\nconst options = computed(() => {\n  return ['@gmail.com', '@163.com', '@qq.com'].map((suffix) => {\n    const prefix = valueRef.value.split('@')[0]\n    return {\n      label: prefix + suffix,\n      value: prefix + suffix\n    }\n  })\n})\n</script>\n\n<template>\n  <n-auto-complete\n    v-model:value=\"value\"\n    :options=\"options\"\n    placeholder=\"Email\"\n    :render-label=\"renderLabel\"\n  />\n</template>\n"
  },
  {
    "path": "src/auto-complete/demos/enUS/group.demo.vue",
    "content": "<markdown>\n# Group\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { computed, ref } from 'vue'\n\nconst valueRef = ref('')\nconst value = valueRef\nconst options = computed(() => {\n  return [\n    ['Google', '@gmail.com'],\n    ['Netease', '@163.com'],\n    ['Tencent', '@qq.com']\n  ].map((emailInfo) => {\n    return {\n      type: 'group',\n      label: emailInfo[0],\n      key: emailInfo[0],\n      children: [valueRef.value.split('@')[0] + emailInfo[1]]\n    }\n  })\n})\n</script>\n\n<template>\n  <n-auto-complete\n    v-model:value=\"value\"\n    :options=\"options\"\n    placeholder=\"Email\"\n  />\n</template>\n"
  },
  {
    "path": "src/auto-complete/demos/enUS/index.demo-entry.md",
    "content": "# AutoComplete\n\nOffer a search hint or maybe guess some likely options?\n\n## Demos\n\n```demo\nbasic.vue\nsize.vue\ngroup.vue\ncustom-input.vue\nafter-select.vue\nshow-options-by-value.vue\ncustomized-rendering.vue\nstatus.vue\nappend.vue\n```\n\n## API\n\n### AutoComplete Props\n\n| Name | Type | Default | Description | Version |\n| --- | --- | --- | --- | --- |\n| append | `boolean` | `false` | Whether to append content to input. | 2.38.0 |\n| blur-after-select | `boolean` | `false` | Whether to blur after selection. |  |\n| clear-after-select | `boolean` | `false` | Whether to clear after selection. |  |\n| clearable | `boolean` | `false` | Whether autocomplete is clearable. |  |\n| default-value | `string` | `null` | Default value of autocomplete. |  |\n| disabled | `boolean` | `false` | Whether the autocomplete is disabled. |  |\n| get-show | `(value: string) => boolean` | `undefined` | Use the input to determine whether to show options on focus. |  |\n| input-props | `InputHTMLAttributes` | `undefined` | The attributes of input element in autocomplete. |  |\n| loading | `boolean` | `false` | Whether to show a loading status. |  |\n| menu-props | `HTMLAttributes` | `undefined` | The menu's dom props. | 2.32.2 |\n| options | `Array<string \\| AutoCompleteOption \\| AutoCompleteGroupOption>` | `[]` | Options to autocomplete from. |  |\n| placeholder | `string` | `'Please Input'` | Autocomplete's placeholder. |  |\n| placement | `'top-start' \\| 'top' \\| 'top-end' \\| 'right-start' \\| 'right' \\| 'right-end' \\| 'bottom-start' \\| 'bottom' \\| 'bottom-end' \\| 'left-start' \\| 'left' \\| 'left-end'` | `'bottom-start'` | Autocomplete's placement. | 2.25.0 |\n| render-label | `(option: SelectOption \\| SelectGroupOption, selected: boolean) => VNodeChild` | `undefined` | Render function for each option label. | 2.24.0 |\n| render-option | `(info: { node: VNode, option: SelectOption \\| SelectGroupOption, selected: boolean }) => VNodeChild` | `undefined` | Render function for each option. | 2.24.0 |\n| scrollbar-props | `ScrollbarProps` | `undefined` | See [Scrollbar props](scrollbar#Scrollbar-Props) | 2.44.0 |\n| show-empty | `boolean` | `false` | Whether to show menu if there's no option. | 2.37.1 |\n| size | `'small' \\| 'medium' \\| 'large'` | `'medium'` | Autocomplete size. |  |\n| status | `'success' \\| 'warning' \\| 'error'` | `undefined` | Validation status. | 2.27.0 |\n| to | `string \\| HTMLElement \\| false` | `body` | Container node of the menu. `false` will keep it not detached. |  |\n| value | `string` | `undefined` | Input of autocomplete. |  |\n| on-blur | `(event: FocusEvent) => void` | `undefined` | On blur callback function. |  |\n| on-focus | `(event: FocusEvent) => void` | `undefined` | On focus callback function. |  |\n| on-select | `(value: string) => void` | `undefined` | On select callback function. |  |\n| on-update:value | `(value: string \\| null) => void` | `undefined` | On update callback function. |  |\n\n#### AutoCompleteOption Properties\n\n| Name     | Type      | Description                     |\n| -------- | --------- | ------------------------------- |\n| disabled | `boolean` | Whether the option is disabled. |\n| label    | `string`  | Option label value.             |\n| value    | `string`  | Option ID (should be unique).   |\n\n#### AutoCompleteGroupOption Properties\n\n| Name     | Type                                  | Description             |\n| -------- | ------------------------------------- | ----------------------- |\n| children | `Array<string \\| AutoCompleteOption>` | Group children options. |\n| label    | `string`                              | Group label.            |\n| key      | `string \\| number`                    | Unique group key.       |\n| type     | `'group'`                             | Required group type.    |\n\n### AutoComplete Slots\n\n| Name | Parameters | Description | Version |\n| --- | --- | --- | --- |\n| default | `(options: { handleInput: (value: string) => void, handleFocus: function, handleBlur: function, value: string, theme: string \\| null })` | Custom input elements, supplied by the user. |  |\n| empty | `()` | Menu's content to show when there's no option. | 2.37.1 |\n| prefix | `()` | Input's prefix content. |  |\n| suffix | `()` | Input's suffix content. |  |\n\n### AutoComplete Methods\n\n| Name  | Type         | Description              | Version |\n| ----- | ------------ | ------------------------ | ------- |\n| blur  | `() => void` | Blur the input element.  | 2.26.2  |\n| focus | `() => void` | Focus the input element. | 2.26.2  |\n"
  },
  {
    "path": "src/auto-complete/demos/enUS/show-options-by-value.demo.vue",
    "content": "<markdown>\n# Whether to show menu\n\nYour can determine is whether to show menu based on value when it is focused.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { computed, ref } from 'vue'\n\nconst valueRef = ref('')\nconst value = valueRef\nconst options = computed(() => {\n  return ['@gmail.com', '@163.com', '@qq.com'].map((suffix) => {\n    const prefix = valueRef.value.split('@')[0]\n    return {\n      label: prefix + suffix,\n      value: prefix + suffix\n    }\n  })\n})\nfunction getShow(value: string) {\n  if (value === 'a') {\n    return true\n  }\n  return false\n}\n</script>\n\n<template>\n  <n-auto-complete\n    v-model:value=\"value\"\n    :options=\"options\"\n    placeholder=\"Input 'a' to show menu\"\n    :get-show=\"getShow\"\n  />\n</template>\n"
  },
  {
    "path": "src/auto-complete/demos/enUS/size.demo.vue",
    "content": "<markdown>\n# Size\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { computed, ref } from 'vue'\n\nconst valueRef = ref('')\nconst value = valueRef\nconst options = computed(() => {\n  return ['@gmail.com', '@163.com', '@qq.com'].map((suffix) => {\n    const prefix = valueRef.value.split('@')[0]\n    return {\n      label: prefix + suffix,\n      value: prefix + suffix\n    }\n  })\n})\n</script>\n\n<template>\n  <n-space vertical>\n    <n-auto-complete\n      v-model:value=\"value\"\n      :options=\"options\"\n      placeholder=\"Email\"\n      size=\"small\"\n    />\n    <n-auto-complete\n      v-model:value=\"value\"\n      :options=\"options\"\n      placeholder=\"Email\"\n      size=\"medium\"\n    />\n    <n-auto-complete\n      v-model:value=\"value\"\n      :options=\"options\"\n      placeholder=\"Email\"\n      size=\"large\"\n    />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/auto-complete/demos/enUS/status.demo.vue",
    "content": "<markdown>\n# Validation status\n\nValidation status can be applied outside form.\n</markdown>\n\n<template>\n  <n-space vertical>\n    <n-auto-complete status=\"warning\" placeholder=\"\" />\n    <n-auto-complete status=\"error\" placeholder=\"\" />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/auto-complete/demos/zhCN/after-select.demo.vue",
    "content": "<markdown>\n# 选择后的动作\n\n在选中选项后清除内容或者选择后 Blur。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { computed, ref } from 'vue'\n\nconst valueRef = ref('')\nconst value = valueRef\nconst options = computed(() => {\n  return ['@gmail.com', '@163.com', '@qq.com'].map((suffix) => {\n    const value = valueRef.value === null ? '' : valueRef.value\n    const prefix = value.split('@')[0]\n    return {\n      label: prefix + suffix,\n      value: prefix + suffix\n    }\n  })\n})\n</script>\n\n<template>\n  <n-space vertical>\n    <n-auto-complete\n      v-model:value=\"value\"\n      :options=\"options\"\n      clear-after-select\n      placeholder=\"选择后清空\"\n    />\n    <n-auto-complete\n      v-model:value=\"value\"\n      :options=\"options\"\n      blur-after-select\n      placeholder=\"选择后 Blur\"\n    />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/auto-complete/demos/zhCN/append.demo.vue",
    "content": "<markdown>\n# 追加模式\n\n在选中选项后追加到输入框中，而不是直接覆盖，配合 get-show 使用。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { computed, ref } from 'vue'\n\nconst valueRef = ref('')\nconst appendValueRef = ref('')\nconst value = valueRef\nconst options = computed(() => {\n  return ['@gmail.com', '@163.com', '@qq.com'].map((suffix) => {\n    const value = valueRef.value === null ? '' : valueRef.value\n    const prefix = value.split('@')[0]\n    return {\n      label: prefix + suffix,\n      value: prefix + suffix\n    }\n  })\n})\nconst appendValue = appendValueRef\nconst appendOptions = computed(() => {\n  return ['gmail.com', '163.com', 'qq.com'].map((suffix) => {\n    return {\n      label: suffix,\n      value: suffix\n    }\n  })\n})\nfunction getShow(value: string) {\n  if (value.endsWith('@')) {\n    return true\n  }\n  return false\n}\n</script>\n\n<template>\n  <n-space vertical>\n    <n-auto-complete\n      v-model:value=\"value\"\n      :options=\"options\"\n      :append=\"false\"\n      placeholder=\"选择后覆盖\"\n    />\n    <n-auto-complete\n      v-model:value=\"appendValue\"\n      :options=\"appendOptions\"\n      :append=\"true\"\n      :get-show=\"getShow\"\n      placeholder=\"配合 get-show 选择后追加\"\n    />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/auto-complete/demos/zhCN/basic.demo.vue",
    "content": "<markdown>\n# 基础用法\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { computed, ref } from 'vue'\n\nconst valueRef = ref('')\nconst value = valueRef\nconst options = computed(() => {\n  return ['@gmail.com', '@163.com', '@qq.com'].map((suffix) => {\n    const prefix = valueRef.value.split('@')[0]\n    return {\n      label: prefix + suffix,\n      value: prefix + suffix\n    }\n  })\n})\n</script>\n\n<template>\n  <n-auto-complete\n    v-model:value=\"value\"\n    :input-props=\"{\n      autocomplete: 'disabled',\n    }\"\n    :options=\"options\"\n    placeholder=\"邮箱\"\n    clearable\n  />\n</template>\n"
  },
  {
    "path": "src/auto-complete/demos/zhCN/custom-input.demo.vue",
    "content": "<markdown>\n# 自定义输入元素\n\n你可以替换 AutoComplete 的输入元素。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { computed, ref } from 'vue'\n\nconst valueRef = ref('')\nconst value = valueRef\nconst options = computed(() => {\n  return ['@gmail.com', '@163.com', '@qq.com'].map((suffix) => {\n    const prefix = valueRef.value.split('@')[0]\n    return {\n      label: prefix + suffix,\n      value: prefix + suffix\n    }\n  })\n})\n</script>\n\n<template>\n  <n-auto-complete v-model:value=\"value\" :options=\"options\">\n    <template\n      #default=\"{ handleInput, handleBlur, handleFocus, value: slotValue }\"\n    >\n      <n-input\n        type=\"textarea\"\n        :value=\"slotValue\"\n        placeholder=\"邮箱\"\n        @input=\"handleInput\"\n        @focus=\"handleFocus\"\n        @blur=\"handleBlur\"\n      />\n    </template>\n  </n-auto-complete>\n</template>\n"
  },
  {
    "path": "src/auto-complete/demos/zhCN/customized-rendering.demo.vue",
    "content": "<markdown>\n# 自定义渲染\n\n使用 `render-label` 自定义选项内容。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { SelectOption } from 'naive-ui'\nimport type { VNodeChild } from 'vue'\nimport { NTag } from 'naive-ui'\nimport { computed, h, ref } from 'vue'\n\nconst valueRef = ref('')\nconst value = valueRef\nfunction renderLabel(option: SelectOption): VNodeChild {\n  return [\n    option.label as string,\n    ' ',\n    h(NTag, { size: 'small', type: 'info' }, { default: () => 'Email' })\n  ]\n}\nconst options = computed(() => {\n  return ['@gmail.com', '@163.com', '@qq.com'].map((suffix) => {\n    const prefix = valueRef.value.split('@')[0]\n    return {\n      label: prefix + suffix,\n      value: prefix + suffix\n    }\n  })\n})\n</script>\n\n<template>\n  <n-auto-complete\n    v-model:value=\"value\"\n    :options=\"options\"\n    placeholder=\"邮箱\"\n    :render-label=\"renderLabel\"\n  />\n</template>\n"
  },
  {
    "path": "src/auto-complete/demos/zhCN/group.demo.vue",
    "content": "<markdown>\n# 成组\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { computed, ref } from 'vue'\n\nconst valueRef = ref('')\nconst value = valueRef\nconst options = computed(() => {\n  return [\n    ['谷歌', '@gmail.com'],\n    ['网易', '@163.com'],\n    ['腾讯', '@qq.com']\n  ].map((emailInfo) => {\n    return {\n      type: 'group',\n      label: emailInfo[0],\n      key: emailInfo[0],\n      children: [valueRef.value.split('@')[0] + emailInfo[1]]\n    }\n  })\n})\n</script>\n\n<template>\n  <n-auto-complete\n    v-model:value=\"value\"\n    :options=\"options\"\n    placeholder=\"邮箱\"\n  />\n</template>\n"
  },
  {
    "path": "src/auto-complete/demos/zhCN/index.demo-entry.md",
    "content": "# 自动填充 Auto Complete\n\n用来当搜索提示或者类似的东西。\n\n## 演示\n\n```demo\nbasic.vue\nsize.vue\ngroup.vue\ncustom-input.vue\nafter-select.vue\nshow-options-by-value.vue\ncustomized-rendering.vue\nstatus.vue\nappend.vue\n```\n\n## API\n\n### AutoComplete Props\n\n| 名称 | 类型 | 默认值 | 说明 | 版本 |\n| --- | --- | --- | --- | --- |\n| append | `boolean` | `false` | 选中后是否追加 | 2.38.0 |\n| blur-after-select | `boolean` | `false` | 选中后是否 blur |  |\n| bordered | `boolean` | `undefined` | 是否显示输入框边框 |  |\n| clear-after-select | `boolean` | `false` | 选中后是否清空 |  |\n| clearable | `boolean` | `false` | 自动填充是否支持可清除 |  |\n| default-value | `string` | `null` | 自动填充的默认值 |  |\n| disabled | `boolean` | `false` | 自动填充是否禁用 |  |\n| get-show | `(value: string) => boolean` | `undefined` | 根据输入值在聚焦的状态中决定是否显示菜单 |  |\n| input-props | `InputHTMLAttributes` | `undefined` | 自动填充中 input 元素的属性 |  |\n| loading | `boolean` | `false` | 是否展示加载状态 |  |\n| menu-props | `HTMLAttributes` | `undefined` | 菜单的 DOM 属性 | 2.32.2 |\n| options | `Array<string \\| AutoCompleteOption \\| AutoCompleteGroupOption>` | `[]` | 自动填充的自定义选项 |  |\n| placeholder | `string` | `'请输入'` | 自动填充的提示信息 |  |\n| placement | `'top-start' \\| 'top' \\| 'top-end' \\| 'right-start' \\| 'right' \\| 'right-end' \\| 'bottom-start' \\| 'bottom' \\| 'bottom-end' \\| 'left-start' \\| 'left' \\| 'left-end'` | `'bottom-start'` | 自动填充的弹出位置 | 2.25.0 |\n| render-label | `(option: SelectOption \\| SelectGroupOption, selected: boolean) => VNodeChild` | `undefined` | 选项标签渲染函数 | 2.24.0 |\n| render-option | `(info: { node: VNode, option: SelectOption \\| SelectGroupOption, selected: boolean }) => VNodeChild` | `undefined` | 选项的渲染函数 | 2.24.0 |\n| scrollbar-props | `ScrollbarProps` | `undefined` | See [Scrollbar props](scrollbar#Scrollbar-Props) | 2.44.0 |\n| show-empty | `boolean` | `false` | 在没有选项的时候是否展示菜单 | 2.37.1 |\n| size | `'small' \\| 'medium' \\| 'large'` | `'medium'` | 自动填充的尺寸大小 |  |\n| status | `'success' \\| 'warning' \\| 'error'` | `undefined` | 验证状态 | 2.27.0 |\n| to | `string \\| HTMLElement \\| false` | `body` | 菜单的容器节点，`false` 会待在原地 |  |\n| value | `string` | `undefined` | 自动填充的数据用户可控 |  |\n| z-index | `number` | `undefined` | 菜单的 z-index |  |\n| on-blur | `(event: FocusEvent) => void` | `undefined` | blur 时触发的回调函数 |  |\n| on-focus | `(event: FocusEvent) => void` | `undefined` | focus 时触发的回调函数 |  |\n| on-select | `(value: string) => void` | `undefined` | select 选中时触发的回调函数 |  |\n| on-update:value | `(value: string \\| null) => void` | `undefined` | 可控数据更新时触发的回调函数 |  |\n\n#### AutoCompleteOption Properties\n\n| 名称     | 类型      | 介绍            |\n| -------- | --------- | --------------- |\n| disabled | `boolean` | 是否禁用        |\n| label    | `string`  | 显示的 label 值 |\n| value    | `string`  | 需要唯一        |\n\n#### AutoCompleteGroupOption Properties\n\n| 名称 | 类型 | 介绍 |\n| --- | --- | --- |\n| children | `Array<string \\| AutoCompleteOption>` | AutoCompleteGroupOption 的 children 项 |\n| label | `string` | AutoCompleteGroupOption 的名字 |\n| key | `string \\| number` | AutoCompleteGroupOption 的 key |\n| type | `'group'` | AutoCompleteGroupOption 的类型 |\n\n### AutoComplete Slots\n\n| 名称 | 参数 | 说明 | 版本 |\n| --- | --- | --- | --- |\n| default | `(options: { handleInput: (value: string) => void, handleFocus: function, handleBlur: function, value: string, theme: string \\| null })` | 自定义输入元素，由用户填充 |  |\n| empty | `()` | 菜单为空时候的内容 | 2.37.1 |\n| prefix | `()` | 输入框头部内容 |  |\n| suffix | `()` | 输入框尾部内容 |  |\n\n### AutoComplete Methods\n\n| 名称  | 类型         | 说明             | 版本   |\n| ----- | ------------ | ---------------- | ------ |\n| blur  | `() => void` | Blur input 元素  | 2.26.2 |\n| focus | `() => void` | Focus input 元素 | 2.26.2 |\n"
  },
  {
    "path": "src/auto-complete/demos/zhCN/show-options-by-value.demo.vue",
    "content": "<markdown>\n# 是否显示菜单\n\n你可以根据输入的值来决定是否显示菜单\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { computed, ref } from 'vue'\n\nconst valueRef = ref('')\nconst value = valueRef\nconst options = computed(() => {\n  return ['@gmail.com', '@163.com', '@qq.com'].map((suffix) => {\n    const prefix = valueRef.value.split('@')[0]\n    return {\n      label: prefix + suffix,\n      value: prefix + suffix\n    }\n  })\n})\nfunction getShow(value: string) {\n  if (value === 'a') {\n    return true\n  }\n  return false\n}\n</script>\n\n<template>\n  <n-auto-complete\n    v-model:value=\"value\"\n    :options=\"options\"\n    placeholder=\"输入 a 显示菜单\"\n    :get-show=\"getShow\"\n  />\n</template>\n"
  },
  {
    "path": "src/auto-complete/demos/zhCN/size.demo.vue",
    "content": "<markdown>\n# 尺寸\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { computed, ref } from 'vue'\n\nconst valueRef = ref('')\nconst value = valueRef\nconst options = computed(() => {\n  return ['@gmail.com', '@163.com', '@qq.com'].map((suffix) => {\n    const prefix = valueRef.value.split('@')[0]\n    return {\n      label: prefix + suffix,\n      value: prefix + suffix\n    }\n  })\n})\n</script>\n\n<template>\n  <n-space vertical>\n    <n-auto-complete\n      v-model:value=\"value\"\n      :options=\"options\"\n      placeholder=\"邮箱\"\n      size=\"small\"\n    />\n    <n-auto-complete\n      v-model:value=\"value\"\n      :options=\"options\"\n      placeholder=\"邮箱\"\n      size=\"medium\"\n    />\n    <n-auto-complete\n      v-model:value=\"value\"\n      :options=\"options\"\n      placeholder=\"邮箱\"\n      size=\"large\"\n    />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/auto-complete/demos/zhCN/status.demo.vue",
    "content": "<markdown>\n# 验证状态\n\n输入的验证状态可以脱离表单使用。\n</markdown>\n\n<template>\n  <n-space vertical>\n    <n-auto-complete status=\"warning\" placeholder=\"\" />\n    <n-auto-complete status=\"error\" placeholder=\"\" />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/auto-complete/index.ts",
    "content": "export { autoCompleteProps, default as NAutoComplete } from './src/AutoComplete'\nexport type { AutoCompleteProps, AutoCompleteSlots } from './src/AutoComplete'\nexport type {\n  AutoCompleteDefaultSlotProps,\n  AutoCompleteGroupOption,\n  AutoCompleteInst,\n  AutoCompleteOption\n} from './src/interface'\nexport type * from './src/public-types'\n"
  },
  {
    "path": "src/auto-complete/src/AutoComplete.tsx",
    "content": "import type { TreeNode } from 'treemate'\nimport type {\n  CSSProperties,\n  HTMLAttributes,\n  InputHTMLAttributes,\n  PropType,\n  SlotsType,\n  VNode\n} from 'vue'\nimport type { FollowerPlacement } from 'vueuc'\nimport type { InternalSelectMenuRef, ScrollbarProps } from '../../_internal'\nimport type {\n  RenderLabel,\n  RenderOption\n} from '../../_internal/select-menu/src/interface'\nimport type { ThemeProps } from '../../_mixins'\nimport type { ExtractPublicPropTypes, MaybeArray } from '../../_utils'\nimport type { FormValidationStatus } from '../../form/src/public-types'\nimport type { InputInst } from '../../input'\nimport type {\n  SelectBaseOption,\n  SelectGroupOption,\n  SelectIgnoredOption\n} from '../../select/src/interface'\nimport type { AutoCompleteTheme } from '../styles'\nimport type {\n  AutoCompleteDefaultSlotProps,\n  AutoCompleteInst,\n  AutoCompleteOption,\n  AutoCompleteOptions,\n  OnSelect,\n  OnSelectImpl,\n  OnUpdateImpl,\n  OnUpdateValue\n} from './interface'\nimport type { AutoCompleteSize } from './public-types'\nimport { getPreciseEventTarget } from 'seemly'\nimport { createTreeMate } from 'treemate'\nimport { clickoutside } from 'vdirs'\nimport { useIsMounted, useMergedState } from 'vooks'\nimport {\n  computed,\n  defineComponent,\n  h,\n  ref,\n  toRef,\n  Transition,\n  watchEffect,\n  withDirectives\n} from 'vue'\nimport { VBinder, VFollower, VTarget } from 'vueuc'\nimport { NInternalSelectMenu } from '../../_internal'\nimport { useConfig, useFormItem, useTheme, useThemeClass } from '../../_mixins'\nimport {\n  call,\n  getFirstSlotVNodeWithTypedProps,\n  useAdjustedTo,\n  warnOnce\n} from '../../_utils'\nimport { NInput } from '../../input'\nimport { createTmOptions } from '../../select/src/utils'\nimport { autoCompleteLight } from '../styles'\nimport style from './styles/index.cssr'\nimport { mapAutoCompleteOptionsToSelectOptions } from './utils'\n\nexport const autoCompleteProps = {\n  ...(useTheme.props as ThemeProps<AutoCompleteTheme>),\n  to: useAdjustedTo.propTo,\n  menuProps: Object as PropType<HTMLAttributes>,\n  append: Boolean,\n  bordered: {\n    type: Boolean as PropType<boolean | undefined>,\n    default: undefined\n  },\n  clearable: {\n    type: Boolean,\n    default: undefined\n  },\n  defaultValue: {\n    type: String as PropType<string | null>,\n    default: null\n  },\n  loading: {\n    type: Boolean,\n    default: undefined\n  },\n  disabled: {\n    type: Boolean as PropType<boolean | undefined>,\n    default: undefined\n  },\n  placeholder: String,\n  placement: {\n    type: String as PropType<FollowerPlacement>,\n    default: 'bottom-start'\n  },\n  value: String,\n  blurAfterSelect: Boolean,\n  clearAfterSelect: Boolean,\n  getShow: Function as PropType<(inputValue: string) => boolean>,\n  showEmpty: Boolean,\n  inputProps: Object as PropType<InputHTMLAttributes>,\n  renderOption: Function as PropType<RenderOption>,\n  renderLabel: Function as PropType<RenderLabel>,\n  size: String as PropType<AutoCompleteSize>,\n  options: {\n    type: Array as PropType<AutoCompleteOptions>,\n    default: () => []\n  },\n  zIndex: Number,\n  status: String as PropType<FormValidationStatus>,\n  'onUpdate:value': [Function, Array] as PropType<MaybeArray<OnUpdateValue>>,\n  onUpdateValue: [Function, Array] as PropType<MaybeArray<OnUpdateValue>>,\n  onSelect: [Function, Array] as PropType<MaybeArray<OnSelect>>,\n  onBlur: [Function, Array] as PropType<MaybeArray<(e: FocusEvent) => void>>,\n  onFocus: [Function, Array] as PropType<MaybeArray<(e: FocusEvent) => void>>,\n  scrollbarProps: Object as PropType<ScrollbarProps>,\n  // deprecated\n  onInput: [Function, Array] as PropType<MaybeArray<OnUpdateValue> | undefined>\n} as const\n\nexport type AutoCompleteProps = ExtractPublicPropTypes<typeof autoCompleteProps>\n\nexport interface AutoCompleteSlots {\n  default?: (options: AutoCompleteDefaultSlotProps) => VNode[]\n  empty?: () => VNode[]\n  prefix?: () => VNode[]\n  suffix?: () => VNode[]\n}\n\nexport default defineComponent({\n  name: 'AutoComplete',\n  props: autoCompleteProps,\n  slots: Object as SlotsType<AutoCompleteSlots>,\n  setup(props) {\n    if (__DEV__) {\n      watchEffect(() => {\n        if (props.onInput !== undefined) {\n          warnOnce(\n            'auto-complete',\n            '`on-input` is deprecated, please use `on-update:value` instead.'\n          )\n        }\n      })\n    }\n    const {\n      mergedBorderedRef,\n      namespaceRef,\n      mergedClsPrefixRef,\n      inlineThemeDisabled,\n      mergedComponentPropsRef\n    } = useConfig(props)\n    const formItem = useFormItem(props, {\n      mergedSize: (NFormItem) => {\n        const { size } = props\n        if (size)\n          return size\n        const { mergedSize: formItemSize } = NFormItem || {}\n        if (formItemSize?.value)\n          return formItemSize.value as AutoCompleteSize\n        const configSize = mergedComponentPropsRef?.value?.AutoComplete?.size\n        if (configSize)\n          return configSize\n        return 'medium'\n      }\n    })\n    const { mergedSizeRef, mergedDisabledRef, mergedStatusRef } = formItem\n    const triggerElRef = ref<HTMLElement | null>(null)\n    const menuInstRef = ref<InternalSelectMenuRef | null>(null)\n\n    const uncontrolledValueRef = ref(props.defaultValue)\n    const controlledValueRef = toRef(props, 'value')\n    const mergedValueRef = useMergedState(\n      controlledValueRef,\n      uncontrolledValueRef\n    )\n    const canBeActivatedRef = ref(false)\n    const isComposingRef = ref(false)\n\n    const themeRef = useTheme(\n      'AutoComplete',\n      '-auto-complete',\n      style,\n      autoCompleteLight,\n      props,\n      mergedClsPrefixRef\n    )\n    const selectOptionsRef = computed(() => {\n      return mapAutoCompleteOptionsToSelectOptions(props.options)\n    })\n    const mergedShowOptionsRef = computed(() => {\n      const { getShow } = props\n      if (getShow) {\n        return getShow(mergedValueRef.value || '')\n      }\n      return !!mergedValueRef.value\n    })\n    const activeRef = computed(() => {\n      return (\n        mergedShowOptionsRef.value\n        && canBeActivatedRef.value\n        && (props.showEmpty ? true : !!selectOptionsRef.value.length)\n      )\n    })\n    const treeMateRef = computed(() =>\n      createTreeMate<SelectBaseOption, SelectGroupOption, SelectIgnoredOption>(\n        selectOptionsRef.value,\n        createTmOptions('value', 'children')\n      )\n    )\n    function doUpdateValue(value: string | null): void {\n      const { 'onUpdate:value': _onUpdateValue, onUpdateValue, onInput } = props\n      const { nTriggerFormInput, nTriggerFormChange } = formItem\n      if (onUpdateValue)\n        call(onUpdateValue as OnUpdateImpl, value)\n      if (_onUpdateValue)\n        call(_onUpdateValue as OnUpdateImpl, value)\n      if (onInput)\n        call(onInput as OnUpdateImpl, value)\n      uncontrolledValueRef.value = value\n      nTriggerFormInput()\n      nTriggerFormChange()\n    }\n    function doSelect(value: string | number): void {\n      const { onSelect } = props\n      const { nTriggerFormInput, nTriggerFormChange } = formItem\n      if (onSelect)\n        call(onSelect as OnSelectImpl, value)\n      nTriggerFormInput()\n      nTriggerFormChange()\n    }\n    function doBlur(e: FocusEvent): void {\n      const { onBlur } = props\n      const { nTriggerFormBlur } = formItem\n      if (onBlur)\n        call(onBlur, e)\n      nTriggerFormBlur()\n    }\n    function doFocus(e: FocusEvent): void {\n      const { onFocus } = props\n      const { nTriggerFormFocus } = formItem\n      if (onFocus)\n        call(onFocus, e)\n      nTriggerFormFocus()\n    }\n    function handleCompositionStart(): void {\n      isComposingRef.value = true\n    }\n    function handleCompositionEnd(): void {\n      window.setTimeout(() => {\n        isComposingRef.value = false\n      }, 0)\n    }\n    function handleKeyDown(e: KeyboardEvent): void {\n      switch (e.key) {\n        case 'Enter':\n          if (!isComposingRef.value) {\n            const pendingOptionTmNode = menuInstRef.value?.getPendingTmNode()\n            if (pendingOptionTmNode) {\n              select(pendingOptionTmNode.rawNode as AutoCompleteOption)\n              e.preventDefault()\n            }\n          }\n          break\n        case 'ArrowDown':\n          menuInstRef.value?.next()\n          break\n        case 'ArrowUp':\n          menuInstRef.value?.prev()\n          break\n      }\n    }\n    function select(option: AutoCompleteOption): void {\n      if (option?.value !== undefined) {\n        doSelect(option.value)\n        if (props.clearAfterSelect) {\n          doUpdateValue(null)\n        }\n        else if (option.label !== undefined) {\n          doUpdateValue(\n            props.append\n              ? `${mergedValueRef.value}${option.label}`\n              : option.label\n          )\n        }\n        canBeActivatedRef.value = false\n        if (props.blurAfterSelect) {\n          blur()\n        }\n      }\n    }\n    function handleClear(): void {\n      doUpdateValue(null)\n    }\n    function handleFocus(e: FocusEvent): void {\n      canBeActivatedRef.value = true\n      doFocus(e)\n    }\n    function handleBlur(e: FocusEvent): void {\n      canBeActivatedRef.value = false\n      doBlur(e)\n    }\n    function handleInput(value: string): void {\n      canBeActivatedRef.value = true\n      doUpdateValue(value)\n    }\n    function handleToggle(option: TreeNode<SelectBaseOption>): void {\n      select(option.rawNode as AutoCompleteOption)\n    }\n    function handleClickOutsideMenu(e: MouseEvent): void {\n      if (\n        !triggerElRef.value?.contains(getPreciseEventTarget(e) as Node | null)\n      ) {\n        canBeActivatedRef.value = false\n      }\n    }\n    function blur(): void {\n      if (triggerElRef.value?.contains(document.activeElement)) {\n        ;(document.activeElement as HTMLElement)?.blur()\n      }\n    }\n    const cssVarsRef = computed(() => {\n      const {\n        common: { cubicBezierEaseInOut },\n        self: { menuBoxShadow }\n      } = themeRef.value\n      return {\n        '--n-menu-box-shadow': menuBoxShadow,\n        '--n-bezier': cubicBezierEaseInOut\n      }\n    })\n    const themeClassHandle = inlineThemeDisabled\n      ? useThemeClass('auto-complete', undefined, cssVarsRef, props)\n      : undefined\n    const inputInstRef = ref<InputInst | null>(null)\n    const exposedMethods: AutoCompleteInst = {\n      focus: () => {\n        inputInstRef.value?.focus()\n      },\n      blur: () => {\n        inputInstRef.value?.blur()\n      }\n    }\n    return {\n      focus: exposedMethods.focus,\n      blur: exposedMethods.blur,\n      inputInstRef,\n      uncontrolledValue: uncontrolledValueRef,\n      mergedValue: mergedValueRef,\n      isMounted: useIsMounted(),\n      adjustedTo: useAdjustedTo(props),\n      menuInstRef,\n      triggerElRef,\n      treeMate: treeMateRef,\n      mergedSize: mergedSizeRef,\n      mergedDisabled: mergedDisabledRef,\n      active: activeRef,\n      mergedStatus: mergedStatusRef,\n      handleClear,\n      handleFocus,\n      handleBlur,\n      handleInput,\n      handleToggle,\n      handleClickOutsideMenu,\n      handleCompositionStart,\n      handleCompositionEnd,\n      handleKeyDown,\n      mergedTheme: themeRef,\n      cssVars: inlineThemeDisabled ? undefined : cssVarsRef,\n      themeClass: themeClassHandle?.themeClass,\n      onRender: themeClassHandle?.onRender,\n      mergedBordered: mergedBorderedRef,\n      namespace: namespaceRef,\n      mergedClsPrefix: mergedClsPrefixRef\n    }\n  },\n  render() {\n    const { mergedClsPrefix } = this\n    return (\n      <div\n        class={`${mergedClsPrefix}-auto-complete`}\n        ref=\"triggerElRef\"\n        onKeydown={this.handleKeyDown}\n        onCompositionstart={this.handleCompositionStart}\n        onCompositionend={this.handleCompositionEnd}\n      >\n        <VBinder>\n          {{\n            default: () => [\n              <VTarget>\n                {{\n                  default: () => {\n                    const defaultSlot = this.$slots.default\n                    if (defaultSlot) {\n                      return getFirstSlotVNodeWithTypedProps(\n                        'default',\n                        defaultSlot,\n                        {\n                          handleInput: this.handleInput,\n                          handleFocus: this.handleFocus,\n                          handleBlur: this.handleBlur,\n                          value: this.mergedValue\n                        }\n                      )\n                    }\n                    const { mergedTheme } = this\n                    return (\n                      <NInput\n                        ref=\"inputInstRef\"\n                        status={this.mergedStatus}\n                        theme={mergedTheme.peers.Input}\n                        themeOverrides={mergedTheme.peerOverrides.Input}\n                        bordered={this.mergedBordered}\n                        value={this.mergedValue}\n                        placeholder={this.placeholder}\n                        size={this.mergedSize}\n                        disabled={this.mergedDisabled}\n                        clearable={this.clearable}\n                        loading={this.loading}\n                        inputProps={this.inputProps}\n                        onClear={this.handleClear}\n                        onFocus={this.handleFocus}\n                        onUpdateValue={this.handleInput}\n                        onBlur={this.handleBlur}\n                      >\n                        {{\n                          suffix: () => this.$slots.suffix?.(),\n                          prefix: () => this.$slots.prefix?.()\n                        }}\n                      </NInput>\n                    )\n                  }\n                }}\n              </VTarget>,\n              <VFollower\n                show={this.active}\n                to={this.adjustedTo}\n                containerClass={this.namespace}\n                zIndex={this.zIndex}\n                teleportDisabled={this.adjustedTo === useAdjustedTo.tdkey}\n                placement={this.placement}\n                width=\"target\"\n              >\n                {{\n                  default: () => (\n                    <Transition\n                      name=\"fade-in-scale-up-transition\"\n                      appear={this.isMounted}\n                    >\n                      {{\n                        default: () => {\n                          this.onRender?.()\n                          if (!this.active)\n                            return null\n                          const { menuProps } = this\n                          return withDirectives(\n                            <NInternalSelectMenu\n                              {...(menuProps as any)}\n                              clsPrefix={mergedClsPrefix}\n                              ref=\"menuInstRef\"\n                              theme={this.mergedTheme.peers.InternalSelectMenu}\n                              themeOverrides={\n                                this.mergedTheme.peerOverrides\n                                  .InternalSelectMenu\n                              }\n                              auto-pending\n                              class={[\n                                `${mergedClsPrefix}-auto-complete-menu`,\n                                this.themeClass,\n                                menuProps?.class\n                              ]}\n                              style={[\n                                menuProps?.style,\n                                this.cssVars as CSSProperties\n                              ]}\n                              treeMate={this.treeMate}\n                              multiple={false}\n                              renderLabel={this.renderLabel}\n                              renderOption={this.renderOption}\n                              size=\"medium\"\n                              onToggle={this.handleToggle}\n                              scrollbarProps={this.scrollbarProps}\n                            >\n                              {{ empty: () => this.$slots.empty?.() }}\n                            </NInternalSelectMenu>,\n                            [\n                              [\n                                clickoutside,\n                                this.handleClickOutsideMenu,\n                                undefined as unknown as string,\n                                { capture: true }\n                              ]\n                            ]\n                          )\n                        }\n                      }}\n                    </Transition>\n                  )\n                }}\n              </VFollower>\n            ]\n          }}\n        </VBinder>\n      </div>\n    )\n  }\n})\n"
  },
  {
    "path": "src/auto-complete/src/interface.ts",
    "content": "import type {\n  SelectBaseOption,\n  SelectGroupOption\n} from '../../select/src/interface'\n\nexport type AutoCompleteOption = SelectBaseOption<string, string>\nexport interface AutoCompleteGroupOption\n  extends Omit<SelectGroupOption, 'children'> {\n  children: AutoCompleteOptions\n}\n\nexport type AutoCompleteOptions = Array<\n  AutoCompleteOption | AutoCompleteGroupOption | string\n>\n\nexport type OnUpdateValue = (value: string & (string | null)) => void\nexport type OnUpdateImpl = (value: string | null) => void\nexport type OnSelect = (value: string & number) => void\nexport type OnSelectImpl = (value: string | number) => void\n\nexport interface AutoCompleteInst {\n  focus: () => void\n  blur: () => void\n}\n\nexport interface AutoCompleteDefaultSlotProps {\n  handleInput: (value: string) => void\n  handleFocus: (e: FocusEvent) => void\n  handleBlur: (e: FocusEvent) => void\n  value: string | null\n}\n"
  },
  {
    "path": "src/auto-complete/src/public-types.ts",
    "content": "export type AutoCompleteSize = 'small' | 'medium' | 'large'\n"
  },
  {
    "path": "src/auto-complete/src/styles/index.cssr.ts",
    "content": "import { fadeInScaleUpTransition } from '../../../_styles/transitions/fade-in-scale-up.cssr'\nimport { c, cB } from '../../../_utils/cssr'\n\n// vars:\n// --n-bezier\n// --n-menu-box-shadow\nexport default c([\n  cB('auto-complete', `\n    z-index: auto;\n    position: relative;\n    display: inline-flex;\n    width: 100%;\n  `),\n  cB('auto-complete-menu', `\n    margin: 4px 0;\n    box-shadow: var(--n-menu-box-shadow);\n  `, [\n    fadeInScaleUpTransition({\n      originalTransition: 'background-color .3s var(--n-bezier), box-shadow .3s var(--n-bezier)'\n    })\n  ])\n])\n"
  },
  {
    "path": "src/auto-complete/src/utils.ts",
    "content": "import type {\n  SelectBaseOption,\n  SelectGroupOption,\n  SelectMixedOption\n} from '../../select/src/interface'\nimport type {\n  AutoCompleteGroupOption,\n  AutoCompleteOption,\n  AutoCompleteOptions\n} from './interface'\n\nexport function mapAutoCompleteOptionsToSelectOptions(\n  options: AutoCompleteOptions\n): SelectMixedOption[] {\n  return options.map(convertAutoCompleteOptionToSelectOption)\n}\n\nfunction convertAutoCompleteOptionToSelectOption(\n  option: AutoCompleteOption | AutoCompleteGroupOption | string\n): SelectMixedOption {\n  if (typeof option === 'string') {\n    return {\n      label: option,\n      value: option\n    }\n  }\n  else if (option.type === 'group') {\n    const groupOption: SelectGroupOption = {\n      type: 'group',\n      label: option.label ?? (option.name as any),\n      value: option.value ?? (option.name as any),\n      key: (option.key || option.name) as any,\n      children: (option.children as Array<string | AutoCompleteOption>).map(\n        groupOption =>\n          convertAutoCompleteOptionToSelectOption(\n            groupOption\n          ) as SelectBaseOption\n      )\n    }\n    return groupOption\n  }\n  else {\n    return option as SelectMixedOption\n  }\n}\n"
  },
  {
    "path": "src/auto-complete/styles/dark.ts",
    "content": "import type { AutoCompleteTheme } from './light'\nimport { internalSelectMenuDark } from '../../_internal/select-menu/styles'\nimport { commonDark } from '../../_styles/common'\nimport { inputDark } from '../../input/styles'\nimport { self } from './light'\n\nconst autoCompleteDark: AutoCompleteTheme = {\n  name: 'AutoComplete',\n  common: commonDark,\n  peers: {\n    InternalSelectMenu: internalSelectMenuDark,\n    Input: inputDark\n  },\n  self\n}\n\nexport default autoCompleteDark\n"
  },
  {
    "path": "src/auto-complete/styles/index.ts",
    "content": "export { default as autoCompleteDark } from './dark'\nexport { default as autoCompleteLight } from './light'\nexport type { AutoCompleteTheme, AutoCompleteThemeVars } from './light'\n"
  },
  {
    "path": "src/auto-complete/styles/light.ts",
    "content": "import type { ThemeCommonVars } from '../../_styles/common'\nimport { internalSelectMenuLight } from '../../_internal/select-menu/styles'\nimport { createTheme } from '../../_mixins'\nimport { commonLight } from '../../_styles/common'\nimport { inputLight } from '../../input/styles'\n\nexport function self(vars: ThemeCommonVars) {\n  const { boxShadow2 } = vars\n  return {\n    menuBoxShadow: boxShadow2\n  }\n}\n\nconst autoCompleteLight = createTheme({\n  name: 'AutoComplete',\n  common: commonLight,\n  peers: {\n    InternalSelectMenu: internalSelectMenuLight,\n    Input: inputLight\n  },\n  self\n})\n\nexport default autoCompleteLight\nexport type AutoCompleteTheme = typeof autoCompleteLight\nexport type AutoCompleteThemeVars = ReturnType<typeof self>\n"
  },
  {
    "path": "src/auto-complete/tests/AutoComplete.spec.ts",
    "content": "import type { AutoCompleteProps } from '../index'\nimport { mount } from '@vue/test-utils'\nimport { NAutoComplete } from '../index'\n\ndescribe('n-auto-complete', () => {\n  it('should work with import on demand', () => {\n    mount(NAutoComplete)\n  })\n\n  it('should work with `clearable` prop', async () => {\n    const wrapper = mount(NAutoComplete)\n    expect(wrapper.find('.n-base-clear').exists()).not.toBe(true)\n    await wrapper.setProps({\n      clearable: true\n    })\n    expect(wrapper.find('.n-base-clear').exists()).toBe(true)\n    wrapper.unmount()\n  })\n\n  it('should work with `disabled` prop', async () => {\n    const wrapper = mount(NAutoComplete)\n    expect(wrapper.find('.n-input').classes()).not.toContain(\n      'n-input--disabled'\n    )\n    await wrapper.setProps({\n      disabled: true\n    })\n    expect(wrapper.find('.n-input').classes()).toContain('n-input--disabled')\n    wrapper.unmount()\n  })\n\n  it('should work with `loading` prop', async () => {\n    const options: AutoCompleteProps['options'] = [\n      '@gmail.com',\n      '@163.com',\n      '@qq.com'\n    ].map((suffix) => {\n      const prefix = 'test'\n      return {\n        label: prefix + suffix,\n        value: prefix + suffix\n      }\n    })\n    const wrapper = mount(NAutoComplete, {\n      props: {\n        options\n      }\n    })\n    expect(wrapper.find('.n-base-loading__container').exists()).toBe(false)\n    await wrapper.setProps({ loading: true })\n    expect(wrapper.find('.n-base-loading__container').exists()).toBe(true)\n    wrapper.unmount()\n  })\n\n  it('should work with `placeholder` prop', async () => {\n    const wrapper = mount(NAutoComplete)\n    expect(wrapper.find('input').attributes('placeholder')).toBe('Please Input')\n    await wrapper.setProps({\n      placeholder: 'test-placeholder'\n    })\n    expect(wrapper.find('input').attributes('placeholder')).toBe(\n      'test-placeholder'\n    )\n    wrapper.unmount()\n  })\n\n  it('should work with `size` prop', async () => {\n    ;(['small', 'medium', 'large'] as const).forEach((size) => {\n      const wrapper = mount(NAutoComplete, { props: { size } })\n      expect(wrapper.find('.n-input').attributes('style')).toMatchSnapshot()\n      wrapper.unmount()\n    })\n  })\n\n  it('should work with `getShow` prop', async () => {\n    const options: AutoCompleteProps['options'] = [\n      '@gmail.com',\n      '@163.com',\n      '@qq.com'\n    ].map((suffix) => {\n      const prefix = 'test'\n      return {\n        label: prefix + suffix,\n        value: prefix + suffix\n      }\n    })\n    const wrapper = mount(NAutoComplete)\n    await wrapper.setProps({\n      getShow: (value: string | null) => {\n        if (value === 'a') {\n          return true\n        }\n        return false\n      },\n      options\n    })\n    expect(document.querySelector('.n-auto-complete-menu')).toEqual(null)\n    wrapper.find('input').setValue('a')\n    await wrapper.find('input').trigger('focus')\n    expect(document.querySelector('.n-auto-complete-menu')).not.toEqual(null)\n    wrapper.unmount()\n  })\n\n  it('should work with `append` prop and `getShow` prop', async () => {\n    const options: AutoCompleteProps['options'] = [\n      'gmail.com',\n      '163.com',\n      'qq.com'\n    ].map((suffix) => {\n      return {\n        label: suffix,\n        value: suffix\n      }\n    })\n    const wrapper = mount(NAutoComplete)\n    await wrapper.setProps({\n      getShow: (value: string | null) => {\n        return !!value?.endsWith('@')\n      },\n      options\n    })\n    expect(document.querySelector('.n-auto-complete-menu')).toEqual(null)\n    wrapper.find('input').setValue('@')\n    await wrapper.find('input').trigger('focus')\n    expect(document.querySelector('.n-auto-complete-menu')).not.toEqual(null)\n    wrapper.unmount()\n  })\n\n  it('should work with `input-props` prop', async () => {\n    const wrapper = mount(NAutoComplete, {\n      props: {\n        inputProps: {\n          id: 'input',\n          max: '10'\n        }\n      }\n    })\n    expect(wrapper.find('input').attributes('max')).toEqual('10')\n    wrapper.unmount()\n  })\n\n  it('should work with `on-blur` prop', async () => {\n    const onBlur = vi.fn()\n    const wrapper = mount(NAutoComplete, {\n      props: { onBlur }\n    })\n    await wrapper.find('input').trigger('focus')\n    await wrapper.find('input').trigger('blur')\n    expect(onBlur).toHaveBeenCalled()\n    wrapper.unmount()\n  })\n\n  it('should work with `on-focus` prop', async () => {\n    const onFocus = vi.fn()\n    const wrapper = mount(NAutoComplete, {\n      props: { onFocus }\n    })\n    await wrapper.find('input').trigger('focus')\n    await wrapper.find('input').trigger('blur')\n    expect(onFocus).toHaveBeenCalled()\n    wrapper.unmount()\n  })\n\n  it('should work with `status` prop', async () => {\n    ;(['success', 'warning', 'error'] as const).forEach((status) => {\n      const wrapper = mount(NAutoComplete, { props: { status } })\n      expect(wrapper.find('.n-input').classes()).toContain(\n        `n-input--${status}-status`\n      )\n      wrapper.unmount()\n    })\n  })\n\n  it('should work with `placement` prop', async () => {\n    ;(\n      [\n        'top-start',\n        'top',\n        'top-end',\n        'right-start',\n        'right',\n        'right-end',\n        'bottom-start',\n        'bottom',\n        'bottom-end',\n        'left-start',\n        'left',\n        'left-end'\n      ] as const\n    ).forEach(async (placement) => {\n      const wrapper = mount(NAutoComplete, { props: { placement } })\n      await vi.waitFor(() => {\n        expect(\n          document\n            .querySelector('.v-binder-follower-content')\n            ?.getAttribute('v-placement')\n        ).toBe(placement)\n      })\n      wrapper.unmount()\n    })\n  })\n})\n"
  },
  {
    "path": "src/auto-complete/tests/__snapshots__/AutoComplete.spec.ts.snap",
    "content": "// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html\n\nexports[`n-auto-complete > should work with \\`size\\` prop 1`] = `\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-count-text-color: rgb(118, 124, 130); --n-count-text-color-disabled: rgba(194, 194, 194, 1); --n-color: rgba(255, 255, 255, 1); --n-font-size: 14px; --n-font-weight: 400; --n-border-radius: 3px; --n-height: 28px; --n-padding-left: 10px; --n-padding-right: 10px; --n-text-color: rgb(51, 54, 57); --n-caret-color: #18a058; --n-text-decoration-color: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-focus: 1px solid #36ad6a; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-icon-size: 16px; --n-line-height-textarea: 1.6; --n-color-disabled: rgb(250, 250, 252); --n-color-focus: rgba(255, 255, 255, 1); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-loading-color: #18a058; --n-caret-color-warning: #f0a020; --n-color-focus-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-loading-color-warning: #f0a020; --n-caret-color-error: #d03050; --n-color-focus-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-loading-color-error: #d03050; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-size: 16px; --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-icon-color-hover: rgba(146, 146, 146, 1); --n-icon-color-pressed: rgba(175, 175, 175, 1); --n-icon-color-disabled: rgba(209, 209, 209, 1); --n-suffix-text-color: rgb(51, 54, 57);\"`;\n\nexports[`n-auto-complete > should work with \\`size\\` prop 2`] = `\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-count-text-color: rgb(118, 124, 130); --n-count-text-color-disabled: rgba(194, 194, 194, 1); --n-color: rgba(255, 255, 255, 1); --n-font-size: 14px; --n-font-weight: 400; --n-border-radius: 3px; --n-height: 34px; --n-padding-left: 12px; --n-padding-right: 12px; --n-text-color: rgb(51, 54, 57); --n-caret-color: #18a058; --n-text-decoration-color: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-focus: 1px solid #36ad6a; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-icon-size: 16px; --n-line-height-textarea: 1.6; --n-color-disabled: rgb(250, 250, 252); --n-color-focus: rgba(255, 255, 255, 1); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-loading-color: #18a058; --n-caret-color-warning: #f0a020; --n-color-focus-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-loading-color-warning: #f0a020; --n-caret-color-error: #d03050; --n-color-focus-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-loading-color-error: #d03050; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-size: 16px; --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-icon-color-hover: rgba(146, 146, 146, 1); --n-icon-color-pressed: rgba(175, 175, 175, 1); --n-icon-color-disabled: rgba(209, 209, 209, 1); --n-suffix-text-color: rgb(51, 54, 57);\"`;\n\nexports[`n-auto-complete > should work with \\`size\\` prop 3`] = `\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-count-text-color: rgb(118, 124, 130); --n-count-text-color-disabled: rgba(194, 194, 194, 1); --n-color: rgba(255, 255, 255, 1); --n-font-size: 15px; --n-font-weight: 400; --n-border-radius: 3px; --n-height: 40px; --n-padding-left: 14px; --n-padding-right: 14px; --n-text-color: rgb(51, 54, 57); --n-caret-color: #18a058; --n-text-decoration-color: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-focus: 1px solid #36ad6a; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-icon-size: 16px; --n-line-height-textarea: 1.6; --n-color-disabled: rgb(250, 250, 252); --n-color-focus: rgba(255, 255, 255, 1); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-loading-color: #18a058; --n-caret-color-warning: #f0a020; --n-color-focus-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-loading-color-warning: #f0a020; --n-caret-color-error: #d03050; --n-color-focus-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-loading-color-error: #d03050; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-size: 16px; --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-icon-color-hover: rgba(146, 146, 146, 1); --n-icon-color-pressed: rgba(175, 175, 175, 1); --n-icon-color-disabled: rgba(209, 209, 209, 1); --n-suffix-text-color: rgb(51, 54, 57);\"`;\n"
  },
  {
    "path": "src/auto-complete/tests/server.spec.tsx",
    "content": "import { setup } from '@css-render/vue3-ssr'\nimport { renderToString } from '@vue/server-renderer'\n/**\n * @vitest-environment node\n */\nimport { createSSRApp, h } from 'vue'\nimport { NAutoComplete } from '../..'\n\ndescribe('server side rendering', () => {\n  it('works', async () => {\n    const app = createSSRApp(() => <NAutoComplete />)\n    setup(app)\n    try {\n      await renderToString(app)\n    }\n    catch (e) {\n      expect(e).not.toBeTruthy()\n    }\n  })\n})\n"
  },
  {
    "path": "src/avatar/demos/enUS/badge.demo.vue",
    "content": "<markdown>\n# Badge\n\nUsing it with `badge` would be nice (if you like tons of notifications).\n</markdown>\n\n<template>\n  <n-badge value=\"999+\">\n    <n-avatar>App</n-avatar>\n  </n-badge>\n</template>\n"
  },
  {
    "path": "src/avatar/demos/enUS/color.demo.vue",
    "content": "<markdown>\n# Color\n\nYou can set colors related to things you want to eat.\n</markdown>\n\n<template>\n  <n-avatar\n    :style=\"{\n      color: 'yellow',\n      backgroundColor: 'red',\n    }\"\n  >\n    M\n  </n-avatar>\n</template>\n"
  },
  {
    "path": "src/avatar/demos/enUS/fallback.demo.vue",
    "content": "<markdown>\n# Fallback\n\nShow 07akioni if loading fails.\n</markdown>\n\n<template>\n  <n-avatar\n    round\n    size=\"small\"\n    src=\"empty.png\"\n    fallback-src=\"https://07akioni.oss-cn-beijing.aliyuncs.com/07akioni.jpeg\"\n  />\n</template>\n"
  },
  {
    "path": "src/avatar/demos/enUS/group.demo.vue",
    "content": "<markdown>\n# Avatar Group\n\nCrowded people.\n\n---\n\nPlease note that the demo uses `NGAvatarGroup` which is available since naive-ui `2.43.0`.\n\nThe `NGAvatarGroup` is the same as `NAvatarGroup` except with a generic `options` prop which can make slots & props types more accurate in Vue files.\n\nThe component is only available in Vue >= `3.3` and in `.vue` files.\n\nIf your environment doesn't support [Vue Generic Components](https://blog.vuejs.org/posts/vue-3-3#generic-components), please use `NAvatarGroup` instead.\n\nThe `NGAvatarGroup` should be imported from `'naive-ui/generic'`.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { AvatarGroupOption } from 'naive-ui'\nimport { NGAvatarGroup } from 'naive-ui/generic'\n\ntype Option = AvatarGroupOption & { name: string }\n\nconst options: Option[] = [\n  {\n    name: 'Leonardo DiCaprio',\n    src: 'https://gw.alipayobjects.com/zos/antfincdn/aPkFc8Sj7n/method-draw-image.svg'\n  },\n  {\n    name: 'Jennifer Lawrence',\n    src: 'https://07akioni.oss-cn-beijing.aliyuncs.com/07akioni.jpeg'\n  },\n  {\n    name: 'Audrey Hepburn',\n    src: 'https://gw.alipayobjects.com/zos/antfincdn/aPkFc8Sj7n/method-draw-image.svg'\n  },\n  {\n    name: 'Anne Hathaway',\n    src: 'https://07akioni.oss-cn-beijing.aliyuncs.com/07akioni.jpeg'\n  },\n  {\n    name: 'Taylor Swift',\n    src: 'https://gw.alipayobjects.com/zos/antfincdn/aPkFc8Sj7n/method-draw-image.svg'\n  }\n]\n\nfunction createDropdownOptions(options: Option[]) {\n  return options.map(option => ({\n    key: option.name,\n    label: option.name\n  }))\n}\n</script>\n\n<template>\n  <NGAvatarGroup :options=\"options\" :size=\"40\" :max=\"3\">\n    <template #avatar=\"{ option: { name, src } }\">\n      <n-tooltip>\n        <template #trigger>\n          <n-avatar :src=\"src\" />\n        </template>\n        {{ name }}\n      </n-tooltip>\n    </template>\n    <template #rest=\"{ options: restOptions, rest }\">\n      <n-dropdown :options=\"createDropdownOptions(restOptions)\" placement=\"top\">\n        <n-avatar>+{{ rest }}</n-avatar>\n      </n-dropdown>\n    </template>\n  </NGAvatarGroup>\n</template>\n"
  },
  {
    "path": "src/avatar/demos/enUS/icon.demo.vue",
    "content": "<markdown>\n# Icon\n\nI like using an icon in an avatar.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { MdCash } from '@vicons/ionicons4'\n</script>\n\n<template>\n  <n-avatar>\n    <n-icon>\n      <MdCash />\n    </n-icon>\n  </n-avatar>\n</template>\n"
  },
  {
    "path": "src/avatar/demos/enUS/index.demo-entry.md",
    "content": "# Avatar\n\nOn the Internet, nobody knows you're a dog.\n\n## Demos\n\n```demo\nsize.vue\nshape.vue\ncolor.vue\nbadge.vue\nicon.vue\nname-size.vue\nfallback.vue\ngroup.vue\nlazy.vue\nv-show-debug.vue\n```\n\n## API\n\n### Avatar Props\n\n| Name | Type | Default | Description | Version |\n| --- | --- | --- | --- | --- |\n| bordered | `boolean` | `false` | Whether to display a avatar with border. |  |\n| color | `string` | `undefined` | The background color of the avatar. |  |\n| fallback-src | `string` | `undefined` | Image URL to show when avatar fails to load. |  |\n| img-props | `ImgHTMLAttributes` | `undefined` | The props of the img element inside the component. | 2.34.0 |\n| intersection-observer-options | `{ root?: Element \\| Document \\| string \\| null, rootMargin?: string, threshold?: number \\| number[]; }` | `undefined` | Intersection observer's config to be applied when `lazy=true`. | 2.31.0 |\n| lazy | `boolean` | `false` | Load image after it enters viewport. When used alone, it will be assigned the property value of [HTMLImageElement.loading](https://developer.mozilla.org/en-US/docs/Web/API/HTMLImageElement/loading). Alternatively, it can be used in conjunction with the `intersection-observer-options` configuration to achieve lazy loading. | 2.31.0 |\n| object-fit | `'fill' \\| 'contain' \\| 'cover' \\| 'none' \\| 'scale-down'` | `'fill'` | Object-fit type of the image in the container. |  |\n| render-fallback | `() => VNodeChild` | `undefined` | Render function of fallback content. | 2.33.4 |\n| render-placeholder | `() => VNodeChild` | `undefined` | Render function of placeholder. | 2.33.4 |\n| round | `boolean` | `false` | Whether to display a rounded avatar. |  |\n| size | `'small' \\| 'medium' \\| 'large' \\| number` | `'medium'` | Avatar's size. |\n| src | `string` | `undefined` | Avatar's image source. |  |\n| on-error | `(e: Event) => void` | `undefined` | Callback executed when the avatar image fails to load. |  |\n\n### AvatarGroup Props\n\nThe generic type is `<T extends AvatarGroupOption = AvatarGroupOption>` (available since `2.43.0`).\n\nIt is only supported in `.vue` files with `Vue >= 3.3`. You can use it by `importing NGAvatarGroup from 'naive-ui/generic'`. Otherwise, please use the regular `n-avatar-group` component.\n\n```ts\ninterface AvatarGroupOption {\n  src: string\n}\n```\n\n| Name | Type | Default | Description | Version |\n| --- | --- | --- | --- | --- |\n| expand-on-hover | `boolean` | `false` | Expand on hover. | 2.37.0 |\n| max | `number` | `undefined` | Max avatar count in the group. |  |\n| max-style | `Object \\| string` | `undefined` | The style of the overflow placeholder. |  |\n| options | `Array<T extends AvatarGroupOption = AvatarGroupOption>` | `[]` | Avatar group options. |  |\n| size | `'small' \\| 'medium' \\| 'large' \\| number` | `'medium'` | Avatar's size. | 2.43.0 |\n| vertical | `boolean` | `false` | Whether display a vertical avatar group. |  |\n\n### Avatar Slots\n\n| Name | Parameters | Description | Version |\n| --- | --- | --- | --- |\n| default | `()` | The content of the avatar. |  |\n| fallback | `()` | Content if avatar load fails. | 2.33.4 |\n| placeholder | `()` | Placeholder shown when image is not loaded. | 2.31.0 |\n\n### AvatarGroup Slots\n\n| Name | Parameters | Description |\n| --- | --- | --- |\n| avatar | `(info: { option: { src: string } })` | Avatar of the avatar group. |\n| default | `()` | The content of the avatar group. |\n| rest | `(info: { options: Array<{ src: string }>, rest: number })` | Overflow indicator of the avatar group. |\n"
  },
  {
    "path": "src/avatar/demos/enUS/lazy.demo.vue",
    "content": "<markdown>\n# Lazy load\n\nLoad the images only after they enter the viewport. There are two ways to use it: one is to use the `lazy` property alone, which will be set to the value of the [HTMLImageElement.loading](https://developer.mozilla.org/en-US/docs/Web/API/HTMLImageElement/loading) property, and the other is to use `lazy` together with the `intersection-observer-options` configuration to implement lazy loading using the [IntersectionObserver](https://developer.mozilla.org/en-US/docs/Web/API/IntersectionObserver) API.\n</markdown>\n\n<script lang=\"ts\" setup>\nconst srcList = [\n  'https://picsum.photos/id/1/100/100',\n  'https://picsum.photos/id/2/100/100',\n  'https://picsum.photos/id/3/100/100',\n  'https://picsum.photos/id/4/100/100',\n  'https://picsum.photos/id/5/100/100',\n  'https://picsum.photos/id/7/100/100',\n  'https://picsum.photos/id/8/100/100',\n  'https://picsum.photos/id/9/100/100',\n  'https://picsum.photos/id/10/100/100',\n  'xxx.png'\n]\n</script>\n\n<template>\n  <n-p>\n    use<n-text code>\n      lazy\n    </n-text> along\n  </n-p>\n  <n-avatar\n    lazy\n    src=\"https://07akioni.oss-cn-beijing.aliyuncs.com/07akioni.jpeg\"\n  />\n  <n-p>\n    use <n-text code>\n      lazy\n    </n-text> with\n    <n-text code>\n      intersection-observer-options\n    </n-text>\n  </n-p>\n  <div\n    id=\"image-scroll-container\"\n    style=\"overflow: auto; height: 100px; gap: 8px\"\n  >\n    <n-space vertical>\n      <n-avatar\n        v-for=\"src of srcList\"\n        :key=\"src\"\n        size=\"small\"\n        lazy\n        :src=\"src\"\n        fallback-src=\"https://07akioni.oss-cn-beijing.aliyuncs.com/07akioni.jpeg\"\n        :render-placeholder=\"() => null\"\n        :intersection-observer-options=\"{\n          root: '#image-scroll-container',\n        }\"\n      />\n    </n-space>\n  </div>\n</template>\n"
  },
  {
    "path": "src/avatar/demos/enUS/name-size.demo.vue",
    "content": "<markdown>\n# Content size\n\nText is resized to fit the avatar.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst value = ref('Oasis')\n</script>\n\n<template>\n  <n-space vertical item-style=\"line-height: 0;\">\n    <n-space>\n      <n-avatar>{{ value }}</n-avatar>\n      <n-avatar round>\n        {{ value }}\n      </n-avatar>\n    </n-space>\n    <n-input v-model:value=\"value\" />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/avatar/demos/enUS/shape.demo.vue",
    "content": "<markdown>\n# Shape\n\nAvatar can be `round`.\n</markdown>\n\n<template>\n  <n-space align=\"flex-end\">\n    <n-avatar\n      round\n      size=\"small\"\n      src=\"https://07akioni.oss-cn-beijing.aliyuncs.com/07akioni.jpeg\"\n    />\n    <n-avatar\n      round\n      size=\"medium\"\n      src=\"https://07akioni.oss-cn-beijing.aliyuncs.com/07akioni.jpeg\"\n    />\n    <n-avatar\n      round\n      size=\"large\"\n      src=\"https://07akioni.oss-cn-beijing.aliyuncs.com/07akioni.jpeg\"\n    />\n    <n-avatar\n      round\n      :size=\"48\"\n      src=\"https://07akioni.oss-cn-beijing.aliyuncs.com/07akioni.jpeg\"\n    />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/avatar/demos/enUS/size.demo.vue",
    "content": "<markdown>\n# Size\n\nAvatar has `small`, `medium` and `large` sizes. You could also use a custom px number for size.\n</markdown>\n\n<template>\n  <n-space align=\"flex-end\">\n    <n-avatar\n      size=\"small\"\n      src=\"https://07akioni.oss-cn-beijing.aliyuncs.com/07akioni.jpeg\"\n    />\n    <n-avatar\n      size=\"medium\"\n      src=\"https://07akioni.oss-cn-beijing.aliyuncs.com/07akioni.jpeg\"\n    />\n    <n-avatar\n      size=\"large\"\n      src=\"https://07akioni.oss-cn-beijing.aliyuncs.com/07akioni.jpeg\"\n    />\n    <n-avatar\n      :size=\"48\"\n      src=\"https://07akioni.oss-cn-beijing.aliyuncs.com/07akioni.jpeg\"\n    />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/avatar/demos/enUS/v-show-debug.demo.vue",
    "content": "<markdown>\n# v-show debug\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { onMounted, onUpdated, ref } from 'vue'\n\nconst isShow = ref(false)\nconst value = ref('Oasis111')\n\nfunction toggle() {\n  isShow.value = !isShow.value\n}\n\nonMounted(() => {\n  console.log('world')\n})\n\nonUpdated(() => {\n  console.log('hello')\n})\n</script>\n\n<template>\n  <n-space vertical item-style=\"line-height: 0;\">\n    <n-space>\n      <n-button @click=\"toggle\">\n        toggle\n      </n-button>\n      <n-avatar v-show=\"isShow\">\n        {{ value }}\n      </n-avatar>\n      <n-avatar v-if=\"isShow\" round>\n        {{ value }}\n      </n-avatar>\n    </n-space>\n    <n-input v-model:value=\"value\" />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/avatar/demos/zhCN/badge.demo.vue",
    "content": "<markdown>\n# 标记\n\n和 `Badge` 一起用也挺好的 (如果你喜欢看到一堆一堆的推送)。\n</markdown>\n\n<template>\n  <n-badge value=\"999+\">\n    <n-avatar>App</n-avatar>\n  </n-badge>\n</template>\n"
  },
  {
    "path": "src/avatar/demos/zhCN/color.demo.vue",
    "content": "<markdown>\n# 颜色\n\n你可以把它设成某种和你爱吃的东西有关的颜色。\n</markdown>\n\n<template>\n  <n-avatar\n    :style=\"{\n      color: 'yellow',\n      backgroundColor: 'red',\n    }\"\n  >\n    M\n  </n-avatar>\n</template>\n"
  },
  {
    "path": "src/avatar/demos/zhCN/error-placeholder-debug.demo.vue",
    "content": "<markdown>\n# Error placeholder debug\n</markdown>\n\n<template>\n  <n-space :wrap-item=\"false\">\n    <n-avatar\n      src=\"https://07akioni.oss-cn-beijing.aliyuncs.com/07akioni.jpeg\"\n      lazy\n      :intersection-observer-options=\"{ root: '.root-layout' }\"\n    >\n      <template #placeholder>\n        PH\n      </template>\n    </n-avatar>\n    <n-avatar\n      src=\"xxx\"\n      lazy\n      :intersection-observer-options=\"{ root: '.root-layout' }\"\n    >\n      <template #placeholder>\n        PH\n      </template>\n    </n-avatar>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/avatar/demos/zhCN/fallback.demo.vue",
    "content": "<markdown>\n# 加载失败时显示的图像\n\n下面的头像加载失败时会展示 07akioni。\n</markdown>\n\n<template>\n  <n-avatar\n    round\n    size=\"small\"\n    src=\"empty.png\"\n    fallback-src=\"https://07akioni.oss-cn-beijing.aliyuncs.com/07akioni.jpeg\"\n  />\n</template>\n"
  },
  {
    "path": "src/avatar/demos/zhCN/group.demo.vue",
    "content": "<markdown>\n# 头像组\n\n人多不一定是好事。\n\n---\n\n请注意，该演示使用了 `NGAvatarGroup` 组件，该组件自 naive-ui 的 `2.43.0` 起才可用。\n\n`NGAvatarGroup` 与 `NAvatarGroup` 几乎完全相同，不同之处在于它新增了一个通用的 `options` 属性（generic `options` prop），这可以使在 `.vue` 文件中使用时让 slots 和 props 的类型更精确。\n\n该组件仅在 Vue >= `3.3` 且在 `.vue` 文件中才能使用。\n\n如果你的开发环境不支持 [Vue 泛型组件](https://blog.vuejs.org/posts/vue-3-3#generic-components)，请改用 `NAvatarGroup`。\n\n`NGAvatarGroup` 应从 `'naive-ui/generic'` 中导入。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { AvatarGroupOption } from 'naive-ui'\nimport { NGAvatarGroup } from 'naive-ui/generic'\n\ntype Option = AvatarGroupOption & { name: string }\n\nconst options: Option[] = [\n  {\n    name: '张三',\n    src: 'https://gw.alipayobjects.com/zos/antfincdn/aPkFc8Sj7n/method-draw-image.svg'\n  },\n  {\n    name: '李四',\n    src: 'https://07akioni.oss-cn-beijing.aliyuncs.com/07akioni.jpeg'\n  },\n  {\n    name: '王五',\n    src: 'https://gw.alipayobjects.com/zos/antfincdn/aPkFc8Sj7n/method-draw-image.svg'\n  },\n  {\n    name: '赵六',\n    src: 'https://07akioni.oss-cn-beijing.aliyuncs.com/07akioni.jpeg'\n  },\n  {\n    name: '七仔',\n    src: 'https://gw.alipayobjects.com/zos/antfincdn/aPkFc8Sj7n/method-draw-image.svg'\n  }\n]\n\nfunction createDropdownOptions(options: Option[]) {\n  return options.map(option => ({\n    key: option.name,\n    label: option.name\n  }))\n}\n</script>\n\n<template>\n  <NGAvatarGroup :options=\"options\" :size=\"40\" :max=\"3\">\n    <template #avatar=\"{ option: { name, src } }\">\n      <n-tooltip>\n        <template #trigger>\n          <n-avatar :src=\"src\" />\n        </template>\n        {{ name }}\n      </n-tooltip>\n    </template>\n    <template #rest=\"{ options: restOptions, rest }\">\n      <n-dropdown :options=\"createDropdownOptions(restOptions)\" placement=\"top\">\n        <n-avatar>+{{ rest }}</n-avatar>\n      </n-dropdown>\n    </template>\n  </NGAvatarGroup>\n</template>\n"
  },
  {
    "path": "src/avatar/demos/zhCN/icon.demo.vue",
    "content": "<markdown>\n# 图标\n\n我喜欢用图标当头像。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { MdCash } from '@vicons/ionicons4'\n</script>\n\n<template>\n  <n-avatar>\n    <n-icon>\n      <MdCash />\n    </n-icon>\n  </n-avatar>\n</template>\n"
  },
  {
    "path": "src/avatar/demos/zhCN/index.demo-entry.md",
    "content": "# 头像 Avatar\n\n在互联网上，没有人知道你是 \\*\\*\\* 。\n\n## 演示\n\n```demo\nerror-placeholder-debug.vue\nsize.vue\nshape.vue\ncolor.vue\nbadge.vue\nicon.vue\nname-size.vue\nfallback.vue\ngroup.vue\nlazy.vue\nv-show-debug.vue\nrtl-debug.vue\n```\n\n## API\n\n### Avatar Props\n\n| 名称 | 类型 | 默认值 | 说明 | 版本 |\n| --- | --- | --- | --- | --- |\n| bordered | `boolean` | `false` | 头像是否带边框 |  |\n| color | `string` | `undefined` | 头像的背景色 |  |\n| fallback-src | `string` | `undefined` | 头像加载失败时显示的图片的地址 |  |\n| img-props | `ImgHTMLAttributes` | `undefined` | 组件中 img 元素的属性 | 2.34.0 |\n| intersection-observer-options | `{ root?: Element \\| Document \\| string \\| null, rootMargin?: string, threshold?: number \\| number[]; }` | `undefined` | `lazy=true` 时 intersection observer 观测的配置 | 2.31.0 |\n| lazy | `boolean` | `false` | 是否让图片进入视口再加载，单独使用将设置为[HTMLImageElement.loading](https://developer.mozilla.org/en-US/docs/Web/API/HTMLImageElement/loading) 的属性值；也可配合 `intersection-observer-options` 配置实现懒加载 | 2.31.0 |\n| object-fit | `'fill' \\| 'contain' \\| 'cover' \\| 'none' \\| 'scale-down'` | `'fill'` | 头像的图片在容器内的的适应类型 |  |\n| render-fallback | `() => VNodeChild` | `undefined` | 加载失败的渲染函数 | 2.33.4 |\n| render-placeholder | `() => VNodeChild` | `undefined` | 占位的渲染函数 | 2.33.4 |\n| round | `boolean` | `false` | 头像是否圆形 |  |\n| size | `'small' \\| 'medium' \\| 'large' \\| number` | `'medium'` | 头像的尺寸 |\n| src | `string` | `undefined` | 头像的地址 |  |\n| on-error | `(e: Event) => void` | `undefined` | 头像的图片加载失败执行的回调 |  |\n\n### AvatarGroup Props\n\n泛型 `<T extends AvatarGroupOption = AvatarGroupOption>`，自 `2.43.0` 可用。\n\n泛型能力仅在 `.vue` 文件中，`Vue >= 3.3`，通过 `import { NGAvatarGroup } from 'naive-ui/generic'` 可用，否则请使用普通的 `n-avatar-group`。\n\n```ts\ninterface AvatarGroupOption {\n  src: string\n}\n```\n\n| 名称 | 类型 | 默认值 | 说明 | 版本 |\n| --- | --- | --- | --- | --- |\n| expand-on-hover | `boolean` | `false` | 悬停时展开 | 2.37.0 |\n| max | `number` | `undefined` | 组内头像显示的最大个数 |  |\n| max-style | `Object \\| string` | `undefined` | 溢出标识的样式 |  |\n| options | `Array<T extends AvatarGroupOption = AvatarGroupOption>` | `[]` | 头像组的选项 |  |\n| size | `'small' \\| 'medium' \\| 'large' \\| number` | `'medium'` | 头像的尺寸 | 2.43.0 |\n| vertical | `boolean` | `false` | 组内头像是否垂直排列 |  |\n\n### Avatar Slots\n\n| 名称        | 参数 | 说明                       | 版本   |\n| ----------- | ---- | -------------------------- | ------ |\n| default     | `()` | 头像内填充的内容           |        |\n| fallback    | `()` | 加载失败的内容             | 2.33.4 |\n| placeholder | `()` | 图像没有完成加载时候的占位 | 2.31.0 |\n\n### AvatarGroup Slots\n\n| 名称 | 参数 | 说明 |\n| --- | --- | --- |\n| avatar | `(info: { option: { src: string } })` | 头像组头像 |\n| default | `()` | 头像组内填充的内容 |\n| rest | `(info: { options: Array<{ src: string }>, rest: number })` | 头像组溢出容器 |\n"
  },
  {
    "path": "src/avatar/demos/zhCN/lazy.demo.vue",
    "content": "<markdown>\n# 懒加载\n\n让图片进入视口再加载，两种使用方式：一种是单独使用 `lazy` 属性，则将设置为原生 [HTMLImageElement.loading](https://developer.mozilla.org/zh-CN/docs/Web/API/HTMLImageElement/loading) 的属性值；\n另一种方式是配合 `intersection-observer-options` 配置，将采用 [IntersectionObserver](https://developer.mozilla.org/zh-CN/docs/Web/API/IntersectionObserver) API 实现懒加载。\n</markdown>\n\n<script lang=\"ts\" setup>\nconst srcList = [\n  'https://picsum.photos/id/1/100/100',\n  'https://picsum.photos/id/2/100/100',\n  'https://picsum.photos/id/3/100/100',\n  'https://picsum.photos/id/4/100/100',\n  'https://picsum.photos/id/5/100/100',\n  'https://picsum.photos/id/7/100/100',\n  'https://picsum.photos/id/8/100/100',\n  'https://picsum.photos/id/9/100/100',\n  'https://picsum.photos/id/10/100/100',\n  'xxx.png'\n]\n</script>\n\n<template>\n  <n-p>\n    单独设置 <n-text code>\n      lazy\n    </n-text> 属性\n  </n-p>\n  <n-avatar\n    lazy\n    src=\"https://07akioni.oss-cn-beijing.aliyuncs.com/07akioni.jpeg\"\n  />\n  <n-p>\n    <n-text code>\n      lazy\n    </n-text> 属性配合\n    <n-text code>\n      intersection-observer-options\n    </n-text>\n  </n-p>\n  <div\n    id=\"image-scroll-container\"\n    style=\"overflow: auto; height: 100px; gap: 8px\"\n  >\n    <n-space vertical>\n      <n-avatar\n        v-for=\"src of srcList\"\n        :key=\"src\"\n        size=\"small\"\n        lazy\n        :src=\"src\"\n        fallback-src=\"https://07akioni.oss-cn-beijing.aliyuncs.com/07akioni.jpeg\"\n        :render-placeholder=\"() => null\"\n        :intersection-observer-options=\"{\n          root: '#image-scroll-container',\n        }\"\n      />\n    </n-space>\n  </div>\n</template>\n"
  },
  {
    "path": "src/avatar/demos/zhCN/name-size.demo.vue",
    "content": "<markdown>\n# 字号\n\n字号会根据内容文字自动调整。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst value = ref('Oasis')\n</script>\n\n<template>\n  <n-space vertical item-style=\"line-height: 0;\">\n    <n-space>\n      <n-avatar>{{ value }}</n-avatar>\n      <n-avatar round>\n        {{ value }}\n      </n-avatar>\n    </n-space>\n    <n-input v-model:value=\"value\" />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/avatar/demos/zhCN/rtl-debug.demo.vue",
    "content": "<markdown>\n# Rtl Debug\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { unstableAvatarGroupRtl, unstableSpaceRtl } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst rtlEnabled = ref(false)\n\nconst rtlStyles = [unstableAvatarGroupRtl, unstableSpaceRtl]\n\nconst options = [\n  {\n    name: 'Leonardo DiCaprio',\n    src: 'https://gw.alipayobjects.com/zos/antfincdn/aPkFc8Sj7n/method-draw-image.svg'\n  },\n  {\n    name: 'Jennifer Lawrence',\n    src: 'https://07akioni.oss-cn-beijing.aliyuncs.com/07akioni.jpeg'\n  },\n  {\n    name: 'Audrey Hepburn',\n    src: 'https://gw.alipayobjects.com/zos/antfincdn/aPkFc8Sj7n/method-draw-image.svg'\n  },\n  {\n    name: 'Anne Hathaway',\n    src: 'https://07akioni.oss-cn-beijing.aliyuncs.com/07akioni.jpeg'\n  },\n  {\n    name: 'Taylor Swift',\n    src: 'https://gw.alipayobjects.com/zos/antfincdn/aPkFc8Sj7n/method-draw-image.svg'\n  }\n]\n</script>\n\n<template>\n  <n-space vertical>\n    <n-space><n-switch v-model:value=\"rtlEnabled\" />Rtl</n-space>\n    <n-config-provider :rtl=\"rtlEnabled ? rtlStyles : undefined\">\n      <n-space vertical>\n        <n-avatar-group :options=\"options\" :size=\"40\" :max=\"3\" />\n        <n-space align=\"flex-end\">\n          <n-avatar\n            size=\"small\"\n            round\n            src=\"https://07akioni.oss-cn-beijing.aliyuncs.com/07akioni.jpeg\"\n          />\n          <n-avatar\n            size=\"medium\"\n            src=\"https://07akioni.oss-cn-beijing.aliyuncs.com/07akioni.jpeg\"\n          />\n          <n-avatar\n            size=\"large\"\n            src=\"https://07akioni.oss-cn-beijing.aliyuncs.com/07akioni.jpeg\"\n          />\n        </n-space>\n      </n-space>\n    </n-config-provider>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/avatar/demos/zhCN/shape.demo.vue",
    "content": "<markdown>\n# 形状\n\n头像可以是圆形。\n</markdown>\n\n<template>\n  <n-space align=\"flex-end\">\n    <n-avatar\n      round\n      size=\"small\"\n      src=\"https://07akioni.oss-cn-beijing.aliyuncs.com/07akioni.jpeg\"\n    />\n    <n-avatar\n      round\n      size=\"medium\"\n      src=\"https://07akioni.oss-cn-beijing.aliyuncs.com/07akioni.jpeg\"\n    />\n    <n-avatar\n      round\n      size=\"large\"\n      src=\"https://07akioni.oss-cn-beijing.aliyuncs.com/07akioni.jpeg\"\n    />\n    <n-avatar\n      round\n      :size=\"48\"\n      src=\"https://07akioni.oss-cn-beijing.aliyuncs.com/07akioni.jpeg\"\n    />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/avatar/demos/zhCN/size.demo.vue",
    "content": "<markdown>\n# 尺寸\n\n头像有 `small`、`medium` 和 `large` 大小，也可以自己设定尺寸。\n</markdown>\n\n<template>\n  <n-space align=\"flex-end\">\n    <n-avatar\n      size=\"small\"\n      src=\"https://07akioni.oss-cn-beijing.aliyuncs.com/07akioni.jpeg\"\n    />\n    <n-avatar\n      size=\"medium\"\n      src=\"https://07akioni.oss-cn-beijing.aliyuncs.com/07akioni.jpeg\"\n    />\n    <n-avatar\n      size=\"large\"\n      src=\"https://07akioni.oss-cn-beijing.aliyuncs.com/07akioni.jpeg\"\n    />\n    <n-avatar\n      :size=\"48\"\n      src=\"https://07akioni.oss-cn-beijing.aliyuncs.com/07akioni.jpeg\"\n    />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/avatar/demos/zhCN/v-show-debug.demo.vue",
    "content": "<markdown>\n# v-show debug\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { onMounted, onUpdated, ref } from 'vue'\n\nconst isShow = ref(false)\nconst value = ref('Oasis111')\n\nfunction toggle() {\n  isShow.value = !isShow.value\n}\n\nonMounted(() => {\n  console.log('world')\n})\n\nonUpdated(() => {\n  console.log('hello')\n})\n</script>\n\n<template>\n  <n-space vertical item-style=\"line-height: 0;\">\n    <n-space>\n      <n-button @click=\"toggle\">\n        toggle\n      </n-button>\n      <n-avatar v-show=\"isShow\">\n        {{ value }}\n      </n-avatar>\n      <n-avatar v-if=\"isShow\" round>\n        {{ value }}\n      </n-avatar>\n    </n-space>\n    <n-input v-model:value=\"value\" />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/avatar/index.ts",
    "content": "export { avatarProps, default as NAvatar } from './src/Avatar'\nexport type { AvatarProps, AvatarSlots } from './src/Avatar'\n"
  },
  {
    "path": "src/avatar/src/Avatar.tsx",
    "content": "import type {\n  ImgHTMLAttributes,\n  PropType,\n  SlotsType,\n  VNode,\n  VNodeChild\n} from 'vue'\nimport type { ThemeProps } from '../../_mixins'\nimport type { ExtractPublicPropTypes } from '../../_utils'\nimport type { IntersectionObserverOptions } from '../../image/src/utils'\nimport type { AvatarTheme } from '../styles'\nimport type { ObjectFit, Size } from './interface'\nimport {\n  computed,\n  defineComponent,\n  h,\n  inject,\n  onBeforeUnmount,\n  onMounted,\n  ref,\n  watch,\n  watchEffect\n} from 'vue'\nimport { VResizeObserver } from 'vueuc'\nimport { useConfig, useTheme, useThemeClass } from '../../_mixins'\nimport {\n  color2Class,\n  createKey,\n  resolveSlot,\n  resolveWrappedSlot\n} from '../../_utils'\nimport { isImageSupportNativeLazy } from '../../_utils/env/is-native-lazy-load'\nimport { observeIntersection } from '../../image/src/utils'\nimport { tagInjectionKey } from '../../tag/src/Tag'\nimport { avatarLight } from '../styles'\nimport { avatarGroupInjectionKey } from './context'\nimport style from './styles/index.cssr'\n\nexport const avatarProps = {\n  ...(useTheme.props as ThemeProps<AvatarTheme>),\n  size: [String, Number] as PropType<Size>,\n  src: String,\n  circle: {\n    type: Boolean,\n    default: undefined\n  },\n  objectFit: String as PropType<ObjectFit>,\n  round: {\n    type: Boolean,\n    default: undefined\n  },\n  bordered: {\n    type: Boolean,\n    default: undefined\n  },\n  onError: Function as PropType<(e: Event) => void>,\n  fallbackSrc: String,\n  intersectionObserverOptions: Object as PropType<IntersectionObserverOptions>,\n  lazy: Boolean,\n  onLoad: Function as PropType<(e: Event) => void>,\n  renderPlaceholder: Function as PropType<() => VNodeChild>,\n  renderFallback: Function as PropType<() => VNodeChild>,\n  imgProps: Object as PropType<ImgHTMLAttributes>,\n  /** @deprecated */\n  color: String\n} as const\n\nexport type AvatarProps = ExtractPublicPropTypes<typeof avatarProps>\n\nexport interface AvatarSlots {\n  default?: () => VNode[]\n  placeholder?: () => VNode[]\n  fallback?: () => VNode[]\n}\n\nexport default defineComponent({\n  name: 'Avatar',\n  props: avatarProps,\n  slots: Object as SlotsType<AvatarSlots>,\n  setup(props) {\n    const { mergedClsPrefixRef, inlineThemeDisabled } = useConfig(props)\n    const hasLoadErrorRef = ref(false)\n    let memoedTextHtml: string | null = null\n    const textRef = ref<HTMLElement | null>(null)\n    const selfRef = ref<HTMLElement | null>(null)\n    const fitTextTransform = (): void => {\n      const { value: textEl } = textRef\n      if (textEl) {\n        if (memoedTextHtml === null || memoedTextHtml !== textEl.innerHTML) {\n          memoedTextHtml = textEl.innerHTML\n          const { value: selfEl } = selfRef\n          if (selfEl) {\n            const { offsetWidth: elWidth, offsetHeight: elHeight } = selfEl\n            const { offsetWidth: textWidth, offsetHeight: textHeight } = textEl\n            const radix = 0.9\n            const ratio = Math.min(\n              (elWidth / textWidth) * radix,\n              (elHeight / textHeight) * radix,\n              1\n            )\n            textEl.style.transform = `translateX(-50%) translateY(-50%) scale(${ratio})`\n          }\n        }\n      }\n    }\n    const NAvatarGroup = inject(avatarGroupInjectionKey, null)\n    const mergedSizeRef = computed(() => {\n      const { size } = props\n      if (size)\n        return size\n      const { size: avatarGroupSize } = NAvatarGroup || {}\n      if (avatarGroupSize)\n        return avatarGroupSize\n      return 'medium'\n    })\n    const themeRef = useTheme(\n      'Avatar',\n      '-avatar',\n      style,\n      avatarLight,\n      props,\n      mergedClsPrefixRef\n    )\n    const TagInjection = inject(tagInjectionKey, null)\n    const mergedRoundRef = computed(() => {\n      if (NAvatarGroup)\n        return true\n      const { round, circle } = props\n      if (round !== undefined || circle !== undefined)\n        return round || circle\n      if (TagInjection) {\n        return TagInjection.roundRef.value\n      }\n      return false\n    })\n    const mergedBorderedRef = computed(() => {\n      if (NAvatarGroup)\n        return true\n      return props.bordered || false\n    })\n    const cssVarsRef = computed(() => {\n      const size = mergedSizeRef.value\n      const round = mergedRoundRef.value\n      const bordered = mergedBorderedRef.value\n      const { color: propColor } = props\n      const {\n        self: {\n          borderRadius,\n          fontSize,\n          color,\n          border,\n          colorModal,\n          colorPopover\n        },\n        common: { cubicBezierEaseInOut }\n      } = themeRef.value\n      let height: string\n      if (typeof size === 'number') {\n        height = `${size}px`\n      }\n      else {\n        height = themeRef.value.self[createKey('height', size)]\n      }\n      return {\n        '--n-font-size': fontSize,\n        '--n-border': bordered ? border : 'none',\n        '--n-border-radius': round ? '50%' : borderRadius,\n        '--n-color': propColor || color,\n        '--n-color-modal': propColor || colorModal,\n        '--n-color-popover': propColor || colorPopover,\n        '--n-bezier': cubicBezierEaseInOut,\n        '--n-merged-size': `var(--n-avatar-size-override, ${height})`\n      }\n    })\n    const themeClassHandle = inlineThemeDisabled\n      ? useThemeClass(\n          'avatar',\n          computed(() => {\n            const size = mergedSizeRef.value\n            const round = mergedRoundRef.value\n            const bordered = mergedBorderedRef.value\n            const { color } = props\n            let hash = ''\n            if (size) {\n              if (typeof size === 'number') {\n                hash += `a${size}`\n              }\n              else {\n                hash += size[0]\n              }\n            }\n            if (round) {\n              hash += 'b'\n            }\n            if (bordered) {\n              hash += 'c'\n            }\n            if (color) {\n              hash += color2Class(color)\n            }\n            return hash\n          }),\n          cssVarsRef,\n          props\n        )\n      : undefined\n\n    const shouldStartLoadingRef = ref(!props.lazy)\n\n    onMounted(() => {\n      // Use IntersectionObserver if lazy and intersectionObserverOptions is set\n      if (props.lazy && props.intersectionObserverOptions) {\n        let unobserve: (() => void) | undefined\n        const stopWatchHandle = watchEffect(() => {\n          unobserve?.()\n          unobserve = undefined\n          if (props.lazy) {\n            unobserve = observeIntersection(\n              selfRef.value,\n              props.intersectionObserverOptions,\n              shouldStartLoadingRef\n            )\n          }\n        })\n        onBeforeUnmount(() => {\n          stopWatchHandle()\n          unobserve?.()\n        })\n      }\n    })\n\n    watch(\n      () => props.src || props.imgProps?.src,\n      () => {\n        hasLoadErrorRef.value = false\n      }\n    )\n\n    const loadedRef = ref(!props.lazy)\n\n    return {\n      textRef,\n      selfRef,\n      mergedRoundRef,\n      mergedClsPrefix: mergedClsPrefixRef,\n      fitTextTransform,\n      cssVars: inlineThemeDisabled ? undefined : cssVarsRef,\n      themeClass: themeClassHandle?.themeClass,\n      onRender: themeClassHandle?.onRender,\n      hasLoadError: hasLoadErrorRef,\n      shouldStartLoading: shouldStartLoadingRef,\n      loaded: loadedRef,\n      mergedOnError: (e: Event) => {\n        if (!shouldStartLoadingRef.value)\n          return\n        hasLoadErrorRef.value = true\n        const { onError, imgProps: { onError: imgPropsOnError } = {} } = props\n        onError?.(e)\n        imgPropsOnError?.(e)\n      },\n      mergedOnLoad: (e: Event) => {\n        const { onLoad, imgProps: { onLoad: imgPropsOnLoad } = {} } = props\n        onLoad?.(e)\n        imgPropsOnLoad?.(e)\n        loadedRef.value = true\n      }\n    }\n  },\n  render() {\n    const {\n      $slots,\n      src,\n      mergedClsPrefix,\n      lazy,\n      onRender,\n      loaded,\n      hasLoadError,\n      imgProps = {}\n    } = this\n    onRender?.()\n    let img: VNodeChild\n    const placeholderNode\n      = !loaded\n        && !hasLoadError\n        && (this.renderPlaceholder\n          ? this.renderPlaceholder()\n          : this.$slots.placeholder?.())\n\n    if (this.hasLoadError) {\n      img = this.renderFallback\n        ? this.renderFallback()\n        : resolveSlot($slots.fallback, () => [\n            <img src={this.fallbackSrc} style={{ objectFit: this.objectFit }} />\n          ])\n    }\n    else {\n      img = resolveWrappedSlot($slots.default, (children) => {\n        if (children) {\n          return (\n            <VResizeObserver onResize={this.fitTextTransform}>\n              {{\n                default: () => (\n                  <span ref=\"textRef\" class={`${mergedClsPrefix}-avatar__text`}>\n                    {children}\n                  </span>\n                )\n              }}\n            </VResizeObserver>\n          )\n        }\n        else if (src || imgProps.src) {\n          const loadSrc = this.src || imgProps.src\n          return h('img', {\n            ...imgProps,\n            loading:\n              // If interseciton observer options is set, do not use native lazy\n              isImageSupportNativeLazy\n              && !this.intersectionObserverOptions\n              && lazy\n                ? 'lazy'\n                : 'eager',\n            src:\n              lazy && this.intersectionObserverOptions\n                ? this.shouldStartLoading\n                  ? loadSrc\n                  : undefined\n                : loadSrc,\n            'data-image-src': loadSrc,\n            onLoad: this.mergedOnLoad,\n            onError: this.mergedOnError,\n            style: [\n              imgProps.style || '',\n              { objectFit: this.objectFit },\n              placeholderNode\n                ? {\n                    height: '0',\n                    width: '0',\n                    visibility: 'hidden',\n                    position: 'absolute'\n                  }\n                : ''\n            ]\n          })\n        }\n      })\n    }\n    return (\n      <span\n        ref=\"selfRef\"\n        class={[`${mergedClsPrefix}-avatar`, this.themeClass]}\n        style={this.cssVars as any}\n      >\n        {img}\n        {lazy && placeholderNode}\n      </span>\n    )\n  }\n})\n"
  },
  {
    "path": "src/avatar/src/context.ts",
    "content": "import type { AvatarGroupInjection } from '../../avatar-group/src/AvatarGroup'\nimport { createInjectionKey } from '../../_utils'\n\nexport const avatarGroupInjectionKey\n  = createInjectionKey<AvatarGroupInjection>('n-avatar-group')\n"
  },
  {
    "path": "src/avatar/src/interface.ts",
    "content": "export type Size = number | 'small' | 'medium' | 'large'\nexport type ObjectFit = 'fill' | 'contain' | 'cover' | 'none' | 'scale-down'\n"
  },
  {
    "path": "src/avatar/src/styles/index.cssr.ts",
    "content": "import { c, cB, cE, insideModal, insidePopover } from '../../../_utils/cssr'\n\n// vars:\n// --n-font-size\n// --n-border-radius\n// --n-color\n// --n-color-modal\n// --n-color-popover\n// --n-bezier\n// --n-merged-size\nexport default cB('avatar', `\n  width: var(--n-merged-size);\n  height: var(--n-merged-size);\n  color: #FFF;\n  font-size: var(--n-font-size);\n  display: inline-flex;\n  position: relative;\n  overflow: hidden;\n  text-align: center;\n  border: var(--n-border);\n  border-radius: var(--n-border-radius);\n  --n-merged-color: var(--n-color);\n  background-color: var(--n-merged-color);\n  transition:\n    border-color .3s var(--n-bezier),\n    background-color .3s var(--n-bezier),\n    color .3s var(--n-bezier);\n`, [\n  insideModal(c('&', '--n-merged-color: var(--n-color-modal);')),\n  insidePopover(c('&', '--n-merged-color: var(--n-color-popover);')),\n  c('img', `\n    width: 100%;\n    height: 100%;\n  `),\n  cE('text', `\n    white-space: nowrap;\n    display: inline-block;\n    position: absolute;\n    left: 50%;\n    top: 50%;\n  `),\n  cB('icon', `\n    vertical-align: bottom;\n    font-size: calc(var(--n-merged-size) - 6px);\n  `),\n  cE('text', 'line-height: 1.25')\n])\n"
  },
  {
    "path": "src/avatar/styles/dark.ts",
    "content": "import type { AvatarTheme } from './light'\nimport { commonDark } from '../../_styles/common'\nimport { self } from './light'\n\nconst avatarDark: AvatarTheme = {\n  name: 'Avatar',\n  common: commonDark,\n  self\n}\n\nexport default avatarDark\n"
  },
  {
    "path": "src/avatar/styles/index.ts",
    "content": "export { default as avatarDark } from './dark'\nexport { default as avatarLight } from './light'\nexport type { AvatarTheme, AvatarThemeVars } from './light'\n"
  },
  {
    "path": "src/avatar/styles/light.ts",
    "content": "import type { Theme } from '../../_mixins'\nimport type { ThemeCommonVars } from '../../_styles/common'\nimport { composite } from 'seemly'\nimport { commonLight } from '../../_styles/common'\n\nexport function self(vars: ThemeCommonVars) {\n  const {\n    borderRadius,\n    avatarColor,\n    cardColor,\n    fontSize,\n    heightTiny,\n    heightSmall,\n    heightMedium,\n    heightLarge,\n    heightHuge,\n    modalColor,\n    popoverColor\n  } = vars\n  return {\n    borderRadius,\n    fontSize,\n    border: `2px solid ${cardColor}`,\n    heightTiny,\n    heightSmall,\n    heightMedium,\n    heightLarge,\n    heightHuge,\n    color: composite(cardColor, avatarColor),\n    colorModal: composite(modalColor, avatarColor),\n    colorPopover: composite(popoverColor, avatarColor)\n  }\n}\n\nexport type AvatarThemeVars = ReturnType<typeof self>\n\nconst avatarLight: Theme<'Avatar', AvatarThemeVars> = {\n  name: 'Avatar',\n  common: commonLight,\n  self\n}\n\nexport default avatarLight\nexport type AvatarTheme = typeof avatarLight\nexport type AvatarGroupTheme = typeof avatarLight\n"
  },
  {
    "path": "src/avatar/tests/Avatar.spec.tsx",
    "content": "import { CashOutline as CashIcon } from '@vicons/ionicons5'\nimport { mount } from '@vue/test-utils'\nimport { h, nextTick } from 'vue'\nimport { NIcon } from '../../icon'\nimport { NAvatar } from '../index'\n\n// Please note that resize observer doesn't work in JSDOM, so text transfrom\n// can't be tested.\ndescribe('n-avatar', () => {\n  // mock offsetHeight offsetWidth\n  const originalOffsetHeight = Object.getOwnPropertyDescriptor(\n    HTMLElement.prototype,\n    'offsetHeight'\n  )\n  const originalOffsetWidth = Object.getOwnPropertyDescriptor(\n    HTMLElement.prototype,\n    'offsetWidth'\n  )\n\n  beforeAll(() => {\n    Object.defineProperty(HTMLElement.prototype, 'offsetHeight', {\n      get() {\n        if (this.className === 'n-avatar__text') {\n          return 80\n        }\n        return 100\n      }\n    })\n    Object.defineProperty(HTMLElement.prototype, 'offsetWidth', {\n      get() {\n        if (this.className === 'n-avatar__text') {\n          return 80\n        }\n        return 100\n      }\n    })\n  })\n\n  afterAll(() => {\n    Object.defineProperty(HTMLElement.prototype, 'offsetHeight', {\n      get: () => originalOffsetHeight\n    })\n    Object.defineProperty(HTMLElement.prototype, 'offsetWidth', {\n      get: () => originalOffsetWidth\n    })\n  })\n\n  it('should work with import on demand', () => {\n    mount(NAvatar)\n  })\n\n  it('size is string', () => {\n    const wrapper = mount(NAvatar, { props: { size: 'medium' } })\n    expect(wrapper.attributes('style')).toContain('--n-merged-size')\n    expect(wrapper.html()).toMatchSnapshot()\n    wrapper.unmount()\n  })\n\n  it('size is number', () => {\n    const wrapper = mount(NAvatar, { props: { size: 50 } })\n    expect(wrapper.attributes('style')).toContain(\n      '--n-merged-size: var(--n-avatar-size-override, 50px);'\n    )\n    expect(wrapper.html()).toMatchSnapshot()\n    wrapper.unmount()\n  })\n\n  it('round avatar', () => {\n    const wrapper = mount(NAvatar, { props: { round: true } })\n    expect(wrapper.attributes('style')).toContain('--n-border-radius: 50%;')\n    expect(wrapper.html()).toMatchSnapshot()\n    wrapper.unmount()\n  })\n\n  it('bordered avatar', () => {\n    const wrapper = mount(NAvatar, { props: { bordered: true } })\n    expect(wrapper.attributes('style')).toContain('--n-border: 2px solid #fff;')\n    expect(wrapper.html()).toMatchSnapshot()\n    wrapper.unmount()\n  })\n\n  it('custom style', () => {\n    const wrapper = mount(NAvatar, {\n      props: { style: { backgroundColor: 'red' } }\n    })\n    expect(wrapper.attributes('style')).toContain('background-color: red;')\n    expect(wrapper.html()).toMatchSnapshot()\n    wrapper.unmount()\n  })\n\n  it('image avatar', () => {\n    const wrapper = mount(NAvatar, {\n      props: {\n        src: 'https://07akioni.oss-cn-beijing.aliyuncs.com/07akioni.jpeg'\n      }\n    })\n    expect(wrapper.find('img').exists()).toBe(true)\n    expect(wrapper.html()).toMatchSnapshot()\n    wrapper.unmount()\n  })\n\n  it('icon avatar', () => {\n    const wrapper = mount(NAvatar, {\n      slots: {\n        default: () =>\n          h(NIcon, null, {\n            default: () => h(CashIcon)\n          })\n      }\n    })\n    expect(wrapper.find('i').classes()).toContain('n-icon')\n    expect(wrapper.html()).toMatchSnapshot()\n    wrapper.unmount()\n  })\n\n  it('avatar adjust text', async () => {\n    const AdjustAvatar = {\n      data() {\n        return {\n          text: ''\n        }\n      },\n      render() {\n        const { text } = this as any\n        return <NAvatar size=\"medium\">{{ default: () => text }}</NAvatar>\n      }\n    }\n    const wrapper = mount(AdjustAvatar)\n    const textNode = wrapper.find('.n-avatar__text')\n    await wrapper.setData({ text: 'adjust text' })\n    await nextTick()\n    expect(textNode.exists()).toBe(true)\n    expect(wrapper.html()).toMatchSnapshot()\n    wrapper.unmount()\n  })\n\n  it('image avatar error handle when load failed', async () => {\n    const onError = vi.fn()\n    const wrapper = mount(NAvatar, {\n      props: {\n        src: 'https://07akioni.oss-cn-beijing.aliyuncs.com/07akioni.jpeg',\n        onError\n      }\n    })\n    await wrapper.find('img').trigger('error')\n    expect(onError).toHaveBeenCalled()\n    wrapper.unmount()\n  })\n\n  it('should work with `objectFit` prop', () => {\n    const wrapper = mount(NAvatar, {\n      props: {\n        src: 'https://07akioni.oss-cn-beijing.aliyuncs.com/07akioni.jpeg',\n        objectFit: 'contain'\n      }\n    })\n    expect(wrapper.find('img').attributes('style')).toContain(\n      'object-fit: contain;'\n    )\n    wrapper.unmount()\n  })\n})\n"
  },
  {
    "path": "src/avatar/tests/__snapshots__/Avatar.spec.tsx.snap",
    "content": "// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html\n\nexports[`n-avatar > avatar adjust text 1`] = `\n\"<span class=\"n-avatar\" style=\"--n-font-size: 14px; --n-border: none; --n-border-radius: 3px; --n-color: rgba(204, 204, 204, 1); --n-color-modal: rgba(204, 204, 204, 1); --n-color-popover: rgba(204, 204, 204, 1); --n-bezier: cubic-bezier(.4, 0, .2, 1); --n-merged-size: var(--n-avatar-size-override, 34px);\"><span class=\"n-avatar__text\">adjust text</span>\n<!----></span>\"\n`;\n\nexports[`n-avatar > bordered avatar 1`] = `\"<span class=\"n-avatar\" style=\"--n-font-size: 14px; --n-border: 2px solid #fff; --n-border-radius: 3px; --n-color: rgba(204, 204, 204, 1); --n-color-modal: rgba(204, 204, 204, 1); --n-color-popover: rgba(204, 204, 204, 1); --n-bezier: cubic-bezier(.4, 0, .2, 1); --n-merged-size: var(--n-avatar-size-override, 34px);\"><!----><!----></span>\"`;\n\nexports[`n-avatar > custom style 1`] = `\"<span class=\"n-avatar\" style=\"--n-font-size: 14px; --n-border: none; --n-border-radius: 3px; --n-color: rgba(204, 204, 204, 1); --n-color-modal: rgba(204, 204, 204, 1); --n-color-popover: rgba(204, 204, 204, 1); --n-bezier: cubic-bezier(.4, 0, .2, 1); --n-merged-size: var(--n-avatar-size-override, 34px); background-color: red;\"><!----><!----></span>\"`;\n\nexports[`n-avatar > icon avatar 1`] = `\n\"<span class=\"n-avatar\" style=\"--n-font-size: 14px; --n-border: none; --n-border-radius: 3px; --n-color: rgba(204, 204, 204, 1); --n-color-modal: rgba(204, 204, 204, 1); --n-color-popover: rgba(204, 204, 204, 1); --n-bezier: cubic-bezier(.4, 0, .2, 1); --n-merged-size: var(--n-avatar-size-override, 34px);\"><span class=\"n-avatar__text\"><i role=\"img\" class=\"n-icon\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1);\"><svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" viewBox=\"0 0 512 512\"><rect x=\"32\" y=\"80\" width=\"448\" height=\"256\" rx=\"16\" ry=\"16\" transform=\"rotate(180 256 208)\" fill=\"none\" stroke=\"currentColor\" stroke-linejoin=\"round\" stroke-width=\"32\"></rect><path fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"32\" d=\"M64 384h384\"></path><path fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"32\" d=\"M96 432h320\"></path><circle cx=\"256\" cy=\"208\" r=\"80\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"32\"></circle><path d=\"M480 160a80 80 0 0 1-80-80\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"32\"></path><path d=\"M32 160a80 80 0 0 0 80-80\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"32\"></path><path d=\"M480 256a80 80 0 0 0-80 80\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"32\"></path><path d=\"M32 256a80 80 0 0 1 80 80\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"32\"></path></svg></i></span>\n<!----></span>\"\n`;\n\nexports[`n-avatar > image avatar 1`] = `\"<span class=\"n-avatar\" style=\"--n-font-size: 14px; --n-border: none; --n-border-radius: 3px; --n-color: rgba(204, 204, 204, 1); --n-color-modal: rgba(204, 204, 204, 1); --n-color-popover: rgba(204, 204, 204, 1); --n-bezier: cubic-bezier(.4, 0, .2, 1); --n-merged-size: var(--n-avatar-size-override, 34px);\"><img loading=\"eager\" src=\"https://07akioni.oss-cn-beijing.aliyuncs.com/07akioni.jpeg\" data-image-src=\"https://07akioni.oss-cn-beijing.aliyuncs.com/07akioni.jpeg\"><!----></span>\"`;\n\nexports[`n-avatar > round avatar 1`] = `\"<span class=\"n-avatar\" style=\"--n-font-size: 14px; --n-border: none; --n-border-radius: 50%; --n-color: rgba(204, 204, 204, 1); --n-color-modal: rgba(204, 204, 204, 1); --n-color-popover: rgba(204, 204, 204, 1); --n-bezier: cubic-bezier(.4, 0, .2, 1); --n-merged-size: var(--n-avatar-size-override, 34px);\"><!----><!----></span>\"`;\n\nexports[`n-avatar > size is number 1`] = `\"<span class=\"n-avatar\" style=\"--n-font-size: 14px; --n-border: none; --n-border-radius: 3px; --n-color: rgba(204, 204, 204, 1); --n-color-modal: rgba(204, 204, 204, 1); --n-color-popover: rgba(204, 204, 204, 1); --n-bezier: cubic-bezier(.4, 0, .2, 1); --n-merged-size: var(--n-avatar-size-override, 50px);\"><!----><!----></span>\"`;\n\nexports[`n-avatar > size is string 1`] = `\"<span class=\"n-avatar\" style=\"--n-font-size: 14px; --n-border: none; --n-border-radius: 3px; --n-color: rgba(204, 204, 204, 1); --n-color-modal: rgba(204, 204, 204, 1); --n-color-popover: rgba(204, 204, 204, 1); --n-bezier: cubic-bezier(.4, 0, .2, 1); --n-merged-size: var(--n-avatar-size-override, 34px);\"><!----><!----></span>\"`;\n"
  },
  {
    "path": "src/avatar/tests/server.spec.tsx",
    "content": "import { setup } from '@css-render/vue3-ssr'\nimport { renderToString } from '@vue/server-renderer'\n/**\n * @vitest-environment node\n */\nimport { createSSRApp, h } from 'vue'\nimport { NAvatar } from '../..'\n\ndescribe('server side rendering', () => {\n  it('works', async () => {\n    const app = createSSRApp(() => <NAvatar />)\n    setup(app)\n    try {\n      await renderToString(app)\n    }\n    catch (e) {\n      expect(e).not.toBeTruthy()\n    }\n  })\n})\n"
  },
  {
    "path": "src/avatar-group/index.ts",
    "content": "export { avatarGroupProps, default as NAvatarGroup } from './src/AvatarGroup'\nexport type { AvatarGroupProps, AvatarGroupSlots } from './src/AvatarGroup'\nexport type * from './src/generic-public-types'\nexport type * from './src/public-types'\n"
  },
  {
    "path": "src/avatar-group/src/AvatarGroup.tsx",
    "content": "import type { CSSProperties, PropType, SlotsType, VNode } from 'vue'\nimport type { ThemeProps } from '../../_mixins'\nimport type { ExtractPublicPropTypes } from '../../_utils'\nimport type { Size } from '../../avatar/src/interface'\nimport type { AvatarGroupTheme } from '../styles'\nimport type {\n  AvatarGroupAvatarSlotProps,\n  AvatarGroupOption,\n  AvatarGroupRestSlotProps\n} from './public-types'\nimport { computed, defineComponent, h, provide } from 'vue'\nimport { useConfig, useTheme } from '../../_mixins'\nimport { useRtl } from '../../_mixins/use-rtl'\nimport NAvatar from '../../avatar/src/Avatar'\nimport { avatarGroupInjectionKey } from '../../avatar/src/context'\nimport { avatarGroupLight } from '../styles'\nimport style from './styles/avatar-group.cssr'\n\nexport interface AvatarGroupInjection {\n  size?: Size | undefined\n}\n\nexport const avatarGroupProps = {\n  ...(useTheme.props as ThemeProps<AvatarGroupTheme>),\n  max: Number,\n  maxStyle: [Object, String] as PropType<CSSProperties | string>,\n  options: {\n    type: Array as PropType<AvatarGroupOption[]>,\n    default: () => []\n  },\n  vertical: Boolean,\n  expandOnHover: Boolean,\n  size: [String, Number] as PropType<Size | undefined>\n} as const\n\nexport type AvatarGroupProps = ExtractPublicPropTypes<typeof avatarGroupProps>\n\nexport interface AvatarGroupSlots {\n  avatar?: (props: AvatarGroupAvatarSlotProps) => VNode[]\n  rest?: (props: AvatarGroupRestSlotProps) => VNode[]\n  default?: () => VNode[]\n}\n\nexport default defineComponent({\n  name: 'AvatarGroup',\n  props: avatarGroupProps,\n  slots: Object as SlotsType<AvatarGroupSlots>,\n  setup(props) {\n    const { mergedClsPrefixRef, mergedRtlRef } = useConfig(props)\n    const mergedThemeRef = useTheme(\n      'AvatarGroup',\n      '-avatar-group',\n      style,\n      avatarGroupLight,\n      props,\n      mergedClsPrefixRef\n    )\n    provide(avatarGroupInjectionKey, props)\n    const rtlEnabledRef = useRtl(\n      'AvatarGroup',\n      mergedRtlRef,\n      mergedClsPrefixRef\n    )\n    const restOptionsRef = computed(() => {\n      const { max } = props\n      if (max === undefined)\n        return undefined\n      const { options } = props\n      if (options.length > max)\n        return options.slice(max - 1, options.length)\n      return []\n    })\n    const displayedOptionsRef = computed(() => {\n      const { options, max } = props\n      if (max === undefined)\n        return options\n      if (options.length > max)\n        return options.slice(0, max - 1)\n      if (options.length === max)\n        return options.slice(0, max)\n      return options\n    })\n    return {\n      mergedTheme: mergedThemeRef,\n      rtlEnabled: rtlEnabledRef,\n      mergedClsPrefix: mergedClsPrefixRef,\n      restOptions: restOptionsRef,\n      displayedOptions: displayedOptionsRef,\n      cssVars: computed(() => {\n        return {\n          '--n-gap': mergedThemeRef.value.self.gap\n        }\n      })\n    }\n  },\n  render() {\n    const {\n      mergedClsPrefix,\n      displayedOptions,\n      restOptions,\n      mergedTheme,\n      $slots\n    } = this\n    return (\n      <div\n        class={[\n          `${mergedClsPrefix}-avatar-group`,\n          this.rtlEnabled && `${mergedClsPrefix}-avatar-group--rtl`,\n          this.vertical && `${mergedClsPrefix}-avatar-group--vertical`,\n          this.expandOnHover\n          && `${mergedClsPrefix}-avatar-group--expand-on-hover`\n        ]}\n        style={this.cssVars}\n        role=\"group\"\n      >\n        {displayedOptions.map((option) => {\n          return $slots.avatar ? (\n            $slots.avatar({ option })\n          ) : (\n            <NAvatar\n              src={option.src}\n              theme={mergedTheme.peers.Avatar}\n              themeOverrides={mergedTheme.peerOverrides.Avatar}\n            />\n          )\n        })}\n        {restOptions !== undefined\n          && restOptions.length > 0\n          && ($slots.rest ? (\n            $slots.rest({ options: restOptions, rest: restOptions.length })\n          ) : (\n            <NAvatar\n              style={this.maxStyle}\n              theme={mergedTheme.peers.Avatar}\n              themeOverrides={mergedTheme.peerOverrides.Avatar}\n            >\n              {{\n                default: () => `+${restOptions.length}`\n              }}\n            </NAvatar>\n          ))}\n      </div>\n    )\n  }\n})\n"
  },
  {
    "path": "src/avatar-group/src/generic-public-types.ts",
    "content": "import type { CSSProperties, VNode } from 'vue'\nimport type { Equal, Expect, ThemeRelatedProps } from '../../_utils'\nimport type { Size } from '../../avatar/src/interface'\nimport type { AvatarGroupProps } from './AvatarGroup'\nimport type {\n  AvatarGroupAvatarSlotProps,\n  AvatarGroupOption,\n  AvatarGroupRestSlotProps\n} from './public-types'\n\ninterface ResolvableAvatarGroupProps<\n  T extends AvatarGroupOption = AvatarGroupOption\n> {\n  options?: T[]\n  vertical?: boolean\n  expandOnHover?: boolean\n  size?: Size\n  max?: number\n  maxStyle?: string | CSSProperties\n}\n\n// eslint-disable-next-line ts/ban-ts-comment\n// @ts-ignore\ntype _\n  //\n  = Expect<\n    Equal<Omit<AvatarGroupProps, ThemeRelatedProps>, ResolvableAvatarGroupProps>\n  >\n\nexport type GAvatarGroupProps<T extends AvatarGroupOption>\n  = ResolvableAvatarGroupProps<T>\n\nexport interface GAvatarGroupSlots<T extends AvatarGroupOption> {\n  avatar?: (props: AvatarGroupAvatarSlotProps<T>) => VNode[]\n  rest?: (props: AvatarGroupRestSlotProps<T>) => VNode[]\n  default?: () => VNode[]\n}\n"
  },
  {
    "path": "src/avatar-group/src/public-types.ts",
    "content": "export interface AvatarGroupAvatarSlotProps<\n  T extends AvatarGroupOption = AvatarGroupOption\n> {\n  option: T\n}\n\nexport interface AvatarGroupRestSlotProps<\n  T extends AvatarGroupOption = AvatarGroupOption\n> {\n  options: Array<T>\n  rest: number\n}\n\nexport interface AvatarGroupOption {\n  src: string\n}\n"
  },
  {
    "path": "src/avatar-group/src/styles/avatar-group-rtl.cssr.ts",
    "content": "import { c, cB, cM, cNotM } from '../../../_utils/cssr'\n\n// --n-gap\nexport default cB('avatar-group', [\n  cM('rtl', `\n    direction: rtl;\n  `, [\n    cNotM('vertical', `\n      flex-direction: row;\n    `, [\n      cB('avatar', [\n        c('&:not(:first-child)', `\n          margin-right: var(--n-gap);\n          margin-left: 0;\n        `)\n      ])\n    ])\n  ])\n])\n"
  },
  {
    "path": "src/avatar-group/src/styles/avatar-group.cssr.ts",
    "content": "import { c, cB, cM, cNotM } from '../../../_utils/cssr/index'\n\n// --n-gap\nexport default cB('avatar-group', `\n  flex-wrap: nowrap;\n  display: inline-flex;\n  position: relative;\n`, [\n  cM('expand-on-hover', [\n    cB('avatar', [\n      c('&:not(:first-child)', `\n         transition: margin .3s var(--n-bezier);\n      `)\n    ]),\n    c('&:hover', [\n      cNotM('vertical', [\n        cB('avatar', [\n          c('&:not(:first-child)', `\n             margin-left: 0 !important;\n          `)\n        ])\n      ]),\n      cM('vertical', [\n        cB('avatar', [\n          c('&:not(:first-child)', `\n             margin-top: 0 !important;\n          `)\n        ])\n      ])\n    ])\n  ]),\n  cNotM('vertical', `\n    flex-direction: row;\n  `, [\n    cB('avatar', [\n      c('&:not(:first-child)', `\n         margin-left: var(--n-gap);\n      `)\n    ])\n  ]),\n  cM('vertical', `\n    flex-direction: column;\n  `, [\n    cB('avatar', [\n      c('&:not(:first-child)', `\n         margin-top: var(--n-gap);\n      `)\n    ])\n  ])\n])\n"
  },
  {
    "path": "src/avatar-group/styles/dark.ts",
    "content": "import type { AvatarGroupTheme } from './light'\nimport { commonDark } from '../../_styles/common'\nimport { avatarDark } from '../../avatar/styles'\nimport { self } from './light'\n\nconst avatarGroupDark: AvatarGroupTheme = {\n  name: 'AvatarGroup',\n  common: commonDark,\n  peers: {\n    Avatar: avatarDark\n  },\n  self\n}\n\nexport default avatarGroupDark\n"
  },
  {
    "path": "src/avatar-group/styles/index.ts",
    "content": "export { default as avatarGroupDark } from './dark'\nexport { default as avatarGroupLight } from './light'\nexport type { AvatarGroupTheme, AvatarGroupThemeVars } from './light'\nexport { avatarGroupRtl } from './rtl'\n"
  },
  {
    "path": "src/avatar-group/styles/light.ts",
    "content": "import { createTheme } from '../../_mixins'\nimport { commonLight } from '../../_styles/common'\nimport { avatarLight } from '../../avatar/styles'\n\nexport type AvatarGroupThemeVars = Record<string, unknown>\n\nexport function self() {\n  return {\n    gap: '-12px'\n  }\n}\n\nconst avatarGroupLight = createTheme({\n  name: 'AvatarGroup',\n  common: commonLight,\n  peers: {\n    Avatar: avatarLight\n  },\n  self\n})\n\nexport default avatarGroupLight\nexport type AvatarGroupTheme = typeof avatarGroupLight\n"
  },
  {
    "path": "src/avatar-group/styles/rtl.ts",
    "content": "import type { RtlItem } from '../../config-provider/src/internal-interface'\nimport rtlStyle from '../src/styles/avatar-group-rtl.cssr'\n\nexport const avatarGroupRtl: RtlItem = {\n  name: 'AvatarGroup',\n  style: rtlStyle\n}\n"
  },
  {
    "path": "src/avatar-group/tests/Avatar.spec.tsx",
    "content": "import { mount } from '@vue/test-utils'\nimport { NAvatarGroup } from '../index'\n\ndescribe('n-avatar-group', () => {\n  it('should work with `options` prop in `avatar group`', async () => {\n    const options = [\n      {\n        name: 'test1',\n        src: 'https://www.naiveui.com/assets/naivelogo.93278402.svg'\n      },\n      {\n        name: 'test2',\n        src: 'https://07akioni.oss-cn-beijing.aliyuncs.com/07akioni.jpeg'\n      },\n      {\n        name: 'test3',\n        src: 'https://gw.alipayobjects.com/zos/antfincdn/aPkFc8Sj7n/method-draw-image.svg'\n      },\n      {\n        name: 'test4',\n        src: 'https://07akioni.oss-cn-beijing.aliyuncs.com/07akioni.jpeg'\n      }\n    ]\n    const wrapper = mount(NAvatarGroup, {\n      props: {\n        options,\n        max: 2\n      }\n    })\n    expect(wrapper.findAll('.n-avatar').length).toBe(2)\n\n    await wrapper.setProps({ vertical: true })\n    expect(wrapper.find('[role=\"group\"]').classes()).toContain(\n      'n-avatar-group--vertical'\n    )\n\n    await wrapper.setProps({ max: 4 })\n    expect(wrapper.find('.n-avatar__text').exists()).toBe(false)\n\n    await wrapper.setProps({ options: [] })\n    expect(wrapper.findAll('.n-avatar').length).toBe(0)\n    wrapper.unmount()\n  })\n})\n"
  },
  {
    "path": "src/avatar-group/tests/server.spec.tsx",
    "content": "import { setup } from '@css-render/vue3-ssr'\nimport { renderToString } from '@vue/server-renderer'\n/**\n * @vitest-environment node\n */\nimport { createSSRApp, h } from 'vue'\nimport { NAvatar } from '../..'\n\ndescribe('server side rendering', () => {\n  it('works', async () => {\n    const app = createSSRApp(() => <NAvatar />)\n    setup(app)\n    try {\n      await renderToString(app)\n    }\n    catch (e) {\n      expect(e).not.toBeTruthy()\n    }\n  })\n})\n"
  },
  {
    "path": "src/back-top/demos/enUS/basic.demo.vue",
    "content": "<markdown>\n# Basic\n\nBackTop will find its first scrollable ascendant element and listen scroll event on it.\n</markdown>\n\n<template>\n  <n-back-top :right=\"100\" />\n</template>\n"
  },
  {
    "path": "src/back-top/demos/enUS/change-position.demo.vue",
    "content": "<markdown>\n# Change position\n\nFor example: right 40px & bottom 160px.\n</markdown>\n\n<template>\n  <n-back-top\n    :right=\"40\"\n    :bottom=\"160\"\n    :style=\"{\n      transition: 'all .3s cubic-bezier(.4, 0, .2, 1)',\n    }\"\n  >\n    <div\n      style=\"\n        width: 200px;\n        height: 40px;\n        line-height: 40px;\n        text-align: center;\n        font-size: 14px;\n      \"\n    >\n      Change Position\n    </div>\n  </n-back-top>\n</template>\n"
  },
  {
    "path": "src/back-top/demos/enUS/index.demo-entry.md",
    "content": "# Back Top\n\n<!--single-column-->\n\nIt helps you back to where you were. However, time never goes back.\n\n## Demos\n\nScroll down to see demos work.\n\n```demo\nbasic.vue\nvisibility-height.vue\nchange-position.vue\ntarget-container-selector.vue\n```\n\n## API\n\n### BackTop Props\n\n| Name | Type | Default | Description |\n| --- | --- | --- | --- |\n| bottom | `number \\| string` | `40` | The height of BackTop from the bottom of the page |\n| listen-to | `string \\| HTMLElement` | `undefined` | The element to be listened to scroll event. If it is `undefined` back top will listen to the nearest scrollable parent. |\n| right | `number \\| string` | `40` | The width of BackTop from the right side of the page |\n| show | `boolean` | `undefined` | Whether to show BackTop |\n| to | `string \\| HTMLElement` | `'body'` | Container node to show BackTop |\n| visibility-height | `number` | `180` | BackTop's trigger scroll top. |\n| on-update:show | `(value: boolean) => void` | `undefined` | Callback is triggered when back-top display changes. |\n"
  },
  {
    "path": "src/back-top/demos/enUS/target-container-selector.demo.vue",
    "content": "<markdown>\n# Target to be listened to\n\nYou can specify target to listen scroll event of.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst scrollContainer = ref<HTMLElement | undefined>(undefined)\n\nconst target = () => scrollContainer.value\n</script>\n\n<template>\n  <n-back-top\n    :listen-to=\"target\"\n    :bottom=\"220\"\n    :visibility-height=\"10\"\n    :style=\"{\n      transition: 'all .3s cubic-bezier(.4, 0, .2, 1)',\n    }\"\n  >\n    <div\n      style=\"\n        width: 200px;\n        height: 40px;\n        line-height: 40px;\n        text-align: center;\n        font-size: 14px;\n      \"\n    >\n      Specify Target\n    </div>\n  </n-back-top>\n  <div\n    ref=\"scrollContainer\"\n    style=\"overflow: auto; height: 72px; line-height: 1.5\"\n  >\n    A funny joke is need to be wrote here.<br>\n    A funny joke is need to be wrote here.<br>\n    A funny joke is need to be wrote here.<br>\n    A funny joke is need to be wrote here.<br>\n    A funny joke is need to be wrote here.<br>\n    A funny joke is need to be wrote here.<br>\n    A funny joke is need to be wrote here.<br>\n  </div>\n</template>\n"
  },
  {
    "path": "src/back-top/demos/enUS/visibility-height.demo.vue",
    "content": "<markdown>\n# Visibility height\n\nYou can change visibility height of backtop.\n</markdown>\n\n<template>\n  <n-back-top\n    :bottom=\"100\"\n    :visibility-height=\"300\"\n    :style=\"{\n      transition: 'all .3s cubic-bezier(.4, 0, .2, 1)',\n    }\"\n  >\n    <div\n      style=\"\n        width: 200px;\n        height: 40px;\n        line-height: 40px;\n        text-align: center;\n        font-size: 14px;\n      \"\n    >\n      Visibility Height: 300px\n    </div>\n  </n-back-top>\n</template>\n"
  },
  {
    "path": "src/back-top/demos/zhCN/basic.demo.vue",
    "content": "<markdown>\n# 基础用法\n\nBackTop 会找到首个可滚动的祖先元素并且监听它的滚动事件。\n</markdown>\n\n<template>\n  <n-back-top :right=\"100\" />\n</template>\n"
  },
  {
    "path": "src/back-top/demos/zhCN/change-position.demo.vue",
    "content": "<markdown>\n# 改变位置\n\n例如：right 40px & bottom 160px。\n</markdown>\n\n<template>\n  <n-back-top :right=\"40\" :bottom=\"160\">\n    <div\n      style=\"\n        width: 200px;\n        height: 40px;\n        line-height: 40px;\n        text-align: center;\n        font-size: 14px;\n      \"\n    >\n      改变位置\n    </div>\n  </n-back-top>\n</template>\n"
  },
  {
    "path": "src/back-top/demos/zhCN/index.demo-entry.md",
    "content": "# 回到顶部 Back Top\n\n<!--single-column-->\n\n它可以帮你回到你曾经到过的地方。不过时间是回不去了。\n\n## 演示\n\n向下滚动页面查看效果。\n\n```demo\nbasic.vue\nvisibility-height.vue\nchange-position.vue\ntarget-container-selector.vue\n```\n\n## API\n\n### BackTop Props\n\n| 名称 | 类型 | 默认值 | 说明 |\n| --- | --- | --- | --- |\n| bottom | `number \\| string` | `40` | BackTop 距离页面底部的高度 |\n| listen-to | `string \\| HTMLElement` | `undefined` | 监听滚动的元素，如果为 `undefined` 会监听距离最近的一个可滚动的祖先节点 |\n| right | `number \\| string` | `40` | BackTop 距离页面右侧的宽度 |\n| show | `boolean` | `undefined` | 是否显示 BackTop（受控） |\n| to | `string \\| HTMLElement` | `'body'` | BackTop 渲染的容器节点 |\n| visibility-height | `number` | `180` | 滚动时触发显示回到顶部的高度 |\n| on-update:show | `(value: boolean) => void` | `undefined` | BackTop 的 show 改变时触发事件 |\n"
  },
  {
    "path": "src/back-top/demos/zhCN/target-container-selector.demo.vue",
    "content": "<markdown>\n# 监听目标\n\n你可以设定监听哪个元素来触发 Back Top。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst scrollContainer = ref<HTMLElement | undefined>(undefined)\n\nconst target = () => scrollContainer.value\n</script>\n\n<template>\n  <n-back-top :listen-to=\"target\" :bottom=\"220\" :visibility-height=\"10\">\n    <div\n      style=\"\n        width: 200px;\n        height: 40px;\n        line-height: 40px;\n        text-align: center;\n        font-size: 14px;\n      \"\n    >\n      指定目标\n    </div>\n  </n-back-top>\n  <div\n    ref=\"scrollContainer\"\n    style=\"overflow: auto; height: 72px; line-height: 1.5\"\n  >\n    这块应该写一个有意思的笑话。<br>\n    这块应该写一个有意思的笑话。<br>\n    这块应该写一个有意思的笑话。<br>\n    这块应该写一个有意思的笑话。<br>\n    这块应该写一个有意思的笑话。<br>\n    这块应该写一个有意思的笑话。<br>\n    这块应该写一个有意思的笑话。<br>\n  </div>\n</template>\n"
  },
  {
    "path": "src/back-top/demos/zhCN/visibility-height.demo.vue",
    "content": "<markdown>\n# 可视高度\n\n可以改变 Back Top 的可视高度。\n</markdown>\n\n<template>\n  <n-back-top :bottom=\"100\" :visibility-height=\"300\">\n    <div\n      style=\"\n        width: 200px;\n        height: 40px;\n        line-height: 40px;\n        text-align: center;\n        font-size: 14px;\n      \"\n    >\n      可视高度：300px\n    </div>\n  </n-back-top>\n</template>\n"
  },
  {
    "path": "src/back-top/index.ts",
    "content": "export { backTopProps, default as NBackTop } from './src/BackTop'\nexport type { BackTopProps } from './src/BackTop'\n"
  },
  {
    "path": "src/back-top/src/BackTop.tsx",
    "content": "import type { PropType } from 'vue'\nimport type { ThemeProps } from '../../_mixins'\nimport type { ExtractPublicPropTypes } from '../../_utils'\nimport type { BackTopTheme } from '../styles'\nimport { getScrollParent, unwrapElement } from 'seemly'\nimport { useIsMounted, useMergedState } from 'vooks'\nimport {\n  computed,\n  defineComponent,\n  h,\n  mergeProps,\n  nextTick,\n  onBeforeUnmount,\n  onMounted,\n  ref,\n  toRef,\n  Transition,\n  watch,\n  watchEffect\n} from 'vue'\nimport { VLazyTeleport } from 'vueuc'\nimport { NBaseIcon } from '../../_internal'\nimport { useConfig, useTheme, useThemeClass } from '../../_mixins'\nimport {\n  formatLength,\n  isDocument,\n  lockHtmlScrollRightCompensationRef,\n  resolveSlot,\n  warn,\n  warnOnce\n} from '../../_utils'\nimport { backTopLight } from '../styles'\nimport renderBackTopIcon from './BackTopIcon'\nimport style from './styles/index.cssr'\n\nexport const backTopProps = {\n  ...(useTheme.props as ThemeProps<BackTopTheme>),\n  show: {\n    type: Boolean as PropType<boolean | undefined>,\n    default: undefined\n  },\n  right: {\n    type: [Number, String] as PropType<string | number>,\n    default: 40\n  },\n  bottom: {\n    type: [Number, String] as PropType<string | number>,\n    default: 40\n  },\n  to: {\n    type: [String, Object] as PropType<HTMLElement | string>,\n    default: 'body'\n  },\n  visibilityHeight: {\n    type: Number,\n    default: 180\n  },\n  listenTo: [String, Object, Function] as PropType<\n    string | HTMLElement | Document | (() => HTMLElement | Document)\n  >,\n  'onUpdate:show': {\n    type: Function,\n    default: () => {}\n  },\n  // deprecated\n  target: Function as PropType<() => HTMLElement>,\n  onShow: Function as unknown as PropType<() => void>,\n  onHide: Function as unknown as PropType<() => void>\n} as const\n\nexport type BackTopProps = ExtractPublicPropTypes<typeof backTopProps>\n\nexport default defineComponent({\n  name: 'BackTop',\n  // make style applied to back-top button\n  inheritAttrs: false,\n  props: backTopProps,\n  setup(props) {\n    if (__DEV__) {\n      watchEffect(() => {\n        if (props.target !== undefined) {\n          warnOnce(\n            'back-top',\n            '`target` is deprecated, please use `listen-to` instead.'\n          )\n        }\n        if (props.onShow !== undefined) {\n          warnOnce(\n            'back-top',\n            '`on-show` is deprecated, please use `on-update:show` instead.'\n          )\n        }\n        if (props.onHide !== undefined) {\n          warnOnce(\n            'back-top',\n            '`on-hide` is deprecated, please use `on-update:show` instead.'\n          )\n        }\n      })\n    }\n    const { mergedClsPrefixRef, inlineThemeDisabled } = useConfig(props)\n\n    const scrollTopRef = ref<number | null>(null)\n    const uncontrolledShowRef = ref(false)\n    watchEffect(() => {\n      const { value: scrollTop } = scrollTopRef\n      if (scrollTop === null) {\n        uncontrolledShowRef.value = false\n        return\n      }\n      uncontrolledShowRef.value = scrollTop >= props.visibilityHeight\n    })\n    const DomInfoReadyRef = ref(false)\n    watch(uncontrolledShowRef, (value) => {\n      if (DomInfoReadyRef.value) {\n        props['onUpdate:show']?.(value)\n      }\n    })\n    const controlledShowRef = toRef(props, 'show')\n    const mergedShowRef = useMergedState(controlledShowRef, uncontrolledShowRef)\n    const transitionDisabledRef = ref(true)\n    const placeholderRef = ref<HTMLElement | null>(null)\n    const styleRef = computed(\n      (): {\n        right: string\n        bottom: string\n      } => {\n        return {\n          right: `calc(${formatLength(props.right)} + ${\n            lockHtmlScrollRightCompensationRef.value\n          })`,\n          bottom: formatLength(props.bottom)\n        }\n      }\n    )\n    let scrollElement: HTMLElement | Document\n    let scrollListenerRegistered: boolean\n    // deprecated\n    watch(mergedShowRef, (value) => {\n      if (DomInfoReadyRef.value) {\n        if (value) {\n          props.onShow?.()\n        }\n        props.onHide?.()\n      }\n    })\n    const themeRef = useTheme(\n      'BackTop',\n      '-back-top',\n      style,\n      backTopLight,\n      props,\n      mergedClsPrefixRef\n    )\n    function init(): void {\n      if (scrollListenerRegistered)\n        return\n      scrollListenerRegistered = true\n      const scrollEl\n        = props.target?.()\n          || unwrapElement(props.listenTo)\n          || getScrollParent(placeholderRef.value)\n      if (!scrollEl) {\n        if (__DEV__) {\n          warn(\n            'back-top',\n            'Container of back-top element is not found. This could be a bug of naive-ui.'\n          )\n        }\n        return\n      }\n      scrollElement\n        = scrollEl === document.documentElement ? document : scrollEl\n      const { to } = props\n      const target = typeof to === 'string' ? document.querySelector(to) : to\n      if (__DEV__ && !target) {\n        warn('back-top', 'Target is not found.')\n      }\n      scrollElement.addEventListener('scroll', handleScroll)\n      handleScroll()\n    }\n    function handleClick(): void {\n      ;(isDocument(scrollElement)\n        ? document.documentElement\n        : scrollElement\n      ).scrollTo({\n        top: 0,\n        behavior: 'smooth'\n      })\n    }\n    function handleScroll(): void {\n      scrollTopRef.value = (\n        isDocument(scrollElement) ? document.documentElement : scrollElement\n      ).scrollTop\n      if (!DomInfoReadyRef.value) {\n        void nextTick(() => {\n          DomInfoReadyRef.value = true\n        })\n      }\n    }\n    function handleAfterEnter(): void {\n      transitionDisabledRef.value = false\n    }\n    onMounted(() => {\n      init()\n      transitionDisabledRef.value = mergedShowRef.value\n    })\n    onBeforeUnmount(() => {\n      if (scrollElement) {\n        scrollElement.removeEventListener('scroll', handleScroll)\n      }\n    })\n\n    const cssVarsRef = computed(() => {\n      const {\n        self: {\n          color,\n          boxShadow,\n          boxShadowHover,\n          boxShadowPressed,\n          iconColor,\n          iconColorHover,\n          iconColorPressed,\n          width,\n          height,\n          iconSize,\n          borderRadius,\n          textColor\n        },\n        common: { cubicBezierEaseInOut }\n      } = themeRef.value\n      return {\n        '--n-bezier': cubicBezierEaseInOut,\n        '--n-border-radius': borderRadius,\n        '--n-height': height,\n        '--n-width': width,\n        '--n-box-shadow': boxShadow,\n        '--n-box-shadow-hover': boxShadowHover,\n        '--n-box-shadow-pressed': boxShadowPressed,\n        '--n-color': color,\n        '--n-icon-size': iconSize,\n        '--n-icon-color': iconColor,\n        '--n-icon-color-hover': iconColorHover,\n        '--n-icon-color-pressed': iconColorPressed,\n        '--n-text-color': textColor\n      }\n    })\n    const themeClassHandle = inlineThemeDisabled\n      ? useThemeClass('back-top', undefined, cssVarsRef, props)\n      : undefined\n    return {\n      placeholderRef,\n      style: styleRef,\n      mergedShow: mergedShowRef,\n      isMounted: useIsMounted(),\n      scrollElement: ref(null),\n      scrollTop: scrollTopRef,\n      DomInfoReady: DomInfoReadyRef,\n      transitionDisabled: transitionDisabledRef,\n      mergedClsPrefix: mergedClsPrefixRef,\n      handleAfterEnter,\n      handleScroll,\n      handleClick,\n      cssVars: inlineThemeDisabled ? undefined : cssVarsRef,\n      themeClass: themeClassHandle?.themeClass,\n      onRender: themeClassHandle?.onRender\n    }\n  },\n  render() {\n    const { mergedClsPrefix } = this\n    return (\n      <div\n        ref=\"placeholderRef\"\n        class={`${mergedClsPrefix}-back-top-placeholder`}\n        style=\"display: none\"\n        aria-hidden\n      >\n        <VLazyTeleport to={this.to} show={this.mergedShow}>\n          {{\n            default: () => (\n              <Transition\n                name=\"fade-in-scale-up-transition\"\n                appear={this.isMounted}\n                onAfterEnter={this.handleAfterEnter}\n              >\n                {{\n                  default: () => {\n                    this.onRender?.()\n                    return this.mergedShow\n                      ? h(\n                          'div',\n                          mergeProps(this.$attrs, {\n                            class: [\n                              `${mergedClsPrefix}-back-top`,\n                              this.themeClass,\n                              this.transitionDisabled\n                              && `${mergedClsPrefix}-back-top--transition-disabled`\n                            ],\n                            style: [this.style, this.cssVars],\n                            onClick: this.handleClick\n                          }),\n                          resolveSlot(this.$slots.default, () => [\n                            <NBaseIcon clsPrefix={mergedClsPrefix}>\n                              {{ default: renderBackTopIcon }}\n                            </NBaseIcon>\n                          ])\n                        )\n                      : null\n                  }\n                }}\n              </Transition>\n            )\n          }}\n        </VLazyTeleport>\n      </div>\n    )\n  }\n})\n"
  },
  {
    "path": "src/back-top/src/BackTopIcon.tsx",
    "content": "import { h } from 'vue'\n\nexport default () => (\n  <svg\n    viewBox=\"0 0 24 24\"\n    version=\"1.1\"\n    xmlns=\"http://www.w3.org/2000/svg\"\n    xlinkHref=\"http://www.w3.org/1999/xlink\"\n  >\n    <g stroke=\"none\" stroke-width=\"1\" fill-rule=\"evenodd\">\n      <g transform=\"translate(-139.000000, -4423.000000)\" fill-rule=\"nonzero\">\n        <g transform=\"translate(120.000000, 4285.000000)\">\n          <g transform=\"translate(7.000000, 126.000000)\">\n            <g transform=\"translate(24.000000, 24.000000) scale(1, -1) translate(-24.000000, -24.000000) translate(12.000000, 12.000000)\">\n              <g transform=\"translate(4.000000, 2.000000)\">\n                <path d=\"M8,0 C8.51283584,0 8.93550716,0.38604019 8.99327227,0.883378875 L9,1 L9,10.584 L12.2928932,7.29289322 C12.6834175,6.90236893 13.3165825,6.90236893 13.7071068,7.29289322 C14.0675907,7.65337718 14.0953203,8.22060824 13.7902954,8.61289944 L13.7071068,8.70710678 L8.70710678,13.7071068 L8.62544899,13.7803112 L8.618,13.784 L8.59530661,13.8036654 L8.4840621,13.8753288 L8.37133602,13.9287745 L8.22929083,13.9735893 L8.14346259,13.9897165 L8.03324678,13.9994506 L7.9137692,13.9962979 L7.77070917,13.9735893 L7.6583843,13.9401293 L7.57677845,13.9063266 L7.47929125,13.8540045 L7.4048407,13.8036865 L7.38131006,13.7856883 C7.35030318,13.7612383 7.32077858,13.7349921 7.29289322,13.7071068 L2.29289322,8.70710678 L2.20970461,8.61289944 C1.90467972,8.22060824 1.93240926,7.65337718 2.29289322,7.29289322 C2.65337718,6.93240926 3.22060824,6.90467972 3.61289944,7.20970461 L3.70710678,7.29289322 L7,10.585 L7,1 L7.00672773,0.883378875 C7.06449284,0.38604019 7.48716416,0 8,0 Z\" />\n                <path d=\"M14.9333333,15.9994506 C15.5224371,15.9994506 16,16.4471659 16,16.9994506 C16,17.5122865 15.5882238,17.9349578 15.0577292,17.9927229 L14.9333333,17.9994506 L1.06666667,17.9994506 C0.477562934,17.9994506 0,17.5517354 0,16.9994506 C0,16.4866148 0.411776203,16.0639435 0.9422708,16.0061783 L1.06666667,15.9994506 L14.9333333,15.9994506 Z\" />\n              </g>\n            </g>\n          </g>\n        </g>\n      </g>\n    </g>\n  </svg>\n)\n"
  },
  {
    "path": "src/back-top/src/styles/index.cssr.ts",
    "content": "import { fadeInScaleUpTransition } from '../../../_styles/transitions/fade-in-scale-up.cssr'\nimport { c, cB, cM } from '../../../_utils/cssr'\n\n// vars:\n// --n-bezier\n// --n-border-radius\n// --n-height\n// --n-width\n// --n-box-shadow\n// --n-box-shadow-hover\n// --n-box-shadow-pressed\n// --n-color\n// --n-icon-size\n// --n-icon-color\n// --n-icon-color-hover\n// --n-icon-color-pressed\n// --n-text-color\nexport default cB('back-top', `\n  position: fixed;\n  right: 40px;\n  bottom: 40px;\n  cursor: pointer;\n  display: flex;\n  align-items: center;\n  justify-content: center;\n  color: var(--n-text-color);\n  transition:\n    color .3s var(--n-bezier),\n    box-shadow .3s var(--n-bezier),\n    background-color .3s var(--n-bezier);\n  border-radius: var(--n-border-radius);\n  height: var(--n-height);\n  min-width: var(--n-width);\n  box-shadow: var(--n-box-shadow);\n  background-color: var(--n-color);\n`, [\n  fadeInScaleUpTransition(),\n  cM('transition-disabled', {\n    transition: 'none !important'\n  }),\n  cB('base-icon', `\n    font-size: var(--n-icon-size);\n    color: var(--n-icon-color);\n    transition: color .3s var(--n-bezier);\n  `),\n  c('svg', {\n    pointerEvents: 'none'\n  }),\n  c('&:hover', {\n    boxShadow: 'var(--n-box-shadow-hover)'\n  }, [\n    cB('base-icon', {\n      color: 'var(--n-icon-color-hover)'\n    })\n  ]),\n  c('&:active', {\n    boxShadow: 'var(--n-box-shadow-pressed)'\n  }, [\n    cB('base-icon', {\n      color: 'var(--n-icon-color-pressed)'\n    })\n  ])\n])\n"
  },
  {
    "path": "src/back-top/styles/_common.ts",
    "content": "export default {\n  width: '44px',\n  height: '44px',\n  borderRadius: '22px',\n  iconSize: '26px'\n}\n"
  },
  {
    "path": "src/back-top/styles/dark.ts",
    "content": "import type { BackTopTheme } from './light'\nimport { commonDark } from '../../_styles/common'\nimport commonVariables from './_common'\n\nconst backTopDark: BackTopTheme = {\n  name: 'BackTop',\n  common: commonDark,\n  self(vars) {\n    const { popoverColor, textColor2, primaryColorHover, primaryColorPressed }\n      = vars\n    return {\n      ...commonVariables,\n      color: popoverColor,\n      textColor: textColor2,\n      iconColor: textColor2,\n      iconColorHover: primaryColorHover,\n      iconColorPressed: primaryColorPressed,\n      boxShadow: '0 2px 8px 0px rgba(0, 0, 0, .12)',\n      boxShadowHover: '0 2px 12px 0px rgba(0, 0, 0, .18)',\n      boxShadowPressed: '0 2px 12px 0px rgba(0, 0, 0, .18)'\n    }\n  }\n}\n\nexport default backTopDark\n"
  },
  {
    "path": "src/back-top/styles/index.ts",
    "content": "export { default as backTopDark } from './dark'\nexport { default as backTopLight } from './light'\nexport type { BackTopTheme, BackTopThemeVars } from './light'\n"
  },
  {
    "path": "src/back-top/styles/light.ts",
    "content": "import type { Theme } from '../../_mixins'\nimport type { ThemeCommonVars } from '../../_styles/common'\nimport { commonLight } from '../../_styles/common'\nimport commonVariables from './_common'\n\nfunction self(vars: ThemeCommonVars) {\n  const { popoverColor, textColor2, primaryColorHover, primaryColorPressed }\n    = vars\n  return {\n    ...commonVariables,\n    color: popoverColor,\n    textColor: textColor2,\n    iconColor: textColor2,\n    iconColorHover: primaryColorHover,\n    iconColorPressed: primaryColorPressed,\n    boxShadow: '0 2px 8px 0px rgba(0, 0, 0, .12)',\n    boxShadowHover: '0 2px 12px 0px rgba(0, 0, 0, .18)',\n    boxShadowPressed: '0 2px 12px 0px rgba(0, 0, 0, .18)'\n  }\n}\n\nexport type BackTopThemeVars = ReturnType<typeof self>\n\nconst backTopLight: Theme<'BackTop', BackTopThemeVars> = {\n  name: 'BackTop',\n  common: commonLight,\n  self\n}\n\nexport default backTopLight\nexport type BackTopTheme = typeof backTopLight\n"
  },
  {
    "path": "src/back-top/tests/BackTop.spec.ts",
    "content": "import { mount } from '@vue/test-utils'\nimport { NBackTop } from '../index'\n\ndescribe('n-back-top', () => {\n  it('should work with import on demand', () => {\n    mount(NBackTop, {\n      attachTo: document.body\n    })\n  })\n\n  it('should work with `show` prop', async () => {\n    document.body.innerHTML = `${document.body.innerHTML}\n      <div id=\"test\" style=\"height: 3000px; width: 100%;\"></div>\n    `\n\n    const wrapper = mount(NBackTop, {\n      attachTo: document.getElementById('test') ?? undefined,\n      props: {\n        show: true\n      }\n    })\n\n    wrapper.element.scrollTop = 1000\n    await wrapper.trigger('scroll')\n    expect(wrapper.html()).toContain('teleport start')\n    wrapper.unmount()\n  })\n})\n"
  },
  {
    "path": "src/back-top/tests/server.spec.tsx",
    "content": "import { setup } from '@css-render/vue3-ssr'\nimport { renderToString } from '@vue/server-renderer'\n/**\n * @vitest-environment node\n */\nimport { createSSRApp, h } from 'vue'\nimport { NBackTop } from '../..'\n\ndescribe('server side rendering', () => {\n  it('works', async () => {\n    const app = createSSRApp(() => <NBackTop />)\n    setup(app)\n    try {\n      await renderToString(app)\n    }\n    catch (e) {\n      expect(e).not.toBeTruthy()\n    }\n  })\n})\n"
  },
  {
    "path": "src/badge/demos/enUS/basic.demo.vue",
    "content": "<markdown>\n# Basic\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { MdAdd, MdRemove } from '@vicons/ionicons4'\nimport { ref } from 'vue'\n\nconst value = ref(5)\n</script>\n\n<template>\n  <n-space :size=\"24\" align=\"center\">\n    <n-badge :value=\"value\" :max=\"15\">\n      <n-avatar />\n    </n-badge>\n    <n-badge :value=\"value\" dot>\n      <n-avatar />\n    </n-badge>\n    <n-button-group>\n      <n-button @click=\"value = Math.min(16, value + 1)\">\n        <template #icon>\n          <n-icon><MdAdd /></n-icon>\n        </template>\n      </n-button>\n      <n-button @click=\"value = Math.max(0, value - 1)\">\n        <template #icon>\n          <n-icon><MdRemove /></n-icon>\n        </template>\n      </n-button>\n    </n-button-group>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/badge/demos/enUS/color.demo.vue",
    "content": "<markdown>\n# Customizing color\n</markdown>\n\n<template>\n  <n-badge value=\"15\" color=\"grey\">\n    <n-avatar />\n  </n-badge>\n</template>\n"
  },
  {
    "path": "src/badge/demos/enUS/custom-content.demo.vue",
    "content": "<markdown>\n# Customizing content\n\nInsert some custom content in it.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { LockClosedOutline } from '@vicons/ionicons5'\n</script>\n\n<template>\n  <n-space :size=\"24\" align=\"center\">\n    <n-badge value=\"new\">\n      <n-avatar />\n    </n-badge>\n    <n-badge value=\"hot\">\n      <n-avatar />\n    </n-badge>\n    <n-badge processing>\n      <n-avatar />\n      <template #value>\n        <n-icon :component=\"LockClosedOutline\" />\n      </template>\n    </n-badge>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/badge/demos/enUS/index.demo-entry.md",
    "content": "# Badge\n\nI bet you have seen it and know how it should be applied.\n\n## Demos\n\n```demo\nbasic.vue\ntype.vue\nprocessing.vue\nshow-zero.vue\noverflow.vue\nmanual.vue\ncustom-content.vue\ncolor.vue\nraw.vue\noffset.vue\n```\n\n## API\n\n### Badge Props\n\n| Name | Type | Default | Description | Version |\n| --- | --- | --- | --- | --- |\n| color | `string` | `undefined` | Badge color. |  |\n| dot | `boolean` | `false` | Show badge as dot. |  |\n| max | `number` | `undefined` | The maximum number of the badge when its value overflows. |  |\n| offset | `[string \\| number, string \\| number]` | `undefined` | Offset of the badge from the left and top of the default position. | 2.34.3 |\n| processing | `boolean` | `false` | Show processing status. |  |\n| show-zero | `boolean` | `false` | Whether to display the badge, even if provided value equals 0. |  |\n| show | `boolean` | `true` | Whether the badge should be shown altogether. |  |\n| type | `'default' \\| 'success' \\| 'error' \\| 'warning' \\| 'info'` | `'default'` | Type of the badge. |  |\n| value | `string \\| number` | `undefined` | Badge's value. |  |\n\n### Badge Slots\n\n| Name    | Parameters | Description      |\n| ------- | ---------- | ---------------- |\n| default | `()`       | Badge's content. |\n"
  },
  {
    "path": "src/badge/demos/enUS/manual.demo.vue",
    "content": "<markdown>\n# Controlled visibility\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { MdAdd, MdRemove } from '@vicons/ionicons4'\nimport { ref } from 'vue'\n\nconst value = ref(5)\nconst show = ref(true)\n</script>\n\n<template>\n  <n-space :size=\"24\" align=\"center\" item-style=\"display: flex;\">\n    <n-badge :value=\"value\" :max=\"15\" :show=\"show\">\n      <n-avatar />\n    </n-badge>\n    <n-badge :value=\"value\" dot :show=\"show\">\n      <n-avatar />\n    </n-badge>\n    <n-button-group>\n      <n-button @click=\"value = Math.min(16, value + 1)\">\n        <template #icon>\n          <n-icon><MdAdd /></n-icon>\n        </template>\n      </n-button>\n      <n-button @click=\"value = Math.max(0, value - 1)\">\n        <template #icon>\n          <n-icon><MdRemove /></n-icon>\n        </template>\n      </n-button>\n    </n-button-group>\n    <n-switch v-model:value=\"show\" />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/badge/demos/enUS/offset.demo.vue",
    "content": "<markdown>\n# Offset\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst value = ref(5)\nconst offset = [-17, 17] as const\n</script>\n\n<template>\n  <n-badge :value=\"value\" :max=\"15\" :offset=\"offset\">\n    <n-avatar />\n  </n-badge>\n</template>\n"
  },
  {
    "path": "src/badge/demos/enUS/overflow.demo.vue",
    "content": "<markdown>\n# Overflow\n\nSet `max` prop to handle overflow situation.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { MdAdd, MdRemove } from '@vicons/ionicons4'\nimport { ref } from 'vue'\n\nconst value = ref(101)\n</script>\n\n<template>\n  <n-space :size=\"24\" align=\"center\">\n    <n-badge :value=\"value\" show-zero>\n      <n-avatar />\n    </n-badge>\n    <n-badge :value=\"value\" :max=\"99\">\n      <n-avatar />\n    </n-badge>\n    <n-badge :value=\"value\" show-zero :max=\"100\">\n      <n-avatar />\n    </n-badge>\n    <n-badge :value=\"value\" show-zero :max=\"10\">\n      <n-avatar />\n    </n-badge>\n    <n-button-group>\n      <n-button @click=\"value = Math.min(16, value + 1)\">\n        <template #icon>\n          <n-icon><MdAdd /></n-icon>\n        </template>\n      </n-button>\n      <n-button @click=\"value = Math.max(0, value - 1)\">\n        <template #icon>\n          <n-icon><MdRemove /></n-icon>\n        </template>\n      </n-button>\n    </n-button-group>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/badge/demos/enUS/processing.demo.vue",
    "content": "<markdown>\n# Processing\n\nSet `processing` prop to indicate it is processing.\n</markdown>\n\n<template>\n  <n-space :size=\"24\" align=\"center\">\n    <n-badge dot processing>\n      <n-avatar />\n    </n-badge>\n    <n-badge :value=\"20\" processing>\n      <n-avatar />\n    </n-badge>\n    <n-badge dot type=\"info\" processing>\n      <n-avatar />\n    </n-badge>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/badge/demos/enUS/raw.demo.vue",
    "content": "<markdown>\n# Raw\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { MdAdd, MdRemove } from '@vicons/ionicons4'\nimport { ref } from 'vue'\n\nconst value = ref(5)\n</script>\n\n<template>\n  <n-space :size=\"24\" align=\"center\" item-style=\"display: flex;\">\n    <n-badge :value=\"value\" :max=\"15\" />\n    <n-badge :value=\"value\" dot />\n    <n-button-group>\n      <n-button @click=\"value = Math.min(16, value + 1)\">\n        <template #icon>\n          <n-icon><MdAdd /></n-icon>\n        </template>\n      </n-button>\n      <n-button @click=\"value = Math.max(0, value - 1)\">\n        <template #icon>\n          <n-icon><MdRemove /></n-icon>\n        </template>\n      </n-button>\n    </n-button-group>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/badge/demos/enUS/show-zero.demo.vue",
    "content": "<markdown>\n# Show zero\n\nSet `show-zero` prop to display zero.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { MdAdd, MdRemove } from '@vicons/ionicons4'\nimport { ref } from 'vue'\n\nconst value = ref(0)\n</script>\n\n<template>\n  <n-space :size=\"24\" align=\"center\">\n    <n-badge :value=\"value\">\n      <n-avatar />\n    </n-badge>\n    <n-badge :value=\"value\" show-zero>\n      <n-avatar />\n    </n-badge>\n    <n-button-group>\n      <n-button @click=\"value = Math.min(16, value + 1)\">\n        <template #icon>\n          <n-icon><MdAdd /></n-icon>\n        </template>\n      </n-button>\n      <n-button @click=\"value = Math.max(0, value - 1)\">\n        <template #icon>\n          <n-icon><MdRemove /></n-icon>\n        </template>\n      </n-button>\n    </n-button-group>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/badge/demos/enUS/type.demo.vue",
    "content": "<markdown>\n# Type\n\nBadge has `default`, `error`, `info`, `success`, `warning` types.\n</markdown>\n\n<template>\n  <n-space :size=\"24\" align=\"center\">\n    <n-badge dot>\n      <n-avatar />\n    </n-badge>\n    <n-badge dot type=\"error\">\n      <n-avatar />\n    </n-badge>\n    <n-badge dot type=\"info\">\n      <n-avatar />\n    </n-badge>\n    <n-badge dot type=\"success\">\n      <n-avatar />\n    </n-badge>\n    <n-badge dot type=\"warning\">\n      <n-avatar />\n    </n-badge>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/badge/demos/zhCN/basic.demo.vue",
    "content": "<markdown>\n# 基础用法\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { MdAdd, MdRemove } from '@vicons/ionicons4'\nimport { ref } from 'vue'\n\nconst value = ref(5)\n</script>\n\n<template>\n  <n-space :size=\"24\" align=\"center\">\n    <n-badge :value=\"value\" :max=\"15\">\n      <n-avatar />\n    </n-badge>\n    <n-badge :value=\"value\" dot>\n      <n-avatar />\n    </n-badge>\n    <n-button-group>\n      <n-button @click=\"value = Math.min(16, value + 1)\">\n        <template #icon>\n          <n-icon><MdAdd /></n-icon>\n        </template>\n      </n-button>\n      <n-button @click=\"value = Math.max(0, value - 1)\">\n        <template #icon>\n          <n-icon><MdRemove /></n-icon>\n        </template>\n      </n-button>\n    </n-button-group>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/badge/demos/zhCN/color.demo.vue",
    "content": "<markdown>\n# 自定义颜色\n</markdown>\n\n<template>\n  <n-badge value=\"15\" color=\"grey\">\n    <n-avatar />\n  </n-badge>\n</template>\n"
  },
  {
    "path": "src/badge/demos/zhCN/custom-content.demo.vue",
    "content": "<markdown>\n# 自定义内容\n\n在里面插入一些自定义内容。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { LockClosedOutline } from '@vicons/ionicons5'\n</script>\n\n<template>\n  <n-space :size=\"24\" align=\"center\">\n    <n-badge value=\"新\">\n      <n-avatar />\n    </n-badge>\n    <n-badge value=\"火\">\n      <n-avatar />\n    </n-badge>\n    <n-badge processing>\n      <n-avatar />\n      <template #value>\n        <n-icon :component=\"LockClosedOutline\" />\n      </template>\n    </n-badge>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/badge/demos/zhCN/index.demo-entry.md",
    "content": "# 标记 Badge\n\n我敢说你肯定见过这玩意而且知道怎么用它。\n\n## 演示\n\n```demo\nbasic.vue\ntype.vue\nprocessing.vue\nshow-zero.vue\noverflow.vue\nmanual.vue\ncustom-content.vue\ncolor.vue\nraw.vue\nrtl-debug.vue\noffset.vue\n```\n\n## API\n\n### Badge Props\n\n| 名称 | 类型 | 默认值 | 说明 | 版本 |\n| --- | --- | --- | --- | --- |\n| color | `string` | `undefined` | 标记的颜色 |  |\n| dot | `boolean` | `false` | 标记是否显示为点 |  |\n| max | `number` | `undefined` | 标记最大数来处理溢出情况 |  |\n| offset | `[string \\| number, string \\| number]` | `undefined` | 距默认位置左侧、上方的偏移量 | 2.34.3 |\n| processing | `boolean` | `false` | 标记显示进度 |  |\n| show-zero | `boolean` | `false` | 标记为 0 时是否显示 |  |\n| show | `boolean` | `true` | 标记受控显示 |  |\n| type | `'default' \\| 'success' \\| 'error' \\| 'warning' \\| 'info'` | `'default'` | 标记显示类型 |  |\n| value | `string \\| number` | `undefined` | 标记数量 |  |\n\n### Badge Slots\n\n| 名称    | 参数 | 说明             |\n| ------- | ---- | ---------------- |\n| default | `()` | 标记内填充的内容 |\n"
  },
  {
    "path": "src/badge/demos/zhCN/manual.demo.vue",
    "content": "<markdown>\n# 受控显示\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { MdAdd, MdRemove } from '@vicons/ionicons4'\nimport { ref } from 'vue'\n\nconst value = ref(5)\nconst show = ref(true)\n</script>\n\n<template>\n  <n-space :size=\"24\" align=\"center\" item-style=\"display: flex;\">\n    <n-badge :value=\"value\" :max=\"15\" :show=\"show\">\n      <n-avatar />\n    </n-badge>\n    <n-badge :value=\"value\" dot :show=\"show\">\n      <n-avatar />\n    </n-badge>\n    <n-button-group>\n      <n-button @click=\"value = Math.min(16, value + 1)\">\n        <template #icon>\n          <n-icon><MdAdd /></n-icon>\n        </template>\n      </n-button>\n      <n-button @click=\"value = Math.max(0, value - 1)\">\n        <template #icon>\n          <n-icon><MdRemove /></n-icon>\n        </template>\n      </n-button>\n    </n-button-group>\n    <n-switch v-model:value=\"show\" />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/badge/demos/zhCN/offset.demo.vue",
    "content": "<markdown>\n# 自定义位置偏移\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst value = ref(5)\nconst offset = [-17, 17] as const\n</script>\n\n<template>\n  <n-badge :value=\"value\" :max=\"15\" :offset=\"offset\">\n    <n-avatar />\n  </n-badge>\n</template>\n"
  },
  {
    "path": "src/badge/demos/zhCN/overflow.demo.vue",
    "content": "<markdown>\n# 溢出\n\n设定 `max` 来处理溢出情况。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { MdAdd, MdRemove } from '@vicons/ionicons4'\nimport { ref } from 'vue'\n\nconst value = ref(101)\n</script>\n\n<template>\n  <n-space :size=\"24\" align=\"center\">\n    <n-badge :value=\"value\" show-zero>\n      <n-avatar />\n    </n-badge>\n    <n-badge :value=\"value\" :max=\"99\">\n      <n-avatar />\n    </n-badge>\n    <n-badge :value=\"value\" show-zero :max=\"100\">\n      <n-avatar />\n    </n-badge>\n    <n-badge :value=\"value\" show-zero :max=\"10\">\n      <n-avatar />\n    </n-badge>\n    <n-button-group>\n      <n-button @click=\"value = Math.min(16, value + 1)\">\n        <template #icon>\n          <n-icon><MdAdd /></n-icon>\n        </template>\n      </n-button>\n      <n-button @click=\"value = Math.max(0, value - 1)\">\n        <template #icon>\n          <n-icon><MdRemove /></n-icon>\n        </template>\n      </n-button>\n    </n-button-group>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/badge/demos/zhCN/processing.demo.vue",
    "content": "<markdown>\n# 处理中\n\n设定 `processing` 来表明正在处理。\n</markdown>\n\n<template>\n  <n-space :size=\"24\" align=\"center\">\n    <n-badge dot processing>\n      <n-avatar />\n    </n-badge>\n    <n-badge :value=\"20\" processing>\n      <n-avatar />\n    </n-badge>\n    <n-badge dot type=\"info\" processing>\n      <n-avatar />\n    </n-badge>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/badge/demos/zhCN/raw.demo.vue",
    "content": "<markdown>\n# 直接使用\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { MdAdd, MdRemove } from '@vicons/ionicons4'\nimport { ref } from 'vue'\n\nconst value = ref(5)\n</script>\n\n<template>\n  <n-space :size=\"24\" align=\"center\" item-style=\"display: flex;\">\n    <n-badge :value=\"value\" :max=\"15\" />\n    <n-badge :value=\"value\" dot />\n    <n-button-group>\n      <n-button @click=\"value = Math.min(16, value + 1)\">\n        <template #icon>\n          <n-icon><MdAdd /></n-icon>\n        </template>\n      </n-button>\n      <n-button @click=\"value = Math.max(0, value - 1)\">\n        <template #icon>\n          <n-icon><MdRemove /></n-icon>\n        </template>\n      </n-button>\n    </n-button-group>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/badge/demos/zhCN/rtl-debug.demo.vue",
    "content": "<markdown>\n# Rtl Debug\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { unstableBadgeRtl } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst rtlEnabled = ref(false)\nconst rtlStyles = [unstableBadgeRtl]\n</script>\n\n<template>\n  <n-space vertical>\n    <n-space><n-switch v-model:value=\"rtlEnabled\" />Rtl</n-space>\n    <n-config-provider :rtl=\"rtlEnabled ? rtlStyles : undefined\">\n      <n-space :size=\"24\" align=\"center\">\n        <n-badge :value=\"5\" processing>\n          <n-avatar />\n        </n-badge>\n        <n-badge :value=\"5\" dot>\n          <n-avatar />\n        </n-badge>\n      </n-space>\n    </n-config-provider>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/badge/demos/zhCN/show-zero.demo.vue",
    "content": "<markdown>\n# 显示 0\n\n设定 `show-zero` 来显示 0。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { MdAdd, MdRemove } from '@vicons/ionicons4'\nimport { ref } from 'vue'\n\nconst value = ref(0)\n</script>\n\n<template>\n  <n-space :size=\"24\" align=\"center\">\n    <n-badge :value=\"value\">\n      <n-avatar />\n    </n-badge>\n    <n-badge :value=\"value\" show-zero>\n      <n-avatar />\n    </n-badge>\n    <n-button-group>\n      <n-button @click=\"value = Math.min(16, value + 1)\">\n        <template #icon>\n          <n-icon><MdAdd /></n-icon>\n        </template>\n      </n-button>\n      <n-button @click=\"value = Math.max(0, value - 1)\">\n        <template #icon>\n          <n-icon><MdRemove /></n-icon>\n        </template>\n      </n-button>\n    </n-button-group>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/badge/demos/zhCN/type.demo.vue",
    "content": "<markdown>\n# 类型\n\n标记有 `default`、`error`、`info`、`success`、`warning` 类型。\n</markdown>\n\n<template>\n  <n-space :size=\"24\" align=\"center\">\n    <n-badge dot>\n      <n-avatar />\n    </n-badge>\n    <n-badge dot type=\"error\">\n      <n-avatar />\n    </n-badge>\n    <n-badge dot type=\"info\">\n      <n-avatar />\n    </n-badge>\n    <n-badge dot type=\"success\">\n      <n-avatar />\n    </n-badge>\n    <n-badge dot type=\"warning\">\n      <n-avatar />\n    </n-badge>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/badge/index.ts",
    "content": "export { badgeProps, default as NBadge } from './src/Badge'\nexport type { BadgeProps } from './src/Badge'\n"
  },
  {
    "path": "src/badge/src/Badge.tsx",
    "content": "import type { CSSProperties, PropType } from 'vue'\nimport type { ThemeProps } from '../../_mixins'\nimport type { ExtractPublicPropTypes } from '../../_utils'\nimport type { BadgeTheme } from '../styles'\nimport { computed, defineComponent, h, onMounted, ref, Transition } from 'vue'\nimport { NBaseSlotMachine, NBaseWave } from '../../_internal'\nimport { useConfig, useTheme, useThemeClass } from '../../_mixins'\nimport { useRtl } from '../../_mixins/use-rtl'\nimport {\n  color2Class,\n  createKey,\n  getTitleAttribute,\n  isSlotEmpty,\n  resolveSlot\n} from '../../_utils'\nimport { badgeLight } from '../styles'\nimport style from './styles/index.cssr'\n\nexport const badgeProps = {\n  ...(useTheme.props as ThemeProps<BadgeTheme>),\n  value: [String, Number] as PropType<string | number>,\n  max: Number,\n  dot: Boolean,\n  type: {\n    type: String as PropType<\n      'success' | 'error' | 'warning' | 'info' | 'default'\n    >,\n    default: 'default'\n  },\n  show: {\n    type: Boolean,\n    default: true\n  },\n  showZero: Boolean,\n  processing: Boolean,\n  color: String,\n  offset: Array as unknown as PropType<\n    readonly [number | string, number | string]\n  >\n} as const\n\nexport type BadgeProps = ExtractPublicPropTypes<typeof badgeProps>\n\nexport default defineComponent({\n  name: 'Badge',\n  props: badgeProps,\n  setup(props, { slots }) {\n    const { mergedClsPrefixRef, inlineThemeDisabled, mergedRtlRef }\n      = useConfig(props)\n    const themeRef = useTheme(\n      'Badge',\n      '-badge',\n      style,\n      badgeLight,\n      props,\n      mergedClsPrefixRef\n    )\n    const appearedRef = ref(false)\n    const handleAfterEnter = (): void => {\n      appearedRef.value = true\n    }\n    const handleAfterLeave = (): void => {\n      appearedRef.value = false\n    }\n    const showBadgeRef = computed(() => {\n      return (\n        props.show\n        && (props.dot\n          || (props.value !== undefined\n            && !(!props.showZero && Number(props.value) <= 0))\n          || !isSlotEmpty(slots.value))\n      )\n    })\n    onMounted(() => {\n      if (showBadgeRef.value)\n        appearedRef.value = true\n    })\n\n    const rtlEnabledRef = useRtl('Badge', mergedRtlRef, mergedClsPrefixRef)\n    const cssVarsRef = computed(() => {\n      const { type, color: propColor } = props\n      const {\n        common: { cubicBezierEaseInOut, cubicBezierEaseOut },\n        self: { [createKey('color', type)]: color, fontFamily, fontSize }\n      } = themeRef.value\n      return {\n        '--n-font-size': fontSize,\n        '--n-font-family': fontFamily,\n        '--n-color': propColor || color,\n        '--n-ripple-color': propColor || color,\n        '--n-bezier': cubicBezierEaseInOut,\n        '--n-ripple-bezier': cubicBezierEaseOut\n      }\n    })\n\n    const themeClassHandle = inlineThemeDisabled\n      ? useThemeClass(\n          'badge',\n          computed(() => {\n            let hash = ''\n            const { type, color } = props\n            if (type) {\n              hash += type[0]\n            }\n            if (color) {\n              hash += color2Class(color)\n            }\n            return hash\n          }),\n          cssVarsRef,\n          props\n        )\n      : undefined\n\n    const offsetStyleRef = computed(() => {\n      const { offset } = props\n      if (!offset)\n        return undefined\n      const [x, y] = offset\n      const reslovedOffsetX = typeof x === 'number' ? `${x}px` : x\n      const reslovedOffsetY = typeof y === 'number' ? `${y}px` : y\n      return {\n        transform: `translate(calc(${\n          rtlEnabledRef?.value ? '50%' : '-50%'\n        } + ${reslovedOffsetX}), ${reslovedOffsetY})`\n      }\n    })\n\n    return {\n      rtlEnabled: rtlEnabledRef,\n      mergedClsPrefix: mergedClsPrefixRef,\n      appeared: appearedRef,\n      showBadge: showBadgeRef,\n      handleAfterEnter,\n      handleAfterLeave,\n      cssVars: inlineThemeDisabled ? undefined : cssVarsRef,\n      themeClass: themeClassHandle?.themeClass,\n      onRender: themeClassHandle?.onRender,\n      offsetStyle: offsetStyleRef\n    }\n  },\n  render() {\n    const { mergedClsPrefix, onRender, themeClass, $slots } = this\n    onRender?.()\n    const children = $slots.default?.()\n    return (\n      <div\n        class={[\n          `${mergedClsPrefix}-badge`,\n          this.rtlEnabled && `${mergedClsPrefix}-badge--rtl`,\n          themeClass,\n          {\n            [`${mergedClsPrefix}-badge--dot`]: this.dot,\n            [`${mergedClsPrefix}-badge--as-is`]: !children\n          }\n        ]}\n        style={this.cssVars as CSSProperties}\n      >\n        {children}\n        <Transition\n          name=\"fade-in-scale-up-transition\"\n          onAfterEnter={this.handleAfterEnter}\n          onAfterLeave={this.handleAfterLeave}\n        >\n          {{\n            default: () =>\n              this.showBadge ? (\n                <sup\n                  class={`${mergedClsPrefix}-badge-sup`}\n                  title={getTitleAttribute(this.value)}\n                  style={this.offsetStyle}\n                >\n                  {resolveSlot($slots.value, () => [\n                    !this.dot ? (\n                      <NBaseSlotMachine\n                        clsPrefix={mergedClsPrefix}\n                        appeared={this.appeared}\n                        max={this.max}\n                        value={this.value}\n                      />\n                    ) : null\n                  ])}\n                  {this.processing ? (\n                    <NBaseWave clsPrefix={mergedClsPrefix} />\n                  ) : null}\n                </sup>\n              ) : null\n          }}\n        </Transition>\n      </div>\n    )\n  }\n})\n"
  },
  {
    "path": "src/badge/src/styles/index.cssr.ts",
    "content": "import { fadeInScaleUpTransition } from '../../../_styles/transitions/fade-in-scale-up.cssr'\nimport { c, cB, cM } from '../../../_utils/cssr'\n\n// vars:\n// --n-color\n// --n-ripple-color\n// --n-bezier\n// --n-ripple-bezier\n// --n-font-size\n// --n-font-family\nexport default c([\n  c('@keyframes badge-wave-spread', {\n    from: {\n      boxShadow: '0 0 0.5px 0px var(--n-ripple-color)',\n      opacity: 0.6\n    },\n    to: {\n      // don't use exact 5px since chrome will display the animation with glitches\n      boxShadow: '0 0 0.5px 4.5px var(--n-ripple-color)',\n      opacity: 0\n    }\n  }),\n  cB('badge', `\n    display: inline-flex;\n    position: relative;\n    vertical-align: middle;\n    font-family: var(--n-font-family);\n  `, [\n    cM('as-is', [\n      cB('badge-sup', {\n        position: 'static',\n        transform: 'translateX(0)'\n      }, [\n        fadeInScaleUpTransition({\n          transformOrigin: 'left bottom',\n          originalTransform: 'translateX(0)'\n        })\n      ])\n    ]),\n    cM('dot', [\n      cB('badge-sup', `\n        height: 8px;\n        width: 8px;\n        padding: 0;\n        min-width: 8px;\n        left: 100%;\n        bottom: calc(100% - 4px);\n      `, [\n        c('::before', 'border-radius: 4px;')\n      ])\n    ]),\n    cB('badge-sup', `\n      background: var(--n-color);\n      transition:\n        background-color .3s var(--n-bezier),\n        color .3s var(--n-bezier);\n      color: #FFF;\n      position: absolute;\n      height: 18px;\n      line-height: 18px;\n      border-radius: 9px;\n      padding: 0 6px;\n      text-align: center;\n      font-size: var(--n-font-size);\n      transform: translateX(-50%);\n      left: 100%;\n      bottom: calc(100% - 9px);\n      font-variant-numeric: tabular-nums;\n      z-index: 2;\n      display: flex;\n      align-items: center;\n    `, [\n      fadeInScaleUpTransition({\n        transformOrigin: 'left bottom',\n        originalTransform: 'translateX(-50%)'\n      }),\n      cB('base-wave', {\n        zIndex: 1,\n        animationDuration: '2s',\n        animationIterationCount: 'infinite',\n        animationDelay: '1s',\n        animationTimingFunction: 'var(--n-ripple-bezier)',\n        animationName: 'badge-wave-spread'\n      }),\n      c('&::before', `\n        opacity: 0;\n        transform: scale(1);\n        border-radius: 9px;\n        content: \"\";\n        position: absolute;\n        left: 0;\n        right: 0;\n        top: 0;\n        bottom: 0;\n      `)\n    ])\n  ])\n])\n"
  },
  {
    "path": "src/badge/src/styles/rtl.cssr.ts",
    "content": "import { cB, cM } from '../../../_utils/cssr'\n\nexport default cB('badge', [\n  cM('rtl', `\n    direction: rtl;\n  `, [\n    cB('badge-sup', `\n      right: 100%;\n      left: unset;\n      transform: translateX(50%);\n      direction: initial;\n    `)\n  ])\n])\n"
  },
  {
    "path": "src/badge/styles/dark.ts",
    "content": "import type { BadgeTheme } from './light'\nimport { commonDark } from '../../_styles/common'\n\nconst badgeDark: BadgeTheme = {\n  name: 'Badge',\n  common: commonDark,\n  self(vars) {\n    const {\n      errorColorSuppl,\n      infoColorSuppl,\n      successColorSuppl,\n      warningColorSuppl,\n      fontFamily\n    } = vars\n    return {\n      color: errorColorSuppl,\n      colorInfo: infoColorSuppl,\n      colorSuccess: successColorSuppl,\n      colorError: errorColorSuppl,\n      colorWarning: warningColorSuppl,\n      fontSize: '12px',\n      fontFamily\n    }\n  }\n}\n\nexport default badgeDark\n"
  },
  {
    "path": "src/badge/styles/index.ts",
    "content": "export { default as badgeDark } from './dark'\nexport { default as badgeLight } from './light'\nexport type { BadgeTheme, BadgeThemeVars } from './light'\nexport { badgeRtl } from './rtl'\n"
  },
  {
    "path": "src/badge/styles/light.ts",
    "content": "import type { Theme } from '../../_mixins'\nimport type { ThemeCommonVars } from '../../_styles/common'\nimport { commonLight } from '../../_styles/common'\n\nfunction self(vars: ThemeCommonVars) {\n  const { errorColor, infoColor, successColor, warningColor, fontFamily } = vars\n  return {\n    color: errorColor,\n    colorInfo: infoColor,\n    colorSuccess: successColor,\n    colorError: errorColor,\n    colorWarning: warningColor,\n    fontSize: '12px',\n    fontFamily\n  }\n}\n\nexport type BadgeThemeVars = ReturnType<typeof self>\n\nconst badgeLight: Theme<'Badge', BadgeThemeVars> = {\n  name: 'Badge',\n  common: commonLight,\n  self\n}\n\nexport default badgeLight\nexport type BadgeTheme = typeof badgeLight\n"
  },
  {
    "path": "src/badge/styles/rtl.ts",
    "content": "import type { RtlItem } from '../../config-provider/src/internal-interface'\nimport rtlStyle from '../src/styles/rtl.cssr'\n\nexport const badgeRtl: RtlItem = {\n  name: 'Badge',\n  style: rtlStyle\n}\n"
  },
  {
    "path": "src/badge/tests/Badge.spec.ts",
    "content": "import { mount } from '@vue/test-utils'\nimport { NBadge } from '../index'\n\ndescribe('n-badge', () => {\n  it('should work with import on demand', () => {\n    mount(NBadge)\n  })\n\n  it('should work with `dot` prop', async () => {\n    const wrapper = mount(NBadge, { props: { value: 5 } })\n    expect(wrapper.find('.n-badge').classes('n-badge--dot')).not.toBe(true)\n    expect(wrapper.find('.n-base-slot-machine').exists()).toBe(true)\n\n    await wrapper.setProps({ dot: true })\n    expect(wrapper.find('.n-badge').classes('n-badge--dot')).toBe(true)\n    expect(wrapper.find('.n-base-slot-machine').exists()).not.toBe(true)\n    wrapper.unmount()\n  })\n\n  it('should work with `color` prop', async () => {\n    const wrapper = mount(NBadge, { props: { value: 5, color: 'grey' } })\n    expect(wrapper.find('.n-badge').attributes('style')).toContain(\n      '--n-color: grey;'\n    )\n    wrapper.unmount()\n  })\n\n  it('should work with `max` prop', async () => {\n    const wrapper = mount(NBadge, { props: { value: 5, max: 5 } })\n    expect(\n      wrapper\n        .find('.n-base-slot-machine-current-number__inner--not-number')\n        .exists()\n    ).not.toBe(true)\n\n    await wrapper.setProps({ value: 6 })\n    expect(\n      wrapper\n        .find('.n-base-slot-machine-current-number__inner--not-number')\n        .exists()\n    ).toBe(true)\n    wrapper.unmount()\n  })\n\n  it('should work with `processing` prop', async () => {\n    const wrapper = mount(NBadge, { props: { value: 5 } })\n    expect(wrapper.find('.n-base-wave').exists()).not.toBe(true)\n\n    await wrapper.setProps({ processing: true })\n    expect(wrapper.find('.n-base-wave').exists()).toBe(true)\n    wrapper.unmount()\n  })\n\n  it('should work with `show-zero` prop', async () => {\n    const wrapper = mount(NBadge, { props: { value: 0 } })\n    expect(wrapper.find('.n-badge-sup').exists()).not.toBe(true)\n\n    await wrapper.setProps({ showZero: true })\n    expect(wrapper.find('.n-badge-sup').exists()).toBe(true)\n    wrapper.unmount()\n  })\n\n  it('should work with `show` prop', async () => {\n    const wrapper = mount(NBadge, { props: { value: 7 } })\n    expect(wrapper.find('.n-badge-sup').exists()).toBe(true)\n\n    await wrapper.setProps({ show: false })\n    expect(wrapper.find('.n-badge-sup').exists()).not.toBe(true)\n    wrapper.unmount()\n  })\n\n  it('should work with `type` prop', () => {\n    const data = [\n      { type: 'default', color: '#d03050' },\n      { type: 'error', color: '#d03050' },\n      { type: 'info', color: '#2080f0' },\n      { type: 'success', color: '#18a058' },\n      { type: 'warning', color: '#f0a020' }\n    ] as const\n\n    data.forEach((item) => {\n      const wrapper = mount(NBadge, {\n        props: {\n          type: item.type,\n          value: 5\n        }\n      })\n\n      expect(wrapper.find('.n-badge').attributes('style')).toContain(item.color)\n      wrapper.unmount()\n    })\n  })\n})\n"
  },
  {
    "path": "src/badge/tests/server.spec.tsx",
    "content": "import { setup } from '@css-render/vue3-ssr'\nimport { renderToString } from '@vue/server-renderer'\n/**\n * @vitest-environment node\n */\nimport { createSSRApp, h } from 'vue'\nimport { NBadge } from '../..'\n\ndescribe('server side rendering', () => {\n  it('works', async () => {\n    const app = createSSRApp(() => <NBadge />)\n    setup(app)\n    try {\n      await renderToString(app)\n    }\n    catch (e) {\n      expect(e).not.toBeTruthy()\n    }\n  })\n})\n"
  },
  {
    "path": "src/breadcrumb/demos/enUS/basic.demo.vue",
    "content": "<markdown>\n# Basic\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { MdCash } from '@vicons/ionicons4'\n</script>\n\n<template>\n  <n-breadcrumb>\n    <n-breadcrumb-item><n-icon :component=\"MdCash\" /> Home</n-breadcrumb-item>\n    <n-breadcrumb-item>\n      <n-icon :component=\"MdCash\" /> Account\n    </n-breadcrumb-item>\n    <n-breadcrumb-item>\n      <n-icon :component=\"MdCash\" /> Category\n    </n-breadcrumb-item>\n  </n-breadcrumb>\n</template>\n"
  },
  {
    "path": "src/breadcrumb/demos/enUS/custom.demo.vue",
    "content": "<markdown>\n# Dropdown\n\nIt is possible to pass a custom template when you want to customize the item link to be, for example a `dropdown` or a `router-link`.\n</markdown>\n\n<script lang=\"ts\" setup>\nconst options1 = [\n  {\n    label: 'David Tao',\n    key: 1\n  },\n  {\n    label: '黑色柳丁',\n    key: 2\n  }\n]\n\nconst options2 = [\n  {\n    label: '小镇姑娘',\n    key: 1\n  },\n  {\n    label: '普通朋友',\n    key: 2\n  }\n]\n</script>\n\n<template>\n  <n-breadcrumb>\n    <n-breadcrumb-item>\n      <n-dropdown :options=\"options1\">\n        <div class=\"trigger\">\n          I'm ok\n        </div>\n      </n-dropdown>\n    </n-breadcrumb-item>\n    <n-breadcrumb-item>\n      <n-dropdown :options=\"options2\">\n        <div class=\"trigger\">\n          I'm ok\n        </div>\n      </n-dropdown>\n    </n-breadcrumb-item>\n  </n-breadcrumb>\n</template>\n\n<style>\n.trigger::before {\n  content: '';\n  position: absolute;\n  left: 0;\n  right: 0;\n  top: 0;\n  bottom: 0;\n  border-radius: inherit;\n}\n</style>\n"
  },
  {
    "path": "src/breadcrumb/demos/enUS/index.demo-entry.md",
    "content": "# Breadcrumb\n\nIt doesn't look like what it calls.\n\n## Demos\n\n```demo\nbasic.vue\ncustom.vue\nseparator.vue\nseparator-per-item.vue\n```\n\n## API\n\n### Breadcrumb Props\n\n| Name      | Type     | Default | Description           |\n| --------- | -------- | ------- | --------------------- |\n| separator | `string` | `'/'`   | Breadcrumb separator. |\n\n### BreadcrumbItem Props\n\n| Name | Type | Default | Description | Version |\n| --- | --- | --- | --- | --- |\n| clickable | `boolean` | `true` | Whether it's clickable. | 2.30.0 |\n| href | `string` | `undefined` | BreadcrumbItem link. |  |\n| separator | `string` | `undefined` | BreadcrumbItem separator. |  |\n| show-separator | `boolean` | `true` | Whether to show the separator. | 2.44.0 |\n\n### Breadcrumb Slots\n\n| Name    | Parameters | Description              |\n| ------- | ---------- | ------------------------ |\n| default | `()`       | Breadcrumb default slot. |\n\n### Breadcrumb Item Slots\n\n| Name      | Parameters | Description                    |\n| --------- | ---------- | ------------------------------ |\n| default   | `()`       | BreadcrumbItem default slot.   |\n| separator | `()`       | BreadcrumbItem separator slot. |\n"
  },
  {
    "path": "src/breadcrumb/demos/enUS/separator-per-item.demo.vue",
    "content": "<markdown>\n# Custom separator by item\n\nUse separator prop or separator slot to custom separator of an item. When both are present, separator slot will be used.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { MdCash } from '@vicons/ionicons4'\n</script>\n\n<template>\n  <n-breadcrumb>\n    <n-breadcrumb-item separator=\">\">\n      <n-icon><MdCash /></n-icon> Home\n    </n-breadcrumb-item>\n    <n-breadcrumb-item>\n      <n-icon><MdCash /></n-icon> Account<template #separator>\n        ~\n      </template>\n    </n-breadcrumb-item>\n    <n-breadcrumb-item>\n      <n-icon><MdCash /></n-icon> Category\n    </n-breadcrumb-item>\n  </n-breadcrumb>\n</template>\n"
  },
  {
    "path": "src/breadcrumb/demos/enUS/separator.demo.vue",
    "content": "<markdown>\n# Customize separator\n\nUse separator prop to custom separator.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { MdCash } from '@vicons/ionicons4'\n</script>\n\n<template>\n  <n-breadcrumb separator=\">\">\n    <n-breadcrumb-item>\n      <n-icon><MdCash /></n-icon> Home\n    </n-breadcrumb-item>\n    <n-breadcrumb-item>\n      <n-icon><MdCash /></n-icon> Account\n    </n-breadcrumb-item>\n    <n-breadcrumb-item>\n      <n-icon><MdCash /></n-icon> Category\n    </n-breadcrumb-item>\n  </n-breadcrumb>\n</template>\n"
  },
  {
    "path": "src/breadcrumb/demos/zhCN/basic.demo.vue",
    "content": "<markdown>\n# 基础用法\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { MdCash } from '@vicons/ionicons4'\n</script>\n\n<template>\n  <n-breadcrumb>\n    <n-breadcrumb-item>\n      <n-icon :component=\"MdCash\" /> 北京总行\n    </n-breadcrumb-item>\n    <n-breadcrumb-item>\n      <n-icon :component=\"MdCash\" /> 天津分行\n    </n-breadcrumb-item>\n    <n-breadcrumb-item>\n      <n-icon :component=\"MdCash\" /> 平山道支行\n    </n-breadcrumb-item>\n  </n-breadcrumb>\n</template>\n"
  },
  {
    "path": "src/breadcrumb/demos/zhCN/custom.demo.vue",
    "content": "<markdown>\n# 下拉菜单\n\n和下拉菜单一起使用。\n</markdown>\n\n<script lang=\"ts\" setup>\nconst options1 = [\n  {\n    label: 'David Tao',\n    key: 1\n  },\n  {\n    label: '黑色柳丁',\n    key: 2\n  }\n]\n\nconst options2 = [\n  {\n    label: '小镇姑娘',\n    key: 1\n  },\n  {\n    label: '普通朋友',\n    key: 2\n  }\n]\n</script>\n\n<template>\n  <n-breadcrumb>\n    <n-breadcrumb-item>\n      <n-dropdown :options=\"options1\">\n        <div class=\"trigger\">\n          I'm ok\n        </div>\n      </n-dropdown>\n    </n-breadcrumb-item>\n    <n-breadcrumb-item>\n      <n-dropdown :options=\"options2\">\n        <div class=\"trigger\">\n          I'm ok\n        </div>\n      </n-dropdown>\n    </n-breadcrumb-item>\n  </n-breadcrumb>\n</template>\n\n<style>\n.trigger {\n  padding: 4px;\n  margin: -4px;\n  border-radius: inherit;\n}\n</style>\n"
  },
  {
    "path": "src/breadcrumb/demos/zhCN/index.demo-entry.md",
    "content": "# 面包屑 Breadcrumb\n\n这东西长得和它名字不怎么像。\n\n## 演示\n\n```demo\nbasic.vue\ncustom.vue\nseparator.vue\nseparator-per-item.vue\n```\n\n## API\n\n### Breadcrumb Props\n\n| 名称      | 类型     | 默认值 | 说明               |\n| --------- | -------- | ------ | ------------------ |\n| separator | `string` | `'/'`  | 面包屑之间的分隔符 |\n\n### BreadcrumbItem Props\n\n| 名称           | 类型      | 默认值      | 说明                   | 版本   |\n| -------------- | --------- | ----------- | ---------------------- | ------ |\n| clickable      | `boolean` | `true`      | 是否可点击             | 2.30.0 |\n| href           | `string`  | `undefined` | 链接地址               |        |\n| separator      | `string`  | `'/'`       | 面包屑子项之间的分隔符 | 2.44.0 |\n| show-separator | `boolean` | `true`      | 是否显示分隔符         |        |\n\n### Breadcrumb Slots\n\n| 名称    | 参数 | 说明                      |\n| ------- | ---- | ------------------------- |\n| default | `()` | Breadcrumb 默认填充的内容 |\n\n### Breadcrumb Item Slots\n\n| 名称      | 参数 | 说明                          |\n| --------- | ---- | ----------------------------- |\n| default   | `()` | BreadcrumbItem 默认填充的内容 |\n| separator | `()` | 分隔符填充的内容              |\n"
  },
  {
    "path": "src/breadcrumb/demos/zhCN/separator-per-item.demo.vue",
    "content": "<markdown>\n# 自定义每项分隔符\n\n使用 separator prop 或 separator slot 自定义每一项的分隔符。如果二者均提供，将优先使用 separator slot。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { MdCash } from '@vicons/ionicons4'\n</script>\n\n<template>\n  <n-breadcrumb>\n    <n-breadcrumb-item separator=\">\">\n      <n-icon><MdCash /></n-icon> 北京总行\n    </n-breadcrumb-item>\n    <n-breadcrumb-item>\n      <n-icon><MdCash /></n-icon> 天津分行<template #separator>\n        ~\n      </template>\n    </n-breadcrumb-item>\n    <n-breadcrumb-item>\n      <n-icon><MdCash /></n-icon> 平山道支行\n    </n-breadcrumb-item>\n  </n-breadcrumb>\n</template>\n"
  },
  {
    "path": "src/breadcrumb/demos/zhCN/separator.demo.vue",
    "content": "<markdown>\n# 自定义分隔符\n\n使用 separator prop 自定义分隔符。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { MdCash } from '@vicons/ionicons4'\n</script>\n\n<template>\n  <n-breadcrumb separator=\">\">\n    <n-breadcrumb-item>\n      <n-icon><MdCash /></n-icon> 北京总行\n    </n-breadcrumb-item>\n    <n-breadcrumb-item>\n      <n-icon><MdCash /></n-icon> 天津分行\n    </n-breadcrumb-item>\n    <n-breadcrumb-item>\n      <n-icon><MdCash /></n-icon> 平山道支行\n    </n-breadcrumb-item>\n  </n-breadcrumb>\n</template>\n"
  },
  {
    "path": "src/breadcrumb/index.ts",
    "content": "export { breadcrumbProps, default as NBreadcrumb } from './src/Breadcrumb'\nexport type { BreadcrumbProps } from './src/Breadcrumb'\nexport {\n  breadcrumbItemProps,\n  default as NBreadcrumbItem\n} from './src/BreadcrumbItem'\nexport type {\n  BreadcrumbItemProps,\n  BreadcrumbItemSlots\n} from './src/BreadcrumbItem'\n"
  },
  {
    "path": "src/breadcrumb/src/Breadcrumb.tsx",
    "content": "import type { CSSProperties, Ref } from 'vue'\nimport type { ThemeProps } from '../../_mixins'\nimport type { ExtractPublicPropTypes } from '../../_utils'\nimport type { BreadcrumbTheme } from '../styles'\nimport { computed, defineComponent, h, provide, toRef } from 'vue'\nimport { useConfig, useTheme, useThemeClass } from '../../_mixins'\nimport { createInjectionKey } from '../../_utils'\nimport { breadcrumbLight } from '../styles'\nimport style from './styles/index.cssr'\n\nexport interface BreadcrumbInjection {\n  separatorRef: Ref<string>\n  mergedClsPrefixRef: Ref<string>\n}\n\nexport const breadcrumbInjectionKey\n  = createInjectionKey<BreadcrumbInjection>('n-breadcrumb')\n\nexport const breadcrumbProps = {\n  ...(useTheme.props as ThemeProps<BreadcrumbTheme>),\n  separator: {\n    type: String,\n    default: '/'\n  }\n} as const\n\nexport type BreadcrumbProps = ExtractPublicPropTypes<typeof breadcrumbProps>\n\nexport default defineComponent({\n  name: 'Breadcrumb',\n  props: breadcrumbProps,\n  setup(props) {\n    const { mergedClsPrefixRef, inlineThemeDisabled } = useConfig(props)\n    const themeRef = useTheme(\n      'Breadcrumb',\n      '-breadcrumb',\n      style,\n      breadcrumbLight,\n      props,\n      mergedClsPrefixRef\n    )\n    provide(breadcrumbInjectionKey, {\n      separatorRef: toRef(props, 'separator'),\n      mergedClsPrefixRef\n    })\n    const cssVarsRef = computed(() => {\n      const {\n        common: { cubicBezierEaseInOut },\n        self: {\n          separatorColor,\n          itemTextColor,\n          itemTextColorHover,\n          itemTextColorPressed,\n          itemTextColorActive,\n          fontSize,\n          fontWeightActive,\n          itemBorderRadius,\n          itemColorHover,\n          itemColorPressed,\n          itemLineHeight\n        }\n      } = themeRef.value\n      return {\n        '--n-font-size': fontSize,\n        '--n-bezier': cubicBezierEaseInOut,\n        '--n-item-text-color': itemTextColor,\n        '--n-item-text-color-hover': itemTextColorHover,\n        '--n-item-text-color-pressed': itemTextColorPressed,\n        '--n-item-text-color-active': itemTextColorActive,\n        '--n-separator-color': separatorColor,\n        '--n-item-color-hover': itemColorHover,\n        '--n-item-color-pressed': itemColorPressed,\n        '--n-item-border-radius': itemBorderRadius,\n        '--n-font-weight-active': fontWeightActive,\n        '--n-item-line-height': itemLineHeight\n      }\n    })\n    const themeClassHandle = inlineThemeDisabled\n      ? useThemeClass('breadcrumb', undefined, cssVarsRef, props)\n      : undefined\n    return {\n      mergedClsPrefix: mergedClsPrefixRef,\n      cssVars: inlineThemeDisabled ? undefined : cssVarsRef,\n      themeClass: themeClassHandle?.themeClass,\n      onRender: themeClassHandle?.onRender\n    }\n  },\n  render() {\n    this.onRender?.()\n    return (\n      <nav\n        class={[`${this.mergedClsPrefix}-breadcrumb`, this.themeClass]}\n        style={this.cssVars as CSSProperties}\n        aria-label=\"Breadcrumb\"\n      >\n        <ul>{this.$slots}</ul>\n      </nav>\n    )\n  }\n})\n"
  },
  {
    "path": "src/breadcrumb/src/BreadcrumbItem.tsx",
    "content": "import type { ExtractPropTypes, PropType, SlotsType, VNode } from 'vue'\nimport { computed, defineComponent, h, inject } from 'vue'\nimport { resolveSlot, warn } from '../../_utils'\nimport { useBrowserLocation } from '../../_utils/composable/use-browser-location'\nimport { breadcrumbInjectionKey } from './Breadcrumb'\n\nexport const breadcrumbItemProps = {\n  separator: String,\n  href: String,\n  clickable: {\n    type: Boolean,\n    default: true\n  },\n  showSeparator: {\n    type: Boolean,\n    default: true\n  },\n  onClick: Function as PropType<(e: MouseEvent) => void>\n} as const\n\nexport type BreadcrumbItemProps = Partial<\n  ExtractPropTypes<typeof breadcrumbItemProps>\n>\n\nexport interface BreadcrumbItemSlots {\n  default?: () => VNode[]\n  separator?: () => VNode[]\n}\n\nexport default defineComponent({\n  name: 'BreadcrumbItem',\n  props: breadcrumbItemProps,\n  slots: Object as SlotsType<BreadcrumbItemSlots>,\n  setup(props, { slots }) {\n    const NBreadcrumb = inject(breadcrumbInjectionKey, null)\n    if (!NBreadcrumb) {\n      if (__DEV__) {\n        warn(\n          'breadcrumb',\n          '`n-breadcrumb-item` must be placed inside `n-breadcrumb`.'\n        )\n      }\n      return () => null\n    }\n    const { separatorRef, mergedClsPrefixRef } = NBreadcrumb\n    const browserLocationRef = useBrowserLocation()\n\n    const htmlTagRef = computed(() => (props.href ? 'a' : 'span'))\n\n    const ariaCurrentRef = computed(() =>\n      browserLocationRef.value.href === props.href ? 'location' : null\n    )\n\n    return () => {\n      const { value: mergedClsPrefix } = mergedClsPrefixRef\n      return (\n        <li\n          class={[\n            `${mergedClsPrefix}-breadcrumb-item`,\n            props.clickable && `${mergedClsPrefix}-breadcrumb-item--clickable`\n          ]}\n        >\n          {h(\n            htmlTagRef.value,\n            {\n              class: `${mergedClsPrefix}-breadcrumb-item__link`,\n              'aria-current': ariaCurrentRef.value,\n              href: props.href,\n              onClick: props.onClick\n            },\n            slots\n          )}\n          {props.showSeparator && (\n            <span\n              class={`${mergedClsPrefix}-breadcrumb-item__separator`}\n              aria-hidden=\"true\"\n            >\n              {resolveSlot(slots.separator, () => [\n                props.separator ?? separatorRef.value\n              ])}\n            </span>\n          )}\n        </li>\n      )\n    }\n  }\n})\n"
  },
  {
    "path": "src/breadcrumb/src/styles/index.cssr.ts",
    "content": "import { c, cB, cE, cM } from '../../../_utils/cssr'\n\n// vars:\n// --n-font-size\n// --n-bezier\n// --n-item-text-color\n// --n-item-text-color-hover\n// --n-item-text-color-pressed\n// --n-item-text-color-active\n// --n-separator-color\n// --n-font-weight-active\n// --n-item-border-radius\n// --n-item-color-hover\n// --n-item-color-active\n// --n-item-line-height\nexport default cB('breadcrumb', `\n  white-space: nowrap;\n  cursor: default;\n  line-height: var(--n-item-line-height);\n`, [\n  c('ul', `\n    list-style: none;\n    padding: 0;\n    margin: 0;\n  `),\n  c('a', `\n    color: inherit;\n    text-decoration: inherit;\n  `),\n  cB('breadcrumb-item', `\n    font-size: var(--n-font-size);\n    transition: color .3s var(--n-bezier);\n    display: inline-flex;\n    align-items: center;\n  `, [\n    cB('icon', `\n      font-size: 18px;\n      vertical-align: -.2em;\n      transition: color .3s var(--n-bezier);\n      color: var(--n-item-text-color);\n    `),\n    c('&:not(:last-child)', [\n      cM('clickable', [\n        cE('link', `\n          cursor: pointer;\n        `, [\n          c('&:hover', `\n            background-color: var(--n-item-color-hover);\n          `),\n          c('&:active', `\n            background-color: var(--n-item-color-pressed);  \n          `)\n        ])\n      ])\n    ]),\n    cE('link', `\n      padding: 4px;\n      border-radius: var(--n-item-border-radius);\n      transition:\n        background-color .3s var(--n-bezier),\n        color .3s var(--n-bezier);\n      color: var(--n-item-text-color);\n      position: relative;\n    `, [\n      c('&:hover', `\n        color: var(--n-item-text-color-hover);\n      `, [\n        cB('icon', `\n          color: var(--n-item-text-color-hover);\n        `)\n      ]),\n      c('&:active', `\n        color: var(--n-item-text-color-pressed);\n      `, [\n        cB('icon', `\n          color: var(--n-item-text-color-pressed);\n        `)\n      ])\n    ]),\n    cE('separator', `\n      margin: 0 8px;\n      color: var(--n-separator-color);\n      transition: color .3s var(--n-bezier);\n      user-select: none;\n      -webkit-user-select: none;\n    `),\n    c('&:last-child', [\n      cE('link', `\n        font-weight: var(--n-font-weight-active);\n        cursor: unset;\n        color: var(--n-item-text-color-active);\n      `, [\n        cB('icon', `\n          color: var(--n-item-text-color-active);\n        `)\n      ]),\n      cE('separator', `\n        display: none;\n      `)\n    ])\n  ])\n])\n"
  },
  {
    "path": "src/breadcrumb/styles/_common.ts",
    "content": "export default {\n  fontWeightActive: '400'\n}\n"
  },
  {
    "path": "src/breadcrumb/styles/dark.ts",
    "content": "import type { BreadcrumbTheme } from './light'\nimport { commonDark } from '../../_styles/common'\nimport { self } from './light'\n\nconst breadcrumbDark: BreadcrumbTheme = {\n  name: 'Breadcrumb',\n  common: commonDark,\n  self\n}\n\nexport default breadcrumbDark\n"
  },
  {
    "path": "src/breadcrumb/styles/index.ts",
    "content": "export { default as breadcrumbDark } from './dark'\nexport { default as breadcrumbLight } from './light'\nexport type { BreadcrumbTheme, BreadcrumbThemeVars } from './light'\n"
  },
  {
    "path": "src/breadcrumb/styles/light.ts",
    "content": "import type { Theme } from '../../_mixins'\nimport type { ThemeCommonVars } from '../../_styles/common'\nimport { commonLight } from '../../_styles/common'\nimport commonVariables from './_common'\n\nexport function self(vars: ThemeCommonVars) {\n  const {\n    fontSize,\n    textColor3,\n    textColor2,\n    borderRadius,\n    buttonColor2Hover,\n    buttonColor2Pressed\n  } = vars\n  return {\n    ...commonVariables,\n    fontSize,\n    itemLineHeight: '1.25',\n    itemTextColor: textColor3,\n    itemTextColorHover: textColor2,\n    itemTextColorPressed: textColor2,\n    itemTextColorActive: textColor2,\n    itemBorderRadius: borderRadius,\n    itemColorHover: buttonColor2Hover,\n    itemColorPressed: buttonColor2Pressed,\n    separatorColor: textColor3\n  }\n}\n\nexport type BreadcrumbThemeVars = ReturnType<typeof self>\n\nconst breadcrumbLight: Theme<'Breadcrumb', BreadcrumbThemeVars> = {\n  name: 'Breadcrumb',\n  common: commonLight,\n  self\n}\n\nexport default breadcrumbLight\nexport type BreadcrumbTheme = typeof breadcrumbLight\n"
  },
  {
    "path": "src/breadcrumb/tests/Breadcrumb.spec.ts",
    "content": "import { mount } from '@vue/test-utils'\nimport { h, ref } from 'vue'\nimport * as useBrowserLocationModule from '../../_utils/composable/use-browser-location'\nimport { NBreadcrumb, NBreadcrumbItem } from '../index'\n\ndescribe('n-breadcrumb', () => {\n  it('should work with import on demand', () => {\n    mount(NBreadcrumb)\n  })\n\n  it('should raise an error if breadcrumbItem is not inside a BreadCrumb', () => {\n    const mockErrorLogger = vi\n      .spyOn(console, 'error')\n      .mockImplementation(() => {})\n    const wrapper = mount(NBreadcrumbItem)\n\n    expect(wrapper.isVisible()).toBe(false)\n    expect(mockErrorLogger).toHaveBeenCalledWith(\n      '[naive/breadcrumb]: `n-breadcrumb-item` must be placed inside `n-breadcrumb`.'\n    )\n    wrapper.unmount()\n  })\n\n  it('should work with Breadcrumb, BreadcrumbItem slots', async () => {\n    const wrapper = mount(NBreadcrumb, {\n      slots: {\n        default: () => [\n          h(NBreadcrumbItem, null, { default: () => 'test-item1' }),\n          h(NBreadcrumbItem, null, { default: () => 'test-item2' })\n        ]\n      }\n    })\n\n    expect(wrapper.find('ul').element.children.length).toBe(2)\n    expect(\n      wrapper.find('ul').element.children[0].getAttribute('class')\n    ).toContain('n-breadcrumb-item')\n    const itemList = wrapper.findAll('.n-breadcrumb-item__link')\n    expect(itemList[0].text()).toBe('test-item1')\n    expect(itemList[1].text()).toBe('test-item2')\n    wrapper.unmount()\n  })\n\n  it('should work with Breadcrumb\\'s `separator` prop', async () => {\n    const wrapper = mount(NBreadcrumb, {\n      props: { separator: '@' },\n      slots: {\n        default: () => [\n          h(NBreadcrumbItem, null, { default: () => 'test-item1' }),\n          h(NBreadcrumbItem, null, { default: () => 'test-item2' })\n        ]\n      }\n    })\n\n    expect(\n      wrapper\n        .findAll('.n-breadcrumb-item__separator')\n        .every(i => i.text() === '@')\n    ).toBe(true)\n    wrapper.unmount()\n  })\n\n  it('should work with BreadcrumbItem\\'s `separator` prop', async () => {\n    const wrapper = mount(NBreadcrumb, {\n      slots: {\n        default: () => [\n          h(\n            NBreadcrumbItem,\n            { separator: '@' },\n            { default: () => 'test-item1' }\n          ),\n          h(NBreadcrumbItem, null, { default: () => 'test-item2' })\n        ]\n      }\n    })\n\n    expect(wrapper.findAll('.n-breadcrumb-item__separator')[0].text()).toBe('@')\n    expect(wrapper.findAll('.n-breadcrumb-item__separator')[1].text()).toBe('/')\n    wrapper.unmount()\n  })\n\n  it('should be possible to pass `href` props to NBreadcrumbItem', () => {\n    const wrapper = mount(NBreadcrumb, {\n      slots: {\n        default: () => [\n          h(NBreadcrumbItem, null, { default: () => 'Home' }),\n          h(NBreadcrumbItem, { href: '/path1' }, { default: () => 'Path1' })\n        ]\n      }\n    })\n\n    const firstBreadcrumbItem = wrapper.find('span.n-breadcrumb-item__link')\n    const secondBreadcrumbItem = wrapper.find('a.n-breadcrumb-item__link')\n\n    expect(firstBreadcrumbItem.exists()).toBe(true)\n    expect(firstBreadcrumbItem.text()).toMatch('Home')\n    expect(secondBreadcrumbItem.exists()).toBe(true)\n    expect(secondBreadcrumbItem.attributes('href')).toMatch('/path1')\n    wrapper.unmount()\n  })\n\n  describe('accessibility', () => {\n    it('should labelled the landmark region', () => {\n      const wrapper = mount(NBreadcrumb)\n      expect(wrapper.find('.n-breadcrumb').attributes('aria-label')).toBe(\n        'Breadcrumb'\n      )\n      wrapper.unmount()\n    })\n\n    it('should add `aria-current` if the item is the current location', () => {\n      const url = 'http://some-domain/path1'\n      const currentUrl = 'http://some-domain/path2'\n      // https://github.com/jsdom/jsdom/issues/3492\n      // https://jestjs.io/blog#known-issues\n      vi.spyOn(\n        useBrowserLocationModule,\n        'useBrowserLocation'\n      ).mockImplementation(() => ref({ href: currentUrl }))\n\n      const wrapper = mount(NBreadcrumb, {\n        slots: {\n          default: () => [\n            h(NBreadcrumbItem, { default: () => 'Home' }),\n            h(\n              NBreadcrumbItem,\n              {\n                href: url\n              },\n              { default: () => 'Path1' }\n            ),\n            h(\n              NBreadcrumbItem,\n              {\n                href: currentUrl\n              },\n              { default: () => 'Path2' }\n            )\n          ]\n        }\n      })\n\n      expect(\n        wrapper.find('span.n-breadcrumb-item__link').attributes('aria-current')\n      ).toBeUndefined()\n      expect(\n        wrapper\n          .find(`a.n-breadcrumb-item__link[href=\"${url}\"]`)\n          .attributes('aria-current')\n      ).toBeUndefined()\n      expect(\n        wrapper\n          .find(`a.n-breadcrumb-item__link[href=\"${currentUrl}\"]`)\n          .attributes('aria-current')\n      ).toBe('location')\n      wrapper.unmount()\n    })\n\n    it('should add `aria-hidden` to the separator', () => {\n      const wrapper = mount(NBreadcrumb, {\n        slots: {\n          default: () => [\n            h(NBreadcrumbItem, { default: () => 'Home' }),\n            h(\n              NBreadcrumbItem,\n              { href: '/path1', isCurrent: true },\n              { default: () => 'Path1' }\n            )\n          ]\n        }\n      })\n\n      expect(\n        wrapper.find('.n-breadcrumb-item__separator').attributes('aria-hidden')\n      ).toBe('true')\n      wrapper.unmount()\n    })\n  })\n})\n"
  },
  {
    "path": "src/breadcrumb/tests/server.spec.tsx",
    "content": "import { setup } from '@css-render/vue3-ssr'\nimport { renderToString } from '@vue/server-renderer'\n/**\n * @vitest-environment node\n */\nimport { createSSRApp, h } from 'vue'\nimport { NBreadcrumb } from '../..'\n\ndescribe('server side rendering', () => {\n  it('works', async () => {\n    const app = createSSRApp(() => <NBreadcrumb />)\n    setup(app)\n    try {\n      await renderToString(app)\n    }\n    catch (e) {\n      expect(e).not.toBeTruthy()\n    }\n  })\n})\n"
  },
  {
    "path": "src/button/demos/enUS/basic.demo.vue",
    "content": "<markdown>\n# Basic\n\nThere are `default`, `primary`, `tertiary`, `info`, `success`, `warning` and `error` button types.\n</markdown>\n\n<template>\n  <n-space>\n    <n-button>Default</n-button>\n    <n-button type=\"tertiary\">\n      Tertiary\n    </n-button>\n    <n-button type=\"primary\">\n      Primary\n    </n-button>\n    <n-button type=\"info\">\n      Info\n    </n-button>\n    <n-button type=\"success\">\n      Success\n    </n-button>\n    <n-button type=\"warning\">\n      Warning\n    </n-button>\n    <n-button type=\"error\">\n      Error\n    </n-button>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/button/demos/enUS/color.demo.vue",
    "content": "<markdown>\n# Custom color\n\nThese two colors look like a toadstool.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { CashOutline as CashIcon } from '@vicons/ionicons5'\n</script>\n\n<template>\n  <n-space align=\"center\">\n    <n-button color=\"#8a2be2\">\n      <template #icon>\n        <n-icon>\n          <CashIcon />\n        </n-icon>\n      </template>\n      #8a2be2\n    </n-button>\n    <n-button color=\"#ff69b4\">\n      <template #icon>\n        <n-icon>\n          <CashIcon />\n        </n-icon>\n      </template>\n      #ff69b4\n    </n-button>\n    <n-button ghost color=\"#8a2be2\">\n      <template #icon>\n        <n-icon>\n          <CashIcon />\n        </n-icon>\n      </template>\n      #8a2be2\n    </n-button>\n    <n-button ghost color=\"#ff69b4\">\n      <template #icon>\n        <n-icon>\n          <CashIcon />\n        </n-icon>\n      </template>\n      #ff69b4\n    </n-button>\n    <n-button text color=\"#8a2be2\">\n      <template #icon>\n        <n-icon>\n          <CashIcon />\n        </n-icon>\n      </template>\n      #8a2be2\n    </n-button>\n    <n-button text color=\"#ff69b4\">\n      <template #icon>\n        <n-icon>\n          <CashIcon />\n        </n-icon>\n      </template>\n      #ff69b4\n    </n-button>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/button/demos/enUS/dashed.demo.vue",
    "content": "<markdown>\n# Dashed\n\nUse `dashed` to show a dashed button.\n</markdown>\n\n<template>\n  <n-space>\n    <n-button dashed>\n      Default\n    </n-button>\n    <n-button type=\"primary\" dashed>\n      Primary\n    </n-button>\n    <n-button type=\"info\" dashed>\n      Info\n    </n-button>\n    <n-button type=\"success\" dashed>\n      Success\n    </n-button>\n    <n-button type=\"warning\" dashed>\n      Warning\n    </n-button>\n    <n-button type=\"error\" dashed>\n      Error\n    </n-button>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/button/demos/enUS/disabled.demo.vue",
    "content": "<markdown>\n# Disabled\n\nButtons can be disabled.\n</markdown>\n\n<template>\n  <n-button disabled>\n    Disabled\n  </n-button>\n</template>\n"
  },
  {
    "path": "src/button/demos/enUS/events.demo.vue",
    "content": "<markdown>\n# Events\n\nHandle events of buttons.\n</markdown>\n\n<script setup lang=\"ts\">\nimport { useMessage } from 'naive-ui'\n\nconst message = useMessage()\nfunction handleClick() {\n  message.info('Button Clicked')\n}\n</script>\n\n<template>\n  <n-button @click=\"handleClick\">\n    Click Me\n  </n-button>\n</template>\n"
  },
  {
    "path": "src/button/demos/enUS/ghost.demo.vue",
    "content": "<markdown>\n# Ghost\n\nGhost buttons have transparent backgrounds.\n</markdown>\n\n<template>\n  <n-space>\n    <n-button ghost>\n      Default\n    </n-button>\n    <n-button type=\"primary\" ghost>\n      Primary\n    </n-button>\n    <n-button type=\"info\" ghost>\n      Info\n    </n-button>\n    <n-button type=\"success\" ghost>\n      Success\n    </n-button>\n    <n-button type=\"warning\" ghost>\n      Warning\n    </n-button>\n    <n-button type=\"error\" ghost>\n      Error\n    </n-button>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/button/demos/enUS/group.demo.vue",
    "content": "<markdown>\n# Button group\n\nButtons can be grouped.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { LogInOutline as LogInIcon } from '@vicons/ionicons5'\n</script>\n\n<template>\n  <n-space>\n    <n-button-group vertical>\n      <n-button round>\n        <template #icon>\n          <n-icon><LogInIcon /></n-icon>\n        </template>\n        Live a\n      </n-button>\n      <n-button ghost>\n        <template #icon>\n          <n-icon><LogInIcon /></n-icon>\n        </template>\n        Sufficient\n      </n-button>\n      <n-button>\n        <template #icon>\n          <n-icon><LogInIcon /></n-icon>\n        </template>\n        Life\n      </n-button>\n    </n-button-group>\n    <n-button-group vertical size=\"large\">\n      <n-button>\n        <template #icon>\n          <n-icon><LogInIcon /></n-icon>\n        </template>\n        With\n      </n-button>\n      <n-button>\n        <template #icon>\n          <n-icon><LogInIcon /></n-icon>\n        </template>\n        Enough\n      </n-button>\n      <n-button ghost round>\n        <template #icon>\n          <n-icon><LogInIcon /></n-icon>\n        </template>\n        Happiness\n      </n-button>\n    </n-button-group>\n    <n-button-group size=\"small\">\n      <n-button round>\n        <template #icon>\n          <n-icon><LogInIcon /></n-icon>\n        </template>\n        Life\n      </n-button>\n      <n-button>\n        <template #icon>\n          <n-icon><LogInIcon /></n-icon>\n        </template>\n        Is\n      </n-button>\n      <n-button>\n        <template #icon>\n          <n-icon><LogInIcon /></n-icon>\n        </template>\n        Good\n      </n-button>\n    </n-button-group>\n    <n-button-group>\n      <n-button ghost>\n        <template #icon>\n          <n-icon><LogInIcon /></n-icon>\n        </template>\n        Eat\n      </n-button>\n      <n-button ghost>\n        <template #icon>\n          <n-icon><LogInIcon /></n-icon>\n        </template>\n        One More\n      </n-button>\n      <n-button round>\n        <template #icon>\n          <n-icon><LogInIcon /></n-icon>\n        </template>\n        Apple\n      </n-button>\n    </n-button-group>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/button/demos/enUS/icon-button.demo.vue",
    "content": "<markdown>\n# Use icons as buttons\n\nSometimes you may want to use an icon as a button and customize its size. You can use the `text` prop and `font-size` style to set it.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { CashOutline as CashIcon } from '@vicons/ionicons5'\n</script>\n\n<template>\n  <n-button text style=\"font-size: 24px\">\n    <n-icon>\n      <CashIcon />\n    </n-icon>\n  </n-button>\n</template>\n"
  },
  {
    "path": "src/button/demos/enUS/icon.demo.vue",
    "content": "<markdown>\n# Icon\n\nIcons can be used in buttons. You can use `render-icon` prop or `icon` slot.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { CashOutline as CashIcon } from '@vicons/ionicons5'\nimport { NIcon } from 'naive-ui'\nimport { h } from 'vue'\n\nfunction renderIcon() {\n  return h(NIcon, null, {\n    default: () => h(CashIcon)\n  })\n}\n</script>\n\n<template>\n  <n-space>\n    <n-button :render-icon=\"renderIcon\">\n      +100$\n    </n-button>\n    <n-button icon-placement=\"right\">\n      <template #icon>\n        <NIcon>\n          <CashIcon />\n        </NIcon>\n      </template>\n      +100$\n    </n-button>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/button/demos/enUS/index.demo-entry.md",
    "content": "# Button\n\nButton is used to trigger some actions.\n\n## Demos\n\n```demo\nbasic.vue\nsecondary.vue\ntertiary.vue\nquaternary.vue\ndashed.vue\nsize.vue\ntext.vue\ntag.vue\ndisabled.vue\nicon.vue\nevents.vue\nshape.vue\nghost.vue\nloading.vue\ncolor.vue\ngroup.vue\nicon-button.vue\npopover.vue\n```\n\n## API\n\n### Button Props\n\n| Name | Type | Default | Description | Version |\n| --- | --- | --- | --- | --- |\n| attr-type | `'button' \\| 'submit' \\| 'reset'` | `'button'` | The `type` attribute of the button's DOM. |  |\n| block | `boolean` | `false` | Whether the button is displayed as block. |  |\n| bordered | `boolean` | `true` | Whether the button shows the border. |  |\n| circle | `boolean` | `false` | Whether the button is round. |  |\n| color | `string` | `undefined` | Button color (support `#FFF`, `#FFFFFF`, `yellow`,`rgb(0, 0, 0)` formatted colors). |  |\n| dashed | `boolean` | `false` | Whether the button's border is a dashed line. |  |\n| disabled | `boolean` | `false` | Whether the button is disabled. |  |\n| focusable | `boolean` | `true` | Whether the button is focusable. |  |\n| ghost | `boolean` | `false` | Whether the button is ghost. |  |\n| native-focus-behavior | `boolean` | Browser is not Safari | Whether to follow button's native focus behavior. Since safari's button can't be focused by click, naive-ui uses some tricks to make it focusable on safari. If you don't need the behavior or need the button to be draggable, you can enable the prop. | 2.28.3 |\n| icon-placement | `'left' \\| 'right'` | `'left'` | The position of the icon in the button. |  |\n| keyboard | `boolean` | `true` | Whether is supports keyboard operation. |  |\n| quaternary | `boolean` | `false` | Whether the button is quaternary button. |  |\n| loading | `boolean` | `false` | Whether the button shows the loading status. |  |\n| spin-props | `{ strokeWidth?: number, stroke?: string, scale?: number, radius?: number }` | `undefined` | Loading icon properties. | 2.44.0 |\n| render-icon | `() => VNodeChild` | `undefined` | Render function that renders button icon. | 2.34.0 |\n| round | `boolean` | `false` | Whether the button shows rounded corners. |  |\n| secondary | `boolean` | `false` | Whether the button is secondary button. |  |\n| size | `'tiny' \\| 'small' \\| 'medium' \\| 'large'` | `'medium'` | Button size. |  |\n| strong | `boolean` | `false` | Whether to use strong text in the button. |  |\n| tertiary | `boolean` | `false` | Whether the button is tertiary button. |  |\n| text | `boolean` | `false` | Whether to display as a text button. |  |\n| text-color | `string` | `undefined` | Button text color (support `#FFF`, `#FFFFFF`, `yellow`,`rgb(0, 0, 0)` formatted colors). |  |\n| type | `'default' \\| 'tertiary' \\| 'primary' \\| 'success' \\| 'info' \\| 'warning' \\| 'error'` | `'default'` | Button type. |  |\n| tag | `string` | `'button'` | What tag need the button be rendered as. |  |\n\n### ButtonGroup Props\n\n| Name | Type | Default | Description |\n| --- | --- | --- | --- |\n| size | `'tiny' \\| 'small' \\| 'medium' \\| 'large'` | `undefined` | The buttons' size in button group. If set, the button's size prop inner group won't work. |\n| vertical | `boolean` | `false` | Directions of buttons in the group. |\n\n### Button Slots\n\n| Name    | Parameters | Description                        |\n| ------- | ---------- | ---------------------------------- |\n| default | `()`       | The default content of the button. |\n| icon    | `()`       | The icon of the button.            |\n\n### ButtonGroup Slots\n\n| Name    | Parameters | Description                            |\n| ------- | ---------- | -------------------------------------- |\n| default | `()`       | The button group is filled by default. |\n"
  },
  {
    "path": "src/button/demos/enUS/loading.demo.vue",
    "content": "<markdown>\n# Loading\n\nButtons can have loading states.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { CashOutline as CashIcon } from '@vicons/ionicons5'\nimport { ref } from 'vue'\n\nconst loading = ref(false)\nfunction handleClick() {\n  loading.value = true\n  setTimeout(() => {\n    loading.value = false\n  }, 2000)\n}\n</script>\n\n<template>\n  <n-space>\n    <n-button :loading=\"loading\" @click=\"handleClick\">\n      <template #icon>\n        <n-icon>\n          <CashIcon />\n        </n-icon>\n      </template>\n      Click Me\n    </n-button>\n    <n-button :loading=\"loading\" icon-placement=\"left\" @click=\"handleClick\">\n      Click Me\n    </n-button>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/button/demos/enUS/popover.demo.vue",
    "content": "<markdown>\n# Using popover in disabled state\n\nThe native disabled button won't trigger some mouse events so `n-popover` can't listen to it. If you need to use it, you can use `tag` prop to change button's behavior.\n</markdown>\n\n<template>\n  <n-space>\n    <n-tooltip>\n      <template #trigger>\n        <n-button disabled tag=\"div\">\n          Disabled button as div\n        </n-button>\n      </template>\n      Lpsum\n    </n-tooltip>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/button/demos/enUS/quaternary.demo.vue",
    "content": "<markdown>\n# Quaternary button\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { CashOutline as CashIcon } from '@vicons/ionicons5'\n</script>\n\n<template>\n  <n-space>\n    <n-button quaternary>\n      Default\n    </n-button>\n    <n-button quaternary type=\"primary\">\n      Primary\n    </n-button>\n    <n-button quaternary type=\"info\">\n      Info\n    </n-button>\n    <n-button quaternary type=\"success\">\n      Success\n    </n-button>\n    <n-button quaternary type=\"warning\">\n      Warning\n    </n-button>\n    <n-button quaternary type=\"error\">\n      Error\n    </n-button>\n    <n-button quaternary round>\n      Default\n    </n-button>\n    <n-button quaternary round type=\"primary\">\n      Primary\n    </n-button>\n    <n-button quaternary round type=\"info\">\n      Info\n    </n-button>\n    <n-button quaternary round type=\"success\">\n      Success\n    </n-button>\n    <n-button quaternary round type=\"warning\">\n      Warning\n    </n-button>\n    <n-button quaternary round type=\"error\">\n      Error\n    </n-button>\n    <n-button quaternary circle>\n      <template #icon>\n        <n-icon><CashIcon /></n-icon>\n      </template>\n    </n-button>\n    <n-button quaternary circle type=\"primary\">\n      <template #icon>\n        <n-icon><CashIcon /></n-icon>\n      </template>\n    </n-button>\n    <n-button quaternary circle type=\"info\">\n      <template #icon>\n        <n-icon><CashIcon /></n-icon>\n      </template>\n    </n-button>\n    <n-button quaternary circle type=\"success\">\n      <template #icon>\n        <n-icon><CashIcon /></n-icon>\n      </template>\n    </n-button>\n    <n-button quaternary circle type=\"warning\">\n      <template #icon>\n        <n-icon><CashIcon /></n-icon>\n      </template>\n    </n-button>\n    <n-button quaternary circle type=\"error\">\n      <template #icon>\n        <n-icon><CashIcon /></n-icon>\n      </template>\n    </n-button>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/button/demos/enUS/secondary.demo.vue",
    "content": "<markdown>\n# Secondary button\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { CashOutline as CashIcon } from '@vicons/ionicons5'\n</script>\n\n<template>\n  <n-space>\n    <n-button strong secondary>\n      Default\n    </n-button>\n    <n-button strong secondary type=\"tertiary\">\n      Tertiary\n    </n-button>\n    <n-button strong secondary type=\"primary\">\n      Primary\n    </n-button>\n    <n-button strong secondary type=\"info\">\n      Info\n    </n-button>\n    <n-button strong secondary type=\"success\">\n      Success\n    </n-button>\n    <n-button strong secondary type=\"warning\">\n      Warning\n    </n-button>\n    <n-button strong secondary type=\"error\">\n      Error\n    </n-button>\n    <n-button strong secondary round>\n      Default\n    </n-button>\n    <n-button strong secondary round type=\"primary\">\n      Primary\n    </n-button>\n    <n-button strong secondary round type=\"info\">\n      Info\n    </n-button>\n    <n-button strong secondary round type=\"success\">\n      Success\n    </n-button>\n    <n-button strong secondary round type=\"warning\">\n      Warning\n    </n-button>\n    <n-button strong secondary round type=\"error\">\n      Error\n    </n-button>\n    <n-button strong secondary circle>\n      <template #icon>\n        <n-icon><CashIcon /></n-icon>\n      </template>\n    </n-button>\n    <n-button strong secondary circle type=\"primary\">\n      <template #icon>\n        <n-icon><CashIcon /></n-icon>\n      </template>\n    </n-button>\n    <n-button strong secondary circle type=\"info\">\n      <template #icon>\n        <n-icon><CashIcon /></n-icon>\n      </template>\n    </n-button>\n    <n-button strong secondary circle type=\"success\">\n      <template #icon>\n        <n-icon><CashIcon /></n-icon>\n      </template>\n    </n-button>\n    <n-button strong secondary circle type=\"warning\">\n      <template #icon>\n        <n-icon><CashIcon /></n-icon>\n      </template>\n    </n-button>\n    <n-button strong secondary circle type=\"error\">\n      <template #icon>\n        <n-icon><CashIcon /></n-icon>\n      </template>\n    </n-button>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/button/demos/enUS/shape.demo.vue",
    "content": "<markdown>\n# Shape\n\nButtons can have different shapes.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { CashOutline as CashIcon } from '@vicons/ionicons5'\n</script>\n\n<template>\n  <n-space>\n    <n-button circle>\n      <template #icon>\n        <n-icon><CashIcon /></n-icon>\n      </template>\n    </n-button>\n    <n-button round>\n      Round\n    </n-button>\n    <n-button>Rect</n-button>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/button/demos/enUS/size.demo.vue",
    "content": "<markdown>\n# Size\n\nButtons can be `tiny`, `small`, `medium` and `large` in size.\n</markdown>\n\n<template>\n  <n-space align=\"baseline\">\n    <n-button size=\"tiny\">\n      Small Small\n    </n-button>\n    <n-button size=\"small\">\n      Small\n    </n-button>\n    <n-button size=\"medium\">\n      Not Small\n    </n-button>\n    <n-button size=\"large\">\n      Not Not Small\n    </n-button>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/button/demos/enUS/tag.demo.vue",
    "content": "<markdown>\n# Tag\n\nYou can render buttons with different tags. For example `<a />`.\n</markdown>\n\n<template>\n  <n-button\n    text\n    tag=\"a\"\n    href=\"https://anyway.fm/news.php\"\n    target=\"_blank\"\n    type=\"primary\"\n  >\n    Anyway.News\n  </n-button>\n</template>\n"
  },
  {
    "path": "src/button/demos/enUS/tertiary.demo.vue",
    "content": "<markdown>\n# Tertiary button\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { CashOutline as CashIcon } from '@vicons/ionicons5'\n</script>\n\n<template>\n  <n-space>\n    <n-button tertiary>\n      Default\n    </n-button>\n    <n-button tertiary type=\"primary\">\n      Primary\n    </n-button>\n    <n-button tertiary type=\"info\">\n      Info\n    </n-button>\n    <n-button tertiary type=\"success\">\n      Success\n    </n-button>\n    <n-button tertiary type=\"warning\">\n      Warning\n    </n-button>\n    <n-button tertiary type=\"error\">\n      Error\n    </n-button>\n    <n-button tertiary round>\n      Default\n    </n-button>\n    <n-button tertiary round type=\"primary\">\n      Primary\n    </n-button>\n    <n-button tertiary round type=\"info\">\n      Info\n    </n-button>\n    <n-button tertiary round type=\"success\">\n      Success\n    </n-button>\n    <n-button tertiary round type=\"warning\">\n      Warning\n    </n-button>\n    <n-button tertiary round type=\"error\">\n      Error\n    </n-button>\n    <n-button tertiary circle>\n      <template #icon>\n        <n-icon><CashIcon /></n-icon>\n      </template>\n    </n-button>\n    <n-button tertiary circle type=\"primary\">\n      <template #icon>\n        <n-icon><CashIcon /></n-icon>\n      </template>\n    </n-button>\n    <n-button tertiary circle type=\"info\">\n      <template #icon>\n        <n-icon><CashIcon /></n-icon>\n      </template>\n    </n-button>\n    <n-button tertiary circle type=\"success\">\n      <template #icon>\n        <n-icon><CashIcon /></n-icon>\n      </template>\n    </n-button>\n    <n-button tertiary circle type=\"warning\">\n      <template #icon>\n        <n-icon><CashIcon /></n-icon>\n      </template>\n    </n-button>\n    <n-button tertiary circle type=\"error\">\n      <template #icon>\n        <n-icon><CashIcon /></n-icon>\n      </template>\n    </n-button>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/button/demos/enUS/text.demo.vue",
    "content": "<markdown>\n# Text button\n\nIt just looks like text.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { TrainOutline as TrainIcon } from '@vicons/ionicons5'\n</script>\n\n<template>\n  <n-button text>\n    <template #icon>\n      <n-icon>\n        <TrainIcon />\n      </n-icon>\n    </template>\n    The Engine is Still Spitting Smoke\n  </n-button>\n</template>\n"
  },
  {
    "path": "src/button/demos/zhCN/basic.demo.vue",
    "content": "<markdown>\n# 基础\n\n按钮的 `type` 分别为 `default`、`tertiary`、`primary`、`info`、`success`、`warning` 和 `error`。\n</markdown>\n\n<template>\n  <n-space>\n    <n-button>Default</n-button>\n    <n-button type=\"tertiary\">\n      Tertiary\n    </n-button>\n    <n-button type=\"primary\">\n      Primary\n    </n-button>\n    <n-button type=\"info\">\n      Info\n    </n-button>\n    <n-button type=\"success\">\n      Success\n    </n-button>\n    <n-button type=\"warning\">\n      Warning\n    </n-button>\n    <n-button type=\"error\">\n      Error\n    </n-button>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/button/demos/zhCN/color.demo.vue",
    "content": "<markdown>\n# 自定义颜色\n\n这两个颜色看起来像毒蘑菇。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { CashOutline as CashIcon } from '@vicons/ionicons5'\n</script>\n\n<template>\n  <n-space align=\"center\">\n    <n-button color=\"#8a2be2\">\n      <template #icon>\n        <n-icon>\n          <CashIcon />\n        </n-icon>\n      </template>\n      #8a2be2\n    </n-button>\n    <n-button color=\"#ff69b4\">\n      <template #icon>\n        <n-icon>\n          <CashIcon />\n        </n-icon>\n      </template>\n      #ff69b4\n    </n-button>\n    <n-button ghost color=\"#8a2be2\">\n      <template #icon>\n        <n-icon>\n          <CashIcon />\n        </n-icon>\n      </template>\n      #8a2be2\n    </n-button>\n    <n-button ghost color=\"#ff69b4\">\n      <template #icon>\n        <n-icon>\n          <CashIcon />\n        </n-icon>\n      </template>\n      #ff69b4\n    </n-button>\n    <n-button text color=\"#8a2be2\">\n      <template #icon>\n        <n-icon>\n          <CashIcon />\n        </n-icon>\n      </template>\n      #8a2be2\n    </n-button>\n    <n-button text color=\"#ff69b4\">\n      <template #icon>\n        <n-icon>\n          <CashIcon />\n        </n-icon>\n      </template>\n      #ff69b4\n    </n-button>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/button/demos/zhCN/dashed.demo.vue",
    "content": "<markdown>\n# 虚线按钮\n\n使用 `dashed` 来使用虚线按钮。\n</markdown>\n\n<template>\n  <n-space>\n    <n-button dashed>\n      Default\n    </n-button>\n    <n-button type=\"primary\" dashed>\n      Primary\n    </n-button>\n    <n-button type=\"info\" dashed>\n      Info\n    </n-button>\n    <n-button type=\"success\" dashed>\n      Success\n    </n-button>\n    <n-button type=\"warning\" dashed>\n      Warning\n    </n-button>\n    <n-button type=\"error\" dashed>\n      Error\n    </n-button>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/button/demos/zhCN/debug.demo.vue",
    "content": "<markdown>\n# debug\n\n`Debug` 用的。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { CashOutline, LogInOutline } from '@vicons/ionicons5'\nimport { unstableButtonGroupRtl, unstableButtonRtl } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst rtlEnabled = ref(false)\nconst rtlStyles = [unstableButtonGroupRtl, unstableButtonRtl]\n</script>\n\n<template>\n  <n-space><n-switch v-model:value=\"rtlEnabled\" />Rtl</n-space>\n  <n-config-provider\n    class=\"debug-zone\"\n    :rtl=\"rtlEnabled ? rtlStyles : undefined\"\n  >\n    <n-button type=\"default\" round>\n      <template #icon>\n        <n-icon><CashOutline /></n-icon>\n      </template>\n      Default\n    </n-button>\n    <n-button type=\"primary\" disabled>\n      <template #icon>\n        <n-icon><CashOutline /></n-icon>\n      </template>\n      Primary\n    </n-button>\n    <n-button type=\"info\" icon-placement=\"right\">\n      <template #icon>\n        <n-icon><CashOutline /></n-icon>\n      </template>\n      Info\n    </n-button>\n    <n-button type=\"warning\">\n      <template #icon>\n        <n-icon><CashOutline /></n-icon>\n      </template>\n      Warning\n    </n-button>\n    <n-button type=\"success\">\n      <template #icon>\n        <n-icon><CashOutline /></n-icon>\n      </template>\n      Success\n    </n-button>\n    <n-button type=\"error\">\n      <template #icon>\n        <n-icon><CashOutline /></n-icon>\n      </template>\n      Error\n    </n-button>\n    <n-button type=\"default\" ghost>\n      <template #icon>\n        <n-icon><CashOutline /></n-icon>\n      </template>\n      Default\n    </n-button>\n    <n-button type=\"primary\" ghost round>\n      <template #icon>\n        <n-icon><CashOutline /></n-icon>\n      </template>\n      Primary\n    </n-button>\n    <n-button type=\"info\" ghost disabled>\n      <template #icon>\n        <n-icon><CashOutline /></n-icon>\n      </template>\n      Info\n    </n-button>\n    <n-button type=\"warning\" ghost icon-placement=\"right\">\n      <template #icon>\n        <n-icon><CashOutline /></n-icon>\n      </template>\n      Warning\n    </n-button>\n    <n-button type=\"success\" ghost>\n      <template #icon>\n        <n-icon><CashOutline /></n-icon>\n      </template>\n      Success\n    </n-button>\n    <n-button type=\"error\" ghost>\n      <template #icon>\n        <n-icon><CashOutline /></n-icon>\n      </template>\n      Error\n    </n-button>\n    <n-button type=\"default\" loading>\n      <template #icon>\n        <n-icon><CashOutline /></n-icon>\n      </template>\n      Default\n    </n-button>\n    <n-button type=\"primary\" loading>\n      <template #icon>\n        <n-icon><CashOutline /></n-icon>\n      </template>\n      Primary\n    </n-button>\n    <n-button type=\"info\" loading round>\n      <template #icon>\n        <n-icon><CashOutline /></n-icon>\n      </template>\n      Info\n    </n-button>\n    <n-button type=\"warning\" loading disabled>\n      <template #icon>\n        <n-icon><CashOutline /></n-icon>\n      </template>\n      Warning\n    </n-button>\n    <n-button type=\"success\" loading icon-placement=\"right\">\n      <template #icon>\n        <n-icon><CashOutline /></n-icon>\n      </template>\n      Success\n    </n-button>\n    <n-button type=\"error\" loading>\n      <template #icon>\n        <n-icon><CashOutline /></n-icon>\n      </template>\n      Error\n    </n-button>\n    <n-button type=\"default\" ghost loading>\n      <template #icon>\n        <n-icon><CashOutline /></n-icon>\n      </template>\n      Default\n    </n-button>\n    <n-button type=\"primary\" ghost loading>\n      <template #icon>\n        <n-icon><CashOutline /></n-icon>\n      </template>\n      Primary\n    </n-button>\n    <n-button type=\"info\" ghost loading>\n      <template #icon>\n        <n-icon><CashOutline /></n-icon>\n      </template>\n      Info\n    </n-button>\n    <n-button type=\"warning\" ghost loading round>\n      <template #icon>\n        <n-icon><CashOutline /></n-icon>\n      </template>\n      Warning\n    </n-button>\n    <n-button type=\"success\" ghost loading disabled>\n      <template #icon>\n        <n-icon><CashOutline /></n-icon>\n      </template>\n      Success\n    </n-button>\n    <n-button type=\"error\" ghost loading icon-placement=\"right\">\n      <template #icon>\n        <n-icon><CashOutline /></n-icon>\n      </template>\n      Error\n    </n-button>\n    <n-button type=\"default\" round block>\n      <template #icon>\n        <n-icon><CashOutline /></n-icon>\n      </template>\n      Default\n    </n-button>\n    <n-button type=\"primary\" disabled block size=\"small\">\n      <template #icon>\n        <n-icon><CashOutline /></n-icon>\n      </template>\n      Primary\n    </n-button>\n    <n-button type=\"info\" icon-placement=\"right\" block size=\"large\">\n      <template #icon>\n        <n-icon><CashOutline /></n-icon>\n      </template>\n      Info\n    </n-button>\n    <n-button type=\"warning\" block ghost>\n      <template #icon>\n        <n-icon><CashOutline /></n-icon>\n      </template>\n      Warning\n    </n-button>\n    <n-button type=\"success\" block loading>\n      <template #icon>\n        <n-icon><CashOutline /></n-icon>\n      </template>\n      Success\n    </n-button>\n    <n-button type=\"error\" block>\n      <template #icon>\n        <n-icon><CashOutline /></n-icon>\n      </template>\n      Error\n    </n-button>\n    <n-button type=\"primary\" disabled circle size=\"small\">\n      <template #icon>\n        <n-icon><CashOutline /></n-icon>\n      </template>\n    </n-button>\n    <n-button type=\"info\" icon-placement=\"right\" circle size=\"large\">\n      <template #icon>\n        <n-icon><CashOutline /></n-icon>\n      </template>\n    </n-button>\n    <n-button type=\"warning\" circle ghost>\n      <template #icon>\n        <n-icon><CashOutline /></n-icon>\n      </template>\n    </n-button>\n    <n-button type=\"success\" circle loading>\n      <template #icon>\n        <n-icon><CashOutline /></n-icon>\n      </template>\n    </n-button>\n    <n-button type=\"error\" circle>\n      <template #icon>\n        <n-icon><CashOutline /></n-icon>\n      </template>\n    </n-button>\n    <n-button type=\"error\">\n      <template #icon>\n        <n-icon><CashOutline /></n-icon>\n      </template>\n      Error\n    </n-button>\n    <n-button type=\"error\" size=\"large\">\n      <template #icon>\n        <n-icon><CashOutline /></n-icon>\n      </template>\n    </n-button>\n    <n-button type=\"error\" round size=\"large\">\n      <template #icon>\n        <n-icon><CashOutline /></n-icon>\n      </template>\n    </n-button>\n    <n-button-group>\n      <n-button type=\"default\" round>\n        <template #icon>\n          <n-icon><CashOutline /></n-icon>\n        </template>\n        Default\n      </n-button>\n      <n-button type=\"primary\" disabled>\n        <template #icon>\n          <n-icon><CashOutline /></n-icon>\n        </template>\n        Primary\n      </n-button>\n      <n-button type=\"info\" icon-placement=\"right\">\n        <template #icon>\n          <n-icon><CashOutline /></n-icon>\n        </template>\n        Info\n      </n-button>\n      <n-button type=\"warning\">\n        <template #icon>\n          <n-icon><CashOutline /></n-icon>\n        </template>\n        Warning\n      </n-button>\n    </n-button-group>\n    <n-button-group vertical>\n      <n-button type=\"default\" round>\n        <template #icon>\n          <n-icon><CashOutline /></n-icon>\n        </template>\n        Default\n      </n-button>\n      <n-button type=\"primary\" disabled>\n        <template #icon>\n          <n-icon><CashOutline /></n-icon>\n        </template>\n        Primary\n      </n-button>\n      <n-button type=\"info\" icon-placement=\"right\">\n        <template #icon>\n          <n-icon><CashOutline /></n-icon>\n        </template>\n        Info\n      </n-button>\n      <n-button type=\"warning\">\n        <template #icon>\n          <n-icon><CashOutline /></n-icon>\n        </template>\n        Warning\n      </n-button>\n    </n-button-group>\n    <n-button text type=\"info\" loading size=\"small\" disabled>\n      Info\n    </n-button>\n    <n-button text type=\"success\">\n      Success\n    </n-button>\n    <n-button text type=\"warning\">\n      Warning\n    </n-button>\n    <n-button text type=\"error\" icon-placement=\"right\">\n      <template #icon>\n        <n-icon><CashOutline /></n-icon>\n      </template>\n      Error\n    </n-button>\n    <n-button-group vertical>\n      <n-button type=\"primary\" round>\n        <template #icon>\n          <n-icon><LogInOutline /></n-icon>\n        </template>\n        活着\n      </n-button>\n      <n-button type=\"warning\" ghost>\n        <template #icon>\n          <n-icon><LogInOutline /></n-icon>\n        </template>\n        不多\n      </n-button>\n      <n-button type=\"error\">\n        <template #icon>\n          <n-icon><LogInOutline /></n-icon>\n        </template>\n        不少\n      </n-button>\n    </n-button-group>\n    <n-button-group vertical size=\"large\">\n      <n-button type=\"success\">\n        <template #icon>\n          <n-icon><LogInOutline /></n-icon>\n        </template>\n        幸福\n      </n-button>\n      <n-button type=\"info\">\n        <template #icon>\n          <n-icon><LogInOutline /></n-icon>\n        </template>\n        刚好\n      </n-button>\n      <n-button type=\"error\" ghost round>\n        <template #icon>\n          <n-icon><LogInOutline /></n-icon>\n        </template>\n        够用\n      </n-button>\n    </n-button-group>\n    <n-button-group size=\"small\">\n      <n-button type=\"default\" round>\n        <template #icon>\n          <n-icon><LogInOutline /></n-icon>\n        </template>\n        活着\n      </n-button>\n      <n-button type=\"default\">\n        <template #icon>\n          <n-icon><LogInOutline /></n-icon>\n        </template>\n        其实\n      </n-button>\n      <n-button type=\"default\">\n        <template #icon>\n          <n-icon><LogInOutline /></n-icon>\n        </template>\n        很好\n      </n-button>\n    </n-button-group>\n    <n-button-group>\n      <n-button type=\"primary\" ghost>\n        <template #icon>\n          <n-icon><LogInOutline /></n-icon>\n        </template>\n        再吃\n      </n-button>\n      <n-button ghost type=\"primary\">\n        <template #icon>\n          <n-icon><LogInOutline /></n-icon>\n        </template>\n        一颗\n      </n-button>\n      <n-button type=\"info\" round>\n        <template #icon>\n          <n-icon><LogInOutline /></n-icon>\n        </template>\n        苹果\n      </n-button>\n    </n-button-group>\n  </n-config-provider>\n</template>\n\n<style>\n.n-button {\n  margin-right: 12px;\n  margin-bottom: 8px;\n}\n.debug-zone {\n  border-radius: 4px;\n  background-color: transparent;\n  transition: background-color 0.3s ease-in-out;\n}\n.n-light-theme .debug-zone {\n  border-radius: 4px;\n  background-color: #ececec;\n}\n</style>\n"
  },
  {
    "path": "src/button/demos/zhCN/disabled.demo.vue",
    "content": "<markdown>\n# 禁用\n\n按钮可以被禁用。\n</markdown>\n\n<template>\n  <n-button disabled>\n    不许点\n  </n-button>\n</template>\n"
  },
  {
    "path": "src/button/demos/zhCN/events.demo.vue",
    "content": "<markdown>\n# 事件\n\n处理按钮的事件。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { useMessage } from 'naive-ui'\n\nconst message = useMessage()\nfunction handleClick() {\n  message.info('Button Clicked')\n}\n</script>\n\n<template>\n  <n-button @click=\"handleClick\">\n    点它\n  </n-button>\n</template>\n"
  },
  {
    "path": "src/button/demos/zhCN/ghost.demo.vue",
    "content": "<markdown>\n# 透明背景\n\n`Ghost` 按钮有透明的背景。\n</markdown>\n\n<template>\n  <n-space>\n    <n-button ghost>\n      Default\n    </n-button>\n    <n-button type=\"primary\" ghost>\n      Primary\n    </n-button>\n    <n-button type=\"info\" ghost>\n      Info\n    </n-button>\n    <n-button type=\"success\" ghost>\n      Success\n    </n-button>\n    <n-button type=\"warning\" ghost>\n      Warning\n    </n-button>\n    <n-button type=\"error\" ghost>\n      Error\n    </n-button>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/button/demos/zhCN/group.demo.vue",
    "content": "<markdown>\n# 按钮组\n\n可以把几个按钮结合成按钮组。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { LogInOutline as LogInIcon } from '@vicons/ionicons5'\n</script>\n\n<template>\n  <n-space>\n    <n-button-group vertical>\n      <n-button round>\n        <template #icon>\n          <n-icon><LogInIcon /></n-icon>\n        </template>\n        活着\n      </n-button>\n      <n-button ghost>\n        <template #icon>\n          <n-icon><LogInIcon /></n-icon>\n        </template>\n        不多\n      </n-button>\n      <n-button>\n        <template #icon>\n          <n-icon><LogInIcon /></n-icon>\n        </template>\n        不少\n      </n-button>\n    </n-button-group>\n    <n-button-group vertical size=\"large\">\n      <n-button>\n        <template #icon>\n          <n-icon><LogInIcon /></n-icon>\n        </template>\n        幸福\n      </n-button>\n      <n-button>\n        <template #icon>\n          <n-icon><LogInIcon /></n-icon>\n        </template>\n        刚好\n      </n-button>\n      <n-button ghost round>\n        <template #icon>\n          <n-icon><LogInIcon /></n-icon>\n        </template>\n        够用\n      </n-button>\n    </n-button-group>\n    <n-button-group size=\"small\">\n      <n-button type=\"default\" round>\n        <template #icon>\n          <n-icon><LogInIcon /></n-icon>\n        </template>\n        活着\n      </n-button>\n      <n-button type=\"default\">\n        <template #icon>\n          <n-icon><LogInIcon /></n-icon>\n        </template>\n        其实\n      </n-button>\n      <n-button type=\"default\">\n        <template #icon>\n          <n-icon><LogInIcon /></n-icon>\n        </template>\n        很好\n      </n-button>\n    </n-button-group>\n    <n-button-group>\n      <n-button ghost>\n        <template #icon>\n          <n-icon><LogInIcon /></n-icon>\n        </template>\n        再吃\n      </n-button>\n      <n-button ghost>\n        <template #icon>\n          <n-icon><LogInIcon /></n-icon>\n        </template>\n        一颗\n      </n-button>\n      <n-button round>\n        <template #icon>\n          <n-icon><LogInIcon /></n-icon>\n        </template>\n        苹果\n      </n-button>\n    </n-button-group>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/button/demos/zhCN/icon-button.demo.vue",
    "content": "<markdown>\n# 使用图标作为按钮\n\n有时你可能会想用图标作为按钮并且自定义一些尺寸。这时你可以使用 `text` 按钮和 `font-size` 来进行设定。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { CashOutline as CashIcon } from '@vicons/ionicons5'\n</script>\n\n<template>\n  <n-button text style=\"font-size: 24px\">\n    <n-icon>\n      <CashIcon />\n    </n-icon>\n  </n-button>\n</template>\n"
  },
  {
    "path": "src/button/demos/zhCN/icon.demo.vue",
    "content": "<markdown>\n# 图标\n\n在按钮上使用图标，可以使用 `render-icon` 属性或 `icon` 插槽。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { CashOutline as CashIcon } from '@vicons/ionicons5'\nimport { NIcon } from 'naive-ui'\nimport { h } from 'vue'\n\nfunction renderIcon() {\n  return h(NIcon, null, {\n    default: () => h(CashIcon)\n  })\n}\n</script>\n\n<template>\n  <n-space>\n    <n-button secondary strong :render-icon=\"renderIcon\">\n      +100 元\n    </n-button>\n    <n-button icon-placement=\"right\" secondary strong>\n      <template #icon>\n        <NIcon>\n          <CashIcon />\n        </NIcon>\n      </template>\n      +100 元\n    </n-button>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/button/demos/zhCN/index.demo-entry.md",
    "content": "# 按钮 Button\n\n按钮用来触发一些操作。\n\n## 演示\n\n```demo\nbasic.vue\nsecondary.vue\ntertiary.vue\nquaternary.vue\ndashed.vue\nsize.vue\ntext.vue\ntag.vue\ndisabled.vue\nicon.vue\nevents.vue\nshape.vue\nghost.vue\nloading.vue\ncolor.vue\ngroup.vue\nicon-button.vue\npopover.vue\nrtl-debug.vue\ndebug.vue\n```\n\n## API\n\n### Button Props\n\n| 名称 | 类型 | 默认值 | 说明 | 版本 |\n| --- | --- | --- | --- | --- |\n| attr-type | `'button' \\| 'submit' \\| 'reset'` | `'button'` | 按钮的 DOM 的 `type` 属性 |  |\n| block | `boolean` | `false` | 按钮是否显示为块级 |  |\n| bordered | `boolean` | `true` | 按钮是否显示 border |  |\n| circle | `boolean` | `false` | 按钮是否为圆形 |  |\n| color | `string` | `undefined` | 按钮颜色（支持形如 `#FFF`， `#FFFFFF`， `yellow`，`rgb(0, 0, 0)` 的颜色） |  |\n| dashed | `boolean` | `false` | 按钮边框是否为虚线 |  |\n| disabled | `boolean` | `false` | 按钮是否禁用 |  |\n| focusable | `boolean` | `true` | 按钮是否可以被聚焦 |  |\n| ghost | `boolean` | `false` | 按钮是否透明 |  |\n| native-focus-behavior | `boolean` | 浏览器不是 Safari | 按钮是否遵循原生的 focus 行为。Safari 原生的 button 无法通过点击被聚焦，所以默认情况下 naive-ui 做了一些处理使它可以被聚焦，如果你不需要这种行为，或者发现你需要让按钮可被拖动，可以开启这个属性 | 2.28.3 |\n| icon-placement | `'left' \\| 'right'` | `'left'` | 按钮中图标的位置 |  |\n| keyboard | `boolean` | `true` | 是否支持键盘操作 |  |\n| loading | `boolean` | `false` | 按钮是否显示加载状态 |  |\n| quaternary | `boolean` | `false` | 是否是四级按钮 |  |\n| spin-props | `{ strokeWidth?: number, stroke?: string, scale?: number, radius?: number }` | `undefined` | 加载图标的属性 | 2.44.0 |\n| render-icon | `() => VNodeChild` | `undefined` | 按钮图标的渲染函数 | 2.34.0 |\n| round | `boolean` | `false` | 按钮是否显示圆角 |  |\n| size | `'tiny' \\| 'small' \\| 'medium' \\| 'large'` | `'medium'` | 按钮的尺寸 |  |\n| secondary | `boolean` | `false` | 是否是次要按钮 |  |\n| strong | `boolean` | `false` | 按钮文字是否加粗 |  |\n| tertiary | `boolean` | `false` | 是否是三级按钮 |  |\n| text | `boolean` | `false` | 是否显示为文本按钮 |  |\n| text-color | `string` | `undefined` | 按钮文字颜色（支持形如 `#FFF`， `#FFFFFF`， `yellow`，`rgb(0, 0, 0)` 的颜色） |  |\n| type | `'default' \\| 'tertiary' \\| 'primary' \\| 'success' \\| 'info' \\| 'warning' \\| 'error'` | `'default'` | 按钮的类型 |  |\n| tag | `string` | `'button'` | 按钮需要被渲染为什么标签 |  |\n\n### ButtonGroup Props\n\n| 名称 | 类型 | 默认值 | 说明 |\n| --- | --- | --- | --- |\n| size | `'tiny' \\| 'small' \\| 'medium' \\| 'large'` | `undefined` | 在组内的按钮的尺寸。如果设定，内部的按钮尺寸将不生效 |\n| vertical | `boolean` | `false` | 组内按钮的排列方式 |\n\n### Button Slots\n\n| 名称    | 参数 | 说明       |\n| ------- | ---- | ---------- |\n| default | `()` | 按钮的内容 |\n| icon    | `()` | 按钮的图标 |\n\n### ButtonGroup Slots\n\n| 名称    | 参数 | 说明         |\n| ------- | ---- | ------------ |\n| default | `()` | 按钮组的内容 |\n"
  },
  {
    "path": "src/button/demos/zhCN/loading.demo.vue",
    "content": "<markdown>\n# 加载中\n\n按钮有加载状态。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { CashOutline as CashIcon } from '@vicons/ionicons5'\nimport { ref } from 'vue'\n\nconst loading = ref(false)\nfunction handleClick() {\n  loading.value = true\n  setTimeout(() => {\n    loading.value = false\n  }, 2000)\n}\n</script>\n\n<template>\n  <n-space>\n    <n-button :loading=\"loading\" @click=\"handleClick\">\n      <template #icon>\n        <n-icon>\n          <CashIcon />\n        </n-icon>\n      </template>\n      点我\n    </n-button>\n    <n-button :loading=\"loading\" @click=\"handleClick\">\n      点我\n    </n-button>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/button/demos/zhCN/popover.demo.vue",
    "content": "<markdown>\n# 配合 Popover 的特殊情况\n\ndisabled 的原生 button 不会触发部分鼠标事件，因此 `n-popover` 无法监听到相关的事件。如果你需要在这种情况下使用，可以使用 `tag` 属性来调整 button 的行为。\n</markdown>\n\n<template>\n  <n-space>\n    <n-tooltip>\n      <template #trigger>\n        <n-button disabled tag=\"div\">\n          突破\n        </n-button>\n      </template>\n      工作遇到困难，齐心协力一起解决\n    </n-tooltip>\n    <n-button>两天加班换一天调休</n-button>\n    <n-tooltip>\n      <template #trigger>\n        <n-button disabled tag=\"div\">\n          惦记\n        </n-button>\n      </template>\n      你必然一身才华，才会被这么多人惦记\n    </n-tooltip>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/button/demos/zhCN/quaternary.demo.vue",
    "content": "<markdown>\n# 次次次要按钮\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { CashOutline as CashIcon } from '@vicons/ionicons5'\n</script>\n\n<template>\n  <n-space>\n    <n-button quaternary>\n      Default\n    </n-button>\n    <n-button quaternary type=\"primary\">\n      Primary\n    </n-button>\n    <n-button quaternary type=\"info\">\n      Info\n    </n-button>\n    <n-button quaternary type=\"success\">\n      Success\n    </n-button>\n    <n-button quaternary type=\"warning\">\n      Warning\n    </n-button>\n    <n-button quaternary type=\"error\">\n      Error\n    </n-button>\n    <n-button quaternary round>\n      Default\n    </n-button>\n    <n-button quaternary round type=\"primary\">\n      Primary\n    </n-button>\n    <n-button quaternary round type=\"info\">\n      Info\n    </n-button>\n    <n-button quaternary round type=\"success\">\n      Success\n    </n-button>\n    <n-button quaternary round type=\"warning\">\n      Warning\n    </n-button>\n    <n-button quaternary round type=\"error\">\n      Error\n    </n-button>\n    <n-button quaternary circle>\n      <template #icon>\n        <n-icon><CashIcon /></n-icon>\n      </template>\n    </n-button>\n    <n-button quaternary circle type=\"primary\">\n      <template #icon>\n        <n-icon><CashIcon /></n-icon>\n      </template>\n    </n-button>\n    <n-button quaternary circle type=\"info\">\n      <template #icon>\n        <n-icon><CashIcon /></n-icon>\n      </template>\n    </n-button>\n    <n-button quaternary circle type=\"success\">\n      <template #icon>\n        <n-icon><CashIcon /></n-icon>\n      </template>\n    </n-button>\n    <n-button quaternary circle type=\"warning\">\n      <template #icon>\n        <n-icon><CashIcon /></n-icon>\n      </template>\n    </n-button>\n    <n-button quaternary circle type=\"error\">\n      <template #icon>\n        <n-icon><CashIcon /></n-icon>\n      </template>\n    </n-button>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/button/demos/zhCN/rtl-debug.demo.vue",
    "content": "<markdown>\n# Rtl Debug\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { CashOutline as CashIcon } from '@vicons/ionicons5'\nimport { unstableButtonRtl } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst rtlEnabled = ref(false)\nconst rtlStyles = [unstableButtonRtl]\n</script>\n\n<template>\n  <n-space vertical>\n    <n-space><n-switch v-model:value=\"rtlEnabled\" />Rtl</n-space>\n    <n-config-provider :rtl=\"rtlEnabled ? rtlStyles : undefined\">\n      <n-space>\n        <n-button>\n          <template #icon>\n            <n-icon>\n              <CashIcon />\n            </n-icon>\n          </template>\n          Rtl Test\n        </n-button>\n        <n-button icon-placement=\"right\">\n          <template #icon>\n            <n-icon>\n              <CashIcon />\n            </n-icon>\n          </template>\n          Rtl Test\n        </n-button>\n      </n-space>\n    </n-config-provider>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/button/demos/zhCN/secondary.demo.vue",
    "content": "<markdown>\n# 次要按钮\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { CashOutline as CashIcon } from '@vicons/ionicons5'\n</script>\n\n<template>\n  <n-space>\n    <n-button strong secondary>\n      Default\n    </n-button>\n    <n-button strong secondary type=\"tertiary\">\n      Tertiary\n    </n-button>\n    <n-button strong secondary type=\"primary\">\n      Primary\n    </n-button>\n    <n-button strong secondary type=\"info\">\n      Info\n    </n-button>\n    <n-button strong secondary type=\"success\">\n      Success\n    </n-button>\n    <n-button strong secondary type=\"warning\">\n      Warning\n    </n-button>\n    <n-button strong secondary type=\"error\">\n      Error\n    </n-button>\n    <n-button strong secondary round>\n      Default\n    </n-button>\n    <n-button strong secondary round type=\"primary\">\n      Primary\n    </n-button>\n    <n-button strong secondary round type=\"info\">\n      Info\n    </n-button>\n    <n-button strong secondary round type=\"success\">\n      Success\n    </n-button>\n    <n-button strong secondary round type=\"warning\">\n      Warning\n    </n-button>\n    <n-button strong secondary round type=\"error\">\n      Error\n    </n-button>\n    <n-button strong secondary circle>\n      <template #icon>\n        <n-icon><CashIcon /></n-icon>\n      </template>\n    </n-button>\n    <n-button strong secondary circle type=\"primary\">\n      <template #icon>\n        <n-icon><CashIcon /></n-icon>\n      </template>\n    </n-button>\n    <n-button strong secondary circle type=\"info\">\n      <template #icon>\n        <n-icon><CashIcon /></n-icon>\n      </template>\n    </n-button>\n    <n-button strong secondary circle type=\"success\">\n      <template #icon>\n        <n-icon><CashIcon /></n-icon>\n      </template>\n    </n-button>\n    <n-button strong secondary circle type=\"warning\">\n      <template #icon>\n        <n-icon><CashIcon /></n-icon>\n      </template>\n    </n-button>\n    <n-button strong secondary circle type=\"error\">\n      <template #icon>\n        <n-icon><CashIcon /></n-icon>\n      </template>\n    </n-button>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/button/demos/zhCN/shape.demo.vue",
    "content": "<markdown>\n# 形状\n\n按钮拥有不同的形状。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { CashOutline as CashIcon } from '@vicons/ionicons5'\n</script>\n\n<template>\n  <n-space>\n    <n-button circle>\n      <template #icon>\n        <n-icon><CashIcon /></n-icon>\n      </template>\n    </n-button>\n    <n-button round>\n      圆角\n    </n-button>\n    <n-button>方</n-button>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/button/demos/zhCN/size.demo.vue",
    "content": "<markdown>\n# 尺寸\n\n有 `tiny`、`small`、`medium` 和 `large` 尺寸。\n</markdown>\n\n<template>\n  <n-space align=\"baseline\">\n    <n-button size=\"tiny\" secondary strong>\n      小小\n    </n-button>\n    <n-button size=\"small\" secondary strong>\n      小\n    </n-button>\n    <n-button size=\"medium\" secondary strong>\n      不小\n    </n-button>\n    <n-button size=\"large\" secondary strong>\n      不不小\n    </n-button>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/button/demos/zhCN/tag.demo.vue",
    "content": "<markdown>\n# 标签\n\n你可以把按钮渲染成不同的标签，比如 `<a />`。\n</markdown>\n\n<template>\n  <n-button\n    text\n    tag=\"a\"\n    href=\"https://anyway.fm/news.php\"\n    target=\"_blank\"\n    type=\"primary\"\n  >\n    安妮薇时报\n  </n-button>\n</template>\n"
  },
  {
    "path": "src/button/demos/zhCN/tertiary.demo.vue",
    "content": "<markdown>\n# 次次要按钮\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { CashOutline as CashIcon } from '@vicons/ionicons5'\n</script>\n\n<template>\n  <n-space>\n    <n-button tertiary>\n      Default\n    </n-button>\n    <n-button tertiary type=\"primary\">\n      Primary\n    </n-button>\n    <n-button tertiary type=\"info\">\n      Info\n    </n-button>\n    <n-button tertiary type=\"success\">\n      Success\n    </n-button>\n    <n-button tertiary type=\"warning\">\n      Warning\n    </n-button>\n    <n-button tertiary type=\"error\">\n      Error\n    </n-button>\n    <n-button tertiary round>\n      Default\n    </n-button>\n    <n-button tertiary round type=\"primary\">\n      Primary\n    </n-button>\n    <n-button tertiary round type=\"info\">\n      Info\n    </n-button>\n    <n-button tertiary round type=\"success\">\n      Success\n    </n-button>\n    <n-button tertiary round type=\"warning\">\n      Warning\n    </n-button>\n    <n-button tertiary round type=\"error\">\n      Error\n    </n-button>\n    <n-button tertiary circle>\n      <template #icon>\n        <n-icon><CashIcon /></n-icon>\n      </template>\n    </n-button>\n    <n-button tertiary circle type=\"primary\">\n      <template #icon>\n        <n-icon><CashIcon /></n-icon>\n      </template>\n    </n-button>\n    <n-button tertiary circle type=\"info\">\n      <template #icon>\n        <n-icon><CashIcon /></n-icon>\n      </template>\n    </n-button>\n    <n-button tertiary circle type=\"success\">\n      <n-icon><CashIcon /></n-icon>\n    </n-button>\n    <n-button tertiary circle type=\"warning\">\n      <template #icon>\n        <n-icon><CashIcon /></n-icon>\n      </template>\n    </n-button>\n    <n-button tertiary circle type=\"error\">\n      <template #icon>\n        <n-icon><CashIcon /></n-icon>\n      </template>\n    </n-button>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/button/demos/zhCN/text.demo.vue",
    "content": "<markdown>\n# 文本按钮\n\n长得就像文本。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { TrainOutline as TrainIcon } from '@vicons/ionicons5'\n</script>\n\n<template>\n  <n-button text>\n    <template #icon>\n      <n-icon>\n        <TrainIcon />\n      </n-icon>\n    </template>\n    那车头依然吐着烟\n  </n-button>\n</template>\n"
  },
  {
    "path": "src/button/index.ts",
    "content": "export {\n  buttonProps,\n  default as NButton,\n  XButton as NxButton\n} from './src/Button'\nexport type { ButtonProps, ButtonSlots } from './src/Button'\nexport type * from './src/public-types'\n"
  },
  {
    "path": "src/button/src/Button.tsx",
    "content": "import type {\n  ButtonHTMLAttributes,\n  CSSProperties,\n  ExtractPropTypes,\n  PropType,\n  SlotsType,\n  VNode,\n  VNodeChild\n} from 'vue'\nimport type { BaseWaveRef } from '../../_internal'\nimport type { ThemeProps } from '../../_mixins'\nimport type { ExtractPublicPropTypes, MaybeArray } from '../../_utils'\nimport type { ButtonTheme } from '../styles'\nimport type { ButtonSize, ButtonSpinProps, ButtonType } from './public-types'\nimport { changeColor } from 'seemly'\nimport { useMemo } from 'vooks'\nimport { computed, defineComponent, h, inject, ref, watchEffect } from 'vue'\nimport {\n  NBaseLoading,\n  NBaseWave,\n  NFadeInExpandTransition,\n  NIconSwitchTransition\n} from '../../_internal'\nimport { useConfig, useFormItem, useTheme, useThemeClass } from '../../_mixins'\nimport { useRtl } from '../../_mixins/use-rtl'\nimport {\n  call,\n  color2Class,\n  createKey,\n  isSlotEmpty,\n  resolveWrappedSlot,\n  warnOnce\n} from '../../_utils'\nimport { createHoverColor, createPressedColor } from '../../_utils/color/index'\nimport { isSafari } from '../../_utils/env/browser'\nimport { buttonGroupInjectionKey } from '../../button-group/src/context'\nimport { buttonLight } from '../styles'\nimport style from './styles/index.cssr'\n\nexport const buttonProps = {\n  ...(useTheme.props as ThemeProps<ButtonTheme>),\n  color: String,\n  textColor: String,\n  text: Boolean,\n  block: Boolean,\n  loading: Boolean,\n  disabled: Boolean,\n  circle: Boolean,\n  size: String as PropType<ButtonSize>,\n  ghost: Boolean,\n  round: Boolean,\n  secondary: Boolean,\n  tertiary: Boolean,\n  quaternary: Boolean,\n  strong: Boolean,\n  focusable: {\n    type: Boolean,\n    default: true\n  },\n  keyboard: {\n    type: Boolean,\n    default: true\n  },\n  tag: {\n    type: String as PropType<keyof HTMLElementTagNameMap>,\n    default: 'button'\n  },\n  type: {\n    type: String as PropType<ButtonType>,\n    default: 'default'\n  },\n  dashed: Boolean,\n  renderIcon: Function as PropType<() => VNodeChild>,\n  iconPlacement: {\n    type: String as PropType<'left' | 'right'>,\n    default: 'left'\n  },\n  attrType: {\n    type: String as PropType<'button' | 'submit' | 'reset'>,\n    default: 'button'\n  },\n  bordered: {\n    type: Boolean,\n    default: true\n  },\n  onClick: [Function, Array] as PropType<MaybeArray<(e: MouseEvent) => void>>,\n  nativeFocusBehavior: {\n    type: Boolean,\n    default: !isSafari\n  },\n  spinProps: Object as PropType<ButtonSpinProps>\n} as const\n\nexport type ButtonProps = ExtractPublicPropTypes<typeof buttonProps>\n\nexport interface ButtonSlots {\n  default?: () => VNode[]\n  icon?: () => VNode[]\n}\n\nconst Button = defineComponent({\n  name: 'Button',\n  props: buttonProps,\n  slots: Object as SlotsType<ButtonSlots>,\n  setup(props) {\n    if (__DEV__) {\n      watchEffect(() => {\n        const { dashed, ghost, text, secondary, tertiary, quaternary } = props\n        if (\n          (dashed || ghost || text)\n          && (secondary || tertiary || quaternary)\n        ) {\n          warnOnce(\n            'button',\n            '`dashed`, `ghost` and `text` props can\\'t be used along with `secondary`, `tertiary` and `quaternary` props.'\n          )\n        }\n      })\n    }\n    const selfElRef = ref<HTMLElement | null>(null)\n    const waveElRef = ref<BaseWaveRef | null>(null)\n    const enterPressedRef = ref(false)\n    const showBorderRef = useMemo(() => {\n      return (\n        !props.quaternary\n        && !props.tertiary\n        && !props.secondary\n        && !props.text\n        && (!props.color || props.ghost || props.dashed)\n        && props.bordered\n      )\n    })\n    const NButtonGroup = inject(buttonGroupInjectionKey, {})\n    const {\n      inlineThemeDisabled,\n      mergedClsPrefixRef,\n      mergedRtlRef,\n      mergedComponentPropsRef\n    } = useConfig(props)\n    const { mergedSizeRef } = useFormItem(\n      {},\n      {\n        defaultSize: 'medium',\n        mergedSize: (NFormItem) => {\n          const { size } = props\n          if (size)\n            return size\n          const { size: buttonGroupSize } = NButtonGroup\n          if (buttonGroupSize)\n            return buttonGroupSize\n\n          const { mergedSize: formItemSize } = NFormItem || {}\n          if (formItemSize)\n            return formItemSize.value\n\n          const configSize = mergedComponentPropsRef?.value?.Button?.size\n          if (configSize)\n            return configSize\n\n          return 'medium'\n        }\n      }\n    )\n    const mergedFocusableRef = computed(() => {\n      return props.focusable && !props.disabled\n    })\n    const handleMousedown = (e: MouseEvent): void => {\n      if (!mergedFocusableRef.value) {\n        e.preventDefault()\n      }\n      if (props.nativeFocusBehavior) {\n        return\n      }\n      e.preventDefault()\n      // normally this won't be called if disabled (when tag is button)\n      // if not, we try to make it behave like a button\n      if (props.disabled) {\n        return\n      }\n      if (mergedFocusableRef.value) {\n        selfElRef.value?.focus({ preventScroll: true })\n      }\n    }\n    const handleClick = (e: MouseEvent): void => {\n      if (!props.disabled && !props.loading) {\n        const { onClick } = props\n        if (onClick)\n          call(onClick, e)\n        if (!props.text) {\n          waveElRef.value?.play()\n        }\n      }\n    }\n    const handleKeyup = (e: KeyboardEvent): void => {\n      switch (e.key) {\n        case 'Enter':\n          if (!props.keyboard) {\n            return\n          }\n          enterPressedRef.value = false\n      }\n    }\n    const handleKeydown = (e: KeyboardEvent): void => {\n      switch (e.key) {\n        case 'Enter':\n          if (!props.keyboard || props.loading) {\n            e.preventDefault()\n            return\n          }\n          enterPressedRef.value = true\n      }\n    }\n    const handleBlur = (): void => {\n      enterPressedRef.value = false\n    }\n    const themeRef = useTheme(\n      'Button',\n      '-button',\n      style,\n      buttonLight,\n      props,\n      mergedClsPrefixRef\n    )\n    const rtlEnabledRef = useRtl('Button', mergedRtlRef, mergedClsPrefixRef)\n    const cssVarsRef = computed(() => {\n      const theme = themeRef.value\n      const {\n        common: { cubicBezierEaseInOut, cubicBezierEaseOut },\n        self\n      } = theme\n      const { rippleDuration, opacityDisabled, fontWeight, fontWeightStrong }\n        = self\n      const size = mergedSizeRef.value\n      const {\n        dashed,\n        type,\n        ghost,\n        text,\n        color,\n        round,\n        circle,\n        textColor,\n        secondary,\n        tertiary,\n        quaternary,\n        strong\n      } = props\n      // font\n      const fontProps = {\n        '--n-font-weight': strong ? fontWeightStrong : fontWeight\n      }\n      // color\n      let colorProps = {\n        '--n-color': 'initial',\n        '--n-color-hover': 'initial',\n        '--n-color-pressed': 'initial',\n        '--n-color-focus': 'initial',\n        '--n-color-disabled': 'initial',\n        '--n-ripple-color': 'initial',\n        '--n-text-color': 'initial',\n        '--n-text-color-hover': 'initial',\n        '--n-text-color-pressed': 'initial',\n        '--n-text-color-focus': 'initial',\n        '--n-text-color-disabled': 'initial'\n      }\n      const typeIsTertiary = type === 'tertiary'\n      const typeIsDefault = type === 'default'\n      const mergedType = typeIsTertiary ? 'default' : type\n      if (text) {\n        const propTextColor = textColor || color\n        const mergedTextColor\n          = propTextColor || self[createKey('textColorText', mergedType)]\n        colorProps = {\n          '--n-color': '#0000',\n          '--n-color-hover': '#0000',\n          '--n-color-pressed': '#0000',\n          '--n-color-focus': '#0000',\n          '--n-color-disabled': '#0000',\n          '--n-ripple-color': '#0000',\n          '--n-text-color': mergedTextColor,\n          '--n-text-color-hover': propTextColor\n            ? createHoverColor(propTextColor)\n            : self[createKey('textColorTextHover', mergedType)],\n          '--n-text-color-pressed': propTextColor\n            ? createPressedColor(propTextColor)\n            : self[createKey('textColorTextPressed', mergedType)],\n          '--n-text-color-focus': propTextColor\n            ? createHoverColor(propTextColor)\n            : self[createKey('textColorTextHover', mergedType)],\n          '--n-text-color-disabled':\n            propTextColor\n            || self[createKey('textColorTextDisabled', mergedType)]\n        }\n      }\n      else if (ghost || dashed) {\n        const mergedTextColor = textColor || color\n        colorProps = {\n          '--n-color': '#0000',\n          '--n-color-hover': '#0000',\n          '--n-color-pressed': '#0000',\n          '--n-color-focus': '#0000',\n          '--n-color-disabled': '#0000',\n          '--n-ripple-color':\n            color || self[createKey('rippleColor', mergedType)],\n          '--n-text-color':\n            mergedTextColor || self[createKey('textColorGhost', mergedType)],\n          '--n-text-color-hover': mergedTextColor\n            ? createHoverColor(mergedTextColor)\n            : self[createKey('textColorGhostHover', mergedType)],\n          '--n-text-color-pressed': mergedTextColor\n            ? createPressedColor(mergedTextColor)\n            : self[createKey('textColorGhostPressed', mergedType)],\n          '--n-text-color-focus': mergedTextColor\n            ? createHoverColor(mergedTextColor)\n            : self[createKey('textColorGhostHover', mergedType)],\n          '--n-text-color-disabled':\n            mergedTextColor\n            || self[createKey('textColorGhostDisabled', mergedType)]\n        }\n      }\n      else if (secondary) {\n        const typeTextColor = typeIsDefault\n          ? self.textColor\n          : typeIsTertiary\n            ? self.textColorTertiary\n            : self[createKey('color', mergedType)]\n        const mergedTextColor = color || typeTextColor\n        const isColoredType = type !== 'default' && type !== 'tertiary'\n        colorProps = {\n          '--n-color': isColoredType\n            ? changeColor(mergedTextColor, {\n                alpha: Number(self.colorOpacitySecondary)\n              })\n            : self.colorSecondary,\n          '--n-color-hover': isColoredType\n            ? changeColor(mergedTextColor, {\n                alpha: Number(self.colorOpacitySecondaryHover)\n              })\n            : self.colorSecondaryHover,\n          '--n-color-pressed': isColoredType\n            ? changeColor(mergedTextColor, {\n                alpha: Number(self.colorOpacitySecondaryPressed)\n              })\n            : self.colorSecondaryPressed,\n          '--n-color-focus': isColoredType\n            ? changeColor(mergedTextColor, {\n                alpha: Number(self.colorOpacitySecondaryHover)\n              })\n            : self.colorSecondaryHover,\n          '--n-color-disabled': self.colorSecondary,\n          '--n-ripple-color': '#0000',\n          '--n-text-color': mergedTextColor,\n          '--n-text-color-hover': mergedTextColor,\n          '--n-text-color-pressed': mergedTextColor,\n          '--n-text-color-focus': mergedTextColor,\n          '--n-text-color-disabled': mergedTextColor\n        }\n      }\n      else if (tertiary || quaternary) {\n        const typeColor = typeIsDefault\n          ? self.textColor\n          : typeIsTertiary\n            ? self.textColorTertiary\n            : self[createKey('color', mergedType)]\n        const mergedColor = color || typeColor\n        if (tertiary) {\n          colorProps['--n-color'] = self.colorTertiary\n          colorProps['--n-color-hover'] = self.colorTertiaryHover\n          colorProps['--n-color-pressed'] = self.colorTertiaryPressed\n          colorProps['--n-color-focus'] = self.colorSecondaryHover\n          colorProps['--n-color-disabled'] = self.colorTertiary\n        }\n        else {\n          colorProps['--n-color'] = self.colorQuaternary\n          colorProps['--n-color-hover'] = self.colorQuaternaryHover\n          colorProps['--n-color-pressed'] = self.colorQuaternaryPressed\n          colorProps['--n-color-focus'] = self.colorQuaternaryHover\n          colorProps['--n-color-disabled'] = self.colorQuaternary\n        }\n        colorProps['--n-ripple-color'] = '#0000'\n        colorProps['--n-text-color'] = mergedColor\n        colorProps['--n-text-color-hover'] = mergedColor\n        colorProps['--n-text-color-pressed'] = mergedColor\n        colorProps['--n-text-color-focus'] = mergedColor\n        colorProps['--n-text-color-disabled'] = mergedColor\n      }\n      else {\n        colorProps = {\n          '--n-color': color || self[createKey('color', mergedType)],\n          '--n-color-hover': color\n            ? createHoverColor(color)\n            : self[createKey('colorHover', mergedType)],\n          '--n-color-pressed': color\n            ? createPressedColor(color)\n            : self[createKey('colorPressed', mergedType)],\n          '--n-color-focus': color\n            ? createHoverColor(color)\n            : self[createKey('colorFocus', mergedType)],\n          '--n-color-disabled':\n            color || self[createKey('colorDisabled', mergedType)],\n          '--n-ripple-color':\n            color || self[createKey('rippleColor', mergedType)],\n          '--n-text-color':\n            textColor\n            || (color\n              ? self.textColorPrimary\n              : typeIsTertiary\n                ? self.textColorTertiary\n                : self[createKey('textColor', mergedType)]),\n          '--n-text-color-hover':\n            textColor\n            || (color\n              ? self.textColorHoverPrimary\n              : self[createKey('textColorHover', mergedType)]),\n          '--n-text-color-pressed':\n            textColor\n            || (color\n              ? self.textColorPressedPrimary\n              : self[createKey('textColorPressed', mergedType)]),\n          '--n-text-color-focus':\n            textColor\n            || (color\n              ? self.textColorFocusPrimary\n              : self[createKey('textColorFocus', mergedType)]),\n          '--n-text-color-disabled':\n            textColor\n            || (color\n              ? self.textColorDisabledPrimary\n              : self[createKey('textColorDisabled', mergedType)])\n        }\n      }\n      // border\n      let borderProps = {\n        '--n-border': 'initial',\n        '--n-border-hover': 'initial',\n        '--n-border-pressed': 'initial',\n        '--n-border-focus': 'initial',\n        '--n-border-disabled': 'initial'\n      }\n      if (text) {\n        borderProps = {\n          '--n-border': 'none',\n          '--n-border-hover': 'none',\n          '--n-border-pressed': 'none',\n          '--n-border-focus': 'none',\n          '--n-border-disabled': 'none'\n        }\n      }\n      else {\n        borderProps = {\n          '--n-border': self[createKey('border', mergedType)],\n          '--n-border-hover': self[createKey('borderHover', mergedType)],\n          '--n-border-pressed': self[createKey('borderPressed', mergedType)],\n          '--n-border-focus': self[createKey('borderFocus', mergedType)],\n          '--n-border-disabled': self[createKey('borderDisabled', mergedType)]\n        }\n      }\n      // size\n      const {\n        [createKey('height', size)]: height,\n        [createKey('fontSize', size)]: fontSize,\n        [createKey('padding', size)]: padding,\n        [createKey('paddingRound', size)]: paddingRound,\n        [createKey('iconSize', size)]: iconSize,\n        [createKey('borderRadius', size)]: borderRadius,\n        [createKey('iconMargin', size)]: iconMargin,\n        waveOpacity\n      } = self\n      const sizeProps = {\n        '--n-width': circle && !text ? height : 'initial',\n        '--n-height': text ? 'initial' : height,\n        '--n-font-size': fontSize,\n        '--n-padding': circle\n          ? 'initial'\n          : text\n            ? 'initial'\n            : round\n              ? paddingRound\n              : padding,\n        '--n-icon-size': iconSize,\n        '--n-icon-margin': iconMargin,\n        '--n-border-radius': text\n          ? 'initial'\n          : circle || round\n            ? height\n            : borderRadius\n      }\n      return {\n        '--n-bezier': cubicBezierEaseInOut,\n        '--n-bezier-ease-out': cubicBezierEaseOut,\n        '--n-ripple-duration': rippleDuration,\n        '--n-opacity-disabled': opacityDisabled,\n        '--n-wave-opacity': waveOpacity,\n        ...fontProps,\n        ...colorProps,\n        ...borderProps,\n        ...sizeProps\n      }\n    })\n    const themeClassHandle = inlineThemeDisabled\n      ? useThemeClass(\n          'button',\n          computed(() => {\n            let hash = ''\n            const {\n              dashed,\n              type,\n              ghost,\n              text,\n              color,\n              round,\n              circle,\n              textColor,\n              secondary,\n              tertiary,\n              quaternary,\n              strong\n            } = props\n            if (dashed)\n              hash += 'a'\n            if (ghost)\n              hash += 'b'\n            if (text)\n              hash += 'c'\n            if (round)\n              hash += 'd'\n            if (circle)\n              hash += 'e'\n            if (secondary)\n              hash += 'f'\n            if (tertiary)\n              hash += 'g'\n            if (quaternary)\n              hash += 'h'\n            if (strong)\n              hash += 'i'\n            if (color)\n              hash += `j${color2Class(color)}`\n            if (textColor)\n              hash += `k${color2Class(textColor)}`\n            const { value: size } = mergedSizeRef\n            hash += `l${size[0]}`\n            hash += `m${type[0]}`\n            return hash\n          }),\n          cssVarsRef,\n          props\n        )\n      : undefined\n\n    return {\n      selfElRef,\n      waveElRef,\n      mergedClsPrefix: mergedClsPrefixRef,\n      mergedFocusable: mergedFocusableRef,\n      mergedSize: mergedSizeRef,\n      showBorder: showBorderRef,\n      enterPressed: enterPressedRef,\n      rtlEnabled: rtlEnabledRef,\n      handleMousedown,\n      handleKeydown,\n      handleBlur,\n      handleKeyup,\n      handleClick,\n      customColorCssVars: computed(() => {\n        const { color } = props\n        if (!color)\n          return null\n        const hoverColor = createHoverColor(color)\n        return {\n          '--n-border-color': color,\n          '--n-border-color-hover': hoverColor,\n          '--n-border-color-pressed': createPressedColor(color),\n          '--n-border-color-focus': hoverColor,\n          '--n-border-color-disabled': color\n        }\n      }),\n      cssVars: inlineThemeDisabled ? undefined : cssVarsRef,\n      themeClass: themeClassHandle?.themeClass,\n      onRender: themeClassHandle?.onRender\n    }\n  },\n  render() {\n    const { mergedClsPrefix, tag: Component, onRender } = this\n    onRender?.()\n    const children = resolveWrappedSlot(\n      this.$slots.default,\n      children =>\n        children && (\n          <span class={`${mergedClsPrefix}-button__content`}>{children}</span>\n        )\n    )\n    return (\n      <Component\n        ref=\"selfElRef\"\n        class={[\n          this.themeClass,\n          `${mergedClsPrefix}-button`,\n          `${mergedClsPrefix}-button--${this.type}-type`,\n          `${mergedClsPrefix}-button--${this.mergedSize}-type`,\n          this.rtlEnabled && `${mergedClsPrefix}-button--rtl`,\n          this.disabled && `${mergedClsPrefix}-button--disabled`,\n          this.block && `${mergedClsPrefix}-button--block`,\n          this.enterPressed && `${mergedClsPrefix}-button--pressed`,\n          !this.text && this.dashed && `${mergedClsPrefix}-button--dashed`,\n          this.color && `${mergedClsPrefix}-button--color`,\n          this.secondary && `${mergedClsPrefix}-button--secondary`,\n          this.loading && `${mergedClsPrefix}-button--loading`,\n          this.ghost && `${mergedClsPrefix}-button--ghost` // required for button group border collapse\n        ]}\n        tabindex={this.mergedFocusable ? 0 : -1}\n        type={this.attrType}\n        style={this.cssVars as CSSProperties}\n        disabled={this.disabled}\n        onClick={this.handleClick}\n        onBlur={this.handleBlur}\n        onMousedown={this.handleMousedown}\n        onKeyup={this.handleKeyup}\n        onKeydown={this.handleKeydown}\n      >\n        {this.iconPlacement === 'right' && children}\n        <NFadeInExpandTransition width>\n          {{\n            default: () =>\n              resolveWrappedSlot(\n                this.$slots.icon,\n                children =>\n                  (this.loading || this.renderIcon || children) && (\n                    <span\n                      class={`${mergedClsPrefix}-button__icon`}\n                      style={{\n                        margin: isSlotEmpty(this.$slots.default) ? '0' : ''\n                      }}\n                    >\n                      <NIconSwitchTransition>\n                        {{\n                          default: () =>\n                            this.loading ? (\n                              <NBaseLoading\n                                clsPrefix={mergedClsPrefix}\n                                key=\"loading\"\n                                class={`${mergedClsPrefix}-icon-slot`}\n                                strokeWidth={20}\n                                {...this.spinProps}\n                              />\n                            ) : (\n                              <div\n                                key=\"icon\"\n                                class={`${mergedClsPrefix}-icon-slot`}\n                                role=\"none\"\n                              >\n                                {this.renderIcon ? this.renderIcon() : children}\n                              </div>\n                            )\n                        }}\n                      </NIconSwitchTransition>\n                    </span>\n                  )\n              )\n          }}\n        </NFadeInExpandTransition>\n        {this.iconPlacement === 'left' && children}\n        {!this.text ? (\n          <NBaseWave ref=\"waveElRef\" clsPrefix={mergedClsPrefix} />\n        ) : null}\n        {this.showBorder ? (\n          <div\n            aria-hidden\n            class={`${mergedClsPrefix}-button__border`}\n            style={this.customColorCssVars as CSSProperties}\n          />\n        ) : null}\n        {this.showBorder ? (\n          <div\n            aria-hidden\n            class={`${mergedClsPrefix}-button__state-border`}\n            style={this.customColorCssVars as CSSProperties}\n          />\n        ) : null}\n      </Component>\n    )\n  }\n})\n\ntype InternalButtonProps = ExtractPropTypes<typeof buttonProps>\ntype NativeButtonProps = Omit<ButtonHTMLAttributes, keyof InternalButtonProps>\ntype MergedProps = Partial<InternalButtonProps & NativeButtonProps>\n\nexport default Button\n\n// XButton is for tsx type checking\n// It's not compatible with render function `h`\n// Currently we don't expose it as public\n// If there's any issue about this, we may expose it\n// Since most people use template, the type checking phase doesn't work as tsx\nexport const XButton: new () => { $props: MergedProps } = Button as any\n\n// Also, we may make XButton a generic type which support `tag` prop\n// but currently vue doesn't export IntrinsicElementAttributes from runtime-dom\n// so we can't easily make an attr map by hand\n// just leave it for later\n"
  },
  {
    "path": "src/button/src/public-types.ts",
    "content": "import type { SharedSpinProps } from '../../_internal'\n\nexport type ButtonSize = 'tiny' | 'small' | 'medium' | 'large'\nexport type ButtonSpinProps = SharedSpinProps\nexport type ButtonType\n  = | 'default'\n    | 'tertiary'\n    | 'primary'\n    | 'info'\n    | 'success'\n    | 'warning'\n    | 'error'\n"
  },
  {
    "path": "src/button/src/styles/index.cssr.ts",
    "content": "import { fadeInWidthExpandTransition } from '../../../_styles/transitions/fade-in-width-expand.cssr'\nimport { iconSwitchTransition } from '../../../_styles/transitions/icon-switch.cssr'\nimport { isBrowser } from '../../../_utils'\nimport { c, cB, cE, cM, cNotM } from '../../../_utils/cssr'\n\n// vars:\n// --n-bezier\n// --n-bezier-ease-out\n// --n-ripple-duration\n// --n-opacity-disabled\n// --n-text-color\n// --n-text-color-hover\n// --n-text-color-pressed\n// --n-text-color-focus\n// --n-text-color-disabled\n// --n-color\n// --n-color-hover\n// --n-color-pressed\n// --n-color-focus\n// --n-color-disabled\n// --n-border\n// --n-border-hover\n// --n-border-pressed\n// --n-border-focus\n// --n-border-disabled\n// --n-ripple-color\n// --n-border-radius\n// --n-height\n// --n-width\n// --n-font-size\n// --n-padding\n// --n-icon-size\n// --n-icon-margin\n// --n-wave-opacity\n// --n-font-weight\n//\n// private-vars:\n// --n-border-color-xxx, used for custom color\nexport default c([\n  cB('button', `\n    margin: 0;\n    font-weight: var(--n-font-weight);\n    line-height: 1;\n    font-family: inherit;\n    padding: var(--n-padding);\n    height: var(--n-height);\n    font-size: var(--n-font-size);\n    border-radius: var(--n-border-radius);\n    color: var(--n-text-color);\n    background-color: var(--n-color);\n    width: var(--n-width);\n    white-space: nowrap;\n    outline: none;\n    position: relative;\n    z-index: auto;\n    border: none;\n    display: inline-flex;\n    flex-wrap: nowrap;\n    flex-shrink: 0;\n    align-items: center;\n    justify-content: center;\n    user-select: none;\n    -webkit-user-select: none;\n    text-align: center;\n    cursor: pointer;\n    text-decoration: none;\n    transition:\n      color .3s var(--n-bezier),\n      background-color .3s var(--n-bezier),\n      opacity .3s var(--n-bezier),\n      border-color .3s var(--n-bezier);\n  `, [\n    cM('color', [\n      cE('border', {\n        borderColor: 'var(--n-border-color)'\n      }),\n      cM('disabled', [\n        cE('border', {\n          borderColor: 'var(--n-border-color-disabled)'\n        })\n      ]),\n      cNotM('disabled', [\n        c('&:focus', [\n          cE('state-border', {\n            borderColor: 'var(--n-border-color-focus)'\n          })\n        ]),\n        c('&:hover', [\n          cE('state-border', {\n            borderColor: 'var(--n-border-color-hover)'\n          })\n        ]),\n        c('&:active', [\n          cE('state-border', {\n            borderColor: 'var(--n-border-color-pressed)'\n          })\n        ]),\n        cM('pressed', [\n          cE('state-border', {\n            borderColor: 'var(--n-border-color-pressed)'\n          })\n        ])\n      ])\n    ]),\n    cM('disabled', {\n      backgroundColor: 'var(--n-color-disabled)',\n      color: 'var(--n-text-color-disabled)'\n    }, [\n      cE('border', {\n        border: 'var(--n-border-disabled)'\n      })\n    ]),\n    cNotM('disabled', [\n      c('&:focus', {\n        backgroundColor: 'var(--n-color-focus)',\n        color: 'var(--n-text-color-focus)'\n      }, [\n        cE('state-border', {\n          border: 'var(--n-border-focus)'\n        })\n      ]),\n      c('&:hover', {\n        backgroundColor: 'var(--n-color-hover)',\n        color: 'var(--n-text-color-hover)'\n      }, [\n        cE('state-border', {\n          border: 'var(--n-border-hover)'\n        })\n      ]),\n      c('&:active', {\n        backgroundColor: 'var(--n-color-pressed)',\n        color: 'var(--n-text-color-pressed)'\n      }, [\n        cE('state-border', {\n          border: 'var(--n-border-pressed)'\n        })\n      ]),\n      cM('pressed', {\n        backgroundColor: 'var(--n-color-pressed)',\n        color: 'var(--n-text-color-pressed)'\n      }, [\n        cE('state-border', {\n          border: 'var(--n-border-pressed)'\n        })\n      ])\n    ]),\n    cM('loading', 'cursor: wait;'),\n    cB('base-wave', `\n      pointer-events: none;\n      top: 0;\n      right: 0;\n      bottom: 0;\n      left: 0;\n      animation-iteration-count: 1;\n      animation-duration: var(--n-ripple-duration);\n      animation-timing-function: var(--n-bezier-ease-out), var(--n-bezier-ease-out);\n    `, [\n      cM('active', {\n        zIndex: 1,\n        animationName: 'button-wave-spread, button-wave-opacity'\n      })\n    ]),\n    (isBrowser && 'MozBoxSizing' in document.createElement('div').style)\n      ? c('&::moz-focus-inner', {\n          border: 0\n        })\n      : null,\n    cE('border, state-border', `\n      position: absolute;\n      left: 0;\n      top: 0;\n      right: 0;\n      bottom: 0;\n      border-radius: inherit;\n      transition: border-color .3s var(--n-bezier);\n      pointer-events: none;\n    `),\n    cE('border', `\n      border: var(--n-border);\n    `),\n    cE('state-border', `\n      border: var(--n-border);\n      border-color: #0000;\n      z-index: 1;\n    `),\n    cE('icon', `\n      margin: var(--n-icon-margin);\n      margin-left: 0;\n      height: var(--n-icon-size);\n      width: var(--n-icon-size);\n      max-width: var(--n-icon-size);\n      font-size: var(--n-icon-size);\n      position: relative;\n      flex-shrink: 0;\n    `, [\n      cB('icon-slot', `\n        height: var(--n-icon-size);\n        width: var(--n-icon-size);\n        position: absolute;\n        left: 0;\n        top: 50%;\n        transform: translateY(-50%);\n        display: flex;\n        align-items: center;\n        justify-content: center;\n      `, [\n        iconSwitchTransition({\n          top: '50%',\n          originalTransform: 'translateY(-50%)'\n        })\n      ]),\n      fadeInWidthExpandTransition()\n    ]),\n    cE('content', `\n      display: flex;\n      align-items: center;\n      flex-wrap: nowrap;\n      min-width: 0;\n    `, [\n      c('~', [\n        cE('icon', {\n          margin: 'var(--n-icon-margin)',\n          marginRight: 0\n        })\n      ])\n    ]),\n    cM('block', `\n      display: flex;\n      width: 100%;\n    `),\n    cM('dashed', [\n      cE('border, state-border', {\n        borderStyle: 'dashed !important'\n      })\n    ]),\n    cM('disabled', {\n      cursor: 'not-allowed',\n      opacity: 'var(--n-opacity-disabled)'\n    })\n  ]),\n  c('@keyframes button-wave-spread', {\n    from: {\n      boxShadow: '0 0 0.5px 0 var(--n-ripple-color)'\n    },\n    to: {\n      // don't use exact 5px since chrome will display the animation with glitches\n      boxShadow: '0 0 0.5px 4.5px var(--n-ripple-color)'\n    }\n  }),\n  c('@keyframes button-wave-opacity', {\n    from: {\n      opacity: 'var(--n-wave-opacity)'\n    },\n    to: {\n      opacity: 0\n    }\n  })\n])\n"
  },
  {
    "path": "src/button/src/styles/rtl.cssr.ts",
    "content": "import { c, cB, cE, cM } from '../../../_utils/cssr'\n\nexport default cB('button', [\n  cM('rtl', `\n    direction: rtl;\n  `, [\n    cE('icon', {\n      margin: 'var(--n-icon-margin)',\n      marginRight: 0\n    }),\n    cE('content', [\n      c('~', [\n        cE('icon', {\n          margin: 'var(--n-icon-margin)',\n          marginLeft: 0\n        })\n      ])\n    ])\n  ])\n])\n"
  },
  {
    "path": "src/button/styles/_common.ts",
    "content": "export default {\n  paddingTiny: '0 6px',\n  paddingSmall: '0 10px',\n  paddingMedium: '0 14px',\n  paddingLarge: '0 18px',\n  paddingRoundTiny: '0 10px',\n  paddingRoundSmall: '0 14px',\n  paddingRoundMedium: '0 18px',\n  paddingRoundLarge: '0 22px',\n  iconMarginTiny: '6px',\n  iconMarginSmall: '6px',\n  iconMarginMedium: '6px',\n  iconMarginLarge: '6px',\n  iconSizeTiny: '14px',\n  iconSizeSmall: '18px',\n  iconSizeMedium: '18px',\n  iconSizeLarge: '20px',\n  rippleDuration: '.6s'\n}\n"
  },
  {
    "path": "src/button/styles/dark.ts",
    "content": "import type { ButtonTheme } from './light'\nimport { commonDark } from '../../_styles/common'\nimport { self } from './light'\n\nconst buttonDark: ButtonTheme = {\n  name: 'Button',\n  common: commonDark,\n  self(vars) {\n    const commonSelf = self(vars)\n    commonSelf.waveOpacity = '0.8'\n    commonSelf.colorOpacitySecondary = '0.16'\n    commonSelf.colorOpacitySecondaryHover = '0.2'\n    commonSelf.colorOpacitySecondaryPressed = '0.12'\n    return commonSelf\n  }\n}\n\nexport default buttonDark\n"
  },
  {
    "path": "src/button/styles/index.ts",
    "content": "export { default as buttonDark } from './dark'\nexport { default as buttonLight } from './light'\nexport type { ButtonTheme, ButtonThemeVars } from './light'\nexport { buttonRtl } from './rtl'\n"
  },
  {
    "path": "src/button/styles/light.ts",
    "content": "import type { Theme } from '../../_mixins'\nimport type { ThemeCommonVars } from '../../_styles/common'\nimport { commonLight } from '../../_styles/common'\nimport commonVariables from './_common'\n\nexport function self(vars: ThemeCommonVars) {\n  const {\n    heightTiny,\n    heightSmall,\n    heightMedium,\n    heightLarge,\n    borderRadius,\n    fontSizeTiny,\n    fontSizeSmall,\n    fontSizeMedium,\n    fontSizeLarge,\n    opacityDisabled,\n    textColor2,\n    textColor3,\n    primaryColorHover,\n    primaryColorPressed,\n    borderColor,\n    primaryColor,\n    baseColor,\n    infoColor,\n    infoColorHover,\n    infoColorPressed,\n    successColor,\n    successColorHover,\n    successColorPressed,\n    warningColor,\n    warningColorHover,\n    warningColorPressed,\n    errorColor,\n    errorColorHover,\n    errorColorPressed,\n    fontWeight,\n    buttonColor2,\n    buttonColor2Hover,\n    buttonColor2Pressed,\n    fontWeightStrong\n  } = vars\n  return {\n    ...commonVariables,\n    heightTiny,\n    heightSmall,\n    heightMedium,\n    heightLarge,\n    borderRadiusTiny: borderRadius,\n    borderRadiusSmall: borderRadius,\n    borderRadiusMedium: borderRadius,\n    borderRadiusLarge: borderRadius,\n    fontSizeTiny,\n    fontSizeSmall,\n    fontSizeMedium,\n    fontSizeLarge,\n    opacityDisabled,\n    // secondary\n    colorOpacitySecondary: '0.16',\n    colorOpacitySecondaryHover: '0.22',\n    colorOpacitySecondaryPressed: '0.28',\n    colorSecondary: buttonColor2,\n    colorSecondaryHover: buttonColor2Hover,\n    colorSecondaryPressed: buttonColor2Pressed,\n    // tertiary\n    colorTertiary: buttonColor2,\n    colorTertiaryHover: buttonColor2Hover,\n    colorTertiaryPressed: buttonColor2Pressed,\n    // quaternary\n    colorQuaternary: '#0000',\n    colorQuaternaryHover: buttonColor2Hover,\n    colorQuaternaryPressed: buttonColor2Pressed,\n    // default type\n    color: '#0000',\n    colorHover: '#0000',\n    colorPressed: '#0000',\n    colorFocus: '#0000',\n    colorDisabled: '#0000',\n    textColor: textColor2,\n    textColorTertiary: textColor3, // tertiary\n    textColorHover: primaryColorHover,\n    textColorPressed: primaryColorPressed,\n    textColorFocus: primaryColorHover,\n    textColorDisabled: textColor2,\n    textColorText: textColor2,\n    textColorTextHover: primaryColorHover,\n    textColorTextPressed: primaryColorPressed,\n    textColorTextFocus: primaryColorHover,\n    textColorTextDisabled: textColor2,\n    textColorGhost: textColor2,\n    textColorGhostHover: primaryColorHover,\n    textColorGhostPressed: primaryColorPressed,\n    textColorGhostFocus: primaryColorHover,\n    textColorGhostDisabled: textColor2,\n    border: `1px solid ${borderColor}`,\n    borderHover: `1px solid ${primaryColorHover}`,\n    borderPressed: `1px solid ${primaryColorPressed}`,\n    borderFocus: `1px solid ${primaryColorHover}`,\n    borderDisabled: `1px solid ${borderColor}`,\n    rippleColor: primaryColor,\n    // primary\n    colorPrimary: primaryColor,\n    colorHoverPrimary: primaryColorHover,\n    colorPressedPrimary: primaryColorPressed,\n    colorFocusPrimary: primaryColorHover,\n    colorDisabledPrimary: primaryColor,\n    textColorPrimary: baseColor,\n    textColorHoverPrimary: baseColor,\n    textColorPressedPrimary: baseColor,\n    textColorFocusPrimary: baseColor,\n    textColorDisabledPrimary: baseColor,\n    textColorTextPrimary: primaryColor,\n    textColorTextHoverPrimary: primaryColorHover,\n    textColorTextPressedPrimary: primaryColorPressed,\n    textColorTextFocusPrimary: primaryColorHover,\n    textColorTextDisabledPrimary: textColor2,\n    textColorGhostPrimary: primaryColor,\n    textColorGhostHoverPrimary: primaryColorHover,\n    textColorGhostPressedPrimary: primaryColorPressed,\n    textColorGhostFocusPrimary: primaryColorHover,\n    textColorGhostDisabledPrimary: primaryColor,\n    borderPrimary: `1px solid ${primaryColor}`,\n    borderHoverPrimary: `1px solid ${primaryColorHover}`,\n    borderPressedPrimary: `1px solid ${primaryColorPressed}`,\n    borderFocusPrimary: `1px solid ${primaryColorHover}`,\n    borderDisabledPrimary: `1px solid ${primaryColor}`,\n    rippleColorPrimary: primaryColor,\n    // info\n    colorInfo: infoColor,\n    colorHoverInfo: infoColorHover,\n    colorPressedInfo: infoColorPressed,\n    colorFocusInfo: infoColorHover,\n    colorDisabledInfo: infoColor,\n    textColorInfo: baseColor,\n    textColorHoverInfo: baseColor,\n    textColorPressedInfo: baseColor,\n    textColorFocusInfo: baseColor,\n    textColorDisabledInfo: baseColor,\n    textColorTextInfo: infoColor,\n    textColorTextHoverInfo: infoColorHover,\n    textColorTextPressedInfo: infoColorPressed,\n    textColorTextFocusInfo: infoColorHover,\n    textColorTextDisabledInfo: textColor2,\n    textColorGhostInfo: infoColor,\n    textColorGhostHoverInfo: infoColorHover,\n    textColorGhostPressedInfo: infoColorPressed,\n    textColorGhostFocusInfo: infoColorHover,\n    textColorGhostDisabledInfo: infoColor,\n    borderInfo: `1px solid ${infoColor}`,\n    borderHoverInfo: `1px solid ${infoColorHover}`,\n    borderPressedInfo: `1px solid ${infoColorPressed}`,\n    borderFocusInfo: `1px solid ${infoColorHover}`,\n    borderDisabledInfo: `1px solid ${infoColor}`,\n    rippleColorInfo: infoColor,\n    // success\n    colorSuccess: successColor,\n    colorHoverSuccess: successColorHover,\n    colorPressedSuccess: successColorPressed,\n    colorFocusSuccess: successColorHover,\n    colorDisabledSuccess: successColor,\n    textColorSuccess: baseColor,\n    textColorHoverSuccess: baseColor,\n    textColorPressedSuccess: baseColor,\n    textColorFocusSuccess: baseColor,\n    textColorDisabledSuccess: baseColor,\n    textColorTextSuccess: successColor,\n    textColorTextHoverSuccess: successColorHover,\n    textColorTextPressedSuccess: successColorPressed,\n    textColorTextFocusSuccess: successColorHover,\n    textColorTextDisabledSuccess: textColor2,\n    textColorGhostSuccess: successColor,\n    textColorGhostHoverSuccess: successColorHover,\n    textColorGhostPressedSuccess: successColorPressed,\n    textColorGhostFocusSuccess: successColorHover,\n    textColorGhostDisabledSuccess: successColor,\n    borderSuccess: `1px solid ${successColor}`,\n    borderHoverSuccess: `1px solid ${successColorHover}`,\n    borderPressedSuccess: `1px solid ${successColorPressed}`,\n    borderFocusSuccess: `1px solid ${successColorHover}`,\n    borderDisabledSuccess: `1px solid ${successColor}`,\n    rippleColorSuccess: successColor,\n    // warning\n    colorWarning: warningColor,\n    colorHoverWarning: warningColorHover,\n    colorPressedWarning: warningColorPressed,\n    colorFocusWarning: warningColorHover,\n    colorDisabledWarning: warningColor,\n    textColorWarning: baseColor,\n    textColorHoverWarning: baseColor,\n    textColorPressedWarning: baseColor,\n    textColorFocusWarning: baseColor,\n    textColorDisabledWarning: baseColor,\n    textColorTextWarning: warningColor,\n    textColorTextHoverWarning: warningColorHover,\n    textColorTextPressedWarning: warningColorPressed,\n    textColorTextFocusWarning: warningColorHover,\n    textColorTextDisabledWarning: textColor2,\n    textColorGhostWarning: warningColor,\n    textColorGhostHoverWarning: warningColorHover,\n    textColorGhostPressedWarning: warningColorPressed,\n    textColorGhostFocusWarning: warningColorHover,\n    textColorGhostDisabledWarning: warningColor,\n    borderWarning: `1px solid ${warningColor}`,\n    borderHoverWarning: `1px solid ${warningColorHover}`,\n    borderPressedWarning: `1px solid ${warningColorPressed}`,\n    borderFocusWarning: `1px solid ${warningColorHover}`,\n    borderDisabledWarning: `1px solid ${warningColor}`,\n    rippleColorWarning: warningColor,\n    // error\n    colorError: errorColor,\n    colorHoverError: errorColorHover,\n    colorPressedError: errorColorPressed,\n    colorFocusError: errorColorHover,\n    colorDisabledError: errorColor,\n    textColorError: baseColor,\n    textColorHoverError: baseColor,\n    textColorPressedError: baseColor,\n    textColorFocusError: baseColor,\n    textColorDisabledError: baseColor,\n    textColorTextError: errorColor,\n    textColorTextHoverError: errorColorHover,\n    textColorTextPressedError: errorColorPressed,\n    textColorTextFocusError: errorColorHover,\n    textColorTextDisabledError: textColor2,\n    textColorGhostError: errorColor,\n    textColorGhostHoverError: errorColorHover,\n    textColorGhostPressedError: errorColorPressed,\n    textColorGhostFocusError: errorColorHover,\n    textColorGhostDisabledError: errorColor,\n    borderError: `1px solid ${errorColor}`,\n    borderHoverError: `1px solid ${errorColorHover}`,\n    borderPressedError: `1px solid ${errorColorPressed}`,\n    borderFocusError: `1px solid ${errorColorHover}`,\n    borderDisabledError: `1px solid ${errorColor}`,\n    rippleColorError: errorColor,\n    waveOpacity: '0.6',\n    fontWeight,\n    fontWeightStrong\n  }\n}\n\nexport type ButtonThemeVars = ReturnType<typeof self>\n\nconst buttonLight: Theme<'Button', ButtonThemeVars> = {\n  name: 'Button',\n  common: commonLight,\n  self\n}\n\nexport default buttonLight\nexport type ButtonTheme = typeof buttonLight\n"
  },
  {
    "path": "src/button/styles/rtl.ts",
    "content": "import type { RtlItem } from '../../config-provider/src/internal-interface'\nimport rtlStyle from '../src/styles/rtl.cssr'\n\nexport const buttonRtl: RtlItem = {\n  name: 'Button',\n  style: rtlStyle\n}\n"
  },
  {
    "path": "src/button/tests/Button.spec.tsx",
    "content": "import { CashOutline as CashIcon } from '@vicons/ionicons5'\nimport { mount } from '@vue/test-utils'\nimport { h } from 'vue'\nimport { NIcon } from '../../icon'\nimport { NButton, NxButton } from '../index'\n\ndescribe('n-button', () => {\n  it('should work with import on demand', () => {\n    mount(NButton)\n  })\n  it('clickable', async () => {\n    const onClick = vi.fn()\n    const inst = mount(NButton, {\n      props: {\n        onClick\n      }\n    })\n    await inst.trigger('click')\n    expect(onClick).toHaveBeenCalled()\n    inst.unmount()\n  })\n  it('keyboard', async () => {\n    const onClick = vi.fn()\n    const inst = mount(NButton, {\n      props: {\n        keyboard: false,\n        onClick\n      }\n    })\n    await inst.trigger('click')\n    expect(onClick).toHaveBeenCalledTimes(1)\n    await inst.trigger('keydown.space')\n    expect(onClick).toHaveBeenCalledTimes(1)\n    await inst.trigger('keydown.enter')\n    expect(onClick).toHaveBeenCalledTimes(1)\n    inst.unmount()\n  })\n  it('disabled', async () => {\n    const onClick = vi.fn()\n    const inst = mount(NButton, {\n      props: {\n        disabled: true,\n        onClick\n      }\n    })\n    await inst.trigger('click')\n    expect(onClick).not.toHaveBeenCalled()\n    inst.unmount()\n  })\n  it('passed native event & attr tsx type checking', () => {\n    ;(() => (\n      <div>\n        <NxButton onMousedown={() => {}} />\n        <NxButton formaction=\"\" />\n      </div>\n    ))()\n  })\n\n  it('should work with `attr-type` prop', () => {\n    ;(['button', 'submit', 'reset'] as const).forEach((type) => {\n      const wrapper = mount(NButton, { props: { attrType: type } })\n      expect(wrapper.find('button').attributes('type')).toContain(type)\n      wrapper.unmount()\n    })\n  })\n\n  it('should work with `block` prop', async () => {\n    const wrapper = mount(NButton)\n    expect(wrapper.find('.n-button').classes()).not.toContain('n-button--block')\n\n    await wrapper.setProps({ block: true })\n    expect(wrapper.find('.n-button').classes()).toContain('n-button--block')\n    wrapper.unmount()\n  })\n\n  it('should work with `type` prop', async () => {\n    ;(['primary', 'info', 'success', 'warning', 'error'] as const).forEach(\n      (type) => {\n        const wrapper = mount(NButton, { props: { type } })\n        expect(wrapper.find('button').classes()).toContain(\n          `n-button--${type}-type`\n        )\n        wrapper.unmount()\n      }\n    )\n  })\n\n  it('should work with `dashed` prop', async () => {\n    const wrapper = mount(NButton)\n\n    await wrapper.setProps({ dashed: true })\n    expect(wrapper.find('button').classes()).toContain('n-button--dashed')\n    wrapper.unmount()\n  })\n\n  it('should work with `bordered` prop', async () => {\n    const wrapper = mount(NButton)\n\n    await wrapper.setProps({ bordered: false })\n    expect(wrapper.find('.n-button__border').exists()).toBe(false)\n    wrapper.unmount()\n  })\n\n  it('should work with `size` prop', async () => {\n    ;(['tiny', 'small', 'medium', 'large'] as const).forEach((size) => {\n      const wrapper = mount(NButton, { props: { size } })\n      expect(wrapper.find('button').attributes('style')).toMatchSnapshot()\n      wrapper.unmount()\n    })\n  })\n\n  it('should work with `text` prop', () => {\n    const wrapper = mount(NButton, {\n      props: {\n        text: true\n      },\n      slots: {\n        default: () => 'test'\n      }\n    })\n    expect(wrapper.find('button').attributes('style')).toMatchSnapshot()\n    expect(wrapper.find('.n-button__content').element.textContent).toBe('test')\n    wrapper.unmount()\n  })\n\n  it('should work with `tag` prop', () => {\n    const wrapper = mount(NButton, {\n      props: {\n        text: true,\n        tag: 'a',\n        href: 'https://www.naiveui.com',\n        target: '_blank',\n        type: 'primary'\n      },\n      slots: {\n        default: () => 'test'\n      }\n    })\n\n    expect(wrapper.find('a').attributes('style')).toMatchSnapshot()\n    expect(wrapper.find('a').classes()).toContain('n-button--primary-type')\n    expect(wrapper.find('a').attributes('type')).toContain('button')\n    expect(wrapper.find('a').attributes('disabled')).toContain('false')\n    expect(wrapper.find('a').attributes('href')).toContain(\n      'https://www.naiveui.com'\n    )\n    expect(wrapper.find('a').attributes('target')).toContain('_blank')\n    expect(wrapper.find('.n-button__content').element.textContent).toBe('test')\n    wrapper.unmount()\n  })\n\n  it('should work with `icon` slot', async () => {\n    const wrapper = mount(NButton, {\n      slots: {\n        icon: () =>\n          h(NIcon, null, {\n            default: () => h(CashIcon)\n          }),\n        default: () => 'test'\n      }\n    })\n\n    expect(wrapper.find('span').classes('n-button__icon')).toBe(true)\n    expect(wrapper.find('div').classes('n-icon-slot')).toBe(true)\n    expect(wrapper.find('i').classes('n-icon')).toBe(true)\n    expect(wrapper.find('i').classes('n-icon')).toBe(true)\n    expect(wrapper.find('.n-button__content').element.textContent).toBe('test')\n    expect(wrapper.find('button').element.children[1].textContent).toBe('test')\n\n    await wrapper.setProps({ iconPlacement: 'right' })\n    expect(wrapper.find('button').element.children[0].textContent).toBe('test')\n    wrapper.unmount()\n  })\n\n  it('should work with `shape` ', async () => {\n    const wrapper = mount(NButton, {\n      props: {\n        circle: true\n      },\n      slots: {\n        icon: () =>\n          h(NIcon, null, {\n            default: () => h(CashIcon)\n          })\n      }\n    })\n    const circleStyle: string[] = [\n      '--n-width: 34px;',\n      '--n-padding: initial;',\n      '--n-border-radius: 34px;'\n    ]\n    let buttonStyle = wrapper.find('button').attributes('style')\n    expect(circleStyle.every(i => buttonStyle?.includes(i))).toBe(true)\n\n    await wrapper.setProps({ circle: false, round: true })\n    const roundStyle: string[] = [\n      '--n-width: initial;',\n      '--n-padding: 0 18px;',\n      '--n-border-radius: 34px;'\n    ]\n    buttonStyle = wrapper.find('button').attributes('style')\n    expect(roundStyle.every(i => buttonStyle?.includes(i))).toBe(true)\n\n    await wrapper.setProps({ circle: false, round: false })\n    const defaultStyle: string[] = [\n      '--n-width: initial;',\n      '--n-padding: 0 14px;',\n      '--n-border-radius: 3px;'\n    ]\n    buttonStyle = wrapper.find('button').attributes('style')\n    expect(defaultStyle.every(i => buttonStyle?.includes(i))).toBe(true)\n    wrapper.unmount()\n  })\n\n  it('should work with `ghost` prop', () => {\n    const wrapper = mount(NButton, {\n      props: {\n        ghost: true\n      },\n      slots: {\n        default: () => 'test'\n      }\n    })\n\n    expect(wrapper.find('button').classes()).toContain('n-button--ghost')\n    wrapper.unmount()\n  })\n\n  it('should work with `icon-placement` prop', async () => {\n    const wrapper = mount(NButton, {\n      slots: {\n        default: () => 'test',\n        icon: () =>\n          h(NIcon, null, {\n            default: () => h(CashIcon)\n          })\n      }\n    })\n    expect(wrapper.findAll('span')[0].attributes('class')).toContain(\n      'n-button__icon'\n    )\n    expect(wrapper.findAll('span')[1].attributes('class')).toContain(\n      'n-button__content'\n    )\n\n    await wrapper.setProps({ iconPlacement: 'right' })\n    expect(wrapper.findAll('span')[0].attributes('class')).toContain(\n      'n-button__content'\n    )\n    expect(wrapper.findAll('span')[1].attributes('class')).toContain(\n      'n-button__icon'\n    )\n    wrapper.unmount()\n  })\n\n  it('should work with `loading` prop', () => {\n    const wrapper = mount(NButton, {\n      props: {\n        loading: true\n      },\n      slots: {\n        default: () => 'test'\n      }\n    })\n\n    expect(wrapper.find('.n-icon-slot').classes()).toContain('n-base-loading')\n    expect(wrapper.find('.n-icon-slot').attributes('aria-label')).toContain(\n      'loading'\n    )\n    wrapper.unmount()\n  })\n\n  it('should work with `color` prop', () => {\n    const wrapper = mount(NButton, {\n      props: {\n        color: '#8a2be2'\n      },\n      slots: {\n        default: () => 'test'\n      }\n    })\n\n    expect(wrapper.find('button').classes()).toContain('n-button--color')\n    const colorStyle: string[] = [\n      '--n-color: #8a2be2;',\n      '--n-color-disabled: #8a2be2;',\n      '--n-ripple-color: #8a2be2;'\n    ]\n    const buttonStyle = wrapper.find('button').attributes('style')\n    expect(colorStyle.every(i => buttonStyle?.includes(i))).toBe(true)\n    wrapper.unmount()\n  })\n\n  it('should work with `text-color` prop', () => {\n    const wrapper = mount(NButton, {\n      props: {\n        'text-color': '#8a2be2'\n      },\n      slots: {\n        default: () => 'test'\n      }\n    })\n\n    const buttonStyle = wrapper.find('button').attributes('style')\n    expect(\n      (\n        [\n          '--n-text-color: #8a2be2;',\n          '--n-text-color-disabled: #8a2be2;'\n        ] as string[]\n      ).every(i => buttonStyle?.includes(i))\n    ).toBe(true)\n    wrapper.unmount()\n  })\n})\n"
  },
  {
    "path": "src/button/tests/__snapshots__/Button.spec.tsx.snap",
    "content": "// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html\n\nexports[`n-button > should work with \\`size\\` prop 1`] = `\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-bezier-ease-out: cubic-bezier(0, 0, .2, 1); --n-ripple-duration: .6s; --n-opacity-disabled: 0.5; --n-wave-opacity: 0.6; --n-font-weight: 400; --n-color: #0000; --n-color-hover: #0000; --n-color-pressed: #0000; --n-color-focus: #0000; --n-color-disabled: #0000; --n-ripple-color: #18a058; --n-text-color: rgb(51, 54, 57); --n-text-color-hover: #36ad6a; --n-text-color-pressed: #0c7a43; --n-text-color-focus: #36ad6a; --n-text-color-disabled: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-pressed: 1px solid #0c7a43; --n-border-focus: 1px solid #36ad6a; --n-border-disabled: 1px solid rgb(224, 224, 230); --n-width: initial; --n-height: 22px; --n-font-size: 12px; --n-padding: 0 6px; --n-icon-size: 14px; --n-icon-margin: 6px; --n-border-radius: 3px;\"`;\n\nexports[`n-button > should work with \\`size\\` prop 2`] = `\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-bezier-ease-out: cubic-bezier(0, 0, .2, 1); --n-ripple-duration: .6s; --n-opacity-disabled: 0.5; --n-wave-opacity: 0.6; --n-font-weight: 400; --n-color: #0000; --n-color-hover: #0000; --n-color-pressed: #0000; --n-color-focus: #0000; --n-color-disabled: #0000; --n-ripple-color: #18a058; --n-text-color: rgb(51, 54, 57); --n-text-color-hover: #36ad6a; --n-text-color-pressed: #0c7a43; --n-text-color-focus: #36ad6a; --n-text-color-disabled: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-pressed: 1px solid #0c7a43; --n-border-focus: 1px solid #36ad6a; --n-border-disabled: 1px solid rgb(224, 224, 230); --n-width: initial; --n-height: 28px; --n-font-size: 14px; --n-padding: 0 10px; --n-icon-size: 18px; --n-icon-margin: 6px; --n-border-radius: 3px;\"`;\n\nexports[`n-button > should work with \\`size\\` prop 3`] = `\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-bezier-ease-out: cubic-bezier(0, 0, .2, 1); --n-ripple-duration: .6s; --n-opacity-disabled: 0.5; --n-wave-opacity: 0.6; --n-font-weight: 400; --n-color: #0000; --n-color-hover: #0000; --n-color-pressed: #0000; --n-color-focus: #0000; --n-color-disabled: #0000; --n-ripple-color: #18a058; --n-text-color: rgb(51, 54, 57); --n-text-color-hover: #36ad6a; --n-text-color-pressed: #0c7a43; --n-text-color-focus: #36ad6a; --n-text-color-disabled: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-pressed: 1px solid #0c7a43; --n-border-focus: 1px solid #36ad6a; --n-border-disabled: 1px solid rgb(224, 224, 230); --n-width: initial; --n-height: 34px; --n-font-size: 14px; --n-padding: 0 14px; --n-icon-size: 18px; --n-icon-margin: 6px; --n-border-radius: 3px;\"`;\n\nexports[`n-button > should work with \\`size\\` prop 4`] = `\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-bezier-ease-out: cubic-bezier(0, 0, .2, 1); --n-ripple-duration: .6s; --n-opacity-disabled: 0.5; --n-wave-opacity: 0.6; --n-font-weight: 400; --n-color: #0000; --n-color-hover: #0000; --n-color-pressed: #0000; --n-color-focus: #0000; --n-color-disabled: #0000; --n-ripple-color: #18a058; --n-text-color: rgb(51, 54, 57); --n-text-color-hover: #36ad6a; --n-text-color-pressed: #0c7a43; --n-text-color-focus: #36ad6a; --n-text-color-disabled: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-pressed: 1px solid #0c7a43; --n-border-focus: 1px solid #36ad6a; --n-border-disabled: 1px solid rgb(224, 224, 230); --n-width: initial; --n-height: 40px; --n-font-size: 15px; --n-padding: 0 18px; --n-icon-size: 20px; --n-icon-margin: 6px; --n-border-radius: 3px;\"`;\n\nexports[`n-button > should work with \\`tag\\` prop 1`] = `\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-bezier-ease-out: cubic-bezier(0, 0, .2, 1); --n-ripple-duration: .6s; --n-opacity-disabled: 0.5; --n-wave-opacity: 0.6; --n-font-weight: 400; --n-color: #0000; --n-color-hover: #0000; --n-color-pressed: #0000; --n-color-focus: #0000; --n-color-disabled: #0000; --n-ripple-color: #0000; --n-text-color: #18a058; --n-text-color-hover: #36ad6a; --n-text-color-pressed: #0c7a43; --n-text-color-focus: #36ad6a; --n-text-color-disabled: rgb(51, 54, 57); --n-border: none; --n-border-hover: none; --n-border-pressed: none; --n-border-focus: none; --n-border-disabled: none; --n-width: initial; --n-height: initial; --n-font-size: 14px; --n-padding: initial; --n-icon-size: 18px; --n-icon-margin: 6px; --n-border-radius: initial;\"`;\n\nexports[`n-button > should work with \\`text\\` prop 1`] = `\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-bezier-ease-out: cubic-bezier(0, 0, .2, 1); --n-ripple-duration: .6s; --n-opacity-disabled: 0.5; --n-wave-opacity: 0.6; --n-font-weight: 400; --n-color: #0000; --n-color-hover: #0000; --n-color-pressed: #0000; --n-color-focus: #0000; --n-color-disabled: #0000; --n-ripple-color: #0000; --n-text-color: rgb(51, 54, 57); --n-text-color-hover: #36ad6a; --n-text-color-pressed: #0c7a43; --n-text-color-focus: #36ad6a; --n-text-color-disabled: rgb(51, 54, 57); --n-border: none; --n-border-hover: none; --n-border-pressed: none; --n-border-focus: none; --n-border-disabled: none; --n-width: initial; --n-height: initial; --n-font-size: 14px; --n-padding: initial; --n-icon-size: 18px; --n-icon-margin: 6px; --n-border-radius: initial;\"`;\n"
  },
  {
    "path": "src/button/tests/server.spec.tsx",
    "content": "import { setup } from '@css-render/vue3-ssr'\nimport { renderToString } from '@vue/server-renderer'\n/**\n * @vitest-environment node\n */\nimport { createSSRApp, h } from 'vue'\nimport { NButton } from '../..'\n\ndescribe('server side rendering', () => {\n  it('works', async () => {\n    const app = createSSRApp(() => <NButton />)\n    setup(app)\n    try {\n      await renderToString(app)\n    }\n    catch (e) {\n      expect(e).not.toBeTruthy()\n    }\n  })\n})\n"
  },
  {
    "path": "src/button-group/index.ts",
    "content": "export { buttonGroupProps, default as NButtonGroup } from './src/ButtonGroup'\nexport type { ButtonGroupProps } from './src/ButtonGroup'\n"
  },
  {
    "path": "src/button-group/src/ButtonGroup.tsx",
    "content": "import type { PropType } from 'vue'\nimport type { ExtractPublicPropTypes } from '../../_utils'\nimport type { ButtonSize } from '../../button/src/public-types'\nimport { defineComponent, h, provide } from 'vue'\nimport { useConfig, useStyle } from '../../_mixins'\nimport { useRtl } from '../../_mixins/use-rtl'\nimport { buttonGroupInjectionKey } from './context'\nimport style from './styles/index.cssr'\n\nexport interface ButtonGroupInjection {\n  size?: ButtonSize | undefined\n}\n\nexport const buttonGroupProps = {\n  size: String as PropType<ButtonSize | undefined>,\n  vertical: Boolean\n} as const\n\nexport type ButtonGroupProps = ExtractPublicPropTypes<typeof buttonGroupProps>\n\nexport default defineComponent({\n  name: 'ButtonGroup',\n  props: buttonGroupProps,\n  setup(props) {\n    const { mergedClsPrefixRef, mergedRtlRef } = useConfig(props)\n    useStyle('-button-group', style, mergedClsPrefixRef)\n    provide(buttonGroupInjectionKey, props)\n    const rtlEnabledRef = useRtl(\n      'ButtonGroup',\n      mergedRtlRef,\n      mergedClsPrefixRef\n    )\n    return {\n      rtlEnabled: rtlEnabledRef,\n      mergedClsPrefix: mergedClsPrefixRef\n    }\n  },\n  render() {\n    const { mergedClsPrefix } = this\n    return (\n      <div\n        class={[\n          `${mergedClsPrefix}-button-group`,\n          this.rtlEnabled && `${mergedClsPrefix}-button-group--rtl`,\n          this.vertical && `${mergedClsPrefix}-button-group--vertical`\n        ]}\n        role=\"group\"\n      >\n        {this.$slots}\n      </div>\n    )\n  }\n})\n"
  },
  {
    "path": "src/button-group/src/context.ts",
    "content": "import type { ButtonGroupInjection } from './ButtonGroup'\nimport { createInjectionKey } from '../../_utils'\n\nexport const buttonGroupInjectionKey\n  = createInjectionKey<ButtonGroupInjection>('n-button-group')\n"
  },
  {
    "path": "src/button-group/src/styles/index.cssr.ts",
    "content": "import type { CNode } from 'css-render'\nimport type { ButtonType } from '../../../button/src/public-types'\nimport { c, cB, cE, cM, cNotM } from '../../../_utils/cssr/index'\n\nexport const zero = '0!important'\nexport const n1 = '-1px!important'\n\nfunction createLeftBorderStyle(type: ButtonType): CNode {\n  return cM(`${type}-type`, [\n    c('& +', [\n      cB('button', {}, [\n        cM(`${type}-type`, [\n          cE('border', {\n            borderLeftWidth: zero\n          }),\n          cE('state-border', {\n            left: n1\n          })\n        ])\n      ])\n    ])\n  ])\n}\n\nfunction createTopBorderStyle(type: ButtonType): CNode {\n  return cM(`${type}-type`, [\n    c('& +', [\n      cB('button', [\n        cM(`${type}-type`, [\n          cE('border', {\n            borderTopWidth: zero\n          }),\n          cE('state-border', {\n            top: n1\n          })\n        ])\n      ])\n    ])\n  ])\n}\n\nexport default cB('button-group', `\n  flex-wrap: nowrap;\n  display: inline-flex;\n  position: relative;\n`, [\n  cNotM('vertical', {\n    flexDirection: 'row'\n  }, [\n    cNotM('rtl', [\n      cB('button', [\n        c('&:first-child:not(:last-child)', `\n          margin-right: ${zero};\n          border-top-right-radius: ${zero};\n          border-bottom-right-radius: ${zero};\n        `),\n        c('&:last-child:not(:first-child)', `\n          margin-left: ${zero};\n          border-top-left-radius: ${zero};\n          border-bottom-left-radius: ${zero};\n        `),\n        c('&:not(:first-child):not(:last-child)', `\n          margin-left: ${zero};\n          margin-right: ${zero};\n          border-radius: ${zero};\n        `),\n        createLeftBorderStyle('default'),\n        cM('ghost', [\n          createLeftBorderStyle('primary'),\n          createLeftBorderStyle('info'),\n          createLeftBorderStyle('success'),\n          createLeftBorderStyle('warning'),\n          createLeftBorderStyle('error')\n        ])\n      ])\n    ])\n  ]),\n  cM('vertical', {\n    flexDirection: 'column'\n  }, [\n    cB('button', [\n      c('&:first-child:not(:last-child)', `\n        margin-bottom: ${zero};\n        margin-left: ${zero};\n        margin-right: ${zero};\n        border-bottom-left-radius: ${zero};\n        border-bottom-right-radius: ${zero};\n      `),\n      c('&:last-child:not(:first-child)', `\n        margin-top: ${zero};\n        margin-left: ${zero};\n        margin-right: ${zero};\n        border-top-left-radius: ${zero};\n        border-top-right-radius: ${zero};\n      `),\n      c('&:not(:first-child):not(:last-child)', `\n        margin: ${zero};\n        border-radius: ${zero};\n      `),\n      createTopBorderStyle('default'),\n      cM('ghost', [\n        createTopBorderStyle('primary'),\n        createTopBorderStyle('info'),\n        createTopBorderStyle('success'),\n        createTopBorderStyle('warning'),\n        createTopBorderStyle('error')\n      ])\n    ])\n  ])\n])\n"
  },
  {
    "path": "src/button-group/src/styles/rtl.cssr.ts",
    "content": "import type { CNode } from 'css-render'\nimport type { ButtonType } from '../../../button/src/public-types'\nimport { c, cB, cE, cM, cNotM } from '../../../_utils/cssr'\nimport { n1, zero } from './index.cssr'\n\nfunction createRightBorderStyle(type: ButtonType): CNode {\n  return cM(`${type}-type`, [\n    c('& +', [\n      cB('button', {}, [\n        cM(`${type}-type`, [\n          cE('border', {\n            borderRightWidth: zero\n          }),\n          cE('state-border', {\n            left: n1\n          })\n        ])\n      ])\n    ])\n  ])\n}\n\nexport default cB('button-group', [\n  cNotM('vertical', [\n    cM('rtl', `\n      direction: rtl;\n    `, [\n      cB('button', [\n        c('&:last-child:not(:first-child)', `\n          margin-right: ${zero};\n          border-top-right-radius: ${zero};\n          border-bottom-right-radius: ${zero};\n        `),\n        c('&:first-child:not(:last-child)', `\n          margin-left: ${zero};\n          border-top-left-radius: ${zero};\n          border-bottom-left-radius: ${zero};\n        `),\n        c('&:not(:last-child):not(:first-child)', `\n          margin-left: ${zero};\n          margin-right: ${zero};\n          border-radius: ${zero};\n        `),\n        createRightBorderStyle('default'),\n        cM('ghost', [\n          createRightBorderStyle('primary'),\n          createRightBorderStyle('info'),\n          createRightBorderStyle('success'),\n          createRightBorderStyle('warning'),\n          createRightBorderStyle('error')\n        ])\n      ])\n    ])\n  ])\n])\n"
  },
  {
    "path": "src/button-group/styles/dark.ts",
    "content": "import type { ButtonGroupTheme } from './light'\nimport { commonDark } from '../../_styles/common'\n\nconst buttonGroupDark: ButtonGroupTheme = {\n  name: 'ButtonGroup',\n  common: commonDark\n}\n\nexport default buttonGroupDark\n"
  },
  {
    "path": "src/button-group/styles/index.ts",
    "content": "export { default as buttonGroupDark } from './dark'\nexport { default as buttonGroupLight } from './light'\nexport { buttonGroupRtl } from './rtl'\n"
  },
  {
    "path": "src/button-group/styles/light.ts",
    "content": "import type { Theme } from '../../_mixins'\nimport { commonLight } from '../../_styles/common'\n\nexport interface ButtonGroupThemeVars {}\n\nconst buttonGroupLight: Theme<'ButtonGroup', ButtonGroupThemeVars> = {\n  name: 'ButtonGroup',\n  common: commonLight\n}\n\nexport default buttonGroupLight\nexport type ButtonGroupTheme = typeof buttonGroupLight\n"
  },
  {
    "path": "src/button-group/styles/rtl.ts",
    "content": "import type { RtlItem } from '../../config-provider/src/internal-interface'\nimport rtlStyle from '../src/styles/rtl.cssr'\n\nexport const buttonGroupRtl: RtlItem = {\n  name: 'ButtonGroup',\n  style: rtlStyle\n}\n"
  },
  {
    "path": "src/button-group/tests/ButtonGroup.spec.tsx",
    "content": "import { mount } from '@vue/test-utils'\nimport { h } from 'vue'\nimport { NButton } from '../../button/index'\nimport { NButtonGroup } from '../index'\n\ndescribe('n-button-group', () => {\n  it('should work with import on demand', () => {\n    mount(NButtonGroup)\n  })\n\n  it('should work with `button group`', async () => {\n    const wrapper = mount(NButtonGroup, {\n      slots: {\n        default: () => [\n          h(NButton, null, {\n            default: () => 'test1'\n          }),\n          h(NButton, null, {\n            default: () => 'test2'\n          }),\n          h(NButton, null, {\n            default: () => 'test3'\n          })\n        ]\n      }\n    })\n\n    expect(wrapper.find('[role=\"group\"]').classes()).toContain('n-button-group')\n    expect(wrapper.findAll('button').length).toBe(3)\n\n    await wrapper.setProps({ vertical: true })\n    expect(wrapper.find('[role=\"group\"]').classes()).toContain(\n      'n-button-group--vertical'\n    )\n    wrapper.unmount()\n  })\n})\n"
  },
  {
    "path": "src/button-group/tests/server.spec.tsx",
    "content": "import { setup } from '@css-render/vue3-ssr'\nimport { renderToString } from '@vue/server-renderer'\n/**\n * @vitest-environment node\n */\nimport { createSSRApp, h } from 'vue'\nimport { NButtonGroup } from '../..'\n\ndescribe('server side rendering', () => {\n  it('works', async () => {\n    const app = createSSRApp(() => <NButtonGroup />)\n    setup(app)\n    try {\n      await renderToString(app)\n    }\n    catch (e) {\n      expect(e).not.toBeTruthy()\n    }\n  })\n})\n"
  },
  {
    "path": "src/calendar/demos/enUS/basic.demo.vue",
    "content": "<markdown>\n# Basic\n\nA basic calendar.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { addDays, isYesterday } from 'date-fns'\nimport { useMessage } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst message = useMessage()\nconst value = ref(addDays(Date.now(), 1).valueOf())\n\nfunction handleUpdateValue(\n  _: number,\n  { year, month, date }: { year: number, month: number, date: number }\n) {\n  message.success(`${year}-${month}-${date}`)\n}\n\nfunction isDateDisabled(timestamp: number) {\n  if (isYesterday(timestamp)) {\n    return true\n  }\n  return false\n}\n</script>\n\n<template>\n  <n-calendar\n    v-model:value=\"value\"\n    #=\"{ year, month, date }\"\n    :is-date-disabled=\"isDateDisabled\"\n    @update:value=\"handleUpdateValue\"\n  >\n    {{ year }}-{{ month }}-{{ date }}\n  </n-calendar>\n</template>\n"
  },
  {
    "path": "src/calendar/demos/enUS/index.demo-entry.md",
    "content": "<!--single-column-->\n\n# Calendar\n\nHow time flies.\n\n## Demos\n\n```demo\nbasic.vue\n```\n\n## API\n\n### Calendar Props\n\n| Name | Type | Default | Description | Version |\n| --- | --- | --- | --- | --- |\n| default-value | `number` | `null` | Default selected date's timestamp. |  |\n| is-date-disabled | `(timestamp: number) => boolean` | `undefined` | Validator of the date. |  |\n| value | `number \\| null` | `undefined` | Selected date's timestamp. |  |\n| on-panel-change | `(info: { year: number, month: number })` | `undefined` | Callback on panel content is changed. | 2.24.0 |\n| on-update:value | `(timestamp: number, info: { year: number, month: number, date: number }) => void` | `undefined` | Callback on date is selected. `month` starts from 1. |  |\n\n## Calendar Slots\n\n| Name | Parameters | Description | Version |\n| --- | --- | --- | --- |\n| default | `({ year: number, month: number, date: number })` | Content to be rendered in each date. |  |\n| header | `(props: { year: number, month: number })` | Header of the calendar. `month` starts from 1. | 2.29.1 |\n"
  },
  {
    "path": "src/calendar/demos/zhCN/basic.demo.vue",
    "content": "<markdown>\n# 基础用法\n\n一个普通的日历。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { addDays, isYesterday } from 'date-fns'\nimport { useMessage } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst message = useMessage()\nconst value = ref(addDays(Date.now(), 1).valueOf())\n\nfunction handleUpdateValue(\n  _: number,\n  { year, month, date }: { year: number, month: number, date: number }\n) {\n  message.success(`${year}-${month}-${date}`)\n}\n\nfunction isDateDisabled(timestamp: number) {\n  if (isYesterday(timestamp)) {\n    return true\n  }\n  return false\n}\n</script>\n\n<template>\n  <n-calendar\n    v-model:value=\"value\"\n    #=\"{ year, month, date }\"\n    :is-date-disabled=\"isDateDisabled\"\n    @update:value=\"handleUpdateValue\"\n  >\n    {{ year }}-{{ month }}-{{ date }}\n  </n-calendar>\n</template>\n"
  },
  {
    "path": "src/calendar/demos/zhCN/index.demo-entry.md",
    "content": "<!--single-column-->\n\n# 日历 Calendar\n\n时间过的快。\n\n## 演示\n\n```demo\nbasic.vue\n```\n\n## API\n\n### Calendar Props\n\n| 名称 | 类型 | 默认值 | 说明 | 版本 |\n| --- | --- | --- | --- | --- |\n| default-value | `number` | `null` | 默认被选中的日期的时间戳 |  |\n| is-date-disabled | `(timestamp: number) => boolean` | `undefined` | 日期禁用的校验函数 |  |\n| value | `number \\| null` | `undefined` | 被选中的日期的时间戳 |  |\n| on-panel-change | `(info: { year: number, month: number })` | `undefined` | 面板内容切换的回调 | 2.24.0 |\n| on-update:value | `(timestamp: number, info: { year: number, month: number, date: number }) => void` | `undefined` | 选中日期的回调，`month` 从 1 开始 |  |\n\n### Calendar Slots\n\n| 名称 | 参数 | 说明 | 版本 |\n| --- | --- | --- | --- |\n| default | `(props: { year: number, month: number, date: number })` | 每个日期中渲染的内容 |  |\n| header | `(props: { year: number, month: number })` | 日历的标题，`month` 从 1 开始 | 2.29.1 |\n"
  },
  {
    "path": "src/calendar/index.ts",
    "content": "export { calendarProps, default as NCalendar } from './src/Calendar'\nexport type { CalendarProps } from './src/Calendar'\n"
  },
  {
    "path": "src/calendar/src/Calendar.tsx",
    "content": "import type { CSSProperties, PropType, SlotsType, VNode } from 'vue'\nimport type { ThemeProps } from '../../_mixins'\nimport type { ExtractPublicPropTypes, MaybeArray } from '../../_utils'\nimport type { CalendarTheme } from '../styles'\nimport type {\n  CalendarDefaultSlotProps,\n  CalendarHeaderSlotProps,\n  DateItem,\n  OnPanelChange,\n  OnUpdateValue\n} from './interface'\nimport {\n  addMonths,\n  format,\n  getMonth,\n  getYear,\n  startOfDay,\n  startOfMonth\n} from 'date-fns'\nimport { useMergedState } from 'vooks'\nimport { computed, defineComponent, Fragment, h, ref, toRef } from 'vue'\nimport { NBaseIcon } from '../../_internal'\nimport { ChevronLeftIcon, ChevronRightIcon } from '../../_internal/icons'\nimport { useConfig, useLocale, useTheme, useThemeClass } from '../../_mixins'\nimport { call, resolveSlotWithTypedProps } from '../../_utils'\nimport { NButton } from '../../button'\nimport { NButtonGroup } from '../../button-group'\nimport { dateArray } from '../../date-picker/src/utils'\nimport { calendarLight } from '../styles'\nimport style from './styles/index.cssr'\n\nexport const calendarProps = {\n  ...(useTheme.props as ThemeProps<CalendarTheme>),\n  isDateDisabled: Function as PropType<(date: number) => boolean | undefined>,\n  value: Number,\n  defaultValue: {\n    type: Number as PropType<number | null>,\n    default: null\n  },\n  onPanelChange: Function as PropType<OnPanelChange>,\n  'onUpdate:value': [Function, Array] as PropType<MaybeArray<OnUpdateValue>>,\n  onUpdateValue: [Function, Array] as PropType<MaybeArray<OnUpdateValue>>\n} as const\n\nexport type CalendarProps = ExtractPublicPropTypes<typeof calendarProps>\n\nexport interface CalendarSlots {\n  default?: (props: CalendarDefaultSlotProps) => VNode[]\n  header?: (props: CalendarHeaderSlotProps) => VNode[]\n}\n\nexport default defineComponent({\n  name: 'Calendar',\n  props: calendarProps,\n  slots: Object as SlotsType<CalendarSlots>,\n  setup(props) {\n    const { mergedClsPrefixRef, inlineThemeDisabled } = useConfig(props)\n    const themeRef = useTheme(\n      'Calendar',\n      '-calendar',\n      style,\n      calendarLight,\n      props,\n      mergedClsPrefixRef\n    )\n    const { localeRef, dateLocaleRef } = useLocale('DatePicker')\n    const now = Date.now()\n    // ts => timestamp\n    const monthTsRef = ref(startOfMonth(props.defaultValue ?? now).valueOf())\n    const uncontrolledValueRef = ref<number | null>(props.defaultValue || null)\n    const mergedValueRef = useMergedState(\n      toRef(props, 'value'),\n      uncontrolledValueRef\n    )\n\n    function doUpdateValue(value: number, time: DateItem): void {\n      const { onUpdateValue, 'onUpdate:value': _onUpdateValue } = props\n      if (onUpdateValue) {\n        call(onUpdateValue, value, time)\n      }\n      if (_onUpdateValue) {\n        call(_onUpdateValue, value, time)\n      }\n      uncontrolledValueRef.value = value\n    }\n\n    function handlePrevClick(): void {\n      const monthTs = addMonths(monthTsRef.value, -1).valueOf()\n      monthTsRef.value = monthTs\n      props.onPanelChange?.({\n        year: getYear(monthTs),\n        month: getMonth(monthTs) + 1\n      })\n    }\n    function handleNextClick(): void {\n      const monthTs = addMonths(monthTsRef.value, 1).valueOf()\n      monthTsRef.value = monthTs\n      props.onPanelChange?.({\n        year: getYear(monthTs),\n        month: getMonth(monthTs) + 1\n      })\n    }\n    function handleTodayClick(): void {\n      const { value: monthTs } = monthTsRef\n      const oldYear = getYear(monthTs)\n      const oldMonth = getMonth(monthTs)\n      const newMonthTs = startOfMonth(now).valueOf()\n      monthTsRef.value = newMonthTs\n      const newYear = getYear(newMonthTs)\n      const newMonth = getMonth(newMonthTs)\n      if (oldYear !== newYear || oldMonth !== newMonth) {\n        props.onPanelChange?.({\n          year: newYear,\n          month: newMonth + 1\n        })\n      }\n    }\n    const cssVarsRef = computed(() => {\n      const {\n        common: { cubicBezierEaseInOut },\n        self: {\n          borderColor,\n          borderColorModal,\n          borderColorPopover,\n          borderRadius,\n          titleFontSize,\n          textColor,\n          titleFontWeight,\n          titleTextColor,\n          dayTextColor,\n          fontSize,\n          lineHeight,\n          dateColorCurrent,\n          dateTextColorCurrent,\n          cellColorHover,\n          cellColor,\n          cellColorModal,\n          barColor,\n          cellColorPopover,\n          cellColorHoverModal,\n          cellColorHoverPopover\n        }\n      } = themeRef.value\n      return {\n        '--n-bezier': cubicBezierEaseInOut,\n        '--n-border-color': borderColor,\n        '--n-border-color-modal': borderColorModal,\n        '--n-border-color-popover': borderColorPopover,\n        '--n-border-radius': borderRadius,\n        '--n-text-color': textColor,\n        '--n-title-font-weight': titleFontWeight,\n        '--n-title-font-size': titleFontSize,\n        '--n-title-text-color': titleTextColor,\n        '--n-day-text-color': dayTextColor,\n        '--n-font-size': fontSize,\n        '--n-line-height': lineHeight,\n        '--n-date-color-current': dateColorCurrent,\n        '--n-date-text-color-current': dateTextColorCurrent,\n        '--n-cell-color': cellColor,\n        '--n-cell-color-modal': cellColorModal,\n        '--n-cell-color-popover': cellColorPopover,\n        '--n-cell-color-hover': cellColorHover,\n        '--n-cell-color-hover-modal': cellColorHoverModal,\n        '--n-cell-color-hover-popover': cellColorHoverPopover,\n        '--n-bar-color': barColor\n      }\n    })\n    const themeClassHandle = inlineThemeDisabled\n      ? useThemeClass('calendar', undefined, cssVarsRef, props)\n      : undefined\n    return {\n      mergedClsPrefix: mergedClsPrefixRef,\n      locale: localeRef,\n      dateLocale: dateLocaleRef,\n      now,\n      mergedValue: mergedValueRef,\n      monthTs: monthTsRef,\n      dateItems: computed(() => {\n        return dateArray(\n          monthTsRef.value,\n          mergedValueRef.value,\n          now,\n          localeRef.value.firstDayOfWeek,\n          true\n        )\n      }),\n      doUpdateValue,\n      handleTodayClick,\n      handlePrevClick,\n      handleNextClick,\n      mergedTheme: themeRef,\n      cssVars: inlineThemeDisabled ? undefined : cssVarsRef,\n      themeClass: themeClassHandle?.themeClass,\n      onRender: themeClassHandle?.onRender\n    }\n  },\n  render() {\n    const {\n      isDateDisabled,\n      mergedClsPrefix,\n      monthTs,\n      cssVars,\n      mergedValue,\n      mergedTheme,\n      $slots,\n      locale: { monthBeforeYear, today },\n      dateLocale: { locale },\n      handleTodayClick,\n      handlePrevClick,\n      handleNextClick,\n      onRender\n    } = this\n    onRender?.()\n    const normalizedValue = mergedValue && startOfDay(mergedValue).valueOf()\n    const year = getYear(monthTs)\n    const calendarMonth = getMonth(monthTs) + 1\n    return (\n      <div\n        class={[`${mergedClsPrefix}-calendar`, this.themeClass]}\n        style={cssVars as CSSProperties}\n      >\n        <div class={`${mergedClsPrefix}-calendar-header`}>\n          <div class={`${mergedClsPrefix}-calendar-header__title`}>\n            {resolveSlotWithTypedProps(\n              $slots.header,\n              { year, month: calendarMonth },\n              () => {\n                const localeMonth = format(monthTs, 'MMMM', { locale })\n                return [\n                  monthBeforeYear\n                    ? `${localeMonth} ${year}`\n                    : `${year} ${localeMonth}`\n                ]\n              }\n            )}\n          </div>\n          <div class={`${mergedClsPrefix}-calendar-header__extra`}>\n            <NButtonGroup>\n              {{\n                default: () => (\n                  <>\n                    <NButton\n                      size=\"small\"\n                      onClick={handlePrevClick}\n                      theme={mergedTheme.peers.Button}\n                      themeOverrides={mergedTheme.peerOverrides.Button}\n                    >\n                      {{\n                        icon: () => (\n                          <NBaseIcon\n                            clsPrefix={mergedClsPrefix}\n                            class={`${mergedClsPrefix}-calendar-prev-btn`}\n                          >\n                            {{ default: () => <ChevronLeftIcon /> }}\n                          </NBaseIcon>\n                        )\n                      }}\n                    </NButton>\n                    <NButton\n                      size=\"small\"\n                      onClick={handleTodayClick}\n                      theme={mergedTheme.peers.Button}\n                      themeOverrides={mergedTheme.peerOverrides.Button}\n                    >\n                      {{ default: () => today }}\n                    </NButton>\n                    <NButton\n                      size=\"small\"\n                      onClick={handleNextClick}\n                      theme={mergedTheme.peers.Button}\n                      themeOverrides={mergedTheme.peerOverrides.Button}\n                    >\n                      {{\n                        icon: () => (\n                          <NBaseIcon\n                            clsPrefix={mergedClsPrefix}\n                            class={`${mergedClsPrefix}-calendar-next-btn`}\n                          >\n                            {{ default: () => <ChevronRightIcon /> }}\n                          </NBaseIcon>\n                        )\n                      }}\n                    </NButton>\n                  </>\n                )\n              }}\n            </NButtonGroup>\n          </div>\n        </div>\n        <div class={`${mergedClsPrefix}-calendar-dates`}>\n          {this.dateItems.map(\n            ({ dateObject, ts, inCurrentMonth, isCurrentDate }, index) => {\n              const { year, month, date } = dateObject\n              const fullDate = format(ts, 'yyyy-MM-dd')\n              // 'notInCurrentMonth' and 'disabled' are both disabled styles, but 'disabled''s cursor are not-allowed\n              const notInCurrentMonth = !inCurrentMonth\n              const disabled = isDateDisabled?.(ts) === true\n              const selected = normalizedValue === startOfDay(ts).valueOf()\n              return (\n                <div\n                  key={`${calendarMonth}-${index}`}\n                  class={[\n                    `${mergedClsPrefix}-calendar-cell`,\n                    disabled && `${mergedClsPrefix}-calendar-cell--disabled`,\n                    notInCurrentMonth\n                    && `${mergedClsPrefix}-calendar-cell--other-month`,\n                    disabled && `${mergedClsPrefix}-calendar-cell--not-allowed`,\n                    isCurrentDate\n                    && `${mergedClsPrefix}-calendar-cell--current`,\n                    selected && `${mergedClsPrefix}-calendar-cell--selected`\n                  ]}\n                  onClick={() => {\n                    if (disabled)\n                      return\n                    const monthTs = startOfMonth(ts).valueOf()\n                    this.monthTs = monthTs\n                    if (notInCurrentMonth) {\n                      this.onPanelChange?.({\n                        year: getYear(monthTs),\n                        month: getMonth(monthTs) + 1\n                      })\n                    }\n                    this.doUpdateValue(ts, {\n                      year,\n                      month: month + 1,\n                      date\n                    })\n                  }}\n                >\n                  <div class={`${mergedClsPrefix}-calendar-date`}>\n                    <div\n                      class={`${mergedClsPrefix}-calendar-date__date`}\n                      title={fullDate}\n                    >\n                      {date}\n                    </div>\n                    {index < 7 && (\n                      <div\n                        class={`${mergedClsPrefix}-calendar-date__day`}\n                        title={fullDate}\n                      >\n                        {format(ts, 'EEE', {\n                          locale\n                        })}\n                      </div>\n                    )}\n                  </div>\n                  {$slots.default?.({\n                    year,\n                    month: month + 1,\n                    date\n                  })}\n                  <div class={`${mergedClsPrefix}-calendar-cell__bar`} />\n                </div>\n              )\n            }\n          )}\n        </div>\n      </div>\n    )\n  }\n})\n"
  },
  {
    "path": "src/calendar/src/interface.ts",
    "content": "export type OnUpdateValue = (value: number, time: DateItem) => void\n\nexport interface DateItem {\n  year: number\n  month: number\n  date: number\n}\n\nexport type OnPanelChange = (info: { year: number, month: number }) => void\n\nexport interface CalendarDefaultSlotProps {\n  year: number\n  month: number\n  date: number\n}\n\nexport interface CalendarHeaderSlotProps {\n  year: number\n  month: number\n}\n"
  },
  {
    "path": "src/calendar/src/styles/index.cssr.ts",
    "content": "import { c, cB, cE, cM, insideModal, insidePopover } from '../../../_utils/cssr'\n\n// vars:\n// --n-bezier\n// --n-border-color\n// --n-border-color-modal\n// --n-border-color-popover\n// --n-border-radius\n// --n-text-color\n// --n-title-font-weight\n// --n-title-font-size\n// --n-title-text-color\n// --n-day-text-color\n// --n-font-size\n// --n-line-height\n// --n-date-color-current\n// --n-cell-color\n// --n-cell-color-hover\n// --n-cell-color-hover-modal\n// --n-cell-color-hover-popover\n// --n-bar-color\nexport default c([\n  cB('calendar', `\n    line-height: var(--n-line-height);\n    font-size: var(--n-font-size);\n    color: var(--n-text-color);\n    height: 720px;\n    display: flex;\n    flex-direction: column;\n  `, [\n    cB('calendar-prev-btn', `\n      cursor: pointer;\n    `),\n    cB('calendar-next-btn', `\n      cursor: pointer;\n    `),\n    cB('calendar-header', `\n      display: flex;\n      align-items: center;\n      line-height: 1;\n      font-size: var(--n-title-font-size);\n      padding: 0 0 18px 0;\n      justify-content: space-between;\n    `, [\n      cE('title', `\n        color: var(--n-title-text-color);\n        font-weight: var(--n-title-font-weight);\n        transition: color .3s var(--n-bezier);\n      `),\n      cE('extra', `\n        display: flex;\n        align-items: center;\n      `)\n    ]),\n    cB('calendar-dates', `\n      display: grid;\n      grid-template-columns: repeat(7, minmax(0, 1fr));\n      grid-auto-rows: 1fr;\n      border-radius: var(--n-border-radius);\n      flex: 1;\n      border-top: 1px solid;\n      border-left: 1px solid;\n      border-color: var(--n-border-color);\n      transition: border-color .3s var(--n-bezier);\n    `),\n    cB('calendar-cell', `\n      box-sizing: border-box;\n      padding: 10px;\n      border-right: 1px solid;\n      border-bottom: 1px solid;\n      border-color: var(--n-border-color);\n      cursor: pointer;\n      position: relative;\n      transition:\n        color .3s var(--n-bezier),\n        border-color .3s var(--n-bezier),\n        background-color .3s var(--n-bezier);\n    `, [\n      c('&:nth-child(7)', `\n        border-top-right-radius: var(--n-border-radius);\n      `),\n      c('&:nth-last-child(7)', `\n        border-bottom-left-radius: var(--n-border-radius);\n      `),\n      c('&:last-child', `\n        border-bottom-right-radius: var(--n-border-radius);\n      `),\n      c('&:hover', `\n        background-color: var(--n-cell-color-hover);\n      `),\n      cE('bar', `\n        position: absolute;\n        left: 0;\n        right: 0;\n        bottom: -1px;\n        height: 3px;\n        background-color: #0000;\n        transition: background-color .3s var(--n-bezier);\n      `),\n      cM('selected', [\n        cE('bar', `\n          background-color: var(--n-bar-color);\n        `)\n      ]),\n      cB('calendar-date', `\n        transition:\n          color .3s var(--n-bezier),\n          border-color .3s var(--n-bezier),\n          background-color .3s var(--n-bezier);\n        color: var(--n-text-color);\n      `, [\n        cE('date', `\n          color: var(--n-text-color);\n        `)\n      ]),\n      cM('disabled, other-month', `\n        color: var(--n-day-text-color);\n      `, [\n        cB('calendar-date', [\n          cE('date', `\n            color: var(--n-day-text-color);\n          `)\n        ])\n      ]),\n      cM('disabled', `\n        cursor: not-allowed;\n      `),\n      cM('current', [\n        cB('calendar-date', [\n          cE('date', `\n            color: var(--n-date-text-color-current);\n            background-color: var(--n-date-color-current);\n          `)\n        ])\n      ]),\n      cB('calendar-date', `\n        position: relative;\n        line-height: 1;\n        display: flex;\n        align-items: center;\n        height: 1em;\n        justify-content: space-between;\n        padding-bottom: .75em;\n      `, [\n        cE('date', `\n          border-radius: 50%;\n          display: flex;\n          align-items: center;\n          justify-content: center;\n          margin-left: -0.4em;\n          width: 1.8em;\n          height: 1.8em;\n          transition:\n            color .3s var(--n-bezier),\n            background-color .3s var(--n-bezier);\n        `),\n        cE('day', `\n          color: var(--n-day-text-color);\n          transition: color .3s var(--n-bezier);\n        `)\n      ])\n    ])\n  ]),\n  insideModal(cB('calendar', [\n    cB('calendar-dates', `\n      border-color: var(--n-border-color-modal);\n    `),\n    cB('calendar-cell', `\n      border-color: var(--n-border-color-modal);\n    `, [\n      c('&:hover', `\n        background-color: var(--n-cell-color-hover-modal);\n      `)\n    ])\n  ])),\n  insidePopover(cB('calendar', [\n    cB('calendar-dates', `\n      border-color: var(--n-border-color-popover);\n    `),\n    cB('calendar-cell', `\n      border-color: var(--n-border-color-popover);\n    `, [\n      c('&:hover', `\n        background-color: var(--n-cell-color-hover-popover);\n      `)\n    ])\n  ]))\n])\n"
  },
  {
    "path": "src/calendar/styles/_common.ts",
    "content": "export default {\n  titleFontSize: '22px'\n}\n"
  },
  {
    "path": "src/calendar/styles/dark.ts",
    "content": "import type { CalendarTheme } from './light'\nimport { commonDark } from '../../_styles/common'\nimport { buttonDark } from '../../button/styles'\nimport { self } from './light'\n\nconst calendarDark: CalendarTheme = {\n  name: 'Calendar',\n  common: commonDark,\n  peers: {\n    Button: buttonDark\n  },\n  self\n}\n\nexport default calendarDark\n"
  },
  {
    "path": "src/calendar/styles/index.ts",
    "content": "export { default as calendarDark } from './dark'\nexport { default as calendarLight } from './light'\nexport type { CalendarTheme, CalendarThemeVars } from './light'\n"
  },
  {
    "path": "src/calendar/styles/light.ts",
    "content": "import type { ThemeCommonVars } from '../../_styles/common'\nimport { composite } from 'seemly'\nimport { createTheme } from '../../_mixins'\nimport { commonLight } from '../../_styles/common'\nimport { buttonLight } from '../../button/styles'\nimport commonVariables from './_common'\n\nexport function self(vars: ThemeCommonVars) {\n  const {\n    borderRadius,\n    fontSize,\n    lineHeight,\n    textColor2,\n    textColor1,\n    textColorDisabled,\n    dividerColor,\n    fontWeightStrong,\n    primaryColor,\n    baseColor,\n    hoverColor,\n    cardColor,\n    modalColor,\n    popoverColor\n  } = vars\n  return {\n    ...commonVariables,\n    borderRadius,\n    borderColor: composite(cardColor, dividerColor),\n    borderColorModal: composite(modalColor, dividerColor),\n    borderColorPopover: composite(popoverColor, dividerColor),\n    textColor: textColor2,\n    titleFontWeight: fontWeightStrong,\n    titleTextColor: textColor1,\n    dayTextColor: textColorDisabled,\n    fontSize,\n    lineHeight,\n    dateColorCurrent: primaryColor,\n    dateTextColorCurrent: baseColor,\n    cellColorHover: composite(cardColor, hoverColor),\n    cellColorHoverModal: composite(modalColor, hoverColor),\n    cellColorHoverPopover: composite(popoverColor, hoverColor),\n    cellColor: cardColor,\n    cellColorModal: modalColor,\n    cellColorPopover: popoverColor,\n    barColor: primaryColor\n  }\n}\n\nexport type CalendarThemeVars = ReturnType<typeof self>\n\nconst calendarLight = createTheme({\n  name: 'Calendar',\n  common: commonLight,\n  peers: {\n    Button: buttonLight\n  },\n  self\n})\n\nexport default calendarLight\nexport type CalendarTheme = typeof calendarLight\n"
  },
  {
    "path": "src/calendar/tests/Calendar.spec.tsx",
    "content": "import { mount } from '@vue/test-utils'\nimport { addMonths, format, getYear, isYesterday } from 'date-fns'\n/* eslint-disable unused-imports/no-unused-vars */\nimport { h } from 'vue'\nimport { NButton } from '../../button'\nimport { NCalendar } from '../index'\n\ndescribe('n-calendar', () => {\n  const now = Date.now()\n\n  it('should work with import on demand', () => {\n    mount(NCalendar)\n  })\n\n  it('props.onUpdate has correct type', () => {\n    ;(() => (\n      <NCalendar\n        onUpdateValue={(\n          value: number,\n          time: {\n            date: number\n            month: number\n            year: number\n          }\n        ) => {}}\n      />\n    ))()\n  })\n\n  it('should follow `default-value` to display month', () => {\n    // May 19 2022\n    const wrapper = mount(NCalendar, { props: { defaultValue: 1652956953562 } })\n    expect(wrapper.find('.n-calendar-header__title').text()).toContain('May')\n    wrapper.unmount()\n  })\n\n  it('should work with `default-value` prop', async () => {\n    const wrapper = mount(NCalendar, { props: { defaultValue: now } })\n    expect(wrapper.find('.n-calendar-cell--selected').exists()).toBe(true)\n    wrapper.unmount()\n  })\n\n  it('should work with `value` prop', async () => {\n    const wrapper = mount(NCalendar, { props: { value: now } })\n    expect(wrapper.find('.n-calendar-cell--selected').exists()).toBe(true)\n    wrapper.unmount()\n  })\n\n  it('should work with `is-date-disabled` prop', async () => {\n    function disableFunction(timestamp: number): boolean {\n      return isYesterday(timestamp)\n    }\n    const wrapper = mount(NCalendar, {\n      props: { 'is-date-disabled': disableFunction }\n    })\n    expect(wrapper.find('.n-calendar-cell--disabled').exists()).toBe(true)\n    wrapper.unmount()\n  })\n\n  it('should work with `on-update:value` prop', async () => {\n    const onUpdate = vi.fn()\n    const wrapper = mount(NCalendar, { props: { 'on-update:value': onUpdate } })\n\n    await wrapper.findAll('.n-calendar-date')[1].trigger('click')\n    expect(onUpdate).toHaveBeenCalled()\n    wrapper.unmount()\n  })\n\n  it('should work with clicked `prev` and `next`', async () => {\n    const wrapper = mount(NCalendar, { props: { defaultValue: now } })\n\n    const nowDate = wrapper.find('.n-calendar-header__title').text()\n    const buttons = wrapper.findAllComponents(NButton)\n\n    await buttons[0].trigger('click')\n    const prevDate = addMonths(now, -1)\n    expect(wrapper.find('.n-calendar-header__title').text()).toBe(\n      `${format(prevDate, 'MMMM')} ${getYear(prevDate)}`\n    )\n\n    await buttons[1].trigger('click')\n    expect(wrapper.find('.n-calendar-header__title').text()).toBe(nowDate)\n    expect(\n      wrapper\n        .find('.n-calendar-cell--current')\n        .find('.n-calendar-date__date')\n        .attributes('title')\n    ).toBe(format(now, 'yyyy-MM-dd'))\n\n    await buttons[2].trigger('click')\n    const nextDate = addMonths(now, 1)\n    expect(wrapper.find('.n-calendar-header__title').text()).toBe(\n      `${format(nextDate, 'MMMM')} ${getYear(nextDate)}`\n    )\n    wrapper.unmount()\n  })\n})\n"
  },
  {
    "path": "src/calendar/tests/server.spec.tsx",
    "content": "import { setup } from '@css-render/vue3-ssr'\nimport { renderToString } from '@vue/server-renderer'\n/**\n * @vitest-environment node\n */\nimport { createSSRApp, h } from 'vue'\nimport { NCalendar } from '../..'\n\ndescribe('server side rendering', () => {\n  it('works', async () => {\n    const app = createSSRApp(() => <NCalendar />)\n    setup(app)\n    try {\n      await renderToString(app)\n    }\n    catch (e) {\n      expect(e).not.toBeTruthy()\n    }\n  })\n})\n"
  },
  {
    "path": "src/card/demos/enUS/basic.demo.vue",
    "content": "<markdown>\n# Basic\n\nA basic card.\n</markdown>\n\n<template>\n  <n-card title=\"Card\">\n    Card Content\n  </n-card>\n</template>\n\n<style>\n.n-card {\n  max-width: 300px;\n}\n</style>\n"
  },
  {
    "path": "src/card/demos/enUS/border.demo.vue",
    "content": "<markdown>\n# Border\n\nCard can be used without border.\n</markdown>\n\n<template>\n  <n-card :bordered=\"false\" title=\"Borderless Card\">\n    Card Content\n  </n-card>\n</template>\n"
  },
  {
    "path": "src/card/demos/enUS/closable.demo.vue",
    "content": "<markdown>\n# Closable\n\nYou may need this when using it in a modal.\n</markdown>\n\n<script setup lang=\"ts\">\nimport { useMessage } from 'naive-ui'\n\nconst message = useMessage()\nfunction handleClose() {\n  message.info('Card Close')\n}\n</script>\n\n<template>\n  <n-card title=\"Card\" closable @close=\"handleClose\">\n    Card Content\n  </n-card>\n</template>\n\n<style>\n.n-card {\n  max-width: 300px;\n}\n</style>\n"
  },
  {
    "path": "src/card/demos/enUS/content-scrollable.demo.vue",
    "content": "<markdown>\n# Content Scroll\n\nEnable `content-scrollable` to keep scrolling inside the content area only. Header and footer stay fixed. It is usually used with a fixed card height.\n</markdown>\n\n<template>\n  <n-card\n    title=\"Task List\"\n    content-scrollable\n    style=\"max-height: 280px\"\n    segmented\n  >\n    <p v-for=\"i in 20\" :key=\"i\" style=\"margin: 0 0 8px 0\">\n      Task {{ i }}: only content area scrolls.\n    </p>\n    <template #footer>\n      Footer actions stay fixed\n    </template>\n  </n-card>\n</template>\n"
  },
  {
    "path": "src/card/demos/enUS/cover.demo.vue",
    "content": "<markdown>\n# Cover\n\nCard can have a cover.\n</markdown>\n\n<template>\n  <n-card title=\"Card with Cover\">\n    <template #cover>\n      <img src=\"https://07akioni.oss-cn-beijing.aliyuncs.com/07akioni.jpeg\">\n    </template>\n    Card Content\n  </n-card>\n</template>\n\n<style>\n.n-card {\n  max-width: 300px;\n}\n</style>\n"
  },
  {
    "path": "src/card/demos/enUS/custom-style.demo.vue",
    "content": "<markdown>\n# Custom\n\nCard provides `content-style`, `header-style`, `footer-style` to help you customize style. For example you want an card with no padding to put whatever you want.\n</markdown>\n\n<template>\n  <n-card content-style=\"padding: 0;\">\n    <n-tabs\n      type=\"line\"\n      size=\"large\"\n      :tabs-padding=\"20\"\n      pane-style=\"padding: 20px;\"\n    >\n      <n-tab-pane name=\"PARKLIFE\">\n        PARKLIFE\n      </n-tab-pane>\n      <n-tab-pane name=\"ROCKLIFE\">\n        ROCKLIFE\n      </n-tab-pane>\n    </n-tabs>\n  </n-card>\n</template>\n"
  },
  {
    "path": "src/card/demos/enUS/embedded.demo.vue",
    "content": "<markdown>\n# Embedded effect\n\nIn light mode, sometimes you may need to make background a bit darker to distinguish card from white background.\n</markdown>\n\n<template>\n  <n-card title=\"🎸 Rock N' Roll Star\" embedded :bordered=\"false\">\n    Tonight I'm a rock 'n' roll star\n    <br>\n    Tonight I'm a rock 'n' roll star\n  </n-card>\n</template>\n\n<style>\n.n-card {\n  max-width: 300px;\n}\n</style>\n"
  },
  {
    "path": "src/card/demos/enUS/hoverable.demo.vue",
    "content": "<markdown>\n# Hoverable\n</markdown>\n\n<template>\n  <n-card title=\"Card\" hoverable>\n    Card Content\n  </n-card>\n</template>\n\n<style>\n.n-card {\n  max-width: 300px;\n}\n</style>\n"
  },
  {
    "path": "src/card/demos/enUS/index.demo-entry.md",
    "content": "# Card\n\nJust put something in it.\n\n## Demos\n\n```demo\nbasic.vue\nsize.vue\ncover.vue\nhoverable.vue\nslots.vue\nborder.vue\nsegment.vue\nclosable.vue\nno-title.vue\ncontent-scrollable.vue\nloading.vue\ncustom-style.vue\nembedded.vue\n```\n\n## Card\n\n### Card Props\n\n| Name | Type | Default | Description | Version |\n| --- | --- | --- | --- | --- |\n| action | `() => VNodeChild` | `undefined` | Operating area content, must be a render function. | 2.38.2 |\n| bordered | `boolean` | `true` | Whether to show the card border. |  |\n| closable | `boolean` | `false` | Is it allowed to close. |  |\n| close-focusable | `boolean` | `false` | Whether the close button can be focused. | 2.43.0 |\n| content | `string \\| (() => VNodeChild)` | `undefined` | Card content, can be a render function. | 2.38.2 |\n| content-class | `string` | `undefined` | The class of the card content area. | 2.36.0 |\n| content-scrollable | `boolean` | `false` | Whether only the card content area is scrollable (recommended with fixed height). | 2.44.0 |\n| content-style | `Object \\| string` | `undefined` | The style of the card content area. |  |\n| cover | `() => VNodeChild` | `undefined` | Cover content, must be a render function. | 2.38.2 |\n| embedded | `boolean` | `false` | Use a darker background color to show the embedding effect (only for bright themes) |  |\n| footer | `() => VNodeChild` | `undefined` | Footer content, must be a render function. | 2.38.2 |\n| footer-class | `string` | `undefined` | The class of the bottom area of the card. | 2.36.0 |\n| footer-style | `Object \\| string` | `undefined` | The style of the bottom area of the card. |  |\n| header-class | `string` | `undefined` | The class of the card head area. | 2.36.0 |\n| header-style | `Object \\| string` | `undefined` | The style of the card head area. |  |\n| header-extra | `() => VNodeChild` | `undefined` | Header extra content, must be a render function. | 2.38.2 |\n| header-extra-class | `string` | `undefined` | The class of the card head extra area. | 2.36.0 |\n| header-extra-style | `Object \\| string` | `undefined` | The style of the card head extra area. | 2.25.0 |\n| hoverable | `boolean` | `false` | Whether to show shadow when hovering on the card. |  |\n| segmented | `boolean \\| { [part in 'content' \\| 'footer' \\| 'action']?: boolean \\| 'soft' }` | `false` | Segment divider settings of the card. |  |\n| size | `'small' \\| 'medium' \\| 'large' \\| 'huge'` | `'medium'` | Card size. |  |\n| tag | `string` | `'div'` | What tag need the card be rendered as. | 2.34.3 |\n| title | `string \\| (() => VNodeChild)` | `undefined` | Card title. | Render function since 2.38.2 |\n| on-close | `() => void` | `undefined` | Callback function triggered upon closing the card. |  |\n\n### Card Slots\n\n| Name         | Parameters | Description             |\n| ------------ | ---------- | ----------------------- |\n| cover        | `()`       | Cover content.          |\n| header       | `()`       | Header content.         |\n| header-extra | `()`       | Header extra content.   |\n| default      | `()`       | Card content.           |\n| footer       | `()`       | Footer content.         |\n| action       | `()`       | Operating area content. |\n"
  },
  {
    "path": "src/card/demos/enUS/loading.demo.vue",
    "content": "<markdown>\n# Loading\n\nUse `n-skeleton` to simulate loading effect.\n</markdown>\n\n<script setup lang=\"ts\">\nimport { ref } from 'vue'\n\nconst loading = ref(true)\n</script>\n\n<template>\n  <n-space vertical>\n    <n-switch v-model:value=\"loading\" />\n    <n-card>\n      <template #header>\n        <n-skeleton v-if=\"loading\" text width=\"60%\" />\n        <template v-else>\n          Lorem Ipsum\n        </template>\n      </template>\n      <n-skeleton v-if=\"loading\" text :repeat=\"6\" />\n      <template v-else>\n        Lorem ipsum dolor sit amet,<br>\n        consectetur adipiscing elit,<br>\n        sed do eiusmod tempor incididunt<br>\n        ut labore et dolore magna aliqua.<br>\n        Ut enim ad minim veniam,<br>\n        quis nostrud exercitation ullamco\n      </template>\n    </n-card>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/card/demos/enUS/no-title.demo.vue",
    "content": "<markdown>\n# No title\n\nNobody said a card must have a title.\n</markdown>\n\n<template>\n  <n-card>No title</n-card>\n</template>\n"
  },
  {
    "path": "src/card/demos/enUS/segment.demo.vue",
    "content": "<markdown>\n# Segmented\n\n`content`, `footer` can be segmented or `soft` segmented. `action` can be segmented. Segment border will appear at the top of segmented parts.\n</markdown>\n\n<template>\n  <n-card\n    title=\"Card Segmented Demo\"\n    :segmented=\"{\n      content: true,\n      footer: 'soft',\n    }\"\n  >\n    <template #header-extra>\n      #header-extra\n    </template>\n    Card Content\n    <template #footer>\n      #footer\n    </template>\n    <template #action>\n      #action\n    </template>\n  </n-card>\n</template>\n"
  },
  {
    "path": "src/card/demos/enUS/size.demo.vue",
    "content": "<markdown>\n# Size\n\nCard has `small`, `medium`, `large`, `huge` sizes.\n</markdown>\n\n<template>\n  <n-space vertical>\n    <n-card title=\"Small Card\" size=\"small\">\n      Card Content\n    </n-card>\n    <n-card title=\"Medium Card\" size=\"medium\">\n      Card Content\n    </n-card>\n    <n-card title=\"Large Card\" size=\"large\">\n      Card Content\n    </n-card>\n    <n-card title=\"Huge Card\" size=\"huge\">\n      Card Content\n    </n-card>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/card/demos/enUS/slots.demo.vue",
    "content": "<markdown>\n# Slots\n\nCard has many slots to help you write less code.\n</markdown>\n\n<template>\n  <n-card title=\"Card Slots Demo\">\n    <template #header-extra>\n      #header-extra\n    </template>\n    Card Content\n    <template #footer>\n      #footer\n    </template>\n    <template #action>\n      #action\n    </template>\n  </n-card>\n</template>\n"
  },
  {
    "path": "src/card/demos/zhCN/basic.demo.vue",
    "content": "<markdown>\n# 基础用法\n\n基础卡片\n</markdown>\n\n<template>\n  <n-card title=\"卡片\">\n    卡片内容\n  </n-card>\n</template>\n\n<style>\n.n-card {\n  max-width: 300px;\n}\n</style>\n"
  },
  {
    "path": "src/card/demos/zhCN/border.demo.vue",
    "content": "<markdown>\n# 边框\n\n卡片可以没有边框。\n</markdown>\n\n<template>\n  <n-card :bordered=\"false\" title=\"无边框的卡片\">\n    卡片内容\n  </n-card>\n</template>\n"
  },
  {
    "path": "src/card/demos/zhCN/closable.demo.vue",
    "content": "<markdown>\n# 可关闭\n\n用于 Modal 的时候，你可能需要这个属性。\n</markdown>\n\n<script setup lang=\"ts\">\nimport { useMessage } from 'naive-ui'\n\nconst message = useMessage()\nfunction handleClose() {\n  message.info('Card Close')\n}\n</script>\n\n<template>\n  <n-card title=\"卡片\" closable @close=\"handleClose\">\n    卡片内容\n  </n-card>\n</template>\n\n<style>\n.n-card {\n  max-width: 300px;\n}\n</style>\n"
  },
  {
    "path": "src/card/demos/zhCN/content-scrollable.demo.vue",
    "content": "<markdown>\n# 内容滚动\n\n开启 `content-scrollable` 后，卡片会把滚动限制在内容区，头部和底部不会跟着滚动。通常配合固定高度使用。\n</markdown>\n\n<template>\n  <n-card\n    title=\"任务列表\"\n    content-scrollable\n    style=\"max-height: 280px\"\n    segmented\n  >\n    <p v-for=\"i in 20\" :key=\"i\" style=\"margin: 0 0 8px 0\">\n      第 {{ i }} 条任务：只滚动内容区域。\n    </p>\n    <template #footer>\n      固定在底部的操作区\n    </template>\n  </n-card>\n</template>\n"
  },
  {
    "path": "src/card/demos/zhCN/cover.demo.vue",
    "content": "<markdown>\n# 封面\n\n卡片可以有封面。\n</markdown>\n\n<template>\n  <n-card title=\"带封面的卡片\">\n    <template #cover>\n      <img src=\"https://07akioni.oss-cn-beijing.aliyuncs.com/07akioni.jpeg\">\n    </template>\n    卡片内容\n  </n-card>\n</template>\n\n<style>\n.n-card {\n  max-width: 300px;\n}\n</style>\n"
  },
  {
    "path": "src/card/demos/zhCN/custom-style.demo.vue",
    "content": "<markdown>\n# 自定义样式\n\n卡片提供 `content-style`、`header-style`、`footer-style` 来帮助你自定义样式，比如你想要一个没有 padding 的卡片来往里面放一些乱七八糟的东西。\n</markdown>\n\n<template>\n  <n-card content-style=\"padding: 0;\">\n    <n-tabs\n      type=\"line\"\n      size=\"large\"\n      :tabs-padding=\"20\"\n      pane-style=\"padding: 20px;\"\n    >\n      <n-tab-pane name=\"PARKLIFE\">\n        PARKLIFE\n      </n-tab-pane>\n      <n-tab-pane name=\"ROCKLIFE\">\n        ROCKLIFE\n      </n-tab-pane>\n    </n-tabs>\n  </n-card>\n</template>\n"
  },
  {
    "path": "src/card/demos/zhCN/embedded-debug.demo.vue",
    "content": "<markdown>\n# embedded debug\n</markdown>\n\n<script setup lang=\"ts\">\nimport { ref } from 'vue'\n\nconst showModal = ref(false)\n</script>\n\n<template>\n  <n-button @click=\"showModal = true\">\n    来吧\n  </n-button>\n  <n-modal v-model:show=\"showModal\" preset=\"dialog\" title=\"Dialog\">\n    <n-card title=\"卡片\" embedded>\n      卡片内容\n    </n-card>\n  </n-modal>\n</template>\n"
  },
  {
    "path": "src/card/demos/zhCN/embedded.demo.vue",
    "content": "<markdown>\n# 嵌入效果\n\n在亮色模式下，有的时候你希望背景色暗一点，来和纯色背景分割。\n</markdown>\n\n<template>\n  <n-card title=\"📖 如何成功\" embedded :bordered=\"false\">\n    如果你年轻的时候不 996，你什么时候可以 996？你一辈子没有\n    996，你觉得你就很骄傲了？这个世界上，我们每一个人都希望成功，都希望美好生活，都希望被尊重，我请问大家，你不付出超越别人的努力和时间，你怎么能够实现你想要的成功？\n  </n-card>\n</template>\n\n<style>\n.n-card {\n  max-width: 300px;\n}\n</style>\n"
  },
  {
    "path": "src/card/demos/zhCN/hoverable.demo.vue",
    "content": "<markdown>\n# 可悬浮\n</markdown>\n\n<template>\n  <n-card title=\"卡片\" hoverable>\n    卡片内容\n  </n-card>\n</template>\n\n<style>\n.n-card {\n  max-width: 300px;\n}\n</style>\n"
  },
  {
    "path": "src/card/demos/zhCN/index.demo-entry.md",
    "content": "# 卡片 Card\n\n放点东西进去。\n\n## 演示\n\n```demo\nbasic.vue\nsize.vue\ncover.vue\nhoverable.vue\nslots.vue\nborder.vue\nsegment.vue\nclosable.vue\nno-title.vue\ncontent-scrollable.vue\nloading.vue\ncustom-style.vue\nembedded.vue\nrtl-debug.vue\nembedded-debug.vue\n```\n\n## API\n\n### Card Props\n\n| 名称 | 类型 | 默认值 | 说明 | 版本 |\n| --- | --- | --- | --- | --- |\n| action | `() => VNodeChild` | `undefined` | 操作区域内容，需要是 render 函数 | 2.38.2 |\n| bordered | `boolean` | `true` | 是否显示卡片边框 |  |\n| closable | `boolean` | `false` | 是否允许关闭 |  |\n| close-focusable | `boolean` | `false` | 关闭按钮是否可以聚焦 | 2.43.0 |\n| content | `string \\| (() => VNodeChild)` | `undefined` | 卡片内容，可以是 render 函数 | 2.38.2 |\n| content-class | `string` | `undefined` | 卡片内容区域的类名 | 2.36.0 |\n| content-scrollable | `boolean` | `false` | 是否仅让卡片内容区域可滚动（建议配合固定高度） | 2.44.0 |\n| content-style | `Object \\| string` | `undefined` | 卡片内容区域的样式 |  |\n| cover | `() => VNodeChild` | `undefined` | 覆盖内容，需要是 render 函数 | 2.38.2 |\n| embedded | `boolean` | `false` | 使用更深的背景色展现嵌入效果，只对亮色主题生效 |  |\n| footer | `() => VNodeChild` | `undefined` | 底部内容 | 2.38.2 |\n| footer-class | `string` | `undefined` | 卡片底部区域的类名 | 2.36.0 |\n| footer-style | `Object \\| string` | `undefined` | 卡片底部区域的样式 |  |\n| header-class | `string` | `undefined` | 卡片头部区域的类名 | 2.36.0 |\n| header-style | `Object \\| string` | `undefined` | 卡片头部区域的样式 |  |\n| header-extra | `() => VNodeChild` | `undefined` | 头部额外内容，需要是 render 函数 | 2.38.2 |\n| header-extra-class | `string` | `undefined` | 卡片头部额外内容的类名 | 2.36.0 |\n| header-extra-style | `Object \\| string` | `undefined` | 卡片头部额外内容的样式 | 2.25.0 |\n| hoverable | `boolean` | `false` | 卡片是否可悬浮 |  |\n| segmented | `boolean \\| { [part in 'content' \\| 'footer' \\| 'action']?: boolean \\| 'soft' }` | `false` | 卡片的分段区域设置 |  |\n| size | `'small' \\| 'medium' \\| 'large' \\| 'huge'` | `'medium'` | 卡片的尺寸 |  |\n| tag | `string` | `'div'` | 卡片组件要渲染为什么标签 | 2.34.3 |\n| title | `string \\| (() => VNodeChild)` | `undefined` | 卡片的标题，可以是 render 函数 | 2.38.2 支持 render 函数 |\n| on-close | `() => void` | `undefined` | 点击卡片关闭图标时的回调 |  |\n\n### Card Slots\n\n| 名称         | 参数 | 说明         |\n| ------------ | ---- | ------------ |\n| cover        | `()` | 覆盖内容     |\n| header       | `()` | 头部内容     |\n| header-extra | `()` | 头部额外内容 |\n| default      | `()` | 卡片内容     |\n| footer       | `()` | 底部内容     |\n| action       | `()` | 操作区域内容 |\n"
  },
  {
    "path": "src/card/demos/zhCN/loading.demo.vue",
    "content": "<markdown>\n# 加载中\n\n使用 `n-skeleton` 模拟加载效果。\n</markdown>\n\n<script setup lang=\"ts\">\nimport { ref } from 'vue'\n\nconst loading = ref(true)\n</script>\n\n<template>\n  <n-space vertical>\n    <n-switch v-model:value=\"loading\" />\n    <n-card>\n      <template #header>\n        <n-skeleton v-if=\"loading\" text width=\"60%\" />\n        <template v-else>\n          I'm OK\n        </template>\n      </template>\n      <n-skeleton v-if=\"loading\" text :repeat=\"6\" />\n      <template v-else>\n        不要忘了留姓名<br>\n        电话和其他事情<br>\n        不要说的太快免得我没写下你大名<br>\n        或许你不再打来<br>\n        我却等到头发白<br>\n        希望有一天你会打来\n      </template>\n    </n-card>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/card/demos/zhCN/no-title.demo.vue",
    "content": "<markdown>\n# 没有标题\n\n谁说卡片一定要有标题呢。\n</markdown>\n\n<template>\n  <n-card>没有标题</n-card>\n</template>\n"
  },
  {
    "path": "src/card/demos/zhCN/rtl-debug.demo.vue",
    "content": "<markdown>\n# Rtl Debug\n</markdown>\n\n<script setup lang=\"ts\">\nimport { unstableCardRtl } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst rtlEnabled = ref(false)\nconst rtlStyles = [unstableCardRtl]\n</script>\n\n<template>\n  <n-space vertical>\n    <n-space><n-switch v-model:value=\"rtlEnabled\" />Rtl</n-space>\n    <n-config-provider :rtl=\"rtlEnabled ? rtlStyles : undefined\">\n      <n-card closable>\n        <template #header>\n          Rtl Header Test\n        </template>\n        <template #header-extra>\n          Rtl Header Extra Test\n        </template>\n        Rtl Content Test\n        <template #footer>\n          Rtl Header Test\n        </template>\n        <template #action>\n          Rtl Action Test\n        </template>\n      </n-card>\n    </n-config-provider>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/card/demos/zhCN/segment.demo.vue",
    "content": "<markdown>\n# 分段\n\n`content` 和 `footer` 可以被分段或 `soft` 分段，`action` 可以被分段。分段分割线会在区域的上方出现。\n</markdown>\n\n<template>\n  <n-card\n    title=\"卡片分段示例\"\n    :segmented=\"{\n      content: true,\n      footer: 'soft',\n    }\"\n  >\n    <template #header-extra>\n      #header-extra\n    </template>\n    卡片内容\n    <template #footer>\n      #footer\n    </template>\n    <template #action>\n      #action\n    </template>\n  </n-card>\n</template>\n"
  },
  {
    "path": "src/card/demos/zhCN/size.demo.vue",
    "content": "<markdown>\n# 尺寸\n\n卡片有 `small`、`medium`、`large`、`huge` 尺寸。\n</markdown>\n\n<template>\n  <n-space vertical>\n    <n-card title=\"小卡片\" size=\"small\">\n      卡片内容\n    </n-card>\n    <n-card title=\"中卡片\" size=\"medium\">\n      卡片内容\n    </n-card>\n    <n-card title=\"大卡片\" size=\"large\">\n      卡片内容\n    </n-card>\n    <n-card title=\"超大卡片\" size=\"huge\">\n      卡片内容\n    </n-card>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/card/demos/zhCN/slots.demo.vue",
    "content": "<markdown>\n# 插槽\n\n卡片有很多插槽，希望能帮你少写点代码。\n</markdown>\n\n<template>\n  <n-card title=\"卡片插槽示例\">\n    <template #header-extra>\n      #header-extra\n    </template>\n    卡片内容\n    <template #footer>\n      #footer\n    </template>\n    <template #action>\n      #action\n    </template>\n  </n-card>\n</template>\n"
  },
  {
    "path": "src/card/index.ts",
    "content": "export { cardProps, default as NCard } from './src/Card'\nexport type { CardProps, CardSegmented, CardSlots } from './src/Card'\nexport type * from './src/public-types'\n"
  },
  {
    "path": "src/card/src/Card.tsx",
    "content": "import type { CSSProperties, PropType, SlotsType, VNode, VNodeChild } from 'vue'\nimport type { ThemeProps } from '../../_mixins'\nimport type { ExtractPublicPropTypes, MaybeArray } from '../../_utils'\nimport type { CardTheme } from '../styles'\nimport type { CardSize } from './public-types'\nimport { getPadding } from 'seemly'\nimport { computed, defineComponent, h } from 'vue'\nimport { NBaseClose, NScrollbar } from '../../_internal'\nimport { useConfig, useTheme, useThemeClass } from '../../_mixins'\nimport { useRtl } from '../../_mixins/use-rtl'\nimport { call, createKey, keysOf, resolveWrappedSlot } from '../../_utils'\nimport { ensureValidVNode } from '../../_utils/vue/resolve-slot'\nimport { cardLight } from '../styles'\nimport style from './styles/index.cssr'\n\nexport interface CardSegmented {\n  content?: boolean | 'soft'\n  footer?: boolean | 'soft'\n  action?: boolean | 'soft'\n}\n\nexport const cardBaseProps = {\n  title: [String, Function] as PropType<string | (() => VNodeChild)>,\n  contentClass: String,\n  contentStyle: [Object, String] as PropType<CSSProperties | string>,\n  contentScrollable: Boolean,\n  headerClass: String,\n  headerStyle: [Object, String] as PropType<CSSProperties | string>,\n  headerExtraClass: String,\n  headerExtraStyle: [Object, String] as PropType<CSSProperties | string>,\n  footerClass: String,\n  footerStyle: [Object, String] as PropType<CSSProperties | string>,\n  embedded: Boolean,\n  segmented: {\n    type: [Boolean, Object] as PropType<boolean | CardSegmented>,\n    default: false\n  },\n  size: String as PropType<CardSize>,\n  bordered: {\n    type: Boolean,\n    default: true\n  },\n  closable: Boolean,\n  hoverable: Boolean,\n  role: String,\n  onClose: [Function, Array] as PropType<MaybeArray<() => void>>,\n  tag: {\n    type: String as PropType<keyof HTMLElementTagNameMap>,\n    default: 'div'\n  },\n  cover: Function as PropType<() => VNodeChild>,\n  content: [String, Function] as PropType<string | (() => VNodeChild)>,\n  footer: Function as PropType<() => VNodeChild>,\n  action: Function as PropType<() => VNodeChild>,\n  headerExtra: Function as PropType<() => VNodeChild>,\n  closeFocusable: Boolean\n} as const\n\nexport const cardBasePropKeys = keysOf(cardBaseProps)\n\nexport const cardProps = {\n  ...(useTheme.props as ThemeProps<CardTheme>),\n  ...cardBaseProps\n}\n\nexport type CardProps = ExtractPublicPropTypes<typeof cardProps>\n\nexport interface CardSlots {\n  default?: () => VNode[]\n  cover?: () => VNode[]\n  header?: () => VNode[]\n  'header-extra'?: () => VNode[]\n  footer?: () => VNode[]\n  action?: () => VNode[]\n}\n\nexport default defineComponent({\n  name: 'Card',\n  props: cardProps,\n  slots: Object as SlotsType<CardSlots>,\n  setup(props) {\n    const handleCloseClick = (): void => {\n      const { onClose } = props\n      if (onClose) {\n        call(onClose)\n      }\n    }\n    const {\n      inlineThemeDisabled,\n      mergedClsPrefixRef,\n      mergedRtlRef,\n      mergedComponentPropsRef\n    } = useConfig(props)\n    const themeRef = useTheme(\n      'Card',\n      '-card',\n      style,\n      cardLight,\n      props,\n      mergedClsPrefixRef\n    )\n    const rtlEnabledRef = useRtl('Card', mergedRtlRef, mergedClsPrefixRef)\n    const mergedSizeRef = computed(() => {\n      return (\n        props.size || mergedComponentPropsRef?.value?.Card?.size || 'medium'\n      )\n    })\n    const cssVarsRef = computed(() => {\n      const mergedSize = mergedSizeRef.value\n      const {\n        self: {\n          color,\n          colorModal,\n          colorTarget,\n          textColor,\n          titleTextColor,\n          titleFontWeight,\n          borderColor,\n          actionColor,\n          borderRadius,\n          lineHeight,\n          closeIconColor,\n          closeIconColorHover,\n          closeIconColorPressed,\n          closeColorHover,\n          closeColorPressed,\n          closeBorderRadius,\n          closeIconSize,\n          closeSize,\n          boxShadow,\n          colorPopover,\n          colorEmbedded,\n          colorEmbeddedModal,\n          colorEmbeddedPopover,\n          [createKey('padding', mergedSize)]: padding,\n          [createKey('fontSize', mergedSize)]: fontSize,\n          [createKey('titleFontSize', mergedSize)]: titleFontSize\n        },\n        common: { cubicBezierEaseInOut }\n      } = themeRef.value\n      const {\n        top: paddingTop,\n        left: paddingLeft,\n        bottom: paddingBottom\n      } = getPadding(padding)\n      return {\n        '--n-bezier': cubicBezierEaseInOut,\n        '--n-border-radius': borderRadius,\n        '--n-color': color,\n        '--n-color-modal': colorModal,\n        '--n-color-popover': colorPopover,\n        '--n-color-embedded': colorEmbedded,\n        '--n-color-embedded-modal': colorEmbeddedModal,\n        '--n-color-embedded-popover': colorEmbeddedPopover,\n        '--n-color-target': colorTarget,\n        '--n-text-color': textColor,\n        '--n-line-height': lineHeight,\n        '--n-action-color': actionColor,\n        '--n-title-text-color': titleTextColor,\n        '--n-title-font-weight': titleFontWeight,\n        '--n-close-icon-color': closeIconColor,\n        '--n-close-icon-color-hover': closeIconColorHover,\n        '--n-close-icon-color-pressed': closeIconColorPressed,\n        '--n-close-color-hover': closeColorHover,\n        '--n-close-color-pressed': closeColorPressed,\n        '--n-border-color': borderColor,\n        '--n-box-shadow': boxShadow,\n        // size\n        '--n-padding-top': paddingTop,\n        '--n-padding-bottom': paddingBottom,\n        '--n-padding-left': paddingLeft,\n        '--n-font-size': fontSize,\n        '--n-title-font-size': titleFontSize,\n        '--n-close-size': closeSize,\n        '--n-close-icon-size': closeIconSize,\n        '--n-close-border-radius': closeBorderRadius\n      }\n    })\n    const themeClassHandle = inlineThemeDisabled\n      ? useThemeClass(\n          'card',\n          computed(() => {\n            return mergedSizeRef.value[0]\n          }),\n          cssVarsRef,\n          props\n        )\n      : undefined\n    return {\n      rtlEnabled: rtlEnabledRef,\n      mergedClsPrefix: mergedClsPrefixRef,\n      mergedTheme: themeRef,\n      handleCloseClick,\n      cssVars: inlineThemeDisabled ? undefined : cssVarsRef,\n      themeClass: themeClassHandle?.themeClass,\n      onRender: themeClassHandle?.onRender\n    }\n  },\n  render() {\n    const {\n      segmented,\n      bordered,\n      hoverable,\n      mergedClsPrefix,\n      rtlEnabled,\n      onRender,\n      embedded,\n      tag: Component,\n      $slots\n    } = this\n    onRender?.()\n    return (\n      <Component\n        class={[\n          `${mergedClsPrefix}-card`,\n          this.themeClass,\n          embedded && `${mergedClsPrefix}-card--embedded`,\n          {\n            [`${mergedClsPrefix}-card--rtl`]: rtlEnabled,\n            [`${mergedClsPrefix}-card--content-scrollable`]:\n              this.contentScrollable,\n            [`${mergedClsPrefix}-card--content${\n              typeof segmented !== 'boolean' && segmented.content === 'soft'\n                ? '-soft'\n                : ''\n            }-segmented`]:\n              segmented === true || (segmented !== false && segmented.content),\n            [`${mergedClsPrefix}-card--footer${\n              typeof segmented !== 'boolean' && segmented.footer === 'soft'\n                ? '-soft'\n                : ''\n            }-segmented`]:\n              segmented === true || (segmented !== false && segmented.footer),\n            [`${mergedClsPrefix}-card--action-segmented`]:\n              segmented === true || (segmented !== false && segmented.action),\n            [`${mergedClsPrefix}-card--bordered`]: bordered,\n            [`${mergedClsPrefix}-card--hoverable`]: hoverable\n          }\n        ]}\n        style={this.cssVars as CSSProperties}\n        role={this.role}\n      >\n        {resolveWrappedSlot($slots.cover, (children) => {\n          const mergedChildren = this.cover\n            ? ensureValidVNode([this.cover()])\n            : children\n          return (\n            mergedChildren && (\n              <div class={`${mergedClsPrefix}-card-cover`} role=\"none\">\n                {mergedChildren}\n              </div>\n            )\n          )\n        })}\n        {resolveWrappedSlot($slots.header, (children) => {\n          const { title } = this\n          const mergedChildren = title\n            ? ensureValidVNode(\n                typeof title === 'function' ? [title()] : [title]\n              )\n            : children\n          return mergedChildren || this.closable ? (\n            <div\n              class={[`${mergedClsPrefix}-card-header`, this.headerClass]}\n              style={this.headerStyle}\n              role=\"heading\"\n            >\n              <div\n                class={`${mergedClsPrefix}-card-header__main`}\n                role=\"heading\"\n              >\n                {mergedChildren}\n              </div>\n              {resolveWrappedSlot($slots['header-extra'], (children) => {\n                const mergedChildren = this.headerExtra\n                  ? ensureValidVNode([this.headerExtra()])\n                  : children\n                return (\n                  mergedChildren && (\n                    <div\n                      class={[\n                        `${mergedClsPrefix}-card-header__extra`,\n                        this.headerExtraClass\n                      ]}\n                      style={this.headerExtraStyle}\n                    >\n                      {mergedChildren}\n                    </div>\n                  )\n                )\n              })}\n              {this.closable && (\n                <NBaseClose\n                  clsPrefix={mergedClsPrefix}\n                  class={`${mergedClsPrefix}-card-header__close`}\n                  onClick={this.handleCloseClick}\n                  focusable={this.closeFocusable}\n                  absolute\n                />\n              )}\n            </div>\n          ) : null\n        })}\n        {resolveWrappedSlot($slots.default, (children) => {\n          const { content } = this\n          const mergedChildren = content\n            ? ensureValidVNode(\n                typeof content === 'function' ? [content()] : [content]\n              )\n            : children\n          return mergedChildren ? (\n            this.contentScrollable ? (\n              <NScrollbar\n                class={`${mergedClsPrefix}-card__content-scrollbar`}\n                contentClass={[\n                  `${mergedClsPrefix}-card-content`,\n                  this.contentClass\n                ]}\n                contentStyle={this.contentStyle}\n              >\n                {mergedChildren}\n              </NScrollbar>\n            ) : (\n              <div\n                class={[`${mergedClsPrefix}-card-content`, this.contentClass]}\n                style={this.contentStyle}\n                role=\"none\"\n              >\n                {mergedChildren}\n              </div>\n            )\n          ) : null\n        })}\n        {resolveWrappedSlot($slots.footer, (children) => {\n          const mergedChildren = this.footer\n            ? ensureValidVNode([this.footer()])\n            : children\n          return (\n            mergedChildren && (\n              <div\n                class={[`${mergedClsPrefix}-card__footer`, this.footerClass]}\n                style={this.footerStyle}\n                role=\"none\"\n              >\n                {mergedChildren}\n              </div>\n            )\n          )\n        })}\n        {resolveWrappedSlot($slots.action, (children) => {\n          const mergedChildren = this.action\n            ? ensureValidVNode([this.action()])\n            : children\n          return (\n            mergedChildren && (\n              <div class={`${mergedClsPrefix}-card__action`} role=\"none\">\n                {mergedChildren}\n              </div>\n            )\n          )\n        })}\n      </Component>\n    )\n  }\n})\n"
  },
  {
    "path": "src/card/src/public-types.ts",
    "content": "export type CardSize = 'small' | 'medium' | 'large' | 'huge'\n"
  },
  {
    "path": "src/card/src/styles/index.cssr.ts",
    "content": "import { asModal, c, cB, cE, cM, insideModal, insidePopover } from '../../../_utils/cssr'\n\nconst contentBaseStyle = cB('card-content', `\n  flex: 1;\n  min-width: 0;\n  box-sizing: border-box;\n  padding: 0 var(--n-padding-left) var(--n-padding-bottom) var(--n-padding-left);\n  font-size: var(--n-font-size);\n`)\n\n// vars:\n// --n-bezier\n// --n-border-radius\n// --n-color\n// --n-color-modal\n// --n-color-popover\n// --n-text-color\n// --n-line-height\n// --n-padding-top\n// --n-padding-bottom\n// --n-padding-left\n// --n-font-size\n// --n-action-color\n// --n-title-font-weight\n// --n-title-font-size\n// --n-title-text-color\n// --n-close-size\n// --n-close-icon-size\n// --n-close-color-hover\n// --n-close-color-pressed\n// --n-close-icon-color\n// --n-close-icon-color-hover\n// --n-close-icon-color-pressed\n// --n-border-color\n// --n-box-shadow\n// --n-color-embedded\n// --n-color-embedded-modal\n// --n-color-embedded-popover\nexport default c([\n  cB('card', `\n    font-size: var(--n-font-size);\n    line-height: var(--n-line-height);\n    display: flex;\n    flex-direction: column;\n    width: 100%;\n    box-sizing: border-box;\n    position: relative;\n    border-radius: var(--n-border-radius);\n    background-color: var(--n-color);\n    color: var(--n-text-color);\n    word-break: break-word;\n    transition: \n      color .3s var(--n-bezier),\n      background-color .3s var(--n-bezier),\n      box-shadow .3s var(--n-bezier),\n      border-color .3s var(--n-bezier);\n  `, [\n    asModal({\n      background: 'var(--n-color-modal)'\n    }),\n    cM('hoverable', [\n      c('&:hover', 'box-shadow: var(--n-box-shadow);')\n    ]),\n    cM('content-segmented', [\n      c('>', [\n        cB('card-content', `\n          padding-top: var(--n-padding-bottom);\n        `),\n        cE('content-scrollbar', [\n          c('>', [\n            cB('scrollbar-container', [\n              c('>', [\n                cB('card-content', `\n                  padding-top: var(--n-padding-bottom);\n                `)\n              ])\n            ])\n          ])\n        ])\n      ])\n    ]),\n    cM('content-soft-segmented', [\n      c('>', [\n        cB('card-content', `\n          margin: 0 var(--n-padding-left);\n          padding: var(--n-padding-bottom) 0;\n        `),\n        cE('content-scrollbar', [\n          c('>', [\n            cB('scrollbar-container', [\n              c('>', [\n                cB('card-content', `\n                  margin: 0 var(--n-padding-left);\n                  padding: var(--n-padding-bottom) 0;\n                `)\n              ])\n            ])\n          ])\n        ])\n      ])\n    ]),\n    cM('footer-segmented', [\n      c('>', [\n        cE('footer', `\n          padding-top: var(--n-padding-bottom);\n        `)\n      ])\n    ]),\n    cM('footer-soft-segmented', [\n      c('>', [\n        cE('footer', `\n          padding: var(--n-padding-bottom) 0;\n          margin: 0 var(--n-padding-left);\n        `)\n      ])\n    ]),\n    c('>', [\n      cB('card-header', `\n        box-sizing: border-box;\n        display: flex;\n        align-items: center;\n        font-size: var(--n-title-font-size);\n        padding:\n          var(--n-padding-top)\n          var(--n-padding-left)\n          var(--n-padding-bottom)\n          var(--n-padding-left);\n      `, [\n        cE('main', `\n          font-weight: var(--n-title-font-weight);\n          transition: color .3s var(--n-bezier);\n          flex: 1;\n          min-width: 0;\n          color: var(--n-title-text-color);\n        `),\n        cE('extra', `\n          display: flex;\n          align-items: center;\n          font-size: var(--n-font-size);\n          font-weight: 400;\n          transition: color .3s var(--n-bezier);\n          color: var(--n-text-color);\n        `),\n        cE('close', `\n          margin: 0 0 0 8px;\n          transition:\n            background-color .3s var(--n-bezier),\n            color .3s var(--n-bezier);\n        `)\n      ]),\n      cE('action', `\n        box-sizing: border-box;\n        transition:\n          background-color .3s var(--n-bezier),\n          border-color .3s var(--n-bezier);\n        background-clip: padding-box;\n        background-color: var(--n-action-color);\n      `),\n      contentBaseStyle,\n      cB('card-content', [\n        c('&:first-child', `\n          padding-top: var(--n-padding-bottom);\n        `)\n      ]),\n      cE('content-scrollbar', `\n        display: flex;\n        flex-direction: column;\n      `, [\n        c('>', [\n          cB('scrollbar-container', [\n            c('>', [\n              contentBaseStyle\n            ])\n          ])\n        ]),\n        c('&:first-child >', [\n          cB('scrollbar-container', [\n            c('>', [\n              cB('card-content', `\n                padding-top: var(--n-padding-bottom);\n              `)\n            ])\n          ])\n        ])\n      ]),\n      cE('footer', `\n        box-sizing: border-box;\n        padding: 0 var(--n-padding-left) var(--n-padding-bottom) var(--n-padding-left);\n        font-size: var(--n-font-size);\n      `, [\n        c('&:first-child', `\n          padding-top: var(--n-padding-bottom);\n        `)\n      ]),\n      cE('action', `\n        background-color: var(--n-action-color);\n        padding: var(--n-padding-bottom) var(--n-padding-left);\n        border-bottom-left-radius: var(--n-border-radius);\n        border-bottom-right-radius: var(--n-border-radius);\n      `)\n    ]),\n    cB('card-cover', `\n      overflow: hidden;\n      width: 100%;\n      border-radius: var(--n-border-radius) var(--n-border-radius) 0 0;\n    `, [\n      c('img', `\n        display: block;\n        width: 100%;\n      `)\n    ]),\n    cM('bordered', `\n      border: 1px solid var(--n-border-color);\n    `, [\n      c('&:target', 'border-color: var(--n-color-target);')\n    ]),\n    cM('action-segmented', [\n      c('>', [\n        cE('action', [\n          c('&:not(:first-child)', `\n            border-top: 1px solid var(--n-border-color);\n          `)\n        ])\n      ])\n    ]),\n    cM('content-segmented, content-soft-segmented', [\n      c('>', [\n        cB('card-content', `\n          transition: border-color 0.3s var(--n-bezier);\n        `, [\n          c('&:not(:first-child)', `\n            border-top: 1px solid var(--n-border-color);\n          `)\n        ]),\n        cE('content-scrollbar', `\n          transition: border-color 0.3s var(--n-bezier);\n        `, [\n          c('&:not(:first-child)', `\n            border-top: 1px solid var(--n-border-color);\n          `)\n        ])\n      ])\n    ]),\n    cM('footer-segmented, footer-soft-segmented', [\n      c('>', [\n        cE('footer', `\n          transition: border-color 0.3s var(--n-bezier);\n        `, [\n          c('&:not(:first-child)', `\n            border-top: 1px solid var(--n-border-color);\n          `)\n        ])\n      ])\n    ]),\n    cM('embedded', `\n      background-color: var(--n-color-embedded);\n    `)\n  ]),\n  insideModal(cB('card', `\n    background: var(--n-color-modal);\n  `, [\n    cM('embedded', `\n      background-color: var(--n-color-embedded-modal);\n    `)\n  ])),\n  insidePopover(cB('card', `\n    background: var(--n-color-popover);\n  `, [\n    cM('embedded', `\n      background-color: var(--n-color-embedded-popover);\n    `)\n  ]))\n])\n"
  },
  {
    "path": "src/card/src/styles/rtl.cssr.ts",
    "content": "import { c, cB, cE, cM } from '../../../_utils/cssr'\n\nexport default cB('card', [\n  cM('rtl', `\n    direction: rtl;\n  `),\n  c('>', [\n    cB('card-header', [\n      c('>', [\n        cE('close', `\n          margin: 0 8px 0 0;\n        `)\n      ])\n    ])\n  ])\n])\n"
  },
  {
    "path": "src/card/styles/_common.ts",
    "content": "export default {\n  paddingSmall: '12px 16px 12px',\n  paddingMedium: '19px 24px 20px',\n  paddingLarge: '23px 32px 24px',\n  paddingHuge: '27px 40px 28px',\n  titleFontSizeSmall: '16px',\n  titleFontSizeMedium: '18px',\n  titleFontSizeLarge: '18px',\n  titleFontSizeHuge: '18px',\n  closeIconSize: '18px',\n  closeSize: '22px'\n}\n"
  },
  {
    "path": "src/card/styles/dark.ts",
    "content": "import type { CardTheme } from './light'\nimport { commonDark } from '../../_styles/common'\nimport { self } from './light'\n\nconst cardDark: CardTheme = {\n  name: 'Card',\n  common: commonDark,\n  self(vars) {\n    const commonSelf = self(vars)\n    const { cardColor, modalColor, popoverColor } = vars\n    commonSelf.colorEmbedded = cardColor\n    commonSelf.colorEmbeddedModal = modalColor\n    commonSelf.colorEmbeddedPopover = popoverColor\n    return commonSelf\n  }\n}\n\nexport default cardDark\n"
  },
  {
    "path": "src/card/styles/index.ts",
    "content": "export { default as cardDark } from './dark'\nexport { default as cardLight } from './light'\nexport type { CardTheme, CardThemeVars } from './light'\nexport { cardRtl } from './rtl'\n"
  },
  {
    "path": "src/card/styles/light.ts",
    "content": "import type { Theme } from '../../_mixins'\nimport type { ThemeCommonVars } from '../../_styles/common'\nimport { commonLight } from '../../_styles/common'\nimport commonVariables from './_common'\n\nexport function self(vars: ThemeCommonVars) {\n  const {\n    primaryColor,\n    borderRadius,\n    lineHeight,\n    fontSize,\n    cardColor,\n    textColor2,\n    textColor1,\n    dividerColor,\n    fontWeightStrong,\n    closeIconColor,\n    closeIconColorHover,\n    closeIconColorPressed,\n    closeColorHover,\n    closeColorPressed,\n    modalColor,\n    boxShadow1,\n    popoverColor,\n    actionColor\n  } = vars\n  return {\n    ...commonVariables,\n    lineHeight,\n    color: cardColor,\n    colorModal: modalColor,\n    colorPopover: popoverColor,\n    colorTarget: primaryColor,\n    colorEmbedded: actionColor,\n    colorEmbeddedModal: actionColor,\n    colorEmbeddedPopover: actionColor,\n    textColor: textColor2,\n    titleTextColor: textColor1,\n    borderColor: dividerColor,\n    actionColor,\n    titleFontWeight: fontWeightStrong,\n    closeColorHover,\n    closeColorPressed,\n    closeBorderRadius: borderRadius,\n    closeIconColor,\n    closeIconColorHover,\n    closeIconColorPressed,\n    fontSizeSmall: fontSize,\n    fontSizeMedium: fontSize,\n    fontSizeLarge: fontSize,\n    fontSizeHuge: fontSize,\n    boxShadow: boxShadow1,\n    borderRadius\n  }\n}\n\nexport type CardThemeVars = ReturnType<typeof self>\n\nconst cardLight: Theme<'Card', CardThemeVars> = {\n  name: 'Card',\n  common: commonLight,\n  self\n}\n\nexport default cardLight\nexport type CardTheme = typeof cardLight\n"
  },
  {
    "path": "src/card/styles/rtl.ts",
    "content": "import type { RtlItem } from '../../config-provider/src/internal-interface'\nimport rtlStyle from '../src/styles/rtl.cssr'\n\nexport const cardRtl: RtlItem = {\n  name: 'Card',\n  style: rtlStyle\n}\n"
  },
  {
    "path": "src/card/tests/Card.spec.ts",
    "content": "import { mount } from '@vue/test-utils'\nimport { NCard } from '../index'\n\ndescribe('n-card', () => {\n  it('should work with import on demand', () => {\n    mount(NCard)\n  })\n\n  it('should work with `title` prop', async () => {\n    const wrapper = mount(NCard)\n\n    expect(wrapper.find('.n-card-header').exists()).toBe(false)\n\n    await wrapper.setProps({ title: 'test' })\n    expect(wrapper.find('.n-card-header').exists()).toBe(true)\n    expect(wrapper.find('.n-card-header__main').text()).toBe('test')\n    wrapper.unmount()\n  })\n\n  it('should work with `size` prop', async () => {\n    const wrapper = mount(NCard)\n\n    await wrapper.setProps({ size: 'small' })\n    expect(wrapper.find('.n-card').attributes('style')).toMatchSnapshot()\n    wrapper.unmount()\n  })\n\n  it('should work with `hoverable` prop', async () => {\n    const wrapper = mount(NCard, {\n      props: {\n        hoverable: true\n      }\n    })\n\n    expect(wrapper.find('.n-card').classes()).toContain('n-card--hoverable')\n    wrapper.unmount()\n  })\n\n  it('should work with `embedded` prop', async () => {\n    const wrapper = mount(NCard)\n\n    expect(wrapper.find('.n-card').attributes('style')).toContain(\n      '--n-color: #fff'\n    )\n    await wrapper.setProps({ embedded: true })\n    expect(wrapper.find('.n-card').attributes('style')).toContain(\n      '--n-color-embedded: rgb(250, 250, 252)'\n    )\n    wrapper.unmount()\n  })\n\n  it('should work with `segmented` prop', async () => {\n    const wrapper = mount(NCard)\n    expect(wrapper.find('.n-card').classes()).not.toContain(\n      'n-card--content-segmented'\n    )\n\n    await wrapper.setProps({\n      segmented: {\n        content: true,\n        footer: 'soft'\n      }\n    })\n    expect(wrapper.find('.n-card').classes()).toContain(\n      'n-card--content-segmented'\n    )\n    wrapper.unmount()\n  })\n\n  it('should work with `slots` ', async () => {\n    const wrapper = mount(NCard, {\n      slots: {\n        cover: () => 'cover',\n        header: () => 'header',\n        'header-extra': () => 'header-extra',\n        default: () => 'content',\n        footer: () => 'footer',\n        action: () => 'action'\n      }\n    })\n\n    expect(wrapper.find('.n-card-cover').exists()).toBe(true)\n    expect(wrapper.find('.n-card-cover').text()).toBe('cover')\n\n    expect(wrapper.find('.n-card-header').exists()).toBe(true)\n    expect(wrapper.find('.n-card-header__main').text()).toBe('header')\n\n    expect(wrapper.find('.n-card-header__extra').exists()).toBe(true)\n    expect(wrapper.find('.n-card-header__extra').text()).toBe('header-extra')\n\n    expect(wrapper.find('.n-card-content').exists()).toBe(true)\n    expect(wrapper.find('.n-card-content').text()).toBe('content')\n\n    expect(wrapper.find('.n-card__footer').exists()).toBe(true)\n    expect(wrapper.find('.n-card__footer').text()).toBe('footer')\n\n    expect(wrapper.find('.n-card__action').exists()).toBe(true)\n    expect(wrapper.find('.n-card__action').text()).toBe('action')\n    wrapper.unmount()\n  })\n\n  it('should work with `bordered` prop', async () => {\n    const wrapper = mount(NCard, {\n      props: {\n        bordered: false\n      }\n    })\n\n    expect(wrapper.find('.n-card--bordered').exists()).toBe(false)\n    wrapper.unmount()\n  })\n\n  it('should work with `closable` and `on-close` prop', async () => {\n    const onClose = vi.fn()\n    const wrapper = mount(NCard, {\n      props: {\n        closable: true,\n        onClose\n      }\n    })\n\n    expect(wrapper.find('.n-card-header__close').exists()).toBe(true)\n    await wrapper.find('.n-card-header__close').trigger('click')\n    expect(onClose).toHaveBeenCalled()\n    wrapper.unmount()\n  })\n\n  it('should work with `header-style` prop', async () => {\n    const testStyle = 'padding: 0px;'\n    const wrapper = mount(NCard, {\n      props: {\n        title: 'test',\n        headerStyle: testStyle\n      },\n      slots: {\n        default: () => 'test'\n      }\n    })\n\n    expect(wrapper.find('.n-card-header').attributes('style')).toContain(\n      testStyle\n    )\n    wrapper.unmount()\n  })\n\n  it('should work with `content-style` prop', async () => {\n    const testStyle = 'padding: 0px;'\n    const wrapper = mount(NCard, {\n      props: {\n        contentStyle: testStyle\n      },\n      slots: {\n        default: () => 'test'\n      }\n    })\n\n    expect(wrapper.find('.n-card-content').attributes('style')).toContain(\n      testStyle\n    )\n    wrapper.unmount()\n  })\n\n  it('should work with `footer-style` prop', async () => {\n    const testStyle = 'padding: 0px;'\n    const wrapper = mount(NCard, {\n      props: {\n        footerStyle: testStyle\n      },\n      slots: {\n        footer: () => 'test'\n      }\n    })\n\n    expect(wrapper.find('.n-card__footer').attributes('style')).toContain(\n      testStyle\n    )\n    wrapper.unmount()\n  })\n\n  it('should work with `header-extra-style` prop', async () => {\n    const testStyle = 'padding: 0px;'\n    const wrapper = mount(NCard, {\n      props: {\n        headerExtraStyle: testStyle\n      },\n      slots: {\n        header: () => 'test-header',\n        'header-extra': () => 'test-header-extra'\n      }\n    })\n\n    expect(wrapper.find('.n-card-header__extra').attributes('style')).toContain(\n      testStyle\n    )\n    wrapper.unmount()\n  })\n})\n"
  },
  {
    "path": "src/card/tests/__snapshots__/Card.spec.ts.snap",
    "content": "// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html\n\nexports[`n-card > should work with \\`size\\` prop 1`] = `\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-border-radius: 3px; --n-color: #fff; --n-color-modal: #fff; --n-color-popover: #fff; --n-color-embedded: rgb(250, 250, 252); --n-color-embedded-modal: rgb(250, 250, 252); --n-color-embedded-popover: rgb(250, 250, 252); --n-color-target: #18a058; --n-text-color: rgb(51, 54, 57); --n-line-height: 1.6; --n-action-color: rgb(250, 250, 252); --n-title-text-color: rgb(31, 34, 37); --n-title-font-weight: 500; --n-close-icon-color: rgba(102, 102, 102, 1); --n-close-icon-color-hover: rgba(102, 102, 102, 1); --n-close-icon-color-pressed: rgba(102, 102, 102, 1); --n-close-color-hover: rgba(0, 0, 0, .09); --n-close-color-pressed: rgba(0, 0, 0, .13); --n-border-color: rgb(239, 239, 245); --n-box-shadow: 0 1px 2px -2px rgba(0, 0, 0, .08), 0 3px 6px 0 rgba(0, 0, 0, .06), 0 5px 12px 4px rgba(0, 0, 0, .04); --n-padding-top: 12px; --n-padding-bottom: 12px; --n-padding-left: 16px; --n-font-size: 14px; --n-title-font-size: 16px; --n-close-size: 22px; --n-close-icon-size: 18px; --n-close-border-radius: 3px;\"`;\n"
  },
  {
    "path": "src/card/tests/server.spec.tsx",
    "content": "import { setup } from '@css-render/vue3-ssr'\nimport { renderToString } from '@vue/server-renderer'\n/**\n * @vitest-environment node\n */\nimport { createSSRApp, h } from 'vue'\nimport { NCard } from '../..'\n\ndescribe('server side rendering', () => {\n  it('works', async () => {\n    const app = createSSRApp(() => <NCard />)\n    setup(app)\n    try {\n      await renderToString(app)\n    }\n    catch (e) {\n      expect(e).not.toBeTruthy()\n    }\n  })\n})\n"
  },
  {
    "path": "src/carousel/demos/enUS/arrow.demo.vue",
    "content": "<markdown>\n# Arrow\n\nSet `show-arrow` to show the arrow。\n</markdown>\n\n<template>\n  <n-carousel show-arrow>\n    <img\n      class=\"carousel-img\"\n      src=\"https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel1.jpeg\"\n    >\n    <img\n      class=\"carousel-img\"\n      src=\"https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel2.jpeg\"\n    >\n    <img\n      class=\"carousel-img\"\n      src=\"https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel3.jpeg\"\n    >\n    <img\n      class=\"carousel-img\"\n      src=\"https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel4.jpeg\"\n    >\n  </n-carousel>\n</template>\n\n<style>\n.carousel-img {\n  width: 100%;\n  height: 240px;\n  object-fit: cover;\n}\n</style>\n"
  },
  {
    "path": "src/carousel/demos/enUS/autoplay.demo.vue",
    "content": "<markdown>\n# Autoplay\n\nSet `autoplay`, it can autoplay。\n</markdown>\n\n<template>\n  <n-carousel autoplay>\n    <img\n      class=\"carousel-img\"\n      src=\"https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel1.jpeg\"\n    >\n    <img\n      class=\"carousel-img\"\n      src=\"https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel2.jpeg\"\n    >\n    <img\n      class=\"carousel-img\"\n      src=\"https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel3.jpeg\"\n    >\n    <img\n      class=\"carousel-img\"\n      src=\"https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel4.jpeg\"\n    >\n  </n-carousel>\n</template>\n\n<style>\n.carousel-img {\n  width: 100%;\n  height: 240px;\n  object-fit: cover;\n}\n</style>\n"
  },
  {
    "path": "src/carousel/demos/enUS/basic.demo.vue",
    "content": "<markdown>\n# Basic\n</markdown>\n\n<template>\n  <n-carousel>\n    <img\n      class=\"carousel-img\"\n      src=\"https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel1.jpeg\"\n    >\n    <img\n      class=\"carousel-img\"\n      src=\"https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel2.jpeg\"\n    >\n    <img\n      class=\"carousel-img\"\n      src=\"https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel3.jpeg\"\n    >\n    <img\n      class=\"carousel-img\"\n      src=\"https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel4.jpeg\"\n    >\n  </n-carousel>\n</template>\n\n<style>\n.carousel-img {\n  width: 100%;\n  height: 240px;\n  object-fit: cover;\n}\n</style>\n"
  },
  {
    "path": "src/carousel/demos/enUS/centered.demo.vue",
    "content": "<markdown>\n# Centered\n\nSet `centered-slides` to center all `slides`, this is only useful when `effect` is `slide` and `card`.\n</markdown>\n\n<template>\n  <n-carousel\n    :space-between=\"30\"\n    :loop=\"false\"\n    slides-per-view=\"auto\"\n    centered-slides\n    draggable\n  >\n    <n-carousel-item style=\"width: 30%\">\n      <img\n        class=\"carousel-img\"\n        src=\"https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel1.jpeg\"\n      >\n    </n-carousel-item>\n    <n-carousel-item style=\"width: 20%\">\n      <img\n        class=\"carousel-img\"\n        src=\"https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel2.jpeg\"\n      >\n    </n-carousel-item>\n    <n-carousel-item style=\"width: 30%\">\n      <img\n        class=\"carousel-img\"\n        src=\"https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel3.jpeg\"\n      >\n    </n-carousel-item>\n    <n-carousel-item style=\"width: 40%\">\n      <img\n        class=\"carousel-img\"\n        src=\"https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel4.jpeg\"\n      >\n    </n-carousel-item>\n  </n-carousel>\n</template>\n\n<style>\n.carousel-img {\n  width: 100%;\n  height: 240px;\n  object-fit: cover;\n}\n</style>\n"
  },
  {
    "path": "src/carousel/demos/enUS/custom-arrow-and-dots.demo.vue",
    "content": "<markdown>\n# Customzing arrow and dots\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ArrowBack, ArrowForward } from '@vicons/ionicons5'\n</script>\n\n<template>\n  <n-carousel show-arrow autoplay>\n    <img\n      class=\"carousel-img\"\n      src=\"https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel1.jpeg\"\n    >\n    <img\n      class=\"carousel-img\"\n      src=\"https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel2.jpeg\"\n    >\n    <img\n      class=\"carousel-img\"\n      src=\"https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel3.jpeg\"\n    >\n    <img\n      class=\"carousel-img\"\n      src=\"https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel4.jpeg\"\n    >\n    <template #arrow=\"{ prev, next }\">\n      <div class=\"custom-arrow\">\n        <button type=\"button\" class=\"custom-arrow--left\" @click=\"prev\">\n          <n-icon><ArrowBack /></n-icon>\n        </button>\n        <button type=\"button\" class=\"custom-arrow--right\" @click=\"next\">\n          <n-icon><ArrowForward /></n-icon>\n        </button>\n      </div>\n    </template>\n    <template #dots=\"{ total, currentIndex, to }\">\n      <ul class=\"custom-dots\">\n        <li\n          v-for=\"index of total\"\n          :key=\"index\"\n          :class=\"{ ['is-active']: currentIndex === index - 1 }\"\n          @click=\"to(index - 1)\"\n        />\n      </ul>\n    </template>\n  </n-carousel>\n</template>\n\n<style>\n.carousel-img {\n  width: 100%;\n  height: 240px;\n  object-fit: cover;\n}\n\n.custom-arrow {\n  display: flex;\n  position: absolute;\n  bottom: 25px;\n  right: 10px;\n}\n\n.custom-arrow button {\n  display: inline-flex;\n  align-items: center;\n  justify-content: center;\n  width: 28px;\n  height: 28px;\n  margin-right: 12px;\n  color: #fff;\n  background-color: rgba(255, 255, 255, 0.1);\n  border-width: 0;\n  border-radius: 8px;\n  transition: background-color 0.3s cubic-bezier(0.4, 0, 0.2, 1);\n  cursor: pointer;\n}\n\n.custom-arrow button:hover {\n  background-color: rgba(255, 255, 255, 0.2);\n}\n\n.custom-arrow button:active {\n  transform: scale(0.95);\n  transform-origin: center;\n}\n\n.custom-dots {\n  display: flex;\n  margin: 0;\n  padding: 0;\n  position: absolute;\n  bottom: 20px;\n  left: 20px;\n}\n\n.custom-dots li {\n  display: inline-block;\n  width: 12px;\n  height: 4px;\n  margin: 0 3px;\n  border-radius: 4px;\n  background-color: rgba(255, 255, 255, 0.4);\n  transition:\n    width 0.3s,\n    background-color 0.3s cubic-bezier(0.4, 0, 0.2, 1);\n  cursor: pointer;\n}\n\n.custom-dots li.is-active {\n  width: 40px;\n  background: #fff;\n}\n</style>\n"
  },
  {
    "path": "src/carousel/demos/enUS/custom-card.demo.vue",
    "content": "<markdown>\n# Customize card\n\nYou can use `next-slide-style` and `prev-slide-style` to adjust the ratio of front & back cards size ratio.\n</markdown>\n\n<template>\n  <n-carousel\n    effect=\"card\"\n    prev-slide-style=\"transform: translateX(-150%) translateZ(-800px);\"\n    next-slide-style=\"transform: translateX(50%) translateZ(-800px);\"\n    style=\"height: 240px\"\n    :show-dots=\"false\"\n  >\n    <n-carousel-item :style=\"{ width: '60%' }\">\n      <img\n        class=\"carousel-img\"\n        src=\"https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel1.jpeg\"\n      >\n    </n-carousel-item>\n    <n-carousel-item :style=\"{ width: '60%' }\">\n      <img\n        class=\"carousel-img\"\n        src=\"https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel2.jpeg\"\n      >\n    </n-carousel-item>\n    <n-carousel-item :style=\"{ width: '60%' }\">\n      <img\n        class=\"carousel-img\"\n        src=\"https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel3.jpeg\"\n      >\n    </n-carousel-item>\n    <n-carousel-item :style=\"{ width: '60%' }\">\n      <img\n        class=\"carousel-img\"\n        src=\"https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel4.jpeg\"\n      >\n    </n-carousel-item>\n  </n-carousel>\n</template>\n\n<style>\n.carousel-img {\n  margin: 0 auto;\n  width: 100%;\n  height: 100%;\n  object-fit: cover;\n}\n</style>\n"
  },
  {
    "path": "src/carousel/demos/enUS/custom-dots.demo.vue",
    "content": "<markdown>\n# Custom Dots\n</markdown>\n\n<template>\n  <n-carousel autoplay>\n    <img\n      class=\"carousel-img\"\n      src=\"https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel1.jpeg\"\n    >\n    <img\n      class=\"carousel-img\"\n      src=\"https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel2.jpeg\"\n    >\n    <img\n      class=\"carousel-img\"\n      src=\"https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel3.jpeg\"\n    >\n    <img\n      class=\"carousel-img\"\n      src=\"https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel4.jpeg\"\n    >\n    <template #dots=\"{ total, currentIndex }\">\n      <span class=\"custom-dots\"> {{ currentIndex + 1 }} / {{ total }} </span>\n    </template>\n  </n-carousel>\n</template>\n\n<style>\n.carousel-img {\n  width: 100%;\n  height: 240px;\n  object-fit: cover;\n}\n\n.custom-dots {\n  font-size: 12px;\n  transform: translateY(5px);\n}\n</style>\n"
  },
  {
    "path": "src/carousel/demos/enUS/dots.demo.vue",
    "content": "<markdown>\n# Dots\n\nSet `dot-type` to change the style of the dots. You can use `:show-dots=\"false\"` to hide the dots.\n\nSet `dot-placement` to change the position of the dots.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst typeRef = ref<'dot' | 'line'>('dot')\nconst placementRef = ref<'top' | 'bottom' | 'left' | 'right'>('bottom')\nconst directionRef = ref<'horizontal' | 'vertical'>('horizontal')\nconst showArrow = ref(false)\nconst type = typeRef\nconst types = ['dot', 'line']\nconst placement = placementRef\nconst placements = ['top', 'bottom', 'left', 'right']\nconst direction = directionRef\nconst directions = ['horizontal', 'vertical']\n</script>\n\n<template>\n  <n-space vertical>\n    <n-radio-group v-model:value=\"type\">\n      <n-radio-button v-for=\"_type in types\" :key=\"_type\" :value=\"_type\">\n        {{ _type }}\n      </n-radio-button>\n    </n-radio-group>\n    <n-radio-group v-model:value=\"placement\">\n      <n-radio-button\n        v-for=\"_placement in placements\"\n        :key=\"_placement\"\n        :value=\"_placement\"\n      >\n        {{ _placement }}\n      </n-radio-button>\n    </n-radio-group>\n    <n-radio-group v-model:value=\"direction\">\n      <n-radio-button\n        v-for=\"_direction in directions\"\n        :key=\"_direction\"\n        :value=\"_direction\"\n      >\n        {{ _direction }}\n      </n-radio-button>\n    </n-radio-group>\n    <n-switch v-model:value=\"showArrow\">\n      <template #checked>\n        Show arrow\n      </template>\n      <template #unchecked>\n        No arrow\n      </template>\n    </n-switch>\n    <n-carousel\n      :direction=\"direction\"\n      :show-arrow=\"showArrow\"\n      :dot-type=\"type\"\n      :dot-placement=\"placement\"\n      style=\"height: 240px\"\n    >\n      <img\n        class=\"carousel-img\"\n        src=\"https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel1.jpeg\"\n      >\n      <img\n        class=\"carousel-img\"\n        src=\"https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel2.jpeg\"\n      >\n      <img\n        class=\"carousel-img\"\n        src=\"https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel3.jpeg\"\n      >\n      <img\n        class=\"carousel-img\"\n        src=\"https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel4.jpeg\"\n      >\n    </n-carousel>\n  </n-space>\n</template>\n\n<style>\n.carousel-img {\n  width: 100%;\n  height: 100%;\n  object-fit: cover;\n}\n</style>\n"
  },
  {
    "path": "src/carousel/demos/enUS/effect.demo.vue",
    "content": "<markdown>\n# Effect\n\nIf you want to customize the transition effect, you can use `transition-props` and set `effect` to `custom`.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { computed, ref } from 'vue'\n\nconst effectRef = ref<'slide' | 'fade' | 'card'>('slide')\nconst isCardRef = computed(() => effectRef.value === 'card')\nconst isCard = isCardRef\nconst myEffect = effectRef\nconst effects = ['slide', 'fade', 'card']\n</script>\n\n<template>\n  <n-radio-group v-model:value=\"myEffect\" style=\"margin-bottom: 10px\">\n    <n-radio-button v-for=\"effect in effects\" :key=\"effect\" :value=\"effect\">\n      {{ effect }}\n    </n-radio-button>\n  </n-radio-group>\n  <n-carousel\n    :key=\"myEffect\"\n    :effect=\"myEffect\"\n    :centered-slides=\"isCard\"\n    :slides-per-view=\"isCard ? 'auto' : 1\"\n    draggable\n    style=\"height: 240px\"\n  >\n    <n-carousel-item :style=\"{ width: isCard ? '60%' : '100%' }\">\n      <img\n        class=\"carousel-img\"\n        src=\"https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel1.jpeg\"\n      >\n    </n-carousel-item>\n    <n-carousel-item :style=\"{ width: isCard ? '60%' : '100%' }\">\n      <img\n        class=\"carousel-img\"\n        src=\"https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel2.jpeg\"\n      >\n    </n-carousel-item>\n    <n-carousel-item :style=\"{ width: isCard ? '60%' : '100%' }\">\n      <img\n        class=\"carousel-img\"\n        src=\"https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel3.jpeg\"\n      >\n    </n-carousel-item>\n    <n-carousel-item :style=\"{ width: isCard ? '60%' : '100%' }\">\n      <img\n        class=\"carousel-img\"\n        src=\"https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel4.jpeg\"\n      >\n    </n-carousel-item>\n  </n-carousel>\n</template>\n\n<style>\n.carousel-img {\n  margin: 0 auto;\n  width: 100%;\n  height: 100%;\n  object-fit: cover;\n}\n</style>\n"
  },
  {
    "path": "src/carousel/demos/enUS/hover.demo.vue",
    "content": "<markdown>\n# Hover\n\nSet the `trigger` to `hover` to trigger the switch when the mouse passes over the dots.\n</markdown>\n\n<template>\n  <n-carousel trigger=\"hover\">\n    <img\n      class=\"carousel-img\"\n      src=\"https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel1.jpeg\"\n    >\n    <img\n      class=\"carousel-img\"\n      src=\"https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel2.jpeg\"\n    >\n    <img\n      class=\"carousel-img\"\n      src=\"https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel3.jpeg\"\n    >\n    <img\n      class=\"carousel-img\"\n      src=\"https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel4.jpeg\"\n    >\n  </n-carousel>\n</template>\n\n<style>\n.carousel-img {\n  width: 100%;\n  height: 240px;\n  object-fit: cover;\n}\n</style>\n"
  },
  {
    "path": "src/carousel/demos/enUS/index.demo-entry.md",
    "content": "# Carousel\n\nIt's usually used to display good news.\n\n## Demos\n\n```demo\nbasic.vue\narrow.vue\nautoplay.vue\ndots.vue\nvertical.vue\nspace-between.vue\nslides-per-view.vue\nslides-per-view-auto.vue\ncentered.vue\neffect.vue\ntransition-name.vue\nhover.vue\nkeyboard.vue\nmousewheel.vue\nsimulate-drag.vue\ncustom-arrow-and-dots.vue\ncustom-card.vue\ncustom-dots.vue\n```\n\n## API\n\n### Carousel Props\n\n| Name | Type | Default | Description | Version |\n| --- | --- | --- | --- | --- |\n| autoplay | `boolean` | `false` | Whether to scroll automatically. |  |\n| centered-slides | `boolean` | `false` | Whether to center the current view carousel. | 2.24.0 |\n| current-index | `number` | `undefined` | current index. | 2.24.0 |\n| default-index | `number` | `0` | default index. | 2.24.0 |\n| direction | `'horizontal' \\| 'vertical'` | `'horizontal'` | Carousel shows the direction. |  |\n| dot-placement | `'top' \\| 'bottom' \\| 'left' \\| 'right'` | `'bottom'` | Dot placement in the panel. | 2.24.0 |\n| dot-type | `'dot' \\| 'line'` | `'dot'` | Dot style. | 2.24.0 |\n| draggable | `boolean` | `false` | Whether to switch the carousel by dragging the mouse. | 2.24.0 |\n| effect | `'slide' \\| 'fade' \\| 'card' \\| 'custom'` | `'slide'` | Transition effect when switching between carousel. | 2.24.0, `'card'` 2.24.2 |\n| interval | `number` | `5000` | Auto play interval (ms). |  |\n| keyboard | `boolean` | `false` | Whether to switch the carousel by pressing the key, it only works when the focus is on Dots. | 2.24.0 |\n| loop | `boolean` | `true` | Whether to loop. | 2.24.0 |\n| mousewheel | `boolean` | `false` | Whether to switch the carousel through the mouse wheel. | 2.24.0 |\n| next-slide-style | `object \\| string` | `undefined` | Next slide's style. | 2.27.0 |\n| prev-slide-style | `object \\| string` | `undefined` | Previous slide's style. | 2.27.0 |\n| show-arrow | `boolean` | `false` | Whether to show arrow buttons. | 2.24.0 |\n| show-dots | `boolean` | `true` | Whether to show dots. | 2.24.0 |\n| slides-per-view | `'auto' \\| number` | `1` | Number of carousels displayed on per view. | 2.24.0 |\n| space-between | `number` | `0` | The spacing between the carousels. | 2.24.0 |\n| touchable | `boolean` | `true` | Whether to switch the carousel by touch. | 2.24.0 |\n| transition-style | `{ transitionDuration?: string, transitionTimingFunction?: string }` | `{ transitionDuration: '300ms' }` | The style of the transition effect. | 2.24.0 |\n| transition-props | `TransitionProps` | `undefined` | Custom transition effect properties, [reference](https://v3.vuejs.org/api/built-in-components.html#transition). | 2.24.0 |\n| trigger | `'click' \\| 'hover'` | `'click'` | The method of manual switching. |  |\n| on-update:current-index | `(currentIndex: number, lastIndex: number) => void` | `undefined` | Callback function when the current index changes. | 2.24.0 |\n\n### Carousel Slots\n\n| Name | Parameters | Description | Version |\n| --- | --- | --- | --- |\n| default | `()` | Carousel content. |\n| arrow | `(info: { total: number, currentIndex: number, to: (index: number) => void, prev: () => void, next: () => void })` | Arrow. | 2.24.0 |\n| dots | `(info: { total: number, currentIndex: number, to: (index: number) => void })` | Dots. | 2.24.0 |\n\n### Carousel Methods\n\n| Name | Type | Description | Version |\n| --- | --- | --- | --- |\n| to | `(index: number) => void` | Slide to index. | 2.24.0 |\n| prev | `() => void` | Slide to previous page. | 2.24.0 |\n| next | `() => void` | Slide to next page. | 2.24.0 |\n| getCurrentIndex | `() => number` | Get current index. | 2.24.0 |\n"
  },
  {
    "path": "src/carousel/demos/enUS/keyboard.demo.vue",
    "content": "<markdown>\n# Keyboard\n\nWhether to switch the carousel by pressing the key, it is only valid when the focus is on Dots.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst directionRef = ref<'horizontal' | 'vertical'>('horizontal')\nconst direction = directionRef\nconst directions = ['horizontal', 'vertical']\n</script>\n\n<template>\n  <n-space vertical>\n    <n-radio-group v-model:value=\"direction\">\n      <n-radio-button\n        v-for=\"_direction in directions\"\n        :key=\"_direction\"\n        :value=\"_direction\"\n      >\n        {{ _direction }}\n      </n-radio-button>\n    </n-radio-group>\n    <n-carousel\n      keyboard\n      :direction=\"direction\"\n      :dot-placement=\"direction === 'vertical' ? 'right' : 'bottom'\"\n      style=\"height: 240px\"\n    >\n      <img\n        class=\"carousel-img\"\n        src=\"https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel1.jpeg\"\n      >\n      <img\n        class=\"carousel-img\"\n        src=\"https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel2.jpeg\"\n      >\n      <img\n        class=\"carousel-img\"\n        src=\"https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel3.jpeg\"\n      >\n      <img\n        class=\"carousel-img\"\n        src=\"https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel4.jpeg\"\n      >\n    </n-carousel>\n  </n-space>\n</template>\n\n<style>\n.carousel-img {\n  width: 100%;\n  height: 240px;\n  object-fit: cover;\n}\n</style>\n"
  },
  {
    "path": "src/carousel/demos/enUS/mousewheel.demo.vue",
    "content": "<markdown>\n# Mousewheel\n</markdown>\n\n<template>\n  <n-carousel\n    direction=\"vertical\"\n    dot-placement=\"right\"\n    mousewheel\n    style=\"width: 100%; height: 240px\"\n  >\n    <img\n      class=\"carousel-img\"\n      src=\"https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel1.jpeg\"\n    >\n    <img\n      class=\"carousel-img\"\n      src=\"https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel2.jpeg\"\n    >\n    <img\n      class=\"carousel-img\"\n      src=\"https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel3.jpeg\"\n    >\n    <img\n      class=\"carousel-img\"\n      src=\"https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel4.jpeg\"\n    >\n  </n-carousel>\n</template>\n\n<style>\n.carousel-img {\n  width: 100%;\n  height: 240px;\n  object-fit: cover;\n}\n</style>\n"
  },
  {
    "path": "src/carousel/demos/enUS/simulate-drag.demo.vue",
    "content": "<markdown>\n# Simulate drag\n\nCarousel enable the `Touch` event simulation by default. If you need the carousel chart to respond to mouse drag, you can use `draggable` prop.\n</markdown>\n\n<template>\n  <n-carousel draggable>\n    <img\n      class=\"carousel-img\"\n      src=\"https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel1.jpeg\"\n    >\n    <img\n      class=\"carousel-img\"\n      src=\"https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel2.jpeg\"\n    >\n    <img\n      class=\"carousel-img\"\n      src=\"https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel3.jpeg\"\n    >\n    <img\n      class=\"carousel-img\"\n      src=\"https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel4.jpeg\"\n    >\n  </n-carousel>\n</template>\n\n<style>\n.carousel-img {\n  width: 100%;\n  height: 240px;\n  object-fit: cover;\n}\n</style>\n"
  },
  {
    "path": "src/carousel/demos/enUS/slides-per-view-auto.demo.vue",
    "content": "<markdown>\n# Auto slides per view\n</markdown>\n\n<template>\n  <n-carousel\n    slides-per-view=\"auto\"\n    :space-between=\"20\"\n    :loop=\"false\"\n    draggable\n  >\n    <n-carousel-item style=\"width: 60%\">\n      <img\n        class=\"carousel-img\"\n        src=\"https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel1.jpeg\"\n      >\n    </n-carousel-item>\n    <n-carousel-item style=\"width: 20%\">\n      <img\n        class=\"carousel-img\"\n        src=\"https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel2.jpeg\"\n      >\n    </n-carousel-item>\n    <n-carousel-item style=\"width: 40%\">\n      <img\n        class=\"carousel-img\"\n        src=\"https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel3.jpeg\"\n      >\n    </n-carousel-item>\n    <n-carousel-item style=\"width: 10%\">\n      <img\n        class=\"carousel-img\"\n        src=\"https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel4.jpeg\"\n      >\n    </n-carousel-item>\n  </n-carousel>\n</template>\n\n<style>\n.carousel-img {\n  width: 100%;\n  height: 240px;\n  object-fit: cover;\n}\n</style>\n"
  },
  {
    "path": "src/carousel/demos/enUS/slides-per-view.demo.vue",
    "content": "<markdown>\n# Slides per view\n\nPlease note that this prop will conflict with `loop`. If you need to customize the number of displays per view, then the `loop` prop will be disabled.\n</markdown>\n\n<template>\n  <n-carousel :slides-per-view=\"3\" :space-between=\"20\" :loop=\"false\" draggable>\n    <img\n      class=\"carousel-img\"\n      src=\"https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel1.jpeg\"\n    >\n    <img\n      class=\"carousel-img\"\n      src=\"https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel2.jpeg\"\n    >\n    <img\n      class=\"carousel-img\"\n      src=\"https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel3.jpeg\"\n    >\n    <img\n      class=\"carousel-img\"\n      src=\"https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel4.jpeg\"\n    >\n  </n-carousel>\n</template>\n\n<style>\n.carousel-img {\n  width: 100%;\n  height: 240px;\n  object-fit: cover;\n}\n</style>\n"
  },
  {
    "path": "src/carousel/demos/enUS/space-between.demo.vue",
    "content": "<markdown>\n# Space between\n</markdown>\n\n<template>\n  <n-carousel :space-between=\"20\" draggable>\n    <img\n      class=\"carousel-img\"\n      src=\"https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel1.jpeg\"\n    >\n    <img\n      class=\"carousel-img\"\n      src=\"https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel2.jpeg\"\n    >\n    <img\n      class=\"carousel-img\"\n      src=\"https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel3.jpeg\"\n    >\n    <img\n      class=\"carousel-img\"\n      src=\"https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel4.jpeg\"\n    >\n  </n-carousel>\n</template>\n\n<style>\n.carousel-img {\n  width: 100%;\n  height: 240px;\n  object-fit: cover;\n}\n</style>\n"
  },
  {
    "path": "src/carousel/demos/enUS/transition-name.demo.vue",
    "content": "<markdown>\n# Customizing transition\n\nIf you want to customize the transition effect, you can use `transition-props` and set `effect` to `'custom'`. For transition props, see [reference](https://v3.vuejs.org/api/built-in-components.html#transition).\n</markdown>\n\n<template>\n  <n-carousel\n    effect=\"custom\"\n    :transition-props=\"{ name: 'creative' }\"\n    show-arrow\n    style=\"width: 100%; height: 240px\"\n  >\n    <img\n      class=\"carousel-img\"\n      src=\"https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel1.jpeg\"\n    >\n    <img\n      class=\"carousel-img\"\n      src=\"https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel2.jpeg\"\n    >\n    <img\n      class=\"carousel-img\"\n      src=\"https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel3.jpeg\"\n    >\n    <img\n      class=\"carousel-img\"\n      src=\"https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel4.jpeg\"\n    >\n  </n-carousel>\n</template>\n\n<style>\n.carousel-img {\n  width: 100%;\n  height: 240px;\n  object-fit: cover;\n}\n\n:deep(.creative-enter-from),\n:deep(.creative-leave-to) {\n  opacity: 0;\n  transform: scale(0.8);\n}\n\n:deep(.creative-enter-active),\n:deep(.creative-leave-active) {\n  transition: all 0.3s ease;\n}\n</style>\n"
  },
  {
    "path": "src/carousel/demos/enUS/vertical.demo.vue",
    "content": "<markdown>\n# Vertical\n</markdown>\n\n<template>\n  <n-carousel\n    direction=\"vertical\"\n    dot-placement=\"right\"\n    style=\"width: 100%; height: 240px\"\n  >\n    <img\n      class=\"carousel-img\"\n      src=\"https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel1.jpeg\"\n    >\n    <img\n      class=\"carousel-img\"\n      src=\"https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel2.jpeg\"\n    >\n    <img\n      class=\"carousel-img\"\n      src=\"https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel3.jpeg\"\n    >\n    <img\n      class=\"carousel-img\"\n      src=\"https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel4.jpeg\"\n    >\n  </n-carousel>\n</template>\n\n<style>\n.carousel-img {\n  width: 100%;\n  height: 240px;\n  object-fit: cover;\n}\n</style>\n"
  },
  {
    "path": "src/carousel/demos/zhCN/arrow.demo.vue",
    "content": "<markdown>\n# 箭头\n\n设定 `show-arrow` 来显示箭头。\n</markdown>\n\n<template>\n  <n-carousel show-arrow>\n    <img\n      class=\"carousel-img\"\n      src=\"https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel1.jpeg\"\n    >\n    <img\n      class=\"carousel-img\"\n      src=\"https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel2.jpeg\"\n    >\n    <img\n      class=\"carousel-img\"\n      src=\"https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel3.jpeg\"\n    >\n    <img\n      class=\"carousel-img\"\n      src=\"https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel4.jpeg\"\n    >\n  </n-carousel>\n</template>\n\n<style>\n.carousel-img {\n  width: 100%;\n  height: 240px;\n  object-fit: cover;\n}\n</style>\n"
  },
  {
    "path": "src/carousel/demos/zhCN/autoplay.demo.vue",
    "content": "<markdown>\n# 自动播放\n\n设定 `autoplay` 然后它就能自己动了。\n</markdown>\n\n<template>\n  <n-carousel autoplay>\n    <img\n      class=\"carousel-img\"\n      src=\"https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel1.jpeg\"\n    >\n    <img\n      class=\"carousel-img\"\n      src=\"https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel2.jpeg\"\n    >\n    <img\n      class=\"carousel-img\"\n      src=\"https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel3.jpeg\"\n    >\n    <img\n      class=\"carousel-img\"\n      src=\"https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel4.jpeg\"\n    >\n  </n-carousel>\n</template>\n\n<style>\n.carousel-img {\n  width: 100%;\n  height: 240px;\n  object-fit: cover;\n}\n</style>\n"
  },
  {
    "path": "src/carousel/demos/zhCN/basic.demo.vue",
    "content": "<markdown>\n# 基础\n</markdown>\n\n<template>\n  <n-carousel>\n    <img\n      class=\"carousel-img\"\n      src=\"https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel1.jpeg\"\n    >\n    <img\n      class=\"carousel-img\"\n      src=\"https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel2.jpeg\"\n    >\n    <img\n      class=\"carousel-img\"\n      src=\"https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel3.jpeg\"\n    >\n    <img\n      class=\"carousel-img\"\n      src=\"https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel4.jpeg\"\n    >\n  </n-carousel>\n</template>\n\n<style>\n.carousel-img {\n  width: 100%;\n  height: 240px;\n  object-fit: cover;\n}\n</style>\n"
  },
  {
    "path": "src/carousel/demos/zhCN/centered.demo.vue",
    "content": "<markdown>\n# 居中\n\n设定 `centered-slides` 来将所有的 `slide` 居中显示，这仅在 `effect` 为 `slide` 以及 `card` 的时候有用。\n</markdown>\n\n<template>\n  <n-carousel\n    :space-between=\"30\"\n    :loop=\"false\"\n    slides-per-view=\"auto\"\n    centered-slides\n    draggable\n  >\n    <n-carousel-item style=\"width: 30%\">\n      <img\n        class=\"carousel-img\"\n        src=\"https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel1.jpeg\"\n      >\n    </n-carousel-item>\n    <n-carousel-item style=\"width: 20%\">\n      <img\n        class=\"carousel-img\"\n        src=\"https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel2.jpeg\"\n      >\n    </n-carousel-item>\n    <n-carousel-item style=\"width: 30%\">\n      <img\n        class=\"carousel-img\"\n        src=\"https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel3.jpeg\"\n      >\n    </n-carousel-item>\n    <n-carousel-item style=\"width: 40%\">\n      <img\n        class=\"carousel-img\"\n        src=\"https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel4.jpeg\"\n      >\n    </n-carousel-item>\n  </n-carousel>\n</template>\n\n<style>\n.carousel-img {\n  width: 100%;\n  height: 240px;\n  object-fit: cover;\n}\n</style>\n"
  },
  {
    "path": "src/carousel/demos/zhCN/custom-arrow-and-dots.demo.vue",
    "content": "<markdown>\n# 自定义箭头以及控制点\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ArrowBack, ArrowForward } from '@vicons/ionicons5'\n</script>\n\n<template>\n  <n-carousel show-arrow autoplay>\n    <img\n      class=\"carousel-img\"\n      src=\"https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel1.jpeg\"\n    >\n    <img\n      class=\"carousel-img\"\n      src=\"https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel2.jpeg\"\n    >\n    <img\n      class=\"carousel-img\"\n      src=\"https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel3.jpeg\"\n    >\n    <img\n      class=\"carousel-img\"\n      src=\"https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel4.jpeg\"\n    >\n    <template #arrow=\"{ prev, next }\">\n      <div class=\"custom-arrow\">\n        <button type=\"button\" class=\"custom-arrow--left\" @click=\"prev\">\n          <n-icon><ArrowBack /></n-icon>\n        </button>\n        <button type=\"button\" class=\"custom-arrow--right\" @click=\"next\">\n          <n-icon><ArrowForward /></n-icon>\n        </button>\n      </div>\n    </template>\n    <template #dots=\"{ total, currentIndex, to }\">\n      <ul class=\"custom-dots\">\n        <li\n          v-for=\"index of total\"\n          :key=\"index\"\n          :class=\"{ ['is-active']: currentIndex === index - 1 }\"\n          @click=\"to(index - 1)\"\n        />\n      </ul>\n    </template>\n  </n-carousel>\n</template>\n\n<style>\n.carousel-img {\n  width: 100%;\n  height: 240px;\n  object-fit: cover;\n}\n\n.custom-arrow {\n  display: flex;\n  position: absolute;\n  bottom: 25px;\n  right: 10px;\n}\n\n.custom-arrow button {\n  display: inline-flex;\n  align-items: center;\n  justify-content: center;\n  width: 28px;\n  height: 28px;\n  margin-right: 12px;\n  color: #fff;\n  background-color: rgba(255, 255, 255, 0.1);\n  border-width: 0;\n  border-radius: 8px;\n  transition: background-color 0.3s cubic-bezier(0.4, 0, 0.2, 1);\n  cursor: pointer;\n}\n\n.custom-arrow button:hover {\n  background-color: rgba(255, 255, 255, 0.2);\n}\n\n.custom-arrow button:active {\n  transform: scale(0.95);\n  transform-origin: center;\n}\n\n.custom-dots {\n  display: flex;\n  margin: 0;\n  padding: 0;\n  position: absolute;\n  bottom: 20px;\n  left: 20px;\n}\n\n.custom-dots li {\n  display: inline-block;\n  width: 12px;\n  height: 4px;\n  margin: 0 3px;\n  border-radius: 4px;\n  background-color: rgba(255, 255, 255, 0.4);\n  transition:\n    width 0.3s,\n    background-color 0.3s cubic-bezier(0.4, 0, 0.2, 1);\n  cursor: pointer;\n}\n\n.custom-dots li.is-active {\n  width: 40px;\n  background: #fff;\n}\n</style>\n"
  },
  {
    "path": "src/carousel/demos/zhCN/custom-card.demo.vue",
    "content": "<markdown>\n# 自定义卡片效果\n\n你可以使用 `next-slide-style` 和 `prev-slide-style` 来调整前后卡片的比例。\n</markdown>\n\n<template>\n  <n-carousel\n    effect=\"card\"\n    prev-slide-style=\"transform: translateX(-150%) translateZ(-800px);\"\n    next-slide-style=\"transform: translateX(50%) translateZ(-800px);\"\n    style=\"height: 240px\"\n    :show-dots=\"false\"\n  >\n    <n-carousel-item :style=\"{ width: '60%' }\">\n      <img\n        class=\"carousel-img\"\n        src=\"https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel1.jpeg\"\n      >\n    </n-carousel-item>\n    <n-carousel-item :style=\"{ width: '60%' }\">\n      <img\n        class=\"carousel-img\"\n        src=\"https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel2.jpeg\"\n      >\n    </n-carousel-item>\n    <n-carousel-item :style=\"{ width: '60%' }\">\n      <img\n        class=\"carousel-img\"\n        src=\"https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel3.jpeg\"\n      >\n    </n-carousel-item>\n    <n-carousel-item :style=\"{ width: '60%' }\">\n      <img\n        class=\"carousel-img\"\n        src=\"https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel4.jpeg\"\n      >\n    </n-carousel-item>\n  </n-carousel>\n</template>\n\n<style>\n.carousel-img {\n  margin: 0 auto;\n  width: 100%;\n  height: 100%;\n  object-fit: cover;\n}\n</style>\n"
  },
  {
    "path": "src/carousel/demos/zhCN/custom-dots.demo.vue",
    "content": "<markdown>\n# 自定义指示点\n</markdown>\n\n<template>\n  <n-carousel autoplay>\n    <img\n      class=\"carousel-img\"\n      src=\"https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel1.jpeg\"\n    >\n    <img\n      class=\"carousel-img\"\n      src=\"https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel2.jpeg\"\n    >\n    <img\n      class=\"carousel-img\"\n      src=\"https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel3.jpeg\"\n    >\n    <img\n      class=\"carousel-img\"\n      src=\"https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel4.jpeg\"\n    >\n    <template #dots=\"{ total, currentIndex }\">\n      <span class=\"custom-dots\"> {{ currentIndex + 1 }} / {{ total }} </span>\n    </template>\n  </n-carousel>\n</template>\n\n<style>\n.carousel-img {\n  width: 100%;\n  height: 240px;\n  object-fit: cover;\n}\n\n.custom-dots {\n  font-size: 12px;\n  transform: translateY(5px);\n}\n</style>\n"
  },
  {
    "path": "src/carousel/demos/zhCN/dots.demo.vue",
    "content": "<markdown>\n# 指示点\n\n设定 `dot-type` 来更改指示器的样式，可以使用 `:show-dots=\"false\"` 来隐藏指示点。\n\n设定 `dot-placement` 来更改指示点的位置。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst typeRef = ref<'dot' | 'line'>('dot')\nconst placementRef = ref<'top' | 'bottom' | 'left' | 'right'>('bottom')\nconst directionRef = ref<'horizontal' | 'vertical'>('horizontal')\nconst showArrow = ref(false)\nconst type = typeRef\nconst types = ['dot', 'line']\nconst placement = placementRef\nconst placements = ['top', 'bottom', 'left', 'right']\nconst direction = directionRef\nconst directions = ['horizontal', 'vertical']\n</script>\n\n<template>\n  <n-space vertical>\n    <n-radio-group v-model:value=\"type\">\n      <n-radio-button v-for=\"_type in types\" :key=\"_type\" :value=\"_type\">\n        {{ _type }}\n      </n-radio-button>\n    </n-radio-group>\n    <n-radio-group v-model:value=\"placement\">\n      <n-radio-button\n        v-for=\"_placement in placements\"\n        :key=\"_placement\"\n        :value=\"_placement\"\n      >\n        {{ _placement }}\n      </n-radio-button>\n    </n-radio-group>\n    <n-radio-group v-model:value=\"direction\">\n      <n-radio-button\n        v-for=\"_direction in directions\"\n        :key=\"_direction\"\n        :value=\"_direction\"\n      >\n        {{ _direction }}\n      </n-radio-button>\n    </n-radio-group>\n    <n-switch v-model:value=\"showArrow\">\n      <template #checked>\n        Show arrow\n      </template>\n      <template #unchecked>\n        No arrow\n      </template>\n    </n-switch>\n    <n-carousel\n      :direction=\"direction\"\n      :show-arrow=\"showArrow\"\n      :dot-type=\"type\"\n      :dot-placement=\"placement\"\n      style=\"height: 240px\"\n    >\n      <img\n        class=\"carousel-img\"\n        src=\"https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel1.jpeg\"\n      >\n      <img\n        class=\"carousel-img\"\n        src=\"https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel2.jpeg\"\n      >\n      <img\n        class=\"carousel-img\"\n        src=\"https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel3.jpeg\"\n      >\n      <img\n        class=\"carousel-img\"\n        src=\"https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel4.jpeg\"\n      >\n    </n-carousel>\n  </n-space>\n</template>\n\n<style>\n.carousel-img {\n  width: 100%;\n  height: 100%;\n  object-fit: cover;\n}\n</style>\n"
  },
  {
    "path": "src/carousel/demos/zhCN/effect.demo.vue",
    "content": "<markdown>\n# 过渡效果\n\n如果你想要自定义过渡效果，可以使用 `transition-props`，并把 `effect` 设置为 `custom`。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { computed, ref } from 'vue'\n\nconst effectRef = ref<'slide' | 'fade' | 'card'>('slide')\nconst isCardRef = computed(() => effectRef.value === 'card')\nconst isCard = isCardRef\nconst myEffect = effectRef\nconst effects = ['slide', 'fade', 'card']\n</script>\n\n<template>\n  <n-radio-group v-model:value=\"myEffect\" style=\"margin-bottom: 10px\">\n    <n-radio-button v-for=\"effect in effects\" :key=\"effect\" :value=\"effect\">\n      {{ effect }}\n    </n-radio-button>\n  </n-radio-group>\n  <n-carousel\n    :key=\"myEffect\"\n    :effect=\"myEffect\"\n    :centered-slides=\"isCard\"\n    :slides-per-view=\"isCard ? 'auto' : 1\"\n    draggable\n    style=\"height: 240px\"\n  >\n    <n-carousel-item :style=\"{ width: isCard ? '60%' : '100%' }\">\n      <img\n        class=\"carousel-img\"\n        src=\"https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel1.jpeg\"\n      >\n    </n-carousel-item>\n    <n-carousel-item :style=\"{ width: isCard ? '60%' : '100%' }\">\n      <img\n        class=\"carousel-img\"\n        src=\"https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel2.jpeg\"\n      >\n    </n-carousel-item>\n    <n-carousel-item :style=\"{ width: isCard ? '60%' : '100%' }\">\n      <img\n        class=\"carousel-img\"\n        src=\"https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel3.jpeg\"\n      >\n    </n-carousel-item>\n    <n-carousel-item :style=\"{ width: isCard ? '60%' : '100%' }\">\n      <img\n        class=\"carousel-img\"\n        src=\"https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel4.jpeg\"\n      >\n    </n-carousel-item>\n  </n-carousel>\n</template>\n\n<style>\n.carousel-img {\n  margin: 0 auto;\n  width: 100%;\n  height: 100%;\n  object-fit: cover;\n}\n</style>\n"
  },
  {
    "path": "src/carousel/demos/zhCN/hover.demo.vue",
    "content": "<markdown>\n# 鼠标经过指示点切换轮播图\n\n设定 `trigger` 为 `hover` 鼠标经过指示点时触发切换。\n</markdown>\n\n<template>\n  <n-carousel trigger=\"hover\">\n    <img\n      class=\"carousel-img\"\n      src=\"https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel1.jpeg\"\n    >\n    <img\n      class=\"carousel-img\"\n      src=\"https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel2.jpeg\"\n    >\n    <img\n      class=\"carousel-img\"\n      src=\"https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel3.jpeg\"\n    >\n    <img\n      class=\"carousel-img\"\n      src=\"https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel4.jpeg\"\n    >\n  </n-carousel>\n</template>\n\n<style>\n.carousel-img {\n  width: 100%;\n  height: 240px;\n  object-fit: cover;\n}\n</style>\n"
  },
  {
    "path": "src/carousel/demos/zhCN/index.demo-entry.md",
    "content": "# 轮播图 Carousel\n\n一般用来播放一些好消息。\n\n## 演示\n\n```demo\nbasic.vue\narrow.vue\nautoplay.vue\ndots.vue\nvertical.vue\nspace-between.vue\nslides-per-view.vue\nslides-per-view-auto.vue\ncentered.vue\neffect.vue\ntransition-name.vue\nhover.vue\nkeyboard.vue\nmousewheel.vue\nsimulate-drag.vue\ncustom-arrow-and-dots.vue\ncustom-card.vue\ncustom-dots.vue\n```\n\n## API\n\n### Carousel Props\n\n| 名称 | 类型 | 默认值 | 说明 | 版本 |\n| --- | --- | --- | --- | --- |\n| autoplay | `boolean` | `false` | 是否自动播放 |  |\n| centered-slides | `boolean` | `false` | 是否居中显示当前页轮播图 | 2.24.0 |\n| current-index | `number` | `undefined` | 当前显示页 | 2.24.0 |\n| default-index | `number` | `0` | 默认显示页 | 2.24.0 |\n| direction | `'horizontal' \\| 'vertical'` | `'horizontal'` | 轮播图显示的方向 |  |\n| dot-placement | `'top' \\| 'bottom' \\| 'left' \\| 'right'` | `'bottom'` | 轮播指示点位置 | 2.24.0 |\n| dot-type | `'dot' \\| 'line'` | `'dot'` | 轮播指示点样式 | 2.24.0 |\n| draggable | `boolean` | `false` | 是否通过鼠标拖拽切换轮播图 | 2.24.0 |\n| effect | `'slide' \\| 'fade' \\| 'card' \\| 'custom'` | `'slide'` | 轮播图切换时的过渡效果 | 2.24.0, `'card'` 2.24.2 |\n| interval | `number` | `5000` | 自动播放的间隔（ms） |  |\n| keyboard | `boolean` | `false` | 是否通过按键切换轮播图，只有焦点在 Dots 上时才起作用 | 2.24.0 |\n| loop | `boolean` | `true` | 是否循环播放 | 2.24.0 |\n| mousewheel | `boolean` | `false` | 是否通过鼠标滚轮切换轮播图 | 2.24.0 |\n| next-slide-style | `object \\| string` | `undefined` | 下一张轮播图的样式 | 2.27.0 |\n| prev-slide-style | `object \\| string` | `undefined` | 上一张轮播图的样式 | 2.27.0 |\n| slides-per-view | `'auto' \\| number` | `1` | 每一页显示的轮播图数量 | 2.24.0 |\n| space-between | `number` | `0` | 轮播图之间的间距 | 2.24.0 |\n| show-arrow | `boolean` | `false` | 是否显示箭头按钮 | 2.24.0 |\n| show-dots | `boolean` | `true` | 是否展示指示点 | 2.24.0 |\n| touchable | `boolean` | `true` | 是否通过触摸拖拽切换轮播图 | 2.24.0 |\n| transition-style | `{ transitionDuration?: string, transitionTimingFunction?: string }` | `{ transitionDuration: '300ms' }` | 过渡效果的样式 | 2.24.0 |\n| transition-props | `TransitionProps` | `undefined` | 自定义过渡效果属性，[参考 Vue 文档](https://v3.cn.vuejs.org/api/built-in-components.html#transition) | 2.24.0 |\n| trigger | `'click' \\| 'hover'` | `'click'` | 触发切换的方式 |  |\n| on-update:current-index | `(currentIndex: number, lastIndex: number) => void` | `undefined` | 当前页变化时的回调函数 | 2.24.0 |\n\n### Carousel Slots\n\n| 名称 | 参数 | 说明 | 版本 |\n| --- | --- | --- | --- |\n| default | `()` | 轮播的内容 |\n| arrow | `(info: { total: number, currentIndex: number, to: (index: number) => void, prev: () => void, next: () => void })` | 箭头 | 2.24.0 |\n| dots | `(info: { total: number, currentIndex: number, to: (index: number) => void })` | 指示点 | 2.24.0 |\n\n### Carousel Methods\n\n| 名称            | 类型                      | 说明         | 版本   |\n| --------------- | ------------------------- | ------------ | ------ |\n| to              | `(index: number) => void` | 滑动至某一页 | 2.24.0 |\n| prev            | `() => void`              | 滑动至前一页 | 2.24.0 |\n| next            | `() => void`              | 滑动至后一页 | 2.24.0 |\n| getCurrentIndex | `() => number`            | 获取当前页   | 2.24.0 |\n"
  },
  {
    "path": "src/carousel/demos/zhCN/keyboard.demo.vue",
    "content": "<markdown>\n# 按键控制\n\n是否通过按键切换轮播图，只有焦点在 Dots 上时才有效。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst directionRef = ref<'horizontal' | 'vertical'>('horizontal')\nconst direction = directionRef\nconst directions = ['horizontal', 'vertical']\n</script>\n\n<template>\n  <n-space vertical>\n    <n-radio-group v-model:value=\"direction\">\n      <n-radio-button\n        v-for=\"_direction in directions\"\n        :key=\"_direction\"\n        :value=\"_direction\"\n      >\n        {{ _direction }}\n      </n-radio-button>\n    </n-radio-group>\n    <n-carousel\n      keyboard\n      :direction=\"direction\"\n      :dot-placement=\"direction === 'vertical' ? 'right' : 'bottom'\"\n      style=\"height: 240px\"\n    >\n      <img\n        class=\"carousel-img\"\n        src=\"https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel1.jpeg\"\n      >\n      <img\n        class=\"carousel-img\"\n        src=\"https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel2.jpeg\"\n      >\n      <img\n        class=\"carousel-img\"\n        src=\"https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel3.jpeg\"\n      >\n      <img\n        class=\"carousel-img\"\n        src=\"https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel4.jpeg\"\n      >\n    </n-carousel>\n  </n-space>\n</template>\n\n<style>\n.carousel-img {\n  width: 100%;\n  height: 240px;\n  object-fit: cover;\n}\n</style>\n"
  },
  {
    "path": "src/carousel/demos/zhCN/mousewheel.demo.vue",
    "content": "<markdown>\n# 鼠标滚轮控制\n</markdown>\n\n<template>\n  <n-carousel\n    direction=\"vertical\"\n    dot-placement=\"right\"\n    mousewheel\n    style=\"width: 100%; height: 240px\"\n  >\n    <img\n      class=\"carousel-img\"\n      src=\"https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel1.jpeg\"\n    >\n    <img\n      class=\"carousel-img\"\n      src=\"https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel2.jpeg\"\n    >\n    <img\n      class=\"carousel-img\"\n      src=\"https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel3.jpeg\"\n    >\n    <img\n      class=\"carousel-img\"\n      src=\"https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel4.jpeg\"\n    >\n  </n-carousel>\n</template>\n\n<style>\n.carousel-img {\n  width: 100%;\n  height: 240px;\n  object-fit: cover;\n}\n</style>\n"
  },
  {
    "path": "src/carousel/demos/zhCN/simulate-drag.demo.vue",
    "content": "<markdown>\n# 模拟拖拽\n\n轮播图会默认启用 `Touch` 事件模拟，如果你需要轮播图响应鼠标拖拽，可以使用 `draggable` 属性。\n</markdown>\n\n<template>\n  <n-carousel draggable>\n    <img\n      class=\"carousel-img\"\n      src=\"https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel1.jpeg\"\n    >\n    <img\n      class=\"carousel-img\"\n      src=\"https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel2.jpeg\"\n    >\n    <img\n      class=\"carousel-img\"\n      src=\"https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel3.jpeg\"\n    >\n    <img\n      class=\"carousel-img\"\n      src=\"https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel4.jpeg\"\n    >\n  </n-carousel>\n</template>\n\n<style>\n.carousel-img {\n  width: 100%;\n  height: 240px;\n  object-fit: cover;\n}\n</style>\n"
  },
  {
    "path": "src/carousel/demos/zhCN/slides-per-view-auto.demo.vue",
    "content": "<markdown>\n# 自动每屏显示数量\n</markdown>\n\n<template>\n  <n-carousel\n    slides-per-view=\"auto\"\n    :space-between=\"20\"\n    :loop=\"false\"\n    draggable\n  >\n    <n-carousel-item style=\"width: 60%\">\n      <img\n        class=\"carousel-img\"\n        src=\"https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel1.jpeg\"\n      >\n    </n-carousel-item>\n    <n-carousel-item style=\"width: 20%\">\n      <img\n        class=\"carousel-img\"\n        src=\"https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel2.jpeg\"\n      >\n    </n-carousel-item>\n    <n-carousel-item style=\"width: 40%\">\n      <img\n        class=\"carousel-img\"\n        src=\"https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel3.jpeg\"\n      >\n    </n-carousel-item>\n    <n-carousel-item style=\"width: 10%\">\n      <img\n        class=\"carousel-img\"\n        src=\"https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel4.jpeg\"\n      >\n    </n-carousel-item>\n  </n-carousel>\n</template>\n\n<style>\n.carousel-img {\n  width: 100%;\n  height: 240px;\n  object-fit: cover;\n}\n</style>\n"
  },
  {
    "path": "src/carousel/demos/zhCN/slides-per-view.demo.vue",
    "content": "<markdown>\n# 每屏显示数量\n\n需要注意，`slides-per-view` 属性会与 `loop` 冲突，如果你需要自定义每屏显示数量，那么 `loop` 功能将被禁用。\n</markdown>\n\n<template>\n  <n-carousel :slides-per-view=\"3\" :space-between=\"20\" :loop=\"false\" draggable>\n    <img\n      class=\"carousel-img\"\n      src=\"https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel1.jpeg\"\n    >\n    <img\n      class=\"carousel-img\"\n      src=\"https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel2.jpeg\"\n    >\n    <img\n      class=\"carousel-img\"\n      src=\"https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel3.jpeg\"\n    >\n    <img\n      class=\"carousel-img\"\n      src=\"https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel4.jpeg\"\n    >\n  </n-carousel>\n</template>\n\n<style>\n.carousel-img {\n  width: 100%;\n  height: 240px;\n  object-fit: cover;\n}\n</style>\n"
  },
  {
    "path": "src/carousel/demos/zhCN/space-between.demo.vue",
    "content": "<markdown>\n# 相邻间距\n</markdown>\n\n<template>\n  <n-carousel :space-between=\"20\" draggable>\n    <img\n      class=\"carousel-img\"\n      src=\"https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel1.jpeg\"\n    >\n    <img\n      class=\"carousel-img\"\n      src=\"https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel2.jpeg\"\n    >\n    <img\n      class=\"carousel-img\"\n      src=\"https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel3.jpeg\"\n    >\n    <img\n      class=\"carousel-img\"\n      src=\"https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel4.jpeg\"\n    >\n  </n-carousel>\n</template>\n\n<style>\n.carousel-img {\n  width: 100%;\n  height: 240px;\n  object-fit: cover;\n}\n</style>\n"
  },
  {
    "path": "src/carousel/demos/zhCN/transition-name.demo.vue",
    "content": "<markdown>\n# 自定义过渡效果\n\n如果你想要自定义过渡效果，可以使用 `transition-props`，并把 `effect` 设置为 `'custom'`，具体配置见[官方文档](https://v3.cn.vuejs.org/api/built-in-components.html#transition)。\n</markdown>\n\n<template>\n  <n-carousel\n    effect=\"custom\"\n    :transition-props=\"{ name: 'creative' }\"\n    show-arrow\n    style=\"width: 100%; height: 240px\"\n  >\n    <img\n      class=\"carousel-img\"\n      src=\"https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel1.jpeg\"\n    >\n    <img\n      class=\"carousel-img\"\n      src=\"https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel2.jpeg\"\n    >\n    <img\n      class=\"carousel-img\"\n      src=\"https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel3.jpeg\"\n    >\n    <img\n      class=\"carousel-img\"\n      src=\"https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel4.jpeg\"\n    >\n  </n-carousel>\n</template>\n\n<style>\n.carousel-img {\n  width: 100%;\n  height: 240px;\n  object-fit: cover;\n}\n\n:deep(.creative-enter-from),\n:deep(.creative-leave-to) {\n  opacity: 0;\n  transform: scale(0.8);\n}\n\n:deep(.creative-enter-active),\n:deep(.creative-leave-active) {\n  transition: all 0.3s ease;\n}\n</style>\n"
  },
  {
    "path": "src/carousel/demos/zhCN/vertical.demo.vue",
    "content": "<markdown>\n# 垂直\n</markdown>\n\n<template>\n  <n-carousel\n    direction=\"vertical\"\n    dot-placement=\"right\"\n    show-arrow\n    style=\"width: 100%; height: 240px\"\n  >\n    <img\n      class=\"carousel-img\"\n      src=\"https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel1.jpeg\"\n    >\n    <img\n      class=\"carousel-img\"\n      src=\"https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel2.jpeg\"\n    >\n    <img\n      class=\"carousel-img\"\n      src=\"https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel3.jpeg\"\n    >\n    <img\n      class=\"carousel-img\"\n      src=\"https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel4.jpeg\"\n    >\n  </n-carousel>\n</template>\n\n<style>\n.carousel-img {\n  width: 100%;\n  height: 240px;\n  object-fit: cover;\n}\n</style>\n"
  },
  {
    "path": "src/carousel/index.ts",
    "content": "export { carouselProps, default as NCarousel } from './src/Carousel'\nexport type { CarouselProps, CarouselSlots } from './src/Carousel'\nexport { default as NCarouselItem } from './src/CarouselItem'\nexport type {\n  CarouselArrowSlotProps,\n  CarouselDotSlotProps,\n  CarouselInst\n} from './src/interface'\n"
  },
  {
    "path": "src/carousel/src/Carousel.tsx",
    "content": "import type {\n  CSSProperties,\n  PropType,\n  Ref,\n  SlotsType,\n  TransitionProps,\n  VNode\n} from 'vue'\nimport type { ThemeProps } from '../../_mixins'\nimport type { ExtractPublicPropTypes } from '../../_utils'\nimport type { CarouselTheme } from '../styles'\nimport type { CarouselContextValue } from './CarouselContext'\nimport type {\n  ArrowScopedSlotProps,\n  CarouselArrowSlotProps,\n  CarouselDotSlotProps,\n  CarouselInst,\n  DotScopedSlotProps,\n  Size\n} from './interface'\nimport { off, on } from 'evtd'\nimport { getPreciseEventTarget } from 'seemly'\nimport { useMergedState } from 'vooks'\nimport {\n  cloneVNode,\n  computed,\n  defineComponent,\n  h,\n  nextTick,\n  normalizeStyle,\n  onBeforeUnmount,\n  onMounted,\n  onUpdated,\n  ref,\n  toRef,\n  Transition,\n  vShow,\n  watch,\n  watchEffect,\n  withDirectives\n} from 'vue'\nimport { VResizeObserver } from 'vueuc'\nimport { useConfig, useTheme, useThemeClass } from '../../_mixins'\nimport { flatten, keep, resolveSlotWithTypedProps } from '../../_utils'\nimport { carouselLight } from '../styles'\nimport NCarouselArrow from './CarouselArrow'\nimport { provideCarouselContext } from './CarouselContext'\nimport NCarouselDots from './CarouselDots'\nimport NCarouselItem, { isCarouselItem } from './CarouselItem'\nimport style from './styles/index.cssr'\nimport {\n  addDuplicateSlides,\n  calculateSize,\n  clampValue,\n  getDisplayIndex,\n  getDisplayTotalView,\n  getNextIndex,\n  getPrevIndex,\n  getRealIndex,\n  isTouchEvent,\n  resolveSpeed\n} from './utils'\n\nconst transitionProperties = [\n  'transitionDuration',\n  'transitionTimingFunction'\n] as const\n\ntype TransitionStyle = Partial<\n  Pick<CSSProperties, (typeof transitionProperties)[number]>\n>\n\nexport const carouselProps = {\n  ...(useTheme.props as ThemeProps<CarouselTheme>),\n  defaultIndex: {\n    type: Number,\n    default: 0\n  },\n  currentIndex: Number,\n  showArrow: Boolean,\n  dotType: {\n    type: String as PropType<'dot' | 'line'>,\n    default: 'dot'\n  },\n  dotPlacement: {\n    type: String as PropType<'top' | 'bottom' | 'left' | 'right'>,\n    default: 'bottom'\n  },\n  slidesPerView: {\n    type: [Number, String] as PropType<number | 'auto'>,\n    default: 1\n  },\n  spaceBetween: {\n    type: Number,\n    default: 0\n  },\n  centeredSlides: Boolean,\n  direction: {\n    type: String as PropType<'horizontal' | 'vertical'>,\n    default: 'horizontal'\n  },\n  autoplay: Boolean,\n  interval: {\n    type: Number,\n    default: 5000\n  },\n  loop: {\n    type: Boolean,\n    default: true\n  },\n  effect: {\n    type: String as PropType<'slide' | 'fade' | 'card' | 'custom'>,\n    default: 'slide'\n  },\n  showDots: {\n    type: Boolean,\n    default: true\n  },\n  trigger: {\n    type: String as PropType<'click' | 'hover'>,\n    default: 'click'\n  },\n  transitionStyle: {\n    type: Object as PropType<TransitionStyle>,\n    default: (): TransitionStyle => ({\n      transitionDuration: '300ms'\n    })\n  },\n  transitionProps: Object as PropType<TransitionProps>,\n  draggable: Boolean,\n  prevSlideStyle: [Object, String] as PropType<CSSProperties | string>,\n  nextSlideStyle: [Object, String] as PropType<CSSProperties | string>,\n  touchable: {\n    type: Boolean,\n    default: true\n  },\n  mousewheel: Boolean,\n  keyboard: Boolean,\n  'onUpdate:currentIndex': Function as PropType<\n    (currentIndex: number, lastIndex: number) => void\n  >,\n  onUpdateCurrentIndex: Function as PropType<\n    (currentIndex: number, lastIndex: number) => void\n  >\n}\n\nexport type CarouselProps = ExtractPublicPropTypes<typeof carouselProps>\n\nexport interface CarouselSlots {\n  default?: () => VNode[]\n  arrow?: (props: CarouselArrowSlotProps) => VNode[]\n  dots?: (props: CarouselDotSlotProps) => VNode[]\n}\n\n// only one carousel is allowed to trigger touch globally\nlet globalDragging = false\n\nexport default defineComponent({\n  name: 'Carousel',\n  props: carouselProps,\n  slots: Object as SlotsType<CarouselSlots>,\n  setup(props) {\n    const { mergedClsPrefixRef, inlineThemeDisabled } = useConfig(props)\n    // Dom\n    const selfElRef = ref<HTMLDivElement | null>(null)\n    const slidesElRef = ref<HTMLDivElement | null>(null)\n    const slideElsRef = ref<HTMLElement[]>([])\n    const slideVNodesRef = { value: [] as VNode[] }\n\n    // Computed states\n    const verticalRef = computed(() => props.direction === 'vertical')\n    const sizeAxisRef = computed(() => (verticalRef.value ? 'height' : 'width'))\n    const spaceAxisRef = computed(() =>\n      verticalRef.value ? 'bottom' : 'right'\n    )\n    const sequenceLayoutRef = computed(() => props.effect === 'slide')\n    const duplicatedableRef = computed(\n      // duplicate the copy operation in `slide` mode,\n      // because only its DOM is sequence layout\n      () => props.loop && props.slidesPerView === 1 && sequenceLayoutRef.value\n    )\n    // user wants to control the transition animation\n    const userWantsControlRef = computed(() => props.effect === 'custom')\n\n    // used to calculate total views\n    const displaySlidesPerViewRef = computed(() =>\n      !sequenceLayoutRef.value || props.centeredSlides ? 1 : props.slidesPerView\n    )\n    // used to calculate the size of each slide\n    const realSlidesPerViewRef = computed(() =>\n      userWantsControlRef.value ? 1 : props.slidesPerView\n    )\n    // we automatically calculate total view for special slides per view\n    const autoSlideSizeRef = computed(\n      () =>\n        displaySlidesPerViewRef.value === 'auto'\n        || (props.slidesPerView === 'auto' && props.centeredSlides)\n    )\n\n    // Carousel size\n    const perViewSizeRef = ref({ width: 0, height: 0 })\n    const slideSizesTrigger = ref(0)\n    const slideSizesRef = computed(() => {\n      const { value: slidesEls } = slideElsRef\n      if (!slidesEls.length)\n        return []\n      // eslint-disable-next-line ts/no-unused-expressions\n      slideSizesTrigger.value\n      const { value: autoSlideSize } = autoSlideSizeRef\n      if (autoSlideSize) {\n        return slidesEls.map(slide => calculateSize(slide))\n      }\n      const { value: slidesPerView } = realSlidesPerViewRef\n      const { value: perViewSize } = perViewSizeRef\n      const { value: axis } = sizeAxisRef\n      let axisSize = perViewSize[axis]\n      if (slidesPerView !== 'auto') {\n        const { spaceBetween } = props\n        const remaining = axisSize - (slidesPerView - 1) * spaceBetween\n        const percentage = 1 / Math.max(1, slidesPerView)\n        axisSize = remaining * percentage\n      }\n      const slideSize = { ...perViewSize, [axis]: axisSize }\n      return slidesEls.map(() => slideSize)\n    })\n\n    // The translate required to reach each slide\n    const slideTranlatesRef = computed(() => {\n      const { value: slideSizes } = slideSizesRef\n      if (!slideSizes.length)\n        return []\n      const { centeredSlides, spaceBetween } = props\n      const { value: axis } = sizeAxisRef\n      const { [axis]: perViewSize } = perViewSizeRef.value\n      let previousTranslate = 0\n      return slideSizes.map(({ [axis]: slideSize }) => {\n        let translate = previousTranslate\n        if (centeredSlides) {\n          translate += (slideSize - perViewSize) / 2\n        }\n        previousTranslate += slideSize + spaceBetween\n        return translate\n      })\n    })\n\n    // Styles\n    const isMountedRef = ref(false)\n    const transitionStyleRef = computed(() => {\n      const { transitionStyle } = props\n      return transitionStyle\n        ? keep(transitionStyle, transitionProperties as any)\n        : {}\n    })\n    const speedRef = computed(() =>\n      userWantsControlRef.value\n        ? 0\n        : resolveSpeed(transitionStyleRef.value.transitionDuration)\n    )\n    const slideStylesRef = computed(() => {\n      const { value: slidesEls } = slideElsRef\n      if (!slidesEls.length)\n        return []\n      const useComputedSize = !(\n        autoSlideSizeRef.value || realSlidesPerViewRef.value === 1\n      )\n      const getSlideSize = (index: number): Partial<Size> | undefined => {\n        if (useComputedSize) {\n          const { value: axis } = sizeAxisRef\n          return {\n            [axis]: `${slideSizesRef.value[index][axis]}px`\n          }\n        }\n      }\n      if (userWantsControlRef.value) {\n        // We center each slide when user wants to control the transition animation,\n        // so there is no need to calculate the offset\n        return slidesEls.map((_, i) => getSlideSize(i))\n      }\n      const { effect, spaceBetween } = props\n      const { value: spaceAxis } = spaceAxisRef\n      return slidesEls.reduce<CSSProperties[]>((styles, _, i) => {\n        const style = {\n          ...getSlideSize(i),\n          [`margin-${spaceAxis}`]: `${spaceBetween}px`\n        }\n        styles.push(style)\n        if (isMountedRef.value && (effect === 'fade' || effect === 'card')) {\n          Object.assign(style, transitionStyleRef.value)\n        }\n        return styles\n      }, [])\n    })\n\n    // Total\n    const totalViewRef = computed(() => {\n      const { value: slidesPerView } = displaySlidesPerViewRef\n      const { length: totalSlides } = slideElsRef.value\n      if (slidesPerView !== 'auto') {\n        return Math.max(totalSlides - slidesPerView, 0) + 1\n      }\n      else {\n        const { value: slideSizes } = slideSizesRef\n        const { length } = slideSizes\n        if (!length)\n          return totalSlides\n        const { value: translates } = slideTranlatesRef\n        const { value: axis } = sizeAxisRef\n        const perViewSize = perViewSizeRef.value[axis]\n        let lastViewSize = slideSizes[slideSizes.length - 1][axis]\n        let i = length\n        while (i > 1 && lastViewSize < perViewSize) {\n          i--\n          lastViewSize += translates[i] - translates[i - 1]\n        }\n        return clampValue(i + 1, 1, length)\n      }\n    })\n    const displayTotalViewRef = computed(() =>\n      getDisplayTotalView(totalViewRef.value, duplicatedableRef.value)\n    )\n\n    // Index\n    const defaultRealIndex = getRealIndex(\n      props.defaultIndex,\n      duplicatedableRef.value\n    )\n    const uncontrolledDisplayIndexRef = ref(\n      getDisplayIndex(\n        defaultRealIndex,\n        totalViewRef.value,\n        duplicatedableRef.value\n      )\n    )\n    const mergedDisplayIndexRef = useMergedState(\n      toRef(props, 'currentIndex'),\n      uncontrolledDisplayIndexRef\n    )\n    const realIndexRef = computed(() =>\n      getRealIndex(mergedDisplayIndexRef.value, duplicatedableRef.value)\n    )\n\n    // Reality methods\n    function toRealIndex(index: number): void {\n      index = clampValue(index, 0, totalViewRef.value - 1)\n      const displayIndex = getDisplayIndex(\n        index,\n        totalViewRef.value,\n        duplicatedableRef.value\n      )\n      const { value: lastDisplayIndex } = mergedDisplayIndexRef\n      if (displayIndex !== mergedDisplayIndexRef.value) {\n        uncontrolledDisplayIndexRef.value = displayIndex\n        props['onUpdate:currentIndex']?.(displayIndex, lastDisplayIndex)\n        props.onUpdateCurrentIndex?.(displayIndex, lastDisplayIndex)\n      }\n    }\n    function getRealPrevIndex(\n      index: number = realIndexRef.value\n    ): number | null {\n      return getPrevIndex(index, totalViewRef.value, props.loop)\n    }\n    function getRealNextIndex(\n      index: number = realIndexRef.value\n    ): number | null {\n      return getNextIndex(index, totalViewRef.value, props.loop)\n    }\n    function isRealPrev(slideOrIndex: HTMLElement | number): boolean {\n      const index = getSlideIndex(slideOrIndex)\n      return (\n        index !== null && getRealPrevIndex() === index && totalViewRef.value > 1\n      )\n    }\n    function isRealNext(slideOrIndex: HTMLElement | number): boolean {\n      const index = getSlideIndex(slideOrIndex)\n      return (\n        index !== null && getRealNextIndex() === index && totalViewRef.value > 1\n      )\n    }\n    function isRealActive(slideOrIndex: HTMLElement | number): boolean {\n      return realIndexRef.value === getSlideIndex(slideOrIndex)\n    }\n\n    // Display methods\n    // They are used to deal with the actual values displayed on the UI\n    function isDisplayActive(index: number): boolean {\n      return mergedDisplayIndexRef.value === index\n    }\n    function isPrevDisabled(): boolean {\n      return getRealPrevIndex() === null\n    }\n    function isNextDisabled(): boolean {\n      return getRealNextIndex() === null\n    }\n\n    // To\n    let expectedTransitionDirection = 0\n    function to(index: number): void {\n      const realIndex = clampValue(\n        getRealIndex(index, duplicatedableRef.value),\n        0,\n        totalViewRef.value\n      )\n      if (\n        index !== mergedDisplayIndexRef.value\n        || realIndex !== realIndexRef.value\n      ) {\n        toRealIndex(realIndex)\n      }\n    }\n    function prev(): void {\n      const prevIndex = getRealPrevIndex()\n      if (prevIndex !== null) {\n        expectedTransitionDirection = -1\n        toRealIndex(prevIndex)\n      }\n    }\n    function next(): void {\n      const nextIndex = getRealNextIndex()\n      if (nextIndex !== null) {\n        expectedTransitionDirection = 1\n        toRealIndex(nextIndex)\n      }\n    }\n\n    // Translate to\n    let inTransition = false\n\n    function prevIfSlideTransitionEnd(): void {\n      if (!inTransition || !duplicatedableRef.value)\n        prev()\n    }\n    function nextIfSlideTransitionEnd(): void {\n      if (!inTransition || !duplicatedableRef.value)\n        next()\n    }\n\n    // record the translate of each slide, so that it can be restored at touch\n    let previousTranslate = 0\n    const translateStyleRef = ref({}) as Ref<CSSProperties>\n    function updateTranslate(translate: number, speed = 0): void {\n      translateStyleRef.value = Object.assign({}, transitionStyleRef.value, {\n        transform: verticalRef.value\n          ? `translateY(${-translate}px)`\n          : `translateX(${-translate}px)`,\n        transitionDuration: `${speed}ms`\n      })\n    }\n    function fixTranslate(speed = 0): void {\n      if (sequenceLayoutRef.value) {\n        translateTo(realIndexRef.value, speed)\n      }\n      else if (previousTranslate !== 0) {\n        if (!inTransition && speed > 0) {\n          inTransition = true\n        }\n        updateTranslate((previousTranslate = 0), speed)\n      }\n    }\n    function translateTo(index: number, speed: number): void {\n      const translate = getTranslate(index)\n      if (translate !== previousTranslate && speed > 0) {\n        inTransition = true\n      }\n      previousTranslate = getTranslate(realIndexRef.value)\n      updateTranslate(translate, speed)\n    }\n    function getTranslate(index: number): number {\n      let translate\n      // Deal with auto slides pre view\n      if (index >= totalViewRef.value - 1) {\n        translate = getLastViewTranslate()\n      }\n      else {\n        translate = slideTranlatesRef.value[index] || 0\n      }\n      return translate\n    }\n    function getLastViewTranslate(): number {\n      if (displaySlidesPerViewRef.value === 'auto') {\n        const { value: axis } = sizeAxisRef\n        const { [axis]: perViewSize } = perViewSizeRef.value\n        const { value: translates } = slideTranlatesRef\n        const lastTranslate = translates[translates.length - 1]\n        let overallSize\n        if (lastTranslate === undefined) {\n          overallSize = perViewSize\n        }\n        else {\n          const { value: slideSizes } = slideSizesRef\n          overallSize = lastTranslate + slideSizes[slideSizes.length - 1][axis]\n        }\n        // Bring the last slide to the edge\n        return overallSize - perViewSize\n      }\n      else {\n        const { value: translates } = slideTranlatesRef\n        return translates[totalViewRef.value - 1] || 0\n      }\n    }\n\n    // Provide\n    const carouselContext: CarouselContextValue = {\n      currentIndexRef: mergedDisplayIndexRef,\n      to,\n      prev: prevIfSlideTransitionEnd,\n      next: nextIfSlideTransitionEnd,\n      isVertical: () => verticalRef.value,\n      isHorizontal: () => !verticalRef.value,\n      isPrev: isRealPrev,\n      isNext: isRealNext,\n      isActive: isRealActive,\n      isPrevDisabled,\n      isNextDisabled,\n      getSlideIndex,\n      getSlideStyle,\n      addSlide,\n      removeSlide,\n      onCarouselItemClick\n    }\n    provideCarouselContext(carouselContext)\n    function addSlide(slide?: HTMLElement): void {\n      if (!slide)\n        return\n      slideElsRef.value.push(slide)\n    }\n    function removeSlide(slide?: HTMLElement): void {\n      if (!slide)\n        return\n      const index = getSlideIndex(slide)\n      if (index !== -1) {\n        slideElsRef.value.splice(index, 1)\n      }\n    }\n    function getSlideIndex(slideOrIndex?: HTMLElement | number): number {\n      return typeof slideOrIndex === 'number'\n        ? slideOrIndex\n        : slideOrIndex\n          ? slideElsRef.value.indexOf(slideOrIndex)\n          : -1\n    }\n    function getSlideStyle(\n      slide: HTMLElement | number\n    ): string | Record<string, string | number> | undefined {\n      const index = getSlideIndex(slide)\n      if (index !== -1) {\n        const styles: any[] = [slideStylesRef.value[index]]\n        const isPrev = carouselContext.isPrev(index)\n        const isNext = carouselContext.isNext(index)\n        if (isPrev) {\n          styles.push(props.prevSlideStyle || '')\n        }\n        if (isNext) {\n          styles.push(props.nextSlideStyle || '')\n        }\n        return normalizeStyle(styles)\n      }\n    }\n    // Drag\n    let dragStartX = 0\n    let dragStartY = 0\n    let dragOffset = 0\n    let dragStartTime = 0\n    let dragging = false\n    let isEffectiveDrag = false\n    function onCarouselItemClick(index: number, event: MouseEvent): void {\n      let allowClick = !inTransition && !dragging && !isEffectiveDrag\n      if (props.effect === 'card' && allowClick && !isRealActive(index)) {\n        to(index)\n        allowClick = false\n      }\n      if (!allowClick) {\n        event.preventDefault()\n        event.stopPropagation()\n      }\n    }\n\n    // Autoplay\n    let autoplayTimer: number | null = null\n    function stopAutoplay(): void {\n      if (autoplayTimer) {\n        clearInterval(autoplayTimer)\n        autoplayTimer = null\n      }\n    }\n    function resetAutoplay(): void {\n      stopAutoplay()\n      const disabled = !props.autoplay || displayTotalViewRef.value < 2\n      if (!disabled) {\n        autoplayTimer = window.setInterval(next, props.interval)\n      }\n    }\n\n    function handleTouchstart(event: MouseEvent | TouchEvent): void {\n      if (globalDragging)\n        return\n      if (\n        !slidesElRef.value?.contains(\n          getPreciseEventTarget(event) as Node | null\n        )\n      ) {\n        return\n      }\n      globalDragging = true\n      dragging = true\n      isEffectiveDrag = false\n      dragStartTime = Date.now()\n      stopAutoplay()\n      if (\n        event.type !== 'touchstart'\n        && !(event.target as HTMLElement).isContentEditable\n      ) {\n        event.preventDefault()\n      }\n      const touchEvent = isTouchEvent(event) ? event.touches[0] : event\n      if (verticalRef.value) {\n        dragStartY = touchEvent.clientY\n      }\n      else {\n        dragStartX = touchEvent.clientX\n      }\n      if (props.touchable) {\n        on('touchmove', document, handleTouchmove)\n        on('touchend', document, handleTouchend)\n        on('touchcancel', document, handleTouchend)\n      }\n      if (props.draggable) {\n        on('mousemove', document, handleTouchmove)\n        on('mouseup', document, handleTouchend)\n      }\n    }\n    function handleTouchmove(event: MouseEvent | TouchEvent): void {\n      const { value: vertical } = verticalRef\n      const { value: axis } = sizeAxisRef\n      const touchEvent = isTouchEvent(event) ? event.touches[0] : event\n      const offset = vertical\n        ? touchEvent.clientY - dragStartY\n        : touchEvent.clientX - dragStartX\n      const perViewSize = perViewSizeRef.value[axis]\n      dragOffset = clampValue(offset, -perViewSize, perViewSize)\n      if (event.cancelable) {\n        event.preventDefault()\n      }\n      if (sequenceLayoutRef.value) {\n        updateTranslate(previousTranslate - dragOffset, 0)\n      }\n    }\n    function handleTouchend(): void {\n      const { value: realIndex } = realIndexRef\n      let currentIndex: number | null = realIndex\n      if (!inTransition && dragOffset !== 0 && sequenceLayoutRef.value) {\n        const currentTranslate = previousTranslate - dragOffset\n        const translates = [\n          ...slideTranlatesRef.value.slice(0, totalViewRef.value - 1),\n          getLastViewTranslate()\n        ]\n        let prevOffset: number | null = null\n        for (let i = 0; i < translates.length; i++) {\n          const offset = Math.abs(translates[i] - currentTranslate)\n          if (prevOffset !== null && prevOffset < offset) {\n            break\n          }\n          prevOffset = offset\n          currentIndex = i\n        }\n      }\n      if (currentIndex === realIndex) {\n        const timeElapsed = Date.now() - dragStartTime\n        const { value: axis } = sizeAxisRef\n        const perViewSize = perViewSizeRef.value[axis]\n        // more than 50% width or faster than 0.4px per ms\n        if (dragOffset > perViewSize / 2 || dragOffset / timeElapsed > 0.4) {\n          prev()\n        }\n        else if (\n          dragOffset < -perViewSize / 2\n          || dragOffset / timeElapsed < -0.4\n        ) {\n          next()\n        }\n      }\n      if (currentIndex !== null && currentIndex !== realIndex) {\n        isEffectiveDrag = true\n        toRealIndex(currentIndex)\n        void nextTick(() => {\n          if (\n            !duplicatedableRef.value\n            || uncontrolledDisplayIndexRef.value !== mergedDisplayIndexRef.value\n          ) {\n            fixTranslate(speedRef.value)\n          }\n        })\n      }\n      else {\n        fixTranslate(speedRef.value)\n      }\n      resetDragStatus()\n      resetAutoplay()\n    }\n    function resetDragStatus(): void {\n      if (dragging) {\n        globalDragging = false\n      }\n      dragging = false\n      dragStartX = 0\n      dragStartY = 0\n      dragOffset = 0\n      dragStartTime = 0\n      off('touchmove', document, handleTouchmove)\n      off('touchend', document, handleTouchend)\n      off('touchcancel', document, handleTouchend)\n      off('mousemove', document, handleTouchmove)\n      off('mouseup', document, handleTouchend)\n    }\n\n    function handleTransitionEnd(): void {\n      if (sequenceLayoutRef.value && inTransition) {\n        const { value: realIndex } = realIndexRef\n        translateTo(realIndex, 0)\n      }\n      else {\n        resetAutoplay()\n      }\n      if (sequenceLayoutRef.value) {\n        translateStyleRef.value.transitionDuration = '0ms'\n      }\n      inTransition = false\n    }\n    function handleMousewheel(event: WheelEvent): void {\n      event.preventDefault()\n      if (inTransition)\n        return\n      let { deltaX, deltaY } = event\n      if (event.shiftKey && !deltaX) {\n        deltaX = deltaY\n      }\n      const prevMultiplier = -1\n      const nextMultiplier = 1\n      const m = (deltaX || deltaY) > 0 ? nextMultiplier : prevMultiplier\n      let rx = 0\n      let ry = 0\n      if (verticalRef.value) {\n        ry = m\n      }\n      else {\n        rx = m\n      }\n      const responseStep = 10\n      if (ry * deltaY >= responseStep || rx * deltaX >= responseStep) {\n        if (m === nextMultiplier && !isNextDisabled()) {\n          next()\n        }\n        else if (m === prevMultiplier && !isPrevDisabled()) {\n          prev()\n        }\n      }\n    }\n    function handleResize(): void {\n      perViewSizeRef.value = calculateSize(selfElRef.value as HTMLElement, true)\n      resetAutoplay()\n    }\n    function handleSlideResize(): void {\n      if (autoSlideSizeRef.value) {\n        slideSizesTrigger.value++\n      }\n    }\n    function handleMouseenter(): void {\n      if (props.autoplay) {\n        stopAutoplay()\n      }\n    }\n    function handleMouseleave(): void {\n      if (props.autoplay) {\n        resetAutoplay()\n      }\n    }\n    onMounted(() => {\n      watchEffect(resetAutoplay)\n      requestAnimationFrame(() => (isMountedRef.value = true))\n    })\n    onBeforeUnmount(() => {\n      resetDragStatus()\n      stopAutoplay()\n    })\n    // Fix index when remounting\n    onUpdated(() => {\n      const { value: slidesEls } = slideElsRef\n      const { value: slideVNodes } = slideVNodesRef\n      const indexMap = new Map<HTMLElement, number>()\n      const getDisplayIndex = (el: HTMLElement): number =>\n        indexMap.has(el) ? indexMap.get(el)! : -1\n      let isChanged = false\n      for (let i = 0; i < slidesEls.length; i++) {\n        const index = slideVNodes.findIndex(v => v.el === slidesEls[i])\n        if (index !== i) {\n          isChanged = true\n        }\n        indexMap.set(slidesEls[i], index)\n      }\n      if (isChanged) {\n        slidesEls.sort((a, b) => getDisplayIndex(a) - getDisplayIndex(b))\n      }\n    })\n    watch(\n      realIndexRef,\n      (nextRealIndex, lastRealIndex) => {\n        if (nextRealIndex === lastRealIndex) {\n          expectedTransitionDirection = 0\n          return\n        }\n        resetAutoplay()\n        if (sequenceLayoutRef.value) {\n          if (duplicatedableRef.value) {\n            const { value: length } = totalViewRef\n            if (\n              expectedTransitionDirection === -1\n              && lastRealIndex === 1\n              && nextRealIndex === length - 2\n            ) {\n              nextRealIndex = 0\n            }\n            else if (\n              expectedTransitionDirection === 1\n              && lastRealIndex === length - 2\n              && nextRealIndex === 1\n            ) {\n              nextRealIndex = length - 1\n            }\n          }\n          translateTo(nextRealIndex, speedRef.value)\n        }\n        else {\n          fixTranslate()\n        }\n        expectedTransitionDirection = 0\n      },\n      { immediate: true }\n    )\n    watch(\n      [duplicatedableRef, displaySlidesPerViewRef],\n      () =>\n        void nextTick(() => {\n          toRealIndex(realIndexRef.value)\n        })\n    )\n    watch(\n      slideTranlatesRef,\n      () => {\n        if (sequenceLayoutRef.value) {\n          fixTranslate()\n        }\n      },\n      {\n        deep: true\n      }\n    )\n    watch(sequenceLayoutRef, (value) => {\n      if (!value) {\n        inTransition = false\n        // if the current mode does not support translate, reset the position of the wrapper\n        updateTranslate((previousTranslate = 0))\n      }\n      else {\n        fixTranslate()\n      }\n    })\n    const slidesControlListenersRef = computed(() => {\n      return {\n        onTouchstartPassive: props.touchable ? handleTouchstart : undefined,\n        onMousedown: props.draggable ? handleTouchstart : undefined,\n        onWheel: props.mousewheel ? handleMousewheel : undefined\n      }\n    })\n    const arrowSlotPropsRef = computed<ArrowScopedSlotProps>(() => ({\n      ...keep(carouselContext, [\n        'to',\n        'prev',\n        'next',\n        'isPrevDisabled',\n        'isNextDisabled'\n      ]),\n      total: displayTotalViewRef.value,\n      currentIndex: mergedDisplayIndexRef.value\n    }))\n    const dotSlotPropsRef = computed<DotScopedSlotProps>(() => ({\n      total: displayTotalViewRef.value,\n      currentIndex: mergedDisplayIndexRef.value,\n      to: carouselContext.to\n    }))\n    const caroulseExposedMethod: CarouselInst = {\n      getCurrentIndex: () => mergedDisplayIndexRef.value,\n      to,\n      prev,\n      next\n    }\n    const themeRef = useTheme(\n      'Carousel',\n      '-carousel',\n      style,\n      carouselLight,\n      props,\n      mergedClsPrefixRef\n    )\n    const cssVarsRef = computed(() => {\n      const {\n        common: { cubicBezierEaseInOut },\n        self: {\n          dotSize,\n          dotColor,\n          dotColorActive,\n          dotColorFocus,\n          dotLineWidth,\n          dotLineWidthActive,\n          arrowColor\n        }\n      } = themeRef.value\n      return {\n        '--n-bezier': cubicBezierEaseInOut,\n        '--n-dot-color': dotColor,\n        '--n-dot-color-focus': dotColorFocus,\n        '--n-dot-color-active': dotColorActive,\n        '--n-dot-size': dotSize,\n        '--n-dot-line-width': dotLineWidth,\n        '--n-dot-line-width-active': dotLineWidthActive,\n        '--n-arrow-color': arrowColor\n      }\n    })\n    const themeClassHandle = inlineThemeDisabled\n      ? useThemeClass('carousel', undefined, cssVarsRef, props)\n      : undefined\n    return {\n      mergedClsPrefix: mergedClsPrefixRef,\n      selfElRef,\n      slidesElRef,\n      slideVNodes: slideVNodesRef,\n      duplicatedable: duplicatedableRef,\n      userWantsControl: userWantsControlRef,\n      autoSlideSize: autoSlideSizeRef,\n      realIndex: realIndexRef,\n      slideStyles: slideStylesRef,\n      translateStyle: translateStyleRef,\n      slidesControlListeners: slidesControlListenersRef,\n      handleTransitionEnd,\n      handleResize,\n      handleSlideResize,\n      handleMouseenter,\n      handleMouseleave,\n      isActive: isDisplayActive,\n      arrowSlotProps: arrowSlotPropsRef,\n      dotSlotProps: dotSlotPropsRef,\n      ...caroulseExposedMethod,\n      cssVars: inlineThemeDisabled ? undefined : cssVarsRef,\n      themeClass: themeClassHandle?.themeClass,\n      onRender: themeClassHandle?.onRender\n    }\n  },\n  render() {\n    const {\n      mergedClsPrefix,\n      showArrow,\n      userWantsControl,\n      slideStyles,\n      dotType,\n      dotPlacement,\n      slidesControlListeners,\n      transitionProps = {},\n      arrowSlotProps,\n      dotSlotProps,\n      $slots: { default: defaultSlot, dots: dotsSlot, arrow: arrowSlot }\n    } = this\n    const children = (defaultSlot && flatten(defaultSlot())) || []\n    let slides = filterCarouselItem(children)\n    if (!slides.length) {\n      slides = children.map(ch => (\n        <NCarouselItem>\n          {{\n            default: () => cloneVNode(ch)\n          }}\n        </NCarouselItem>\n      ))\n    }\n    if (this.duplicatedable) {\n      slides = addDuplicateSlides(slides)\n    }\n    this.slideVNodes.value = slides\n    // When users need to customize the size of the slide,\n    // we listen to them to fix the current translate\n    if (this.autoSlideSize) {\n      slides = slides.map(slide => (\n        <VResizeObserver onResize={this.handleSlideResize}>\n          {{\n            default: () => slide\n          }}\n        </VResizeObserver>\n      ))\n    }\n    this.onRender?.()\n    return (\n      <div\n        ref=\"selfElRef\"\n        class={[\n          this.themeClass,\n          `${mergedClsPrefix}-carousel`,\n          this.direction === 'vertical'\n          && `${mergedClsPrefix}-carousel--vertical`,\n          this.showArrow && `${mergedClsPrefix}-carousel--show-arrow`,\n          `${mergedClsPrefix}-carousel--${dotPlacement}`,\n          `${mergedClsPrefix}-carousel--${this.direction}`,\n          `${mergedClsPrefix}-carousel--${this.effect}`,\n          userWantsControl && `${mergedClsPrefix}-carousel--usercontrol`\n        ]}\n        style={this.cssVars as CSSProperties}\n        {...slidesControlListeners}\n        onMouseenter={this.handleMouseenter}\n        onMouseleave={this.handleMouseleave}\n      >\n        <VResizeObserver onResize={this.handleResize}>\n          {{\n            default: () => (\n              <div\n                ref=\"slidesElRef\"\n                class={`${mergedClsPrefix}-carousel__slides`}\n                role=\"listbox\"\n                style={this.translateStyle}\n                onTransitionend={this.handleTransitionEnd}\n              >\n                {userWantsControl\n                  ? slides.map((slide, i) => (\n                      <div style={slideStyles[i]} key={i}>\n                        {withDirectives(\n                          <Transition {...transitionProps}>\n                            {{\n                              default: () => slide\n                            }}\n                          </Transition>,\n                          [[vShow, this.isActive(i)]]\n                        )}\n                      </div>\n                    ))\n                  : slides}\n              </div>\n            )\n          }}\n        </VResizeObserver>\n        {this.showDots\n          && dotSlotProps.total > 1\n          && resolveSlotWithTypedProps(dotsSlot, dotSlotProps, () => [\n            <NCarouselDots\n              key={dotType + dotPlacement}\n              total={dotSlotProps.total}\n              currentIndex={dotSlotProps.currentIndex}\n              dotType={dotType}\n              trigger={this.trigger}\n              keyboard={this.keyboard}\n            />\n          ])}\n        {showArrow\n          && resolveSlotWithTypedProps(arrowSlot, arrowSlotProps, () => [\n            <NCarouselArrow />\n          ])}\n      </div>\n    )\n  }\n})\n\nfunction filterCarouselItem(vnodes: VNode[]): VNode[] {\n  return vnodes.reduce<VNode[]>((carouselItems, vnode) => {\n    if (isCarouselItem(vnode)) {\n      carouselItems.push(vnode)\n    }\n    return carouselItems\n  }, [])\n}\n"
  },
  {
    "path": "src/carousel/src/CarouselArrow.tsx",
    "content": "import { defineComponent, h } from 'vue'\nimport { useConfig } from '../../_mixins'\nimport { useCarouselContext } from './CarouselContext'\n\nfunction renderBackwardIcon() {\n  return (\n    <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 16 16\">\n      <g fill=\"none\">\n        <path\n          d=\"M10.26 3.2a.75.75 0 0 1 .04 1.06L6.773 8l3.527 3.74a.75.75 0 1 1-1.1 1.02l-4-4.25a.75.75 0 0 1 0-1.02l4-4.25a.75.75 0 0 1 1.06-.04z\"\n          fill=\"currentColor\"\n        >\n        </path>\n      </g>\n    </svg>\n  )\n}\n\nfunction renderForwardIcon() {\n  return (\n    <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 16 16\">\n      <g fill=\"none\">\n        <path\n          d=\"M5.74 3.2a.75.75 0 0 0-.04 1.06L9.227 8L5.7 11.74a.75.75 0 1 0 1.1 1.02l4-4.25a.75.75 0 0 0 0-1.02l-4-4.25a.75.75 0 0 0-1.06-.04z\"\n          fill=\"currentColor\"\n        >\n        </path>\n      </g>\n    </svg>\n  )\n}\n\nexport default defineComponent({\n  name: 'CarouselArrow',\n  setup(props) {\n    const { mergedClsPrefixRef } = useConfig(props)\n    const { isVertical, isPrevDisabled, isNextDisabled, prev, next }\n      = useCarouselContext()\n    return {\n      mergedClsPrefix: mergedClsPrefixRef,\n      isVertical,\n      isPrevDisabled,\n      isNextDisabled,\n      prev,\n      next\n    }\n  },\n  render() {\n    const { mergedClsPrefix } = this\n    return (\n      <div class={`${mergedClsPrefix}-carousel__arrow-group`}>\n        <div\n          class={[\n            `${mergedClsPrefix}-carousel__arrow`,\n            this.isPrevDisabled()\n            && `${mergedClsPrefix}-carousel__arrow--disabled`\n          ]}\n          role=\"button\"\n          onClick={this.prev}\n        >\n          {renderBackwardIcon()}\n        </div>\n        <div\n          class={[\n            `${mergedClsPrefix}-carousel__arrow`,\n            this.isNextDisabled()\n            && `${mergedClsPrefix}-carousel__arrow--disabled`\n          ]}\n          role=\"button\"\n          onClick={this.next}\n        >\n          {renderForwardIcon()}\n        </div>\n      </div>\n    )\n  }\n})\n"
  },
  {
    "path": "src/carousel/src/CarouselContext.ts",
    "content": "import type { ComputedRef } from 'vue'\nimport { inject, provide } from 'vue'\nimport { createInjectionKey, throwError } from '../../_utils'\n\nexport interface CarouselContextValue {\n  currentIndexRef: ComputedRef<number>\n  to: (index: number) => void\n  prev: () => void\n  next: () => void\n  isVertical: () => boolean\n  isHorizontal: () => boolean\n  isPrev: (slideOrIndex: HTMLElement | number) => boolean\n  isNext: (slideOrIndex: HTMLElement | number) => boolean\n  isActive: (slideOrIndex: HTMLElement | number) => boolean\n  isPrevDisabled: () => boolean\n  isNextDisabled: () => boolean\n  getSlideIndex: (slideOrIndex?: HTMLElement | number) => number\n  getSlideStyle: (\n    slideOrIndex: HTMLElement | number\n  ) => string | Record<string, string | number> | undefined\n  addSlide: (slide?: HTMLElement) => void\n  removeSlide: (slide?: HTMLElement) => void\n  onCarouselItemClick: (index: number, event: MouseEvent) => void\n}\n\nconst carouselMethodsInjectionKey\n  = createInjectionKey<CarouselContextValue>('n-carousel-methods')\n\nexport function provideCarouselContext(\n  contextValue: CarouselContextValue\n): void {\n  provide(carouselMethodsInjectionKey, contextValue)\n}\n\nexport function useCarouselContext(\n  location: string = 'unknown',\n  component: string = 'component'\n): CarouselContextValue {\n  const CarouselContext = inject(carouselMethodsInjectionKey)\n  if (!CarouselContext) {\n    throwError(\n      location,\n      `\\`${component}\\` must be placed inside \\`n-carousel\\`.`\n    )\n  }\n  return CarouselContext\n}\n"
  },
  {
    "path": "src/carousel/src/CarouselDots.tsx",
    "content": "import type { PropType } from 'vue'\nimport type { ExtractPublicPropTypes } from '../../_utils'\nimport { indexMap } from 'seemly'\nimport { defineComponent, h, onBeforeUpdate, ref } from 'vue'\nimport { useConfig } from '../../_mixins'\nimport { useCarouselContext } from './CarouselContext'\n\nconst carouselDotsProps = {\n  total: {\n    type: Number,\n    default: 0\n  },\n  currentIndex: {\n    type: Number,\n    default: 0\n  },\n  dotType: {\n    type: String as PropType<'dot' | 'line' | 'never'>,\n    default: 'dot'\n  },\n  trigger: {\n    type: String as PropType<'click' | 'hover'>,\n    default: 'click'\n  },\n  keyboard: Boolean\n}\n\nexport type CarouselDotsProps = ExtractPublicPropTypes<typeof carouselDotsProps>\n\nexport default defineComponent({\n  name: 'CarouselDots',\n  props: carouselDotsProps,\n  setup(props) {\n    const { mergedClsPrefixRef } = useConfig(props)\n    const dotElsRef = ref<HTMLElement[]>([])\n    const NCarousel = useCarouselContext()\n    function handleKeydown(e: KeyboardEvent, current: number): void {\n      switch (e.key) {\n        case 'Enter':\n        case ' ':\n          e.preventDefault()\n          NCarousel.to(current)\n          return\n      }\n      if (props.keyboard) {\n        handleKeyboard(e)\n      }\n    }\n    function handleMouseenter(current: number): void {\n      if (props.trigger === 'hover') {\n        NCarousel.to(current)\n      }\n    }\n    function handleClick(current: number): void {\n      if (props.trigger === 'click') {\n        NCarousel.to(current)\n      }\n    }\n    function handleKeyboard(e: KeyboardEvent): void {\n      if (e.shiftKey || e.altKey || e.ctrlKey || e.metaKey) {\n        return\n      }\n      const nodeName = document.activeElement?.nodeName.toLowerCase()\n      if (nodeName === 'input' || nodeName === 'textarea') {\n        return\n      }\n      const { code: keycode } = e\n      const isVerticalNext = keycode === 'PageUp' || keycode === 'ArrowUp'\n      const isVerticalPrev = keycode === 'PageDown' || keycode === 'ArrowDown'\n      const isHorizontalNext = keycode === 'PageUp' || keycode === 'ArrowRight'\n      const isHorizontalPrev = keycode === 'PageDown' || keycode === 'ArrowLeft'\n      const vertical = NCarousel.isVertical()\n      const wantToNext = vertical ? isVerticalNext : isHorizontalNext\n      const wantToPrev = vertical ? isVerticalPrev : isHorizontalPrev\n      if (!wantToNext && !wantToPrev) {\n        return\n      }\n      e.preventDefault()\n      if (wantToNext && !NCarousel.isNextDisabled()) {\n        NCarousel.next()\n        focusDot(NCarousel.currentIndexRef.value)\n      }\n      else if (wantToPrev && !NCarousel.isPrevDisabled()) {\n        NCarousel.prev()\n        focusDot(NCarousel.currentIndexRef.value)\n      }\n    }\n    function focusDot(index: number): void {\n      dotElsRef.value[index]?.focus()\n    }\n    onBeforeUpdate(() => (dotElsRef.value.length = 0))\n    return {\n      mergedClsPrefix: mergedClsPrefixRef,\n      dotEls: dotElsRef,\n      handleKeydown,\n      handleMouseenter,\n      handleClick\n    }\n  },\n  render() {\n    const { mergedClsPrefix, dotEls } = this\n    return (\n      <div\n        class={[\n          `${mergedClsPrefix}-carousel__dots`,\n          `${mergedClsPrefix}-carousel__dots--${this.dotType}`\n        ]}\n        role=\"tablist\"\n      >\n        {indexMap(this.total, (i) => {\n          const selected = i === this.currentIndex\n          return (\n            <div\n              aria-selected={selected}\n              ref={el => dotEls.push(el as HTMLElement)}\n              role=\"button\"\n              tabindex=\"0\"\n              class={[\n                `${mergedClsPrefix}-carousel__dot`,\n                selected && `${mergedClsPrefix}-carousel__dot--active`\n              ]}\n              key={i}\n              onClick={() => {\n                this.handleClick(i)\n              }}\n              onMouseenter={() => {\n                this.handleMouseenter(i)\n              }}\n              onKeydown={(e) => {\n                this.handleKeydown(e, i)\n              }}\n            />\n          )\n        })}\n      </div>\n    )\n  }\n})\n"
  },
  {
    "path": "src/carousel/src/CarouselItem.tsx",
    "content": "import type { VNode } from 'vue'\nimport { camelCase } from 'lodash-es'\nimport {\n  computed,\n  defineComponent,\n  h,\n  onBeforeUnmount,\n  onMounted,\n  ref\n} from 'vue'\nimport { useConfig } from '../../_mixins'\nimport { useCarouselContext } from './CarouselContext'\n\nconst CarouselItemName = 'CarouselItem'\n\nexport function isCarouselItem(child: VNode): boolean {\n  return (child.type as any)?.name === CarouselItemName\n}\n\nexport default defineComponent({\n  name: CarouselItemName,\n  setup(props) {\n    const { mergedClsPrefixRef } = useConfig(props)\n    const NCarousel = useCarouselContext(\n      camelCase(CarouselItemName),\n      `n-${camelCase(CarouselItemName)}`\n    )\n    const selfElRef = ref<HTMLElement>()\n    const indexRef = computed(() => {\n      const { value: selfEl } = selfElRef\n      return selfEl ? NCarousel.getSlideIndex(selfEl) : -1\n    })\n    const isPrevRef = computed(() => NCarousel.isPrev(indexRef.value))\n    const isNextRef = computed(() => NCarousel.isNext(indexRef.value))\n    const isActiveRef = computed(() => NCarousel.isActive(indexRef.value))\n    const styleRef = computed(() => NCarousel.getSlideStyle(indexRef.value))\n    onMounted(() => {\n      NCarousel.addSlide(selfElRef.value)\n    })\n    onBeforeUnmount(() => {\n      NCarousel.removeSlide(selfElRef.value)\n    })\n    function handleClick(event: MouseEvent): void {\n      const { value: index } = indexRef\n      if (index !== undefined) {\n        NCarousel?.onCarouselItemClick(index, event)\n      }\n    }\n    return {\n      mergedClsPrefix: mergedClsPrefixRef,\n      selfElRef,\n      isPrev: isPrevRef,\n      isNext: isNextRef,\n      isActive: isActiveRef,\n      index: indexRef,\n      style: styleRef,\n      handleClick\n    }\n  },\n  render() {\n    const {\n      $slots: slots,\n      mergedClsPrefix,\n      isPrev,\n      isNext,\n      isActive,\n      index,\n      style\n    } = this\n    const className = [\n      `${mergedClsPrefix}-carousel__slide`,\n      {\n        [`${mergedClsPrefix}-carousel__slide--current`]: isActive,\n        [`${mergedClsPrefix}-carousel__slide--prev`]: isPrev,\n        [`${mergedClsPrefix}-carousel__slide--next`]: isNext\n      }\n    ]\n    return (\n      <div\n        ref=\"selfElRef\"\n        class={className}\n        role=\"option\"\n        tabindex=\"-1\"\n        data-index={index}\n        aria-hidden={!isActive}\n        style={style}\n        // We use ts-ignore for vue-tsc, since it seems to patch native event\n        // for vue components\n        // @ts-expect-error vue's tsx has type for capture events\n        onClickCapture={this.handleClick}\n      >\n        {slots.default?.({\n          isPrev,\n          isNext,\n          isActive,\n          index\n        })}\n      </div>\n    )\n  }\n})\n"
  },
  {
    "path": "src/carousel/src/interface.ts",
    "content": "import type { CarouselContextValue } from './CarouselContext'\n\nexport interface CarouselInst {\n  getCurrentIndex: () => number\n  to: (index: number) => void\n  prev: () => void\n  next: () => void\n}\n\nexport interface ArrowScopedSlotProps\n  extends Pick<\n    CarouselContextValue,\n    'to' | 'prev' | 'next' | 'isPrevDisabled' | 'isNextDisabled'\n  > {\n  total: number\n  currentIndex: number\n}\n\nexport interface DotScopedSlotProps extends Pick<CarouselContextValue, 'to'> {\n  total: number\n  currentIndex: number\n}\n\nexport interface Size {\n  width: number\n  height: number\n}\n\nexport interface CarouselArrowSlotProps {\n  total: number\n  currentIndex: number\n  to: (index: number) => void\n  prev: () => void\n  next: () => void\n}\n\nexport interface CarouselDotSlotProps {\n  total: number\n  currentIndex: number\n  to: (index: number) => void\n}\n"
  },
  {
    "path": "src/carousel/src/styles/index.cssr.ts",
    "content": "import { c, cB, cE, cM } from '../../../_utils/cssr'\n\n// vars:\n// --n-bezier\n// --n-dot-color\n// --n-dot-color-focus\n// --n-dot-color-active\n// --n-dot-size\n// --n-dot-line-width\n// --n-dot-line-width-active\n// --n-arrow-color\nexport default cB('carousel', `\n  position: relative;\n  width: 100%;\n  height: 100%;\n  touch-action: pan-y;\n  overflow: hidden;\n`, [\n  cE('slides', `\n    display: flex;\n    width: 100%;\n    height: 100%;\n    transition-timing-function: var(--n-bezier);\n    transition-property: transform;\n  `, [\n    cE('slide', `\n      flex-shrink: 0;\n      position: relative;\n      width: 100%;\n      height: 100%;\n      outline: none;\n      overflow: hidden;\n    `, [\n      c('> img', `\n        display: block;\n      `)\n    ])\n  ]),\n  cE('dots', `\n    position: absolute;\n    display: flex;\n    flex-wrap: nowrap;\n  `, [\n    cM('dot', [\n      cE('dot', `\n        height: var(--n-dot-size);\n        width: var(--n-dot-size);\n        background-color: var(--n-dot-color);\n        border-radius: 50%;\n        cursor: pointer;\n        transition:\n          box-shadow .3s var(--n-bezier),\n          background-color .3s var(--n-bezier);\n        outline: none;\n      `, [\n        c('&:focus', `\n          background-color: var(--n-dot-color-focus);\n        `),\n        cM('active', `\n          background-color: var(--n-dot-color-active);\n        `)\n      ])\n    ]),\n    cM('line', [\n      cE('dot', `\n        border-radius: 9999px;\n        width: var(--n-dot-line-width);\n        height: 4px;\n        background-color: var(--n-dot-color);\n        cursor: pointer;\n        transition:\n          width .3s var(--n-bezier),\n          box-shadow .3s var(--n-bezier),\n          background-color .3s var(--n-bezier);\n        outline: none;\n      `, [\n        c('&:focus', `\n          background-color: var(--n-dot-color-focus);\n        `),\n        cM('active', `\n          width: var(--n-dot-line-width-active);\n          background-color: var(--n-dot-color-active);\n        `)\n      ])\n    ])\n  ]),\n  cE('arrow', `\n    transition: background-color .3s var(--n-bezier);\n    cursor: pointer;\n    height: 28px;\n    width: 28px;\n    display: flex;\n    align-items: center;\n    justify-content: center;\n    background-color: rgba(255, 255, 255, .2);\n    color: var(--n-arrow-color);\n    border-radius: 8px;\n    user-select: none;\n    -webkit-user-select: none;\n    font-size: 18px;\n  `, [\n    c('svg', `\n      height: 1em;\n      width: 1em;\n    `),\n    c('&:hover', `\n      background-color: rgba(255, 255, 255, .3);\n    `)\n  ]),\n  cM('vertical', `\n    touch-action: pan-x;\n  `, [\n    cE('slides', `\n      flex-direction: column;\n    `),\n    cM('fade', [\n      cE('slide', `\n        top: 50%;\n        left: unset;\n        transform: translateY(-50%);\n      `)\n    ]),\n    cM('card', [\n      cE('slide', `\n        top: 50%;\n        left: unset;\n        transform: translateY(-50%) translateZ(-400px);\n      `, [\n        cM('current', `\n          transform: translateY(-50%) translateZ(0);\n        `),\n        cM('prev', `\n          transform: translateY(-100%) translateZ(-200px);\n        `),\n        cM('next', `\n          transform: translateY(0%) translateZ(-200px);\n        `)\n      ])\n    ])\n  ]),\n  cM('usercontrol', [\n    cE('slides', [\n      c('>', [\n        c('div', `\n          position: absolute;\n          top: 50%;\n          left: 50%;\n          width: 100%;\n          height: 100%;\n          transform: translate(-50%, -50%);\n        `)\n      ])\n    ])\n  ]),\n  cM('left', [\n    cE('dots', `\n      transform: translateY(-50%);\n      top: 50%;\n      left: 12px;\n      flex-direction: column;\n    `, [\n      cM('line', [\n        cE('dot', `\n          width: 4px;\n          height: var(--n-dot-line-width);\n          margin: 4px 0;\n          transition:\n            height .3s var(--n-bezier),\n            box-shadow .3s var(--n-bezier),\n            background-color .3s var(--n-bezier);\n          outline: none;\n        `, [\n          cM('active', `\n            height: var(--n-dot-line-width-active);\n          `)\n        ])\n      ])\n    ]),\n    cE('dot', `\n      margin: 4px 0;\n    `)\n  ]),\n  cE('arrow-group', `\n    position: absolute;\n    display: flex;\n    flex-wrap: nowrap;\n  `),\n  cM('vertical', [\n    cE('arrow', `\n      transform: rotate(90deg);\n    `)\n  ]),\n  cM('show-arrow', [\n    cM('bottom', [\n      cE('dots', `\n        transform: translateX(0);\n        bottom: 18px;\n        left: 18px;\n      `)\n    ]),\n    cM('top', [\n      cE('dots', `\n        transform: translateX(0);\n        top: 18px;\n        left: 18px;\n      `)\n    ]),\n    cM('left', [\n      cE('dots', `\n        transform: translateX(0);\n        top: 18px;\n        left: 18px;\n      `)\n    ]),\n    cM('right', [\n      cE('dots', `\n        transform: translateX(0);\n        top: 18px;\n        right: 18px;\n      `)\n    ])\n  ]),\n  cM('left', [\n    cE('arrow-group', `\n      bottom: 12px;\n      left: 12px;\n      flex-direction: column;\n    `, [\n      c('> *:first-child', `\n        margin-bottom: 12px;\n      `)\n    ])\n  ]),\n  cM('right', [\n    cE('dots', `\n      transform: translateY(-50%);\n      top: 50%;\n      right: 12px;\n      flex-direction: column;\n    `, [\n      cM('line', [\n        cE('dot', `\n          width: 4px;\n          height: var(--n-dot-line-width);\n          margin: 4px 0;\n          transition:\n            height .3s var(--n-bezier),\n            box-shadow .3s var(--n-bezier),\n            background-color .3s var(--n-bezier);\n          outline: none;\n        `, [\n          cM('active', `\n            height: var(--n-dot-line-width-active);\n          `)\n        ])\n      ])\n    ]),\n    cE('dot', `\n      margin: 4px 0;\n    `),\n    cE('arrow-group', `\n      bottom: 12px;\n      right: 12px;\n      flex-direction: column;\n    `, [\n      c('> *:first-child', `\n        margin-bottom: 12px;\n      `)\n    ])\n  ]),\n  cM('top', [\n    cE('dots', `\n      transform: translateX(-50%);\n      top: 12px;\n      left: 50%;\n    `, [\n      cM('line', [\n        cE('dot', `\n          margin: 0 4px;\n        `)\n      ])\n    ]),\n    cE('dot', `\n      margin: 0 4px;\n    `),\n    cE('arrow-group', `\n      top: 12px;\n      right: 12px;\n    `, [\n      c('> *:first-child', `\n        margin-right: 12px;\n      `)\n    ])\n  ]),\n  cM('bottom', [\n    cE('dots', `\n      transform: translateX(-50%);\n      bottom: 12px;\n      left: 50%;\n    `, [\n      cM('line', [\n        cE('dot', `\n          margin: 0 4px;\n        `)\n      ])\n    ]),\n    cE('dot', `\n      margin: 0 4px;\n    `),\n    cE('arrow-group', `\n      bottom: 12px;\n      right: 12px;\n    `, [\n      c('> *:first-child', `\n        margin-right: 12px;\n      `)\n    ])\n  ]),\n  cM('fade', [\n    cE('slide', `\n      position: absolute;\n      opacity: 0;\n      transition-property: opacity;\n      pointer-events: none;\n    `, [\n      cM('current', `\n        opacity: 1;\n        pointer-events: auto;\n      `)\n    ])\n  ]),\n  cM('card', [\n    cE('slides', `\n      perspective: 1000px;\n    `),\n    cE('slide', `\n      position: absolute;\n      left: 50%;\n      opacity: 0;\n      transform: translateX(-50%) translateZ(-400px);\n      transition-property: opacity, transform;\n    `, [\n      cM('current', `\n        opacity: 1;\n        transform: translateX(-50%) translateZ(0);\n        z-index: 1;\n      `),\n      cM('prev', `\n        opacity: 0.4;\n        transform: translateX(-100%) translateZ(-200px);\n      `),\n      cM('next', `\n        opacity: 0.4;\n        transform: translateX(0%) translateZ(-200px);\n      `)\n    ])\n  ])\n])\n"
  },
  {
    "path": "src/carousel/src/utils/duplicatedLogic.ts",
    "content": "// Because of the nature of the loop slide work,\n// we need to add duplicates to the left and right of the carousel\n// slot    [ 0 1 2 ]\n// display 2 0 1 2 0\n// real    0 1 2 3 4\n\nimport type { VNode } from 'vue'\nimport { cloneVNode } from 'vue'\n\nexport function addDuplicateSlides(slides: VNode[]): VNode[] {\n  const { length } = slides\n  if (length > 1) {\n    slides.push(duplicateSlide(slides[0], 0, 'append'))\n    slides.unshift(duplicateSlide(slides[length - 1], length - 1, 'prepend'))\n    return slides\n  }\n  return slides\n}\n\nfunction duplicateSlide(\n  child: VNode,\n  index: number,\n  position: 'prepend' | 'append'\n): VNode {\n  return cloneVNode(child, {\n    // for patch\n    key: `carousel-item-duplicate-${index}-${position}`\n  })\n}\n\nexport function getDisplayIndex(\n  current: number,\n  length: number,\n  duplicatedable: boolean\n): number {\n  if (length === 1)\n    return 0\n  return !duplicatedable\n    ? current\n    : current === 0\n      ? length - 3\n      : current === length - 1\n        ? 0\n        : current - 1\n}\n\nexport function getRealIndex(\n  current: number,\n  duplicatedable?: boolean\n): number {\n  return !duplicatedable ? current : current + 1\n}\n\nexport function getPrevIndex(\n  current: number,\n  length: number,\n  duplicatedable?: boolean\n): number | null {\n  if (current < 0)\n    return null\n  return current === 0 ? (duplicatedable ? length - 1 : null) : current - 1\n}\n\nexport function getNextIndex(\n  current: number,\n  length: number,\n  duplicatedable?: boolean\n): number | null {\n  if (current > length - 1)\n    return null\n  return current === length - 1 ? (duplicatedable ? 0 : null) : current + 1\n}\n\nexport function getDisplayTotalView(\n  total: number,\n  duplicatedable?: boolean\n): number {\n  return duplicatedable && total > 3 ? total - 2 : total\n}\n"
  },
  {
    "path": "src/carousel/src/utils/event.ts",
    "content": "export function isTouchEvent(e: MouseEvent | TouchEvent): e is TouchEvent {\n  return window.TouchEvent && e instanceof window.TouchEvent\n}\n"
  },
  {
    "path": "src/carousel/src/utils/index.ts",
    "content": "import type { Size } from '../interface'\n\nexport * from './duplicatedLogic'\nexport * from './event'\n\nexport function calculateSize(element: HTMLElement, innerOnly?: boolean): Size {\n  let { offsetWidth: width, offsetHeight: height } = element\n  if (innerOnly) {\n    const style = getComputedStyle(element)\n    width\n      = width\n        - Number.parseFloat(style.getPropertyValue('padding-left'))\n        - Number.parseFloat(style.getPropertyValue('padding-right'))\n    height\n      = height\n        - Number.parseFloat(style.getPropertyValue('padding-top'))\n        - Number.parseFloat(style.getPropertyValue('padding-bottom'))\n  }\n  return { width, height }\n}\n\nexport function clampValue(value: number, min: number, max: number): number {\n  return value < min ? min : value > max ? max : value\n}\n\nexport function resolveSpeed(value?: string | number): number {\n  if (value === undefined)\n    return 0\n  if (typeof value === 'number')\n    return value\n  const timeRE = /^((\\d+)?\\.?\\d+?)(ms|s)?$/\n  const match = value.match(timeRE)\n  if (match) {\n    const [, number, , unit = 'ms'] = match\n    return Number(number) * (unit === 'ms' ? 1 : 1000)\n  }\n  return 0\n}\n"
  },
  {
    "path": "src/carousel/styles/dark.ts",
    "content": "import type { CarouselTheme } from './light'\nimport { commonDark } from '../../_styles/common'\nimport { self } from './light'\n\nconst carouselDark: CarouselTheme = {\n  name: 'Carousel',\n  common: commonDark,\n  self\n}\n\nexport default carouselDark\n"
  },
  {
    "path": "src/carousel/styles/index.ts",
    "content": "export { default as carouselDark } from './dark'\nexport { default as carouselLight } from './light'\nexport type { CarouselTheme, CarouselThemeVars } from './light'\n"
  },
  {
    "path": "src/carousel/styles/light.ts",
    "content": "import type { Theme } from '../../_mixins'\nimport { commonLight } from '../../_styles/common'\n\nexport function self() {\n  return {\n    dotSize: '8px',\n    dotColor: 'rgba(255, 255, 255, .3)',\n    dotColorActive: 'rgba(255, 255, 255, 1)',\n    dotColorFocus: 'rgba(255, 255, 255, .5)',\n    dotLineWidth: '16px',\n    dotLineWidthActive: '24px',\n    arrowColor: '#eee'\n  }\n}\n\nexport type CarouselThemeVars = ReturnType<typeof self>\n\nconst carouselLight: Theme<'Carousel', CarouselThemeVars> = {\n  name: 'Carousel',\n  common: commonLight,\n  self\n}\n\nexport default carouselLight\nexport type CarouselTheme = typeof carouselLight\n"
  },
  {
    "path": "src/carousel/tests/Carousel.spec.tsx",
    "content": "import { mount } from '@vue/test-utils'\nimport { sleep } from 'seemly'\nimport { h, nextTick } from 'vue'\nimport { NCarousel, NCarouselItem } from '../index'\n\ndescribe('n-carousel', () => {\n  afterEach(() => {\n    vi.useRealTimers()\n  })\n\n  it('should work with import on demand', () => {\n    const wrapper = mount(NCarousel)\n    wrapper.unmount()\n  })\n\n  it('should work with `autoplay` and `interval` prop', async () => {\n    const wrapper = mount(NCarousel, {\n      slots: {\n        default: () => {\n          return [...Array.from({ length: 3 }).keys()].map((i) => {\n            return h('div', {}, i.toString())\n          })\n        }\n      }\n    })\n\n    await wrapper.setProps({ autoplay: true, interval: 50 })\n\n    await sleep(25)\n    // Because `autoplay` is `true`, `[data-index=\"${0}\"]` `aria-hidden` must not be `false` at the moment\n    expect(wrapper.find(`[data-index=\"${0}\"]`).attributes('aria-hidden')).toBe(\n      'true'\n    )\n\n    await sleep(25)\n    // Because `autoplay` is `true` and `interval` is `50`, both `[data-index=\"${0}\"]` and `[data-index=\"${0}\"]` `aria-hidden` must not be `false` at the moment\n    ;([0, 1] as const).forEach((i) => {\n      expect(\n        wrapper.find(`[data-index=\"${i}\"]`).attributes('aria-hidden')\n      ).toBe('true')\n    })\n    wrapper.unmount()\n  })\n\n  it('should work with `dot-placement` prop', async () => {\n    const wrapper = mount(NCarousel)\n\n    for (const placement of ['top', 'bottom', 'left', 'right'] as const) {\n      await wrapper.setProps({ dotPlacement: placement })\n      expect(wrapper.find('.n-carousel').classes()).toContain(\n        `n-carousel--${placement}`\n      )\n    }\n    wrapper.unmount()\n  })\n\n  it('should work with `interval` prop', async () => {\n    const wrapper = mount(NCarousel, {\n      props: {\n        interval: 100,\n        autoplay: true\n      },\n      slots: {\n        default: () => {\n          return [...Array.from({ length: 3 }).keys()].map((i) => {\n            return h('div', {}, i.toString())\n          })\n        }\n      }\n    })\n\n    await sleep(100)\n    expect(\n      wrapper\n        .find('.n-carousel__slides')\n        .find('[data-index=\"2\"]')\n        .attributes('aria-hidden')\n    ).toBe('false')\n    expect(\n      wrapper\n        .find('.n-carousel__dots')\n        .findAll('.n-carousel__dot')[1]\n        .attributes('aria-selected')\n    ).toBe('true')\n    wrapper.unmount()\n  })\n\n  it('should work with `show-arrow` prop', async () => {\n    const wrapper = mount(NCarousel)\n\n    await wrapper.setProps({\n      showArrow: true\n    })\n\n    expect(wrapper.find('.n-carousel__arrow-group').exists()).toBe(true)\n    expect(wrapper.find('.n-carousel__arrow').exists()).toBe(true)\n    wrapper.unmount()\n  })\n\n  it('arrow button should work', async () => {\n    const wrapper = mount(NCarousel, {\n      props: {\n        loop: false\n      },\n      slots: {\n        default: () => {\n          return [\n            h('img', {\n              style: 'width: 100%; height: 240px; object-fit: cover;',\n              src: 'https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel4.jpeg'\n            }),\n            h('img', {\n              style: 'width: 100%; height: 240px; object-fit: cover;',\n              src: 'https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel4.jpeg'\n            })\n          ]\n        }\n      }\n    })\n\n    await wrapper.setProps({\n      showArrow: true\n    })\n\n    const slidesDOMArray = wrapper.findAll('.n-carousel__slide')\n\n    expect(slidesDOMArray[0].attributes('aria-hidden')).toBe('false')\n\n    await wrapper.findAll('.n-carousel__arrow')[1].trigger('click')\n    expect(slidesDOMArray[1].attributes('aria-hidden')).toBe('false')\n\n    await wrapper.findAll('.n-carousel__arrow')[0].trigger('click')\n    expect(slidesDOMArray[0].attributes('aria-hidden')).toBe('false')\n    wrapper.unmount()\n  })\n\n  it('should work with `centered-slides` prop', async () => {\n    const wrapper = mount(NCarousel, {\n      props: {\n        slidesPerView: 'auto',\n        loop: false\n      },\n      attrs: {\n        style: 'width: 240px;height: 300px;'\n      },\n      slots: {\n        default: () => {\n          return [...Array.from({ length: 5 }).keys()].map((i) => {\n            return h(NCarouselItem, {\n              style: `width: ${(i + 1) * 10}%;`,\n              slots: {\n                default: () => h('div', {}, i.toString())\n              }\n            })\n          })\n        }\n      }\n    })\n\n    const wrapperRect = wrapper.element.getBoundingClientRect()\n\n    const slidesDOMArray = wrapper.findAll('.n-carousel__slide')\n    for (let i = 0; i < slidesDOMArray.length; i++) {\n      const slideDOM = slidesDOMArray[i]\n      const rect = slideDOM.element.getBoundingClientRect()\n      expect(rect.left - wrapperRect.left).toBe(\n        (wrapperRect.width - rect.width) / 2\n      )\n\n      wrapper.vm.next()\n      await nextTick()\n    }\n    wrapper.unmount()\n  })\n\n  it('should work with `trigger` prop', async () => {\n    const wrapper = mount(NCarousel, {\n      props: {\n        loop: false\n      },\n      slots: {\n        default: () => {\n          return [...Array.from({ length: 3 }).keys()].map((i) => {\n            return h('div', {}, i.toString())\n          })\n        }\n      }\n    })\n\n    const dotsDOMArray = wrapper.findAll('.n-carousel__dot')\n    const slidesDOMArray = wrapper.findAll('.n-carousel__slide')\n\n    const triggerEvent = {\n      click: 'click',\n      hover: 'mouseenter'\n    }\n    const triggers = Object.keys(triggerEvent) as Array<\n      keyof typeof triggerEvent\n    >\n    for (let i = 0; i < triggers.length; i++) {\n      const trigger = triggers[i]\n      const event = triggerEvent[triggers[i]]\n      await wrapper.setProps({\n        trigger\n      })\n\n      for (let j = 0; j < dotsDOMArray.length; j++) {\n        const dotsDOM = dotsDOMArray[j]\n        await dotsDOM.trigger(event)\n        expect(slidesDOMArray[j].attributes('aria-hidden')).toBe('false')\n      }\n    }\n    wrapper.unmount()\n  })\n\n  it('should work with `current-index` prop', async () => {\n    vi.useFakeTimers()\n    const wrapper = mount(NCarousel, {\n      props: {\n        currentIndex: 0,\n        transitionStyle: { transitionDuration: '0ms' },\n        loop: false\n      },\n      slots: {\n        default: () => {\n          return [\n            h('img', {\n              style: 'width: 100%; height: 240px; object-fit: cover;',\n              src: 'https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel3.jpeg'\n            }),\n            h('img', {\n              style: 'width: 100%; height: 240px; object-fit: cover;',\n              src: 'https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel4.jpeg'\n            })\n          ]\n        }\n      }\n    })\n\n    await nextTick()\n    expect(\n      wrapper\n        .find('.n-carousel__slide--current')\n        .element.children[0].getAttribute('src')\n    ).toBe(\n      'https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel3.jpeg'\n    )\n\n    await wrapper.setProps({ currentIndex: 1 })\n\n    expect(wrapper.vm.getCurrentIndex()).toBe(1)\n    const actives = wrapper\n      .findAll('.n-carousel__slide')\n      .filter(s => s.attributes('aria-hidden') === 'false')\n    expect(actives.length).toBe(1)\n    const currentSlide = actives[0]\n    expect(currentSlide.attributes('data-index')).toBe('1')\n    expect(currentSlide.classes()).toContain('n-carousel__slide--current')\n    expect(currentSlide.element.children[0].getAttribute('src')).toBe(\n      'https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel4.jpeg'\n    )\n    wrapper.unmount()\n  })\n\n  it('should work with `dot-type` prop', async () => {\n    const wrapper = mount(NCarousel, {\n      props: {\n        currentIndex: 0\n      },\n      slots: {\n        default: () => {\n          return [\n            h('img', {\n              style: 'width: 100%; height: 240px; object-fit: cover;',\n              src: 'https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel3.jpeg'\n            }),\n            h('img', {\n              style: 'width: 100%; height: 240px; object-fit: cover;',\n              src: 'https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel4.jpeg'\n            })\n          ]\n        }\n      }\n    })\n\n    await sleep(100)\n    expect(wrapper.find('.n-carousel__dots').classes()).toContain(\n      'n-carousel__dots--dot'\n    )\n    await wrapper.setProps({ dotType: 'line' })\n    await sleep(100)\n    expect(wrapper.find('.n-carousel__dots').classes()).toContain(\n      'n-carousel__dots--line'\n    )\n    wrapper.unmount()\n  })\n\n  it('should work with `effect` prop', async () => {\n    const wrapper = mount(NCarousel)\n\n    for (const effect of ['slide', 'fade', 'card', 'custom'] as const) {\n      await wrapper.setProps({ effect })\n      await sleep(100)\n      expect(wrapper.find('.n-carousel').classes()).toContain(\n        `n-carousel--${effect}`\n      )\n    }\n\n    wrapper.unmount()\n  })\n\n  it('should work with `keyboard` prop', async () => {\n    const wrapper = mount(NCarousel, {\n      props: {\n        keyboard: true\n      },\n      slots: {\n        default: () => {\n          return [\n            h('img', {\n              style: 'width: 100%; height: 240px; object-fit: cover;',\n              src: 'https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel3.jpeg'\n            }),\n            h('img', {\n              style: 'width: 100%; height: 240px; object-fit: cover;',\n              src: 'https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel4.jpeg'\n            })\n          ]\n        }\n      }\n    })\n\n    await sleep(100)\n    await wrapper.find('.n-carousel__dot').trigger('click')\n    await wrapper.find('.n-carousel__dot').trigger('keydown', {\n      code: 'ArrowRight'\n    })\n    await sleep(100)\n    expect(\n      wrapper.findAll('.n-carousel__dot')[1].attributes('aria-selected')\n    ).toBe('true')\n    await wrapper.find('.n-carousel__dot').trigger('keydown', {\n      code: 'ArrowLeft'\n    })\n    await sleep(100)\n    expect(\n      wrapper.findAll('.n-carousel__dot')[0].attributes('aria-selected')\n    ).toBe('true')\n    wrapper.unmount()\n  })\n\n  it('should work with `space-between` prop', async () => {\n    const wrapper = mount(NCarousel, {\n      slots: {\n        default: () => {\n          return [\n            h('img', {\n              style: 'width: 100%; height: 240px; object-fit: cover;',\n              src: 'https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel3.jpeg'\n            }),\n            h('img', {\n              style: 'width: 100%; height: 240px; object-fit: cover;',\n              src: 'https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel4.jpeg'\n            })\n          ]\n        }\n      }\n    })\n\n    await sleep(100)\n    expect(\n      wrapper.find('.n-carousel__slide').attributes('style')\n    ).not.toContain('margin-right: 25px;')\n\n    await wrapper.setProps({ spaceBetween: 25 })\n    expect(wrapper.find('.n-carousel__slide').attributes('style')).toContain(\n      'margin-right: 25px;'\n    )\n    wrapper.unmount()\n  })\n\n  it('should work with `show-dots` prop', async () => {\n    const wrapper = mount(NCarousel, {\n      slots: {\n        default: () => {\n          return [\n            h('img', {\n              style: 'width: 100%; height: 240px; object-fit: cover;',\n              src: 'https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel3.jpeg'\n            }),\n            h('img', {\n              style: 'width: 100%; height: 240px; object-fit: cover;',\n              src: 'https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel4.jpeg'\n            })\n          ]\n        }\n      }\n    })\n    await sleep(100)\n    expect(wrapper.find('.n-carousel__dots').exists()).toBe(true)\n\n    await wrapper.setProps({\n      showDots: false\n    })\n    await sleep(100)\n    expect(wrapper.find('.n-carousel__dots').exists()).not.toBe(true)\n    wrapper.unmount()\n  })\n\n  it('should work with `on-update:current-index` prop', async () => {\n    const onUpdate = vi.fn()\n    const wrapper = mount(NCarousel, {\n      props: {\n        onUpdateCurrentIndex: onUpdate\n      },\n      slots: {\n        default: () => {\n          return [\n            h('img', {\n              style: 'width: 100%; height: 240px; object-fit: cover;',\n              src: 'https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel3.jpeg'\n            }),\n            h('img', {\n              style: 'width: 100%; height: 240px; object-fit: cover;',\n              src: 'https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel4.jpeg'\n            })\n          ]\n        }\n      }\n    })\n\n    await sleep(100)\n    await wrapper.findAll('.n-carousel__dot')[1].trigger('click')\n    expect(onUpdate).toHaveBeenCalled()\n    wrapper.unmount()\n  })\n})\n"
  },
  {
    "path": "src/carousel/tests/server.spec.tsx",
    "content": "import { setup } from '@css-render/vue3-ssr'\nimport { renderToString } from '@vue/server-renderer'\n/**\n * @vitest-environment node\n */\nimport { createSSRApp, h } from 'vue'\nimport { NCarousel } from '../..'\n\ndescribe('server side rendering', () => {\n  it('works', async () => {\n    const app = createSSRApp(() => <NCarousel />)\n    setup(app)\n    try {\n      await renderToString(app)\n    }\n    catch (e) {\n      expect(e).not.toBeTruthy()\n    }\n  })\n})\n"
  },
  {
    "path": "src/cascader/demos/enUS/action.demo.vue",
    "content": "<markdown>\n# Slots\n\nIs there anybody who needs slots on a cascader menu?\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { CascaderOption } from 'naive-ui'\nimport Flash16Regular from '@vicons/fluent/Flash16Regular'\nimport { ref } from 'vue'\n\nfunction getOptions(depth = 2, iterator = 1, prefix = '') {\n  const length = 12\n  const options: CascaderOption[] = []\n  for (let i = 1; i <= length; ++i) {\n    if (iterator === 1) {\n      options.push({\n        value: `${i}`,\n        label: `${i}`,\n        disabled: i % 5 === 0,\n        children: getOptions(depth, iterator + 1, `${String(i)}`)\n      })\n    }\n    else if (iterator === depth) {\n      options.push({\n        value: `${prefix}-${i}`,\n        label: `${prefix}-${i}`,\n        disabled: i % 5 === 0\n      })\n    }\n    else {\n      options.push({\n        value: `${prefix}-${i}`,\n        label: `${prefix}-${i}`,\n        disabled: i % 5 === 0,\n        children: getOptions(depth, iterator + 1, `${prefix}-${i}`)\n      })\n    }\n  }\n  return options\n}\n\nconst value = ref(null)\nconst options = getOptions()\n</script>\n\n<template>\n  <n-cascader\n    v-model:value=\"value\"\n    placeholder=\"Meaningless values\"\n    :options=\"options\"\n  >\n    <template #action>\n      Standing on a bridge that can divide the world\n    </template>\n    <template #arrow>\n      <Flash16Regular />\n    </template>\n  </n-cascader>\n</template>\n"
  },
  {
    "path": "src/cascader/demos/enUS/check-strategy.demo.vue",
    "content": "<markdown>\n# Setting check strategy\n\nSet the way to show checked options. `all` means showing all checked nodes. `parent` means showing all checked parent nodes when all child node are checked. `child` means showing all child nodes.\n</markdown>\n\n<script lang=\"ts\">\nimport type { CascaderOption } from 'naive-ui'\nimport { defineComponent, ref } from 'vue'\n\nfunction getOptions(depth = 4, iterator = 1, prefix = '') {\n  const length = 3\n  const options: CascaderOption[] = []\n  for (let i = 1; i <= length; ++i) {\n    if (iterator === 1) {\n      options.push({\n        value: `${i}`,\n        label: `${i}`,\n        disabled: i % 5 === 0,\n        children: getOptions(depth, iterator + 1, `${i}`)\n      })\n    }\n    else if (iterator === depth) {\n      options.push({\n        value: `${prefix}-${i}`,\n        label: `${prefix}-${i}`,\n        disabled: i % 5 === 0\n      })\n    }\n    else {\n      options.push({\n        value: `${prefix}-${i}`,\n        label: `${prefix}-${i}`,\n        disabled: i % 5 === 0,\n        children: getOptions(depth, iterator + 1, `${prefix}-${i}`)\n      })\n    }\n  }\n  return options\n}\n\nexport default defineComponent({\n  setup() {\n    return {\n      checkStrategy: ref<'all' | 'child' | 'parent'>('all'),\n      options: getOptions(),\n      handleUpdateValue: (values: string | string[]) => {\n        console.log(values)\n      }\n    }\n  }\n})\n</script>\n\n<template>\n  <n-space vertical>\n    <n-radio-group v-model:value=\"checkStrategy\">\n      <n-radio-button value=\"all\">\n        All\n      </n-radio-button>\n      <n-radio-button value=\"parent\">\n        Parent\n      </n-radio-button>\n      <n-radio-button value=\"child\">\n        Child\n      </n-radio-button>\n    </n-radio-group>\n\n    <n-cascader\n      multiple\n      cascade\n      :check-strategy=\"checkStrategy\"\n      :options=\"options\"\n      :default-value=\"['1-1-1-1', '1-1-2-1', '1-1-2-2', '1-1-2-3']\"\n      @update:value=\"handleUpdateValue\"\n    />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/cascader/demos/enUS/custom-field.demo.vue",
    "content": "<markdown>\n# Customizing Fields\n\nVarious data would come from backend.\n</markdown>\n\n<script lang=\"ts\" setup>\nconst options = [\n  {\n    whateverLabel: 'Rubber Soul',\n    whateverValue: 'Rubber Soul',\n    whateverChildren: [\n      {\n        whateverLabel:\n          'Everybody\\'s Got Something to Hide Except Me and My Monkey',\n        whateverValue:\n          'Everybody\\'s Got Something to Hide Except Me and My Monkey'\n      },\n      {\n        whateverLabel: 'Drive My Car',\n        whateverValue: 'Drive My Car',\n        disabled: true\n      },\n      {\n        whateverLabel: 'Norwegian Wood',\n        whateverValue: 'Norwegian Wood'\n      },\n      {\n        whateverLabel: 'You Won\\'t See',\n        whateverValue: 'You Won\\'t See',\n        disabled: true\n      },\n      {\n        whateverLabel: 'Nowhere Man',\n        whateverValue: 'Nowhere Man'\n      },\n      {\n        whateverLabel: 'Think For Yourself',\n        whateverValue: 'Think For Yourself'\n      },\n      {\n        whateverLabel: 'The Word',\n        whateverValue: 'The Word'\n      },\n      {\n        whateverLabel: 'Michelle',\n        whateverValue: 'Michelle',\n        disabled: true\n      },\n      {\n        whateverLabel: 'What goes on',\n        whateverValue: 'What goes on'\n      },\n      {\n        whateverLabel: 'Girl',\n        whateverValue: 'Girl'\n      },\n      {\n        whateverLabel: 'I\\'m looking through you',\n        whateverValue: 'I\\'m looking through you'\n      },\n      {\n        whateverLabel: 'In My Life',\n        whateverValue: 'In My Life'\n      },\n      {\n        whateverLabel: 'Wait',\n        whateverValue: 'Wait'\n      }\n    ]\n  },\n  {\n    whateverLabel: 'Let It Be',\n    whateverValue: 'Let It Be Album',\n    whateverChildren: [\n      {\n        whateverLabel: 'Two Of Us',\n        whateverValue: 'Two Of Us'\n      },\n      {\n        whateverLabel: 'Dig A Pony',\n        whateverValue: 'Dig A Pony'\n      },\n      {\n        whateverLabel: 'Across The Universe',\n        whateverValue: 'Across The Universe'\n      },\n      {\n        whateverLabel: 'I Me Mine',\n        whateverValue: 'I Me Mine'\n      },\n      {\n        whateverLabel: 'Dig It',\n        whateverValue: 'Dig It'\n      },\n      {\n        whateverLabel: 'Let It Be',\n        whateverValue: 'Let It Be'\n      },\n      {\n        whateverLabel: 'Maggie Mae',\n        whateverValue: 'Maggie Mae'\n      },\n      {\n        whateverLabel: 'I\\'ve Got A Feeling',\n        whateverValue: 'I\\'ve Got A Feeling'\n      },\n      {\n        whateverLabel: 'One After 909',\n        whateverValue: 'One After 909'\n      },\n      {\n        whateverLabel: 'The Long And Winding Road',\n        whateverValue: 'The Long And Winding Road'\n      },\n      {\n        whateverLabel: 'For You Blue',\n        whateverValue: 'For You Blue'\n      },\n      {\n        whateverLabel: 'Get Back',\n        whateverValue: 'Get Back'\n      }\n    ]\n  }\n]\n</script>\n\n<template>\n  <n-cascader\n    :options=\"options\"\n    default-value=\"Drive My Car\"\n    label-field=\"whateverLabel\"\n    value-field=\"whateverValue\"\n    children-field=\"whateverChildren\"\n  />\n</template>\n"
  },
  {
    "path": "src/cascader/demos/enUS/custom-render.demo.vue",
    "content": "<markdown>\n# Customized rendering\n\nThe `render-label` can be used to batch render cascader menu options.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { CascaderOption } from 'naive-ui'\nimport { ref } from 'vue'\n\nfunction getOptions(depth = 3, iterator = 1, prefix = '') {\n  const length = 12\n  const options: CascaderOption[] = []\n  for (let i = 1; i <= length; ++i) {\n    if (iterator === 1) {\n      options.push({\n        value: `v-${i}`,\n        label: `l-${i}`,\n        disabled: i % 5 === 0,\n        children: getOptions(depth, iterator + 1, `${String(i)}`)\n      })\n    }\n    else if (iterator === depth) {\n      options.push({\n        value: `v-${prefix}-${i}`,\n        label: `l-${prefix}-${i}`,\n        disabled: i % 5 === 0\n      })\n    }\n    else {\n      options.push({\n        value: `v-${prefix}-${i}`,\n        label: `l-${prefix}-${i}`,\n        disabled: i % 5 === 0,\n        children: getOptions(depth, iterator + 1, `${prefix}-${i}`)\n      })\n    }\n  }\n  return options\n}\n\nconst value = ref(null)\nconst options = getOptions()\n\nfunction handleUpdateValue(...args: unknown[]) {\n  console.log(...args)\n}\n\nfunction renderLabel(option: { value?: string | number, label?: string }) {\n  return `prefix ${option.label}`\n}\n</script>\n\n<template>\n  <n-cascader\n    v-model:value=\"value\"\n    placeholder=\"Meaningless values\"\n    :options=\"options\"\n    :filterable=\"true\"\n    :render-label=\"renderLabel\"\n    @update:value=\"handleUpdateValue\"\n  />\n</template>\n"
  },
  {
    "path": "src/cascader/demos/enUS/focus.demo.vue",
    "content": "<markdown>\n# Focus & blur manually\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { CascaderInst } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst cascaderInstRef = ref<CascaderInst | null>(null)\n\nfunction handleClick() {\n  cascaderInstRef.value?.focus()\n  setTimeout(() => {\n    cascaderInstRef.value?.blur()\n  }, 1000)\n}\n</script>\n\n<template>\n  <n-space item-style=\"display: flex; align-item: center;\">\n    <n-button @click=\"handleClick\">\n      Focus then blur in 1 second\n    </n-button>\n    <n-cascader ref=\"cascaderInstRef\" style=\"width: 200px\" />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/cascader/demos/enUS/index.demo-entry.md",
    "content": "# Cascader\n\nCascader can be used to display and select tree structured data.\n\n## Demos\n\n```demo\nsingle.vue\nmultiple.vue\nsize.vue\nsingle-lazy.vue\nmultiple-lazy.vue\naction.vue\nvirtual.vue\ncheck-strategy.vue\ncustom-field.vue\ncustom-render.vue\nfocus.vue\nstatus.vue\n```\n\n## API\n\n### Cascader Props\n\n| Name | Type | Default | Description | Version |\n| --- | --- | --- | --- | --- |\n| allow-checking-not-loaded | `boolean` | `false` | Whether to allow cascade checking on not loaded nodes. If you want to use this, you should know the `value` may be incomplete. Also, you should aware about the consistency bewteen naive's checking logic and your backend's checking logic, especially when there are disabled nodes. | 2.28.1 |\n| cascade | `boolean` | `true` | Whether to cascade the checkbox selection onto children. |  |\n| check-strategy | `string` | `'all'` | The way to show checked options. `all` means showing all checked node. `parent` means showing all checked parent node when all child node are checked (not working in single select mode). `child` means showing all child node. |  |\n| children-field | `string` | `'children'` | The children field in `CascaderOption`. |  |\n| clearable | `boolean` | `false` | Whether the cascader is clearable. |  |\n| clear-filter-after-select | `boolean` | `true` | When multiple and filter is true, whether to clear filter keyword after select an option. | 2.25.3 |\n| default-value | `string \\| number \\| Array<number \\| string> \\| null` | `null` | Data selected by default if no value is set. |  |\n| disabled | `boolean` | `false` | Whether to disable the cascader. |  |\n| disabled-field | `string` | `'disabled'` | The disabled field in `CascaderOption`. | 2.32.2 |\n| ellipsis-tag-popover-props | `PopoverProps` | `undefined` | `popover` props of the preview ellipsis tag. | 2.37.0 |\n| expand-trigger | `'click' \\| 'hover'` | `'click'` | If `remote` is set, `'hover'` won't work. |  |\n| filterable | `boolean` | `false` | Note: If `remote` is set, this won't have any effect. |  |\n| filter | `(pattern: string, option: CascaderOption, path: CascaderOption[]) => boolean` | A string based filter algorithm. | Filter function of the cascader. |  |\n| filter-menu-props | `HTMLAttributes` | `undefined` | The filter menu's dom props. | 2.27.0 |\n| get-column-style | `(detail: { level: number }) => string \\| object` | `undefined` | Function that resolves column style. `level` starts from `0`. | 2.38.2 |\n| value-field | `string` | `'value'` | The value field in `CascaderOption`. |  |\n| label-field | `string` | `'label'` | The label field in `CascaderOption`. |  |\n| max-tag-count | `number \\| 'responsive'` | `undefined` | Max tag count in multiple select mode. `responsive` will keep all the tags in single line. |  |\n| menu-props | `HTMLAttributes` | `undefined` | The menu's dom props. | 2.27.0 |\n| multiple | `boolean` | `false` | Whether to allow multiple options being selected. |  |\n| options | `CascaderOption[]` | `[]` | Options of the cascader. |  |\n| placeholder | `string` | `'Please Select'` | Placeholder text. |  |\n| placement | `'top-start' \\| 'top' \\| 'top-end' \\| 'right-start' \\| 'right' \\| 'right-end' \\| 'bottom-start' \\| 'bottom' \\| 'bottom-end' \\| 'left-start' \\| 'left' \\| 'left-end'` | `'bottom-start'` | Cascader placement. | 2.25.0 |\n| remote | `boolean` | `false` | Whether to obtain data remotely. |  |\n| render-prefix | `(info: { option: CascaderOption, node: VNode \\| null, checked: boolean }) => VNodeChild` | `undefined` | Render function of all the options' prefix. | 2.38.2 |\n| render-label | `(option: CascaderOption, checked: boolean) => VNodeChild` | `undefined` | Render function for cascader menu option label. | 2.24.0 |\n| render-suffix | `(info: { option: CascaderOption, node: VNode \\| null, checked: boolean }) => VNodeChild` | `undefined` | Render function of all the options' suffix. | 2.38.2 |\n| scrollbar-props | `ScrollbarProps` | `undefined` | See [Scrollbar props](scrollbar#Scrollbar-Props) | 2.44.0 |\n| separator | `string` | `' / '` | Selected option path value separator (used with `show-path`). |  |\n| show | `boolean` | `undefined` | Whether to show the menu. |  |\n| show-path | `boolean` | `true` | Whether to show the selected options as a path. |  |\n| size | `'small' \\| 'medium' \\| 'large'` | `'medium'` | Cascader size. |  |\n| spin-props | `{ strokeWidth?: number, stroke?: string, scale?: number, radius?: number }` | `undefined` | Loading icon properties. | 2.44.0 |\n| status | `'success' \\| 'warning' \\| 'error'` | `undefined` | Validation status. | 2.27.0 |\n| to | `string \\| HTMLElement \\| false` | `body` | Container node of the menu. `false` will keep it not detached. |  |\n| value | `string \\| number \\| Array<number \\| string> \\| null` | `undefined` | Value of the cascader (if being set manually). |  |\n| virtual-scroll | `boolean` | `true` | Whether to enable virtual scrolling. |  |\n| on-blur | `() => void` | `undefined` | Callback on blurred. |  |\n| on-focus | `() => void` | `undefined` | Callback on focused. |  |\n| on-load | `(option: CascaderOption) => Promise<void>` | `undefined` | Callback when a node is loaded. Set `option.children` in the returned promise. Loading will stop after the promise is resolved or rejected. |  |\n| on-update:show | `(value: boolean) => void` | `undefined` | Callback executed when menu is opened & closed. |  |\n| on-update:value | `(value: string \\| number \\| Array<string \\| number> \\| null, option: CascaderOption \\| Array<CascaderOption \\| null> \\| null, pathValues: Array<CascaderOption \\| null> \\| Array<CascaderOption[] \\| null> \\| null) => void` | `undefined` | Callback executed when the value changes. |  |\n\n#### CascaderOption Properties\n\n| Name | Type | Description | Version |\n| --- | --- | --- | --- |\n| label | `string` | Label of the option. |  |\n| value | `string \\| number` | Value of the option. |  |\n| disabled? | `boolean` | Whether this option is disabled. |  |\n| children? | `CascaderOption` | The children options of this option. |  |\n\n### Cascader Slots\n\n| Name | Parameters | Description | Version |\n| --- | --- | --- | --- |\n| action | `()` | Action content displayed in the cascading menu. |  |\n| arrow | `()` | Arrow content displayed in the cascading menu. | 2.32.2 |\n| empty | `()` | Empty state slot for the options cascading menu. | 2.22.0 |\n| not-found | `()` | Data not found slot when searching. | 2.34.0 |\n\n### Cascader Methods\n\n| Name | Type | Description | Version |\n| --- | --- | --- | --- |\n| blur | `() => void` | Blur. | 2.24.2 |\n| focus | `() => void` | Focus. | 2.24.2 |\n| getCheckedData | `() => { keys: Array<string \\| number>, options: Array<TreeOption \\| null> }` | Get checked data. | 2.34.0 |\n| getIndeterminateData | `() => { keys: Array<string \\| number>, options: Array<TreeOption \\| null> }` | Get indeterminate data. | 2.34.0 |\n"
  },
  {
    "path": "src/cascader/demos/enUS/multiple-lazy.demo.vue",
    "content": "<markdown>\n# Multiple (async)\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { CascaderOption } from 'naive-ui'\nimport { ref } from 'vue'\n\nfunction getChildren(option: CascaderOption) {\n  const children = []\n  for (let i = 0; i <= (option as { depth: number }).depth; ++i) {\n    children.push({\n      label: `${option.label}-${i}`,\n      value: `${option.label}-${i}`,\n      depth: (option as { depth: number }).depth + 1,\n      isLeaf: option.depth === 3\n    })\n  }\n  return children\n}\n\nconst checkStrategy = ref<'all' | 'parent' | 'child'>('all')\nconst allowCheckingNotLoaded = ref(false)\nconst cascade = ref(true)\nconst showPath = ref(true)\nconst value = ref(null)\nconst options = ref([\n  {\n    label: 'l-0',\n    value: 'v-0',\n    depth: 1,\n    isLeaf: false\n  }\n])\n\nfunction handleLoad(option: CascaderOption) {\n  return new Promise<void>((resolve) => {\n    window.setTimeout(() => {\n      option.children = getChildren(option)\n      resolve()\n    }, 1000)\n  })\n}\n</script>\n\n<template>\n  <n-space vertical>\n    <n-space align=\"center\">\n      <n-radio-group v-model:value=\"checkStrategy\">\n        <n-radio-button value=\"all\">\n          All\n        </n-radio-button>\n        <n-radio-button value=\"parent\">\n          Parent\n        </n-radio-button>\n        <n-radio-button value=\"child\">\n          Child\n        </n-radio-button>\n      </n-radio-group>\n      <n-space><n-switch v-model:value=\"cascade\" />Cascade</n-space>\n      <n-space><n-switch v-model:value=\"showPath\" />Show Path</n-space>\n      <n-space>\n        <n-switch v-model:value=\"allowCheckingNotLoaded\" />Allow Checking Not\n        Loaded\n      </n-space>\n    </n-space>\n    <n-cascader\n      v-model:value=\"value\"\n      multiple\n      placeholder=\"Meaningless values\"\n      :options=\"options\"\n      :cascade=\"cascade\"\n      :check-strategy=\"checkStrategy\"\n      :show-path=\"showPath\"\n      :allow-checking-not-loaded=\"allowCheckingNotLoaded\"\n      remote\n      :on-load=\"handleLoad\"\n    />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/cascader/demos/enUS/multiple.demo.vue",
    "content": "<markdown>\n# Multiple\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { CascaderOption } from 'naive-ui'\nimport { ref } from 'vue'\n\nfunction getOptions(depth = 3, iterator = 1, prefix = '') {\n  const length = 12\n  const options: CascaderOption[] = []\n  for (let i = 1; i <= length; ++i) {\n    if (iterator === 1) {\n      options.push({\n        value: `v-${i}`,\n        label: `l-${i}`,\n        disabled: i % 5 === 0,\n        children: getOptions(depth, iterator + 1, `${String(i)}`)\n      })\n    }\n    else if (iterator === depth) {\n      options.push({\n        value: `v-${prefix}-${i}`,\n        label: `l-${prefix}-${i}`,\n        disabled: i % 5 === 0\n      })\n    }\n    else {\n      options.push({\n        value: `v-${prefix}-${i}`,\n        label: `l-${prefix}-${i}`,\n        disabled: i % 5 === 0,\n        children: getOptions(depth, iterator + 1, `${prefix}-${i}`)\n      })\n    }\n  }\n  return options\n}\n\nconst checkStrategyIsChild = ref(true)\nconst cascade = ref(true)\nconst showPath = ref(true)\nconst hoverTrigger = ref(false)\nconst value = ref(null)\nconst filterable = ref(false)\nconst responsiveMaxTagCount = ref(true)\nconst clearFilterAfterSelect = ref(true)\nconst options = getOptions()\n\nfunction handleUpdateValue(value: string[], options: CascaderOption[]) {\n  console.log(value, options)\n}\n</script>\n\n<template>\n  <n-space vertical>\n    <n-space>\n      <n-space>\n        <n-switch v-model:value=\"checkStrategyIsChild\" />Child Check Strategy\n      </n-space>\n      <n-space><n-switch v-model:value=\"cascade\" />Cascade</n-space>\n      <n-space><n-switch v-model:value=\"showPath\" />Show Path</n-space>\n      <n-space><n-switch v-model:value=\"hoverTrigger\" />Hover Trigger</n-space>\n      <n-space><n-switch v-model:value=\"filterable\" />Filterable</n-space>\n      <n-space>\n        <n-switch v-model:value=\"responsiveMaxTagCount\" />Responsive MaxTagCount\n      </n-space>\n      <n-space>\n        <n-switch\n          v-model:value=\"clearFilterAfterSelect\"\n        />clearFilterAfterSelect\n      </n-space>\n    </n-space>\n    <n-cascader\n      v-model:value=\"value\"\n      multiple\n      placeholder=\"Meaningless values\"\n      clearable\n      :max-tag-count=\"responsiveMaxTagCount ? 'responsive' : undefined\"\n      :expand-trigger=\"hoverTrigger ? 'hover' : 'click'\"\n      :options=\"options\"\n      :cascade=\"cascade\"\n      :check-strategy=\"checkStrategyIsChild ? 'child' : 'all'\"\n      :show-path=\"showPath\"\n      :filterable=\"filterable\"\n      :clear-filter-after-select=\"clearFilterAfterSelect\"\n      @update:value=\"handleUpdateValue\"\n    />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/cascader/demos/enUS/single-lazy.demo.vue",
    "content": "<markdown>\n# Single (async)\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { CascaderOption } from 'naive-ui'\nimport { ref } from 'vue'\n\nfunction getChildren(option: CascaderOption) {\n  const children = []\n  for (let i = 0; i <= (option as { depth: number }).depth; ++i) {\n    children.push({\n      label: `${option.label}-${i}`,\n      value: `${option.label}-${i}`,\n      depth: (option as { depth: number }).depth + 1,\n      isLeaf: option.depth === 3\n    })\n  }\n  return children\n}\n\nconst checkStrategyIsChild = ref(true)\nconst showPath = ref(true)\nconst value = ref(null)\nconst options = ref([\n  {\n    label: 'l-0',\n    value: 'v-0',\n    depth: 1,\n    isLeaf: false\n  }\n])\n\nfunction handleLoad(option: CascaderOption) {\n  return new Promise<void>((resolve) => {\n    window.setTimeout(() => {\n      option.children = getChildren(option)\n      resolve()\n    }, 1000)\n  })\n}\n</script>\n\n<template>\n  <n-space vertical>\n    <n-space>\n      <n-space>\n        <n-switch v-model:value=\"checkStrategyIsChild\" />Child Check Strategy\n      </n-space>\n      <n-space><n-switch v-model:value=\"showPath\" />Show Path</n-space>\n    </n-space>\n    <n-cascader\n      v-model:value=\"value\"\n      placeholder=\"Meaningless values\"\n      :options=\"options\"\n      :check-strategy=\"checkStrategyIsChild ? 'child' : 'all'\"\n      :show-path=\"showPath\"\n      remote\n      :on-load=\"handleLoad\"\n    />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/cascader/demos/enUS/single.demo.vue",
    "content": "<markdown>\n# Single\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { CascaderOption } from 'naive-ui'\nimport { ref } from 'vue'\n\nfunction getOptions(depth = 3, iterator = 1, prefix = '') {\n  const length = 12\n  const options: CascaderOption[] = []\n  for (let i = 1; i <= length; ++i) {\n    if (iterator === 1) {\n      options.push({\n        value: `v-${i}`,\n        label: `l-${i}`,\n        disabled: i % 5 === 0,\n        children: getOptions(depth, iterator + 1, `${String(i)}`)\n      })\n    }\n    else if (iterator === depth) {\n      options.push({\n        value: `v-${prefix}-${i}`,\n        label: `l-${prefix}-${i}`,\n        disabled: i % 5 === 0\n      })\n    }\n    else {\n      options.push({\n        value: `v-${prefix}-${i}`,\n        label: `l-${prefix}-${i}`,\n        disabled: i % 5 === 0,\n        children: getOptions(depth, iterator + 1, `${prefix}-${i}`)\n      })\n    }\n  }\n  return options\n}\n\nconst checkStrategyIsChild = ref(true)\nconst showPath = ref(true)\nconst hoverTrigger = ref(false)\nconst filterable = ref(false)\nconst value = ref(null)\nconst options = getOptions()\n\nfunction handleUpdateValue(value: string, option: CascaderOption) {\n  console.log(value, option)\n}\n</script>\n\n<template>\n  <n-space vertical>\n    <n-space>\n      <n-space>\n        <n-switch v-model:value=\"checkStrategyIsChild\" />Child Check Strategy\n      </n-space>\n      <n-space><n-switch v-model:value=\"showPath\" />Show Path</n-space>\n      <n-space><n-switch v-model:value=\"hoverTrigger\" />Hover Trigger</n-space>\n      <n-space><n-switch v-model:value=\"filterable\" />Filterable</n-space>\n    </n-space>\n    <n-cascader\n      v-model:value=\"value\"\n      placeholder=\"Meaningless values\"\n      :expand-trigger=\"hoverTrigger ? 'hover' : 'click'\"\n      :options=\"options\"\n      :check-strategy=\"checkStrategyIsChild ? 'child' : 'all'\"\n      :show-path=\"showPath\"\n      :filterable=\"filterable\"\n      @update:value=\"handleUpdateValue\"\n    />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/cascader/demos/enUS/size.demo.vue",
    "content": "<markdown>\n# Size\n\nCascader has `small`, `medium` and `large` sizes.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { CascaderOption } from 'naive-ui'\nimport { ref } from 'vue'\n\nfunction getOptions(depth = 2, iterator = 1, prefix = '') {\n  const length = 12\n  const options: CascaderOption[] = []\n  for (let i = 1; i <= length; ++i) {\n    if (iterator === 1) {\n      options.push({\n        value: `${i}`,\n        label: `${i}`,\n        disabled: i % 5 === 0,\n        children: getOptions(depth, iterator + 1, `${String(i)}`)\n      })\n    }\n    else if (iterator === depth) {\n      options.push({\n        value: `${prefix}-${i}`,\n        label: `${prefix}-${i}`,\n        disabled: i % 5 === 0\n      })\n    }\n    else {\n      options.push({\n        value: `${prefix}-${i}`,\n        label: `${prefix}-${i}`,\n        disabled: i % 5 === 0,\n        children: getOptions(depth, iterator + 1, `${prefix}-${i}`)\n      })\n    }\n  }\n  return options\n}\n\nconst value = ref(null)\nconst options = getOptions()\n</script>\n\n<template>\n  <n-space vertical>\n    <n-cascader\n      v-model:value=\"value\"\n      placeholder=\"Meaningless values\"\n      :options=\"options\"\n      check-strategy=\"child\"\n      size=\"small\"\n    />\n    <n-cascader\n      v-model:value=\"value\"\n      placeholder=\"Meaningless values\"\n      :options=\"options\"\n      check-strategy=\"child\"\n      size=\"medium\"\n    />\n    <n-cascader\n      v-model:value=\"value\"\n      placeholder=\"Meaningless values\"\n      :options=\"options\"\n      check-strategy=\"child\"\n      size=\"large\"\n    />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/cascader/demos/enUS/status.demo.vue",
    "content": "<markdown>\n# Validation status\n\nValidation status can be applied outside form.\n</markdown>\n\n<template>\n  <n-space vertical>\n    <n-cascader status=\"warning\" placeholder=\"\" />\n    <n-cascader status=\"error\" placeholder=\"\" />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/cascader/demos/enUS/virtual.demo.vue",
    "content": "<markdown>\n# Large data\n\nIn this example there are 5000 \\* 2 \\* 2 = 20000 entries.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { CascaderOption } from 'naive-ui'\nimport { ref } from 'vue'\n\nfunction getOptions(depth = 3, iterator = 1, prefix = '') {\n  const length = iterator === 1 ? 5000 : 2\n  const options: CascaderOption[] = []\n  for (let i = 1; i <= length; ++i) {\n    if (iterator === 1) {\n      options.push({\n        value: `v-${i}`,\n        label: `l-${i}`,\n        disabled: i % 5 === 0,\n        children: getOptions(depth, iterator + 1, `${String(i)}`)\n      })\n    }\n    else if (iterator === depth) {\n      options.push({\n        value: `v-${prefix}-${i}`,\n        label: `l-${prefix}-${i}`,\n        disabled: i % 5 === 0\n      })\n    }\n    else {\n      options.push({\n        value: `v-${prefix}-${i}`,\n        label: `l-${prefix}-${i}`,\n        disabled: i % 5 === 0,\n        children: getOptions(depth, iterator + 1, `${prefix}-${i}`)\n      })\n    }\n  }\n  return options\n}\n\nconst checkStrategyIsChild = ref(true)\nconst cascade = ref(true)\nconst showPath = ref(true)\nconst hoverTrigger = ref(false)\nconst filterable = ref(false)\nconst value = ref(null)\nconst options = getOptions()\n</script>\n\n<template>\n  <n-space vertical>\n    <n-space>\n      <n-space>\n        <n-switch v-model:value=\"checkStrategyIsChild\" />Child Check Strategy\n      </n-space>\n      <n-space><n-switch v-model:value=\"cascade\" />Cascade</n-space>\n      <n-space><n-switch v-model:value=\"showPath\" />Show Path</n-space>\n      <n-space><n-switch v-model:value=\"hoverTrigger\" />Hover Trigger</n-space>\n      <n-space><n-switch v-model:value=\"filterable\" />Filterable</n-space>\n    </n-space>\n    <n-cascader\n      v-model:value=\"value\"\n      placeholder=\"Meaningless Value\"\n      :expand-trigger=\"hoverTrigger ? 'hover' : 'click'\"\n      :options=\"options\"\n      :cascade=\"cascade\"\n      :check-strategy=\"checkStrategyIsChild ? 'child' : 'all'\"\n      :show-path=\"showPath\"\n      :filterable=\"filterable\"\n    />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/cascader/demos/zhCN/action.demo.vue",
    "content": "<markdown>\n# 插槽\n\n有人要在级联菜单里用这些插槽吗？\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { CascaderOption } from 'naive-ui'\nimport Flash16Regular from '@vicons/fluent/Flash16Regular'\nimport { ref } from 'vue'\n\nfunction getOptions(depth = 2, iterator = 1, prefix = '') {\n  const length = 12\n  const options: CascaderOption[] = []\n  for (let i = 1; i <= length; ++i) {\n    if (iterator === 1) {\n      options.push({\n        value: `${i}`,\n        label: `${i}`,\n        disabled: i % 5 === 0,\n        children: getOptions(depth, iterator + 1, `${String(i)}`)\n      })\n    }\n    else if (iterator === depth) {\n      options.push({\n        value: `${prefix}-${i}`,\n        label: `${prefix}-${i}`,\n        disabled: i % 5 === 0\n      })\n    }\n    else {\n      options.push({\n        value: `${prefix}-${i}`,\n        label: `${prefix}-${i}`,\n        disabled: i % 5 === 0,\n        children: getOptions(depth, iterator + 1, `${prefix}-${i}`)\n      })\n    }\n  }\n  return options\n}\n\nconst value = ref(null)\nconst options = getOptions()\n</script>\n\n<template>\n  <n-cascader v-model:value=\"value\" placeholder=\"没啥用的值\" :options=\"options\">\n    <template #action>\n      站在能分割世界的桥\n    </template>\n    <template #arrow>\n      <Flash16Regular />\n    </template>\n  </n-cascader>\n</template>\n"
  },
  {
    "path": "src/cascader/demos/zhCN/check-strategy.demo.vue",
    "content": "<markdown>\n# 指定勾选策略\n\n设置勾选策略来指定显示的勾选节点，`all` 表示显示全部选中节点；`parent` 表示只显示父节点（当父节点下所有子节点都选中时）；`child` 表示只显示子节点。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { CascaderOption } from 'naive-ui'\nimport { ref } from 'vue'\n\nfunction getOptions(depth = 4, iterator = 1, prefix = '') {\n  const length = 3\n  const options: CascaderOption[] = []\n  for (let i = 1; i <= length; ++i) {\n    if (iterator === 1) {\n      options.push({\n        value: `${i}`,\n        label: `${i}`,\n        disabled: i % 5 === 0,\n        children: getOptions(depth, iterator + 1, `${i}`)\n      })\n    }\n    else if (iterator === depth) {\n      options.push({\n        value: `${prefix}-${i}`,\n        label: `${prefix}-${i}`,\n        disabled: i % 5 === 0\n      })\n    }\n    else {\n      options.push({\n        value: `${prefix}-${i}`,\n        label: `${prefix}-${i}`,\n        disabled: i % 5 === 0,\n        children: getOptions(depth, iterator + 1, `${prefix}-${i}`)\n      })\n    }\n  }\n  return options\n}\n\nconst checkStrategy = ref<'all' | 'child' | 'parent'>('all')\nconst options = getOptions()\n\nfunction handleUpdateValue(values: string | string[]) {\n  console.log(values)\n}\n</script>\n\n<template>\n  <n-space vertical>\n    <n-radio-group v-model:value=\"checkStrategy\">\n      <n-radio-button value=\"all\">\n        All\n      </n-radio-button>\n      <n-radio-button value=\"parent\">\n        Parent\n      </n-radio-button>\n      <n-radio-button value=\"child\">\n        Child\n      </n-radio-button>\n    </n-radio-group>\n    <n-cascader\n      multiple\n      cascade\n      :check-strategy=\"checkStrategy\"\n      :options=\"options\"\n      :default-value=\"['1-1-1-1', '1-1-2-1', '1-1-2-2', '1-1-2-3']\"\n      @update:value=\"handleUpdateValue\"\n    />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/cascader/demos/zhCN/custom-field.demo.vue",
    "content": "<markdown>\n# 自定义字段\n\n后端会传来各种各样的数据。\n</markdown>\n\n<script lang=\"ts\" setup>\nconst options = [\n  {\n    whateverLabel: 'Rubber Soul',\n    whateverValue: 'Rubber Soul',\n    whateverChildren: [\n      {\n        whateverLabel:\n          'Everybody\\'s Got Something to Hide Except Me and My Monkey',\n        whateverValue:\n          'Everybody\\'s Got Something to Hide Except Me and My Monkey'\n      },\n      {\n        whateverLabel: 'Drive My Car',\n        whateverValue: 'Drive My Car',\n        disabled: true\n      },\n      {\n        whateverLabel: 'Norwegian Wood',\n        whateverValue: 'Norwegian Wood'\n      },\n      {\n        whateverLabel: 'You Won\\'t See',\n        whateverValue: 'You Won\\'t See',\n        disabled: true\n      },\n      {\n        whateverLabel: 'Nowhere Man',\n        whateverValue: 'Nowhere Man'\n      },\n      {\n        whateverLabel: 'Think For Yourself',\n        whateverValue: 'Think For Yourself'\n      },\n      {\n        whateverLabel: 'The Word',\n        whateverValue: 'The Word'\n      },\n      {\n        whateverLabel: 'Michelle',\n        whateverValue: 'Michelle',\n        disabled: true\n      },\n      {\n        whateverLabel: 'What goes on',\n        whateverValue: 'What goes on'\n      },\n      {\n        whateverLabel: 'Girl',\n        whateverValue: 'Girl'\n      },\n      {\n        whateverLabel: 'I\\'m looking through you',\n        whateverValue: 'I\\'m looking through you'\n      },\n      {\n        whateverLabel: 'In My Life',\n        whateverValue: 'In My Life'\n      },\n      {\n        whateverLabel: 'Wait',\n        whateverValue: 'Wait'\n      }\n    ]\n  },\n  {\n    whateverLabel: 'Let It Be',\n    whateverValue: 'Let It Be Album',\n    whateverChildren: [\n      {\n        whateverLabel: 'Two Of Us',\n        whateverValue: 'Two Of Us'\n      },\n      {\n        whateverLabel: 'Dig A Pony',\n        whateverValue: 'Dig A Pony'\n      },\n      {\n        whateverLabel: 'Across The Universe',\n        whateverValue: 'Across The Universe'\n      },\n      {\n        whateverLabel: 'I Me Mine',\n        whateverValue: 'I Me Mine'\n      },\n      {\n        whateverLabel: 'Dig It',\n        whateverValue: 'Dig It'\n      },\n      {\n        whateverLabel: 'Let It Be',\n        whateverValue: 'Let It Be'\n      },\n      {\n        whateverLabel: 'Maggie Mae',\n        whateverValue: 'Maggie Mae'\n      },\n      {\n        whateverLabel: 'I\\'ve Got A Feeling',\n        whateverValue: 'I\\'ve Got A Feeling'\n      },\n      {\n        whateverLabel: 'One After 909',\n        whateverValue: 'One After 909'\n      },\n      {\n        whateverLabel: 'The Long And Winding Road',\n        whateverValue: 'The Long And Winding Road'\n      },\n      {\n        whateverLabel: 'For You Blue',\n        whateverValue: 'For You Blue'\n      },\n      {\n        whateverLabel: 'Get Back',\n        whateverValue: 'Get Back'\n      }\n    ]\n  }\n]\n</script>\n\n<template>\n  <n-cascader\n    :options=\"options\"\n    default-value=\"Drive My Car\"\n    label-field=\"whateverLabel\"\n    value-field=\"whateverValue\"\n    children-field=\"whateverChildren\"\n  />\n</template>\n"
  },
  {
    "path": "src/cascader/demos/zhCN/custom-render.demo.vue",
    "content": "<markdown>\n# 自定义渲染\n\n使用 `render-label` 可以批量控制 cascader 菜单的选项渲染。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { CascaderOption } from 'naive-ui'\nimport { ref } from 'vue'\n\nfunction getOptions(depth = 3, iterator = 1, prefix = '') {\n  const length = 12\n  const options: CascaderOption[] = []\n  for (let i = 1; i <= length; ++i) {\n    if (iterator === 1) {\n      options.push({\n        value: `v-${i}`,\n        label: `l-${i}`,\n        disabled: i % 5 === 0,\n        children: getOptions(depth, iterator + 1, `${String(i)}`)\n      })\n    }\n    else if (iterator === depth) {\n      options.push({\n        value: `v-${prefix}-${i}`,\n        label: `l-${prefix}-${i}`,\n        disabled: i % 5 === 0\n      })\n    }\n    else {\n      options.push({\n        value: `v-${prefix}-${i}`,\n        label: `l-${prefix}-${i}`,\n        disabled: i % 5 === 0,\n        children: getOptions(depth, iterator + 1, `${prefix}-${i}`)\n      })\n    }\n  }\n  return options\n}\n\nconst value = ref(null)\nconst options = getOptions()\n\nfunction handleUpdateValue(...args: unknown[]) {\n  console.log(...args)\n}\n\nfunction renderLabel(option: { value?: string | number, label?: string }) {\n  return `prefix ${option.label}`\n}\n</script>\n\n<template>\n  <n-cascader\n    v-model:value=\"value\"\n    placeholder=\"没啥用的值\"\n    :options=\"options\"\n    :filterable=\"true\"\n    :render-label=\"renderLabel\"\n    @update:value=\"handleUpdateValue\"\n  />\n</template>\n"
  },
  {
    "path": "src/cascader/demos/zhCN/default-value-debug.demo.vue",
    "content": "<markdown>\n# Default value debug\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { CascaderOption } from 'naive-ui'\nimport { ref } from 'vue'\n\nfunction getOptions(depth = 3, iterator = 1, prefix = '') {\n  const length = 12\n  const options: CascaderOption[] = []\n  for (let i = 1; i <= length; ++i) {\n    if (iterator === 1) {\n      options.push({\n        value: `v-${i}`,\n        label: `l-${i}`,\n        disabled: i % 5 === 0,\n        children: getOptions(depth, iterator + 1, `${String(i)}`)\n      })\n    }\n    else if (iterator === depth) {\n      options.push({\n        value: `v-${prefix}-${i}`,\n        label: `l-${prefix}-${i}`,\n        disabled: i % 5 === 0\n      })\n    }\n    else {\n      options.push({\n        value: `v-${prefix}-${i}`,\n        label: `l-${prefix}-${i}`,\n        disabled: i % 5 === 0,\n        children: getOptions(depth, iterator + 1, `${prefix}-${i}`)\n      })\n    }\n  }\n  return options\n}\n\nconst checkStrategyIsChild = ref(true)\nconst showPath = ref(true)\nconst hoverTrigger = ref(false)\nconst filterable = ref(false)\nconst singleValue = ref('v-1-1-11')\nconst multipleValue = ref<string[]>(['v-2-1-11', 'v-3-1-11'])\nconst options = getOptions()\n\nfunction handleUpdateValue(value: string, option: CascaderOption) {\n  console.log(value, option)\n}\n</script>\n\n<template>\n  <n-space vertical>\n    <n-space>\n      <n-space>\n        <n-switch v-model:value=\"checkStrategyIsChild\" />Child Check Strategy\n      </n-space>\n      <n-space><n-switch v-model:value=\"showPath\" />Show Path</n-space>\n      <n-space><n-switch v-model:value=\"hoverTrigger\" />Hover Trigger</n-space>\n      <n-space><n-switch v-model:value=\"filterable\" />Filterable</n-space>\n    </n-space>\n    <n-cascader\n      v-model:value=\"singleValue\"\n      placeholder=\"没啥用的值\"\n      :expand-trigger=\"hoverTrigger ? 'hover' : 'click'\"\n      :options=\"options\"\n      :check-strategy=\"checkStrategyIsChild ? 'child' : 'all'\"\n      :show-path=\"showPath\"\n      :filterable=\"filterable\"\n      @update:value=\"handleUpdateValue\"\n    />\n    <n-cascader\n      v-model:value=\"multipleValue\"\n      placeholder=\"没啥用的值\"\n      multiple\n      :expand-trigger=\"hoverTrigger ? 'hover' : 'click'\"\n      :options=\"options\"\n      :check-strategy=\"checkStrategyIsChild ? 'child' : 'all'\"\n      :show-path=\"showPath\"\n      :filterable=\"filterable\"\n      @update:value=\"handleUpdateValue\"\n    />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/cascader/demos/zhCN/focus.demo.vue",
    "content": "<markdown>\n# 手动 focus & blur\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { CascaderInst } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst cascaderInstRef = ref<CascaderInst | null>(null)\n\nfunction handleClick() {\n  cascaderInstRef.value?.focus()\n  setTimeout(() => {\n    cascaderInstRef.value?.blur()\n  }, 1000)\n}\n</script>\n\n<template>\n  <n-space item-style=\"display: flex; align-item: center;\">\n    <n-button @click=\"handleClick\">\n      聚焦，一秒后失效\n    </n-button>\n    <n-cascader ref=\"cascaderInstRef\" style=\"width: 200px\" />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/cascader/demos/zhCN/index.demo-entry.md",
    "content": "# 级联选择 Cascader\n\n用来选一些树型信息。\n\n## 演示\n\n```demo\nsingle.vue\nmultiple.vue\nsize.vue\nsingle-lazy.vue\nmultiple-lazy.vue\naction.vue\nvirtual.vue\ncheck-strategy.vue\ncustom-field.vue\ncustom-render.vue\nfocus.vue\nstatus.vue\ndefault-value-debug.vue\n```\n\n## API\n\n### Cascader Props\n\n| 名称 | 类型 | 默认值 | 说明 | 版本 |\n| --- | --- | --- | --- | --- |\n| allow-checking-not-loaded | `boolean` | `false` | 是否允许级联勾选还没有完全加载的节点。如果你要用这个属性，请记住 `value` 可能是不完整的，并且请注意勾选行为和后端计算逻辑的一致性，尤其是有禁用节点的情况下 | 2.28.1 |\n| bordered | `boolean` | `undefined` | 是否显示输入框边框 |  |\n| cascade | `boolean` | `true` | 在多选时是否关联选项 |  |\n| check-strategy | `string` | `'all'` | 设置勾选策略来指定显示的勾选节点，`all` 表示显示全部选中节点；`parent` 表示只显示父节点（当父节点下所有子节点都选中时，对于单选无效）；`child` 表示只显示子节点 |  |\n| children-field | `string` | `'children'` | 替代 `CascaderOption` 中的 children 字段名 |  |\n| clearable | `boolean` | `false` | 值是否可清除 |  |\n| clear-filter-after-select | `boolean` | `true` | 是否在可过滤和多选的情况下选中一个选项后保留当前的搜索关键词 | 2.25.3 |\n| default-value | `string \\| number \\| Array<number \\| string> \\| null` | `null` | 级联菜单默认选中的数据 |  |\n| disabled | `boolean` | `false` | 是否禁用 |  |\n| disabled-field | `string` | `'disabled'` | 替代 `CascaderOption` 中的 disabled 字段名 | 2.32.2 |\n| ellipsis-tag-popover-props | `PopoverProps` | `undefined` | 选中选项过多省略显示时，预览弹出 `popover` 的属性 | 2.37.0 |\n| expand-trigger | `'click' \\| 'hover'` | `'click'` | 在 `remote` 被设定时 `'hover'` 不生效 |  |\n| filterable | `boolean` | `false` | `remote` 被设定时不生效 |  |\n| filter | `(pattern: string, option: CascaderOption, path: CascaderOption[]) => boolean` | 一个基于字符串的过滤算法 | 过滤选项的函数 |  |\n| filter-menu-props | `HTMLAttributes` | `undefined` | 可过滤菜单的 DOM 属性 | 2.27.0 |\n| get-column-style | `(detail: { level: number }) => string \\| object` | `undefined` | 获取列样式的函数，`level` 从 `0` 开始 | 2.38.2 |\n| value-field | `string` | `'value'` | 替代 `CascaderOption` 中的 value 字段名 |  |\n| label-field | `string` | `'label'` | 替代 `CascaderOption` 中的 label 字段名 |  |\n| max-tag-count | `number \\| 'responsive'` | `undefined` | 多选标签的最大显示数量，`responsive` 会将所有标签保持在一行 |  |\n| menu-props | `HTMLAttributes` | `undefined` | 菜单的 DOM 属性 | 2.27.0 |\n| multiple | `boolean` | `false` | 是否支持多选 |  |\n| options | `CascaderOption[]` | `[]` | 填充的 options 数据 |  |\n| placeholder | `string` | `'请选择'` | 提示信息 |  |\n| placement | `'top-start' \\| 'top' \\| 'top-end' \\| 'right-start' \\| 'right' \\| 'right-end' \\| 'bottom-start' \\| 'bottom' \\| 'bottom-end' \\| 'left-start' \\| 'left' \\| 'left-end'` | `'bottom-start'` | 弹出位置 | 2.25.0 |\n| remote | `boolean` | `false` | 是否远程获取数据 |  |\n| render-prefix | `(info: { option: CascaderOption, node: VNode \\| null, checked: boolean }) => VNodeChild` | `undefined` | 节点前缀的渲染函数 | 2.38.2 |\n| render-label | `(option: CascaderOption, checked: boolean) => VNodeChild` | `undefined` | Cascader 菜单选项标签渲染函数 | 2.24.0 |\n| render-suffix | `(info: { option: CascaderOption, checked: boolean }) => VNodeChild` | `undefined` | 节点后缀的渲染函数 | 2.38.2 |\n| scrollbar-props | `ScrollbarProps` | `undefined` | See [Scrollbar props](scrollbar#Scrollbar-Props) | 2.44.0 |\n| separator | `string` | `' / '` | 数据分隔符 |  |\n| show | `boolean` | `undefined` | 是否打开菜单 |  |\n| show-path | `boolean` | `true` | 是否在选择器中显示选项路径 |  |\n| size | `'small' \\| 'medium' \\| 'large'` | `'medium'` | 尺寸 |  |\n| spin-props | `{ strokeWidth?: number, stroke?: string, scale?: number, radius?: number }` | `undefined` | 加载图标的属性 | 2.44.0 |\n| status | `'success' \\| 'warning' \\| 'error'` | `undefined` | 验证状态 | 2.27.0 |\n| to | `string \\| HTMLElement \\| false` | `body` | 菜单的容器节点，`false` 会待在原地 |  |\n| value | `string \\| number \\| Array<number \\| string> \\| null` | `undefined` | 级联选择的数据受控 |  |\n| virtual-scroll | `boolean` | `true` | 是否支持虚拟滚动 |  |\n| on-blur | `() => void` | `undefined` | 用户 blur 时执行的回调 |  |\n| on-focus | `() => void` | `undefined` | 用户 focus 时执行的回调 |  |\n| on-load | `(option: CascaderOption) => Promise<void>` | `undefined` | 在点击未加载完成节点时的回调，在返回的 promise 中设定 `option.children`，在返回的 promise resolve 或 reject 之后完成加载 |  |\n| on-update:show | `(value: boolean) => void` | `undefined` | 菜单打开关闭的回调 |  |\n| on-update:value | `(value: string \\| number \\| Array<string \\| number> \\| null, option: CascaderOption \\| Array<CascaderOption \\| null> \\| null, pathValues: Array<CascaderOption \\| null> \\| Array<CascaderOption[] \\| null> \\| null) => void` | `undefined` | 值改变时执行的回调 |  |\n\n#### CascaderOption Properties\n\n| 名称      | 类型               | 描述                     | 版本 |\n| --------- | ------------------ | ------------------------ | ---- |\n| label     | `string`           | label 标签，用于展示信息 |      |\n| value     | `string \\| number` | 对应 label 的 value 值   |      |\n| disabled? | `boolean`          | 该项是否禁用             |      |\n| children? | `CascaderOption`   | 该项的子项数据           |      |\n\n### Cascader Slots\n\n| 名称      | 参数 | 描述                             | 版本   |\n| --------- | ---- | -------------------------------- | ------ |\n| action    | `()` | 级联菜单中显示的 action 填充内容 |        |\n| arrow     | `()` | 箭头的 slot                      | 2.32.2 |\n| empty     | `()` | 级联菜单无数据时的 slot          | 2.22.0 |\n| not-found | `()` | 搜索不到数据时候的 slot          | 2.34.0 |\n\n### Cascader Methods\n\n| 名称 | 类型 | 说明 | 版本 |\n| --- | --- | --- | --- |\n| blur | `() => void` | 失焦 | 2.24.2 |\n| focus | `() => void` | 聚焦 | 2.24.2 |\n| getCheckedData | `() => { keys: Array<string \\| number>, options: Array<TreeOption \\| null> }` | 获取选中的数据 | 2.34.0 |\n| getIndeterminateData | `() => { keys: Array<string \\| number>, options: Array<TreeOption \\| null> }` | 获取半选的数据 | 2.34.0 |\n"
  },
  {
    "path": "src/cascader/demos/zhCN/multiple-lazy.demo.vue",
    "content": "<markdown>\n# 多项（异步）\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { CascaderOption } from 'naive-ui'\nimport { ref } from 'vue'\n\nfunction getChildren(option: CascaderOption) {\n  const children = []\n  for (let i = 0; i <= (option as { depth: number }).depth; ++i) {\n    children.push({\n      label: `${option.label}-${i}`,\n      value: `${option.label}-${i}`,\n      depth: (option as { depth: number }).depth + 1,\n      isLeaf: option.depth === 3\n    })\n  }\n  return children\n}\n\nconst checkStrategy = ref<'all' | 'parent' | 'child'>('all')\nconst allowCheckingNotLoaded = ref(false)\nconst cascade = ref(true)\nconst showPath = ref(true)\nconst value = ref(null)\nconst options = ref([\n  {\n    label: 'l-0',\n    value: 'v-0',\n    depth: 1,\n    isLeaf: false\n  }\n])\n\nfunction handleLoad(option: CascaderOption) {\n  return new Promise<void>((resolve) => {\n    window.setTimeout(() => {\n      option.children = getChildren(option)\n      resolve()\n    }, 1000)\n  })\n}\n</script>\n\n<template>\n  <n-space vertical>\n    <n-space align=\"center\">\n      <n-radio-group v-model:value=\"checkStrategy\">\n        <n-radio-button value=\"all\">\n          All\n        </n-radio-button>\n        <n-radio-button value=\"parent\">\n          Parent\n        </n-radio-button>\n        <n-radio-button value=\"child\">\n          Child\n        </n-radio-button>\n      </n-radio-group>\n      <n-space><n-switch v-model:value=\"cascade\" />Cascade</n-space>\n      <n-space><n-switch v-model:value=\"showPath\" />Show Path</n-space>\n      <n-space>\n        <n-switch v-model:value=\"allowCheckingNotLoaded\" />Allow Checking Not\n        Loaded\n      </n-space>\n    </n-space>\n    <n-cascader\n      v-model:value=\"value\"\n      multiple\n      placeholder=\"没啥用的值\"\n      :options=\"options\"\n      :cascade=\"cascade\"\n      :check-strategy=\"checkStrategy\"\n      :show-path=\"showPath\"\n      :allow-checking-not-loaded=\"allowCheckingNotLoaded\"\n      remote\n      :on-load=\"handleLoad\"\n    />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/cascader/demos/zhCN/multiple.demo.vue",
    "content": "<markdown>\n# 多项\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { CascaderOption } from 'naive-ui'\nimport { ref } from 'vue'\n\nfunction getOptions(depth = 3, iterator = 1, prefix = '') {\n  const length = 12\n  const options: CascaderOption[] = []\n  for (let i = 1; i <= length; ++i) {\n    if (iterator === 1) {\n      options.push({\n        value: `v-${i}`,\n        label: `l-${i}`,\n        disabled: i % 5 === 0,\n        children: getOptions(depth, iterator + 1, `${String(i)}`)\n      })\n    }\n    else if (iterator === depth) {\n      options.push({\n        value: `v-${prefix}-${i}`,\n        label: `l-${prefix}-${i}`,\n        disabled: i % 5 === 0\n      })\n    }\n    else {\n      options.push({\n        value: `v-${prefix}-${i}`,\n        label: `l-${prefix}-${i}`,\n        disabled: i % 5 === 0,\n        children: getOptions(depth, iterator + 1, `${prefix}-${i}`)\n      })\n    }\n  }\n  return options\n}\n\nconst checkStrategyIsChild = ref(true)\nconst cascade = ref(true)\nconst showPath = ref(true)\nconst hoverTrigger = ref(false)\nconst value = ref(null)\nconst filterable = ref(false)\nconst responsiveMaxTagCount = ref(true)\nconst clearFilterAfterSelect = ref(true)\nconst options = getOptions()\n\nfunction handleUpdateValue(value: string[], options: CascaderOption[]) {\n  console.log(value, options)\n}\n</script>\n\n<template>\n  <n-space vertical>\n    <n-space>\n      <n-space>\n        <n-switch v-model:value=\"checkStrategyIsChild\" />Child Check Strategy\n      </n-space>\n      <n-space><n-switch v-model:value=\"cascade\" />Cascade</n-space>\n      <n-space><n-switch v-model:value=\"showPath\" />Show Path</n-space>\n      <n-space><n-switch v-model:value=\"hoverTrigger\" />Hover Trigger</n-space>\n      <n-space><n-switch v-model:value=\"filterable\" />Filterable</n-space>\n      <n-space>\n        <n-switch v-model:value=\"responsiveMaxTagCount\" />Responsive MaxTagCount\n      </n-space>\n      <n-space>\n        <n-switch\n          v-model:value=\"clearFilterAfterSelect\"\n        />clearFilterAfterSelect\n      </n-space>\n    </n-space>\n    <n-cascader\n      v-model:value=\"value\"\n      multiple\n      clearable\n      placeholder=\"没啥用的值\"\n      :max-tag-count=\"responsiveMaxTagCount ? 'responsive' : undefined\"\n      :expand-trigger=\"hoverTrigger ? 'hover' : 'click'\"\n      :options=\"options\"\n      :cascade=\"cascade\"\n      :check-strategy=\"checkStrategyIsChild ? 'child' : 'all'\"\n      :show-path=\"showPath\"\n      :filterable=\"filterable\"\n      :clear-filter-after-select=\"clearFilterAfterSelect\"\n      @update:value=\"handleUpdateValue\"\n    />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/cascader/demos/zhCN/single-lazy.demo.vue",
    "content": "<markdown>\n# 单项（异步）\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { CascaderOption } from 'naive-ui'\nimport { ref } from 'vue'\n\nfunction getChildren(option: CascaderOption) {\n  const children = []\n  for (let i = 0; i <= (option as { depth: number }).depth; ++i) {\n    children.push({\n      label: `${option.label}-${i}`,\n      value: `${option.label}-${i}`,\n      depth: (option as { depth: number }).depth + 1,\n      isLeaf: option.depth === 3\n    })\n  }\n  return children\n}\n\nconst checkStrategyIsChild = ref(true)\nconst showPath = ref(true)\nconst value = ref(null)\nconst options = ref([\n  {\n    label: 'l-0',\n    value: 'v-0',\n    depth: 1,\n    isLeaf: false\n  }\n])\n\nfunction handleLoad(option: CascaderOption) {\n  return new Promise<void>((resolve) => {\n    window.setTimeout(() => {\n      option.children = getChildren(option)\n      resolve()\n    }, 1000)\n  })\n}\n</script>\n\n<template>\n  <n-space vertical>\n    <n-space>\n      <n-space>\n        <n-switch v-model:value=\"checkStrategyIsChild\" />Child Check Strategy\n      </n-space>\n      <n-space><n-switch v-model:value=\"showPath\" />Show Path</n-space>\n    </n-space>\n    <n-cascader\n      v-model:value=\"value\"\n      placeholder=\"没啥用的值\"\n      :options=\"options\"\n      :check-strategy=\"checkStrategyIsChild ? 'child' : 'all'\"\n      :show-path=\"showPath\"\n      remote\n      :on-load=\"handleLoad\"\n    />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/cascader/demos/zhCN/single.demo.vue",
    "content": "<markdown>\n# 单选\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { CascaderOption } from 'naive-ui'\nimport { ref } from 'vue'\n\nfunction getOptions(depth = 3, iterator = 1, prefix = '') {\n  const length = 12\n  const options: CascaderOption[] = []\n  for (let i = 1; i <= length; ++i) {\n    if (iterator === 1) {\n      options.push({\n        value: `v-${i}`,\n        label: `l-${i}`,\n        disabled: i % 5 === 0,\n        children: getOptions(depth, iterator + 1, `${String(i)}`)\n      })\n    }\n    else if (iterator === depth) {\n      options.push({\n        value: `v-${prefix}-${i}`,\n        label: `l-${prefix}-${i}`,\n        disabled: i % 5 === 0\n      })\n    }\n    else {\n      options.push({\n        value: `v-${prefix}-${i}`,\n        label: `l-${prefix}-${i}`,\n        disabled: i % 5 === 0,\n        children: getOptions(depth, iterator + 1, `${prefix}-${i}`)\n      })\n    }\n  }\n  return options\n}\n\nconst checkStrategyIsChild = ref(true)\nconst showPath = ref(true)\nconst hoverTrigger = ref(false)\nconst filterable = ref(false)\nconst value = ref(null)\nconst options = getOptions()\n\nfunction handleUpdateValue(value: string, option: CascaderOption) {\n  console.log(value, option)\n}\n</script>\n\n<template>\n  <n-space vertical>\n    <n-space>\n      <n-space>\n        <n-switch v-model:value=\"checkStrategyIsChild\" />Child Check Strategy\n      </n-space>\n      <n-space><n-switch v-model:value=\"showPath\" />Show Path</n-space>\n      <n-space><n-switch v-model:value=\"hoverTrigger\" />Hover Trigger</n-space>\n      <n-space><n-switch v-model:value=\"filterable\" />Filterable</n-space>\n    </n-space>\n    <n-cascader\n      v-model:value=\"value\"\n      placeholder=\"没啥用的值\"\n      :expand-trigger=\"hoverTrigger ? 'hover' : 'click'\"\n      :options=\"options\"\n      :check-strategy=\"checkStrategyIsChild ? 'child' : 'all'\"\n      :show-path=\"showPath\"\n      :filterable=\"filterable\"\n      @update:value=\"handleUpdateValue\"\n    />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/cascader/demos/zhCN/size.demo.vue",
    "content": "<markdown>\n# 尺寸\n\n级联选择有 `small`、`medium` 和 `large` 尺寸。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { CascaderOption } from 'naive-ui'\nimport { ref } from 'vue'\n\nfunction getOptions(depth = 2, iterator = 1, prefix = '') {\n  const length = 12\n  const options: CascaderOption[] = []\n  for (let i = 1; i <= length; ++i) {\n    if (iterator === 1) {\n      options.push({\n        value: `${i}`,\n        label: `${i}`,\n        disabled: i % 5 === 0,\n        children: getOptions(depth, iterator + 1, `${String(i)}`)\n      })\n    }\n    else if (iterator === depth) {\n      options.push({\n        value: `${prefix}-${i}`,\n        label: `${prefix}-${i}`,\n        disabled: i % 5 === 0\n      })\n    }\n    else {\n      options.push({\n        value: `${prefix}-${i}`,\n        label: `${prefix}-${i}`,\n        disabled: i % 5 === 0,\n        children: getOptions(depth, iterator + 1, `${prefix}-${i}`)\n      })\n    }\n  }\n  return options\n}\n\nconst value = ref(null)\nconst options = getOptions()\n</script>\n\n<template>\n  <n-space vertical>\n    <n-cascader\n      v-model:value=\"value\"\n      placeholder=\"没啥用的值\"\n      :options=\"options\"\n      check-strategy=\"child\"\n      size=\"small\"\n    />\n    <n-cascader\n      v-model:value=\"value\"\n      placeholder=\"没啥用的值\"\n      :options=\"options\"\n      check-strategy=\"child\"\n      size=\"medium\"\n    />\n    <n-cascader\n      v-model:value=\"value\"\n      placeholder=\"没啥用的值\"\n      :options=\"options\"\n      check-strategy=\"child\"\n      size=\"large\"\n    />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/cascader/demos/zhCN/status.demo.vue",
    "content": "<markdown>\n# 验证状态\n\n输入的验证状态可以脱离表单使用。\n</markdown>\n\n<template>\n  <n-space vertical>\n    <n-cascader status=\"warning\" placeholder=\"\" />\n    <n-cascader status=\"error\" placeholder=\"\" />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/cascader/demos/zhCN/virtual.demo.vue",
    "content": "<markdown>\n# 大量数据\n\n下面这个例子有 5000 \\* 2 \\* 2 = 20000 条数据。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { CascaderOption } from 'naive-ui'\nimport { ref } from 'vue'\n\nfunction getOptions(depth = 3, iterator = 1, prefix = '') {\n  const length = iterator === 1 ? 5000 : 2\n  const options: CascaderOption[] = []\n  for (let i = 1; i <= length; ++i) {\n    if (iterator === 1) {\n      options.push({\n        value: `v-${i}`,\n        label: `l-${i}`,\n        disabled: i % 5 === 0,\n        children: getOptions(depth, iterator + 1, `${String(i)}`)\n      })\n    }\n    else if (iterator === depth) {\n      options.push({\n        value: `v-${prefix}-${i}`,\n        label: `l-${prefix}-${i}`,\n        disabled: i % 5 === 0\n      })\n    }\n    else {\n      options.push({\n        value: `v-${prefix}-${i}`,\n        label: `l-${prefix}-${i}`,\n        disabled: i % 5 === 0,\n        children: getOptions(depth, iterator + 1, `${prefix}-${i}`)\n      })\n    }\n  }\n  return options\n}\n\nconst checkStrategyIsChild = ref(true)\nconst cascade = ref(true)\nconst showPath = ref(true)\nconst hoverTrigger = ref(false)\nconst filterable = ref(false)\nconst value = ref(null)\nconst options = getOptions()\n</script>\n\n<template>\n  <n-space vertical>\n    <n-space>\n      <n-space>\n        <n-switch v-model:value=\"checkStrategyIsChild\" />Child Check Strategy\n      </n-space>\n      <n-space><n-switch v-model:value=\"cascade\" />Cascade</n-space>\n      <n-space><n-switch v-model:value=\"showPath\" />Show Path</n-space>\n      <n-space><n-switch v-model:value=\"hoverTrigger\" />Hover Trigger</n-space>\n      <n-space><n-switch v-model:value=\"filterable\" />Filterable</n-space>\n    </n-space>\n    <n-cascader\n      v-model:value=\"value\"\n      placeholder=\"没啥用的值\"\n      :expand-trigger=\"hoverTrigger ? 'hover' : 'click'\"\n      :options=\"options\"\n      :cascade=\"cascade\"\n      :check-strategy=\"checkStrategyIsChild ? 'child' : 'all'\"\n      :show-path=\"showPath\"\n      :filterable=\"filterable\"\n    />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/cascader/index.ts",
    "content": "export { cascaderProps, default as NCascader } from './src/Cascader'\nexport type { CascaderProps, CascaderSlots } from './src/Cascader'\nexport type { CascaderInst, CascaderOption } from './src/interface'\nexport type * from './src/public-types'\n"
  },
  {
    "path": "src/cascader/src/Cascader.tsx",
    "content": "import type { CheckStrategy } from 'treemate'\nimport type {\n  CSSProperties,\n  HTMLAttributes,\n  PropType,\n  SlotsType,\n  VNode,\n  VNodeChild\n} from 'vue'\nimport type { FollowerInst, FollowerPlacement } from 'vueuc'\nimport type { InternalSelectionInst, ScrollbarProps } from '../../_internal'\nimport type { ThemeProps } from '../../_mixins'\nimport type { ExtractPublicPropTypes, MaybeArray } from '../../_utils'\nimport type { FormValidationStatus } from '../../form/src/public-types'\nimport type { PopoverProps } from '../../popover'\nimport type { SelectBaseOption } from '../../select/src/interface'\nimport type { CascaderTheme } from '../styles'\nimport type {\n  CascaderInst,\n  CascaderMenuInstance,\n  CascaderOption,\n  ExpandTrigger,\n  Filter,\n  Key,\n  OnLoad,\n  OnUpdateValue,\n  OnUpdateValueImpl,\n  SelectMenuInstance,\n  Value\n} from './interface'\nimport type { CascaderSize, CascaderSpinProps } from './public-types'\nimport { changeColor, depx, getPreciseEventTarget, happensIn } from 'seemly'\nimport { createTreeMate, SubtreeNotLoadedError } from 'treemate'\nimport { useIsMounted, useMergedState } from 'vooks'\nimport {\n  computed,\n  defineComponent,\n  h,\n  isReactive,\n  nextTick,\n  provide,\n  ref,\n  toRef,\n  watch,\n  watchEffect\n} from 'vue'\nimport { VBinder, VFollower, VTarget } from 'vueuc'\nimport { NInternalSelection } from '../../_internal'\nimport {\n  useConfig,\n  useFormItem,\n  useLocale,\n  useTheme,\n  useThemeClass\n} from '../../_mixins'\nimport {\n  call,\n  markEventEffectPerformed,\n  useAdjustedTo,\n  warnOnce\n} from '../../_utils'\nimport { cascaderLight } from '../styles'\nimport CascaderMenu from './CascaderMenu'\nimport CascaderSelectMenu from './CascaderSelectMenu'\nimport { cascaderInjectionKey } from './interface'\nimport style from './styles/index.cssr'\nimport { getPathLabel, getRawNodePath } from './utils'\n\nexport const cascaderProps = {\n  ...(useTheme.props as ThemeProps<CascaderTheme>),\n  allowCheckingNotLoaded: Boolean,\n  to: useAdjustedTo.propTo,\n  bordered: {\n    type: Boolean as PropType<boolean | undefined>,\n    default: undefined\n  },\n  options: {\n    type: Array as PropType<CascaderOption[]>,\n    default: () => []\n  },\n  value: [String, Number, Array] as PropType<Value | null>,\n  defaultValue: {\n    type: [String, Number, Array] as PropType<Value | null>,\n    default: null\n  },\n  placeholder: String,\n  multiple: Boolean,\n  size: String as PropType<CascaderSize>,\n  filterable: Boolean,\n  disabled: {\n    type: Boolean as PropType<boolean | undefined>,\n    default: undefined\n  },\n  disabledField: {\n    type: String,\n    default: 'disabled'\n  },\n  expandTrigger: {\n    type: String as PropType<ExpandTrigger>,\n    default: 'click'\n  },\n  clearable: Boolean,\n  clearFilterAfterSelect: {\n    type: Boolean,\n    default: true\n  },\n  remote: Boolean,\n  onLoad: Function as PropType<OnLoad>,\n  separator: {\n    type: String,\n    default: ' / '\n  },\n  filter: Function as PropType<Filter>,\n  placement: {\n    type: String as PropType<FollowerPlacement>,\n    default: 'bottom-start'\n  },\n  cascade: {\n    type: Boolean,\n    default: true\n  },\n  leafOnly: Boolean,\n  showPath: {\n    type: Boolean,\n    default: true\n  },\n  show: {\n    type: Boolean as PropType<boolean | undefined>,\n    default: undefined\n  },\n  maxTagCount: [String, Number] as PropType<number | 'responsive'>,\n  ellipsisTagPopoverProps: Object as PropType<PopoverProps>,\n  menuProps: Object as PropType<HTMLAttributes>,\n  filterMenuProps: Object as PropType<HTMLAttributes>,\n  virtualScroll: {\n    type: Boolean,\n    default: true\n  },\n  checkStrategy: {\n    type: String as PropType<CheckStrategy>,\n    default: 'all'\n  },\n  valueField: {\n    type: String,\n    default: 'value'\n  },\n  labelField: {\n    type: String,\n    default: 'label'\n  },\n  childrenField: {\n    type: String,\n    default: 'children'\n  },\n  renderLabel: Function as PropType<\n    (option: CascaderOption, checked: boolean) => VNodeChild\n  >,\n  status: String as PropType<FormValidationStatus>,\n  'onUpdate:value': [Function, Array] as PropType<MaybeArray<OnUpdateValue>>,\n  onUpdateValue: [Function, Array] as PropType<MaybeArray<OnUpdateValue>>,\n  'onUpdate:show': [Function, Array] as PropType<\n    MaybeArray<(show: boolean) => void>\n  >,\n  onUpdateShow: [Function, Array] as PropType<\n    MaybeArray<(show: boolean) => void>\n  >,\n  onBlur: Function as PropType<(e: FocusEvent) => void>,\n  onFocus: Function as PropType<(e: FocusEvent) => void>,\n  getColumnStyle: Function as PropType<\n    (detail: { level: number }) => string | CSSProperties\n  >,\n  spinProps: Object as PropType<CascaderSpinProps>,\n  renderPrefix: Function as PropType<\n    (props: {\n      option: CascaderOption\n      checked: boolean\n      node: VNode | null\n    }) => VNodeChild\n  >,\n  renderSuffix: Function as PropType<\n    (props: {\n      option: CascaderOption\n      checked: boolean\n      node: VNode | null\n    }) => VNodeChild\n  >,\n  scrollbarProps: Object as PropType<ScrollbarProps>,\n  // deprecated\n  onChange: [Function, Array] as PropType<MaybeArray<OnUpdateValue> | undefined>\n} as const\n\nexport type CascaderProps = ExtractPublicPropTypes<typeof cascaderProps>\n\nexport interface CascaderSlots {\n  action?: () => VNode[]\n  arrow?: () => VNode[]\n  empty?: () => VNode[]\n  'not-found'?: () => VNode[]\n}\n\nexport default defineComponent({\n  name: 'Cascader',\n  props: cascaderProps,\n  slots: Object as SlotsType<CascaderSlots>,\n  setup(props, { slots }) {\n    if (__DEV__) {\n      watchEffect(() => {\n        if (props.leafOnly) {\n          warnOnce(\n            'cascader',\n            '`leaf-only` is deprecated, please use `check-strategy=\"child\"` instead'\n          )\n        }\n        if (props.onChange !== undefined) {\n          warnOnce(\n            'cascader',\n            '`on-change` is deprecated, please use `on-update:value` instead.'\n          )\n        }\n      })\n    }\n    const {\n      mergedBorderedRef,\n      mergedClsPrefixRef,\n      namespaceRef,\n      inlineThemeDisabled,\n      mergedComponentPropsRef\n    } = useConfig(props)\n    const themeRef = useTheme(\n      'Cascader',\n      '-cascader',\n      style,\n      cascaderLight,\n      props,\n      mergedClsPrefixRef\n    )\n    const { localeRef } = useLocale('Cascader')\n    const uncontrolledValueRef = ref(props.defaultValue)\n    const controlledValueRef = computed(() => props.value)\n    const mergedValueRef = useMergedState(\n      controlledValueRef,\n      uncontrolledValueRef\n    )\n    const mergedCheckStrategyRef = computed(() => {\n      return props.leafOnly ? 'child' : props.checkStrategy\n    })\n    const patternRef = ref('')\n    const formItem = useFormItem(props, {\n      mergedSize: (NFormItem) => {\n        const { size } = props\n        if (size)\n          return size\n        const { mergedSize: formItemSize } = NFormItem || {}\n        if (formItemSize?.value)\n          return formItemSize.value as CascaderSize\n        const configSize = mergedComponentPropsRef?.value?.Cascader?.size\n        if (configSize)\n          return configSize\n        return 'medium'\n      }\n    })\n    const { mergedSizeRef, mergedDisabledRef, mergedStatusRef } = formItem\n    const cascaderMenuInstRef = ref<CascaderMenuInstance | null>(null)\n    const selectMenuInstRef = ref<SelectMenuInstance | null>(null)\n    const triggerInstRef = ref<InternalSelectionInst | null>(null)\n    const keyboardKeyRef = ref<Key | null>(null)\n    const hoverKeyRef = ref<Key | null>(null)\n    const loadingKeySetRef = ref<Set<Key>>(new Set())\n    const selectMenuFollowerRef = ref<FollowerInst | null>(null)\n    const cascaderMenuFollowerRef = ref<FollowerInst | null>(null)\n    const adjustedToRef = useAdjustedTo(props)\n    const focusedRef = ref(false)\n    const addLoadingKey = (key: Key): void => {\n      loadingKeySetRef.value.add(key)\n    }\n    const deleteLoadingKey = (key: Key): void => {\n      loadingKeySetRef.value.delete(key)\n    }\n    const treeMateRef = computed(() => {\n      const { valueField, childrenField, disabledField } = props\n      return createTreeMate(props.options, {\n        getDisabled(node) {\n          return (node as any)[disabledField]\n        },\n        getKey(node) {\n          return (node as any)[valueField]\n        },\n        getChildren(node) {\n          return (node as any)[childrenField]\n        }\n      })\n    })\n    const mergedKeysRef = computed(() => {\n      const { cascade, multiple } = props\n      if (multiple && Array.isArray(mergedValueRef.value)) {\n        return treeMateRef.value.getCheckedKeys(mergedValueRef.value, {\n          cascade,\n          allowNotLoaded: props.allowCheckingNotLoaded\n        })\n      }\n      else {\n        return {\n          checkedKeys: [],\n          indeterminateKeys: []\n        }\n      }\n    })\n    const checkedKeysRef = computed(() => mergedKeysRef.value.checkedKeys)\n    const indeterminateKeysRef = computed(\n      () => mergedKeysRef.value.indeterminateKeys\n    )\n    const menuModelRef = computed(() => {\n      const { treeNodePath, treeNode } = treeMateRef.value.getPath(\n        hoverKeyRef.value\n      )\n      let ret\n      if (treeNode === null) {\n        ret = [treeMateRef.value.treeNodes]\n      }\n      else {\n        ret = treeNodePath.map(treeNode => treeNode.siblings)\n        if (\n          !treeNode.isLeaf\n          && !loadingKeySetRef.value.has(treeNode.key)\n          && treeNode.children\n        ) {\n          ret.push(treeNode.children)\n        }\n      }\n      return ret\n    })\n    const hoverKeyPathRef = computed(() => {\n      const { keyPath } = treeMateRef.value.getPath(hoverKeyRef.value)\n      return keyPath\n    })\n    const optionHeightRef = computed(() => {\n      return themeRef.value.self.optionHeight\n    })\n    if (isReactive(props.options)) {\n      watch(props.options, (value, oldValue) => {\n        if (!(value === oldValue)) {\n          hoverKeyRef.value = null\n          keyboardKeyRef.value = null\n        }\n      })\n    }\n    const uncontrolledShowRef = ref(false)\n    function doUpdateShow(value: boolean): void {\n      const { onUpdateShow, 'onUpdate:show': _onUpdateShow } = props\n      if (onUpdateShow) {\n        call(onUpdateShow, value)\n      }\n      if (_onUpdateShow) {\n        call(_onUpdateShow, value)\n      }\n      uncontrolledShowRef.value = value\n    }\n    function doUpdateValue(\n      value: Value | null,\n      option: CascaderOption | null | Array<CascaderOption | null>,\n      optionPath: null | CascaderOption[] | Array<CascaderOption[] | null>\n    ): void {\n      const {\n        onUpdateValue,\n        'onUpdate:value': _onUpdateValue,\n        onChange\n      } = props\n      const { nTriggerFormInput, nTriggerFormChange } = formItem\n      if (onUpdateValue) {\n        call(onUpdateValue as OnUpdateValueImpl, value, option, optionPath)\n      }\n      if (_onUpdateValue) {\n        call(_onUpdateValue as OnUpdateValueImpl, value, option, optionPath)\n      }\n      if (onChange) {\n        call(onChange as OnUpdateValueImpl, value, option, optionPath)\n      }\n      uncontrolledValueRef.value = value\n      nTriggerFormInput()\n      nTriggerFormChange()\n    }\n    function updateKeyboardKey(key: Key | null): void {\n      keyboardKeyRef.value = key\n    }\n    function updateHoverKey(key: Key | null): void {\n      hoverKeyRef.value = key\n    }\n    function getOptionsByKeys(keys: Key[]): Array<CascaderOption | null> {\n      const {\n        value: { getNode }\n      } = treeMateRef\n      return keys.map(keys => getNode(keys)?.rawNode || null)\n    }\n    function doCheck(key: Key): boolean {\n      const { cascade, multiple, filterable } = props\n      const {\n        value: { check, getNode, getPath }\n      } = treeMateRef\n      if (multiple) {\n        try {\n          const { checkedKeys } = check(key, mergedKeysRef.value.checkedKeys, {\n            cascade,\n            checkStrategy: mergedCheckStrategyRef.value,\n            allowNotLoaded: props.allowCheckingNotLoaded\n          })\n          doUpdateValue(\n            checkedKeys,\n            getOptionsByKeys(checkedKeys),\n            checkedKeys.map(checkedKey =>\n              getRawNodePath(getPath(checkedKey)?.treeNodePath)\n            )\n          )\n          if (filterable)\n            focusSelectionInput()\n          keyboardKeyRef.value = key\n          hoverKeyRef.value = key\n        }\n        catch (err) {\n          if (err instanceof SubtreeNotLoadedError) {\n            if (cascaderMenuInstRef.value) {\n              const tmNode = getNode(key)\n              if (tmNode !== null) {\n                cascaderMenuInstRef.value.showErrorMessage(\n                  (tmNode.rawNode as any)[props.labelField] as string\n                )\n              }\n            }\n          }\n          else {\n            throw err\n          }\n        }\n      }\n      else {\n        if (mergedCheckStrategyRef.value === 'child') {\n          const tmNode = getNode(key)\n          if (tmNode?.isLeaf) {\n            doUpdateValue(\n              key,\n              tmNode.rawNode,\n              getRawNodePath(getPath(key).treeNodePath)\n            )\n          }\n          else {\n            return false\n          }\n        }\n        else {\n          const tmNode = getNode(key)\n          doUpdateValue(\n            key,\n            tmNode?.rawNode || null,\n            getRawNodePath(getPath(key)?.treeNodePath)\n          )\n        }\n      }\n      return true\n    }\n    function doUncheck(key: Key): void {\n      const { cascade, multiple } = props\n      if (multiple) {\n        const {\n          value: { uncheck, getNode, getPath }\n        } = treeMateRef\n        const { checkedKeys } = uncheck(key, mergedKeysRef.value.checkedKeys, {\n          cascade,\n          checkStrategy: mergedCheckStrategyRef.value,\n          allowNotLoaded: props.allowCheckingNotLoaded\n        })\n        doUpdateValue(\n          checkedKeys,\n          checkedKeys.map(checkedKey => getNode(checkedKey)?.rawNode || null),\n          checkedKeys.map(checkedKey =>\n            getRawNodePath(getPath(checkedKey)?.treeNodePath)\n          )\n        )\n        keyboardKeyRef.value = key\n        hoverKeyRef.value = key\n      }\n    }\n    const selectedOptionsRef = computed(() => {\n      if (props.multiple) {\n        const { showPath, separator, labelField, cascade } = props\n        const { getCheckedKeys, getNode } = treeMateRef.value\n        const value = getCheckedKeys(checkedKeysRef.value, {\n          cascade,\n          checkStrategy: mergedCheckStrategyRef.value,\n          allowNotLoaded: props.allowCheckingNotLoaded\n        }).checkedKeys\n        return value.map((key) => {\n          const node = getNode(key)\n          if (node === null) {\n            return {\n              label: String(key),\n              value: key\n            }\n          }\n          else {\n            return {\n              label: showPath\n                ? getPathLabel(node, separator, labelField)\n                : (node.rawNode as any)[labelField],\n              value: node.key\n            }\n          }\n        })\n      }\n      else {\n        return []\n      }\n    })\n    const selectedOptionRef = computed(() => {\n      const { multiple, showPath, separator, labelField } = props\n      const { value } = mergedValueRef\n      if (!multiple && !Array.isArray(value)) {\n        const { getNode } = treeMateRef.value\n        if (value === null) {\n          return null\n        }\n        const node = getNode(value)\n        if (node === null) {\n          return {\n            label: String(value),\n            value\n          }\n        }\n        else {\n          return {\n            label: showPath\n              ? getPathLabel(node, separator, labelField)\n              : (node.rawNode as any)[labelField],\n            value: node.key\n          }\n        }\n      }\n      else {\n        return null\n      }\n    })\n    const controlledShowRef = toRef(props, 'show')\n    const mergedShowRef = useMergedState(controlledShowRef, uncontrolledShowRef)\n    const localizedPlaceholderRef = computed(() => {\n      const { placeholder } = props\n      if (placeholder !== undefined)\n        return placeholder\n      return localeRef.value.placeholder\n    })\n    // select option related\n    const showSelectMenuRef = computed(() => {\n      return !!(props.filterable && patternRef.value)\n    })\n    // init hover key\n    watch(\n      mergedShowRef,\n      (show) => {\n        if (!show)\n          return\n        if (props.multiple)\n          return\n        const { value } = mergedValueRef\n        if (!Array.isArray(value) && value !== null) {\n          keyboardKeyRef.value = value\n          hoverKeyRef.value = value\n          void nextTick(() => {\n            if (!mergedShowRef.value)\n              return\n            const { value: hoverKey } = hoverKeyRef\n            if (mergedValueRef.value !== null) {\n              const node = treeMateRef.value.getNode(hoverKey)\n              if (node) {\n                cascaderMenuInstRef.value?.scroll(\n                  node.level,\n                  node.index,\n                  depx(optionHeightRef.value)\n                )\n              }\n            }\n          })\n        }\n        else {\n          keyboardKeyRef.value = null\n          hoverKeyRef.value = null\n        }\n      },\n      {\n        immediate: true\n      }\n    )\n    // --- methods\n    function doBlur(e: FocusEvent): void {\n      const { onBlur } = props\n      const { nTriggerFormBlur } = formItem\n      if (onBlur)\n        call(onBlur, e)\n      nTriggerFormBlur()\n    }\n    function doFocus(e: FocusEvent): void {\n      const { onFocus } = props\n      const { nTriggerFormFocus } = formItem\n      if (onFocus)\n        call(onFocus, e)\n      nTriggerFormFocus()\n    }\n    function focusSelectionInput(): void {\n      triggerInstRef.value?.focusInput()\n    }\n    function focusSelection(): void {\n      triggerInstRef.value?.focus()\n    }\n    function openMenu(): void {\n      if (!mergedDisabledRef.value) {\n        patternRef.value = ''\n        doUpdateShow(true)\n        if (props.filterable) {\n          focusSelectionInput()\n        }\n      }\n    }\n    function closeMenu(returnFocus = false): void {\n      if (returnFocus) {\n        focusSelection()\n      }\n      doUpdateShow(false)\n      patternRef.value = ''\n    }\n    function handleCascaderMenuClickOutside(e: MouseEvent): void {\n      if (showSelectMenuRef.value)\n        return\n      if (mergedShowRef.value) {\n        if (\n          !triggerInstRef.value?.$el.contains(\n            getPreciseEventTarget(e) as Node | null\n          )\n        ) {\n          closeMenu()\n        }\n      }\n    }\n    function handleSelectMenuClickOutside(e: MouseEvent): void {\n      if (!showSelectMenuRef.value)\n        return\n      handleCascaderMenuClickOutside(e)\n    }\n    function clearPattern(): void {\n      if (props.clearFilterAfterSelect)\n        patternRef.value = ''\n    }\n    // --- keyboard\n    function move(direction: 'prev' | 'next' | 'child' | 'parent'): void {\n      const { value: keyboardKey } = keyboardKeyRef\n      const { value: treeMate } = treeMateRef\n      switch (direction) {\n        case 'prev':\n          if (keyboardKey !== null) {\n            const node = treeMate.getPrev(keyboardKey, { loop: true })\n            if (node !== null) {\n              updateKeyboardKey(node.key)\n              cascaderMenuInstRef.value?.scroll(\n                node.level,\n                node.index,\n                depx(optionHeightRef.value)\n              )\n            }\n          }\n          break\n        case 'next':\n          if (keyboardKey === null) {\n            const node = treeMate.getFirstAvailableNode()\n            if (node !== null) {\n              updateKeyboardKey(node.key)\n              cascaderMenuInstRef.value?.scroll(\n                node.level,\n                node.index,\n                depx(optionHeightRef.value)\n              )\n            }\n          }\n          else {\n            const node = treeMate.getNext(keyboardKey, { loop: true })\n            if (node !== null) {\n              updateKeyboardKey(node.key)\n              cascaderMenuInstRef.value?.scroll(\n                node.level,\n                node.index,\n                depx(optionHeightRef.value)\n              )\n            }\n          }\n          break\n        case 'child':\n          if (keyboardKey !== null) {\n            const currentNode = treeMate.getNode(keyboardKey)\n            if (currentNode !== null) {\n              if (currentNode.shallowLoaded) {\n                const node = treeMate.getChild(keyboardKey)\n                if (node !== null) {\n                  updateHoverKey(keyboardKey)\n                  updateKeyboardKey(node.key)\n                }\n              }\n              else {\n                const { value: loadingKeySet } = loadingKeySetRef\n                if (!loadingKeySet.has(keyboardKey)) {\n                  addLoadingKey(keyboardKey)\n                  updateHoverKey(keyboardKey)\n                  const { onLoad } = props\n                  if (onLoad) {\n                    onLoad(currentNode.rawNode)\n                      .then(() => {\n                        deleteLoadingKey(keyboardKey)\n                      })\n                      .catch(() => {\n                        deleteLoadingKey(keyboardKey)\n                      })\n                  }\n                }\n              }\n            }\n          }\n          break\n        case 'parent':\n          if (keyboardKey !== null) {\n            const node = treeMate.getParent(keyboardKey)\n            if (node !== null) {\n              updateKeyboardKey(node.key)\n              const parentNode = node.getParent()\n              if (parentNode === null) {\n                updateHoverKey(null)\n              }\n              else {\n                updateHoverKey(parentNode.key)\n              }\n            }\n          }\n          break\n      }\n    }\n    function handleKeydown(e: KeyboardEvent): void {\n      switch (e.key) {\n        case ' ':\n        case 'ArrowDown':\n        case 'ArrowUp':\n          if (props.filterable && mergedShowRef.value) {\n            break\n          }\n          e.preventDefault()\n          break\n      }\n      if (happensIn(e, 'action'))\n        return\n      switch (e.key) {\n        case ' ':\n          if (props.filterable)\n            return\n        // eslint-disable-next-line no-fallthrough\n        case 'Enter':\n          if (!mergedShowRef.value) {\n            openMenu()\n          }\n          else {\n            const { value: showSelectMenu } = showSelectMenuRef\n            const { value: keyboardKey } = keyboardKeyRef\n            if (!showSelectMenu) {\n              if (keyboardKey !== null) {\n                if (\n                  checkedKeysRef.value.includes(keyboardKey)\n                  || indeterminateKeysRef.value.includes(keyboardKey)\n                ) {\n                  doUncheck(keyboardKey)\n                }\n                else {\n                  const checkIsValid = doCheck(keyboardKey)\n                  if (!props.multiple && checkIsValid) {\n                    closeMenu(true)\n                  }\n                }\n              }\n            }\n            else {\n              if (selectMenuInstRef.value) {\n                const hasCorrespondingOption = selectMenuInstRef.value.enter()\n                if (hasCorrespondingOption)\n                  clearPattern()\n              }\n            }\n          }\n          break\n        case 'ArrowUp':\n          e.preventDefault()\n          if (mergedShowRef.value) {\n            if (showSelectMenuRef.value) {\n              selectMenuInstRef.value?.prev()\n            }\n            else {\n              move('prev')\n            }\n          }\n          break\n        case 'ArrowDown':\n          e.preventDefault()\n          if (mergedShowRef.value) {\n            if (showSelectMenuRef.value) {\n              selectMenuInstRef.value?.next()\n            }\n            else {\n              move('next')\n            }\n          }\n          else {\n            openMenu()\n          }\n          break\n        case 'ArrowLeft':\n          e.preventDefault()\n          if (mergedShowRef.value && !showSelectMenuRef.value) {\n            move('parent')\n          }\n          break\n        case 'ArrowRight':\n          e.preventDefault()\n          if (mergedShowRef.value && !showSelectMenuRef.value) {\n            move('child')\n          }\n          break\n        case 'Escape':\n          if (mergedShowRef.value) {\n            markEventEffectPerformed(e)\n            closeMenu(true)\n          }\n      }\n    }\n    function handleMenuKeydown(e: KeyboardEvent): void {\n      handleKeydown(e)\n    }\n    // --- search\n    function handleClear(e: MouseEvent): void {\n      e.stopPropagation()\n      if (props.multiple) {\n        doUpdateValue([], [], [])\n      }\n      else {\n        doUpdateValue(null, null, null)\n      }\n    }\n    function handleTriggerFocus(e: FocusEvent): void {\n      if (!cascaderMenuInstRef.value?.$el.contains(e.relatedTarget as Node)) {\n        focusedRef.value = true\n        doFocus(e)\n      }\n    }\n    function handleTriggerBlur(e: FocusEvent): void {\n      if (!cascaderMenuInstRef.value?.$el.contains(e.relatedTarget as Node)) {\n        focusedRef.value = false\n        doBlur(e)\n        closeMenu()\n      }\n    }\n    function handleMenuFocus(e: FocusEvent): void {\n      if (!triggerInstRef.value?.$el.contains(e.relatedTarget as Node)) {\n        focusedRef.value = true\n        doFocus(e)\n      }\n    }\n    function handleMenuBlur(e: FocusEvent): void {\n      if (!triggerInstRef.value?.$el.contains(e.relatedTarget as Node)) {\n        focusedRef.value = false\n        doBlur(e)\n      }\n    }\n    function handleMenuMousedown(e: MouseEvent): void {\n      if (!happensIn(e, 'action')) {\n        if (props.multiple && props.filter) {\n          e.preventDefault()\n          focusSelectionInput()\n        }\n      }\n    }\n    function handleMenuTabout(): void {\n      closeMenu(true)\n    }\n    function handleTriggerClick(): void {\n      if (props.filterable) {\n        openMenu()\n      }\n      else {\n        if (mergedShowRef.value) {\n          closeMenu(true)\n        }\n        else {\n          openMenu()\n        }\n      }\n    }\n    function handlePatternInput(e: InputEvent): void {\n      patternRef.value = (e.target as HTMLInputElement).value\n    }\n    function handleDeleteOption(option: SelectBaseOption): void {\n      const { multiple } = props\n      const { value: mergedValue } = mergedValueRef\n      if (\n        multiple\n        && Array.isArray(mergedValue)\n        && option.value !== undefined\n      ) {\n        doUncheck(option.value)\n      }\n      else {\n        doUpdateValue(null, null, null)\n      }\n    }\n    // sync position\n    function syncSelectMenuPosition(): void {\n      selectMenuFollowerRef.value?.syncPosition()\n    }\n    function syncCascaderMenuPosition(): void {\n      cascaderMenuFollowerRef.value?.syncPosition()\n    }\n    function handleTriggerResize(): void {\n      if (mergedShowRef.value) {\n        if (showSelectMenuRef.value) {\n          syncSelectMenuPosition()\n        }\n        else {\n          syncCascaderMenuPosition()\n        }\n      }\n    }\n    const showCheckboxRef = computed(() => {\n      if (props.multiple && props.cascade)\n        return true\n      if (mergedCheckStrategyRef.value !== 'child')\n        return true\n      return false\n    })\n    provide(cascaderInjectionKey, {\n      slots,\n      mergedClsPrefixRef,\n      mergedThemeRef: themeRef,\n      mergedValueRef,\n      checkedKeysRef,\n      indeterminateKeysRef,\n      hoverKeyPathRef,\n      mergedCheckStrategyRef,\n      showCheckboxRef,\n      cascadeRef: toRef(props, 'cascade'),\n      multipleRef: toRef(props, 'multiple'),\n      keyboardKeyRef,\n      hoverKeyRef,\n      remoteRef: toRef(props, 'remote'),\n      loadingKeySetRef,\n      expandTriggerRef: toRef(props, 'expandTrigger'),\n      isMountedRef: useIsMounted(),\n      onLoadRef: toRef(props, 'onLoad'),\n      virtualScrollRef: toRef(props, 'virtualScroll'),\n      optionHeightRef,\n      localeRef,\n      labelFieldRef: toRef(props, 'labelField'),\n      renderLabelRef: toRef(props, 'renderLabel'),\n      getColumnStyleRef: toRef(props, 'getColumnStyle'),\n      renderPrefixRef: toRef(props, 'renderPrefix'),\n      renderSuffixRef: toRef(props, 'renderSuffix'),\n      spinPropsRef: toRef(props, 'spinProps'),\n      syncCascaderMenuPosition,\n      syncSelectMenuPosition,\n      updateKeyboardKey,\n      updateHoverKey,\n      addLoadingKey,\n      deleteLoadingKey,\n      doCheck,\n      doUncheck,\n      closeMenu,\n      handleSelectMenuClickOutside,\n      handleCascaderMenuClickOutside,\n      scrollbarPropsRef: toRef(props, 'scrollbarProps'),\n      clearPattern\n    })\n    const exposedMethods: CascaderInst = {\n      focus: () => {\n        triggerInstRef.value?.focus()\n      },\n      blur: () => {\n        triggerInstRef.value?.blur()\n      },\n      getCheckedData: () => {\n        if (showCheckboxRef.value) {\n          const checkedKeys = checkedKeysRef.value\n          return {\n            keys: checkedKeys,\n            options: getOptionsByKeys(checkedKeys)\n          }\n        }\n        return {\n          keys: [],\n          options: []\n        }\n      },\n      getIndeterminateData: () => {\n        if (showCheckboxRef.value) {\n          const indeterminateKeys = indeterminateKeysRef.value\n          return {\n            keys: indeterminateKeys,\n            options: getOptionsByKeys(indeterminateKeys)\n          }\n        }\n        return {\n          keys: [],\n          options: []\n        }\n      }\n    }\n    const cssVarsRef = computed(() => {\n      const {\n        self: {\n          optionArrowColor,\n          optionTextColor,\n          optionTextColorActive,\n          optionTextColorDisabled,\n          optionCheckMarkColor,\n          menuColor,\n          menuBoxShadow,\n          menuDividerColor,\n          menuBorderRadius,\n          menuHeight,\n          optionColorHover,\n          optionHeight,\n          optionFontSize,\n          loadingColor,\n          columnWidth\n        },\n        common: { cubicBezierEaseInOut }\n      } = themeRef.value\n      return {\n        '--n-bezier': cubicBezierEaseInOut,\n        '--n-menu-border-radius': menuBorderRadius,\n        '--n-menu-box-shadow': menuBoxShadow,\n        '--n-menu-height': menuHeight,\n        '--n-column-width': columnWidth,\n        '--n-menu-color': menuColor,\n        '--n-menu-divider-color': menuDividerColor,\n        '--n-option-height': optionHeight,\n        '--n-option-font-size': optionFontSize,\n        '--n-option-text-color': optionTextColor,\n        '--n-option-text-color-disabled': optionTextColorDisabled,\n        '--n-option-text-color-active': optionTextColorActive,\n        '--n-option-color-hover': optionColorHover,\n        '--n-option-check-mark-color': optionCheckMarkColor,\n        '--n-option-arrow-color': optionArrowColor,\n        '--n-menu-mask-color': changeColor(menuColor, { alpha: 0.75 }),\n        '--n-loading-color': loadingColor\n      }\n    })\n    const themeClassHandle = inlineThemeDisabled\n      ? useThemeClass('cascader', undefined, cssVarsRef, props)\n      : undefined\n    return {\n      ...exposedMethods,\n      handleTriggerResize,\n      mergedStatus: mergedStatusRef,\n      selectMenuFollowerRef,\n      cascaderMenuFollowerRef,\n      triggerInstRef,\n      selectMenuInstRef,\n      cascaderMenuInstRef,\n      mergedBordered: mergedBorderedRef,\n      mergedClsPrefix: mergedClsPrefixRef,\n      namespace: namespaceRef,\n      mergedValue: mergedValueRef,\n      mergedShow: mergedShowRef,\n      showSelectMenu: showSelectMenuRef,\n      pattern: patternRef,\n      treeMate: treeMateRef,\n      mergedSize: mergedSizeRef,\n      mergedDisabled: mergedDisabledRef,\n      localizedPlaceholder: localizedPlaceholderRef,\n      selectedOption: selectedOptionRef,\n      selectedOptions: selectedOptionsRef,\n      adjustedTo: adjustedToRef,\n      menuModel: menuModelRef,\n      handleMenuTabout,\n      handleMenuFocus,\n      handleMenuBlur,\n      handleMenuKeydown,\n      handleMenuMousedown,\n      handleTriggerFocus,\n      handleTriggerBlur,\n      handleTriggerClick,\n      handleClear,\n      handleDeleteOption,\n      handlePatternInput,\n      handleKeydown,\n      focused: focusedRef,\n      optionHeight: optionHeightRef,\n      mergedTheme: themeRef,\n      cssVars: inlineThemeDisabled ? undefined : cssVarsRef,\n      themeClass: themeClassHandle?.themeClass,\n      onRender: themeClassHandle?.onRender\n    }\n  },\n  render() {\n    const { mergedClsPrefix } = this\n    return (\n      <div class={`${mergedClsPrefix}-cascader`}>\n        <VBinder>\n          {{\n            default: () => [\n              <VTarget>\n                {{\n                  default: () => (\n                    <NInternalSelection\n                      onResize={this.handleTriggerResize}\n                      ref=\"triggerInstRef\"\n                      status={this.mergedStatus}\n                      clsPrefix={mergedClsPrefix}\n                      maxTagCount={this.maxTagCount}\n                      ellipsisTagPopoverProps={this.ellipsisTagPopoverProps}\n                      bordered={this.mergedBordered}\n                      size={this.mergedSize}\n                      theme={this.mergedTheme.peers.InternalSelection}\n                      themeOverrides={\n                        this.mergedTheme.peerOverrides.InternalSelection\n                      }\n                      active={this.mergedShow}\n                      pattern={this.pattern}\n                      placeholder={this.localizedPlaceholder}\n                      selectedOption={this.selectedOption}\n                      selectedOptions={this.selectedOptions}\n                      multiple={this.multiple}\n                      filterable={this.filterable}\n                      clearable={this.clearable}\n                      disabled={this.mergedDisabled}\n                      focused={this.focused}\n                      onFocus={this.handleTriggerFocus}\n                      onBlur={this.handleTriggerBlur}\n                      onClick={this.handleTriggerClick}\n                      onClear={this.handleClear}\n                      onDeleteOption={this.handleDeleteOption}\n                      onPatternInput={this.handlePatternInput}\n                      onKeydown={this.handleKeydown}\n                    >\n                      {{\n                        arrow: () => this.$slots.arrow?.()\n                      }}\n                    </NInternalSelection>\n                  )\n                }}\n              </VTarget>,\n              <VFollower\n                key=\"cascaderMenu\"\n                ref=\"cascaderMenuFollowerRef\"\n                show={this.mergedShow && !this.showSelectMenu}\n                containerClass={this.namespace}\n                placement={this.placement}\n                width={!this.options.length ? 'target' : undefined}\n                teleportDisabled={this.adjustedTo === useAdjustedTo.tdkey}\n                to={this.adjustedTo}\n              >\n                {{\n                  default: () => {\n                    this.onRender?.()\n                    const { menuProps } = this\n                    return (\n                      <CascaderMenu\n                        {...menuProps}\n                        ref=\"cascaderMenuInstRef\"\n                        class={[this.themeClass, menuProps?.class]}\n                        value={this.mergedValue}\n                        show={this.mergedShow && !this.showSelectMenu}\n                        menuModel={this.menuModel}\n                        style={[\n                          this.cssVars as CSSProperties,\n                          menuProps?.style\n                        ]}\n                        onFocus={this.handleMenuFocus}\n                        onBlur={this.handleMenuBlur}\n                        onKeydown={this.handleMenuKeydown}\n                        onMousedown={this.handleMenuMousedown}\n                        onTabout={this.handleMenuTabout}\n                      >\n                        {{\n                          action: () => this.$slots.action?.(),\n                          empty: () => this.$slots.empty?.()\n                        }}\n                      </CascaderMenu>\n                    )\n                  }\n                }}\n              </VFollower>,\n              <VFollower\n                key=\"selectMenu\"\n                ref=\"selectMenuFollowerRef\"\n                show={this.mergedShow && this.showSelectMenu}\n                containerClass={this.namespace}\n                width=\"target\"\n                placement={this.placement}\n                to={this.adjustedTo}\n                teleportDisabled={this.adjustedTo === useAdjustedTo.tdkey}\n              >\n                {{\n                  default: () => {\n                    this.onRender?.()\n                    const { filterMenuProps } = this\n                    return (\n                      <CascaderSelectMenu\n                        {...filterMenuProps}\n                        ref=\"selectMenuInstRef\"\n                        class={[this.themeClass, filterMenuProps?.class]}\n                        value={this.mergedValue}\n                        show={this.mergedShow && this.showSelectMenu}\n                        pattern={this.pattern}\n                        multiple={this.multiple}\n                        tmNodes={this.treeMate.treeNodes}\n                        filter={this.filter}\n                        labelField={this.labelField}\n                        separator={this.separator}\n                        style={[\n                          this.cssVars as CSSProperties,\n                          filterMenuProps?.style\n                        ]}\n                      />\n                    )\n                  }\n                }}\n              </VFollower>\n            ]\n          }}\n        </VBinder>\n      </div>\n    )\n  }\n})\n"
  },
  {
    "path": "src/cascader/src/CascaderMenu.tsx",
    "content": "import type { PropType } from 'vue'\nimport type { FollowerPlacement } from 'vueuc'\nimport type { MenuMaskRef } from '../../_internal/menu-mask'\nimport type {\n  CascaderMenuExposedMethods,\n  CascaderSubmenuInstance,\n  MenuModel,\n  Value\n} from './interface'\nimport { clickoutside } from 'vdirs'\nimport {\n  computed,\n  defineComponent,\n  h,\n  inject,\n  ref,\n  Transition,\n  withDirectives\n} from 'vue'\nimport { NBaseMenuMask } from '../../_internal'\nimport FocusDetector from '../../_internal/focus-detector'\nimport { useConfig } from '../../_mixins'\nimport { resolveSlot, resolveWrappedSlot, useOnResize } from '../../_utils'\nimport { NEmpty } from '../../empty'\nimport NCascaderSubmenu from './CascaderSubmenu'\nimport { cascaderInjectionKey } from './interface'\n\nexport default defineComponent({\n  name: 'NCascaderMenu',\n  props: {\n    value: [String, Number, Array] as PropType<Value | null>,\n    placement: {\n      type: String as PropType<FollowerPlacement>,\n      default: 'bottom-start'\n    },\n    show: Boolean,\n    menuModel: {\n      type: Array as PropType<MenuModel>,\n      required: true\n    },\n    loading: Boolean,\n    onFocus: {\n      type: Function as PropType<(e: FocusEvent) => void>,\n      required: true\n    },\n    onBlur: {\n      type: Function as PropType<(e: FocusEvent) => void>,\n      required: true\n    },\n    onKeydown: {\n      type: Function as PropType<(e: KeyboardEvent) => void>,\n      required: true\n    },\n    onMousedown: {\n      type: Function as PropType<(e: MouseEvent) => void>,\n      required: true\n    },\n    onTabout: {\n      type: Function as PropType<() => void>,\n      required: true\n    }\n  },\n  setup(props) {\n    const {\n      localeRef,\n      isMountedRef,\n      mergedClsPrefixRef,\n      syncCascaderMenuPosition,\n      handleCascaderMenuClickOutside,\n      mergedThemeRef,\n      getColumnStyleRef\n    } = inject(cascaderInjectionKey)!\n    const { mergedComponentPropsRef } = useConfig()\n    const submenuInstRefs: CascaderSubmenuInstance[] = []\n    const maskInstRef = ref<MenuMaskRef | null>(null)\n    const selfElRef = ref<HTMLElement | null>(null)\n    function handleResize(): void {\n      syncCascaderMenuPosition()\n    }\n    useOnResize(selfElRef, handleResize)\n    function showErrorMessage(label: string): void {\n      const {\n        value: { loadingRequiredMessage }\n      } = localeRef\n      maskInstRef.value?.showOnce(loadingRequiredMessage(label))\n    }\n    function handleClickOutside(e: MouseEvent): void {\n      handleCascaderMenuClickOutside(e)\n    }\n    function handleFocusin(e: FocusEvent): void {\n      const { value: selfEl } = selfElRef\n      if (!selfEl)\n        return\n      if (!selfEl.contains(e.relatedTarget as Node)) {\n        props.onFocus(e)\n      }\n    }\n    function handleFocusout(e: FocusEvent): void {\n      const { value: selfEl } = selfElRef\n      if (!selfEl)\n        return\n      if (!selfEl.contains(e.relatedTarget as Node)) {\n        props.onBlur(e)\n      }\n    }\n    const exposedRef: CascaderMenuExposedMethods = {\n      scroll(depth: number, index: number, elSize: number) {\n        const submenuInst = submenuInstRefs[depth]\n        if (submenuInst) {\n          submenuInst.scroll(index, elSize)\n        }\n      },\n      showErrorMessage\n    }\n    return {\n      isMounted: isMountedRef,\n      mergedClsPrefix: mergedClsPrefixRef,\n      selfElRef,\n      submenuInstRefs,\n      maskInstRef,\n      mergedTheme: mergedThemeRef,\n      mergedRenderEmpty: computed(() => {\n        return mergedComponentPropsRef?.value?.Cascader?.renderEmpty\n      }),\n      getColumnStyle: getColumnStyleRef,\n      handleFocusin,\n      handleFocusout,\n      handleClickOutside,\n      ...exposedRef\n    }\n  },\n  render() {\n    const { submenuInstRefs, mergedClsPrefix, mergedTheme } = this\n    return (\n      <Transition name=\"fade-in-scale-up-transition\" appear={this.isMounted}>\n        {{\n          default: () => {\n            if (!this.show)\n              return null\n            return withDirectives(\n              <div\n                tabindex=\"0\"\n                ref=\"selfElRef\"\n                class={`${mergedClsPrefix}-cascader-menu`}\n                onMousedown={this.onMousedown}\n                onFocusin={this.handleFocusin}\n                onFocusout={this.handleFocusout}\n                onKeydown={this.onKeydown}\n              >\n                {this.menuModel[0].length ? (\n                  <div class={`${mergedClsPrefix}-cascader-submenu-wrapper`}>\n                    {this.menuModel.map((submenuOptions, index) => (\n                      <NCascaderSubmenu\n                        style={this.getColumnStyle?.({ level: index })}\n                        ref={\n                          ((instance: CascaderSubmenuInstance) => {\n                            if (instance) {\n                              submenuInstRefs[index] = instance\n                            }\n                          }) as any\n                        }\n                        key={index}\n                        tmNodes={submenuOptions}\n                        depth={index + 1}\n                      />\n                    ))}\n                    <NBaseMenuMask\n                      clsPrefix={mergedClsPrefix}\n                      ref=\"maskInstRef\"\n                    />\n                  </div>\n                ) : (\n                  <div class={`${mergedClsPrefix}-cascader-menu__empty`}>\n                    {resolveSlot(this.$slots.empty, () => {\n                      return [\n                        this.mergedRenderEmpty?.() || (\n                          <NEmpty\n                            theme={mergedTheme.peers.Empty}\n                            themeOverrides={mergedTheme.peerOverrides.Empty}\n                          />\n                        )\n                      ]\n                    })}\n                  </div>\n                )}\n                {resolveWrappedSlot(\n                  this.$slots.action,\n                  children =>\n                    children && (\n                      <div\n                        class={`${mergedClsPrefix}-cascader-menu-action`}\n                        data-action\n                      >\n                        {children}\n                      </div>\n                    )\n                )}\n                <FocusDetector onFocus={this.onTabout} />\n              </div>,\n              [\n                [\n                  clickoutside,\n                  this.handleClickOutside,\n                  undefined as unknown as string,\n                  { capture: true }\n                ]\n              ]\n            )\n          }\n        }}\n      </Transition>\n    )\n  }\n})\n"
  },
  {
    "path": "src/cascader/src/CascaderOption.tsx",
    "content": "import type { PropType, VNode } from 'vue'\nimport type { TmNode } from './interface'\nimport { happensIn } from 'seemly'\nimport { useMemo } from 'vooks'\nimport { computed, defineComponent, h, inject, Transition } from 'vue'\nimport { NBaseIcon, NBaseLoading } from '../../_internal'\nimport { CheckmarkIcon, ChevronRightIcon } from '../../_internal/icons'\nimport { NCheckbox } from '../../checkbox'\nimport { cascaderInjectionKey } from './interface'\n\nexport default defineComponent({\n  name: 'NCascaderOption',\n  props: {\n    tmNode: {\n      type: Object as PropType<TmNode>,\n      required: true\n    }\n  },\n  setup(props) {\n    const {\n      expandTriggerRef,\n      remoteRef,\n      multipleRef,\n      mergedValueRef,\n      checkedKeysRef,\n      indeterminateKeysRef,\n      hoverKeyPathRef,\n      keyboardKeyRef,\n      loadingKeySetRef,\n      cascadeRef,\n      mergedCheckStrategyRef,\n      onLoadRef,\n      mergedClsPrefixRef,\n      mergedThemeRef,\n      labelFieldRef,\n      showCheckboxRef,\n      renderPrefixRef,\n      renderSuffixRef,\n      spinPropsRef,\n      updateHoverKey,\n      updateKeyboardKey,\n      addLoadingKey,\n      deleteLoadingKey,\n      closeMenu,\n      doCheck,\n      doUncheck,\n      renderLabelRef\n    } = inject(cascaderInjectionKey)!\n    const valueRef = computed(() => props.tmNode.key)\n    const useHoverTriggerRef = computed(() => {\n      const { value: expandTrigger } = expandTriggerRef\n      const { value: remote } = remoteRef\n      return !remote && expandTrigger === 'hover'\n    })\n    const mergedHandleMouseEnterRef = computed(() => {\n      if (useHoverTriggerRef.value) {\n        return handleMouseEnter\n      }\n      return undefined\n    })\n    const mergedHandleMouseMoveRef = computed(() => {\n      if (useHoverTriggerRef.value) {\n        return handleMouseMove\n      }\n      return undefined\n    })\n    const checkedRef = useMemo(() => {\n      const { value: multiple } = multipleRef\n      if (!multiple)\n        return mergedValueRef.value === valueRef.value\n      return checkedKeysRef.value.includes(valueRef.value)\n    })\n    const indeterminateRef = useMemo(() => {\n      if (!multipleRef.value)\n        return false\n      return indeterminateKeysRef.value.includes(valueRef.value)\n    })\n    const hoverPendingRef = useMemo(() => {\n      return hoverKeyPathRef.value.includes(valueRef.value)\n    })\n    const keyboardPendingRef = useMemo(() => {\n      const { value: keyboardKey } = keyboardKeyRef\n      if (keyboardKey === null)\n        return false\n      return keyboardKey === valueRef.value\n    })\n    const isLoadingRef = useMemo(() => {\n      if (remoteRef.value) {\n        return loadingKeySetRef.value.has(valueRef.value)\n      }\n      return false\n    })\n    const isLeafRef = computed(() => props.tmNode.isLeaf)\n    const disabledRef = computed(() => props.tmNode.disabled)\n    const labelRef = computed(\n      () => (props.tmNode.rawNode as any)[labelFieldRef.value]\n    )\n    const isShallowLoadedRef = computed(() => {\n      return props.tmNode.shallowLoaded\n    })\n    function handleClick(e: MouseEvent): void {\n      if (disabledRef.value)\n        return\n      const { value: remote } = remoteRef\n      const { value: loadingKeySet } = loadingKeySetRef\n      const { value: onLoad } = onLoadRef\n      const { value } = valueRef\n      const { value: isLeaf } = isLeafRef\n      const { value: isShallowLoaded } = isShallowLoadedRef\n      if (!happensIn(e, 'checkbox')) {\n        if (remote && !isShallowLoaded && !loadingKeySet.has(value) && onLoad) {\n          addLoadingKey(value)\n          onLoad(props.tmNode.rawNode)\n            .then(() => {\n              deleteLoadingKey(value)\n            })\n            .catch(() => {\n              deleteLoadingKey(value)\n            })\n        }\n        updateHoverKey(value)\n        updateKeyboardKey(value)\n      }\n      if (isLeaf) {\n        toggleCheckbox()\n      }\n    }\n    function handleMouseEnter(): void {\n      if (!useHoverTriggerRef.value || disabledRef.value)\n        return\n      const { value } = valueRef\n      updateHoverKey(value)\n      updateKeyboardKey(value)\n    }\n    function handleMouseMove(): void {\n      if (!useHoverTriggerRef.value)\n        return\n      handleMouseEnter()\n    }\n    function handleCheckboxUpdateValue(): void {\n      const { value: isLeaf } = isLeafRef\n      if (!isLeaf)\n        toggleCheckbox()\n    }\n    function toggleCheckbox(): void {\n      const { value: multiple } = multipleRef\n      const { value } = valueRef\n      if (multiple) {\n        if (indeterminateRef.value || checkedRef.value) {\n          doUncheck(value)\n        }\n        else {\n          doCheck(value)\n        }\n      }\n      else {\n        doCheck(value)\n        closeMenu(true)\n      }\n    }\n    return {\n      checkStrategy: mergedCheckStrategyRef,\n      multiple: multipleRef,\n      cascade: cascadeRef,\n      checked: checkedRef,\n      indeterminate: indeterminateRef,\n      hoverPending: hoverPendingRef,\n      keyboardPending: keyboardPendingRef,\n      isLoading: isLoadingRef,\n      showCheckbox: showCheckboxRef,\n      isLeaf: isLeafRef,\n      disabled: disabledRef,\n      label: labelRef,\n      mergedClsPrefix: mergedClsPrefixRef,\n      mergedTheme: mergedThemeRef,\n      spinProps: spinPropsRef,\n      handleClick,\n      handleCheckboxUpdateValue,\n      mergedHandleMouseEnter: mergedHandleMouseEnterRef,\n      mergedHandleMouseMove: mergedHandleMouseMoveRef,\n      renderLabel: renderLabelRef,\n      renderPrefix: renderPrefixRef,\n      renderSuffix: renderSuffixRef\n    }\n  },\n  render() {\n    const {\n      mergedClsPrefix,\n      showCheckbox,\n      renderLabel,\n      renderPrefix,\n      renderSuffix\n    } = this\n\n    let prefixNode: VNode | null = null\n    if (showCheckbox || renderPrefix) {\n      const originalNode = this.showCheckbox ? (\n        <NCheckbox\n          focusable={false}\n          data-checkbox\n          disabled={this.disabled}\n          checked={this.checked}\n          indeterminate={this.indeterminate}\n          theme={this.mergedTheme.peers.Checkbox}\n          themeOverrides={this.mergedTheme.peerOverrides.Checkbox}\n          onUpdateChecked={this.handleCheckboxUpdateValue}\n        />\n      ) : null\n      prefixNode = (\n        <div class={`${mergedClsPrefix}-cascader-option__prefix`}>\n          {renderPrefix\n            ? renderPrefix({\n                option: this.tmNode.rawNode,\n                checked: this.checked,\n                node: originalNode\n              })\n            : originalNode}\n        </div>\n      )\n    }\n    let suffixNode: VNode | null = null\n    const originalSuffixChild = (\n      <div class={`${mergedClsPrefix}-cascader-option-icon-placeholder`}>\n        {!this.isLeaf ? (\n          <NBaseLoading\n            clsPrefix={mergedClsPrefix}\n            scale={0.85}\n            strokeWidth={24}\n            show={this.isLoading}\n            class={`${mergedClsPrefix}-cascader-option-icon`}\n            {...this.spinProps}\n          >\n            {{\n              default: () => (\n                <NBaseIcon\n                  clsPrefix={mergedClsPrefix}\n                  key=\"arrow\"\n                  class={`${mergedClsPrefix}-cascader-option-icon ${mergedClsPrefix}-cascader-option-icon--arrow`}\n                >\n                  {{\n                    default: () => <ChevronRightIcon />\n                  }}\n                </NBaseIcon>\n              )\n            }}\n          </NBaseLoading>\n        ) : this.checkStrategy === 'child'\n          && !(this.multiple && this.cascade) ? (\n              <Transition name=\"fade-in-scale-up-transition\">\n                {{\n                  default: () =>\n                    this.checked ? (\n                      <NBaseIcon\n                        clsPrefix={mergedClsPrefix}\n                        class={`${mergedClsPrefix}-cascader-option-icon ${mergedClsPrefix}-cascader-option-icon--checkmark`}\n                      >\n                        {{ default: () => <CheckmarkIcon /> }}\n                      </NBaseIcon>\n                    ) : null\n                }}\n              </Transition>\n            ) : null}\n      </div>\n    )\n    suffixNode = (\n      <div class={`${mergedClsPrefix}-cascader-option__suffix`}>\n        {renderSuffix\n          ? renderSuffix({\n              option: this.tmNode.rawNode,\n              checked: this.checked,\n              node: originalSuffixChild\n            })\n          : originalSuffixChild}\n      </div>\n    )\n    return (\n      <div\n        class={[\n          `${mergedClsPrefix}-cascader-option`,\n          this.keyboardPending\n          || (this.hoverPending\n            && `${mergedClsPrefix}-cascader-option--pending`),\n          this.disabled && `${mergedClsPrefix}-cascader-option--disabled`,\n          this.showCheckbox && `${mergedClsPrefix}-cascader-option--show-prefix`\n        ]}\n        onMouseenter={this.mergedHandleMouseEnter}\n        onMousemove={this.mergedHandleMouseMove}\n        onClick={this.handleClick}\n      >\n        {prefixNode}\n        <span class={`${mergedClsPrefix}-cascader-option__label`}>\n          {renderLabel\n            ? renderLabel(this.tmNode.rawNode, this.checked)\n            : this.label}\n        </span>\n        {suffixNode}\n      </div>\n    )\n  }\n})\n"
  },
  {
    "path": "src/cascader/src/CascaderSelectMenu.tsx",
    "content": "import type { TreeNode } from 'treemate'\nimport type { PropType } from 'vue'\nimport type { InternalSelectMenuRef } from '../../_internal'\nimport type {\n  SelectBaseOption,\n  SelectGroupOption,\n  SelectIgnoredOption\n} from '../../select/src/interface'\nimport type {\n  CascaderOption,\n  Filter,\n  SelectMenuInstance,\n  TmNode,\n  Value\n} from './interface'\nimport { createTreeMate } from 'treemate'\nimport { clickoutside } from 'vdirs'\nimport {\n  computed,\n  defineComponent,\n  h,\n  inject,\n  ref,\n  Transition,\n  withDirectives\n} from 'vue'\nimport { NInternalSelectMenu } from '../../_internal'\nimport { resolveSlot } from '../../_utils'\nimport { createTmOptions } from '../../select/src/utils'\nimport { cascaderInjectionKey } from './interface'\nimport { createSelectOptions } from './utils'\n\nexport default defineComponent({\n  name: 'NCascaderSelectMenu',\n  props: {\n    value: {\n      type: [String, Number, Array] as PropType<Value | null>,\n      default: null\n    },\n    show: Boolean,\n    pattern: {\n      type: String,\n      default: ''\n    },\n    multiple: Boolean,\n    tmNodes: {\n      type: Array as PropType<TmNode[]>,\n      default: () => []\n    },\n    filter: Function as PropType<Filter>,\n    labelField: {\n      type: String,\n      required: true\n    },\n    separator: {\n      type: String,\n      required: true\n    }\n  },\n  setup(props) {\n    const {\n      isMountedRef,\n      mergedValueRef,\n      mergedClsPrefixRef,\n      mergedThemeRef,\n      mergedCheckStrategyRef,\n      slots: cascaderSlots,\n      syncSelectMenuPosition,\n      closeMenu,\n      handleSelectMenuClickOutside,\n      doUncheck: cascaderDoUncheck,\n      doCheck: cascaderDoCheck,\n      scrollbarPropsRef,\n      clearPattern\n    } = inject(cascaderInjectionKey)!\n    const menuInstRef = ref<InternalSelectMenuRef | null>(null)\n    const selectOptionsRef = computed(() => {\n      return createSelectOptions(\n        props.tmNodes,\n        mergedCheckStrategyRef.value === 'child',\n        props.labelField,\n        props.separator\n      )\n    })\n    const mergedFilterRef = computed(() => {\n      const { filter } = props\n      if (filter)\n        return filter\n      const { labelField } = props\n      return (pattern: string, _: CascaderOption, path: CascaderOption[]) =>\n        path.some(\n          option =>\n            option[labelField]\n            && ~(option[labelField] as any)\n              .toLowerCase()\n              .indexOf(pattern.toLowerCase())\n        )\n    })\n    const filteredSelectOptionsRef = computed(() => {\n      const { pattern } = props\n      const { value: mergedFilter } = mergedFilterRef\n      return (\n        pattern\n          ? selectOptionsRef.value.filter((option) => {\n              return mergedFilter(pattern, option.rawNode, option.path)\n            })\n          : selectOptionsRef.value\n      ).map(option => ({\n        value: option.value,\n        label: option.label\n      }))\n    })\n    const selectTreeMateRef = computed(() => {\n      return createTreeMate<\n        SelectBaseOption,\n        SelectGroupOption,\n        SelectIgnoredOption\n      >(filteredSelectOptionsRef.value, createTmOptions('value', 'children'))\n    })\n    function handleResize(): void {\n      syncSelectMenuPosition()\n    }\n    function handleToggle(tmNode: TreeNode<SelectBaseOption>): void {\n      doCheck(tmNode)\n    }\n    // We don't care what type the tmNode is, we only care about its key\n    function doCheck(tmNode: TreeNode<SelectBaseOption>): void {\n      if (props.multiple) {\n        const { value: mergedValue } = mergedValueRef\n        if (Array.isArray(mergedValue)) {\n          if (!mergedValue.includes(tmNode.key)) {\n            cascaderDoCheck(tmNode.key)\n          }\n          else {\n            cascaderDoUncheck(tmNode.key)\n          }\n        }\n        else if (mergedValue === null) {\n          cascaderDoCheck(tmNode.key)\n        }\n        clearPattern()\n      }\n      else {\n        cascaderDoCheck(tmNode.key)\n        // currently the select menu is set to focusable\n        // however just leave it here\n        closeMenu(true)\n      }\n    }\n    function prev(): void {\n      menuInstRef.value?.prev()\n    }\n    function next(): void {\n      menuInstRef.value?.next()\n    }\n    function enter(): boolean {\n      if (menuInstRef) {\n        const pendingOptionTmNode = menuInstRef.value?.getPendingTmNode()\n        if (pendingOptionTmNode) {\n          doCheck(pendingOptionTmNode)\n        }\n        return true\n      }\n      return false\n    }\n    function handleClickOutside(e: MouseEvent): void {\n      handleSelectMenuClickOutside(e)\n    }\n    const exposedRef: SelectMenuInstance = {\n      prev,\n      next,\n      enter\n    }\n    return {\n      isMounted: isMountedRef,\n      mergedTheme: mergedThemeRef,\n      mergedClsPrefix: mergedClsPrefixRef,\n      menuInstRef,\n      selectTreeMate: selectTreeMateRef,\n      handleResize,\n      handleToggle,\n      handleClickOutside,\n      cascaderSlots,\n      scrollbarProps: scrollbarPropsRef,\n      ...exposedRef\n    }\n  },\n  render() {\n    const { mergedClsPrefix, isMounted, mergedTheme, cascaderSlots } = this\n    return (\n      <Transition name=\"fade-in-scale-up-transition\" appear={isMounted}>\n        {{\n          default: () =>\n            this.show\n              ? withDirectives(\n                  <NInternalSelectMenu\n                    ref=\"menuInstRef\"\n                    onResize={this.handleResize}\n                    clsPrefix={mergedClsPrefix}\n                    class={`${mergedClsPrefix}-cascader-menu`}\n                    autoPending\n                    themeOverrides={\n                      mergedTheme.peerOverrides.InternalSelectMenu\n                    }\n                    theme={mergedTheme.peers.InternalSelectMenu}\n                    treeMate={this.selectTreeMate}\n                    multiple={this.multiple}\n                    value={this.value}\n                    onToggle={this.handleToggle}\n                    scrollbarProps={this.scrollbarProps}\n                  >\n                    {{\n                      empty: () =>\n                        resolveSlot(cascaderSlots['not-found'], () => [])\n                    }}\n                  </NInternalSelectMenu>,\n                  [\n                    [\n                      clickoutside,\n                      this.handleClickOutside,\n                      undefined as unknown as string,\n                      { capture: true }\n                    ]\n                  ]\n                )\n              : null\n        }}\n      </Transition>\n    )\n  }\n})\n"
  },
  {
    "path": "src/cascader/src/CascaderSubmenu.tsx",
    "content": "import type { PropType } from 'vue'\nimport type { VirtualListInst } from 'vueuc'\nimport type { ScrollbarInst } from '../../_internal'\nimport type { CascaderSubmenuInstance, TmNode } from './interface'\nimport { depx } from 'seemly'\nimport { computed, defineComponent, h, inject, ref } from 'vue'\nimport { VirtualList } from 'vueuc'\nimport { NScrollbar } from '../../_internal'\nimport NCascaderOption from './CascaderOption'\nimport { cascaderInjectionKey } from './interface'\n\nexport default defineComponent({\n  name: 'CascaderSubmenu',\n  props: {\n    depth: {\n      type: Number,\n      required: true\n    },\n    tmNodes: {\n      type: Array as PropType<TmNode[]>,\n      required: true\n    }\n  },\n  setup() {\n    const {\n      virtualScrollRef,\n      mergedClsPrefixRef,\n      mergedThemeRef,\n      optionHeightRef\n    } = inject(cascaderInjectionKey)!\n    const scrollbarInstRef = ref<ScrollbarInst | null>(null)\n    const vlInstRef = ref<VirtualListInst | null>(null)\n    const inst: CascaderSubmenuInstance = {\n      scroll(index: number, elSize: number) {\n        if (virtualScrollRef.value) {\n          vlInstRef.value?.scrollTo({\n            index\n          })\n        }\n        else {\n          scrollbarInstRef.value?.scrollTo({\n            index,\n            elSize\n          })\n        }\n      }\n    }\n    return {\n      mergedClsPrefix: mergedClsPrefixRef,\n      mergedTheme: mergedThemeRef,\n      scrollbarInstRef,\n      vlInstRef,\n      virtualScroll: virtualScrollRef,\n      itemSize: computed(() => depx(optionHeightRef.value)),\n      handleVlScroll: () => {\n        scrollbarInstRef.value?.sync()\n      },\n      getVlContainer: () => {\n        return vlInstRef.value?.listElRef\n      },\n      getVlContent: () => {\n        return vlInstRef.value?.itemsElRef\n      },\n      ...inst\n    }\n  },\n  render() {\n    const { mergedClsPrefix, mergedTheme, virtualScroll } = this\n    return (\n      <div\n        class={[\n          virtualScroll && `${mergedClsPrefix}-cascader-submenu--virtual`,\n          `${mergedClsPrefix}-cascader-submenu`\n        ]}\n      >\n        <NScrollbar\n          ref=\"scrollbarInstRef\"\n          theme={mergedTheme.peers.Scrollbar}\n          themeOverrides={mergedTheme.peerOverrides.Scrollbar}\n          container={virtualScroll ? this.getVlContainer : undefined}\n          content={virtualScroll ? this.getVlContent : undefined}\n        >\n          {{\n            default: () =>\n              virtualScroll ? (\n                <VirtualList\n                  items={this.tmNodes}\n                  itemSize={this.itemSize}\n                  onScroll={this.handleVlScroll}\n                  showScrollbar={false}\n                  ref=\"vlInstRef\"\n                >\n                  {{\n                    default: ({ item: tmNode }: { item: TmNode }) => (\n                      <NCascaderOption key={tmNode.key} tmNode={tmNode} />\n                    )\n                  }}\n                </VirtualList>\n              ) : (\n                this.tmNodes.map(tmNode => (\n                  <NCascaderOption key={tmNode.key} tmNode={tmNode} />\n                ))\n              )\n          }}\n        </NScrollbar>\n      </div>\n    )\n  }\n})\n"
  },
  {
    "path": "src/cascader/src/interface.ts",
    "content": "import type { CheckStrategy, TreeNode } from 'treemate'\nimport type { CSSProperties, Ref, Slots, VNode, VNodeChild } from 'vue'\nimport type { ScrollbarProps } from '../../_internal'\nimport type { MergedTheme } from '../../_mixins'\nimport type { NLocale } from '../../locales'\nimport type { CascaderTheme } from '../styles'\nimport type { CascaderSpinProps } from './public-types'\nimport { createInjectionKey } from '../../_utils'\n\nexport type ValueAtom = string | number\nexport type Value = ValueAtom | ValueAtom[]\n\nexport type Key = ValueAtom\n\nexport interface CascaderOption {\n  label?: string\n  value?: ValueAtom\n  disabled?: boolean\n  children?: CascaderOption[]\n  [key: string]: unknown\n}\n\nexport type ExpandTrigger = 'hover' | 'click'\n\nexport type TmNode = TreeNode<CascaderOption>\n\nexport type Filter = (\n  pattern: string,\n  option: CascaderOption,\n  path: CascaderOption[]\n) => boolean\n\nexport type OnLoad = (option: CascaderOption) => Promise<void>\n\nexport type OnUpdateValue = (\n  value: string\n    & number\n    & string[]\n    & number[]\n    & Array<string | number>\n    & (string | null)\n    & (number | null)\n    & (string[] | null)\n    & (number[] | null)\n    & (Array<string | number> | null),\n  option: null\n    & CascaderOption\n    & CascaderOption[]\n    & Array<CascaderOption | null>,\n  path: null & CascaderOption[] & Array<CascaderOption[] | null>\n) => void\n\nexport type OnUpdateValueImpl = (\n  value: Value | null,\n  option: CascaderOption | null | Array<CascaderOption | null>,\n  path: Array<CascaderOption[] | null> | CascaderOption[] | null\n) => void\n\nexport type MenuModel = TmNode[][]\n\nexport interface CascaderInjection {\n  slots: Slots\n  mergedClsPrefixRef: Ref<string>\n  mergedThemeRef: Ref<MergedTheme<CascaderTheme>>\n  mergedValueRef: Ref<Value | null>\n  checkedKeysRef: Ref<Key[]>\n  indeterminateKeysRef: Ref<Key[]>\n  hoverKeyPathRef: Ref<Key[]>\n  mergedCheckStrategyRef: Ref<CheckStrategy>\n  multipleRef: Ref<boolean>\n  keyboardKeyRef: Ref<Key | null>\n  hoverKeyRef: Ref<Key | null>\n  remoteRef: Ref<boolean>\n  loadingKeySetRef: Ref<Set<Key>>\n  expandTriggerRef: Ref<ExpandTrigger>\n  isMountedRef: Ref<boolean>\n  cascadeRef: Ref<boolean>\n  onLoadRef: Ref<((value: CascaderOption) => Promise<void>) | undefined>\n  localeRef: Ref<NLocale['Cascader']>\n  virtualScrollRef: Ref<boolean>\n  optionHeightRef: Ref<string>\n  labelFieldRef: Ref<string>\n  showCheckboxRef: Ref<boolean>\n  getColumnStyleRef: Ref<\n    ((detail: { level: number }) => string | CSSProperties) | undefined\n  >\n  renderPrefixRef: Ref<\n    | ((info: {\n      option: CascaderOption\n      checked: boolean\n      node: VNode | null\n    }) => VNodeChild)\n    | undefined\n  >\n  renderSuffixRef: Ref<\n    | ((info: {\n      option: CascaderOption\n      checked: boolean\n      node: VNode | null\n    }) => VNodeChild)\n    | undefined\n  >\n  syncCascaderMenuPosition: () => void\n  syncSelectMenuPosition: () => void\n  updateKeyboardKey: (value: Key | null) => void\n  updateHoverKey: (value: Key | null) => void\n  addLoadingKey: (value: Key) => void\n  deleteLoadingKey: (value: Key) => void\n  doCheck: (value: Key) => void\n  doUncheck: (value: Key) => void\n  closeMenu: (returnFocus?: boolean) => void\n  handleSelectMenuClickOutside: (e: MouseEvent) => void\n  handleCascaderMenuClickOutside: (e: MouseEvent) => void\n  renderLabelRef: Ref<\n    ((option: CascaderOption, checked: boolean) => VNodeChild) | undefined\n  >\n  spinPropsRef: Ref<CascaderSpinProps | undefined>\n  scrollbarPropsRef: Ref<ScrollbarProps | undefined>\n  clearPattern: () => void\n}\n\nexport interface CascaderSubmenuInstance {\n  scroll: (index: number, elSize: number) => void\n}\n\nexport interface CascaderMenuExposedMethods {\n  scroll: (depth: number, index: number, elSize: number) => void\n  showErrorMessage: (label: string) => void\n}\n\nexport type CascaderMenuInstance = {\n  $el: HTMLElement\n} & CascaderMenuExposedMethods\n\nexport interface SelectMenuInstance {\n  prev: () => void\n  next: () => void\n  enter: () => boolean\n}\n\nexport const cascaderInjectionKey\n  = createInjectionKey<CascaderInjection>('n-cascader')\n\nexport interface CascaderInst {\n  focus: () => void\n  blur: () => void\n  getCheckedData: () => { keys: Key[], options: Array<CascaderOption | null> }\n  getIndeterminateData: () => {\n    keys: Key[]\n    options: Array<CascaderOption | null>\n  }\n}\n"
  },
  {
    "path": "src/cascader/src/public-types.ts",
    "content": "import type { SharedSpinProps } from '../../_internal'\n\nexport type CascaderSize = 'small' | 'medium' | 'large'\nexport type CascaderSpinProps = SharedSpinProps\n"
  },
  {
    "path": "src/cascader/src/styles/index.cssr.ts",
    "content": "import { fadeInScaleUpTransition } from '../../../_styles/transitions/fade-in-scale-up.cssr'\nimport { c, cB, cE, cM } from '../../../_utils/cssr'\n\n// vars:\n// --n-menu-border-radius\n// --n-menu-box-shadow\n// --n-menu-height\n// --n-menu-color\n// --n-menu-divider-color\n// --n-option-height\n// --n-option-font-size\n// --n-option-text-color\n// --n-option-text-color-disabled\n// --n-option-text-color-active\n// --n-option-color-hover\n// --n-option-check-mark-color\n// --n-option-arrow-color\n// --n-menu-mask-color\n// --n-loading-color\nexport default c([\n  cB('cascader-menu', `\n    outline: none;\n    position: relative;\n    margin: 4px 0;\n    display: flex;\n    flex-flow: column nowrap;\n    border-radius: var(--n-menu-border-radius);\n    overflow: hidden;\n    box-shadow: var(--n-menu-box-shadow);\n    color: var(--n-option-text-color);\n    background-color: var(--n-menu-color);\n  `, [\n    fadeInScaleUpTransition({ transformOrigin: 'inherit', duration: '0.2s' }),\n    cE('empty', `\n      display: flex;\n      padding: 12px 32px;\n      flex: 1;\n      justify-content: center;\n    `),\n    // if width not set, cascader select menu's inner scroll area's width is\n    // not correct, which won't change after select menu width is set\n    cB('scrollbar', `\n      width: 100%;\n    `),\n    cB('base-menu-mask', `\n      background-color: var(--n-menu-mask-color);\n    `),\n    cB('base-loading', `\n      color: var(--n-loading-color);\n    `),\n    cB('cascader-submenu-wrapper', `\n      position: relative;\n      display: flex;\n      flex-wrap: nowrap;\n    `),\n    cB('cascader-submenu', `\n      height: var(--n-menu-height);\n      min-width: var(--n-column-width);\n      position: relative;\n    `, [\n      cM('virtual', `\n        width: var(--n-column-width);\n      `),\n      cB('scrollbar-content', `\n        position: relative;\n      `),\n      c('&:first-child', `\n        border-top-left-radius: var(--n-menu-border-radius);\n        border-bottom-left-radius: var(--n-menu-border-radius);\n      `),\n      c('&:last-child', `\n        border-top-right-radius: var(--n-menu-border-radius);\n        border-bottom-right-radius: var(--n-menu-border-radius);\n      `),\n      c('&:not(:first-child)', `\n        border-left: 1px solid var(--n-menu-divider-color);\n      `)\n    ]),\n    cB('cascader-menu-action', `\n      box-sizing: border-box;\n      padding: 8px;\n      border-top: 1px solid var(--n-menu-divider-color);\n    `),\n    cB('cascader-option', `\n      height: var(--n-option-height);\n      line-height: var(--n-option-height);\n      font-size: var(--n-option-font-size);\n      padding: 0 0 0 18px;\n      box-sizing: border-box;\n      min-width: 182px;\n      background-color: #0000;\n      display: flex;\n      align-items: center;\n      white-space: nowrap;\n      position: relative;\n      cursor: pointer;\n      transition:\n        background-color .2s var(--n-bezier),\n        color 0.2s var(--n-bezier);\n    `, [\n      cM('show-prefix', `\n        padding-left: 0;\n      `),\n      cE('label', `\n        flex: 1 0 0;\n        overflow: hidden;\n        text-overflow: ellipsis;\n      `),\n      cE('prefix', `\n        min-width: 32px;\n        display: flex;\n        align-items: center;\n        justify-content: center;\n      `),\n      cE('suffix', `\n        min-width: 32px;\n        display: flex;\n        align-items: center;\n        justify-content: center;\n      `),\n      cB('cascader-option-icon-placeholder', `\n        line-height: 0;\n        position: relative;\n        width: 16px;\n        height: 16px;\n        font-size: 16px;\n      `, [\n        cB('cascader-option-icon', [\n          cM('checkmark', `\n            color: var(--n-option-check-mark-color);\n          `, [\n            fadeInScaleUpTransition({\n              originalTransition: 'background-color .3s var(--n-bezier), box-shadow .3s var(--n-bezier)'\n            })\n          ]),\n          cM('arrow', `\n            color: var(--n-option-arrow-color);\n          `)\n        ])\n      ]),\n      cM('selected', `\n        color: var(--n-option-text-color-active);\n      `),\n      cM('active', `\n        color: var(--n-option-text-color-active);\n        background-color: var(--n-option-color-hover);\n      `),\n      cM('pending', `\n        background-color: var(--n-option-color-hover);\n      `),\n      c('&:hover', `\n        background-color: var(--n-option-color-hover);\n      `),\n      cM('disabled', `\n        color: var(--n-option-text-color-disabled);\n        background-color: #0000;\n        cursor: not-allowed;\n      `, [\n        cB('cascader-option-icon', [\n          cM('arrow', `\n            color: var(--n-option-text-color-disabled);\n          `)\n        ])\n      ])\n    ])\n  ]),\n  cB('cascader', `\n    z-index: auto;\n    position: relative;\n    width: 100%;\n  `)\n])\n"
  },
  {
    "path": "src/cascader/src/utils.ts",
    "content": "import type { SelectBaseOption } from '../../select/src/interface'\nimport type { CascaderOption, TmNode } from './interface'\n\nfunction getRawNodePath(tmNodes: TmNode[]): CascaderOption[]\nfunction getRawNodePath(tmNodes: TmNode[] | undefined): CascaderOption[] | null\nfunction getRawNodePath(\n  tmNodes: TmNode[] | undefined\n): CascaderOption[] | null {\n  if (!tmNodes)\n    return null\n  return tmNodes.map(tmNode => tmNode.rawNode)\n}\n\nexport { getRawNodePath }\n\nfunction createSelectOptions(\n  tmNodes: TmNode[],\n  checkStrategyIsChild: boolean,\n  labelField: string,\n  separator: string\n): Array<\n  SelectBaseOption & { rawNode: CascaderOption, path: CascaderOption[] }\n> {\n  const selectOptions: Array<\n    SelectBaseOption & { rawNode: CascaderOption, path: CascaderOption[] }\n  > = []\n  const path: CascaderOption[] = []\n  function traverse(_tmNodes: TmNode[]): void {\n    for (const tmNode of _tmNodes) {\n      if (tmNode.disabled)\n        continue\n      const { rawNode } = tmNode\n      path.push(rawNode)\n      if (tmNode.isLeaf || !checkStrategyIsChild) {\n        selectOptions.push({\n          label: getPathLabel(tmNode, separator, labelField),\n          value: tmNode.key,\n          rawNode: tmNode.rawNode,\n          path: Array.from(path)\n        })\n      }\n      if (!tmNode.isLeaf && tmNode.children) {\n        traverse(tmNode.children)\n      }\n      path.pop()\n    }\n  }\n  traverse(tmNodes)\n  return selectOptions\n}\n\nfunction getPathLabel(\n  node: TmNode | null,\n  separator: string,\n  labelField: string\n): string {\n  const path: string[] = []\n  while (node) {\n    path.push((node.rawNode as any)[labelField] as string)\n    node = node.parent\n  }\n  return path.reverse().join(separator)\n}\n\nexport { createSelectOptions, getPathLabel }\n"
  },
  {
    "path": "src/cascader/styles/dark.ts",
    "content": "import type { CascaderTheme } from './light'\nimport { scrollbarDark } from '../../_internal/scrollbar/styles'\nimport { internalSelectMenuDark } from '../../_internal/select-menu/styles'\nimport { internalSelectionDark } from '../../_internal/selection/styles'\nimport { commonDark } from '../../_styles/common'\nimport { checkboxDark } from '../../checkbox/styles'\nimport { emptyLight } from '../../empty/styles'\nimport { self } from './light'\n\nconst cascaderDark: CascaderTheme = {\n  name: 'Cascader',\n  common: commonDark,\n  peers: {\n    InternalSelectMenu: internalSelectMenuDark,\n    InternalSelection: internalSelectionDark,\n    Scrollbar: scrollbarDark,\n    Checkbox: checkboxDark,\n    Empty: emptyLight\n  },\n  self\n}\n\nexport default cascaderDark\n"
  },
  {
    "path": "src/cascader/styles/index.ts",
    "content": "export { default as cascaderDark } from './dark'\nexport { default as cascaderLight } from './light'\nexport type { CascaderTheme, CascaderThemeVars } from './light'\n"
  },
  {
    "path": "src/cascader/styles/light.ts",
    "content": "import type { ThemeCommonVars } from '../../_styles/common'\nimport { scrollbarLight } from '../../_internal/scrollbar/styles'\nimport { internalSelectMenuLight } from '../../_internal/select-menu/styles'\nimport { internalSelectionLight } from '../../_internal/selection/styles'\nimport { createTheme } from '../../_mixins'\nimport { commonLight } from '../../_styles/common'\nimport { checkboxLight } from '../../checkbox/styles'\nimport { emptyLight } from '../../empty/styles'\n\nexport function self(vars: ThemeCommonVars) {\n  const {\n    borderRadius,\n    boxShadow2,\n    popoverColor,\n    textColor2,\n    textColor3,\n    primaryColor,\n    textColorDisabled,\n    dividerColor,\n    hoverColor,\n    fontSizeMedium,\n    heightMedium\n  } = vars\n  return {\n    menuBorderRadius: borderRadius,\n    menuColor: popoverColor,\n    menuBoxShadow: boxShadow2,\n    menuDividerColor: dividerColor,\n    menuHeight: 'calc(var(--n-option-height) * 6.6)',\n    optionArrowColor: textColor3,\n    optionHeight: heightMedium,\n    optionFontSize: fontSizeMedium,\n    optionColorHover: hoverColor,\n    optionTextColor: textColor2,\n    optionTextColorActive: primaryColor,\n    optionTextColorDisabled: textColorDisabled,\n    optionCheckMarkColor: primaryColor,\n    loadingColor: primaryColor,\n    columnWidth: '180px'\n  }\n}\n\nexport type CascaderThemeVars = ReturnType<typeof self>\n\nconst cascaderLight = createTheme({\n  name: 'Cascader',\n  common: commonLight,\n  peers: {\n    InternalSelectMenu: internalSelectMenuLight,\n    InternalSelection: internalSelectionLight,\n    Scrollbar: scrollbarLight,\n    Checkbox: checkboxLight,\n    Empty: emptyLight\n  },\n  self\n})\n\nexport default cascaderLight\nexport type CascaderTheme = typeof cascaderLight\n"
  },
  {
    "path": "src/cascader/tests/Cascader.spec.ts",
    "content": "import type { CascaderOption } from '../src/interface'\nimport { mount } from '@vue/test-utils'\nimport { nextTick } from 'vue'\nimport { NCascader } from '../index'\n\nfunction getOptions(depth = 3, iterator = 1, prefix = ''): CascaderOption[] {\n  const length = 12\n  const options: CascaderOption[] = []\n  for (let i = 1; i <= length; ++i) {\n    if (iterator === 1) {\n      options.push({\n        value: `v-${i}`,\n        label: `l-${i}`,\n        disabled: i % 5 === 0,\n        children: getOptions(depth, iterator + 1, `${String(i)}`)\n      })\n    }\n    else if (iterator === depth) {\n      options.push({\n        value: `v-${prefix}-${i}`,\n        label: `l-${prefix}-${i}`,\n        disabled: i % 5 === 0\n      })\n    }\n    else {\n      options.push({\n        value: `v-${prefix}-${i}`,\n        label: `l-${prefix}-${i}`,\n        disabled: i % 5 === 0,\n        children: getOptions(depth, iterator + 1, `${prefix}-${i}`)\n      })\n    }\n  }\n  return options\n}\n\ndescribe('n-cascader', () => {\n  it('should work with import on demand', () => {\n    mount(NCascader)\n  })\n\n  it('should work with `disabled` prop', async () => {\n    const wrapper = mount(NCascader)\n    expect(wrapper.find('.n-base-selection').classes()).not.toContain(\n      'n-base-selection--disabled'\n    )\n\n    await wrapper.setProps({ disabled: true })\n    expect(wrapper.find('.n-base-selection').classes()).toContain(\n      'n-base-selection--disabled'\n    )\n    wrapper.unmount()\n  })\n\n  it('should work with `size` prop', async () => {\n    ;(['small', 'medium', 'large'] as const).forEach((i) => {\n      const wrapper = mount(NCascader, { props: { size: i } })\n      expect(\n        wrapper.find('.n-base-selection').attributes('style')\n      ).toMatchSnapshot()\n      wrapper.unmount()\n    })\n  })\n\n  it('should work with `status` prop', async () => {\n    ;(['success', 'warning', 'error'] as const).forEach((status) => {\n      const wrapper = mount(NCascader, { props: { status } })\n      expect(wrapper.find('.n-base-selection').classes()).toContain(\n        `n-base-selection--${status}-status`\n      )\n      wrapper.unmount()\n    })\n  })\n\n  it('should work with `placeholder` prop', async () => {\n    const wrapper = mount(NCascader, {\n      props: { placeholder: 'test-placeholder' }\n    })\n    expect(wrapper.find('.n-base-selection-placeholder').text()).toBe(\n      'test-placeholder'\n    )\n    wrapper.unmount()\n  })\n\n  it('should work with `placement` prop', async () => {\n    const placements = [\n      'top-start',\n      'top',\n      'top-end',\n      'right-start',\n      'right',\n      'right-end',\n      'bottom-start',\n      'bottom',\n      'bottom-end',\n      'left-start',\n      'left',\n      'left-end'\n    ] as const\n\n    for (const placement of placements) {\n      const wrapper = mount(NCascader, {\n        attachTo: document.body,\n        props: {\n          placement,\n          show: true\n        }\n      })\n\n      await nextTick()\n\n      await vi.waitFor(() => {\n        const followerContents = document.querySelectorAll(\n          '.v-binder-follower-content'\n        )\n        const currentFollower = followerContents.item(\n          followerContents.length - 1\n        )\n\n        expect(currentFollower.getAttribute('v-placement')).toBe(placement)\n      })\n      wrapper.unmount()\n      await nextTick()\n    }\n  })\n\n  it('should work with `filterable` prop', async () => {\n    const wrapper = mount(NCascader, {\n      props: { filterable: false }\n    })\n    expect(wrapper.find('input').exists()).not.toBe(true)\n\n    await wrapper.setProps({ filterable: true })\n    expect(wrapper.find('input').exists()).toBe(true)\n    wrapper.unmount()\n  })\n\n  it('should work with `default-value` prop', async () => {\n    const wrapper = mount(NCascader, {\n      props: { options: getOptions(), defaultValue: 'l-1-1-2' }\n    })\n    expect(wrapper.find('.n-base-selection-input').text()).toBe('l-1-1-2')\n    wrapper.unmount()\n  })\n\n  it('should work with `multiple` prop', async () => {\n    const wrapper = mount(NCascader, {\n      props: { options: getOptions() }\n    })\n    expect(wrapper.find('.n-base-selection-label').exists()).toBe(true)\n    expect(wrapper.find('.n-base-selection-tags').exists()).not.toBe(true)\n\n    await wrapper.setProps({ multiple: true })\n\n    expect(wrapper.find('.n-base-selection-tags').exists()).toBe(true)\n    expect(wrapper.find('.n-base-selection-label').exists()).not.toBe(true)\n    wrapper.unmount()\n  })\n\n  it('should work with `label-field` `value-field` `children-field` props', async () => {\n    const wrapper = mount(NCascader, {\n      props: {\n        options: [\n          {\n            whateverLabel: 'Rubber Soul',\n            whateverValue: 'Rubber Soul',\n            whateverChildren: [\n              {\n                whateverLabel:\n                  'Everybody\\'s Got Something to Hide Except Me and My Monkey',\n                whateverValue:\n                  'Everybody\\'s Got Something to Hide Except Me and My Monkey'\n              }\n            ]\n          }\n        ],\n        'label-field': 'whateverLabel',\n        'value-field': 'whateverValue',\n        'children-field': 'whateverChildren',\n        'default-value':\n          'Everybody\\'s Got Something to Hide Except Me and My Monkey'\n      }\n    })\n    expect(wrapper.find('.n-base-selection-label').text()).toBe(\n      'Rubber Soul / Everybody\\'s Got Something to Hide Except Me and My Monkey'\n    )\n    wrapper.unmount()\n  })\n\n  it('should work with `check-strategy=child`', async () => {\n    const wrapper = mount(NCascader, {\n      attachTo: document.body,\n      props: { options: getOptions(), virtualScroll: false }\n    })\n    await wrapper.setProps({ show: true })\n\n    expect(document.querySelector('.n-checkbox')).not.toEqual(null)\n\n    await wrapper.setProps({ checkStrategy: 'child' })\n\n    expect(document.querySelector('.n-checkbox')).toEqual(null)\n    wrapper.unmount()\n  })\n\n  it('should work with `on-blur` prop', async () => {\n    const onBlur = vi.fn()\n    const wrapper = mount(NCascader, {\n      props: { options: getOptions(), onBlur }\n    })\n    await wrapper.find('.n-base-selection').trigger('focusout')\n    expect(onBlur).toHaveBeenCalled()\n    wrapper.unmount()\n  })\n\n  it('should work with `on-focus` prop', async () => {\n    const onFocus = vi.fn()\n    const wrapper = mount(NCascader, {\n      props: { options: getOptions(), onFocus }\n    })\n    await wrapper.find('.n-base-selection').trigger('focusin')\n    expect(onFocus).toHaveBeenCalled()\n    wrapper.unmount()\n  })\n\n  it('should be active after clicked', async () => {\n    const wrapper = mount(NCascader, {\n      attachTo: document.body,\n      props: {\n        options: getOptions()\n      }\n    })\n\n    const selection = wrapper.find('.n-base-selection')\n\n    await selection.trigger('click')\n    expect(selection.classes()).toContain('n-base-selection--active')\n\n    expect(document.querySelector('.n-cascader-menu')).not.toEqual(null)\n\n    await selection.trigger('click')\n    expect(selection.classes()).not.toContain('n-base-selection--active')\n    expect(document.querySelector('.n-cascader-menu')).toEqual(null)\n    wrapper.unmount()\n  })\n\n  it('should be active after click outside', async () => {\n    const mousedownEvent = new MouseEvent('mousedown', { bubbles: true })\n    const mouseupEvent = new MouseEvent('mouseup', { bubbles: true })\n    const wrapper = mount(NCascader, {\n      attachTo: document.body,\n      props: {\n        options: getOptions()\n      }\n    })\n\n    await wrapper.find('.n-base-selection').trigger('click')\n    expect(document.querySelector('.n-cascader-menu')).not.toEqual(null)\n    document.body.click()\n    document.body.dispatchEvent(mousedownEvent)\n    document.body.dispatchEvent(mouseupEvent)\n    await nextTick()\n    expect(document.querySelector('.n-cascader-menu')).toEqual(null)\n    wrapper.unmount()\n  })\n})\n"
  },
  {
    "path": "src/cascader/tests/__snapshots__/Cascader.spec.ts.snap",
    "content": "// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html\n\nexports[`n-cascader > should work with \\`size\\` prop 1`] = `\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-border: 1px solid rgb(224, 224, 230); --n-border-active: 1px solid #18a058; --n-border-focus: 1px solid #36ad6a; --n-border-hover: 1px solid #36ad6a; --n-border-radius: 3px; --n-box-shadow-active: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-box-shadow-hover: none; --n-caret-color: #18a058; --n-color: rgba(255, 255, 255, 1); --n-color-active: rgba(255, 255, 255, 1); --n-color-disabled: rgb(250, 250, 252); --n-font-size: 14px; --n-height: 28px; --n-padding-single-top: 0; --n-padding-multiple-top: 3px; --n-padding-single-right: 26px; --n-padding-multiple-right: 26px; --n-padding-single-left: 12px; --n-padding-multiple-left: 12px; --n-padding-single-bottom: 0; --n-padding-multiple-bottom: 0; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-text-color: rgb(51, 54, 57); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-arrow-color: rgba(194, 194, 194, 1); --n-arrow-color-disabled: rgba(209, 209, 209, 1); --n-loading-color: #18a058; --n-color-active-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-box-shadow-active-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-box-shadow-hover-warning: none; --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-border-active-warning: 1px solid #f0a020; --n-color-active-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-box-shadow-active-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-box-shadow-hover-error: none; --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-border-active-error: 1px solid #d03050; --n-clear-size: 16px; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-arrow-size: 16px; --n-font-weight: 400;\"`;\n\nexports[`n-cascader > should work with \\`size\\` prop 2`] = `\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-border: 1px solid rgb(224, 224, 230); --n-border-active: 1px solid #18a058; --n-border-focus: 1px solid #36ad6a; --n-border-hover: 1px solid #36ad6a; --n-border-radius: 3px; --n-box-shadow-active: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-box-shadow-hover: none; --n-caret-color: #18a058; --n-color: rgba(255, 255, 255, 1); --n-color-active: rgba(255, 255, 255, 1); --n-color-disabled: rgb(250, 250, 252); --n-font-size: 14px; --n-height: 34px; --n-padding-single-top: 0; --n-padding-multiple-top: 3px; --n-padding-single-right: 26px; --n-padding-multiple-right: 26px; --n-padding-single-left: 12px; --n-padding-multiple-left: 12px; --n-padding-single-bottom: 0; --n-padding-multiple-bottom: 0; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-text-color: rgb(51, 54, 57); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-arrow-color: rgba(194, 194, 194, 1); --n-arrow-color-disabled: rgba(209, 209, 209, 1); --n-loading-color: #18a058; --n-color-active-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-box-shadow-active-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-box-shadow-hover-warning: none; --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-border-active-warning: 1px solid #f0a020; --n-color-active-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-box-shadow-active-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-box-shadow-hover-error: none; --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-border-active-error: 1px solid #d03050; --n-clear-size: 16px; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-arrow-size: 16px; --n-font-weight: 400;\"`;\n\nexports[`n-cascader > should work with \\`size\\` prop 3`] = `\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-border: 1px solid rgb(224, 224, 230); --n-border-active: 1px solid #18a058; --n-border-focus: 1px solid #36ad6a; --n-border-hover: 1px solid #36ad6a; --n-border-radius: 3px; --n-box-shadow-active: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-box-shadow-hover: none; --n-caret-color: #18a058; --n-color: rgba(255, 255, 255, 1); --n-color-active: rgba(255, 255, 255, 1); --n-color-disabled: rgb(250, 250, 252); --n-font-size: 15px; --n-height: 40px; --n-padding-single-top: 0; --n-padding-multiple-top: 3px; --n-padding-single-right: 26px; --n-padding-multiple-right: 26px; --n-padding-single-left: 12px; --n-padding-multiple-left: 12px; --n-padding-single-bottom: 0; --n-padding-multiple-bottom: 0; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-text-color: rgb(51, 54, 57); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-arrow-color: rgba(194, 194, 194, 1); --n-arrow-color-disabled: rgba(209, 209, 209, 1); --n-loading-color: #18a058; --n-color-active-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-box-shadow-active-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-box-shadow-hover-warning: none; --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-border-active-warning: 1px solid #f0a020; --n-color-active-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-box-shadow-active-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-box-shadow-hover-error: none; --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-border-active-error: 1px solid #d03050; --n-clear-size: 16px; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-arrow-size: 16px; --n-font-weight: 400;\"`;\n"
  },
  {
    "path": "src/cascader/tests/server.spec.tsx",
    "content": "import { setup } from '@css-render/vue3-ssr'\nimport { renderToString } from '@vue/server-renderer'\n/**\n * @vitest-environment node\n */\nimport { createSSRApp, h } from 'vue'\nimport { NCascader } from '../..'\n\ndescribe('server side rendering', () => {\n  it('works', async () => {\n    const app = createSSRApp(() => <NCascader />)\n    setup(app)\n    try {\n      await renderToString(app)\n    }\n    catch (e) {\n      expect(e).not.toBeTruthy()\n    }\n  })\n})\n"
  },
  {
    "path": "src/checkbox/demos/enUS/basic.demo.vue",
    "content": "<markdown>\n# Basic\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst value = ref(false)\nconst disabled = ref(true)\n</script>\n\n<template>\n  <n-space item-style=\"display: flex;\" align=\"center\">\n    <n-checkbox v-model:checked=\"value\">\n      Checkbox\n    </n-checkbox>\n    <n-checkbox v-model:checked=\"value\" />\n    <n-checkbox v-model:checked=\"value\" :disabled=\"disabled\">\n      Checkbox\n    </n-checkbox>\n    <n-button size=\"small\" @click=\"disabled = !disabled\">\n      Disabled\n    </n-button>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/checkbox/demos/enUS/controlled.demo.vue",
    "content": "<markdown>\n# Controlled checkbox\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst value = ref(false)\n</script>\n\n<template>\n  <n-space align=\"center\" item-style=\"display: flex;\">\n    <n-checkbox :checked=\"value\">\n      Checkbox\n    </n-checkbox>\n    <n-switch v-model:value=\"value\" />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/checkbox/demos/enUS/customize-value.demo.vue",
    "content": "<markdown>\n# Customizing checked value\n\nUse `checked-value` and `unchecked-value` to customize value.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { useMessage } from 'naive-ui'\n\nconst message = useMessage()\nfunction handleUpdateChecked(value: boolean) {\n  message.info(String(value))\n}\n</script>\n\n<template>\n  <n-checkbox\n    checked-value=\"Foo\"\n    unchecked-value=\"Bar\"\n    @update:checked=\"handleUpdateChecked\"\n  >\n    FooBar\n  </n-checkbox>\n</template>\n"
  },
  {
    "path": "src/checkbox/demos/enUS/event.demo.vue",
    "content": "<markdown>\n# Event\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { useMessage } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst checkedRef = ref(false)\nconst citiesRef = ref<(string | number)[] | null>(null)\nconst message = useMessage()\n\nfunction handleCheckedChange(checked: boolean) {\n  checkedRef.value = checked\n  message.info(JSON.stringify(checked))\n}\n\nfunction handleUpdateValue(value: (string | number)[]) {\n  citiesRef.value = value\n  message.info(JSON.stringify(value))\n}\n</script>\n\n<template>\n  <n-space item-style=\"display: flex;\" vertical>\n    <n-checkbox\n      v-model:checked=\"checkedRef\"\n      label=\"Event\"\n      @update:checked=\"handleCheckedChange\"\n    />\n    <n-checkbox-group\n      v-model:value=\"citiesRef\"\n      @update:value=\"handleUpdateValue\"\n    >\n      <n-space item-style=\"display: flex;\" align=\"center\">\n        <n-checkbox value=\"Beijing\" label=\"Beijing\" />\n        <n-checkbox value=\"Shanghai\" label=\"Shanghai\" />\n        <n-checkbox value=\"Guangzhou\" label=\"Guangzhou\" />\n        <n-checkbox value=\"Shenzhen\" label=\"Shenzhen\" />\n      </n-space>\n    </n-checkbox-group>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/checkbox/demos/enUS/focus.demo.vue",
    "content": "<markdown>\n# Focus & blur manually\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { CheckboxInst } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst checkboxInstRef = ref<CheckboxInst | null>(null)\n\nfunction handleClick() {\n  checkboxInstRef.value?.focus()\n  setTimeout(() => {\n    checkboxInstRef.value?.blur()\n  }, 1000)\n}\n</script>\n\n<template>\n  <n-space item-style=\"display: flex; align-items: center;\">\n    <n-button @click=\"handleClick\">\n      Focus then blur in 1 second\n    </n-button>\n    <n-checkbox ref=\"checkboxInstRef\" />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/checkbox/demos/enUS/grid.demo.vue",
    "content": "<markdown>\n# Grid\n\nUse checkboxes with a grid.\n</markdown>\n\n<template>\n  <n-checkbox-group>\n    <n-grid :y-gap=\"8\" :cols=\"2\">\n      <n-gi>\n        <n-checkbox value=\"Pushes Open\" label=\"Pushes Open\" />\n      </n-gi>\n      <n-gi>\n        <n-checkbox value=\"The Window\" label=\"The Window\" />\n      </n-gi>\n      <n-gi>\n        <n-checkbox value=\"And Raises\" label=\"And Raises\" />\n      </n-gi>\n      <n-gi>\n        <n-checkbox value=\"The Spyglass\" label=\"The Spyglass\" />\n      </n-gi>\n    </n-grid>\n  </n-checkbox-group>\n</template>\n"
  },
  {
    "path": "src/checkbox/demos/enUS/group.demo.vue",
    "content": "<markdown>\n# Checkbox group\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst cities = ref(null)\n</script>\n\n<template>\n  <n-checkbox-group v-model:value=\"cities\">\n    <n-space item-style=\"display: flex;\">\n      <n-checkbox value=\"Beijing\" label=\"Beijing\" />\n      <n-checkbox value=\"Shanghai\" label=\"Shanghai\" />\n      <n-checkbox value=\"Guangzhou\" label=\"Guangzhou\" />\n      <n-checkbox value=\"Shenzhen\" label=\"Shenzhen\" />\n    </n-space>\n  </n-checkbox-group>\n</template>\n"
  },
  {
    "path": "src/checkbox/demos/enUS/indeterminate.demo.vue",
    "content": "<markdown>\n# Indeterminate\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst value = ref(false)\nconst indeterminate = ref(false)\n</script>\n\n<template>\n  <n-space item-style=\"display: flex;\" align=\"center\">\n    <n-checkbox v-model:checked=\"value\" :indeterminate=\"indeterminate\">\n      Checkbox\n    </n-checkbox>\n    <n-checkbox v-model:checked=\"value\" :indeterminate=\"indeterminate\" />\n    <n-checkbox\n      v-model:checked=\"value\"\n      :indeterminate=\"indeterminate\"\n      disabled\n    />\n    <n-switch v-model:value=\"value\">\n      <template #checked>\n        checked\n      </template>\n      <template #unchecked>\n        Unchecked\n      </template>\n    </n-switch>\n    <n-switch v-model:value=\"indeterminate\">\n      <template #checked>\n        Indeterminate\n      </template>\n      <template #unchecked>\n        Not indeterminate\n      </template>\n    </n-switch>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/checkbox/demos/enUS/index.demo-entry.md",
    "content": "# Checkbox\n\nYo, yo, check it out.\n\n## Demos\n\n```demo\nbasic.vue\nsize.vue\ngroup.vue\ngrid.vue\nindeterminate.vue\ncontrolled.vue\nevent.vue\ncustomize-value.vue\nfocus.vue\n```\n\n## API\n\n### Checkbox Props\n\n| Name | Type | Default | Description |\n| --- | --- | --- | --- |\n| checked | `boolean` | `false` | Whether the checkbox is being checked manually. |\n| checked-value | `string \\| boolean \\| number` | `true` | Value of checked state. |\n| default-checked | `boolean` | `false` | Whether the checkbox is checked by default. |\n| disabled | `boolean` | `false` | Whether the checkbox is disabled. |\n| focusable | `boolean` | `true` | Whether the checkbox gains focus after being checked. |\n| indeterminate | `boolean` | `false` | Whether the checkbox can have a third indeterminate state. |\n| label | `string` | `undefined` | Checkbox label. |\n| size | `'small' \\| 'medium' \\| 'large'` | `'medium'` | The size of the checkbox. |\n| unchecked-value | `string \\| boolean \\| number` | `false` | Value of unchecked state. |\n| value | `string \\| number` | `undefined` | The value of the checkbox to be used in a checkbox group. |\n| on-update:checked | `(checked: boolean) => void` | `undefined` | Callback function triggered on a checked status change. |\n\n### CheckboxGroup Props\n\n| Name | Type | Default | Description | Version |\n| --- | --- | --- | --- | --- |\n| disabled | `boolean` | `false` | Whether the checkbox group is disabled. |  |\n| default-value | `Array<string \\| number>` | `null` | Checkbox group's default selected value. |  |\n| max | `number` | `undefined` | The maximum number of checkboxes that can be checked. |  |\n| min | `number` | `undefined` | The minimum number of checkboxes that can be checked. |  |\n| value | `Array<string \\| number> \\| null` | `undefined` | Manually set values of a checkbox group. |  |\n| on-update:value | `(value: (string \\| number)[], meta: { actionType: 'check' \\| 'uncheck', value: string \\| number }) => void` | `undefined` | Callback when the checkbox group's value changes. | `meta` 2.32.0 |\n\n### Checkbox Slots\n\n| Name    | Parameters | Description              |\n| ------- | ---------- | ------------------------ |\n| default | `()`       | Content of the checkbox. |\n\n### CheckboxGroup Slots\n\n| Name    | Parameters | Description                    |\n| ------- | ---------- | ------------------------------ |\n| default | `()`       | Content of the checkbox group. |\n\n### Checkbox Methods\n\n| Name  | Type         | Description | Version |\n| ----- | ------------ | ----------- | ------- |\n| focus | `() => void` | Focus.      | 2.24.2  |\n| blur  | `() => void` | Blur.       | 2.24.2  |\n"
  },
  {
    "path": "src/checkbox/demos/enUS/size.demo.vue",
    "content": "<markdown>\n# Size\n</markdown>\n\n<template>\n  <n-space item-style=\"display: flex;\" align=\"center\">\n    <n-checkbox size=\"small\" label=\"small\" />\n    <n-checkbox size=\"medium\" label=\"medium\" />\n    <n-checkbox size=\"large\" label=\"large\" />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/checkbox/demos/zhCN/basic.demo.vue",
    "content": "<markdown>\n# 基础用法\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst value = ref(false)\nconst disabled = ref(true)\n</script>\n\n<template>\n  <n-space item-style=\"display: flex;\" align=\"center\">\n    <n-checkbox v-model:checked=\"value\">\n      复选框\n    </n-checkbox>\n    <n-checkbox v-model:checked=\"value\" />\n    <n-checkbox v-model:checked=\"value\" :disabled=\"disabled\">\n      复选框\n    </n-checkbox>\n    <n-button size=\"small\" @click=\"disabled = !disabled\">\n      禁用\n    </n-button>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/checkbox/demos/zhCN/controlled.demo.vue",
    "content": "<markdown>\n# 受控状态\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst value = ref(false)\n</script>\n\n<template>\n  <n-space align=\"center\" item-style=\"display: flex;\">\n    <n-checkbox :checked=\"value\">\n      复选框\n    </n-checkbox>\n    <n-switch v-model:value=\"value\" />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/checkbox/demos/zhCN/customize-value.demo.vue",
    "content": "<markdown>\n# 自定义选中的值\n\n使用 `checked-value` 和 `unchecked-value` 制定选中的值。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { useMessage } from 'naive-ui'\n\nconst message = useMessage()\nfunction handleUpdateChecked(value: boolean) {\n  message.info(String(value))\n}\n</script>\n\n<template>\n  <n-checkbox\n    checked-value=\"周末加班\"\n    unchecked-value=\"周末支持一下\"\n    @update:checked=\"handleUpdateChecked\"\n  >\n    抉择时刻\n  </n-checkbox>\n</template>\n"
  },
  {
    "path": "src/checkbox/demos/zhCN/event.demo.vue",
    "content": "<markdown>\n# 事件\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { useMessage } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst checkedRef = ref(false)\nconst citiesRef = ref<(string | number)[] | null>(null)\nconst message = useMessage()\n\nfunction handleCheckedChange(checked: boolean) {\n  checkedRef.value = checked\n  message.info(JSON.stringify(checked))\n}\n\nfunction handleUpdateValue(value: (string | number)[]) {\n  citiesRef.value = value\n  message.info(JSON.stringify(value))\n}\n</script>\n\n<template>\n  <n-space item-style=\"display: flex;\" vertical>\n    <n-checkbox\n      :checked=\"checkedRef\"\n      label=\"事件\"\n      @update:checked=\"handleCheckedChange\"\n    />\n    <n-checkbox-group :value=\"citiesRef\" @update:value=\"handleUpdateValue\">\n      <n-space item-style=\"display: flex;\" align=\"center\">\n        <n-checkbox value=\"Beijing\" label=\"北京\" />\n        <n-checkbox value=\"Shanghai\" label=\"上海\" />\n        <n-checkbox value=\"Guangzhou\" label=\"广州\" />\n        <n-checkbox value=\"Shenzhen\" label=\"深圳\" />\n      </n-space>\n    </n-checkbox-group>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/checkbox/demos/zhCN/focus.demo.vue",
    "content": "<markdown>\n# 手动 focus & blur\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { CheckboxInst } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst checkboxInstRef = ref<CheckboxInst | null>(null)\n\nfunction handleClick() {\n  checkboxInstRef.value?.focus()\n  setTimeout(() => {\n    checkboxInstRef.value?.blur()\n  }, 1000)\n}\n</script>\n\n<template>\n  <n-space item-style=\"display: flex; align-items: center;\">\n    <n-button @click=\"handleClick\">\n      聚焦，一秒后失效\n    </n-button>\n    <n-checkbox ref=\"checkboxInstRef\" />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/checkbox/demos/zhCN/grid.demo.vue",
    "content": "<markdown>\n# 栅格\n\n和栅格一起使用。\n</markdown>\n\n<template>\n  <n-checkbox-group>\n    <n-grid :y-gap=\"8\" :cols=\"2\">\n      <n-gi>\n        <n-checkbox value=\"Pushes Open\" label=\"推开\" />\n      </n-gi>\n      <n-gi>\n        <n-checkbox value=\"The Window\" label=\"窗户\" />\n      </n-gi>\n      <n-gi>\n        <n-checkbox value=\"And Raises\" label=\"举起\" />\n      </n-gi>\n      <n-gi>\n        <n-checkbox value=\"The Spyglass\" label=\"望远镜\" />\n      </n-gi>\n    </n-grid>\n  </n-checkbox-group>\n</template>\n"
  },
  {
    "path": "src/checkbox/demos/zhCN/group.demo.vue",
    "content": "<markdown>\n# 选项组\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst cities = ref(null)\n</script>\n\n<template>\n  <n-checkbox-group v-model:value=\"cities\">\n    <n-space item-style=\"display: flex;\">\n      <n-checkbox value=\"Beijing\" label=\"北京\" />\n      <n-checkbox value=\"Shanghai\" label=\"上海\" />\n      <n-checkbox value=\"Guangzhou\" label=\"广州\" />\n      <n-checkbox value=\"Shenzhen\" label=\"深圳\" />\n    </n-space>\n  </n-checkbox-group>\n</template>\n"
  },
  {
    "path": "src/checkbox/demos/zhCN/indeterminate.demo.vue",
    "content": "<markdown>\n# 部分选中\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst value = ref(false)\nconst indeterminate = ref(false)\n</script>\n\n<template>\n  <n-space item-style=\"display: flex;\" align=\"center\">\n    <n-checkbox v-model:checked=\"value\" :indeterminate=\"indeterminate\">\n      复选框\n    </n-checkbox>\n    <n-checkbox v-model:checked=\"value\" :indeterminate=\"indeterminate\" />\n    <n-checkbox\n      v-model:checked=\"value\"\n      :indeterminate=\"indeterminate\"\n      disabled\n    />\n    <n-switch v-model:value=\"value\">\n      <template #checked>\n        选中\n      </template>\n      <template #unchecked>\n        没选中\n      </template>\n    </n-switch>\n    <n-switch v-model:value=\"indeterminate\">\n      <template #checked>\n        部分选中\n      </template>\n      <template #unchecked>\n        非部分选中\n      </template>\n    </n-switch>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/checkbox/demos/zhCN/index.demo-entry.md",
    "content": "# 复选框 Checkbox\n\n哟，哟，Check it out。\n\n## 演示\n\n```demo\nbasic.vue\nsize.vue\ngroup.vue\ngrid.vue\nindeterminate.vue\ncontrolled.vue\nevent.vue\ncustomize-value.vue\nfocus.vue\nrtl-debug.vue\n```\n\n## API\n\n### Checkbox Props\n\n| 名称 | 类型 | 默认值 | 说明 |\n| --- | --- | --- | --- |\n| checked | `boolean` | `false` | 受控状态下是否选中 |\n| checked-value | `string \\| boolean \\| number` | `true` | 选中时对应的值 |\n| default-checked | `boolean` | `false` | 非受控模式下默认是否选中 |\n| disabled | `boolean` | `false` | 是否禁用 |\n| focusable | `boolean` | `true` | 是否可被 focus |\n| indeterminate | `boolean` | `false` | 是否部分选中 |\n| label | `string` | `undefined` | Checkbox 的标签 |\n| size | `'small' \\| 'medium' \\| 'large'` | `'medium'` | 组件尺寸 |\n| unchecked-value | `string \\| boolean \\| number` | `false` | 未选中时对应的值 |\n| value | `string \\| number` | `undefined` | Checkbox 在 checkbox group 中使用的值 |\n| on-update:checked | `(checked: boolean) => void` | `undefined` | 当 checked 改变时触发的回调函数 |\n\n### CheckboxGroup Props\n\n| 名称 | 类型 | 默认值 | 说明 | 版本 |\n| --- | --- | --- | --- | --- |\n| disabled | `boolean` | `false` | 选项组是否禁用 |  |\n| default-value | `Array<string \\| number>` | `null` | 选项组非受控模式下的默认值 |  |\n| max | `number` | `undefined` | 可被勾选的 checkbox 的最大数量 |  |\n| min | `number` | `undefined` | 可被勾选的 checkbox 的最小数量 |  |\n| value | `Array<string \\| number> \\| null` | `undefined` | 选项组受控模式下的值 |  |\n| on-update:value | `(value: (string \\| number)[], meta: { actionType: 'check' \\| 'uncheck', value: string \\| number }) => void` | `undefined` | 选项组的值改变时的回调 | `meta` 2.32.0 |\n\n### Checkbox Slots\n\n| 名称    | 参数 | 说明                |\n| ------- | ---- | ------------------- |\n| default | `()` | Checkbox 的标签内容 |\n\n### CheckboxGroup Slots\n\n| 名称    | 参数 | 说明                 |\n| ------- | ---- | -------------------- |\n| default | `()` | CheckboxGroup 的内容 |\n\n### Checkbox Methods\n\n| 名称  | 类型         | 说明 | 版本   |\n| ----- | ------------ | ---- | ------ |\n| focus | `() => void` | 聚焦 | 2.24.2 |\n| blur  | `() => void` | 失焦 | 2.24.2 |\n"
  },
  {
    "path": "src/checkbox/demos/zhCN/rtl-debug.demo.vue",
    "content": "<markdown>\n# Rtl Debug\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { unstableCheckboxRtl } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst value = ref(false)\nconst rtlEnabled = ref(false)\nconst rtlStyles = [unstableCheckboxRtl]\n</script>\n\n<template>\n  <n-space vertical>\n    <n-space><n-switch v-model:value=\"rtlEnabled\" />Rtl</n-space>\n    <n-config-provider :rtl=\"rtlEnabled ? rtlStyles : undefined\">\n      <n-checkbox v-model:checked=\"value\">\n        复选框\n      </n-checkbox>\n    </n-config-provider>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/checkbox/demos/zhCN/size.demo.vue",
    "content": "<markdown>\n# 尺寸\n</markdown>\n\n<template>\n  <n-space item-style=\"display: flex;\" align=\"center\">\n    <n-checkbox size=\"small\" label=\"小\" />\n    <n-checkbox size=\"medium\" label=\"中\" />\n    <n-checkbox size=\"large\" label=\"大\" />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/checkbox/index.ts",
    "content": "export { checkboxProps, default as NCheckbox } from './src/Checkbox'\nexport type { CheckboxProps } from './src/Checkbox'\nexport {\n  checkboxGroupProps,\n  default as NCheckboxGroup\n} from './src/CheckboxGroup'\nexport type { CheckboxGroupProps } from './src/CheckboxGroup'\nexport type { CheckboxInst } from './src/interface'\nexport type * from './src/public-types'\n"
  },
  {
    "path": "src/checkbox/src/CheckMark.tsx",
    "content": "import type { VNode } from 'vue'\nimport { h } from 'vue'\n\nexport default (): VNode => (\n  <svg viewBox=\"0 0 64 64\" class=\"check-icon\">\n    <path d=\"M50.42,16.76L22.34,39.45l-8.1-11.46c-1.12-1.58-3.3-1.96-4.88-0.84c-1.58,1.12-1.95,3.3-0.84,4.88l10.26,14.51  c0.56,0.79,1.42,1.31,2.38,1.45c0.16,0.02,0.32,0.03,0.48,0.03c0.8,0,1.57-0.27,2.2-0.78l30.99-25.03c1.5-1.21,1.74-3.42,0.52-4.92  C54.13,15.78,51.93,15.55,50.42,16.76z\" />\n  </svg>\n)\n"
  },
  {
    "path": "src/checkbox/src/Checkbox.tsx",
    "content": "import type { CSSProperties, PropType } from 'vue'\nimport type { ThemeProps } from '../../_mixins'\nimport type { ExtractPublicPropTypes, MaybeArray } from '../../_utils'\nimport type { CheckboxTheme } from '../styles'\nimport type {\n  CheckboxInst,\n  OnUpdateChecked,\n  OnUpdateCheckedImpl\n} from './interface'\nimport type { CheckboxSize } from './public-types'\nimport { on } from 'evtd'\nimport { createId } from 'seemly'\nimport { useMemo, useMergedState } from 'vooks'\nimport {\n  computed,\n  defineComponent,\n  h,\n  inject,\n  ref,\n  toRef,\n  watchEffect\n} from 'vue'\nimport { NIconSwitchTransition } from '../../_internal'\nimport { useConfig, useFormItem, useTheme, useThemeClass } from '../../_mixins'\nimport { useRtl } from '../../_mixins/use-rtl'\nimport { call, createKey, resolveWrappedSlot, warnOnce } from '../../_utils'\nimport { checkboxLight } from '../styles'\nimport { checkboxGroupInjectionKey } from './CheckboxGroup'\nimport renderCheckMark from './CheckMark'\nimport renderLineMark from './LineMark'\nimport style from './styles/index.cssr'\n\nexport const checkboxProps = {\n  ...(useTheme.props as ThemeProps<CheckboxTheme>),\n  size: String as PropType<CheckboxSize>,\n  checked: {\n    type: [Boolean, String, Number] as PropType<\n      boolean | string | number | undefined\n    >,\n    default: undefined\n  },\n  defaultChecked: {\n    type: [Boolean, String, Number] as PropType<boolean | string | number>,\n    default: false\n  },\n  value: [String, Number] as PropType<string | number>,\n  disabled: {\n    type: Boolean as PropType<boolean | undefined>,\n    default: undefined\n  },\n  indeterminate: Boolean,\n  label: String,\n  focusable: {\n    type: Boolean,\n    default: true\n  },\n  checkedValue: {\n    type: [Boolean, String, Number],\n    default: true\n  },\n  uncheckedValue: {\n    type: [Boolean, String, Number],\n    default: false\n  },\n  'onUpdate:checked': [Function, Array] as PropType<\n    MaybeArray<OnUpdateChecked>\n  >,\n  onUpdateChecked: [Function, Array] as PropType<MaybeArray<OnUpdateChecked>>,\n  // private\n  privateInsideTable: Boolean,\n  // deprecated\n  onChange: [Function, Array] as PropType<MaybeArray<OnUpdateChecked>>\n}\n\nexport type CheckboxProps = ExtractPublicPropTypes<typeof checkboxProps>\n\nexport default defineComponent({\n  name: 'Checkbox',\n  props: checkboxProps,\n  setup(props) {\n    if (__DEV__) {\n      watchEffect(() => {\n        if (props.onChange) {\n          warnOnce(\n            'checkbox',\n            '`on-change` is deprecated, please use `on-update:checked` instead.'\n          )\n        }\n      })\n    }\n    const NCheckboxGroup = inject(checkboxGroupInjectionKey, null)\n    const selfRef = ref<HTMLDivElement | null>(null)\n    const {\n      mergedClsPrefixRef,\n      inlineThemeDisabled,\n      mergedRtlRef,\n      mergedComponentPropsRef\n    } = useConfig(props)\n    const uncontrolledCheckedRef = ref(props.defaultChecked)\n    const controlledCheckedRef = toRef(props, 'checked')\n    const mergedCheckedRef = useMergedState(\n      controlledCheckedRef,\n      uncontrolledCheckedRef\n    )\n    const renderedCheckedRef = useMemo(() => {\n      if (NCheckboxGroup) {\n        const groupValueSet = NCheckboxGroup.valueSetRef.value\n        if (groupValueSet && props.value !== undefined) {\n          return groupValueSet.has(props.value)\n        }\n        return false\n      }\n      else {\n        return mergedCheckedRef.value === props.checkedValue\n      }\n    })\n    const formItem = useFormItem(props, {\n      mergedSize(NFormItem) {\n        const { size } = props\n        if (size !== undefined)\n          return size\n        if (NCheckboxGroup) {\n          const { value: mergedSize } = NCheckboxGroup.mergedSizeRef\n          if (mergedSize !== undefined) {\n            return mergedSize\n          }\n        }\n        if (NFormItem) {\n          const { mergedSize } = NFormItem\n          if (mergedSize !== undefined)\n            return mergedSize.value\n        }\n        const configSize = mergedComponentPropsRef?.value?.Checkbox?.size\n        if (configSize)\n          return configSize\n        return 'medium'\n      },\n      mergedDisabled(NFormItem) {\n        const { disabled } = props\n        if (disabled !== undefined)\n          return disabled\n        if (NCheckboxGroup) {\n          if (NCheckboxGroup.disabledRef.value)\n            return true\n          const {\n            maxRef: { value: max },\n            checkedCountRef\n          } = NCheckboxGroup\n          if (\n            max !== undefined\n            && checkedCountRef.value >= max\n            && !renderedCheckedRef.value\n          ) {\n            return true\n          }\n          const {\n            minRef: { value: min }\n          } = NCheckboxGroup\n          if (\n            min !== undefined\n            && checkedCountRef.value <= min\n            && renderedCheckedRef.value\n          ) {\n            return true\n          }\n        }\n        if (NFormItem) {\n          return NFormItem.disabled.value\n        }\n        return false\n      }\n    })\n    const { mergedDisabledRef, mergedSizeRef } = formItem\n    const themeRef = useTheme(\n      'Checkbox',\n      '-checkbox',\n      style,\n      checkboxLight,\n      props,\n      mergedClsPrefixRef\n    )\n    function toggle(e: MouseEvent | KeyboardEvent): void {\n      if (NCheckboxGroup && props.value !== undefined) {\n        NCheckboxGroup.toggleCheckbox(!renderedCheckedRef.value, props.value)\n      }\n      else {\n        const {\n          onChange,\n          'onUpdate:checked': _onUpdateCheck,\n          onUpdateChecked\n        } = props\n        const { nTriggerFormInput, nTriggerFormChange } = formItem\n        const nextChecked = renderedCheckedRef.value\n          ? props.uncheckedValue\n          : props.checkedValue\n        if (_onUpdateCheck) {\n          call(_onUpdateCheck as OnUpdateCheckedImpl, nextChecked, e)\n        }\n        if (onUpdateChecked) {\n          call(onUpdateChecked as OnUpdateCheckedImpl, nextChecked, e)\n        }\n        if (onChange)\n          call(onChange as OnUpdateCheckedImpl, nextChecked, e) // deprecated\n        nTriggerFormInput()\n        nTriggerFormChange()\n        uncontrolledCheckedRef.value = nextChecked\n      }\n    }\n    function handleClick(e: MouseEvent): void {\n      if (!mergedDisabledRef.value) {\n        toggle(e)\n      }\n    }\n    function handleKeyUp(e: KeyboardEvent): void {\n      if (mergedDisabledRef.value)\n        return\n      switch (e.key) {\n        case ' ':\n        case 'Enter':\n          toggle(e)\n      }\n    }\n    function handleKeyDown(e: KeyboardEvent): void {\n      switch (e.key) {\n        case ' ':\n          e.preventDefault()\n      }\n    }\n    const exposedMethods: CheckboxInst = {\n      focus: () => {\n        selfRef.value?.focus()\n      },\n      blur: () => {\n        selfRef.value?.blur()\n      }\n    }\n    const rtlEnabledRef = useRtl('Checkbox', mergedRtlRef, mergedClsPrefixRef)\n    const cssVarsRef = computed(() => {\n      const { value: mergedSize } = mergedSizeRef\n      const {\n        common: { cubicBezierEaseInOut },\n        self: {\n          borderRadius,\n          color,\n          colorChecked,\n          colorDisabled,\n          colorTableHeader,\n          colorTableHeaderModal,\n          colorTableHeaderPopover,\n          checkMarkColor,\n          checkMarkColorDisabled,\n          border,\n          borderFocus,\n          borderDisabled,\n          borderChecked,\n          boxShadowFocus,\n          textColor,\n          textColorDisabled,\n          checkMarkColorDisabledChecked,\n          colorDisabledChecked,\n          borderDisabledChecked,\n          labelPadding,\n          labelLineHeight,\n          labelFontWeight,\n          [createKey('fontSize', mergedSize)]: fontSize,\n          [createKey('size', mergedSize)]: size\n        }\n      } = themeRef.value\n      return {\n        '--n-label-line-height': labelLineHeight,\n        '--n-label-font-weight': labelFontWeight,\n        '--n-size': size,\n        '--n-bezier': cubicBezierEaseInOut,\n        '--n-border-radius': borderRadius,\n        '--n-border': border,\n        '--n-border-checked': borderChecked,\n        '--n-border-focus': borderFocus,\n        '--n-border-disabled': borderDisabled,\n        '--n-border-disabled-checked': borderDisabledChecked,\n        '--n-box-shadow-focus': boxShadowFocus,\n        '--n-color': color,\n        '--n-color-checked': colorChecked,\n        '--n-color-table': colorTableHeader,\n        '--n-color-table-modal': colorTableHeaderModal,\n        '--n-color-table-popover': colorTableHeaderPopover,\n        '--n-color-disabled': colorDisabled,\n        '--n-color-disabled-checked': colorDisabledChecked,\n        '--n-text-color': textColor,\n        '--n-text-color-disabled': textColorDisabled,\n        '--n-check-mark-color': checkMarkColor,\n        '--n-check-mark-color-disabled': checkMarkColorDisabled,\n        '--n-check-mark-color-disabled-checked': checkMarkColorDisabledChecked,\n        '--n-font-size': fontSize,\n        '--n-label-padding': labelPadding\n      }\n    })\n    const themeClassHandle = inlineThemeDisabled\n      ? useThemeClass(\n          'checkbox',\n          computed(() => mergedSizeRef.value[0]),\n          cssVarsRef,\n          props\n        )\n      : undefined\n    return Object.assign(formItem, exposedMethods, {\n      rtlEnabled: rtlEnabledRef,\n      selfRef,\n      mergedClsPrefix: mergedClsPrefixRef,\n      mergedDisabled: mergedDisabledRef,\n      renderedChecked: renderedCheckedRef,\n      mergedTheme: themeRef,\n      labelId: createId(),\n      handleClick,\n      handleKeyUp,\n      handleKeyDown,\n      cssVars: inlineThemeDisabled ? undefined : cssVarsRef,\n      themeClass: themeClassHandle?.themeClass,\n      onRender: themeClassHandle?.onRender\n    })\n  },\n  render() {\n    const {\n      $slots,\n      renderedChecked,\n      mergedDisabled,\n      indeterminate,\n      privateInsideTable,\n      cssVars,\n      labelId,\n      label,\n      mergedClsPrefix,\n      focusable,\n      handleKeyUp,\n      handleKeyDown,\n      handleClick\n    } = this\n    this.onRender?.()\n    const labelNode = resolveWrappedSlot($slots.default, (children) => {\n      if (label || children) {\n        return (\n          <span class={`${mergedClsPrefix}-checkbox__label`} id={labelId}>\n            {label || children}\n          </span>\n        )\n      }\n      return null\n    })\n    return (\n      <div\n        ref=\"selfRef\"\n        class={[\n          `${mergedClsPrefix}-checkbox`,\n          this.themeClass,\n          this.rtlEnabled && `${mergedClsPrefix}-checkbox--rtl`,\n          renderedChecked && `${mergedClsPrefix}-checkbox--checked`,\n          mergedDisabled && `${mergedClsPrefix}-checkbox--disabled`,\n          indeterminate && `${mergedClsPrefix}-checkbox--indeterminate`,\n          privateInsideTable && `${mergedClsPrefix}-checkbox--inside-table`,\n          labelNode && `${mergedClsPrefix}-checkbox--show-label`\n        ]}\n        tabindex={mergedDisabled || !focusable ? undefined : 0}\n        role=\"checkbox\"\n        aria-checked={indeterminate ? 'mixed' : renderedChecked}\n        aria-labelledby={labelId}\n        style={cssVars as CSSProperties}\n        onKeyup={handleKeyUp}\n        onKeydown={handleKeyDown}\n        onClick={handleClick}\n        onMousedown={() => {\n          on(\n            'selectstart',\n            window,\n            (e: Event): void => {\n              e.preventDefault()\n            },\n            {\n              once: true\n            }\n          )\n        }}\n      >\n        <div class={`${mergedClsPrefix}-checkbox-box-wrapper`}>\n          &nbsp;\n          <div class={`${mergedClsPrefix}-checkbox-box`}>\n            <NIconSwitchTransition>\n              {{\n                default: () =>\n                  this.indeterminate ? (\n                    <div\n                      key=\"indeterminate\"\n                      class={`${mergedClsPrefix}-checkbox-icon`}\n                    >\n                      {renderLineMark()}\n                    </div>\n                  ) : (\n                    <div key=\"check\" class={`${mergedClsPrefix}-checkbox-icon`}>\n                      {renderCheckMark()}\n                    </div>\n                  )\n              }}\n            </NIconSwitchTransition>\n            <div class={`${mergedClsPrefix}-checkbox-box__border`} />\n          </div>\n        </div>\n        {labelNode}\n      </div>\n    )\n  }\n})\n"
  },
  {
    "path": "src/checkbox/src/CheckboxGroup.tsx",
    "content": "import type { ComputedRef, PropType, Ref } from 'vue'\nimport type { ExtractPublicPropTypes, MaybeArray } from '../../_utils'\nimport { useMergedState } from 'vooks'\nimport {\n  computed,\n  defineComponent,\n  h,\n  provide,\n  ref,\n  toRef,\n  watchEffect\n} from 'vue'\nimport { useConfig, useFormItem } from '../../_mixins'\nimport { call, createInjectionKey, warnOnce } from '../../_utils'\n\nexport interface CheckboxGroupInjection {\n  checkedCountRef: ComputedRef<number>\n  maxRef: Ref<number | undefined>\n  minRef: Ref<number | undefined>\n  disabledRef: Ref<boolean>\n  valueSetRef: Ref<Set<string | number>>\n  mergedSizeRef: Ref<'small' | 'medium' | 'large'>\n  toggleCheckbox: (checked: boolean, checkboxValue: string | number) => void\n}\n\nexport const checkboxGroupInjectionKey\n  = createInjectionKey<CheckboxGroupInjection>('n-checkbox-group')\n\nexport const checkboxGroupProps = {\n  min: Number,\n  max: Number,\n  size: String as PropType<'small' | 'medium' | 'large'>,\n  value: Array as PropType<Array<string | number> | null>,\n  defaultValue: {\n    type: Array as PropType<Array<string | number> | null>,\n    default: null\n  },\n  disabled: {\n    type: Boolean as PropType<boolean | undefined>,\n    default: undefined\n  },\n  'onUpdate:value': [Function, Array] as PropType<\n    MaybeArray<\n      (\n        value: Array<string | number>,\n        meta: {\n          actionType: 'check' | 'uncheck'\n          value: string | number\n        }\n      ) => void\n    >\n  >,\n  onUpdateValue: [Function, Array] as PropType<\n    MaybeArray<\n      (\n        value: Array<string | number>,\n        meta: {\n          actionType: 'check' | 'uncheck'\n          value: string | number\n        }\n      ) => void\n    >\n  >,\n  // deprecated\n  onChange: [Function, Array] as PropType<\n    MaybeArray<(value: Array<string | number>) => void> | undefined\n  >\n} as const\n\nexport type CheckboxGroupProps = ExtractPublicPropTypes<\n  typeof checkboxGroupProps\n>\n\nexport default defineComponent({\n  name: 'CheckboxGroup',\n  props: checkboxGroupProps,\n  setup(props) {\n    if (__DEV__) {\n      watchEffect(() => {\n        if (props.onChange !== undefined) {\n          warnOnce(\n            'checkbox-group',\n            '`on-change` is deprecated, please use `on-update:value` instead.'\n          )\n        }\n      })\n    }\n    const { mergedClsPrefixRef } = useConfig(props)\n    const formItem = useFormItem(props)\n    const { mergedSizeRef, mergedDisabledRef } = formItem\n    const uncontrolledValueRef = ref(props.defaultValue)\n    const controlledValueRef = computed(() => props.value)\n    const mergedValueRef = useMergedState(\n      controlledValueRef,\n      uncontrolledValueRef\n    )\n    const checkedCount = computed(() => {\n      return mergedValueRef.value?.length || 0\n    })\n\n    const valueSetRef = computed<Set<string | number>>(() => {\n      if (Array.isArray(mergedValueRef.value)) {\n        return new Set(mergedValueRef.value)\n      }\n      return new Set()\n    })\n    function toggleCheckbox(\n      checked: boolean,\n      checkboxValue: string | number\n    ): void {\n      const { nTriggerFormInput, nTriggerFormChange } = formItem\n      const {\n        onChange,\n        'onUpdate:value': _onUpdateValue,\n        onUpdateValue\n      } = props\n\n      if (Array.isArray(mergedValueRef.value)) {\n        const groupValue = Array.from(mergedValueRef.value)\n        const index = groupValue.findIndex(value => value === checkboxValue)\n        if (checked) {\n          if (!~index) {\n            groupValue.push(checkboxValue)\n            if (onUpdateValue) {\n              call(onUpdateValue, groupValue, {\n                actionType: 'check',\n                value: checkboxValue\n              })\n            }\n            if (_onUpdateValue) {\n              call(_onUpdateValue, groupValue, {\n                actionType: 'check',\n                value: checkboxValue\n              })\n            }\n            nTriggerFormInput()\n            nTriggerFormChange()\n            uncontrolledValueRef.value = groupValue\n            // deprecated\n            if (onChange)\n              call(onChange, groupValue)\n          }\n        }\n        else {\n          if (~index) {\n            groupValue.splice(index, 1)\n            if (onUpdateValue) {\n              call(onUpdateValue, groupValue, {\n                actionType: 'uncheck',\n                value: checkboxValue\n              })\n            }\n            if (_onUpdateValue) {\n              call(_onUpdateValue, groupValue, {\n                actionType: 'uncheck',\n                value: checkboxValue\n              })\n            }\n            if (onChange)\n              call(onChange, groupValue) // deprecated\n            uncontrolledValueRef.value = groupValue\n            nTriggerFormInput()\n            nTriggerFormChange()\n          }\n        }\n      }\n      else {\n        if (checked) {\n          if (onUpdateValue) {\n            call(onUpdateValue, [checkboxValue], {\n              actionType: 'check',\n              value: checkboxValue\n            })\n          }\n          if (_onUpdateValue) {\n            call(_onUpdateValue, [checkboxValue], {\n              actionType: 'check',\n              value: checkboxValue\n            })\n          }\n          if (onChange)\n            call(onChange, [checkboxValue]) // deprecated\n          uncontrolledValueRef.value = [checkboxValue]\n          nTriggerFormInput()\n          nTriggerFormChange()\n        }\n        else {\n          if (onUpdateValue) {\n            call(onUpdateValue, [], {\n              actionType: 'uncheck',\n              value: checkboxValue\n            })\n          }\n          if (_onUpdateValue) {\n            call(_onUpdateValue, [], {\n              actionType: 'uncheck',\n              value: checkboxValue\n            })\n          }\n          if (onChange)\n            call(onChange, []) // deprecated\n          uncontrolledValueRef.value = []\n          nTriggerFormInput()\n          nTriggerFormChange()\n        }\n      }\n    }\n    provide(checkboxGroupInjectionKey, {\n      checkedCountRef: checkedCount,\n      maxRef: toRef(props, 'max'),\n      minRef: toRef(props, 'min'),\n      valueSetRef,\n      disabledRef: mergedDisabledRef,\n      mergedSizeRef,\n      toggleCheckbox\n    })\n    return {\n      mergedClsPrefix: mergedClsPrefixRef\n    }\n  },\n  render() {\n    return (\n      <div class={`${this.mergedClsPrefix}-checkbox-group`} role=\"group\">\n        {this.$slots}\n      </div>\n    )\n  }\n})\n"
  },
  {
    "path": "src/checkbox/src/LineMark.tsx",
    "content": "import type { VNode } from 'vue'\nimport { h } from 'vue'\n\nexport default (): VNode => (\n  <svg viewBox=\"0 0 100 100\" class=\"line-icon\">\n    <path d=\"M80.2,55.5H21.4c-2.8,0-5.1-2.5-5.1-5.5l0,0c0-3,2.3-5.5,5.1-5.5h58.7c2.8,0,5.1,2.5,5.1,5.5l0,0C85.2,53.1,82.9,55.5,80.2,55.5z\" />\n  </svg>\n)\n"
  },
  {
    "path": "src/checkbox/src/interface.ts",
    "content": "export type OnUpdateChecked = (\n  value: string & number & boolean,\n  e: MouseEvent | KeyboardEvent\n) => void\nexport type OnUpdateCheckedImpl = (\n  value: string | number | boolean,\n  e: MouseEvent | KeyboardEvent\n) => void\n\nexport interface CheckboxInst {\n  focus: () => void\n  blur: () => void\n}\n"
  },
  {
    "path": "src/checkbox/src/public-types.ts",
    "content": "export type CheckboxSize = 'small' | 'medium' | 'large'\n"
  },
  {
    "path": "src/checkbox/src/styles/index.cssr.ts",
    "content": "import { iconSwitchTransition } from '../../../_styles/transitions/icon-switch.cssr'\nimport { c, cB, cE, cM, insideModal, insidePopover } from '../../../_utils/cssr'\n\n// vars:\n// --n-label-line-height\n// --n-bezier\n// --n-size\n// --n-border\n// --n-border-focus\n// --n-border-checked\n// --n-border-disabled\n// --n-border-disabled-checked\n// --n-box-shadow-focus\n// --n-color\n// --n-color-checked\n// --n-color-table\n// --n-color-table-modal\n// --n-color-disabled\n// --n-color-disabled-checked\n// --n-text-color\n// --n-text-color-disabled\n// --n-check-mark-color\n// --n-check-mark-color-disabled\n// --n-check-mark-color-disabled-checked\n// --n-border-radius\n// --n-font-size\n// --n-label-padding\nexport default c([\n  cB('checkbox', `\n    font-size: var(--n-font-size);\n    outline: none;\n    cursor: pointer;\n    display: inline-flex;\n    flex-wrap: nowrap;\n    align-items: flex-start;\n    word-break: break-word;\n    line-height: var(--n-size);\n    --n-merged-color-table: var(--n-color-table);\n  `, [\n    cM('show-label', 'line-height: var(--n-label-line-height);'),\n    c('&:hover', [\n      cB('checkbox-box', [\n        cE('border', 'border: var(--n-border-checked);')\n      ])\n    ]),\n    c('&:focus:not(:active)', [\n      cB('checkbox-box', [\n        cE('border', `\n          border: var(--n-border-focus);\n          box-shadow: var(--n-box-shadow-focus);\n        `)\n      ])\n    ]),\n    cM('inside-table', [\n      cB('checkbox-box', `\n        background-color: var(--n-merged-color-table);\n      `)\n    ]),\n    cM('checked', [\n      cB('checkbox-box', `\n        background-color: var(--n-color-checked);\n      `, [\n        cB('checkbox-icon', [\n          // if not set width to 100%, safari & old chrome won't display the icon\n          c('.check-icon', `\n            opacity: 1;\n            transform: scale(1);\n          `)\n        ])\n      ])\n    ]),\n    cM('indeterminate', [\n      cB('checkbox-box', [\n        cB('checkbox-icon', [\n          c('.check-icon', `\n            opacity: 0;\n            transform: scale(.5);\n          `),\n          c('.line-icon', `\n            opacity: 1;\n            transform: scale(1);\n          `)\n        ])\n      ])\n    ]),\n    cM('checked, indeterminate', [\n      c('&:focus:not(:active)', [\n        cB('checkbox-box', [\n          cE('border', `\n            border: var(--n-border-checked);\n            box-shadow: var(--n-box-shadow-focus);\n          `)\n        ])\n      ]),\n      cB('checkbox-box', `\n        background-color: var(--n-color-checked);\n        border-left: 0;\n        border-top: 0;\n      `, [\n        cE('border', {\n          border: 'var(--n-border-checked)'\n        })\n      ])\n    ]),\n    cM('disabled', {\n      cursor: 'not-allowed'\n    }, [\n      cM('checked', [\n        cB('checkbox-box', `\n          background-color: var(--n-color-disabled-checked);\n        `, [\n          cE('border', {\n            border: 'var(--n-border-disabled-checked)'\n          }),\n          cB('checkbox-icon', [\n            c('.check-icon, .line-icon', {\n              fill: 'var(--n-check-mark-color-disabled-checked)'\n            })\n          ])\n        ])\n      ]),\n      cB('checkbox-box', `\n        background-color: var(--n-color-disabled);\n      `, [\n        cE('border', `\n          border: var(--n-border-disabled);\n        `),\n        cB('checkbox-icon', [\n          c('.check-icon, .line-icon', `\n            fill: var(--n-check-mark-color-disabled);\n          `)\n        ])\n      ]),\n      cE('label', `\n        color: var(--n-text-color-disabled);\n      `)\n    ]),\n    cB('checkbox-box-wrapper', `\n      position: relative;\n      width: var(--n-size);\n      flex-shrink: 0;\n      flex-grow: 0;\n      user-select: none;\n      -webkit-user-select: none;\n    `),\n    cB('checkbox-box', `\n      position: absolute;\n      left: 0;\n      top: 50%;\n      transform: translateY(-50%);\n      height: var(--n-size);\n      width: var(--n-size);\n      display: inline-block;\n      box-sizing: border-box;\n      border-radius: var(--n-border-radius);\n      background-color: var(--n-color);\n      transition: background-color 0.3s var(--n-bezier);\n    `, [\n      cE('border', `\n        transition:\n          border-color .3s var(--n-bezier),\n          box-shadow .3s var(--n-bezier);\n        border-radius: inherit;\n        position: absolute;\n        left: 0;\n        right: 0;\n        top: 0;\n        bottom: 0;\n        border: var(--n-border);\n      `),\n      cB('checkbox-icon', `\n        display: flex;\n        align-items: center;\n        justify-content: center;\n        position: absolute;\n        left: 1px;\n        right: 1px;\n        top: 1px;\n        bottom: 1px;\n      `, [\n        c('.check-icon, .line-icon', `\n          width: 100%;\n          fill: var(--n-check-mark-color);\n          opacity: 0;\n          transform: scale(0.5);\n          transform-origin: center;\n          transition:\n            fill 0.3s var(--n-bezier),\n            transform 0.3s var(--n-bezier),\n            opacity 0.3s var(--n-bezier),\n            border-color 0.3s var(--n-bezier);\n        `),\n        iconSwitchTransition({\n          left: '1px',\n          top: '1px'\n        })\n      ])\n    ]),\n    cE('label', `\n      color: var(--n-text-color);\n      transition: color .3s var(--n-bezier);\n      user-select: none;\n      -webkit-user-select: none;\n      padding: var(--n-label-padding);\n      font-weight: var(--n-label-font-weight);\n    `, [\n      c('&:empty', {\n        display: 'none'\n      })\n    ])\n  ]),\n  // modal table header checkbox\n  insideModal(\n    cB('checkbox', `\n      --n-merged-color-table: var(--n-color-table-modal);\n    `)\n  ),\n  // popover table header checkbox\n  insidePopover(\n    cB('checkbox', `\n      --n-merged-color-table: var(--n-color-table-popover);\n    `)\n  )\n])\n"
  },
  {
    "path": "src/checkbox/src/styles/rtl.cssr.ts",
    "content": "import { cB, cM } from '../../../_utils/cssr'\n\nexport default cB('checkbox', [\n  cM('rtl', `\n    direction: rtl;\n  `)\n])\n"
  },
  {
    "path": "src/checkbox/styles/_common.ts",
    "content": "export default {\n  sizeSmall: '14px',\n  sizeMedium: '16px',\n  sizeLarge: '18px',\n  labelPadding: '0 8px',\n  labelFontWeight: '400'\n}\n"
  },
  {
    "path": "src/checkbox/styles/dark.ts",
    "content": "import type { CheckboxTheme } from './light'\nimport { commonDark } from '../../_styles/common'\nimport { self } from './light'\n\nconst checkboxDark: CheckboxTheme = {\n  name: 'Checkbox',\n  common: commonDark,\n  self(vars) {\n    const { cardColor } = vars\n    const commonSelf = self(vars)\n    commonSelf.color = '#0000'\n    commonSelf.checkMarkColor = cardColor\n    return commonSelf\n  }\n}\n\nexport default checkboxDark\n"
  },
  {
    "path": "src/checkbox/styles/index.ts",
    "content": "export { default as checkboxDark } from './dark'\nexport { default as checkboxLight } from './light'\nexport type { CheckboxTheme, CheckboxThemeVars } from './light'\nexport { checkboxRtl } from './rtl'\n"
  },
  {
    "path": "src/checkbox/styles/light.ts",
    "content": "import type { Theme } from '../../_mixins'\nimport type { ThemeCommonVars } from '../../_styles/common'\nimport { changeColor } from 'seemly'\nimport { commonLight } from '../../_styles/common'\nimport commonVariables from './_common'\n\nexport function self(vars: ThemeCommonVars) {\n  const {\n    baseColor,\n    inputColorDisabled,\n    cardColor,\n    modalColor,\n    popoverColor,\n    textColorDisabled,\n    borderColor,\n    primaryColor,\n    textColor2,\n    fontSizeSmall,\n    fontSizeMedium,\n    fontSizeLarge,\n    borderRadiusSmall,\n    lineHeight\n  } = vars\n  return {\n    ...commonVariables,\n    labelLineHeight: lineHeight,\n    fontSizeSmall,\n    fontSizeMedium,\n    fontSizeLarge,\n    borderRadius: borderRadiusSmall,\n    color: baseColor,\n    colorChecked: primaryColor,\n    colorDisabled: inputColorDisabled,\n    colorDisabledChecked: inputColorDisabled,\n    colorTableHeader: cardColor,\n    colorTableHeaderModal: modalColor,\n    colorTableHeaderPopover: popoverColor,\n    checkMarkColor: baseColor,\n    checkMarkColorDisabled: textColorDisabled,\n    checkMarkColorDisabledChecked: textColorDisabled,\n    border: `1px solid ${borderColor}`,\n    borderDisabled: `1px solid ${borderColor}`,\n    borderDisabledChecked: `1px solid ${borderColor}`,\n    borderChecked: `1px solid ${primaryColor}`,\n    borderFocus: `1px solid ${primaryColor}`,\n    boxShadowFocus: `0 0 0 2px ${changeColor(primaryColor, { alpha: 0.3 })}`,\n    textColor: textColor2,\n    textColorDisabled\n  }\n}\n\nexport type CheckboxThemeVars = ReturnType<typeof self>\n\nconst checkboxLight: Theme<'Checkbox', CheckboxThemeVars> = {\n  name: 'Checkbox',\n  common: commonLight,\n  self\n}\n\nexport default checkboxLight\nexport type CheckboxTheme = typeof checkboxLight\n"
  },
  {
    "path": "src/checkbox/styles/rtl.ts",
    "content": "import type { RtlItem } from '../../config-provider/src/internal-interface'\nimport rtlStyle from '../src/styles/rtl.cssr'\n\nexport const checkboxRtl: RtlItem = {\n  name: 'Checkbox',\n  style: rtlStyle\n}\n"
  },
  {
    "path": "src/checkbox/tests/Checkbox.spec.tsx",
    "content": "import type { VueWrapper } from '@vue/test-utils'\nimport { mount } from '@vue/test-utils'\nimport { Fragment, h } from 'vue'\nimport { NForm, NFormItem } from '../../form'\nimport { NCheckbox, NCheckboxGroup } from '../index'\n\nfunction expectChecked(wrapper: VueWrapper<any>, value: boolean): void {\n  expect(wrapper.classes().some(c => c.includes('checked'))).toEqual(value)\n  expect(wrapper.find('.n-checkbox').attributes('aria-checked')).toBe(\n    value.toString()\n  )\n}\n\ndescribe('n-checkbox', () => {\n  it('should work with import on demand', () => {\n    mount(NCheckbox)\n  })\n\n  describe('uncontrolled mode', () => {\n    it('works', async () => {\n      const wrapper = mount(NCheckbox)\n      expectChecked(wrapper, false)\n      await wrapper.trigger('click')\n      expectChecked(wrapper, true)\n      await wrapper.trigger('click')\n      expectChecked(wrapper, false)\n      wrapper.unmount()\n    })\n    it('props.defaultChecked', () => {\n      const wrapper = mount(NCheckbox, {\n        props: {\n          defaultChecked: true\n        }\n      })\n      expectChecked(wrapper, true)\n      wrapper.unmount()\n    })\n  })\n\n  it('should work with `checked-value` prop', async () => {\n    const onUpdateChecked = vi.fn()\n    const wrapper = mount(NCheckbox, {\n      props: {\n        checkedValue: 'fooo',\n        uncheckedValue: 'barr',\n        onUpdateChecked\n      }\n    })\n    await wrapper.trigger('click')\n    expect(onUpdateChecked.mock.calls[0][0]).toEqual('fooo')\n    await wrapper.trigger('click')\n    expect(onUpdateChecked.mock.calls[1][0]).toEqual('barr')\n    await wrapper.trigger('click')\n    expect(onUpdateChecked.mock.calls[2][0]).toEqual('fooo')\n    wrapper.unmount()\n  })\n\n  it('should work with `checked-value` prop in type layer', () => {\n    const onUpdateChecked1: (value: string) => void = () => {}\n    const onUpdateChecked2: (value: number) => void = () => {}\n    const onUpdateChecked3: (value: boolean) => void = () => {}\n    <Fragment>\n      <NCheckbox\n        onUpdateChecked={onUpdateChecked1}\n        checked=\"123\"\n        defaultChecked=\"123\"\n      />\n      <NCheckbox\n        onUpdateChecked={onUpdateChecked2}\n        checked={123}\n        defaultChecked={123}\n      />\n      <NCheckbox\n        onUpdateChecked={onUpdateChecked3}\n        checked={true}\n        defaultChecked={false}\n      />\n    </Fragment>\n  })\n\n  it('should work with `indeterminate` prop', () => {\n    const wrapper = mount(NCheckbox, {\n      props: {\n        indeterminate: true\n      },\n      slots: {\n        default: () => 'test'\n      }\n    })\n    expect(wrapper.find('.n-checkbox').classes()).toContain(\n      'n-checkbox--indeterminate'\n    )\n    expect(wrapper.find('.n-checkbox').attributes('aria-checked')).toBe('mixed')\n    wrapper.unmount()\n  })\n\n  it('should work with `disabled` prop', () => {\n    const wrapper = mount(NCheckbox, {\n      props: {\n        disabled: true\n      },\n      slots: {\n        default: () => 'test'\n      }\n    })\n    expect(wrapper.find('.n-checkbox').classes()).toContain(\n      'n-checkbox--disabled'\n    )\n    wrapper.unmount()\n  })\n\n  it('should work with `focusable` prop', async () => {\n    const wrapper = mount(NCheckbox, {\n      props: {\n        focusable: false\n      },\n      slots: {\n        default: () => 'test'\n      }\n    })\n    expect(wrapper.find('[tabindex]').exists()).not.toBe(true)\n\n    await wrapper.setProps({ focusable: true })\n    expect(wrapper.find('[tabindex]').exists()).toBe(true)\n    expect(wrapper.find('.n-checkbox').attributes('tabindex')).toContain('0')\n    wrapper.unmount()\n  })\n\n  it('should work with `label` prop', async () => {\n    const wrapper = mount(NCheckbox, {\n      props: {\n        label: 'test'\n      }\n    })\n    expect(wrapper.find('.n-checkbox__label').text()).toContain('test')\n    wrapper.unmount()\n  })\n\n  it('should work with `on-update:checked` & `onUpdateChecked` prop', async () => {\n    const onClick = vi.fn()\n    const wrapper = mount(NCheckbox, {\n      props: {\n        'onUpdate:checked': onClick,\n        onUpdateChecked: onClick\n      },\n      slots: {\n        default: () => 'test'\n      }\n    })\n\n    await wrapper.trigger('click')\n    expect(onClick).toHaveBeenCalledTimes(2)\n    wrapper.unmount()\n  })\n\n  it('should work with default slots', async () => {\n    const wrapper = mount(NCheckbox, {\n      slots: {\n        default: () => 'test'\n      }\n    })\n\n    expect(wrapper.find('.n-checkbox__label').text()).toContain('test')\n    wrapper.unmount()\n  })\n\n  it('should work with `size` prop', () => {\n    ;(['small', 'medium', 'large'] as const).forEach((i) => {\n      const wrapper = mount(NCheckbox, { props: { size: i } })\n      expect(wrapper.find('.n-checkbox').attributes('style')).toMatchSnapshot()\n      wrapper.unmount()\n    })\n  })\n\n  it('should show correct style with `NForm` component', () => {\n    const wrapper = mount(() => (\n      <NForm size=\"medium\">\n        {{\n          default: () => {\n            return (\n              <NFormItem>\n                {{\n                  default: () => <NCheckbox />\n                }}\n              </NFormItem>\n            )\n          }\n        }}\n      </NForm>\n    ))\n\n    expect(wrapper.find('.n-checkbox').attributes('style')).toMatchSnapshot()\n    wrapper.unmount()\n  })\n\n  describe('accessibility', () => {\n    it('should have a role of \"checkbox\"', () => {\n      const wrapper = mount(NCheckbox)\n      expect(wrapper.find('.n-checkbox').attributes('role')).toBe('checkbox')\n      wrapper.unmount()\n    })\n\n    it('should set a default aria-labelledby', () => {\n      const labelId = 'custom-id'\n      const wrapper = mount(() => <NCheckbox aria-labelledby={labelId} />)\n      expect(wrapper.find('.n-checkbox').attributes('aria-labelledby')).toMatch(\n        labelId\n      )\n      wrapper.unmount()\n    })\n  })\n})\n\ndescribe('n-checkbox-group', () => {\n  it('should work with import on demand', () => {\n    mount(NCheckboxGroup)\n  })\n\n  it('should have a role of \"group\"', () => {\n    const wrapper = mount(NCheckboxGroup)\n    expect(wrapper.find('.n-checkbox-group').attributes('role')).toBe('group')\n    wrapper.unmount()\n  })\n\n  it('should work with `disabled` prop', () => {\n    const wrapper = mount(NCheckboxGroup, {\n      props: {\n        disabled: true\n      },\n      slots: {\n        default: () => h(NCheckbox, null, { default: () => 'test' })\n      }\n    })\n    expect(wrapper.find('.n-checkbox--disabled').exists()).toBe(true)\n    wrapper.unmount()\n  })\n\n  it('should work with `on-update:value` prop', async () => {\n    const onClick = vi.fn()\n    const wrapper = mount(NCheckboxGroup, {\n      props: {\n        'on-update:value': onClick\n      },\n      slots: {\n        default: () => h(NCheckbox, { value: 'test' })\n      }\n    })\n    await wrapper.findComponent(NCheckbox).trigger('click')\n    expect(onClick).toHaveBeenCalled()\n    wrapper.unmount()\n  })\n\n  it('should work with default slots', async () => {\n    const wrapper = mount(NCheckboxGroup, {\n      props: {\n        disabled: true\n      },\n      slots: {\n        default: () => h(NCheckbox, null, { default: () => 'test' })\n      }\n    })\n    expect(wrapper.find('.n-checkbox__label').text()).toContain('test')\n    wrapper.unmount()\n  })\n\n  it('should work with `min` prop', async () => {\n    const wrapper = mount(NCheckboxGroup, {\n      props: {\n        min: 1,\n        value: ['Shanghai']\n      },\n      slots: {\n        default: () => [\n          h(NCheckbox, { value: 'Shanghai' }, { default: () => 'Shanghai' }),\n          h(NCheckbox, { value: 'Beijing' }, { default: () => 'Beijing' }),\n          h(NCheckbox, { value: 'Shenzhen' }, { default: () => 'Shenzhen' })\n        ]\n      }\n    })\n    expect(wrapper.findAll('.n-checkbox').length).toBe(3)\n\n    expect(wrapper.findAll('.n-checkbox')[0].classes()).toContain(\n      'n-checkbox--disabled'\n    )\n    expect(wrapper.findAll('.n-checkbox')[0].classes()).toContain(\n      'n-checkbox--checked'\n    )\n    expect(wrapper.findAll('.n-checkbox')[1].classes()).not.toContain(\n      'n-checkbox--checked'\n    )\n    expect(wrapper.findAll('.n-checkbox')[1].classes()).not.toContain(\n      'n-checkbox--disabled'\n    )\n    wrapper.unmount()\n  })\n\n  it('should work with `max` prop', async () => {\n    const wrapper = mount(NCheckboxGroup, {\n      props: {\n        max: 2,\n        value: ['Shanghai', 'Beijing']\n      },\n      slots: {\n        default: () => [\n          h(NCheckbox, { value: 'Shanghai' }, { default: () => 'Shanghai' }),\n          h(NCheckbox, { value: 'Beijing' }, { default: () => 'Beijing' }),\n          h(NCheckbox, { value: 'Shenzhen' }, { default: () => 'Shenzhen' })\n        ]\n      }\n    })\n    expect(wrapper.findAll('.n-checkbox').length).toBe(3)\n\n    expect(wrapper.findAll('.n-checkbox')[0].classes()).not.toContain(\n      'n-checkbox--disabled'\n    )\n    expect(wrapper.findAll('.n-checkbox')[0].classes()).toContain(\n      'n-checkbox--checked'\n    )\n    expect(wrapper.findAll('.n-checkbox')[1].classes()).toContain(\n      'n-checkbox--checked'\n    )\n    expect(wrapper.findAll('.n-checkbox')[1].classes()).not.toContain(\n      'n-checkbox--disabled'\n    )\n    expect(wrapper.findAll('.n-checkbox')[2].classes()).not.toContain(\n      'n-checkbox--checked'\n    )\n    expect(wrapper.findAll('.n-checkbox')[2].classes()).toContain(\n      'n-checkbox--disabled'\n    )\n    wrapper.unmount()\n  })\n\n  it('should work with `max` and `min` prop', async () => {\n    const wrapper = mount(NCheckboxGroup, {\n      props: {\n        max: 2,\n        min: 1\n      },\n      slots: {\n        default: () => [\n          h(NCheckbox, { value: 'Shanghai' }, { default: () => 'Shanghai' }),\n          h(NCheckbox, { value: 'Beijing' }, { default: () => 'Beijing' }),\n          h(NCheckbox, { value: 'Shenzhen' }, { default: () => 'Shenzhen' })\n        ]\n      }\n    })\n\n    await wrapper.setProps({\n      value: ['Shanghai']\n    })\n    expect(wrapper.findAll('.n-checkbox').length).toBe(3)\n\n    expect(wrapper.findAll('.n-checkbox')[0].classes()).toContain(\n      'n-checkbox--disabled'\n    )\n    expect(wrapper.findAll('.n-checkbox')[0].classes()).toContain(\n      'n-checkbox--checked'\n    )\n    expect(wrapper.findAll('.n-checkbox')[1].classes()).not.toContain(\n      'n-checkbox--checked'\n    )\n    expect(wrapper.findAll('.n-checkbox')[1].classes()).not.toContain(\n      'n-checkbox--disabled'\n    )\n    expect(wrapper.findAll('.n-checkbox')[2].classes()).not.toContain(\n      'n-checkbox--checked'\n    )\n    expect(wrapper.findAll('.n-checkbox')[2].classes()).not.toContain(\n      'n-checkbox--disabled'\n    )\n    await wrapper.setProps({\n      value: ['Shanghai', 'Beijing']\n    })\n\n    expect(wrapper.findAll('.n-checkbox')[0].classes()).not.toContain(\n      'n-checkbox--disabled'\n    )\n    expect(wrapper.findAll('.n-checkbox')[0].classes()).toContain(\n      'n-checkbox--checked'\n    )\n    expect(wrapper.findAll('.n-checkbox')[1].classes()).toContain(\n      'n-checkbox--checked'\n    )\n    expect(wrapper.findAll('.n-checkbox')[1].classes()).not.toContain(\n      'n-checkbox--disabled'\n    )\n    expect(wrapper.findAll('.n-checkbox')[2].classes()).not.toContain(\n      'n-checkbox--checked'\n    )\n    expect(wrapper.findAll('.n-checkbox')[2].classes()).toContain(\n      'n-checkbox--disabled'\n    )\n    wrapper.unmount()\n  })\n})\n"
  },
  {
    "path": "src/checkbox/tests/__snapshots__/Checkbox.spec.tsx.snap",
    "content": "// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html\n\nexports[`n-checkbox > should show correct style with \\`NForm\\` component 1`] = `\"--n-label-line-height: 1.6; --n-label-font-weight: 400; --n-size: 16px; --n-bezier: cubic-bezier(.4, 0, .2, 1); --n-border-radius: 2px; --n-border: 1px solid rgb(224, 224, 230); --n-border-checked: 1px solid #18a058; --n-border-focus: 1px solid #18a058; --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-disabled-checked: 1px solid rgb(224, 224, 230); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.3); --n-color: #FFF; --n-color-checked: #18a058; --n-color-table: #fff; --n-color-table-modal: #fff; --n-color-table-popover: #fff; --n-color-disabled: rgb(250, 250, 252); --n-color-disabled-checked: rgb(250, 250, 252); --n-text-color: rgb(51, 54, 57); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-check-mark-color: #FFF; --n-check-mark-color-disabled: rgba(194, 194, 194, 1); --n-check-mark-color-disabled-checked: rgba(194, 194, 194, 1); --n-font-size: 14px; --n-label-padding: 0 8px;\"`;\n\nexports[`n-checkbox > should work with \\`size\\` prop 1`] = `\"--n-label-line-height: 1.6; --n-label-font-weight: 400; --n-size: 14px; --n-bezier: cubic-bezier(.4, 0, .2, 1); --n-border-radius: 2px; --n-border: 1px solid rgb(224, 224, 230); --n-border-checked: 1px solid #18a058; --n-border-focus: 1px solid #18a058; --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-disabled-checked: 1px solid rgb(224, 224, 230); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.3); --n-color: #FFF; --n-color-checked: #18a058; --n-color-table: #fff; --n-color-table-modal: #fff; --n-color-table-popover: #fff; --n-color-disabled: rgb(250, 250, 252); --n-color-disabled-checked: rgb(250, 250, 252); --n-text-color: rgb(51, 54, 57); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-check-mark-color: #FFF; --n-check-mark-color-disabled: rgba(194, 194, 194, 1); --n-check-mark-color-disabled-checked: rgba(194, 194, 194, 1); --n-font-size: 14px; --n-label-padding: 0 8px;\"`;\n\nexports[`n-checkbox > should work with \\`size\\` prop 2`] = `\"--n-label-line-height: 1.6; --n-label-font-weight: 400; --n-size: 16px; --n-bezier: cubic-bezier(.4, 0, .2, 1); --n-border-radius: 2px; --n-border: 1px solid rgb(224, 224, 230); --n-border-checked: 1px solid #18a058; --n-border-focus: 1px solid #18a058; --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-disabled-checked: 1px solid rgb(224, 224, 230); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.3); --n-color: #FFF; --n-color-checked: #18a058; --n-color-table: #fff; --n-color-table-modal: #fff; --n-color-table-popover: #fff; --n-color-disabled: rgb(250, 250, 252); --n-color-disabled-checked: rgb(250, 250, 252); --n-text-color: rgb(51, 54, 57); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-check-mark-color: #FFF; --n-check-mark-color-disabled: rgba(194, 194, 194, 1); --n-check-mark-color-disabled-checked: rgba(194, 194, 194, 1); --n-font-size: 14px; --n-label-padding: 0 8px;\"`;\n\nexports[`n-checkbox > should work with \\`size\\` prop 3`] = `\"--n-label-line-height: 1.6; --n-label-font-weight: 400; --n-size: 18px; --n-bezier: cubic-bezier(.4, 0, .2, 1); --n-border-radius: 2px; --n-border: 1px solid rgb(224, 224, 230); --n-border-checked: 1px solid #18a058; --n-border-focus: 1px solid #18a058; --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-disabled-checked: 1px solid rgb(224, 224, 230); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.3); --n-color: #FFF; --n-color-checked: #18a058; --n-color-table: #fff; --n-color-table-modal: #fff; --n-color-table-popover: #fff; --n-color-disabled: rgb(250, 250, 252); --n-color-disabled-checked: rgb(250, 250, 252); --n-text-color: rgb(51, 54, 57); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-check-mark-color: #FFF; --n-check-mark-color-disabled: rgba(194, 194, 194, 1); --n-check-mark-color-disabled-checked: rgba(194, 194, 194, 1); --n-font-size: 15px; --n-label-padding: 0 8px;\"`;\n"
  },
  {
    "path": "src/checkbox/tests/server.spec.tsx",
    "content": "import { setup } from '@css-render/vue3-ssr'\nimport { renderToString } from '@vue/server-renderer'\n/**\n * @vitest-environment node\n */\nimport { createSSRApp, h } from 'vue'\nimport { NCheckbox } from '../..'\n\ndescribe('server side rendering', () => {\n  it('works', async () => {\n    const app = createSSRApp(() => <NCheckbox />)\n    setup(app)\n    try {\n      await renderToString(app)\n    }\n    catch (e) {\n      expect(e).not.toBeTruthy()\n    }\n  })\n})\n"
  },
  {
    "path": "src/code/demos/enUS/basic.demo.vue",
    "content": "<markdown>\n# Basic\n\nFor example, JavaScript, Python and C++.\n</markdown>\n\n<script lang=\"ts\" setup>\nconst cppCode = `int main () {\n  std::cout << \"Hello Naive UI\";\n  return 0;\n}`\n</script>\n\n<template>\n  <div style=\"overflow: auto\">\n    <n-space vertical :size=\"16\">\n      <n-code\n        code=\"\nfunction sleep (ms = 1000) {\n  return new Promise(resolve => setTimeout(resolve, ms))\n}\n\"\n        language=\"javascript\"\n      />\n      <n-code\n        code=\"\ndef say_hello():\n    print('Hello Naive UI')\n\"\n        language=\"python\"\n      />\n      <n-code :code=\"cppCode\" language=\"cpp\" />\n    </n-space>\n  </div>\n</template>\n"
  },
  {
    "path": "src/code/demos/enUS/index.demo-entry.md",
    "content": "# Code\n\n## Prequisites\n\n<n-alert title=\"Note\" type=\"warning\" style=\"margin-bottom: 16px;\" :bordered=\"false\">\n  Due to package size, Naive UI doesn't include highlight.js. If you want to use Code, make sure you have set highlightjs before using it.\n</n-alert>\n\nThe following code shows how to set hljs of Code. Importing highlight.js on demand is recommonded, because it can significantly reduce bundle size of your app.\n\n```html\n<template>\n  <n-config-provider :hljs=\"hljs\">\n    <my-app />\n  </n-config-provider>\n</template>\n\n<script>\n  import { defineComponent } from 'vue'\n  import hljs from 'highlight.js/lib/core'\n  import javascript from 'highlight.js/lib/languages/javascript'\n\n  hljs.registerLanguage('javascript', javascript)\n\n  export default defineComponent({\n    setup() {\n      return {\n        hljs\n      }\n    }\n  })\n</script>\n```\n\n## Demos\n\n```demo\nbasic.vue\ninline.vue\nsoftwrap.vue\nline-numbers.vue\n```\n\n## API\n\n### Code Props\n\n| Name | Type | Default | Description | Version |\n| --- | --- | --- | --- | --- |\n| code | `string` | `''` | Incoming code string. |  |\n| hljs | `Object` | `undefined` | If you want to set hljs locally, pass it using this prop. |  |\n| inline | `boolean` | `false` | Whether the code is displayed as inline. |  |\n| language | `string` | `undefined` | Code language in highlightjs. |  |\n| show-line-numbers | `boolean` | `false` | Whether to show line numbers. Won't work if `inline` or `word-wrap` is `true`. | 2.32.0 |\n| trim | `boolean` | `true` | Whether to display trimmed code. |  |\n| word-wrap | `boolean` | `false` | Whether to display word-wrapped code. | 2.24.0 |\n"
  },
  {
    "path": "src/code/demos/enUS/inline.demo.vue",
    "content": "<markdown>\n# Inline\n\nFor example, JavaScript.\n</markdown>\n\n<script lang=\"ts\" setup>\nconst code = 'console.log(\"Hello World\")'\n</script>\n\n<template>\n  <div>\n    JavaScript\n    <n-code :code=\"code\" language=\"javascript\" inline />\n  </div>\n</template>\n"
  },
  {
    "path": "src/code/demos/enUS/line-numbers.demo.vue",
    "content": "<markdown>\n# Line numbers\n\nIt can show line numbers in the code block.\n</markdown>\n\n<script lang=\"ts\" setup>\nconst code = `#include <bits/stdc++.h>\nusing namespace std;\n\nint main() {\n  cout <<\"\\\\n\" <<endl;\n  cout <<\"\\\\n\" <<endl;\n  cout <<\"\\\\n\" <<endl;\n  cout <<\"\\\\n\" <<endl;\n  cout <<\"\\\\n\" <<endl;\n  cout <<\"\\\\n\" <<endl;\n  cout <<\"\\\\n\" <<endl;\n  cout <<\"\\\\n\" <<endl;\n  cout <<\"\\\\n\" <<endl;\n  cout <<\"\\\\n\" <<endl;\n  return 0;\n}`\n</script>\n\n<template>\n  <div style=\"overflow: auto\">\n    <n-code :code=\"code\" language=\"cpp\" show-line-numbers />\n  </div>\n</template>\n"
  },
  {
    "path": "src/code/demos/enUS/softwrap.demo.vue",
    "content": "<markdown>\n# Soft wrap\n\nCode can wrap content if it overflows.\n</markdown>\n\n<script lang=\"ts\" setup>\nconst code = `\nfunction padEnd(string, length, chars) {\n  const strLength = length ? stringSize(string) : 0\n  return (length && strLength < length)? (string + createPadding(length - strLength, chars)): (string || '')\n}\n      `\n</script>\n\n<template>\n  <n-code :code=\"code\" language=\"js\" word-wrap />\n</template>\n"
  },
  {
    "path": "src/code/demos/zhCN/basic.demo.vue",
    "content": "<markdown>\n# 基础用法\n\nJavaScript、Python、C++ 的例子。\n</markdown>\n\n<script lang=\"ts\" setup>\nconst cppCode = `int main () {\n  std::cout << \"Hello Naive UI\";\n  return 0;\n}`\n</script>\n\n<template>\n  <div style=\"overflow: auto\">\n    <n-space vertical :size=\"16\">\n      <n-code\n        code=\"\nfunction sleep (ms = 1000) {\n  return new Promise(resolve => setTimeout(resolve, ms))\n}\n\"\n        language=\"javascript\"\n      />\n      <n-code\n        code=\"\ndef say_hello():\n    print('Hello Naive UI')\n\"\n        language=\"python\"\n      />\n      <n-code :code=\"cppCode\" language=\"cpp\" />\n    </n-space>\n  </div>\n</template>\n"
  },
  {
    "path": "src/code/demos/zhCN/index.demo-entry.md",
    "content": "# 代码 Code\n\n## 预备条件\n\n<n-alert title=\"注意\" type=\"warning\" style=\"margin-bottom: 16px;\" :bordered=\"false\">\n  由于包体积原因，Naive UI 不内置 highlight.js。如果你需要使用代码组件，请确保你在使用之前已经设定了 highlight.js。\n</n-alert>\n\n下面的代码展示了如何为 Code 设定 hljs。比较推荐的方式是按需引入，因为它可以极大地减小打包尺寸。\n\n```html\n<template>\n  <n-config-provider :hljs=\"hljs\">\n    <my-app />\n  </n-config-provider>\n</template>\n\n<script>\n  import { defineComponent } from 'vue'\n  import hljs from 'highlight.js/lib/core'\n  import javascript from 'highlight.js/lib/languages/javascript'\n\n  hljs.registerLanguage('javascript', javascript)\n\n  export default defineComponent({\n    setup() {\n      return {\n        hljs\n      }\n    }\n  })\n</script>\n```\n\n## 演示\n\n```demo\nbasic.vue\ninline.vue\nsoftwrap.vue\nloop-debug.vue\nline-numbers.vue\n```\n\n## API\n\n### Code Props\n\n| 名称 | 类型 | 默认值 | 说明 | 版本 |\n| --- | --- | --- | --- | --- |\n| code | `string` | `''` | 传入的 code 字符串 |  |\n| inline | `boolean` | `false` | 使用行内样式 |  |\n| hljs | `Object` | `undefined` | 如果你想局部设定 hljs，可以通过这个属性传给组件 |  |\n| language | `string` | `undefined` | 代码在 highlightjs 中的语言 |  |\n| show-line-numbers | `boolean` | `false` | 是否显示行号，在 `inline` 或 `word-wrap` 的情况下不生效 | 2.32.0 |\n| trim | `boolean` | `true` | 是否显示 trim 后的代码 |  |\n| word-wrap | `boolean` | `false` | 代码过长时是否自动换行 | 2.24.0 |\n"
  },
  {
    "path": "src/code/demos/zhCN/inline.demo.vue",
    "content": "<markdown>\n# 行内显示\n\nJavaScript 的例子。\n</markdown>\n\n<script lang=\"ts\" setup>\nconst code = 'console.log(\"工具人的日子不好过\")'\n</script>\n\n<template>\n  <div>\n    JavaScript\n    <n-code :code=\"code\" language=\"javascript\" inline />\n  </div>\n</template>\n"
  },
  {
    "path": "src/code/demos/zhCN/line-numbers.demo.vue",
    "content": "<markdown>\n# 显示行号\n\n可以在代码块左侧显示行号。\n</markdown>\n\n<script lang=\"ts\" setup>\nconst code = `#include <bits/stdc++.h>\nusing namespace std;\n\nint main() {\n  cout <<\"你\" << endl;\n  cout <<\"觉\" << endl;\n  cout <<\"得\" << endl;\n  cout <<\"恨\" << endl;\n  cout <<\"却\" << endl;\n  cout <<\"离\" << endl;\n  cout <<\"不\" << endl;\n  cout <<\"开\" << endl;\n  return 0;\n}`\n</script>\n\n<template>\n  <div style=\"overflow: auto\">\n    <n-code :code=\"code\" language=\"cpp\" show-line-numbers />\n  </div>\n</template>\n"
  },
  {
    "path": "src/code/demos/zhCN/loop-debug.demo.vue",
    "content": "<markdown>\n# Loop debug\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { onBeforeUnmount, ref } from 'vue'\n\nconst code = ref('')\n\nconst id = setInterval(() => {\n  code.value = `Current: ${String(new Date())}`\n}, 1000)\n\nonBeforeUnmount(() => {\n  clearInterval(id)\n})\n</script>\n\n<template>\n  <n-code :code=\"code\" />\n</template>\n"
  },
  {
    "path": "src/code/demos/zhCN/softwrap.demo.vue",
    "content": "<markdown>\n# 软换行\n\ncode 可以在溢出时自动换行。\n</markdown>\n\n<script lang=\"ts\" setup>\nconst code = `\nfunction padEnd(string, length, chars) {\n  const strLength = length ? stringSize(string) : 0\n  return (length && strLength < length)? (string + createPadding(length - strLength, chars)): (string || '')\n}\n      `\n</script>\n\n<template>\n  <n-code :code=\"code\" language=\"js\" word-wrap />\n</template>\n"
  },
  {
    "path": "src/code/index.ts",
    "content": "export { codeProps, default as NCode } from './src/Code'\nexport type { CodeProps } from './src/Code'\n"
  },
  {
    "path": "src/code/src/Code.tsx",
    "content": "import type { PropType } from 'vue'\nimport type { Hljs, ThemeProps } from '../../_mixins'\nimport type { ExtractPublicPropTypes } from '../../_utils'\nimport type { CodeTheme } from '../styles'\nimport { computed, defineComponent, h, onMounted, ref, toRef, watch } from 'vue'\nimport { useConfig, useHljs, useTheme, useThemeClass } from '../../_mixins'\nimport { codeLight } from '../styles'\nimport style from './styles/index.cssr'\n\nexport const codeProps = {\n  ...(useTheme.props as ThemeProps<CodeTheme>),\n  language: String,\n  code: {\n    type: String,\n    default: ''\n  },\n  trim: {\n    type: Boolean,\n    default: true\n  },\n  hljs: Object as PropType<Hljs>,\n  uri: Boolean,\n  inline: Boolean,\n  wordWrap: Boolean,\n  showLineNumbers: Boolean,\n  // In n-log, we only need to mount code's style for highlight\n  internalFontSize: Number,\n  internalNoHighlight: Boolean\n}\n\nexport type CodeProps = ExtractPublicPropTypes<typeof codeProps>\n\nexport default defineComponent({\n  name: 'Code',\n  props: codeProps,\n  setup(props, { slots }) {\n    const { internalNoHighlight } = props\n    const { mergedClsPrefixRef, inlineThemeDisabled } = useConfig()\n    const codeRef = ref<HTMLElement | null>(null)\n    const hljsRef = internalNoHighlight ? { value: undefined } : useHljs(props)\n    const createCodeHtml = (\n      language: string,\n      code: string,\n      trim: boolean\n    ): string | null => {\n      const { value: hljs } = hljsRef\n      if (!hljs) {\n        return null\n      }\n      if (!(language && hljs.getLanguage(language))) {\n        return null\n      }\n      return hljs.highlight(trim ? code.trim() : code, {\n        language\n      }).value\n    }\n    const mergedShowLineNumbersRef = computed(() => {\n      if (props.inline || props.wordWrap)\n        return false\n      return props.showLineNumbers\n    })\n    const setCode = (): void => {\n      if (slots.default)\n        return\n      const { value: codeEl } = codeRef\n      if (!codeEl)\n        return\n      const { language } = props\n      const code = props.uri\n        ? window.decodeURIComponent(props.code)\n        : props.code\n      if (language) {\n        const html = createCodeHtml(language, code, props.trim)\n        if (html !== null) {\n          if (props.inline) {\n            codeEl.innerHTML = html\n          }\n          else {\n            const prevPreEl = codeEl.querySelector('.__code__')\n            if (prevPreEl)\n              codeEl.removeChild(prevPreEl)\n            const preEl = document.createElement('pre')\n            preEl.className = '__code__'\n            preEl.innerHTML = html\n            codeEl.appendChild(preEl)\n          }\n          return\n        }\n      }\n      if (props.inline) {\n        codeEl.textContent = code\n        return\n      }\n      const maybePreEl = codeEl.querySelector('.__code__')\n      if (maybePreEl) {\n        maybePreEl.textContent = code\n      }\n      else {\n        const wrap = document.createElement('pre')\n        wrap.className = '__code__'\n        wrap.textContent = code\n        codeEl.innerHTML = ''\n        codeEl.appendChild(wrap)\n      }\n    }\n    onMounted(setCode)\n    watch(toRef(props, 'language'), setCode)\n    watch(toRef(props, 'code'), setCode)\n    if (!internalNoHighlight)\n      watch(hljsRef, setCode)\n    const themeRef = useTheme(\n      'Code',\n      '-code',\n      style,\n      codeLight,\n      props,\n      mergedClsPrefixRef\n    )\n    const cssVarsRef = computed(() => {\n      const {\n        common: { cubicBezierEaseInOut, fontFamilyMono },\n        self: {\n          textColor,\n          fontSize,\n          fontWeightStrong,\n          lineNumberTextColor,\n          // extracted from hljs atom-one-light.scss\n          'mono-3': $1,\n          'hue-1': $2,\n          'hue-2': $3,\n          'hue-3': $4,\n          'hue-4': $5,\n          'hue-5': $6,\n          'hue-5-2': $7,\n          'hue-6': $8,\n          'hue-6-2': $9\n        }\n      } = themeRef.value\n      const { internalFontSize } = props\n      return {\n        '--n-font-size': internalFontSize ? `${internalFontSize}px` : fontSize,\n        '--n-font-family': fontFamilyMono,\n        '--n-font-weight-strong': fontWeightStrong,\n        '--n-bezier': cubicBezierEaseInOut,\n        '--n-text-color': textColor,\n        '--n-mono-3': $1,\n        '--n-hue-1': $2,\n        '--n-hue-2': $3,\n        '--n-hue-3': $4,\n        '--n-hue-4': $5,\n        '--n-hue-5': $6,\n        '--n-hue-5-2': $7,\n        '--n-hue-6': $8,\n        '--n-hue-6-2': $9,\n        '--n-line-number-text-color': lineNumberTextColor\n      }\n    })\n    const themeClassHandle = inlineThemeDisabled\n      ? useThemeClass(\n          'code',\n          computed(() => {\n            return `${props.internalFontSize || 'a'}`\n          }),\n          cssVarsRef,\n          props\n        )\n      : undefined\n    return {\n      mergedClsPrefix: mergedClsPrefixRef,\n      codeRef,\n      mergedShowLineNumbers: mergedShowLineNumbersRef,\n      lineNumbers: computed(() => {\n        let number = 1\n        const numbers: number[] = []\n        let lastIsLineWrap = false\n        for (const char of props.code) {\n          if (char === '\\n') {\n            lastIsLineWrap = true\n            numbers.push(number++)\n          }\n          else {\n            lastIsLineWrap = false\n          }\n        }\n        if (!lastIsLineWrap) {\n          numbers.push(number++)\n        }\n        return numbers.join('\\n')\n      }),\n      cssVars: inlineThemeDisabled ? undefined : cssVarsRef,\n      themeClass: themeClassHandle?.themeClass,\n      onRender: themeClassHandle?.onRender\n    }\n  },\n  render() {\n    const { mergedClsPrefix, wordWrap, mergedShowLineNumbers, onRender } = this\n    onRender?.()\n    return (\n      <code\n        class={[\n          `${mergedClsPrefix}-code`,\n          this.themeClass,\n          wordWrap && `${mergedClsPrefix}-code--word-wrap`,\n          mergedShowLineNumbers && `${mergedClsPrefix}-code--show-line-numbers`\n        ]}\n        style={this.cssVars as any}\n        ref=\"codeRef\"\n      >\n        {mergedShowLineNumbers ? (\n          <pre class={`${mergedClsPrefix}-code__line-numbers`}>\n            {this.lineNumbers}\n          </pre>\n        ) : null}\n        {this.$slots.default?.()}\n      </code>\n    )\n  }\n})\n"
  },
  {
    "path": "src/code/src/styles/index.cssr.ts",
    "content": "import { c, cB, cE, cM } from '../../../_utils/cssr'\n\n// vars:\n// --n-font-size\n// --n-font-family\n// --n-font-weight-strong\n// --n-bezier\n// --n-text-color\n// --n-mono-3\n// --n-hue-1\n// --n-hue-2\n// --n-hue-3\n// --n-hue-4\n// --n-hue-5\n// --n-hue-5-2\n// --n-hue-6\n// --n-hue-6-2\n// --n-line-number-color\n// --n-line-number-text-color\nexport default c([\n  cB('code', `\n    font-size: var(--n-font-size);\n    font-family: var(--n-font-family);\n  `, [\n    cM('show-line-numbers', `\n      display: flex;\n    `),\n    cE('line-numbers', `\n      user-select: none;\n      padding-right: 12px;\n      text-align: right;\n      transition: color .3s var(--n-bezier);\n      color: var(--n-line-number-text-color);\n    `),\n    cM('word-wrap', [\n      c('pre', `\n        white-space: pre-wrap;\n        word-break: break-all;\n      `)\n    ]),\n    c('pre', `\n      margin: 0;\n      line-height: inherit;\n      font-size: inherit;\n      font-family: inherit;\n    `),\n    c('[class^=hljs]', `\n      color: var(--n-text-color);\n      transition: \n        color .3s var(--n-bezier),\n        background-color .3s var(--n-bezier);\n    `)\n  ]),\n  ({ props }) => {\n    const codeClass = `${props.bPrefix}code`\n    return [\n      `${codeClass} .hljs-comment,\n      ${codeClass} .hljs-quote {\n        color: var(--n-mono-3);\n        font-style: italic;\n      }`,\n      `${codeClass} .hljs-doctag,\n      ${codeClass} .hljs-keyword,\n      ${codeClass} .hljs-formula {\n        color: var(--n-hue-3);\n      }`,\n      `${codeClass} .hljs-section,\n      ${codeClass} .hljs-name,\n      ${codeClass} .hljs-selector-tag,\n      ${codeClass} .hljs-deletion,\n      ${codeClass} .hljs-subst {\n        color: var(--n-hue-5);\n      }`,\n      `${codeClass} .hljs-literal {\n        color: var(--n-hue-1);\n      }`,\n      `${codeClass} .hljs-string,\n      ${codeClass} .hljs-regexp,\n      ${codeClass} .hljs-addition,\n      ${codeClass} .hljs-attribute,\n      ${codeClass} .hljs-meta-string {\n        color: var(--n-hue-4);\n      }`,\n      `${codeClass} .hljs-built_in,\n      ${codeClass} .hljs-class .hljs-title {\n        color: var(--n-hue-6-2);\n      }`,\n      `${codeClass} .hljs-attr,\n      ${codeClass} .hljs-variable,\n      ${codeClass} .hljs-template-variable,\n      ${codeClass} .hljs-type,\n      ${codeClass} .hljs-selector-class,\n      ${codeClass} .hljs-selector-attr,\n      ${codeClass} .hljs-selector-pseudo,\n      ${codeClass} .hljs-number {\n        color: var(--n-hue-6);\n      }`,\n      `${codeClass} .hljs-symbol,\n      ${codeClass} .hljs-bullet,\n      ${codeClass} .hljs-link,\n      ${codeClass} .hljs-meta,\n      ${codeClass} .hljs-selector-id,\n      ${codeClass} .hljs-title {\n        color: var(--n-hue-2);\n      }`,\n      `${codeClass} .hljs-emphasis {\n        font-style: italic;\n      }`,\n      `${codeClass} .hljs-strong {\n        font-weight: var(--n-font-weight-strong);\n      }`,\n      `${codeClass} .hljs-link {\n        text-decoration: underline;\n      }`\n    ]\n  }\n])\n"
  },
  {
    "path": "src/code/styles/dark.ts",
    "content": "import type { CodeTheme } from './light'\nimport { commonDark } from '../../_styles/common'\n\nconst codeDark: CodeTheme = {\n  name: 'Code',\n  common: commonDark,\n  self(vars) {\n    const { textColor2, fontSize, fontWeightStrong, textColor3 } = vars\n    return {\n      textColor: textColor2,\n      fontSize,\n      fontWeightStrong,\n      // extracted from hljs atom-one-dark.scss\n      'mono-3': '#5c6370',\n      'hue-1': '#56b6c2',\n      'hue-2': '#61aeee',\n      'hue-3': '#c678dd',\n      'hue-4': '#98c379',\n      'hue-5': '#e06c75',\n      'hue-5-2': '#be5046',\n      'hue-6': '#d19a66',\n      'hue-6-2': '#e6c07b',\n      // line-number styles\n      lineNumberTextColor: textColor3\n    }\n  }\n}\n\nexport default codeDark\n"
  },
  {
    "path": "src/code/styles/index.ts",
    "content": "export { default as codeDark } from './dark'\nexport { default as codeLight } from './light'\nexport type { CodeTheme, CodeThemeVars } from './light'\n"
  },
  {
    "path": "src/code/styles/light.ts",
    "content": "import type { Theme } from '../../_mixins/use-theme'\nimport type { ThemeCommonVars } from '../../_styles/common'\nimport { commonLight } from '../../_styles/common'\n\nfunction self(vars: ThemeCommonVars) {\n  const { textColor2, fontSize, fontWeightStrong, textColor3 } = vars\n  return {\n    textColor: textColor2,\n    fontSize,\n    fontWeightStrong,\n    // extracted from hljs atom-one-light.scss\n    'mono-3': '#a0a1a7',\n    'hue-1': '#0184bb',\n    'hue-2': '#4078f2',\n    'hue-3': '#a626a4',\n    'hue-4': '#50a14f',\n    'hue-5': '#e45649',\n    'hue-5-2': '#c91243',\n    'hue-6': '#986801',\n    'hue-6-2': '#c18401',\n    // line-number styles\n    lineNumberTextColor: textColor3\n  }\n}\n\nexport type CodeThemeVars = ReturnType<typeof self>\n\nconst codeLight: Theme<'Code', CodeThemeVars> = {\n  name: 'Code',\n  common: commonLight,\n  self\n}\n\nexport default codeLight\nexport type CodeTheme = typeof codeLight\n"
  },
  {
    "path": "src/code/tests/Code.spec.tsx",
    "content": "import { mount } from '@vue/test-utils'\nimport hljs from 'highlight.js/lib/core'\nimport javascript from 'highlight.js/lib/languages/javascript'\nimport { h, toRaw } from 'vue'\nimport { NCode } from '../index'\n\nhljs.registerLanguage('javascript', javascript)\n\ndescribe('n-code', () => {\n  it('should warn when no hljs is set', () => {\n    const spy = vi.spyOn(console, 'error').mockImplementation(() => {})\n    mount(NCode)\n    expect(spy).toHaveBeenCalled()\n  })\n  it('should work with `code` prop', () => {\n    const wrapper = mount(NCode, {\n      props: {\n        code: 'console.log(a)'\n      }\n    })\n    expect(wrapper.text()).toEqual('console.log(a)')\n    wrapper.unmount()\n  })\n  it('should work with `language` prop', () => {\n    const wrapper = mount(() => {\n      return (\n        <NCode code=\"console.log(a)\" language=\"javascript\" hljs={toRaw(hljs)} />\n      )\n    })\n    expect(wrapper.find('.hljs-variable').text()).toBe('console')\n    wrapper.unmount()\n  })\n  it('should work with `hljs` prop', () => {\n    const wrapper = mount(() => {\n      return (\n        <NCode code=\"console.log(a)\" language=\"javascript\" hljs={toRaw(hljs)} />\n      )\n    })\n    expect(wrapper.find('.function_').text()).toBe('log')\n    wrapper.unmount()\n  })\n  it('should work with `trim` prop', () => {\n    const wrapper = mount(NCode, {\n      props: {\n        code: '    console.log( a )  ',\n        trim: false\n      }\n    })\n    expect(wrapper.find('pre').element.textContent).toContain(\n      '    console.log( a )  '\n    )\n    wrapper.unmount()\n  })\n  it('should work with `default` slot', () => {\n    const wrapper = mount(NCode, {\n      slots: {\n        default: () => 'console.log(a)'\n      }\n    })\n    expect(wrapper.text()).toBe('console.log(a)')\n    wrapper.unmount()\n  })\n})\n"
  },
  {
    "path": "src/code/tests/server.spec.tsx",
    "content": "import { setup } from '@css-render/vue3-ssr'\nimport { renderToString } from '@vue/server-renderer'\nimport hljs from 'highlight.js/lib/core'\nimport javascript from 'highlight.js/lib/languages/javascript'\n/**\n * @vitest-environment node\n */\nimport { createSSRApp, h } from 'vue'\nimport { NCode } from '../..'\nimport { NConfigProvider } from '../../config-provider'\n\nhljs.registerLanguage('javascript', javascript)\n\ndescribe('server side rendering', () => {\n  it('works', async () => {\n    const app = createSSRApp(() => (\n      <NConfigProvider hljs={hljs}>\n        {{\n          default: () => <NCode />\n        }}\n      </NConfigProvider>\n    ))\n    setup(app)\n    try {\n      await renderToString(app)\n    }\n    catch (e) {\n      expect(e).not.toBeTruthy()\n    }\n  })\n})\n"
  },
  {
    "path": "src/collapse/demos/enUS/accordion.demo.vue",
    "content": "<markdown>\n# Accordion\n\nLike an accordion.\n</markdown>\n\n<template>\n  <n-collapse default-expanded-names=\"1\" accordion>\n    <n-collapse-item title=\"right\" name=\"1\">\n      <div>good</div>\n    </n-collapse-item>\n    <n-collapse-item title=\"right\" name=\"2\">\n      <div>good</div>\n    </n-collapse-item>\n  </n-collapse>\n</template>\n"
  },
  {
    "path": "src/collapse/demos/enUS/arrow-placement.demo.vue",
    "content": "<markdown>\n# Arrow placement\n\nUse `arrow-placement` to set the placement of arrow.\n</markdown>\n\n<template>\n  <n-collapse arrow-placement=\"right\">\n    <n-collapse-item title=\"right\" name=\"1\">\n      <div>good</div>\n    </n-collapse-item>\n    <n-collapse-item title=\"right\" name=\"2\">\n      <div>nice</div>\n    </n-collapse-item>\n    <n-collapse-item title=\"right\" name=\"3\">\n      <div>very good</div>\n    </n-collapse-item>\n  </n-collapse>\n</template>\n"
  },
  {
    "path": "src/collapse/demos/enUS/basic.demo.vue",
    "content": "<markdown>\n# Basic\n</markdown>\n\n<template>\n  <n-collapse>\n    <n-collapse-item title=\"right\" name=\"1\">\n      <div>good</div>\n    </n-collapse-item>\n    <n-collapse-item title=\"right\" name=\"2\">\n      <div>nice</div>\n    </n-collapse-item>\n    <n-collapse-item title=\"right\" name=\"3\">\n      <div>very good</div>\n    </n-collapse-item>\n  </n-collapse>\n</template>\n"
  },
  {
    "path": "src/collapse/demos/enUS/customize-icon.demo.vue",
    "content": "<markdown>\n# Customize icon\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { CashOutline as CashIcon } from '@vicons/ionicons5'\n</script>\n\n<template>\n  <n-collapse>\n    <template #header-extra>\n      <n-icon><CashIcon /></n-icon>\n    </template>\n    <template #arrow>\n      <n-icon>\n        <CashIcon />\n      </n-icon>\n    </template>\n    <n-collapse-item title=\"Bronze\" name=\"1\">\n      <div>good</div>\n    </n-collapse-item>\n    <n-collapse-item title=\"Silver\" name=\"2\">\n      <div>nice</div>\n    </n-collapse-item>\n    <n-collapse-item title=\"Gold\" name=\"3\">\n      <div>very good</div>\n    </n-collapse-item>\n  </n-collapse>\n</template>\n"
  },
  {
    "path": "src/collapse/demos/enUS/default-expanded.demo.vue",
    "content": "<markdown>\n# Default expanded\n\nIt should be noted that even if only one panel you want to set to be expanded, `default-expanded-names` should also be passed in an array, unless `accordion` is set to `true`.\n</markdown>\n\n<template>\n  <n-collapse :default-expanded-names=\"['2', '3']\">\n    <n-collapse-item title=\"green light\" name=\"1\">\n      <n-collapse :default-expanded-names=\"['2']\">\n        <n-collapse-item title=\"on\" name=\"1\">\n          <div>pass</div>\n        </n-collapse-item>\n        <n-collapse-item title=\"flashing\" name=\"2\">\n          <div>pass fastly</div>\n        </n-collapse-item>\n      </n-collapse>\n    </n-collapse-item>\n    <n-collapse-item title=\"red light\" name=\"2\">\n      <div>stop</div>\n    </n-collapse-item>\n    <n-collapse-item title=\"amber light\" name=\"3\">\n      <div>warn</div>\n    </n-collapse-item>\n  </n-collapse>\n</template>\n"
  },
  {
    "path": "src/collapse/demos/enUS/disabled.demo.vue",
    "content": "<markdown>\n# Disabled\n</markdown>\n\n<template>\n  <n-collapse>\n    <n-collapse-item title=\"right\" name=\"1\">\n      <div>good</div>\n    </n-collapse-item>\n    <n-collapse-item title=\"right\" name=\"2\" disabled>\n      <div>nice</div>\n    </n-collapse-item>\n    <n-collapse-item title=\"right\" name=\"3\">\n      <div>very good</div>\n    </n-collapse-item>\n  </n-collapse>\n</template>\n"
  },
  {
    "path": "src/collapse/demos/enUS/display-directive.demo.vue",
    "content": "<markdown>\n# Display directive\n\nSet `display-directive` to `if` or `show` to determine whether to keep the DOM inside `n-collapse-item` when inactive.\n</markdown>\n\n<template>\n  <n-collapse display-directive=\"show\">\n    <n-collapse-item title=\"right\" name=\"1\">\n      <n-collapse>\n        <n-collapse-item title=\"right\" name=\"1\">\n          <div>good</div>\n        </n-collapse-item>\n        <n-collapse-item title=\"right\" name=\"2\">\n          <div>good</div>\n        </n-collapse-item>\n      </n-collapse>\n    </n-collapse-item>\n    <n-collapse-item title=\"right\" name=\"2\">\n      <div>good</div>\n    </n-collapse-item>\n  </n-collapse>\n</template>\n"
  },
  {
    "path": "src/collapse/demos/enUS/header-extra.demo.vue",
    "content": "<markdown>\n# Extra info in header\n\nPut some info on the right side of the item.\n</markdown>\n\n<template>\n  <n-collapse>\n    <n-collapse-item title=\"right\" name=\"1\">\n      good\n      <template #header-extra>\n        good\n      </template>\n    </n-collapse-item>\n    <n-collapse-item title=\"right\" name=\"2\">\n      nice\n      <template #header-extra>\n        nice\n      </template>\n    </n-collapse-item>\n    <n-collapse-item title=\"right\" name=\"3\">\n      very good\n      <template #header-extra>\n        very good\n      </template>\n    </n-collapse-item>\n  </n-collapse>\n</template>\n"
  },
  {
    "path": "src/collapse/demos/enUS/index.demo-entry.md",
    "content": "# Collapse\n\nI saw it appears in many side control panels.\n\n## Demos\n\n```demo\nbasic.vue\narrow-placement.vue\naccordion.vue\nnested.vue\ndisplay-directive.vue\nitem-header-click.vue\ncustomize-icon.vue\ndefault-expanded.vue\nheader-extra.vue\ndisabled.vue\ntrigger-areas.vue\n```\n\n## API\n\n### Collapse Props\n\n| Name | Type | Default | Description | Version |\n| --- | --- | --- | --- | --- |\n| accordion | `boolean` | `false` | Only allow one panel open at a time. |\n| arrow-placement | `'left' \\| 'right'` | `'left'` | Arrow placement side of text. |\n| default-expanded-names | `string \\| number \\| Array<string \\| number> \\| null` | `null` | Pre-expanded panels that can still be collapsed. If `accordion` mode is set, it should be a non-array value. |\n| display-directive | `'if' \\| 'show'` | `'if'` | The display directive to use when `n-collapse-item` renders content. `'if'` corresponds to `v-if` and `'show'` corresponds to `v-show`. |\n| expanded-names | `string \\| number \\| Array<string \\| number> \\| null` | `undefined` | Expanded panels that cannot be collapsed. If `accordion` mode is set, it should be a non-array value. |\n| trigger-areas | `Array<'main' \\| 'arrow' \\| 'extra'>` | `['main', 'arrow', 'extra']` | Expansion trigger areas. If you don't want to trigger expansion on some areas, you can use the prop. | 2.37.1 |\n| on-item-header-click | `(data: { name: string \\| number, expanded: boolean, event: MouseEvent }) => void` | `undefined` | Callback function triggered when the title is clicked. |\n| on-update:expanded-names | `(expandedNames: Array<string \\| number> \\| string \\| number \\| null) => void` | `undefined` | Callback function triggered when the expanded-names array is changed. |\n\n### CollapseItem Props\n\n| Name | Type | Default | Description | Version |\n| --- | --- | --- | --- | --- |\n| disabled | `boolean` | `false` | Whether the item is disabled. | 2.32.2 |\n| display-directive | `'if' \\| 'show'` | `undefined` | The display directive to use when it is rendering its content. `'if'` corresponds to `v-if` and `'show'` corresponds to `v-show`. When it is set to `undefined` the value will follow its outer `n-collapse`. |  |\n| name | `string \\| number` | random string | Item identifier (should be unique). |  |\n| title | `string` | `undefined` | Title. |  |\n\n### Collapse Slots\n\n| Name | Parameters | Description |\n| --- | --- | --- |\n| arrow | `(props: { collapsed: boolean })` | Custom icons for folding panels. |\n| default | `()` | The contents of the collapsible panel. |\n| header | `(props: { collapsed: boolean })` | The content of the header of the collapsed panel node. |\n\n### CollapseItem Slots\n\n| Name | Parameters | Description |\n| --- | --- | --- |\n| arrow | `(props: { collapsed: boolean })` | The custom icon of the node header of the collapsible panel. |\n| default | `()` | The contents of the collapsible panel node. |\n| header | `(props: { collapsed: boolean })` | The content of the header of the collapsed panel node. |\n| header-extra | `(props: { collapsed: boolean })` | The extra content of the header of the collapsed panel node. |\n"
  },
  {
    "path": "src/collapse/demos/enUS/item-header-click.demo.vue",
    "content": "<markdown>\n# Click on item header\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { CollapseProps } from 'naive-ui'\nimport { useMessage } from 'naive-ui'\n\nconst message = useMessage()\nconst handleItemHeaderClick: CollapseProps['onItemHeaderClick'] = ({\n  name,\n  expanded\n}) => {\n  message.info(`Name: ${name}, Expanded: ${expanded}`)\n}\n</script>\n\n<template>\n  <n-collapse @item-header-click=\"handleItemHeaderClick\">\n    <n-collapse-item name=\"1\">\n      <template #header>\n        Bronze\n      </template>\n      <div>Okay</div>\n    </n-collapse-item>\n    <n-collapse-item name=\"2\">\n      <template #header>\n        Silver\n      </template>\n      <div>Good</div>\n    </n-collapse-item>\n    <n-collapse-item name=\"3\">\n      <template #header>\n        Gold\n      </template>\n      <div>Excellent</div>\n    </n-collapse-item>\n  </n-collapse>\n</template>\n"
  },
  {
    "path": "src/collapse/demos/enUS/nested.demo.vue",
    "content": "<markdown>\n# Nested\n\nIt can be nested.\n</markdown>\n\n<template>\n  <n-collapse>\n    <n-collapse-item title=\"right\" name=\"1\">\n      <n-collapse>\n        <n-collapse-item title=\"right\" name=\"1\">\n          <div>good</div>\n        </n-collapse-item>\n        <n-collapse-item title=\"right\" name=\"2\">\n          <div>good</div>\n        </n-collapse-item>\n      </n-collapse>\n    </n-collapse-item>\n    <n-collapse-item title=\"right\" name=\"2\">\n      <div>good</div>\n    </n-collapse-item>\n  </n-collapse>\n</template>\n"
  },
  {
    "path": "src/collapse/demos/enUS/trigger-areas.demo.vue",
    "content": "<markdown>\n# Trigger areas\n\nIf you want to customize expansion trigger areas of collapse, you can use `trigger-areas` property.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { computed, ref } from 'vue'\n\nconst mainRef = ref(true)\nconst extraRef = ref(true)\nconst arrowRef = ref(true)\nconst triggerAreasRef = computed(() => {\n  const areas: Array<'main' | 'extra' | 'arrow'> = []\n  if (mainRef.value)\n    areas.push('main')\n  if (extraRef.value)\n    areas.push('extra')\n  if (arrowRef.value)\n    areas.push('arrow')\n  return areas\n})\n\n// Export variables for template\nconst main = mainRef\nconst extra = extraRef\nconst arrow = arrowRef\nconst triggerAreas = triggerAreasRef\n</script>\n\n<template>\n  <n-flex vertical>\n    <n-flex>\n      <n-tag v-model:checked=\"main\" checkable>\n        main\n      </n-tag>\n      <n-tag v-model:checked=\"extra\" checkable>\n        extra\n      </n-tag>\n      <n-tag v-model:checked=\"arrow\" checkable>\n        arrow\n      </n-tag>\n    </n-flex>\n    <n-collapse :trigger-areas=\"triggerAreas\">\n      <n-collapse-item title=\"right\" name=\"1\">\n        <template #header-extra>\n          Extra\n        </template>\n        <div>good</div>\n      </n-collapse-item>\n      <n-collapse-item title=\"right\" name=\"2\">\n        <template #header-extra>\n          Extra\n        </template>\n        <div>nice</div>\n      </n-collapse-item>\n      <n-collapse-item title=\"right\" name=\"3\">\n        <template #header-extra>\n          Extra\n        </template>\n        <div>very good</div>\n      </n-collapse-item>\n    </n-collapse>\n  </n-flex>\n</template>\n"
  },
  {
    "path": "src/collapse/demos/zhCN/accordion.demo.vue",
    "content": "<markdown>\n# 手风琴\n\n像一个手风琴\n</markdown>\n\n<template>\n  <n-collapse default-expanded-names=\"1\" accordion>\n    <n-collapse-item title=\"动态类型\" name=\"1\">\n      <div>Python</div>\n    </n-collapse-item>\n    <n-collapse-item title=\"静态类型\" name=\"2\">\n      <div>Java</div>\n    </n-collapse-item>\n  </n-collapse>\n</template>\n"
  },
  {
    "path": "src/collapse/demos/zhCN/arrow-placement.demo.vue",
    "content": "<markdown>\n# 箭头位置\n\n使用 `arrow-placement` 来设定箭头的位置。\n</markdown>\n\n<template>\n  <n-collapse arrow-placement=\"right\">\n    <n-collapse-item title=\"青铜\" name=\"1\">\n      <div>可以</div>\n    </n-collapse-item>\n    <n-collapse-item title=\"白银\" name=\"2\">\n      <div>很好</div>\n    </n-collapse-item>\n    <n-collapse-item title=\"黄金\" name=\"3\">\n      <div>真棒</div>\n    </n-collapse-item>\n  </n-collapse>\n</template>\n"
  },
  {
    "path": "src/collapse/demos/zhCN/basic.demo.vue",
    "content": "<markdown>\n# 基础\n</markdown>\n\n<template>\n  <n-collapse>\n    <n-collapse-item title=\"青铜\" name=\"1\">\n      <div>可以</div>\n    </n-collapse-item>\n    <n-collapse-item title=\"白银\" name=\"2\">\n      <div>很好</div>\n    </n-collapse-item>\n    <n-collapse-item title=\"黄金\" name=\"3\">\n      <div>真棒</div>\n    </n-collapse-item>\n  </n-collapse>\n</template>\n"
  },
  {
    "path": "src/collapse/demos/zhCN/customize-icon.demo.vue",
    "content": "<markdown>\n# 自定义图标\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { CashOutline as CashIcon } from '@vicons/ionicons5'\n</script>\n\n<template>\n  <n-collapse>\n    <template #header-extra>\n      <n-icon><CashIcon /></n-icon>\n    </template>\n    <template #arrow>\n      <n-icon>\n        <CashIcon />\n      </n-icon>\n    </template>\n    <n-collapse-item title=\"青铜\" name=\"1\">\n      <div>可以</div>\n    </n-collapse-item>\n    <n-collapse-item title=\"白银\" name=\"2\">\n      <div>很好</div>\n    </n-collapse-item>\n    <n-collapse-item title=\"黄金\" name=\"3\">\n      <div>真棒</div>\n    </n-collapse-item>\n  </n-collapse>\n</template>\n"
  },
  {
    "path": "src/collapse/demos/zhCN/default-expanded.demo.vue",
    "content": "<markdown>\n# 默认展开\n\n应当注意的是，即使只打算展开一个面板，`default-expanded-names`也应当传入数组，除非使用了`accordion`。\n</markdown>\n\n<template>\n  <n-collapse :default-expanded-names=\"['2', '3']\">\n    <n-collapse-item title=\"绿灯\" name=\"1\">\n      <n-collapse :default-expanded-names=\"['2']\">\n        <n-collapse-item title=\"常亮\" name=\"1\">\n          <div>通过</div>\n        </n-collapse-item>\n        <n-collapse-item title=\"闪烁\" name=\"2\">\n          <div>快速通过</div>\n        </n-collapse-item>\n      </n-collapse>\n    </n-collapse-item>\n    <n-collapse-item title=\"红灯\" name=\"2\">\n      <div>停</div>\n    </n-collapse-item>\n    <n-collapse-item title=\"黄灯\" name=\"3\">\n      <div>注意</div>\n    </n-collapse-item>\n  </n-collapse>\n</template>\n"
  },
  {
    "path": "src/collapse/demos/zhCN/disabled.demo.vue",
    "content": "<markdown>\n# 禁用\n</markdown>\n\n<template>\n  <n-collapse>\n    <n-collapse-item title=\"青铜\" name=\"1\">\n      <div>可以</div>\n    </n-collapse-item>\n    <n-collapse-item title=\"白银\" name=\"2\" disabled>\n      <div>很好</div>\n    </n-collapse-item>\n    <n-collapse-item title=\"黄金\" name=\"3\">\n      <div>真棒</div>\n    </n-collapse-item>\n  </n-collapse>\n</template>\n"
  },
  {
    "path": "src/collapse/demos/zhCN/display-directive.demo.vue",
    "content": "<markdown>\n# 显示指令\n\n设定 `display-directive` 为 `if` 或 `show` 来控制 `n-collapse-item` 里面的 DOM 是否保持。\n</markdown>\n\n<template>\n  <n-collapse display-directive=\"show\">\n    <n-collapse-item title=\"绿灯\" name=\"1\">\n      <n-collapse>\n        <n-collapse-item title=\"常亮\" name=\"1\">\n          <div>通过</div>\n        </n-collapse-item>\n        <n-collapse-item title=\"闪烁\" name=\"2\">\n          <div>快速通过</div>\n        </n-collapse-item>\n      </n-collapse>\n    </n-collapse-item>\n    <n-collapse-item title=\"红灯\" name=\"2\">\n      <div>停</div>\n    </n-collapse-item>\n  </n-collapse>\n</template>\n"
  },
  {
    "path": "src/collapse/demos/zhCN/header-extra.demo.vue",
    "content": "<markdown>\n# 额外信息\n\n在右边放一些信息。\n</markdown>\n\n<template>\n  <n-collapse>\n    <n-collapse-item title=\"张三\" name=\"1\">\n      一周小结：行动是打破平庸最好的回击\n      <template #header-extra>\n        本周工作日工作时长：58 小时\n      </template>\n    </n-collapse-item>\n    <n-collapse-item title=\"李四\" name=\"2\">\n      一周小结：勤奋是获取成功的唯一捷径\n      <template #header-extra>\n        本周工作日工作时长：62 小时\n      </template>\n    </n-collapse-item>\n    <n-collapse-item name=\"3\">\n      <n-text type=\"error\">\n        一周小结：生产队的驴都不敢这么休息，建议优化\n      </n-text>\n      <template #header>\n        <n-text type=\"error\">\n          王五\n        </n-text>\n      </template>\n      <template #header-extra>\n        <n-text type=\"error\">\n          本周工作日工作时长：45 小时\n        </n-text>\n      </template>\n    </n-collapse-item>\n  </n-collapse>\n</template>\n"
  },
  {
    "path": "src/collapse/demos/zhCN/index.demo-entry.md",
    "content": "# 折叠面板 Collapse\n\n我看到它总被用在界面边栏的控制面板上。\n\n## 演示\n\n```demo\nbasic.vue\narrow-placement.vue\naccordion.vue\nnested.vue\ndisplay-directive.vue\nitem-header-click.vue\ncustomize-icon.vue\ndefault-expanded.vue\nheader-extra.vue\ndisabled.vue\ntrigger-areas.vue\nrtl-debug.vue\n```\n\n## API\n\n### Collapse Props\n\n| 名称 | 类型 | 默认值 | 说明 | 版本 |\n| --- | --- | --- | --- | --- |\n| accordion | `boolean` | `false` | 是否只允许展开一个面板 |  |\n| arrow-placement | `'left' \\| 'right'` | `'left'` | 箭头位置 |  |\n| default-expanded-names | `string \\| number \\| Array<string \\| number> \\| null` | `null` | 非受控模式下展开的面板 `name`。`accordion` 模式时不为数组 |  |\n| display-directive | `'if' \\| 'show'` | `'if'` | 内部 `n-collapse-item` 在控制内容是否渲染时使用的指令，`'if'` 对应 `v-if`，`'show'` 对应 `v-show` |  |\n| expanded-names | `string \\| number \\| Array<string \\| number> \\| null` | `undefined` | 受控模式下展开的面板的 `name`，`accordion` 模式时不为数组 |  |\n| trigger-areas | `Array<'main' \\| 'arrow' \\| 'extra'>` | `['main', 'arrow', 'extra']` | 触发展开的区域，如果不想让某些区域触发展开，可以使用此属性 | 2.37.1 |\n| on-item-header-click | `(data: { name: string \\| number, expanded: boolean, event: MouseEvent }) => void` | `undefined` | 点击标题时触发的回调函数 |  |\n| on-update:expanded-names | `(expandedNames: Array<string \\| number> \\| string \\| number \\| null) => void` | `undefined` | 展开内容改变时触发的回调函数 |  |\n\n### CollapseItem Props\n\n| 名称 | 类型 | 默认值 | 说明 | 版本 |\n| --- | --- | --- | --- | --- |\n| disabled | `boolean` | `false` | 是否禁用展开 | 2.32.2 |\n| display-directive | `'if' \\| 'show'` | `undefined` | 自身在控制内容是否渲染时使用的指令，`'if'` 对应 `v-if`，`'show'` 对应 `v-show`。在设定为 `undefined` 的时候跟随外层的 `n-collapse` |  |\n| name | `string \\| number` | 随机字符串 | 名称 |  |\n| title | `string` | `undefined` | 标题 |  |\n\n### Collapse Slots\n\n| 名称 | 参数 | 说明 |\n| --- | --- | --- |\n| arrow | `(props: { collapsed: boolean })` | 折叠面板的自定义图标 |\n| default | `()` | 折叠面板的内容 |\n| header-extra | `(props: { collapsed: boolean })` | 折叠面板节点头部的额外内容 |\n\n### CollapseItem Slots\n\n| 名称 | 参数 | 说明 |\n| --- | --- | --- |\n| arrow | `(props: { collapsed: boolean })` | 折叠面板节点头部的自定义图标 |\n| default | `()` | 折叠面板节点的内容 |\n| header | `(props: { collapsed: boolean })` | 折叠面板节点头部的内容 |\n| header-extra | `(props: { collapsed: boolean })` | 折叠面板节点头部的额外内容 |\n"
  },
  {
    "path": "src/collapse/demos/zhCN/item-header-click.demo.vue",
    "content": "<markdown>\n# 点击标题\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { CollapseProps } from 'naive-ui'\nimport { useMessage } from 'naive-ui'\n\nconst message = useMessage()\nconst handleItemHeaderClick: CollapseProps['onItemHeaderClick'] = ({\n  name,\n  expanded\n}) => {\n  message.info(`Name: ${name}, Expanded: ${expanded}`)\n}\n</script>\n\n<template>\n  <n-collapse @item-header-click=\"handleItemHeaderClick\">\n    <n-collapse-item name=\"1\">\n      <template #header>\n        青铜\n      </template>\n      <div>可以</div>\n    </n-collapse-item>\n    <n-collapse-item name=\"2\">\n      <template #header>\n        白银\n      </template>\n      <div>很好</div>\n    </n-collapse-item>\n    <n-collapse-item name=\"3\">\n      <template #header>\n        黄金\n      </template>\n      <div>真棒</div>\n    </n-collapse-item>\n  </n-collapse>\n</template>\n"
  },
  {
    "path": "src/collapse/demos/zhCN/nested.demo.vue",
    "content": "<markdown>\n# 嵌套\n\n可以嵌套。\n</markdown>\n\n<template>\n  <n-collapse>\n    <n-collapse-item title=\"绿灯\" name=\"1\">\n      <n-collapse>\n        <n-collapse-item title=\"常亮\" name=\"1\">\n          <div>通过</div>\n        </n-collapse-item>\n        <n-collapse-item title=\"闪烁\" name=\"2\">\n          <div>快速通过</div>\n        </n-collapse-item>\n      </n-collapse>\n    </n-collapse-item>\n    <n-collapse-item title=\"红灯\" name=\"2\">\n      <div>停</div>\n    </n-collapse-item>\n  </n-collapse>\n</template>\n"
  },
  {
    "path": "src/collapse/demos/zhCN/rtl-debug.demo.vue",
    "content": "<markdown>\n# Rtl Debug\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { unstableCollapseRtl } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst rtlEnabled = ref(false)\nconst rtlStyles = [unstableCollapseRtl]\n</script>\n\n<template>\n  <n-space vertical>\n    <n-space><n-switch v-model:value=\"rtlEnabled\" />Rtl</n-space>\n    <n-config-provider :rtl=\"rtlEnabled ? rtlStyles : undefined\">\n      <n-collapse>\n        <n-collapse-item title=\"青铜\" name=\"1\">\n          <div>可以</div>\n        </n-collapse-item>\n        <n-collapse-item title=\"白银\" name=\"2\">\n          <div>很好</div>\n        </n-collapse-item>\n        <n-collapse-item title=\"黄金\" name=\"3\">\n          <div>真棒</div>\n        </n-collapse-item>\n      </n-collapse>\n    </n-config-provider>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/collapse/demos/zhCN/trigger-areas.demo.vue",
    "content": "<markdown>\n# 触发展开的区域\n\n当你需要自定义展开区域时，可以使用 `trigger-areas` 属性来指定触发展开的区域。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { computed, ref } from 'vue'\n\nconst mainRef = ref(true)\nconst extraRef = ref(true)\nconst arrowRef = ref(true)\nconst triggerAreasRef = computed(() => {\n  const areas: Array<'main' | 'extra' | 'arrow'> = []\n  if (mainRef.value)\n    areas.push('main')\n  if (extraRef.value)\n    areas.push('extra')\n  if (arrowRef.value)\n    areas.push('arrow')\n  return areas\n})\n\n// 导出为模板可用的变量\nconst main = mainRef\nconst extra = extraRef\nconst arrow = arrowRef\nconst triggerAreas = triggerAreasRef\n</script>\n\n<template>\n  <n-flex vertical>\n    <n-flex>\n      <n-tag v-model:checked=\"main\" checkable>\n        main\n      </n-tag>\n      <n-tag v-model:checked=\"extra\" checkable>\n        extra\n      </n-tag>\n      <n-tag v-model:checked=\"arrow\" checkable>\n        arrow\n      </n-tag>\n    </n-flex>\n    <n-collapse :trigger-areas=\"triggerAreas\">\n      <n-collapse-item title=\"青铜\" name=\"1\">\n        <template #header-extra>\n          Extra\n        </template>\n        <div>可以</div>\n      </n-collapse-item>\n      <n-collapse-item title=\"白银\" name=\"2\">\n        <template #header-extra>\n          Extra\n        </template>\n        <div>很好</div>\n      </n-collapse-item>\n      <n-collapse-item title=\"黄金\" name=\"3\">\n        <template #header-extra>\n          Extra\n        </template>\n        <div>真棒</div>\n      </n-collapse-item>\n    </n-collapse>\n  </n-flex>\n</template>\n"
  },
  {
    "path": "src/collapse/index.ts",
    "content": "export { collapseProps, default as NCollapse } from './src/Collapse'\nexport type { CollapseProps, CollapseSlots } from './src/Collapse'\nexport { collapseItemProps, default as NCollapseItem } from './src/CollapseItem'\nexport type { CollapseItemProps, CollapseItemSlots } from './src/CollapseItem'\nexport type {\n  CollapseArrowSlotProps,\n  CollapseItemArrowSlotProps,\n  CollapseItemHeaderExtraSlotProps,\n  CollapseItemHeaderSlotProps\n} from './src/interface'\n"
  },
  {
    "path": "src/collapse/src/Collapse.tsx",
    "content": "import type {\n  CSSProperties,\n  ExtractPropTypes,\n  PropType,\n  Ref,\n  SlotsType,\n  VNode\n} from 'vue'\nimport type { ThemeProps } from '../../_mixins'\nimport type { ExtractPublicPropTypes, MaybeArray } from '../../_utils'\nimport type { CollapseTheme } from '../styles'\nimport type {\n  CollapseArrowSlotProps,\n  CollapseItemHeaderExtraSlotProps,\n  CollapseItemHeaderSlotProps,\n  HeaderClickInfo,\n  OnItemHeaderClick,\n  OnItemHeaderClickImpl,\n  OnUpdateExpandedNames,\n  OnUpdateExpandedNamesImpl\n} from './interface'\nimport { useMergedState } from 'vooks'\nimport { computed, defineComponent, h, provide, ref } from 'vue'\nimport { useConfig, useTheme, useThemeClass } from '../../_mixins'\nimport { useRtl } from '../../_mixins/use-rtl'\nimport { call, createInjectionKey, warn } from '../../_utils'\nimport { collapseLight } from '../styles'\nimport style from './styles/index.cssr'\n\nexport const collapseProps = {\n  ...(useTheme.props as ThemeProps<CollapseTheme>),\n  defaultExpandedNames: {\n    type: [Array, String] as PropType<\n      string | number | Array<string | number> | null\n    >,\n    default: null\n  },\n  expandedNames: [Array, String] as PropType<\n    string | number | Array<string | number> | null\n  >,\n  arrowPlacement: {\n    type: String as PropType<'left' | 'right'>,\n    default: 'left'\n  },\n  accordion: {\n    type: Boolean,\n    default: false\n  },\n  displayDirective: {\n    type: String as PropType<'if' | 'show'>,\n    default: 'if'\n  },\n  triggerAreas: {\n    type: Array as PropType<Array<'main' | 'extra' | 'arrow'>>,\n    default: () => ['main', 'extra', 'arrow']\n  },\n  onItemHeaderClick: [Function, Array] as PropType<\n    MaybeArray<OnItemHeaderClick>\n  >,\n  'onUpdate:expandedNames': [Function, Array] as PropType<\n    MaybeArray<OnUpdateExpandedNames>\n  >,\n  onUpdateExpandedNames: [Function, Array] as PropType<\n    MaybeArray<OnUpdateExpandedNames>\n  >,\n  // deprecated\n  onExpandedNamesChange: {\n    type: [Function, Array] as PropType<\n      MaybeArray<OnUpdateExpandedNames> | undefined\n    >,\n    validator: () => {\n      if (__DEV__) {\n        warn(\n          'collapse',\n          '`on-expanded-names-change` is deprecated, please use `on-update:expanded-names` instead.'\n        )\n      }\n      return true\n    },\n    default: undefined\n  }\n} as const\n\nexport type CollapseProps = ExtractPublicPropTypes<typeof collapseProps>\n\nexport interface CollapseSlots {\n  default?: () => VNode[]\n  arrow?: (props: CollapseArrowSlotProps) => VNode[]\n  header?: (props: CollapseItemHeaderSlotProps) => VNode[]\n  'header-extra'?: (props: CollapseItemHeaderExtraSlotProps) => VNode[]\n}\n\nexport interface NCollapseInjection {\n  props: ExtractPropTypes<typeof collapseProps>\n  expandedNamesRef: Ref<string | number | Array<string | number> | null>\n  mergedClsPrefixRef: Ref<string>\n  slots: CollapseSlots\n  toggleItem: (\n    collapse: boolean,\n    name: string | number,\n    event: MouseEvent\n  ) => void\n}\n\nexport const collapseInjectionKey\n  = createInjectionKey<NCollapseInjection>('n-collapse')\n\nexport default defineComponent({\n  name: 'Collapse',\n  props: collapseProps,\n  slots: Object as SlotsType<CollapseSlots>,\n  setup(props, { slots }) {\n    const { mergedClsPrefixRef, inlineThemeDisabled, mergedRtlRef }\n      = useConfig(props)\n    const uncontrolledExpandedNamesRef = ref<\n      string | number | Array<string | number> | null\n    >(props.defaultExpandedNames)\n    const controlledExpandedNamesRef = computed(() => props.expandedNames)\n    const mergedExpandedNamesRef = useMergedState(\n      controlledExpandedNamesRef,\n      uncontrolledExpandedNamesRef\n    )\n    const themeRef = useTheme(\n      'Collapse',\n      '-collapse',\n      style,\n      collapseLight,\n      props,\n      mergedClsPrefixRef\n    )\n    function doUpdateExpandedNames(\n      names: Array<string | number> | string | number\n    ): void {\n      const {\n        'onUpdate:expandedNames': _onUpdateExpandedNames,\n        onUpdateExpandedNames,\n        onExpandedNamesChange\n      } = props\n      if (onUpdateExpandedNames) {\n        call(onUpdateExpandedNames as OnUpdateExpandedNamesImpl, names)\n      }\n      if (_onUpdateExpandedNames) {\n        call(_onUpdateExpandedNames as OnUpdateExpandedNamesImpl, names)\n      }\n      if (onExpandedNamesChange) {\n        call(onExpandedNamesChange as OnUpdateExpandedNamesImpl, names)\n      }\n      uncontrolledExpandedNamesRef.value = names\n    }\n    function doItemHeaderClick<T extends string | number>(\n      info: HeaderClickInfo<T>\n    ): void {\n      const { onItemHeaderClick } = props\n      if (onItemHeaderClick) {\n        call(onItemHeaderClick as OnItemHeaderClickImpl, info)\n      }\n    }\n    function toggleItem(\n      collapse: boolean,\n      name: string | number,\n      event: MouseEvent\n    ): void {\n      const { accordion } = props\n      const { value: expandedNames } = mergedExpandedNamesRef\n      if (accordion) {\n        if (collapse) {\n          doUpdateExpandedNames([name])\n          doItemHeaderClick({ name, expanded: true, event })\n        }\n        else {\n          doUpdateExpandedNames([])\n          doItemHeaderClick({ name, expanded: false, event })\n        }\n      }\n      else {\n        if (!Array.isArray(expandedNames)) {\n          doUpdateExpandedNames([name])\n          doItemHeaderClick({ name, expanded: true, event })\n        }\n        else {\n          const activeNames = expandedNames.slice()\n          const index = activeNames.findIndex(\n            activeName => name === activeName\n          )\n          if (~index) {\n            activeNames.splice(index, 1)\n            doUpdateExpandedNames(activeNames)\n            doItemHeaderClick({ name, expanded: false, event })\n          }\n          else {\n            activeNames.push(name)\n            doUpdateExpandedNames(activeNames)\n            doItemHeaderClick({ name, expanded: true, event })\n          }\n        }\n      }\n    }\n    provide(collapseInjectionKey, {\n      props,\n      mergedClsPrefixRef,\n      expandedNamesRef: mergedExpandedNamesRef,\n      slots,\n      toggleItem\n    })\n    const rtlEnabledRef = useRtl('Collapse', mergedRtlRef, mergedClsPrefixRef)\n    const cssVarsRef = computed(() => {\n      const {\n        common: { cubicBezierEaseInOut },\n        self: {\n          titleFontWeight,\n          dividerColor,\n          titlePadding,\n          titleTextColor,\n          titleTextColorDisabled,\n          textColor,\n          arrowColor,\n          fontSize,\n          titleFontSize,\n          arrowColorDisabled,\n          itemMargin\n        }\n      } = themeRef.value\n      return {\n        '--n-font-size': fontSize,\n        '--n-bezier': cubicBezierEaseInOut,\n        '--n-text-color': textColor,\n        '--n-divider-color': dividerColor,\n        '--n-title-padding': titlePadding,\n        '--n-title-font-size': titleFontSize,\n        '--n-title-text-color': titleTextColor,\n        '--n-title-text-color-disabled': titleTextColorDisabled,\n        '--n-title-font-weight': titleFontWeight,\n        '--n-arrow-color': arrowColor,\n        '--n-arrow-color-disabled': arrowColorDisabled,\n        '--n-item-margin': itemMargin\n      }\n    })\n    const themeClassHandle = inlineThemeDisabled\n      ? useThemeClass('collapse', undefined, cssVarsRef, props)\n      : undefined\n    return {\n      rtlEnabled: rtlEnabledRef,\n      mergedTheme: themeRef,\n      mergedClsPrefix: mergedClsPrefixRef,\n      cssVars: inlineThemeDisabled ? undefined : cssVarsRef,\n      themeClass: themeClassHandle?.themeClass,\n      onRender: themeClassHandle?.onRender\n    }\n  },\n  render() {\n    this.onRender?.()\n    return (\n      <div\n        class={[\n          `${this.mergedClsPrefix}-collapse`,\n          this.rtlEnabled && `${this.mergedClsPrefix}-collapse--rtl`,\n          this.themeClass\n        ]}\n        style={this.cssVars as CSSProperties}\n      >\n        {this.$slots}\n      </div>\n    )\n  }\n})\n"
  },
  {
    "path": "src/collapse/src/CollapseItem.tsx",
    "content": "import type { PropType, VNode } from 'vue'\nimport type { ExtractPublicPropTypes } from '../../_utils'\nimport type {\n  CollapseItemArrowSlotProps,\n  CollapseItemHeaderExtraSlotProps,\n  CollapseItemHeaderSlotProps\n} from './interface'\nimport { createId, happensIn } from 'seemly'\nimport { useMemo } from 'vooks'\nimport { computed, defineComponent, h, inject, toRef } from 'vue'\nimport { NBaseIcon } from '../../_internal'\nimport {\n  ChevronLeftIcon as ArrowLeftIcon,\n  ChevronRightIcon as ArrowRightIcon\n} from '../../_internal/icons'\nimport { useConfig } from '../../_mixins'\nimport { useRtl } from '../../_mixins/use-rtl'\nimport {\n  resolveSlotWithTypedProps,\n  resolveWrappedSlotWithProps,\n  throwError\n} from '../../_utils'\nimport { collapseInjectionKey } from './Collapse'\nimport NCollapseItemContent from './CollapseItemContent'\n\nexport const collapseItemProps = {\n  title: String,\n  name: [String, Number] as PropType<string | number>,\n  disabled: Boolean,\n  displayDirective: String as PropType<'if' | 'show'>\n} as const\n\nexport type CollapseItemProps = ExtractPublicPropTypes<typeof collapseItemProps>\n\nexport interface CollapseItemSlots {\n  default?: () => VNode[]\n  header?: (props: CollapseItemHeaderSlotProps) => VNode[]\n  'header-extra'?: (props: CollapseItemHeaderExtraSlotProps) => VNode[]\n  arrow?: (props: CollapseItemArrowSlotProps) => VNode[]\n}\n\nexport default defineComponent({\n  name: 'CollapseItem',\n  props: collapseItemProps,\n  setup(props) {\n    const { mergedRtlRef } = useConfig(props)\n    const randomName = createId()\n    const mergedNameRef = useMemo(() => {\n      return props.name ?? randomName\n    })\n    const NCollapse = inject(collapseInjectionKey)\n    if (!NCollapse) {\n      throwError(\n        'collapse-item',\n        '`n-collapse-item` must be placed inside `n-collapse`.'\n      )\n    }\n    const {\n      expandedNamesRef,\n      props: collapseProps,\n      mergedClsPrefixRef,\n      slots: collapseSlots\n    } = NCollapse\n\n    const collapsedRef = computed<boolean>(() => {\n      const { value: expandedNames } = expandedNamesRef\n      if (Array.isArray(expandedNames)) {\n        const { value: name } = mergedNameRef\n        return !~expandedNames.findIndex(\n          expandedName => expandedName === name\n        )\n      }\n      else if (expandedNames) {\n        const { value: name } = mergedNameRef\n        return name !== expandedNames\n      }\n      return true\n    })\n    const rtlEnabledRef = useRtl('Collapse', mergedRtlRef, mergedClsPrefixRef)\n    return {\n      rtlEnabled: rtlEnabledRef,\n      collapseSlots,\n      randomName,\n      mergedClsPrefix: mergedClsPrefixRef,\n      collapsed: collapsedRef,\n      triggerAreas: toRef(collapseProps, 'triggerAreas'),\n      mergedDisplayDirective: computed<'if' | 'show'>(() => {\n        const { displayDirective } = props\n        if (displayDirective) {\n          return displayDirective\n        }\n        else {\n          return collapseProps.displayDirective\n        }\n      }),\n      arrowPlacement: computed<'left' | 'right'>(() => {\n        return collapseProps.arrowPlacement\n      }),\n      handleClick(e: MouseEvent) {\n        let happensInArea: 'arrow' | 'main' | 'extra' = 'main'\n        if (happensIn(e, 'arrow'))\n          happensInArea = 'arrow'\n        if (happensIn(e, 'extra'))\n          happensInArea = 'extra'\n        if (!collapseProps.triggerAreas.includes(happensInArea)) {\n          return\n        }\n        if (NCollapse && !props.disabled) {\n          NCollapse.toggleItem(collapsedRef.value, mergedNameRef.value, e)\n        }\n      }\n    }\n  },\n  render() {\n    const {\n      collapseSlots,\n      $slots,\n      arrowPlacement,\n      collapsed,\n      mergedDisplayDirective,\n      mergedClsPrefix,\n      disabled,\n      triggerAreas\n    } = this\n    const headerNode = resolveSlotWithTypedProps(\n      $slots.header,\n      { collapsed },\n      () => [this.title]\n    )\n    const headerExtraSlot\n      = $slots['header-extra'] || collapseSlots['header-extra']\n    const arrowSlot = $slots.arrow || collapseSlots.arrow\n    return (\n      <div\n        class={[\n          `${mergedClsPrefix}-collapse-item`,\n          `${mergedClsPrefix}-collapse-item--${arrowPlacement}-arrow-placement`,\n          disabled && `${mergedClsPrefix}-collapse-item--disabled`,\n          !collapsed && `${mergedClsPrefix}-collapse-item--active`,\n          triggerAreas.map((area) => {\n            return `${mergedClsPrefix}-collapse-item--trigger-area-${area}`\n          })\n        ]}\n      >\n        <div\n          class={[\n            `${mergedClsPrefix}-collapse-item__header`,\n            !collapsed && `${mergedClsPrefix}-collapse-item__header--active`\n          ]}\n        >\n          <div\n            class={`${mergedClsPrefix}-collapse-item__header-main`}\n            onClick={this.handleClick}\n          >\n            {arrowPlacement === 'right' && headerNode}\n            <div\n              class={`${mergedClsPrefix}-collapse-item-arrow`}\n              key={this.rtlEnabled ? 0 : 1}\n              data-arrow\n            >\n              {resolveSlotWithTypedProps(arrowSlot, { collapsed }, () => [\n                <NBaseIcon clsPrefix={mergedClsPrefix}>\n                  {{\n                    default: () =>\n                      this.rtlEnabled ? <ArrowLeftIcon /> : <ArrowRightIcon />\n                  }}\n                </NBaseIcon>\n              ])}\n            </div>\n            {arrowPlacement === 'left' && headerNode}\n          </div>\n          {resolveWrappedSlotWithProps(\n            headerExtraSlot,\n            { collapsed },\n            children => (\n              <div\n                class={`${mergedClsPrefix}-collapse-item__header-extra`}\n                onClick={this.handleClick}\n                data-extra\n              >\n                {children}\n              </div>\n            )\n          )}\n        </div>\n        <NCollapseItemContent\n          clsPrefix={mergedClsPrefix}\n          displayDirective={mergedDisplayDirective}\n          show={!collapsed}\n        >\n          {$slots}\n        </NCollapseItemContent>\n      </div>\n    )\n  }\n})\n"
  },
  {
    "path": "src/collapse/src/CollapseItemContent.tsx",
    "content": "import type { PropType } from 'vue'\nimport { useFalseUntilTruthy } from 'vooks'\nimport { defineComponent, h, toRef, vShow, withDirectives } from 'vue'\nimport { NFadeInExpandTransition } from '../../_internal'\n\nexport default defineComponent({\n  name: 'CollapseItemContent',\n  props: {\n    displayDirective: {\n      type: String as PropType<'if' | 'show'>,\n      required: true\n    },\n    show: Boolean,\n    clsPrefix: {\n      type: String,\n      required: true\n    }\n  },\n  setup(props) {\n    const onceTrueRef = useFalseUntilTruthy(toRef(props, 'show'))\n    return {\n      onceTrue: onceTrueRef\n    }\n  },\n  render() {\n    return (\n      <NFadeInExpandTransition>\n        {{\n          default: () => {\n            const { show, displayDirective, onceTrue, clsPrefix } = this\n            const useVShow = displayDirective === 'show' && onceTrue\n            const contentNode = (\n              <div class={`${clsPrefix}-collapse-item__content-wrapper`}>\n                <div class={`${clsPrefix}-collapse-item__content-inner`}>\n                  {this.$slots}\n                </div>\n              </div>\n            )\n            return useVShow\n              ? withDirectives(contentNode, [[vShow, show]])\n              : show\n                ? contentNode\n                : null\n          }\n        }}\n      </NFadeInExpandTransition>\n    )\n  }\n})\n"
  },
  {
    "path": "src/collapse/src/interface.ts",
    "content": "export type OnUpdateExpandedNames = <\n  T extends string[]\n  & number[]\n  & Array<string | number>\n  & (string | number | null)\n  & (string | null)\n  & (number | null)\n>(\n  value: T\n) => void\n\nexport type OnUpdateExpandedNamesImpl = <\n  T extends\n  | string[]\n  | number[]\n  | Array<string | number>\n  | (string | number | null)\n  | (string | null)\n  | (number | null)\n>(\n  value: T\n) => void\n\nexport type OnItemHeaderClick = <T extends string & number & (string | number)>(\n  info: HeaderClickInfo<T>\n) => void\n\nexport type OnItemHeaderClickImpl = <\n  T extends string | number | (string | number)\n>(\n  info: HeaderClickInfo<T>\n) => void\n\nexport interface HeaderClickInfo<T> {\n  name: T\n  expanded: boolean\n  event: MouseEvent\n}\n\nexport interface CollapseArrowSlotProps {\n  collapsed: boolean\n}\n\nexport interface CollapseItemHeaderSlotProps {\n  collapsed: boolean\n}\n\nexport interface CollapseItemHeaderExtraSlotProps {\n  collapsed: boolean\n}\n\nexport interface CollapseItemArrowSlotProps {\n  collapsed: boolean\n}\n"
  },
  {
    "path": "src/collapse/src/styles/index.cssr.ts",
    "content": "import { fadeInHeightExpandTransition } from '../../../_styles/transitions/fade-in-height-expand.cssr'\nimport { c, cB, cE, cM, cNotM } from '../../../_utils/cssr'\n\n// vars:\n// --n-font-size\n// --n-bezier\n// --n-text-color\n// --n-divider-color\n// --n-title-padding\n// --n-title-font-size\n// --n-title-text-color\n// --n-title-font-weight\n// --n-arrow-color\n// --n-arrow-color-disabled\n// --n-title-text-color-disabled\n// --n-item-margin\nexport default cB('collapse', 'width: 100%;', [\n  cB('collapse-item', `\n    font-size: var(--n-font-size);\n    color: var(--n-text-color);\n    transition:\n      color .3s var(--n-bezier),\n      border-color .3s var(--n-bezier);\n    margin: var(--n-item-margin);\n  `, [\n    cM('disabled', [\n      cE('header', 'cursor: not-allowed;', [\n        cE('header-main', `\n          color: var(--n-title-text-color-disabled);\n        `),\n        cB('collapse-item-arrow', `\n          color: var(--n-arrow-color-disabled);\n        `)\n      ])\n    ]),\n    cB('collapse-item', 'margin-left: 32px;'),\n    c('&:first-child', 'margin-top: 0;'),\n    c('&:first-child >', [\n      cE('header', 'padding-top: 0;')\n    ]),\n    cM('left-arrow-placement', [\n      cE('header', [\n        cB('collapse-item-arrow', 'margin-right: 4px;')\n      ])\n    ]),\n    cM('right-arrow-placement', [\n      cE('header', [\n        cB('collapse-item-arrow', 'margin-left: 4px;')\n      ])\n    ]),\n    cE('content-wrapper', [\n      cE('content-inner', 'padding-top: 16px;'),\n      fadeInHeightExpandTransition({ duration: '0.15s' })\n    ]),\n    cM('active', [\n      cE('header', [\n        cM('active', [\n          cB('collapse-item-arrow', 'transform: rotate(90deg);')\n        ])\n      ])\n    ]),\n    c('&:not(:first-child)', 'border-top: 1px solid var(--n-divider-color);'),\n    cNotM('disabled', [\n      cM('trigger-area-main', [\n        cE('header', [\n          cE('header-main', 'cursor: pointer;'),\n          cB('collapse-item-arrow', 'cursor: default;')\n        ])\n      ]),\n      cM('trigger-area-arrow', [\n        cE('header', [\n          cB('collapse-item-arrow', 'cursor: pointer;')\n        ])\n      ]),\n      cM('trigger-area-extra', [\n        cE('header', [\n          cE('header-extra', 'cursor: pointer;')\n        ])\n      ])\n    ]),\n    cE('header', `\n      font-size: var(--n-title-font-size);\n      display: flex;\n      flex-wrap: nowrap;\n      align-items: center;\n      transition: color .3s var(--n-bezier);\n      position: relative;\n      padding: var(--n-title-padding);\n      color: var(--n-title-text-color);\n    `, [\n      cE('header-main', `\n        display: flex;\n        flex-wrap: nowrap;\n        align-items: center;\n        font-weight: var(--n-title-font-weight);\n        transition: color .3s var(--n-bezier);\n        flex: 1;\n        color: var(--n-title-text-color);\n      `),\n      cE('header-extra', `\n        display: flex;\n        align-items: center;\n        transition: color .3s var(--n-bezier);\n        color: var(--n-text-color);\n      `),\n      cB('collapse-item-arrow', `\n        display: flex;\n        transition:\n          transform .15s var(--n-bezier),\n          color .3s var(--n-bezier);\n        font-size: 18px;\n        color: var(--n-arrow-color);\n      `)\n    ])\n  ])\n])\n"
  },
  {
    "path": "src/collapse/src/styles/rtl.cssr.ts",
    "content": "import { cB, cE, cM } from '../../../_utils/cssr'\n\nexport default cB('collapse', [\n  cM('rtl', `\n    direction: rtl;\n  `, [\n    cB('collapse-item', [\n      cB('collapse-item', {\n        marginRight: '32px',\n        marginLeft: 0\n      }),\n      cM('left-arrow-placement', [\n        cE('header', [\n          cB('collapse-item-arrow', {\n            marginRight: 0,\n            marginLeft: '4px'\n          })\n        ])\n      ]),\n      cM('right-arrow-placement', [\n        cE('header', [\n          cB('collapse-item-arrow', {\n            marginLeft: 0,\n            marginRight: '4px'\n          })\n        ])\n      ]),\n      cM('active', [\n        cE('header', [\n          cM('active', [\n            cB('collapse-item-arrow', {\n              transform: 'rotate(-90deg)'\n            })\n          ])\n        ])\n      ])\n    ])\n  ])\n])\n"
  },
  {
    "path": "src/collapse/styles/dark.ts",
    "content": "import type { CollapseTheme } from './light'\nimport { commonDark } from '../../_styles/common'\nimport { self } from './light'\n\nconst collapseDark: CollapseTheme = {\n  name: 'Collapse',\n  common: commonDark,\n  self\n}\n\nexport default collapseDark\n"
  },
  {
    "path": "src/collapse/styles/index.ts",
    "content": "export { default as collapseDark } from './dark'\nexport { default as collapseLight } from './light'\nexport type { CollapseTheme, CollapseThemeVars } from './light'\nexport { collapseRtl } from './rtl'\n"
  },
  {
    "path": "src/collapse/styles/light.ts",
    "content": "import type { Theme } from '../../_mixins/use-theme'\nimport type { ThemeCommonVars } from '../../_styles/common'\nimport { commonLight } from '../../_styles/common'\n\nexport function self(vars: ThemeCommonVars) {\n  const {\n    fontWeight,\n    textColor1,\n    textColor2,\n    textColorDisabled,\n    dividerColor,\n    fontSize\n  } = vars\n  return {\n    titleFontSize: fontSize,\n    titleFontWeight: fontWeight,\n    dividerColor,\n    titleTextColor: textColor1,\n    titleTextColorDisabled: textColorDisabled,\n    fontSize,\n    textColor: textColor2,\n    arrowColor: textColor2,\n    arrowColorDisabled: textColorDisabled,\n    itemMargin: '16px 0 0 0',\n    titlePadding: '16px 0 0 0'\n  }\n}\n\nexport type CollapseThemeVars = ReturnType<typeof self>\n\nconst collapseLight: Theme<'Collapse', CollapseThemeVars> = {\n  name: 'Collapse',\n  common: commonLight,\n  self\n}\n\nexport default collapseLight\nexport type CollapseTheme = typeof collapseLight\n"
  },
  {
    "path": "src/collapse/styles/rtl.ts",
    "content": "import type { RtlItem } from '../../config-provider/src/internal-interface'\nimport rtlStyle from '../src/styles/rtl.cssr'\n\nexport const collapseRtl: RtlItem = {\n  name: 'Collapse',\n  style: rtlStyle\n}\n"
  },
  {
    "path": "src/collapse/tests/Collapse.spec.tsx",
    "content": "import { mount } from '@vue/test-utils'\nimport { h } from 'vue'\nimport { NCollapse, NCollapseItem } from '../index'\n\ndescribe('n-collapse', () => {\n  it('should work with import on demand', () => {\n    mount(NCollapse)\n  })\n\n  it('can customize icon', () => {\n    const wrapper = mount(() => {\n      return (\n        <NCollapse>\n          {{\n            arrow: () => <div class=\"my-icon\"></div>,\n            default: () => <NCollapseItem name=\"1\"></NCollapseItem>\n          }}\n        </NCollapse>\n      )\n    })\n    expect(wrapper.find('.my-icon').exists()).toEqual(true)\n    wrapper.unmount()\n  })\n\n  it('should work with `accordion` prop', async () => {\n    const wrapper = mount(NCollapse, {\n      slots: {\n        default: () => [\n          <NCollapseItem name=\"1\">\n            {{ default: () => <div class=\"ci1\">ci1</div> }}\n          </NCollapseItem>,\n          <NCollapseItem name=\"2\">\n            {{ default: () => <div class=\"ci2\">ci2</div> }}\n          </NCollapseItem>,\n          <NCollapseItem name=\"3\">\n            {{ default: () => <div class=\"ci3\">ci3</div> }}\n          </NCollapseItem>\n        ]\n      }\n    })\n\n    const headerMains = wrapper.findAll('.n-collapse-item__header-main')\n    await headerMains[0].trigger('click')\n    await headerMains[1].trigger('click')\n\n    expect(wrapper.findAll('.n-collapse-item__header')[0].classes()).toContain(\n      'n-collapse-item__header--active'\n    )\n    expect(wrapper.findAll('.n-collapse-item__header')[1].classes()).toContain(\n      'n-collapse-item__header--active'\n    )\n\n    await wrapper.setProps({\n      accordion: true\n    })\n\n    await headerMains[2].trigger('click')\n    expect(\n      wrapper.findAll('.n-collapse-item__header')[0].classes()\n    ).not.toContain('n-collapse-item__header--active')\n    expect(\n      wrapper.findAll('.n-collapse-item__header')[1].classes()\n    ).not.toContain('n-collapse-item__header--active')\n    expect(wrapper.findAll('.n-collapse-item__header')[2].classes()).toContain(\n      'n-collapse-item__header--active'\n    )\n    wrapper.unmount()\n  })\n\n  it('should work with `arrow-placement` prop', async () => {\n    const wrapper = mount(NCollapse, {\n      slots: {\n        default: () => <NCollapseItem name=\"1\"></NCollapseItem>\n      }\n    })\n    expect(wrapper.find('.n-collapse-item').classes()).toContain(\n      'n-collapse-item--left-arrow-placement'\n    )\n\n    await wrapper.setProps({ arrowPlacement: 'right' })\n    expect(wrapper.find('.n-collapse-item').classes()).toContain(\n      'n-collapse-item--right-arrow-placement'\n    )\n    wrapper.unmount()\n  })\n\n  it('should work with nested structure', async () => {\n    const wrapper = mount(NCollapse, {\n      slots: {\n        default: () =>\n          h(\n            NCollapseItem,\n            { name: '1' },\n            {\n              default: () =>\n                h(NCollapse, null, {\n                  default: () => h(NCollapseItem, { name: '2' })\n                })\n            }\n          )\n      }\n    })\n\n    await wrapper.find('.n-collapse-item__header-main').trigger('click')\n    expect(wrapper.find('.n-collapse-item__header').classes()).toContain(\n      'n-collapse-item__header--active'\n    )\n    await wrapper\n      .find('.n-collapse-item__content-wrapper')\n      .find('.n-collapse-item__header-main')\n      .trigger('click')\n    expect(\n      wrapper\n        .find('.n-collapse-item__content-wrapper')\n        .find('.n-collapse-item__header')\n        .classes()\n    ).toContain('n-collapse-item__header--active')\n    wrapper.unmount()\n  })\n\n  it('should work with `display-directive` prop', async () => {\n    const wrapper = mount(NCollapse, {\n      props: {\n        displayDirective: 'show'\n      },\n      slots: {\n        default: () =>\n          h(\n            NCollapseItem,\n            { name: '1' },\n            { default: () => h('div', null, { default: () => 'test' }) }\n          )\n      }\n    })\n\n    await wrapper.find('.n-collapse-item__header-main').trigger('click')\n    await wrapper.find('.n-collapse-item__header-main').trigger('click')\n    expect(\n      wrapper.find('.n-collapse-item__content-wrapper').attributes('style')\n    ).toBe('display: none;')\n\n    await wrapper.setProps({\n      displayDirective: 'if'\n    })\n\n    await wrapper.find('.n-collapse-item__header-main').trigger('click')\n    await wrapper.find('.n-collapse-item__header-main').trigger('click')\n    expect(wrapper.find('.n-collapse-item__content-wrapper').exists()).toBe(\n      false\n    )\n    wrapper.unmount()\n  })\n\n  it('should work with `on-item-header-click` prop', async () => {\n    const onClick = vi.fn()\n    const wrapper = mount(NCollapse, {\n      props: {\n        onItemHeaderClick: onClick\n      },\n      slots: {\n        default: () => <NCollapseItem name=\"1\"></NCollapseItem>\n      }\n    })\n    const triggerNodeWrapper = wrapper.find('.n-collapse-item__header-main')\n    await triggerNodeWrapper.trigger('click')\n    expect(onClick).toHaveBeenCalled()\n    wrapper.unmount()\n  })\n\n  it('should work with `slots` ', async () => {\n    const wrapper = mount(NCollapse, {\n      slots: {\n        header: () => 'header',\n        'header-extra': () => 'header-extra',\n        default: () => <NCollapseItem name=\"1\"></NCollapseItem>,\n        arrow: () => 'arrow'\n      }\n    })\n    expect(wrapper.find('.n-collapse-item__header-main').exists()).toBe(true)\n    expect(wrapper.find('.n-collapse-item__header-main').text()).toBe('arrow')\n\n    expect(wrapper.find('.n-collapse-item__header-extra').exists()).toBe(true)\n    expect(wrapper.find('.n-collapse-item__header-extra').text()).toBe(\n      'header-extra'\n    )\n\n    expect(wrapper.find('.n-collapse-item-arrow').exists()).toBe(true)\n    expect(wrapper.find('.n-collapse-item-arrow').text()).toBe('arrow')\n    wrapper.unmount()\n  })\n\n  it('props.defaultExpandedNames', async () => {\n    let wrapper = mount(NCollapse, {\n      props: {\n        defaultExpandedNames: ['1']\n      },\n      slots: {\n        default: () => [\n          <NCollapseItem name=\"1\">\n            {{ default: () => <div class=\"ci1\"></div> }}\n          </NCollapseItem>,\n          <NCollapseItem name=\"2\">\n            {{ default: () => <div class=\"ci2\"></div> }}\n          </NCollapseItem>\n        ]\n      }\n    })\n    expect(wrapper.find('.ci1').isVisible()).toEqual(true)\n    expect(wrapper.find('.ci2').exists()).toEqual(false)\n    wrapper = mount(NCollapse, {\n      props: {\n        accordion: true,\n        defaultExpandedNames: '1'\n      },\n      slots: {\n        default: () => [\n          <NCollapseItem name=\"1\">\n            {{ default: () => <div class=\"ci1\"></div> }}\n          </NCollapseItem>,\n          <NCollapseItem name=\"2\">\n            {{ default: () => <div class=\"ci2\"></div> }}\n          </NCollapseItem>\n        ]\n      }\n    })\n    expect(wrapper.find('.ci1').isVisible()).toEqual(true)\n    expect(wrapper.find('.ci2').exists()).toEqual(false)\n    wrapper.unmount()\n  })\n\n  it('should work with collapseItem component `title` prop', async () => {\n    const wrapper = mount(NCollapse, {\n      slots: {\n        default: () => <NCollapseItem title=\"test\"></NCollapseItem>\n      }\n    })\n\n    await wrapper.find('.n-collapse-item__header-main').trigger('click')\n    expect(wrapper.find('.n-collapse-item__header-main').text()).toBe('test')\n    wrapper.unmount()\n  })\n})\n"
  },
  {
    "path": "src/collapse/tests/server.spec.tsx",
    "content": "import { setup } from '@css-render/vue3-ssr'\nimport { renderToString } from '@vue/server-renderer'\n/**\n * @vitest-environment node\n */\nimport { createSSRApp, h } from 'vue'\nimport { NCollapse } from '../..'\n\ndescribe('server side rendering', () => {\n  it('works', async () => {\n    const app = createSSRApp(() => <NCollapse />)\n    setup(app)\n    try {\n      await renderToString(app)\n    }\n    catch (e) {\n      expect(e).not.toBeTruthy()\n    }\n  })\n})\n"
  },
  {
    "path": "src/collapse-transition/demos/enUS/basic.demo.vue",
    "content": "<markdown>\n# Basic\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst show = ref(true)\n</script>\n\n<template>\n  <n-space vertical>\n    <n-switch v-model:value=\"show\">\n      <template #checked>\n        Show\n      </template>\n      <template #unchecked>\n        Hide\n      </template>\n    </n-switch>\n    <n-collapse-transition :show=\"show\">\n      \"There is no single development, in either technology or management\n      technique, which by itself promises even one order of magnitude [tenfold]\n      improvement within a decade in productivity, in reliability, in\n      simplicity.\"\n    </n-collapse-transition>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/collapse-transition/demos/enUS/index.demo-entry.md",
    "content": "# Collapse Transition\n\nA collapse item without any form of encapsulation.\n\n## Demos\n\n```demo\nbasic.vue\n```\n\n## API\n\n### CollapseTransition Props\n\n| Name   | Type      | Default | Description                                 |\n| ------ | --------- | ------- | ------------------------------------------- |\n| appear | `boolean` | `false` | Whether to play animation on first mounted. |\n| show   | `boolean` | `true`  | Whether to show content.                    |\n\n### CollapseTransition Slots\n\n| Name    | Parameters | Description                        |\n| ------- | ---------- | ---------------------------------- |\n| default | `()`       | The content inside the transition. |\n"
  },
  {
    "path": "src/collapse-transition/demos/zhCN/basic.demo.vue",
    "content": "<markdown>\n# 基本用法\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst show = ref(true)\n</script>\n\n<template>\n  <n-space vertical>\n    <n-switch v-model:value=\"show\">\n      <template #checked>\n        展开\n      </template>\n      <template #unchecked>\n        折叠\n      </template>\n    </n-switch>\n    <n-collapse-transition :show=\"show\">\n      感知度，方法论，组合拳，引爆点，点线面，精细化，差异化，平台化，结构化，影响力，耦合性，便捷性，一致性，端到端，短平快，护城河，体验感，颗粒度\n    </n-collapse-transition>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/collapse-transition/demos/zhCN/index.demo-entry.md",
    "content": "# 折叠渐变 Collapse Transition\n\n一个没什么封装的 collapse item。\n\n## 演示\n\n```demo\nbasic.vue\nrtl-debug.vue\n```\n\n## API\n\n### CollapseTransition Props\n\n| 名称   | 类型      | 默认值  | 说明                     |\n| ------ | --------- | ------- | ------------------------ |\n| appear | `boolean` | `false` | 是否在首次出现时播放动画 |\n| show   | `boolean` | `true`  | 是否展示内容             |\n\n### CollapseTransition Slots\n\n| 名称    | 参数 | 说明       |\n| ------- | ---- | ---------- |\n| default | `()` | 渐变的内容 |\n"
  },
  {
    "path": "src/collapse-transition/demos/zhCN/rtl-debug.demo.vue",
    "content": "<markdown>\n# Rtl Debug\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { unstableCollapseTransitionRtl } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst rtlEnabled = ref(false)\nconst rtlStyles = [unstableCollapseTransitionRtl]\nconst show = ref(true)\n</script>\n\n<template>\n  <n-space vertical>\n    <n-space><n-switch v-model:value=\"rtlEnabled\" />Rtl</n-space>\n    <n-config-provider :rtl=\"rtlEnabled ? rtlStyles : undefined\">\n      <n-space vertical>\n        <n-switch v-model:value=\"show\">\n          <template #checked>\n            Show\n          </template>\n          <template #unchecked>\n            Hide\n          </template>\n        </n-switch>\n        <n-collapse-transition :show=\"show\">\n          感知度，方法论，组合拳，引爆点，点线面，精细化，差异化，平台化，结构化，影响力，耦合性，便捷性，一致性，端到端，短平快，护城河，体验感，颗粒度\n        </n-collapse-transition>\n      </n-space>\n    </n-config-provider>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/collapse-transition/index.ts",
    "content": "export {\n  collapseTransitionProps,\n  default as NCollapseTransition\n} from './src/CollapseTransition'\nexport type { CollapseTransitionProps } from './src/CollapseTransition'\n"
  },
  {
    "path": "src/collapse-transition/src/CollapseTransition.tsx",
    "content": "import type { PropType } from 'vue'\nimport type { ThemeProps } from '../../_mixins'\nimport type { ExtractPublicPropTypes } from '../../_utils'\nimport type { CollapseTransitionTheme } from '../styles'\nimport { computed, defineComponent, h, mergeProps, watchEffect } from 'vue'\nimport { NFadeInExpandTransition } from '../../_internal'\nimport { useConfig, useTheme, useThemeClass } from '../../_mixins'\nimport { useRtl } from '../../_mixins/use-rtl'\nimport { warnOnce } from '../../_utils'\nimport { collapseTransitionLight } from '../styles'\nimport style from './styles/index.cssr'\n\nexport const collapseTransitionProps = {\n  ...(useTheme.props as ThemeProps<CollapseTransitionTheme>),\n  show: {\n    type: Boolean,\n    default: true\n  },\n  appear: Boolean,\n  // The collapsed is implemented with mistake, collapsed=true would make it show\n  // However there's no possibility to change so I just let it deprecated and use\n  // `show` prop instead.\n  /** @deprecated */\n  collapsed: {\n    type: Boolean as PropType<boolean | undefined>,\n    default: undefined\n  }\n} as const\n\nexport type CollapseTransitionProps = ExtractPublicPropTypes<\n  typeof collapseTransitionProps\n>\n\nexport default defineComponent({\n  name: 'CollapseTransition',\n  props: collapseTransitionProps,\n  inheritAttrs: false,\n  setup(props) {\n    if (__DEV__) {\n      watchEffect(() => {\n        if (props.collapsed !== undefined) {\n          warnOnce(\n            'collapse-transition',\n            '`collapsed` is deprecated, please use `show` instead'\n          )\n        }\n      })\n    }\n    const { mergedClsPrefixRef, inlineThemeDisabled, mergedRtlRef }\n      = useConfig(props)\n    const mergedThemeRef = useTheme(\n      'CollapseTransition',\n      '-collapse-transition',\n      style,\n      collapseTransitionLight,\n      props,\n      mergedClsPrefixRef\n    )\n    const rtlEnabledRef = useRtl(\n      'CollapseTransition',\n      mergedRtlRef,\n      mergedClsPrefixRef\n    )\n    const mergedShowRef = computed(() => {\n      if (props.collapsed !== undefined) {\n        // No mistake, it's implemented with error at first, just keep it here\n        return props.collapsed\n      }\n      return props.show\n    })\n\n    const cssVarsRef = computed(() => {\n      const {\n        self: { bezier }\n      } = mergedThemeRef.value\n      return {\n        '--n-bezier': bezier\n      }\n    })\n    const themeClassHandle = inlineThemeDisabled\n      ? useThemeClass('collapse-transition', undefined, cssVarsRef, props)\n      : undefined\n\n    return {\n      rtlEnabled: rtlEnabledRef,\n      mergedShow: mergedShowRef,\n      mergedClsPrefix: mergedClsPrefixRef,\n      cssVars: inlineThemeDisabled ? undefined : cssVarsRef,\n      themeClass: themeClassHandle?.themeClass,\n      onRender: themeClassHandle?.onRender\n    }\n  },\n  render() {\n    return (\n      <NFadeInExpandTransition appear={this.appear}>\n        {{\n          default: () => {\n            if (!this.mergedShow)\n              return\n            this.onRender?.()\n            return h(\n              'div', // Don't use jsx since it would cause useless spread in each rendering\n              mergeProps(\n                {\n                  class: [\n                    `${this.mergedClsPrefix}-collapse-transition`,\n                    this.rtlEnabled\n                    && `${this.mergedClsPrefix}-collapse-transition--rtl`,\n                    this.themeClass\n                  ],\n                  style: this.cssVars\n                },\n                this.$attrs\n              ),\n              this.$slots\n            )\n          }\n        }}\n      </NFadeInExpandTransition>\n    )\n  }\n})\n"
  },
  {
    "path": "src/collapse-transition/src/styles/index.cssr.ts",
    "content": "import { fadeInHeightExpandTransition } from '../../../_styles/transitions/fade-in-height-expand.cssr'\nimport { cB } from '../../../_utils/cssr'\n\nexport default cB('collapse-transition', {\n  width: '100%'\n}, [\n  fadeInHeightExpandTransition()\n])\n"
  },
  {
    "path": "src/collapse-transition/src/styles/rtl.cssr.ts",
    "content": "import { cB, cM } from '../../../_utils/cssr'\n\nexport default cB('collapse-transition', [\n  cM('rtl', `\n    direction: rtl;\n    text-align: right;\n  `)\n])\n"
  },
  {
    "path": "src/collapse-transition/styles/dark.ts",
    "content": "import type { CollapseTransitionTheme } from './light'\nimport { commonDark } from '../../_styles/common'\nimport { self } from './light'\n\nconst collapseTransitionDark: CollapseTransitionTheme = {\n  name: 'CollapseTransition',\n  common: commonDark,\n  self\n}\n\nexport default collapseTransitionDark\n"
  },
  {
    "path": "src/collapse-transition/styles/index.ts",
    "content": "export { default as collapseTransitionDark } from './dark'\nexport { default as collapseTransitionLight } from './light'\nexport type {\n  CollapseTransitionTheme,\n  CollapseTransitionThemeVars\n} from './light'\nexport { collapseTransitionRtl } from './rtl'\n"
  },
  {
    "path": "src/collapse-transition/styles/light.ts",
    "content": "import type { Theme } from '../../_mixins/use-theme'\nimport type { ThemeCommonVars } from '../../_styles/common'\nimport { commonLight } from '../../_styles/common'\n\nexport function self(vars: ThemeCommonVars) {\n  const { cubicBezierEaseInOut } = vars\n  return {\n    bezier: cubicBezierEaseInOut\n  }\n}\n\nexport type CollapseTransitionThemeVars = ReturnType<typeof self>\n\nconst collapseTransitionLight: Theme<\n  'CollapseTransition',\n  CollapseTransitionThemeVars\n> = {\n  name: 'CollapseTransition',\n  common: commonLight,\n  self\n}\n\nexport default collapseTransitionLight\nexport type CollapseTransitionTheme = typeof collapseTransitionLight\n"
  },
  {
    "path": "src/collapse-transition/styles/rtl.ts",
    "content": "import type { RtlItem } from '../../config-provider/src/internal-interface'\nimport rtlStyle from '../src/styles/rtl.cssr'\n\nexport const collapseTransitionRtl: RtlItem = {\n  name: 'CollapseTransition',\n  style: rtlStyle\n}\n"
  },
  {
    "path": "src/collapse-transition/tests/CollapseTransition.spec.tsx",
    "content": "import { mount } from '@vue/test-utils'\nimport { NCollapseTransition } from '../index'\n\ndescribe('n-collapse', () => {\n  it('should work with import on demand', () => {\n    mount(NCollapseTransition)\n  })\n\n  it('should work with `show` prop', async () => {\n    const wrapper = mount(NCollapseTransition)\n    expect(wrapper.find('.n-collapse-transition').exists()).toBe(true)\n\n    await wrapper.setProps({ show: false })\n    expect(wrapper.find('.n-collapse-transition').exists()).toBe(false)\n    wrapper.unmount()\n  })\n\n  it('should work with `default` slot', async () => {\n    const wrapper = mount(NCollapseTransition, {\n      slots: { default: () => 'test' }\n    })\n    expect(wrapper.find('.n-collapse-transition').exists()).toBe(true)\n    expect(wrapper.find('.n-collapse-transition').text()).toBe('test')\n    wrapper.unmount()\n  })\n})\n"
  },
  {
    "path": "src/collapse-transition/tests/server.spec.tsx",
    "content": "import { setup } from '@css-render/vue3-ssr'\nimport { renderToString } from '@vue/server-renderer'\n/**\n * @vitest-environment node\n */\nimport { createSSRApp, h } from 'vue'\nimport { NCollapse } from '../..'\n\ndescribe('server side rendering', () => {\n  it('works', async () => {\n    const app = createSSRApp(() => <NCollapse />)\n    setup(app)\n    try {\n      await renderToString(app)\n    }\n    catch (e) {\n      expect(e).not.toBeTruthy()\n    }\n  })\n})\n"
  },
  {
    "path": "src/color-picker/demos/enUS/actions.demo.vue",
    "content": "<markdown>\n# Clearable\n\nIf you want the color picker to be clearable, you can add `'clear'` in `'actions'` prop.\n</markdown>\n\n<template>\n  <n-color-picker :actions=\"['clear']\" />\n</template>\n"
  },
  {
    "path": "src/color-picker/demos/enUS/alpha.demo.vue",
    "content": "<markdown>\n# Alpha\n\nUse `show-alpha` to control whether the alpha channel can be adjusted.\n</markdown>\n\n<script lang=\"ts\" setup>\nfunction handleConfirm(value: string) {\n  console.log(value)\n}\n</script>\n\n<template>\n  <n-color-picker\n    :show-alpha=\"false\"\n    :actions=\"['confirm']\"\n    @confirm=\"handleConfirm\"\n  />\n</template>\n"
  },
  {
    "path": "src/color-picker/demos/enUS/basic.demo.vue",
    "content": "<markdown>\n# Basic\n\nA basic color picker. Note: when choosing a color in a particular mode, that's the mode that will be used.\n</markdown>\n\n<template>\n  <n-color-picker />\n</template>\n"
  },
  {
    "path": "src/color-picker/demos/enUS/disabled.demo.vue",
    "content": "<markdown>\n# Disabled\n</markdown>\n\n<template>\n  <n-color-picker disabled />\n</template>\n"
  },
  {
    "path": "src/color-picker/demos/enUS/form.demo.vue",
    "content": "<markdown>\n# Use with form\n\nIt seems this example is useless, but it's a data input component so I just left it here.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { reactive } from 'vue'\n\nconst model = reactive({\n  color: '#18A058'\n})\n\nconst colorRule = {\n  trigger: 'change',\n  validator(_: unknown, value: string) {\n    if (value !== '#18A058')\n      return new Error('Don\\'t change the color')\n  }\n}\n</script>\n\n<template>\n  <n-form :model=\"model\">\n    <n-form-item label=\"Color(#18A058)\" path=\"color\" :rule=\"colorRule\">\n      <n-color-picker v-model:value=\"model.color\" :show-alpha=\"false\" />\n    </n-form-item>\n  </n-form>\n</template>\n"
  },
  {
    "path": "src/color-picker/demos/enUS/index.demo-entry.md",
    "content": "# Color Picker\n\nUnlike the real world, these color values are discrete.\n\n## Demos\n\n```demo\nbasic.vue\nalpha.vue\nsize.vue\ndisabled.vue\nmodes.vue\nactions.vue\nform.vue\nswatches.vue\ntrigger.vue\nnative.vue\n```\n\n## API\n\n### ColorPicker Props\n\n| Name | Type | Default | Description | Version |\n| --- | --- | --- | --- | --- |\n| default-show | `boolean` | `undefined` | Whether to show the color panel by default. |  |\n| default-value | `string` | Black color value of 1st mode's corresponding value. | Default value of the picker. |  |\n| modes | `Array<'rgb' \\| 'hex' \\| 'hsl' \\| 'hsv'>` | `['rgb', 'hex', 'hsl']` | The value format of the picker. Notice that value will follow the mode once you select a new value from the picker. |  |\n| placement | `'top-start' \\| 'top' \\| 'top-end' \\| 'right-start' \\| 'right' \\| 'right-end' \\| 'bottom-start' \\| 'bottom' \\| 'bottom-end' \\| 'left-start' \\| 'left' \\| 'left-end'` | `'bottom-start'` | Color panel placement. | 2.25.0 |\n| render-label | `(color: string \\| null) => VNodeChild` | `undefined` | Label render function of the color picker trigger. | 2.24.0 |\n| show | `boolean` | `undefined` | Whether the color panel is shown. |  |\n| show-alpha | `boolean` | `true` | Whether the alpha channel can be adjusted. |  |\n| show-preview | `boolean` | `false` | Whether the color preview is shown. |  |\n| size | `'small' \\| 'medium' \\| 'large'` | `'medium'` | Size of the picker. |  |\n| disabled | `boolean` | `false` | Whether to disable the color picker. | 2.24.5 |\n| swatches | `string[]` | `undefined` | Value of the swatches. |  |\n| to | `string \\| HTMLElement \\| false` | `'body'` | Where to attach the panel to. `false` will keep it not detached. |  |\n| value | `string \\| null` | `undefined` | Value of the picker. |  |\n| on-complete | `(value: string) => void` | `undefined` | Callback once the value is changed completely (not called during mousemove). |  |\n| on-confirm | `(value: string) => void` | `undefined` | Callback once the confirm button is clicked. | 2.29.0 |\n| on-clear | `() => void` | `undefined` | Callback once the clear button is clicked. | 2.39.0 |\n| on-update:show | `(value: boolean) => void` | `undefined` | Callback once panel the show status is changed. |  |\n| on-update:value | `(value: string) => void` | `undefined` | Callback once the value is changed. |  |\n| actions | `Array<'confirm' \\| 'clear'> \\| null` | `null` | The types of buttons to be shown in the panel. |  |\n\n### ColorPicker Slots\n\n| Name | Parameters | Description | Version |\n| --- | --- | --- | --- |\n| action | `()` | Custom action. | 2.24.0 |\n| label | `(color: string \\| null)` | Label of the color picker trigger. | 2.24.0 |\n| trigger | `(props: { value: string \\| null , onClick: (() => void) \\| undefined, ref: (ref: Element \\| ComponentPublicInstance \\| null }) => void })` | Custom trigger element. Only one element is allowed & it can't be pure text. | 2.44.0 |\n\n## Q & A\n\n### How to get color value from name?\n\nNaive doesn't provide it builtin. You can create a color map, like [https://github.com/bgrins/TinyColor/blob/master/tinycolor.js#L803](https://github.com/bgrins/TinyColor/blob/master/tinycolor.js#L803).\n\nOr you can create a function like this.\n\n```js\nexport function getRgb(colorName) {\n  const el = document.createElement('div')\n  el.style.color = colorName\n  document.body.appendChild(el)\n  const rgbColor = getComputedStyle(el).color\n  document.body.removeChild(el)\n  return rgbColor\n}\n```\n"
  },
  {
    "path": "src/color-picker/demos/enUS/modes.demo.vue",
    "content": "<markdown>\n# Set mode\n\nUse `modes` to set restrict the available modes.\n</markdown>\n\n<template>\n  <n-color-picker :modes=\"['hex']\" />\n</template>\n"
  },
  {
    "path": "src/color-picker/demos/enUS/native.demo.vue",
    "content": "<markdown>\n# Native\n\nWe provide a way to trigger the browser's native color selector by clicking on the color preview block, because browser manufacturers have implemented some great features on the native color selector, which you may need.\n</markdown>\n\n<template>\n  <n-color-picker :show-preview=\"true\" />\n</template>\n"
  },
  {
    "path": "src/color-picker/demos/enUS/size.demo.vue",
    "content": "<markdown>\n# Size\n\n`small`, `medium`, `large`.\n</markdown>\n\n<template>\n  <n-space vertical>\n    <n-color-picker size=\"small\" />\n    <n-color-picker />\n    <n-color-picker size=\"large\" />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/color-picker/demos/enUS/swatches.demo.vue",
    "content": "<markdown>\n# Swatches\n\nSet color swatches for users to choose.\n</markdown>\n\n<template>\n  <n-color-picker\n    :swatches=\"[\n      '#FFFFFF',\n      '#18A058',\n      '#2080F0',\n      '#F0A020',\n      'rgba(208, 48, 80, 1)',\n    ]\"\n  />\n</template>\n"
  },
  {
    "path": "src/color-picker/demos/enUS/trigger.demo.vue",
    "content": "<markdown>\n# Custom Trigger\n\nUse the `trigger` slot to customize the trigger.\n</markdown>\n\n<script lang=\"ts\">\nimport { ColorWand as PaletteIcon } from '@vicons/ionicons5'\nimport { defineComponent, ref } from 'vue'\n\nexport default defineComponent({\n  components: {\n    PaletteIcon\n  },\n  setup() {\n    return {\n      color1: ref('#18a058'),\n      color2: ref('#5136C9'),\n      color3: ref('#722ed1')\n    }\n  }\n})\n</script>\n\n<template>\n  <n-flex :wrap=\"false\" align=\"center\">\n    <n-color-picker v-model:value=\"color1\">\n      <template #trigger=\"{ value, onClick, ref: triggerRef }\">\n        <n-button :ref=\"triggerRef\" circle quaternary @click=\"onClick\">\n          <template #icon>\n            <n-icon :color=\"value || '#000'\">\n              <PaletteIcon />\n            </n-icon>\n          </template>\n        </n-button>\n      </template>\n    </n-color-picker>\n\n    <n-color-picker v-model:value=\"color2\">\n      <template #trigger=\"{ value, onClick, ref: triggerRef }\">\n        <div\n          :ref=\"triggerRef\"\n          :style=\"{\n            width: '22px',\n            height: '22px',\n            borderRadius: '50%',\n            backgroundColor: value || '#000',\n            cursor: 'pointer',\n            border: '2px solid #fff',\n            boxShadow: '0 2px 8px rgba(0, 0, 0, 0.15)',\n          }\"\n          @click=\"onClick\"\n        />\n      </template>\n    </n-color-picker>\n\n    <n-color-picker v-model:value=\"color3\">\n      <template #trigger=\"{ value, onClick, ref: triggerRef }\">\n        <n-text\n          :ref=\"triggerRef\"\n          :style=\"{ color: value }\"\n          style=\"cursor: pointer\"\n          @click=\"onClick\"\n        >\n          {{ value }}\n        </n-text>\n      </template>\n    </n-color-picker>\n  </n-flex>\n</template>\n"
  },
  {
    "path": "src/color-picker/demos/zhCN/actions.demo.vue",
    "content": "<markdown>\n# 可清除\n\n如果你希望颜色选择器可以清空，你可以在 `'actions'` 属性中添加 `'clear'`。\n</markdown>\n\n<template>\n  <n-color-picker :actions=\"['clear']\" />\n</template>\n"
  },
  {
    "path": "src/color-picker/demos/zhCN/alpha.demo.vue",
    "content": "<markdown>\n# 不透明度\n\n用 `show-alpha` 设定是否可调节 alpha 通道。\n</markdown>\n\n<script lang=\"ts\" setup>\nfunction handleConfirm(value: string) {\n  console.log(value)\n}\n</script>\n\n<template>\n  <n-color-picker\n    :show-alpha=\"false\"\n    :actions=\"['confirm']\"\n    @confirm=\"handleConfirm\"\n  />\n</template>\n"
  },
  {
    "path": "src/color-picker/demos/zhCN/basic.demo.vue",
    "content": "<markdown>\n# 基础用法\n\n一个基本的颜色选择器。注意如果你在某个模式下选择了值，那么颜色选择器的值的格式会跟随模式。\n</markdown>\n\n<template>\n  <n-color-picker />\n</template>\n"
  },
  {
    "path": "src/color-picker/demos/zhCN/close-debug.demo.vue",
    "content": "<markdown>\n# Close debug\n</markdown>\n\n<template>\n  <n-color-picker />\n  <n-button style=\"margin-left: 120px\" @mousedown.stop>\n    Stop mousedown\n  </n-button>\n</template>\n"
  },
  {
    "path": "src/color-picker/demos/zhCN/disabled.demo.vue",
    "content": "<markdown>\n# 禁用\n</markdown>\n\n<template>\n  <n-color-picker disabled />\n</template>\n"
  },
  {
    "path": "src/color-picker/demos/zhCN/form.demo.vue",
    "content": "<markdown>\n# 和表单一起使用\n\n我感觉这个例子没啥用，不过既然它也算个数据录入组件，就写上吧。\n</markdown>\n\n<script lang=\"ts\">\nimport { defineComponent, reactive } from 'vue'\n\nexport default defineComponent({\n  setup() {\n    const model = reactive({\n      color: '#18A058'\n    })\n    return {\n      model,\n      colorRule: {\n        trigger: 'change',\n        validator(_: unknown, value: string) {\n          if (value !== '#18A058')\n            return new Error('不许改颜色')\n        }\n      }\n    }\n  }\n})\n</script>\n\n<template>\n  <n-form :model=\"model\">\n    <n-form-item label=\"颜色（#18A058）\" path=\"color\" :rule=\"colorRule\">\n      <n-color-picker v-model:value=\"model.color\" :show-alpha=\"false\" />\n    </n-form-item>\n  </n-form>\n</template>\n"
  },
  {
    "path": "src/color-picker/demos/zhCN/index.demo-entry.md",
    "content": "# 颜色选择器 Color Picker\n\n和真实世界比起来，它的空间是不连续的。\n\n## 演示\n\n```demo\nbasic.vue\nalpha.vue\nsize.vue\ndisabled.vue\nmodes.vue\nactions.vue\nform.vue\nswatches.vue\ntrigger.vue\nnative.vue\nclose-debug.vue\n```\n\n## API\n\n### ColorPicker Props\n\n| 名称 | 类型 | 默认值 | 说明 | 版本 |\n| --- | --- | --- | --- | --- |\n| default-show | `boolean` | `undefined` | 默认是否展示弹出层 |  |\n| default-value | `string \\| null` | 和第一个 mode 对应的黑色值 | 默认的颜色值 |  |\n| modes | `Array<'rgb' \\| 'hex' \\| 'hsl' \\| 'hsv'>` | `['rgb', 'hex', 'hsl']` | 颜色选择器支持颜色的格式，注意一旦你在某个模式下选择了值，颜色选择器值的格式将跟随这个格式 |  |\n| placement | `'top-start' \\| 'top' \\| 'top-end' \\| 'right-start' \\| 'right' \\| 'right-end' \\| 'bottom-start' \\| 'bottom' \\| 'bottom-end' \\| 'left-start' \\| 'left' \\| 'left-end'` | `'bottom-start'` | 面板的弹出位置 | 2.25.0 |\n| render-label | `(color: string \\| null) => VNodeChild` | `undefined` | 触发器的内容 | 2.24.0 |\n| show | `boolean` | `undefined` | 是否展示面板 |  |\n| show-alpha | `boolean` | `true` | 是否可调节 alpha 通道 |  |\n| show-preview | `boolean` | `false` | 是否展示颜色预览块 |  |\n| size | `'small' \\| 'medium' \\| 'large'` | `'medium'` | 颜色选择器的尺寸 |  |\n| disabled | `boolean` | `false` | 是否禁用 | 2.24.5 |\n| swatches | `string[]` | `undefined` | 色板的值 |  |\n| to | `string \\| HTMLElement \\| false` | `'body'` | 面板的卸载位置，`false` 会待在原地 |  |\n| value | `string \\| null` | `undefined` | 颜色选择器的值 |  |\n| on-complete | `(value: string) => void` | `undefined` | 颜色完成改变后的回调（在鼠标移动时候不会调用） |  |\n| on-confirm | `(value: string) => void` | `undefined` | 点击确定按钮的回调 | 2.29.0 |\n| on-clear | `() => void` | `undefined` | 点击清除按钮的回调 | 2.39.0 |\n| on-update:show | `(value: boolean) => void` | `undefined` | 面板可见状态改变的回调 |  |\n| on-update:value | `(value: string) => void` | `undefined` | 颜色改变时的回调 |  |\n| actions | `Array<'confirm' \\| 'clear'> \\| null` | `null` | 显示按钮 |  |\n\n### ColorPicker Slots\n\n| 名称 | 参数 | 说明 | 版本 |\n| --- | --- | --- | --- |\n| action | `()` | 菜单操作区域的 slot | 2.24.0 |\n| label | `(color: string \\| null)` | 触发器的内容 | 2.24.0 |\n| trigger | `(props: { value: string \\| null , onClick: (() => void) \\| undefined, ref: (ref: Element \\| ComponentPublicInstance \\| null }) => void })` | 自定义触发器，只允许一个元素，不可以是纯文本 | 2.44.0 |\n\n## Q & A\n\n### 如何从颜色名称转化为色值\n\nnaive 不内置提供这种功能，你可以自己建立一个对象进行映射，见 [https://github.com/bgrins/TinyColor/blob/master/tinycolor.js#L803](https://github.com/bgrins/TinyColor/blob/master/tinycolor.js#L803)。\n\n或者你自己写一个函数，例如：\n\n```js\nexport function getRgb(colorName) {\n  const el = document.createElement('div')\n  el.style.color = colorName\n  document.body.appendChild(el)\n  const rgbColor = getComputedStyle(el).color\n  document.body.removeChild(el)\n  return rgbColor\n}\n```\n"
  },
  {
    "path": "src/color-picker/demos/zhCN/modes.demo.vue",
    "content": "<markdown>\n# 设定模式\n\n使用 `modes` 设定可选模式。\n</markdown>\n\n<template>\n  <n-color-picker :modes=\"['hex']\" />\n</template>\n"
  },
  {
    "path": "src/color-picker/demos/zhCN/native.demo.vue",
    "content": "<markdown>\n# 原生\n\n我们提供了一种通过点击颜色预览块来触发浏览器原生的颜色选择器的方式，因为浏览器厂商在原生的颜色选择器上实现了一些很棒的功能，你可能会需要。\n</markdown>\n\n<template>\n  <n-color-picker :show-preview=\"true\" />\n</template>\n"
  },
  {
    "path": "src/color-picker/demos/zhCN/size.demo.vue",
    "content": "<markdown>\n# 尺寸\n\n`small`、`medium`、`large`。\n</markdown>\n\n<template>\n  <n-space vertical>\n    <n-color-picker size=\"small\" />\n    <n-color-picker />\n    <n-color-picker size=\"large\" />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/color-picker/demos/zhCN/swatches.demo.vue",
    "content": "<markdown>\n# 色板\n\n你也可以预设一个色板供用户选择。\n</markdown>\n\n<template>\n  <n-color-picker\n    :swatches=\"[\n      '#FFFFFF',\n      '#18A058',\n      '#2080F0',\n      '#F0A020',\n      'rgba(208, 48, 80, 1)',\n    ]\"\n  />\n</template>\n"
  },
  {
    "path": "src/color-picker/demos/zhCN/trigger.demo.vue",
    "content": "<markdown>\n# 自定义触发器\n\n使用 `trigger` 插槽自定义触发器。\n</markdown>\n\n<script lang=\"ts\">\nimport { ColorWand as PaletteIcon } from '@vicons/ionicons5'\nimport { defineComponent, ref } from 'vue'\n\nexport default defineComponent({\n  components: {\n    PaletteIcon\n  },\n  setup() {\n    return {\n      color1: ref('#18a058'),\n      color2: ref('#5136C9'),\n      color3: ref('#722ed1')\n    }\n  }\n})\n</script>\n\n<template>\n  <n-flex :wrap=\"false\" align=\"center\">\n    <n-color-picker v-model:value=\"color1\">\n      <template #trigger=\"{ value, onClick, ref: triggerRef }\">\n        <n-button :ref=\"triggerRef\" circle quaternary @click=\"onClick\">\n          <template #icon>\n            <n-icon :color=\"value || '#000'\">\n              <PaletteIcon />\n            </n-icon>\n          </template>\n        </n-button>\n      </template>\n    </n-color-picker>\n\n    <n-color-picker v-model:value=\"color2\">\n      <template #trigger=\"{ value, onClick, ref: triggerRef }\">\n        <div\n          :ref=\"triggerRef\"\n          :style=\"{\n            width: '22px',\n            height: '22px',\n            borderRadius: '50%',\n            backgroundColor: value || '#000',\n            cursor: 'pointer',\n            border: '2px solid #fff',\n            boxShadow: '0 2px 8px rgba(0, 0, 0, 0.15)',\n          }\"\n          @click=\"onClick\"\n        />\n      </template>\n    </n-color-picker>\n\n    <n-color-picker v-model:value=\"color3\">\n      <template #trigger=\"{ value, onClick, ref: triggerRef }\">\n        <n-text\n          :ref=\"triggerRef\"\n          :style=\"{ color: value }\"\n          style=\"cursor: pointer\"\n          @click=\"onClick\"\n        >\n          {{ value }}\n        </n-text>\n      </template>\n    </n-color-picker>\n  </n-flex>\n</template>\n"
  },
  {
    "path": "src/color-picker/index.ts",
    "content": "export { colorPickerProps, default as NColorPicker } from './src/ColorPicker'\nexport type { ColorPickerProps, ColorPickerSlots } from './src/ColorPicker'\nexport type * from './src/public-types'\n"
  },
  {
    "path": "src/color-picker/src/AlphaSlider.tsx",
    "content": "import type { RGBA } from 'seemly'\nimport type { PropType } from 'vue'\nimport { off, on } from 'evtd'\nimport { toRgbaString } from 'seemly'\nimport { computed, defineComponent, h, ref } from 'vue'\nimport { normalizeAlpha } from './utils'\n\nconst HANDLE_SIZE = '12px'\nconst HANDLE_SIZE_NUM = 12\nconst RADIUS = '6px'\n\nexport default defineComponent({\n  name: 'AlphaSlider',\n  props: {\n    clsPrefix: {\n      type: String,\n      required: true\n    },\n    rgba: {\n      type: Array as unknown as PropType<RGBA | null>,\n      default: null\n    },\n    alpha: {\n      type: Number,\n      default: 0\n    },\n    onUpdateAlpha: {\n      type: Function as PropType<(value: number) => void>,\n      required: true\n    },\n    onComplete: Function as PropType<() => void>\n  },\n  setup(props) {\n    const railRef = ref<HTMLElement | null>(null)\n    function handleMouseDown(e: MouseEvent): void {\n      if (!railRef.value || !props.rgba)\n        return\n      on('mousemove', document, handleMouseMove)\n      on('mouseup', document, handleMouseUp)\n      handleMouseMove(e)\n    }\n    function handleMouseMove(e: MouseEvent): void {\n      const { value: railEl } = railRef\n      if (!railEl)\n        return\n      const { width, left } = railEl.getBoundingClientRect()\n      const newAlpha = (e.clientX - left) / (width - HANDLE_SIZE_NUM)\n      props.onUpdateAlpha(normalizeAlpha(newAlpha))\n    }\n    function handleMouseUp(): void {\n      off('mousemove', document, handleMouseMove)\n      off('mouseup', document, handleMouseUp)\n      props.onComplete?.()\n    }\n    return {\n      railRef,\n      railBackgroundImage: computed(() => {\n        const { rgba } = props\n        if (!rgba)\n          return ''\n        return `linear-gradient(to right, rgba(${rgba[0]}, ${rgba[1]}, ${rgba[2]}, 0) 0%, rgba(${rgba[0]}, ${rgba[1]}, ${rgba[2]}, 1) 100%)`\n      }),\n      handleMouseDown\n    }\n  },\n  render() {\n    const { clsPrefix } = this\n    return (\n      <div\n        class={`${clsPrefix}-color-picker-slider`}\n        ref=\"railRef\"\n        style={{\n          height: HANDLE_SIZE,\n          borderRadius: RADIUS\n        }}\n        onMousedown={this.handleMouseDown}\n      >\n        <div\n          style={{\n            borderRadius: RADIUS,\n            position: 'absolute',\n            left: 0,\n            right: 0,\n            top: 0,\n            bottom: 0,\n            overflow: 'hidden'\n          }}\n        >\n          <div class={`${clsPrefix}-color-picker-checkboard`} />\n          <div\n            class={`${clsPrefix}-color-picker-slider__image`}\n            style={{\n              backgroundImage: this.railBackgroundImage\n            }}\n          />\n        </div>\n        {this.rgba && (\n          <div\n            style={{\n              position: 'absolute',\n              left: RADIUS,\n              right: RADIUS,\n              top: 0,\n              bottom: 0\n            }}\n          >\n            <div\n              class={`${clsPrefix}-color-picker-handle`}\n              style={{\n                left: `calc(${this.alpha * 100}% - ${RADIUS})`,\n                borderRadius: RADIUS,\n                width: HANDLE_SIZE,\n                height: HANDLE_SIZE\n              }}\n            >\n              <div\n                class={`${clsPrefix}-color-picker-handle__fill`}\n                style={{\n                  backgroundColor: toRgbaString(this.rgba),\n                  borderRadius: RADIUS,\n                  width: HANDLE_SIZE,\n                  height: HANDLE_SIZE\n                }}\n              />\n            </div>\n          </div>\n        )}\n      </div>\n    )\n  }\n})\n"
  },
  {
    "path": "src/color-picker/src/ColorInput.tsx",
    "content": "import type { HSL, HSLA, HSV, HSVA, RGB, RGBA } from 'seemly'\nimport type { PropType } from 'vue'\nimport type { ColorPickerMode } from './utils'\nimport {\n  toHexaString,\n  toHexString,\n  toHslaString,\n  toHslString,\n  toHsvaString,\n  toHsvString,\n  toRgbaString,\n  toRgbString\n} from 'seemly'\nimport { defineComponent, h } from 'vue'\nimport { NInputGroup } from '../../input'\nimport ColorInputUnit from './ColorInputUnit'\n\nexport default defineComponent({\n  name: 'ColorInput',\n  props: {\n    clsPrefix: {\n      type: String,\n      required: true\n    },\n    mode: {\n      type: String as PropType<ColorPickerMode>,\n      required: true\n    },\n    modes: {\n      type: Array as PropType<ColorPickerMode[]>,\n      required: true\n    },\n    showAlpha: {\n      type: Boolean,\n      required: true\n    },\n    value: {\n      // for hex to get percise value\n      type: String as PropType<string | null>,\n      default: null\n    },\n    valueArr: {\n      type: Array as unknown as PropType<HSVA | RGBA | HSLA | null>,\n      default: null\n    },\n    onUpdateValue: {\n      type: Function as PropType<(value: string) => void>,\n      required: true\n    },\n    onUpdateMode: {\n      type: Function as PropType<() => void>,\n      required: true\n    }\n  },\n  setup(props) {\n    return {\n      handleUnitUpdateValue(index: number, value: number | string) {\n        const { showAlpha } = props\n        if (props.mode === 'hex') {\n          props.onUpdateValue(\n            (showAlpha ? toHexaString : toHexString)(value as string)\n          )\n          return\n        }\n        let nextValueArr: any\n        if (props.valueArr === null) {\n          nextValueArr = [0, 0, 0, 0]\n        }\n        else {\n          nextValueArr = Array.from(props.valueArr) as typeof props.valueArr\n        }\n        switch (props.mode) {\n          case 'hsv':\n            nextValueArr[index] = value\n            props.onUpdateValue(\n              (showAlpha ? toHsvaString : toHsvString)(\n                nextValueArr as HSVA | HSV\n              )\n            )\n            break\n          case 'rgb':\n            nextValueArr[index] = value\n            props.onUpdateValue(\n              (showAlpha ? toRgbaString : toRgbString)(\n                nextValueArr as RGBA | RGB\n              )\n            )\n            break\n          case 'hsl':\n            nextValueArr[index] = value\n            props.onUpdateValue(\n              (showAlpha ? toHslaString : toHslString)(\n                nextValueArr as HSLA | HSL\n              )\n            )\n            break\n        }\n      }\n    }\n  },\n  render() {\n    const { clsPrefix, modes } = this\n    return (\n      <div class={`${clsPrefix}-color-picker-input`}>\n        <div\n          class={`${clsPrefix}-color-picker-input__mode`}\n          onClick={this.onUpdateMode}\n          style={{\n            cursor: modes.length === 1 ? '' : 'pointer'\n          }}\n        >\n          {this.mode.toUpperCase() + (this.showAlpha ? 'A' : '')}\n        </div>\n        <NInputGroup>\n          {{\n            default: () => {\n              const { mode, valueArr, showAlpha } = this\n              if (mode === 'hex') {\n                // hex and rgba shares the same value arr\n                let hexValue: string | null = null\n                try {\n                  hexValue\n                    = valueArr === null\n                      ? null\n                      : (showAlpha ? toHexaString : toHexString)(\n                          valueArr as RGBA\n                        )\n                }\n                catch {}\n                return (\n                  <ColorInputUnit\n                    label=\"HEX\"\n                    showAlpha={showAlpha}\n                    value={hexValue}\n                    onUpdateValue={(unitValue) => {\n                      this.handleUnitUpdateValue(0, unitValue)\n                    }}\n                  />\n                )\n              }\n              return (mode + (showAlpha ? 'a' : '')).split('').map((v, i) => (\n                <ColorInputUnit\n                  label={v.toUpperCase()}\n                  value={valueArr === null ? null : valueArr[i]}\n                  onUpdateValue={(unitValue) => {\n                    this.handleUnitUpdateValue(i, unitValue)\n                  }}\n                />\n              ))\n            }\n          }}\n        </NInputGroup>\n      </div>\n    )\n  }\n})\n"
  },
  {
    "path": "src/color-picker/src/ColorInputUnit.tsx",
    "content": "import type { PropType } from 'vue'\nimport { defineComponent, h, inject, ref, watchEffect } from 'vue'\nimport { NInput } from '../../input'\nimport { colorPickerInjectionKey } from './context'\n\n// 0 - 255\nfunction normalizeRgbUnit(value: string): number | false {\n  if (/^\\d{1,3}\\.?\\d*$/.test(value.trim())) {\n    return Math.max(0, Math.min(Number.parseInt(value), 255))\n  }\n  return false\n}\n\n// 0 - 360\nfunction normalizeHueUnit(value: string): number | false {\n  if (/^\\d{1,3}\\.?\\d*$/.test(value.trim())) {\n    return Math.max(0, Math.min(Number.parseInt(value), 360))\n  }\n  return false\n}\n\n// 0 - 100\nfunction normalizeSlvUnit(value: string): number | false {\n  if (/^\\d{1,3}\\.?\\d*$/.test(value.trim())) {\n    return Math.max(0, Math.min(Number.parseInt(value), 100))\n  }\n  return false\n}\n\nfunction normalizeHexaUnit(value: string): boolean {\n  const trimmedValue = value.trim()\n  if (/^#[0-9a-fA-F]+$/.test(trimmedValue)) {\n    return [4, 5, 7, 9].includes(trimmedValue.length)\n  }\n  return false\n}\n\n// 0 - 100%\nfunction normalizeAlphaUnit(value: string): number | false {\n  if (/^\\d{1,3}\\.?\\d*%$/.test(value.trim())) {\n    return Math.max(0, Math.min(Number.parseInt(value) / 100, 100))\n  }\n  return false\n}\n\nconst inputThemeOverrides = {\n  paddingSmall: '0 4px'\n}\n\nexport default defineComponent({\n  name: 'ColorInputUnit',\n  props: {\n    label: {\n      type: String,\n      required: true\n    },\n    value: {\n      type: [Number, String] as PropType<number | string | null>,\n      default: null\n    },\n    showAlpha: Boolean,\n    onUpdateValue: {\n      type: Function as PropType<(value: number | string) => void>,\n      required: true\n    }\n  },\n  setup(props) {\n    const inputValueRef = ref<string>('')\n    const { themeRef } = inject(colorPickerInjectionKey, null)!\n    watchEffect(() => {\n      inputValueRef.value = getInputString()\n    })\n    function getInputString(): string {\n      const { value } = props\n      if (value === null)\n        return ''\n      const { label } = props\n      if (label === 'HEX') {\n        return value as string\n      }\n      if (label === 'A') {\n        return `${Math.floor((value as number) * 100)}%`\n      }\n      return String(Math.floor(value as number))\n    }\n    function handleInputUpdateValue(value: string): void {\n      inputValueRef.value = value\n    }\n    function handleInputChange(value: string): void {\n      let unit: number | false\n      let valid: boolean\n      switch (props.label) {\n        case 'HEX':\n          valid = normalizeHexaUnit(value)\n          if (valid) {\n            props.onUpdateValue(value)\n          }\n          inputValueRef.value = getInputString() // to normalized new value\n          break\n        case 'H':\n          unit = normalizeHueUnit(value)\n          if (unit === false) {\n            inputValueRef.value = getInputString()\n          }\n          else {\n            props.onUpdateValue(unit)\n          }\n          break\n        case 'S':\n        case 'L':\n        case 'V':\n          unit = normalizeSlvUnit(value)\n          if (unit === false) {\n            inputValueRef.value = getInputString()\n          }\n          else {\n            props.onUpdateValue(unit)\n          }\n          break\n        case 'A':\n          unit = normalizeAlphaUnit(value)\n          if (unit === false) {\n            inputValueRef.value = getInputString()\n          }\n          else {\n            props.onUpdateValue(unit)\n          }\n          break\n        case 'R':\n        case 'G':\n        case 'B':\n          unit = normalizeRgbUnit(value)\n          if (unit === false) {\n            inputValueRef.value = getInputString()\n          }\n          else {\n            props.onUpdateValue(unit)\n          }\n          break\n      }\n    }\n    return {\n      mergedTheme: themeRef,\n      inputValue: inputValueRef,\n      handleInputChange,\n      handleInputUpdateValue\n    }\n  },\n  render() {\n    const { mergedTheme } = this\n    return (\n      <NInput\n        size=\"small\"\n        placeholder={this.label}\n        theme={mergedTheme.peers.Input}\n        themeOverrides={mergedTheme.peerOverrides.Input}\n        builtinThemeOverrides={inputThemeOverrides}\n        value={this.inputValue}\n        onUpdateValue={this.handleInputUpdateValue}\n        onChange={this.handleInputChange}\n        // add more space for xxx% input\n        style={this.label === 'A' ? 'flex-grow: 1.25;' : ''}\n      />\n    )\n  }\n})\n"
  },
  {
    "path": "src/color-picker/src/ColorPicker.tsx",
    "content": "import type { HSLA, HSVA, RGBA } from 'seemly'\nimport type {\n  ComponentPublicInstance,\n  CSSProperties,\n  PropType,\n  Ref,\n  SlotsType,\n  VNode\n} from 'vue'\nimport type { FollowerPlacement } from 'vueuc'\nimport type { ThemeProps } from '../../_mixins'\nimport type { ExtractPublicPropTypes, MaybeArray } from '../../_utils'\nimport type { ColorPickerTheme } from '../styles'\nimport type {\n  OnClear,\n  OnConfirmImpl,\n  OnUpdateValue,\n  OnUpdateValueImpl,\n  RenderLabel\n} from './interface'\nimport type { ColorPickerSize } from './public-types'\nimport type { ActionType, ColorPickerMode } from './utils'\nimport {\n  getPreciseEventTarget,\n  hsl2hsv,\n  hsl2rgb,\n  hsla,\n  hsv2hsl,\n  hsv2rgb,\n  hsva,\n  rgb2hsl,\n  rgb2hsv,\n  rgba,\n  toHexaString,\n  toHexString,\n  toHslaString,\n  toHslString,\n  toHsvaString,\n  toHsvString,\n  toRgbaString,\n  toRgbString\n} from 'seemly'\nimport { clickoutside } from 'vdirs'\nimport { useIsMounted, useMergedState } from 'vooks'\nimport {\n  computed,\n  defineComponent,\n  h,\n  mergeProps,\n  nextTick,\n  provide,\n  ref,\n  toRef,\n  Transition,\n  watch,\n  watchEffect,\n  withDirectives\n} from 'vue'\nimport { VBinder, VFollower, VTarget } from 'vueuc'\nimport {\n  useConfig,\n  useFormItem,\n  useLocale,\n  useTheme,\n  useThemeClass\n} from '../../_mixins'\nimport {\n  call,\n  createKey,\n  keep,\n  mergeEventHandlers,\n  resolveWrappedSlotWithProps,\n  useAdjustedTo\n} from '../../_utils'\nimport { NButton } from '../../button'\nimport { colorPickerLight } from '../styles'\nimport AlphaSlider from './AlphaSlider'\nimport ColorInput from './ColorInput'\nimport ColorPickerSwatches from './ColorPickerSwatches'\nimport ColorPickerTrigger from './ColorPickerTrigger'\nimport ColorPreview from './ColorPreview'\nimport { colorPickerInjectionKey } from './context'\nimport HueSlider from './HueSlider'\nimport Pallete from './Pallete'\nimport style from './styles/index.cssr'\nimport { deriveDefaultValue, getModeFromValue } from './utils'\n\nexport const colorPickerProps = {\n  ...(useTheme.props as ThemeProps<ColorPickerTheme>),\n  value: String as PropType<string | null>,\n  show: {\n    type: Boolean as PropType<boolean | undefined>,\n    default: undefined\n  },\n  defaultShow: Boolean,\n  defaultValue: String as PropType<string | null>,\n  modes: {\n    type: Array as PropType<ColorPickerMode[]>,\n    // no hsva by default since browser doesn't support it\n    default: () => ['rgb', 'hex', 'hsl']\n  },\n  placement: {\n    type: String as PropType<FollowerPlacement>,\n    default: 'bottom-start'\n  },\n  to: useAdjustedTo.propTo,\n  showAlpha: {\n    type: Boolean,\n    default: true\n  },\n  showPreview: Boolean,\n  swatches: Array as PropType<string[]>,\n  disabled: {\n    type: Boolean as PropType<boolean | undefined>,\n    default: undefined\n  },\n  actions: {\n    type: Array as PropType<ActionType[]>,\n    default: null\n  },\n  internalActions: Array as PropType<ReadonlyArray<'redo' | 'undo'>>,\n  size: String as PropType<ColorPickerSize>,\n  renderLabel: Function as PropType<RenderLabel>,\n  onComplete: Function as PropType<OnUpdateValue>,\n  onConfirm: Function as PropType<OnUpdateValue>,\n  onClear: Function as PropType<OnClear>,\n  'onUpdate:show': [Function, Array] as PropType<\n    MaybeArray<(value: boolean) => void>\n  >,\n  onUpdateShow: [Function, Array] as PropType<\n    MaybeArray<(value: boolean) => void>\n  >,\n  'onUpdate:value': [Function, Array] as PropType<MaybeArray<OnUpdateValue>>,\n  onUpdateValue: [Function, Array] as PropType<MaybeArray<OnUpdateValue>>\n} as const\n\nexport type ColorPickerProps = ExtractPublicPropTypes<typeof colorPickerProps>\n\nexport interface ColorPickerSlots {\n  default?: () => VNode[]\n  label?: (color: string | null) => VNode[]\n  action?: () => VNode[]\n  trigger?: (props: {\n    value: string | null\n    onClick: (() => void) | undefined\n    ref: (el: any) => void\n  }) => VNode[]\n}\n\nexport default defineComponent({\n  name: 'ColorPicker',\n  inheritAttrs: false,\n  props: colorPickerProps,\n  slots: Object as SlotsType<ColorPickerSlots>,\n  setup(props, { slots }) {\n    let triggerRef: Element | ComponentPublicInstance | null = null\n    function setTriggerRef(el: Element | ComponentPublicInstance | null): void {\n      triggerRef = el\n    }\n    let upcomingValue: string | null = null\n\n    const {\n      mergedClsPrefixRef,\n      namespaceRef,\n      inlineThemeDisabled,\n      mergedComponentPropsRef\n    } = useConfig(props)\n    const formItem = useFormItem(props, {\n      mergedSize: (NFormItem) => {\n        const { size } = props\n        if (size)\n          return size\n        const { mergedSize: formItemSize } = NFormItem || {}\n        if (formItemSize?.value)\n          return formItemSize.value as ColorPickerSize\n        const configSize = mergedComponentPropsRef?.value?.ColorPicker?.size\n        if (configSize)\n          return configSize\n        return 'medium'\n      }\n    })\n    const { mergedSizeRef, mergedDisabledRef } = formItem\n    const { localeRef } = useLocale('global')\n\n    const themeRef = useTheme(\n      'ColorPicker',\n      '-color-picker',\n      style,\n      colorPickerLight,\n      props,\n      mergedClsPrefixRef\n    )\n\n    provide(colorPickerInjectionKey, {\n      themeRef,\n      renderLabelRef: toRef(props, 'renderLabel'),\n      colorPickerSlots: slots\n    })\n\n    const uncontrolledShowRef = ref(props.defaultShow)\n    const mergedShowRef = useMergedState(\n      toRef(props, 'show'),\n      uncontrolledShowRef\n    )\n    function doUpdateShow(value: boolean): void {\n      const { onUpdateShow, 'onUpdate:show': _onUpdateShow } = props\n      if (onUpdateShow)\n        call(onUpdateShow, value)\n      if (_onUpdateShow)\n        call(_onUpdateShow, value)\n      uncontrolledShowRef.value = value\n    }\n\n    const { defaultValue } = props\n    const uncontrolledValueRef = ref(\n      defaultValue === undefined\n        ? deriveDefaultValue(props.modes, props.showAlpha)\n        : defaultValue\n    )\n    const mergedValueRef = useMergedState(\n      toRef(props, 'value'),\n      uncontrolledValueRef\n    )\n\n    const undoStackRef: Ref<Array<string | null>> = ref([mergedValueRef.value])\n    const valueIndexRef = ref(0)\n\n    const valueModeRef = computed(() => getModeFromValue(mergedValueRef.value))\n\n    const { modes } = props\n    const displayedModeRef = ref<ColorPickerMode>(\n      getModeFromValue(mergedValueRef.value) || modes[0] || 'rgb'\n    )\n\n    function handleUpdateDisplayedMode(): void {\n      const { modes } = props\n      const { value: displayedMode } = displayedModeRef\n      const currentModeIndex = modes.findIndex(mode => mode === displayedMode)\n      if (~currentModeIndex) {\n        displayedModeRef.value = modes[(currentModeIndex + 1) % modes.length]\n      }\n      else {\n        displayedModeRef.value = 'rgb'\n      }\n    }\n\n    let _h: number, // avoid conflict with render function's h\n      s: number,\n      l: number,\n      v: number,\n      r: number,\n      g: number,\n      b: number,\n      a: number\n\n    const hsvaRef = computed<HSVA | null>(() => {\n      const { value: mergedValue } = mergedValueRef\n      if (!mergedValue)\n        return null\n      switch (valueModeRef.value!) {\n        case 'hsv':\n          return hsva(mergedValue)\n        case 'hsl':\n          ;[_h, s, l, a] = hsla(mergedValue)\n          return [...hsl2hsv(_h, s, l), a]\n        case 'rgb':\n        case 'hex':\n          ;[r, g, b, a] = rgba(mergedValue)\n          return [...rgb2hsv(r, g, b), a]\n      }\n    })\n\n    const rgbaRef = computed<RGBA | null>(() => {\n      const { value: mergedValue } = mergedValueRef\n      if (!mergedValue)\n        return null\n      switch (valueModeRef.value!) {\n        case 'rgb':\n        case 'hex':\n          return rgba(mergedValue)\n        case 'hsv':\n          ;[_h, s, v, a] = hsva(mergedValue)\n          return [...hsv2rgb(_h, s, v), a]\n        case 'hsl':\n          ;[_h, s, l, a] = hsla(mergedValue)\n          return [...hsl2rgb(_h, s, l), a]\n      }\n    })\n\n    const hslaRef = computed<HSLA | null>(() => {\n      const { value: mergedValue } = mergedValueRef\n      if (!mergedValue)\n        return null\n      switch (valueModeRef.value!) {\n        case 'hsl':\n          return hsla(mergedValue)\n        case 'hsv':\n          ;[_h, s, v, a] = hsva(mergedValue)\n          return [...hsv2hsl(_h, s, v), a]\n        case 'rgb':\n        case 'hex':\n          ;[r, g, b, a] = rgba(mergedValue)\n          return [...rgb2hsl(r, g, b), a]\n      }\n    })\n\n    const mergedValueArrRef = computed(() => {\n      switch (displayedModeRef.value) {\n        case 'rgb':\n        case 'hex':\n          return rgbaRef.value\n        case 'hsv':\n          return hsvaRef.value\n        case 'hsl':\n          return hslaRef.value\n      }\n    })\n\n    const displayedHueRef = ref<number>(0)\n    const displayedAlphaRef = ref<number>(1)\n    const displayedSvRef = ref<[number, number]>([0, 0])\n\n    function handleUpdateSv(s: number, v: number): void {\n      const { value: hsvaArr } = hsvaRef\n      const hue = displayedHueRef.value\n      const alpha = hsvaArr ? hsvaArr[3] : 1\n      displayedSvRef.value = [s, v]\n      const { showAlpha } = props\n      switch (displayedModeRef.value) {\n        case 'hsv':\n          doUpdateValue(\n            (showAlpha ? toHsvaString : toHsvString)([hue, s, v, alpha]),\n            'cursor'\n          )\n          break\n        case 'hsl':\n          doUpdateValue(\n            (showAlpha ? toHslaString : toHslString)([\n              ...hsv2hsl(hue, s, v),\n              alpha\n            ]),\n            'cursor'\n          )\n          break\n        case 'rgb':\n          doUpdateValue(\n            (showAlpha ? toRgbaString : toRgbString)([\n              ...hsv2rgb(hue, s, v),\n              alpha\n            ]),\n            'cursor'\n          )\n          break\n        case 'hex':\n          doUpdateValue(\n            (showAlpha ? toHexaString : toHexString)([\n              ...hsv2rgb(hue, s, v),\n              alpha\n            ]),\n            'cursor'\n          )\n          break\n      }\n    }\n\n    function handleUpdateHue(hue: number): void {\n      displayedHueRef.value = hue\n      const { value: hsvaArr } = hsvaRef\n      if (!hsvaArr) {\n        return\n      }\n      const [, s, v, a] = hsvaArr\n      const { showAlpha } = props\n      switch (displayedModeRef.value) {\n        case 'hsv':\n          doUpdateValue(\n            (showAlpha ? toHsvaString : toHsvString)([hue, s, v, a]),\n            'cursor'\n          )\n          break\n        case 'rgb':\n          doUpdateValue(\n            (showAlpha ? toRgbaString : toRgbString)([\n              ...hsv2rgb(hue, s, v),\n              a\n            ]),\n            'cursor'\n          )\n          break\n        case 'hex':\n          doUpdateValue(\n            (showAlpha ? toHexaString : toHexString)([\n              ...hsv2rgb(hue, s, v),\n              a\n            ]),\n            'cursor'\n          )\n          break\n        case 'hsl':\n          doUpdateValue(\n            (showAlpha ? toHslaString : toHslString)([\n              ...hsv2hsl(hue, s, v),\n              a\n            ]),\n            'cursor'\n          )\n          break\n      }\n    }\n\n    function handleUpdateAlpha(alpha: number): void {\n      switch (displayedModeRef.value) {\n        case 'hsv':\n          ;[_h, s, v] = hsvaRef.value!\n          doUpdateValue(toHsvaString([_h, s, v, alpha]), 'cursor')\n          break\n        case 'rgb':\n          ;[r, g, b] = rgbaRef.value!\n          doUpdateValue(toRgbaString([r, g, b, alpha]), 'cursor')\n          break\n        case 'hex':\n          ;[r, g, b] = rgbaRef.value!\n          doUpdateValue(toHexaString([r, g, b, alpha]), 'cursor')\n          break\n        case 'hsl':\n          ;[_h, s, l] = hslaRef.value!\n          doUpdateValue(toHslaString([_h, s, l, alpha]), 'cursor')\n          break\n      }\n      displayedAlphaRef.value = alpha\n    }\n\n    function doUpdateValue(\n      value: string | null,\n      updateSource: 'cursor' | 'input'\n    ): void {\n      if (updateSource === 'cursor') {\n        upcomingValue = value\n      }\n      else {\n        upcomingValue = null\n      }\n      const { nTriggerFormChange, nTriggerFormInput } = formItem\n      const { onUpdateValue, 'onUpdate:value': _onUpdateValue } = props\n      if (onUpdateValue)\n        call(onUpdateValue as OnUpdateValueImpl, value)\n      if (_onUpdateValue)\n        call(_onUpdateValue as OnUpdateValueImpl, value)\n      nTriggerFormChange()\n      nTriggerFormInput()\n      uncontrolledValueRef.value = value\n    }\n\n    function handleInputUpdateValue(value: string): void {\n      doUpdateValue(value, 'input')\n      void nextTick(handleComplete)\n    }\n\n    function handleComplete(pushStack: boolean = true): void {\n      const { value } = mergedValueRef\n      // no value & only hue changes will complete with no value\n      if (value) {\n        const { nTriggerFormChange, nTriggerFormInput } = formItem\n        const { onComplete } = props\n        if (onComplete) {\n          ;(onComplete as OnUpdateValueImpl)(value)\n        }\n        const { value: undoStack } = undoStackRef\n        const { value: valueIndex } = valueIndexRef\n        if (pushStack) {\n          undoStack.splice(valueIndex + 1, undoStack.length, value)\n          valueIndexRef.value = valueIndex + 1\n        }\n        nTriggerFormChange()\n        nTriggerFormInput()\n      }\n    }\n\n    function undo(): void {\n      const { value: valueIndex } = valueIndexRef\n      if (valueIndex - 1 < 0)\n        return\n      doUpdateValue(undoStackRef.value[valueIndex - 1], 'input')\n      handleComplete(false)\n      valueIndexRef.value = valueIndex - 1\n    }\n\n    function redo(): void {\n      const { value: valueIndex } = valueIndexRef\n      if (valueIndex < 0 || valueIndex + 1 >= undoStackRef.value.length)\n        return\n      doUpdateValue(undoStackRef.value[valueIndex + 1], 'input')\n      handleComplete(false)\n      valueIndexRef.value = valueIndex + 1\n    }\n\n    function handleClear(): void {\n      doUpdateValue(null, 'input')\n      const { onClear } = props\n      if (onClear) {\n        onClear()\n      }\n      doUpdateShow(false)\n    }\n\n    function handleConfirm(): void {\n      const { value } = mergedValueRef\n      const { onConfirm } = props\n      if (onConfirm) {\n        ;(onConfirm as OnConfirmImpl)(value)\n      }\n      doUpdateShow(false)\n    }\n\n    const undoableRef = computed(() => valueIndexRef.value >= 1)\n    const redoableRef = computed(() => {\n      const { value: undoStack } = undoStackRef\n      return undoStack.length > 1 && valueIndexRef.value < undoStack.length - 1\n    })\n\n    watch(mergedShowRef, (value) => {\n      if (!value) {\n        undoStackRef.value = [mergedValueRef.value]\n        valueIndexRef.value = 0\n      }\n    })\n\n    watchEffect(() => {\n      if (upcomingValue && upcomingValue === mergedValueRef.value) {\n        // let it works in uncontrolled mode\n      }\n      else {\n        const { value } = hsvaRef\n        if (value) {\n          displayedHueRef.value = value[0]\n          displayedAlphaRef.value = value[3]\n          displayedSvRef.value = [value[1], value[2]]\n        }\n      }\n      upcomingValue = null\n    })\n\n    const cssVarsRef = computed(() => {\n      const { value: mergedSize } = mergedSizeRef\n      const {\n        common: { cubicBezierEaseInOut },\n        self: {\n          textColor,\n          color,\n          panelFontSize,\n          boxShadow,\n          border,\n          borderRadius,\n          dividerColor,\n          [createKey('height', mergedSize)]: height,\n          [createKey('fontSize', mergedSize)]: fontSize\n        }\n      } = themeRef.value\n      return {\n        '--n-bezier': cubicBezierEaseInOut,\n        '--n-text-color': textColor,\n        '--n-color': color,\n        '--n-panel-font-size': panelFontSize,\n        '--n-font-size': fontSize,\n        '--n-box-shadow': boxShadow,\n        '--n-border': border,\n        '--n-border-radius': borderRadius,\n        '--n-height': height,\n        '--n-divider-color': dividerColor\n      }\n    })\n    const themeClassHandle = inlineThemeDisabled\n      ? useThemeClass(\n          'color-picker',\n          computed(() => {\n            return mergedSizeRef.value[0]\n          }),\n          cssVarsRef,\n          props\n        )\n      : undefined\n\n    function renderPanel(): VNode {\n      const { value: rgba } = rgbaRef\n      const { value: displayedHue } = displayedHueRef\n      const { internalActions, modes, actions } = props\n      const { value: mergedTheme } = themeRef\n      const { value: mergedClsPrefix } = mergedClsPrefixRef\n      return (\n        <div\n          class={[\n            `${mergedClsPrefix}-color-picker-panel`,\n            themeClassHandle?.themeClass.value\n          ]}\n          onDragstart={(e) => {\n            e.preventDefault()\n          }}\n          style={\n            inlineThemeDisabled\n              ? undefined\n              : (cssVarsRef.value as CSSProperties)\n          }\n        >\n          <div class={`${mergedClsPrefix}-color-picker-control`}>\n            <Pallete\n              clsPrefix={mergedClsPrefix}\n              rgba={rgba}\n              displayedHue={displayedHue}\n              displayedSv={displayedSvRef.value}\n              onUpdateSV={handleUpdateSv}\n              onComplete={handleComplete}\n            />\n            <div class={`${mergedClsPrefix}-color-picker-preview`}>\n              <div class={`${mergedClsPrefix}-color-picker-preview__sliders`}>\n                <HueSlider\n                  clsPrefix={mergedClsPrefix}\n                  hue={displayedHue}\n                  onUpdateHue={handleUpdateHue}\n                  onComplete={handleComplete}\n                />\n                {props.showAlpha ? (\n                  <AlphaSlider\n                    clsPrefix={mergedClsPrefix}\n                    rgba={rgba}\n                    alpha={displayedAlphaRef.value}\n                    onUpdateAlpha={handleUpdateAlpha}\n                    onComplete={handleComplete}\n                  />\n                ) : null}\n              </div>\n              {props.showPreview ? (\n                <ColorPreview\n                  clsPrefix={mergedClsPrefix}\n                  mode={displayedModeRef.value}\n                  color={rgbaRef.value && toHexString(rgbaRef.value)}\n                  onUpdateColor={(color) => {\n                    doUpdateValue(color, 'input')\n                  }}\n                />\n              ) : null}\n            </div>\n            <ColorInput\n              clsPrefix={mergedClsPrefix}\n              showAlpha={props.showAlpha}\n              mode={displayedModeRef.value}\n              modes={modes}\n              onUpdateMode={handleUpdateDisplayedMode}\n              value={mergedValueRef.value}\n              valueArr={mergedValueArrRef.value}\n              onUpdateValue={handleInputUpdateValue}\n            />\n            {props.swatches?.length && (\n              <ColorPickerSwatches\n                clsPrefix={mergedClsPrefix}\n                mode={displayedModeRef.value}\n                swatches={props.swatches}\n                onUpdateColor={(color) => {\n                  doUpdateValue(color, 'input')\n                }}\n              />\n            )}\n          </div>\n          {actions?.length ? (\n            <div class={`${mergedClsPrefix}-color-picker-action`}>\n              {actions.includes('confirm') && (\n                <NButton\n                  size=\"small\"\n                  onClick={handleConfirm}\n                  theme={mergedTheme.peers.Button}\n                  themeOverrides={mergedTheme.peerOverrides.Button}\n                >\n                  {{ default: () => localeRef.value.confirm }}\n                </NButton>\n              )}\n              {actions.includes('clear') && (\n                <NButton\n                  size=\"small\"\n                  onClick={handleClear}\n                  disabled={!mergedValueRef.value}\n                  theme={mergedTheme.peers.Button}\n                  themeOverrides={mergedTheme.peerOverrides.Button}\n                >\n                  {{ default: () => localeRef.value.clear }}\n                </NButton>\n              )}\n            </div>\n          ) : null}\n          {slots.action ? (\n            <div class={`${mergedClsPrefix}-color-picker-action`}>\n              {{ default: slots.action }}\n            </div>\n          ) : internalActions ? (\n            <div class={`${mergedClsPrefix}-color-picker-action`}>\n              {internalActions.includes('undo') && (\n                <NButton\n                  size=\"small\"\n                  onClick={undo}\n                  disabled={!undoableRef.value}\n                  theme={mergedTheme.peers.Button}\n                  themeOverrides={mergedTheme.peerOverrides.Button}\n                >\n                  {{ default: () => localeRef.value.undo }}\n                </NButton>\n              )}\n              {internalActions.includes('redo') && (\n                <NButton\n                  size=\"small\"\n                  onClick={redo}\n                  disabled={!redoableRef.value}\n                  theme={mergedTheme.peers.Button}\n                  themeOverrides={mergedTheme.peerOverrides.Button}\n                >\n                  {{ default: () => localeRef.value.redo }}\n                </NButton>\n              )}\n            </div>\n          ) : null}\n        </div>\n      )\n    }\n\n    return {\n      mergedClsPrefix: mergedClsPrefixRef,\n      namespace: namespaceRef,\n      hsla: hslaRef,\n      rgba: rgbaRef,\n      mergedShow: mergedShowRef,\n      mergedDisabled: mergedDisabledRef,\n      isMounted: useIsMounted(),\n      adjustedTo: useAdjustedTo(props),\n      mergedValue: mergedValueRef,\n      handleTriggerClick() {\n        if (mergedDisabledRef.value) {\n          return\n        }\n        doUpdateShow(true)\n      },\n      setTriggerRef,\n      handleClickOutside(e: MouseEvent) {\n        if (triggerRef instanceof Element) {\n          if (triggerRef.contains(getPreciseEventTarget(e) as Node | null)) {\n            return\n          }\n        }\n        else if (triggerRef) {\n          if (\n            triggerRef.$el.contains(getPreciseEventTarget(e) as Node | null)\n          ) {\n            return\n          }\n        }\n        doUpdateShow(false)\n      },\n      renderPanel,\n      cssVars: inlineThemeDisabled ? undefined : cssVarsRef,\n      themeClass: themeClassHandle?.themeClass,\n      onRender: themeClassHandle?.onRender\n    }\n  },\n  render() {\n    const { mergedClsPrefix, onRender } = this\n    onRender?.()\n    return (\n      <VBinder>\n        {{\n          default: () => [\n            <VTarget>\n              {{\n                default: () => {\n                  const triggerProps = mergeProps(this.$attrs, {\n                    ref: this.setTriggerRef,\n                    value: this.mergedValue,\n                    style: this.cssVars,\n                    class: this.themeClass\n                  })\n                  const onClick = mergeEventHandlers([\n                    this.mergedDisabled ? undefined : this.handleTriggerClick,\n                    this.$attrs.onClick as ((e: MouseEvent) => void) | undefined\n                  ])\n                  triggerProps.onClick = onClick\n                  return resolveWrappedSlotWithProps(\n                    this.$slots.trigger,\n                    keep(triggerProps, ['value', 'onClick', 'ref']),\n                    (children) => {\n                      const triggerNode = children || (\n                        <ColorPickerTrigger\n                          {...triggerProps}\n                          clsPrefix={mergedClsPrefix}\n                          hsla={this.hsla}\n                          disabled={this.mergedDisabled}\n                        />\n                      )\n                      return triggerNode\n                    }\n                  )\n                }\n              }}\n            </VTarget>,\n            <VFollower\n              placement={this.placement}\n              show={this.mergedShow}\n              containerClass={this.namespace}\n              teleportDisabled={this.adjustedTo === useAdjustedTo.tdkey}\n              to={this.adjustedTo}\n            >\n              {{\n                default: () => (\n                  <Transition\n                    name=\"fade-in-scale-up-transition\"\n                    appear={this.isMounted}\n                  >\n                    {{\n                      default: () =>\n                        this.mergedShow\n                          ? withDirectives(this.renderPanel(), [\n                              [\n                                clickoutside,\n                                this.handleClickOutside,\n                                undefined as any as string,\n                                { capture: true }\n                              ]\n                            ])\n                          : null\n                    }}\n                  </Transition>\n                )\n              }}\n            </VFollower>\n          ]\n        }}\n      </VBinder>\n    )\n  }\n})\n"
  },
  {
    "path": "src/color-picker/src/ColorPickerSwatches.tsx",
    "content": "import type { PropType } from 'vue'\nimport type { ColorPickerMode } from './utils'\nimport { hsv2rgb, hsva, toRgbaString } from 'seemly'\nimport { computed, defineComponent, h } from 'vue'\nimport { warn } from '../../_utils'\nimport { convertColor, getModeFromValue } from './utils'\n\n// Try to normalize the color values to ensure that they are valid CSS colors\nfunction normalizeColor(color: string, mode: ColorPickerMode | null): string {\n  if (mode === 'hsv') {\n    const [h, s, v, a] = hsva(color)\n    return toRgbaString([...hsv2rgb(h, s, v), a])\n  }\n  // For the mode that is not in preset, we keep the original value.\n  // For color names, they are legal to CSS, so we don’t deal with them,\n  // and only standardize them when outputting.\n  return color\n}\n\nfunction getHexFromName(color: string): string {\n  const ctx = document.createElement('canvas').getContext('2d')\n  if (!ctx) {\n    return '#000000'\n  }\n  ctx.fillStyle = color\n  return ctx.fillStyle\n}\n\ninterface ParsedColor {\n  value: string\n  mode: ColorPickerMode | null\n  legalValue: string\n}\n\nexport default defineComponent({\n  name: 'ColorPickerSwatches',\n  props: {\n    clsPrefix: {\n      type: String,\n      required: true\n    },\n    mode: {\n      type: String as PropType<ColorPickerMode>,\n      required: true\n    },\n    swatches: {\n      type: Array as PropType<string[]>,\n      required: true\n    },\n    onUpdateColor: {\n      type: Function as PropType<(value: string) => void>,\n      required: true\n    }\n  },\n  setup(props) {\n    const parsedSwatchesRef = computed<ParsedColor[]>(() =>\n      props.swatches.map((value) => {\n        const mode = getModeFromValue(value)\n        return {\n          value,\n          mode,\n          legalValue: normalizeColor(value, mode)\n        }\n      })\n    )\n\n    function normalizeOutput(parsed: ParsedColor): string {\n      const { mode: modeProp } = props\n      let { value, mode: swatchColorMode } = parsed\n      // color name is converted to hex\n      if (!swatchColorMode) {\n        swatchColorMode = 'hex'\n        if (/^[a-zA-Z]+$/.test(value)) {\n          value = getHexFromName(value)\n        }\n        else {\n          // for invalid color, we make it black\n          warn('color-picker', `color ${value} in swatches is invalid.`)\n          value = '#000000'\n        }\n      }\n\n      if (swatchColorMode === modeProp)\n        return value\n\n      // swatch value to current mode value\n      return convertColor(value, modeProp, swatchColorMode)\n    }\n\n    function handleSwatchSelect(parsed: ParsedColor): void {\n      props.onUpdateColor(normalizeOutput(parsed))\n    }\n\n    function handleSwatchKeyDown(e: KeyboardEvent, parsed: ParsedColor): void {\n      if (e.key === 'Enter')\n        handleSwatchSelect(parsed)\n    }\n\n    return {\n      parsedSwatchesRef,\n      handleSwatchSelect,\n      handleSwatchKeyDown\n    }\n  },\n  render() {\n    const { clsPrefix } = this\n    return (\n      <div class={`${clsPrefix}-color-picker-swatches`}>\n        {this.parsedSwatchesRef.map(swatch => (\n          <div\n            class={`${clsPrefix}-color-picker-swatch`}\n            tabindex={0}\n            onClick={() => {\n              this.handleSwatchSelect(swatch)\n            }}\n            onKeydown={(e) => {\n              this.handleSwatchKeyDown(e, swatch)\n            }}\n          >\n            <div\n              class={`${clsPrefix}-color-picker-swatch__fill`}\n              style={{ background: swatch.legalValue }}\n            />\n          </div>\n        ))}\n      </div>\n    )\n  }\n})\n"
  },
  {
    "path": "src/color-picker/src/ColorPickerTrigger.tsx",
    "content": "import type { HSLA } from 'seemly'\nimport type { PropType, SlotsType } from 'vue'\nimport { toHslaString } from 'seemly'\nimport { defineComponent, h, inject } from 'vue'\nimport { colorPickerInjectionKey } from './context'\nimport { getWCAGContrast } from './utils'\n\nexport default defineComponent({\n  name: 'ColorPickerTrigger',\n  slots: Object as SlotsType<Record<string, never>>,\n  props: {\n    clsPrefix: {\n      type: String,\n      required: true\n    },\n    value: {\n      type: String as PropType<string | null>,\n      default: null\n    },\n    hsla: {\n      type: Array as unknown as PropType<HSLA | null>,\n      default: null\n    },\n    disabled: Boolean,\n    onClick: Function as PropType<() => void>\n  },\n  setup(props) {\n    const { colorPickerSlots, renderLabelRef } = inject(\n      colorPickerInjectionKey,\n      null\n    )!\n    return () => {\n      const { hsla, value, clsPrefix, onClick, disabled } = props\n      const renderLabel = colorPickerSlots.label || renderLabelRef.value\n      return (\n        <div\n          class={[\n            `${clsPrefix}-color-picker`,\n            disabled && `${clsPrefix}-color-picker--disabled`\n          ]}\n          onClick={disabled ? undefined : onClick}\n        >\n          <div class={`${clsPrefix}-color-picker__fill`}>\n            <div class={`${clsPrefix}-color-picker-checkboard`} />\n            <div\n              style={{\n                position: 'absolute',\n                left: 0,\n                right: 0,\n                top: 0,\n                bottom: 0,\n                backgroundColor: hsla ? toHslaString(hsla) : ''\n              }}\n            />\n            {value && hsla ? (\n              <div\n                class={`${clsPrefix}-color-picker__value`}\n                style={{\n                  color: getWCAGContrast(hsla) ? 'white' : 'black'\n                }}\n              >\n                {renderLabel ? renderLabel(value) : value}\n              </div>\n            ) : null}\n          </div>\n        </div>\n      )\n    }\n  }\n})\n"
  },
  {
    "path": "src/color-picker/src/ColorPreview.tsx",
    "content": "import type { PropType } from 'vue'\nimport type { ColorPickerMode } from './utils'\nimport { defineComponent, h } from 'vue'\nimport { convertColor, getModeFromValue } from './utils'\n\nexport default defineComponent({\n  name: 'ColorPreview',\n  props: {\n    clsPrefix: {\n      type: String,\n      required: true\n    },\n    mode: {\n      type: String as PropType<ColorPickerMode>,\n      required: true\n    },\n    color: {\n      type: String as PropType<string | null>,\n      default: null,\n      validator: (value: string) => {\n        const mode = getModeFromValue(value)\n        return Boolean(!value || (mode && mode !== 'hsv'))\n      }\n    },\n    onUpdateColor: {\n      type: Function as PropType<(value: string) => void>,\n      required: true\n    }\n  },\n  setup(props) {\n    function handleChange(e: Event): void {\n      // hex\n      const value = (e.target as HTMLInputElement).value\n      props.onUpdateColor?.(\n        convertColor(value.toUpperCase(), props.mode, 'hex')\n      )\n      e.stopPropagation()\n    }\n\n    return {\n      handleChange\n    }\n  },\n  render() {\n    const { clsPrefix } = this\n    return (\n      <div class={`${clsPrefix}-color-picker-preview__preview`}>\n        <span\n          class={`${clsPrefix}-color-picker-preview__fill`}\n          style={{\n            background: this.color || '#000000'\n          }}\n        />\n        <input\n          class={`${clsPrefix}-color-picker-preview__input`}\n          type=\"color\"\n          value={this.color}\n          onChange={this.handleChange}\n        />\n      </div>\n    )\n  }\n})\n"
  },
  {
    "path": "src/color-picker/src/HueSlider.tsx",
    "content": "import type { PropType } from 'vue'\nimport { off, on } from 'evtd'\nimport { defineComponent, h, ref } from 'vue'\nimport { normalizeHue } from './utils'\n\nconst HANDLE_SIZE = '12px'\nconst HANDLE_SIZE_NUM = 12\nconst RADIUS = '6px'\nconst RADIUS_NUM = 6\n\nconst GRADIENT\n  = 'linear-gradient(90deg,red,#ff0 16.66%,#0f0 33.33%,#0ff 50%,#00f 66.66%,#f0f 83.33%,red)'\n\nexport default defineComponent({\n  name: 'HueSlider',\n  props: {\n    clsPrefix: {\n      type: String,\n      required: true\n    },\n    hue: {\n      type: Number,\n      required: true\n    },\n    onUpdateHue: {\n      type: Function as PropType<(value: number) => void>,\n      required: true\n    },\n    onComplete: Function as PropType<() => void>\n  },\n  setup(props) {\n    const railRef = ref<HTMLElement | null>(null)\n    function handleMouseDown(e: MouseEvent): void {\n      if (!railRef.value)\n        return\n      on('mousemove', document, handleMouseMove)\n      on('mouseup', document, handleMouseUp)\n      handleMouseMove(e)\n    }\n    function handleMouseMove(e: MouseEvent): void {\n      const { value: railEl } = railRef\n      if (!railEl)\n        return\n      const { width, left } = railEl.getBoundingClientRect()\n      const newHue = normalizeHue(\n        ((e.clientX - left - RADIUS_NUM) / (width - HANDLE_SIZE_NUM)) * 360\n      )\n      props.onUpdateHue(newHue)\n    }\n    function handleMouseUp(): void {\n      off('mousemove', document, handleMouseMove)\n      off('mouseup', document, handleMouseUp)\n      props.onComplete?.()\n    }\n    return {\n      railRef,\n      handleMouseDown\n    }\n  },\n  render() {\n    const { clsPrefix } = this\n    return (\n      <div\n        class={`${clsPrefix}-color-picker-slider`}\n        style={{\n          height: HANDLE_SIZE,\n          borderRadius: RADIUS\n        }}\n      >\n        <div\n          ref=\"railRef\"\n          style={{\n            boxShadow: 'inset 0 0 2px 0 rgba(0, 0, 0, .24)',\n            boxSizing: 'border-box',\n            backgroundImage: GRADIENT,\n            height: HANDLE_SIZE,\n            borderRadius: RADIUS,\n            position: 'relative'\n          }}\n          onMousedown={this.handleMouseDown}\n        >\n          <div\n            style={{\n              position: 'absolute',\n              left: RADIUS,\n              right: RADIUS,\n              top: 0,\n              bottom: 0\n            }}\n          >\n            <div\n              class={`${clsPrefix}-color-picker-handle`}\n              style={{\n                left: `calc((${this.hue}%) / 359 * 100 - ${RADIUS})`,\n                borderRadius: RADIUS,\n                width: HANDLE_SIZE,\n                height: HANDLE_SIZE\n              }}\n            >\n              <div\n                class={`${clsPrefix}-color-picker-handle__fill`}\n                style={{\n                  backgroundColor: `hsl(${this.hue}, 100%, 50%)`,\n                  borderRadius: RADIUS,\n                  width: HANDLE_SIZE,\n                  height: HANDLE_SIZE\n                }}\n              />\n            </div>\n          </div>\n        </div>\n      </div>\n    )\n  }\n})\n"
  },
  {
    "path": "src/color-picker/src/Pallete.tsx",
    "content": "import type { HSVA } from 'seemly'\nimport type { PropType } from 'vue'\nimport { off, on } from 'evtd'\nimport { computed, defineComponent, h, ref } from 'vue'\n\nconst HANDLE_SIZE = '12px'\nconst RADIUS = '6px'\n\nexport default defineComponent({\n  name: 'Pallete',\n  props: {\n    clsPrefix: {\n      type: String,\n      required: true\n    },\n    rgba: {\n      type: Array as unknown as PropType<HSVA | null>,\n      default: null\n    },\n    // 0 - 360\n    displayedHue: {\n      type: Number,\n      required: true\n    },\n    displayedSv: {\n      type: Array as unknown as PropType<[number, number]>,\n      required: true\n    },\n    onUpdateSV: {\n      type: Function as PropType<(s: number, v: number) => void>,\n      required: true\n    },\n    onComplete: Function as PropType<() => void>\n  },\n  setup(props) {\n    const palleteRef = ref<HTMLElement | null>(null)\n    function handleMouseDown(e: MouseEvent): void {\n      if (!palleteRef.value)\n        return\n      on('mousemove', document, handleMouseMove)\n      on('mouseup', document, handleMouseUp)\n      handleMouseMove(e)\n    }\n    function handleMouseMove(e: MouseEvent): void {\n      const { value: palleteEl } = palleteRef\n      if (!palleteEl)\n        return\n      const { width, height, left, bottom } = palleteEl.getBoundingClientRect()\n      const newV = (bottom - e.clientY) / height\n      const newS = (e.clientX - left) / width\n      const normalizedNewS = 100 * (newS > 1 ? 1 : newS < 0 ? 0 : newS)\n      const normalizedNewV = 100 * (newV > 1 ? 1 : newV < 0 ? 0 : newV)\n      props.onUpdateSV(normalizedNewS, normalizedNewV)\n    }\n    function handleMouseUp(): void {\n      off('mousemove', document, handleMouseMove)\n      off('mouseup', document, handleMouseUp)\n      props.onComplete?.()\n    }\n    return {\n      palleteRef,\n      handleColor: computed(() => {\n        const { rgba } = props\n        if (!rgba)\n          return ''\n        return `rgb(${rgba[0]}, ${rgba[1]}, ${rgba[2]})`\n      }),\n      handleMouseDown\n    }\n  },\n  render() {\n    const { clsPrefix } = this\n    return (\n      <div\n        class={`${clsPrefix}-color-picker-pallete`}\n        onMousedown={this.handleMouseDown}\n        ref=\"palleteRef\"\n      >\n        <div\n          class={`${clsPrefix}-color-picker-pallete__layer`}\n          style={{\n            backgroundImage: `linear-gradient(90deg, white, hsl(${this.displayedHue}, 100%, 50%))`\n          }}\n        />\n        <div\n          class={`${clsPrefix}-color-picker-pallete__layer ${clsPrefix}-color-picker-pallete__layer--shadowed`}\n          style={{\n            backgroundImage:\n              'linear-gradient(180deg, rgba(0, 0, 0, 0%), rgba(0, 0, 0, 100%))'\n          }}\n        />\n        {this.rgba && (\n          <div\n            class={`${clsPrefix}-color-picker-handle`}\n            style={{\n              width: HANDLE_SIZE,\n              height: HANDLE_SIZE,\n              borderRadius: RADIUS,\n              left: `calc(${this.displayedSv[0]}% - ${RADIUS})`,\n              bottom: `calc(${this.displayedSv[1]}% - ${RADIUS})`\n            }}\n          >\n            <div\n              class={`${clsPrefix}-color-picker-handle__fill`}\n              style={{\n                backgroundColor: this.handleColor,\n                borderRadius: RADIUS,\n                width: HANDLE_SIZE,\n                height: HANDLE_SIZE\n              }}\n            />\n          </div>\n        )}\n      </div>\n    )\n  }\n})\n"
  },
  {
    "path": "src/color-picker/src/context.ts",
    "content": "import type { ComputedRef, Ref } from 'vue'\nimport type { MergedTheme } from '../../_mixins'\nimport type { ColorPickerTheme } from '../styles'\nimport type { ColorPickerSlots } from './ColorPicker'\nimport type { RenderLabel } from './interface'\nimport { createInjectionKey } from '../../_utils'\n\nexport const colorPickerInjectionKey = createInjectionKey<{\n  themeRef: ComputedRef<MergedTheme<ColorPickerTheme>>\n  colorPickerSlots: ColorPickerSlots\n  renderLabelRef: Ref<RenderLabel | undefined>\n}>('n-color-picker')\n"
  },
  {
    "path": "src/color-picker/src/interface.ts",
    "content": "import type { VNodeChild } from 'vue'\n\nexport type OnUpdateValue = (value: string & null) => void\nexport type OnConfirm = OnUpdateValue\nexport type OnClear = () => void\nexport type OnUpdateValueImpl = (value: string | null) => void\nexport type OnConfirmImpl = OnUpdateValueImpl\n\nexport type RenderLabel = (value: string | null) => VNodeChild\n"
  },
  {
    "path": "src/color-picker/src/public-types.ts",
    "content": "export type ColorPickerSize = 'small' | 'medium' | 'large'\n"
  },
  {
    "path": "src/color-picker/src/styles/index.cssr.ts",
    "content": "import { fadeInScaleUpTransition } from '../../../_styles/transitions/fade-in-scale-up.cssr'\nimport { c, cB, cE, cM } from '../../../_utils/cssr'\n\n// vars:\n// --n-color\n// --n-text-color\n// --n-border-radius\n// --n-panel-font-size\n// --n-font-size\n// --n-bezier\n// --n-height\n// --n-box-shadow\n// --n-divider-color\nexport default c([\n  cB('color-picker-panel', `\n    margin: 4px 0;\n    width: 240px;\n    font-size: var(--n-panel-font-size);\n    color: var(--n-text-color);\n    background-color: var(--n-color);\n    transition:\n      box-shadow .3s var(--n-bezier),\n      color .3s var(--n-bezier),\n      background-color .3s var(--n-bezier);\n    border-radius: var(--n-border-radius);\n    box-shadow: var(--n-box-shadow);\n  `, [\n    fadeInScaleUpTransition(),\n    cB('input', `\n      text-align: center;\n    `)\n  ]),\n  cB('color-picker-checkboard', `\n    background: white; \n    position: absolute;\n    left: 0;\n    right: 0;\n    top: 0;\n    bottom: 0;\n  `, [\n    c('&::after', `\n      background-image: linear-gradient(45deg, #DDD 25%, #0000 25%), linear-gradient(-45deg, #DDD 25%, #0000 25%), linear-gradient(45deg, #0000 75%, #DDD 75%), linear-gradient(-45deg, #0000 75%, #DDD 75%);\n      background-size: 12px 12px;\n      background-position: 0 0, 0 6px, 6px -6px, -6px 0px;\n      background-repeat: repeat;\n      content: \"\";\n      position: absolute;\n      left: 0;\n      right: 0;\n      top: 0;\n      bottom: 0;\n    `)\n  ]),\n  cB('color-picker-slider', `\n    margin-bottom: 8px;\n    position: relative;\n    box-sizing: border-box;\n  `, [\n    cE('image', `\n      position: absolute;\n      left: 0;\n      right: 0;\n      top: 0;\n      bottom: 0;\n    `),\n    c('&::after', `\n      content: \"\";\n      position: absolute;\n      border-radius: inherit;\n      left: 0;\n      right: 0;\n      top: 0;\n      bottom: 0;\n      box-shadow: inset 0 0 2px 0 rgba(0, 0, 0, .24);\n      pointer-events: none;\n    `)\n  ]),\n  cB('color-picker-handle', `\n    z-index: 1;\n    box-shadow: 0 0 2px 0 rgba(0, 0, 0, .45);\n    position: absolute;\n    background-color: white;\n    overflow: hidden;\n  `, [\n    cE('fill', `\n      box-sizing: border-box;\n      border: 2px solid white;\n    `)\n  ]),\n  cB('color-picker-pallete', `\n    height: 180px;\n    position: relative;\n    margin-bottom: 8px;\n    cursor: crosshair;\n  `, [\n    cE('layer', `\n      position: absolute;\n      left: 0;\n      right: 0;\n      top: 0;\n      bottom: 0;\n    `, [\n      cM('shadowed', `\n        box-shadow: inset 0 0 2px 0 rgba(0, 0, 0, .24);\n      `)\n    ])\n  ]),\n  cB('color-picker-preview', `\n    display: flex;\n  `, [\n    cE('sliders', `\n      flex: 1 0 auto;\n    `),\n    cE('preview', `\n      position: relative;\n      height: 30px;\n      width: 30px;\n      margin: 0 0 8px 6px;\n      border-radius: 50%;\n      box-shadow: rgba(0, 0, 0, .15) 0px 0px 0px 1px inset;\n      overflow: hidden;\n    `),\n    cE('fill', `\n      display: block;\n      width: 30px;\n      height: 30px;\n    `),\n    cE('input', `\n      position: absolute;\n      top: 0;\n      left: 0;\n      width: 30px;\n      height: 30px;\n      opacity: 0;\n      z-index: 1;\n    `)\n  ]),\n  cB('color-picker-input', `\n    display: flex;\n    align-items: center;\n  `, [\n    cB('input', `\n      flex-grow: 1;\n      flex-basis: 0;\n    `),\n    cE('mode', `\n      width: 72px;\n      text-align: center;\n    `)\n  ]),\n  cB('color-picker-control', `\n    padding: 12px;\n  `),\n  cB('color-picker-action', `\n    display: flex;\n    margin-top: -4px;\n    border-top: 1px solid var(--n-divider-color);\n    padding: 8px 12px;\n    justify-content: flex-end;\n  `, [\n    cB('button', 'margin-left: 8px;')\n  ]),\n  cB('color-picker', `\n    display: inline-block;\n    box-sizing: border-box;\n    height: var(--n-height);\n    font-size: var(--n-font-size);\n    width: 100%;\n    position: relative;\n    cursor: pointer;\n    border: var(--n-border);\n    border-radius: var(--n-border-radius);\n    transition: border-color .3s var(--n-bezier);\n  `, [\n    cM('disabled', 'cursor: not-allowed'),\n    cE('value', `\n      white-space: nowrap;\n      position: relative;\n    `),\n    cE('fill', `\n      border-radius: var(--n-border-radius);\n      position: absolute;\n      display: flex;\n      align-items: center;\n      justify-content: center;\n      left: 4px;\n      right: 4px;\n      top: 4px;\n      bottom: 4px;\n    `),\n    cB('color-picker-checkboard', `\n      border-radius: var(--n-border-radius);\n    `, [\n      c('&::after', `\n        --n-block-size: calc((var(--n-height) - 8px) / 3);\n        background-size: calc(var(--n-block-size) * 2) calc(var(--n-block-size) * 2);\n        background-position: 0 0, 0 var(--n-block-size), var(--n-block-size) calc(-1 * var(--n-block-size)), calc(-1 * var(--n-block-size)) 0px;  \n      `)\n    ])\n  ]),\n  cB('color-picker-swatches', `\n    display: grid;\n    grid-gap: 8px;\n    flex-wrap: wrap;\n    position: relative;\n    grid-template-columns: repeat(auto-fill, 18px);\n    margin-top: 10px;\n  `, [\n    cB('color-picker-swatch', `\n      width: 18px;\n      height: 18px;\n      background-image: linear-gradient(45deg, #DDD 25%, #0000 25%), linear-gradient(-45deg, #DDD 25%, #0000 25%), linear-gradient(45deg, #0000 75%, #DDD 75%), linear-gradient(-45deg, #0000 75%, #DDD 75%);\n      background-size: 8px 8px;\n      background-position: 0px 0, 0px 4px, 4px -4px, -4px 0px;\n      background-repeat: repeat;\n    `, [\n      cE('fill', `\n        position: relative;\n        width: 100%;\n        height: 100%;\n        border-radius: 3px;\n        box-shadow: rgba(0, 0, 0, .15) 0px 0px 0px 1px inset;\n        cursor: pointer;\n      `),\n      c('&:focus', `\n        outline: none;\n      `, [\n        cE('fill', [\n          c('&::after', `\n            position: absolute;\n            top: 0;\n            right: 0;\n            bottom: 0;\n            left: 0;\n            background: inherit;\n            filter: blur(2px);\n            content: \"\";\n          `)\n        ])\n      ])\n    ])\n  ])\n])\n"
  },
  {
    "path": "src/color-picker/src/utils.ts",
    "content": "import type { HSLA, RGB } from 'seemly'\nimport {\n  hsl2hsv,\n  hsl2rgb,\n  hsla,\n  hsv2hsl,\n  hsv2rgb,\n  hsva,\n  rgb2hsl,\n  rgb2hsv,\n  rgba,\n  toHexaString,\n  toHslaString,\n  toHsvaString,\n  toRgbaString\n} from 'seemly'\nimport { warn } from '../../_utils'\n\nexport type ColorPickerMode = 'rgb' | 'hsl' | 'hsv' | 'hex'\n\nexport type ActionType = 'confirm' | 'clear'\n\nexport function deriveDefaultValue(\n  modes: ColorPickerMode[],\n  showAlpha: boolean\n): string {\n  const mode = modes[0]\n  switch (mode) {\n    case 'hex':\n      return showAlpha ? '#000000FF' : '#000000'\n    case 'rgb':\n      return showAlpha ? 'rgba(0, 0, 0, 1)' : 'rgb(0, 0, 0)'\n    case 'hsl':\n      return showAlpha ? 'hsla(0, 0%, 0%, 1)' : 'hsl(0, 0%, 0%)'\n    case 'hsv':\n      return showAlpha ? 'hsva(0, 0%, 0%, 1)' : 'hsv(0, 0%, 0%)'\n  }\n  if (__DEV__)\n    warn('color-picker', 'props.modes is invalid.')\n  // in case of invalid modes\n  return '#000000'\n}\n\nexport function getModeFromValue(color: string | null): ColorPickerMode | null {\n  if (color === null)\n    return null\n  if (/^ *#/.test(color))\n    return 'hex'\n  if (color.includes('rgb'))\n    return 'rgb'\n  if (color.includes('hsl'))\n    return 'hsl'\n  if (color.includes('hsv'))\n    return 'hsv'\n  return null\n}\n\nexport function getWCAGContrast(\n  hsla: HSLA,\n  contrastColor: RGB = [255, 255, 255],\n  level: 'AA' | 'AAA' = 'AA'\n): boolean {\n  const [r, g, b, a] = rgba(toHslaString(hsla))\n\n  if (a === 1) {\n    const luminance1 = rgb2luminance([r, g, b])\n    const luminance2 = rgb2luminance(contrastColor)\n    const contrast\n      = (Math.max(luminance1, luminance2) + 0.05)\n        / (Math.min(luminance1, luminance2) + 0.05)\n    return contrast >= (level === 'AA' ? 4.5 : 7)\n  }\n\n  const blendedR = Math.round(r * a + contrastColor[0] * (1 - a))\n  const blendedG = Math.round(g * a + contrastColor[1] * (1 - a))\n  const blendedB = Math.round(b * a + contrastColor[2] * (1 - a))\n\n  const luminanceBlended = rgb2luminance([blendedR, blendedG, blendedB])\n  const luminanceWhite = rgb2luminance(contrastColor)\n  const contrastBlended\n    = (Math.max(luminanceBlended, luminanceWhite) + 0.05)\n      / (Math.min(luminanceBlended, luminanceWhite) + 0.05)\n\n  return contrastBlended >= (level === 'AA' ? 4.5 : 7)\n}\n\nfunction rgb2luminance(rgb: RGB): number {\n  const [cr, cg, cb] = rgb.map((c) => {\n    c /= 255\n    return c <= 0.03928 ? c / 12.92 : ((c + 0.055) / 1.055) ** 2.4\n  })\n  return 0.2126 * cr + 0.7152 * cg + 0.0722 * cb\n}\n\nexport function floor(color: number[]): number[] {\n  return color.map(channel => Math.floor(channel))\n}\n\nexport function normalizeHue(hue: number): number {\n  hue = Math.round(hue)\n  return hue >= 360 ? 359 : hue < 0 ? 0 : hue\n}\n\nexport function normalizeAlpha(alpha: number): number {\n  alpha = Math.round(alpha * 100) / 100\n  return alpha > 1 ? 1 : alpha < 0 ? 0 : alpha\n}\n\nconst convert = {\n  rgb: {\n    hex(value: string): string {\n      return toHexaString(rgba(value))\n    },\n    hsl(value: string): string {\n      const [r, g, b, a] = rgba(value)\n      return toHslaString([...rgb2hsl(r, g, b), a])\n    },\n    hsv(value: string): string {\n      const [r, g, b, a] = rgba(value)\n      return toHsvaString([...rgb2hsv(r, g, b), a])\n    }\n  },\n  hex: {\n    rgb(value: string): string {\n      return toRgbaString(rgba(value))\n    },\n    hsl(value: string): string {\n      const [r, g, b, a] = rgba(value)\n      return toHslaString([...rgb2hsl(r, g, b), a])\n    },\n    hsv(value: string): string {\n      const [r, g, b, a] = rgba(value)\n      return toHsvaString([...rgb2hsv(r, g, b), a])\n    }\n  },\n  hsl: {\n    hex(value: string): string {\n      const [h, s, l, a] = hsla(value)\n      return toHexaString([...hsl2rgb(h, s, l), a])\n    },\n    rgb(value: string): string {\n      const [h, s, l, a] = hsla(value)\n      return toRgbaString([...hsl2rgb(h, s, l), a])\n    },\n    hsv(value: string): string {\n      const [h, s, l, a] = hsla(value)\n      return toHsvaString([...hsl2hsv(h, s, l), a])\n    }\n  },\n  hsv: {\n    hex(value: string): string {\n      const [h, s, v, a] = hsva(value)\n      return toHexaString([...hsv2rgb(h, s, v), a])\n    },\n    rgb(value: string) {\n      const [h, s, v, a] = hsva(value)\n      return toRgbaString([...hsv2rgb(h, s, v), a])\n    },\n    hsl(value: string): string {\n      const [h, s, v, a] = hsva(value)\n      return toHslaString([...hsv2hsl(h, s, v), a])\n    }\n  }\n} as const\n\n/**\n * Convert color value by mode\n */\n// overload 1: known type of color conversion\n// we have built-in color conversion\n// return value can be determined as `string`\nexport function convertColor(\n  value: string,\n  mode: ColorPickerMode,\n  originalMode: ColorPickerMode\n): string\n// overload 2: unknown type of color conversion\n// the color value may be invalid\n// so the return value may be `null`\nexport function convertColor(\n  value: string,\n  mode: ColorPickerMode,\n  originalMode?: null\n): string | null\n// implementation\nexport function convertColor(\n  value: string,\n  mode: ColorPickerMode,\n  originalMode?: ColorPickerMode | null\n): string | null {\n  originalMode = originalMode || getModeFromValue(value)\n\n  if (!originalMode)\n    return null\n  if (originalMode === mode)\n    return value\n\n  const conversions = convert[originalMode]\n  return (conversions as any)[mode](value)\n}\n"
  },
  {
    "path": "src/color-picker/styles/dark.ts",
    "content": "import type { ColorPickerTheme } from './light'\nimport { commonDark } from '../../_styles/common'\nimport { buttonDark } from '../../button/styles'\nimport { inputDark } from '../../input/styles'\nimport { self } from './light'\n\nconst colorPickerDark: ColorPickerTheme = {\n  name: 'ColorPicker',\n  common: commonDark,\n  peers: {\n    Input: inputDark,\n    Button: buttonDark\n  },\n  self\n}\n\nexport default colorPickerDark\n"
  },
  {
    "path": "src/color-picker/styles/index.ts",
    "content": "export { default as colorPickerDark } from './dark'\nexport { default as colorPickerLight } from './light'\nexport type { ColorPickerTheme, ColorPickerThemeVars } from './light'\n"
  },
  {
    "path": "src/color-picker/styles/light.ts",
    "content": "import type { ThemeCommonVars } from '../../_styles/common'\nimport { createTheme } from '../../_mixins/use-theme'\nimport { commonLight } from '../../_styles/common'\nimport { buttonLight } from '../../button/styles'\nimport { inputLight } from '../../input/styles'\n\nexport function self(vars: ThemeCommonVars) {\n  const {\n    fontSize,\n    boxShadow2,\n    popoverColor,\n    textColor2,\n    borderRadius,\n    borderColor,\n    heightSmall,\n    heightMedium,\n    heightLarge,\n    fontSizeSmall,\n    fontSizeMedium,\n    fontSizeLarge,\n    dividerColor\n  } = vars\n  return {\n    panelFontSize: fontSize,\n    boxShadow: boxShadow2,\n    color: popoverColor,\n    textColor: textColor2,\n    borderRadius,\n    border: `1px solid ${borderColor}`,\n    heightSmall,\n    heightMedium,\n    heightLarge,\n    fontSizeSmall,\n    fontSizeMedium,\n    fontSizeLarge,\n    dividerColor\n  }\n}\n\nexport type ColorPickerThemeVars = ReturnType<typeof self>\n\nconst colorPickerLight = createTheme({\n  name: 'ColorPicker',\n  common: commonLight,\n  peers: {\n    Input: inputLight,\n    Button: buttonLight\n  },\n  self\n})\n\nexport default colorPickerLight\nexport type ColorPickerTheme = typeof colorPickerLight\n"
  },
  {
    "path": "src/color-picker/tests/ColorPicker.spec.tsx",
    "content": "import type { ColorPickerMode } from '../src/utils'\nimport { mount } from '@vue/test-utils'\nimport { h, nextTick } from 'vue'\nimport { NButton } from '../../button'\nimport { NColorPicker } from '../index'\n\ndescribe('n-color-picker', () => {\n  it('should work with import on demand', () => {\n    mount(NColorPicker)\n  })\n  describe('props.modes', () => {\n    it('multiple modes', async () => {\n      const wrapper = mount(NColorPicker, {\n        attachTo: document.body,\n        props: {\n          modes: ['hex', 'hsl']\n        }\n      })\n      await wrapper.find('.n-color-picker').trigger('click')\n      expect(document.querySelector('.n-color-picker-panel')).not.toEqual(null)\n      const modeDom = document.querySelector('.n-color-picker-input__mode')\n      expect(modeDom?.textContent).toEqual('HEXA')\n      ;(modeDom as HTMLElement).click()\n      await nextTick()\n      expect(modeDom?.textContent).toEqual('HSLA')\n      ;(modeDom as HTMLElement).click()\n      await nextTick()\n      expect(modeDom?.textContent).toEqual('HEXA')\n      wrapper.unmount()\n    })\n    it('single mode', async () => {\n      const wrapper = mount(NColorPicker, {\n        attachTo: document.body,\n        props: {\n          modes: ['hsl']\n        }\n      })\n      await wrapper.find('.n-color-picker').trigger('click')\n      expect(document.querySelector('.n-color-picker-panel')).not.toEqual(null)\n      const modeDom = document.querySelector('.n-color-picker-input__mode')\n      expect(modeDom?.textContent).toEqual('HSLA')\n      ;(modeDom as HTMLElement).click()\n      await nextTick()\n      expect(modeDom?.textContent).toEqual('HSLA')\n      wrapper.unmount()\n    })\n    it('single mode with empty string', async () => {\n      const wrapper = mount(NColorPicker, {\n        attachTo: document.body,\n        props: {\n          value: '',\n          modes: ['hsl']\n        }\n      })\n      await wrapper.find('.n-color-picker').trigger('click')\n      expect(document.querySelector('.n-color-picker-panel')).not.toEqual(null)\n      const modeDom = document.querySelector('.n-color-picker-input__mode')\n      expect(modeDom?.textContent).toEqual('HSLA')\n      ;(modeDom as HTMLElement).click()\n      await nextTick()\n      expect(modeDom?.textContent).toEqual('HSLA')\n      wrapper.unmount()\n    })\n    it('has correct default value', () => {\n      const input: Array<{ modes: ColorPickerMode[], value: string }> = [\n        {\n          modes: ['hsl'],\n          value: 'hsla(0, 0%, 0%, 1)'\n        },\n        {\n          modes: ['rgb'],\n          value: 'rgb(0, 00, 0, 1)'\n        },\n        {\n          modes: ['hex'],\n          value: '#00000000'\n        },\n        {\n          modes: ['hsv', 'hsl'],\n          value: 'hsv(0, 0%, 0%, 1)'\n        }\n      ]\n      input.forEach(({ modes, value }) => {\n        const wrapper = mount(NColorPicker, {\n          props: {\n            modes\n          }\n        })\n        expect(wrapper.text().includes(value))\n        wrapper.unmount()\n      })\n    })\n  })\n  describe('props.control', () => {\n    it('confirm and cancel button', async () => {\n      const wrapper = mount(NColorPicker, {\n        attachTo: document.body,\n        props: {\n          actions: ['confirm']\n        }\n      })\n      await wrapper.find('.n-color-picker').trigger('click')\n      expect(document.querySelector('.n-color-picker-panel')).not.toEqual(null)\n      expect(document.querySelector('.n-color-picker-pallete')).not.toEqual(\n        null\n      )\n      expect(document.querySelector('.n-button')).not.toEqual(null)\n      await wrapper.findComponent(NButton).trigger('click')\n      expect(document.querySelector('.n-color-picker-panel')).toEqual(null)\n      expect(document.querySelector('.n-color-picker-pallete')).toEqual(null)\n      wrapper.unmount()\n    })\n  })\n  describe('props.swatches', () => {\n    it('make the colors legal', async () => {\n      const wrapper = mount(NColorPicker, {\n        attachTo: document.body,\n        props: {\n          swatches: ['hsva(0, 0%, 0%, 1)']\n        }\n      })\n      await wrapper.find('.n-color-picker').trigger('click')\n      expect(\n        document\n          .querySelector('.n-color-picker-swatch__fill')\n          ?.getAttribute('style')\n      ).toContain('background: rgb(0, 0, 0);')\n      wrapper.unmount()\n    })\n    it('output according to mode', async () => {\n      const onUpdateValue = vi.fn()\n      const output = {\n        RGBA: {\n          mode: 'rgb',\n          value: 'rgba(0, 0, 0, 1)'\n        },\n        HSLA: {\n          mode: 'hsl',\n          value: 'hsla(0, 0%, 0%, 1)'\n        },\n        HSVA: {\n          mode: 'hsv',\n          value: 'hsva(0, 0%, 0%, 1)'\n        },\n        HEXA: {\n          mode: 'hex',\n          value: '#000000'\n        }\n      }\n      const modes = Object.values(output).map(\n        v => v.mode\n      ) as ColorPickerMode[]\n      const wrapper = mount(NColorPicker, {\n        attachTo: document.body,\n        props: {\n          swatches: ['black'],\n          modes,\n          onUpdateValue\n        }\n      })\n      await wrapper.find('.n-color-picker').trigger('click')\n      const swatch = document.querySelector('.n-color-picker-swatch')\n      const modeDom = document.querySelector('.n-color-picker-input__mode')\n      let length = modes.length\n      let currentMode: string | null | undefined = null\n      // eslint-disable-next-line no-cond-assign\n      while (length && (currentMode = modeDom?.textContent)) {\n        ;(swatch as HTMLElement).click()\n        await nextTick()\n        const actualOutput = output[currentMode as keyof typeof output]\n        if (actualOutput) {\n          expect(onUpdateValue).toHaveBeenCalledWith(actualOutput.value)\n        }\n        ;(modeDom as HTMLElement).click()\n        await nextTick()\n        length--\n      }\n      wrapper.unmount()\n    })\n  })\n})\ndescribe('props.label', () => {\n  it('render custom label', async () => {\n    const wrapper = mount(NColorPicker, {\n      attachTo: document.body,\n      props: {\n        value: '#FF0000',\n        renderLabel: () => h('span', 'custom')\n      }\n    })\n    await nextTick()\n    expect(\n      document.querySelector('.n-color-picker__value')?.textContent\n    ).toEqual('custom')\n    wrapper.unmount()\n  })\n})\n\ndescribe('n-color-picker 2', () => {\n  it('should work with `placement` prop', async () => {\n    ;(\n      [\n        'top-start',\n        'top',\n        'top-end',\n        'right-start',\n        'right',\n        'right-end',\n        'bottom-start',\n        'bottom',\n        'bottom-end',\n        'left-start',\n        'left',\n        'left-end'\n      ] as const\n    ).forEach(async (placement) => {\n      const wrapper = mount(NColorPicker, { props: { placement } })\n      await vi.waitFor(() => {\n        expect(\n          document\n            .querySelector('.v-binder-follower-content')\n            ?.getAttribute('v-placement')\n        ).toBe(placement)\n      })\n      wrapper.unmount()\n    })\n  })\n\n  it('should work with `disabled` prop', async () => {\n    const wrapper = mount(NColorPicker)\n    expect(wrapper.find('.n-color-picker').classes()).not.toContain(\n      'n-color-picker--disabled'\n    )\n\n    await wrapper.setProps({ disabled: true })\n    expect(wrapper.find('.n-color-picker').classes()).toContain(\n      'n-color-picker--disabled'\n    )\n    wrapper.unmount()\n  })\n\n  it('should work with `render-label` prop', async () => {\n    const wrapper = mount(NColorPicker)\n    expect(wrapper.find('.n-color-picker__value').text()).not.toBe('test-label')\n\n    await wrapper.setProps({ renderLabel: () => 'test-label' })\n    expect(wrapper.find('.n-color-picker__value').text()).toBe('test-label')\n    wrapper.unmount()\n  })\n\n  describe('attrs (style & click)', () => {\n    it('applies passed style to trigger', () => {\n      const wrapper = mount(NColorPicker, {\n        attrs: {\n          style: 'margin-top: 12px; padding-left: 8px;'\n        }\n      })\n      const trigger = wrapper.find('.n-color-picker').element as HTMLElement\n      expect(trigger.style.marginTop).toBe('12px')\n      expect(trigger.style.paddingLeft).toBe('8px')\n      wrapper.unmount()\n    })\n\n    it('calls passed onClick when trigger is clicked', async () => {\n      const onClick = vi.fn()\n      const wrapper = mount(NColorPicker, {\n        attrs: { onClick }\n      })\n      await wrapper.find('.n-color-picker').trigger('click')\n      expect(onClick).toHaveBeenCalledTimes(1)\n      wrapper.unmount()\n    })\n\n    it('merges internal trigger click with passed onClick (both run)', async () => {\n      const onClick = vi.fn()\n      const wrapper = mount(NColorPicker, {\n        attachTo: document.body,\n        attrs: { onClick }\n      })\n      await wrapper.find('.n-color-picker').trigger('click')\n      expect(onClick).toHaveBeenCalledTimes(1)\n      expect(document.querySelector('.n-color-picker-panel')).not.toEqual(null)\n      wrapper.unmount()\n    })\n  })\n})\n"
  },
  {
    "path": "src/color-picker/tests/server.spec.tsx",
    "content": "import { setup } from '@css-render/vue3-ssr'\nimport { renderToString } from '@vue/server-renderer'\n/**\n * @vitest-environment node\n */\nimport { createSSRApp, h } from 'vue'\nimport { NColorPicker } from '../..'\n\ndescribe('server side rendering', () => {\n  it('works', async () => {\n    const app = createSSRApp(() => <NColorPicker />)\n    setup(app)\n    try {\n      await renderToString(app)\n    }\n    catch (e) {\n      expect(e).not.toBeTruthy()\n    }\n  })\n})\n"
  },
  {
    "path": "src/components.ts",
    "content": "export * from './affix'\nexport * from './alert'\nexport * from './anchor'\nexport * from './auto-complete'\nexport * from './avatar'\nexport * from './avatar-group'\nexport * from './back-top'\nexport * from './badge'\nexport * from './breadcrumb'\nexport * from './button'\nexport * from './button-group'\nexport * from './calendar'\nexport * from './card'\nexport * from './carousel'\nexport * from './cascader'\nexport * from './checkbox'\nexport * from './code'\nexport * from './collapse'\nexport * from './collapse-transition'\nexport * from './color-picker'\nexport * from './config-provider'\nexport * from './countdown'\nexport * from './data-table'\nexport * from './date-picker'\nexport * from './descriptions'\nexport * from './dialog'\nexport * from './discrete'\nexport * from './divider'\nexport * from './drawer'\nexport * from './dropdown'\nexport * from './dynamic-input'\nexport * from './dynamic-tags'\nexport * from './element'\nexport * from './ellipsis'\nexport * from './empty'\nexport * from './equation'\nexport * from './flex'\nexport * from './float-button'\nexport * from './float-button-group'\nexport * from './form'\nexport * from './global-style'\nexport * from './gradient-text'\nexport * from './grid'\nexport * from './heatmap'\nexport * from './highlight'\nexport * from './icon'\nexport * from './icon-wrapper'\nexport * from './image'\nexport * from './infinite-scroll'\nexport * from './input'\nexport * from './input-number'\nexport * from './input-otp'\nexport * from './layout'\nexport * from './legacy-grid'\nexport * from './legacy-transfer'\nexport * from './list'\nexport * from './loading-bar'\nexport * from './log'\nexport * from './marquee'\nexport * from './mention'\nexport * from './menu'\nexport * from './message'\nexport * from './modal'\nexport * from './notification'\nexport * from './number-animation'\nexport * from './page-header'\nexport * from './pagination'\nexport * from './popconfirm'\nexport * from './popover'\nexport * from './popselect'\nexport * from './progress'\nexport * from './qr-code'\nexport * from './radio'\nexport * from './rate'\nexport * from './result'\nexport * from './scrollbar'\nexport * from './select'\nexport * from './skeleton'\nexport * from './slider'\nexport * from './space'\nexport * from './spin'\nexport * from './split'\nexport * from './statistic'\nexport * from './steps'\nexport * from './switch'\nexport * from './table'\nexport * from './tabs'\nexport * from './tag'\nexport * from './thing'\nexport * from './time'\nexport * from './time-picker'\nexport * from './timeline'\nexport * from './tooltip'\nexport * from './transfer'\nexport * from './tree'\nexport * from './tree-select'\nexport * from './typography'\nexport * from './upload'\nexport * from './virtual-list'\nexport * from './watermark'\n"
  },
  {
    "path": "src/composables/index.ts",
    "content": "export { useThemeVars } from './use-theme-vars'\n"
  },
  {
    "path": "src/composables/use-theme-vars.ts",
    "content": "import type { ComputedRef } from 'vue'\nimport type { ThemeCommonVars } from '../_styles/common'\nimport type { CustomThemeCommonVars } from '../config-provider'\nimport { computed, inject } from 'vue'\nimport { commonLight } from '../_styles/common'\nimport { configProviderInjectionKey } from '../config-provider/src/context'\n\nexport function useThemeVars(): ComputedRef<\n  ThemeCommonVars & CustomThemeCommonVars\n> {\n  const configProviderInjection = inject(configProviderInjectionKey, null)\n  return computed(() => {\n    if (configProviderInjection === null)\n      return commonLight\n    const {\n      mergedThemeRef: { value: mergedTheme },\n      mergedThemeOverridesRef: { value: mergedThemeOverrides }\n    } = configProviderInjection\n    const currentThemeVars = mergedTheme?.common || commonLight\n    if (mergedThemeOverrides?.common) {\n      return Object.assign({}, currentThemeVars, mergedThemeOverrides.common)\n    }\n    else {\n      return currentThemeVars\n    }\n  })\n}\n"
  },
  {
    "path": "src/config-consumer/demos/enUS/index.demo-entry.md",
    "content": "# Config Consumer\n\nConfig Consumer is built for getting config (usually as global config) of Config Provider.\n\n## Demos\n\n```demo\nbasic\n```\n\n## Events\n\n| Name | Parameters | Default | Description |\n| --- | --- | --- | --- |\n| on-namespace-change | `(namespace: string) => void` | `undefined` | Callback triggered when namespace is changed |\n\n## Slots\n\n| Name    | Parameters                         | Description |\n| ------- | ---------------------------------- | ----------- |\n| default | `(options: { namespace: string })` |             |\n"
  },
  {
    "path": "src/config-consumer/demos/zhCN/index.demo-entry.md",
    "content": "# 配置消费者 Config Consumer\n\n配置消费者的作用是获取全局化配置的（通常是全局的）配置。\n\n## 演示\n\n```demo\nbasic\ntheme-environment-debug\ncolor-debug\n```\n\n## Props\n\n| 名称 | 参数 | 默认值 | 说明 |\n| --- | --- | --- | --- |\n| on-namespace-change | `(namespace: string) => void` | `undefined` | namespace 改成时触发的回调 |\n\n## Slots\n\n| 名称 | 参数 | 说明 |\n| --- | --- | --- |\n| default | `(options: { namespace: string })` | Config Consumer 默认填充的内容 |\n"
  },
  {
    "path": "src/config-provider/demos/enUS/index.demo-entry.md",
    "content": "# Config Provider\n\nConfig Provider is used to set global theme, set global language and set namespace for components (detached parts).\n\nFor more info about theming, see [Customizing Theme](../docs/customize-theme).\n\n## Demos\n\n```demo\ntheme.vue\nnamespace.vue\ninherit-theme.vue\nos-theme.vue\nlanguage.vue\ntransparent.vue\ninline-theme-disabled.vue\nsize.vue\n```\n\n## API\n\n### ConfigProvider Props\n\n| Name | Type | Default | Description | Version |\n| --- | --- | --- | --- | --- |\n| abstract | `boolean` | `false` | If `n-config-provider` has no wrapper DOM |  |\n| breakpoints | `{ [k: string]: number }` | `{ xs: <640, s: ≥640, m: ≥1024, l: ≥1280, xl: ≥1536, xxl: ≥1920 }` | Responsive breakpoints, it will be used in `n-grid`. The prop is not responsive, you need to set it on its first mount. |  |\n| cls-prefix | `string` | `undefined` | The class prefix of all inner components. (Since `2.40.0`) If you don't set the `cls-prefix` prop of `n-config-provider`, it will inherit the class prefix from its parent by default. Note that this prop is not reactive. |  |\n| component-options | `GlobalComponentConfig` | `undefined` | Global component options. Some props can be configured per component. If set to `undefined` it will inherit its parent `n-config-provider`. |  |\n| date-locale | `DateLocale \\| null` | `undefined` | The date locale object to be consumed by its child. If set to `null` it will use the default `dateEnUS` locale. If set to `undefined` it will inherit its parent `n-config-provider`. |  |\n| inline-theme-disabled | `boolean` | `false` | Whether to disabled inline theme CSS variables. If you won't change theme overrides frequently in client side, and need SSR or make devtools looks clear. You can enable the prop. Note that the prop is not responsive. | 2.26.0 |\n| katex | `object` | `undefined` | Katex object for `n-equation`. | 2.34.0 |\n| locale | `Locale \\| null` | `undefined` | The locale object to be consumed by its child. If set to `null` it will use the default `enUS` locale. If set to `undefined` it will inherit its parent `n-config-provider`. |  |\n| namespace | `string` | `undefined` | Class name of detached parts of components inside `n-config-provider` |  |\n| preflight-style-disabled | `boolean` | `false` | Whether to disabled preflight style of naive-ui. If you disable it, you can take control of all global css. Also you can use `n-global-style` to apply global style (which is recommend since global style will be reactive). | 2.29.0 |\n| style-mount-target | `ParentNode` | `undefined` | Mounting target of style elements of components. Note that this prop is not reactive. | 2.40.0 |\n| tag | `string` | `'div'` | What tag `n-config-provider` will be rendered as |  |\n| theme | `Theme \\| null` | `undefined` | The theme object to be consumed by its child. If set to `null` it will use the default light theme. If set to `undefined` it will inherit its parent `n-config-provider`. For more details please see [Customizing Theme](../docs/customize-theme). |  |\n| theme-overrides | `ThemeOverrides \\| null` | `undefined` | The theme vars overrides to be consumed by its child. If set to `null` it will clear all theme vars. If set to `undefined` it will inherit its parent `n-config-provider`. For more details please see [Customizing Theme](../docs/customize-theme). |  |\n\n#### GlobalComponentConfig Type\n\n```ts\ninterface GlobalComponentConfig {\n  AutoComplete?: {\n    size?: AutoCompleteSize\n  }\n  Button?: {\n    size?: ButtonSize\n  }\n  Card?: {\n    size?: CardSize\n  }\n  Cascader?: {\n    size?: CascaderSize\n    renderEmpty?: () => VNodeChild\n  }\n  Checkbox?: {\n    size?: CheckboxSize\n  }\n  ColorPicker?: {\n    size?: ColorPickerSize\n  }\n  DataTable?: {\n    size?: DataTableSize\n    renderFilter?: DataTableRenderFilter\n    renderSorter?: DataTableRenderSorter\n    renderEmpty?: () => VNodeChild\n  }\n  DatePicker?: {\n    size?: DatePickerSize\n    timePickerSize?: TimePickerSize\n  }\n  Descriptions?: {\n    size?: DescriptionsSize\n  }\n  Dialog?: {\n    iconPlacement?: IconPlacement\n  }\n  Dropdown?: {\n    size?: DropdownSize\n  }\n  DynamicInput?: {\n    buttonSize?: ButtonSize\n  }\n  DynamicTags?: {\n    size?: DynamicTagsSize\n  }\n  Empty?: Pick<EmptyProps, 'description' | 'renderIcon'>\n  Form?: {\n    size?: FormSize\n  }\n  Input?: {\n    size?: InputSize\n  }\n  InputNumber?: {\n    size?: InputNumberSize\n  }\n  InputOtp?: {\n    size?: InputOtpSize\n  }\n  Mention?: {\n    size?: MentionSize\n  }\n  Pagination?: {\n    size?: PaginationSize\n    inputSize?: InputSize\n    selectSize?: SelectSize\n  }\n  Popselect?: {\n    size?: PopselectSize\n  }\n  Radio?: {\n    size?: RadioSize\n  }\n  Rate?: {\n    size?: RateSize\n  }\n  Result?: {\n    size?: ResultSize\n  }\n  Select?: {\n    size?: SelectSize\n    renderEmpty?: () => VNodeChild\n  }\n  Skeleton?: {\n    size?: SkeletonSize\n  }\n  Space?: {\n    size?: SpaceSize\n  }\n  Switch?: {\n    size?: SwitchSize\n  }\n  Table?: {\n    size?: TableSize\n  }\n  Tabs?: {\n    size?: TabsSize\n  }\n  Tag?: {\n    size?: TagSize\n  }\n  TimePicker?: {\n    size?: TimePickerSize\n  }\n  Transfer?: {\n    size?: TransferSize\n    renderEmpty?: () => VNodeChild\n  }\n  Tree?: {\n    renderEmpty?: () => VNodeChild\n  }\n  TreeSelect?: {\n    size?: TreeSelectSize\n    renderEmpty?: () => VNodeChild\n  }\n}\n```\n"
  },
  {
    "path": "src/config-provider/demos/enUS/inherit-theme.demo.vue",
    "content": "<markdown>\n# Inherit theme\n\nIf you don't set theme of `n-config-provider`, the theme of `n-config-provider` is inherited by default.\n</markdown>\n\n<template>\n  <n-config-provider>\n    <n-tag>Oops</n-tag>\n  </n-config-provider>\n</template>\n"
  },
  {
    "path": "src/config-provider/demos/enUS/inline-theme-disabled.demo.vue",
    "content": "<markdown>\n# Disable inline theme\n\nBy default, naive-ui uses inline style to hold theme variables, so every component is bound with large amount of inline CSS. If you need SSR, or just make your devtools clear, you can enable `inline-theme-disabled` prop.\n\nNote that if you will change `theme-overrides` frequently, it's not recommended to enable the prop. Many outdated style elements will be keeped after `theme-overrides` changes.\n\nThe prop is not responsive.\n</markdown>\n\n<template>\n  <n-config-provider inline-theme-disabled>\n    <n-button>No inline CSS variable on the button</n-button>\n  </n-config-provider>\n</template>\n"
  },
  {
    "path": "src/config-provider/demos/enUS/language.demo.vue",
    "content": "<markdown>\n# Locale\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { NDateLocale, NLocale } from 'naive-ui'\nimport { dateZhCN, zhCN } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst locale = ref<NLocale | null>(null)\nconst dateLocale = ref<NDateLocale | null>(null)\n</script>\n\n<template>\n  <n-space vertical>\n    <n-space>\n      <n-button\n        @click=\"\n          () => {\n            locale = null\n            dateLocale = null\n          }\n        \"\n      >\n        en-US\n      </n-button>\n      <n-button\n        @click=\"\n          () => {\n            locale = zhCN\n            dateLocale = dateZhCN\n          }\n        \"\n      >\n        zh-CN\n      </n-button>\n    </n-space>\n    <n-config-provider :locale=\"locale\" :date-locale=\"dateLocale\">\n      <n-date-picker />\n    </n-config-provider>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/config-provider/demos/enUS/namespace.demo.vue",
    "content": "<markdown>\n# Namespace (class on detached DOM)\n\nSome parts of component are detached to `document.body`. If you want to add a class to those detached elements, use `namespace` prop of `n-config-provider`. Open devtools to see detached part.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst ns = ref('custom-app-namespace1')\nconst isActive = ref(false)\n</script>\n\n<template>\n  <n-config-provider :namespace=\"ns\">\n    <n-tooltip placement=\"bottom\" trigger=\"click\">\n      <template #trigger>\n        <n-button @click=\"isActive = true\">\n          Activate Component with Detached Content\n        </n-button>\n      </template>\n      <span>Detached Part</span>\n    </n-tooltip>\n  </n-config-provider>\n</template>\n"
  },
  {
    "path": "src/config-provider/demos/enUS/os-theme.demo.vue",
    "content": "<markdown>\n# Use OS theme\n\nNaive UI provides `useOsTheme` to get the current theme of your OS.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { darkTheme, useOsTheme } from 'naive-ui'\nimport { computed } from 'vue'\n\nconst osTheme = useOsTheme()\nconst theme = computed(() => (osTheme.value === 'dark' ? darkTheme : null))\n</script>\n\n<template>\n  <n-config-provider :theme=\"theme\">\n    <n-card> Your current system theme is {{ osTheme }}. </n-card>\n  </n-config-provider>\n</template>\n"
  },
  {
    "path": "src/config-provider/demos/enUS/size.demo.vue",
    "content": "<markdown>\n# Component Size\n\nConfigure component size with `component-options`.\n</markdown>\n\n<script setup lang=\"ts\">\nimport { computed, ref } from 'vue'\n\ntype ComponentSize = 'small' | 'medium' | 'large'\n\nconst size = ref<ComponentSize>('small')\n\nfunction handleBtnClick(_size: ComponentSize): void {\n  size.value = _size\n}\n\nconst componentOptions = computed(() => ({\n  Button: { size: size.value },\n  Card: { size: size.value },\n  Pagination: { size: size.value },\n  Tag: { size: size.value }\n}))\n</script>\n\n<template>\n  <n-button-group>\n    <n-button @click=\"handleBtnClick('small')\">\n      Smaller\n    </n-button>\n    <n-button @click=\"handleBtnClick('medium')\">\n      Medium\n    </n-button>\n    <n-button @click=\"handleBtnClick('large')\">\n      Larger\n    </n-button>\n  </n-button-group>\n  <n-divider />\n  <n-config-provider :component-options=\"componentOptions\">\n    <n-space vertical>\n      <n-button>Button</n-button>\n      <n-tag closable>\n        Tag\n      </n-tag>\n      <n-card title=\"Card\">\n        Card Content\n      </n-card>\n      <n-pagination :page-count=\"20\" />\n    </n-space>\n  </n-config-provider>\n</template>\n"
  },
  {
    "path": "src/config-provider/demos/enUS/theme.demo.vue",
    "content": "<markdown>\n# Theme\n\nSet theme of inner components of `n-config-provider`.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { GlobalTheme } from 'naive-ui'\nimport { darkTheme } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst theme = ref<GlobalTheme | null>(null)\n</script>\n\n<template>\n  <n-config-provider :theme=\"theme\">\n    <n-card>\n      <n-space>\n        <n-button @click=\"theme = darkTheme\">\n          Dark\n        </n-button>\n        <n-button @click=\"theme = null\">\n          Light\n        </n-button>\n      </n-space>\n    </n-card>\n  </n-config-provider>\n</template>\n"
  },
  {
    "path": "src/config-provider/demos/enUS/transparent.demo.vue",
    "content": "<markdown>\n# No wrapper DOM\n\nIf you don't need wrapper DOM, set `abstract` on it.\n</markdown>\n\n<template>\n  <n-config-provider abstract>\n    <n-card>\n      <n-tag>No Wrapper DOM</n-tag>\n    </n-card>\n  </n-config-provider>\n</template>\n"
  },
  {
    "path": "src/config-provider/demos/zhCN/index.demo-entry.md",
    "content": "# 全局化配置 Config Provider\n\n全局化配置设置内部组件的主题、语言和组件卸载于其他位置的 DOM 的类名。\n\n了解更多关于主题设定的信息，参见[调整主题](../docs/customize-theme)。\n\n## 演示\n\n```demo\ntheme.vue\nnamespace.vue\ninherit-theme.vue\nos-theme.vue\nlanguage.vue\ntransparent.vue\ninline-theme-disabled.vue\nsize.vue\n```\n\n## API\n\n### ConfigProvider Props\n\n| 名称 | 类型 | 默认值 | 说明 | 版本 |\n| --- | --- | --- | --- | --- |\n| abstract | `boolean` | `false` | 是否不存在 DOM 包裹 |  |\n| breakpoints | `{ [k: string]: number }` | `{ xs: <640, s: ≥640, m: ≥1024, l: ≥1280, xl: ≥1536, xxl: ≥1920 }` | 屏幕响应式断点，对 `n-grid` 生效。这个属性不是响应式的，你需要在组件第一次挂载时就设定好 |  |\n| cls-prefix | `string` | `undefined` | 内部所有组件的类的前缀。（从 `2.40.0` 开始）如果不设置 `n-config-provider` 的类前缀 `cls-prefix`，则默认继承父级的类前缀。注意，该属性不是响应式的。 |  |\n| component-options | `GlobalComponentConfig` | `undefined` | 全局组件配置项。一些属性可以按组件维度分别配置。为 `undefined` 时会继承上级 `n-config-provider` |  |\n| date-locale | `DateLocale \\| null` | `undefined` | 对后代组件生效的日期语言对象，为 `null` 时会使用默认 `dateEnUS`，为 `undefined` 时会继承上级 `n-config-provider` |  |\n| inline-theme-disabled | `boolean` | `false` | 是否禁用 inline css 主题变量，如果你不会频繁调整主题变量，并且需要 SSR 或者想让 devtools 看起来更干净，可以打开这个选项。注意，这个属性不是响应式的 | 2.26.0 |\n| katex | `object` | `undefined` | 公式组件需要的 katex 对象 | 2.34.0 |\n| locale | `Locale \\| null` | `undefined` | 对后代组件生效的语言对象，为 `null` 时会使用默认 `enUS`，为 `undefined` 时会继承上级 `n-config-provider` |  |\n| namespace | `string` | `undefined` | `n-config-provider` 内部组件被卸载于其他位置的 DOM 的类名 |  |\n| preflight-style-disabled | `boolean` | `false` | 是否禁用默认样式，如果你禁用了它，便可以完全控制全局样式。你也可以使用 `n-global-style` 去挂载全局样式（推荐，样式是响应式的） | 2.29.0 |\n| style-mount-target | `ParentNode` | `undefined` | 组件样式的挂载位置。注意，该属性不是响应式的。 | 2.40.0 |\n| tag | `string` | `'div'` | `n-config-provider` 被渲染成的元素 |  |\n| theme | `Theme \\| null` | `undefined` | 对后代组件生效的主题对象，为 `null` 时会使用默认亮色，为 `undefined` 时会继承上级 `n-config-provider`。更多信息参见[调整主题](../docs/customize-theme) |  |\n| theme-overrides | `ThemeOverrides \\| null` | `undefined` | 对后代组件生效的主题变量覆盖，为 `null` 时会清除全部覆盖变量，为 `undefined` 时会继承上级 `n-config-provider`。更多信息参见[调整主题](../docs/customize-theme) |  |\n\n#### GlobalComponentConfig 类型\n\n```ts\ninterface GlobalComponentConfig {\n  AutoComplete?: {\n    size?: AutoCompleteSize\n  }\n  Button?: {\n    size?: ButtonSize\n  }\n  Card?: {\n    size?: CardSize\n  }\n  Cascader?: {\n    size?: CascaderSize\n    renderEmpty?: () => VNodeChild\n  }\n  Checkbox?: {\n    size?: CheckboxSize\n  }\n  ColorPicker?: {\n    size?: ColorPickerSize\n  }\n  DataTable?: {\n    size?: DataTableSize\n    renderFilter?: DataTableRenderFilter\n    renderSorter?: DataTableRenderSorter\n    renderEmpty?: () => VNodeChild\n  }\n  DatePicker?: {\n    size?: DatePickerSize\n    timePickerSize?: TimePickerSize\n  }\n  Descriptions?: {\n    size?: DescriptionsSize\n  }\n  Dialog?: {\n    iconPlacement?: IconPlacement\n  }\n  Dropdown?: {\n    size?: DropdownSize\n  }\n  DynamicInput?: {\n    buttonSize?: ButtonSize\n  }\n  DynamicTags?: {\n    size?: DynamicTagsSize\n  }\n  Empty?: Pick<EmptyProps, 'description' | 'renderIcon'>\n  Form?: {\n    size?: FormSize\n  }\n  Input?: {\n    size?: InputSize\n  }\n  InputNumber?: {\n    size?: InputNumberSize\n  }\n  InputOtp?: {\n    size?: InputOtpSize\n  }\n  Mention?: {\n    size?: MentionSize\n  }\n  Pagination?: {\n    size?: PaginationSize\n    inputSize?: InputSize\n    selectSize?: SelectSize\n  }\n  Popselect?: {\n    size?: PopselectSize\n  }\n  Radio?: {\n    size?: RadioSize\n  }\n  Rate?: {\n    size?: RateSize\n  }\n  Result?: {\n    size?: ResultSize\n  }\n  Select?: {\n    size?: SelectSize\n    renderEmpty?: () => VNodeChild\n  }\n  Skeleton?: {\n    size?: SkeletonSize\n  }\n  Space?: {\n    size?: SpaceSize\n  }\n  Switch?: {\n    size?: SwitchSize\n  }\n  Table?: {\n    size?: TableSize\n  }\n  Tabs?: {\n    size?: TabsSize\n  }\n  Tag?: {\n    size?: TagSize\n  }\n  TimePicker?: {\n    size?: TimePickerSize\n  }\n  Transfer?: {\n    size?: TransferSize\n    renderEmpty?: () => VNodeChild\n  }\n  Tree?: {\n    renderEmpty?: () => VNodeChild\n  }\n  TreeSelect?: {\n    size?: TreeSelectSize\n    renderEmpty?: () => VNodeChild\n  }\n}\n```\n"
  },
  {
    "path": "src/config-provider/demos/zhCN/inherit-theme.demo.vue",
    "content": "<markdown>\n# 继承主题\n\n如果不设置 `n-config-provider` 的主题，则 `n-config-provider` 主题默认继承外面的主题。\n</markdown>\n\n<template>\n  <n-config-provider>\n    <n-tag>噢</n-tag>\n  </n-config-provider>\n</template>\n"
  },
  {
    "path": "src/config-provider/demos/zhCN/inline-theme-disabled.demo.vue",
    "content": "<markdown>\n# 禁用 inline 主题\n\nnaive-ui 默认情况下使用 inline style 作为主题变量的载体，因此每个组件上都会挂载许多 inline CSS。如果你需要 SSR，或者想让开发者工具看起来更干净，可以打开 `inline-theme-disabled` 属性。\n\n注意，如果你需要频繁的改动 `theme-overrides`，不建议使用这个属性，这样会生成大量无用的 style 标签。\n\n这个属性不是响应式的。\n</markdown>\n\n<template>\n  <n-config-provider inline-theme-disabled>\n    <n-button>不再有 inline CSS 变量的按钮</n-button>\n  </n-config-provider>\n</template>\n"
  },
  {
    "path": "src/config-provider/demos/zhCN/language.demo.vue",
    "content": "<markdown>\n# 国际化\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { NDateLocale, NLocale } from 'naive-ui'\nimport { dateZhCN, zhCN } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst locale = ref<NLocale | null>(null)\nconst dateLocale = ref<NDateLocale | null>(null)\n</script>\n\n<template>\n  <n-space vertical>\n    <n-space>\n      <n-button\n        @click=\"\n          () => {\n            locale = null\n            dateLocale = null\n          }\n        \"\n      >\n        英文\n      </n-button>\n      <n-button\n        @click=\"\n          () => {\n            locale = zhCN\n            dateLocale = dateZhCN\n          }\n        \"\n      >\n        中文\n      </n-button>\n    </n-space>\n    <n-config-provider :locale=\"locale\" :date-locale=\"dateLocale\">\n      <n-date-picker />\n    </n-config-provider>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/config-provider/demos/zhCN/namespace.demo.vue",
    "content": "<markdown>\n# 命名空间（挂载内容的类名）\n\n组件的一部分是挂载在 `document.body` 上的。如需给这些可卸载的元素添加 class，使用 `n-config-provider` 的 `namespace` 属性。打开开发者工具可以看到被卸载的 DOM。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst ns = ref('custom-app-namespace1')\nconst isActive = ref(false)\n</script>\n\n<template>\n  <n-config-provider :namespace=\"ns\">\n    <n-tooltip placement=\"bottom\" trigger=\"click\">\n      <template #trigger>\n        <n-button @click=\"isActive = true\">\n          激活含卸载内容的组件\n        </n-button>\n      </template>\n      <span>卸载内容</span>\n    </n-tooltip>\n  </n-config-provider>\n</template>\n"
  },
  {
    "path": "src/config-provider/demos/zhCN/os-theme.demo.vue",
    "content": "<markdown>\n# 使用操作系统主题\n\nNaive UI 提供 `useOsTheme` 来获取当前操作系统的主题。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { darkTheme, useOsTheme } from 'naive-ui'\nimport { computed } from 'vue'\n\nconst osTheme = useOsTheme()\nconst theme = computed(() => (osTheme.value === 'dark' ? darkTheme : null))\n</script>\n\n<template>\n  <n-config-provider :theme=\"theme\">\n    <n-card> 当前操作系统的主题是 {{ osTheme }}。 </n-card>\n  </n-config-provider>\n</template>\n"
  },
  {
    "path": "src/config-provider/demos/zhCN/overrides-inherit-debug.demo.vue",
    "content": "<markdown>\n# Theme Overrides Debug\n</markdown>\n\n<script lang=\"ts\" setup>\nconst overrides1 = {\n  Button: {\n    colorInfo: 'red',\n    colorError: 'yellow'\n  }\n}\n\nconst overrides2 = {\n  Button: {\n    colorWarning: 'blue',\n    colorError: 'green'\n  }\n}\n</script>\n\n<template>\n  <n-config-provider :theme-overrides=\"overrides1\">\n    <n-config-provider :theme-overrides=\"overrides2\">\n      <n-button type=\"info\">\n        Red(Parent)\n      </n-button>\n      <n-button type=\"error\">\n        Green(Child Override)\n      </n-button>\n      <n-button type=\"warning\">\n        Blue(Child)\n      </n-button>\n    </n-config-provider>\n  </n-config-provider>\n</template>\n"
  },
  {
    "path": "src/config-provider/demos/zhCN/size.demo.vue",
    "content": "<markdown>\n# 组件尺寸\n\n通过 `component-options` 按组件配置尺寸。\n</markdown>\n\n<script setup lang=\"ts\">\nimport { computed, ref } from 'vue'\n\ntype ComponentSize = 'small' | 'medium' | 'large'\n\nconst size = ref<ComponentSize>('small')\n\nfunction handleBtnClick(_size: ComponentSize): void {\n  size.value = _size\n}\n\nconst componentOptions = computed(() => ({\n  Button: { size: size.value },\n  Card: { size: size.value },\n  Pagination: { size: size.value },\n  Tag: { size: size.value }\n}))\n</script>\n\n<template>\n  <n-button-group>\n    <n-button @click=\"handleBtnClick('small')\">\n      小一点儿\n    </n-button>\n    <n-button @click=\"handleBtnClick('medium')\">\n      中规中矩\n    </n-button>\n    <n-button @click=\"handleBtnClick('large')\">\n      大一点儿\n    </n-button>\n  </n-button-group>\n  <n-divider />\n  <n-config-provider :component-options=\"componentOptions\">\n    <n-space vertical>\n      <n-button>按钮</n-button>\n      <n-tag closable>\n        标签\n      </n-tag>\n      <n-card title=\"卡片\">\n        卡片内容\n      </n-card>\n      <n-pagination :page-count=\"20\" />\n    </n-space>\n  </n-config-provider>\n</template>\n"
  },
  {
    "path": "src/config-provider/demos/zhCN/theme.demo.vue",
    "content": "<markdown>\n# 主题\n\n设置 `n-config-provider` 内部组件的主题。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { GlobalTheme } from 'naive-ui'\nimport { darkTheme } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst theme = ref<GlobalTheme | null>(null)\n</script>\n\n<template>\n  <n-config-provider :theme=\"theme\">\n    <n-card>\n      <n-space>\n        <n-button @click=\"theme = darkTheme\">\n          深色\n        </n-button>\n        <n-button @click=\"theme = null\">\n          浅色\n        </n-button>\n      </n-space>\n    </n-card>\n  </n-config-provider>\n</template>\n"
  },
  {
    "path": "src/config-provider/demos/zhCN/transparent.demo.vue",
    "content": "<markdown>\n# 不需要包裹 DOM\n\n如果不需要包裹 DOM，设置 `abstract`。\n</markdown>\n\n<template>\n  <n-config-provider abstract>\n    <n-card>\n      <n-tag>无包裹 DOM</n-tag>\n    </n-card>\n  </n-config-provider>\n</template>\n"
  },
  {
    "path": "src/config-provider/index.ts",
    "content": "export {\n  configProviderProps,\n  default as NConfigProvider\n} from './src/ConfigProvider'\nexport type { ConfigProviderProps } from './src/ConfigProvider'\nexport * from './src/interface'\n"
  },
  {
    "path": "src/config-provider/src/ConfigProvider.ts",
    "content": "import type { ComputedRef, ExtractPropTypes, PropType } from 'vue'\nimport type { Hljs } from '../../_mixins'\nimport type { NDateLocale, NLocale } from '../../locales'\nimport type {\n  GlobalComponentConfig,\n  GlobalIconConfig,\n  GlobalTheme,\n  GlobalThemeOverrides\n} from './interface'\nimport type {\n  Breakpoints,\n  RtlEnabledState,\n  RtlProp\n} from './internal-interface'\nimport type { Katex } from './katex'\nimport { hash } from 'css-render'\nimport { merge } from 'lodash-es'\nimport { useMemo } from 'vooks'\nimport { computed, defineComponent, h, inject, markRaw, provide } from 'vue'\nimport { defaultClsPrefix } from '../../_mixins'\nimport { warn } from '../../_utils'\nimport { configProviderInjectionKey } from './context'\n\nexport const configProviderProps = {\n  abstract: Boolean,\n  bordered: {\n    type: Boolean as PropType<boolean | undefined>,\n    default: undefined\n  },\n  clsPrefix: String,\n  locale: Object as PropType<NLocale | null>,\n  dateLocale: Object as PropType<NDateLocale | null>,\n  namespace: String,\n  rtl: Array as PropType<RtlProp>,\n  tag: {\n    type: String,\n    default: 'div'\n  },\n  hljs: Object as PropType<Hljs>,\n  katex: Object as PropType<Katex>,\n  theme: Object as PropType<GlobalTheme | null>,\n  themeOverrides: Object as PropType<GlobalThemeOverrides | null>,\n  componentOptions: Object as PropType<GlobalComponentConfig>,\n  icons: Object as PropType<GlobalIconConfig>,\n  breakpoints: Object as PropType<Breakpoints>,\n  preflightStyleDisabled: Boolean,\n  styleMountTarget: Object as PropType<ParentNode | null>,\n  inlineThemeDisabled: {\n    type: Boolean,\n    default: undefined\n  },\n  // deprecated\n  as: {\n    type: String as PropType<string | undefined>,\n    validator: () => {\n      warn('config-provider', '`as` is deprecated, please use `tag` instead.')\n      return true\n    },\n    default: undefined\n  }\n} as const\n\nexport type ConfigProviderProps = Partial<\n  ExtractPropTypes<typeof configProviderProps>\n>\n\nexport default defineComponent({\n  name: 'ConfigProvider',\n  alias: ['App'],\n  props: configProviderProps,\n  setup(props) {\n    const NConfigProvider = inject(configProviderInjectionKey, null)\n    const mergedThemeRef = computed(() => {\n      const { theme } = props\n      if (theme === null)\n        return undefined\n      const inheritedTheme = NConfigProvider?.mergedThemeRef.value\n      return theme === undefined\n        ? inheritedTheme\n        : inheritedTheme === undefined\n          ? theme\n          : Object.assign({}, inheritedTheme, theme)\n    })\n    const mergedThemeOverridesRef = computed(() => {\n      const { themeOverrides } = props\n      // stop inheriting themeOverrides\n      if (themeOverrides === null)\n        return undefined\n      // use inherited themeOverrides\n      if (themeOverrides === undefined) {\n        return NConfigProvider?.mergedThemeOverridesRef.value\n      }\n      else {\n        const inheritedThemeOverrides\n          = NConfigProvider?.mergedThemeOverridesRef.value\n        if (inheritedThemeOverrides === undefined) {\n          // no inherited, use self overrides\n          return themeOverrides\n        }\n        else {\n          // merge overrides\n          return merge({}, inheritedThemeOverrides, themeOverrides)\n        }\n      }\n    })\n    const mergedNamespaceRef = useMemo(() => {\n      const { namespace } = props\n      return namespace === undefined\n        ? NConfigProvider?.mergedNamespaceRef.value\n        : namespace\n    })\n    const mergedBorderedRef = useMemo(() => {\n      const { bordered } = props\n      return bordered === undefined\n        ? NConfigProvider?.mergedBorderedRef.value\n        : bordered\n    })\n    const mergedIconsRef = computed(() => {\n      const { icons } = props\n      return icons === undefined ? NConfigProvider?.mergedIconsRef.value : icons\n    })\n    const mergedComponentPropsRef = computed(() => {\n      const { componentOptions } = props\n      if (componentOptions !== undefined)\n        return componentOptions\n      return NConfigProvider?.mergedComponentPropsRef.value\n    })\n    const mergedClsPrefixRef = computed(() => {\n      const { clsPrefix } = props\n      if (clsPrefix !== undefined)\n        return clsPrefix\n      if (NConfigProvider)\n        return NConfigProvider.mergedClsPrefixRef.value\n      return defaultClsPrefix\n    })\n    const mergedRtlRef: ComputedRef<RtlEnabledState | undefined> = computed(\n      () => {\n        const { rtl } = props\n        if (rtl === undefined) {\n          return NConfigProvider?.mergedRtlRef.value\n        }\n        const rtlEnabledState: RtlEnabledState = {}\n        for (const rtlInfo of rtl) {\n          rtlEnabledState[rtlInfo.name] = markRaw(rtlInfo)\n          rtlInfo.peers?.forEach((peerRtlInfo) => {\n            if (!(peerRtlInfo.name in rtlEnabledState)) {\n              rtlEnabledState[peerRtlInfo.name] = markRaw(peerRtlInfo)\n            }\n          })\n        }\n        return rtlEnabledState\n      }\n    )\n    const mergedBreakpointsRef = computed(() => {\n      return props.breakpoints || NConfigProvider?.mergedBreakpointsRef.value\n    })\n    const inlineThemeDisabled\n      = props.inlineThemeDisabled || NConfigProvider?.inlineThemeDisabled\n    const preflightStyleDisabled\n      = props.preflightStyleDisabled || NConfigProvider?.preflightStyleDisabled\n    const styleMountTarget\n      = props.styleMountTarget || NConfigProvider?.styleMountTarget\n    const mergedThemeHashRef = computed(() => {\n      const { value: theme } = mergedThemeRef\n      const { value: mergedThemeOverrides } = mergedThemeOverridesRef\n      const hasThemeOverrides\n        = mergedThemeOverrides && Object.keys(mergedThemeOverrides).length !== 0\n      const themeName = theme?.name\n      if (themeName) {\n        if (hasThemeOverrides) {\n          return `${themeName}-${hash(\n            JSON.stringify(mergedThemeOverridesRef.value)\n          )}`\n        }\n        return themeName\n      }\n      else {\n        if (hasThemeOverrides) {\n          return hash(JSON.stringify(mergedThemeOverridesRef.value))\n        }\n        return ''\n      }\n    })\n    provide(configProviderInjectionKey, {\n      mergedThemeHashRef,\n      mergedBreakpointsRef,\n      mergedRtlRef,\n      mergedIconsRef,\n      mergedComponentPropsRef,\n      mergedBorderedRef,\n      mergedNamespaceRef,\n      mergedClsPrefixRef,\n      mergedLocaleRef: computed(() => {\n        const { locale } = props\n        if (locale === null)\n          return undefined\n        return locale === undefined\n          ? NConfigProvider?.mergedLocaleRef.value\n          : locale\n      }),\n      mergedDateLocaleRef: computed(() => {\n        const { dateLocale } = props\n        if (dateLocale === null)\n          return undefined\n        return dateLocale === undefined\n          ? NConfigProvider?.mergedDateLocaleRef.value\n          : dateLocale\n      }),\n      mergedHljsRef: computed(() => {\n        const { hljs } = props\n        return hljs === undefined ? NConfigProvider?.mergedHljsRef.value : hljs\n      }),\n      mergedKatexRef: computed(() => {\n        const { katex } = props\n        return katex === undefined\n          ? NConfigProvider?.mergedKatexRef.value\n          : katex\n      }),\n      mergedThemeRef,\n      mergedThemeOverridesRef,\n      inlineThemeDisabled: inlineThemeDisabled || false,\n      preflightStyleDisabled: preflightStyleDisabled || false,\n      styleMountTarget\n    })\n    return {\n      mergedClsPrefix: mergedClsPrefixRef,\n      mergedBordered: mergedBorderedRef,\n      mergedNamespace: mergedNamespaceRef,\n      mergedTheme: mergedThemeRef,\n      mergedThemeOverrides: mergedThemeOverridesRef\n    }\n  },\n  render() {\n    return !this.abstract\n      ? h(\n          this.as || this.tag,\n          {\n            class: `${this.mergedClsPrefix || defaultClsPrefix}-config-provider`\n          },\n          this.$slots.default?.()\n        )\n      : this.$slots.default?.()\n  }\n})\n"
  },
  {
    "path": "src/config-provider/src/config.ts",
    "content": "export const defaultBreakpoints = {\n  xs: 0, // mobile\n  s: 640, // tablet\n  m: 1024, // laptop s\n  l: 1280, // laptop\n  xl: 1536, // laptop l\n  xxl: 1920 // normal desktop display\n} as const\n"
  },
  {
    "path": "src/config-provider/src/context.ts",
    "content": "import type { ConfigProviderInjection } from './internal-interface'\nimport { createInjectionKey } from '../../_utils'\n\nexport const configProviderInjectionKey\n  = createInjectionKey<ConfigProviderInjection>('n-config-provider')\n"
  },
  {
    "path": "src/config-provider/src/interface.ts",
    "content": "import type { ExtractThemeOverrides } from '../../_mixins/use-theme'\nimport type { ThemeCommonVars } from '../../_styles/common'\nimport type { GlobalThemeWithoutCommon } from './internal-interface'\n\nexport type { ThemeCommonVars }\n\nexport interface CustomThemeCommonVars {}\n\nexport interface GlobalTheme extends GlobalThemeWithoutCommon {\n  name: string\n  common?: ThemeCommonVars\n}\n\nexport type GlobalThemeOverrides = {\n  common?: Partial<ThemeCommonVars & CustomThemeCommonVars>\n} & {\n  [key in keyof GlobalThemeWithoutCommon]?: ExtractThemeOverrides<\n    GlobalThemeWithoutCommon[key]\n  >\n}\n\nexport type {\n  GlobalComponentConfig,\n  GlobalIconConfig\n} from './internal-interface'\n"
  },
  {
    "path": "src/config-provider/src/internal-interface.ts",
    "content": "import type { CNode } from 'css-render'\nimport type { Ref, VNodeChild } from 'vue'\nimport type { ScrollbarTheme } from '../../_internal/scrollbar/styles'\nimport type { InternalSelectMenuTheme } from '../../_internal/select-menu/styles'\nimport type { InternalSelectionTheme } from '../../_internal/selection/styles'\nimport type { Hljs } from '../../_mixins'\nimport type { AlertTheme } from '../../alert/styles'\nimport type { AnchorTheme } from '../../anchor/styles'\nimport type { AutoCompleteSize } from '../../auto-complete/src/public-types'\nimport type { AutoCompleteTheme } from '../../auto-complete/styles'\nimport type { AvatarGroupTheme } from '../../avatar-group/styles'\nimport type { AvatarTheme } from '../../avatar/styles'\nimport type { BackTopTheme } from '../../back-top/styles'\nimport type { BadgeTheme } from '../../badge/styles'\nimport type { BreadcrumbTheme } from '../../breadcrumb/styles'\nimport type { ButtonGroupTheme } from '../../button-group/styles/light'\nimport type { ButtonSize } from '../../button/src/public-types'\nimport type { ButtonTheme } from '../../button/styles'\nimport type { CalendarTheme } from '../../calendar/styles'\nimport type { CardSize } from '../../card/src/public-types'\nimport type { CardTheme } from '../../card/styles'\nimport type { CarouselTheme } from '../../carousel/styles'\nimport type { CascaderSize } from '../../cascader/src/public-types'\nimport type { CascaderTheme } from '../../cascader/styles'\nimport type { CheckboxSize } from '../../checkbox/src/public-types'\nimport type { CheckboxTheme } from '../../checkbox/styles'\nimport type { CodeTheme } from '../../code/styles'\nimport type { CollapseTransitionTheme } from '../../collapse-transition/styles'\nimport type { CollapseTheme } from '../../collapse/styles'\nimport type { ColorPickerSize } from '../../color-picker/src/public-types'\nimport type { ColorPickerTheme } from '../../color-picker/styles'\nimport type {\n  DataTableRenderFilter,\n  DataTableRenderSorter\n} from '../../data-table'\nimport type { DataTableSize } from '../../data-table/src/public-types'\nimport type { DataTableTheme } from '../../data-table/styles'\nimport type { DatePickerSize } from '../../date-picker/src/public-types'\nimport type { DatePickerTheme } from '../../date-picker/styles'\nimport type { DescriptionsSize } from '../../descriptions/src/public-types'\nimport type { DescriptionsTheme } from '../../descriptions/styles'\nimport type { IconPlacement } from '../../dialog/src/interface'\nimport type { DialogTheme } from '../../dialog/styles'\nimport type { DividerTheme } from '../../divider/styles'\nimport type { DrawerTheme } from '../../drawer/styles'\nimport type { DropdownSize } from '../../dropdown/src/public-types'\nimport type { DropdownTheme } from '../../dropdown/styles'\nimport type { DynamicInputTheme } from '../../dynamic-input/styles'\nimport type { DynamicTagsSize } from '../../dynamic-tags/src/public-types'\nimport type { DynamicTagsTheme } from '../../dynamic-tags/styles'\nimport type { ElementTheme } from '../../element/styles'\nimport type { EllipsisTheme } from '../../ellipsis/styles'\nimport type { EmptyProps } from '../../empty'\nimport type { EmptyTheme } from '../../empty/styles'\nimport type { EquationTheme } from '../../equation/styles'\nimport type { FlexTheme } from '../../flex/styles'\nimport type { FloatButtonGroupTheme } from '../../float-button-group/styles'\nimport type { FloatButtonTheme } from '../../float-button/styles'\nimport type { FormSize } from '../../form/src/public-types'\nimport type { FormTheme } from '../../form/styles'\nimport type { GradientTextTheme } from '../../gradient-text/styles'\nimport type { HeatmapTheme } from '../../heatmap/styles'\nimport type { IconWrapperTheme } from '../../icon-wrapper/styles'\nimport type { IconTheme } from '../../icon/styles'\nimport type { ImageTheme } from '../../image/styles'\nimport type { InputNumberSize } from '../../input-number/src/public-types'\nimport type { InputNumberTheme } from '../../input-number/styles'\nimport type { InputOtpSize } from '../../input-otp/src/public-types'\nimport type { InputOtpTheme } from '../../input-otp/styles'\nimport type { InputSize } from '../../input/src/public-types'\nimport type { InputTheme } from '../../input/styles'\nimport type { LayoutTheme } from '../../layout/styles'\nimport type { RowTheme } from '../../legacy-grid/styles'\nimport type { LegacyTransferTheme } from '../../legacy-transfer/styles'\nimport type { ListTheme } from '../../list/styles'\nimport type { LoadingBarTheme } from '../../loading-bar/styles'\nimport type { NDateLocale, NLocale } from '../../locales'\nimport type { LogTheme } from '../../log/styles'\nimport type { MarqueeTheme } from '../../marquee/styles'\nimport type { MentionSize } from '../../mention/src/public-types'\nimport type { MentionTheme } from '../../mention/styles'\nimport type { MenuTheme } from '../../menu/styles'\nimport type { MessageTheme } from '../../message/styles'\nimport type { ModalTheme } from '../../modal/styles'\nimport type { NotificationTheme } from '../../notification/styles'\nimport type { PageHeaderTheme } from '../../page-header/styles'\nimport type { PaginationSize } from '../../pagination/src/public-types'\nimport type { PaginationTheme } from '../../pagination/styles'\nimport type { PopconfirmTheme } from '../../popconfirm/styles'\nimport type { PopoverTheme } from '../../popover/styles'\nimport type { PopselectSize } from '../../popselect/src/public-types'\nimport type { PopselectTheme } from '../../popselect/styles'\nimport type { ProgressTheme } from '../../progress/styles'\nimport type { QrCodeTheme } from '../../qr-code/styles'\nimport type { RadioSize } from '../../radio/src/public-types'\nimport type { RadioTheme } from '../../radio/styles'\nimport type { RateSize } from '../../rate/src/public-types'\nimport type { RateTheme } from '../../rate/styles'\nimport type { ResultSize } from '../../result/src/public-types'\nimport type { ResultTheme } from '../../result/styles'\nimport type { SelectSize } from '../../select/src/public-types'\nimport type { SelectTheme } from '../../select/styles'\nimport type { SkeletonSize } from '../../skeleton/src/public-types'\nimport type { SkeletonTheme } from '../../skeleton/styles'\nimport type { SliderTheme } from '../../slider/styles'\nimport type { SpaceSize } from '../../space/src/public-types'\nimport type { SpaceTheme } from '../../space/styles'\nimport type { SpinTheme } from '../../spin/styles'\nimport type { SplitTheme } from '../../split/styles'\nimport type { StatisticTheme } from '../../statistic/styles'\nimport type { StepsTheme } from '../../steps/styles'\nimport type { SwitchSize } from '../../switch/src/public-types'\nimport type { SwitchTheme } from '../../switch/styles'\nimport type { TableSize } from '../../table/src/public-types'\nimport type { TableTheme } from '../../table/styles'\nimport type { TabsSize } from '../../tabs/src/public-types'\nimport type { TabsTheme } from '../../tabs/styles'\nimport type { TagSize } from '../../tag/src/public-types'\nimport type { TagTheme } from '../../tag/styles'\nimport type { ThingTheme } from '../../thing/styles'\nimport type { TimePickerSize } from '../../time-picker/src/public-types'\nimport type { TimePickerTheme } from '../../time-picker/styles'\nimport type { TimelineTheme } from '../../timeline/styles'\nimport type { TooltipTheme } from '../../tooltip/styles'\nimport type { TransferSize } from '../../transfer/src/public-types'\nimport type { TransferTheme } from '../../transfer/styles'\nimport type { TreeSelectSize } from '../../tree-select/src/public-types'\nimport type { TreeSelectTheme } from '../../tree-select/styles'\nimport type { TreeTheme } from '../../tree/styles'\nimport type { TypographyTheme } from '../../typography/styles'\nimport type { UploadTheme } from '../../upload/styles'\nimport type { WatermarkTheme } from '../../watermark/styles'\nimport type { GlobalTheme, GlobalThemeOverrides } from './interface'\nimport type { Katex } from './katex'\n\nexport interface GlobalThemeWithoutCommon {\n  Alert?: AlertTheme\n  Anchor?: AnchorTheme\n  AutoComplete?: AutoCompleteTheme\n  Avatar?: AvatarTheme\n  AvatarGroup?: AvatarGroupTheme\n  BackTop?: BackTopTheme\n  Badge?: BadgeTheme\n  Breadcrumb?: BreadcrumbTheme\n  Button?: ButtonTheme\n  ButtonGroup?: ButtonGroupTheme\n  Calendar?: CalendarTheme\n  Card?: CardTheme\n  Carousel?: CarouselTheme\n  Cascader?: CascaderTheme\n  Checkbox?: CheckboxTheme\n  Code?: CodeTheme\n  Collapse?: CollapseTheme\n  CollapseTransition?: CollapseTransitionTheme\n  ColorPicker?: ColorPickerTheme\n  DataTable?: DataTableTheme\n  DatePicker?: DatePickerTheme\n  Descriptions?: DescriptionsTheme\n  Dialog?: DialogTheme\n  Divider?: DividerTheme\n  Drawer?: DrawerTheme\n  Dropdown?: DropdownTheme\n  DynamicInput?: DynamicInputTheme\n  DynamicTags?: DynamicTagsTheme\n  Element?: ElementTheme\n  Ellipsis?: EllipsisTheme\n  Empty?: EmptyTheme\n  Equation?: EquationTheme\n  Flex?: FlexTheme\n  Form?: FormTheme\n  FloatButton?: FloatButtonTheme\n  FloatButtonGroup?: FloatButtonGroupTheme\n  GradientText?: GradientTextTheme\n  Icon?: IconTheme\n  IconWrapper?: IconWrapperTheme\n  Image?: ImageTheme\n  Input?: InputTheme\n  InputNumber?: InputNumberTheme\n  InputOtp?: InputOtpTheme\n  Layout?: LayoutTheme\n  LegacyTransfer?: LegacyTransferTheme\n  List?: ListTheme\n  LoadingBar?: LoadingBarTheme\n  Log?: LogTheme\n  Menu?: MenuTheme\n  Mention?: MentionTheme\n  Message?: MessageTheme\n  Modal?: ModalTheme\n  Notification?: NotificationTheme\n  PageHeader?: PageHeaderTheme\n  Pagination?: PaginationTheme\n  Popconfirm?: PopconfirmTheme\n  Popover?: PopoverTheme\n  Popselect?: PopselectTheme\n  Progress?: ProgressTheme\n  QrCode?: QrCodeTheme\n  Radio?: RadioTheme\n  Rate?: RateTheme\n  Result?: ResultTheme\n  Scrollbar?: ScrollbarTheme\n  Select?: SelectTheme\n  Skeleton?: SkeletonTheme\n  Slider?: SliderTheme\n  Space?: SpaceTheme\n  Spin?: SpinTheme\n  Statistic?: StatisticTheme\n  Steps?: StepsTheme\n  Switch?: SwitchTheme\n  Table?: TableTheme\n  Tabs?: TabsTheme\n  Tag?: TagTheme\n  Thing?: ThingTheme\n  TimePicker?: TimePickerTheme\n  Timeline?: TimelineTheme\n  Tooltip?: TooltipTheme\n  Transfer?: TransferTheme\n  Tree?: TreeTheme\n  TreeSelect?: TreeSelectTheme\n  Typography?: TypographyTheme\n  Upload?: UploadTheme\n  Watermark?: WatermarkTheme\n  Split?: SplitTheme\n  Row?: RowTheme\n  Marquee?: MarqueeTheme\n  Heatmap?: HeatmapTheme\n  // internal\n  InternalSelectMenu?: InternalSelectMenuTheme\n  InternalSelection?: InternalSelectionTheme\n}\n\nexport interface GlobalComponentConfig {\n  AutoComplete?: {\n    size?: AutoCompleteSize\n  }\n  Cascader?: {\n    size?: CascaderSize\n    renderEmpty?: () => VNodeChild\n  }\n  Button?: {\n    size?: ButtonSize\n  }\n  Card?: {\n    size?: CardSize\n  }\n  Checkbox?: {\n    size?: CheckboxSize\n  }\n  Pagination?: {\n    size?: PaginationSize\n    inputSize?: InputSize\n    selectSize?: SelectSize\n  }\n  ColorPicker?: {\n    size?: ColorPickerSize\n  }\n  DatePicker?: {\n    size?: DatePickerSize\n    timePickerSize?: TimePickerSize\n  }\n  Dialog?: {\n    iconPlacement?: IconPlacement\n  }\n  DataTable?: {\n    size?: DataTableSize\n    renderFilter?: DataTableRenderFilter\n    renderSorter?: DataTableRenderSorter\n    renderEmpty?: () => VNodeChild\n  }\n  Descriptions?: {\n    size?: DescriptionsSize\n  }\n  Dropdown?: {\n    size?: DropdownSize\n  }\n  DynamicInput?: {\n    buttonSize?: ButtonSize\n  }\n  DynamicTags?: {\n    size?: DynamicTagsSize\n  }\n  Empty?: Pick<EmptyProps, 'description' | 'renderIcon'>\n  Form?: {\n    size?: FormSize\n  }\n  Input?: {\n    size?: InputSize\n  }\n  InputNumber?: {\n    size?: InputNumberSize\n  }\n  InputOtp?: {\n    size?: InputOtpSize\n  }\n  Mention?: {\n    size?: MentionSize\n  }\n  Select?: {\n    size?: SelectSize\n    renderEmpty?: () => VNodeChild\n  }\n  Popselect?: {\n    size?: PopselectSize\n  }\n  Radio?: {\n    size?: RadioSize\n  }\n  Rate?: {\n    size?: RateSize\n  }\n  Result?: {\n    size?: ResultSize\n  }\n  Skeleton?: {\n    size?: SkeletonSize\n  }\n  Space?: {\n    size?: SpaceSize\n  }\n  Switch?: {\n    size?: SwitchSize\n  }\n  Table?: {\n    size?: TableSize\n  }\n  Tabs?: {\n    size?: TabsSize\n  }\n  Tag?: {\n    size?: TagSize\n  }\n  TimePicker?: {\n    size?: TimePickerSize\n  }\n  Transfer?: {\n    size?: TransferSize\n    renderEmpty?: () => VNodeChild\n  }\n  Tree?: {\n    renderEmpty?: () => VNodeChild\n  }\n  TreeSelect?: {\n    size?: TreeSelectSize\n    renderEmpty?: () => VNodeChild\n  }\n}\n\nexport interface GlobalIconConfig {\n  attach?: () => VNodeChild\n  cancel?: () => VNodeChild\n  clear?: () => VNodeChild\n  close?: () => VNodeChild\n  date?: () => VNodeChild\n  download?: () => VNodeChild\n  error?: () => VNodeChild\n  info?: () => VNodeChild\n  retry?: () => VNodeChild\n  success?: () => VNodeChild\n  time?: () => VNodeChild\n  to?: () => VNodeChild\n  trash?: () => VNodeChild\n  warning?: () => VNodeChild\n  rotateClockwise?: () => VNodeChild\n  rotateCounterclockwise?: () => VNodeChild\n  zoomIn?: () => VNodeChild\n  zoomOut?: () => VNodeChild\n}\n\nexport interface RtlItem {\n  name: keyof GlobalThemeWithoutCommon\n  style: CNode\n  peers?: RtlItem[]\n}\nexport type RtlProp = RtlItem[]\n\nexport type RtlEnabledState = Partial<\n  Record<keyof GlobalThemeWithoutCommon, RtlItem>\n>\n\nexport type Breakpoints = Record<string, number> | undefined\n\nexport interface ConfigProviderInjection {\n  mergedBreakpointsRef: Ref<Breakpoints | undefined>\n  mergedClsPrefixRef: Ref<string>\n  mergedBorderedRef: Ref<boolean | undefined>\n  mergedNamespaceRef: Ref<string | undefined>\n  mergedLocaleRef: Ref<NLocale | undefined>\n  mergedDateLocaleRef: Ref<NDateLocale | undefined>\n  mergedHljsRef: Ref<Hljs | undefined>\n  mergedKatexRef: Ref<Katex | undefined>\n  mergedComponentPropsRef: Ref<GlobalComponentConfig | undefined>\n  mergedIconsRef: Ref<GlobalIconConfig | undefined>\n  mergedThemeRef: Ref<GlobalTheme | undefined>\n  mergedThemeOverridesRef: Ref<GlobalThemeOverrides | undefined>\n  mergedRtlRef: Ref<RtlEnabledState | undefined>\n  mergedThemeHashRef: Ref<string>\n  // non-reactive\n  inlineThemeDisabled: boolean\n  preflightStyleDisabled: boolean\n  styleMountTarget: ParentNode | undefined\n}\n"
  },
  {
    "path": "src/config-provider/src/katex.ts",
    "content": "import type katex from 'katex'\n\nexport type Katex = typeof katex\n"
  },
  {
    "path": "src/config-provider/tests/ComponentSize.spec.tsx",
    "content": "import { mount } from '@vue/test-utils'\nimport { h, nextTick } from 'vue'\nimport { NAutoComplete } from '../../auto-complete'\nimport { NButton } from '../../button'\nimport { NCard } from '../../card'\nimport { NCascader } from '../../cascader'\nimport { NCheckbox } from '../../checkbox'\nimport { NColorPicker } from '../../color-picker'\nimport { NDataTable } from '../../data-table'\nimport { NDatePicker } from '../../date-picker'\nimport { NDescriptions } from '../../descriptions'\nimport { NDialog } from '../../dialog'\nimport { NDropdown } from '../../dropdown'\nimport { NDynamicInput } from '../../dynamic-input'\nimport { NDynamicTags } from '../../dynamic-tags'\nimport { NEmpty } from '../../empty'\nimport { NForm, NFormItem } from '../../form'\nimport { NInput } from '../../input'\nimport { NInputNumber } from '../../input-number'\nimport { NInputOtp } from '../../input-otp'\nimport { NMention } from '../../mention'\nimport { NPagination } from '../../pagination'\nimport { NPopselect } from '../../popselect'\nimport { NRadio } from '../../radio'\nimport { NRate } from '../../rate'\nimport { NResult } from '../../result'\nimport { NSelect } from '../../select'\nimport { NSkeleton } from '../../skeleton'\nimport { NSpace } from '../../space'\nimport { NSwitch } from '../../switch'\nimport { NTable } from '../../table'\nimport { NTabs } from '../../tabs'\nimport { NTag } from '../../tag'\nimport { NTimePicker } from '../../time-picker'\nimport { NTransfer } from '../../transfer'\nimport { NTree } from '../../tree'\nimport { NTreeSelect } from '../../tree-select'\nimport { NConfigProvider } from '../index'\n\nfunction mountWithConfig(\n  component: any,\n  configKey: string,\n  config: Record<string, any>,\n  extraProps: Record<string, any> = {},\n  slots: Record<string, any> = {}\n) {\n  return mount(NConfigProvider, {\n    props: {\n      componentOptions: {\n        [configKey]: config\n      }\n    },\n    slots: {\n      default: () => h(component, { ...extraProps }, slots)\n    }\n  })\n}\n\nfunction mountDirect(\n  component: any,\n  props: Record<string, any> = {},\n  slots: Record<string, any> = {}\n) {\n  return mount(component, { props, slots })\n}\n\nfunction testGlobalSize(\n  component: any,\n  configKey: string,\n  selector: string,\n  sizes: readonly string[],\n  extraProps: Record<string, any> = {}\n) {\n  sizes.forEach((size) => {\n    const globalWrapper = mountWithConfig(\n      component,\n      configKey,\n      { size },\n      extraProps\n    )\n    const propWrapper = mountDirect(component, { size, ...extraProps })\n    expect(globalWrapper.find(selector).attributes('style')).toBe(\n      propWrapper.find(selector).attributes('style')\n    )\n    globalWrapper.unmount()\n    propWrapper.unmount()\n  })\n}\n\nconst SML = ['small', 'medium', 'large'] as const\n\ndescribe('n-config-provider componentOptions', () => {\n  // ---- Size configs ----\n\n  it('should work with AutoComplete global size', () => {\n    testGlobalSize(NAutoComplete, 'AutoComplete', '.n-input', SML)\n  })\n\n  it('should work with Button global size', () => {\n    testGlobalSize(NButton, 'Button', 'button', [\n      'tiny',\n      'small',\n      'medium',\n      'large'\n    ])\n  })\n\n  it('should work with Card global size', () => {\n    testGlobalSize(NCard, 'Card', '.n-card', SML)\n  })\n\n  it('should work with Cascader global size', () => {\n    testGlobalSize(NCascader, 'Cascader', '.n-base-selection', SML, {\n      options: []\n    })\n  })\n\n  it('should work with Checkbox global size', () => {\n    testGlobalSize(NCheckbox, 'Checkbox', '.n-checkbox', SML)\n  })\n\n  it('should work with ColorPicker global size', () => {\n    testGlobalSize(NColorPicker, 'ColorPicker', '.n-color-picker', SML)\n  })\n\n  it('should work with DataTable global size', () => {\n    testGlobalSize(NDataTable, 'DataTable', '.n-data-table', SML, {\n      columns: [],\n      data: []\n    })\n  })\n\n  it('should work with DatePicker global size', () => {\n    testGlobalSize(NDatePicker, 'DatePicker', '.n-input', SML)\n  })\n\n  it('should work with Descriptions global size', () => {\n    testGlobalSize(NDescriptions, 'Descriptions', '.n-descriptions', SML)\n  })\n\n  it('should work with Dropdown global size', async () => {\n    const dropdownOptions = [\n      { label: 'opt1', key: '1' },\n      { label: 'opt2', key: '2' }\n    ]\n    for (const size of SML) {\n      const wrapper = mount(NConfigProvider, {\n        attachTo: document.body,\n        props: { componentOptions: { Dropdown: { size } } },\n        slots: {\n          default: () =>\n            h(\n              NDropdown,\n              { trigger: 'click', options: dropdownOptions },\n              { default: () => h('button', { class: 'dd-trigger' }, 'trigger') }\n            )\n        }\n      })\n      await wrapper.find('.dd-trigger').trigger('click')\n      await nextTick()\n      const menu = document.querySelector('.n-dropdown')\n      expect(menu?.classList.contains(`n-dropdown--${size}-size`)).toBe(true)\n      wrapper.unmount()\n    }\n  })\n\n  it('should work with DynamicTags global size', () => {\n    testGlobalSize(NDynamicTags, 'DynamicTags', '.n-dynamic-tags', SML)\n  })\n\n  it('should work with Form global size', () => {\n    SML.forEach((size) => {\n      const globalWrapper = mount(NConfigProvider, {\n        props: { componentOptions: { Form: { size } } },\n        slots: {\n          default: () =>\n            h(NForm, null, {\n              default: () =>\n                h(\n                  NFormItem,\n                  { label: 'test' },\n                  {\n                    default: () => h(NInput)\n                  }\n                )\n            })\n        }\n      })\n      const propWrapper = mount(NForm, {\n        props: { size },\n        slots: {\n          default: () =>\n            h(\n              NFormItem,\n              { label: 'test' },\n              {\n                default: () => h(NInput)\n              }\n            )\n        }\n      })\n      expect(globalWrapper.find('.n-input').attributes('style')).toBe(\n        propWrapper.find('.n-input').attributes('style')\n      )\n      globalWrapper.unmount()\n      propWrapper.unmount()\n    })\n  })\n\n  it('should work with Input global size', () => {\n    testGlobalSize(NInput, 'Input', '.n-input', SML)\n  })\n\n  it('should work with InputNumber global size', () => {\n    testGlobalSize(NInputNumber, 'InputNumber', '.n-input-number', SML)\n  })\n\n  it('should work with InputOtp global size', () => {\n    testGlobalSize(NInputOtp, 'InputOtp', '.n-input-otp', SML)\n  })\n\n  it('should work with Mention global size', () => {\n    testGlobalSize(NMention, 'Mention', '.n-input', SML, { options: [] })\n  })\n\n  it('should work with Pagination global size', () => {\n    testGlobalSize(NPagination, 'Pagination', '.n-pagination', SML, {\n      pageCount: 10\n    })\n  })\n\n  it('should work with Popselect global size', async () => {\n    const psOptions = [\n      { label: 'opt1', value: '1' },\n      { label: 'opt2', value: '2' }\n    ]\n    for (const size of SML) {\n      const wrapper = mount(NConfigProvider, {\n        attachTo: document.body,\n        props: { componentOptions: { Popselect: { size } } },\n        slots: {\n          default: () =>\n            h(\n              NPopselect,\n              { trigger: 'click', options: psOptions },\n              {\n                default: () => h('button', { class: 'ps-trigger' }, 'trigger')\n              }\n            )\n        }\n      })\n      await wrapper.find('.ps-trigger').trigger('click')\n      await nextTick()\n      const menu = document.querySelector('.n-base-select-menu')\n      expect(menu?.classList.contains(`n-base-select-menu--${size}-size`)).toBe(\n        true\n      )\n      wrapper.unmount()\n    }\n  })\n\n  it('should work with Radio global size', () => {\n    testGlobalSize(NRadio, 'Radio', '.n-radio', SML)\n  })\n\n  it('should work with Rate global size', () => {\n    testGlobalSize(NRate, 'Rate', '.n-rate', SML)\n  })\n\n  it('should work with Result global size', () => {\n    testGlobalSize(NResult, 'Result', '.n-result', SML)\n  })\n\n  it('should work with Select global size', () => {\n    testGlobalSize(NSelect, 'Select', '.n-base-selection', SML)\n  })\n\n  it('should work with Skeleton global size', () => {\n    testGlobalSize(NSkeleton, 'Skeleton', '.n-skeleton', SML)\n  })\n\n  it('should work with Space global size', () => {\n    SML.forEach((size) => {\n      const globalWrapper = mountWithConfig(\n        NSpace,\n        'Space',\n        { size },\n        {},\n        { default: () => [h('div', 'a'), h('div', 'b')] }\n      )\n      const propWrapper = mountDirect(\n        NSpace,\n        { size },\n        { default: () => [h('div', 'a'), h('div', 'b')] }\n      )\n      expect(globalWrapper.find('[role=\"none\"]').attributes('style')).toBe(\n        propWrapper.find('[role=\"none\"]').attributes('style')\n      )\n      globalWrapper.unmount()\n      propWrapper.unmount()\n    })\n  })\n\n  it('should work with Switch global size', () => {\n    testGlobalSize(NSwitch, 'Switch', '.n-switch', SML)\n  })\n\n  it('should work with Table global size', () => {\n    testGlobalSize(NTable, 'Table', '.n-table', SML)\n  })\n\n  it('should work with Tabs global size', () => {\n    testGlobalSize(NTabs, 'Tabs', '.n-tabs', SML)\n  })\n\n  it('should work with Tag global size', () => {\n    testGlobalSize(NTag, 'Tag', '.n-tag', SML)\n  })\n\n  it('should work with TimePicker global size', () => {\n    testGlobalSize(NTimePicker, 'TimePicker', '.n-input', SML)\n  })\n\n  it('should work with Transfer global size', () => {\n    testGlobalSize(NTransfer, 'Transfer', '.n-transfer', SML, {\n      options: []\n    })\n  })\n\n  it('should work with TreeSelect global size', () => {\n    testGlobalSize(NTreeSelect, 'TreeSelect', '.n-base-selection', SML, {\n      options: []\n    })\n  })\n\n  // ---- Non-size configs ----\n\n  it('should work with DatePicker global timePickerSize', async () => {\n    for (const size of SML) {\n      const wrapper = mount(NConfigProvider, {\n        attachTo: document.body,\n        props: {\n          componentOptions: { DatePicker: { timePickerSize: size } }\n        },\n        slots: {\n          default: () => h(NDatePicker, { type: 'datetime' })\n        }\n      })\n      await wrapper.find('.n-input').trigger('click')\n      await nextTick()\n      const panel = document.querySelector('.n-date-panel')\n      expect(panel).not.toBeNull()\n      const tpInput = panel?.querySelector('.n-time-picker .n-input')\n      expect(tpInput).not.toBeNull()\n      expect(tpInput?.classList.contains(`n-input--${size}-size`)).toBe(true)\n      wrapper.unmount()\n    }\n  })\n\n  it('should work with Dialog global iconPlacement', () => {\n    const wrapper = mountWithConfig(\n      NDialog,\n      'Dialog',\n      { iconPlacement: 'top' },\n      { title: 'Test', content: 'Content' }\n    )\n    const directWrapper = mountDirect(NDialog, {\n      iconPlacement: 'top',\n      title: 'Test',\n      content: 'Content'\n    })\n    expect(wrapper.find('.n-dialog').html()).toBe(\n      directWrapper.find('.n-dialog').html()\n    )\n    wrapper.unmount()\n    directWrapper.unmount()\n  })\n\n  it('should work with DynamicInput global buttonSize', () => {\n    SML.forEach((size) => {\n      const globalWrapper = mountWithConfig(\n        NDynamicInput,\n        'DynamicInput',\n        { buttonSize: size },\n        { defaultValue: ['a'] }\n      )\n      const buttons = globalWrapper.findAll(\n        '.n-dynamic-input-item__action button'\n      )\n      expect(buttons.length).toBeGreaterThan(0)\n      buttons.forEach((btn) => {\n        expect(btn.classes()).toContain(`n-button--${size}-type`)\n      })\n      globalWrapper.unmount()\n    })\n  })\n\n  it('should work with Empty global description', () => {\n    const wrapper = mountWithConfig(NEmpty, 'Empty', {\n      description: 'custom empty text'\n    })\n    expect(wrapper.text()).toContain('custom empty text')\n    wrapper.unmount()\n  })\n\n  it('should work with Empty global renderIcon', () => {\n    const wrapper = mountWithConfig(NEmpty, 'Empty', {\n      renderIcon: () => h('div', { class: 'custom-icon' }, 'icon')\n    })\n    expect(wrapper.find('.custom-icon').exists()).toBe(true)\n    wrapper.unmount()\n  })\n\n  it('should work with Pagination global inputSize and selectSize', () => {\n    const wrapper = mountWithConfig(\n      NPagination,\n      'Pagination',\n      { inputSize: 'small', selectSize: 'small' },\n      {\n        pageCount: 100,\n        showQuickJumper: true,\n        showSizePicker: true,\n        pageSizes: [10, 20]\n      }\n    )\n    expect(wrapper.find('.n-pagination').exists()).toBe(true)\n    wrapper.unmount()\n  })\n\n  it('should work with Cascader global renderEmpty', async () => {\n    const wrapper = mount(NConfigProvider, {\n      attachTo: document.body,\n      props: {\n        componentOptions: {\n          Cascader: {\n            renderEmpty: () =>\n              h('div', { class: 'cascader-custom-empty' }, 'no data')\n          }\n        }\n      },\n      slots: {\n        default: () => h(NCascader, { options: [] })\n      }\n    })\n    await wrapper.find('.n-base-selection').trigger('click')\n    await nextTick()\n    const menu = document.querySelector('.n-cascader-menu')\n    expect(menu).not.toBeNull()\n    expect(menu?.querySelector('.cascader-custom-empty')?.textContent).toBe(\n      'no data'\n    )\n    wrapper.unmount()\n  })\n\n  it('should work with Select global renderEmpty', async () => {\n    const wrapper = mount(NConfigProvider, {\n      attachTo: document.body,\n      props: {\n        componentOptions: {\n          Select: {\n            renderEmpty: () =>\n              h('div', { class: 'select-custom-empty' }, 'no data')\n          }\n        }\n      },\n      slots: {\n        default: () => h(NSelect, { options: [] })\n      }\n    })\n    await wrapper.find('.n-base-selection').trigger('click')\n    await nextTick()\n    const menu = document.querySelector('.n-base-select-menu')\n    expect(menu).not.toBeNull()\n    expect(menu?.querySelector('.select-custom-empty')?.textContent).toBe(\n      'no data'\n    )\n    wrapper.unmount()\n  })\n\n  it('should work with DataTable global renderEmpty', () => {\n    const wrapper = mountWithConfig(\n      NDataTable,\n      'DataTable',\n      { renderEmpty: () => h('div', { class: 'custom-empty' }, 'no data') },\n      { columns: [{ title: 'Name', key: 'name' }], data: [] }\n    )\n    expect(wrapper.find('.custom-empty').exists()).toBe(true)\n    wrapper.unmount()\n  })\n\n  it('should work with Transfer global renderEmpty', () => {\n    const wrapper = mountWithConfig(\n      NTransfer,\n      'Transfer',\n      {\n        renderEmpty: () =>\n          h('div', { class: 'transfer-custom-empty' }, 'no data')\n      },\n      { options: [] }\n    )\n    const empties = wrapper.findAll('.transfer-custom-empty')\n    expect(empties.length).toBeGreaterThan(0)\n    expect(empties[0].text()).toBe('no data')\n    wrapper.unmount()\n  })\n\n  it('should work with Tree global renderEmpty', () => {\n    const wrapper = mountWithConfig(NTree, 'Tree', {\n      renderEmpty: () => h('div', { class: 'custom-empty' }, 'no data')\n    })\n    expect(wrapper.find('.custom-empty').exists()).toBe(true)\n    wrapper.unmount()\n  })\n\n  it('should work with TreeSelect global renderEmpty', async () => {\n    const wrapper = mount(NConfigProvider, {\n      attachTo: document.body,\n      props: {\n        componentOptions: {\n          TreeSelect: {\n            renderEmpty: () =>\n              h('div', { class: 'treeselect-custom-empty' }, 'no data')\n          }\n        }\n      },\n      slots: {\n        default: () => h(NTreeSelect, { options: [] })\n      }\n    })\n    await wrapper.find('.n-base-selection').trigger('click')\n    await nextTick()\n    const menu = document.querySelector('.n-tree-select-menu')\n    expect(menu).not.toBeNull()\n    expect(menu?.querySelector('.treeselect-custom-empty')?.textContent).toBe(\n      'no data'\n    )\n    wrapper.unmount()\n  })\n\n  // ---- Priority test ----\n\n  it('prop size should override global size', () => {\n    const wrapper = mount(NConfigProvider, {\n      props: {\n        componentOptions: { Input: { size: 'small' } }\n      },\n      slots: {\n        default: () => h(NInput, { size: 'large' })\n      }\n    })\n    const directWrapper = mountDirect(NInput, { size: 'large' })\n    expect(wrapper.find('.n-input').attributes('style')).toBe(\n      directWrapper.find('.n-input').attributes('style')\n    )\n    wrapper.unmount()\n    directWrapper.unmount()\n  })\n})\n"
  },
  {
    "path": "src/config-provider/tests/ConfigProvider.spec.ts",
    "content": "import { mount } from '@vue/test-utils'\nimport { NConfigProvider } from '../index'\n\ndescribe('n-config-provider', () => {\n  it('should work with import on demand', () => {\n    mount(NConfigProvider)\n  })\n})\n"
  },
  {
    "path": "src/config-provider/tests/server.spec.tsx",
    "content": "import { setup } from '@css-render/vue3-ssr'\nimport { renderToString } from '@vue/server-renderer'\n/**\n * @vitest-environment node\n */\nimport { createSSRApp, h } from 'vue'\nimport { NButton, NConfigProvider } from '../..'\n\ndescribe('server side rendering', () => {\n  it('works', async () => {\n    const app = createSSRApp(() => (\n      <NConfigProvider>\n        {{\n          default: () => <NButton />\n        }}\n      </NConfigProvider>\n    ))\n    setup(app)\n    try {\n      await renderToString(app)\n    }\n    catch (e) {\n      expect(e).not.toBeTruthy()\n    }\n  })\n})\n"
  },
  {
    "path": "src/countdown/demos/enUS/basic.demo.vue",
    "content": "<markdown>\n# Basic\n\nA countdown string.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst active = ref(false)\n</script>\n\n<template>\n  <n-space>\n    <span style=\"font-variant-numeric: tabular-nums\">\n      <n-countdown :duration=\"5000\" :active=\"active\" />\n    </span>\n    <n-switch v-model:value=\"active\" />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/countdown/demos/enUS/index.demo-entry.md",
    "content": "# Countdown\n\nA second is passed after a second has passed.\n\n## Demos\n\n```demo\nbasic.vue\nprecision.vue\nrender.vue\nreset.vue\n```\n\n## API\n\n### Countdown Props\n\n| Name | Type | Default | Description | Version |\n| --- | --- | --- | --- | --- |\n| active | `boolean` | `true` | Whether countdown is active. | 2.23.2 |\n| duration | `number` | `0` | The duration of the countdown (unit is millisecond). Not reactive. | 2.23.2 |\n| precision | `0 \\| 1 \\| 2 \\| 3` | `0` | The precision of the second. | 2.23.2 |\n| render | `(props: { hours: number, minutes: number, seconds: number, milliseconds: number }) => VNodeChild` | `undefined` | Time's render function | 2.23.2 |\n| on-finish | `() => void` | `undefined` | The callback on countdown is finished. | 2.23.2 |\n\n### Countdown Methods\n\n| Name  | Type         | Description      | Version |\n| ----- | ------------ | ---------------- | ------- |\n| reset | `() => void` | Reset countdown. | 2.31.0  |\n"
  },
  {
    "path": "src/countdown/demos/enUS/precision.demo.vue",
    "content": "<markdown>\n# Precision\n\n🧐🧐🧐\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst active = ref(false)\n</script>\n\n<template>\n  <n-space>\n    <span style=\"font-variant-numeric: tabular-nums; white-space: nowrap\">\n      <n-countdown :duration=\"3600 * 1000\" :active=\"active\" />\n    </span>\n    <span style=\"font-variant-numeric: tabular-nums; white-space: nowrap\">\n      <n-countdown :duration=\"3600 * 1000\" :active=\"active\" :precision=\"1\" />\n    </span>\n    <span style=\"font-variant-numeric: tabular-nums; white-space: nowrap\">\n      <n-countdown :duration=\"3600 * 1000\" :active=\"active\" :precision=\"2\" />\n    </span>\n    <span style=\"font-variant-numeric: tabular-nums; white-space: nowrap\">\n      <n-countdown :duration=\"3600 * 1000\" :active=\"active\" :precision=\"3\" />\n    </span>\n    <n-switch v-model:value=\"active\" />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/countdown/demos/enUS/render.demo.vue",
    "content": "<markdown>\n# Customizing countdown\n\nDo whatever you want.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { CountdownProps } from 'naive-ui'\nimport { h, ref } from 'vue'\n\nconst renderCountdown: CountdownProps['render'] = ({\n  hours,\n  minutes,\n  seconds\n}) => {\n  return [\n    h(\n      'span',\n      {\n        style: 'display: inline-block; transform: rotate(90deg);'\n      },\n      [String(hours).padStart(2, '0')]\n    ),\n    ':',\n    h(\n      'span',\n      {\n        style: 'display: inline-block; transform: rotate(180deg);'\n      },\n      [String(minutes).padStart(2, '0')]\n    ),\n    ':',\n    h(\n      'span',\n      {\n        style: 'display: inline-block; transform: rotate(270deg);'\n      },\n      [String(seconds).padStart(2, '0')]\n    )\n  ]\n}\n\nconst active = ref(false)\n</script>\n\n<template>\n  <n-space item-style=\"display: flex; align-items: center;\">\n    <n-statistic label=\"I'm free to be whatever I\" tabular-nums>\n      <n-countdown\n        :render=\"renderCountdown\"\n        :duration=\"996 * 1000\"\n        :active=\"active\"\n      />\n    </n-statistic>\n    <n-switch v-model:value=\"active\" />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/countdown/demos/enUS/reset.demo.vue",
    "content": "<markdown>\n# Reset\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { CountdownInst } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst active = ref(true)\nconst countdown = ref<CountdownInst | null>(null)\n\nfunction handleReset() {\n  countdown.value?.reset()\n}\n</script>\n\n<template>\n  <n-space>\n    <span style=\"font-variant-numeric: tabular-nums\">\n      <n-countdown ref=\"countdown\" :duration=\"86400000\" :active=\"active\" />\n    </span>\n    <n-button size=\"tiny\" @click=\"handleReset\">\n      Reset\n    </n-button>\n    <n-switch v-model:value=\"active\" />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/countdown/demos/zhCN/basic.demo.vue",
    "content": "<markdown>\n# 基础用法\n\n一个字符串而已。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst active = ref(false)\n</script>\n\n<template>\n  <n-space>\n    <span style=\"font-variant-numeric: tabular-nums\">\n      <n-countdown :duration=\"5000\" :active=\"active\" />\n    </span>\n    <n-switch v-model:value=\"active\" />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/countdown/demos/zhCN/finish-debug.demo.vue",
    "content": "<markdown>\n# Finish debug\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst active = ref(false)\nfunction handleFinish() {\n  console.log('finish')\n}\n</script>\n\n<template>\n  <n-space>\n    <span style=\"font-variant-numeric: tabular-nums\">\n      <n-countdown :duration=\"5000\" :active=\"active\" @finish=\"handleFinish\" />\n      <br>\n      <n-countdown\n        :duration=\"5000\"\n        :active=\"active\"\n        :precision=\"1\"\n        @finish=\"handleFinish\"\n      />\n    </span>\n    <n-switch v-model:value=\"active\" />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/countdown/demos/zhCN/index.demo-entry.md",
    "content": "# 倒计时 Countdown\n\n每过一秒，就会少一秒。\n\n## 演示\n\n```demo\nbasic.vue\nprecision.vue\nrender.vue\nreset.vue\nfinish-debug.vue\n```\n\n## API\n\n### Countdown Props\n\n| 名称 | 类型 | 默认值 | 说明 | 版本 |\n| --- | --- | --- | --- | --- |\n| active | `boolean` | `true` | 是否处于计时状态 | 2.23.2 |\n| duration | `number` | `0` | 倒计时持续时间，单位毫秒，非响应式 | 2.23.2 |\n| precision | `0 \\| 1 \\| 2 \\| 3` | `0` | 倒计时的秒显示的精度 | 2.23.2 |\n| render | `(props: { hours: number, minutes: number, seconds: number, milliseconds: number }) => VNodeChild` | `undefined` | 时间的渲染函数 | 2.23.2 |\n| on-finish | `() => void` | `undefined` | 倒计时结束的回调 | 2.23.2 |\n\n### Countdown Methods\n\n| 名称  | 类型         | 说明 | 版本   |\n| ----- | ------------ | ---- | ------ |\n| reset | `() => void` | 重置 | 2.31.0 |\n"
  },
  {
    "path": "src/countdown/demos/zhCN/precision.demo.vue",
    "content": "<markdown>\n# 精度\n\n知道的太多对你没有好处。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst active = ref(false)\n</script>\n\n<template>\n  <n-space>\n    <span style=\"font-variant-numeric: tabular-nums; white-space: nowrap\">\n      <n-countdown :duration=\"3600 * 1000\" :active=\"active\" />\n    </span>\n    <span style=\"font-variant-numeric: tabular-nums; white-space: nowrap\">\n      <n-countdown :duration=\"3600 * 1000\" :active=\"active\" :precision=\"1\" />\n    </span>\n    <span style=\"font-variant-numeric: tabular-nums; white-space: nowrap\">\n      <n-countdown :duration=\"3600 * 1000\" :active=\"active\" :precision=\"2\" />\n    </span>\n    <span style=\"font-variant-numeric: tabular-nums; white-space: nowrap\">\n      <n-countdown :duration=\"3600 * 1000\" :active=\"active\" :precision=\"3\" />\n    </span>\n    <n-switch v-model:value=\"active\" />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/countdown/demos/zhCN/render.demo.vue",
    "content": "<markdown>\n# 自定义倒计时\n\n你们的产品经理可能想玩很多花样，所以就安排一下。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { CountdownProps } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst renderCountdown: CountdownProps['render'] = ({\n  hours,\n  minutes,\n  seconds\n}) => {\n  return `烫烫烫${String(hours).padStart(2, '0')}锟斤拷${String(\n    minutes\n  ).padStart(2, '0')}:${String(seconds).padStart(2, '0')}`\n}\n\nconst active = ref(false)\n</script>\n\n<template>\n  <n-space item-style=\"display: flex; align-items: center;\">\n    <n-statistic label=\"大哥你玩技术，玩它有啥用啊\" tabular-nums>\n      <n-countdown\n        :render=\"renderCountdown\"\n        :duration=\"996 * 1000\"\n        :active=\"active\"\n      />\n    </n-statistic>\n    <n-switch v-model:value=\"active\" />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/countdown/demos/zhCN/reset.demo.vue",
    "content": "<markdown>\n# 重置\n\n青春是挽不回的水，转眼消失在指尖。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { CountdownInst } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst active = ref(true)\nconst countdown = ref<CountdownInst | null>(null)\n\nfunction handleReset() {\n  countdown.value?.reset()\n}\n</script>\n\n<template>\n  <n-space>\n    <span style=\"font-variant-numeric: tabular-nums\">\n      <n-countdown ref=\"countdown\" :duration=\"86400000\" :active=\"active\" />\n    </span>\n    <n-button size=\"tiny\" @click=\"handleReset\">\n      重置\n    </n-button>\n    <n-switch v-model:value=\"active\" />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/countdown/index.ts",
    "content": "export { countdownProps, default as NCountdown } from './src/Countdown'\nexport type {\n  CountdownInst,\n  CountdownProps,\n  CountdownTimeInfo\n} from './src/Countdown'\n"
  },
  {
    "path": "src/countdown/src/Countdown.tsx",
    "content": "import type { PropType, VNodeChild } from 'vue'\nimport type { ExtractPublicPropTypes } from '../../_utils'\nimport {\n  defineComponent,\n  onBeforeUnmount,\n  onMounted,\n  ref,\n  watchEffect\n} from 'vue'\n\nexport interface CountdownTimeInfo {\n  hours: number\n  minutes: number\n  seconds: number\n  milliseconds: number\n}\n\nexport interface CountdownInst {\n  reset: () => void\n}\n\nexport const countdownProps = {\n  duration: {\n    type: Number,\n    default: 0\n  },\n  active: {\n    type: Boolean,\n    default: true\n  },\n  precision: {\n    type: Number as PropType<0 | 1 | 2 | 3>,\n    default: 0\n  },\n  render: Function as PropType<(props: CountdownTimeInfo) => VNodeChild>,\n  onFinish: Function as PropType<() => void>\n}\n\nexport type CountdownProps = ExtractPublicPropTypes<typeof countdownProps>\n\nexport default defineComponent({\n  name: 'Countdown',\n  props: countdownProps,\n  setup(props) {\n    let timerId: number | null = null\n    let elapsed = 0\n    let finished = false\n\n    // in ms\n    const distanceRef = ref(0)\n    watchEffect(() => {\n      distanceRef.value = props.duration\n    })\n\n    let pnow = -1\n\n    function getDistance(time: DOMHighResTimeStamp): number {\n      return props.duration - elapsed + pnow - time\n    }\n\n    function getTimeInfo(distance: number): CountdownTimeInfo {\n      const hours = Math.floor(distance / 3600000)\n      const minutes = Math.floor((distance % 3600000) / 60000)\n      const seconds = Math.floor((distance % 60000) / 1000)\n      const milliseconds = Math.floor(distance % 1000)\n      return {\n        hours,\n        minutes,\n        seconds,\n        milliseconds\n      }\n    }\n\n    function getDisplayValue(info: CountdownTimeInfo): string {\n      const { hours, minutes, seconds, milliseconds } = info\n      const { precision } = props\n      switch (precision) {\n        case 0:\n          return `${String(hours).padStart(2, '0')}:${String(minutes).padStart(\n            2,\n            '0'\n          )}:${String(seconds).padStart(2, '0')}`\n        default:\n          return `${String(hours).padStart(2, '0')}:${String(minutes).padStart(\n            2,\n            '0'\n          )}:${String(seconds).padStart(2, '0')}.${String(\n            Math.floor(\n              milliseconds / (precision === 1 ? 100 : precision === 2 ? 10 : 1)\n            )\n          ).padStart(precision, '0')}`\n      }\n    }\n\n    const frame = (): void => {\n      const { precision } = props\n      const distance = getDistance(performance.now())\n      if (distance <= 0) {\n        distanceRef.value = 0\n        stopTimer()\n        if (!finished) {\n          finished = true\n          props.onFinish?.()\n        }\n        return\n      }\n      let leftTime: number\n      switch (precision) {\n        case 3:\n        case 2:\n          leftTime = distance % 34 // about 30 fps\n          break\n        case 1:\n          leftTime = distance % 100\n          break\n        default:\n          leftTime = distance % 1000\n      }\n      distanceRef.value = distance\n      timerId = window.setTimeout(() => {\n        frame()\n      }, leftTime)\n    }\n\n    function stopTimer(): void {\n      if (timerId !== null) {\n        window.clearTimeout(timerId)\n        timerId = null\n      }\n    }\n    onMounted(() => {\n      watchEffect(() => {\n        if (props.active) {\n          pnow = performance.now()\n          frame()\n        }\n        else {\n          const now = performance.now()\n          if (pnow !== -1) {\n            elapsed += now - pnow\n          }\n          stopTimer()\n        }\n      })\n    })\n    onBeforeUnmount(() => {\n      stopTimer()\n    })\n\n    function reset(): void {\n      distanceRef.value = props.duration\n      elapsed = 0\n      pnow = performance.now()\n      if (props.active && finished) {\n        frame()\n      }\n      finished = false\n    }\n\n    const countdownExposedMethod: CountdownInst = {\n      reset\n    }\n    return Object.assign(countdownExposedMethod, {\n      distance: distanceRef,\n      getTimeInfo,\n      getDisplayValue\n    })\n  },\n  render() {\n    const { render, precision, distance, getTimeInfo, getDisplayValue } = this\n    let timeInfo: CountdownTimeInfo\n    switch (precision) {\n      case 0:\n        timeInfo = getTimeInfo(distance + 999)\n        timeInfo.milliseconds = 0\n        break\n      case 1:\n        timeInfo = getTimeInfo(distance + 99)\n        timeInfo.milliseconds = Math.floor(timeInfo.milliseconds / 100) * 100\n        break\n      case 2:\n        timeInfo = getTimeInfo(distance + 9)\n        timeInfo.milliseconds = Math.floor(timeInfo.milliseconds / 10) * 10\n        break\n      case 3:\n        timeInfo = getTimeInfo(distance)\n    }\n    if (render) {\n      return render(timeInfo)\n    }\n    else {\n      return getDisplayValue(timeInfo)\n    }\n  }\n})\n"
  },
  {
    "path": "src/countdown/tests/Countdown.spec.ts",
    "content": "import type { CountdownProps } from '../index'\nimport { mount } from '@vue/test-utils'\nimport { sleep } from 'seemly'\nimport { NCountdown } from '../index'\n\ndescribe('n-countdown', () => {\n  it('should work with import on demand', () => {\n    mount(NCountdown)\n  })\n  it('should work with `duration` prop', async () => {\n    const wrapper = mount(NCountdown, {\n      props: {\n        duration: 2 * 3600 * 1000\n      }\n    })\n    expect(wrapper.text()).toBe('02:00:00')\n    wrapper.unmount()\n  })\n  it('should work with `precision`&`active` prop`', async () => {\n    const wrapper = mount(NCountdown, {\n      props: {\n        duration: 2 * 3600 * 1000,\n        active: false\n      }\n    })\n    expect(wrapper.text()).toBe('02:00:00')\n    await wrapper.setProps({ precision: 1 })\n    expect(wrapper.text()).toBe('02:00:00.0')\n    await wrapper.setProps({ precision: 2 })\n    expect(wrapper.text()).toBe('02:00:00.00')\n    await wrapper.setProps({ precision: 3 })\n    expect(wrapper.text()).toBe('02:00:00.000')\n    await wrapper.setProps({ active: true })\n    expect(wrapper.text()).not.toBe('02:00:00.000')\n    wrapper.unmount()\n  })\n  it('should work with `render` prop', () => {\n    const render: CountdownProps['render'] = ({\n      hours = 1,\n      minutes = 1,\n      seconds = 1,\n      milliseconds = 1\n    }) => {\n      return `${hours}:${minutes}:${seconds}:${milliseconds}`\n    }\n    const wrapper = mount(NCountdown, {\n      props: {\n        render\n      }\n    })\n    expect(wrapper.text()).not.toBe('1:1:1:1')\n    wrapper.unmount()\n  })\n  it('should work with `on-finish` prop', async () => {\n    const onFinish = vi.fn()\n    const wrapper = mount(NCountdown, {\n      props: {\n        duration: 1,\n        onFinish\n      }\n    })\n    await sleep(100)\n    expect(onFinish).toHaveBeenCalled()\n    wrapper.unmount()\n  })\n})\n"
  },
  {
    "path": "src/countdown/tests/server.spec.tsx",
    "content": "import { setup } from '@css-render/vue3-ssr'\nimport { renderToString } from '@vue/server-renderer'\n/**\n * @vitest-environment node\n */\nimport { createSSRApp, h } from 'vue'\nimport { NCountdown } from '../..'\n\ndescribe('server side rendering', () => {\n  it('works', async () => {\n    const app = createSSRApp(() => <NCountdown />)\n    setup(app)\n    try {\n      await renderToString(app)\n    }\n    catch (e) {\n      expect(e).not.toBeTruthy()\n    }\n  })\n})\n"
  },
  {
    "path": "src/create.ts",
    "content": "import type { App, Component, DefineComponent } from 'vue'\nimport version from './version'\n\ntype ComponentType = any\n\nexport interface NUiInstance {\n  version: string\n  componentPrefix: string\n  install: (app: App) => void\n}\n\ninterface NUiCreateOptions {\n  components?: ComponentType[]\n  componentPrefix?: string\n}\n\nfunction create({\n  componentPrefix = 'N',\n  components = []\n}: NUiCreateOptions = {}): NUiInstance {\n  const installTargets: App[] = []\n  function registerComponent(\n    app: App,\n    name: string,\n    component: ComponentType\n  ): void {\n    const registered = app.component(componentPrefix + name)\n    if (!registered) {\n      app.component(\n        componentPrefix + name,\n        component as Component<any> | DefineComponent<any>\n      )\n    }\n  }\n  function install(app: App): void {\n    if (installTargets.includes(app))\n      return\n    installTargets.push(app)\n    components.forEach((component) => {\n      const { name, alias } = component\n      registerComponent(app, name as string, component)\n      if (alias) {\n        alias.forEach((aliasName: string) => {\n          registerComponent(app, aliasName, component)\n        })\n      }\n    })\n  }\n  return {\n    version,\n    componentPrefix,\n    install\n  }\n}\n\nexport default create\n"
  },
  {
    "path": "src/data-table/demos/enUS/ajax-usage.demo.vue",
    "content": "<markdown>\n  # Async\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type {\n  DataTableColumn,\n  DataTableColumns,\n  DataTableFilterState,\n  DataTableSortOrder,\n  DataTableSortState,\n  PaginationInfo\n} from 'naive-ui'\nimport type { FilterOptionValue } from '../../src/interface'\nimport { onMounted, reactive, ref } from 'vue'\n\ninterface RowData {\n  column1: number\n  column2: number\n  column3: string\n}\n\nconst column1: DataTableColumn<RowData> = {\n  title: 'column1',\n  key: 'column1',\n  sorter: true,\n  sortOrder: false\n}\n\nconst column2: DataTableColumn<RowData> = {\n  title: 'column2',\n  key: 'column2',\n  filter: true,\n  filterOptionValues: [],\n  filterOptions: [\n    {\n      label: 'Value1',\n      value: 1\n    },\n    {\n      label: 'Value2',\n      value: 2\n    }\n  ]\n}\n\nconst columns: DataTableColumns<RowData> = [\n  column1,\n  column2,\n  {\n    title: 'Column3',\n    key: 'column3'\n  }\n]\n\nconst data = Array.from({ length: 987 })\n  .fill(null)\n  .map((_, index) => {\n    return {\n      column1: index,\n      column2: (index % 2) + 1,\n      column3: `a${index}`\n    }\n  })\n\ninterface QueryParams {\n  page: number\n  pageSize: number\n  order?: DataTableSortOrder\n  filterValues?: FilterOptionValue[] | null | undefined\n}\n\ninterface QueryResult {\n  pageCount: number\n  data: RowData[]\n  total: number\n}\n\nfunction query({\n  page,\n  pageSize = 10,\n  order = 'ascend',\n  filterValues = []\n}: QueryParams): Promise<QueryResult> {\n  return new Promise((resolve) => {\n    const copiedData = data.map(v => v)\n    const orderedData = order === 'descend' ? copiedData.reverse() : copiedData\n    const filteredData = filterValues?.length\n      ? orderedData.filter(row => filterValues?.includes(row.column2))\n      : orderedData\n    const pagedData = filteredData.slice((page - 1) * pageSize, page * pageSize)\n    const total = filteredData.length\n    const pageCount = Math.ceil(filteredData.length / pageSize)\n    setTimeout(\n      () =>\n        resolve({\n          pageCount,\n          data: pagedData,\n          total\n        }),\n      1500\n    )\n  })\n}\n\nconst dataRef = ref<RowData[]>([])\nconst loadingRef = ref(true)\nconst column1Reactive = reactive(column1)\nconst column2Reactive = reactive(column2)\nconst paginationReactive = reactive({\n  page: 1,\n  pageCount: 1,\n  pageSize: 10,\n  itemCount: 0,\n  prefix({ itemCount }: PaginationInfo) {\n    return `Total is ${itemCount}.`\n  }\n})\n\nonMounted(() => {\n  query({\n    page: paginationReactive.page,\n    pageSize: paginationReactive.pageSize,\n    order: column1Reactive.sortOrder,\n    filterValues: column2Reactive.filterOptionValues\n  }).then((data) => {\n    dataRef.value = data.data\n    paginationReactive.pageCount = data.pageCount\n    paginationReactive.itemCount = data.total\n    loadingRef.value = false\n  })\n})\n\nfunction rowKey(rowData: RowData) {\n  return rowData.column1\n}\n\nfunction handleSorterChange(sorter: DataTableSortState) {\n  if (!sorter || sorter.columnKey === 'column1') {\n    if (!loadingRef.value) {\n      loadingRef.value = true\n      query({\n        page: paginationReactive.page,\n        pageSize: paginationReactive.pageSize,\n        order: !sorter ? false : sorter.order,\n        filterValues: column2Reactive.filterOptionValues\n      }).then((data) => {\n        column1Reactive.sortOrder = !sorter ? false : sorter.order\n        dataRef.value = data.data\n        paginationReactive.pageCount = data.pageCount\n        paginationReactive.itemCount = data.total\n        loadingRef.value = false\n      })\n    }\n  }\n}\n\nfunction handleFiltersChange(filters: DataTableFilterState) {\n  if (!loadingRef.value) {\n    loadingRef.value = true\n    const filterValues = Array.isArray(filters.column2) ? filters.column2 : []\n    query({\n      page: paginationReactive.page,\n      pageSize: paginationReactive.pageSize,\n      order: column1Reactive.sortOrder,\n      filterValues\n    }).then((data) => {\n      column2Reactive.filterOptionValues = filterValues\n      dataRef.value = data.data\n      paginationReactive.pageCount = data.pageCount\n      paginationReactive.itemCount = data.total\n      loadingRef.value = false\n    })\n  }\n}\n\nfunction handlePageChange(currentPage: number) {\n  if (!loadingRef.value) {\n    loadingRef.value = true\n    query({\n      page: currentPage,\n      pageSize: paginationReactive.pageSize,\n      order: column1Reactive.sortOrder,\n      filterValues: column2Reactive.filterOptionValues\n    }).then((data) => {\n      dataRef.value = data.data\n      paginationReactive.page = currentPage\n      paginationReactive.pageCount = data.pageCount\n      paginationReactive.itemCount = data.total\n      loadingRef.value = false\n    })\n  }\n}\n</script>\n\n<template>\n  <n-data-table\n    remote\n    :columns=\"columns\"\n    :data=\"dataRef\"\n    :loading=\"loadingRef\"\n    :pagination=\"paginationReactive\"\n    :row-key=\"rowKey\"\n    @update:sorter=\"handleSorterChange\"\n    @update:filters=\"handleFiltersChange\"\n    @update:page=\"handlePageChange\"\n  />\n</template>\n"
  },
  {
    "path": "src/data-table/demos/enUS/async-expand.demo.vue",
    "content": "<markdown>\n# Async expand tree data\n\nChange data in `onLoad` prop.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { DataTableColumns } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst columns: DataTableColumns = [\n  { type: 'selection' },\n  { key: 'example', title: 'Example' }\n]\nconst dataRef = ref([\n  { key: 'p1', example: 'p1', isLeaf: false },\n  { key: 'p2', example: 'p2', isLeaf: false },\n  { key: 'p3', example: 'p3', isLeaf: false }\n])\n\nfunction onLoad(row: Record<string, unknown>) {\n  return new Promise<void>((resolve) => {\n    setTimeout(() => {\n      row.children = [{ key: `${row.key}-1`, example: `${row.key}-1` }]\n      resolve()\n    }, 1000)\n  })\n}\n</script>\n\n<template>\n  <n-data-table\n    :columns=\"columns\"\n    :data=\"dataRef\"\n    :cascade=\"false\"\n    allow-checking-not-loaded\n    @load=\"onLoad\"\n  />\n</template>\n"
  },
  {
    "path": "src/data-table/demos/enUS/basic.demo.vue",
    "content": "<markdown>\n# Basic usage\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { DataTableColumns } from 'naive-ui'\nimport { NButton, useMessage } from 'naive-ui'\nimport { h } from 'vue'\n\ninterface Song {\n  no: number\n  title: string\n  length: string\n}\n\nfunction createColumns({\n  play\n}: {\n  play: (row: Song) => void\n}): DataTableColumns<Song> {\n  return [\n    {\n      title: 'No',\n      key: 'no'\n    },\n    {\n      title: 'Title',\n      key: 'title'\n    },\n    {\n      title: 'Length',\n      key: 'length'\n    },\n    {\n      title: 'Action',\n      key: 'actions',\n      render(row) {\n        return h(\n          NButton,\n          {\n            strong: true,\n            tertiary: true,\n            size: 'small',\n            onClick: () => play(row)\n          },\n          { default: () => 'Play' }\n        )\n      }\n    }\n  ]\n}\n\nconst data: Song[] = [\n  { no: 3, title: 'Wonderwall', length: '4:18' },\n  { no: 4, title: 'Don\\'t Look Back in Anger', length: '4:48' },\n  { no: 12, title: 'Champagne Supernova', length: '7:27' }\n]\n\nconst message = useMessage()\nconst columns = createColumns({\n  play(row: Song) {\n    message.info(`Play ${row.title}`)\n  }\n})\nconst pagination = false as const\n</script>\n\n<template>\n  <n-data-table\n    :columns=\"columns\"\n    :data=\"data\"\n    :pagination=\"pagination\"\n    :bordered=\"false\"\n  />\n</template>\n"
  },
  {
    "path": "src/data-table/demos/enUS/border.demo.vue",
    "content": "<markdown>\n# Unbordered & no row divider & no column divider\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { DataTableColumns } from 'naive-ui'\nimport { NButton, NTag, useMessage } from 'naive-ui'\nimport { h } from 'vue'\n\ninterface RowData {\n  key: number\n  name: string\n  age: number\n  address: string\n  tags: string[]\n}\n\nfunction createColumns({\n  sendMail\n}: {\n  sendMail: (rowData: RowData) => void\n}): DataTableColumns<RowData> {\n  return [\n    {\n      title: 'Name',\n      key: 'name'\n    },\n    {\n      title: 'Age',\n      key: 'age'\n    },\n    {\n      title: 'Address',\n      key: 'address'\n    },\n    {\n      title: 'Tags',\n      key: 'tags',\n      render(row) {\n        const tags = row.tags.map((tagKey) => {\n          return h(\n            NTag,\n            {\n              style: {\n                marginRight: '6px'\n              },\n              type: 'info',\n              bordered: false\n            },\n            {\n              default: () => tagKey\n            }\n          )\n        })\n        return tags\n      }\n    },\n    {\n      title: 'Action',\n      key: 'actions',\n      render(row) {\n        return h(\n          NButton,\n          {\n            size: 'small',\n            onClick: () => sendMail(row)\n          },\n          { default: () => 'Send Email' }\n        )\n      }\n    }\n  ]\n}\n\nfunction createData(): RowData[] {\n  return [\n    {\n      key: 0,\n      name: 'John Brown',\n      age: 32,\n      address: 'New York No. 1 Lake Park',\n      tags: ['nice', 'developer']\n    },\n    {\n      key: 1,\n      name: 'Jim Green',\n      age: 42,\n      address: 'London No. 1 Lake Park',\n      tags: ['wow']\n    },\n    {\n      key: 2,\n      name: 'Joe Black',\n      age: 32,\n      address: 'Sidney No. 1 Lake Park',\n      tags: ['cool', 'teacher']\n    }\n  ]\n}\n\nconst message = useMessage()\nconst data = createData()\nconst columns = createColumns({\n  sendMail(rowData) {\n    message.info(`send mail to ${rowData.name}`)\n  }\n})\nconst pagination = {\n  pageSize: 10\n}\n</script>\n\n<template>\n  <n-space vertical :size=\"12\">\n    <n-data-table\n      :bordered=\"false\"\n      :single-line=\"false\"\n      :columns=\"columns\"\n      :data=\"data\"\n      :pagination=\"pagination\"\n    />\n    <n-data-table\n      :bordered=\"false\"\n      :columns=\"columns\"\n      :data=\"data\"\n      :pagination=\"pagination\"\n    />\n    <n-data-table\n      :bordered=\"false\"\n      :single-line=\"false\"\n      single-column\n      :columns=\"columns\"\n      :data=\"data\"\n      :pagination=\"pagination\"\n    />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/data-table/demos/enUS/column-draggable.demo.vue",
    "content": "<markdown>\n# Column draggable\n\nOnly support leaf nodes.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { DataTableColumns } from 'naive-ui'\nimport { NButton, useMessage } from 'naive-ui'\nimport { h } from 'vue'\n\ninterface Song {\n  no: number\n  title: string\n  length: string\n}\n\nfunction createColumns({\n  play\n}: {\n  play: (row: Song) => void\n}): DataTableColumns<Song> {\n  return [\n    {\n      title: 'No',\n      key: 'no',\n      width: 50\n    },\n    {\n      title: 'Title',\n      key: 'title',\n      resizable: true\n    },\n    {\n      title: 'Length',\n      key: 'length',\n      resizable: true,\n      minWidth: 50,\n      maxWidth: 100\n    },\n    {\n      title: 'Action',\n      key: 'actions',\n      render(row) {\n        return h(\n          NButton,\n          {\n            strong: true,\n            tertiary: true,\n            size: 'small',\n            onClick: () => play(row)\n          },\n          { default: () => 'Play' }\n        )\n      }\n    }\n  ]\n}\n\nconst data: Song[] = [\n  { no: 3, title: 'Wonderwall', length: '4:18' },\n  { no: 4, title: 'Don\\'t Look Back in Anger', length: '4:48' },\n  { no: 12, title: 'Champagne Supernova', length: '7:27' }\n]\n\nconst message = useMessage()\nconst columns = createColumns({\n  play(row: Song) {\n    message.info(`Play ${row.title}`)\n  }\n})\nconst pagination = false as const\n</script>\n\n<template>\n  <n-data-table\n    :columns=\"columns\"\n    :data=\"data\"\n    :pagination=\"pagination\"\n    :bordered=\"false\"\n  />\n</template>\n"
  },
  {
    "path": "src/data-table/demos/enUS/context-menu.demo.vue",
    "content": "<markdown>\n# Context menu\n\nUse `n-dropdown` to implement a context menu.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { DataTableColumns, DropdownOption } from 'naive-ui'\nimport { useMessage } from 'naive-ui'\nimport { h, nextTick, ref } from 'vue'\n\ninterface Song {\n  no: number\n  title: string\n  length: string\n}\n\nconst data: Song[] = [\n  { no: 1, title: 'Hello', length: '3:21' },\n  { no: 2, title: 'Roll with It', length: '3:59' },\n  { no: 3, title: 'Wonderwall', length: '4:18' },\n  { no: 4, title: 'Don\\'t Look Back in Anger', length: '4:48' },\n  { no: 5, title: 'Hey Now!', length: '5:41' },\n  { no: 6, title: 'Untitled', length: '0:44' },\n  { no: 7, title: 'Some Might Say', length: '5:29' },\n  { no: 8, title: 'Cast No Shadow', length: '4:51' },\n  { no: 9, title: 'She\\'s Electric', length: '3:40' },\n  { no: 10, title: 'Monring Glory', length: '5:03' },\n  { no: 11, title: 'Untitled', length: '0:39' },\n  { no: 12, title: 'Champagne Supernova', length: '7:27' }\n]\n\nconst options: DropdownOption[] = [\n  {\n    label: '编辑',\n    key: 'edit'\n  },\n  {\n    label: () => h('span', { style: { color: 'red' } }, '删除'),\n    key: 'delete'\n  }\n]\n\nconst message = useMessage()\nconst showDropdownRef = ref(false)\nconst xRef = ref(0)\nconst yRef = ref(0)\nconst colsReactive: DataTableColumns<Song> = [\n  {\n    title: 'No.',\n    key: 'no'\n  },\n  {\n    title: 'Title',\n    key: 'title'\n  },\n  {\n    title: 'Length',\n    key: 'length'\n  }\n]\n\nconst cols = colsReactive\nconst showDropdown = showDropdownRef\nconst x = xRef\nconst y = yRef\n\nfunction handleSelect() {\n  showDropdownRef.value = false\n}\n\nfunction onClickoutside() {\n  showDropdownRef.value = false\n}\n\nfunction rowProps(row: Song) {\n  return {\n    onContextmenu: (e: MouseEvent) => {\n      message.info(JSON.stringify(row, null, 2))\n      e.preventDefault()\n      showDropdownRef.value = false\n      nextTick().then(() => {\n        showDropdownRef.value = true\n        xRef.value = e.clientX\n        yRef.value = e.clientY\n      })\n    }\n  }\n}\n</script>\n\n<template>\n  <n-data-table :columns=\"cols\" :data=\"data\" :row-props=\"rowProps\" />\n  <n-dropdown\n    placement=\"bottom-start\"\n    trigger=\"manual\"\n    :x=\"x\"\n    :y=\"y\"\n    :options=\"options\"\n    :show=\"showDropdown\"\n    :on-clickoutside=\"onClickoutside\"\n    @select=\"handleSelect\"\n  />\n</template>\n"
  },
  {
    "path": "src/data-table/demos/enUS/controlled-filter.demo.vue",
    "content": "<markdown>\n# Controlled filter\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type {\n  DataTableBaseColumn,\n  DataTableColumns,\n  DataTableFilterState\n} from 'naive-ui'\nimport { reactive } from 'vue'\n\ninterface Row {\n  key: number\n  name: string\n  age: number\n  address: string\n}\n\nconst data = [\n  {\n    key: 0,\n    name: 'John Brown',\n    age: 32,\n    address: 'New York No. 1 Lake Park'\n  },\n  {\n    key: 1,\n    name: 'Jim Green',\n    age: 42,\n    address: 'London No. 1 Lake Park'\n  },\n  {\n    key: 2,\n    name: 'Joe Black',\n    age: 32,\n    address: 'Sidney No. 1 Lake Park'\n  },\n  {\n    key: 3,\n    name: 'Jim Red',\n    age: 32,\n    address: 'London No. 2 Lake Park'\n  }\n]\n\nconst addressColumn = reactive<DataTableBaseColumn<Row>>({\n  title: 'Address',\n  key: 'address',\n  filterMultiple: false,\n  filterOptionValue: null,\n  sorter: 'default',\n  filterOptions: [\n    {\n      label: 'London',\n      value: 'London'\n    },\n    {\n      label: 'New York',\n      value: 'New York'\n    }\n  ],\n  filter(value, row) {\n    return !!~row.address.indexOf(value.toString())\n  }\n})\n\nconst columns = reactive<DataTableColumns<Row>>([\n  {\n    title: 'Name',\n    key: 'name',\n    sorter(rowA, rowB) {\n      return rowA.name.length - rowB.name.length\n    }\n  },\n  {\n    title: 'Age',\n    key: 'age',\n    sorter(rowA, rowB) {\n      return rowA.age - rowB.age\n    }\n  },\n  addressColumn\n])\n\nconst pagination = { pageSize: 5 }\n\nfunction filterAddress() {\n  addressColumn.filterOptionValue = 'London'\n}\n\nfunction unfilterAddress() {\n  addressColumn.filterOptionValue = null\n}\n\nfunction handleUpdateFilter(\n  filters: DataTableFilterState,\n  sourceColumn: DataTableBaseColumn\n) {\n  addressColumn.filterOptionValue = filters[sourceColumn.key] as string\n}\n</script>\n\n<template>\n  <n-space vertical :size=\"12\">\n    <n-space>\n      <n-button @click=\"filterAddress\">\n        Filter Address(Use Value 'London')\n      </n-button>\n      <n-button @click=\"unfilterAddress\">\n        Clear Address Filters\n      </n-button>\n    </n-space>\n    <n-data-table\n      :columns=\"columns\"\n      :data=\"data\"\n      :pagination=\"pagination\"\n      @update:filters=\"handleUpdateFilter\"\n    />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/data-table/demos/enUS/controlled-multiple-sorter.demo.vue",
    "content": "<markdown>\n  # Controlled multi-column sorting\n\n  If column object's `sortOrder` is set to `'ascend'`, `'descend'` or `false`, the data table would be in controlled state.\n\n  If you only want UI to display multiple sort state, you can leave `compare` empty.\n  </markdown>\n\n<script lang=\"ts\" setup>\nimport type {\n  DataTableColumnKey,\n  DataTableColumns,\n  DataTableSortOrder,\n  DataTableSortState\n} from 'naive-ui'\nimport { computed, ref } from 'vue'\n\ninterface RowData {\n  key: number\n  name: string\n  age: number\n  chinese: number\n  math: number\n  english: number\n}\n\nconst data: RowData[] = [\n  {\n    key: 0,\n    name: 'John Brown',\n    age: 32,\n    chinese: 98,\n    math: 60,\n    english: 70\n  },\n  {\n    key: 1,\n    name: 'Jim Green',\n    age: 42,\n    chinese: 98,\n    math: 66,\n    english: 89\n  },\n  {\n    key: 2,\n    name: 'Joe Black',\n    age: 32,\n    chinese: 98,\n    math: 66,\n    english: 89\n  },\n  {\n    key: 3,\n    name: 'Jim Red',\n    age: 32,\n    chinese: 88,\n    math: 99,\n    english: 89\n  }\n]\n\nconst sortStates = ref<DataTableSortState[]>([])\nconst sortKeyMapOrder = computed<\n  Record<DataTableColumnKey, DataTableSortOrder>\n>(() =>\n  sortStates.value.reduce(\n    (\n      result: Record<DataTableColumnKey, DataTableSortOrder>,\n      { columnKey, order }\n    ) => {\n      result[columnKey] = order\n      return result\n    },\n    {}\n  )\n)\nconst pagination = ref({ pageSize: 5 })\n\nconst columns = computed<DataTableColumns<RowData>>(() => [\n  {\n    title: 'Name',\n    key: 'name'\n  },\n  {\n    title: 'Age',\n    key: 'age',\n    sortOrder: sortKeyMapOrder.value.age || false,\n    sorter(rowA, rowB) {\n      return rowA.age - rowB.age\n    }\n  },\n  {\n    title: 'Chinese Score',\n    key: 'chinese',\n    sortOrder: sortKeyMapOrder.value.chinese || false,\n    sorter: {\n      compare: (a, b) => a.chinese - b.chinese,\n      multiple: 3\n    }\n  },\n  {\n    title: 'Math Score',\n    key: 'math',\n    sortOrder: sortKeyMapOrder.value.math || false,\n    sorter: {\n      compare: (a, b) => a.math - b.math,\n      multiple: 2\n    }\n  },\n  {\n    title: 'English Score',\n    sortOrder: sortKeyMapOrder.value.english || false,\n    key: 'english',\n    sorter: {\n      compare: (a, b) => a.english - b.english,\n      multiple: 1\n    }\n  }\n])\n\nfunction handleUpdateSorter(sorters: DataTableSortState[]) {\n  console.log(sorters)\n  sortStates.value = ([] as DataTableSortState[]).concat(sorters)\n}\n</script>\n\n<template>\n  <n-data-table\n    :columns=\"columns\"\n    :data=\"data\"\n    :pagination=\"pagination\"\n    @update:sorter=\"handleUpdateSorter\"\n  />\n</template>\n"
  },
  {
    "path": "src/data-table/demos/enUS/controlled-page.demo.vue",
    "content": "<markdown>\n# Controlled pagination\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { reactive } from 'vue'\n\nconst columns = [\n  {\n    title: 'Name',\n    key: 'name'\n  },\n  {\n    title: 'Age',\n    key: 'age'\n  },\n  {\n    title: 'Address',\n    key: 'address'\n  }\n]\n\nconst data = Array.from({ length: 46 }).map((_, index) => ({\n  key: index,\n  name: `Edward King ${index}`,\n  age: 32,\n  address: `London, Park Lane no. ${index}`\n}))\n\nconst pagination = reactive({\n  page: 2,\n  pageSize: 5,\n  showSizePicker: true,\n  pageSizes: [3, 5, 7],\n  onChange: (page: number) => {\n    pagination.page = page\n  },\n  onUpdatePageSize: (pageSize: number) => {\n    pagination.pageSize = pageSize\n    pagination.page = 1\n  }\n})\n</script>\n\n<template>\n  <n-data-table :columns=\"columns\" :data=\"data\" :pagination=\"pagination\" />\n</template>\n"
  },
  {
    "path": "src/data-table/demos/enUS/controlled-sorter.demo.vue",
    "content": "<markdown>\n# Controlled sorter\n\nIf one of the column objects' `sortOrder` is set to `'ascend'`, `'descend'` or `false`. The sorting behavior the table will be in a controlled manner. If multiple columns' `sortOrder` are set to `'ascend'` or `'descend'`, only first column of them will be applied.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type {\n  DataTableBaseColumn,\n  DataTableSortOrder,\n  DataTableSortState\n} from 'naive-ui'\nimport { reactive, ref } from 'vue'\n\ninterface RowData {\n  key: number\n  name: string\n  age: number\n  address: string\n}\n\nconst nameColumn: DataTableBaseColumn<RowData> = {\n  title: 'Name',\n  key: 'name',\n  sortOrder: false,\n  sorter: 'default'\n}\n\nconst ageColumn: DataTableBaseColumn<RowData> = {\n  title: 'Age',\n  key: 'age',\n  sortOrder: false,\n  sorter(rowA, rowB) {\n    return rowA.age - rowB.age\n  }\n}\n\nconst columns: DataTableBaseColumn<RowData>[] = [\n  nameColumn,\n  ageColumn,\n  {\n    title: 'Address',\n    key: 'address',\n    defaultFilterOptionValues: ['London', 'New York'],\n    filterOptions: [\n      {\n        label: 'London',\n        value: 'London'\n      },\n      {\n        label: 'New York',\n        value: 'New York'\n      }\n    ],\n    filter(value, row) {\n      return row.address.includes(value as string)\n    }\n  }\n]\n\nconst data = [\n  {\n    key: 0,\n    name: 'John Brown',\n    age: 38,\n    address: 'New York No. 1 Lake Park'\n  },\n  {\n    key: 1,\n    name: 'Jim Green',\n    age: 42,\n    address: 'London No. 1 Lake Park'\n  },\n  {\n    key: 2,\n    name: 'Joe Black',\n    age: 36,\n    address: 'Sidney No. 1 Lake Park'\n  },\n  {\n    key: 3,\n    name: 'Jim Red',\n    age: 32,\n    address: 'London No. 2 Lake Park'\n  }\n]\n\nconst nameColumnReactive = reactive(nameColumn)\nconst ageColumnReactive = reactive(ageColumn)\nconst columnsRef = ref<DataTableBaseColumn<RowData>[]>(columns)\nconst pagination = { pageSize: 5 }\n\nfunction handleSorterChange(sorter: DataTableSortState) {\n  columnsRef.value.forEach((column: DataTableBaseColumn<RowData>) => {\n    /** column.sortOrder !== undefined means it is uncontrolled */\n    if (column.sortOrder === undefined)\n      return\n    if (!sorter) {\n      column.sortOrder = false\n      return\n    }\n    if (column.key === sorter.columnKey)\n      column.sortOrder = sorter.order\n    else column.sortOrder = false\n  })\n}\n\nfunction sortName(order: DataTableSortOrder) {\n  nameColumnReactive.sortOrder = order\n}\n\nfunction clearSorter() {\n  nameColumnReactive.sortOrder = false\n  ageColumnReactive.sortOrder = false\n}\n</script>\n\n<template>\n  <n-space vertical :size=\"12\">\n    <n-space>\n      <n-button @click=\"sortName('ascend')\">\n        Sort By Name (Ascend)\n      </n-button>\n      <n-button @click=\"sortName('descend')\">\n        Sort By Name (Descend)\n      </n-button>\n      <n-button @click=\"clearSorter\">\n        Clear Sorter\n      </n-button>\n    </n-space>\n    <n-data-table\n      :columns=\"columns\"\n      :data=\"data\"\n      :pagination=\"pagination\"\n      @update:sorter=\"handleSorterChange\"\n    />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/data-table/demos/enUS/custom-filter-menu.demo.vue",
    "content": "<markdown>\n# Customize Icons\n\nYou can customize filter & filter menu & sorter & expand icon.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { DataTableBaseColumn, DataTableColumns } from 'naive-ui'\nimport { PawOutline, SearchOutline } from '@vicons/ionicons5'\nimport { NButton, NIcon, NSpace } from 'naive-ui'\nimport { h, reactive } from 'vue'\n\nconst data = [\n  {\n    Left: '1',\n    Right: '1',\n    key: 1\n  },\n  {\n    Left: '2',\n    Right: '2',\n    key: 2\n  }\n]\n\nfunction renderExpandIcon() {\n  return h(NIcon, null, { default: () => h(PawOutline) })\n}\n\nconst filterColumn = reactive<DataTableBaseColumn>({\n  title: 'Right',\n  key: 'Right',\n  filter: 'default',\n  filterOptionValue: null,\n  renderFilterIcon: () => {\n    return h(NIcon, null, { default: () => h(SearchOutline) })\n  },\n  renderFilterMenu: ({ hide }) => {\n    return h(\n      NSpace,\n      { style: { padding: '12px' }, vertical: true },\n      {\n        default: () => [\n          h(\n            NButton,\n            {\n              onClick: () => {\n                filterColumn.filterOptionValue = '1'\n              }\n            },\n            { default: () => 'Filter by 1' }\n          ),\n          h(\n            NButton,\n            {\n              onClick: () => {\n                filterColumn.filterOptionValue = '2'\n              }\n            },\n            { default: () => 'Filter by 2' }\n          ),\n          h(\n            NButton,\n            {\n              onClick: () => {\n                filterColumn.filterOptionValue = null\n                hide()\n              }\n            },\n            { default: () => 'clear' }\n          )\n        ]\n      }\n    )\n  }\n})\n\nconst cols = reactive<DataTableColumns>([\n  {\n    type: 'expand',\n    renderExpand: () => {\n      return 'Expand content'\n    }\n  },\n  {\n    title: 'Left',\n    key: 'Left',\n    sorter: 'default',\n    renderSorterIcon: ({ order }) => {\n      const style = 'transform: translateY(-3px);'\n      if (order === false)\n        return h('div', { style }, ['🤔'])\n      if (order === 'ascend')\n        return h('div', { style }, ['👇'])\n      if (order === 'descend')\n        return h('div', { style }, ['👆'])\n    }\n  },\n  filterColumn\n])\n</script>\n\n<template>\n  <n-data-table\n    :columns=\"cols\"\n    :data=\"data\"\n    :render-expand-icon=\"renderExpandIcon\"\n  />\n</template>\n"
  },
  {
    "path": "src/data-table/demos/enUS/custom-select.demo.vue",
    "content": "<markdown>\n# Custom selection menu\n\nSet `options` on a selection type column to create selection dropdown near header checkbox.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { DataTableColumns } from 'naive-ui'\nimport { repeat } from 'seemly'\nimport { ref } from 'vue'\n\ninterface RowData {\n  name: string\n  age: number\n  address: string\n  key: number\n}\n\nconst data = repeat(46, undefined).map<RowData>((_, index) => ({\n  name: `Edward King ${index}`,\n  age: 32,\n  address: `London, Park Lane no. ${index}`,\n  key: index\n}))\n\nconst checkedRowKeysRef = ref<Array<string | number>>([])\nconst columns: DataTableColumns<RowData> = [\n  {\n    type: 'selection',\n    options: [\n      'all',\n      'none',\n      {\n        label: 'Select first 2 rows',\n        key: 'f2',\n        onSelect: (pageData) => {\n          checkedRowKeysRef.value = pageData.map(row => row.key).slice(0, 2)\n        }\n      }\n    ],\n    disabled(row) {\n      return row.name === 'Edward King 3'\n    }\n  },\n  {\n    title: 'Name',\n    key: 'name'\n  },\n  {\n    title: 'Age',\n    key: 'age'\n  },\n  {\n    title: 'Address',\n    key: 'address'\n  }\n]\n\nconst pagination = {\n  pageSize: 6\n}\n</script>\n\n<template>\n  <n-p>\n    You have selected {{ checkedRowKeysRef.length }} row{{\n      checkedRowKeysRef.length < 2 ? '' : 's'\n    }}.\n  </n-p>\n  <n-data-table\n    v-model:checked-row-keys=\"checkedRowKeysRef\"\n    :columns=\"columns\"\n    :data=\"data\"\n    :pagination=\"pagination\"\n  />\n</template>\n"
  },
  {
    "path": "src/data-table/demos/enUS/custom-sorter.demo.vue",
    "content": "<markdown>\n# Custom sorter\n</markdown>\n\n<script setup lang=\"ts\">\nimport type { DataTableColumns } from 'naive-ui'\nimport { NDataTable } from 'naive-ui'\nimport { ref } from 'vue'\n\ninterface RowData {\n  key: number\n  name: string\n  age: number\n  address: string\n  score: number\n}\n\nfunction createColumns(): DataTableColumns<RowData> {\n  return [\n    {\n      title: 'Name',\n      key: 'name'\n    },\n    {\n      title: 'Age ( only asc/desc switch )',\n      key: 'age',\n      sorter: (row1, row2) => row1.age - row2.age,\n      defaultSortOrder: 'ascend',\n      customNextSortOrder: (order) => {\n        if (order === 'ascend')\n          return 'descend'\n        return 'ascend'\n      }\n    },\n    {\n      title: 'Score ( default three-state )',\n      key: 'score',\n      sorter: (row1, row2) => row1.score - row2.score\n    },\n    {\n      title: 'Address',\n      key: 'address'\n    }\n  ]\n}\n\nconst data = [\n  {\n    key: 0,\n    name: 'John Brown',\n    age: 32,\n    address: 'New York No. 1 Lake Park',\n    score: 89\n  },\n  {\n    key: 1,\n    name: 'Jim Green',\n    age: 42,\n    address: 'London No. 1 Lake Park',\n    score: 92\n  },\n  {\n    key: 2,\n    name: 'Joe Black',\n    age: 32,\n    address: 'Sidney No. 1 Lake Park',\n    score: 78\n  }\n]\n\nconst columns = createColumns()\nconst pagination = ref({ pageSize: 10 })\n</script>\n\n<template>\n  <NDataTable :columns=\"columns\" :data=\"data\" :pagination=\"pagination\" />\n</template>\n"
  },
  {
    "path": "src/data-table/demos/enUS/custom-style.demo.vue",
    "content": "<markdown>\n# Custom style\n\nColumn: Set `className` property on column object to assign a class name to a certain column.\n</markdown>\n\n<script lang=\"ts\" setup>\ninterface RowData {\n  key: number\n  name: string\n  age: number\n  address: string\n}\n\nconst data: RowData[] = [\n  {\n    key: 0,\n    name: 'John Brown',\n    age: 32,\n    address: 'New York No. 1 Lake Park'\n  },\n  {\n    key: 1,\n    name: 'Jim Green',\n    age: 42,\n    address: 'London No. 1 Lake Park'\n  },\n  {\n    key: 2,\n    name: 'Joe Black',\n    age: 32,\n    address: 'Sidney No. 1 Lake Park'\n  }\n]\n\nconst columns = [\n  {\n    title: 'Name',\n    key: 'name'\n  },\n  {\n    title: 'Age',\n    key: 'age',\n    className: 'age'\n  },\n  {\n    title: 'Address',\n    key: 'address'\n  }\n]\n\nfunction rowClassName(row: RowData) {\n  if (row.age > 32) {\n    return 'too-old'\n  }\n  return ''\n}\n</script>\n\n<template>\n  <n-data-table\n    :columns=\"columns\"\n    :data=\"data\"\n    :row-class-name=\"rowClassName\"\n  />\n</template>\n\n<style>\n:deep(.too-old td) {\n  color: rgba(255, 0, 0, 0.75) !important;\n}\n:deep(.age) {\n  color: rgba(0, 128, 0, 0.75) !important;\n}\n:deep(.too-old .age) {\n  color: rgba(0, 0, 128, 0.75) !important;\n}\n</style>\n"
  },
  {
    "path": "src/data-table/demos/enUS/ellipsis-tooltip.demo.vue",
    "content": "<markdown>\n# Ellipsis with tooltip\n\nSet `column.ellipsis.tooltip` to make ellipsis have tooltip. `column.ellipsis` accepts the same props as `n-ellipsis`.\n</markdown>\n\n<script lang=\"ts\" setup>\nconst columns = [\n  {\n    title: 'Name',\n    key: 'name'\n  },\n  {\n    title: 'Age',\n    key: 'age'\n  },\n  {\n    title: 'Address',\n    key: 'address',\n    width: 100,\n    ellipsis: {\n      tooltip: true\n    }\n  },\n  {\n    title: 'Another Address',\n    key: 'anotherAddress',\n    width: 100,\n    ellipsis: {\n      tooltip: true\n    }\n  }\n]\n\nconst data = [\n  {\n    key: 0,\n    name: 'John Brown',\n    age: 32,\n    address: 'New York No. 1 Lake Park',\n    anotherAddress: 'New York No. 1 Lake Park'\n  },\n  {\n    key: 1,\n    name: 'Jim Green',\n    age: 42,\n    address: 'London No. 1 Lake Park',\n    anotherAddress: 'New York No. 1 Lake Park'\n  },\n  {\n    key: 2,\n    name: 'Joe Black',\n    age: 32,\n    address: 'Sidney No. 1 Lake Park',\n    anotherAddress: 'New York No. 1 Lake Park'\n  }\n]\n\nconst pagination = { pageSize: 10 }\n</script>\n\n<template>\n  <n-data-table :columns=\"columns\" :data=\"data\" :pagination=\"pagination\" />\n</template>\n"
  },
  {
    "path": "src/data-table/demos/enUS/ellipsis.demo.vue",
    "content": "<markdown>\n# Ellipsis\n\nEllipsize cell content via setting `column.ellipsis`.\n</markdown>\n\n<script lang=\"ts\" setup>\nconst columns = [\n  {\n    title: 'Name',\n    key: 'name'\n  },\n  {\n    title: 'Age',\n    key: 'age'\n  },\n  {\n    title: 'Address',\n    key: 'address',\n    width: 100,\n    ellipsis: true\n  },\n  {\n    title: 'Another Address',\n    key: 'anotherAddress',\n    width: 100,\n    ellipsis: true\n  }\n]\n\nconst data = [\n  {\n    key: 0,\n    name: 'John Brown',\n    age: 32,\n    address: 'New York No. 1 Lake Park',\n    anotherAddress: 'New York No. 1 Lake Park'\n  },\n  {\n    key: 1,\n    name: 'Jim Green',\n    age: 42,\n    address: 'London No. 1 Lake Park',\n    anotherAddress: 'New York No. 1 Lake Park'\n  },\n  {\n    key: 2,\n    name: 'Joe Black',\n    age: 32,\n    address: 'Sidney No. 1 Lake Park',\n    anotherAddress: 'New York No. 1 Lake Park'\n  }\n]\n\nconst pagination = { pageSize: 10 }\n</script>\n\n<template>\n  <n-data-table :columns=\"columns\" :data=\"data\" :pagination=\"pagination\" />\n</template>\n"
  },
  {
    "path": "src/data-table/demos/enUS/empty.demo.vue",
    "content": "<markdown>\n# Empty\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nfunction createColumns() {\n  return [\n    {\n      title: 'Name',\n      key: 'name'\n    },\n    {\n      title: 'Age',\n      key: 'age'\n    },\n    {\n      title: 'Address',\n      key: 'address'\n    },\n    {\n      title: 'Tags',\n      key: 'tags'\n    },\n    {\n      title: 'Action',\n      key: 'actions'\n    }\n  ]\n}\n\nconst data = ref([])\nconst columns = createColumns()\n</script>\n\n<template>\n  <n-data-table :columns=\"columns\" :data=\"data\" />\n</template>\n"
  },
  {
    "path": "src/data-table/demos/enUS/expand.demo.vue",
    "content": "<markdown>\n# Expand rows\n\nNote that: Expanded rows are not included in the `index` of `render`.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { DataTableColumns } from 'naive-ui'\nimport { NButton, NTag, useMessage } from 'naive-ui'\nimport { h } from 'vue'\n\ninterface RowData {\n  key: number\n  name: string\n  age: number\n  address: string\n  tags: string[]\n}\n\nfunction createColumns({\n  sendMail\n}: {\n  sendMail: (rowData: RowData) => void\n}): DataTableColumns<RowData> {\n  return [\n    {\n      type: 'selection'\n    },\n    {\n      type: 'expand',\n      expandable: rowData => rowData.name !== 'Jim Green',\n      renderExpand: (rowData) => {\n        return `${rowData.name} is a good guy.`\n      }\n    },\n    {\n      title: '#',\n      key: 'key',\n      render: (_, index) => {\n        return `${index + 1}`\n      }\n    },\n    {\n      title: 'Name',\n      key: 'name'\n    },\n    {\n      title: 'Age',\n      key: 'age'\n    },\n    {\n      title: 'Address',\n      key: 'address'\n    },\n    {\n      title: 'Tags',\n      key: 'tags',\n      render(row) {\n        const tags = row.tags.map((tagKey) => {\n          return h(\n            NTag,\n            {\n              style: {\n                marginRight: '6px'\n              },\n              type: 'info',\n              bordered: false\n            },\n            {\n              default: () => tagKey\n            }\n          )\n        })\n        return tags\n      }\n    },\n    {\n      title: 'Action',\n      key: 'actions',\n      render(row) {\n        return h(\n          NButton,\n          {\n            size: 'small',\n            onClick: () => sendMail(row)\n          },\n          { default: () => 'Send Email' }\n        )\n      }\n    }\n  ]\n}\n\nfunction createData(): RowData[] {\n  return [\n    {\n      key: 0,\n      name: 'John Brown',\n      age: 32,\n      address: 'New York No. 1 Lake Park',\n      tags: ['nice', 'developer']\n    },\n    {\n      key: 1,\n      name: 'Jim Green',\n      age: 42,\n      address: 'London No. 1 Lake Park',\n      tags: ['wow']\n    },\n    {\n      key: 2,\n      name: 'Joe Black',\n      age: 32,\n      address: 'Sidney No. 1 Lake Park',\n      tags: ['cool', 'teacher']\n    }\n  ]\n}\n\nconst message = useMessage()\nconst data = createData()\nconst columns = createColumns({\n  sendMail(rowData) {\n    message.info(`send mail to ${rowData.name}`)\n  }\n})\nconst pagination = {\n  pageSize: 10\n}\n</script>\n\n<template>\n  <n-data-table\n    :columns=\"columns\"\n    :data=\"data\"\n    :pagination=\"pagination\"\n    default-expand-all\n  />\n</template>\n"
  },
  {
    "path": "src/data-table/demos/enUS/export-csv.demo.vue",
    "content": "<markdown>\n# Export CSV\n\nYou can use `downloadCsv` method to export data as CSV file.\n\nIf default CSV generation logic can't fit your needs, for example, `title` uses render function, or you need to adjust data format for each cell, you can customize the exported header and cell data with `get-csv-header` and `get-csv-cell` props.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type {\n  DataTableColumns,\n  DataTableGetCsvCell,\n  DataTableGetCsvHeader,\n  DataTableInst,\n  DataTableRowData\n} from 'naive-ui'\nimport { h, ref } from 'vue'\n\ninterface Song {\n  key: number\n  name: string\n  age: number\n  address: string\n}\n\nconst columns: DataTableColumns<DataTableRowData> = [\n  {\n    title: 'Name',\n    key: 'name',\n    sorter: 'default',\n    render(rowData) {\n      return h('span', { style: { color: 'blue' } }, rowData.name)\n    }\n  },\n  {\n    title: () => h('span', { style: { color: 'red' } }, 'Age'),\n    key: 'age',\n    sorter: (row1: object, row2: object) =>\n      (row1 as Song).age - (row2 as Song).age\n  },\n  {\n    title: 'Address',\n    key: 'address',\n    filterOptions: [\n      {\n        label: 'London',\n        value: 'London'\n      },\n      {\n        label: 'New York',\n        value: 'New York'\n      }\n    ],\n    filter: (value: string | number, row: object) => {\n      return !!~(row as Song).address.indexOf(value as string)\n    }\n  }\n]\n\nconst data: Song[] = [\n  {\n    key: 0,\n    name: 'John Brown',\n    age: 18,\n    address: 'New York No. 1 Lake Park'\n  },\n  {\n    key: 1,\n    name: 'Jim Green',\n    age: 28,\n    address: 'London No. 1 Lake Park'\n  },\n  {\n    key: 2,\n    name: 'Joe Black',\n    age: 38,\n    address: 'Sidney No. 1 Lake Park'\n  },\n  {\n    key: 3,\n    name: 'Jim Red',\n    age: 48,\n    address: 'London No. 2 Lake Park'\n  }\n]\n\nconst tableRef = ref<DataTableInst>()\n\nfunction downloadCsv() {\n  return tableRef.value?.downloadCsv({ fileName: 'data-table' })\n}\n\nfunction exportSorterAndFilterCsv() {\n  return tableRef.value?.downloadCsv({\n    fileName: 'sorter-filter',\n    keepOriginalData: false\n  })\n}\n\nconst getCsvCell: DataTableGetCsvCell = (value, _, column) => {\n  if (column.key === 'age') {\n    return `${value} years old`\n  }\n  return value\n}\n\nconst getCsvHeader: DataTableGetCsvHeader = (col) => {\n  if (typeof col.title === 'function') {\n    return col.key === 'age' ? 'Age' : 'Unknown'\n  }\n  else {\n    return col.title || 'Unknown'\n  }\n}\n\nconst pagination = false as const\n</script>\n\n<template>\n  <n-space vertical :size=\"12\">\n    <n-space>\n      <n-button @click=\"downloadCsv\">\n        Export CSV (original data)\n      </n-button>\n      <n-button @click=\"exportSorterAndFilterCsv\">\n        Export CSV (displayed data)\n      </n-button>\n    </n-space>\n    <n-data-table\n      ref=\"tableRef\"\n      :columns=\"columns\"\n      :data=\"data\"\n      :pagination=\"pagination\"\n      :bordered=\"false\"\n      :get-csv-cell=\"getCsvCell\"\n      :get-csv-header=\"getCsvHeader\"\n    />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/data-table/demos/enUS/filter-and-sorter.demo.vue",
    "content": "<markdown>\n  # Uncontrolled filter and sorter\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { DataTableColumns, DataTableInst } from 'naive-ui'\nimport { ref } from 'vue'\n\ninterface RowData {\n  key: number\n  name: string\n  age: number\n  address: string\n}\n\nconst columns: DataTableColumns<RowData> = [\n  {\n    title: 'Name',\n    key: 'name',\n    defaultSortOrder: 'ascend',\n    sorter: 'default'\n  },\n  {\n    title: 'Age',\n    key: 'age',\n    sorter: (row1, row2) => row1.age - row2.age\n  },\n  {\n    title: 'Address',\n    key: 'address',\n    defaultFilterOptionValues: ['London', 'New York'],\n    filterOptions: [\n      {\n        label: 'London',\n        value: 'London'\n      },\n      {\n        label: 'New York',\n        value: 'New York'\n      }\n    ],\n    filter(value, row) {\n      return Boolean(~row.address.indexOf(value as string))\n    }\n  }\n]\n\nconst data = [\n  {\n    key: 0,\n    name: 'John Brown',\n    age: 32,\n    address: 'New York No. 1 Lake Park'\n  },\n  {\n    key: 1,\n    name: 'Jim Green',\n    age: 42,\n    address: 'London No. 1 Lake Park'\n  },\n  {\n    key: 2,\n    name: 'Joe Black',\n    age: 32,\n    address: 'Sidney No. 1 Lake Park'\n  },\n  {\n    key: 3,\n    name: 'Jim Red',\n    age: 32,\n    address: 'London No. 2 Lake Park'\n  }\n]\n\nconst table = ref<DataTableInst | null>(null)\nconst pagination = { pageSize: 5 }\n\nfunction filterAddress() {\n  table.value?.filter({\n    address: ['London']\n  })\n}\n\nfunction sortName() {\n  table.value?.sort('name', 'ascend')\n}\n\nfunction clearFilters() {\n  table.value?.clearFilters()\n}\n\nfunction clearSorter() {\n  table.value?.clearSorter()\n}\n</script>\n\n<template>\n  <n-space vertical :size=\"12\">\n    <n-space>\n      <n-button @click=\"sortName\">\n        Sort By Name (Ascend)\n      </n-button>\n      <n-button @click=\"filterAddress\">\n        Filter Address (London)\n      </n-button>\n      <n-button @click=\"clearFilters\">\n        Clear Filters\n      </n-button>\n      <n-button @click=\"clearSorter\">\n        Clear Sorter\n      </n-button>\n    </n-space>\n    <n-data-table\n      ref=\"table\"\n      :columns=\"columns\"\n      :data=\"data\"\n      :pagination=\"pagination\"\n    />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/data-table/demos/enUS/fixed-header-column.demo.vue",
    "content": "<markdown>\n# Fixed header and column\n\nNote that: If you have set fixed column, you should also set `scroll-x`.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { DataTableColumns } from 'naive-ui'\nimport { h } from 'vue'\n\ninterface RowData {\n  key: number\n  name: string\n  age: number\n  address: string\n  tags: string[]\n}\n\nfunction createColumns(): DataTableColumns<RowData> {\n  return [\n    {\n      type: 'selection',\n      fixed: 'left'\n    },\n    {\n      title: 'Name',\n      key: 'name',\n      width: 200,\n      fixed: 'left'\n    },\n    {\n      title: 'Age',\n      key: 'age',\n      width: 100,\n      fixed: 'left'\n    },\n    {\n      title: 'Row',\n      key: 'row',\n      render(row, index) {\n        return h('span', ['row ', index])\n      }\n    },\n    {\n      title: 'Row1',\n      key: 'row1',\n      render(row, index) {\n        return h('span', ['row ', index])\n      }\n    },\n    {\n      title: 'Row2',\n      key: 'row2',\n      render(row, index) {\n        return h('span', ['row ', index])\n      },\n      width: 100,\n      fixed: 'right'\n    },\n    {\n      title: 'Address',\n      key: 'address',\n      width: 200,\n      fixed: 'right'\n    }\n  ]\n}\n\nconst data = Array.from({ length: 46 }).map((_, index) => ({\n  key: index,\n  name: `Edward King ${index}`,\n  age: 32,\n  address: `London, Park Lane no. ${index}`\n}))\nconst columns = createColumns()\nconst pagination = { pageSize: 10 }\n</script>\n\n<template>\n  <n-data-table\n    :columns=\"columns\"\n    :data=\"data\"\n    :pagination=\"pagination\"\n    :max-height=\"250\"\n    :scroll-x=\"1800\"\n  />\n</template>\n"
  },
  {
    "path": "src/data-table/demos/enUS/fixed-header.demo.vue",
    "content": "<markdown>\n# Fixed header\n\nDisplay large amounts of data in scrollable view by set `max-height`.\n</markdown>\n\n<script lang=\"ts\" setup>\nconst columns = [\n  {\n    title: 'Name',\n    key: 'name'\n  },\n  {\n    title: 'Age',\n    key: 'age'\n  },\n  {\n    title: 'Address',\n    key: 'address'\n  }\n]\n\nconst data = Array.from({ length: 46 }).map((_, index) => ({\n  key: index,\n  name: `Edward King ${index}`,\n  age: 32,\n  address: `London, Park Lane no. ${index}`\n}))\n\nconst pagination = {\n  pageSize: 15\n}\n</script>\n\n<template>\n  <n-data-table\n    :columns=\"columns\"\n    :data=\"data\"\n    :pagination=\"pagination\"\n    :max-height=\"250\"\n  />\n</template>\n"
  },
  {
    "path": "src/data-table/demos/enUS/flex-height.demo.vue",
    "content": "<markdown>\n# Flex height\n\nIf you want to set the overall height of the table, you can set the `flex-height` property.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { DataTableColumns } from 'naive-ui'\nimport { h, ref } from 'vue'\n\ninterface RowData {\n  key: number\n  name: string\n  age: number\n  address: string\n  tags: string[]\n}\n\nfunction createColumns(): DataTableColumns<RowData> {\n  return [\n    {\n      type: 'selection',\n      fixed: 'left'\n    },\n    {\n      title: 'Name',\n      key: 'name',\n      width: 200,\n      fixed: 'left'\n    },\n    {\n      title: 'Age',\n      key: 'age',\n      width: 100,\n      fixed: 'left'\n    },\n    {\n      title: 'Row',\n      key: 'row',\n      render(row, index) {\n        return h('span', ['row ', index])\n      }\n    },\n    {\n      title: 'Row1',\n      key: 'row1',\n      render(row, index) {\n        return h('span', ['row ', index])\n      }\n    },\n    {\n      title: 'Row2',\n      key: 'row2',\n      render(row, index) {\n        return h('span', ['row ', index])\n      },\n      width: 100,\n      fixed: 'right'\n    },\n    {\n      title: 'Address',\n      key: 'address',\n      width: 200,\n      fixed: 'right'\n    }\n  ]\n}\n\nconst data = Array.from({ length: 46 }).map((_, index) => ({\n  key: index,\n  name: `Edward King ${index}`,\n  age: 32,\n  address: `London, Park Lane no. ${index}`\n}))\nconst columns = createColumns()\nconst pagination = { pageSize: 10 }\nconst height = ref(200)\n</script>\n\n<template>\n  <n-space vertical>\n    <n-slider\n      v-model:value=\"height\"\n      :min=\"200\"\n      :max=\"500\"\n      :step=\"100\"\n      style=\"max-width: 180px\"\n    />\n    <n-data-table\n      :columns=\"columns\"\n      :data=\"data\"\n      :pagination=\"pagination\"\n      :scroll-x=\"1800\"\n      :style=\"{ height: `${height}px` }\"\n      flex-height\n    />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/data-table/demos/enUS/group-header.demo.vue",
    "content": "<markdown>\n# Grouped header\n\nNote: If you want grouped header to be fixed, you need to set width of all fixed columns, includes columns with `children`. If not it may not display normally.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nfunction createCols() {\n  return [\n    {\n      title: 'Name',\n      key: 'name'\n    },\n    {\n      title: 'Attrs',\n      key: 'attrs',\n      children: [\n        {\n          title: 'Attack',\n          key: 'attack',\n          children: [\n            {\n              title: 'Physics Attack',\n              key: 'physicsAttack'\n            },\n            {\n              title: 'Magic Attack',\n              key: 'magicAttack'\n            }\n          ]\n        },\n        {\n          title: 'Defend',\n          key: 'defend'\n        },\n        {\n          title: 'Speed',\n          key: 'speed'\n        }\n      ]\n    }\n  ]\n}\n\nfunction createData() {\n  return Array.from({ length: 50 }).map((_, i) => {\n    return {\n      key: i,\n      name: `name_${i}`,\n      physicsAttack: `physicsAttack_${i}`,\n      magicAttack: `magicAttack_${i}`,\n      defend: `defend_${i}`,\n      speed: `speed_${i}`\n    }\n  })\n}\n\nconst data = ref(createData())\nconst columns = ref(createCols())\nconst pagination = ref({\n  pageSize: 10\n})\n</script>\n\n<template>\n  <n-data-table\n    :data=\"data\"\n    :columns=\"columns\"\n    :single-line=\"false\"\n    :pagination=\"pagination\"\n  />\n</template>\n"
  },
  {
    "path": "src/data-table/demos/enUS/index.demo-entry.md",
    "content": "# Data Table\n\n<!--single-column-->\n\nDataTable is used to displays rows of structured data.\n\n<n-alert type=\"warning\" title=\"Caveat\" :bordered=\"false\">\n  <n-ul align-text>\n    <li>\n      Each item of the array passing in the <n-text code>data</n-text> prop represents a row of rendered data, and each row of data must have a unique <n-text code>key</n-text>, otherwise the <n-text code>row-key</n-text> prop must be specified on the table.\n    </li>\n    <li>\n      In non-async mode, page count is determined by data's count. Even if you pass a <n-text code>page-count</n-text> in, it won't change data table's displayed page count. If you want it behaves in this way, you should set <n-text code>remote</n-text> prop.\n    </li>\n    <li>\n      If you want to use the data returned by the server for display, paging, filtering, sorting, please refer to <n-a href=\"#ajax-usage\">Async</n-a>.\n    </li>\n  </n-ul>\n</n-alert>\n\n## Demos\n\n```demo\nbasic.vue\nempty.vue\nborder.vue\nsize.vue\nrow-props.vue\nmerge-cell.vue\nfilter-and-sorter.vue\npagination-behavior-on-filter.vue\nmultiple-sorter.vue\ncustom-sorter.vue\ncolumn-draggable.vue\nselect.vue\nselect-single.vue\ncustom-select.vue\ngroup-header.vue\ncontrolled-page.vue\ncontrolled-filter.vue\ncontrolled-sorter.vue\ncontrolled-multiple-sorter.vue\nfixed-header.vue\nfixed-header-column.vue\nsummary.vue\nellipsis.vue\nellipsis-tooltip.vue\nexpand.vue\nrender-header.vue\ncustom-style.vue\najax-usage.vue\nvirtual.vue\nvirtual-x.vue\ncustom-filter-menu.vue\ntree.vue\nflex-height.vue\nstriped.vue\nsimple-editable.vue\nswitchable-editable.vue\ncontext-menu.vue\nasync-expand.vue\nrender-cell.vue\nexport-csv.vue\n```\n\n## API\n\n### DataTable Props\n\n| Name | Type | Default | Description | Version |\n| --- | --- | --- | --- | --- |\n| allow-checking-not-loaded | `boolean` | `false` | Whether to allow cascade checking on not loaded nodes. If you want to use this, you should know the `check-row-keys` may be incomplete. | 2.28.0 |\n| bordered | `boolean` | `true` | Whether to show border. |  |\n| bottom-bordered | `boolean` | `true` | Whether to show bottom border. |  |\n| checked-row-keys | `Array<string \\| number>` | `undefined` | The keys of checked rows. |  |\n| cascade | `boolean` | `true` | Whether to do cascade checking when using tree data. |  |\n| children-key | `string` | `'children'` | The key of children data in tree data's data entity. |  |\n| columns | `Array<DataTableColumn>` | `[]` | Columns to display. |  |\n| data | `Array<object>` | `[]` | Data to display. |  |\n| default-checked-row-keys | `Array<string \\| number>` | `[]` | The key value selected by default. |  |\n| default-expanded-row-keys | `Array<string \\| number>` | `[]` | The key value of the expanded tree data by default |  |\n| default-expand-all | `boolean` | `false` | Whether to expand all expandable rows. Can't be used with async expanding data. | 2.30.4 |\n| expanded-row-keys | `Array<string \\| number>` | `undefined` | Expanded row keys. |  |\n| filter-icon-popover-props | `PopoverProps` | `{ trigger: click, placement: bottom }` | Filter icon's Popover attribute of the button, See [Popover props](popover#Popover-Props) | 2.39.0 |\n| flex-height | `boolean` | `false` | Whether to make table body's height auto fit table area height. Make it enabled will make `table-layout` always set to `'fixed'`. |  |\n| get-csv-cell | `(value: any, row: object, col: DataTableBaseColumn) => string` | `undefined` | Get CSV's cell content. | 2.40.2 |\n| get-csv-header | `(cols: Array<DataTableColumn>) => string` | `undefined` | Get CSV's header content. | 2.40.2 |\n| header-height | `number` | `28` | Header height value when `virtual-scroll-header` is enabled. | 2.40.0 |\n| height-for-row | `(rowData: object, index: number) => number` | `undefined` | Height configuration function for each row of the table. It must be used with `virtual-scroll-x`. If it's not configured, each rows height would be set to `min-row-height`. | 2.40.0 |\n| indent | `number` | `16` | Indent of row content when using tree data. |  |\n| loading | `boolean` | `false` | Whether to display loading status. |  |\n| max-height | `number \\| string` | `undefined` | The max-height of the table content. Can be a CSS value. |  |\n| min-height | `number \\| string` | `undefined` | The min-height of the table content. Can be a CSS value. |  |\n| min-row-height | `number` | `28` | Min row height of the table when `virtual-scroll` or `virtual-scroll-x` is enabled. Each row's height must be larger than its value. | 2.40.0 |\n| paginate-single-page | `boolean` | `true` | Whether show pagination data is less than one page. | 2.28.0 |\n| pagination | `false \\| object` | `false` | See [Pagination props](pagination#Pagination-Props) |  |\n| pagination-behavior-on-filter | `'first' \\| 'current'` | `'current'` | The behavior of pagination after filter state is changed. `'first'` means returning to first page on filter, `'current'` means keep at current page on filter. | 2.28.3 |\n| remote | `boolean` | `false` | If data-table do automatic paging. You may set it to `true` in async usage. |  |\n| render-cell | `(value: any, rowData: object, column: DataTableBaseColumn) => VNodeChild` | `undefined` | Render function of cell, it will be overwritten by columns' `render`. | 2.30.5 |\n| render-expand-icon | `({ expanded, rowData }: { expanded: boolean, rowData: object }) => VNodeChild` | `undefined` | Render function of expand icon. | 2.32.2, `expanded`: 2.34.4, `rowData`: `2.40.0` |\n| row-class-name | `string \\| (rowData: object, rowIndex : number) => string` | `undefined` | Class name of each row. |  |\n| row-key | `(rowData: object) => (number \\| string)` | `undefined` | Generate the key of the row by row data (if you don't want to set the key). |  |\n| row-props | `(rowData: object, rowIndex : number) => HTMLAttributes` | `undefined` | Customize row attributes. |  |\n| scroll-x | `number \\| string` | `undefined` | If columns are horizontal fixed, scroll-x need to be set. |  |\n| scrollbar-props | `ScrollbarProps` | `undefined` | See [Scrollbar props](scrollbar#Scrollbar-Props), the `on-scroll` attribute already exists in the `DataTable`, the `on-scroll` attribute does not take effect here. |  |\n| single-column | `boolean` | `false` | Whether rows are not divided. If the prop is `true`, table cell has no `border-bottom`. |  |\n| single-line | `boolean` | `true` | Whether columns are not divided. If the prop is `true`, table cell has no `border-right`. |  |\n| size | `'small' \\| 'medium' \\| 'large'` | `'medium'` | Table size. |  |\n| spin-props | `{ strokeWidth?: number, stroke?: string, scale?: number, radius?: number }` | `undefined` | Table spin's props. | 2.34.0 |\n| sticky-expanded-rows | `boolean` | `false` | Expanded row content remains sticky. | 2.32.2 |\n| striped | `boolean` | `false` | Whether to show zebra stripes on rows. |  |\n| summary | `DataTableCreateSummary` | `undefined` | Data of table summary row. For types, see <n-a href=\"#DataTableCreateSummary-Type\">DataTableCreateSummary Type</n-a>. |  |\n| summary-placement | `'top' \\| 'bottom'` | `'bottom'` | Summary rows placement. | 2.33.3 |\n| table-layout | `'auto' \\| 'fixed'` | `'auto'` | Style `table-layout` of the table. When `ellipsis` or `max-height` or `flex-height` are set, it will always be `'fixed'` regardless of what you set. |  |\n| virtual-scroll | `boolean` | `false` | Whether to use virtual scrolling to deal with large data. Make sure `max-height` is set before using it. When `virtual-scroll` is `true`, `rowSpan` will not take effect. |  |\n| virtual-scroll-header | `boolean` | `false` | Whether to use virtual scrolling in table header. If there are too many columns, you can enable the prop. You must configure `header-height` at the same time. Enabling the prop will disable header cells that cross columns & rows. | 2.40.0 |\n| virtual-scroll-x | `boolean` | `false` | Whether to use horizontal virtual scrolling in table body. If there are too many columns, you can enable the prop. Enabling the prop will disable body cells that cross columns & rows. If the prop is enabled, every column should have `width` prop configured and `virtual-scroll`, `scroll-x`, `min-row-height`, `height-for-row`, `virtual-scroll-header` (optional), `header-height` (optional) props should be configured at the same time. You can refer to <n-a href=\"#virtual-x.vue\">the example</n-a>. | 2.40.0 |\n| on-load | `(rowData: object) => Promise<void>` | `undefined` | Callback of async tree data expanding. | 2.27.0 |\n| on-scroll | `(e: Event) => void` | `undefined` | Callback of table body scrolling. | 2.29.1 |\n| on-update:checked-row-keys | `(keys: Array<string \\| number>, rows: object[], meta: { row: object \\| undefined, action: 'check' \\| 'uncheck' \\| 'checkAll' \\| 'uncheckAll' }) => void` | `undefined` | The callback function triggered when the checked-row-keys value changes. | `rows` 2.30.5, `meta` 2.33.4 |\n| on-update:expanded-row-keys | `(keys: Array<string \\| number>) => void` | `undefined` | The callback function triggered when the expanded-row-keys value changes. |  |\n| on-update:filters | `(filters: DataTableFilterState, initiatorColumn: DataTableBaseColumn)` | `undefined` | The callback function triggered when the filters data changes. |  |\n| on-update:page | `(page: number)` | `undefined` | Callback function triggered when the page changes. |  |\n| on-update:page-size | `(pageSize: number) => void` | `undefined` | Callback function triggered when the page-size changes. |  |\n| on-update:sorter | `(options: DataTableSortState \\| DataTableSortState[] \\| null) => void` | `undefined` | If the change column is sorted by multiple columns, will return `DataTableSortState[] \\| null`, otherwise return `DataTableSortState \\| null`. |  |\n\n#### DataTableColumn Properties\n\n| Name | Type | Default | Description | Version |\n| --- | --- | --- | --- | --- |\n| align | `'left' \\| 'right' \\| 'center'` | `'left'` | Text align in column. |  |\n| allowExport | `boolean` | `true` | Can the column exported | 2.40.0 |\n| cellProps | `(rowData: object, rowIndex: number) => object` | `undefined` | HTML attributes of the column's cell. | 2.27.0 |\n| children | `DataTableColumn[]` | `undefined` | Child nodes of a grouped column. |  |\n| className | `string` | `undefined` | Class name of the column. |  |\n| colSpan | `(rowData: object, rowIndex: number) => number` | `undefined` | The col span of the column cell. |  |\n| customNextSortOrder | `(order: 'descend' \\| 'ascend' \\| false) => 'descend' \\| 'ascend' \\| false` | `undefined` | A function for custom next sorting status. | 2.43.0 |\n| defaultFilterOptionValue | `string \\| number \\| null` | `null` | The default active filter option value in uncontrolled manner. (works when not using multiple filters). |  |\n| defaultFilterOptionValues | `Array<string \\| number>` | `[]` | The default active filter option values in uncontrolled manner. (works when there are multiple filters). |  |\n| defaultSortOrder | `'descend' \\| 'ascend' \\| false` | `false` | The default sort order of the table in uncontrolled manner. |  |\n| disabled | `(rowData: object) => boolean` | `() => false` | Whether the row is checkable. |  |\n| ellipsis | `boolean \\| EllipsisProps` | `false` | Ellipsis options when content overflows. |  |\n| ellipsis-component | `'ellipsis' \\| 'performant-ellipsis'` | `'ellipsis'` | Component for rendering text ellipsis. It works when `ellipsis` is `EllipsisProps`. If it's `'ellipsis'`, table will use regular `n-ellipsis` component to render text ellipsis. If it's `'performant-ellipsis'`, table will use `n-performant-ellipsis` to render text ellipsis. In the later situation, rendering speed will be much faster but component inside table cell would be unmounted & remounted. | 2.35.0 |\n| expandable | `(rowData: object) => boolean` | `undefined` | Whethe the row is expandable. Only works when `type` is `'expand'`. |  |\n| filter | `boolean \\| (optionValue: string \\| number, rowData: object) => boolean \\| 'default'` | `false` | The filter of the column. If set to `true`, it will only display filter button on the column, which can be used in async status. |  |\n| filterMode | `'and' \\| 'or'` | `'or'` | The filter mode. |  |\n| filterMultiple | `boolean` | `true` | Can the column filtered by multiple values. |  |\n| filterOptionValue | `string \\| number \\| null` | `undefined` | The active filter option value in controlled manner. If not set, the filter of the column works in an uncontrolled manner. (works when not using multiple filters). |  |\n| filterOptionValues | `Array<string \\| number> \\| null` | `undefined` | The active filter option values in controlled manner. If not set, the filter of the column works in an uncontrolled manner. (works when there are multiple filters). |  |\n| filterOptions | `Array<{ label: string, value: string \\| number}>` | `undefined` | Filter options. |  |\n| fixed | `'left \\| 'right' \\| false` | `false` | Whether the column needs to be fixed. |  |\n| key | `string \\| number` | `undefined` | Unique key of this column, this is not repeatable. |  |\n| maxWidth | `number \\| string` | `undefined` | Max width of the column. Only works when `resizable` is `true`. | 2.33.4 |\n| minWidth | `number \\| string` | `undefined` | Min width of the column. | 2.28.3 |\n| multiple | `boolean` | `true` | Whether to enable multiple selection mode. Only works when `type` is `'selection'`. | 2.31.0 |\n| options | `Array<'all' \\| 'none' \\| { label: string, key: string \\| number, onSelect: (pageData: RowData[]) => void }>` | `undefined` | Options of custom selection. Only work with `type='selection'`. |  |\n| render | `(rowData: object, rowIndex: number) => VNodeChild` | `undefined` | Render function of column row cell. |  |\n| renderExpand | `(rowData: object, rowIndex: number) => VNodeChild` | `undefined` | Render function of the expand area. Only works when `type` is `'expand'`. |  |\n| renderFilter | `(options: { active: boolean, show: boolean }) => VNodeChild` | `undefined` | Render function of column filter trigger. |  |\n| renderFilterIcon | `(options: { active: boolean, show: boolean }) => VNodeChild` | `undefined` | Render function of column filter icon. |  |\n| renderFilterMenu | `(actions: { hide: () => void }) => VNodeChild` | `undefined` | Render function of column filter menu. |  |\n| renderSorter | `(options: { order: 'descend' \\| 'ascend' \\| false }) => VNodeChild` | `undefined` | Render function of column sorter trigger. | 2.24.2 |\n| renderSorterIcon | `(options: { order: 'descend' \\| 'ascend' \\| false }) => VNodeChild` | `undefined` | Render function of column sorter icon. | 2.24.2 |\n| resizable | `boolean` | `undefined` | Whethe the column width can be dragged. | 2.33.4 |\n| rowSpan | `(rowData: object, rowIndex: number) => number` | `undefined` | The row span of the cell. |  |\n| sortOrder | `'descend' \\| 'ascend' \\| false` | `undefined` | The controlled sort order of the column. If multiple columns' sortOrder is set, the first one will affect. |  |\n| sorter | `boolean \\| function \\| 'default'` | `false` | The sorter of the column. If set `'default'`, it will use a basic builtin compare function. If set to `true`, it will only display sort icon on the column, which can be used in async status. Otherwise it works like `Array.sort`'s compare function. |  |\n| title | `string \\| (() => VNodeChild)` | `undefined` | Column title, Can be a render function. |  |\n| titleAlign | `'left' \\| 'right' \\| 'center'` | `null` | alignment of the table header. If omitted, the value of the above align attribute will be applied | 2.34.4 |\n| titleColSpan | `number` | `undefined` | The number of cells occupied by the title col. |  |\n| tree | `boolean` | `false` | Whether to show tree data expand trigger in the column. | 2.28.3 |\n| type | `'selection' \\| 'expand'` | `undefined` | Column type. |  |\n| width | `number \\| string` | `undefined` | Width of the column (**required and should be number** when fixed). | 2.24.0 (`string` type) |\n\nThe following types can be imported from the package.\n\n#### DataTableSortState Type\n\n```ts\ninterface DataTableSortState {\n  columnKey: string | number\n  sorter: 'default' | function | boolean\n  order: 'ascend' | 'descend' | false\n}\n```\n\n#### DataTableFilterState Type\n\n```ts\ninterface DataTableFilterState {\n  [key: string]: Array<string | number> | string | number | null | undefined\n}\n```\n\n#### DataTableCreateSummary Type\n\n```ts\ntype DataTableCreateSummary = (pageData: RowData[]) =>\n  | Array<{\n    [columnKey: string]: {\n      value?: VNodeChild\n      colSpan?: number\n      rowSpan?: number\n    }\n  }>\n  | {\n    [columnKey: string]: {\n      value?: VNodeChild\n      colSpan?: number\n      rowSpan?: number\n    }\n  }\n```\n\n### DataTable Methods\n\nThese methods can help you control table in an uncontrolled manner. However, it's not recommended to use them to implement some async operations. If async operations is needed, use table in a **controlled** manner.\n\n| Name | Type | Description | Version |\n| --- | --- | --- | --- |\n| clearFilters | `() => void` | Clear all filter state. |  |\n| clearSorter | `() => void` | Clear all sort state. |  |\n| downloadCsv | `(options?: { fileName?: string, keepOriginalData?: boolean }) => void` | Download CSV. | 2.37.0 |\n| filters | `(filters: DataTableFilterState \\| null) => void` | Set the active filters of the table. |  |\n| page | `(page: number) => void` | Manually set the page. |  |\n| scrollTo | `(options: { left?: number, top?: number, behavior?: ScrollBehavior }): void & (x: number, y: number) => void` | Scroll content. | 2.30.4 |\n| sort | `(columnKey: string \\| number, order: 'ascend' \\| 'descend' \\| false) => void` | Set the sort state of the table. |  |\n\n### DataTable Slots\n\n| Name    | Type | Description                                       | Version |\n| ------- | ---- | ------------------------------------------------- | ------- |\n| empty   | `()` | Custom description when data of table is empty.   |         |\n| loading | `()` | Custom description when data of table is loading. | 2.34.0  |\n"
  },
  {
    "path": "src/data-table/demos/enUS/merge-cell.demo.vue",
    "content": "<markdown>\n  # Merge cell\n\n  Set colspan and rowspan by setting `colSpan` and `rowSpan` of column object. Set colspan in header by setting `titleColSpan` of column object.\n  </markdown>\n\n<script lang=\"ts\" setup>\nimport type { DataTableColumns } from 'naive-ui'\nimport { NButton, NTag, useMessage } from 'naive-ui'\nimport { h } from 'vue'\n\ninterface RowData {\n  key: number\n  name: string\n  age: number\n  address: string\n  tags: string[]\n}\n\ninterface SendMail {\n  (rowData: RowData): void\n}\n\nfunction createColumns({\n  sendMail\n}: {\n  sendMail: SendMail\n}): DataTableColumns<RowData> {\n  return [\n    {\n      title: 'Name',\n      titleColSpan: 2,\n      key: 'name',\n      rowSpan: (rowData, rowIndex) => (rowIndex === 0 ? 2 : 1),\n      colSpan: (rowData, rowIndex) => (rowIndex === 0 ? 2 : 1)\n    },\n    {\n      title: 'Age',\n      key: 'age'\n    },\n    {\n      title: 'Address',\n      key: 'address',\n      colSpan: (rowData, rowIndex) => (rowIndex === 2 ? 2 : 1)\n    },\n    {\n      title: 'Tags',\n      key: 'tags',\n      titleColSpan: 2,\n      render(row) {\n        const tags = row.tags.map((tagKey) => {\n          return h(\n            NTag,\n            {\n              style: {\n                marginRight: '6px'\n              },\n              type: 'info',\n              bordered: false\n            },\n            {\n              default: () => tagKey\n            }\n          )\n        })\n        return tags\n      }\n    },\n    {\n      title: 'Action',\n      key: 'actions',\n      rowSpan: (rowData, rowIndex) => (rowIndex === 0 ? 2 : 1),\n      render(row) {\n        return h(\n          NButton,\n          {\n            size: 'small',\n            onClick: () => sendMail(row)\n          },\n          { default: () => 'Send Email' }\n        )\n      }\n    }\n  ]\n}\n\nfunction createData(): RowData[] {\n  return [\n    {\n      key: 0,\n      name: 'John Brown',\n      age: 32,\n      address: 'New York No. 1 Lake Park',\n      tags: ['nice', 'developer']\n    },\n    {\n      key: 1,\n      name: 'Jim Green',\n      age: 42,\n      address: 'London No. 1 Lake Park',\n      tags: ['wow']\n    },\n    {\n      key: 2,\n      name: 'Joe Black',\n      age: 32,\n      address: 'Sidney No. 1 Lake Park',\n      tags: ['cool', 'teacher']\n    }\n  ]\n}\n\nconst message = useMessage()\nfunction sendMail(rowData: RowData) {\n  message.info(`send mail to ${rowData.name}`)\n}\n\nconst data = createData()\nconst columns = createColumns({ sendMail })\nconst pagination = {\n  pageSize: 10\n}\n</script>\n\n<template>\n  <n-data-table\n    :columns=\"columns\"\n    :data=\"data\"\n    :pagination=\"pagination\"\n    :single-line=\"false\"\n  />\n</template>\n"
  },
  {
    "path": "src/data-table/demos/enUS/multiple-sorter.demo.vue",
    "content": "<markdown>\n  # Multiple column sorting\n\n  Set `multiple` and `compare` on `sorter` to enable multiple column sorting. `multiple` is the priority of sorting (larger value means higher priority).\n  </markdown>\n\n<script lang=\"ts\" setup>\nimport type { DataTableColumns, DataTableInst } from 'naive-ui'\nimport { ref } from 'vue'\n\ninterface RowData {\n  key: number\n  name: string\n  age: number\n  address: string\n  chinese: number\n  math: number\n  english: number\n}\n\nconst columns: DataTableColumns<RowData> = [\n  {\n    title: 'Name',\n    key: 'name'\n  },\n  {\n    title: 'Age',\n    key: 'age',\n    sorter: (row1, row2) => row1.age - row2.age\n  },\n  {\n    title: 'Chinese Score',\n    key: 'chinese',\n    defaultSortOrder: false,\n    sorter: {\n      compare: (a, b) => a.chinese - b.chinese,\n      multiple: 3\n    }\n  },\n  {\n    title: 'Math Score',\n    defaultSortOrder: false,\n    key: 'math',\n    sorter: {\n      compare: (a, b) => a.math - b.math,\n      multiple: 2\n    }\n  },\n  {\n    title: 'English Score',\n    defaultSortOrder: false,\n    key: 'english',\n    sorter: {\n      compare: (a, b) => a.english - b.english,\n      multiple: 1\n    }\n  },\n  {\n    title: 'Address',\n    key: 'address',\n    filterOptions: [\n      {\n        label: 'London',\n        value: 'London'\n      },\n      {\n        label: 'New York',\n        value: 'New York'\n      }\n    ],\n    filter(value, row) {\n      return Boolean(~row.address.indexOf(value as string))\n    }\n  }\n]\n\nconst data: RowData[] = [\n  {\n    key: 0,\n    name: 'John Brown',\n    age: 32,\n    address: 'New York No. 1 Lake Park',\n    chinese: 98,\n    math: 60,\n    english: 70\n  },\n  {\n    key: 1,\n    name: 'Jim Green',\n    age: 42,\n    address: 'London No. 1 Lake Park',\n    chinese: 98,\n    math: 66,\n    english: 89\n  },\n  {\n    key: 2,\n    name: 'Joe Black',\n    age: 32,\n    address: 'Sidney No. 1 Lake Park',\n    chinese: 98,\n    math: 66,\n    english: 89\n  },\n  {\n    key: 3,\n    name: 'Jim Red',\n    age: 32,\n    address: 'London No. 2 Lake Park',\n    chinese: 88,\n    math: 99,\n    english: 89\n  }\n]\n\nconst dataTableInst = ref<DataTableInst | null>(null)\nconst pagination = ref({ pageSize: 5 })\n\nfunction filterAddress() {\n  dataTableInst.value?.filter({\n    address: ['London']\n  })\n}\n\nfunction sortName() {\n  dataTableInst.value?.sort('name', 'ascend')\n}\n\nfunction clearFilters() {\n  dataTableInst.value?.clearFilters()\n}\n\nfunction clearSorter() {\n  dataTableInst.value?.clearSorter()\n}\n</script>\n\n<template>\n  <n-space vertical :size=\"12\">\n    <n-space>\n      <n-button @click=\"sortName\">\n        Sort By Name (Ascend)\n      </n-button>\n      <n-button @click=\"filterAddress\">\n        Filter Address (London)\n      </n-button>\n      <n-button @click=\"clearFilters\">\n        Clear Filters\n      </n-button>\n      <n-button @click=\"clearSorter\">\n        Clear Sorter\n      </n-button>\n    </n-space>\n    <n-data-table\n      ref=\"dataTableInst\"\n      :columns=\"columns\"\n      :data=\"data\"\n      :pagination=\"pagination\"\n    />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/data-table/demos/enUS/pagination-behavior-on-filter.demo.vue",
    "content": "<markdown>\n# Filter page state\n\nSet `pagination-behavior-on-filter` to control the behavior (whether to stay at current page of return to the first page) on filter state changed.\n\nIf table stays on the current page and the total amount of filtered data cannot reach the current page, the last page of data would be shown.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { DataTableColumns } from 'naive-ui'\n\ninterface RowData {\n  key: number\n  name: string\n  age: number\n  address: string\n}\n\nconst columns: DataTableColumns<RowData> = [\n  {\n    title: 'Name',\n    key: 'name'\n  },\n  {\n    title: 'Age',\n    key: 'age'\n  },\n  {\n    title: 'Address',\n    key: 'address',\n    defaultFilterOptionValues: [],\n    filterOptions: [\n      {\n        label: 'London',\n        value: 'London'\n      },\n      {\n        label: 'New York',\n        value: 'New York'\n      }\n    ],\n    filter(value, row) {\n      return !!~row.address.indexOf(String(value))\n    }\n  }\n]\n\nconst data: RowData[] = [\n  {\n    key: 1,\n    name: 'John Brown',\n    age: 32,\n    address: 'New York No. 1 Lake Park'\n  },\n  {\n    key: 2,\n    name: 'Jim Green',\n    age: 42,\n    address: 'London No. 1 Lake Park'\n  },\n  {\n    key: 3,\n    name: 'Joe Black',\n    age: 32,\n    address: 'Sidney No. 1 Lake Park'\n  },\n  {\n    key: 4,\n    name: 'Jim Red',\n    age: 32,\n    address: 'London No. 2 Lake Park'\n  }\n]\n\nconst pagination = { pageSize: 3 }\n</script>\n\n<template>\n  <n-data-table\n    pagination-behavior-on-filter=\"first\"\n    :columns=\"columns\"\n    :data=\"data\"\n    :pagination=\"pagination\"\n  />\n</template>\n"
  },
  {
    "path": "src/data-table/demos/enUS/render-cell.demo.vue",
    "content": "<markdown>\n# Customized cell rendering\n\nYou may use `render-cell` to customize empty state.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { DataTableColumns } from 'naive-ui'\nimport { NText } from 'naive-ui'\nimport { h } from 'vue'\n\ninterface Song {\n  no: number\n  note: string\n}\n\nfunction createColumns(): DataTableColumns<Song> {\n  return [\n    {\n      title: 'Date',\n      key: 'no',\n      width: 120,\n      render: (_, index) => {\n        return index + 1\n      }\n    },\n    {\n      title: 'Note',\n      key: 'note'\n    }\n  ]\n}\n\nconst data: Song[] = [\n  { no: 3, note: '' },\n  { no: 4, note: '' },\n  { no: 12, note: '' },\n  { no: 10, note: '' },\n  { no: 19, note: '' }\n]\n\nconst columns = createColumns()\n\nfunction renderCell(value: string | number) {\n  if (!value) {\n    return h(NText, { depth: 3 }, { default: () => 'Empty' })\n  }\n  return value\n}\n</script>\n\n<template>\n  <n-data-table :columns=\"columns\" :data=\"data\" :render-cell=\"renderCell\" />\n</template>\n"
  },
  {
    "path": "src/data-table/demos/enUS/render-header.demo.vue",
    "content": "<markdown>\n  # Customized column header rendering\n  </markdown>\n\n<script lang=\"ts\" setup>\nimport type { DataTableBaseColumn, DataTableColumns } from 'naive-ui'\nimport type { ComponentInternalInstance, VNode, VNodeChild } from 'vue'\nimport { NGradientText, NTooltip } from 'naive-ui'\nimport { getCurrentInstance, h } from 'vue'\n\ninterface RowData extends Record<string, unknown> {\n  key: number\n  name: string\n  age: number\n  address: string\n}\n\nfunction renderTooltip(trigger: VNode, content: string): VNodeChild {\n  return h(NTooltip, null, {\n    trigger: () => trigger,\n    default: () => content\n  })\n}\n\nfunction createColumns(\n  _instance: ComponentInternalInstance | null\n): DataTableColumns<RowData> {\n  return [\n    {\n      key: 'name',\n      title(_column: DataTableBaseColumn<RowData>) {\n        return renderTooltip(\n          h(\n            NGradientText,\n            {\n              size: 24,\n              type: 'danger'\n            },\n            { default: () => 'Name' }\n          ),\n          'Tooltip Content'\n        )\n      }\n    },\n    {\n      key: 'age',\n      title(_column: DataTableBaseColumn<RowData>) {\n        return h(\n          NGradientText,\n          {\n            size: '20',\n            type: 'info'\n          },\n          { default: () => 'Age' }\n        )\n      }\n    },\n    {\n      key: 'address',\n      title(_column: DataTableBaseColumn<RowData>) {\n        return h(\n          NGradientText,\n          {\n            size: '16',\n            type: 'warning'\n          },\n          { default: () => 'Address' }\n        )\n      }\n    }\n  ]\n}\n\nconst data = [\n  {\n    key: 0,\n    name: 'John Brown',\n    age: 32,\n    address: 'New York No. 1 Lake Park'\n  },\n  {\n    key: 1,\n    name: 'Jim Green',\n    age: 42,\n    address: 'London No. 1 Lake Park'\n  },\n  {\n    key: 2,\n    name: 'Joe Black',\n    age: 32,\n    address: 'Sidney No. 1 Lake Park'\n  }\n]\n\nconst instance = getCurrentInstance()\nconst columns = createColumns(instance)\nconst pagination = {\n  pageSize: 10\n}\n</script>\n\n<template>\n  <n-data-table :columns=\"columns\" :data=\"data\" :pagination=\"pagination\" />\n</template>\n"
  },
  {
    "path": "src/data-table/demos/enUS/row-props.demo.vue",
    "content": "<markdown>\n# Custom row props\n\nIf you want to add attr or event handlers to a row, use `row-props` prop.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { useMessage } from 'naive-ui'\n\ninterface RowData {\n  key: number\n  name: string\n  age: string\n  address: string\n}\n\nconst message = useMessage()\n\nfunction rowProps(row: RowData) {\n  return {\n    style: 'cursor: pointer;',\n    onClick: () => {\n      message.info(row.name)\n    }\n  }\n}\n\nconst columns = [\n  {\n    title: 'Name',\n    key: 'name'\n  },\n  {\n    title: 'Age',\n    key: 'age'\n  },\n  {\n    title: 'Address',\n    key: 'address'\n  }\n]\n\nconst data = [\n  {\n    key: 0,\n    name: '07akioni',\n    age: '18',\n    address: 'Yiheyuan Road'\n  },\n  {\n    key: 1,\n    name: '08akioni',\n    age: '14',\n    address: 'Pingshan Road'\n  },\n  {\n    key: 2,\n    name: '09akioni',\n    age: '22',\n    address: 'Haidian Bridge'\n  }\n]\n</script>\n\n<template>\n  <n-data-table :columns=\"columns\" :data=\"data\" :row-props=\"rowProps\" />\n</template>\n"
  },
  {
    "path": "src/data-table/demos/enUS/select-single.demo.vue",
    "content": "<markdown>\n# Single selection\n\nSet `multiple: false` to make the column of `type='selection` a single selection mode.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { DataTableColumns } from 'naive-ui'\nimport { ref } from 'vue'\n\ninterface RowData {\n  key: number\n  name: string\n  age: number\n  address: string\n}\n\nconst data = Array.from({ length: 46 }).map((_, index) => ({\n  name: `Edward King ${index}`,\n  age: 32,\n  address: `London, Park Lane no. ${index}`,\n  key: index\n}))\n\nfunction createColumns(): DataTableColumns<RowData> {\n  return [\n    {\n      type: 'selection',\n      multiple: false,\n      disabled(row: RowData) {\n        return row.name === 'Edward King 3'\n      }\n    },\n    {\n      title: 'Name',\n      key: 'name'\n    },\n    {\n      title: 'Age',\n      key: 'age'\n    },\n    {\n      title: 'Address',\n      key: 'address'\n    }\n  ]\n}\n\nconst checkedRowKeysRef = ref([4, 1])\nconst columns = createColumns()\nconst pagination = {\n  pageSize: 6\n}\n</script>\n\n<template>\n  <n-data-table\n    v-model:checked-row-keys=\"checkedRowKeysRef\"\n    :columns=\"columns\"\n    :data=\"data\"\n    :pagination=\"pagination\"\n  />\n</template>\n"
  },
  {
    "path": "src/data-table/demos/enUS/select.demo.vue",
    "content": "<markdown>\n# Selection\n\nRows can be selectable by making first column's type as `selection`.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { DataTableColumns, DataTableRowKey } from 'naive-ui'\nimport { ref } from 'vue'\n\ninterface RowData {\n  key: number\n  name: string\n  age: string\n  address: string\n}\n\nfunction createColumns(): DataTableColumns<RowData> {\n  return [\n    {\n      type: 'selection',\n      disabled(row: RowData) {\n        return row.name === 'Edward King 3'\n      }\n    },\n    {\n      title: 'Name',\n      key: 'name'\n    },\n    {\n      title: 'Age',\n      key: 'age'\n    },\n    {\n      title: 'Address',\n      key: 'address'\n    }\n  ]\n}\n\nconst data = Array.from({ length: 46 }).map((_, index) => ({\n  name: `Edward King ${index}`,\n  age: 32,\n  address: `London, Park Lane no. ${index}`\n}))\n\nconst checkedRowKeysRef = ref<DataTableRowKey[]>([])\nconst columns = createColumns()\nconst pagination = {\n  pageSize: 5\n}\n\nfunction rowKey(row: RowData) {\n  return row.address\n}\n\nfunction handleCheck(rowKeys: DataTableRowKey[]) {\n  checkedRowKeysRef.value = rowKeys\n}\n</script>\n\n<template>\n  <n-p>\n    You have selected {{ checkedRowKeysRef.length }} row{{\n      checkedRowKeysRef.length < 2 ? '' : 's'\n    }}.\n  </n-p>\n\n  <n-data-table\n    :columns=\"columns\"\n    :data=\"data\"\n    :pagination=\"pagination\"\n    :row-key=\"rowKey\"\n    @update:checked-row-keys=\"handleCheck\"\n  />\n</template>\n"
  },
  {
    "path": "src/data-table/demos/enUS/simple-editable.demo.vue",
    "content": "<markdown>\n# Simple Editable Table\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { DataTableColumns } from 'naive-ui'\nimport { NInput } from 'naive-ui'\nimport { h, ref } from 'vue'\n\ninterface RowData {\n  key: number\n  name: string\n  age: string\n  address: string\n}\n\nfunction createData(): RowData[] {\n  return [\n    {\n      key: 0,\n      name: 'John Brown',\n      age: '32',\n      address: 'New York No. 1 Lake Park'\n    },\n    {\n      key: 1,\n      name: 'Jim Green',\n      age: '42',\n      address: 'London No. 1 Lake Park'\n    },\n    {\n      key: 2,\n      name: 'Joe Black',\n      age: '32',\n      address: 'Sidney No. 1 Lake Park'\n    }\n  ]\n}\n\nconst data = ref(createData())\n\nfunction createColumns(): DataTableColumns<RowData> {\n  return [\n    {\n      title: 'Name',\n      key: 'name',\n      render(row, index) {\n        return h(NInput, {\n          value: row.name,\n          onUpdateValue(v) {\n            data.value[index].name = v\n          }\n        })\n      }\n    },\n    {\n      title: 'Age',\n      key: 'age',\n      render(row, index) {\n        return h(NInput, {\n          value: row.age,\n          onUpdateValue(v) {\n            data.value[index].age = v\n          }\n        })\n      }\n    },\n    {\n      title: 'Address',\n      key: 'address',\n      render(row, index) {\n        return h(NInput, {\n          value: row.address,\n          onUpdateValue(v) {\n            data.value[index].address = v\n          }\n        })\n      }\n    }\n  ]\n}\n\nconst columns = createColumns()\nconst pagination = {\n  pageSize: 10\n}\n</script>\n\n<template>\n  <n-data-table :columns=\"columns\" :data=\"data\" :pagination=\"pagination\" />\n  <pre>{{ JSON.stringify(data, null, 2) }}</pre>\n</template>\n"
  },
  {
    "path": "src/data-table/demos/enUS/size.demo.vue",
    "content": "<markdown>\n# Size\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { DataTableColumns } from 'naive-ui'\nimport { NButton, NTag, useMessage } from 'naive-ui'\nimport { h } from 'vue'\n\ninterface RowData {\n  key: number\n  name: string\n  age: number\n  address: string\n  tags: string[]\n}\n\nfunction createColumns({\n  sendMail\n}: {\n  sendMail: (rowData: RowData) => void\n}): DataTableColumns<RowData> {\n  return [\n    {\n      title: 'Name',\n      key: 'name'\n    },\n    {\n      title: 'Age',\n      key: 'age'\n    },\n    {\n      title: 'Address',\n      key: 'address'\n    },\n    {\n      title: 'Tags',\n      key: 'tags',\n      render(row) {\n        const tags = row.tags.map((tagKey) => {\n          return h(\n            NTag,\n            {\n              style: {\n                marginRight: '6px'\n              },\n              type: 'info',\n              bordered: false\n            },\n            {\n              default: () => tagKey\n            }\n          )\n        })\n        return tags\n      }\n    },\n    {\n      title: 'Action',\n      key: 'actions',\n      render(row) {\n        return h(\n          NButton,\n          {\n            size: 'small',\n            onClick: () => sendMail(row)\n          },\n          { default: () => 'Send Email' }\n        )\n      }\n    }\n  ]\n}\n\nfunction createData(): RowData[] {\n  return [\n    {\n      key: 0,\n      name: 'John Brown',\n      age: 32,\n      address: 'New York No. 1 Lake Park',\n      tags: ['nice', 'developer']\n    },\n    {\n      key: 1,\n      name: 'Jim Green',\n      age: 42,\n      address: 'London No. 1 Lake Park',\n      tags: ['wow']\n    },\n    {\n      key: 2,\n      name: 'Joe Black',\n      age: 32,\n      address: 'Sidney No. 1 Lake Park',\n      tags: ['cool', 'teacher']\n    }\n  ]\n}\n\nconst message = useMessage()\nconst data = createData()\nconst columns = createColumns({\n  sendMail(rowData) {\n    message.info(`send mail to ${rowData.name}`)\n  }\n})\nconst pagination = {\n  pageSize: 10\n}\n</script>\n\n<template>\n  <n-space vertical :size=\"12\">\n    <n-data-table\n      size=\"small\"\n      :columns=\"columns\"\n      :data=\"data\"\n      :pagination=\"pagination\"\n    />\n    <n-data-table\n      size=\"large\"\n      :columns=\"columns\"\n      :data=\"data\"\n      :pagination=\"pagination\"\n    />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/data-table/demos/enUS/striped.demo.vue",
    "content": "<markdown>\n# Striped\n\nUsing `striped` prop to make it easier to distinguish rows.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { DataTableColumns } from 'naive-ui'\n\ninterface RowData {\n  key: number\n  name: string\n  age: number\n  address: string\n}\n\nfunction createColumns(): DataTableColumns<RowData> {\n  return [\n    {\n      type: 'selection'\n    },\n    {\n      title: 'Name',\n      key: 'name'\n    },\n    {\n      title: 'Age',\n      key: 'age'\n    },\n    {\n      title: 'Address',\n      key: 'address'\n    }\n  ]\n}\n\nfunction createData(): RowData[] {\n  return [\n    {\n      key: 0,\n      name: 'John Brown',\n      age: 32,\n      address: 'New York No. 1 Lake Park'\n    },\n    {\n      key: 1,\n      name: 'Jim Green',\n      age: 42,\n      address: 'London No. 1 Lake Park'\n    },\n    {\n      key: 2,\n      name: 'Joe Black',\n      age: 32,\n      address: 'Sidney No. 1 Lake Park'\n    }\n  ]\n}\n\nconst data = createData()\nconst columns = createColumns()\n</script>\n\n<template>\n  <n-data-table :columns=\"columns\" :data=\"data\" striped />\n</template>\n"
  },
  {
    "path": "src/data-table/demos/enUS/summary.demo.vue",
    "content": "<markdown>\n# Summary\n\nUse `summary` prop to render summary.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { DataTableColumns, DataTableCreateSummary } from 'naive-ui'\nimport { h } from 'vue'\n\ninterface RowData {\n  key: number\n  name: string\n  age: number\n  address: string\n}\n\nfunction createColumns(): DataTableColumns<RowData> {\n  return [\n    {\n      type: 'selection'\n    },\n    {\n      title: 'Name',\n      key: 'name'\n    },\n    {\n      title: 'Age',\n      key: 'age'\n    },\n    {\n      title: 'Address',\n      key: 'address'\n    }\n  ]\n}\n\nfunction createData(): RowData[] {\n  return [\n    {\n      key: 0,\n      name: 'John Brown',\n      age: 32,\n      address: 'New York No. 1 Lake Park'\n    },\n    {\n      key: 1,\n      name: 'Jim Green',\n      age: 42,\n      address: 'London No. 1 Lake Park'\n    },\n    {\n      key: 2,\n      name: 'Joe Black',\n      age: 32,\n      address: 'Sidney No. 1 Lake Park'\n    }\n  ]\n}\n\nconst createSummary: DataTableCreateSummary = (pageData) => {\n  return {\n    name: {\n      value: h(\n        'span',\n        { style: { color: 'red' } },\n        (pageData as unknown as RowData[]).reduce(\n          (prevValue, row) => prevValue + row.age,\n          0\n        )\n      ),\n      colSpan: 3\n    }\n  }\n}\n\nconst summary = createSummary\nconst data = createData()\nconst columns = createColumns()\n</script>\n\n<template>\n  <n-data-table :columns=\"columns\" :data=\"data\" :summary=\"summary\" />\n</template>\n"
  },
  {
    "path": "src/data-table/demos/enUS/switchable-editable.demo.vue",
    "content": "<markdown>\n  # Switchable Editable Table\n  </markdown>\n\n<script lang=\"ts\" setup>\nimport type { InputInst } from 'naive-ui'\nimport type { PropType } from 'vue'\nimport { NInput } from 'naive-ui'\nimport { computed, defineComponent, h, nextTick, ref } from 'vue'\n\ninterface RowData {\n  key: number\n  name: string\n  age: number\n  address: string\n}\n\ninterface OnUpdateValue {\n  (value: string): void\n}\n\nfunction createData(): RowData[] {\n  return Array.from({ length: 100 }).map((_, index) => ({\n    key: index,\n    name: `John Brown ${index}`,\n    age: (Math.random() * 40) | 0,\n    address: `New York No. ${index} Lake Park`\n  }))\n}\n\nconst ShowOrEdit = defineComponent({\n  props: {\n    value: [String, Number],\n    onUpdateValue: [Function, Array] as PropType<OnUpdateValue>\n  },\n  setup(props) {\n    const isEdit = ref(false)\n    const inputRef = ref<InputInst | null>(null)\n    const inputValue = ref(props.value)\n    function handleOnClick() {\n      isEdit.value = true\n      nextTick(() => {\n        inputRef.value?.focus()\n      })\n    }\n    function handleChange() {\n      props.onUpdateValue?.(String(inputValue.value))\n      isEdit.value = false\n    }\n    return () =>\n      h(\n        'div',\n        {\n          style: 'min-height: 22px',\n          onClick: handleOnClick\n        },\n        isEdit.value\n          ? h(NInput, {\n              ref: inputRef,\n              value: String(inputValue.value),\n              onUpdateValue: (v) => {\n                inputValue.value = v\n              },\n              onChange: handleChange,\n              onBlur: handleChange\n            })\n          : props.value\n      )\n  }\n})\n\nconst data = ref(createData())\nconst page = ref(1)\n\nfunction getDataIndex(key: number) {\n  return data.value.findIndex(item => item.key === key)\n}\nfunction handlePageChange(curPage: number) {\n  page.value = curPage\n}\n\nconst paginationRef = computed(() => ({\n  pageSize: 10,\n  page: page.value\n}))\n\nconst columns = [\n  {\n    title: 'Name',\n    key: 'name',\n    width: 150,\n    render(row: RowData) {\n      const index = getDataIndex(row.key)\n      return h(ShowOrEdit, {\n        value: row.name,\n        onUpdateValue(v: string) {\n          data.value[index].name = v\n        }\n      })\n    }\n  },\n  {\n    title: 'Age',\n    key: 'age',\n    width: 100,\n    render(row: RowData) {\n      const index = getDataIndex(row.key)\n      return h(ShowOrEdit, {\n        value: row.age,\n        onUpdateValue(v: string) {\n          data.value[index].age = Number(v)\n        }\n      })\n    }\n  },\n  {\n    title: 'Address',\n    key: 'address',\n    render(row: RowData) {\n      const index = getDataIndex(row.key)\n      return h(ShowOrEdit, {\n        value: row.address,\n        onUpdateValue(v: string) {\n          data.value[index].address = v\n        }\n      })\n    }\n  }\n]\n</script>\n\n<template>\n  <n-data-table\n    :key=\"(row: RowData) => row.key\"\n    :columns=\"columns\"\n    :data=\"data\"\n    :pagination=\"paginationRef\"\n    :on-update:page=\"handlePageChange\"\n  />\n</template>\n"
  },
  {
    "path": "src/data-table/demos/enUS/tree.demo.vue",
    "content": "<markdown>\n# Tree data\n\nSet `children` in row data to show tree data. If you want to use other key to get children, you can set another `children-key`.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { DataTableColumns } from 'naive-ui'\n\ninterface RowData {\n  name: string\n  index: string\n  children?: RowData[]\n}\n\nconst data: RowData[] = [\n  {\n    name: '07akioni',\n    index: '07',\n    children: [\n      {\n        name: '08akioni',\n        index: '08',\n        children: [\n          {\n            name: '09akioni',\n            index: '09'\n          },\n          {\n            name: '10akioni',\n            index: '10'\n          }\n        ]\n      }\n    ]\n  },\n  {\n    name: '11akioni',\n    index: '11'\n  }\n]\n\nconst columns: DataTableColumns<RowData> = [\n  {\n    type: 'selection'\n  },\n  {\n    title: 'name',\n    key: 'name'\n  },\n  {\n    title: 'index',\n    key: 'index'\n  }\n]\n\nfunction rowKey(row: RowData) {\n  return row.index\n}\n</script>\n\n<template>\n  <n-data-table\n    :columns=\"columns\"\n    :data=\"data\"\n    :row-key=\"rowKey\"\n    default-expand-all\n  />\n</template>\n"
  },
  {
    "path": "src/data-table/demos/enUS/virtual-x.demo.vue",
    "content": "<markdown>\n# Large data (rows & cols)\n\nIf you have a large amount of row and column data, such as thousands of rows and hundreds of columns, `naive-ui` provides horizontal + vertical virtual scrolling functionality.\n\nDue to the inherent complexity of horizontal virtual scrolling, the corresponding configuration can be quite complex, with most of the following content being necessary:\n\n1. Configure `virtual-scroll` to enable vertical virtual scrolling.\n2. Configure `virtual-scroll-x` to enable horizontal virtual scrolling:\n    - Each column needs to have a `width` property configured.\n    - Configure the `scroll-x` property, setting it to the total width of all columns.\n    - Configure the `min-row-height` property, setting it to the minimum height of each row, where all rows must be larger than this value.\n    - Configure the `height-for-row` property, which is used to set the height of each row (since only a portion of the cells in each row are always visible, this cannot be automatically calculated). If not configured, the height of each row will be set to `min-row-height`.\n3. If needed, configure `virtual-scroll-header`. By default, the header will still be fully rendered to maintain compatibility. You can enable virtual rendering for the header with this configuration:\n    - Configure the `header-height` property, setting it to the height of the header.\n\nThe example below corresponds to a table with 1000 rows * 1000 columns.\n\n`naive-ui`'s table can easily support table data in the millions. You won't find this kind of functionality in many free component libraries.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { DataTableColumns } from 'naive-ui'\n\ninterface RowData {\n  key: number\n  name: string\n  age: number\n  address: string\n}\n\nconst columns: DataTableColumns<RowData> = []\n\nlet scrollX = 0\n\nfor (let i = 0; i < 1000; ++i) {\n  scrollX += 100\n  columns.push({\n    title: `Col ${i}`,\n    width: 100,\n    key: i,\n    fixed: i <= 1 ? 'left' : i > 997 ? 'right' : undefined,\n    render(_, rowIndex) {\n      return `${i}-${rowIndex}`\n    }\n  })\n}\n\nconst data: RowData[] = Array.from({ length: 1000 }).map((_, index) => ({\n  key: index,\n  name: `Edward King ${index}`,\n  age: 32,\n  address: `London, Park Lane no. ${index}`\n}))\n\nconst heightForRow = () => 48\n</script>\n\n<template>\n  <n-data-table\n    :columns=\"columns\"\n    :data=\"data\"\n    :max-height=\"250\"\n    virtual-scroll\n    virtual-scroll-x\n    :scroll-x=\"scrollX\"\n    :min-row-height=\"48\"\n    :height-for-row=\"heightForRow\"\n    virtual-scroll-header\n    :header-height=\"48\"\n  />\n</template>\n"
  },
  {
    "path": "src/data-table/demos/enUS/virtual.demo.vue",
    "content": "<markdown>\n# Large data\n\n**Tip: When `virtual-scroll` is `true`, `rowSpan` will not take effect.**\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { DataTableColumns } from 'naive-ui'\nimport { h } from 'vue'\n\ninterface RowData {\n  key: number\n  name: string\n  age: number\n  address: string\n}\n\nconst columns: DataTableColumns<RowData> = [\n  {\n    type: 'selection',\n    fixed: 'left'\n  },\n  {\n    title: 'Name',\n    key: 'name',\n    width: 200,\n    fixed: 'left'\n  },\n  {\n    title: 'Age',\n    key: 'age',\n    width: 100,\n    fixed: 'left'\n  },\n  {\n    title: 'Row',\n    key: 'row',\n    render(row, index) {\n      return h('span', ['row ', index])\n    }\n  },\n  {\n    title: 'Row1',\n    key: 'row1',\n    render(row, index) {\n      return h('span', ['row ', index])\n    }\n  },\n  {\n    title: 'Row2',\n    key: 'row2',\n    render(row, index) {\n      return h('span', ['row ', index])\n    },\n    width: 100,\n    fixed: 'right'\n  },\n  {\n    title: 'Address',\n    key: 'address',\n    width: 200,\n    fixed: 'right'\n  }\n]\n\nconst data: RowData[] = Array.from({ length: 5000 }).map((_, index) => ({\n  key: index,\n  name: `Edward King ${index}`,\n  age: 32,\n  address: `London, Park Lane no. ${index}`\n}))\n</script>\n\n<template>\n  <n-data-table\n    :columns=\"columns\"\n    :data=\"data\"\n    :max-height=\"250\"\n    :scroll-x=\"1800\"\n    virtual-scroll\n  />\n</template>\n"
  },
  {
    "path": "src/data-table/demos/zhCN/ajax-usage.demo.vue",
    "content": "<markdown>\n# 异步\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type {\n  DataTableColumn,\n  DataTableColumns,\n  DataTableFilterState,\n  DataTableSortOrder,\n  DataTableSortState,\n  PaginationInfo\n} from 'naive-ui'\nimport type { FilterOptionValue } from '../../src/interface'\nimport { onMounted, reactive, ref } from 'vue'\n\ninterface RowData {\n  column1: number\n  column2: number\n  column3: string\n}\n\nconst column1: DataTableColumn<RowData> = {\n  title: 'column1',\n  key: 'column1',\n  sorter: true,\n  sortOrder: false\n}\n\nconst column2: DataTableColumn<RowData> = {\n  title: 'column2',\n  key: 'column2',\n  filter: true,\n  filterOptionValues: [],\n  filterOptions: [\n    {\n      label: 'Value1',\n      value: 1\n    },\n    {\n      label: 'Value2',\n      value: 2\n    }\n  ]\n}\n\nconst columns: DataTableColumns<RowData> = [\n  column1,\n  column2,\n  {\n    title: 'Column3',\n    key: 'column3'\n  }\n]\n\nconst data = Array.from({ length: 987 })\n  .fill(null)\n  .map((_, index) => {\n    return {\n      column1: index,\n      column2: (index % 2) + 1,\n      column3: `a${index}`\n    }\n  })\n\ninterface QueryParams {\n  page: number\n  pageSize: number\n  order?: DataTableSortOrder\n  filterValues?: FilterOptionValue[] | null | undefined\n}\n\ninterface QueryResult {\n  pageCount: number\n  data: RowData[]\n  total: number\n}\n\nfunction query({\n  page,\n  pageSize = 10,\n  order = 'ascend',\n  filterValues = []\n}: QueryParams): Promise<QueryResult> {\n  return new Promise((resolve) => {\n    const copiedData = data.map(v => v)\n    const orderedData = order === 'descend' ? copiedData.reverse() : copiedData\n    const filteredData = filterValues?.length\n      ? orderedData.filter(row => filterValues?.includes(row.column2))\n      : orderedData\n    const pagedData = filteredData.slice((page - 1) * pageSize, page * pageSize)\n    const total = filteredData.length\n    const pageCount = Math.ceil(filteredData.length / pageSize)\n    setTimeout(\n      () =>\n        resolve({\n          pageCount,\n          data: pagedData,\n          total\n        }),\n      1500\n    )\n  })\n}\n\nconst dataRef = ref<RowData[]>([])\nconst loadingRef = ref(true)\nconst columnsRef = ref(columns)\nconst column1Reactive = reactive(column1)\nconst column2Reactive = reactive(column2)\nconst paginationReactive = reactive({\n  page: 1,\n  pageCount: 1,\n  pageSize: 10,\n  itemCount: 0,\n  prefix({ itemCount }: PaginationInfo) {\n    return `Total is ${itemCount}.`\n  }\n})\n\nonMounted(() => {\n  query({\n    page: paginationReactive.page,\n    pageSize: paginationReactive.pageSize,\n    order: column1Reactive.sortOrder,\n    filterValues: column2Reactive.filterOptionValues\n  }).then((data) => {\n    dataRef.value = data.data\n    paginationReactive.pageCount = data.pageCount\n    paginationReactive.itemCount = data.total\n    loadingRef.value = false\n  })\n})\n\nfunction rowKey(rowData: RowData) {\n  return rowData.column1\n}\n\nfunction handleSorterChange(sorter: DataTableSortState) {\n  if (!sorter || sorter.columnKey === 'column1') {\n    if (!loadingRef.value) {\n      loadingRef.value = true\n      query({\n        page: paginationReactive.page,\n        pageSize: paginationReactive.pageSize,\n        order: !sorter ? false : sorter.order,\n        filterValues: column2Reactive.filterOptionValues\n      }).then((data) => {\n        column1Reactive.sortOrder = !sorter ? false : sorter.order\n        dataRef.value = data.data\n        paginationReactive.pageCount = data.pageCount\n        paginationReactive.itemCount = data.total\n        loadingRef.value = false\n      })\n    }\n  }\n}\n\nfunction handleFiltersChange(filters: DataTableFilterState) {\n  if (!loadingRef.value) {\n    loadingRef.value = true\n    const filterValues = Array.isArray(filters.column2) ? filters.column2 : []\n    query({\n      page: paginationReactive.page,\n      pageSize: paginationReactive.pageSize,\n      order: column1Reactive.sortOrder,\n      filterValues\n    }).then((data) => {\n      column2Reactive.filterOptionValues = filterValues\n      dataRef.value = data.data\n      paginationReactive.pageCount = data.pageCount\n      paginationReactive.itemCount = data.total\n      loadingRef.value = false\n    })\n  }\n}\n\nfunction handlePageChange(currentPage: number) {\n  if (!loadingRef.value) {\n    loadingRef.value = true\n    query({\n      page: currentPage,\n      pageSize: paginationReactive.pageSize,\n      order: column1Reactive.sortOrder,\n      filterValues: column2Reactive.filterOptionValues\n    }).then((data) => {\n      dataRef.value = data.data\n      paginationReactive.page = currentPage\n      paginationReactive.pageCount = data.pageCount\n      paginationReactive.itemCount = data.total\n      loadingRef.value = false\n    })\n  }\n}\n</script>\n\n<template>\n  <n-data-table\n    remote\n    :columns=\"columnsRef\"\n    :data=\"dataRef\"\n    :loading=\"loadingRef\"\n    :pagination=\"paginationReactive\"\n    :row-key=\"rowKey\"\n    @update:sorter=\"handleSorterChange\"\n    @update:filters=\"handleFiltersChange\"\n    @update:page=\"handlePageChange\"\n  />\n</template>\n"
  },
  {
    "path": "src/data-table/demos/zhCN/async-expand.demo.vue",
    "content": "<markdown>\n# 异步展开树形数据\n\n在 `onLoad` 回调中更改数据。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { DataTableColumns } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst columns: DataTableColumns = [\n  { type: 'selection' },\n  { key: 'example', title: 'Example' }\n]\nconst dataRef = ref([\n  { key: 'p1', example: 'p1', isLeaf: false },\n  { key: 'p2', example: 'p2', isLeaf: false },\n  { key: 'p3', example: 'p3', isLeaf: false }\n])\nconst data = dataRef\n\nfunction onLoad(row: Record<string, unknown>) {\n  return new Promise<void>((resolve) => {\n    setTimeout(() => {\n      row.children = [{ key: `${row.key}-1`, example: `${row.key}-1` }]\n      resolve()\n    }, 1000)\n  })\n}\n</script>\n\n<template>\n  <n-data-table\n    :columns=\"columns\"\n    :data=\"data\"\n    :cascade=\"false\"\n    allow-checking-not-loaded\n    @load=\"onLoad\"\n  />\n</template>\n"
  },
  {
    "path": "src/data-table/demos/zhCN/basic.demo.vue",
    "content": "<markdown>\n# 基础用法\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { DataTableColumns } from 'naive-ui'\nimport { NButton, useMessage } from 'naive-ui'\nimport { h } from 'vue'\n\ninterface Song {\n  no: number\n  title: string\n  length: string\n}\n\nfunction createColumns({\n  play\n}: {\n  play: (row: Song) => void\n}): DataTableColumns<Song> {\n  return [\n    {\n      title: 'No',\n      key: 'no'\n    },\n    {\n      title: 'Title',\n      key: 'title'\n    },\n    {\n      title: 'Length',\n      key: 'length'\n    },\n    {\n      title: 'Action',\n      key: 'actions',\n      render(row) {\n        return h(\n          NButton,\n          {\n            strong: true,\n            tertiary: true,\n            size: 'small',\n            onClick: () => play(row)\n          },\n          { default: () => 'Play' }\n        )\n      }\n    }\n  ]\n}\n\nconst data: Song[] = [\n  { no: 3, title: 'Wonderwall', length: '4:18' },\n  { no: 4, title: 'Don\\'t Look Back in Anger', length: '4:48' },\n  { no: 12, title: 'Champagne Supernova', length: '7:27' }\n]\n\nconst message = useMessage()\nconst columns = createColumns({\n  play(row: Song) {\n    message.info(`Play ${row.title}`)\n  }\n})\nconst pagination = false as const\n</script>\n\n<template>\n  <n-data-table\n    :columns=\"columns\"\n    :data=\"data\"\n    :pagination=\"pagination\"\n    :bordered=\"false\"\n  />\n</template>\n"
  },
  {
    "path": "src/data-table/demos/zhCN/border.demo.vue",
    "content": "<markdown>\n# 无边框 & 无列分隔 & 无行分隔\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { DataTableColumns } from 'naive-ui'\nimport { NButton, NTag, useMessage } from 'naive-ui'\nimport { h } from 'vue'\n\ninterface RowData {\n  key: number\n  name: string\n  age: number\n  address: string\n  tags: string[]\n}\n\nfunction createColumns({\n  sendMail\n}: {\n  sendMail: (rowData: RowData) => void\n}): DataTableColumns<RowData> {\n  return [\n    {\n      title: 'Name',\n      key: 'name'\n    },\n    {\n      title: 'Age',\n      key: 'age'\n    },\n    {\n      title: 'Address',\n      key: 'address'\n    },\n    {\n      title: 'Tags',\n      key: 'tags',\n      render(row) {\n        const tags = row.tags.map((tagKey) => {\n          return h(\n            NTag,\n            {\n              style: {\n                marginRight: '6px'\n              },\n              type: 'info',\n              bordered: false\n            },\n            {\n              default: () => tagKey\n            }\n          )\n        })\n        return tags\n      }\n    },\n    {\n      title: 'Action',\n      key: 'actions',\n      render(row) {\n        return h(\n          NButton,\n          {\n            size: 'small',\n            onClick: () => sendMail(row)\n          },\n          { default: () => 'Send Email' }\n        )\n      }\n    }\n  ]\n}\n\nfunction createData(): RowData[] {\n  return [\n    {\n      key: 0,\n      name: 'John Brown',\n      age: 32,\n      address: 'New York No. 1 Lake Park',\n      tags: ['nice', 'developer']\n    },\n    {\n      key: 1,\n      name: 'Jim Green',\n      age: 42,\n      address: 'London No. 1 Lake Park',\n      tags: ['wow']\n    },\n    {\n      key: 2,\n      name: 'Joe Black',\n      age: 32,\n      address: 'Sidney No. 1 Lake Park',\n      tags: ['cool', 'teacher']\n    }\n  ]\n}\n\nconst message = useMessage()\nconst data = createData()\nconst columns = createColumns({\n  sendMail(rowData) {\n    message.info(`send mail to ${rowData.name}`)\n  }\n})\nconst pagination = {\n  pageSize: 10\n}\n</script>\n\n<template>\n  <n-space vertical :size=\"12\">\n    <n-data-table\n      :bordered=\"false\"\n      :single-line=\"false\"\n      :columns=\"columns\"\n      :data=\"data\"\n      :pagination=\"pagination\"\n    />\n    <n-data-table\n      :bordered=\"false\"\n      :columns=\"columns\"\n      :data=\"data\"\n      :pagination=\"pagination\"\n    />\n    <n-data-table\n      :bordered=\"false\"\n      :single-line=\"false\"\n      single-column\n      :columns=\"columns\"\n      :data=\"data\"\n      :pagination=\"pagination\"\n    />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/data-table/demos/zhCN/column-draggable.demo.vue",
    "content": "<markdown>\n# 列宽拖拽\n\n仅支持叶子结点。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { DataTableColumns } from 'naive-ui'\nimport { NButton, useMessage } from 'naive-ui'\nimport { h } from 'vue'\n\ninterface Song {\n  no: number\n  title: string\n  length: string\n}\n\nfunction createColumns({\n  play\n}: {\n  play: (row: Song) => void\n}): DataTableColumns<Song> {\n  return [\n    {\n      title: 'No',\n      key: 'no',\n      width: 50\n    },\n    {\n      title: 'Title',\n      key: 'title',\n      resizable: true\n    },\n    {\n      title: 'Length (minWidth: 100, maxWidth: 500)',\n      key: 'length',\n      resizable: true,\n      minWidth: 100,\n      maxWidth: 500\n    },\n    {\n      title: 'Action',\n      key: 'actions',\n      render(row) {\n        return h(\n          NButton,\n          {\n            strong: true,\n            tertiary: true,\n            size: 'small',\n            onClick: () => play(row)\n          },\n          { default: () => 'Play' }\n        )\n      }\n    }\n  ]\n}\n\nconst data: Song[] = [\n  { no: 3, title: 'Wonderwall', length: '4:18' },\n  { no: 4, title: 'Don\\'t Look Back in Anger', length: '4:48' },\n  { no: 12, title: 'Champagne Supernova', length: '7:27' }\n]\n\nconst message = useMessage()\nconst columns = createColumns({\n  play(row: Song) {\n    message.info(`Play ${row.title}`)\n  }\n})\nconst pagination = false as const\n</script>\n\n<template>\n  <n-data-table\n    :columns=\"columns\"\n    :data=\"data\"\n    :pagination=\"pagination\"\n    :bordered=\"false\"\n  />\n</template>\n"
  },
  {
    "path": "src/data-table/demos/zhCN/context-menu.demo.vue",
    "content": "<markdown>\n# 右键菜单\n\n配合 `n-dropdown` 实现右键菜单。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { DataTableColumns, DropdownOption } from 'naive-ui'\nimport { useMessage } from 'naive-ui'\nimport { h, nextTick, ref } from 'vue'\n\ninterface Song {\n  no: number\n  title: string\n  length: string\n}\n\nconst data: Song[] = [\n  { no: 1, title: 'Hello', length: '3:21' },\n  { no: 2, title: 'Roll with It', length: '3:59' },\n  { no: 3, title: 'Wonderwall', length: '4:18' },\n  { no: 4, title: 'Don\\'t Look Back in Anger', length: '4:48' },\n  { no: 5, title: 'Hey Now!', length: '5:41' },\n  { no: 6, title: 'Untitled', length: '0:44' },\n  { no: 7, title: 'Some Might Say', length: '5:29' },\n  { no: 8, title: 'Cast No Shadow', length: '4:51' },\n  { no: 9, title: 'She\\'s Electric', length: '3:40' },\n  { no: 10, title: 'Monring Glory', length: '5:03' },\n  { no: 11, title: 'Untitled', length: '0:39' },\n  { no: 12, title: 'Champagne Supernova', length: '7:27' }\n]\n\nconst options: DropdownOption[] = [\n  {\n    label: '编辑',\n    key: 'edit'\n  },\n  {\n    label: () => h('span', { style: { color: 'red' } }, '删除'),\n    key: 'delete'\n  }\n]\n\nconst message = useMessage()\nconst showDropdownRef = ref(false)\nconst xRef = ref(0)\nconst yRef = ref(0)\nconst colsReactive: DataTableColumns<Song> = [\n  {\n    title: 'No.',\n    key: 'no'\n  },\n  {\n    title: 'Title',\n    key: 'title'\n  },\n  {\n    title: 'Length',\n    key: 'length'\n  }\n]\n\nconst cols = colsReactive\nconst showDropdown = showDropdownRef\nconst x = xRef\nconst y = yRef\n\nfunction handleSelect() {\n  showDropdownRef.value = false\n}\n\nfunction onClickoutside() {\n  showDropdownRef.value = false\n}\n\nfunction rowProps(row: Song) {\n  return {\n    onContextmenu: (e: MouseEvent) => {\n      message.info(JSON.stringify(row, null, 2))\n      e.preventDefault()\n      showDropdownRef.value = false\n      nextTick().then(() => {\n        showDropdownRef.value = true\n        xRef.value = e.clientX\n        yRef.value = e.clientY\n      })\n    }\n  }\n}\n</script>\n\n<template>\n  <n-data-table :columns=\"cols\" :data=\"data\" :row-props=\"rowProps\" />\n  <n-dropdown\n    placement=\"bottom-start\"\n    trigger=\"manual\"\n    :x=\"x\"\n    :y=\"y\"\n    :options=\"options\"\n    :show=\"showDropdown\"\n    :on-clickoutside=\"onClickoutside\"\n    @select=\"handleSelect\"\n  />\n</template>\n"
  },
  {
    "path": "src/data-table/demos/zhCN/controlled-filter.demo.vue",
    "content": "<markdown>\n# 受控的过滤器\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type {\n  DataTableBaseColumn,\n  DataTableColumns,\n  DataTableFilterState\n} from 'naive-ui'\nimport { reactive } from 'vue'\n\ninterface Row {\n  key: number\n  name: string\n  age: number\n  address: string\n}\n\nconst data = [\n  {\n    key: 0,\n    name: 'John Brown',\n    age: 32,\n    address: 'New York No. 1 Lake Park'\n  },\n  {\n    key: 1,\n    name: 'Jim Green',\n    age: 42,\n    address: 'London No. 1 Lake Park'\n  },\n  {\n    key: 2,\n    name: 'Joe Black',\n    age: 32,\n    address: 'Sidney No. 1 Lake Park'\n  },\n  {\n    key: 3,\n    name: 'Jim Red',\n    age: 32,\n    address: 'London No. 2 Lake Park'\n  }\n]\n\nconst addressColumn = reactive<DataTableBaseColumn<Row>>({\n  title: 'Address',\n  key: 'address',\n  filterMultiple: false,\n  filterOptionValue: null,\n  sorter: 'default',\n  filterOptions: [\n    {\n      label: 'London',\n      value: 'London'\n    },\n    {\n      label: 'New York',\n      value: 'New York'\n    }\n  ],\n  filter(value, row) {\n    return !!~row.address.indexOf(value.toString())\n  }\n})\n\nconst columns = reactive<DataTableColumns<Row>>([\n  {\n    title: 'Name',\n    key: 'name',\n    sorter(rowA, rowB) {\n      return rowA.name.length - rowB.name.length\n    }\n  },\n  {\n    title: 'Age',\n    key: 'age',\n    sorter(rowA, rowB) {\n      return rowA.age - rowB.age\n    }\n  },\n  addressColumn\n])\n\nconst pagination = { pageSize: 5 }\n\nfunction filterAddress() {\n  addressColumn.filterOptionValue = 'London'\n}\n\nfunction unfilterAddress() {\n  addressColumn.filterOptionValue = null\n}\n\nfunction handleUpdateFilter(\n  filters: DataTableFilterState,\n  sourceColumn: DataTableBaseColumn\n) {\n  addressColumn.filterOptionValue = filters[sourceColumn.key] as string\n}\n</script>\n\n<template>\n  <n-space vertical :size=\"12\">\n    <n-space>\n      <n-button @click=\"filterAddress\">\n        Filter Address(Use Value 'London')\n      </n-button>\n      <n-button @click=\"unfilterAddress\">\n        Clear Address Filters\n      </n-button>\n    </n-space>\n    <n-data-table\n      :columns=\"columns\"\n      :data=\"data\"\n      :pagination=\"pagination\"\n      @update:filters=\"handleUpdateFilter\"\n    />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/data-table/demos/zhCN/controlled-multiple-sorter.demo.vue",
    "content": "<markdown>\n  # 受控的多列排序\n\n  如果列对象的 `sortOrder` 属性被设为 `'ascend'`、`'descend'` 或者 `false`，表格的排序将为受控状态。\n\n  如果你只需要 UI 显示多列排序的状态，那么不传 `compare` 即可。\n  </markdown>\n\n<script lang=\"ts\" setup>\nimport type {\n  DataTableColumnKey,\n  DataTableColumns,\n  DataTableSortOrder,\n  DataTableSortState\n} from 'naive-ui'\nimport { computed, ref } from 'vue'\n\ninterface RowData {\n  key: number\n  name: string\n  age: number\n  chinese: number\n  math: number\n  english: number\n}\n\nconst data: RowData[] = [\n  {\n    key: 0,\n    name: 'John Brown',\n    age: 32,\n    chinese: 98,\n    math: 60,\n    english: 70\n  },\n  {\n    key: 1,\n    name: 'Jim Green',\n    age: 42,\n    chinese: 98,\n    math: 66,\n    english: 89\n  },\n  {\n    key: 2,\n    name: 'Joe Black',\n    age: 32,\n    chinese: 98,\n    math: 66,\n    english: 89\n  },\n  {\n    key: 3,\n    name: 'Jim Red',\n    age: 32,\n    chinese: 88,\n    math: 99,\n    english: 89\n  }\n]\n\nconst sortStates = ref<DataTableSortState[]>([])\nconst sortKeyMapOrder = computed<\n  Record<DataTableColumnKey, DataTableSortOrder>\n>(() =>\n  sortStates.value.reduce(\n    (\n      result: Record<DataTableColumnKey, DataTableSortOrder>,\n      { columnKey, order }\n    ) => {\n      result[columnKey] = order\n      return result\n    },\n    {}\n  )\n)\nconst pagination = ref({ pageSize: 5 })\n\nconst columns = computed<DataTableColumns<RowData>>(() => [\n  {\n    title: 'Name',\n    key: 'name'\n  },\n  {\n    title: 'Age',\n    key: 'age',\n    sortOrder: sortKeyMapOrder.value.age || false,\n    sorter(rowA, rowB) {\n      return rowA.age - rowB.age\n    }\n  },\n  {\n    title: 'Chinese Score',\n    key: 'chinese',\n    sortOrder: sortKeyMapOrder.value.chinese || false,\n    sorter: {\n      compare: (a, b) => a.chinese - b.chinese,\n      multiple: 3\n    }\n  },\n  {\n    title: 'Math Score',\n    key: 'math',\n    sortOrder: sortKeyMapOrder.value.math || false,\n    sorter: {\n      compare: (a, b) => a.math - b.math,\n      multiple: 2\n    }\n  },\n  {\n    title: 'English Score',\n    sortOrder: sortKeyMapOrder.value.english || false,\n    key: 'english',\n    sorter: {\n      compare: (a, b) => a.english - b.english,\n      multiple: 1\n    }\n  }\n])\n\nfunction handleUpdateSorter(sorters: DataTableSortState[]) {\n  console.log(sorters)\n  sortStates.value = ([] as DataTableSortState[]).concat(sorters)\n}\n</script>\n\n<template>\n  <n-data-table\n    :columns=\"columns\"\n    :data=\"data\"\n    :pagination=\"pagination\"\n    @update:sorter=\"handleUpdateSorter\"\n  />\n</template>\n"
  },
  {
    "path": "src/data-table/demos/zhCN/controlled-page.demo.vue",
    "content": "<markdown>\n# 受控的分页\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { reactive } from 'vue'\n\nconst columns = [\n  {\n    title: 'Name',\n    key: 'name'\n  },\n  {\n    title: 'Age',\n    key: 'age'\n  },\n  {\n    title: 'Address',\n    key: 'address'\n  }\n]\n\nconst data = Array.from({ length: 46 }).map((_, index) => ({\n  key: index,\n  name: `Edward King ${index}`,\n  age: 32,\n  address: `London, Park Lane no. ${index}`\n}))\n\nconst pagination = reactive({\n  page: 2,\n  pageSize: 5,\n  showSizePicker: true,\n  pageSizes: [3, 5, 7],\n  onChange: (page: number) => {\n    pagination.page = page\n  },\n  onUpdatePageSize: (pageSize: number) => {\n    pagination.pageSize = pageSize\n    pagination.page = 1\n  }\n})\n</script>\n\n<template>\n  <n-data-table :columns=\"columns\" :data=\"data\" :pagination=\"pagination\" />\n</template>\n"
  },
  {
    "path": "src/data-table/demos/zhCN/controlled-sorter.demo.vue",
    "content": "<markdown>\n# 受控的排序\n\n如果列对象的 `sortOrder` 属性被设为 `'ascend'`、`'descend'` 或者 `false`，表格的排序将为受控状态。如果很多列的 `sortOrder` 都被设定了，那么只有他们之中的第一列会生效。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type {\n  DataTableBaseColumn,\n  DataTableSortOrder,\n  DataTableSortState\n} from 'naive-ui'\nimport { reactive, ref } from 'vue'\n\ninterface RowData {\n  key: number\n  name: string\n  age: number\n  address: string\n}\n\nconst nameColumn: DataTableBaseColumn<RowData> = {\n  title: 'Name',\n  key: 'name',\n  sortOrder: false,\n  sorter: 'default'\n}\n\nconst ageColumn: DataTableBaseColumn<RowData> = {\n  title: 'Age',\n  key: 'age',\n  sortOrder: false,\n  sorter(rowA, rowB) {\n    return rowA.age - rowB.age\n  }\n}\n\nconst columns: DataTableBaseColumn<RowData>[] = [\n  nameColumn,\n  ageColumn,\n  {\n    title: 'Address',\n    key: 'address',\n    defaultFilterOptionValues: ['London', 'New York'],\n    filterOptions: [\n      {\n        label: 'London',\n        value: 'London'\n      },\n      {\n        label: 'New York',\n        value: 'New York'\n      }\n    ],\n    filter(value, row) {\n      return row.address.includes(value as string)\n    }\n  }\n]\n\nconst data = [\n  {\n    key: 0,\n    name: 'John Brown',\n    age: 38,\n    address: 'New York No. 1 Lake Park'\n  },\n  {\n    key: 1,\n    name: 'Jim Green',\n    age: 42,\n    address: 'London No. 1 Lake Park'\n  },\n  {\n    key: 2,\n    name: 'Joe Black',\n    age: 36,\n    address: 'Sidney No. 1 Lake Park'\n  },\n  {\n    key: 3,\n    name: 'Jim Red',\n    age: 32,\n    address: 'London No. 2 Lake Park'\n  }\n]\n\nconst nameColumnReactive = reactive(nameColumn)\nconst ageColumnReactive = reactive(ageColumn)\nconst columnsRef = ref<DataTableBaseColumn<RowData>[]>(columns)\nconst pagination = { pageSize: 5 }\n\nfunction handleSorterChange(sorter: DataTableSortState) {\n  columnsRef.value.forEach((column: DataTableBaseColumn<RowData>) => {\n    /** column.sortOrder !== undefined means it is uncontrolled */\n    if (column.sortOrder === undefined)\n      return\n    if (!sorter) {\n      column.sortOrder = false\n      return\n    }\n    if (column.key === sorter.columnKey)\n      column.sortOrder = sorter.order\n    else column.sortOrder = false\n  })\n}\n\nfunction sortName(order: DataTableSortOrder) {\n  nameColumnReactive.sortOrder = order\n}\n\nfunction clearSorter() {\n  nameColumnReactive.sortOrder = false\n  ageColumnReactive.sortOrder = false\n}\n</script>\n\n<template>\n  <n-space vertical :size=\"12\">\n    <n-space>\n      <n-button @click=\"sortName('ascend')\">\n        Sort By Name (Ascend)\n      </n-button>\n      <n-button @click=\"sortName('descend')\">\n        Sort By Name (Descend)\n      </n-button>\n      <n-button @click=\"clearSorter\">\n        Clear Sorter\n      </n-button>\n    </n-space>\n    <n-data-table\n      :columns=\"columns\"\n      :data=\"data\"\n      :pagination=\"pagination\"\n      @update:sorter=\"handleSorterChange\"\n    />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/data-table/demos/zhCN/custom-expand-icon-debug.demo.vue",
    "content": "<markdown>\n# 自定义展开图标\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { DataTableColumns } from 'naive-ui'\nimport { ArrowForward } from '@vicons/ionicons5'\nimport { NIcon } from 'naive-ui'\nimport { h } from 'vue'\n\ninterface RowData {\n  name: string\n  key: string\n  children?: RowData[]\n}\n\nfunction createData(): RowData[] {\n  return [\n    {\n      name: 'John Brown',\n      key: '1'\n    },\n    {\n      name: 'Jim Green',\n      key: '2'\n    },\n    {\n      name: 'Joe Black',\n      key: '3'\n    }\n  ]\n}\n\nconst columns: DataTableColumns<RowData> = [\n  {\n    type: 'expand',\n    renderExpand: (rowData) => {\n      return `${rowData.name} is a good guy.`\n    }\n  },\n  {\n    title: '#',\n    key: 'key',\n    render: (_, index) => {\n      return `${index + 1}`\n    }\n  },\n  {\n    title: 'Name',\n    key: 'name'\n  },\n  {\n    title: 'index',\n    key: 'key'\n  }\n]\n\nconst data = createData()\n\nfunction renderExpandIcon() {\n  return h(NIcon, null, { default: () => h(ArrowForward) })\n}\n</script>\n\n<template>\n  <n-data-table\n    :columns=\"columns\"\n    :data=\"data\"\n    :render-expand-icon=\"renderExpandIcon\"\n    default-expand-all\n  />\n</template>\n"
  },
  {
    "path": "src/data-table/demos/zhCN/custom-filter-menu.demo.vue",
    "content": "<markdown>\n# 自定义图标\n\n你可以自定义过滤图标、过滤菜单、排序图标、展开图标的样式。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { DataTableBaseColumn, DataTableColumns } from 'naive-ui'\nimport { PawOutline, SearchOutline } from '@vicons/ionicons5'\nimport { NButton, NIcon, NSpace } from 'naive-ui'\nimport { h, reactive } from 'vue'\n\nconst data = [\n  {\n    Left: '1',\n    Right: '1',\n    key: 1\n  },\n  {\n    Left: '2',\n    Right: '2',\n    key: 2\n  }\n]\n\nfunction renderExpandIcon() {\n  return h(NIcon, null, { default: () => h(PawOutline) })\n}\n\nconst filterColumn = reactive<DataTableBaseColumn>({\n  title: 'Right',\n  key: 'Right',\n  filter: 'default',\n  filterOptionValue: null,\n  renderFilterIcon: () => {\n    return h(NIcon, null, { default: () => h(SearchOutline) })\n  },\n  renderFilterMenu: ({ hide }) => {\n    return h(\n      NSpace,\n      { style: { padding: '12px' }, vertical: true },\n      {\n        default: () => [\n          h(\n            NButton,\n            {\n              onClick: () => {\n                filterColumn.filterOptionValue = '1'\n              }\n            },\n            { default: () => 'Filter by 1' }\n          ),\n          h(\n            NButton,\n            {\n              onClick: () => {\n                filterColumn.filterOptionValue = '2'\n              }\n            },\n            { default: () => 'Filter by 2' }\n          ),\n          h(\n            NButton,\n            {\n              onClick: () => {\n                filterColumn.filterOptionValue = null\n                hide()\n              }\n            },\n            { default: () => 'clear' }\n          )\n        ]\n      }\n    )\n  }\n})\n\nconst cols = reactive<DataTableColumns>([\n  {\n    type: 'expand',\n    renderExpand: () => {\n      return 'Expand content'\n    }\n  },\n  {\n    title: 'Left',\n    key: 'Left',\n    sorter: 'default',\n    renderSorterIcon: ({ order }) => {\n      const style = 'transform: translateY(-3px);'\n      if (order === false)\n        return h('div', { style }, ['🤔'])\n      if (order === 'ascend')\n        return h('div', { style }, ['👇'])\n      if (order === 'descend')\n        return h('div', { style }, ['👆'])\n    }\n  },\n  filterColumn\n])\n</script>\n\n<template>\n  <n-data-table\n    :columns=\"cols\"\n    :data=\"data\"\n    :render-expand-icon=\"renderExpandIcon\"\n  />\n</template>\n"
  },
  {
    "path": "src/data-table/demos/zhCN/custom-select.demo.vue",
    "content": "<markdown>\n# 自定义选择项菜单\n\n在 `type='selection'` 的列设定 `options` 来在头部勾选框旁边创建下拉菜单。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { DataTableColumns } from 'naive-ui'\nimport { repeat } from 'seemly'\nimport { ref } from 'vue'\n\ninterface RowData {\n  name: string\n  age: number\n  address: string\n  key: number\n}\n\nconst data = repeat(46, undefined).map<RowData>((_, index) => ({\n  name: `Edward King ${index}`,\n  age: 32,\n  address: `London, Park Lane no. ${index}`,\n  key: index\n}))\n\nconst checkedRowKeysRef = ref<Array<string | number>>([])\nconst columns: DataTableColumns<RowData> = [\n  {\n    type: 'selection',\n    options: [\n      'all',\n      'none',\n      {\n        label: '选中前 2 行',\n        key: 'f2',\n        onSelect: (pageData) => {\n          checkedRowKeysRef.value = pageData.map(row => row.key).slice(0, 2)\n        }\n      }\n    ],\n    disabled(row) {\n      return row.name === 'Edward King 3'\n    }\n  },\n  {\n    title: 'Name',\n    key: 'name'\n  },\n  {\n    title: 'Age',\n    key: 'age'\n  },\n  {\n    title: 'Address',\n    key: 'address'\n  }\n]\n\nconst checkedRowKeys = checkedRowKeysRef\nconst pagination = {\n  pageSize: 6\n}\n</script>\n\n<template>\n  <n-p>你选中了 {{ checkedRowKeys.length }} 行。</n-p>\n  <n-data-table\n    v-model:checked-row-keys=\"checkedRowKeys\"\n    :columns=\"columns\"\n    :data=\"data\"\n    :pagination=\"pagination\"\n  />\n</template>\n"
  },
  {
    "path": "src/data-table/demos/zhCN/custom-sorter.demo.vue",
    "content": "<markdown>\n# 自定义排序\n</markdown>\n\n<script setup lang=\"ts\">\nimport type { DataTableColumns } from 'naive-ui'\nimport { NDataTable } from 'naive-ui'\nimport { ref } from 'vue'\n\ninterface RowData {\n  key: number\n  name: string\n  age: number\n  address: string\n  score: number\n}\n\nfunction createColumns(): DataTableColumns<RowData> {\n  return [\n    {\n      title: 'Name',\n      key: 'name'\n    },\n    {\n      title: 'Age ( 仅升序和降序切换 )',\n      key: 'age',\n      sorter: (row1, row2) => row1.age - row2.age,\n      defaultSortOrder: 'ascend',\n      customNextSortOrder: (order) => {\n        if (order === 'ascend')\n          return 'descend'\n        return 'ascend'\n      }\n    },\n    {\n      title: 'Score ( 常规三态排序 )',\n      key: 'score',\n      sorter: (row1, row2) => row1.score - row2.score\n    },\n    {\n      title: 'Address',\n      key: 'address'\n    }\n  ]\n}\n\nconst data = [\n  {\n    key: 0,\n    name: 'John Brown',\n    age: 32,\n    address: 'New York No. 1 Lake Park',\n    score: 89\n  },\n  {\n    key: 1,\n    name: 'Jim Green',\n    age: 42,\n    address: 'London No. 1 Lake Park',\n    score: 92\n  },\n  {\n    key: 2,\n    name: 'Joe Black',\n    age: 32,\n    address: 'Sidney No. 1 Lake Park',\n    score: 78\n  }\n]\n\nconst columns = createColumns()\nconst pagination = ref({ pageSize: 10 })\n</script>\n\n<template>\n  <NDataTable :columns=\"columns\" :data=\"data\" :pagination=\"pagination\" />\n</template>\n"
  },
  {
    "path": "src/data-table/demos/zhCN/custom-style.demo.vue",
    "content": "<markdown>\n# 自定义样式\n\n列：在列对象上设定 `className` 属性为确定的列设定 class。\n</markdown>\n\n<script lang=\"ts\" setup>\ninterface RowData {\n  key: number\n  name: string\n  age: number\n  address: string\n}\n\nconst data: RowData[] = [\n  {\n    key: 0,\n    name: 'John Brown',\n    age: 32,\n    address: 'New York No. 1 Lake Park'\n  },\n  {\n    key: 1,\n    name: 'Jim Green',\n    age: 42,\n    address: 'London No. 1 Lake Park'\n  },\n  {\n    key: 2,\n    name: 'Joe Black',\n    age: 32,\n    address: 'Sidney No. 1 Lake Park'\n  }\n]\n\nconst columns = [\n  {\n    title: 'Name',\n    key: 'name'\n  },\n  {\n    title: 'Age',\n    key: 'age',\n    className: 'age'\n  },\n  {\n    title: 'Address',\n    key: 'address'\n  }\n]\n\nfunction rowClassName(row: RowData) {\n  if (row.age > 32) {\n    return 'too-old'\n  }\n  return ''\n}\n</script>\n\n<template>\n  <n-data-table\n    :columns=\"columns\"\n    :data=\"data\"\n    :row-class-name=\"rowClassName\"\n  />\n</template>\n\n<style>\n:deep(.too-old td) {\n  color: rgba(255, 0, 0, 0.75) !important;\n}\n:deep(.age) {\n  color: rgba(0, 128, 0, 0.75) !important;\n}\n:deep(.too-old .age) {\n  color: rgba(0, 0, 128, 0.75) !important;\n}\n</style>\n"
  },
  {
    "path": "src/data-table/demos/zhCN/debug.demo.vue",
    "content": "<markdown>\n# Debug\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { DataTableColumns, PaginationProps } from 'naive-ui'\nimport { NButton, useMessage } from 'naive-ui'\nimport { h, ref } from 'vue'\n\ninterface Song {\n  no: number\n  title: string\n  length: string\n}\n\nfunction createColumns({\n  play\n}: {\n  play: (row: Song) => void\n}): DataTableColumns<Song> {\n  return [\n    {\n      title: 'No',\n      key: 'no'\n    },\n    {\n      title: 'Title',\n      key: 'title',\n      align: 'right'\n    },\n    {\n      title: 'Length',\n      key: 'length',\n      align: 'center'\n    },\n    {\n      title: 'Action',\n      key: 'actions',\n      render(row) {\n        return h(\n          NButton,\n          {\n            strong: true,\n            tertiary: true,\n            size: 'small',\n            onClick: () => play(row)\n          },\n          { default: () => 'Play' }\n        )\n      }\n    }\n  ]\n}\n\nconst data: Song[] = [\n  { no: 3, title: 'Wonderwall', length: '4:18' },\n  { no: 4, title: 'Don\\'t Look Back in Anger', length: '4:48' },\n  { no: 12, title: 'Champagne Supernova', length: '7:27' }\n]\n\nconst message = useMessage()\nconst pagination: PaginationProps = {\n  prefix: ({ startIndex, endIndex }) => {\n    return ['startIndex', startIndex, 'endIndex', endIndex]\n  }\n}\nconst columns = createColumns({\n  play(row: Song) {\n    message.info(`Play ${row.title}`)\n  }\n})\nconst loading = ref(false)\n</script>\n\n<template>\n  <n-switch v-model:value=\"loading\">\n    <template #checked>\n      Loading\n    </template>\n    <template #unchecked>\n      Not loading\n    </template>\n  </n-switch>\n  <n-data-table\n    :loading=\"loading\"\n    :columns=\"columns\"\n    :data=\"data\"\n    :pagination=\"pagination\"\n    :bordered=\"false\"\n  />\n</template>\n"
  },
  {
    "path": "src/data-table/demos/zhCN/ellipsis-debug.demo.vue",
    "content": "<markdown>\n# Ellipsis debug\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { DataTableColumns } from 'naive-ui'\nimport { h } from 'vue'\n\ninterface RowData {\n  key: number\n  name: string\n  age: number\n  address: string\n  tags: string[]\n}\n\nfunction createColumns(): DataTableColumns<RowData> {\n  return [\n    {\n      type: 'selection',\n      fixed: 'left'\n    },\n    {\n      title: 'Age',\n      key: 'age',\n      width: 100,\n      fixed: 'left'\n    },\n    {\n      title: 'Name',\n      key: 'name',\n      width: 200,\n      ellipsis: true,\n      fixed: 'left'\n    },\n    {\n      title: 'Row',\n      key: 'row',\n      render(row, index) {\n        return h('span', ['row ', index])\n      }\n    },\n    {\n      title: 'Row1',\n      key: 'row1',\n      render(row, index) {\n        return h('span', ['row ', index])\n      }\n    },\n    {\n      title: 'Row2',\n      key: 'row2',\n      render(row, index) {\n        return h('span', ['row ', index])\n      },\n      width: 100,\n      fixed: 'right'\n    },\n    {\n      title: 'Address',\n      key: 'address',\n      width: 200,\n      fixed: 'right'\n    }\n  ]\n}\n\nconst data = Array.from({ length: 46 }).map((_, index) => ({\n  key: index,\n  name: `Edward King ${index}`,\n  age: 32,\n  address: `London, Park Lane no. ${index}`\n}))\nconst columns = createColumns()\nconst pagination = { pageSize: 10 }\n</script>\n\n<template>\n  <n-data-table\n    :columns=\"columns\"\n    :data=\"data\"\n    :pagination=\"pagination\"\n    :max-height=\"250\"\n    :scroll-x=\"1800\"\n  />\n</template>\n"
  },
  {
    "path": "src/data-table/demos/zhCN/ellipsis-tooltip.demo.vue",
    "content": "<markdown>\n# 带提示的省略\n\n通过设定 `column.ellipsis.tooltip` 使得省略内容有弹出提示。`column.ellipsis` 接受的属性和 `n-ellipsis` 相同。\n</markdown>\n\n<script lang=\"ts\" setup>\nconst columns = [\n  {\n    title: 'Name',\n    key: 'name'\n  },\n  {\n    title: 'Age',\n    key: 'age'\n  },\n  {\n    title: 'Address',\n    key: 'address',\n    width: 100,\n    ellipsis: {\n      tooltip: true\n    }\n  },\n  {\n    title: 'Another Address',\n    key: 'anotherAddress',\n    width: 100,\n    ellipsis: {\n      tooltip: true\n    }\n  }\n]\n\nconst data = [\n  {\n    key: 0,\n    name: 'John Brown',\n    age: 32,\n    address: 'New York No. 1 Lake Park',\n    anotherAddress: 'New York No. 1 Lake Park'\n  },\n  {\n    key: 1,\n    name: 'Jim Green',\n    age: 42,\n    address: 'London No. 1 Lake Park',\n    anotherAddress: 'New York No. 1 Lake Park'\n  },\n  {\n    key: 2,\n    name: 'Joe Black',\n    age: 32,\n    address: 'Sidney No. 1 Lake Park',\n    anotherAddress: 'New York No. 1 Lake Park'\n  }\n]\n\nconst pagination = { pageSize: 10 }\n</script>\n\n<template>\n  <n-data-table :columns=\"columns\" :data=\"data\" :pagination=\"pagination\" />\n</template>\n"
  },
  {
    "path": "src/data-table/demos/zhCN/ellipsis.demo.vue",
    "content": "<markdown>\n# 省略\n\n通过设定 `column.ellipsis` 省略单元格内容。\n</markdown>\n\n<script lang=\"ts\" setup>\nconst columns = [\n  {\n    title: 'Name',\n    key: 'name'\n  },\n  {\n    title: 'Age',\n    key: 'age'\n  },\n  {\n    title: 'Address',\n    key: 'address',\n    width: 100,\n    ellipsis: true\n  },\n  {\n    title: 'Another Address',\n    key: 'anotherAddress',\n    width: 100,\n    ellipsis: true\n  }\n]\n\nconst data = [\n  {\n    key: 0,\n    name: 'John Brown',\n    age: 32,\n    address: 'New York No. 1 Lake Park',\n    anotherAddress: 'New York No. 1 Lake Park'\n  },\n  {\n    key: 1,\n    name: 'Jim Green',\n    age: 42,\n    address: 'London No. 1 Lake Park',\n    anotherAddress: 'New York No. 1 Lake Park'\n  },\n  {\n    key: 2,\n    name: 'Joe Black',\n    age: 32,\n    address: 'Sidney No. 1 Lake Park',\n    anotherAddress: 'New York No. 1 Lake Park'\n  }\n]\n\nconst pagination = { pageSize: 10 }\n</script>\n\n<template>\n  <n-data-table :columns=\"columns\" :data=\"data\" :pagination=\"pagination\" />\n</template>\n"
  },
  {
    "path": "src/data-table/demos/zhCN/empty-scroll-debug.demo.vue",
    "content": "<markdown>\n# 空表格 & 滚动条 Debug\n\n覆盖空表格以及所有可能出现滚动条的场景组合，验证有数据和无数据时的滚动条行为。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { DataTableColumns } from 'naive-ui'\n\ninterface RowData {\n  key: number\n  name: string\n  age: number\n  address: string\n  city: string\n  zip: string\n  country: string\n  phone: string\n  email: string\n}\n\nconst columns: DataTableColumns<RowData> = [\n  { title: 'Name', key: 'name', width: 200, fixed: 'left' },\n  { title: 'Age', key: 'age', width: 100 },\n  { title: 'Address', key: 'address', width: 300 },\n  { title: 'City', key: 'city', width: 200 },\n  { title: 'Zip', key: 'zip', width: 150 },\n  { title: 'Country', key: 'country', width: 200 },\n  { title: 'Phone', key: 'phone', width: 200 },\n  { title: 'Email', key: 'email', width: 250, fixed: 'right' }\n]\n\nconst manyRows: RowData[] = Array.from({ length: 50 }).map((_, i) => ({\n  key: i,\n  name: `User ${i}`,\n  age: 20 + (i % 30),\n  address: `No. ${i} Park Lane`,\n  city: `City ${i}`,\n  zip: `${10000 + i}`,\n  country: `Country ${i % 5}`,\n  phone: `+1-555-${String(i).padStart(4, '0')}`,\n  email: `user${i}@example.com`\n}))\n\nconst fewRows: RowData[] = manyRows.slice(0, 3)\nconst emptyData: RowData[] = []\n</script>\n\n<template>\n  <n-space vertical size=\"large\">\n    <n-h3>一、仅 scroll-x</n-h3>\n\n    <n-card title=\"1. scroll-x + 多数据\">\n      <n-data-table\n        :columns=\"columns\"\n        :data=\"manyRows\"\n        :scroll-x=\"1800\"\n        :pagination=\"{ pageSize: 5 }\"\n      />\n    </n-card>\n\n    <n-card title=\"2. scroll-x + 少量数据\">\n      <n-data-table :columns=\"columns\" :data=\"fewRows\" :scroll-x=\"1800\" />\n    </n-card>\n\n    <n-card title=\"3. scroll-x + 无数据\">\n      <n-data-table :columns=\"columns\" :data=\"emptyData\" :scroll-x=\"1800\" />\n    </n-card>\n\n    <n-h3>二、max-height + scroll-x</n-h3>\n\n    <n-card title=\"4. max-height + scroll-x + 多数据（纵向+横向滚动条）\">\n      <n-data-table\n        :columns=\"columns\"\n        :data=\"manyRows\"\n        :scroll-x=\"1800\"\n        :max-height=\"200\"\n      />\n    </n-card>\n\n    <n-card title=\"5. max-height + scroll-x + 少量数据（不超 max-height）\">\n      <n-data-table\n        :columns=\"columns\"\n        :data=\"fewRows\"\n        :scroll-x=\"1800\"\n        :max-height=\"300\"\n      />\n    </n-card>\n\n    <n-card title=\"6. max-height + scroll-x + 无数据\">\n      <n-data-table\n        :columns=\"columns\"\n        :data=\"emptyData\"\n        :scroll-x=\"1800\"\n        :max-height=\"300\"\n      />\n    </n-card>\n\n    <n-card title=\"7. max-height（无 scroll-x）+ 多数据\">\n      <n-data-table :columns=\"columns\" :data=\"manyRows\" :max-height=\"200\" />\n    </n-card>\n\n    <n-card title=\"8. max-height（无 scroll-x）+ 无数据\">\n      <n-data-table :columns=\"columns\" :data=\"emptyData\" :max-height=\"300\" />\n    </n-card>\n\n    <n-h3>三、flex-height + scroll-x</n-h3>\n\n    <n-card title=\"9. flex-height + scroll-x + 多数据（纵向+横向滚动条）\">\n      <n-data-table\n        :columns=\"columns\"\n        :data=\"manyRows\"\n        :scroll-x=\"1800\"\n        flex-height\n        style=\"height: 250px\"\n      />\n    </n-card>\n\n    <n-card title=\"10. flex-height + scroll-x + 少量数据\">\n      <n-data-table\n        :columns=\"columns\"\n        :data=\"fewRows\"\n        :scroll-x=\"1800\"\n        flex-height\n        style=\"height: 300px\"\n      />\n    </n-card>\n\n    <n-card title=\"11. flex-height + scroll-x + 无数据\">\n      <n-data-table\n        :columns=\"columns\"\n        :data=\"emptyData\"\n        :scroll-x=\"1800\"\n        flex-height\n        style=\"height: 300px\"\n      />\n    </n-card>\n\n    <n-card title=\"12. flex-height（无 scroll-x）+ 多数据\">\n      <n-data-table\n        :columns=\"columns\"\n        :data=\"manyRows\"\n        flex-height\n        style=\"height: 250px\"\n      />\n    </n-card>\n\n    <n-card title=\"13. flex-height（无 scroll-x）+ 无数据\">\n      <n-data-table\n        :columns=\"columns\"\n        :data=\"emptyData\"\n        flex-height\n        style=\"height: 300px\"\n      />\n    </n-card>\n\n    <n-h3>四、fixed columns + scroll-x</n-h3>\n\n    <n-card title=\"14. fixed columns + scroll-x + 多数据\">\n      <n-data-table\n        :columns=\"columns\"\n        :data=\"manyRows\"\n        :scroll-x=\"1800\"\n        :max-height=\"200\"\n      />\n    </n-card>\n\n    <n-card title=\"15. fixed columns + scroll-x + 无数据\">\n      <n-data-table\n        :columns=\"columns\"\n        :data=\"emptyData\"\n        :scroll-x=\"1800\"\n        :max-height=\"300\"\n      />\n    </n-card>\n\n    <n-card title=\"16. fixed columns + flex-height + scroll-x + 无数据\">\n      <n-data-table\n        :columns=\"columns\"\n        :data=\"emptyData\"\n        :scroll-x=\"1800\"\n        flex-height\n        style=\"height: 300px\"\n      />\n    </n-card>\n\n    <n-h3>五、min-height + scroll-x</n-h3>\n\n    <n-card title=\"17. min-height + max-height + scroll-x + 无数据\">\n      <n-data-table\n        :columns=\"columns\"\n        :data=\"emptyData\"\n        :scroll-x=\"1800\"\n        :max-height=\"400\"\n        :min-height=\"150\"\n      />\n    </n-card>\n\n    <n-card title=\"18. min-height + max-height + scroll-x + 少量数据\">\n      <n-data-table\n        :columns=\"columns\"\n        :data=\"fewRows\"\n        :scroll-x=\"1800\"\n        :max-height=\"400\"\n        :min-height=\"150\"\n      />\n    </n-card>\n\n    <n-h3>六、无 scroll-x 基准对照</n-h3>\n\n    <n-card title=\"19. 无 scroll-x + 有数据（基准）\">\n      <n-data-table :columns=\"columns\" :data=\"fewRows\" />\n    </n-card>\n\n    <n-card title=\"20. 无 scroll-x + 无数据（基准）\">\n      <n-data-table :columns=\"columns\" :data=\"emptyData\" />\n    </n-card>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/data-table/demos/zhCN/empty.demo.vue",
    "content": "<markdown>\n# 空表格\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nfunction createColumns() {\n  return [\n    {\n      title: 'Name',\n      key: 'name'\n    },\n    {\n      title: 'Age',\n      key: 'age'\n    },\n    {\n      title: 'Address',\n      key: 'address'\n    },\n    {\n      title: 'Tags',\n      key: 'tags'\n    },\n    {\n      title: 'Action',\n      key: 'actions'\n    }\n  ]\n}\n\nconst data = ref([])\nconst columns = createColumns()\n</script>\n\n<template>\n  <n-data-table :columns=\"columns\" :data=\"data\" />\n</template>\n"
  },
  {
    "path": "src/data-table/demos/zhCN/expand.demo.vue",
    "content": "<markdown>\n# 可展开\n\n注意：展开行不计入 `render` 的 `index` 内\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { DataTableColumns } from 'naive-ui'\nimport { NButton, NTag, useMessage } from 'naive-ui'\nimport { h } from 'vue'\n\ninterface RowData {\n  key: number\n  name: string\n  age: number\n  address: string\n  tags: string[]\n}\n\nfunction createColumns({\n  sendMail\n}: {\n  sendMail: (rowData: RowData) => void\n}): DataTableColumns<RowData> {\n  return [\n    {\n      type: 'selection'\n    },\n    {\n      type: 'expand',\n      expandable: rowData => rowData.name !== 'Jim Green',\n      renderExpand: (rowData) => {\n        return `${rowData.name} is a good guy.`\n      }\n    },\n    {\n      title: '#',\n      key: 'key',\n      render: (_, index) => {\n        return `${index + 1}`\n      }\n    },\n    {\n      title: 'Name',\n      key: 'name'\n    },\n    {\n      title: 'Age',\n      key: 'age'\n    },\n    {\n      title: 'Address',\n      key: 'address'\n    },\n    {\n      title: 'Tags',\n      key: 'tags',\n      render(row) {\n        const tags = row.tags.map((tagKey) => {\n          return h(\n            NTag,\n            {\n              style: {\n                marginRight: '6px'\n              },\n              type: 'info',\n              bordered: false\n            },\n            {\n              default: () => tagKey\n            }\n          )\n        })\n        return tags\n      }\n    },\n    {\n      title: 'Action',\n      key: 'actions',\n      render(row) {\n        return h(\n          NButton,\n          {\n            size: 'small',\n            onClick: () => sendMail(row)\n          },\n          { default: () => 'Send Email' }\n        )\n      }\n    }\n  ]\n}\n\nfunction createData(): RowData[] {\n  return [\n    {\n      key: 0,\n      name: 'John Brown',\n      age: 32,\n      address: 'New York No. 1 Lake Park',\n      tags: ['nice', 'developer']\n    },\n    {\n      key: 1,\n      name: 'Jim Green',\n      age: 42,\n      address: 'London No. 1 Lake Park',\n      tags: ['wow']\n    },\n    {\n      key: 2,\n      name: 'Joe Black',\n      age: 32,\n      address: 'Sidney No. 1 Lake Park',\n      tags: ['cool', 'teacher']\n    }\n  ]\n}\n\nconst message = useMessage()\nconst data = createData()\nconst columns = createColumns({\n  sendMail(rowData) {\n    message.info(`send mail to ${rowData.name}`)\n  }\n})\nconst pagination = {\n  pageSize: 10\n}\n</script>\n\n<template>\n  <n-data-table\n    :columns=\"columns\"\n    :data=\"data\"\n    :pagination=\"pagination\"\n    default-expand-all\n  />\n</template>\n"
  },
  {
    "path": "src/data-table/demos/zhCN/expandable-debug.demo.vue",
    "content": "<markdown>\n# Expandable debug\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { DataTableColumn } from 'naive-ui'\nimport { NButton, NDataTable } from 'naive-ui'\nimport { h, ref } from 'vue'\n\nexport interface RowData {\n  key: number\n  name: string\n  age: number\n  address: string\n  show?: number\n}\n\nexport type RowData1 = RowData & {\n  data: RowData[]\n}\n\nconst data = ref<RowData1[]>([\n  {\n    key: 0,\n    name: 'John Brown',\n    age: 32,\n    address: 'New York No. 1 Lake Park',\n    data: [\n      {\n        key: 0,\n        name: 'John Brown',\n        age: 32,\n        address: 'New York No. 1 Lake Park',\n        show: 0\n      },\n      {\n        key: 1,\n        name: 'Jim Green',\n        age: 42,\n        address: 'London No. 1 Lake Park',\n        show: 0\n      },\n      {\n        key: 2,\n        name: 'Joe Black',\n        age: 32,\n        address: 'Sidney No. 1 Lake Park',\n        show: 0\n      }\n    ]\n  },\n  {\n    key: 1,\n    name: 'Jim Green',\n    age: 42,\n    address: 'London No. 1 Lake Park',\n    data: []\n  },\n  {\n    key: 2,\n    name: 'Joe Black',\n    age: 32,\n    address: 'Sidney No. 1 Lake Park',\n    data: []\n  }\n])\n\nfunction handleDelete(key: number) {\n  data.value[0].data[key].show = -1\n}\n\nconst dataColumns: DataTableColumn<RowData>[] = [\n  {\n    title: 'Name',\n    key: 'name'\n  },\n  {\n    title: 'Age',\n    key: 'age'\n  },\n  {\n    title: 'Address',\n    key: 'address'\n  },\n  {\n    title: 'Operation',\n    key: 'operation',\n    render(rowData) {\n      return h(\n        NButton,\n        {\n          text: true,\n          onClick: () => handleDelete(rowData.key)\n        },\n        { default: () => 'Delete' }\n      )\n    }\n  }\n]\n\nconst columns1: DataTableColumn<RowData1>[] = [\n  {\n    type: 'expand',\n    expandable: (rowData) => {\n      return rowData.data.filter(item => item.show !== -1).length > 0\n    },\n    renderExpand: (rowData) => {\n      if (rowData.data.filter(item => item.show !== -1).length > 0) {\n        return h(NDataTable, {\n          data: rowData.data.filter(item => item.show !== -1),\n          index: rowData.key,\n          columns: dataColumns\n        })\n      }\n      return undefined\n    }\n  },\n  {\n    title: 'Name',\n    key: 'name'\n  },\n  {\n    title: 'Age',\n    key: 'age'\n  },\n  {\n    title: 'Address',\n    key: 'address'\n  }\n]\n</script>\n\n<template>\n  <NDataTable :columns=\"columns1\" :data=\"data\" default-expand-all />\n</template>\n"
  },
  {
    "path": "src/data-table/demos/zhCN/export-csv.demo.vue",
    "content": "<markdown>\n# 导出 CSV\n\n你可以用 `downloadCsv` 方法导出表格数据为 CSV 文件。\n\n如果默认的 CSV 生成逻辑不能满足你的需求，例如 `title` 使用了渲染函数，或者需要调整每个单元格的数据格式，你可以用 `get-csv-header` 和 `get-csv-cell` 属性自定义导出的表头和单元格。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type {\n  DataTableColumns,\n  DataTableGetCsvCell,\n  DataTableGetCsvHeader,\n  DataTableInst,\n  DataTableRowData\n} from 'naive-ui'\nimport { h, ref } from 'vue'\n\ninterface Song {\n  key: number\n  name: string\n  age: number\n  address: string\n}\n\nconst columns: DataTableColumns<DataTableRowData> = [\n  {\n    title: 'Name',\n    key: 'name',\n    sorter: 'default',\n    render(rowData) {\n      return h('span', { style: { color: 'blue' } }, rowData.name)\n    }\n  },\n  {\n    title: () => h('span', { style: { color: 'red' } }, 'Age'),\n    key: 'age',\n    sorter: (row1: object, row2: object) =>\n      (row1 as Song).age - (row2 as Song).age\n  },\n  {\n    title: 'Address',\n    key: 'address',\n    filterOptions: [\n      {\n        label: 'London',\n        value: 'London'\n      },\n      {\n        label: 'New York',\n        value: 'New York'\n      }\n    ],\n    filter: (value: string | number, row: object) => {\n      return !!~(row as Song).address.indexOf(value as string)\n    }\n  }\n]\n\nconst data: Song[] = [\n  {\n    key: 0,\n    name: 'John Brown',\n    age: 18,\n    address: 'New York No. 1 Lake Park'\n  },\n  {\n    key: 1,\n    name: 'Jim Green',\n    age: 28,\n    address: 'London No. 1 Lake Park'\n  },\n  {\n    key: 2,\n    name: 'Joe Black',\n    age: 38,\n    address: 'Sidney No. 1 Lake Park'\n  },\n  {\n    key: 3,\n    name: 'Jim Red',\n    age: 48,\n    address: 'London No. 2 Lake Park'\n  }\n]\n\nconst tableRef = ref<DataTableInst>()\n\nfunction downloadCsv() {\n  return tableRef.value?.downloadCsv({ fileName: 'data-table' })\n}\n\nfunction exportSorterAndFilterCsv() {\n  return tableRef.value?.downloadCsv({\n    fileName: 'sorter-filter',\n    keepOriginalData: false\n  })\n}\n\nconst getCsvCell: DataTableGetCsvCell = (value, _, column) => {\n  if (column.key === 'age') {\n    return `${value} years old`\n  }\n  return value\n}\n\nconst getCsvHeader: DataTableGetCsvHeader = (col) => {\n  if (typeof col.title === 'function') {\n    return col.key === 'age' ? 'Age' : 'Unknown'\n  }\n  else {\n    return col.title || 'Unknown'\n  }\n}\n\nconst pagination = false as const\n</script>\n\n<template>\n  <n-space vertical :size=\"12\">\n    <n-space>\n      <n-button @click=\"downloadCsv\">\n        导出 CSV（原始数据）\n      </n-button>\n      <n-button @click=\"exportSorterAndFilterCsv\">\n        导出 CSV（展示的数据）\n      </n-button>\n    </n-space>\n    <n-data-table\n      ref=\"tableRef\"\n      :columns=\"columns\"\n      :data=\"data\"\n      :pagination=\"pagination\"\n      :bordered=\"false\"\n      :get-csv-cell=\"getCsvCell\"\n      :get-csv-header=\"getCsvHeader\"\n    />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/data-table/demos/zhCN/filter-and-sorter.demo.vue",
    "content": "<markdown>\n  # 非受控过滤 & 排序\n  </markdown>\n\n<script lang=\"ts\">\nimport type { DataTableColumns, DataTableInst } from 'naive-ui'\nimport { defineComponent, ref } from 'vue'\n\ninterface RowData {\n  key: number\n  name: string\n  age: number\n  address: string\n}\n\nconst columns: DataTableColumns<RowData> = [\n  {\n    title: 'Name',\n    key: 'name',\n    defaultSortOrder: 'ascend',\n    sorter: 'default'\n  },\n  {\n    title: 'Age',\n    key: 'age',\n    sorter: (row1, row2) => row1.age - row2.age\n  },\n  {\n    title: 'Address',\n    key: 'address',\n    defaultFilterOptionValues: ['London', 'New York'],\n    filterOptions: [\n      {\n        label: 'London',\n        value: 'London'\n      },\n      {\n        label: 'New York',\n        value: 'New York'\n      }\n    ],\n    filter(value, row) {\n      return Boolean(~row.address.indexOf(value as string))\n    }\n  }\n]\n\nconst data = [\n  {\n    key: 0,\n    name: 'John Brown',\n    age: 32,\n    address: 'New York No. 1 Lake Park'\n  },\n  {\n    key: 1,\n    name: 'Jim Green',\n    age: 42,\n    address: 'London No. 1 Lake Park'\n  },\n  {\n    key: 2,\n    name: 'Joe Black',\n    age: 32,\n    address: 'Sidney No. 1 Lake Park'\n  },\n  {\n    key: 3,\n    name: 'Jim Red',\n    age: 32,\n    address: 'London No. 2 Lake Park'\n  }\n]\n\nexport default defineComponent({\n  setup() {\n    const tableRef = ref<DataTableInst | null>(null)\n\n    return {\n      table: tableRef,\n      data,\n      columns,\n      pagination: { pageSize: 5 },\n      filterAddress() {\n        tableRef.value?.filter({\n          address: ['London']\n        })\n      },\n      sortName() {\n        tableRef.value?.sort('name', 'ascend')\n      },\n      clearFilters() {\n        tableRef.value?.filter(null)\n      },\n      clearSorter() {\n        tableRef.value?.clearSorter()\n      }\n    }\n  }\n})\n</script>\n\n<template>\n  <n-space vertical :size=\"12\">\n    <n-space>\n      <n-button @click=\"sortName\">\n        Sort By Name (Ascend)\n      </n-button>\n      <n-button @click=\"filterAddress\">\n        Filter Address (London)\n      </n-button>\n      <n-button @click=\"clearFilters\">\n        Clear Filters\n      </n-button>\n      <n-button @click=\"clearSorter\">\n        Clear Sorter\n      </n-button>\n    </n-space>\n    <n-data-table\n      ref=\"table\"\n      :columns=\"columns\"\n      :data=\"data\"\n      :pagination=\"pagination\"\n    />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/data-table/demos/zhCN/fixed-column-debug.demo.vue",
    "content": "<markdown>\n  # Debug\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nfunction createCols(): any {\n  return [\n    {\n      title: 'Name',\n      key: 'name',\n      fixed: 'left',\n      children: [\n        {\n          title: '1',\n          key: '1',\n          fixed: 'left',\n          width: 100\n        },\n        {\n          title: '2',\n          key: '2',\n          fixed: 'left',\n          width: 100\n        },\n        {\n          title: '3',\n          key: '3',\n          fixed: 'left',\n          width: 100\n        },\n        {\n          title: '4',\n          key: '4',\n          fixed: 'left',\n          width: 100\n        },\n        {\n          title: '5',\n          key: '5',\n          fixed: 'left',\n          width: 100\n        },\n        {\n          title: '6',\n          key: '6',\n          fixed: 'left',\n          width: 100\n        }\n      ]\n    },\n    { title: 'Name2', key: 'name1', fixed: 'left', width: 100 },\n    { title: 'Name3', key: 'name2', fixed: 'left', width: 100 },\n    {\n      title: 'Attrs',\n      key: 'attrs',\n      children: [\n        {\n          title: 'Attack',\n          key: 'attack',\n          children: [\n            {\n              title: 'Physics Attack',\n              key: 'physicsAttack'\n            },\n            {\n              title: 'Magic Attack',\n              key: 'magicAttack'\n            }\n          ]\n        },\n        {\n          title: 'Defend',\n          key: 'defend'\n        },\n        {\n          title: 'Speed',\n          key: 'speed'\n        },\n        {\n          title: 'Defend1',\n          key: 'defend1'\n        },\n        {\n          title: 'Speed2',\n          key: 'speed2'\n        }\n      ]\n    }\n  ]\n}\n\nfunction createData() {\n  return Array.from({ length: 50 })\n    .fill(null)\n    .map((_, i) => {\n      return {\n        key: i,\n        name: `name_${i}`,\n        physicsAttack: `physicsAttack_${i}`,\n        magicAttack: `magicAttack_${i}`,\n        defend: `defend_${i}`,\n        speed: `speed_${i}`\n      }\n    })\n}\n\nconst data = ref(createData())\nconst columns = ref(createCols())\nconst pagination = ref({\n  pageSize: 10\n})\n</script>\n\n<template>\n  <n-data-table\n    bordered\n    :scroll-x=\"2000\"\n    :max-height=\"200\"\n    :data=\"data\"\n    :columns=\"columns\"\n    :single-line=\"false\"\n    :pagination=\"pagination\"\n  />\n</template>\n"
  },
  {
    "path": "src/data-table/demos/zhCN/fixed-column2-debug.demo.vue",
    "content": "<markdown>\n  # Debug\n</markdown>\n\n<script lang=\"ts\" setup>\nfunction createColumns(): any {\n  return [\n    {\n      title: '1',\n      key: '1',\n      fixed: 'left',\n      align: 'center',\n      children: [\n        {\n          title: '2',\n          key: '2',\n          fixed: 'left',\n          align: 'center',\n          children: [\n            {\n              title: '4',\n              key: '4',\n              fixed: 'left',\n              width: 100,\n              align: 'center'\n            },\n            {\n              title: '5',\n              key: '5',\n              fixed: 'left',\n              width: 100,\n              align: 'center'\n            }\n          ]\n        },\n        {\n          title: '3',\n          key: '3',\n          fixed: 'left',\n          width: 100,\n          align: 'center',\n          children: [\n            {\n              title: '6',\n              key: '6',\n              fixed: 'left',\n              width: 100,\n              align: 'center'\n            },\n            {\n              title: '7',\n              key: '7',\n              fixed: 'left',\n              width: 100,\n              align: 'center'\n            }\n          ]\n        }\n      ]\n    },\n    { title: 'Test1', key: 'test1' },\n    { title: 'Test2', key: 'test2' },\n    { title: 'Test3', key: 'test3' },\n    {\n      title: 'Group A',\n      key: 'ga',\n      fixed: 'right',\n      align: 'center',\n      children: [\n        {\n          title: 'A1',\n          key: 'a1',\n          width: 100,\n          fixed: 'right',\n          align: 'center'\n        },\n        {\n          title: 'A2',\n          key: 'a2',\n          width: 100,\n          fixed: 'right',\n          align: 'center'\n        }\n      ]\n    },\n    {\n      title: 'Group B',\n      key: 'gb',\n      fixed: 'right',\n      align: 'center',\n      children: [\n        {\n          title: 'B1',\n          key: 'b1',\n          width: 100,\n          fixed: 'right',\n          align: 'center'\n        },\n        {\n          title: 'B2',\n          key: 'b2',\n          width: 100,\n          fixed: 'right',\n          align: 'center'\n        }\n      ]\n    }\n  ]\n}\n\nfunction createData() {\n  return [\n    {\n      4: 4,\n      5: 5,\n      6: 6,\n      7: 7,\n      test1: 'test1',\n      test2: 'test2',\n      test3: 'test3',\n      a1: 'a1',\n      a2: 'a2',\n      b1: 'b1',\n      b2: 'b2'\n    }\n  ]\n}\n\nconst data = createData()\nconst columns = createColumns()\nconst pagination = { pageSize: 10 }\n</script>\n\n<template>\n  <n-data-table\n    :columns=\"columns\"\n    :data=\"data\"\n    :pagination=\"pagination\"\n    :scroll-x=\"2000\"\n  />\n</template>\n"
  },
  {
    "path": "src/data-table/demos/zhCN/fixed-header-column.demo.vue",
    "content": "<markdown>\n# 固定头部和列\n\n注意：如果设定了固定的列，你需要同时设定 `scroll-x`。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { DataTableColumns } from 'naive-ui'\nimport { h } from 'vue'\n\ninterface RowData {\n  key: number\n  name: string\n  age: number\n  address: string\n  tags: string[]\n}\n\nfunction createColumns(): DataTableColumns<RowData> {\n  return [\n    {\n      type: 'selection',\n      fixed: 'left'\n    },\n    {\n      title: 'Name',\n      key: 'name',\n      width: 200,\n      fixed: 'left'\n    },\n    {\n      title: 'Age',\n      key: 'age',\n      width: 100,\n      fixed: 'left'\n    },\n    {\n      title: 'Row',\n      key: 'row',\n      render(row, index) {\n        return h('span', ['row ', index])\n      }\n    },\n    {\n      title: 'Row1',\n      key: 'row1',\n      render(row, index) {\n        return h('span', ['row ', index])\n      }\n    },\n    {\n      title: 'Row2',\n      key: 'row2',\n      render(row, index) {\n        return h('span', ['row ', index])\n      },\n      width: 100,\n      fixed: 'right'\n    },\n    {\n      title: 'Address',\n      key: 'address',\n      width: 200,\n      fixed: 'right'\n    }\n  ]\n}\n\nconst data = Array.from({ length: 46 }).map((_, index) => ({\n  key: index,\n  name: `Edward King ${index}`,\n  age: 32,\n  address: `London, Park Lane no. ${index}`\n}))\nconst columns = createColumns()\nconst pagination = { pageSize: 10 }\n</script>\n\n<template>\n  <n-data-table\n    :columns=\"columns\"\n    :data=\"data\"\n    :pagination=\"pagination\"\n    :max-height=\"250\"\n    :scroll-x=\"1800\"\n  />\n</template>\n"
  },
  {
    "path": "src/data-table/demos/zhCN/fixed-header.demo.vue",
    "content": "<markdown>\n# 固定头部\n\n在展示大量数据的时候通过设定 `max-height` 来固定头部、滚动数据。\n</markdown>\n\n<script lang=\"ts\" setup>\nconst columns = [\n  {\n    title: 'Name',\n    key: 'name'\n  },\n  {\n    title: 'Age',\n    key: 'age'\n  },\n  {\n    title: 'Address',\n    key: 'address'\n  }\n]\n\nconst data = Array.from({ length: 46 }).map((_, index) => ({\n  key: index,\n  name: `Edward King ${index}`,\n  age: 32,\n  address: `London, Park Lane no. ${index}`\n}))\n\nconst pagination = {\n  pageSize: 15\n}\n</script>\n\n<template>\n  <n-data-table\n    :columns=\"columns\"\n    :data=\"data\"\n    :pagination=\"pagination\"\n    :max-height=\"250\"\n  />\n</template>\n"
  },
  {
    "path": "src/data-table/demos/zhCN/flex-height.demo.vue",
    "content": "<markdown>\n# 弹性高度\n\n如果你想设定表格的整体高度，你可以在设定好表格高度的情况下设定 `flex-height` 属性。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { DataTableColumns } from 'naive-ui'\nimport { h, ref } from 'vue'\n\ninterface RowData {\n  key: number\n  name: string\n  age: number\n  address: string\n  tags: string[]\n}\n\nfunction createColumns(): DataTableColumns<RowData> {\n  return [\n    {\n      type: 'selection',\n      fixed: 'left'\n    },\n    {\n      title: 'Name',\n      key: 'name',\n      width: 200,\n      fixed: 'left'\n    },\n    {\n      title: 'Age',\n      key: 'age',\n      width: 100,\n      fixed: 'left'\n    },\n    {\n      title: 'Row',\n      key: 'row',\n      render(row, index) {\n        return h('span', ['row ', index])\n      }\n    },\n    {\n      title: 'Row1',\n      key: 'row1',\n      render(row, index) {\n        return h('span', ['row ', index])\n      }\n    },\n    {\n      title: 'Row2',\n      key: 'row2',\n      render(row, index) {\n        return h('span', ['row ', index])\n      },\n      width: 100,\n      fixed: 'right'\n    },\n    {\n      title: 'Address',\n      key: 'address',\n      width: 200,\n      fixed: 'right'\n    }\n  ]\n}\n\nconst data = Array.from({ length: 46 }).map((_, index) => ({\n  key: index,\n  name: `Edward King ${index}`,\n  age: 32,\n  address: `London, Park Lane no. ${index}`\n}))\nconst columns = createColumns()\nconst pagination = { pageSize: 10 }\nconst height = ref(200)\n</script>\n\n<template>\n  <n-space vertical>\n    <n-slider\n      v-model:value=\"height\"\n      :min=\"200\"\n      :max=\"500\"\n      :step=\"100\"\n      style=\"max-width: 180px\"\n    />\n    <n-data-table\n      :columns=\"columns\"\n      :data=\"data\"\n      :pagination=\"pagination\"\n      :scroll-x=\"1800\"\n      :style=\"{ height: `${height}px` }\"\n      flex-height\n    />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/data-table/demos/zhCN/group-header.demo.vue",
    "content": "<markdown>\n# 表头分组\n\n注意：如果你希望分组的表头拥有固定列的效果，你需要给所有固定列表头都设定好宽度，包括所有的父级节点，否则可能产生错位。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nfunction createCols() {\n  return [\n    {\n      title: 'Name',\n      key: 'name'\n    },\n    {\n      title: 'Attrs',\n      key: 'attrs',\n      children: [\n        {\n          title: 'Attack',\n          key: 'attack',\n          children: [\n            {\n              title: 'Physics Attack',\n              key: 'physicsAttack'\n            },\n            {\n              title: 'Magic Attack',\n              key: 'magicAttack'\n            }\n          ]\n        },\n        {\n          title: 'Defend',\n          key: 'defend'\n        },\n        {\n          title: 'Speed',\n          key: 'speed'\n        }\n      ]\n    }\n  ]\n}\n\nfunction createData() {\n  return Array.from({ length: 50 }).map((_, i) => {\n    return {\n      key: i,\n      name: `name_${i}`,\n      physicsAttack: `physicsAttack_${i}`,\n      magicAttack: `magicAttack_${i}`,\n      defend: `defend_${i}`,\n      speed: `speed_${i}`\n    }\n  })\n}\n\nconst data = ref(createData())\nconst columns = ref(createCols())\nconst pagination = ref({\n  pageSize: 10\n})\n</script>\n\n<template>\n  <n-data-table\n    :data=\"data\"\n    :columns=\"columns\"\n    :single-line=\"false\"\n    :pagination=\"pagination\"\n  />\n</template>\n"
  },
  {
    "path": "src/data-table/demos/zhCN/height-debug.demo.vue",
    "content": "<markdown>\n# 自定义渲染列头\n</markdown>\n\n<script lang=\"ts\">\nimport type { DataTableBaseColumn, DataTableColumns } from 'naive-ui'\nimport type { ComponentInternalInstance, VNode, VNodeChild } from 'vue'\nimport { NGradientText, NTooltip } from 'naive-ui'\nimport { defineComponent, getCurrentInstance, h } from 'vue'\n\ninterface RowData extends Record<string, unknown> {\n  key: number\n  name: string\n  age: number\n  address: string\n}\n\nfunction renderTooltip(trigger: VNode, content: string): VNodeChild {\n  return h(NTooltip, null, {\n    trigger: () => trigger,\n    default: () => content\n  })\n}\n\nfunction createColumns(\n  _instance: ComponentInternalInstance | null\n): DataTableColumns<RowData> {\n  return [\n    {\n      key: 'name',\n      title(_column: DataTableBaseColumn<RowData>) {\n        return renderTooltip(\n          h(\n            NGradientText,\n            {\n              size: 24,\n              type: 'danger'\n            },\n            { default: () => 'Name' }\n          ),\n          'Tooltip Content'\n        )\n      }\n    },\n    {\n      key: 'age',\n      title(_column: DataTableBaseColumn<RowData>) {\n        return h(\n          NGradientText,\n          {\n            size: '20',\n            type: 'info'\n          },\n          { default: () => 'Age' }\n        )\n      }\n    },\n    {\n      key: 'address',\n      title(_column: DataTableBaseColumn<RowData>) {\n        return h(\n          NGradientText,\n          {\n            size: '16',\n            type: 'warning'\n          },\n          { default: () => 'Address' }\n        )\n      }\n    }\n  ]\n}\n\nconst data = [\n  {\n    key: 0,\n    name: 'John Brown',\n    age: 32,\n    address: 'New York No. 1 Lake Park'\n  },\n  {\n    key: 1,\n    name: 'Jim Green',\n    age: 42,\n    address: 'London No. 1 Lake Park'\n  },\n  {\n    key: 2,\n    name: 'Joe Black',\n    age: 32,\n    address: 'Sidney No. 1 Lake Park'\n  }\n]\n\nexport default defineComponent({\n  setup() {\n    const instance = getCurrentInstance()\n    return {\n      data,\n      columns: createColumns(instance),\n      pagination: {\n        pageSize: 10\n      }\n    }\n  }\n})\n</script>\n\n<template>\n  <n-data-table :columns=\"columns\" :data=\"data\" :pagination=\"pagination\" />\n</template>\n"
  },
  {
    "path": "src/data-table/demos/zhCN/index.demo-entry.md",
    "content": "# 数据表格 Data Table\n\n<!--single-column-->\n\n数据表格用来显示一些格式化信息。\n\n<n-alert type=\"warning\" title=\"注意\" style=\"margin-bottom: 16px;\" :bordered=\"false\">\n  <n-ul align-text>\n    <li>\n      传入 <n-text code>data</n-text> 属性的数组的每一项都代表渲染的一行数据，每一行数据都要有唯一的 <n-text code>key</n-text>，否则需要在 table 上声明 <n-text code>row-key</n-text> 属性。\n    </li>\n    <li>\n      在非异步状况下，总页数 <n-text code>page-count</n-text> 是由数据的数量决定的，即使传入 <n-text code>page-count</n-text> 也不会生效，如果你希望指定总页数，需要设定 <n-text code>remote</n-text> 属性。\n    </li>\n    <li>\n    如果你想使用服务端返回的数据进行展示，分页，过滤，排序等，请参考<n-a href=\"#ajax-usage\">异步</n-a>。\n    </li>\n  </n-ul>\n</n-alert>\n\n## 演示\n\n```demo\nsummary-debug.vue\ndebug.vue\nbasic.vue\nempty.vue\nborder.vue\nsize.vue\nrow-props.vue\nmerge-cell.vue\nfilter-and-sorter.vue\npagination-behavior-on-filter.vue\nmultiple-sorter.vue\ncustom-sorter.vue\ncolumn-draggable.vue\nselect.vue\nselect-single.vue\ncustom-select.vue\ngroup-header.vue\ncontrolled-page.vue\ncontrolled-filter.vue\ncontrolled-sorter.vue\ncontrolled-multiple-sorter.vue\nfixed-header.vue\nfixed-header-column.vue\nsummary.vue\nellipsis.vue\nellipsis-tooltip.vue\nexpand.vue\nrender-header.vue\ncustom-style.vue\najax-usage.vue\nvirtual.vue\nvirtual-x.vue\ncustom-filter-menu.vue\ntree.vue\nflex-height.vue\nstriped.vue\nsimple-editable.vue\nswitchable-editable.vue\ncontext-menu.vue\nasync-expand.vue\nrender-cell.vue\nexport-csv.vue\nfixed-column-debug.vue\nfixed-column2-debug.vue\nscroll-debug.vue\nheight-debug.vue\nkeep-alive-debug.vue\nellipsis-debug.vue\ncustom-expand-icon-debug.vue\nexpandable-debug.vue\nrtl-debug.vue\n```\n\n## API\n\n### DataTable Props\n\n| 名称 | 类型 | 默认值 | 说明 | 版本 |\n| --- | --- | --- | --- | --- |\n| allow-checking-not-loaded | `boolean` | `false` | 是否允许级联勾选还没有完全加载的节点。如果你要用这个属性，请记住 `checked-row-keys` 可能是不完整的 | 2.28.0 |\n| bordered | `boolean` | `true` | 是否显示 border |  |\n| bottom-bordered | `boolean` | `true` | 是否显示 bottom border |  |\n| checked-row-keys | `Array<string \\| number>` | `undefined` | 被选中的行的 key |  |\n| cascade | `boolean` | `true` | 在进行树型数据选择的时候是否级联 |  |\n| children-key | `string` | `'children'` | 树形数据下后代节点在数据中的 key |  |\n| columns | `Array<DataTableColumn>` | `[]` | 需要展示的列 |  |\n| data | `Array<object>` | `[]` | 需要展示的数据 |  |\n| default-checked-row-keys | `Array<string \\| number>` | `[]` | 默认选中的 key 值 |  |\n| default-expanded-row-keys | `Array<string \\| number>` | `[]` | 默认展开行的 key 值 |  |\n| default-expand-all | `boolean` | `false` | 是否默认展开全部可展开的行，不可在异步展开行时使用 | 2.30.4 |\n| expanded-row-keys | `Array<string \\| number>` | `undefined` | 展开行的 key 值 |  |\n| filter-icon-popover-props | `PopoverProps` | `{ trigger: click, placement: bottom }` | 过滤按钮的 Popover 属性，属性参考 [Popover props](popover#Popover-Props) | 2.39.0 |\n| flex-height | `boolean` | `false` | 是否让表格主体的高度自动适应整个表格区域的高度，打开这个选项会让 `table-layout` 始终为 `'fixed'` |  |\n| get-csv-cell | `(value: any, row: object, col: DataTableBaseColumn) => string` | `undefined` | 获取 CSV 的单元格数据 | 2.40.2 |\n| get-csv-header | `(cols: Array<DataTableColumn>) => string` | `undefined` | 获取 CSV 的 header | 2.40.2 |\n| header-height | `number` | `28` | 在开启 `virtual-scroll-header` 属性的情况下，表头的高度 | 2.40.0 |\n| height-for-row | `(rowData: object, index: number) => number` | `undefined` | 每行高度的配置函数，必须配合 `virtual-scroll-x` 使用，如果不进行配置，每一行的高度会被设为 `min-row-height` | 2.40.0 |\n| indent | `number` | `16` | 使用树形数据时行内容的缩进 |  |\n| loading | `boolean` | `false` | 是否显示 loading 状态 |  |\n| max-height | `number \\| string` | `undefined` | 表格内容的最大高度，可以是 CSS 属性值 |  |\n| min-height | `number \\| string` | `undefined` | 表格内容的最低高度，可以是 CSS 属性值 |  |\n| min-row-height | `number` | `28` | 在开启 `virtual-scroll` 或 `virtual-scroll-x` 的情况下，每一行的最小高度，所有的行的高度必须比这个值更大 | 2.40.0 |\n| paginate-single-page | `boolean` | `true` | 当表格数据只有一页时是否显示分页面 | 2.28.0 |\n| pagination | `false \\| object` | `false` | 属性参考 [Pagination props](pagination#Pagination-Props) |  |\n| pagination-behavior-on-filter | `'first' \\| 'current'` | `'current'` | 过滤操作后页面的状态，`'first'` 为回到首页，`'current'` 为停留在当前页 | 2.28.3 |\n| remote | `boolean` | `false` | 表格是否自动分页数据，在异步的状况下你可能需要把它设为 `true` |  |\n| render-cell | `(value: any, rowData: object, column: DataTableBaseColumn) => VNodeChild` | `undefined` | 自定义单元格渲染，优先级低于列的 `render` | 2.30.5 |\n| render-expand-icon | `({ expanded, rowData }: { expanded: boolean, rowData: object }) => VNodeChild` | `undefined` | 自定义渲染展开图标 | 2.32.2, `expanded`: 2.34.4, `rowData`: `2.40.0` |\n| row-class-name | `string \\| (rowData: object, index : number) => string` | `undefined` | 每一行上的类名 |  |\n| row-key | `(rowData: object) => (number \\| string)` | `undefined` | 通过行数据创建行的 key（如果你不想给每一行加上 key） |  |\n| row-props | `(rowData: object, rowIndex : number) => HTMLAttributes` | `undefined` | 自定义行属性 |  |\n| scroll-x | `number \\| string` | `undefined` | 表格内容的横向宽度，如果列被水平固定了，则需要设定它 |  |\n| scrollbar-props | `ScrollbarProps` | `undefined` | 属性参考 [Scrollbar props](scrollbar#Scrollbar-Props)，`DataTable` 中已存在 `on-scroll` 属性，此处 `on-scroll` 属性不生效 |  |\n| single-column | `boolean` | `false` | 是否不设定行的分割线，当参数为`true`时，则单元格没有下边线 |  |\n| single-line | `boolean` | `true` | 是否不设定列的分割线，当参数值为 `true` 时，则单元格没有右边线 |  |\n| size | `'small' \\| 'medium' \\| 'large'` | `'medium'` | 表格的尺寸 |  |\n| spin-props | `{ strokeWidth?: number, stroke?: string, scale?: number, radius?: number }` | `undefined` | 表格 spin 的属性 | 2.34.0 |\n| sticky-expanded-rows | `boolean` | `false` | 展开行是否不随表格横向滚动 | 2.32.2 |\n| striped | `boolean` | `false` | 是否使用斑马线条纹 |  |\n| summary | `DataTableCreateSummary` | `undefined` | 表格总结栏的数据，类型见 <n-a href=\"#DataTableCreateSummary-Type\">DataTableCreateSummary Type</n-a> |  |\n| summary-placement | `'top' \\| 'bottom'` | `'bottom'` | 总结栏的位置 | 2.33.3 |\n| table-layout | `'auto' \\| 'fixed'` | `'auto'` | 表格的 `table-layout` 样式属性，在设定 `ellipsis` 或 `max-height` 的情况下固定为 `'fixed'` |  |\n| virtual-scroll | `boolean` | `false` | 是否开启虚拟滚动，应对大规模数据，开启前请设定好 `max-height`。当 `virtual-scroll` 为 `true` 时，`rowSpan` 将不生效 |  |\n| virtual-scroll-header | `boolean` | `false` | 是否打开表头的虚拟滚动，如果横向列太多，可以考虑打开此属性，打开此属性会导致表头单元格跨行列的功能不可用，同时必须要配置 `header-height` | 2.40.0 |\n| virtual-scroll-x | `boolean` | `false` | 是否打开表主体的横向虚拟滚动，如果横向列太多，可以考虑打开此属性，打开此属性会导致单元格跨行列的功能不可用，此属性开启时，必须要和 `virtual-scroll`、`scroll-x`、`min-row-height`、`height-for-row`、`virtual-scroll-header`、`header-height` 属性配合使用，同时每一列必须都配置 `width` 属性，你可以参考 <n-a href=\"#virtual-x.vue\">完整的例子</n-a> | 2.40.0 |\n| on-load | `(rowData: object) => Promise<void>` | `undefined` | 异步展开树形数据的回调 | 2.27.0 |\n| on-scroll | `(e: Event) => void` | `undefined` | 表格主体滚动的回调 | 2.29.1 |\n| on-update:checked-row-keys | `(keys: Array<string \\| number>, rows: object[], meta: { row: object \\| undefined, action: 'check' \\| 'uncheck' \\| 'checkAll' \\| 'uncheckAll' }) => void` | `undefined` | checked-row-keys 值改变时触发的回调函数 | `rows` 2.30.5, `meta` 2.33.4 |\n| on-update:expanded-row-keys | `(keys: Array<string \\| number>) => void` | `undefined` | expanded-row-keys 值改变时触发的回调函数 |  |\n| on-update:filters | `(filters: DataTableFilterState, initiatorColumn: DataTableBaseColumn)` | `undefined` | filters 数据改变时触发的回调函数 |\n| on-update:page | `(page: number)` | `undefined` | page 改变时触发的回调函数 |  |\n| on-update:page-size | `(pageSize: number) => void` | `undefined` | page-size 改变时触发的回调函数 |  |\n| on-update:sorter | `(options: DataTableSortState \\| DataTableSortState[] \\| null) => void` | `undefined` | 如果变动列为多列排序则返回 `DataTableSortState[] \\| null` 否则返回 `DataTableSortState \\| null` |  |\n\n#### DataTableColumn Properties\n\n| 名称 | 类型 | 默认值 | 说明 | 版本 |\n| --- | --- | --- | --- | --- |\n| align | `'left' \\| 'right' \\| 'center'` | `'left'` | 列内的文本排列 |  |\n| allowExport | `boolean` | `true` | 这一列是否可以导出 | 2.40.0 |\n| cellProps | `(rowData: object, rowIndex: number) => object` | `undefined` | 该列单元格的 HTML 属性 | 2.27.0 |\n| children | `DataTableColumn[]` | `undefined` | 成组列头的子节点 |  |\n| className | `string` | `undefined` | 列的类名 |  |\n| colSpan | `(rowData: object, rowIndex: number) => number` | `undefined` | 该列单元格的的 col span |  |\n| customNextSortOrder | `(order: 'descend' \\| 'ascend' \\| false) => 'descend' \\| 'ascend' \\| false` | `undefined` | 使用这个函数自定义下一个排序的状态 | 2.43.0 |\n| defaultFilterOptionValue | `string \\| number \\| null` | `null` | 非受控状态下默认的过滤器选项值（过滤器单选时生效） |  |\n| defaultFilterOptionValues | `Array<string \\| number>` | `[]` | 非受控状态下默认的过滤器选项值（过滤器多选时生效） |  |\n| defaultSortOrder | `'descend' \\| 'ascend' \\| false` | `false` | 非受控状态下表格默认的排序方式 |  |\n| disabled | `(rowData: object) => boolean` | `undefined` | 是否禁用 |  |\n| ellipsis | `boolean \\| EllipsisProps` | `false` | 文本溢出的设置 |  |\n| ellipsis-component | `'ellipsis' \\| 'performant-ellipsis'` | `'ellipsis'` | 渲染文本溢出时使用的组件，在 `ellipsis` 属性为 `EllipsisProps` 时生效。若为 `'ellipsis'` 则使用常规的 `n-ellipsis` 组件渲染，若为 `'performant-ellipsis'` 则使用 `n-performant-ellipsis` 渲染，这种情况下会有更高的渲染性能，但是每个折叠的单元格中的组件有可能被重新卸载和挂载 | 2.35.0 |\n| expandable | `(rowData: object) => boolean` | `undefined` | 行是否可展开，仅在 `type` 为 `'expand'` 时生效 |  |\n| filter | `boolean \\| (optionValue: string \\| number, rowData: object) => boolean \\| 'default'` | `undefined` | 这一列的过滤方法。如果设为 `true`，表格将只会在这列展示一个排序图标，在异步的时候可能有用。 |  |\n| filterMode | `'and' \\| 'or'` | `'or'` | 同一列筛选方式为与还是或 |  |\n| filterMultiple | `boolean` | `true` | 同一列是否可以筛选多个 |  |\n| filterOptionValue | `string \\| number \\| null` | `undefined` | 受控状态下，当前激活的过滤器选项值。如果不做设定，这一列的过滤行为将是非受控的（过滤器单选时生效） |  |\n| filterOptionValues | `Array<string \\| number> \\| null` | `undefined` | 受控状态下，当前激活的过滤器选项值数组。如果不做设定，这一列的过滤行为将是非受控的（过滤器多选时生效） |  |\n| filterOptions | `Array<{ label: string, value: string \\| number}>` | `undefined` | filter 的 options 数据 |  |\n| fixed | `'left \\| 'right' \\| false` | `false` | 该列是否需要 fixed |  |\n| key | `string \\| number` | `undefined` | 这一列的 key，不可重复。 |  |\n| maxWidth | `number \\| string` | `undefined` | 列的最大宽度，仅在 `resizable` 为 `true` 的时候生效 | 2.33.4 |\n| minWidth | `number \\| string` | `undefined` | 列的最小宽度 | 2.28.3 |\n| multiple | `boolean` | `true` | 是否开启多选，仅在 `type` 为 `'selection'` 的时候生效 | 2.31.0 |\n| options | `Array<'all' \\| 'none' \\| { label: string, key: string \\| number, onSelect: (pageData: RowData[]) => void }>` | `undefined` | 自定义选择项的选项，只对 `type='selection'` 生效 |  |\n| render | `(rowData: object, rowIndex: number) => VNodeChild` | `undefined` | 渲染函数，渲染这一列的每一行的单元格 |  |\n| renderExpand | `(rowData: object, rowIndex: number) => VNodeChild` | `undefined` | 展开区域的渲染函数，仅在 `type` 为 `'expand'` 的时候生效 |  |\n| renderFilter | `(options: { active: boolean, show: boolean }) => VNodeChild` | `undefined` | 渲染函数，渲染过滤器触发元素 |  |\n| renderFilterIcon | `(options: { active: boolean, show: boolean }) => VNodeChild` | `undefined` | 渲染函数，渲染过滤器图标 |  |\n| renderFilterMenu | `(actions: { hide: () => void }) => VNodeChild` | `undefined` | 渲染函数，渲染这一列的过滤器菜单 |  |\n| renderSorter | `(options: { order: 'descend' \\| 'ascend' \\| false }) => VNodeChild` | `undefined` | 渲染函数，渲染排序触发 | 2.24.2 |\n| renderSorterIcon | `(options: { order: 'descend' \\| 'ascend' \\| false }) => VNodeChild` | `undefined` | 渲染函数，渲染排序图标 | 2.24.2 |\n| resizable | `boolean` | `undefined` | 列宽是否可以拖动 | 2.33.4 |\n| rowSpan | `(rowData: object, rowIndex: number) => number` | `undefined` | 该列单元格的 row span |  |\n| sortOrder | `'descend' \\| 'ascend' \\| false` | `undefined` | 受控状态下表格的排序方式。如果多列都设定了有效值，那么只有第一个会生效 |  |\n| sorter | `boolean \\| function \\| 'default'` | `undefined` | 这一列的排序方法。如果设为 `'default'` 表格将会使用一个内置的排序函数；如果设为 `true`，表格将只会在这列展示一个排序图标，在异步的时候可能有用。其他情况下它工作的方式类似 `Array.sort` 的对比函数 |  |\n| title | `string \\| (() => VNodeChild)` | `undefined` | 列的 title 信息，可以是渲染函数 |  |\n| titleAlign | `'left' \\| 'right' \\| 'center'` | `'null'` | 表头列对齐方式，若不设置该项，则使用列内的文本排列 | 2.34.4 |\n| titleColSpan | `number` | `undefined` | title 列占据的列数 |  |\n| tree | `boolean` | `false` | 是否在这一列展示树形数据的展开按钮 | 2.28.3 |\n| type | `'selection' \\| 'expand'` | `undefined` | 列的类型 |  |\n| width | `number \\| string` | `undefined` | 列的宽度（在列固定时是**必需**的，并且需要为 `number` 类型） | 2.24.0（`string` 类型） |\n\n下面的类型可以直接从包中引入。\n\n#### DataTableSortState Type\n\n```ts\ninterface DataTableSortState {\n  columnKey: string | number\n  sorter: 'default' | function | boolean\n  order: 'ascend' | 'descend' | false\n}\n```\n\n#### DataTableFilterState Type\n\n```ts\ninterface DataTableFilterState {\n  [key: string]: Array<string | number> | string | number | null | undefined\n}\n```\n\n#### DataTableCreateSummary Type\n\n```ts\ntype DataTableCreateSummary = (pageData: RowData[]) =>\n  | Array<{\n    [columnKey: string]: {\n      value?: VNodeChild\n      colSpan?: number\n      rowSpan?: number\n    }\n  }>\n  | {\n    [columnKey: string]: {\n      value?: VNodeChild\n      colSpan?: number\n      rowSpan?: number\n    }\n  }\n```\n\n### DataTable Methods\n\n这些方法可以帮助你在非受控的状态下改变表格，但是，并不推荐在异步的状况下使用这些方法。如果需要异步操作，最好用**受控**的方式使用表格。\n\n| 名称 | 类型 | 说明 | 版本 |\n| --- | --- | --- | --- |\n| clearFilters | `() => void` | 清空所有的 filter 状态 |  |\n| clearSorter | `() => void` | 清空所有的 sort 状态 |  |\n| downloadCsv | `(options?: { fileName?: string, keepOriginalData?: boolean }) => void` | 下载 CSV | 2.37.0 |\n| filters | `(filters: DataTableFilterState \\| null) => void` | 设定表格当前的过滤器 |  |\n| page | `(page: number) => void` | 手动设置 page |  |\n| scrollTo | `(options: { left?: number, top?: number, behavior?: ScrollBehavior }): void & (x: number, y: number) => void` | 滚动内容 | 2.30.4 |\n| sort | `(columnKey: string \\| number \\| null, order: 'ascend' \\| 'descend' \\| false) => void` | 设定表格的过滤状态 |  |\n\n### DataTable Slots\n\n| 名称    | 参数 | 说明                  | 版本   |\n| ------- | ---- | --------------------- | ------ |\n| empty   | `()` | 表格数据为空时的展示  |        |\n| loading | `()` | 表格 loading 时的展示 | 2.34.0 |\n"
  },
  {
    "path": "src/data-table/demos/zhCN/keep-alive-debug.demo.vue",
    "content": "<markdown>\n# Keep alive debug\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst showTable = ref(false)\n</script>\n\n<template>\n  <n-button @click=\"showTable = !showTable\">\n    showTable: {{ showTable }}\n  </n-button>\n  <!-- 不虚拟\n  <keep-alive>\n    <component :is=\"showTable ? 'component-a' : 'n-empty'\" />\n  </keep-alive> -->\n  虚拟\n  <keep-alive>\n    <component :is=\"showTable ? 'component-b' : 'n-empty'\" />\n  </keep-alive>\n</template>\n"
  },
  {
    "path": "src/data-table/demos/zhCN/merge-cell.demo.vue",
    "content": "<markdown>\n  # 合并单元格\n\n  设定列的 `colSpan` 和 `rowSpan` 来控制单元格的 `colspan` 和 `rowspan`。设定列的 `titleColSpan` 控制表头的 colspan。\n  </markdown>\n\n<script lang=\"ts\" setup>\nimport type { DataTableColumns } from 'naive-ui'\nimport { NButton, NTag, useMessage } from 'naive-ui'\nimport { h } from 'vue'\n\ninterface RowData {\n  key: number\n  name: string\n  age: number\n  address: string\n  tags: string[]\n}\n\ninterface SendMail {\n  (rowData: RowData): void\n}\n\nfunction createColumns({\n  sendMail\n}: {\n  sendMail: SendMail\n}): DataTableColumns<RowData> {\n  return [\n    {\n      title: 'Name',\n      titleColSpan: 2,\n      key: 'name',\n      rowSpan: (rowData, rowIndex) => (rowIndex === 0 ? 2 : 1),\n      colSpan: (rowData, rowIndex) => (rowIndex === 0 ? 2 : 1)\n    },\n    {\n      title: 'Age',\n      key: 'age'\n    },\n    {\n      title: 'Address',\n      key: 'address',\n      colSpan: (rowData, rowIndex) => (rowIndex === 2 ? 2 : 1)\n    },\n    {\n      title: 'Tags',\n      key: 'tags',\n      titleColSpan: 2,\n      render(row) {\n        const tags = row.tags.map((tagKey) => {\n          return h(\n            NTag,\n            {\n              style: {\n                marginRight: '6px'\n              },\n              type: 'info',\n              bordered: false\n            },\n            {\n              default: () => tagKey\n            }\n          )\n        })\n        return tags\n      }\n    },\n    {\n      title: 'Action',\n      key: 'actions',\n      rowSpan: (rowData, rowIndex) => (rowIndex === 0 ? 2 : 1),\n      render(row) {\n        return h(\n          NButton,\n          {\n            size: 'small',\n            onClick: () => sendMail(row)\n          },\n          { default: () => 'Send Email' }\n        )\n      }\n    }\n  ]\n}\n\nfunction createData(): RowData[] {\n  return [\n    {\n      key: 0,\n      name: 'John Brown',\n      age: 32,\n      address: 'New York No. 1 Lake Park',\n      tags: ['nice', 'developer']\n    },\n    {\n      key: 1,\n      name: 'Jim Green',\n      age: 42,\n      address: 'London No. 1 Lake Park',\n      tags: ['wow']\n    },\n    {\n      key: 2,\n      name: 'Joe Black',\n      age: 32,\n      address: 'Sidney No. 1 Lake Park',\n      tags: ['cool', 'teacher']\n    }\n  ]\n}\n\nconst message = useMessage()\nfunction sendMail(rowData: RowData) {\n  message.info(`send mail to ${rowData.name}`)\n}\n\nconst data = createData()\nconst columns = createColumns({ sendMail })\nconst pagination = {\n  pageSize: 10\n}\n</script>\n\n<template>\n  <n-data-table\n    :columns=\"columns\"\n    :data=\"data\"\n    :pagination=\"pagination\"\n    :single-line=\"false\"\n  />\n</template>\n"
  },
  {
    "path": "src/data-table/demos/zhCN/multiple-sorter.demo.vue",
    "content": "<markdown>\n  # 多列排序\n\n  为 `sorter` 设定 `multiple` 和 `compare` 来开启多列排序，其中 `multiple` 为多列排序的优先级，越高优先级越高。\n  </markdown>\n\n<script lang=\"ts\">\nimport type { DataTableColumns, DataTableInst } from 'naive-ui'\nimport { defineComponent, ref } from 'vue'\n\ninterface RowData {\n  key: number\n  name: string\n  age: number\n  address: string\n  chinese: number\n  math: number\n  english: number\n}\n\nconst columns: DataTableColumns<RowData> = [\n  {\n    title: 'Name',\n    key: 'name'\n  },\n  {\n    title: 'Age',\n    key: 'age',\n    sorter: (row1, row2) => row1.age - row2.age\n  },\n  {\n    title: 'Chinese Score',\n    key: 'chinese',\n    defaultSortOrder: false,\n    sorter: {\n      compare: (a, b) => a.chinese - b.chinese,\n      multiple: 3\n    }\n  },\n  {\n    title: 'Math Score',\n    defaultSortOrder: false,\n    key: 'math',\n    sorter: {\n      compare: (a, b) => a.math - b.math,\n      multiple: 2\n    }\n  },\n  {\n    title: 'English Score',\n    defaultSortOrder: false,\n    key: 'english',\n    sorter: {\n      compare: (a, b) => a.english - b.english,\n      multiple: 1\n    }\n  },\n  {\n    title: 'Address',\n    key: 'address',\n    filterOptions: [\n      {\n        label: 'London',\n        value: 'London'\n      },\n      {\n        label: 'New York',\n        value: 'New York'\n      }\n    ],\n    filter(value, row) {\n      return Boolean(~row.address.indexOf(value as string))\n    }\n  }\n]\n\nconst data: RowData[] = [\n  {\n    key: 0,\n    name: 'John Brown',\n    age: 32,\n    address: 'New York No. 1 Lake Park',\n    chinese: 98,\n    math: 60,\n    english: 70\n  },\n  {\n    key: 1,\n    name: 'Jim Green',\n    age: 42,\n    address: 'London No. 1 Lake Park',\n    chinese: 98,\n    math: 66,\n    english: 89\n  },\n  {\n    key: 2,\n    name: 'Joe Black',\n    age: 32,\n    address: 'Sidney No. 1 Lake Park',\n    chinese: 98,\n    math: 66,\n    english: 89\n  },\n  {\n    key: 3,\n    name: 'Jim Red',\n    age: 32,\n    address: 'London No. 2 Lake Park',\n    chinese: 88,\n    math: 99,\n    english: 89\n  }\n]\n\nexport default defineComponent({\n  setup() {\n    const dataTableInstRef = ref<DataTableInst | null>(null)\n    return {\n      data,\n      columns,\n      dataTableInst: dataTableInstRef,\n      pagination: ref({ pageSize: 5 }),\n      filterAddress() {\n        dataTableInstRef.value?.filter({\n          address: ['London']\n        })\n      },\n      sortName() {\n        dataTableInstRef.value?.sort('name', 'ascend')\n      },\n      clearFilters() {\n        dataTableInstRef.value?.filter(null)\n      },\n      clearSorter() {\n        dataTableInstRef.value?.clearSorter()\n      }\n    }\n  }\n})\n</script>\n\n<template>\n  <n-space vertical :size=\"12\">\n    <n-space>\n      <n-button @click=\"sortName\">\n        Sort By Name (Ascend)\n      </n-button>\n      <n-button @click=\"filterAddress\">\n        Filter Address (London)\n      </n-button>\n      <n-button @click=\"clearFilters\">\n        Clear Filters\n      </n-button>\n      <n-button @click=\"clearSorter\">\n        Clear Sorter\n      </n-button>\n    </n-space>\n    <n-data-table\n      ref=\"dataTableInst\"\n      :columns=\"columns\"\n      :data=\"data\"\n      :pagination=\"pagination\"\n    />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/data-table/demos/zhCN/pagination-behavior-on-filter.demo.vue",
    "content": "<markdown>\n# 过滤后页面状态\n\n配置 `pagination-behavior-on-filter` 控制过滤后的页面停留在当前页还是首页。\n\n如果设置停留在当前页，过滤后的数据总数达不到当前页时，会展示最后一页的数据。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { DataTableColumns } from 'naive-ui'\n\ninterface RowData {\n  key: number\n  name: string\n  age: number\n  address: string\n}\n\nconst columns: DataTableColumns<RowData> = [\n  {\n    title: 'Name',\n    key: 'name'\n  },\n  {\n    title: 'Age',\n    key: 'age'\n  },\n  {\n    title: 'Address',\n    key: 'address',\n    defaultFilterOptionValues: [],\n    filterOptions: [\n      {\n        label: 'London',\n        value: 'London'\n      },\n      {\n        label: 'New York',\n        value: 'New York'\n      }\n    ],\n    filter(value, row) {\n      return !!~row.address.indexOf(String(value))\n    }\n  }\n]\n\nconst data: RowData[] = [\n  {\n    key: 1,\n    name: 'John Brown',\n    age: 32,\n    address: 'New York No. 1 Lake Park'\n  },\n  {\n    key: 2,\n    name: 'Jim Green',\n    age: 42,\n    address: 'London No. 1 Lake Park'\n  },\n  {\n    key: 3,\n    name: 'Joe Black',\n    age: 32,\n    address: 'Sidney No. 1 Lake Park'\n  },\n  {\n    key: 4,\n    name: 'Jim Red',\n    age: 32,\n    address: 'London No. 2 Lake Park'\n  }\n]\n\nconst pagination = { pageSize: 3 }\n</script>\n\n<template>\n  <n-data-table\n    pagination-behavior-on-filter=\"first\"\n    :columns=\"columns\"\n    :data=\"data\"\n    :pagination=\"pagination\"\n  />\n</template>\n"
  },
  {
    "path": "src/data-table/demos/zhCN/render-cell.demo.vue",
    "content": "<markdown>\n# 自定义单元格\n\n你可以使用 `render-cell` 去渲染空状态。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { DataTableColumns } from 'naive-ui'\nimport { NText } from 'naive-ui'\nimport { h } from 'vue'\n\ninterface Song {\n  no: number\n  note: string\n}\n\nfunction createColumns(): DataTableColumns<Song> {\n  return [\n    {\n      title: '日期',\n      key: 'no',\n      width: 120,\n      render: (_, index) => {\n        return `星期 ${index + 1}`\n      }\n    },\n    {\n      title: '记录',\n      key: 'note'\n    }\n  ]\n}\n\nconst data: Song[] = [\n  { no: 3, note: '' },\n  { no: 4, note: '' },\n  { no: 12, note: '' },\n  { no: 10, note: '' },\n  { no: 19, note: '' }\n]\n\nconst columns = createColumns()\n\nfunction renderCell(value: string | number) {\n  if (!value) {\n    return h(NText, { depth: 3 }, { default: () => '未填写' })\n  }\n  return value\n}\n</script>\n\n<template>\n  <n-data-table :columns=\"columns\" :data=\"data\" :render-cell=\"renderCell\" />\n</template>\n"
  },
  {
    "path": "src/data-table/demos/zhCN/render-header.demo.vue",
    "content": "<markdown>\n  # 自定义渲染列头\n  </markdown>\n\n<script lang=\"ts\">\nimport type { DataTableBaseColumn, DataTableColumns } from 'naive-ui'\nimport type { ComponentInternalInstance, VNode, VNodeChild } from 'vue'\nimport { NGradientText, NTooltip } from 'naive-ui'\nimport { defineComponent, getCurrentInstance, h } from 'vue'\n\ninterface RowData extends Record<string, unknown> {\n  key: number\n  name: string\n  age: number\n  address: string\n}\n\nfunction renderTooltip(trigger: VNode, content: string): VNodeChild {\n  return h(NTooltip, null, {\n    trigger: () => trigger,\n    default: () => content\n  })\n}\n\nfunction createColumns(\n  _instance: ComponentInternalInstance | null\n): DataTableColumns<RowData> {\n  return [\n    {\n      key: 'name',\n      title(_column: DataTableBaseColumn<RowData>) {\n        return renderTooltip(\n          h(\n            NGradientText,\n            {\n              size: 24,\n              type: 'danger'\n            },\n            { default: () => 'Name' }\n          ),\n          'Tooltip Content'\n        )\n      }\n    },\n    {\n      key: 'age',\n      title(_column: DataTableBaseColumn<RowData>) {\n        return h(\n          NGradientText,\n          {\n            size: '20',\n            type: 'info'\n          },\n          { default: () => 'Age' }\n        )\n      }\n    },\n    {\n      key: 'address',\n      title(_column: DataTableBaseColumn<RowData>) {\n        return h(\n          NGradientText,\n          {\n            size: '16',\n            type: 'warning'\n          },\n          { default: () => 'Address' }\n        )\n      }\n    }\n  ]\n}\n\nconst data = [\n  {\n    key: 0,\n    name: 'John Brown',\n    age: 32,\n    address: 'New York No. 1 Lake Park'\n  },\n  {\n    key: 1,\n    name: 'Jim Green',\n    age: 42,\n    address: 'London No. 1 Lake Park'\n  },\n  {\n    key: 2,\n    name: 'Joe Black',\n    age: 32,\n    address: 'Sidney No. 1 Lake Park'\n  }\n]\n\nexport default defineComponent({\n  setup() {\n    const instance = getCurrentInstance()\n    return {\n      data,\n      columns: createColumns(instance),\n      pagination: {\n        pageSize: 10\n      }\n    }\n  }\n})\n</script>\n\n<template>\n  <n-data-table :columns=\"columns\" :data=\"data\" :pagination=\"pagination\" />\n</template>\n"
  },
  {
    "path": "src/data-table/demos/zhCN/row-props.demo.vue",
    "content": "<markdown>\n# 自定义行属性\n\n如果你想给行增加一些属性或者事件处理器，使用 `row-props` 属性。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { useMessage } from 'naive-ui'\n\ninterface RowData {\n  key: number\n  name: string\n  age: string\n  address: string\n}\n\nconst message = useMessage()\n\nfunction rowProps(row: RowData) {\n  return {\n    style: 'cursor: pointer;',\n    onClick: () => {\n      message.info(row.name)\n    }\n  }\n}\n\nconst columns = [\n  {\n    title: 'Name',\n    key: 'name'\n  },\n  {\n    title: 'Age',\n    key: 'age'\n  },\n  {\n    title: 'Address',\n    key: 'address'\n  }\n]\n\nconst data = [\n  {\n    key: 0,\n    name: '07akioni',\n    age: '18',\n    address: 'Yiheyuan Road'\n  },\n  {\n    key: 1,\n    name: '08akioni',\n    age: '14',\n    address: 'Pingshan Road'\n  },\n  {\n    key: 2,\n    name: '09akioni',\n    age: '22',\n    address: 'Haidian Bridge'\n  }\n]\n</script>\n\n<template>\n  <n-data-table :columns=\"columns\" :data=\"data\" :row-props=\"rowProps\" />\n</template>\n"
  },
  {
    "path": "src/data-table/demos/zhCN/rtl-debug.demo.vue",
    "content": "<markdown>\n# Rtl Debug\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type {\n  DataTableBaseColumn,\n  DataTableColumns,\n  DataTableFilterState\n} from 'naive-ui'\nimport { unstableDataTableRtl } from 'naive-ui'\nimport { reactive, ref } from 'vue'\n\ninterface Row {\n  key: number\n  name: string\n  age: number\n  address: string\n}\n\nconst data = [\n  {\n    key: 0,\n    name: 'John Brown',\n    age: 32,\n    address: 'New York No. 1 Lake Park'\n  },\n  {\n    key: 1,\n    name: 'Jim Green',\n    age: 42,\n    address: 'London No. 1 Lake Park'\n  },\n  {\n    key: 2,\n    name: 'Joe Black',\n    age: 32,\n    address: 'Sidney No. 1 Lake Park'\n  },\n  {\n    key: 3,\n    name: 'Jim Red',\n    age: 32,\n    address: 'London No. 2 Lake Park'\n  },\n  {\n    key: 4,\n    name: 'Jim Red',\n    age: 32,\n    address: 'London No. 2 Lake Park'\n  },\n  {\n    key: 5,\n    name: 'Jim Red',\n    age: 32,\n    address: 'London No. 2 Lake Park'\n  },\n  {\n    key: 6,\n    name: 'Jim Red',\n    age: 32,\n    address: 'London No. 2 Lake Park'\n  },\n  {\n    key: 7,\n    name: 'Jim Red',\n    age: 32,\n    address: 'London No. 2 Lake Park'\n  },\n  {\n    key: 8,\n    name: 'Jim Red',\n    age: 32,\n    address: 'London No. 2 Lake Park'\n  },\n  {\n    key: 9,\n    name: 'Jim Red',\n    age: 32,\n    address: 'London No. 2 Lake Park'\n  },\n  {\n    key: 10,\n    name: 'Jim Red',\n    age: 32,\n    address: 'London No. 2 Lake Park'\n  }\n]\n\nconst addressColumn = reactive<DataTableBaseColumn<Row>>({\n  title: 'Address',\n  key: 'address',\n  filterMultiple: false,\n  filterOptionValue: null,\n  sorter: 'default',\n  filterOptions: [\n    {\n      label: 'London',\n      value: 'London'\n    },\n    {\n      label: 'New York',\n      value: 'New York'\n    }\n  ],\n  filter(value, row) {\n    return !!~row.address.indexOf(value.toString())\n  }\n})\n\nconst columns = reactive<DataTableColumns<Row>>([\n  {\n    title: 'Name',\n    key: 'name',\n    sorter(rowA, rowB) {\n      return rowA.name.length - rowB.name.length\n    }\n  },\n  {\n    title: 'Age',\n    key: 'age',\n    sorter(rowA, rowB) {\n      return rowA.age - rowB.age\n    }\n  },\n  addressColumn\n])\n\nconst paginationReactive = reactive({\n  page: 1,\n  pageSize: 5,\n  showSizePicker: true,\n  pageSizes: [3, 5, 7],\n  onChange: (page: number) => {\n    paginationReactive.page = page\n  },\n  onUpdatePageSize: (pageSize: number) => {\n    paginationReactive.pageSize = pageSize\n    paginationReactive.page = 1\n  }\n})\n\nconst rtlEnabled = ref(true)\nconst rtlStyles = [unstableDataTableRtl]\nconst pagination = paginationReactive\n\nfunction filterAddress() {\n  addressColumn.filterOptionValue = 'London'\n}\n\nfunction unfilterAddress() {\n  addressColumn.filterOptionValue = null\n}\n\nfunction handleUpdateFilter(\n  filters: DataTableFilterState,\n  sourceColumn: DataTableBaseColumn\n) {\n  addressColumn.filterOptionValue = filters[sourceColumn.key] as string\n}\n</script>\n\n<template>\n  <n-space vertical :size=\"12\">\n    <n-config-provider :rtl=\"rtlEnabled ? rtlStyles : undefined\">\n      <div :dir=\"rtlEnabled ? 'rtl' : 'ltr'\">\n        <n-button @click=\"filterAddress\">\n          Filter Address(Use Value 'London')\n        </n-button>\n        <n-button @click=\"unfilterAddress\">\n          Clear Address Filters\n        </n-button>\n      </div>\n      <n-space><n-switch v-model:value=\"rtlEnabled\" />Rtl</n-space>\n      {{ rtlEnabled }}\n      <n-data-table\n        :columns=\"columns\"\n        :data=\"data\"\n        :pagination=\"pagination\"\n        @update:filters=\"handleUpdateFilter\"\n      />\n    </n-config-provider>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/data-table/demos/zhCN/scroll-debug.demo.vue",
    "content": "<markdown>\n# Scroll Debug\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { h } from 'vue'\n\ninterface RowData {\n  [key: string]: string\n}\n\nconst label0\n  = 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy'\n\nconst label\n  = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'\n\nconst columns = [\n  {\n    key: '1',\n    title: '1',\n    render(rowData: RowData) {\n      return h('div', { style: 'white-space: nowrap;' }, rowData['1'])\n    }\n  },\n  {\n    key: '2',\n    title: '2',\n    render(rowData: RowData) {\n      return h('div', { style: 'white-space: nowrap;' }, rowData['2'])\n    }\n  }\n]\n\nconst data = [\n  {\n    1: label0,\n    2: label\n  },\n  {\n    1: label0,\n    2: label\n  },\n  {\n    1: label0,\n    2: label\n  },\n  {\n    1: label0,\n    2: label\n  }\n]\n\nconst data1 = [\n  {\n    1: 'x',\n    2: 'x'\n  },\n  {\n    1: 'x',\n    2: 'x'\n  },\n  {\n    1: 'x',\n    2: 'x'\n  },\n  {\n    1: 'x',\n    2: 'x'\n  }\n]\n</script>\n\n<template>\n  Flex Height, Auto Layout Overflow, No Max Height\n  <n-data-table\n    :columns=\"columns\"\n    :data=\"data\"\n    style=\"height: 180px\"\n    flex-height\n  />\n\n  Auto Layout Overflow, No Max Height\n  <n-data-table :columns=\"columns\" :data=\"data\" />\n\n  Auto Layout Overflow, Max Height\n  <n-data-table :columns=\"columns\" :data=\"data\" :max-height=\"60\" />\n\n  Fixed Layout Overflow, No Max Height\n  <n-data-table :columns=\"columns\" :data=\"data\" table-layout=\"fixed\" />\n\n  Fixed Layout Overflow, Max Height\n  <n-data-table\n    :columns=\"columns\"\n    :data=\"data\"\n    table-layout=\"fixed\"\n    :max-height=\"60\"\n  />\n\n  Auto Layout No Overflow, No Max Height\n  <n-data-table :columns=\"columns\" :data=\"data1\" />\n\n  Auto Layout No Overflow, Max Height\n  <n-data-table :columns=\"columns\" :data=\"data1\" :max-height=\"60\" />\n\n  Fixed Layout No Overflow, No Max Height\n  <n-data-table :columns=\"columns\" :data=\"data1\" table-layout=\"fixed\" />\n\n  Fixed Layout No Overflow, Max Height\n  <n-data-table\n    :columns=\"columns\"\n    :data=\"data1\"\n    table-layout=\"fixed\"\n    :max-height=\"60\"\n  />\n\n  Auto Layout No Overflow, No Max Height, Small Scroll X\n  <n-data-table :columns=\"columns\" :data=\"data1\" :scroll-x=\"300\" />\n\n  Auto Layout No Overflow, Max Height\n  <n-data-table\n    :columns=\"columns\"\n    :data=\"data1\"\n    :max-height=\"60\"\n    :scroll-x=\"300\"\n  />\n\n  Fixed Layout No Overflow, No Max Height\n  <n-data-table\n    :columns=\"columns\"\n    :data=\"data1\"\n    table-layout=\"fixed\"\n    :scroll-x=\"300\"\n  />\n\n  Fixed Layout No Overflow, Max Height\n  <n-data-table\n    :columns=\"columns\"\n    :data=\"data1\"\n    table-layout=\"fixed\"\n    :max-height=\"60\"\n    :scroll-x=\"300\"\n  />\n</template>\n"
  },
  {
    "path": "src/data-table/demos/zhCN/select-single.demo.vue",
    "content": "<markdown>\n# 选中行(单选)\n\n在 `type='selection'` 的列，同时设置 `multiple=false` 来变成单选模式。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { DataTableColumns } from 'naive-ui'\nimport { ref } from 'vue'\n\ninterface RowData {\n  key: number\n  name: string\n  age: number\n  address: string\n}\n\nconst data = Array.from({ length: 46 }).map((_, index) => ({\n  name: `Edward King ${index}`,\n  age: 32,\n  address: `London, Park Lane no. ${index}`,\n  key: index\n}))\n\nfunction createColumns(): DataTableColumns<RowData> {\n  return [\n    {\n      type: 'selection',\n      multiple: false,\n      disabled(row: RowData) {\n        return row.name === 'Edward King 3'\n      }\n    },\n    {\n      title: 'Name',\n      key: 'name'\n    },\n    {\n      title: 'Age',\n      key: 'age'\n    },\n    {\n      title: 'Address',\n      key: 'address'\n    }\n  ]\n}\n\nconst checkedRowKeysRef = ref([4, 1])\nconst checkedRowKeys = checkedRowKeysRef\nconst pagination = {\n  pageSize: 6\n}\nconst columns = createColumns()\n</script>\n\n<template>\n  <n-data-table\n    v-model:checked-row-keys=\"checkedRowKeys\"\n    :columns=\"columns\"\n    :data=\"data\"\n    :pagination=\"pagination\"\n  />\n</template>\n"
  },
  {
    "path": "src/data-table/demos/zhCN/select.demo.vue",
    "content": "<markdown>\n# 选中行\n\n可以通过把第一列的类型设为 `selection` 来让行变成可选的。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { DataTableColumns, DataTableRowKey } from 'naive-ui'\nimport { ref } from 'vue'\n\ninterface RowData {\n  key: number\n  name: string\n  age: string\n  address: string\n}\n\nfunction createColumns(): DataTableColumns<RowData> {\n  return [\n    {\n      type: 'selection',\n      disabled(row: RowData) {\n        return row.name === 'Edward King 3'\n      }\n    },\n    {\n      title: 'Name',\n      key: 'name'\n    },\n    {\n      title: 'Age',\n      key: 'age'\n    },\n    {\n      title: 'Address',\n      key: 'address'\n    }\n  ]\n}\n\nconst data = Array.from({ length: 46 }).map((_, index) => ({\n  name: `Edward King ${index}`,\n  age: 32,\n  address: `London, Park Lane no. ${index}`\n}))\n\nconst checkedRowKeysRef = ref<DataTableRowKey[]>([])\nconst columns = createColumns()\nconst pagination = {\n  pageSize: 5\n}\n\nfunction rowKey(row: RowData) {\n  return row.address\n}\n\nfunction handleCheck(rowKeys: DataTableRowKey[]) {\n  checkedRowKeysRef.value = rowKeys\n}\n</script>\n\n<template>\n  <n-p> 你选中了 {{ checkedRowKeysRef.length }} 行。 </n-p>\n\n  <n-data-table\n    :columns=\"columns\"\n    :data=\"data\"\n    :pagination=\"pagination\"\n    :row-key=\"rowKey\"\n    @update:checked-row-keys=\"handleCheck\"\n  />\n</template>\n"
  },
  {
    "path": "src/data-table/demos/zhCN/simple-editable.demo.vue",
    "content": "<markdown>\n# 简单的可编辑表格\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { DataTableColumns } from 'naive-ui'\nimport { NInput } from 'naive-ui'\nimport { h, ref } from 'vue'\n\ninterface RowData {\n  key: number\n  name: string\n  age: string\n  address: string\n}\n\nfunction createData(): RowData[] {\n  return [\n    {\n      key: 0,\n      name: 'John Brown',\n      age: '32',\n      address: 'New York No. 1 Lake Park'\n    },\n    {\n      key: 1,\n      name: 'Jim Green',\n      age: '42',\n      address: 'London No. 1 Lake Park'\n    },\n    {\n      key: 2,\n      name: 'Joe Black',\n      age: '32',\n      address: 'Sidney No. 1 Lake Park'\n    }\n  ]\n}\n\nconst data = ref(createData())\nfunction createColumns(): DataTableColumns<RowData> {\n  return [\n    {\n      title: 'Name',\n      key: 'name',\n      render(row, index) {\n        return h(NInput, {\n          value: row.name,\n          onUpdateValue(v) {\n            data.value[index].name = v\n          }\n        })\n      }\n    },\n    {\n      title: 'Age',\n      key: 'age',\n      render(row, index) {\n        return h(NInput, {\n          value: row.age,\n          onUpdateValue(v) {\n            data.value[index].age = v\n          }\n        })\n      }\n    },\n    {\n      title: 'Address',\n      key: 'address',\n      render(row, index) {\n        return h(NInput, {\n          value: row.address,\n          onUpdateValue(v) {\n            data.value[index].address = v\n          }\n        })\n      }\n    }\n  ]\n}\n\nconst columns = createColumns()\nconst pagination = {\n  pageSize: 10\n}\n</script>\n\n<template>\n  <n-data-table :columns=\"columns\" :data=\"data\" :pagination=\"pagination\" />\n  <pre>{{ JSON.stringify(data, null, 2) }}</pre>\n</template>\n"
  },
  {
    "path": "src/data-table/demos/zhCN/size.demo.vue",
    "content": "<markdown>\n# 尺寸\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { DataTableColumns } from 'naive-ui'\nimport { NButton, NTag, useMessage } from 'naive-ui'\nimport { h } from 'vue'\n\ninterface RowData {\n  key: number\n  name: string\n  age: number\n  address: string\n  tags: string[]\n}\n\nfunction createColumns({\n  sendMail\n}: {\n  sendMail: (rowData: RowData) => void\n}): DataTableColumns<RowData> {\n  return [\n    {\n      title: 'Name',\n      key: 'name'\n    },\n    {\n      title: 'Age',\n      key: 'age'\n    },\n    {\n      title: 'Address',\n      key: 'address'\n    },\n    {\n      title: 'Tags',\n      key: 'tags',\n      render(row) {\n        const tags = row.tags.map((tagKey) => {\n          return h(\n            NTag,\n            {\n              style: {\n                marginRight: '6px'\n              },\n              type: 'info',\n              bordered: false\n            },\n            {\n              default: () => tagKey\n            }\n          )\n        })\n        return tags\n      }\n    },\n    {\n      title: 'Action',\n      key: 'actions',\n      render(row) {\n        return h(\n          NButton,\n          {\n            size: 'small',\n            onClick: () => sendMail(row)\n          },\n          { default: () => 'Send Email' }\n        )\n      }\n    }\n  ]\n}\n\nfunction createData(): RowData[] {\n  return [\n    {\n      key: 0,\n      name: 'John Brown',\n      age: 32,\n      address: 'New York No. 1 Lake Park',\n      tags: ['nice', 'developer']\n    },\n    {\n      key: 1,\n      name: 'Jim Green',\n      age: 42,\n      address: 'London No. 1 Lake Park',\n      tags: ['wow']\n    },\n    {\n      key: 2,\n      name: 'Joe Black',\n      age: 32,\n      address: 'Sidney No. 1 Lake Park',\n      tags: ['cool', 'teacher']\n    }\n  ]\n}\n\nconst message = useMessage()\nconst data = createData()\nconst columns = createColumns({\n  sendMail(rowData) {\n    message.info(`send mail to ${rowData.name}`)\n  }\n})\nconst pagination = {\n  pageSize: 10\n}\n</script>\n\n<template>\n  <n-space vertical :size=\"12\">\n    <n-data-table\n      size=\"small\"\n      :columns=\"columns\"\n      :data=\"data\"\n      :pagination=\"pagination\"\n    />\n    <n-data-table\n      size=\"large\"\n      :columns=\"columns\"\n      :data=\"data\"\n      :pagination=\"pagination\"\n    />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/data-table/demos/zhCN/striped.demo.vue",
    "content": "<markdown>\n# 条纹\n\n使用 `striped` 属性渲染条纹，使得表格明暗交替。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { DataTableColumns } from 'naive-ui'\n\ninterface RowData {\n  key: number\n  name: string\n  age: number\n  address: string\n}\n\nfunction createColumns(): DataTableColumns<RowData> {\n  return [\n    {\n      type: 'selection'\n    },\n    {\n      title: 'Name',\n      key: 'name'\n    },\n    {\n      title: 'Age',\n      key: 'age'\n    },\n    {\n      title: 'Address',\n      key: 'address'\n    }\n  ]\n}\n\nfunction createData(): RowData[] {\n  return [\n    {\n      key: 0,\n      name: 'John Brown',\n      age: 32,\n      address: 'New York No. 1 Lake Park'\n    },\n    {\n      key: 1,\n      name: 'Jim Green',\n      age: 42,\n      address: 'London No. 1 Lake Park'\n    },\n    {\n      key: 2,\n      name: 'Joe Black',\n      age: 32,\n      address: 'Sidney No. 1 Lake Park'\n    }\n  ]\n}\n\nconst data = createData()\nconst columns = createColumns()\n</script>\n\n<template>\n  <n-data-table :columns=\"columns\" :data=\"data\" striped />\n</template>\n"
  },
  {
    "path": "src/data-table/demos/zhCN/summary-debug.demo.vue",
    "content": "<markdown>\n  # Summary debug\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { h } from 'vue'\n\nfunction createColumns() {\n  return [\n    {\n      title: 'parehnt',\n      children: [\n        {\n          title: 'Age',\n          key: 'age'\n        },\n        {\n          title: 'Name',\n          key: 'name',\n          fixed: 'left'\n        }\n      ]\n    },\n    {\n      title: 'Address',\n      key: 'address'\n    }\n  ] as any\n}\n\nfunction createData() {\n  return [\n    {\n      key: 0,\n      name: 'John Brown',\n      age: 32,\n      address: 'New York No. 1 Lake Park'\n    },\n    {\n      key: 1,\n      name: 'Jim Green',\n      age: 42,\n      address: 'London No. 1 Lake Park'\n    },\n    {\n      key: 2,\n      name: 'Joe Black',\n      age: 32,\n      address: 'Sidney No. 1 Lake Park'\n    }\n  ]\n}\n\nfunction createSummary() {\n  return [\n    {\n      name: {\n        value: h('span', { style: { color: 'red' } }, '7'),\n        colSpan: 2,\n        rowSpan: 1\n      },\n      age: {\n        value: h('span', null, '6')\n      }\n    }\n  ]\n}\n\nconst summary = createSummary\nconst data = createData()\nconst columns = createColumns()\n</script>\n\n<template>\n  <n-data-table :columns=\"columns\" :data=\"data\" :summary=\"summary\" />\n</template>\n"
  },
  {
    "path": "src/data-table/demos/zhCN/summary.demo.vue",
    "content": "<markdown>\n# 总结栏\n\n使用 `summary` 属性渲染总结栏。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { DataTableColumns, DataTableCreateSummary } from 'naive-ui'\nimport { h } from 'vue'\n\ninterface RowData {\n  key: number\n  name: string\n  age: number\n  address: string\n}\n\nfunction createColumns(): DataTableColumns<RowData> {\n  return [\n    {\n      type: 'selection'\n    },\n    {\n      title: 'Name',\n      key: 'name'\n    },\n    {\n      title: 'Age',\n      key: 'age'\n    },\n    {\n      title: 'Address',\n      key: 'address'\n    }\n  ]\n}\n\nfunction createData(): RowData[] {\n  return [\n    {\n      key: 0,\n      name: 'John Brown',\n      age: 32,\n      address: 'New York No. 1 Lake Park'\n    },\n    {\n      key: 1,\n      name: 'Jim Green',\n      age: 42,\n      address: 'London No. 1 Lake Park'\n    },\n    {\n      key: 2,\n      name: 'Joe Black',\n      age: 32,\n      address: 'Sidney No. 1 Lake Park'\n    }\n  ]\n}\n\nconst createSummary: DataTableCreateSummary = (pageData) => {\n  return {\n    name: {\n      value: h(\n        'span',\n        { style: { color: 'red' } },\n        (pageData as unknown as RowData[]).reduce(\n          (prevValue, row) => prevValue + row.age,\n          0\n        )\n      ),\n      colSpan: 3\n    }\n  }\n}\n\nconst summary = createSummary\nconst data = createData()\nconst columns = createColumns()\n</script>\n\n<template>\n  <n-data-table :columns=\"columns\" :data=\"data\" :summary=\"summary\" />\n</template>\n"
  },
  {
    "path": "src/data-table/demos/zhCN/switchable-editable.demo.vue",
    "content": "<markdown>\n  # 可切换的可编辑表格\n  </markdown>\n\n<script lang=\"ts\">\nimport type { InputInst } from 'naive-ui'\nimport type { PropType } from 'vue'\nimport { NInput } from 'naive-ui'\nimport { computed, defineComponent, h, nextTick, ref } from 'vue'\n\ninterface RowData {\n  key: number\n  name: string\n  age: number\n  address: string\n}\n\ninterface OnUpdateValue {\n  (value: string): void\n}\n\nfunction createData(): RowData[] {\n  return Array.from({ length: 100 }).map((_, index) => ({\n    key: index,\n    name: `John Brown ${index}`,\n    age: (Math.random() * 40) | 0,\n    address: `New York No. ${index} Lake Park`\n  }))\n}\n\nconst ShowOrEdit = defineComponent({\n  props: {\n    value: [String, Number],\n    onUpdateValue: [Function, Array] as PropType<OnUpdateValue>\n  },\n  setup(props) {\n    const isEdit = ref(false)\n    const inputRef = ref<InputInst | null>(null)\n    const inputValue = ref(props.value)\n    function handleOnClick() {\n      isEdit.value = true\n      nextTick(() => {\n        inputRef.value?.focus()\n      })\n    }\n    function handleChange() {\n      props.onUpdateValue?.(String(inputValue.value))\n      isEdit.value = false\n    }\n    return () =>\n      h(\n        'div',\n        {\n          style: 'min-height: 22px',\n          onClick: handleOnClick\n        },\n        isEdit.value\n          ? h(NInput, {\n              ref: inputRef,\n              value: String(inputValue.value),\n              onUpdateValue: (v) => {\n                inputValue.value = v\n              },\n              onChange: handleChange,\n              onBlur: handleChange\n            })\n          : props.value\n      )\n  }\n})\n\nexport default defineComponent({\n  setup() {\n    const data = ref(createData())\n    const page = ref(1)\n\n    const getDataIndex = (key: number) => {\n      return data.value.findIndex(item => item.key === key)\n    }\n    const handlePageChange = (curPage: number) => {\n      page.value = curPage\n    }\n\n    const paginationRef = computed(() => ({\n      pageSize: 10,\n      page: page.value\n    }))\n\n    return {\n      data,\n      paginationRef,\n      handlePageChange,\n      columns: [\n        {\n          title: 'Name',\n          key: 'name',\n          width: 150,\n          render(row: RowData) {\n            const index = getDataIndex(row.key)\n            return h(ShowOrEdit, {\n              value: row.name,\n              onUpdateValue(v: string) {\n                data.value[index].name = v\n              }\n            })\n          }\n        },\n        {\n          title: 'Age',\n          key: 'age',\n          width: 100,\n          render(row: RowData) {\n            const index = getDataIndex(row.key)\n            return h(ShowOrEdit, {\n              value: row.age,\n              onUpdateValue(v: string) {\n                data.value[index].age = Number(v)\n              }\n            })\n          }\n        },\n        {\n          title: 'Address',\n          key: 'address',\n          render(row: RowData) {\n            const index = getDataIndex(row.key)\n            return h(ShowOrEdit, {\n              value: row.address,\n              onUpdateValue(v: string) {\n                data.value[index].address = v\n              }\n            })\n          }\n        }\n      ]\n    }\n  }\n})\n</script>\n\n<template>\n  <n-data-table\n    :key=\"(row: RowData) => row.key\"\n    :columns=\"columns\"\n    :data=\"data\"\n    :pagination=\"paginationRef\"\n    :on-update:page=\"handlePageChange\"\n  />\n</template>\n"
  },
  {
    "path": "src/data-table/demos/zhCN/tree.demo.vue",
    "content": "<markdown>\n# 树型数据\n\n在行数据中设定 `children` 来展示树型数据。如果你想用别的 key 来获取 children，那么可以设定 `children-key`。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { DataTableColumns } from 'naive-ui'\n\ninterface RowData {\n  name: string\n  index: string\n  children?: RowData[]\n}\n\nconst data: RowData[] = [\n  {\n    name: '07akioni',\n    index: '07',\n    children: [\n      {\n        name: '08akioni',\n        index: '08',\n        children: [\n          {\n            name: '09akioni',\n            index: '09'\n          },\n          {\n            name: '10akioni',\n            index: '10'\n          }\n        ]\n      }\n    ]\n  },\n  {\n    name: '11akioni',\n    index: '11'\n  }\n]\n\nconst columns: DataTableColumns<RowData> = [\n  {\n    type: 'selection'\n  },\n  {\n    title: 'name',\n    key: 'name'\n  },\n  {\n    title: 'index',\n    key: 'index'\n  }\n]\n\nfunction rowKey(row: RowData) {\n  return row.index\n}\n</script>\n\n<template>\n  <n-data-table\n    :columns=\"columns\"\n    :data=\"data\"\n    :row-key=\"rowKey\"\n    default-expand-all\n  />\n</template>\n"
  },
  {
    "path": "src/data-table/demos/zhCN/virtual-x.demo.vue",
    "content": "<markdown>\n# 大量数据（行和列）\n\n如果你有大量行数据和列数据，例如几千行 + 几百列，`naive-ui` 提供了横向 + 纵向虚拟滚动的功能。\n\n因为横向虚拟滚动的天然的复杂性，对应的配置也会较为复杂，以下多数内容都是必须的：\n\n1. 配置 `virtual-scroll` 打开纵向虚拟滚动\n2. 配置 `virtual-scroll-x` 打开横向虚拟滚动\n    - 每一个列都需要配置 `width` 属性\n    - 配置 `scroll-x` 属性，设为所有列的总宽度\n    - 配置 `min-row-height` 属性，设为每一行的最小高度，所有的行高度必须比这个值更大\n    - 配置 `height-for-row` 属性，用于配置每一行的高度（因为每一行永远只有一部分格子是可见的，因此无法自动求出），如果不配置，每一行的高度会被设为 `min-row-height`\n3. 如有需要，配置 `virtual-scroll-header`，默认情况下，表头依然会全量渲染以保持兼容性，你可以通过此配置来打开表头的虚拟渲染\n    - 配置 `header-height` 属性，设为表头的高度\n\n下面的例子对应了一个 1000 行 * 1000 列的表格。\n\n`naive-ui` 的表格可以轻松的支持千万级的表格数据，你在不收钱的组件库不容易找得到这样的功能。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { DataTableColumns } from 'naive-ui'\n\ninterface RowData {\n  key: number\n  name: string\n  age: number\n  address: string\n}\n\nconst columns: DataTableColumns<RowData> = []\n\nlet scrollX = 0\n\nfor (let i = 0; i < 1000; ++i) {\n  scrollX += 100\n  columns.push({\n    title: `Col ${i}`,\n    width: 100,\n    key: i,\n    fixed: i <= 1 ? 'left' : i > 997 ? 'right' : undefined,\n    render(_, rowIndex) {\n      return `${i}-${rowIndex}`\n    }\n  })\n}\n\nconst data: RowData[] = Array.from({ length: 1000 }).map((_, index) => ({\n  key: index,\n  name: `Edward King ${index}`,\n  age: 32,\n  address: `London, Park Lane no. ${index}`\n}))\n\nconst heightForRow = () => 48\n</script>\n\n<template>\n  <n-data-table\n    :columns=\"columns\"\n    :data=\"data\"\n    :max-height=\"250\"\n    virtual-scroll\n    virtual-scroll-x\n    :scroll-x=\"scrollX\"\n    :min-row-height=\"48\"\n    :height-for-row=\"heightForRow\"\n    virtual-scroll-header\n    :header-height=\"48\"\n  />\n</template>\n"
  },
  {
    "path": "src/data-table/demos/zhCN/virtual.demo.vue",
    "content": "<markdown>\n# 大量数据\n\n**注意：当 `virtual-scroll` 为 `true` 时，`rowSpan` 将不生效。**\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { DataTableColumns } from 'naive-ui'\nimport { h } from 'vue'\n\ninterface RowData {\n  key: number\n  name: string\n  age: number\n  address: string\n}\n\nconst columns: DataTableColumns<RowData> = [\n  {\n    type: 'selection',\n    fixed: 'left'\n  },\n  {\n    title: 'Name',\n    key: 'name',\n    width: 200,\n    fixed: 'left'\n  },\n  {\n    title: 'Age',\n    key: 'age',\n    width: 100,\n    fixed: 'left'\n  },\n  {\n    title: 'Row',\n    key: 'row',\n    render(row, index) {\n      return h('span', ['row ', index])\n    }\n  },\n  {\n    title: 'Row1',\n    key: 'row1',\n    render(row, index) {\n      return h('span', ['row ', index])\n    }\n  },\n  {\n    title: 'Row2',\n    key: 'row2',\n    render(row, index) {\n      return h('span', ['row ', index])\n    },\n    width: 100,\n    fixed: 'right'\n  },\n  {\n    title: 'Address',\n    key: 'address',\n    width: 200,\n    fixed: 'right'\n  }\n]\n\nconst data: RowData[] = Array.from({ length: 5000 }).map((_, index) => ({\n  key: index,\n  name: `Edward King ${index}`,\n  age: 32,\n  address: `London, Park Lane no. ${index}`\n}))\n</script>\n\n<template>\n  <n-data-table\n    :columns=\"columns\"\n    :data=\"data\"\n    :max-height=\"250\"\n    :scroll-x=\"1800\"\n    virtual-scroll\n  />\n</template>\n"
  },
  {
    "path": "src/data-table/index.ts",
    "content": "export { default as NDataTable } from './src/DataTable'\nexport { dataTableProps } from './src/interface'\nexport type {\n  TableBaseColumn as DataTableBaseColumn,\n  TableColumn as DataTableColumn,\n  TableColumnGroup as DataTableColumnGroup,\n  ColumnKey as DataTableColumnKey,\n  TableColumns as DataTableColumns,\n  CreateRowClassName as DataTableCreateRowClassName,\n  CreateRowKey as DataTableCreateRowKey,\n  CreateRowProps as DataTableCreateRowProps,\n  CreateSummary as DataTableCreateSummary,\n  TableExpandColumn as DataTableExpandColumn,\n  FilterState as DataTableFilterState,\n  DataTableInst,\n  DataTableProps,\n  RenderFilter as DataTableRenderFilter,\n  RenderFilterIcon as DataTableRenderFilterIcon,\n  RenderSorter as DataTableRenderSorter,\n  RenderSorterIcon as DataTableRenderSorterIcon,\n  RowData as DataTableRowData,\n  RowKey as DataTableRowKey,\n  TableSelectionColumn as DataTableSelectionColumn,\n  DataTableSlots,\n  SortOrder as DataTableSortOrder,\n  SortState as DataTableSortState\n} from './src/interface'\nexport type * from './src/public-types'\n"
  },
  {
    "path": "src/data-table/src/DataTable.tsx",
    "content": "import type { CSSProperties, SlotsType } from 'vue'\nimport type {\n  CsvOptionsType,\n  DataTableInst,\n  DataTableSlots,\n  MainTableRef,\n  RowKey\n} from './interface'\nimport { createId } from 'seemly'\nimport {\n  computed,\n  defineComponent,\n  h,\n  provide,\n  ref,\n  toRef,\n  Transition,\n  watchEffect\n} from 'vue'\nimport { NBaseLoading } from '../../_internal'\nimport {\n  useConfig,\n  useLocale,\n  useRtl,\n  useTheme,\n  useThemeClass\n} from '../../_mixins'\nimport { createKey, download, resolveSlot, warnOnce } from '../../_utils'\nimport { NPagination } from '../../pagination'\nimport { dataTableLight } from '../styles'\nimport { dataTableInjectionKey, dataTableProps } from './interface'\nimport MainTable from './MainTable'\nimport style from './styles/index.cssr'\nimport { useCheck } from './use-check'\nimport { useExpand } from './use-expand'\nimport { useGroupHeader } from './use-group-header'\nimport { useResizable } from './use-resizable'\nimport { useScroll } from './use-scroll'\nimport { useTableData } from './use-table-data'\nimport { generateCsv } from './utils'\n\nexport default defineComponent({\n  name: 'DataTable',\n  alias: ['AdvancedTable'],\n  props: dataTableProps,\n  slots: Object as SlotsType<DataTableSlots>,\n  setup(props, { slots }) {\n    if (__DEV__) {\n      watchEffect(() => {\n        if (props.onPageChange !== undefined) {\n          warnOnce(\n            'data-table',\n            '`on-page-change` is deprecated, please use `on-update:page` instead.'\n          )\n        }\n        if (props.onPageSizeChange !== undefined) {\n          warnOnce(\n            'data-table',\n            '`on-page-size-change` is deprecated, please use `on-update:page-size` instead.'\n          )\n        }\n        if (props.onSorterChange !== undefined) {\n          warnOnce(\n            'data-table',\n            '`on-sorter-change` is deprecated, please use `on-update:sorter` instead.'\n          )\n        }\n        if (props.onFiltersChange !== undefined) {\n          warnOnce(\n            'data-table',\n            '`on-filters-change` is deprecated, please use `on-update:filters` instead.'\n          )\n        }\n        if (props.onCheckedRowKeysChange !== undefined) {\n          warnOnce(\n            'data-table',\n            '`on-checked-row-keys-change` is deprecated, please use `on-update:checked-row-keys` instead.'\n          )\n        }\n      })\n    }\n\n    const {\n      mergedBorderedRef,\n      mergedClsPrefixRef,\n      inlineThemeDisabled,\n      mergedRtlRef,\n      mergedComponentPropsRef\n    } = useConfig(props)\n    const rtlEnabledRef = useRtl('DataTable', mergedRtlRef, mergedClsPrefixRef)\n    const mergedSizeRef = computed(() => {\n      return (\n        props.size\n        || mergedComponentPropsRef?.value?.DataTable?.size\n        || 'medium'\n      )\n    })\n    const mergedBottomBorderedRef = computed(() => {\n      const { bottomBordered } = props\n      // do not add bottom bordered class if bordered is true\n      // since border is displayed on wrapper\n      if (mergedBorderedRef.value)\n        return false\n      if (bottomBordered !== undefined)\n        return bottomBordered\n      return true\n    })\n    const themeRef = useTheme(\n      'DataTable',\n      '-data-table',\n      style,\n      dataTableLight,\n      props,\n      mergedClsPrefixRef\n    )\n    const bodyWidthRef = ref<number | null>(null)\n    const mainTableInstRef = ref<MainTableRef | null>(null)\n    const { getResizableWidth, clearResizableWidth, doUpdateResizableWidth }\n      = useResizable()\n    const { rowsRef, colsRef, dataRelatedColsRef, hasEllipsisRef }\n      = useGroupHeader(props, getResizableWidth)\n\n    const {\n      treeMateRef,\n      mergedCurrentPageRef,\n      paginatedDataRef,\n      rawPaginatedDataRef,\n      selectionColumnRef,\n      hoverKeyRef,\n      mergedPaginationRef,\n      mergedFilterStateRef,\n      mergedSortStateRef,\n      childTriggerColIndexRef,\n      doUpdatePage,\n      doUpdateFilters,\n      onUnstableColumnResize,\n      deriveNextSorter,\n      filter,\n      filters,\n      clearFilter,\n      clearFilters,\n      clearSorter,\n      page,\n      sort\n    } = useTableData(props, { dataRelatedColsRef })\n\n    const downloadCsv = (options?: CsvOptionsType): void => {\n      const { fileName = 'data.csv', keepOriginalData = false } = options || {}\n      const data = keepOriginalData ? props.data : rawPaginatedDataRef.value\n      const csvData = generateCsv(\n        props.columns,\n        data,\n        props.getCsvCell,\n        props.getCsvHeader\n      )\n      const blob = new Blob([csvData], { type: 'text/csv;charset=utf-8' })\n      const downloadUrl = URL.createObjectURL(blob)\n      download(\n        downloadUrl,\n        fileName.endsWith('.csv') ? fileName : `${fileName}.csv`\n      )\n      URL.revokeObjectURL(downloadUrl)\n    }\n\n    const {\n      doCheckAll,\n      doUncheckAll,\n      doCheck,\n      doUncheck,\n      headerCheckboxDisabledRef,\n      someRowsCheckedRef,\n      allRowsCheckedRef,\n      mergedCheckedRowKeySetRef,\n      mergedInderminateRowKeySetRef\n    } = useCheck(props, {\n      selectionColumnRef,\n      treeMateRef,\n      paginatedDataRef\n    })\n    const {\n      stickyExpandedRowsRef,\n      mergedExpandedRowKeysRef,\n      renderExpandRef,\n      expandableRef,\n      doUpdateExpandedRowKeys\n    } = useExpand(props, treeMateRef)\n    const maxHeightRef = toRef(props, 'maxHeight')\n    const mergedTableLayoutRef = computed(() => {\n      // Layout\n      // virtual |descrete header | ellpisis => fixed\n      //    = virtual | maxHeight | ellpisis => fixed\n      if (\n        props.virtualScroll\n        || props.flexHeight\n        || props.maxHeight !== undefined\n        || hasEllipsisRef.value\n      ) {\n        return 'fixed'\n      }\n      return props.tableLayout\n    })\n    const {\n      handleTableBodyScroll,\n      handleTableHeaderScroll,\n      syncScrollState,\n      setHeaderScrollLeft,\n      leftActiveFixedColKeyRef,\n      leftActiveFixedChildrenColKeysRef,\n      rightActiveFixedColKeyRef,\n      rightActiveFixedChildrenColKeysRef,\n      leftFixedColumnsRef,\n      rightFixedColumnsRef,\n      fixedColumnLeftMapRef,\n      fixedColumnRightMapRef,\n      xScrollableRef,\n      explicitlyScrollableRef\n    } = useScroll(props, {\n      bodyWidthRef,\n      mainTableInstRef,\n      mergedCurrentPageRef,\n      maxHeightRef,\n      mergedTableLayoutRef\n    })\n    const { localeRef } = useLocale('DataTable')\n\n    provide(dataTableInjectionKey, {\n      xScrollableRef,\n      explicitlyScrollableRef,\n      props,\n      treeMateRef,\n      renderExpandIconRef: toRef(props, 'renderExpandIcon'),\n      loadingKeySetRef: ref(new Set<RowKey>()),\n      slots,\n      indentRef: toRef(props, 'indent'),\n      childTriggerColIndexRef,\n      bodyWidthRef,\n      componentId: createId(),\n      hoverKeyRef,\n      mergedClsPrefixRef,\n      mergedThemeRef: themeRef,\n      scrollXRef: computed(() => props.scrollX),\n      rowsRef,\n      colsRef,\n      paginatedDataRef,\n      leftActiveFixedColKeyRef,\n      leftActiveFixedChildrenColKeysRef,\n      rightActiveFixedColKeyRef,\n      rightActiveFixedChildrenColKeysRef,\n      leftFixedColumnsRef,\n      rightFixedColumnsRef,\n      fixedColumnLeftMapRef,\n      fixedColumnRightMapRef,\n      mergedCurrentPageRef,\n      someRowsCheckedRef,\n      allRowsCheckedRef,\n      mergedSortStateRef,\n      mergedFilterStateRef,\n      loadingRef: toRef(props, 'loading'),\n      rowClassNameRef: toRef(props, 'rowClassName'),\n      mergedCheckedRowKeySetRef,\n      mergedExpandedRowKeysRef,\n      mergedInderminateRowKeySetRef,\n      localeRef,\n      expandableRef,\n      stickyExpandedRowsRef,\n      rowKeyRef: toRef(props, 'rowKey'),\n      renderExpandRef,\n      summaryRef: toRef(props, 'summary'),\n      virtualScrollRef: toRef(props, 'virtualScroll'),\n      virtualScrollXRef: toRef(props, 'virtualScrollX'),\n      heightForRowRef: toRef(props, 'heightForRow'),\n      minRowHeightRef: toRef(props, 'minRowHeight'),\n      virtualScrollHeaderRef: toRef(props, 'virtualScrollHeader'),\n      headerHeightRef: toRef(props, 'headerHeight'),\n      rowPropsRef: toRef(props, 'rowProps'),\n      stripedRef: toRef(props, 'striped'),\n      checkOptionsRef: computed(() => {\n        const { value: selectionColumn } = selectionColumnRef\n        return selectionColumn?.options\n      }),\n      rawPaginatedDataRef,\n      filterMenuCssVarsRef: computed(() => {\n        const {\n          self: { actionDividerColor, actionPadding, actionButtonMargin }\n        } = themeRef.value\n        return {\n          '--n-action-padding': actionPadding,\n          '--n-action-button-margin': actionButtonMargin,\n          '--n-action-divider-color': actionDividerColor\n        } satisfies CSSProperties\n      }),\n      onLoadRef: toRef(props, 'onLoad'),\n      mergedTableLayoutRef,\n      maxHeightRef,\n      minHeightRef: toRef(props, 'minHeight'),\n      flexHeightRef: toRef(props, 'flexHeight'),\n      headerCheckboxDisabledRef,\n      paginationBehaviorOnFilterRef: toRef(props, 'paginationBehaviorOnFilter'),\n      summaryPlacementRef: toRef(props, 'summaryPlacement'),\n      filterIconPopoverPropsRef: toRef(props, 'filterIconPopoverProps'),\n      scrollbarPropsRef: toRef(props, 'scrollbarProps'),\n      syncScrollState,\n      doUpdatePage,\n      doUpdateFilters,\n      getResizableWidth,\n      onUnstableColumnResize,\n      clearResizableWidth,\n      doUpdateResizableWidth,\n      deriveNextSorter,\n      doCheck,\n      doUncheck,\n      doCheckAll,\n      doUncheckAll,\n      doUpdateExpandedRowKeys,\n      handleTableHeaderScroll,\n      handleTableBodyScroll,\n      setHeaderScrollLeft,\n      renderCell: toRef(props, 'renderCell')\n    })\n    const exposedMethods: DataTableInst = {\n      filter,\n      filters,\n      clearFilters,\n      clearSorter,\n      page,\n      sort,\n      clearFilter,\n      downloadCsv,\n      scrollTo: (arg0: any, arg1?: any) => {\n        mainTableInstRef.value?.scrollTo(arg0, arg1)\n      }\n    }\n    const cssVarsRef = computed(() => {\n      const mergedSize = mergedSizeRef.value\n      const {\n        common: { cubicBezierEaseInOut },\n        self: {\n          borderColor,\n          tdColorHover,\n          tdColorSorting,\n          tdColorSortingModal,\n          tdColorSortingPopover,\n          thColorSorting,\n          thColorSortingModal,\n          thColorSortingPopover,\n          thColor,\n          thColorHover,\n          tdColor,\n          tdTextColor,\n          thTextColor,\n          thFontWeight,\n          thButtonColorHover,\n          thIconColor,\n          thIconColorActive,\n          filterSize,\n          borderRadius,\n          lineHeight,\n          tdColorModal,\n          thColorModal,\n          borderColorModal,\n          thColorHoverModal,\n          tdColorHoverModal,\n          borderColorPopover,\n          thColorPopover,\n          tdColorPopover,\n          tdColorHoverPopover,\n          thColorHoverPopover,\n          paginationMargin,\n          emptyPadding,\n          boxShadowAfter,\n          boxShadowBefore,\n          sorterSize,\n          resizableContainerSize,\n          resizableSize,\n          loadingColor,\n          loadingSize,\n          opacityLoading,\n          tdColorStriped,\n          tdColorStripedModal,\n          tdColorStripedPopover,\n          [createKey('fontSize', mergedSize)]: fontSize,\n          [createKey('thPadding', mergedSize)]: thPadding,\n          [createKey('tdPadding', mergedSize)]: tdPadding\n        }\n      } = themeRef.value\n      return {\n        '--n-font-size': fontSize,\n        '--n-th-padding': thPadding,\n        '--n-td-padding': tdPadding,\n        '--n-bezier': cubicBezierEaseInOut,\n        '--n-border-radius': borderRadius,\n        '--n-line-height': lineHeight,\n        '--n-border-color': borderColor,\n        '--n-border-color-modal': borderColorModal,\n        '--n-border-color-popover': borderColorPopover,\n        '--n-th-color': thColor,\n        '--n-th-color-hover': thColorHover,\n        '--n-th-color-modal': thColorModal,\n        '--n-th-color-hover-modal': thColorHoverModal,\n        '--n-th-color-popover': thColorPopover,\n        '--n-th-color-hover-popover': thColorHoverPopover,\n        '--n-td-color': tdColor,\n        '--n-td-color-hover': tdColorHover,\n        '--n-td-color-modal': tdColorModal,\n        '--n-td-color-hover-modal': tdColorHoverModal,\n        '--n-td-color-popover': tdColorPopover,\n        '--n-td-color-hover-popover': tdColorHoverPopover,\n        '--n-th-text-color': thTextColor,\n        '--n-td-text-color': tdTextColor,\n        '--n-th-font-weight': thFontWeight,\n        '--n-th-button-color-hover': thButtonColorHover,\n        '--n-th-icon-color': thIconColor,\n        '--n-th-icon-color-active': thIconColorActive,\n        '--n-filter-size': filterSize,\n        '--n-pagination-margin': paginationMargin,\n        '--n-empty-padding': emptyPadding,\n        '--n-box-shadow-before': boxShadowBefore,\n        '--n-box-shadow-after': boxShadowAfter,\n        '--n-sorter-size': sorterSize,\n        '--n-resizable-container-size': resizableContainerSize,\n        '--n-resizable-size': resizableSize,\n        '--n-loading-size': loadingSize,\n        '--n-loading-color': loadingColor,\n        '--n-opacity-loading': opacityLoading,\n        '--n-td-color-striped': tdColorStriped,\n        '--n-td-color-striped-modal': tdColorStripedModal,\n        '--n-td-color-striped-popover': tdColorStripedPopover,\n        '--n-td-color-sorting': tdColorSorting,\n        '--n-td-color-sorting-modal': tdColorSortingModal,\n        '--n-td-color-sorting-popover': tdColorSortingPopover,\n        '--n-th-color-sorting': thColorSorting,\n        '--n-th-color-sorting-modal': thColorSortingModal,\n        '--n-th-color-sorting-popover': thColorSortingPopover\n      }\n    })\n    const themeClassHandle = inlineThemeDisabled\n      ? useThemeClass(\n          'data-table',\n          computed(() => mergedSizeRef.value[0]),\n          cssVarsRef,\n          props\n        )\n      : undefined\n    const mergedShowPaginationRef = computed(() => {\n      if (!props.pagination)\n        return false\n      if (props.paginateSinglePage)\n        return true\n      const mergedPagination = mergedPaginationRef.value\n      const { pageCount } = mergedPagination\n      if (pageCount !== undefined)\n        return pageCount > 1\n      return (\n        mergedPagination.itemCount\n        && mergedPagination.pageSize\n        && mergedPagination.itemCount > mergedPagination.pageSize\n      )\n    })\n    return {\n      mainTableInstRef,\n      mergedClsPrefix: mergedClsPrefixRef,\n      rtlEnabled: rtlEnabledRef,\n      mergedTheme: themeRef,\n      paginatedData: paginatedDataRef,\n      mergedBordered: mergedBorderedRef,\n      mergedBottomBordered: mergedBottomBorderedRef,\n      mergedPagination: mergedPaginationRef,\n      mergedShowPagination: mergedShowPaginationRef,\n      cssVars: inlineThemeDisabled ? undefined : cssVarsRef,\n      themeClass: themeClassHandle?.themeClass,\n      onRender: themeClassHandle?.onRender,\n      ...exposedMethods\n    }\n  },\n  render() {\n    const { mergedClsPrefix, themeClass, onRender, $slots, spinProps } = this\n    onRender?.()\n    return (\n      <div\n        class={[\n          `${mergedClsPrefix}-data-table`,\n          this.rtlEnabled && `${mergedClsPrefix}-data-table--rtl`,\n          themeClass,\n          {\n            [`${mergedClsPrefix}-data-table--bordered`]: this.mergedBordered,\n            [`${mergedClsPrefix}-data-table--bottom-bordered`]:\n              this.mergedBottomBordered,\n            [`${mergedClsPrefix}-data-table--single-line`]: this.singleLine,\n            [`${mergedClsPrefix}-data-table--single-column`]: this.singleColumn,\n            [`${mergedClsPrefix}-data-table--loading`]: this.loading,\n            [`${mergedClsPrefix}-data-table--flex-height`]: this.flexHeight\n          }\n        ]}\n        style={this.cssVars as CSSProperties}\n      >\n        <div class={`${mergedClsPrefix}-data-table-wrapper`}>\n          <MainTable ref=\"mainTableInstRef\" />\n        </div>\n        {this.mergedShowPagination ? (\n          <div class={`${mergedClsPrefix}-data-table__pagination`}>\n            <NPagination\n              theme={this.mergedTheme.peers.Pagination}\n              themeOverrides={this.mergedTheme.peerOverrides.Pagination}\n              disabled={this.loading}\n              {...this.mergedPagination}\n            />\n          </div>\n        ) : null}\n        <Transition name=\"fade-in-scale-up-transition\">\n          {{\n            default: () => {\n              return this.loading ? (\n                <div class={`${mergedClsPrefix}-data-table-loading-wrapper`}>\n                  {resolveSlot($slots.loading, () => [\n                    <NBaseLoading\n                      clsPrefix={mergedClsPrefix}\n                      strokeWidth={20}\n                      {...spinProps}\n                    />\n                  ])}\n                </div>\n              ) : null\n            }\n          }}\n        </Transition>\n      </div>\n    )\n  }\n})\n"
  },
  {
    "path": "src/data-table/src/HeaderButton/FilterButton.tsx",
    "content": "import type { PropType } from 'vue'\nimport type {\n  ColumnKey,\n  FilterOption,\n  FilterOptionValue,\n  FilterState,\n  TableBaseColumn\n} from '../interface'\nimport { computed, defineComponent, h, inject, ref } from 'vue'\nimport { NBaseIcon } from '../../../_internal'\nimport { FilterIcon } from '../../../_internal/icons'\nimport { useConfig } from '../../../_mixins'\nimport { NPopover } from '../../../popover'\nimport { dataTableInjectionKey } from '../interface'\nimport NDataTableFilterMenu from './FilterMenu'\nimport RenderFilter from './RenderFilter'\n\nfunction createFilterState(\n  currentFilterState: FilterState,\n  columnKey: ColumnKey,\n  mergedFilterValue: FilterOptionValue | FilterOptionValue[] | null\n): FilterState {\n  const nextFilterState = Object.assign({}, currentFilterState)\n  nextFilterState[columnKey] = mergedFilterValue\n  return nextFilterState\n}\n\nexport default defineComponent({\n  name: 'DataTableFilterButton',\n  props: {\n    column: {\n      type: Object as PropType<TableBaseColumn>,\n      required: true\n    },\n    options: {\n      type: Array as PropType<FilterOption[]>,\n      default: () => []\n    }\n  },\n  setup(props) {\n    const { mergedComponentPropsRef } = useConfig()\n    const {\n      mergedThemeRef,\n      mergedClsPrefixRef,\n      mergedFilterStateRef,\n      filterMenuCssVarsRef,\n      paginationBehaviorOnFilterRef,\n      doUpdatePage,\n      doUpdateFilters,\n      filterIconPopoverPropsRef\n    } = inject(dataTableInjectionKey)!\n    const showPopoverRef = ref(false)\n    const filterStateRef = mergedFilterStateRef\n    const filterMultipleRef = computed(() => {\n      return props.column.filterMultiple !== false\n    })\n    const mergedFilterValueRef = computed(() => {\n      const filterValue = filterStateRef.value[props.column.key]\n      if (filterValue === undefined) {\n        const { value: multiple } = filterMultipleRef\n        if (multiple)\n          return []\n        else return null\n      }\n      return filterValue\n    })\n    const activeRef = computed(() => {\n      const { value: filterValue } = mergedFilterValueRef\n      if (Array.isArray(filterValue)) {\n        return filterValue.length > 0\n      }\n      return filterValue !== null\n    })\n    const mergedRenderFilterRef = computed(() => {\n      return (\n        mergedComponentPropsRef?.value?.DataTable?.renderFilter\n        || props.column.renderFilter\n      )\n    })\n    function handleFilterChange(\n      mergedFilterValue: FilterOptionValue | FilterOptionValue[] | null\n    ): void {\n      const nextFilterState = createFilterState(\n        filterStateRef.value,\n        props.column.key,\n        mergedFilterValue\n      )\n      doUpdateFilters(nextFilterState, props.column)\n      if (paginationBehaviorOnFilterRef.value === 'first') {\n        doUpdatePage(1)\n      }\n    }\n    function handleFilterMenuCancel(): void {\n      showPopoverRef.value = false\n    }\n    function handleFilterMenuConfirm(): void {\n      showPopoverRef.value = false\n    }\n    return {\n      mergedTheme: mergedThemeRef,\n      mergedClsPrefix: mergedClsPrefixRef,\n      active: activeRef,\n      showPopover: showPopoverRef,\n      mergedRenderFilter: mergedRenderFilterRef,\n      filterIconPopoverProps: filterIconPopoverPropsRef,\n      filterMultiple: filterMultipleRef,\n      mergedFilterValue: mergedFilterValueRef,\n      filterMenuCssVars: filterMenuCssVarsRef,\n      handleFilterChange,\n      handleFilterMenuConfirm,\n      handleFilterMenuCancel\n    }\n  },\n  render() {\n    const {\n      mergedTheme,\n      mergedClsPrefix,\n      handleFilterMenuCancel,\n      filterIconPopoverProps\n    } = this\n    return (\n      <NPopover\n        show={this.showPopover}\n        onUpdateShow={v => (this.showPopover = v)}\n        trigger=\"click\"\n        theme={mergedTheme.peers.Popover}\n        themeOverrides={mergedTheme.peerOverrides.Popover}\n        placement=\"bottom\"\n        {...filterIconPopoverProps}\n        style={{ padding: 0 }}\n      >\n        {{\n          trigger: () => {\n            const { mergedRenderFilter } = this\n            if (mergedRenderFilter) {\n              return (\n                <RenderFilter\n                  data-data-table-filter\n                  render={mergedRenderFilter}\n                  active={this.active}\n                  show={this.showPopover}\n                />\n              )\n            }\n            const { renderFilterIcon } = this.column\n            return (\n              <div\n                data-data-table-filter\n                class={[\n                  `${mergedClsPrefix}-data-table-filter`,\n                  {\n                    [`${mergedClsPrefix}-data-table-filter--active`]:\n                      this.active,\n                    [`${mergedClsPrefix}-data-table-filter--show`]:\n                      this.showPopover\n                  }\n                ]}\n              >\n                {renderFilterIcon ? (\n                  renderFilterIcon({\n                    active: this.active,\n                    show: this.showPopover\n                  })\n                ) : (\n                  <NBaseIcon clsPrefix={mergedClsPrefix}>\n                    {{ default: () => <FilterIcon /> }}\n                  </NBaseIcon>\n                )}\n              </div>\n            )\n          },\n          default: () => {\n            const { renderFilterMenu } = this.column\n            return renderFilterMenu ? (\n              renderFilterMenu({ hide: handleFilterMenuCancel })\n            ) : (\n              <NDataTableFilterMenu\n                style={this.filterMenuCssVars}\n                radioGroupName={String(this.column.key)}\n                multiple={this.filterMultiple}\n                value={this.mergedFilterValue}\n                options={this.options}\n                column={this.column}\n                onChange={this.handleFilterChange}\n                onClear={this.handleFilterMenuCancel}\n                onConfirm={this.handleFilterMenuConfirm}\n              />\n            )\n          }\n        }}\n      </NPopover>\n    )\n  }\n})\n"
  },
  {
    "path": "src/data-table/src/HeaderButton/FilterMenu.tsx",
    "content": "import type { PropType } from 'vue'\nimport type {\n  FilterOption,\n  FilterOptionValue,\n  OnFilterMenuChange,\n  OnFilterMenuChangeImpl,\n  TableBaseColumn\n} from '../interface'\nimport { computed, defineComponent, h, inject, ref } from 'vue'\nimport { NScrollbar } from '../../../_internal'\nimport { useConfig, useRtl } from '../../../_mixins'\nimport { NButton } from '../../../button'\nimport { NCheckbox, NCheckboxGroup } from '../../../checkbox'\nimport { NRadio, NRadioGroup } from '../../../radio'\nimport { dataTableInjectionKey } from '../interface'\nimport { shouldUseArrayInSingleMode } from '../utils'\n\nexport default defineComponent({\n  name: 'DataTableFilterMenu',\n  props: {\n    column: {\n      type: Object as PropType<TableBaseColumn>,\n      required: true\n    },\n    radioGroupName: {\n      type: String,\n      required: true\n    },\n    multiple: {\n      type: Boolean,\n      required: true\n    },\n    value: {\n      type: [Array, String, Number] as PropType<\n        FilterOptionValue | FilterOptionValue[] | null\n      >,\n      default: null\n    },\n    options: {\n      type: Array as PropType<FilterOption[]>,\n      required: true\n    },\n    onConfirm: {\n      type: Function as PropType<() => void>,\n      required: true\n    },\n    onClear: {\n      type: Function as PropType<() => void>,\n      required: true\n    },\n    onChange: {\n      type: Function as PropType<OnFilterMenuChange>,\n      required: true\n    }\n  },\n  setup(props) {\n    const { mergedClsPrefixRef: mergedClsPrefixRefRtl, mergedRtlRef }\n      = useConfig(props)\n    const rtlEnabledRef = useRtl(\n      'DataTable',\n      mergedRtlRef,\n      mergedClsPrefixRefRtl\n    )\n\n    const { mergedClsPrefixRef, mergedThemeRef, localeRef } = inject(\n      dataTableInjectionKey\n    )!\n    // to be compared with changed value\n    // const initialValueRef = ref(props.value)\n    const temporalValueRef = ref(props.value)\n    const checkboxGroupValueRef = computed(() => {\n      const { value: temporalValue } = temporalValueRef\n      if (!Array.isArray(temporalValue))\n        return null\n      return temporalValue\n    })\n    const radioGroupValueRef = computed(() => {\n      const { value: temporalValue } = temporalValueRef\n      if (shouldUseArrayInSingleMode(props.column)) {\n        return (\n          (Array.isArray(temporalValue)\n            && temporalValue.length\n            && temporalValue[0])\n          || null\n        )\n      }\n      if (!Array.isArray(temporalValue))\n        return temporalValue\n      return null\n    })\n    function doChange(\n      value: FilterOptionValue | FilterOptionValue[] | null\n    ): void {\n      // May need to check if equal\n      ;(props.onChange as OnFilterMenuChangeImpl)(value)\n    }\n    function handleChange(\n      value: FilterOptionValue | FilterOptionValue[]\n    ): void {\n      if (props.multiple && Array.isArray(value)) {\n        temporalValueRef.value = value\n      }\n      else if (\n        shouldUseArrayInSingleMode(props.column)\n        && !Array.isArray(value)\n      ) {\n        /** this branch is for compatibility */\n        temporalValueRef.value = [value]\n      }\n      else {\n        temporalValueRef.value = value\n      }\n    }\n    function handleConfirmClick(): void {\n      doChange(temporalValueRef.value)\n      props.onConfirm()\n    }\n    function handleClearClick(): void {\n      if (props.multiple || shouldUseArrayInSingleMode(props.column)) {\n        doChange([])\n      }\n      else {\n        doChange(null)\n      }\n      props.onClear()\n    }\n    return {\n      mergedClsPrefix: mergedClsPrefixRef,\n      rtlEnabled: rtlEnabledRef,\n      mergedTheme: mergedThemeRef,\n      locale: localeRef,\n      checkboxGroupValue: checkboxGroupValueRef,\n      radioGroupValue: radioGroupValueRef,\n      handleChange,\n      handleConfirmClick,\n      handleClearClick\n    }\n  },\n  render() {\n    const { mergedTheme, locale, mergedClsPrefix } = this\n    return (\n      <div\n        class={[\n          `${mergedClsPrefix}-data-table-filter-menu`,\n          this.rtlEnabled && `${mergedClsPrefix}-data-table-filter-menu--rtl`\n        ]}\n      >\n        <NScrollbar>\n          {{\n            default: () => {\n              const { checkboxGroupValue, handleChange } = this\n              return this.multiple ? (\n                <NCheckboxGroup\n                  value={checkboxGroupValue}\n                  class={`${mergedClsPrefix}-data-table-filter-menu__group`}\n                  onUpdateValue={handleChange}\n                >\n                  {{\n                    default: () =>\n                      this.options.map((option) => {\n                        return (\n                          <NCheckbox\n                            key={option.value}\n                            theme={mergedTheme.peers.Checkbox}\n                            themeOverrides={mergedTheme.peerOverrides.Checkbox}\n                            value={option.value}\n                          >\n                            {{ default: () => option.label }}\n                          </NCheckbox>\n                        )\n                      })\n                  }}\n                </NCheckboxGroup>\n              ) : (\n                <NRadioGroup\n                  name={this.radioGroupName}\n                  class={`${mergedClsPrefix}-data-table-filter-menu__group`}\n                  value={this.radioGroupValue}\n                  onUpdateValue={this.handleChange}\n                >\n                  {{\n                    default: () =>\n                      this.options.map(option => (\n                        <NRadio\n                          key={option.value}\n                          value={option.value}\n                          theme={mergedTheme.peers.Radio}\n                          themeOverrides={mergedTheme.peerOverrides.Radio}\n                        >\n                          {{ default: () => option.label }}\n                        </NRadio>\n                      ))\n                  }}\n                </NRadioGroup>\n              )\n            }\n          }}\n        </NScrollbar>\n        <div class={`${mergedClsPrefix}-data-table-filter-menu__action`}>\n          <NButton\n            size=\"tiny\"\n            theme={mergedTheme.peers.Button}\n            themeOverrides={mergedTheme.peerOverrides.Button}\n            onClick={this.handleClearClick}\n          >\n            {{ default: () => locale.clear }}\n          </NButton>\n          <NButton\n            theme={mergedTheme.peers.Button}\n            themeOverrides={mergedTheme.peerOverrides.Button}\n            type=\"primary\"\n            size=\"tiny\"\n            onClick={this.handleConfirmClick}\n          >\n            {{ default: () => locale.confirm }}\n          </NButton>\n        </div>\n      </div>\n    )\n  }\n})\n"
  },
  {
    "path": "src/data-table/src/HeaderButton/RenderFilter.ts",
    "content": "import type { PropType } from 'vue'\nimport type { RenderFilter } from '../interface'\nimport { defineComponent } from 'vue'\n\nexport default defineComponent({\n  name: 'DataTableRenderFilter',\n  props: {\n    render: {\n      type: Function as PropType<RenderFilter>,\n      required: true\n    },\n    active: {\n      type: Boolean,\n      default: false\n    },\n    show: {\n      type: Boolean,\n      default: false\n    }\n  },\n  render() {\n    const { render, active, show } = this\n    return render({\n      active,\n      show\n    })\n  }\n})\n"
  },
  {
    "path": "src/data-table/src/HeaderButton/RenderSorter.ts",
    "content": "import type { PropType } from 'vue'\nimport type { RenderSorter, SortOrder } from '../interface'\nimport { defineComponent } from 'vue'\n\nexport default defineComponent({\n  name: 'DataTableRenderSorter',\n  props: {\n    render: {\n      type: Function as PropType<RenderSorter>,\n      required: true\n    },\n    order: {\n      // asc, desc\n      type: [String, Boolean] as PropType<SortOrder>,\n      default: false\n    }\n  },\n  render() {\n    const { render, order } = this\n    return render({\n      order\n    })\n  }\n})\n"
  },
  {
    "path": "src/data-table/src/HeaderButton/ResizeButton.tsx",
    "content": "import type { PropType } from 'vue'\nimport { off, on } from 'evtd'\nimport { defineComponent, h, inject, onBeforeUnmount, ref } from 'vue'\nimport { dataTableInjectionKey } from '../interface'\n\nexport default defineComponent({\n  name: 'ColumnResizeButton',\n  props: {\n    onResizeStart: Function,\n    onResize: Function as PropType<(displacementX: number) => void>,\n    onResizeEnd: Function\n  },\n  setup(props) {\n    const { mergedClsPrefixRef } = inject(dataTableInjectionKey)!\n    const activeRef = ref(false)\n    let startX = 0\n    function getMouseX(e: MouseEvent): number {\n      return e.clientX\n    }\n    function handleMousedown(e: MouseEvent): void {\n      e.preventDefault()\n      const alreadyStarted = activeRef.value\n      startX = getMouseX(e)\n      activeRef.value = true\n      if (!alreadyStarted) {\n        on('mousemove', window, handleMousemove)\n        on('mouseup', window, handleMouseup)\n        props.onResizeStart?.()\n      }\n    }\n    function handleMousemove(e: MouseEvent): void {\n      props.onResize?.(getMouseX(e) - startX)\n    }\n    function handleMouseup(): void {\n      activeRef.value = false\n      props.onResizeEnd?.()\n      off('mousemove', window, handleMousemove)\n      off('mouseup', window, handleMouseup)\n    }\n    onBeforeUnmount(() => {\n      off('mousemove', window, handleMousemove)\n      off('mouseup', window, handleMouseup)\n    })\n    return {\n      mergedClsPrefix: mergedClsPrefixRef,\n      active: activeRef,\n      handleMousedown\n    }\n  },\n  render() {\n    const { mergedClsPrefix } = this\n    return (\n      <span\n        data-data-table-resizable\n        class={[\n          `${mergedClsPrefix}-data-table-resize-button`,\n          this.active && `${mergedClsPrefix}-data-table-resize-button--active`\n        ]}\n        onMousedown={this.handleMousedown}\n      />\n    )\n  }\n})\n"
  },
  {
    "path": "src/data-table/src/HeaderButton/SortButton.tsx",
    "content": "import type { PropType } from 'vue'\nimport type { TableBaseColumn } from '../interface'\nimport { computed, defineComponent, h, inject } from 'vue'\nimport { NBaseIcon } from '../../../_internal'\nimport { ArrowDownIcon } from '../../../_internal/icons'\nimport { useConfig } from '../../../_mixins'\nimport { dataTableInjectionKey } from '../interface'\nimport RenderSorter from './RenderSorter'\n\nexport default defineComponent({\n  name: 'SortIcon',\n  props: {\n    column: {\n      type: Object as PropType<TableBaseColumn>,\n      required: true\n    }\n  },\n  setup(props) {\n    const { mergedComponentPropsRef } = useConfig()\n    const { mergedSortStateRef, mergedClsPrefixRef } = inject(\n      dataTableInjectionKey\n    )!\n    const sortStateRef = computed(() =>\n      mergedSortStateRef.value.find(\n        state => state.columnKey === props.column.key\n      )\n    )\n\n    const activeRef = computed(() => {\n      return sortStateRef.value !== undefined\n    })\n    const mergedSortOrderRef = computed(() => {\n      const { value: sortState } = sortStateRef\n      if (sortState && activeRef.value) {\n        return sortState.order\n      }\n      return false\n    })\n    const mergedRenderSorterRef = computed(() => {\n      return (\n        mergedComponentPropsRef?.value?.DataTable?.renderSorter\n        || props.column.renderSorter\n      )\n    })\n    return {\n      mergedClsPrefix: mergedClsPrefixRef,\n      active: activeRef,\n      mergedSortOrder: mergedSortOrderRef,\n      mergedRenderSorter: mergedRenderSorterRef\n    }\n  },\n  render() {\n    const { mergedRenderSorter, mergedSortOrder, mergedClsPrefix } = this\n    const { renderSorterIcon } = this.column\n    return mergedRenderSorter ? (\n      <RenderSorter render={mergedRenderSorter} order={mergedSortOrder} />\n    ) : (\n      <span\n        class={[\n          `${mergedClsPrefix}-data-table-sorter`,\n          mergedSortOrder === 'ascend'\n          && `${mergedClsPrefix}-data-table-sorter--asc`,\n          mergedSortOrder === 'descend'\n          && `${mergedClsPrefix}-data-table-sorter--desc`\n        ]}\n      >\n        {renderSorterIcon ? (\n          renderSorterIcon({ order: mergedSortOrder })\n        ) : (\n          <NBaseIcon clsPrefix={mergedClsPrefix}>\n            {{ default: () => <ArrowDownIcon /> }}\n          </NBaseIcon>\n        )}\n      </span>\n    )\n  }\n})\n"
  },
  {
    "path": "src/data-table/src/MainTable.tsx",
    "content": "import type {\n  MainTableBodyRef,\n  MainTableHeaderRef,\n  MainTableRef\n} from './interface'\nimport { computed, defineComponent, h, inject, ref, watchEffect } from 'vue'\nimport { formatLength } from '../../_utils'\nimport { dataTableInjectionKey } from './interface'\nimport TableBody from './TableParts/Body'\nimport TableHeader from './TableParts/Header'\n\nexport default defineComponent({\n  name: 'MainTable',\n  setup() {\n    const {\n      mergedClsPrefixRef,\n      rightFixedColumnsRef,\n      leftFixedColumnsRef,\n      bodyWidthRef,\n      maxHeightRef,\n      minHeightRef,\n      flexHeightRef,\n      virtualScrollHeaderRef,\n      syncScrollState,\n      scrollXRef\n    } = inject(dataTableInjectionKey)!\n\n    const headerInstRef = ref<MainTableHeaderRef | null>(null)\n    const bodyInstRef = ref<MainTableBodyRef | null>(null)\n    const selfElRef = ref<HTMLElement | null>(null)\n\n    const fixedStateInitializedRef = ref(\n      !(leftFixedColumnsRef.value.length || rightFixedColumnsRef.value.length)\n    )\n\n    const bodyStyleRef = computed(() => {\n      return {\n        maxHeight: formatLength(maxHeightRef.value),\n        minHeight: formatLength(minHeightRef.value)\n      }\n    })\n    function handleBodyResize(entry: ResizeObserverEntry): void {\n      bodyWidthRef.value = entry.contentRect.width\n      syncScrollState()\n      if (!fixedStateInitializedRef.value) {\n        fixedStateInitializedRef.value = true\n      }\n    }\n    function getHeaderElement(): HTMLElement | null {\n      const { value } = headerInstRef\n      if (value) {\n        if (virtualScrollHeaderRef.value) {\n          return value.virtualListRef?.listElRef || null\n        }\n        else {\n          return value.$el\n        }\n      }\n      return null\n    }\n    function getBodyElement(): HTMLElement | null {\n      const { value } = bodyInstRef\n      if (value) {\n        return value.getScrollContainer()\n      }\n      return null\n    }\n    const exposedMethods: MainTableRef = {\n      getBodyElement,\n      getHeaderElement,\n      scrollTo(arg0: any, arg1?: any) {\n        bodyInstRef.value?.scrollTo(arg0, arg1)\n      }\n    }\n    watchEffect(() => {\n      const { value: selfEl } = selfElRef\n      if (!selfEl)\n        return\n      const transitionDisabledClass = `${mergedClsPrefixRef.value}-data-table-base-table--transition-disabled`\n      if (fixedStateInitializedRef.value) {\n        setTimeout(() => {\n          selfEl.classList.remove(transitionDisabledClass)\n        }, 0)\n      }\n      else {\n        selfEl.classList.add(transitionDisabledClass)\n      }\n    })\n    return {\n      maxHeight: maxHeightRef,\n      mergedClsPrefix: mergedClsPrefixRef,\n      selfElRef,\n      headerInstRef,\n      bodyInstRef,\n      bodyStyle: bodyStyleRef,\n      flexHeight: flexHeightRef,\n      handleBodyResize,\n      scrollX: scrollXRef,\n      ...exposedMethods\n    }\n  },\n  render() {\n    const { mergedClsPrefix, maxHeight, flexHeight } = this\n    const headerInBody = maxHeight === undefined && !flexHeight\n    return (\n      <div class={`${mergedClsPrefix}-data-table-base-table`} ref=\"selfElRef\">\n        {headerInBody ? null : <TableHeader ref=\"headerInstRef\" />}\n        <TableBody\n          ref=\"bodyInstRef\"\n          bodyStyle={this.bodyStyle}\n          showHeader={headerInBody}\n          flexHeight={flexHeight}\n          onResize={this.handleBodyResize}\n        />\n      </div>\n    )\n  }\n})\n"
  },
  {
    "path": "src/data-table/src/TableParts/Body.tsx",
    "content": "import type { CNode } from 'css-render'\nimport type { CSSProperties, PropType, VNode, VNodeChild } from 'vue'\nimport type { VirtualListInst } from 'vueuc'\nimport type { ScrollbarInst } from '../../../_internal'\nimport type {\n  ColumnKey,\n  MainTableBodyRef,\n  RowData,\n  RowKey,\n  SummaryRowData,\n  TmNode\n} from '../interface'\nimport type { ColItem } from '../use-group-header'\nimport { pxfy, repeat } from 'seemly'\nimport { useMemo } from 'vooks'\nimport {\n  computed,\n  defineComponent,\n  Fragment,\n  h,\n  inject,\n  onUnmounted,\n  ref,\n  watchEffect\n} from 'vue'\nimport { VirtualList, VResizeObserver } from 'vueuc'\nimport { NScrollbar } from '../../../_internal'\nimport { cssrAnchorMetaName } from '../../../_mixins/common'\nimport { formatLength, resolveSlot, warn } from '../../../_utils'\nimport { c } from '../../../_utils/cssr'\nimport { configProviderInjectionKey } from '../../../config-provider/src/context'\nimport { NEmpty } from '../../../empty'\nimport { dataTableInjectionKey } from '../interface'\nimport { createRowClassName, getColKey, isColumnSorting } from '../utils'\nimport RenderSafeCheckbox from './BodyCheckbox'\nimport RenderSafeRadio from './BodyRadio'\nimport Cell from './Cell'\nimport ExpandTrigger from './ExpandTrigger'\nimport TableHeader from './Header'\n\ninterface StyleCProps {\n  leftActiveFixedColKey: ColumnKey | null\n  leftActiveFixedChildrenColKeys: ColumnKey[]\n  rightActiveFixedColKey: ColumnKey | null\n  rightActiveFixedChildrenColKeys: ColumnKey[]\n  componentId: string\n}\n\ninterface NormalRowRenderInfo {\n  striped: boolean\n  tmNode: TmNode\n  key: RowKey\n  index: number\n}\n\ntype RowRenderInfo\n  = | {\n    isSummaryRow: true\n    key: RowKey\n    tmNode: {\n      rawNode: SummaryRowData\n      disabled: boolean\n    }\n    index: number\n  }\n  | NormalRowRenderInfo\n  | {\n    isExpandedRow: true\n    tmNode: TmNode\n    key: RowKey\n    index: number\n  }\n\nfunction flatten(\n  rowInfos: NormalRowRenderInfo[],\n  expandedRowKeys: Set<RowKey>\n): NormalRowRenderInfo[] {\n  const fRows: NormalRowRenderInfo[] = []\n  function traverse(rs: TmNode[], rootIndex: number): void {\n    rs.forEach((r) => {\n      if (r.children && expandedRowKeys.has(r.key)) {\n        fRows.push({\n          tmNode: r,\n          striped: false,\n          key: r.key,\n          index: rootIndex\n        })\n        traverse(r.children, rootIndex)\n      }\n      else {\n        fRows.push({\n          key: r.key,\n          tmNode: r,\n          striped: false,\n          index: rootIndex\n        })\n      }\n    })\n  }\n  rowInfos.forEach((rowInfo) => {\n    fRows.push(rowInfo)\n    const { children } = rowInfo.tmNode\n    if (children && expandedRowKeys.has(rowInfo.key)) {\n      traverse(children, rowInfo.index)\n    }\n  })\n  return fRows\n}\n\nconst VirtualListItemWrapper = defineComponent({\n  props: {\n    clsPrefix: {\n      type: String,\n      required: true\n    },\n    id: {\n      type: String,\n      required: true\n    },\n    cols: {\n      type: Array as PropType<ColItem[]>,\n      required: true\n    },\n    onMouseenter: Function as PropType<(e: MouseEvent) => void>,\n    onMouseleave: Function as PropType<(e: MouseEvent) => void>\n  },\n  render() {\n    const { clsPrefix, id, cols, onMouseenter, onMouseleave } = this\n    return (\n      <table\n        style={{ tableLayout: 'fixed' }}\n        class={`${clsPrefix}-data-table-table`}\n        onMouseenter={onMouseenter}\n        onMouseleave={onMouseleave}\n      >\n        <colgroup>\n          {cols.map(col => (\n            <col key={col.key} style={col.style}></col>\n          ))}\n        </colgroup>\n        <tbody data-n-id={id} class={`${clsPrefix}-data-table-tbody`}>\n          {this.$slots}\n        </tbody>\n      </table>\n    )\n  }\n})\n\nexport default defineComponent({\n  name: 'DataTableBody',\n  props: {\n    onResize: Function as PropType<(e: ResizeObserverEntry) => void>,\n    showHeader: Boolean,\n    flexHeight: Boolean,\n    bodyStyle: Object as PropType<CSSProperties>\n  },\n  setup(props) {\n    const {\n      slots: dataTableSlots,\n      bodyWidthRef,\n      mergedExpandedRowKeysRef,\n      mergedClsPrefixRef,\n      mergedThemeRef,\n      scrollXRef,\n      colsRef,\n      paginatedDataRef,\n      rawPaginatedDataRef,\n      fixedColumnLeftMapRef,\n      fixedColumnRightMapRef,\n      mergedCurrentPageRef,\n      rowClassNameRef,\n      leftActiveFixedColKeyRef,\n      leftActiveFixedChildrenColKeysRef,\n      rightActiveFixedColKeyRef,\n      rightActiveFixedChildrenColKeysRef,\n      renderExpandRef,\n      hoverKeyRef,\n      summaryRef,\n      mergedSortStateRef,\n      virtualScrollRef,\n      virtualScrollXRef,\n      heightForRowRef,\n      minRowHeightRef,\n      componentId,\n      mergedTableLayoutRef,\n      childTriggerColIndexRef,\n      indentRef,\n      rowPropsRef,\n      stripedRef,\n      loadingRef,\n      onLoadRef,\n      loadingKeySetRef,\n      expandableRef,\n      stickyExpandedRowsRef,\n      renderExpandIconRef,\n      summaryPlacementRef,\n      treeMateRef,\n      scrollbarPropsRef,\n      setHeaderScrollLeft,\n      doUpdateExpandedRowKeys,\n      handleTableBodyScroll,\n      doCheck,\n      doUncheck,\n      renderCell,\n      xScrollableRef,\n      explicitlyScrollableRef\n    } = inject(dataTableInjectionKey)!\n    const NConfigProvider = inject(configProviderInjectionKey)\n    const scrollbarInstRef = ref<ScrollbarInst | null>(null)\n    const virtualListRef = ref<VirtualListInst | null>(null)\n    const emptyElRef = ref<HTMLElement | null>(null)\n    const mergedRenderEmptyRef = computed(() => {\n      return NConfigProvider?.mergedComponentPropsRef.value?.DataTable\n        ?.renderEmpty\n    })\n    const emptyRef = useMemo(() => paginatedDataRef.value.length === 0)\n    const shouldDisplayVirtualListRef = useMemo(\n      () => virtualScrollRef.value && !emptyRef.value\n    )\n    let lastSelectedKey: string | number = ''\n    const mergedExpandedRowKeySetRef = computed(() => {\n      return new Set(mergedExpandedRowKeysRef.value)\n    })\n    function getRowInfo(key: RowKey): RowData | undefined {\n      return treeMateRef.value.getNode(key)?.rawNode\n    }\n    function handleCheckboxUpdateChecked(\n      tmNode: { key: RowKey },\n      checked: boolean,\n      shiftKey: boolean\n    ): void {\n      const rowInfo = getRowInfo(tmNode.key)\n      if (!rowInfo) {\n        warn('data-table', `fail to get row data with key ${tmNode.key}`)\n        return\n      }\n      if (shiftKey) {\n        const lastIndex = paginatedDataRef.value.findIndex(\n          item => item.key === lastSelectedKey\n        )\n        if (lastIndex !== -1) {\n          const currentIndex = paginatedDataRef.value.findIndex(\n            item => item.key === tmNode.key\n          )\n          const start = Math.min(lastIndex, currentIndex)\n          const end = Math.max(lastIndex, currentIndex)\n          const rowKeysToCheck: RowKey[] = []\n          paginatedDataRef.value.slice(start, end + 1).forEach((r) => {\n            if (!r.disabled) {\n              rowKeysToCheck.push(r.key)\n            }\n          })\n          if (checked) {\n            doCheck(rowKeysToCheck, false, rowInfo)\n          }\n          else {\n            doUncheck(rowKeysToCheck, rowInfo)\n          }\n          lastSelectedKey = tmNode.key\n          return\n        }\n      }\n      if (checked) {\n        doCheck(tmNode.key, false, rowInfo)\n      }\n      else {\n        doUncheck(tmNode.key, rowInfo)\n      }\n      lastSelectedKey = tmNode.key\n    }\n\n    function handleRadioUpdateChecked(tmNode: { key: RowKey }): void {\n      const rowInfo = getRowInfo(tmNode.key)\n      if (!rowInfo) {\n        warn('data-table', `fail to get row data with key ${tmNode.key}`)\n        return\n      }\n      doCheck(tmNode.key, true, rowInfo)\n    }\n\n    function getScrollContainer(): HTMLElement | null {\n      if (shouldDisplayVirtualListRef.value) {\n        return virtualListContainer()\n      }\n      const { value } = scrollbarInstRef\n      if (value)\n        return value.containerRef\n      return null\n    }\n    // For table row with children, tmNode is non-nullable\n    // For table row is expandable but is not tree data, tmNode is null\n    function handleUpdateExpanded(key: RowKey, tmNode: TmNode | null): void {\n      if (loadingKeySetRef.value.has(key))\n        return\n      const { value: mergedExpandedRowKeys } = mergedExpandedRowKeysRef\n      const index = mergedExpandedRowKeys.indexOf(key)\n      const nextExpandedKeys = Array.from(mergedExpandedRowKeys)\n      if (~index) {\n        nextExpandedKeys.splice(index, 1)\n        doUpdateExpandedRowKeys(nextExpandedKeys)\n      }\n      else {\n        if (tmNode && !tmNode.isLeaf && !tmNode.shallowLoaded) {\n          loadingKeySetRef.value.add(key)\n          void onLoadRef\n            .value?.(tmNode.rawNode)\n            .then(() => {\n              const { value: futureMergedExpandedRowKeys }\n                = mergedExpandedRowKeysRef\n              const futureNextExpandedKeys = Array.from(\n                futureMergedExpandedRowKeys\n              )\n              const index = futureNextExpandedKeys.indexOf(key)\n              if (!~index) {\n                futureNextExpandedKeys.push(key)\n              }\n              doUpdateExpandedRowKeys(futureNextExpandedKeys)\n            })\n            .finally(() => {\n              loadingKeySetRef.value.delete(key)\n            })\n        }\n        else {\n          nextExpandedKeys.push(key)\n          doUpdateExpandedRowKeys(nextExpandedKeys)\n        }\n      }\n    }\n    function handleMouseleaveTable(): void {\n      hoverKeyRef.value = null\n    }\n    function virtualListContainer(): HTMLElement | null {\n      const { value } = virtualListRef\n      return value?.listElRef || null\n    }\n    function virtualListContent(): HTMLElement | null {\n      const { value } = virtualListRef\n      return value?.itemsElRef || null\n    }\n    function handleVirtualListScroll(e: Event): void {\n      handleTableBodyScroll(e)\n      scrollbarInstRef.value?.sync()\n    }\n    function handleVirtualListResize(e: ResizeObserverEntry): void {\n      const { onResize } = props\n      if (onResize)\n        onResize(e)\n      scrollbarInstRef.value?.sync()\n    }\n    const exposedMethods: MainTableBodyRef = {\n      getScrollContainer,\n      scrollTo(arg0: any, arg1?: any) {\n        if (virtualScrollRef.value) {\n          virtualListRef.value?.scrollTo(arg0, arg1)\n        }\n        else {\n          scrollbarInstRef.value?.scrollTo(arg0, arg1)\n        }\n      }\n    }\n\n    // manually control shadow style to avoid rerender\n    const style = c([\n      ({ props: cProps }: { props: StyleCProps }) => {\n        const createActiveLeftFixedStyle = (\n          leftActiveFixedColKey: ColumnKey | null\n        ): CNode | null => {\n          if (leftActiveFixedColKey === null)\n            return null\n          return c(\n            `[data-n-id=\"${cProps.componentId}\"] [data-col-key=\"${leftActiveFixedColKey}\"]::after`,\n            { boxShadow: 'var(--n-box-shadow-after)' }\n          )\n        }\n\n        const createActiveRightFixedStyle = (\n          rightActiveFixedColKey: ColumnKey | null\n        ): CNode | null => {\n          if (rightActiveFixedColKey === null)\n            return null\n          return c(\n            `[data-n-id=\"${cProps.componentId}\"] [data-col-key=\"${rightActiveFixedColKey}\"]::before`,\n            { boxShadow: 'var(--n-box-shadow-before)' }\n          )\n        }\n\n        return c([\n          createActiveLeftFixedStyle(cProps.leftActiveFixedColKey),\n          createActiveRightFixedStyle(cProps.rightActiveFixedColKey),\n          cProps.leftActiveFixedChildrenColKeys.map(leftActiveFixedColKey =>\n            createActiveLeftFixedStyle(leftActiveFixedColKey)\n          ),\n          cProps.rightActiveFixedChildrenColKeys.map(rightActiveFixedColKey =>\n            createActiveRightFixedStyle(rightActiveFixedColKey)\n          )\n        ])\n      }\n    ])\n    let fixedStyleMounted = false\n    watchEffect(() => {\n      const { value: leftActiveFixedColKey } = leftActiveFixedColKeyRef\n      const { value: leftActiveFixedChildrenColKeys }\n        = leftActiveFixedChildrenColKeysRef\n      const { value: rightActiveFixedColKey } = rightActiveFixedColKeyRef\n      const { value: rightActiveFixedChildrenColKeys }\n        = rightActiveFixedChildrenColKeysRef\n      if (\n        !fixedStyleMounted\n        && leftActiveFixedColKey === null\n        && rightActiveFixedColKey === null\n      ) {\n        return\n      }\n\n      const cProps: StyleCProps = {\n        leftActiveFixedColKey,\n        leftActiveFixedChildrenColKeys,\n        rightActiveFixedColKey,\n        rightActiveFixedChildrenColKeys,\n        componentId\n      }\n      style.mount({\n        id: `n-${componentId}`,\n        force: true,\n        props: cProps,\n        anchorMetaName: cssrAnchorMetaName,\n        parent: NConfigProvider?.styleMountTarget\n      })\n      fixedStyleMounted = true\n    })\n    onUnmounted(() => {\n      style.unmount({\n        id: `n-${componentId}`,\n        parent: NConfigProvider?.styleMountTarget\n      })\n    })\n    return {\n      bodyWidth: bodyWidthRef,\n      summaryPlacement: summaryPlacementRef,\n      dataTableSlots,\n      componentId,\n      scrollbarInstRef,\n      virtualListRef,\n      emptyElRef,\n      summary: summaryRef,\n      mergedClsPrefix: mergedClsPrefixRef,\n      mergedTheme: mergedThemeRef,\n      mergedRenderEmpty: mergedRenderEmptyRef,\n      scrollX: scrollXRef,\n      cols: colsRef,\n      loading: loadingRef,\n      shouldDisplayVirtualList: shouldDisplayVirtualListRef,\n      empty: emptyRef,\n      paginatedDataAndInfo: computed(() => {\n        const { value: striped } = stripedRef\n        let hasChildren = false\n        const data = paginatedDataRef.value.map(\n          striped\n            ? (tmNode, index) => {\n                if (!tmNode.isLeaf)\n                  hasChildren = true\n                return {\n                  tmNode,\n                  key: tmNode.key,\n                  striped: index % 2 === 1,\n                  index\n                }\n              }\n            : (tmNode, index) => {\n                if (!tmNode.isLeaf)\n                  hasChildren = true\n                return {\n                  tmNode,\n                  key: tmNode.key,\n                  striped: false,\n                  index\n                }\n              }\n        )\n        return {\n          data,\n          hasChildren\n        }\n      }),\n      rawPaginatedData: rawPaginatedDataRef,\n      fixedColumnLeftMap: fixedColumnLeftMapRef,\n      fixedColumnRightMap: fixedColumnRightMapRef,\n      currentPage: mergedCurrentPageRef,\n      rowClassName: rowClassNameRef,\n      renderExpand: renderExpandRef,\n      mergedExpandedRowKeySet: mergedExpandedRowKeySetRef,\n      hoverKey: hoverKeyRef,\n      mergedSortState: mergedSortStateRef,\n      virtualScroll: virtualScrollRef,\n      virtualScrollX: virtualScrollXRef,\n      heightForRow: heightForRowRef,\n      minRowHeight: minRowHeightRef,\n      mergedTableLayout: mergedTableLayoutRef,\n      childTriggerColIndex: childTriggerColIndexRef,\n      indent: indentRef,\n      rowProps: rowPropsRef,\n      loadingKeySet: loadingKeySetRef,\n      expandable: expandableRef,\n      stickyExpandedRows: stickyExpandedRowsRef,\n      renderExpandIcon: renderExpandIconRef,\n      scrollbarProps: scrollbarPropsRef,\n      setHeaderScrollLeft,\n      handleVirtualListScroll,\n      handleVirtualListResize,\n      handleMouseleaveTable,\n      virtualListContainer,\n      virtualListContent,\n      handleTableBodyScroll,\n      handleCheckboxUpdateChecked,\n      handleRadioUpdateChecked,\n      handleUpdateExpanded,\n      renderCell,\n      explicitlyScrollable: explicitlyScrollableRef,\n      xScrollable: xScrollableRef,\n      ...exposedMethods\n    }\n  },\n  render() {\n    const {\n      mergedTheme,\n      scrollX,\n      mergedClsPrefix,\n      explicitlyScrollable,\n      xScrollable,\n      loadingKeySet,\n      onResize,\n      setHeaderScrollLeft,\n      empty,\n      shouldDisplayVirtualList\n    } = this\n\n    const contentStyle: CSSProperties = {\n      minWidth: formatLength(scrollX) || '100%'\n    }\n    if (scrollX)\n      contentStyle.width = '100%'\n\n    const createEmptyNode = (): VNode => (\n      <div\n        class={[\n          `${mergedClsPrefix}-data-table-empty`,\n          this.loading && `${mergedClsPrefix}-data-table-empty--hide`\n        ]}\n        style={[\n          this.bodyStyle,\n          xScrollable\n            ? 'position: sticky; left: 0; width: var(--n-scrollbar-current-width);'\n            : undefined\n        ]}\n        ref=\"emptyElRef\"\n      >\n        {resolveSlot(this.dataTableSlots.empty, () => {\n          return [\n            this.mergedRenderEmpty?.() || (\n              <NEmpty\n                theme={this.mergedTheme.peers.Empty}\n                themeOverrides={this.mergedTheme.peerOverrides.Empty}\n              />\n            )\n          ]\n        })}\n      </div>\n    )\n\n    const tableNode = (\n      <NScrollbar\n        {...this.scrollbarProps}\n        ref=\"scrollbarInstRef\"\n        scrollable={explicitlyScrollable || xScrollable}\n        class={`${mergedClsPrefix}-data-table-base-table-body`}\n        style={!empty ? this.bodyStyle : 'height: initial;'}\n        theme={mergedTheme.peers.Scrollbar}\n        themeOverrides={mergedTheme.peerOverrides.Scrollbar}\n        contentStyle={contentStyle}\n        container={\n          shouldDisplayVirtualList ? this.virtualListContainer : undefined\n        }\n        content={shouldDisplayVirtualList ? this.virtualListContent : undefined}\n        horizontalRailStyle={{ zIndex: 3 }}\n        verticalRailStyle={{ zIndex: 3 }}\n        internalExposeWidthCssVar={xScrollable && empty}\n        xScrollable={xScrollable}\n        onScroll={\n          shouldDisplayVirtualList ? undefined : this.handleTableBodyScroll\n        }\n        internalOnUpdateScrollLeft={setHeaderScrollLeft}\n        onResize={onResize}\n      >\n        {{\n          default: () => {\n            if (\n              this.empty\n              && !this.showHeader\n              && (this.explicitlyScrollable || this.xScrollable)\n            ) {\n              // Placeholder for outer header to sync scroll state\n              return createEmptyNode()\n            }\n            // coordinate to pass if there are cells that cross row & col\n            const cordToPass: Record<number, number[]> = {}\n            // coordinate to related hover keys\n            const cordKey: Record<number, Record<number, RowKey[]>> = {}\n            const {\n              cols,\n              paginatedDataAndInfo,\n              mergedTheme,\n              fixedColumnLeftMap,\n              fixedColumnRightMap,\n              currentPage,\n              rowClassName,\n              mergedSortState,\n              mergedExpandedRowKeySet,\n              stickyExpandedRows,\n              componentId,\n              childTriggerColIndex,\n              expandable,\n              rowProps,\n              handleMouseleaveTable,\n              renderExpand,\n              summary,\n              handleCheckboxUpdateChecked,\n              handleRadioUpdateChecked,\n              handleUpdateExpanded,\n              heightForRow,\n              minRowHeight,\n              virtualScrollX\n            } = this\n            const { length: colCount } = cols\n\n            let mergedData: RowRenderInfo[]\n\n            // if there is children in data, we should expand mergedData first\n\n            const { data: paginatedData, hasChildren } = paginatedDataAndInfo\n\n            const mergedPaginationData = hasChildren\n              ? flatten(paginatedData, mergedExpandedRowKeySet)\n              : paginatedData\n\n            if (summary) {\n              const summaryRows = summary(this.rawPaginatedData)\n              if (Array.isArray(summaryRows)) {\n                const summaryRowData = summaryRows.map((row, i) => ({\n                  isSummaryRow: true as const,\n                  key: `__n_summary__${i}`,\n                  tmNode: {\n                    rawNode: row,\n                    disabled: true\n                  },\n                  index: -1\n                }))\n                mergedData\n                  = this.summaryPlacement === 'top'\n                    ? [...summaryRowData, ...mergedPaginationData]\n                    : [...mergedPaginationData, ...summaryRowData]\n              }\n              else {\n                const summaryRowData = {\n                  isSummaryRow: true as const,\n                  key: '__n_summary__',\n                  tmNode: {\n                    rawNode: summaryRows,\n                    disabled: true\n                  },\n                  index: -1\n                }\n                mergedData\n                  = this.summaryPlacement === 'top'\n                    ? [summaryRowData, ...mergedPaginationData]\n                    : [...mergedPaginationData, summaryRowData]\n              }\n            }\n            else {\n              mergedData = mergedPaginationData\n            }\n\n            const indentStyle = hasChildren\n              ? { width: pxfy(this.indent) }\n              : undefined\n\n            // Tile the data of the expanded row\n            const displayedData: RowRenderInfo[] = []\n            mergedData.forEach((rowInfo) => {\n              if (\n                renderExpand\n                && mergedExpandedRowKeySet.has(rowInfo.key)\n                && (!expandable || expandable(rowInfo.tmNode.rawNode))\n              ) {\n                displayedData.push(rowInfo, {\n                  isExpandedRow: true,\n                  key: `${rowInfo.key}-expand`, // solve key repeat of the expanded row\n                  tmNode: rowInfo.tmNode as TmNode,\n                  index: rowInfo.index\n                })\n              }\n              else {\n                displayedData.push(rowInfo)\n              }\n            })\n\n            const { length: rowCount } = displayedData\n\n            const rowIndexToKey: Record<number, RowKey> = {}\n            paginatedData.forEach(({ tmNode }, rowIndex) => {\n              rowIndexToKey[rowIndex] = tmNode.key\n            })\n\n            const bodyWidth = stickyExpandedRows ? this.bodyWidth : null\n            const bodyWidthPx\n              = bodyWidth === null ? undefined : `${bodyWidth}px`\n\n            const CellComponent = (this.virtualScrollX ? 'div' : 'td') as 'td'\n            let leftFixedColsCount = 0\n            let rightFixedColsCount = 0\n            if (virtualScrollX) {\n              cols.forEach((col) => {\n                if (col.column.fixed === 'left') {\n                  leftFixedColsCount++\n                }\n                else if (col.column.fixed === 'right') {\n                  rightFixedColsCount++\n                }\n              })\n            }\n\n            const renderRow = ({\n              // Normal\n              rowInfo,\n              displayedRowIndex,\n              isVirtual,\n              // Virtual X\n              isVirtualX,\n              startColIndex,\n              endColIndex,\n              getLeft\n            }: {\n              rowInfo: RowRenderInfo\n              displayedRowIndex: number\n              isVirtual: boolean\n              // for horizontal virtual list\n              isVirtualX: boolean\n              startColIndex: number\n              endColIndex: number\n              getLeft: (index: number) => number\n            }): VNode => {\n              const { index: actualRowIndex } = rowInfo\n              if ('isExpandedRow' in rowInfo) {\n                const {\n                  tmNode: { key, rawNode }\n                } = rowInfo\n                return (\n                  <tr\n                    class={`${mergedClsPrefix}-data-table-tr ${mergedClsPrefix}-data-table-tr--expanded`}\n                    key={`${key}__expand`}\n                  >\n                    <td\n                      class={[\n                        `${mergedClsPrefix}-data-table-td`,\n                        `${mergedClsPrefix}-data-table-td--last-col`,\n                        displayedRowIndex + 1 === rowCount\n                        && `${mergedClsPrefix}-data-table-td--last-row`\n                      ]}\n                      colspan={colCount}\n                    >\n                      {stickyExpandedRows ? (\n                        <div\n                          class={`${mergedClsPrefix}-data-table-expand`}\n                          style={{\n                            width: bodyWidthPx\n                          }}\n                        >\n                          {renderExpand!(rawNode, actualRowIndex)}\n                        </div>\n                      ) : (\n                        renderExpand!(rawNode, actualRowIndex)\n                      )}\n                    </td>\n                  </tr>\n                )\n              }\n              const isSummary = 'isSummaryRow' in rowInfo\n              const striped = !isSummary && rowInfo.striped\n              const { tmNode, key: rowKey } = rowInfo\n              const { rawNode: rowData } = tmNode\n              const expanded = mergedExpandedRowKeySet.has(rowKey)\n              const props = rowProps\n                ? rowProps(rowData, actualRowIndex)\n                : undefined\n              const mergedRowClassName\n                = typeof rowClassName === 'string'\n                  ? rowClassName\n                  : createRowClassName(rowData, actualRowIndex, rowClassName)\n              const iteratedCols = isVirtualX\n                ? cols.filter((col, index) => {\n                    if (startColIndex <= index && index <= endColIndex)\n                      return true\n                    if (col.column.fixed) {\n                      return true\n                    }\n                    return false\n                  })\n                : cols\n              const virtualXRowHeight = isVirtualX\n                ? pxfy(heightForRow?.(rowData, actualRowIndex) || minRowHeight)\n                : undefined\n              const cells = iteratedCols.map((col) => {\n                const colIndex = col.index\n                if (displayedRowIndex in cordToPass) {\n                  const cordOfRowToPass = cordToPass[displayedRowIndex]\n                  const indexInCordOfRowToPass\n                    = cordOfRowToPass.indexOf(colIndex)\n                  if (~indexInCordOfRowToPass) {\n                    cordOfRowToPass.splice(indexInCordOfRowToPass, 1)\n                    return null\n                  }\n                }\n                // TODO: Simplify row calculation\n                const { column } = col\n                const colKey = getColKey(col)\n                const { rowSpan, colSpan } = column\n                const mergedColSpan = isSummary\n                  ? rowInfo.tmNode.rawNode[colKey]?.colSpan || 1 // optional for #1276\n                  : colSpan\n                    ? colSpan(rowData, actualRowIndex)\n                    : 1\n                const mergedRowSpan = isSummary\n                  ? rowInfo.tmNode.rawNode[colKey]?.rowSpan || 1 // optional for #1276\n                  : rowSpan\n                    ? rowSpan(rowData, actualRowIndex)\n                    : 1\n                const isLastCol = colIndex + mergedColSpan === colCount\n                const isLastRow = displayedRowIndex + mergedRowSpan === rowCount\n                const isCrossRowTd = mergedRowSpan > 1\n                if (isCrossRowTd) {\n                  cordKey[displayedRowIndex] = {\n                    [colIndex]: []\n                  }\n                }\n                if (mergedColSpan > 1 || isCrossRowTd) {\n                  for (\n                    let i = displayedRowIndex;\n                    i < displayedRowIndex + mergedRowSpan;\n                    ++i\n                  ) {\n                    if (isCrossRowTd) {\n                      cordKey[displayedRowIndex][colIndex].push(\n                        rowIndexToKey[i]\n                      )\n                    }\n                    for (let j = colIndex; j < colIndex + mergedColSpan; ++j) {\n                      if (i === displayedRowIndex && j === colIndex) {\n                        continue\n                      }\n                      if (!(i in cordToPass)) {\n                        cordToPass[i] = [j]\n                      }\n                      else {\n                        cordToPass[i].push(j)\n                      }\n                    }\n                  }\n                }\n                const hoverKey = isCrossRowTd ? this.hoverKey : null\n                const { cellProps } = column\n                const resolvedCellProps = cellProps?.(rowData, actualRowIndex)\n                const indentOffsetStyle = {\n                  '--indent-offset': '' as string | number\n                }\n                const FinalCellComponent = column.fixed ? 'td' : CellComponent\n                return (\n                  <FinalCellComponent\n                    {...resolvedCellProps}\n                    key={colKey}\n                    style={[\n                      {\n                        textAlign: column.align || undefined,\n                        width: pxfy(column.width)\n                      },\n                      isVirtualX && {\n                        height: virtualXRowHeight\n                      },\n                      isVirtualX && !column.fixed\n                        ? {\n                            position: 'absolute',\n                            left: pxfy(getLeft(colIndex)),\n                            top: 0,\n                            bottom: 0\n                          }\n                        : {\n                            left: pxfy(fixedColumnLeftMap[colKey]?.start),\n                            right: pxfy(fixedColumnRightMap[colKey]?.start)\n                          },\n                      indentOffsetStyle as CSSProperties,\n                      resolvedCellProps?.style || ''\n                    ]}\n                    colspan={mergedColSpan}\n                    rowspan={isVirtual ? undefined : mergedRowSpan}\n                    data-col-key={colKey}\n                    class={[\n                      `${mergedClsPrefix}-data-table-td`,\n                      column.className,\n                      resolvedCellProps?.class,\n                      isSummary && `${mergedClsPrefix}-data-table-td--summary`,\n                      hoverKey !== null\n                      && cordKey[displayedRowIndex][colIndex].includes(\n                        hoverKey\n                      )\n                      && `${mergedClsPrefix}-data-table-td--hover`,\n                      isColumnSorting(column, mergedSortState)\n                      && `${mergedClsPrefix}-data-table-td--sorting`,\n                      column.fixed\n                      && `${mergedClsPrefix}-data-table-td--fixed-${column.fixed}`,\n                      column.align\n                      && `${mergedClsPrefix}-data-table-td--${column.align}-align`,\n                      column.type === 'selection'\n                      && `${mergedClsPrefix}-data-table-td--selection`,\n                      column.type === 'expand'\n                      && `${mergedClsPrefix}-data-table-td--expand`,\n                      isLastCol && `${mergedClsPrefix}-data-table-td--last-col`,\n                      isLastRow && `${mergedClsPrefix}-data-table-td--last-row`\n                    ]}\n                  >\n                    {hasChildren && colIndex === childTriggerColIndex\n                      ? [\n                          repeat(\n                            (indentOffsetStyle['--indent-offset'] = isSummary\n                              ? 0\n                              : rowInfo.tmNode.level),\n                            <div\n                              class={`${mergedClsPrefix}-data-table-indent`}\n                              style={indentStyle}\n                            />\n                          ),\n                          isSummary || rowInfo.tmNode.isLeaf ? (\n                            <div\n                              class={`${mergedClsPrefix}-data-table-expand-placeholder`}\n                            />\n                          ) : (\n                            <ExpandTrigger\n                              class={`${mergedClsPrefix}-data-table-expand-trigger`}\n                              clsPrefix={mergedClsPrefix}\n                              expanded={expanded}\n                              rowData={rowData}\n                              renderExpandIcon={this.renderExpandIcon}\n                              loading={loadingKeySet.has(rowInfo.key)}\n                              onClick={() => {\n                                handleUpdateExpanded(rowKey, rowInfo.tmNode)\n                              }}\n                            />\n                          )\n                        ]\n                      : null}\n                    {column.type === 'selection' ? (\n                      !isSummary ? (\n                        column.multiple === false ? (\n                          <RenderSafeRadio\n                            key={currentPage}\n                            rowKey={rowKey}\n                            disabled={rowInfo.tmNode.disabled}\n                            onUpdateChecked={() => {\n                              handleRadioUpdateChecked(rowInfo.tmNode)\n                            }}\n                          />\n                        ) : (\n                          <RenderSafeCheckbox\n                            key={currentPage}\n                            rowKey={rowKey}\n                            disabled={rowInfo.tmNode.disabled}\n                            onUpdateChecked={(checked: boolean, e) => {\n                              handleCheckboxUpdateChecked(\n                                rowInfo.tmNode,\n                                checked,\n                                e.shiftKey\n                              )\n                            }}\n                          />\n                        )\n                      ) : null\n                    ) : column.type === 'expand' ? (\n                      !isSummary ? (\n                        !column.expandable || column.expandable?.(rowData) ? (\n                          <ExpandTrigger\n                            clsPrefix={mergedClsPrefix}\n                            rowData={rowData}\n                            expanded={expanded}\n                            renderExpandIcon={this.renderExpandIcon}\n                            onClick={() => {\n                              handleUpdateExpanded(rowKey, null)\n                            }}\n                          />\n                        ) : null\n                      ) : null\n                    ) : (\n                      <Cell\n                        clsPrefix={mergedClsPrefix}\n                        index={actualRowIndex}\n                        row={rowData}\n                        column={column}\n                        isSummary={isSummary}\n                        mergedTheme={mergedTheme}\n                        renderCell={this.renderCell}\n                      />\n                    )}\n                  </FinalCellComponent>\n                )\n              })\n\n              if (isVirtualX) {\n                if (leftFixedColsCount && rightFixedColsCount) {\n                  cells.splice(\n                    leftFixedColsCount,\n                    0,\n                    <td\n                      colspan={\n                        cols.length - leftFixedColsCount - rightFixedColsCount\n                      }\n                      style={{\n                        pointerEvents: 'none',\n                        visibility: 'hidden',\n                        height: 0\n                      }}\n                    />\n                  )\n                }\n              }\n\n              const row = (\n                <tr\n                  {...props}\n                  onMouseenter={(e) => {\n                    this.hoverKey = rowKey\n                    props?.onMouseenter?.(e)\n                  }}\n                  key={rowKey}\n                  class={[\n                    `${mergedClsPrefix}-data-table-tr`,\n                    isSummary && `${mergedClsPrefix}-data-table-tr--summary`,\n                    striped && `${mergedClsPrefix}-data-table-tr--striped`,\n                    expanded && `${mergedClsPrefix}-data-table-tr--expanded`,\n                    mergedRowClassName,\n                    props?.class\n                  ]}\n                  style={[\n                    props?.style,\n                    isVirtualX && { height: virtualXRowHeight }\n                  ]}\n                >\n                  {cells}\n                </tr>\n              )\n              return row\n            }\n\n            if (!this.shouldDisplayVirtualList) {\n              return (\n                <>\n                  <table\n                    class={`${mergedClsPrefix}-data-table-table`}\n                    onMouseleave={handleMouseleaveTable}\n                    style={{\n                      tableLayout: this.mergedTableLayout\n                    }}\n                  >\n                    <colgroup>\n                      {cols.map(col => (\n                        <col key={col.key} style={col.style}></col>\n                      ))}\n                    </colgroup>\n                    {this.showHeader ? <TableHeader discrete={false} /> : null}\n                    {!this.empty ? (\n                      <tbody\n                        data-n-id={componentId}\n                        class={`${mergedClsPrefix}-data-table-tbody`}\n                      >\n                        {displayedData.map((rowInfo, displayedRowIndex) => {\n                          return renderRow({\n                            rowInfo,\n                            displayedRowIndex,\n                            isVirtual: false,\n                            isVirtualX: false,\n                            startColIndex: -1,\n                            endColIndex: -1,\n                            getLeft(_index) {\n                              return -1\n                            }\n                          })\n                        })}\n                      </tbody>\n                    ) : null}\n                  </table>\n                  {this.empty && this.xScrollable ? createEmptyNode() : null}\n                </>\n              )\n            }\n            else {\n              return (\n                <VirtualList\n                  ref=\"virtualListRef\"\n                  items={displayedData}\n                  itemSize={this.minRowHeight}\n                  visibleItemsTag={VirtualListItemWrapper}\n                  visibleItemsProps={{\n                    clsPrefix: mergedClsPrefix,\n                    id: componentId,\n                    cols,\n                    onMouseleave: handleMouseleaveTable\n                  }}\n                  showScrollbar={false}\n                  onResize={this.handleVirtualListResize}\n                  onScroll={this.handleVirtualListScroll}\n                  itemsStyle={contentStyle}\n                  itemResizable={!virtualScrollX}\n                  columns={cols}\n                  renderItemWithCols={\n                    virtualScrollX\n                      ? ({\n                          itemIndex,\n                          item,\n                          startColIndex,\n                          endColIndex,\n                          getLeft\n                        }) => {\n                          return renderRow({\n                            displayedRowIndex: itemIndex,\n                            isVirtual: true,\n                            isVirtualX: true,\n                            rowInfo: item as RowRenderInfo,\n                            startColIndex,\n                            endColIndex,\n                            getLeft\n                          })\n                        }\n                      : undefined\n                  }\n                >\n                  {{\n                    default: ({\n                      item,\n                      index,\n                      renderedItemWithCols\n                    }: {\n                      item: RowRenderInfo\n                      index: number\n                      renderedItemWithCols: VNodeChild\n                    }) => {\n                      if (renderedItemWithCols)\n                        return renderedItemWithCols\n                      return renderRow({\n                        rowInfo: item,\n                        displayedRowIndex: index,\n                        isVirtual: true,\n                        isVirtualX: false,\n                        startColIndex: 0,\n                        endColIndex: 0,\n                        getLeft(_index) {\n                          return 0\n                        }\n                      })\n                    }\n                  }}\n                </VirtualList>\n              )\n            }\n          }\n        }}\n      </NScrollbar>\n    )\n\n    if (this.empty) {\n      if (this.explicitlyScrollable || this.xScrollable) {\n        // empty node is integrated into table node\n        return tableNode\n      }\n      else {\n        return (\n          <VResizeObserver onResize={this.onResize}>\n            {{ default: createEmptyNode }}\n          </VResizeObserver>\n        )\n      }\n    }\n    return tableNode\n  }\n})\n"
  },
  {
    "path": "src/data-table/src/TableParts/BodyCheckbox.tsx",
    "content": "import type { PropType } from 'vue'\nimport type { RowKey } from '../interface'\nimport { defineComponent, h, inject } from 'vue'\nimport { NCheckbox } from '../../../checkbox'\nimport { dataTableInjectionKey } from '../interface'\n\n// Extract the checkbox to avoid useless rendering in table body\nexport default defineComponent({\n  name: 'DataTableBodyCheckbox',\n  props: {\n    rowKey: {\n      type: [String, Number] as PropType<RowKey>,\n      required: true\n    },\n    disabled: {\n      type: Boolean,\n      required: true\n    },\n    onUpdateChecked: {\n      type: Function as PropType<\n        (checked: boolean, e: MouseEvent | KeyboardEvent) => void\n      >,\n      required: true\n    }\n  },\n  setup(props) {\n    const { mergedCheckedRowKeySetRef, mergedInderminateRowKeySetRef } = inject(\n      dataTableInjectionKey\n    )!\n    return () => {\n      const { rowKey } = props\n      return (\n        <NCheckbox\n          privateInsideTable\n          disabled={props.disabled}\n          indeterminate={mergedInderminateRowKeySetRef.value.has(rowKey)}\n          checked={mergedCheckedRowKeySetRef.value.has(rowKey)}\n          onUpdateChecked={props.onUpdateChecked}\n        />\n      )\n    }\n  }\n})\n"
  },
  {
    "path": "src/data-table/src/TableParts/BodyRadio.tsx",
    "content": "import type { PropType } from 'vue'\nimport type { RowKey } from '../interface'\nimport { defineComponent, h, inject } from 'vue'\nimport { NRadio } from '../../../radio'\nimport { dataTableInjectionKey } from '../interface'\n\n// Extract the radio to avoid useless rendering in table body\nexport default defineComponent({\n  name: 'DataTableBodyRadio',\n  props: {\n    rowKey: {\n      type: [String, Number] as PropType<RowKey>,\n      required: true\n    },\n    disabled: {\n      type: Boolean,\n      required: true\n    },\n    onUpdateChecked: {\n      type: Function as PropType<(checked: boolean) => void>,\n      required: true\n    }\n  },\n  setup(props) {\n    const { mergedCheckedRowKeySetRef, componentId } = inject(\n      dataTableInjectionKey\n    )!\n    return () => {\n      const { rowKey } = props\n      return (\n        <NRadio\n          name={componentId}\n          disabled={props.disabled}\n          checked={mergedCheckedRowKeySetRef.value.has(rowKey)}\n          onUpdateChecked={props.onUpdateChecked}\n        />\n      )\n    }\n  }\n})\n"
  },
  {
    "path": "src/data-table/src/TableParts/Cell.tsx",
    "content": "import type { PropType, VNodeChild } from 'vue'\nimport type { MergedTheme } from '../../../_mixins'\nimport type { DataTableTheme } from '../../styles'\nimport type {\n  InternalRowData,\n  SummaryCell,\n  TableBaseColumn\n} from '../interface'\nimport { get } from 'lodash-es'\nimport { defineComponent, h } from 'vue'\nimport NEllipsis from '../../../ellipsis/src/Ellipsis'\nimport { NPerformantEllipsis } from '../../../ellipsis/src/PerformantEllipsis'\n\nexport default defineComponent({\n  name: 'DataTableCell',\n  props: {\n    clsPrefix: {\n      type: String,\n      required: true\n    },\n    row: {\n      type: Object as PropType<InternalRowData>,\n      required: true\n    },\n    index: {\n      type: Number,\n      required: true\n    },\n    column: {\n      type: Object as PropType<TableBaseColumn>,\n      required: true\n    },\n    isSummary: Boolean,\n    mergedTheme: {\n      type: Object as PropType<MergedTheme<DataTableTheme>>,\n      required: true\n    },\n    renderCell: Function as PropType<\n      (value: any, rowData: object, column: any) => VNodeChild\n    >\n  },\n  render() {\n    const { isSummary, column, row, renderCell } = this\n    let cell: VNodeChild\n    const { render, key, ellipsis } = column\n    if (render && !isSummary) {\n      cell = render(row, this.index)\n    }\n    else {\n      if (isSummary) {\n        cell = (row[key] as SummaryCell)?.value\n      }\n      else {\n        cell = renderCell\n          ? renderCell(get(row, key), row, column)\n          : get(row, key)\n      }\n    }\n    if (ellipsis) {\n      if (typeof ellipsis === 'object') {\n        const { mergedTheme } = this\n        if (column.ellipsisComponent === 'performant-ellipsis') {\n          return (\n            <NPerformantEllipsis\n              {...ellipsis}\n              theme={mergedTheme.peers.Ellipsis}\n              themeOverrides={mergedTheme.peerOverrides.Ellipsis}\n            >\n              {{ default: () => cell }}\n            </NPerformantEllipsis>\n          )\n        }\n        return (\n          <NEllipsis\n            {...ellipsis}\n            theme={mergedTheme.peers.Ellipsis}\n            themeOverrides={mergedTheme.peerOverrides.Ellipsis}\n          >\n            {{ default: () => cell }}\n          </NEllipsis>\n        )\n      }\n      else {\n        return (\n          <span class={`${this.clsPrefix}-data-table-td__ellipsis`}>\n            {cell}\n          </span>\n        )\n      }\n    }\n    return cell\n  }\n})\n"
  },
  {
    "path": "src/data-table/src/TableParts/ExpandTrigger.tsx",
    "content": "import type { PropType } from 'vue'\nimport type { RenderExpandIcon, RowData } from '../interface'\nimport { defineComponent, h } from 'vue'\nimport {\n  NBaseIcon,\n  NBaseLoading,\n  NIconSwitchTransition\n} from '../../../_internal'\nimport { ChevronRightIcon } from '../../../_internal/icons'\n\nexport default defineComponent({\n  name: 'DataTableExpandTrigger',\n  props: {\n    clsPrefix: {\n      type: String,\n      required: true\n    },\n    expanded: Boolean,\n    loading: Boolean,\n    onClick: {\n      type: Function as PropType<() => void>,\n      required: true\n    },\n    renderExpandIcon: {\n      type: Function as PropType<RenderExpandIcon>\n    },\n    rowData: {\n      type: Object as PropType<RowData>,\n      required: true\n    }\n  },\n  render() {\n    const { clsPrefix } = this\n    return (\n      <div\n        class={[\n          `${clsPrefix}-data-table-expand-trigger`,\n          this.expanded && `${clsPrefix}-data-table-expand-trigger--expanded`\n        ]}\n        onClick={this.onClick}\n        onMousedown={(e) => {\n          e.preventDefault()\n        }}\n      >\n        <NIconSwitchTransition>\n          {{\n            default: () => {\n              return this.loading ? (\n                <NBaseLoading\n                  key=\"loading\"\n                  clsPrefix={this.clsPrefix}\n                  radius={85}\n                  strokeWidth={15}\n                  scale={0.88}\n                />\n              ) : this.renderExpandIcon ? (\n                this.renderExpandIcon({\n                  expanded: this.expanded,\n                  rowData: this.rowData\n                })\n              ) : (\n                <NBaseIcon clsPrefix={clsPrefix} key=\"base-icon\">\n                  {{\n                    default: () => <ChevronRightIcon />\n                  }}\n                </NBaseIcon>\n              )\n            }\n          }}\n        </NIconSwitchTransition>\n      </div>\n    )\n  }\n})\n"
  },
  {
    "path": "src/data-table/src/TableParts/Header.tsx",
    "content": "import type { PropType, VNode, VNodeChild } from 'vue'\nimport type { VirtualListInst } from 'vueuc'\nimport type {\n  ColumnKey,\n  TableBaseColumn,\n  TableColumnGroup,\n  TableExpandColumn\n} from '../interface'\nimport type { ColItem, RowItem } from '../use-group-header'\nimport { happensIn, pxfy } from 'seemly'\nimport { defineComponent, Fragment, h, inject, ref } from 'vue'\nimport { VVirtualList } from 'vueuc'\nimport { formatLength } from '../../../_utils'\nimport { NCheckbox } from '../../../checkbox'\nimport { NEllipsis } from '../../../ellipsis'\nimport FilterButton from '../HeaderButton/FilterButton'\nimport ResizeButton from '../HeaderButton/ResizeButton'\nimport SortButton from '../HeaderButton/SortButton'\nimport { dataTableInjectionKey } from '../interface'\nimport {\n  clampValueFollowCSSRules,\n  createNextSorter,\n  getColKey,\n  isColumnFilterable,\n  isColumnResizable,\n  isColumnSortable,\n  isColumnSorting\n} from '../utils'\nimport SelectionMenu from './SelectionMenu'\n\nfunction renderTitle(\n  column: TableExpandColumn | TableBaseColumn | TableColumnGroup\n): VNodeChild {\n  return typeof column.title === 'function'\n    ? column.title(column as never)\n    : column.title\n}\n\nconst VirtualListItemWrapper = defineComponent({\n  props: {\n    clsPrefix: {\n      type: String,\n      required: true\n    },\n    id: {\n      type: String,\n      required: true\n    },\n    cols: {\n      type: Array as PropType<ColItem[]>,\n      required: true\n    },\n    width: String\n  },\n  render() {\n    const { clsPrefix, id, cols, width } = this\n    return (\n      <table\n        style={{ tableLayout: 'fixed', width }}\n        class={`${clsPrefix}-data-table-table`}\n      >\n        <colgroup>\n          {cols.map(col => (\n            <col key={col.key} style={col.style}></col>\n          ))}\n        </colgroup>\n        <thead data-n-id={id} class={`${clsPrefix}-data-table-thead`}>\n          {this.$slots}\n        </thead>\n      </table>\n    )\n  }\n})\n\nexport default defineComponent({\n  name: 'DataTableHeader',\n  props: {\n    discrete: {\n      type: Boolean,\n      default: true\n    }\n  },\n  setup() {\n    const {\n      mergedClsPrefixRef,\n      scrollXRef,\n      fixedColumnLeftMapRef,\n      fixedColumnRightMapRef,\n      mergedCurrentPageRef,\n      allRowsCheckedRef,\n      someRowsCheckedRef,\n      rowsRef,\n      colsRef,\n      mergedThemeRef,\n      checkOptionsRef,\n      mergedSortStateRef,\n      componentId,\n      mergedTableLayoutRef,\n      headerCheckboxDisabledRef,\n      virtualScrollHeaderRef,\n      headerHeightRef,\n      onUnstableColumnResize,\n      doUpdateResizableWidth,\n      handleTableHeaderScroll,\n      deriveNextSorter,\n      doUncheckAll,\n      doCheckAll\n    } = inject(dataTableInjectionKey)!\n    const virtualListRef = ref<VirtualListInst | null>()\n    const cellElsRef = ref<Record<ColumnKey, HTMLTableCellElement>>({})\n    function getCellActualWidth(key: ColumnKey): number | undefined {\n      const element = cellElsRef.value[key]\n      return element?.getBoundingClientRect().width\n    }\n    function handleCheckboxUpdateChecked(): void {\n      if (allRowsCheckedRef.value) {\n        doUncheckAll()\n      }\n      else {\n        doCheckAll()\n      }\n    }\n    function handleColHeaderClick(\n      e: MouseEvent,\n      column: TableBaseColumn\n    ): void {\n      if (\n        happensIn(e, 'dataTableFilter')\n        || happensIn(e, 'dataTableResizable')\n      ) {\n        return\n      }\n      if (!isColumnSortable(column))\n        return\n      const activeSorter\n        = mergedSortStateRef.value.find(\n          state => state.columnKey === column.key\n        ) || null\n      const nextSorter = createNextSorter(column, activeSorter)\n      deriveNextSorter(nextSorter)\n    }\n    const resizeStartWidthMap = new Map<ColumnKey, number | undefined>()\n    function handleColumnResizeStart(column: TableBaseColumn): void {\n      resizeStartWidthMap.set(column.key, getCellActualWidth(column.key))\n    }\n    function handleColumnResize(\n      column: TableBaseColumn,\n      displacementX: number\n    ): void {\n      const startWidth = resizeStartWidthMap.get(column.key)\n      if (startWidth === undefined) {\n        return\n      }\n      const widthAfterResize = startWidth + displacementX\n      const limitWidth = clampValueFollowCSSRules(\n        widthAfterResize,\n        column.minWidth,\n        column.maxWidth\n      )\n      onUnstableColumnResize(\n        widthAfterResize,\n        limitWidth,\n        column,\n        getCellActualWidth\n      )\n      doUpdateResizableWidth(column, limitWidth)\n    }\n    return {\n      cellElsRef,\n      componentId,\n      mergedSortState: mergedSortStateRef,\n      mergedClsPrefix: mergedClsPrefixRef,\n      scrollX: scrollXRef,\n      fixedColumnLeftMap: fixedColumnLeftMapRef,\n      fixedColumnRightMap: fixedColumnRightMapRef,\n      currentPage: mergedCurrentPageRef,\n      allRowsChecked: allRowsCheckedRef,\n      someRowsChecked: someRowsCheckedRef,\n      rows: rowsRef,\n      cols: colsRef,\n      mergedTheme: mergedThemeRef,\n      checkOptions: checkOptionsRef,\n      mergedTableLayout: mergedTableLayoutRef,\n      headerCheckboxDisabled: headerCheckboxDisabledRef,\n      headerHeight: headerHeightRef,\n      virtualScrollHeader: virtualScrollHeaderRef,\n      virtualListRef,\n      handleCheckboxUpdateChecked,\n      handleColHeaderClick,\n      handleTableHeaderScroll,\n      handleColumnResizeStart,\n      handleColumnResize\n    }\n  },\n  render() {\n    const {\n      cellElsRef,\n      mergedClsPrefix,\n      fixedColumnLeftMap,\n      fixedColumnRightMap,\n      currentPage,\n      allRowsChecked,\n      someRowsChecked,\n      rows,\n      cols,\n      mergedTheme,\n      checkOptions,\n      componentId,\n      discrete,\n      mergedTableLayout,\n      headerCheckboxDisabled,\n      mergedSortState,\n      virtualScrollHeader,\n      handleColHeaderClick,\n      handleCheckboxUpdateChecked,\n      handleColumnResizeStart,\n      handleColumnResize\n    } = this\n    let hasEllipsis = false\n\n    const renderRow = (\n      row: RowItem[],\n      getLeft: ((index: number) => number) | null,\n      headerHeightPx: string | undefined\n    ) =>\n      row.map(({ column, colIndex, colSpan, rowSpan, isLast }) => {\n        const key = getColKey(column)\n        const { ellipsis } = column\n        if (!hasEllipsis && ellipsis)\n          hasEllipsis = true\n        const createColumnVNode = (): VNode | null => {\n          if (column.type === 'selection') {\n            return column.multiple !== false ? (\n              <>\n                <NCheckbox\n                  key={currentPage}\n                  privateInsideTable\n                  checked={allRowsChecked}\n                  indeterminate={someRowsChecked}\n                  disabled={headerCheckboxDisabled}\n                  onUpdateChecked={handleCheckboxUpdateChecked}\n                />\n                {checkOptions ? (\n                  <SelectionMenu clsPrefix={mergedClsPrefix} />\n                ) : null}\n              </>\n            ) : null\n          }\n          return (\n            <>\n              <div class={`${mergedClsPrefix}-data-table-th__title-wrapper`}>\n                <div class={`${mergedClsPrefix}-data-table-th__title`}>\n                  {ellipsis === true || (ellipsis && !ellipsis.tooltip) ? (\n                    <div class={`${mergedClsPrefix}-data-table-th__ellipsis`}>\n                      {renderTitle(column)}\n                    </div>\n                  ) : ellipsis && typeof ellipsis === 'object' ? (\n                    <NEllipsis\n                      {...ellipsis}\n                      theme={mergedTheme.peers.Ellipsis}\n                      themeOverrides={mergedTheme.peerOverrides.Ellipsis}\n                    >\n                      {{\n                        default: () => renderTitle(column)\n                      }}\n                    </NEllipsis>\n                  ) : (\n                    renderTitle(column)\n                  )}\n                </div>\n                {isColumnSortable(column) ? (\n                  <SortButton column={column as TableBaseColumn} />\n                ) : null}\n              </div>\n              {isColumnFilterable(column) ? (\n                <FilterButton\n                  column={column as TableBaseColumn}\n                  options={column.filterOptions}\n                />\n              ) : null}\n              {isColumnResizable(column) ? (\n                <ResizeButton\n                  onResizeStart={() => {\n                    handleColumnResizeStart(column as TableBaseColumn)\n                  }}\n                  onResize={(displacementX) => {\n                    handleColumnResize(column as TableBaseColumn, displacementX)\n                  }}\n                />\n              ) : null}\n            </>\n          )\n        }\n        const leftFixed = key in fixedColumnLeftMap\n        const rightFixed = key in fixedColumnRightMap\n        const CellComponent = (getLeft && !column.fixed ? 'div' : 'th') as 'th'\n        return (\n          <CellComponent\n            ref={el => (cellElsRef[key] = el as HTMLTableCellElement)}\n            key={key}\n            style={[\n              getLeft && !column.fixed\n                ? {\n                    position: 'absolute',\n                    left: pxfy(getLeft(colIndex)),\n                    top: 0,\n                    bottom: 0\n                  }\n                : {\n                    left: pxfy(fixedColumnLeftMap[key]?.start),\n                    right: pxfy(fixedColumnRightMap[key]?.start)\n                  },\n              {\n                width: pxfy(column.width),\n                textAlign: column.titleAlign || column.align,\n                height: headerHeightPx\n              }\n            ]}\n            colspan={colSpan}\n            rowspan={rowSpan}\n            data-col-key={key}\n            class={[\n              `${mergedClsPrefix}-data-table-th`,\n              (leftFixed || rightFixed)\n              && `${mergedClsPrefix}-data-table-th--fixed-${\n                leftFixed ? 'left' : 'right'\n              }`,\n              {\n                [`${mergedClsPrefix}-data-table-th--sorting`]: isColumnSorting(\n                  column,\n                  mergedSortState\n                ),\n                [`${mergedClsPrefix}-data-table-th--filterable`]:\n                  isColumnFilterable(column),\n                [`${mergedClsPrefix}-data-table-th--sortable`]:\n                  isColumnSortable(column),\n                [`${mergedClsPrefix}-data-table-th--selection`]:\n                  column.type === 'selection',\n                [`${mergedClsPrefix}-data-table-th--last`]: isLast\n              },\n              column.className\n            ]}\n            onClick={\n              column.type !== 'selection'\n              && column.type !== 'expand'\n              && !('children' in column)\n                ? (e) => {\n                    handleColHeaderClick(e, column)\n                  }\n                : undefined\n            }\n          >\n            {createColumnVNode()}\n          </CellComponent>\n        )\n      })\n\n    if (virtualScrollHeader) {\n      const { headerHeight } = this\n\n      let leftFixedColsCount = 0\n      let rightFixedColsCount = 0\n\n      cols.forEach((col) => {\n        if (col.column.fixed === 'left') {\n          leftFixedColsCount++\n        }\n        else if (col.column.fixed === 'right') {\n          rightFixedColsCount++\n        }\n      })\n\n      return (\n        <VVirtualList\n          ref=\"virtualListRef\"\n          class={`${mergedClsPrefix}-data-table-base-table-header`}\n          style={{ height: pxfy(headerHeight) }}\n          onScroll={this.handleTableHeaderScroll}\n          columns={cols}\n          itemSize={headerHeight}\n          showScrollbar={false}\n          items={[{}]}\n          itemResizable={false}\n          visibleItemsTag={VirtualListItemWrapper}\n          visibleItemsProps={{\n            clsPrefix: mergedClsPrefix,\n            id: componentId,\n            cols,\n            width: formatLength(this.scrollX)\n          }}\n          renderItemWithCols={({ startColIndex, endColIndex, getLeft }) => {\n            const row = cols\n              .map<RowItem>((col, index) => {\n                return {\n                  column: col.column,\n                  isLast: index === cols.length - 1,\n                  colIndex: col.index,\n                  colSpan: 1,\n                  rowSpan: 1\n                }\n              })\n              .filter(({ column }, index) => {\n                if (startColIndex <= index && index <= endColIndex) {\n                  return true\n                }\n                if (column.fixed) {\n                  return true\n                }\n                return false\n              })\n\n            const cells = renderRow(row, getLeft, pxfy(headerHeight))\n\n            cells.splice(\n              leftFixedColsCount,\n              0,\n              <th\n                colspan={cols.length - leftFixedColsCount - rightFixedColsCount}\n                style={{\n                  pointerEvents: 'none',\n                  visibility: 'hidden',\n                  height: 0\n                }}\n              />\n            )\n            return <tr style={{ position: 'relative' }}>{cells}</tr>\n          }}\n        >\n          {{\n            default: ({\n              renderedItemWithCols\n            }: {\n              renderedItemWithCols: VNodeChild\n            }) => renderedItemWithCols\n          }}\n        </VVirtualList>\n      )\n    }\n\n    const theadVNode = (\n      <thead\n        class={`${mergedClsPrefix}-data-table-thead`}\n        data-n-id={componentId}\n      >\n        {rows.map((row) => {\n          return (\n            <tr class={`${mergedClsPrefix}-data-table-tr`}>\n              {renderRow(row, null, undefined)}\n            </tr>\n          )\n        })}\n      </thead>\n    )\n    if (!discrete) {\n      return theadVNode\n    }\n    const { handleTableHeaderScroll, scrollX } = this\n    return (\n      <div\n        class={`${mergedClsPrefix}-data-table-base-table-header`}\n        onScroll={handleTableHeaderScroll}\n      >\n        <table\n          class={`${mergedClsPrefix}-data-table-table`}\n          style={{\n            minWidth: formatLength(scrollX),\n            tableLayout: mergedTableLayout\n          }}\n        >\n          <colgroup>\n            {cols.map(col => (\n              <col key={col.key} style={col.style} />\n            ))}\n          </colgroup>\n          {theadVNode}\n        </table>\n      </div>\n    )\n  }\n})\n"
  },
  {
    "path": "src/data-table/src/TableParts/SelectionMenu.tsx",
    "content": "import type { Ref } from 'vue'\nimport type { NLocale } from '../../../locales'\nimport type { DataTableSelectionOption, InternalRowData } from '../interface'\nimport { computed, defineComponent, h, inject } from 'vue'\nimport { NBaseIcon } from '../../../_internal'\nimport { ChevronDownIcon } from '../../../_internal/icons'\nimport { NDropdown } from '../../../dropdown'\nimport { dataTableInjectionKey } from '../interface'\n\nconst allKey = '_n_all__'\nconst noneKey = '_n_none__'\n\nfunction createSelectHandler(\n  options:\n    | Array<\n      | DataTableSelectionOption\n      | {\n        label: string\n        key: string | number\n        onSelect: (pageData: InternalRowData[]) => void\n      }\n    >\n    | undefined,\n  rawPaginatedDataRef: Ref<InternalRowData[]>,\n  doCheckAll: (checkWholeTable?: boolean) => void,\n  doUncheckAll: (checkWholeTable?: boolean) => void\n): (key: string | number) => void {\n  if (!options)\n    return () => {}\n  return (key: string | number) => {\n    for (const option of options) {\n      switch (key) {\n        case allKey:\n          doCheckAll(true)\n          return\n        case noneKey:\n          doUncheckAll(true)\n          return\n        default:\n          if (typeof option === 'object' && option.key === key) {\n            option.onSelect(rawPaginatedDataRef.value)\n            return\n          }\n      }\n    }\n  }\n}\n\nfunction createDropdownOptions(\n  options:\n    | Array<\n      | DataTableSelectionOption\n      | {\n        label: string\n        key: string | number\n        onSelect: (pageData: InternalRowData[]) => void\n      }\n    >\n    | undefined,\n  localeRef: NLocale['DataTable']\n): Array<{ label: string, key: string | number }> {\n  if (!options)\n    return []\n  return options.map((option) => {\n    switch (option) {\n      case 'all':\n        return {\n          label: localeRef.checkTableAll,\n          key: allKey\n        }\n      case 'none':\n        return {\n          label: localeRef.uncheckTableAll,\n          key: noneKey\n        }\n      default:\n        return option\n    }\n  })\n}\n\nexport default defineComponent({\n  name: 'DataTableSelectionMenu',\n  props: {\n    clsPrefix: {\n      type: String,\n      required: true\n    }\n  },\n  setup(props) {\n    const {\n      props: dataTableProps,\n      localeRef,\n      checkOptionsRef,\n      rawPaginatedDataRef,\n      doCheckAll,\n      doUncheckAll\n    } = inject(dataTableInjectionKey)!\n    const handleSelectRef = computed(() =>\n      createSelectHandler(\n        checkOptionsRef.value,\n        rawPaginatedDataRef,\n        doCheckAll,\n        doUncheckAll\n      )\n    )\n    const optionsRef = computed(() =>\n      createDropdownOptions(checkOptionsRef.value, localeRef.value)\n    )\n    return () => {\n      const { clsPrefix } = props\n      return (\n        <NDropdown\n          theme={dataTableProps.theme?.peers?.Dropdown}\n          themeOverrides={dataTableProps.themeOverrides?.peers?.Dropdown}\n          options={optionsRef.value}\n          onSelect={handleSelectRef.value}\n        >\n          {{\n            default: () => (\n              <NBaseIcon\n                clsPrefix={clsPrefix}\n                class={`${clsPrefix}-data-table-check-extra`}\n              >\n                {{\n                  default: () => <ChevronDownIcon />\n                }}\n              </NBaseIcon>\n            )\n          }}\n        </NDropdown>\n      )\n    }\n  }\n})\n"
  },
  {
    "path": "src/data-table/src/interface.ts",
    "content": "import type { TreeMate, TreeNode } from 'treemate'\nimport type {\n  CSSProperties,\n  ExtractPropTypes,\n  HTMLAttributes,\n  PropType,\n  Ref,\n  VNode,\n  VNodeChild\n} from 'vue'\nimport type { VirtualListInst } from 'vueuc'\nimport type { MergedTheme, ThemeProps } from '../../_mixins'\nimport type { ExtractPublicPropTypes, MaybeArray } from '../../_utils'\nimport type { EllipsisProps } from '../../ellipsis/src/Ellipsis'\nimport type { NLocale } from '../../locales'\nimport type { PaginationProps } from '../../pagination'\nimport type { PopoverProps } from '../../popover'\nimport type { ScrollbarProps, ScrollTo } from '../../scrollbar/src/Scrollbar'\nimport type { DataTableTheme } from '../styles'\nimport type {\n  DataTableGetCsvCell,\n  DataTableGetCsvHeader,\n  DataTableSize,\n  DataTableSpinProps\n} from './public-types'\nimport type { ColItem, RowItem } from './use-group-header'\nimport { useTheme } from '../../_mixins'\nimport { createInjectionKey } from '../../_utils'\n\nexport const dataTableProps = {\n  ...(useTheme.props as ThemeProps<DataTableTheme>),\n  onUnstableColumnResize: Function as PropType<\n    (\n      resizedWidth: number,\n      limitedWidth: number,\n      column: TableBaseColumn,\n      getColumnWidth: (key: ColumnKey) => number | undefined\n    ) => void\n  >,\n  pagination: {\n    type: [Object, Boolean] as PropType<false | PaginationProps>,\n    default: false\n  },\n  paginateSinglePage: {\n    type: Boolean,\n    default: true\n  },\n  minHeight: [Number, String] as PropType<string | number>,\n  maxHeight: [Number, String] as PropType<string | number>,\n  // Use any type as row data to make prop data acceptable\n  columns: {\n    type: Array as PropType<TableColumns<any>>,\n    default: () => []\n  },\n  rowClassName: [String, Function] as PropType<\n    string | CreateRowClassName<any>\n  >,\n  rowProps: Function as PropType<CreateRowProps<any>>,\n  rowKey: Function as PropType<CreateRowKey<any>>,\n  summary: [Function] as PropType<CreateSummary<any>>,\n  data: {\n    type: Array as PropType<RowData[]>,\n    default: () => []\n  },\n  loading: Boolean,\n  bordered: {\n    type: Boolean as PropType<boolean | undefined>,\n    default: undefined\n  },\n  bottomBordered: {\n    type: Boolean as PropType<boolean | undefined>,\n    default: undefined\n  },\n  striped: Boolean,\n  scrollX: [Number, String] as PropType<string | number>,\n  defaultCheckedRowKeys: {\n    type: Array as PropType<RowKey[]>,\n    default: () => []\n  },\n  checkedRowKeys: Array as PropType<RowKey[]>,\n  singleLine: {\n    type: Boolean,\n    default: true\n  },\n  singleColumn: Boolean,\n  size: String as PropType<DataTableSize>,\n  remote: Boolean,\n  defaultExpandedRowKeys: {\n    type: Array as PropType<RowKey[]>,\n    default: []\n  },\n  defaultExpandAll: Boolean,\n  expandedRowKeys: Array as PropType<RowKey[]>,\n  stickyExpandedRows: Boolean,\n  virtualScroll: Boolean,\n  virtualScrollX: Boolean,\n  virtualScrollHeader: Boolean,\n  headerHeight: { type: Number, default: 28 },\n  heightForRow: Function as PropType<DataTableHeightForRow>,\n  minRowHeight: { type: Number, default: 28 },\n  tableLayout: {\n    type: String as PropType<'auto' | 'fixed'>,\n    default: 'auto'\n  },\n  allowCheckingNotLoaded: Boolean,\n  cascade: {\n    type: Boolean,\n    default: true\n  },\n  childrenKey: {\n    type: String,\n    default: 'children'\n  },\n  indent: {\n    type: Number,\n    default: 16\n  },\n  flexHeight: Boolean,\n  summaryPlacement: {\n    type: String as PropType<'top' | 'bottom'>,\n    default: 'bottom'\n  },\n  paginationBehaviorOnFilter: {\n    type: String as PropType<'first' | 'current'>,\n    default: 'current'\n  },\n  filterIconPopoverProps: Object as PropType<PopoverProps>,\n  scrollbarProps: Object as PropType<ScrollbarProps>,\n  renderCell: Function as PropType<\n    (value: any, rowData: object, column: TableBaseColumn) => VNodeChild\n  >,\n  renderExpandIcon: Function as PropType<RenderExpandIcon>,\n  spinProps: Object as PropType<DataTableSpinProps>,\n  getCsvCell: Function as PropType<DataTableGetCsvCell>,\n  getCsvHeader: Function as PropType<DataTableGetCsvHeader>,\n  onLoad: Function as PropType<DataTableOnLoad>,\n  'onUpdate:page': [Function, Array] as PropType<\n    PaginationProps['onUpdate:page']\n  >,\n  onUpdatePage: [Function, Array] as PropType<PaginationProps['onUpdate:page']>,\n  'onUpdate:pageSize': [Function, Array] as PropType<\n    PaginationProps['onUpdate:pageSize']\n  >,\n  onUpdatePageSize: [Function, Array] as PropType<\n    PaginationProps['onUpdate:pageSize']\n  >,\n  'onUpdate:sorter': [Function, Array] as PropType<MaybeArray<OnUpdateSorter>>,\n  onUpdateSorter: [Function, Array] as PropType<MaybeArray<OnUpdateSorter>>,\n  'onUpdate:filters': [Function, Array] as PropType<\n    MaybeArray<OnUpdateFilters>\n  >,\n  onUpdateFilters: [Function, Array] as PropType<MaybeArray<OnUpdateFilters>>,\n  'onUpdate:checkedRowKeys': [Function, Array] as PropType<\n    MaybeArray<OnUpdateCheckedRowKeys>\n  >,\n  onUpdateCheckedRowKeys: [Function, Array] as PropType<\n    MaybeArray<OnUpdateCheckedRowKeys>\n  >,\n  'onUpdate:expandedRowKeys': [Function, Array] as PropType<\n    MaybeArray<OnUpdateExpandedRowKeys>\n  >,\n  onUpdateExpandedRowKeys: [Function, Array] as PropType<\n    MaybeArray<OnUpdateExpandedRowKeys>\n  >,\n  onScroll: Function as PropType<(e: Event) => void>,\n  // deprecated\n  onPageChange: [Function, Array] as PropType<PaginationProps['onUpdate:page']>,\n  onPageSizeChange: [Function, Array] as PropType<\n    PaginationProps['onUpdate:pageSize']\n  >,\n  onSorterChange: [Function, Array] as PropType<\n    MaybeArray<OnUpdateSorter> | undefined\n  >,\n  onFiltersChange: [Function, Array] as PropType<\n    MaybeArray<OnUpdateFilters> | undefined\n  >,\n  onCheckedRowKeysChange: [Function, Array] as PropType<\n    MaybeArray<OnUpdateCheckedRowKeys> | undefined\n  >\n} as const\n\nexport interface DataTableSlots {\n  default?: () => VNode[]\n  empty?: () => VNode[]\n  loading?: () => VNode[]\n}\n\nexport type FilterOptionValue = string | number\nexport type ColumnKey = string | number\nexport type RowKey = string | number\n\nexport type SortOrderFlag = 1 | -1 | 0\n\nexport type RowData = Record<string, any>\n\nexport type InternalRowData = Record<string, unknown>\n\nexport type CreateRowKey<T = InternalRowData> = (row: T) => RowKey\nexport type CreateRowClassName<T = InternalRowData> = (\n  row: T,\n  index: number\n) => string\nexport type CreateRowProps<T = InternalRowData> = (\n  row: T,\n  index: number\n) => HTMLAttributes\nexport type CreateCellProps<T = InternalRowData> = (\n  row: T,\n  index: number\n) => HTMLAttributes\n\nexport type CompareFn<T = InternalRowData> = (row1: T, row2: T) => number\nexport type Sorter<T = InternalRowData> = CompareFn<T> | SorterMultiple<T>\nexport interface SorterMultiple<T = InternalRowData> {\n  multiple: number\n  compare?: CompareFn<T> | 'default'\n}\n\nexport type Filter<T = InternalRowData> = (\n  filterOptionValue: FilterOptionValue,\n  row: T\n) => boolean\n\nexport interface FilterOption {\n  label: string\n  value: FilterOptionValue\n}\n\nexport type TmNode = TreeNode<InternalRowData>\n\n// for compat may add null\nexport type SortOrder = 'ascend' | 'descend' | false\n\nexport type Ellipsis = boolean | EllipsisProps\n\nexport interface CommonColumnInfo<T = InternalRowData> {\n  fixed?: 'left' | 'right'\n  width?: number | string\n  minWidth?: number | string\n  maxWidth?: number | string\n  className?: string\n  align?: 'left' | 'center' | 'right'\n  titleAlign?: 'left' | 'center' | 'right'\n  ellipsis?: Ellipsis\n  ellipsisComponent?: 'ellipsis' | 'performant-ellipsis'\n  allowExport?: boolean\n  cellProps?: (rowData: T, rowIndex: number) => HTMLAttributes\n}\n\nexport type DataTableHeightForRow<T = RowData> = (\n  rowData: T,\n  rowIndex: number\n) => number\n\nexport type TableColumnTitle\n  = | string\n    | ((column: TableBaseColumn) => VNodeChild)\n\nexport type TableExpandColumnTitle\n  = | string\n    | ((column: TableExpandColumn) => VNodeChild)\n\nexport type TableColumnGroupTitle\n  = | string\n    | ((column: TableColumnGroup) => VNodeChild)\n\nexport type TableColumnGroup<T = InternalRowData> = {\n  title?: TableColumnGroupTitle\n  type?: never\n  key: ColumnKey\n  children: Array<TableBaseColumn<T>>\n\n  // to suppress type error in table header\n  resizable?: boolean\n  filterOptions?: never\n} & CommonColumnInfo<T>\n\nexport type TableBaseColumn<T = InternalRowData> = {\n  title?: TableColumnTitle\n  titleColSpan?: number\n  // for compat maybe default\n  type?: never\n  key: ColumnKey\n\n  tree?: boolean\n\n  sorter?: boolean | Sorter<T> | 'default'\n  defaultSortOrder?: SortOrder\n  sortOrder?: SortOrder // controlled\n  customNextSortOrder?: (order: SortOrder) => SortOrder\n\n  resizable?: boolean\n  minWidth?: string | number\n  maxWidth?: string | number\n\n  filter?: 'default' | boolean | Filter<T>\n  filterOptions?: FilterOption[]\n  filterOptionValues?: FilterOptionValue[] | null // controlled\n  filterOptionValue?: FilterOptionValue | null // controlled\n  filterMode?: 'or' | 'and'\n\n  defaultFilterOptionValues?: FilterOptionValue[] | null\n  defaultFilterOptionValue?: FilterOptionValue | null\n  filterMultiple?: boolean\n\n  render?: (rowData: T, rowIndex: number) => VNodeChild\n  renderFilter?: RenderFilter\n  renderFilterIcon?: RenderFilterIcon\n  renderSorter?: RenderSorter\n  renderSorterIcon?: RenderSorterIcon\n  renderFilterMenu?: RenderFilterMenu\n  colSpan?: (rowData: T, rowIndex: number) => number\n  rowSpan?: (rowData: T, rowIndex: number) => number\n} & CommonColumnInfo<T>\n\nexport type TableSelectionColumn<T = InternalRowData> = {\n  type: 'selection'\n  multiple?: boolean\n  disabled?: (row: T) => boolean\n  options?: DataTableSelectionOptions<T>\n\n  // to suppress type error in utils\n  sorter?: never\n  resizable?: boolean\n  filter?: never\n  filterOptions?: never\n  filterOptionValues?: never\n  filterOptionValue?: never\n  colSpan?: never\n  rowSpan?: never\n} & CommonColumnInfo<T>\n\nexport type RenderExpand<T = InternalRowData> = (\n  row: T,\n  index: number\n) => VNodeChild\nexport type RenderExpandIcon = ({\n  expanded,\n  rowData\n}: {\n  expanded: boolean\n  rowData: RowData\n}) => VNodeChild\n\n// TODO: we should deprecate `index` since it would change after row is expanded\nexport type Expandable<T = InternalRowData> = (row: T) => boolean\nexport interface TableExpandColumn<T = InternalRowData>\n  extends Omit<TableSelectionColumn<T>, 'type'> {\n  type: 'expand'\n  title?: TableExpandColumnTitle\n  renderExpand: RenderExpand<T>\n  expandable?: Expandable<T>\n}\n\nexport type TableColumn<T = InternalRowData>\n  = | TableColumnGroup<T>\n    | TableBaseColumn<T>\n    | TableSelectionColumn<T>\n    | TableExpandColumn<T>\nexport type TableColumns<T = InternalRowData> = Array<TableColumn<T>>\n\nexport type DataTableSelectionOptions<T = InternalRowData> = Array<\n  | DataTableSelectionOption\n  | { label: string, key: string | number, onSelect: (pageData: T[]) => void }\n>\nexport interface DataTableInjection {\n  props: DataTableSetupProps\n  slots: DataTableSlots\n  indentRef: Ref<number>\n  childTriggerColIndexRef: Ref<number>\n  componentId: string\n  checkOptionsRef: Ref<DataTableSelectionOptions | undefined>\n  hoverKeyRef: Ref<RowKey | null>\n  mergedClsPrefixRef: Ref<string>\n  mergedThemeRef: Ref<MergedTheme<DataTableTheme>>\n  scrollXRef: Ref<string | number | undefined>\n  rowsRef: Ref<RowItem[][]>\n  colsRef: Ref<ColItem[]>\n  paginatedDataRef: Ref<TmNode[]>\n  leftFixedColumnsRef: Ref<TableColumns>\n  rightFixedColumnsRef: Ref<TableColumns>\n  leftActiveFixedColKeyRef: Ref<ColumnKey | null>\n  leftActiveFixedChildrenColKeysRef: Ref<ColumnKey[]>\n  rightActiveFixedColKeyRef: Ref<ColumnKey | null>\n  rightActiveFixedChildrenColKeysRef: Ref<ColumnKey[]>\n  fixedColumnLeftMapRef: Ref<\n    Record<ColumnKey, { start: number, end: number } | undefined>\n  >\n  fixedColumnRightMapRef: Ref<\n    Record<ColumnKey, { start: number, end: number } | undefined>\n  >\n  mergedCurrentPageRef: Ref<number>\n  someRowsCheckedRef: Ref<boolean>\n  allRowsCheckedRef: Ref<boolean>\n  mergedSortStateRef: Ref<SortState[]>\n  mergedFilterStateRef: Ref<FilterState>\n  loadingRef: Ref<boolean>\n  rowClassNameRef: Ref<string | CreateRowClassName | undefined>\n  mergedCheckedRowKeySetRef: Ref<Set<RowKey>>\n  mergedInderminateRowKeySetRef: Ref<Set<RowKey>>\n  localeRef: Ref<NLocale['DataTable']>\n  filterMenuCssVarsRef: Ref<CSSProperties>\n  mergedExpandedRowKeysRef: Ref<RowKey[]>\n  rowKeyRef: Ref<CreateRowKey | undefined>\n  renderExpandRef: Ref<undefined | RenderExpand>\n  summaryRef: Ref<undefined | CreateSummary>\n  rawPaginatedDataRef: Ref<InternalRowData[]>\n  virtualScrollRef: Ref<boolean>\n  virtualScrollXRef: Ref<boolean>\n  minRowHeightRef: Ref<number>\n  heightForRowRef: Ref<DataTableHeightForRow | undefined>\n  virtualScrollHeaderRef: Ref<boolean>\n  headerHeightRef: Ref<number>\n  bodyWidthRef: Ref<number | null>\n  mergedTableLayoutRef: Ref<'auto' | 'fixed'>\n  maxHeightRef: Ref<string | number | undefined>\n  minHeightRef: Ref<string | number | undefined>\n  xScrollableRef: Ref<boolean>\n  explicitlyScrollableRef: Ref<boolean>\n  rowPropsRef: Ref<CreateRowProps | undefined>\n  flexHeightRef: Ref<boolean>\n  headerCheckboxDisabledRef: Ref<boolean>\n  stripedRef: Ref<boolean>\n  onLoadRef: Ref<DataTableOnLoad | undefined>\n  loadingKeySetRef: Ref<Set<RowKey>>\n  paginationBehaviorOnFilterRef: Ref<'current' | 'first'>\n  expandableRef: Ref<Expandable<any> | undefined>\n  stickyExpandedRowsRef: Ref<boolean>\n  renderExpandIconRef: Ref<undefined | RenderExpandIcon>\n  summaryPlacementRef: Ref<'top' | 'bottom'>\n  filterIconPopoverPropsRef: Ref<PopoverProps | undefined>\n  treeMateRef: Ref<TreeMate<InternalRowData, InternalRowData, InternalRowData>>\n  scrollbarPropsRef: Ref<ScrollbarProps | undefined>\n  doUpdatePage: (page: number) => void\n  doUpdateExpandedRowKeys: (keys: RowKey[]) => void\n  doUpdateFilters: (filters: FilterState, sourceColumn: TableBaseColumn) => void\n  onUnstableColumnResize: (\n    resizedWidth: number,\n    limitedWidth: number,\n    column: TableBaseColumn,\n    getColumnWidth: (key: ColumnKey) => number | undefined\n  ) => void\n  getResizableWidth: (key: ColumnKey) => number | undefined\n  clearResizableWidth: () => void\n  doUpdateResizableWidth: (column: TableColumn, width: number) => void\n  deriveNextSorter: (sorter: SortState | null) => void\n  doUncheckAll: (checkWholeTable?: boolean) => void\n  doCheckAll: (checkWholeTable?: boolean) => void\n  doCheck: (\n    rowKey: RowKey | RowKey[],\n    single: boolean,\n    rowInfo: RowData\n  ) => void\n  doUncheck: (rowKey: RowKey | RowKey[], rowInfo: RowData) => void\n  handleTableHeaderScroll: (e: Event) => void\n  handleTableBodyScroll: (e: Event) => void\n  syncScrollState: (deltaX?: number, deltaY?: number) => void\n  setHeaderScrollLeft: (scrollLeft: number) => void\n  renderCell: Ref<\n    | undefined\n    | ((value: any, rowData: object, column: TableBaseColumn) => VNodeChild)\n  >\n}\n\nexport const dataTableInjectionKey\n  = createInjectionKey<DataTableInjection>('n-data-table')\n\nexport interface MainTableInjection {\n  leftActiveFixedColKey: ColumnKey | null\n  rightActiveFixedColKey: ColumnKey | null\n}\n\nexport type RenderFilter = (props: {\n  active: boolean\n  show: boolean\n}) => VNodeChild\n\nexport type RenderFilterIcon = RenderFilter\n\nexport type RenderSorter = (props: { order: SortOrder }) => VNodeChild\n\nexport type RenderSorterIcon = RenderSorter\n\nexport type RenderFilterMenu = (actions: { hide: () => void }) => VNodeChild\n\nexport type OnUpdateExpandedRowKeys = (keys: RowKey[]) => void\nexport type OnUpdateCheckedRowKeys = (\n  keys: RowKey[],\n  rows: InternalRowData[],\n  meta: {\n    row: InternalRowData | undefined\n    action: 'check' | 'uncheck' | 'checkAll' | 'uncheckAll'\n  }\n) => void\n\n// `null` only occurs when clearSorter is called\nexport type OnUpdateSorter = (sortState: SortState & SortState[] & null) => void\nexport type OnUpdateSorterImpl = (\n  sortState: SortState | SortState[] | null\n) => void\nexport type OnUpdateFilters = (\n  filterState: FilterState,\n  sourceColumn: TableBaseColumn\n) => void\n\nexport interface SortState {\n  columnKey: ColumnKey\n  order: SortOrder\n  // Sorter    => sync data + functional sorter\n  // 'default' => sync data + default sorter\n  // true      => async data\n  // false     => show nothing\n  sorter: Sorter | boolean | 'default'\n}\n\nexport type FilterState = Record<\n  string,\n  FilterOptionValue[] | FilterOptionValue | null | undefined\n>\n\nexport interface MainTableRef {\n  getHeaderElement: () => HTMLElement | null\n  getBodyElement: () => HTMLElement | null\n  scrollTo: ScrollTo\n}\n\nexport interface MainTableBodyRef {\n  getScrollContainer: () => HTMLElement | null\n  scrollTo: ScrollTo\n}\n\nexport interface MainTableHeaderRef {\n  $el: HTMLElement | null\n  virtualListRef: Ref<VirtualListInst | null>\n}\n\nexport type OnFilterMenuChange = <\n  T extends FilterOptionValue[] & (FilterOptionValue | null)\n>(\n  value: T\n) => void\nexport type OnFilterMenuChangeImpl = (\n  value: FilterOptionValue[] | FilterOptionValue | null\n) => void\n\nexport interface DataTableInst {\n  filter: (filters: FilterState | null) => void\n  filters: (filters: FilterState | null) => void\n  clearFilters: () => void\n  clearSorter: () => void\n  page: (page: number) => void\n  sort: (columnKey: ColumnKey, order: SortOrder) => void\n  scrollTo: ScrollTo\n  downloadCsv: (options?: CsvOptionsType) => void\n  /** @deprecated it but just leave it here, it does no harm */\n  clearFilter: () => void\n}\n\nexport type CreateSummary<T = InternalRowData> = (\n  pageData: T[]\n) => SummaryRowData | SummaryRowData[]\n\nexport interface SummaryCell {\n  value?: VNodeChild\n  colSpan?: number\n  rowSpan?: number\n}\nexport type SummaryRowData = Record<string, SummaryCell>\n\nexport type DataTableOnLoad = (node: RowData) => Promise<void>\n\nexport type DataTableSelectionOption = 'all' | 'none'\n\nexport type DataTableProps = ExtractPublicPropTypes<typeof dataTableProps>\nexport type DataTableSetupProps = ExtractPropTypes<typeof dataTableProps>\n\nexport interface CsvOptionsType {\n  fileName?: string\n  keepOriginalData?: boolean\n}\n"
  },
  {
    "path": "src/data-table/src/public-types.ts",
    "content": "import type { SharedSpinProps } from '../../_internal'\nimport type { TableBaseColumn } from './interface'\n\nexport type DataTableGetCsvCell = (\n  value: any,\n  rowData: object,\n  column: TableBaseColumn\n) => string\nexport type DataTableGetCsvHeader = (column: TableBaseColumn) => string\nexport type DataTableSize = 'small' | 'medium' | 'large'\nexport type DataTableSpinProps = SharedSpinProps\n"
  },
  {
    "path": "src/data-table/src/styles/index.cssr.ts",
    "content": "import type { CNode } from 'css-render'\nimport { fadeInScaleUpTransition } from '../../../_styles/transitions/fade-in-scale-up.cssr'\nimport { iconSwitchTransition } from '../../../_styles/transitions/icon-switch.cssr'\nimport { c, cB, cE, cM, cNotM, insideModal, insidePopover } from '../../../_utils/cssr'\n\nconst fixedColumnStyle = createFixedColumnStyle()\n\n// vars:\n// --n-font-size\n// --n-th-padding\n// --n-td-padding\n// --n-bezier\n// --n-border-radius\n// --n-line-height\n// --n-border-color\n// --n-border-color-modal\n// --n-border-color-popover\n// --n-th-color\n// --n-th-color-hover\n// --n-th-color-sorting\n// --n-th-color-modal\n// --n-th-color-hover-modal\n// --n-th-color-sorting-modal\n// --n-th-color-popover\n// --n-th-color-hover-popover\n// --n-th-color-sorting-popover\n// --n-td-color\n// --n-td-color-hover\n// --n-td-color-sorting\n// --n-td-color-modal\n// --n-td-color-hover-modal\n// --n-td-color-sorting-modal\n// --n-td-color-popover\n// --n-td-color-hover-popover\n// --n-td-color-sorting-popover\n// --n-th-text-color\n// --n-td-text-color\n// --n-th-font-weight\n// --n-th-button-color-hover\n// --n-th-icon-color\n// --n-th-icon-color-active\n// --n-filter-size\n// --n-action-divider-color\n// --n-action-padding\n// --n-action-button-margin\n// --n-pagination-margin\n// --n-empty-padding\n// --n-sorter-size\n// --n-resizable-container-size\n// --n-resizable-size\n// --n-loading-size\n// --n-loading-color\n// --n-opacity-loading\n\n// --n-box-shadow-before used in Body.tsx\n// --n-box-shadow-after used in Body.tsx\n\n// --indent-offset for ellipsis & expand trigger\nexport default c([\n  cB('data-table', `\n    width: 100%;\n    font-size: var(--n-font-size);\n    display: flex;\n    flex-direction: column;\n    position: relative;\n    --n-merged-th-color: var(--n-th-color);\n    --n-merged-td-color: var(--n-td-color);\n    --n-merged-border-color: var(--n-border-color);\n    --n-merged-th-color-hover: var(--n-th-color-hover);\n    --n-merged-th-color-sorting: var(--n-th-color-sorting);\n    --n-merged-td-color-hover: var(--n-td-color-hover);\n    --n-merged-td-color-sorting: var(--n-td-color-sorting);\n    --n-merged-td-color-striped: var(--n-td-color-striped);\n  `, [\n    cB('data-table-wrapper', `\n      flex-grow: 1;\n      display: flex;\n      flex-direction: column;\n    `),\n    cM('flex-height', [\n      c('>', [\n        cB('data-table-wrapper', [\n          c('>', [\n            cB('data-table-base-table', `\n              display: flex;\n              flex-direction: column;\n              flex-grow: 1;\n            `, [\n              c('>', [\n                cB('data-table-base-table-body', 'flex-basis: 0;', [\n                  // last-child means there is no empty icon\n                  // body is a scrollbar, we need to override height 100%\n                  c('&:last-child', 'flex-grow: 1;')\n                ])\n              ])\n            ])\n          ])\n        ])\n      ])\n    ]),\n    c('>', [\n      cB('data-table-loading-wrapper', `\n        color: var(--n-loading-color);\n        font-size: var(--n-loading-size);\n        position: absolute;\n        left: 50%;\n        top: 50%;\n        transform: translateX(-50%) translateY(-50%);\n        transition: color .3s var(--n-bezier);\n        display: flex;\n        align-items: center;\n        justify-content: center;\n      `, [\n        fadeInScaleUpTransition({\n          originalTransform: 'translateX(-50%) translateY(-50%)'\n        })\n      ])\n    ]),\n    cB('data-table-expand-placeholder', `\n      margin-right: 8px;\n      display: inline-block;\n      width: 16px;\n      height: 1px;\n    `),\n    cB('data-table-indent', `\n      display: inline-block;\n      height: 1px;\n    `),\n    cB('data-table-expand-trigger', `\n      display: inline-flex;\n      margin-right: 8px;\n      cursor: pointer;\n      font-size: 16px;\n      vertical-align: -0.2em;\n      position: relative;\n      width: 16px;\n      height: 16px;\n      color: var(--n-td-text-color);\n      transition: color .3s var(--n-bezier);\n    `, [\n      cM('expanded', [\n        cB('icon', 'transform: rotate(90deg);', [\n          iconSwitchTransition({\n            originalTransform: 'rotate(90deg)'\n          })\n        ]),\n        cB('base-icon', 'transform: rotate(90deg);', [\n          iconSwitchTransition({\n            originalTransform: 'rotate(90deg)'\n          })\n        ])\n      ]),\n      cB('base-loading', `\n        color: var(--n-loading-color);\n        transition: color .3s var(--n-bezier);\n        position: absolute;\n        left: 0;\n        right: 0;\n        top: 0;\n        bottom: 0;\n      `, [\n        iconSwitchTransition()\n      ]),\n      cB('icon', `\n        position: absolute;\n        left: 0;\n        right: 0;\n        top: 0;\n        bottom: 0;\n      `, [\n        iconSwitchTransition()\n      ]),\n      cB('base-icon', `\n        position: absolute;\n        left: 0;\n        right: 0;\n        top: 0;\n        bottom: 0;\n      `, [\n        iconSwitchTransition()\n      ])\n    ]),\n    cB('data-table-thead', `\n      transition: background-color .3s var(--n-bezier);\n      background-color: var(--n-merged-th-color);\n    `),\n    cB('data-table-tr', `\n      position: relative;\n      box-sizing: border-box;\n      background-clip: padding-box;\n      transition: background-color .3s var(--n-bezier);\n    `, [\n      cB('data-table-expand', `\n        position: sticky;\n        left: 0;\n        overflow: hidden;\n        margin: calc(var(--n-th-padding) * -1);\n        padding: var(--n-th-padding);\n        box-sizing: border-box;\n      `),\n      cM('striped', 'background-color: var(--n-merged-td-color-striped);', [\n        cB('data-table-td', 'background-color: var(--n-merged-td-color-striped);')\n      ]),\n      cNotM('summary', [\n        c('&:hover', 'background-color: var(--n-merged-td-color-hover);', [\n          c('>', [\n            cB('data-table-td', 'background-color: var(--n-merged-td-color-hover);')\n          ])\n        ])\n      ])\n    ]),\n    cB('data-table-th', `\n      padding: var(--n-th-padding);\n      position: relative;\n      text-align: start;\n      box-sizing: border-box;\n      background-color: var(--n-merged-th-color);\n      border-color: var(--n-merged-border-color);\n      border-bottom: 1px solid var(--n-merged-border-color);\n      color: var(--n-th-text-color);\n      transition:\n        border-color .3s var(--n-bezier),\n        color .3s var(--n-bezier),\n        background-color .3s var(--n-bezier);\n      font-weight: var(--n-th-font-weight);\n    `, [\n      cM('filterable', `\n        padding-right: 36px;\n      `, [\n        cM('sortable', `\n          padding-right: calc(var(--n-th-padding) + 36px);\n        `)\n      ]),\n      fixedColumnStyle,\n      cM('selection', `\n        padding: 0;\n        text-align: center;\n        line-height: 0;\n        z-index: 3;\n      `),\n      cE('title-wrapper', `\n        display: flex;\n        align-items: center;\n        flex-wrap: nowrap;\n        max-width: 100%;\n      `, [\n        cE('title', `\n          flex: 1;\n          min-width: 0;\n        `)\n      ]),\n      cE('ellipsis', `\n        display: inline-block;\n        vertical-align: bottom;\n        text-overflow: ellipsis;\n        overflow: hidden;\n        white-space: nowrap;\n        max-width: 100%;\n      `),\n      cM('hover', `\n        background-color: var(--n-merged-th-color-hover);\n      `),\n      cM('sorting', `\n        background-color: var(--n-merged-th-color-sorting);\n      `),\n      cM('sortable', `\n        cursor: pointer;\n      `, [\n        cE('ellipsis', `\n          max-width: calc(100% - 18px);\n        `),\n        c('&:hover', `\n          background-color: var(--n-merged-th-color-hover);\n        `)\n      ]),\n      cB('data-table-sorter', `\n        height: var(--n-sorter-size);\n        width: var(--n-sorter-size);\n        margin-left: 4px;\n        position: relative;\n        display: inline-flex;\n        align-items: center;\n        justify-content: center;\n        vertical-align: -0.2em;\n        color: var(--n-th-icon-color);\n        transition: color .3s var(--n-bezier);\n      `, [\n        cB('base-icon', 'transition: transform .3s var(--n-bezier)'),\n        cM('desc', [\n          cB('base-icon', `\n            transform: rotate(0deg);\n          `)\n        ]),\n        cM('asc', [\n          cB('base-icon', `\n            transform: rotate(-180deg);\n          `)\n        ]),\n        cM('asc, desc', `\n          color: var(--n-th-icon-color-active);\n        `)\n      ]),\n      cB('data-table-resize-button', `\n        width: var(--n-resizable-container-size);\n        position: absolute;\n        top: 0;\n        right: calc(var(--n-resizable-container-size) / 2);\n        bottom: 0;\n        cursor: col-resize;\n        user-select: none;\n      `, [\n        c('&::after', `\n          width: var(--n-resizable-size);\n          height: 50%;\n          position: absolute;\n          top: 50%;\n          left: calc(var(--n-resizable-container-size) / 2);\n          bottom: 0;\n          background-color: var(--n-merged-border-color);\n          transform: translateY(-50%);\n          transition: background-color .3s var(--n-bezier);\n          z-index: 1;\n          content: '';\n        `),\n        cM('active', [\n          c('&::after', `          \n            background-color: var(--n-th-icon-color-active);\n          `)\n        ]),\n        c('&:hover::after', `\n          background-color: var(--n-th-icon-color-active);\n        `)\n      ]),\n      cB('data-table-filter', `\n        position: absolute;\n        z-index: auto;\n        right: 0;\n        width: 36px;\n        top: 0;\n        bottom: 0;\n        cursor: pointer;\n        display: flex;\n        justify-content: center;\n        align-items: center;\n        transition:\n          background-color .3s var(--n-bezier),\n          color .3s var(--n-bezier);\n        font-size: var(--n-filter-size);\n        color: var(--n-th-icon-color);\n      `, [\n        c('&:hover', `\n          background-color: var(--n-th-button-color-hover);\n        `),\n        cM('show', `\n          background-color: var(--n-th-button-color-hover);\n        `),\n        cM('active', `\n          background-color: var(--n-th-button-color-hover);\n          color: var(--n-th-icon-color-active);\n        `)\n      ])\n    ]),\n    cB('data-table-td', `\n      padding: var(--n-td-padding);\n      text-align: start;\n      box-sizing: border-box;\n      border: none;\n      background-color: var(--n-merged-td-color);\n      color: var(--n-td-text-color);\n      border-bottom: 1px solid var(--n-merged-border-color);\n      transition:\n        box-shadow .3s var(--n-bezier),\n        background-color .3s var(--n-bezier),\n        border-color .3s var(--n-bezier),\n        color .3s var(--n-bezier);\n    `, [\n      cM('expand', [\n        cB('data-table-expand-trigger', `\n          margin-right: 0;\n        `)\n      ]),\n      cM('last-row', `\n        border-bottom: 0 solid var(--n-merged-border-color);\n      `, [\n        // make sure there is no overlap between bottom border and\n        // fixed column box shadow\n        c('&::after', `\n          bottom: 0 !important;\n        `),\n        c('&::before', `\n          bottom: 0 !important;\n        `)\n      ]),\n      cM('summary', `\n        background-color: var(--n-merged-th-color);\n      `),\n      cM('hover', `\n        background-color: var(--n-merged-td-color-hover);\n      `),\n      cM('sorting', `\n        background-color: var(--n-merged-td-color-sorting);\n      `),\n      cE('ellipsis', `\n        display: inline-block;\n        text-overflow: ellipsis;\n        overflow: hidden;\n        white-space: nowrap;\n        max-width: 100%;\n        vertical-align: bottom;\n        max-width: calc(100% - var(--indent-offset, -1.5) * 16px - 24px);\n      `),\n      cM('selection, expand', `\n        text-align: center;\n        padding: 0;\n        line-height: 0;\n      `),\n      fixedColumnStyle\n    ]),\n    cB('data-table-empty', `\n      box-sizing: border-box;\n      padding: var(--n-empty-padding);\n      flex-grow: 1;\n      flex-shrink: 0;\n      opacity: 1;\n      display: flex;\n      align-items: center;\n      justify-content: center;\n      transition: opacity .3s var(--n-bezier);\n    `, [\n      cM('hide', `\n        opacity: 0;\n      `)\n    ]),\n    cE('pagination', `\n      margin: var(--n-pagination-margin);\n      display: flex;\n      justify-content: flex-end;\n    `),\n    cB('data-table-wrapper', `\n      position: relative;\n      opacity: 1;\n      transition: opacity .3s var(--n-bezier), border-color .3s var(--n-bezier);\n      border-top-left-radius: var(--n-border-radius);\n      border-top-right-radius: var(--n-border-radius);\n      line-height: var(--n-line-height);\n    `),\n    cM('loading', [\n      cB('data-table-wrapper', `\n        opacity: var(--n-opacity-loading);\n        pointer-events: none;\n      `)\n    ]),\n    cM('single-column', [\n      cB('data-table-td', `\n        border-bottom: 0 solid var(--n-merged-border-color);\n      `, [\n        c('&::after, &::before', `\n          bottom: 0 !important;\n        `)\n      ])\n    ]),\n    cNotM('single-line', [\n      cB('data-table-th', `\n        border-right: 1px solid var(--n-merged-border-color);\n      `, [\n        cM('last', `\n          border-right: 0 solid var(--n-merged-border-color);\n        `)\n      ]),\n      cB('data-table-td', `\n        border-right: 1px solid var(--n-merged-border-color);\n      `, [\n        cM('last-col', `\n          border-right: 0 solid var(--n-merged-border-color);\n        `)\n      ])\n    ]),\n    cM('bordered', [\n      cB('data-table-wrapper', `\n        border: 1px solid var(--n-merged-border-color);\n        border-bottom-left-radius: var(--n-border-radius);\n        border-bottom-right-radius: var(--n-border-radius);\n        overflow: hidden;\n      `)\n    ]),\n    cB('data-table-base-table', [\n      cM('transition-disabled', [\n        cB('data-table-th', [c('&::after, &::before', 'transition: none;')]),\n        cB('data-table-td', [c('&::after, &::before', 'transition: none;')])\n      ])\n    ]),\n    cM('bottom-bordered', [\n      cB('data-table-td', [\n        cM('last-row', `\n          border-bottom: 1px solid var(--n-merged-border-color);\n        `)\n      ])\n    ]),\n    cB('data-table-table', `\n      font-variant-numeric: tabular-nums;\n      width: 100%;\n      word-break: break-word;\n      transition: background-color .3s var(--n-bezier);\n      border-collapse: separate;\n      border-spacing: 0;\n      background-color: var(--n-merged-td-color);\n    `),\n    cB('data-table-base-table-header', `\n      border-top-left-radius: calc(var(--n-border-radius) - 1px);\n      border-top-right-radius: calc(var(--n-border-radius) - 1px);\n      z-index: 3;\n      overflow: scroll;\n      flex-shrink: 0;\n      transition: border-color .3s var(--n-bezier);\n      scrollbar-width: none;\n    `, [\n      c('&::-webkit-scrollbar, &::-webkit-scrollbar-track-piece, &::-webkit-scrollbar-thumb', `\n        display: none;\n        width: 0;\n        height: 0;\n      `)\n    ]),\n    cB('data-table-check-extra', `\n      transition: color .3s var(--n-bezier);\n      color: var(--n-th-icon-color);\n      position: absolute;\n      font-size: 14px;\n      right: -4px;\n      top: 50%;\n      transform: translateY(-50%);\n      z-index: 1;\n    `)\n  ]),\n  cB('data-table-filter-menu', [\n    cB('scrollbar', `\n      max-height: 240px;\n    `),\n    cE('group', `\n      display: flex;\n      flex-direction: column;\n      padding: 12px 12px 0 12px;\n    `, [\n      cB('checkbox', `\n        margin-bottom: 12px;\n        margin-right: 0;\n      `),\n      cB('radio', `\n        margin-bottom: 12px;\n        margin-right: 0;\n      `)\n    ]),\n    cE('action', `\n      padding: var(--n-action-padding);\n      display: flex;\n      flex-wrap: nowrap;\n      justify-content: space-evenly;\n      border-top: 1px solid var(--n-action-divider-color);\n    `, [\n      cB('button', [\n        c('&:not(:last-child)', `\n          margin: var(--n-action-button-margin);\n        `),\n        c('&:last-child', `\n          margin-right: 0;\n        `)\n      ])\n    ]),\n    cB('divider', `\n      margin: 0 !important;\n    `)\n  ]),\n  insideModal(cB('data-table', `\n    --n-merged-th-color: var(--n-th-color-modal);\n    --n-merged-td-color: var(--n-td-color-modal);\n    --n-merged-border-color: var(--n-border-color-modal);\n    --n-merged-th-color-hover: var(--n-th-color-hover-modal);\n    --n-merged-td-color-hover: var(--n-td-color-hover-modal);\n    --n-merged-th-color-sorting: var(--n-th-color-hover-modal);\n    --n-merged-td-color-sorting: var(--n-td-color-hover-modal);\n    --n-merged-td-color-striped: var(--n-td-color-striped-modal);\n  `)),\n  insidePopover(cB('data-table', `\n    --n-merged-th-color: var(--n-th-color-popover);\n    --n-merged-td-color: var(--n-td-color-popover);\n    --n-merged-border-color: var(--n-border-color-popover);\n    --n-merged-th-color-hover: var(--n-th-color-hover-popover);\n    --n-merged-td-color-hover: var(--n-td-color-hover-popover);\n    --n-merged-th-color-sorting: var(--n-th-color-hover-popover);\n    --n-merged-td-color-sorting: var(--n-td-color-hover-popover);\n    --n-merged-td-color-striped: var(--n-td-color-striped-popover);\n  `))\n])\n\nfunction createFixedColumnStyle(): CNode[] {\n  return [\n    cM('fixed-left', `\n      left: 0;\n      position: sticky;\n      z-index: 2;\n    `, [\n      c('&::after', `\n        pointer-events: none;\n        content: \"\";\n        width: 36px;\n        display: inline-block;\n        position: absolute;\n        top: 0;\n        bottom: -1px;\n        transition: box-shadow .2s var(--n-bezier);\n        right: -36px;\n      `)\n    ]),\n    cM('fixed-right', `\n      right: 0;\n      position: sticky;\n      z-index: 1;\n    `, [\n      c('&::before', `\n        pointer-events: none;\n        content: \"\";\n        width: 36px;\n        display: inline-block;\n        position: absolute;\n        top: 0;\n        bottom: -1px;\n        transition: box-shadow .2s var(--n-bezier);\n        left: -36px;\n      `)\n    ])\n  ]\n}\n"
  },
  {
    "path": "src/data-table/src/styles/rtl.cssr.ts",
    "content": "import { c, cB, cM } from '../../../_utils/cssr'\n\nexport default c([\n  cB('data-table', [\n    cM('rtl', `\n      direction: rtl;\n    `, [\n      cB('data-table-th', [\n        cM('filterable', `\n          padding-left: 36px;\n          padding-right: var(--n-th-padding);\n        `, [\n          cM('sortable', `\n            padding-right: var(--n-th-padding);\n            padding-left: calc(var(--n-th-padding) + 36px);\n          `)\n        ]),\n        cB('data-table-sorter', `\n          margin-left: 0;\n          margin-right: 4px;\n        `),\n        cB('data-table-filter', `\n          right: unset;\n          left: 0;\n        `)\n      ])\n    ])\n  ]),\n  cB('data-table-filter-menu', [\n    cM('rtl', `\n      direction: rtl;\n    `)\n  ])\n])\n"
  },
  {
    "path": "src/data-table/src/use-check.ts",
    "content": "import type { TreeMate } from 'treemate'\nimport type { ComputedRef } from 'vue'\nimport type {\n  DataTableSetupProps,\n  InternalRowData,\n  RowData,\n  RowKey,\n  TableSelectionColumn,\n  TmNode\n} from './interface'\nimport { computed, ref } from 'vue'\nimport { call } from '../../_utils'\n\nexport function useCheck(\n  props: DataTableSetupProps,\n  data: {\n    selectionColumnRef: ComputedRef<TableSelectionColumn | null>\n    paginatedDataRef: ComputedRef<TmNode[]>\n    treeMateRef: ComputedRef<TreeMate<InternalRowData>>\n  }\n) {\n  const { paginatedDataRef, treeMateRef, selectionColumnRef } = data\n  const uncontrolledCheckedRowKeysRef = ref(props.defaultCheckedRowKeys)\n  const mergedCheckState = computed(() => {\n    const { checkedRowKeys } = props\n    const sourceKeys\n      = checkedRowKeys === undefined\n        ? uncontrolledCheckedRowKeysRef.value\n        : checkedRowKeys\n    if (selectionColumnRef.value?.multiple === false) {\n      return {\n        checkedKeys: sourceKeys.slice(0, 1),\n        indeterminateKeys: []\n      }\n    }\n    return treeMateRef.value.getCheckedKeys(sourceKeys, {\n      cascade: props.cascade,\n      allowNotLoaded: props.allowCheckingNotLoaded\n    })\n  })\n\n  const mergedCheckedRowKeysRef = computed(\n    () => mergedCheckState.value.checkedKeys\n  )\n  const mergedInderminateRowKeysRef = computed(\n    () => mergedCheckState.value.indeterminateKeys\n  )\n  const mergedCheckedRowKeySetRef = computed(() => {\n    return new Set(mergedCheckedRowKeysRef.value)\n  })\n  const mergedInderminateRowKeySetRef = computed(() => {\n    return new Set(mergedInderminateRowKeysRef.value)\n  })\n  const countOfCurrentPageCheckedRowsRef = computed(() => {\n    const { value: mergedCheckedRowKeySet } = mergedCheckedRowKeySetRef\n    return paginatedDataRef.value.reduce((total, tmNode) => {\n      const { key, disabled } = tmNode\n      return total + (!disabled && mergedCheckedRowKeySet.has(key) ? 1 : 0)\n    }, 0)\n  })\n  const countOfCurrentPageDisabledRowsRef = computed(() => {\n    return paginatedDataRef.value.filter(item => item.disabled).length\n  })\n  const someRowsCheckedRef = computed(() => {\n    const { length } = paginatedDataRef.value\n    const { value: mergedInderminateRowKeySet } = mergedInderminateRowKeySetRef\n    return (\n      (countOfCurrentPageCheckedRowsRef.value > 0\n        && countOfCurrentPageCheckedRowsRef.value\n        < length - countOfCurrentPageDisabledRowsRef.value)\n      || paginatedDataRef.value.some(rowData =>\n        mergedInderminateRowKeySet.has(rowData.key)\n      )\n    )\n  })\n  const allRowsCheckedRef = computed(() => {\n    const { length } = paginatedDataRef.value\n    return (\n      countOfCurrentPageCheckedRowsRef.value !== 0\n      && countOfCurrentPageCheckedRowsRef.value\n      === length - countOfCurrentPageDisabledRowsRef.value\n    )\n  })\n  const headerCheckboxDisabledRef = computed(() => {\n    return paginatedDataRef.value.length === 0\n  })\n  function doUpdateCheckedRowKeys(\n    keys: RowKey[],\n    row: RowData | undefined,\n    action: 'check' | 'uncheck' | 'checkAll' | 'uncheckAll'\n  ): void {\n    const {\n      'onUpdate:checkedRowKeys': _onUpdateCheckedRowKeys,\n      onUpdateCheckedRowKeys,\n      onCheckedRowKeysChange\n    } = props\n    const rows: InternalRowData[] = []\n    const {\n      value: { getNode }\n    } = treeMateRef\n    keys.forEach((key) => {\n      const row = getNode(key)?.rawNode\n      rows.push(row!)\n    })\n    if (_onUpdateCheckedRowKeys) {\n      call(_onUpdateCheckedRowKeys, keys, rows, { row, action })\n    }\n    if (onUpdateCheckedRowKeys) {\n      call(onUpdateCheckedRowKeys, keys, rows, { row, action })\n    }\n    if (onCheckedRowKeysChange) {\n      call(onCheckedRowKeysChange, keys, rows, { row, action })\n    }\n    uncontrolledCheckedRowKeysRef.value = keys\n  }\n  function doCheck(\n    rowKey: RowKey | RowKey[],\n    single: boolean = false,\n    rowInfo: RowData\n  ): void {\n    if (props.loading)\n      return\n    if (single) {\n      doUpdateCheckedRowKeys(\n        Array.isArray(rowKey) ? rowKey.slice(0, 1) : [rowKey],\n        rowInfo,\n        'check'\n      )\n      return\n    }\n    doUpdateCheckedRowKeys(\n      treeMateRef.value.check(rowKey, mergedCheckedRowKeysRef.value, {\n        cascade: props.cascade,\n        allowNotLoaded: props.allowCheckingNotLoaded\n      }).checkedKeys,\n      rowInfo,\n      'check'\n    )\n  }\n  function doUncheck(rowKey: RowKey | RowKey[], rowInfo: RowData): void {\n    if (props.loading)\n      return\n    doUpdateCheckedRowKeys(\n      treeMateRef.value.uncheck(rowKey, mergedCheckedRowKeysRef.value, {\n        cascade: props.cascade,\n        allowNotLoaded: props.allowCheckingNotLoaded\n      }).checkedKeys,\n      rowInfo,\n      'uncheck'\n    )\n  }\n  function doCheckAll(checkWholeTable: boolean = false): void {\n    const { value: column } = selectionColumnRef\n    if (!column || props.loading)\n      return\n    const rowKeysToCheck: RowKey[] = []\n    ;(checkWholeTable\n      ? treeMateRef.value.treeNodes\n      : paginatedDataRef.value\n    ).forEach((tmNode) => {\n      if (!tmNode.disabled) {\n        rowKeysToCheck.push(tmNode.key)\n      }\n    })\n    // alway cascade, to emit correct row keys\n    doUpdateCheckedRowKeys(\n      treeMateRef.value.check(rowKeysToCheck, mergedCheckedRowKeysRef.value, {\n        cascade: true,\n        allowNotLoaded: props.allowCheckingNotLoaded\n      }).checkedKeys,\n      undefined,\n      'checkAll'\n    )\n  }\n  function doUncheckAll(checkWholeTable: boolean = false): void {\n    const { value: column } = selectionColumnRef\n    if (!column || props.loading)\n      return\n    const rowKeysToUncheck: RowKey[] = []\n    ;(checkWholeTable\n      ? treeMateRef.value.treeNodes\n      : paginatedDataRef.value\n    ).forEach((tmNode) => {\n      if (!tmNode.disabled) {\n        rowKeysToUncheck.push(tmNode.key)\n      }\n    })\n    // alway cascade, to emit correct row keys\n    doUpdateCheckedRowKeys(\n      treeMateRef.value.uncheck(\n        rowKeysToUncheck,\n        mergedCheckedRowKeysRef.value,\n        {\n          cascade: true,\n          allowNotLoaded: props.allowCheckingNotLoaded\n        }\n      ).checkedKeys,\n      undefined,\n      'uncheckAll'\n    )\n  }\n  return {\n    mergedCheckedRowKeySetRef,\n    mergedCheckedRowKeysRef,\n    mergedInderminateRowKeySetRef,\n    someRowsCheckedRef,\n    allRowsCheckedRef,\n    headerCheckboxDisabledRef,\n    doUpdateCheckedRowKeys,\n    doCheckAll,\n    doUncheckAll,\n    doCheck,\n    doUncheck\n  }\n}\n"
  },
  {
    "path": "src/data-table/src/use-expand.ts",
    "content": "import type { TreeMate } from 'treemate'\nimport type { Ref } from 'vue'\nimport type {\n  DataTableSetupProps,\n  Expandable,\n  InternalRowData,\n  RowKey\n} from './interface'\nimport { useMemo, useMergedState } from 'vooks'\nimport { ref, toRef } from 'vue'\nimport { call, warn } from '../../_utils'\n\nexport function useExpand(\n  props: DataTableSetupProps,\n  treeMateRef: Ref<TreeMate<InternalRowData, InternalRowData, InternalRowData>>\n) {\n  const renderExpandRef = useMemo(() => {\n    for (const col of props.columns) {\n      if (col.type === 'expand') {\n        if (__DEV__ && !col.renderExpand) {\n          warn(\n            'data-table',\n            'column with type `expand` has no `renderExpand` prop.'\n          )\n        }\n        return col.renderExpand\n      }\n    }\n  })\n  const expandableRef = useMemo(() => {\n    // It's not reactive\n    let expandable: Expandable<any> | undefined\n    for (const col of props.columns) {\n      if (col.type === 'expand') {\n        expandable = col.expandable\n        break\n      }\n    }\n    return expandable\n  })\n\n  const uncontrolledExpandedRowKeysRef = ref(\n    props.defaultExpandAll\n      ? renderExpandRef?.value\n        ? (() => {\n            const expandedKeys: RowKey[] = []\n            treeMateRef.value.treeNodes.forEach((tmNode) => {\n              if (expandableRef.value?.(tmNode.rawNode)) {\n                expandedKeys.push(tmNode.key)\n              }\n            })\n            return expandedKeys\n          })()\n        : treeMateRef.value.getNonLeafKeys()\n      : props.defaultExpandedRowKeys\n  )\n  const controlledExpandedRowKeysRef = toRef(props, 'expandedRowKeys')\n  const stickyExpandedRowsRef = toRef(props, 'stickyExpandedRows')\n  const mergedExpandedRowKeysRef = useMergedState(\n    controlledExpandedRowKeysRef,\n    uncontrolledExpandedRowKeysRef\n  )\n  function doUpdateExpandedRowKeys(expandedKeys: RowKey[]): void {\n    const {\n      onUpdateExpandedRowKeys,\n      'onUpdate:expandedRowKeys': _onUpdateExpandedRowKeys\n    } = props\n    if (onUpdateExpandedRowKeys) {\n      call(onUpdateExpandedRowKeys, expandedKeys)\n    }\n    if (_onUpdateExpandedRowKeys) {\n      call(_onUpdateExpandedRowKeys, expandedKeys)\n    }\n    uncontrolledExpandedRowKeysRef.value = expandedKeys\n  }\n  return {\n    stickyExpandedRowsRef,\n    mergedExpandedRowKeysRef,\n    renderExpandRef,\n    expandableRef,\n    doUpdateExpandedRowKeys\n  }\n}\n"
  },
  {
    "path": "src/data-table/src/use-group-header.ts",
    "content": "import type { ComputedRef, CSSProperties } from 'vue'\nimport type {\n  ColumnKey,\n  DataTableSetupProps,\n  TableBaseColumn,\n  TableColumn,\n  TableColumns,\n  TableExpandColumn,\n  TableSelectionColumn\n} from './interface'\nimport { computed } from 'vue'\nimport { formatLength } from '../../_utils'\nimport { createCustomWidthStyle, getColKey } from './utils'\n\nexport interface RowItem {\n  colSpan: number\n  rowSpan: number\n  column: TableColumn\n  colIndex: number\n  isLast: boolean\n}\nexport interface ColItem {\n  key: string | number\n  style: CSSProperties\n  column: TableSelectionColumn | TableExpandColumn | TableBaseColumn\n  index: number\n  /**\n   * The width property is only applied to horizontally virtual scroll table\n   */\n  width: number\n}\n\ntype RowItemMap = WeakMap<TableColumn, RowItem>\nfunction getRowsAndCols(\n  columns: TableColumns,\n  getResizableWidth: (key: ColumnKey) => number | undefined\n): {\n  hasEllipsis: boolean\n  rows: RowItem[][]\n  cols: ColItem[]\n  dataRelatedCols: Array<\n    TableSelectionColumn | TableBaseColumn | TableExpandColumn\n  >\n} {\n  const rows: RowItem[][] = []\n  const cols: ColItem[] = []\n  const dataRelatedCols: Array<\n    TableSelectionColumn | TableBaseColumn | TableExpandColumn\n  > = []\n  const rowItemMap: RowItemMap = new WeakMap()\n  let maxDepth = -1\n  let totalRowSpan = 0\n  let hasEllipsis = false\n  let currentLeafIndex = 0\n  function ensureMaxDepth(columns: TableColumns, currentDepth: number): void {\n    if (currentDepth > maxDepth) {\n      rows[currentDepth] = []\n      maxDepth = currentDepth\n    }\n    columns.forEach((column) => {\n      if ('children' in column) {\n        ensureMaxDepth(column.children, currentDepth + 1)\n      }\n      else {\n        const key = 'key' in column ? column.key : undefined\n        cols.push({\n          key: getColKey(column),\n          style: createCustomWidthStyle(\n            column,\n            key !== undefined ? formatLength(getResizableWidth(key)) : undefined\n          ),\n          column,\n          index: currentLeafIndex++,\n          // The width property is only applied to horizontally virtual scroll table\n          width: column.width === undefined ? 128 : Number(column.width)\n        })\n        totalRowSpan += 1\n        if (!hasEllipsis) {\n          hasEllipsis = !!column.ellipsis\n        }\n        dataRelatedCols.push(column)\n      }\n    })\n  }\n  ensureMaxDepth(columns, 0)\n  currentLeafIndex = 0\n  function ensureColLayout(columns: TableColumns, currentDepth: number): void {\n    let hideUntilIndex = 0\n    columns.forEach((column) => {\n      if ('children' in column) {\n        // do not allow colSpan > 1 for non-leaf th\n        // we will execute the calculation logic\n        const cachedCurrentLeafIndex = currentLeafIndex\n        const rowItem: RowItem = {\n          column,\n          colIndex: currentLeafIndex,\n          colSpan: 0,\n          rowSpan: 1,\n          isLast: false\n        }\n        ensureColLayout(column.children, currentDepth + 1)\n        column.children.forEach((childColumn) => {\n          rowItem.colSpan += rowItemMap.get(childColumn)?.colSpan ?? 0\n        })\n        if (cachedCurrentLeafIndex + rowItem.colSpan === totalRowSpan) {\n          rowItem.isLast = true\n        }\n        rowItemMap.set(column, rowItem)\n        rows[currentDepth].push(rowItem)\n      }\n      else {\n        if (currentLeafIndex < hideUntilIndex) {\n          currentLeafIndex += 1\n          return\n        }\n        let colSpan: number = 1\n        if ('titleColSpan' in column) {\n          colSpan = column.titleColSpan ?? 1\n        }\n        if (colSpan > 1) {\n          hideUntilIndex = currentLeafIndex + colSpan\n        }\n        const isLast = currentLeafIndex + colSpan === totalRowSpan\n        const rowItem: RowItem = {\n          column,\n          colSpan,\n          colIndex: currentLeafIndex,\n          rowSpan: maxDepth - currentDepth + 1,\n          isLast\n        }\n        rowItemMap.set(column, rowItem)\n        rows[currentDepth].push(rowItem)\n        currentLeafIndex += 1\n      }\n    })\n  }\n  ensureColLayout(columns, 0)\n\n  return {\n    hasEllipsis,\n    rows,\n    cols,\n    dataRelatedCols\n  }\n}\n\nexport function useGroupHeader(\n  props: DataTableSetupProps,\n  getResizableWidth: (key: ColumnKey) => number | undefined\n): {\n  rowsRef: ComputedRef<RowItem[][]>\n  colsRef: ComputedRef<ColItem[]>\n  hasEllipsisRef: ComputedRef<boolean>\n  dataRelatedColsRef: ComputedRef<\n    Array<TableSelectionColumn | TableBaseColumn | TableExpandColumn>\n  >\n} {\n  const rowsAndCols = computed(() =>\n    getRowsAndCols(props.columns, getResizableWidth)\n  )\n  return {\n    rowsRef: computed(() => rowsAndCols.value.rows),\n    colsRef: computed(() => rowsAndCols.value.cols),\n    hasEllipsisRef: computed(() => rowsAndCols.value.hasEllipsis),\n    dataRelatedColsRef: computed(() => rowsAndCols.value.dataRelatedCols)\n  }\n}\n"
  },
  {
    "path": "src/data-table/src/use-resizable.ts",
    "content": "import type { ColumnKey, TableColumn } from './interface'\nimport { ref } from 'vue'\nimport { isColumnResizable } from './utils'\n\nexport function useResizable() {\n  const resizableWidthsRef = ref<Record<ColumnKey, number>>({})\n  function getResizableWidth(key: ColumnKey): number | undefined {\n    return resizableWidthsRef.value[key]\n  }\n  function doUpdateResizableWidth(column: TableColumn, width: number): void {\n    if (isColumnResizable(column) && 'key' in column) {\n      resizableWidthsRef.value[column.key] = width\n    }\n  }\n  function clearResizableWidth(): void {\n    resizableWidthsRef.value = {}\n  }\n  return {\n    getResizableWidth,\n    doUpdateResizableWidth,\n    clearResizableWidth\n  }\n}\n"
  },
  {
    "path": "src/data-table/src/use-scroll.ts",
    "content": "import type { ComputedRef, Ref } from 'vue'\nimport type {\n  ColumnKey,\n  DataTableSetupProps,\n  MainTableRef,\n  TableColumn\n} from './interface'\nimport { beforeNextFrameOnce } from 'seemly'\nimport { computed, ref, watch } from 'vue'\nimport { formatLength } from '../../_utils'\nimport { getColKey, getNumberColWidth } from './utils'\n\nexport function useScroll(\n  props: DataTableSetupProps,\n  {\n    mainTableInstRef,\n    mergedCurrentPageRef,\n    bodyWidthRef,\n    maxHeightRef,\n    mergedTableLayoutRef\n  }: {\n    maxHeightRef: Ref<string | number | undefined>\n    bodyWidthRef: Ref<null | number>\n    mainTableInstRef: Ref<MainTableRef | null>\n    mergedCurrentPageRef: ComputedRef<number>\n    mergedTableLayoutRef: Ref<'auto' | 'fixed'>\n  }\n) {\n  const explicitlyScrollableRef = computed(\n    () =>\n      props.scrollX !== undefined\n      || maxHeightRef.value !== undefined\n      || props.flexHeight\n  )\n  const xScrollableRef = computed(() => {\n    // For a basic table with auto layout whose content may overflow we will\n    // make it scrollable, which differs from browser's native behavior.\n    // For native behavior, see\n    // https://developer.mozilla.org/en-US/docs/Web/CSS/table-layout\n    const isBasicAutoLayout\n      = !explicitlyScrollableRef.value && mergedTableLayoutRef.value === 'auto'\n    return props.scrollX !== undefined || isBasicAutoLayout\n  })\n\n  let lastScrollLeft = 0\n  const scrollPartRef = ref<'head' | 'body' | undefined>()\n  const leftActiveFixedColKeyRef = ref<ColumnKey | null>(null)\n  const leftActiveFixedChildrenColKeysRef = ref<ColumnKey[]>([])\n  const rightActiveFixedColKeyRef = ref<ColumnKey | null>(null)\n  const rightActiveFixedChildrenColKeysRef = ref<ColumnKey[]>([])\n  const styleScrollXRef = computed(() => {\n    return formatLength(props.scrollX)\n  })\n  const leftFixedColumnsRef = computed(() => {\n    return props.columns.filter(column => column.fixed === 'left')\n  })\n  const rightFixedColumnsRef = computed(() => {\n    return props.columns.filter(column => column.fixed === 'right')\n  })\n  const fixedColumnLeftMapRef = computed(() => {\n    const columns: Record<\n      ColumnKey,\n      { start: number, end: number } | undefined\n    > = {}\n    let left = 0\n    function traverse(cols: TableColumn[]): void {\n      cols.forEach((col) => {\n        const positionInfo = { start: left, end: 0 }\n        columns[getColKey(col)] = positionInfo\n        if ('children' in col) {\n          traverse(col.children)\n          positionInfo.end = left\n        }\n        else {\n          left += getNumberColWidth(col) || 0\n          positionInfo.end = left\n        }\n      })\n    }\n    traverse(leftFixedColumnsRef.value)\n    return columns\n  })\n  const fixedColumnRightMapRef = computed(() => {\n    const columns: Record<\n      ColumnKey,\n      { start: number, end: number } | undefined\n    > = {}\n    let right = 0\n    function traverse(cols: TableColumn[]): void {\n      for (let i = cols.length - 1; i >= 0; --i) {\n        const col = cols[i]\n        const positionInfo = { start: right, end: 0 }\n        columns[getColKey(col)] = positionInfo\n        if ('children' in col) {\n          traverse(col.children)\n          positionInfo.end = right\n        }\n        else {\n          right += getNumberColWidth(col) || 0\n          positionInfo.end = right\n        }\n      }\n    }\n    traverse(rightFixedColumnsRef.value)\n    return columns\n  })\n  function deriveActiveLeftFixedColumn(): void {\n    // target is header element\n    const { value: leftFixedColumns } = leftFixedColumnsRef\n    let leftWidth = 0\n    const { value: fixedColumnLeftMap } = fixedColumnLeftMapRef\n    let leftActiveFixedColKey: string | number | null = null\n    for (let i = 0; i < leftFixedColumns.length; ++i) {\n      const key = getColKey(leftFixedColumns[i])\n      if (lastScrollLeft > (fixedColumnLeftMap[key]?.start || 0) - leftWidth) {\n        leftActiveFixedColKey = key\n        leftWidth = fixedColumnLeftMap[key]?.end || 0\n      }\n      else {\n        break\n      }\n    }\n    leftActiveFixedColKeyRef.value = leftActiveFixedColKey\n  }\n  function deriveActiveLeftFixedChildrenColumns(): void {\n    leftActiveFixedChildrenColKeysRef.value = []\n    let activeLeftFixedColumn = props.columns.find(\n      col => getColKey(col) === leftActiveFixedColKeyRef.value\n    )\n    while (activeLeftFixedColumn && 'children' in activeLeftFixedColumn) {\n      const length: number = activeLeftFixedColumn.children.length\n      if (length === 0)\n        break\n      const nextActiveLeftFixedColumn\n        = activeLeftFixedColumn.children[length - 1]\n      leftActiveFixedChildrenColKeysRef.value.push(\n        getColKey(nextActiveLeftFixedColumn)\n      )\n      activeLeftFixedColumn = nextActiveLeftFixedColumn\n    }\n  }\n  function deriveActiveRightFixedColumn(): void {\n    // target is header element\n    const { value: rightFixedColumns } = rightFixedColumnsRef\n    const scrollWidth = Number(props.scrollX)\n    const { value: tableWidth } = bodyWidthRef\n    if (tableWidth === null)\n      return\n    let rightWidth = 0\n    let rightActiveFixedColKey: string | number | null = null\n    const { value: fixedColumnRightMap } = fixedColumnRightMapRef\n    for (let i = rightFixedColumns.length - 1; i >= 0; --i) {\n      const key = getColKey(rightFixedColumns[i])\n      if (\n        Math.round(\n          lastScrollLeft\n          + (fixedColumnRightMap[key]?.start || 0)\n          + tableWidth\n          - rightWidth\n        ) < scrollWidth\n      ) {\n        rightActiveFixedColKey = key\n        rightWidth = fixedColumnRightMap[key]?.end || 0\n      }\n      else {\n        break\n      }\n    }\n    rightActiveFixedColKeyRef.value = rightActiveFixedColKey\n  }\n  function deriveActiveRightFixedChildrenColumns(): void {\n    rightActiveFixedChildrenColKeysRef.value = []\n    let activeRightFixedColumn = props.columns.find(\n      col => getColKey(col) === rightActiveFixedColKeyRef.value\n    )\n    while (\n      activeRightFixedColumn\n      && 'children' in activeRightFixedColumn\n      && activeRightFixedColumn.children.length\n    ) {\n      const nextActiveRightFixedColumn = activeRightFixedColumn.children[0]\n      rightActiveFixedChildrenColKeysRef.value.push(\n        getColKey(nextActiveRightFixedColumn)\n      )\n      activeRightFixedColumn = nextActiveRightFixedColumn\n    }\n  }\n\n  function getScrollElements(): {\n    header: HTMLElement | null\n    body: HTMLElement | null\n  } {\n    const header = mainTableInstRef.value\n      ? mainTableInstRef.value.getHeaderElement()\n      : null\n    const body = mainTableInstRef.value\n      ? mainTableInstRef.value.getBodyElement()\n      : null\n    return {\n      header,\n      body\n    }\n  }\n  function scrollMainTableBodyToTop(): void {\n    const { body } = getScrollElements()\n    if (body) {\n      body.scrollTop = 0\n    }\n  }\n  function handleTableHeaderScroll(): void {\n    if (scrollPartRef.value !== 'body') {\n      beforeNextFrameOnce(syncScrollState)\n    }\n    else {\n      scrollPartRef.value = undefined\n    }\n  }\n  function handleTableBodyScroll(e: Event): void {\n    props.onScroll?.(e)\n    if (scrollPartRef.value !== 'head') {\n      beforeNextFrameOnce(syncScrollState)\n    }\n    else {\n      scrollPartRef.value = undefined\n    }\n  }\n  function syncScrollState(): void {\n    // We can't simply use props.scrollX to determine whether the table has\n    // need to be sync since user may set column width for each column.\n    // Just let it be, the scroll listener won't be triggered for a basic table.\n    const { header, body } = getScrollElements()\n    if (!body)\n      return\n    const { value: tableWidth } = bodyWidthRef\n    if (tableWidth === null)\n      return\n    if (header) {\n      // we need to deal with overscroll\n      const directionHead = lastScrollLeft - header.scrollLeft\n      scrollPartRef.value = directionHead !== 0 ? 'head' : 'body'\n      if (scrollPartRef.value === 'head') {\n        lastScrollLeft = header.scrollLeft\n        body.scrollLeft = lastScrollLeft\n      }\n      else {\n        lastScrollLeft = body.scrollLeft\n        header.scrollLeft = lastScrollLeft\n      }\n    }\n    else {\n      lastScrollLeft = body.scrollLeft\n    }\n    deriveActiveLeftFixedColumn()\n    deriveActiveLeftFixedChildrenColumns()\n    deriveActiveRightFixedColumn()\n    deriveActiveRightFixedChildrenColumns()\n  }\n  function setHeaderScrollLeft(left: number): void {\n    const { header } = getScrollElements()\n    if (!header)\n      return\n    header.scrollLeft = left\n    syncScrollState()\n  }\n  watch(mergedCurrentPageRef, () => {\n    scrollMainTableBodyToTop()\n  })\n  return {\n    styleScrollXRef,\n    fixedColumnLeftMapRef,\n    fixedColumnRightMapRef,\n    leftFixedColumnsRef,\n    rightFixedColumnsRef,\n    leftActiveFixedColKeyRef,\n    leftActiveFixedChildrenColKeysRef,\n    rightActiveFixedColKeyRef,\n    rightActiveFixedChildrenColKeysRef,\n    syncScrollState,\n    handleTableBodyScroll,\n    handleTableHeaderScroll,\n    setHeaderScrollLeft,\n    explicitlyScrollableRef,\n    xScrollableRef\n  }\n}\n"
  },
  {
    "path": "src/data-table/src/use-sorter.ts",
    "content": "import type { ComputedRef } from 'vue'\nimport type {\n  ColumnKey,\n  CompareFn,\n  DataTableSetupProps,\n  InternalRowData,\n  OnUpdateSorterImpl,\n  SortOrder,\n  SortState,\n  TableBaseColumn,\n  TableExpandColumn,\n  TableSelectionColumn,\n  TmNode\n} from './interface'\nimport { computed, ref } from 'vue'\nimport { call } from '../../_utils'\nimport { getFlagOfOrder } from './utils'\n\nfunction getMultiplePriority(\n  sorter: TableBaseColumn['sorter']\n): number | false {\n  if (typeof sorter === 'object' && typeof sorter.multiple === 'number') {\n    return sorter.multiple\n  }\n  return false\n}\n\nfunction getSortFunction(\n  sorter: TableBaseColumn['sorter'],\n  columnKey: ColumnKey\n): CompareFn | false {\n  if (\n    columnKey\n    && (sorter === undefined\n      || sorter === 'default'\n      || (typeof sorter === 'object' && sorter.compare === 'default'))\n  ) {\n    return getDefaultSorterFn(columnKey)\n  }\n  if (typeof sorter === 'function') {\n    return sorter\n  }\n  if (\n    sorter\n    && typeof sorter === 'object'\n    && sorter.compare\n    && sorter.compare !== 'default'\n  ) {\n    return sorter.compare\n  }\n  return false\n}\n\nfunction getDefaultSorterFn(\n  columnKey: ColumnKey\n): (row1: InternalRowData, row2: InternalRowData) => number {\n  return (row1: InternalRowData, row2: InternalRowData) => {\n    const value1 = row1[columnKey]\n    const value2 = row2[columnKey]\n\n    if (value1 === null || value1 === undefined) {\n      if (value2 === null || value2 === undefined)\n        return 0\n      return -1\n    }\n    else if (value2 === null || value2 === undefined) {\n      return 1\n    }\n    else if (typeof value1 === 'number' && typeof value2 === 'number') {\n      return value1 - value2\n    }\n    else if (typeof value1 === 'string' && typeof value2 === 'string') {\n      return value1.localeCompare(value2)\n    }\n    return 0\n  }\n}\n\nexport function useSorter(\n  props: DataTableSetupProps,\n  {\n    dataRelatedColsRef,\n    filteredDataRef\n  }: {\n    dataRelatedColsRef: ComputedRef<\n      Array<TableSelectionColumn | TableBaseColumn | TableExpandColumn>\n    >\n    filteredDataRef: ComputedRef<TmNode[]>\n  }\n) {\n  const defaultSortState: SortState[] = []\n\n  // initialize\n  dataRelatedColsRef.value.forEach((column) => {\n    if (column.sorter !== undefined) {\n      updateSortStatesByNewSortState(defaultSortState, {\n        columnKey: column.key,\n        sorter: column.sorter,\n        order: column.defaultSortOrder ?? false\n      })\n    }\n  })\n\n  const uncontrolledSortStateRef = ref<SortState | SortState[] | null>(\n    defaultSortState\n  )\n  const mergedSortStateRef = computed(() => {\n    // If one of the columns's sort order is false or 'ascend' or 'descend',\n    // the table's controll functionality should work in controlled manner.\n    const columnsWithControlledSortOrder = dataRelatedColsRef.value.filter(\n      column =>\n        column.type !== 'selection'\n        && column.sorter !== undefined\n        && (column.sortOrder === 'ascend'\n          || column.sortOrder === 'descend'\n          || column.sortOrder === false)\n    )\n    // if multiple columns are controlled sortable, then we need to find columns with active sortOrder\n    const columnToSort: TableBaseColumn[] | undefined = (\n      columnsWithControlledSortOrder as TableBaseColumn[]\n    ).filter((col: TableBaseColumn) => col.sortOrder !== false)\n    if (columnToSort.length) {\n      return columnToSort.map((column) => {\n        return {\n          columnKey: column.key,\n          // column to sort has controlled sorter\n          // sorter && sort order won't be undefined\n          order: column.sortOrder!,\n          sorter: column.sorter!\n        }\n      })\n    }\n    // If any column is in controlled mode, the sorting state of the table is\n    // in controlled mode\n    if (columnsWithControlledSortOrder.length)\n      return []\n    const { value: uncontrolledSortState } = uncontrolledSortStateRef\n    if (Array.isArray(uncontrolledSortState)) {\n      return uncontrolledSortState\n    }\n    else if (uncontrolledSortState) {\n      return [uncontrolledSortState]\n    }\n    else {\n      return []\n    }\n  })\n  const sortedDataRef = computed<TmNode[]>(() => {\n    const activeSorters = mergedSortStateRef.value.slice().sort((a, b) => {\n      const item1Priority = getMultiplePriority(a.sorter) || 0\n      const item2Priority = getMultiplePriority(b.sorter) || 0\n      return item2Priority - item1Priority\n    })\n    if (activeSorters.length) {\n      const filteredData = filteredDataRef.value.slice()\n      return filteredData.sort((tmNode1, tmNode2) => {\n        let compareResult = 0\n        activeSorters.some((sorterState) => {\n          const { columnKey, sorter, order } = sorterState\n\n          const compareFn = getSortFunction(sorter, columnKey)\n          if (compareFn && order) {\n            compareResult = compareFn(tmNode1.rawNode, tmNode2.rawNode)\n\n            if (compareResult !== 0) {\n              compareResult = compareResult * getFlagOfOrder(order)\n              return true\n            }\n          }\n          return false\n        })\n        return compareResult\n      })\n    }\n    return filteredDataRef.value\n  })\n\n  function getUpdatedSorterState(\n    sortState: SortState | null\n  ): SortState | SortState[] | null {\n    let currentSortState = mergedSortStateRef.value.slice()\n    // Multiple sorter (if you clicked on a multiple sort column)\n    if (sortState && getMultiplePriority(sortState.sorter) !== false) {\n      // clear column is not multiple sort\n      currentSortState = currentSortState.filter(\n        sortState => getMultiplePriority(sortState.sorter) !== false\n      )\n      updateSortStatesByNewSortState(currentSortState, sortState)\n      return currentSortState\n    }\n    else if (sortState) {\n      // single sorter\n      return sortState\n    }\n    // no sorter\n    return null\n  }\n\n  function deriveNextSorter(sortState: SortState | null): void {\n    const nextSorterState: SortState | SortState[] | null\n      = getUpdatedSorterState(sortState)\n    doUpdateSorter(nextSorterState)\n  }\n\n  function doUpdateSorter(sortState: SortState | SortState[] | null): void {\n    const {\n      'onUpdate:sorter': _onUpdateSorter,\n      onUpdateSorter,\n      onSorterChange\n    } = props\n\n    if (_onUpdateSorter) {\n      call(_onUpdateSorter as OnUpdateSorterImpl, sortState)\n    }\n    if (onUpdateSorter) {\n      call(onUpdateSorter as OnUpdateSorterImpl, sortState)\n    }\n    if (onSorterChange) {\n      call(onSorterChange as OnUpdateSorterImpl, sortState)\n    }\n    uncontrolledSortStateRef.value = sortState\n  }\n\n  function sort(columnKey: ColumnKey, order: SortOrder = 'ascend'): void {\n    if (!columnKey) {\n      clearSorter()\n    }\n    else {\n      const columnToSort = dataRelatedColsRef.value.find(\n        column =>\n          column.type !== 'selection'\n          && column.type !== 'expand'\n          && column.key === columnKey\n      )\n      if (!columnToSort?.sorter)\n        return\n      const sorter = columnToSort.sorter\n      deriveNextSorter({\n        columnKey,\n        sorter,\n        order\n      })\n    }\n  }\n\n  function clearSorter(): void {\n    doUpdateSorter(null)\n  }\n\n  function updateSortStatesByNewSortState(\n    sortStates: SortState[],\n    sortState: SortState\n  ): void {\n    const index = sortStates.findIndex(\n      state => sortState?.columnKey && state.columnKey === sortState.columnKey\n    )\n    if (index !== undefined && index >= 0) {\n      sortStates[index] = sortState\n    }\n    else {\n      sortStates.push(sortState)\n    }\n  }\n\n  return {\n    clearSorter,\n    sort,\n    sortedDataRef,\n    mergedSortStateRef,\n    deriveNextSorter\n  }\n}\n"
  },
  {
    "path": "src/data-table/src/use-table-data.ts",
    "content": "import type { ComputedRef } from 'vue'\nimport type { PaginationProps } from '../../pagination/src/Pagination'\nimport type {\n  ColumnKey,\n  DataTableSetupProps,\n  Filter,\n  FilterOptionValue,\n  FilterState,\n  InternalRowData,\n  RowKey,\n  TableBaseColumn,\n  TableExpandColumn,\n  TableSelectionColumn,\n  TmNode\n} from './interface'\nimport { createTreeMate } from 'treemate'\nimport { useMemo, useMergedState } from 'vooks'\nimport { computed, ref } from 'vue'\nimport { call, warn } from '../../_utils'\nimport { getDefaultPageSize } from '../../pagination/src/utils'\nimport { useSorter } from './use-sorter'\nimport { createShallowClonedObject } from './utils'\n\n// useTableData combines filter, sorter and pagination\nexport function useTableData(\n  props: DataTableSetupProps,\n  {\n    dataRelatedColsRef\n  }: {\n    dataRelatedColsRef: ComputedRef<\n      Array<TableSelectionColumn | TableBaseColumn | TableExpandColumn>\n    >\n  }\n) {\n  const selectionColumnRef = computed<TableSelectionColumn | null>(() => {\n    const getSelectionColumn = (\n      cols: typeof props.columns\n    ): TableSelectionColumn | null => {\n      for (let i = 0; i < cols.length; ++i) {\n        const col = cols[i]\n        if ('children' in col) {\n          return getSelectionColumn(col.children)\n        }\n        else if (col.type === 'selection') {\n          return col\n        }\n      }\n      return null\n    }\n    return getSelectionColumn(props.columns)\n  })\n\n  const treeMateRef = computed(() => {\n    const { childrenKey } = props\n    return createTreeMate<InternalRowData>(props.data, {\n      ignoreEmptyChildren: true,\n      getKey: props.rowKey,\n      getChildren: rowData => rowData[childrenKey],\n      getDisabled: (rowData) => {\n        if (selectionColumnRef.value?.disabled?.(rowData)) {\n          return true\n        }\n        return false\n      }\n    })\n  })\n\n  const childTriggerColIndexRef = useMemo<number>(() => {\n    const { columns } = props\n    const { length } = columns\n    let firstContentfulColIndex: number | null = null\n    for (let i = 0; i < length; ++i) {\n      const col = columns[i]\n      if (!col.type && firstContentfulColIndex === null) {\n        firstContentfulColIndex = i\n      }\n      if ('tree' in col && col.tree) {\n        return i\n      }\n    }\n    return firstContentfulColIndex || 0\n  })\n\n  const uncontrolledFilterStateRef = ref<FilterState>({})\n  const { pagination } = props\n  const uncontrolledCurrentPageRef = ref(\n    pagination ? pagination.defaultPage || 1 : 1\n  )\n  const uncontrolledPageSizeRef = ref(getDefaultPageSize(pagination))\n\n  const mergedFilterStateRef = computed<FilterState>(() => {\n    const columnsWithControlledFilter = dataRelatedColsRef.value.filter(\n      (column) => {\n        return (\n          column.filterOptionValues !== undefined\n          || column.filterOptionValue !== undefined\n        )\n      }\n    )\n    const controlledFilterState: FilterState = {}\n    columnsWithControlledFilter.forEach((column) => {\n      if (column.type === 'selection' || column.type === 'expand')\n        return\n      if (column.filterOptionValues === undefined) {\n        controlledFilterState[column.key] = column.filterOptionValue ?? null\n      }\n      else {\n        controlledFilterState[column.key] = column.filterOptionValues\n      }\n    })\n    const activeFilters = Object.assign(\n      createShallowClonedObject(uncontrolledFilterStateRef.value),\n      controlledFilterState\n    )\n    return activeFilters\n  })\n\n  const filteredDataRef = computed<TmNode[]>(() => {\n    const mergedFilterState = mergedFilterStateRef.value\n    const { columns } = props\n    function createDefaultFilter(columnKey: ColumnKey): Filter {\n      return (filterOptionValue: FilterOptionValue, row: InternalRowData) =>\n        !!~String(row[columnKey]).indexOf(String(filterOptionValue))\n    }\n    const {\n      value: { treeNodes: data }\n    } = treeMateRef\n    const columnEntries: Array<[ColumnKey, TableBaseColumn]> = []\n    columns.forEach((column) => {\n      if (\n        column.type === 'selection'\n        || column.type === 'expand'\n        || 'children' in column\n      ) {\n        return\n      }\n      columnEntries.push([column.key, column])\n    })\n    return data\n      ? data.filter((tmNode) => {\n          const { rawNode: row } = tmNode\n          // traverse all filters\n          for (const [columnKey, column] of columnEntries) {\n            let activeFilterOptionValues = mergedFilterState[columnKey]\n            if (activeFilterOptionValues == null)\n              continue\n            if (!Array.isArray(activeFilterOptionValues)) {\n              activeFilterOptionValues = [activeFilterOptionValues]\n            }\n            if (!activeFilterOptionValues.length)\n              continue\n            // When async, filter won't be set, so data won't be filtered\n            const filter\n              = column.filter === 'default'\n                ? createDefaultFilter(columnKey)\n                : column.filter\n            if (column && typeof filter === 'function') {\n              if (column.filterMode === 'and') {\n                if (\n                  activeFilterOptionValues.some(\n                    filterOptionValue => !filter(filterOptionValue, row)\n                  )\n                ) {\n                  return false\n                }\n              }\n              else {\n                if (\n                  activeFilterOptionValues.some(filterOptionValue =>\n                    filter(filterOptionValue, row)\n                  )\n                ) {\n                  continue\n                }\n                else {\n                  return false\n                }\n              }\n            }\n          }\n          return true\n        })\n      : []\n  })\n\n  const {\n    sortedDataRef,\n    deriveNextSorter,\n    mergedSortStateRef,\n    sort,\n    clearSorter\n  } = useSorter(props, {\n    dataRelatedColsRef,\n    filteredDataRef\n  })\n\n  // initialize\n  dataRelatedColsRef.value.forEach((column) => {\n    if (column.filter) {\n      const defaultFilterOptionValues = column.defaultFilterOptionValues\n      if (column.filterMultiple) {\n        uncontrolledFilterStateRef.value[column.key]\n          = defaultFilterOptionValues || []\n      }\n      else if (defaultFilterOptionValues !== undefined) {\n        // this branch is for compatibility, someone may use `values` in single filter mode\n        uncontrolledFilterStateRef.value[column.key]\n          = defaultFilterOptionValues === null ? [] : defaultFilterOptionValues\n      }\n      else {\n        uncontrolledFilterStateRef.value[column.key]\n          = column.defaultFilterOptionValue ?? null\n      }\n    }\n  })\n\n  const controlledCurrentPageRef = computed(() => {\n    const { pagination } = props\n    if (pagination === false)\n      return undefined\n    return pagination.page\n  })\n  const controlledPageSizeRef = computed(() => {\n    const { pagination } = props\n    if (pagination === false)\n      return undefined\n    return pagination.pageSize\n  })\n\n  const _mergedCurrentPageRef = useMergedState(\n    controlledCurrentPageRef,\n    uncontrolledCurrentPageRef\n  )\n\n  const mergedPageSizeRef = useMergedState(\n    controlledPageSizeRef,\n    uncontrolledPageSizeRef\n  )\n\n  const boundedMergedCurrentPageRef = useMemo<number>(() => {\n    const page = _mergedCurrentPageRef.value\n    return props.remote\n      ? page\n      : Math.max(\n          1,\n          Math.min(\n            Math.ceil(filteredDataRef.value.length / mergedPageSizeRef.value),\n            page\n          )\n        )\n  })\n\n  const mergedPageCountRef = computed(() => {\n    const { pagination } = props\n    if (pagination) {\n      const { pageCount } = pagination\n      if (pageCount !== undefined)\n        return pageCount\n    }\n    return undefined\n  })\n\n  const paginatedDataRef = computed<TmNode[]>(() => {\n    if (props.remote)\n      return treeMateRef.value.treeNodes\n    if (!props.pagination)\n      return sortedDataRef.value\n    const pageSize = mergedPageSizeRef.value\n    const startIndex = (boundedMergedCurrentPageRef.value - 1) * pageSize\n    return sortedDataRef.value.slice(startIndex, startIndex + pageSize)\n  })\n\n  const rawPaginatedDataRef = computed<InternalRowData[]>(() => {\n    return paginatedDataRef.value.map(tmNode => tmNode.rawNode)\n  })\n\n  function mergedOnUpdatePage(page: number): void {\n    const { pagination } = props\n    if (pagination) {\n      const {\n        onChange,\n        'onUpdate:page': _onUpdatePage,\n        onUpdatePage\n      } = pagination\n      if (onChange)\n        call(onChange, page)\n      if (onUpdatePage)\n        call(onUpdatePage, page)\n      if (_onUpdatePage)\n        call(_onUpdatePage, page)\n      doUpdatePage(page)\n    }\n  }\n  function mergedOnUpdatePageSize(pageSize: number): void {\n    const { pagination } = props\n    if (pagination) {\n      const {\n        onPageSizeChange,\n        'onUpdate:pageSize': _onUpdatePageSize,\n        onUpdatePageSize\n      } = pagination\n      if (onPageSizeChange)\n        call(onPageSizeChange, pageSize)\n      if (onUpdatePageSize)\n        call(onUpdatePageSize, pageSize)\n      if (_onUpdatePageSize)\n        call(_onUpdatePageSize, pageSize)\n      doUpdatePageSize(pageSize)\n    }\n  }\n  const mergedItemCountRef = computed(() => {\n    if (props.remote) {\n      const { pagination } = props\n      if (pagination) {\n        const { itemCount } = pagination\n        if (itemCount !== undefined)\n          return itemCount\n      }\n      return undefined\n    }\n    return filteredDataRef.value.length\n  })\n  const mergedPaginationRef = computed<PaginationProps>(() => {\n    return {\n      ...props.pagination,\n      // reset deprecated methods\n      onChange: undefined,\n      onUpdatePage: undefined,\n      onUpdatePageSize: undefined,\n      onPageSizeChange: undefined,\n      'onUpdate:page': mergedOnUpdatePage,\n      'onUpdate:pageSize': mergedOnUpdatePageSize,\n      // writing merged props after pagination to avoid\n      // pagination[key] === undefined\n      // key still exists but value is undefined\n      page: boundedMergedCurrentPageRef.value,\n      pageSize: mergedPageSizeRef.value,\n      pageCount:\n        mergedItemCountRef.value === undefined\n          ? mergedPageCountRef.value\n          : undefined,\n      itemCount: mergedItemCountRef.value\n    }\n  })\n\n  function doUpdatePage(page: number): void {\n    const { 'onUpdate:page': _onUpdatePage, onPageChange, onUpdatePage } = props\n    if (onUpdatePage)\n      call(onUpdatePage, page)\n    if (_onUpdatePage)\n      call(_onUpdatePage, page)\n    if (onPageChange)\n      call(onPageChange, page)\n    uncontrolledCurrentPageRef.value = page\n  }\n  function doUpdatePageSize(pageSize: number): void {\n    const {\n      'onUpdate:pageSize': _onUpdatePageSize,\n      onPageSizeChange,\n      onUpdatePageSize\n    } = props\n    if (onPageSizeChange)\n      call(onPageSizeChange, pageSize)\n    if (onUpdatePageSize)\n      call(onUpdatePageSize, pageSize)\n    if (_onUpdatePageSize)\n      call(_onUpdatePageSize, pageSize)\n    uncontrolledPageSizeRef.value = pageSize\n  }\n\n  function doUpdateFilters(\n    filters: FilterState,\n    sourceColumn: TableBaseColumn\n  ): void {\n    const {\n      onUpdateFilters,\n      'onUpdate:filters': _onUpdateFilters,\n      onFiltersChange\n    } = props\n    if (onUpdateFilters)\n      call(onUpdateFilters, filters, sourceColumn)\n    if (_onUpdateFilters)\n      call(_onUpdateFilters, filters, sourceColumn)\n    if (onFiltersChange)\n      call(onFiltersChange, filters, sourceColumn)\n    uncontrolledFilterStateRef.value = filters\n  }\n\n  function onUnstableColumnResize(\n    resizedWidth: number,\n    limitedWidth: number,\n    column: TableBaseColumn,\n    getColumnWidth: (key: ColumnKey) => number | undefined\n  ): void {\n    props.onUnstableColumnResize?.(\n      resizedWidth,\n      limitedWidth,\n      column,\n      getColumnWidth\n    )\n  }\n\n  function page(page: number): void {\n    doUpdatePage(page)\n  }\n  function clearFilter(): void {\n    clearFilters()\n  }\n  function clearFilters(): void {\n    filters({})\n  }\n  function filters(filters: FilterState | null): void {\n    filter(filters)\n  }\n  function filter(filters: FilterState | null): void {\n    if (!filters) {\n      uncontrolledFilterStateRef.value = {}\n    }\n    else if (filters) {\n      uncontrolledFilterStateRef.value = createShallowClonedObject(filters)\n    }\n    else if (__DEV__) {\n      warn('data-table', '`filters` is not an object')\n    }\n  }\n  return {\n    treeMateRef,\n    mergedCurrentPageRef: boundedMergedCurrentPageRef,\n    mergedPaginationRef,\n    paginatedDataRef,\n    rawPaginatedDataRef,\n    mergedFilterStateRef,\n    mergedSortStateRef,\n    hoverKeyRef: ref<RowKey | null>(null),\n    selectionColumnRef,\n    childTriggerColIndexRef,\n    doUpdateFilters,\n    deriveNextSorter,\n    doUpdatePageSize,\n    doUpdatePage,\n    onUnstableColumnResize,\n    // exported methods\n    filter,\n    filters,\n    clearFilter,\n    clearFilters,\n    clearSorter,\n    page,\n    sort\n  }\n}\n"
  },
  {
    "path": "src/data-table/src/utils.ts",
    "content": "import type { CSSProperties } from 'vue'\nimport type {\n  CreateRowClassName,\n  InternalRowData,\n  RowData,\n  SortOrder,\n  SortOrderFlag,\n  SortState,\n  TableBaseColumn,\n  TableColumn,\n  TableExpandColumn,\n  TableSelectionColumn\n} from './interface'\nimport type { DataTableGetCsvCell, DataTableGetCsvHeader } from './public-types'\nimport { depx } from 'seemly'\nimport { formatLength } from '../../_utils'\n\nexport const SELECTION_COL_WIDTH = 40\nexport const EXPAND_COL_WIDTH = 40\n\nexport function getNumberColWidth(col: TableColumn): number | undefined {\n  if (col.type === 'selection') {\n    return col.width === undefined ? SELECTION_COL_WIDTH : depx(col.width)\n  }\n  if (col.type === 'expand') {\n    return col.width === undefined ? EXPAND_COL_WIDTH : depx(col.width)\n  }\n  if ('children' in col)\n    return undefined\n  if (typeof col.width === 'string') {\n    return depx(col.width)\n  }\n  return col.width\n}\n\nexport function getStringColWidth(col: TableColumn): string | undefined {\n  if (col.type === 'selection') {\n    return formatLength(col.width ?? SELECTION_COL_WIDTH)\n  }\n  if (col.type === 'expand') {\n    return formatLength(col.width ?? EXPAND_COL_WIDTH)\n  }\n  if ('children' in col) {\n    return undefined\n  }\n  return formatLength(col.width)\n}\n\nexport function getColKey(col: TableColumn): string | number {\n  if (col.type === 'selection')\n    return '__n_selection__'\n  if (col.type === 'expand')\n    return '__n_expand__'\n  return col.key\n}\n\nexport function createShallowClonedObject<T>(object: T): T {\n  if (!object)\n    return object\n  if (typeof object === 'object') {\n    return Object.assign({}, object)\n  }\n  return object\n}\n\nexport function getFlagOfOrder(order: SortOrder): SortOrderFlag {\n  if (order === 'ascend')\n    return 1\n  else if (order === 'descend')\n    return -1\n  return 0\n}\n\n// priority: min-width > max-width > width\nexport function clampValueFollowCSSRules(\n  value: number,\n  min?: number | string,\n  max?: number | string\n): number {\n  if (max !== undefined) {\n    value = Math.min(\n      value,\n      typeof max === 'number' ? max : Number.parseFloat(max)\n    )\n  }\n  if (min !== undefined) {\n    value = Math.max(\n      value,\n      typeof min === 'number' ? min : Number.parseFloat(min)\n    )\n  }\n  return value\n}\n\nexport function createCustomWidthStyle(\n  column: TableBaseColumn | TableSelectionColumn | TableExpandColumn,\n  resizedWidth?: string\n): CSSProperties {\n  if (resizedWidth !== undefined) {\n    return {\n      width: resizedWidth,\n      minWidth: resizedWidth,\n      maxWidth: resizedWidth\n    }\n  }\n  const width = getStringColWidth(column)\n  const { minWidth, maxWidth } = column\n  return {\n    width,\n    minWidth: formatLength(minWidth) || width,\n    maxWidth: formatLength(maxWidth)\n  }\n}\n\nexport function createRowClassName(\n  row: InternalRowData,\n  index: number,\n  rowClassName?: string | CreateRowClassName\n): string {\n  if (typeof rowClassName === 'function')\n    return rowClassName(row, index)\n  return rowClassName || ''\n}\n\n// for compatibility\n// If column.filterOptionValues or column.defaultFilterOptionValues is set, use\n// array value\nexport function shouldUseArrayInSingleMode(column: TableBaseColumn): boolean {\n  return (\n    column.filterOptionValues !== undefined\n    || (column.filterOptionValue === undefined\n      && column.defaultFilterOptionValues !== undefined)\n  )\n}\n\nexport function isColumnSortable(column: TableColumn): boolean {\n  if ('children' in column)\n    return false\n  return !!column.sorter\n}\n\nexport function isColumnResizable(column: TableColumn): boolean {\n  if ('children' in column && !!column.children.length)\n    return false\n  return !!column.resizable\n}\n\nexport function isColumnFilterable(column: TableColumn): boolean {\n  if ('children' in column)\n    return false\n  return (\n    !!column.filter && (!!column.filterOptions || !!column.renderFilterMenu)\n  )\n}\n\nfunction getNextOrderOf(order: SortOrder): SortOrder {\n  if (!order)\n    return 'descend'\n  else if (order === 'descend')\n    return 'ascend'\n  return false\n}\n\nexport function createNextSorter(\n  column: TableBaseColumn,\n  currentSortState: SortState | null\n): SortState | null {\n  if (column.sorter === undefined)\n    return null\n\n  const { customNextSortOrder } = column\n\n  if (currentSortState === null || currentSortState.columnKey !== column.key) {\n    return {\n      columnKey: column.key,\n      sorter: column.sorter,\n      order: getNextOrderOf(false)\n    }\n  }\n  else {\n    return {\n      ...currentSortState,\n      order: (customNextSortOrder || getNextOrderOf)(currentSortState.order)\n    }\n  }\n}\n\nexport function isColumnSorting(\n  column: TableColumn,\n  mergedSortState: SortState[]\n): boolean {\n  return (\n    mergedSortState.find(\n      state =>\n        state.columnKey === (column as TableBaseColumn).key && state.order\n    ) !== undefined\n  )\n}\n\nfunction formatCsvCell(value: unknown): string {\n  if (typeof value === 'string') {\n    return value.replace(/,/g, '\\\\,')\n  }\n  else if (value === null || value === undefined) {\n    return ''\n  }\n  else {\n    return `${value}`.replace(/,/g, '\\\\,')\n  }\n}\n\nexport function generateCsv(\n  columns: TableColumn[],\n  data: RowData[],\n  getCsvCell: DataTableGetCsvCell | undefined,\n  getCsvHeader: DataTableGetCsvHeader | undefined\n): string {\n  const exportableColumns = columns.filter(\n    column =>\n      column.type !== 'expand'\n      && column.type !== 'selection'\n      && column.allowExport !== false\n  )\n  const header = exportableColumns\n    .map((col: any) => {\n      return getCsvHeader ? getCsvHeader(col) : col.title\n    })\n    .join(',')\n  const rows = data.map((row) => {\n    return exportableColumns\n      .map((col: any) => {\n        return getCsvCell\n          ? getCsvCell(row[col.key], row, col)\n          : formatCsvCell(row[col.key])\n      })\n      .join(',')\n  })\n  return [header, ...rows].join('\\n')\n}\n"
  },
  {
    "path": "src/data-table/styles/_common.ts",
    "content": "export default {\n  thPaddingSmall: '8px',\n  thPaddingMedium: '12px',\n  thPaddingLarge: '12px',\n  tdPaddingSmall: '8px',\n  tdPaddingMedium: '12px',\n  tdPaddingLarge: '12px',\n  sorterSize: '15px',\n  resizableContainerSize: '8px',\n  resizableSize: '2px',\n  filterSize: '15px',\n  paginationMargin: '12px 0 0 0',\n  emptyPadding: '48px 0',\n  actionPadding: '8px 12px',\n  actionButtonMargin: '0 8px 0 0'\n}\n"
  },
  {
    "path": "src/data-table/styles/dark.ts",
    "content": "import type { DataTableTheme } from './light'\nimport { scrollbarDark } from '../../_internal/scrollbar/styles'\nimport { commonDark } from '../../_styles/common'\nimport { buttonDark } from '../../button/styles'\nimport { checkboxDark } from '../../checkbox/styles'\nimport { dropdownDark } from '../../dropdown/styles'\nimport { ellipsisDark } from '../../ellipsis/styles'\nimport { emptyDark } from '../../empty/styles'\nimport { paginationDark } from '../../pagination/styles'\nimport { popoverDark } from '../../popover/styles'\nimport { radioDark } from '../../radio/styles'\nimport { self } from './light'\n\nconst dataTableDark: DataTableTheme = {\n  name: 'DataTable',\n  common: commonDark,\n  peers: {\n    Button: buttonDark,\n    Checkbox: checkboxDark,\n    Radio: radioDark,\n    Pagination: paginationDark,\n    Scrollbar: scrollbarDark,\n    Empty: emptyDark,\n    Popover: popoverDark,\n    Ellipsis: ellipsisDark,\n    Dropdown: dropdownDark\n  },\n  self(vars) {\n    const commonSelf = self(vars)\n    commonSelf.boxShadowAfter = 'inset 12px 0 8px -12px rgba(0, 0, 0, .36)'\n    commonSelf.boxShadowBefore = 'inset -12px 0 8px -12px rgba(0, 0, 0, .36)'\n    return commonSelf\n  }\n}\n\nexport default dataTableDark\n"
  },
  {
    "path": "src/data-table/styles/index.ts",
    "content": "export { default as dataTableDark } from './dark'\nexport { default as dataTableLight } from './light'\nexport type { DataTableTheme, DataTableThemeVars } from './light'\nexport { DataTableRtl } from './rtl'\n"
  },
  {
    "path": "src/data-table/styles/light.ts",
    "content": "import type { ThemeCommonVars } from '../../_styles/common'\nimport { composite } from 'seemly'\nimport { scrollbarLight } from '../../_internal/scrollbar/styles'\nimport { createTheme } from '../../_mixins'\nimport { commonLight } from '../../_styles/common'\nimport { buttonLight } from '../../button/styles'\nimport { checkboxLight } from '../../checkbox/styles'\nimport { dropdownLight } from '../../dropdown/styles'\nimport { ellipsisLight } from '../../ellipsis/styles'\nimport { emptyLight } from '../../empty/styles'\nimport { paginationLight } from '../../pagination/styles'\nimport { popoverLight } from '../../popover/styles'\nimport { radioLight } from '../../radio/styles'\nimport commonVariables from './_common'\n\nexport function self(vars: ThemeCommonVars) {\n  const {\n    cardColor,\n    modalColor,\n    popoverColor,\n    textColor2,\n    textColor1,\n    tableHeaderColor,\n    tableColorHover,\n    iconColor,\n    primaryColor,\n    fontWeightStrong,\n    borderRadius,\n    lineHeight,\n    fontSizeSmall,\n    fontSizeMedium,\n    fontSizeLarge,\n    dividerColor,\n    heightSmall,\n    opacityDisabled,\n    tableColorStriped\n  } = vars\n  return {\n    ...commonVariables,\n    actionDividerColor: dividerColor,\n    lineHeight,\n    borderRadius,\n    fontSizeSmall,\n    fontSizeMedium,\n    fontSizeLarge,\n    borderColor: composite(cardColor, dividerColor),\n    tdColorHover: composite(cardColor, tableColorHover),\n    tdColorSorting: composite(cardColor, tableColorHover),\n    tdColorStriped: composite(cardColor, tableColorStriped),\n    thColor: composite(cardColor, tableHeaderColor),\n    thColorHover: composite(\n      composite(cardColor, tableHeaderColor),\n      tableColorHover\n    ),\n    thColorSorting: composite(\n      composite(cardColor, tableHeaderColor),\n      tableColorHover\n    ),\n    tdColor: cardColor,\n    tdTextColor: textColor2,\n    thTextColor: textColor1,\n    thFontWeight: fontWeightStrong,\n    thButtonColorHover: tableColorHover,\n    thIconColor: iconColor,\n    thIconColorActive: primaryColor,\n    // modal\n    borderColorModal: composite(modalColor, dividerColor),\n    tdColorHoverModal: composite(modalColor, tableColorHover),\n    tdColorSortingModal: composite(modalColor, tableColorHover),\n    tdColorStripedModal: composite(modalColor, tableColorStriped),\n    thColorModal: composite(modalColor, tableHeaderColor),\n    thColorHoverModal: composite(\n      composite(modalColor, tableHeaderColor),\n      tableColorHover\n    ),\n    thColorSortingModal: composite(\n      composite(modalColor, tableHeaderColor),\n      tableColorHover\n    ),\n    tdColorModal: modalColor,\n    // popover\n    borderColorPopover: composite(popoverColor, dividerColor),\n    tdColorHoverPopover: composite(popoverColor, tableColorHover),\n    tdColorSortingPopover: composite(popoverColor, tableColorHover),\n    tdColorStripedPopover: composite(popoverColor, tableColorStriped),\n    thColorPopover: composite(popoverColor, tableHeaderColor),\n    thColorHoverPopover: composite(\n      composite(popoverColor, tableHeaderColor),\n      tableColorHover\n    ),\n    thColorSortingPopover: composite(\n      composite(popoverColor, tableHeaderColor),\n      tableColorHover\n    ),\n    tdColorPopover: popoverColor,\n    boxShadowBefore: 'inset -12px 0 8px -12px rgba(0, 0, 0, .18)',\n    boxShadowAfter: 'inset 12px 0 8px -12px rgba(0, 0, 0, .18)',\n    // loading\n    loadingColor: primaryColor,\n    loadingSize: heightSmall,\n    opacityLoading: opacityDisabled\n  }\n}\n\nexport type DataTableThemeVars = ReturnType<typeof self>\n\nconst dataTableLight = createTheme({\n  name: 'DataTable',\n  common: commonLight,\n  peers: {\n    Button: buttonLight,\n    Checkbox: checkboxLight,\n    Radio: radioLight,\n    Pagination: paginationLight,\n    Scrollbar: scrollbarLight,\n    Empty: emptyLight,\n    Popover: popoverLight,\n    Ellipsis: ellipsisLight,\n    Dropdown: dropdownLight\n  },\n  self\n})\n\nexport default dataTableLight\nexport type DataTableTheme = typeof dataTableLight\n"
  },
  {
    "path": "src/data-table/styles/rtl.ts",
    "content": "import type { RtlItem } from '../../config-provider/src/internal-interface'\nimport { scrollbarRtl } from '../../_internal/scrollbar/styles'\nimport { paginationRtl } from '../../pagination/styles'\nimport rtlStyle from '../src/styles/rtl.cssr'\n\nexport const DataTableRtl: RtlItem = {\n  name: 'DataTable',\n  style: rtlStyle,\n  peers: [scrollbarRtl, paginationRtl]\n}\n"
  },
  {
    "path": "src/data-table/tests/DataTable.spec.tsx",
    "content": "import type { HTMLAttributes } from 'vue'\n/* eslint-disable unused-imports/no-unused-vars */\nimport type { DataTableColumns, DataTableInst } from '../index'\nimport { mount } from '@vue/test-utils'\nimport { h, nextTick, ref } from 'vue'\nimport { NButton } from '../../button'\nimport { NButtonGroup } from '../../button-group'\nimport { NDataTable } from '../index'\n\ndescribe('n-data-table', () => {\n  it('should work with import on demand', () => {\n    mount(NDataTable)\n  })\n  it('show custom empty', () => {\n    const columns = [\n      {\n        title: 'Name',\n        key: 'name'\n      }\n    ]\n    const wrapper = mount(() => (\n      <NDataTable columns={columns} data={[]}>\n        {{\n          empty: () => <div class=\"empty-info\">empty</div>\n        }}\n      </NDataTable>\n    ))\n    expect(wrapper.find('.empty-info').exists()).toEqual(true)\n    wrapper.unmount()\n  })\n  it('should work with `itemCount` without `remote`', () => {\n    const columns = [\n      {\n        title: 'Name',\n        key: 'name'\n      }\n    ]\n    const data = Array.from({ length: 978 })\n      .fill(0)\n      .map((_, index) => {\n        return {\n          name: index\n        }\n      })\n    const pagination = {\n      page: 1,\n      pageCount: 1,\n      pageSize: 10,\n      itemCount: 0,\n      prefix({ itemCount }: { itemCount: number | undefined }) {\n        return itemCount\n      }\n    }\n    const wrapper = mount(() => (\n      <NDataTable columns={columns} data={data} pagination={pagination} />\n    ))\n    expect(wrapper.find('.n-pagination-prefix').text()).toEqual('978')\n    wrapper.unmount()\n  })\n\n  it('should work with `itemCount` with `remote`', async () => {\n    const pagination = {\n      page: 1,\n      pageSize: 10,\n      itemCount: 978,\n      prefix({ itemCount }: { itemCount: number | undefined }) {\n        return itemCount\n      }\n    }\n    let data = Array.from({ length: 978 })\n      .fill(0)\n      .map((_, index) => {\n        return {\n          name: index\n        }\n      })\n    const onPageChange = vi.fn(async (page: number): Promise<void> => {\n      await vi.waitFor(() => {\n        pagination.page = page\n        pagination.itemCount = data.length\n        data = data.slice(\n          (page - 1) * pagination.pageSize,\n          page * pagination.pageSize\n        )\n      })\n    })\n    const columns = [\n      {\n        title: 'Name',\n        key: 'name'\n      }\n    ]\n    const wrapper = mount(() => (\n      <NDataTable\n        columns={columns}\n        data={data}\n        pagination={pagination}\n        remote\n        onUpdatePage={onPageChange}\n      />\n    ))\n    void wrapper.findAll('.n-pagination-item')[2].trigger('click')\n    await nextTick()\n    expect(onPageChange).toHaveBeenCalled()\n    expect(wrapper.find('.n-pagination-prefix').text()).toEqual('978')\n    wrapper.unmount()\n  })\n\n  it('should work with `bordered` prop', async () => {\n    const columns = [\n      {\n        title: 'Name',\n        key: 'name'\n      }\n    ]\n    const data = Array.from({ length: 978 })\n      .fill(0)\n      .map((_, index) => {\n        return {\n          name: index\n        }\n      })\n    let wrapper = mount(() => <NDataTable columns={columns} data={data} />)\n    expect(wrapper.find('.n-data-table').classes()).toContain(\n      'n-data-table--bordered'\n    )\n\n    wrapper = mount(() => (\n      <NDataTable columns={columns} data={data} bordered={false} />\n    ))\n    expect(wrapper.find('.n-data-table').classes()).not.toContain(\n      'n-data-table--bordered'\n    )\n    wrapper.unmount()\n  })\n\n  it('should work with `bottom-bordered` prop', async () => {\n    const columns = [\n      {\n        title: 'Name',\n        key: 'name'\n      }\n    ]\n    const data = Array.from({ length: 978 })\n      .fill(0)\n      .map((_, index) => {\n        return {\n          name: index\n        }\n      })\n    let wrapper = mount(() => (\n      <NDataTable columns={columns} data={data} bordered={false} />\n    ))\n    expect(wrapper.find('.n-data-table').classes()).toContain(\n      'n-data-table--bottom-bordered'\n    )\n\n    wrapper = mount(() => (\n      <NDataTable\n        columns={columns}\n        data={data}\n        bordered={false}\n        bottom-bordered={false}\n      />\n    ))\n    expect(wrapper.find('.n-data-table').classes()).not.toContain(\n      'n-data-table--bottom-bordered'\n    )\n    wrapper.unmount()\n  })\n\n  it('should work with `loading` prop', async () => {\n    const columns = [\n      {\n        title: 'Name',\n        key: 'name'\n      }\n    ]\n    const data = Array.from({ length: 978 })\n      .fill(0)\n      .map((_, index) => {\n        return {\n          name: index\n        }\n      })\n    let wrapper = mount(() => <NDataTable columns={columns} data={data} />)\n    expect(wrapper.find('.n-base-loading').exists()).not.toBe(true)\n\n    wrapper = mount(() => (\n      <NDataTable columns={columns} data={data} loading={true} />\n    ))\n    expect(wrapper.find('.n-base-loading').exists()).toBe(true)\n    wrapper.unmount()\n  })\n\n  it('should work with `flex-height` prop', async () => {\n    const columns = [\n      {\n        title: 'Name',\n        key: 'name'\n      }\n    ]\n    const data = Array.from({ length: 978 })\n      .fill(0)\n      .map((_, index) => {\n        return {\n          name: index\n        }\n      })\n    let wrapper = mount(() => <NDataTable columns={columns} data={data} />)\n    expect(wrapper.find('.n-data-table').classes()).not.toContain(\n      'n-data-table--flex-height'\n    )\n\n    wrapper = mount(() => (\n      <NDataTable columns={columns} data={data} flexHeight={true} />\n    ))\n    expect(wrapper.find('.n-data-table').classes()).toContain(\n      'n-data-table--flex-height'\n    )\n    wrapper.unmount()\n  })\n\n  it('should work with `row-class-name` prop', async () => {\n    const columns = [\n      {\n        title: 'Name',\n        key: 'name'\n      }\n    ]\n    const data = Array.from({ length: 978 })\n      .fill(0)\n      .map((_, index) => {\n        return {\n          name: index\n        }\n      })\n    const getRowClassName = (rowData: any, index: number): string => {\n      return `${index}-test`\n    }\n    let wrapper = mount(() => <NDataTable columns={columns} data={data} />)\n    expect(wrapper.find('tbody .n-data-table-tr').classes()).not.toContain(\n      'test'\n    )\n\n    wrapper = mount(() => (\n      <NDataTable columns={columns} data={data} rowClassName=\"test\" />\n    ))\n    expect(wrapper.find('tbody .n-data-table-tr').classes()).toContain('test')\n\n    wrapper = mount(() => (\n      <NDataTable\n        columns={columns}\n        data={data}\n        rowClassName={getRowClassName}\n      />\n    ))\n    expect(wrapper.find('tbody .n-data-table-tr').classes()).toContain('0-test')\n    wrapper.unmount()\n  })\n\n  describe('should work with multiple sorter', () => {\n    interface UserData {\n      name: string\n      age: number\n      address: string\n      chinese: number\n      math: number\n      english: number\n    }\n    const columns: DataTableColumns<UserData> = [\n      {\n        title: 'Name',\n        key: 'name'\n      },\n      {\n        title: () => h('span', { id: 'age-title' }, 'Age'),\n        className: 'age-col',\n        key: 'age',\n        sorter: (a, b) => a.age - b.age\n      },\n      {\n        title: () => <span id=\"chinese-title\">Chinese Score</span>,\n        key: 'chinese',\n        defaultSortOrder: false,\n        className: 'chinese-col',\n        sorter: {\n          compare: (a, b) => a.chinese - b.chinese,\n          multiple: 3\n        }\n      },\n      {\n        title: () => <span id=\"math-title\">Math Score</span>,\n        defaultSortOrder: false,\n        className: 'math-col',\n        key: 'math',\n        sorter: {\n          compare: (a, b) => a.math - b.math,\n          multiple: 2\n        }\n      },\n      {\n        title: () => <span id=\"english-title\">English Score</span>,\n        className: 'english-col',\n        defaultSortOrder: false,\n        key: 'english',\n        sorter: {\n          compare: (a, b) => a.english - b.english,\n          multiple: 1\n        }\n      },\n      {\n        title: 'Address',\n        key: 'address',\n        filterOptions: [\n          {\n            label: 'London',\n            value: 'London'\n          },\n          {\n            label: 'New York',\n            value: 'New York'\n          },\n          {\n            label: 'Sidney',\n            value: 'Sidney'\n          }\n        ],\n        filter(value: any, row) {\n          return row.address.includes(value as string)\n        }\n      }\n    ]\n\n    const data = [\n      {\n        name: 'John Brown',\n        age: 32,\n        address: 'New York No. 1 Lake Park',\n        chinese: 98,\n        math: 60,\n        english: 70\n      },\n      {\n        name: 'Jim Green',\n        age: 42,\n        address: 'London No. 1 Lake Park',\n        chinese: 98,\n        math: 66,\n        english: 89\n      },\n      {\n        name: 'Joe Black',\n        age: 32,\n        address: 'Sidney No. 1 Lake Park',\n        chinese: 98,\n        math: 66,\n        english: 89\n      },\n      {\n        name: 'Jim Red',\n        age: 32,\n        address: 'London No. 2 Lake Park',\n        chinese: 88,\n        math: 99,\n        english: 89\n      }\n    ]\n    const tableRef = ref<DataTableInst | null>(null)\n    const wrapper = mount(\n      () => <NDataTable ref={tableRef} columns={columns} data={data} />,\n      {\n        attachTo: document.body\n      }\n    )\n    const checkIsMatched = async (\n      colClassName: string,\n      target: number[]\n    ): Promise<boolean> => {\n      const cols = wrapper.findAll(colClassName)\n      const colNums = cols.slice(1).map(item => Number(item.text()))\n      const matchResult = String(colNums) === String(target)\n      if (!matchResult) {\n        // console.log(colClassName, String(colNums), String(target))\n      }\n      return String(colNums) === String(target)\n    }\n    const checkScoreIsMatched = async (\n      targets: [number[], number[], number[]]\n    ): Promise<boolean> => {\n      const matchResult\n        = (await checkIsMatched('.chinese-col', targets[0]))\n          && (await checkIsMatched('.math-col', targets[1]))\n          && (await checkIsMatched('.english-col', targets[2]))\n\n      return matchResult\n    }\n    const chineseDom: HTMLElement | null\n      = document.querySelector('#chinese-title')\n    const mathDom: HTMLElement | null = document.querySelector('#math-title')\n    const englishDom: HTMLElement | null\n      = document.querySelector('#english-title')\n    const ageDom: HTMLElement | null = document.querySelector('#age-title')\n\n    it('chinese: descend, math: false, english: false', async () => {\n      chineseDom?.click()\n      expect(\n        await checkScoreIsMatched([\n          [98, 98, 98, 88],\n          [60, 66, 66, 99],\n          [70, 89, 89, 89]\n        ])\n      ).toEqual(true)\n    })\n    it('chinese: descend, math: descend, english: false', async () => {\n      mathDom?.click()\n      await nextTick()\n      expect(\n        await checkScoreIsMatched([\n          [98, 98, 98, 88],\n          [66, 66, 60, 99],\n          [89, 89, 70, 89]\n        ])\n      ).toEqual(true)\n    })\n\n    it('chinese: descend, math: descend, english: descend', async () => {\n      englishDom?.click()\n      await nextTick()\n      expect(\n        await checkScoreIsMatched([\n          [98, 98, 98, 88],\n          [66, 66, 60, 99],\n          [89, 89, 70, 89]\n        ])\n      ).toEqual(true)\n    })\n\n    it('chinese: ascend, math: descend, english: descend', async () => {\n      chineseDom?.click()\n      await nextTick()\n      expect(\n        await checkScoreIsMatched([\n          [88, 98, 98, 98],\n          [99, 66, 66, 60],\n          [89, 89, 89, 70]\n        ])\n      ).toEqual(true)\n    })\n\n    it('chinese: false, math: descend, english: descend', async () => {\n      chineseDom?.click()\n      await nextTick()\n      expect(\n        await checkScoreIsMatched([\n          [88, 98, 98, 98],\n          [99, 66, 66, 60],\n          [89, 89, 89, 70]\n        ])\n      ).toEqual(true)\n    })\n\n    it('chinese: false, math: ascend, english: descend', async () => {\n      mathDom?.click()\n      await nextTick()\n      expect(\n        await checkScoreIsMatched([\n          [98, 98, 98, 88],\n          [60, 66, 66, 99],\n          [70, 89, 89, 89]\n        ])\n      ).toEqual(true)\n    })\n\n    it('chinese: false, math: false, english: descend', async () => {\n      mathDom?.click()\n      await nextTick()\n      expect(\n        await checkScoreIsMatched([\n          [98, 98, 88, 98],\n          [66, 66, 99, 60],\n          [89, 89, 89, 70]\n        ])\n      ).toEqual(true)\n    })\n\n    it('chinese: descend, math: false, english: descend', async () => {\n      chineseDom?.click()\n      await nextTick()\n      expect(\n        await checkScoreIsMatched([\n          [98, 98, 98, 88],\n          [66, 66, 60, 99],\n          [89, 89, 70, 89]\n        ])\n      ).toEqual(true)\n    })\n\n    it('filter: Sidney and New York', async () => {\n      if (tableRef.value) {\n        tableRef.value.filter({\n          address: ['Sidney', 'New York']\n        })\n      }\n      await nextTick()\n      const result = await checkScoreIsMatched([\n        [98, 98],\n        [66, 60],\n        [89, 70]\n      ])\n      expect(result).toEqual(true)\n      if (tableRef.value) {\n        tableRef.value.filter(null)\n      }\n    })\n\n    it('age: descend', async () => {\n      ageDom?.click()\n      await nextTick()\n      const result\n        = (await checkIsMatched('.age-col', [42, 32, 32, 32]))\n          && (await checkScoreIsMatched([\n            [98, 98, 98, 88],\n            [66, 60, 66, 99],\n            [89, 70, 89, 89]\n          ]))\n      expect(result).toEqual(true)\n    })\n  })\n\n  it('should work with `indent` prop', async () => {\n    const columns = [\n      {\n        title: 'name',\n        key: 'name'\n      },\n      {\n        title: 'index',\n        key: 'index'\n      }\n    ]\n    const data = [\n      {\n        name: '07akioni',\n        index: '07',\n        children: [\n          {\n            name: '08akioni',\n            index: '08',\n            children: [\n              {\n                name: '09akioni',\n                index: '09'\n              },\n              {\n                name: '10akioni',\n                index: '10'\n              }\n            ]\n          }\n        ]\n      }\n    ]\n    const rowKey = (row: any): number => row.index\n    let wrapper = mount(() => (\n      <NDataTable\n        columns={columns}\n        data={data}\n        row-key={rowKey}\n        default-expanded-row-keys={['07']}\n      />\n    ))\n    expect(wrapper.find('.n-data-table-indent').attributes('style')).toContain(\n      'width: 16px'\n    )\n\n    wrapper = mount(() => (\n      <NDataTable\n        columns={columns}\n        data={data}\n        row-key={rowKey}\n        default-expanded-row-keys={['07']}\n        indent={20}\n      />\n    ))\n    expect(wrapper.find('.n-data-table-indent').attributes('style')).toContain(\n      'width: 20px'\n    )\n    wrapper.unmount()\n  })\n\n  it('should work with `row-props` prop', async () => {\n    const columns = [\n      {\n        title: 'Name',\n        key: 'name'\n      }\n    ]\n    const data = Array.from({ length: 978 })\n      .fill(0)\n      .map((_, index) => {\n        return {\n          name: index\n        }\n      })\n    const rowProps = (): any => ({\n      style: 'cursor: pointer;'\n    })\n    let wrapper = mount(() => <NDataTable columns={columns} data={data} />)\n    expect(wrapper.find('tbody .n-data-table-tr').attributes('style')).toBe(\n      undefined\n    )\n\n    wrapper = mount(() => (\n      <NDataTable columns={columns} data={data} row-props={rowProps} />\n    ))\n    expect(\n      wrapper.find('tbody .n-data-table-tr').attributes('style')\n    ).toContain('cursor: pointer')\n    wrapper.unmount()\n  })\n\n  it('should work with `scroll-x` prop', async () => {\n    const columns = [\n      {\n        title: 'Name',\n        key: 'name'\n      }\n    ]\n    const data = Array.from({ length: 978 })\n      .fill(0)\n      .map((_, index) => {\n        return {\n          name: index\n        }\n      })\n    let wrapper = mount(() => <NDataTable columns={columns} data={data} />)\n    expect(\n      wrapper.find('.n-scrollbar-content').attributes('style')\n    ).not.toContain('min-width: 1800px')\n\n    wrapper = mount(() => (\n      <NDataTable columns={columns} data={data} scroll-x={1800} />\n    ))\n    expect(wrapper.find('.n-scrollbar-content').attributes('style')).toContain(\n      'min-width: 1800px'\n    )\n    wrapper.unmount()\n  })\n\n  it('should work with `single-column` prop', async () => {\n    const columns = [\n      {\n        title: 'Name',\n        key: 'name'\n      }\n    ]\n    const data = Array.from({ length: 978 })\n      .fill(0)\n      .map((_, index) => {\n        return {\n          name: index\n        }\n      })\n    let wrapper = mount(() => <NDataTable columns={columns} data={data} />)\n    expect(wrapper.find('.n-data-table').classes()).not.toContain(\n      'n-data-table--single-column'\n    )\n    wrapper = mount(() => (\n      <NDataTable columns={columns} data={data} single-column={true} />\n    ))\n    expect(wrapper.find('.n-data-table').classes()).toContain(\n      'n-data-table--single-column'\n    )\n    wrapper.unmount()\n  })\n\n  it('should work with `single-line` prop', async () => {\n    const columns = [\n      {\n        title: 'Name',\n        key: 'name'\n      }\n    ]\n    const data = Array.from({ length: 978 })\n      .fill(0)\n      .map((_, index) => {\n        return {\n          name: index\n        }\n      })\n    let wrapper = mount(() => <NDataTable columns={columns} data={data} />)\n    expect(wrapper.find('.n-data-table').classes()).toContain(\n      'n-data-table--single-line'\n    )\n    wrapper = mount(() => (\n      <NDataTable columns={columns} data={data} single-line={false} />\n    ))\n    expect(wrapper.find('.n-data-table').classes()).not.toContain(\n      'n-data-table--single-line'\n    )\n    wrapper.unmount()\n  })\n\n  it('should work with `size` prop', async () => {\n    const columns = [\n      {\n        title: 'Name',\n        key: 'name'\n      }\n    ]\n    const data = Array.from({ length: 978 })\n      .fill(0)\n      .map((_, index) => {\n        return {\n          name: index\n        }\n      })\n    ;(['small', 'medium', 'large'] as const).forEach((size) => {\n      const wrapper = mount(() => (\n        <NDataTable columns={columns} data={data} size={size} />\n      ))\n      expect(\n        wrapper.find('.n-data-table').attributes('style')\n      ).toMatchSnapshot()\n      wrapper.unmount()\n    })\n  })\n\n  it('should work with `summary` prop', async () => {\n    interface Data {\n      name: number\n      age: number\n    }\n    const columns = [\n      {\n        title: 'Name',\n        key: 'name'\n      },\n      {\n        title: 'Age',\n        key: 'age'\n      }\n    ]\n    const data = Array.from({ length: 10 })\n      .fill(0)\n      .map((_, index) => {\n        return {\n          name: index,\n          age: index\n        }\n      })\n    const summary = (pageData: Data[]) => {\n      return {\n        name: {\n          value: pageData.reduce((prevValue, row) => prevValue + row.age, 0),\n          colSpan: 1,\n          rowSpan: 2\n        },\n        age: {\n          value: pageData.reduce((prevValue, row) => prevValue + row.age, 0),\n          colSpan: 2,\n          rowSpan: 1\n        }\n      }\n    }\n    const wrapper = mount(() => (\n      <NDataTable columns={columns} data={data} summary={summary} />\n    ))\n    expect(\n      wrapper.findAll('.n-data-table-td--summary')[0].attributes('data-col-key')\n    ).toBe('name')\n    expect(\n      wrapper.findAll('.n-data-table-td--summary')[0].attributes('colspan')\n    ).toBe('1')\n    expect(\n      wrapper.findAll('.n-data-table-td--summary')[0].attributes('rowspan')\n    ).toBe('2')\n    expect(wrapper.findAll('.n-data-table-td--summary')[0].text()).toBe('45')\n\n    expect(\n      wrapper.findAll('.n-data-table-td--summary')[1].attributes('data-col-key')\n    ).toBe('age')\n    expect(\n      wrapper.findAll('.n-data-table-td--summary')[1].attributes('colspan')\n    ).toBe('2')\n    expect(\n      wrapper.findAll('.n-data-table-td--summary')[1].attributes('rowspan')\n    ).toBe('1')\n    expect(wrapper.findAll('.n-data-table-td--summary')[1].text()).toBe('45')\n    wrapper.unmount()\n  })\n\n  it('should work with `table-layout` prop', async () => {\n    const columns = [\n      {\n        title: 'Name',\n        key: 'name'\n      }\n    ]\n    const data = Array.from({ length: 978 })\n      .fill(0)\n      .map((_, index) => {\n        return {\n          name: index\n        }\n      })\n    let wrapper = mount(() => <NDataTable columns={columns} data={data} />)\n    expect(wrapper.find('table').attributes('style')).toContain(\n      'table-layout: auto'\n    )\n    wrapper = mount(() => (\n      <NDataTable columns={columns} data={data} table-layout=\"fixed\" />\n    ))\n    expect(wrapper.find('table').attributes('style')).toContain(\n      'table-layout: fixed'\n    )\n    wrapper.unmount()\n  })\n\n  it('should work with `virtual-scroll` prop', async () => {\n    const columns = [\n      {\n        title: 'Name',\n        key: 'name'\n      }\n    ]\n    const data = Array.from({ length: 978 })\n      .fill(0)\n      .map((_, index) => {\n        return {\n          name: index\n        }\n      })\n    let wrapper = mount(() => <NDataTable columns={columns} data={data} />)\n    expect(wrapper.find('tbody').element.children.length).not.toBe(0)\n    wrapper = mount(() => (\n      <NDataTable columns={columns} data={data} virtual-scroll={true} />\n    ))\n    expect(wrapper.find('tbody').element.children.length).toBe(0)\n    wrapper.unmount()\n  })\n\n  it('should work with `on-update:checked-row-keys` prop', async () => {\n    const handleCheck = vi.fn()\n    const columns: DataTableColumns = [\n      {\n        type: 'selection'\n      },\n      {\n        title: 'Name',\n        key: 'name'\n      }\n    ]\n    const data = Array.from({ length: 2 })\n      .fill(0)\n      .map((_, index) => {\n        return {\n          name: index\n        }\n      })\n    const rowKey = (row: any): number => row.name\n    const wrapper = mount(() => (\n      <NDataTable\n        columns={columns}\n        data={data}\n        row-key={rowKey}\n        onUpdateCheckedRowKeys={handleCheck}\n      />\n    ))\n    await wrapper.find('.n-checkbox').trigger('click')\n    expect(handleCheck).toHaveBeenCalled()\n    wrapper.unmount()\n  })\n})\n\ndescribe('props.columns', () => {\n  it('has correct type', () => {\n    interface Data {\n      collegeID: number\n      collegeName: string\n    }\n    const data: Data[] = [\n      {\n        collegeID: 1,\n        collegeName: 'Peking University'\n      }\n    ]\n    const createRowKey = (row: Data): number => row.collegeID\n    const createRowClassName = (row: Data): string => 'star kirby'\n    const createRowProps = (row: Data): HTMLAttributes => ({\n      style: { color: 'red' }\n    })\n    const createSummary = (pageData: Data[]) => {\n      return {\n        collegeID: {\n          value: pageData.reduce(\n            (prevValue, row) => prevValue + row.collegeID,\n            0\n          ),\n          colSpan: 3\n        }\n      }\n    }\n    const columns: DataTableColumns<Data> = [\n      {\n        title: 'collegeID',\n        key: 'collegeID',\n        align: 'center',\n        sorter: (row1, row2) => row1.collegeID - row2.collegeID\n      },\n      {\n        title: 'collegeName',\n        key: 'collegeName',\n        align: 'center',\n        defaultSortOrder: 'ascend'\n      },\n      {\n        title: '操作',\n        key: 'actions',\n        render(row) {\n          return (\n            <NButtonGroup>\n              {{\n                default: () => {\n                  return (\n                    [\n                      {\n                        text: '修改',\n                        type: 'warning'\n                      },\n                      {\n                        text: '删除',\n                        type: 'error'\n                      }\n                    ] as const\n                  ).map(({ type, text }) => (\n                    <NButton type={type} round dashed>\n                      {{ default: () => text }}\n                    </NButton>\n                  ))\n                }\n              }}\n            </NButtonGroup>\n          )\n        }\n      }\n    ]\n    mount(() => (\n      <NDataTable\n        columns={columns}\n        data={data}\n        rowKey={createRowKey}\n        rowClassName={createRowClassName}\n        rowProps={createRowProps}\n        summary={createSummary}\n      />\n    )).unmount()\n  })\n\n  it('should work with `align` prop', async () => {\n    const data = Array.from({ length: 5 })\n      .fill(0)\n      .map((_, index) => {\n        return {\n          name: index,\n          age: index + 1\n        }\n      })\n    const rowKey = (row: any): number => row.name\n    ;(['left', 'right', 'center'] as const).forEach((align) => {\n      const columns: DataTableColumns = [\n        {\n          title: 'Name',\n          key: 'name',\n          align\n        },\n        {\n          title: 'Age',\n          key: 'age'\n        }\n      ]\n      const wrapper = mount(() => (\n        <NDataTable columns={columns} data={data} row-key={rowKey} />\n      ))\n      expect(wrapper.find('tbody .n-data-table-td').classes()).toContain(\n        `n-data-table-td--${align}-align`\n      )\n      expect(\n        wrapper.find('tbody .n-data-table-td').attributes('style')\n      ).toContain(`text-align: ${align}`)\n      wrapper.unmount()\n    })\n  })\n\n  it('should work with `rowSpan` `colSpan` prop', async () => {\n    const columns: DataTableColumns = [\n      {\n        title: 'Name',\n        key: 'name',\n        rowSpan: (rowData, rowIndex) => (rowIndex === 0 ? 2 : 1),\n        colSpan: (rowData, rowIndex) => (rowIndex === 0 ? 3 : 1)\n      },\n      {\n        title: 'Age',\n        key: 'age'\n      }\n    ]\n    const data = Array.from({ length: 5 })\n      .fill(0)\n      .map((_, index) => {\n        return {\n          name: index,\n          age: index + 1\n        }\n      })\n    const rowKey = (row: any): number => row.name\n    const wrapper = mount(() => (\n      <NDataTable columns={columns} data={data} row-key={rowKey} />\n    ))\n    expect(wrapper.find('tbody .n-data-table-td').attributes('colspan')).toBe(\n      '3'\n    )\n    expect(wrapper.find('tbody .n-data-table-td').attributes('rowspan')).toBe(\n      '2'\n    )\n    wrapper.unmount()\n  })\n\n  it('should work with `ellipsis` prop', async () => {\n    const columns: DataTableColumns = [\n      {\n        title: 'Name',\n        key: 'name',\n        width: 100,\n        ellipsis: true\n      },\n      {\n        title: 'Age',\n        key: 'age',\n        width: 100,\n        ellipsis: {\n          tooltip: true\n        }\n      }\n    ]\n    const data = Array.from({ length: 5 })\n      .fill(0)\n      .map((_, index) => {\n        return {\n          name: `testtesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttest${index}`,\n          age: `testtesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttest${index}`\n        }\n      })\n    const rowKey = (row: any): number => row.name\n    const wrapper = mount(() => (\n      <NDataTable columns={columns} data={data} row-key={rowKey} />\n    ))\n    expect(wrapper.find('tbody .n-data-table-td__ellipsis').exists()).toBe(true)\n    expect(wrapper.find('tbody .n-ellipsis').exists()).toBe(true)\n    expect(wrapper.find('tbody .n-ellipsis').attributes('style')).toContain(\n      'text-overflow: ellipsis'\n    )\n    wrapper.unmount()\n  })\n\n  it('should work with `children` prop', async () => {\n    const columns: DataTableColumns = [\n      {\n        title: 'Name',\n        key: 'name',\n        width: 100\n      },\n      {\n        title: 'Age',\n        key: 'age',\n        width: 100,\n        children: [\n          {\n            title: 'test1',\n            key: 'test1'\n          },\n          {\n            title: 'test2',\n            key: 'test2'\n          }\n        ]\n      }\n    ]\n    const data = Array.from({ length: 5 })\n      .fill(0)\n      .map((_, index) => {\n        return {\n          name: index,\n          age: index,\n          test1: index,\n          test2: index\n        }\n      })\n    const rowKey = (row: any): number => row.name\n    const wrapper = mount(() => (\n      <NDataTable columns={columns} data={data} row-key={rowKey} />\n    ))\n    expect(\n      wrapper.find('thead [data-col-key=\"name\"]').attributes('colspan')\n    ).toBe('1')\n    expect(\n      wrapper.find('thead [data-col-key=\"name\"]').attributes('rowspan')\n    ).toBe('2')\n    expect(\n      wrapper.find('thead [data-col-key=\"age\"]').attributes('colspan')\n    ).toBe('2')\n    expect(\n      wrapper.find('thead [data-col-key=\"age\"]').attributes('rowspan')\n    ).toBe('1')\n    expect(\n      wrapper.find('thead [data-col-key=\"test1\"]').attributes('colspan')\n    ).toBe('1')\n    expect(\n      wrapper.find('thead [data-col-key=\"test1\"]').attributes('rowspan')\n    ).toBe('1')\n    expect(\n      wrapper.find('thead [data-col-key=\"test2\"]').attributes('colspan')\n    ).toBe('1')\n    expect(\n      wrapper.find('thead [data-col-key=\"test2\"]').attributes('rowspan')\n    ).toBe('1')\n    wrapper.unmount()\n  })\n\n  it('should work with `className` prop', async () => {\n    const columns: DataTableColumns = [\n      {\n        title: 'Name',\n        key: 'name',\n        className: 'test-name'\n      },\n      {\n        title: 'Age',\n        key: 'age',\n        className: 'test-age'\n      }\n    ]\n    const data = Array.from({ length: 5 })\n      .fill(0)\n      .map((_, index) => {\n        return {\n          name: index,\n          age: index\n        }\n      })\n    const rowKey = (row: any): number => row.name\n    const wrapper = mount(() => (\n      <NDataTable columns={columns} data={data} row-key={rowKey} />\n    ))\n    expect(wrapper.find('thead [data-col-key=\"name\"]').classes()).toContain(\n      'test-name'\n    )\n    expect(wrapper.find('thead [data-col-key=\"age\"]').classes()).toContain(\n      'test-age'\n    )\n    wrapper.unmount()\n  })\n\n  it('should work with `render` prop', async () => {\n    const columns: DataTableColumns = [\n      {\n        title: 'Name',\n        key: 'name',\n        render(rowData: any, rowIndex: number) {\n          return `${String(rowData.name)}-${rowIndex}`\n        }\n      }\n    ]\n    const data = Array.from({ length: 5 })\n      .fill(0)\n      .map((_, index) => {\n        return {\n          name: index\n        }\n      })\n    const rowKey = (row: any): number => row.name\n    const wrapper = mount(() => (\n      <NDataTable columns={columns} data={data} row-key={rowKey} />\n    ))\n    expect(wrapper.find('tbody [data-col-key=\"name\"]').text()).toContain('0-0')\n    wrapper.unmount()\n  })\n\n  it('should work with `renderExpand` `expandable` prop', async () => {\n    const columns: DataTableColumns = [\n      {\n        type: 'expand',\n        expandable: rowData => rowData.name === 0,\n        renderExpand: (rowData: any) => {\n          return `${String(rowData.name)} is a good guy.`\n        }\n      },\n      {\n        title: 'Name',\n        key: 'name',\n        render(rowData: any, rowIndex: number) {\n          return `${String(rowData.name)}-${rowIndex}`\n        }\n      }\n    ]\n    const data = Array.from({ length: 5 })\n      .fill(0)\n      .map((_, index) => {\n        return {\n          name: index\n        }\n      })\n    const rowKey = (row: any): number => row.name\n    const wrapper = mount(() => (\n      <NDataTable columns={columns} data={data} row-key={rowKey} />\n    ))\n    expect(wrapper.findAll('tbody .n-data-table-td--expand').length).toBe(5)\n    expect(wrapper.findAll('tbody td')[0].attributes('data-col-key')).toContain(\n      '__n_expand__'\n    )\n    expect(wrapper.findAll('tbody td')[0].attributes('class')).toContain(\n      'n-data-table-td--expand'\n    )\n    void wrapper\n      .findAll('tbody .n-data-table-expand-trigger')[0]\n      .trigger('click')\n    await nextTick()\n    expect(wrapper.findAll('tbody tr').length).toBe(6)\n    expect(wrapper.find('tbody [colspan=\"2\"]').text()).toContain(\n      '0 is a good guy.'\n    )\n    wrapper.unmount()\n  })\n\n  it('should work with `children` prop 2', async () => {\n    const columns: DataTableColumns = [\n      {\n        title: 'Name',\n        key: 'name',\n        width: 100\n      },\n      {\n        title: 'Age',\n        key: 'age',\n        width: 200\n      }\n    ]\n    const data = Array.from({ length: 5 })\n      .fill(0)\n      .map((_, index) => {\n        return {\n          name: index,\n          age: index\n        }\n      })\n    const rowKey = (row: any): number => row.name\n    const wrapper = mount(() => (\n      <NDataTable columns={columns} data={data} row-key={rowKey} />\n    ))\n    expect(wrapper.findAll('colgroup col')[0].attributes('style')).toContain(\n      'width: 100px; min-width: 100px'\n    )\n    expect(wrapper.findAll('colgroup col')[1].attributes('style')).toContain(\n      'width: 200px; min-width: 200px'\n    )\n    wrapper.unmount()\n  })\n\n  it('should work with `striped` prop', async () => {\n    const columns: DataTableColumns = [\n      {\n        title: 'Name',\n        key: 'name',\n        width: 100\n      },\n      {\n        title: 'Age',\n        key: 'age',\n        width: 200\n      }\n    ]\n    const data = Array.from({ length: 5 })\n      .fill(0)\n      .map((_, index) => {\n        return {\n          name: index,\n          age: index\n        }\n      })\n    const wrapper = mount(() => (\n      <NDataTable columns={columns} data={data} striped />\n    ))\n\n    const trList = wrapper.find('tbody').findAll('.n-data-table-tr')\n    expect(trList[1].attributes('class')).toContain('n-data-table-tr--striped')\n    expect(trList[0].attributes('class')).not.toContain(\n      'n-data-table-tr--striped'\n    )\n    expect(trList[2].attributes('class')).not.toContain(\n      'n-data-table-tr--striped'\n    )\n    wrapper.unmount()\n  })\n\n  it('should work with `column.multiple` prop', async () => {\n    const columns: DataTableColumns = [\n      {\n        type: 'selection',\n        multiple: false\n      },\n      {\n        title: 'Name',\n        key: 'name'\n      }\n    ]\n    const data = Array.from({ length: 5 })\n      .fill(0)\n      .map((_, index) => {\n        return {\n          name: index,\n          key: index\n        }\n      })\n\n    const checkedRowKeys = ref([4, 1])\n\n    const handleCheck = (e: any): void => {\n      checkedRowKeys.value = e\n    }\n\n    const wrapper = mount(\n      () => (\n        <NDataTable\n          columns={columns}\n          data={data}\n          onUpdateCheckedRowKeys={handleCheck}\n          checked-row-keys={checkedRowKeys.value}\n        />\n      ),\n      {\n        attachTo: document.body\n      }\n    )\n\n    const radios = wrapper.findAll('.n-radio')\n\n    expect(radios[4].classes()).toContain('n-radio--checked')\n    expect(radios[1].classes()).not.toContain('n-radio--checked')\n\n    await radios[1].trigger('click')\n\n    expect(radios[1].classes()).toContain('n-radio--checked')\n    expect(radios[4].classes()).not.toContain('n-radio--checked')\n\n    wrapper.unmount()\n  })\n})\n"
  },
  {
    "path": "src/data-table/tests/__snapshots__/DataTable.spec.tsx.snap",
    "content": "// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html\n\nexports[`n-data-table > should work with \\`size\\` prop 1`] = `\"--n-font-size: 14px; --n-th-padding: 8px; --n-td-padding: 8px; --n-bezier: cubic-bezier(.4, 0, .2, 1); --n-border-radius: 3px; --n-line-height: 1.6; --n-border-color: rgba(239, 239, 245, 1); --n-border-color-modal: rgba(239, 239, 245, 1); --n-border-color-popover: rgba(239, 239, 245, 1); --n-th-color: rgba(250, 250, 252, 1); --n-th-color-hover: rgba(243, 243, 247, 1); --n-th-color-modal: rgba(250, 250, 252, 1); --n-th-color-hover-modal: rgba(243, 243, 247, 1); --n-th-color-popover: rgba(250, 250, 252, 1); --n-th-color-hover-popover: rgba(243, 243, 247, 1); --n-td-color: #fff; --n-td-color-hover: rgba(247, 247, 250, 1); --n-td-color-modal: #fff; --n-td-color-hover-modal: rgba(247, 247, 250, 1); --n-td-color-popover: #fff; --n-td-color-hover-popover: rgba(247, 247, 250, 1); --n-th-text-color: rgb(31, 34, 37); --n-td-text-color: rgb(51, 54, 57); --n-th-font-weight: 500; --n-th-button-color-hover: rgba(0, 0, 100, 0.03); --n-th-icon-color: rgba(194, 194, 194, 1); --n-th-icon-color-active: #18a058; --n-filter-size: 15px; --n-pagination-margin: 12px 0 0 0; --n-empty-padding: 48px 0; --n-box-shadow-before: inset -12px 0 8px -12px rgba(0, 0, 0, .18); --n-box-shadow-after: inset 12px 0 8px -12px rgba(0, 0, 0, .18); --n-sorter-size: 15px; --n-resizable-container-size: 8px; --n-resizable-size: 2px; --n-loading-size: 28px; --n-loading-color: #18a058; --n-opacity-loading: 0.5; --n-td-color-striped: rgba(250, 250, 252, 1); --n-td-color-striped-modal: rgba(250, 250, 252, 1); --n-td-color-striped-popover: rgba(250, 250, 252, 1); --n-td-color-sorting: rgba(247, 247, 250, 1); --n-td-color-sorting-modal: rgba(247, 247, 250, 1); --n-td-color-sorting-popover: rgba(247, 247, 250, 1); --n-th-color-sorting: rgba(243, 243, 247, 1); --n-th-color-sorting-modal: rgba(243, 243, 247, 1); --n-th-color-sorting-popover: rgba(243, 243, 247, 1);\"`;\n\nexports[`n-data-table > should work with \\`size\\` prop 2`] = `\"--n-font-size: 14px; --n-th-padding: 12px; --n-td-padding: 12px; --n-bezier: cubic-bezier(.4, 0, .2, 1); --n-border-radius: 3px; --n-line-height: 1.6; --n-border-color: rgba(239, 239, 245, 1); --n-border-color-modal: rgba(239, 239, 245, 1); --n-border-color-popover: rgba(239, 239, 245, 1); --n-th-color: rgba(250, 250, 252, 1); --n-th-color-hover: rgba(243, 243, 247, 1); --n-th-color-modal: rgba(250, 250, 252, 1); --n-th-color-hover-modal: rgba(243, 243, 247, 1); --n-th-color-popover: rgba(250, 250, 252, 1); --n-th-color-hover-popover: rgba(243, 243, 247, 1); --n-td-color: #fff; --n-td-color-hover: rgba(247, 247, 250, 1); --n-td-color-modal: #fff; --n-td-color-hover-modal: rgba(247, 247, 250, 1); --n-td-color-popover: #fff; --n-td-color-hover-popover: rgba(247, 247, 250, 1); --n-th-text-color: rgb(31, 34, 37); --n-td-text-color: rgb(51, 54, 57); --n-th-font-weight: 500; --n-th-button-color-hover: rgba(0, 0, 100, 0.03); --n-th-icon-color: rgba(194, 194, 194, 1); --n-th-icon-color-active: #18a058; --n-filter-size: 15px; --n-pagination-margin: 12px 0 0 0; --n-empty-padding: 48px 0; --n-box-shadow-before: inset -12px 0 8px -12px rgba(0, 0, 0, .18); --n-box-shadow-after: inset 12px 0 8px -12px rgba(0, 0, 0, .18); --n-sorter-size: 15px; --n-resizable-container-size: 8px; --n-resizable-size: 2px; --n-loading-size: 28px; --n-loading-color: #18a058; --n-opacity-loading: 0.5; --n-td-color-striped: rgba(250, 250, 252, 1); --n-td-color-striped-modal: rgba(250, 250, 252, 1); --n-td-color-striped-popover: rgba(250, 250, 252, 1); --n-td-color-sorting: rgba(247, 247, 250, 1); --n-td-color-sorting-modal: rgba(247, 247, 250, 1); --n-td-color-sorting-popover: rgba(247, 247, 250, 1); --n-th-color-sorting: rgba(243, 243, 247, 1); --n-th-color-sorting-modal: rgba(243, 243, 247, 1); --n-th-color-sorting-popover: rgba(243, 243, 247, 1);\"`;\n\nexports[`n-data-table > should work with \\`size\\` prop 3`] = `\"--n-font-size: 15px; --n-th-padding: 12px; --n-td-padding: 12px; --n-bezier: cubic-bezier(.4, 0, .2, 1); --n-border-radius: 3px; --n-line-height: 1.6; --n-border-color: rgba(239, 239, 245, 1); --n-border-color-modal: rgba(239, 239, 245, 1); --n-border-color-popover: rgba(239, 239, 245, 1); --n-th-color: rgba(250, 250, 252, 1); --n-th-color-hover: rgba(243, 243, 247, 1); --n-th-color-modal: rgba(250, 250, 252, 1); --n-th-color-hover-modal: rgba(243, 243, 247, 1); --n-th-color-popover: rgba(250, 250, 252, 1); --n-th-color-hover-popover: rgba(243, 243, 247, 1); --n-td-color: #fff; --n-td-color-hover: rgba(247, 247, 250, 1); --n-td-color-modal: #fff; --n-td-color-hover-modal: rgba(247, 247, 250, 1); --n-td-color-popover: #fff; --n-td-color-hover-popover: rgba(247, 247, 250, 1); --n-th-text-color: rgb(31, 34, 37); --n-td-text-color: rgb(51, 54, 57); --n-th-font-weight: 500; --n-th-button-color-hover: rgba(0, 0, 100, 0.03); --n-th-icon-color: rgba(194, 194, 194, 1); --n-th-icon-color-active: #18a058; --n-filter-size: 15px; --n-pagination-margin: 12px 0 0 0; --n-empty-padding: 48px 0; --n-box-shadow-before: inset -12px 0 8px -12px rgba(0, 0, 0, .18); --n-box-shadow-after: inset 12px 0 8px -12px rgba(0, 0, 0, .18); --n-sorter-size: 15px; --n-resizable-container-size: 8px; --n-resizable-size: 2px; --n-loading-size: 28px; --n-loading-color: #18a058; --n-opacity-loading: 0.5; --n-td-color-striped: rgba(250, 250, 252, 1); --n-td-color-striped-modal: rgba(250, 250, 252, 1); --n-td-color-striped-popover: rgba(250, 250, 252, 1); --n-td-color-sorting: rgba(247, 247, 250, 1); --n-td-color-sorting-modal: rgba(247, 247, 250, 1); --n-td-color-sorting-popover: rgba(247, 247, 250, 1); --n-th-color-sorting: rgba(243, 243, 247, 1); --n-th-color-sorting-modal: rgba(243, 243, 247, 1); --n-th-color-sorting-popover: rgba(243, 243, 247, 1);\"`;\n"
  },
  {
    "path": "src/data-table/tests/server.spec.tsx",
    "content": "import { setup } from '@css-render/vue3-ssr'\nimport { renderToString } from '@vue/server-renderer'\n/**\n * @vitest-environment node\n */\nimport { createSSRApp, h } from 'vue'\nimport { NDataTable } from '../..'\n\ndescribe('server side rendering', () => {\n  it('works', async () => {\n    const app = createSSRApp(() => <NDataTable />)\n    setup(app)\n    try {\n      await renderToString(app)\n    }\n    catch (e) {\n      expect(e).not.toBeTruthy()\n    }\n  })\n})\n"
  },
  {
    "path": "src/date-picker/demos/enUS/actions.demo.vue",
    "content": "<markdown>\n# Actions\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst ts1 = ref(null)\nconst ts2 = ref(1183135260000)\nconst range1 = ref(null)\nconst range2 = ref(null)\n</script>\n\n<template>\n  <n-space vertical>\n    <n-date-picker v-model:value=\"ts1\" type=\"date\" :actions=\"['now']\" />\n    <n-date-picker v-model:value=\"ts2\" type=\"datetime\" :actions=\"['now']\" />\n    <n-date-picker\n      v-model:value=\"range1\"\n      update-value-on-close\n      type=\"daterange\"\n      :actions=\"null\"\n    />\n    <n-date-picker\n      v-model:value=\"range2\"\n      update-value-on-close\n      type=\"datetimerange\"\n      :actions=\"['clear']\"\n    />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/date-picker/demos/enUS/close-panel-on-select.demo.vue",
    "content": "<markdown>\n  # Close panel on select year or month\n\n  By using the `fast-year-select` and `fast-month-select` properties, you can implement the closing of the year and month panel after selecting the year or month.\n</markdown>\n\n<script lang=\"ts\">\nimport { defineComponent, ref } from 'vue'\n\nexport default defineComponent({\n  setup() {\n    return {\n      timestamp: ref(1183135260000),\n      range: ref<[number, number]>([1183135260000, Date.now()])\n    }\n  }\n})\n</script>\n\n<template>\n  <NFlex vertical>\n    <n-date-picker\n      v-model:value=\"timestamp\"\n      type=\"date\"\n      fast-year-select\n      fast-month-select\n    />\n    <n-date-picker\n      v-model:value=\"timestamp\"\n      type=\"datetime\"\n      fast-year-select\n      fast-month-select\n    />\n    <n-date-picker\n      v-model:value=\"range\"\n      type=\"daterange\"\n      fast-year-select\n      fast-month-select\n    />\n    <n-date-picker\n      v-model:value=\"range\"\n      type=\"datetimerange\"\n      fast-year-select\n      fast-month-select\n    />\n    <pre>{{ JSON.stringify(timestamp) }}</pre>\n  </NFlex>\n</template>\n"
  },
  {
    "path": "src/date-picker/demos/enUS/date.demo.vue",
    "content": "<markdown>\n# Date\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst timestamp = ref(1183135260000)\n</script>\n\n<template>\n  <n-date-picker v-model:value=\"timestamp\" type=\"date\" />\n  <pre>{{ JSON.stringify(timestamp) }}</pre>\n</template>\n"
  },
  {
    "path": "src/date-picker/demos/enUS/daterange.demo.vue",
    "content": "<markdown>\n# Date range\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst range = ref<[number, number]>([1183135260000, Date.now()])\n</script>\n\n<template>\n  <n-date-picker v-model:value=\"range\" type=\"daterange\" clearable />\n  <pre>{{ JSON.stringify(range) }}</pre>\n</template>\n"
  },
  {
    "path": "src/date-picker/demos/enUS/datetime.demo.vue",
    "content": "<markdown>\n# Date time\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst timestamp = ref(1183135260000)\n</script>\n\n<template>\n  <n-date-picker v-model:value=\"timestamp\" type=\"datetime\" clearable />\n  <pre>{{ JSON.stringify(timestamp) }}</pre>\n</template>\n"
  },
  {
    "path": "src/date-picker/demos/enUS/datetimeformat.demo.vue",
    "content": "<markdown>\n# Formatted value\n\nHonestly I don't like the feature. Since at most of time it's not a best practice to passing time string around. However, real world is complex, I hope it can help you resolve some tricky problems.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst formattedValue = ref('2007-06-30 12:08:55')\n</script>\n\n<template>\n  <pre>{{ formattedValue }}</pre>\n  <n-date-picker\n    v-model:formatted-value=\"formattedValue\"\n    value-format=\"yyyy-MM-dd HH:mm:ss\"\n    type=\"datetime\"\n    clearable\n  />\n</template>\n"
  },
  {
    "path": "src/date-picker/demos/enUS/datetimerange.demo.vue",
    "content": "<markdown>\n# Date time range\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst range = ref<[number, number]>([1183135260000, Date.now()])\n</script>\n\n<template>\n  <n-date-picker v-model:value=\"range\" type=\"datetimerange\" clearable />\n  <pre>{{ JSON.stringify(range) }}</pre>\n</template>\n"
  },
  {
    "path": "src/date-picker/demos/enUS/default-time.demo.vue",
    "content": "<markdown>\n# Default time\n\nYou can set the default time of picked date.\n</markdown>\n\n<script setup lang=\"ts\">\nimport { format, isAfter, isToday } from 'date-fns'\n\nfunction getSingleDefaultTime(timestamp: number): string {\n  const now = new Date()\n\n  if (isToday(timestamp)) {\n    return format(new Date(), 'HH:mm:ss')\n  }\n  if (isAfter(now, timestamp)) {\n    return '23:59:59'\n  }\n  else {\n    return '00:00:00'\n  }\n}\n\nfunction getRangeDefaultTime(timestamp: number, position: 'start' | 'end'): string {\n  const now = new Date()\n\n  if (position === 'start') {\n    return '00:00:00'\n  }\n\n  if (isToday(timestamp)) {\n    return format(new Date(), 'HH:mm:ss')\n  }\n  if (isAfter(now, timestamp)) {\n    return '23:59:59'\n  }\n  else {\n    return '00:00:00'\n  }\n}\n</script>\n\n<template>\n  <n-space vertical>\n    <n-date-picker type=\"datetime\" clearable default-time=\"13:22:11\" />\n    <n-date-picker type=\"datetime\" clearable default-time=\"16:00:00\" />\n    <n-date-picker\n      type=\"datetime\"\n      clearable\n      :default-time=\"getSingleDefaultTime\"\n    />\n    <n-date-picker type=\"datetimerange\" clearable default-time=\"13:22:11\" />\n    <n-date-picker\n      type=\"datetimerange\"\n      clearable\n      :default-time=\"['16:00:00', undefined]\"\n    />\n    <n-date-picker\n      type=\"datetimerange\"\n      clearable\n      :default-time=\"['13:22:11', '16:00:00']\"\n    />\n    <n-date-picker\n      type=\"datetimerange\"\n      clearable\n      :default-time=\"getRangeDefaultTime\"\n    />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/date-picker/demos/enUS/disabled-time.demo.vue",
    "content": "<markdown>\n# Disabled specific time\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { startOfDay } from 'date-fns'\n\nconst d = 86400000\nconst h = 3600000\nconst m = 60000\nconst s = 1000\n\nfunction dateDisabled(ts: number) {\n  const date = new Date(ts).getDate()\n  return date < 15\n}\n\nfunction timeDisabled(ts: number) {\n  const date = new Date(ts).getDate()\n  return {\n    isHourDisabled: (hour: number) => {\n      return date >= 15 && hour < 12\n    }\n  }\n}\n\nfunction isRangeDateDisabled(\n  ts: number,\n  type: 'start' | 'end',\n  range: [number, number] | null\n) {\n  if (type === 'start' && range !== null) {\n    return startOfDay(range[1]).valueOf() - startOfDay(ts).valueOf() <= d * 6\n  }\n  if (type === 'end' && range !== null) {\n    return startOfDay(ts).valueOf() - startOfDay(range[0]).valueOf() <= d * 6\n  }\n  return false\n}\n\nfunction isRangeTimeDisabled(\n  current: number,\n  type: 'start' | 'end',\n  range: [number, number]\n) {\n  if (type === 'start') {\n    return {\n      isHourDisabled: (hour: number) => {\n        return range[1] - startOfDay(range[0]).valueOf() - hour * h < d * 7\n      },\n      isMinuteDisabled: (minute: number, hour: number | null) => {\n        if (hour === null)\n          return false\n        return (\n          range[1] - startOfDay(range[0]).valueOf() - hour * h - minute * m\n          < d * 7\n        )\n      },\n      isSecondDisabled: (\n        second: number,\n        minute: number | null,\n        hour: number | null\n      ) => {\n        if (hour === null || minute === null)\n          return false\n        return (\n          range[1]\n          - startOfDay(range[0]).valueOf()\n          - hour * h\n          - minute * m\n          - second * s\n          < d * 7\n        )\n      }\n    }\n  }\n  else {\n    return {\n      isHourDisabled: (hour: number) => {\n        return (\n          startOfDay(range[1]).valueOf() + hour * h + (h - s) - range[0] < d * 7\n        )\n      },\n      isMinuteDisabled: (minute: number, hour: number | null) => {\n        if (hour === null)\n          return false\n        return (\n          startOfDay(range[1]).valueOf()\n          + hour * h\n          + minute * m\n          + (m - s)\n          - range[0]\n          < d * 7\n        )\n      },\n      isSecondDisabled: (\n        second: number,\n        minute: number | null,\n        hour: number | null\n      ) => {\n        if (hour === null || minute === null)\n          return false\n        return (\n          startOfDay(range[1]).valueOf()\n          + hour * h\n          + minute * m\n          + second * s\n          - range[0]\n          < d * 7\n        )\n      }\n    }\n  }\n}\n\nfunction disablePreviousDate(ts: number) {\n  return ts > Date.now()\n}\n</script>\n\n<template>\n  <n-space vertical>\n    Disable first half of the month\n    <n-date-picker\n      type=\"date\"\n      :default-value=\"Date.now()\"\n      :is-date-disabled=\"dateDisabled\"\n    />\n    Disable first half of the month & AM at second half of the month\n    <n-date-picker\n      type=\"datetime\"\n      :default-value=\"Date.now()\"\n      :is-date-disabled=\"dateDisabled\"\n      :is-time-disabled=\"timeDisabled\"\n    />\n    At least 7 days\n    <n-date-picker\n      type=\"daterange\"\n      :default-value=\"[Date.now(), Date.now() + 86400000]\"\n      :is-date-disabled=\"isRangeDateDisabled\"\n    />\n    At least 7 days\n    <n-date-picker\n      type=\"datetimerange\"\n      :default-value=\"[Date.now(), Date.now() + 86400000]\"\n      :is-date-disabled=\"isRangeDateDisabled\"\n      :is-time-disabled=\"isRangeTimeDisabled\"\n    />\n    Only allow previous date\n    <n-date-picker\n      type=\"daterange\"\n      :default-value=\"[Date.now(), Date.now() + 86400000]\"\n      :is-date-disabled=\"disablePreviousDate\"\n    />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/date-picker/demos/enUS/disabled.demo.vue",
    "content": "<markdown>\n# Disabled\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst datetime = ref(null)\nconst date = ref(null)\nconst datetimerange = ref(null)\nconst daterange = ref(null)\nconst disabled = ref(true)\n</script>\n\n<template>\n  <n-space vertical>\n    <n-date-picker v-model:value=\"date\" type=\"date\" :disabled=\"disabled\" />\n    <n-date-picker\n      v-model:value=\"datetime\"\n      type=\"datetime\"\n      :disabled=\"disabled\"\n    />\n    <n-date-picker\n      v-model:value=\"daterange\"\n      :disabled=\"disabled\"\n      type=\"daterange\"\n    />\n    <n-date-picker\n      v-model:value=\"datetimerange\"\n      :disabled=\"disabled\"\n      type=\"datetimerange\"\n    />\n    <n-switch v-model:value=\"disabled\" />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/date-picker/demos/enUS/events.demo.vue",
    "content": "<markdown>\n# Events\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { useMessage } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst message = useMessage()\nconst datetime = ref(1183135260000)\nconst date = ref(null)\nconst datetimerange = ref(null)\nconst daterange = ref(null)\nconst disabled = ref(false)\n\nfunction onBlur1() {\n  message.info('Blur-1')\n}\n\nfunction onChange1(value: number) {\n  message.info(`Change-1 ${value}`)\n}\n\nfunction onBlur2() {\n  message.error('Blur-2')\n}\n\nfunction onChange2(value: number) {\n  message.error(`Change-2 ${value}`)\n}\n\nfunction onBlur3() {\n  message.warning('Blur-3')\n}\n\nfunction onChange3(value: number) {\n  message.warning(`Change-3 ${value}`)\n}\n\nfunction onBlur4() {\n  message.success('Blur-4')\n}\n\nfunction onChange4(value: number) {\n  message.success(`Change-4 ${value}`)\n}\n\nfunction onClear() {\n  message.info('Clear-5')\n}\n\nfunction onConfirm(value: number | number[] | null) {\n  message.info(`Confirm-5 ${value}`)\n}\n</script>\n\n<template>\n  <n-space vertical>\n    <n-date-picker\n      v-model:value=\"datetime\"\n      type=\"datetime\"\n      :disabled=\"disabled\"\n      @blur=\"onBlur1\"\n      @update:value=\"onChange1\"\n    />\n    <n-date-picker\n      v-model:value=\"date\"\n      type=\"date\"\n      :disabled=\"disabled\"\n      @blur=\"onBlur2\"\n      @update:value=\"onChange2\"\n    />\n    <n-date-picker\n      v-model:value=\"datetimerange\"\n      :disabled=\"disabled\"\n      type=\"datetimerange\"\n      @blur=\"onBlur3\"\n      @update:value=\"onChange3\"\n    />\n    <n-date-picker\n      v-model:value=\"daterange\"\n      :disabled=\"disabled\"\n      type=\"daterange\"\n      @blur=\"onBlur4\"\n      @update:value=\"onChange4\"\n    />\n    <n-date-picker\n      v-model:value=\"daterange\"\n      :disabled=\"disabled\"\n      type=\"daterange\"\n      @clear=\"onClear\"\n      @confirm=\"onConfirm\"\n    />\n    <n-switch v-model:value=\"disabled\" />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/date-picker/demos/enUS/focus.demo.vue",
    "content": "<markdown>\n# Focus & blur manually\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { DatePickerInst } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst datePickerInstRef = ref<DatePickerInst | null>(null)\n\nfunction handleClick() {\n  datePickerInstRef.value?.focus()\n  setTimeout(() => {\n    datePickerInstRef.value?.blur()\n  }, 1000)\n}\n</script>\n\n<template>\n  <n-space item-style=\"display: flex; align-item: center;\">\n    <n-button @click=\"handleClick\">\n      Focus then blur in 1 second\n    </n-button>\n    <n-date-picker ref=\"datePickerInstRef\" style=\"width: 200px\" />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/date-picker/demos/enUS/footerslot.demo.vue",
    "content": "<markdown>\n# Extra footer\n</markdown>\n\n<template>\n  <n-space vertical>\n    <n-date-picker type=\"date\">\n      <template #footer>\n        extra footer\n      </template>\n    </n-date-picker>\n    <n-date-picker type=\"datetime\">\n      <template #footer>\n        extra footer\n      </template>\n    </n-date-picker>\n    <n-date-picker type=\"daterange\">\n      <template #footer>\n        extra footer\n      </template>\n    </n-date-picker>\n    <n-date-picker type=\"datetimerange\">\n      <template #footer>\n        extra footer\n      </template>\n    </n-date-picker>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/date-picker/demos/enUS/format.demo.vue",
    "content": "<markdown>\n# Format\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst timestamp = ref(null)\nconst timestamp2 = ref(1183135260000)\nconst format = 'yyyy/MM/dd - HH:mm'\n</script>\n\n<template>\n  <n-space vertical>\n    <n-date-picker\n      v-model:value=\"timestamp\"\n      type=\"datetime\"\n      clearable\n      :format=\"format\"\n    />\n    <n-date-picker\n      v-model:value=\"timestamp2\"\n      type=\"datetime\"\n      :format=\"format\"\n      clearable\n    />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/date-picker/demos/enUS/icon.demo.vue",
    "content": "<markdown>\n# Icon\n</markdown>\n\n<script lang=\"ts\" setup>\nimport {\n  ChevronBackCircle,\n  ChevronBackCircleOutline,\n  ChevronForwardCircle,\n  ChevronForwardCircleOutline,\n  RocketOutline,\n  TrendingUpSharp\n} from '@vicons/ionicons5'\n</script>\n\n<template>\n  <n-space vertical>\n    <n-date-picker type=\"date\">\n      <template #date-icon>\n        <n-icon :size=\"16\" :component=\"RocketOutline\" />\n      </template>\n      <template #prev-year>\n        <n-icon :size=\"16\" :component=\"ChevronBackCircle\" />\n      </template>\n      <template #prev-month>\n        <n-icon :size=\"16\" :component=\"ChevronBackCircleOutline\" />\n      </template>\n      <template #next-month>\n        <n-icon :size=\"16\" :component=\"ChevronForwardCircleOutline\" />\n      </template>\n      <template #next-year>\n        <n-icon :size=\"16\" :component=\"ChevronForwardCircle\" />\n      </template>\n    </n-date-picker>\n    <n-date-picker type=\"daterange\">\n      <template #separator>\n        <n-icon :size=\"16\" :component=\"TrendingUpSharp\" />\n      </template>\n      <template #date-icon>\n        <n-icon :size=\"16\" :component=\"RocketOutline\" />\n      </template>\n    </n-date-picker>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/date-picker/demos/enUS/index.demo-entry.md",
    "content": "# Date Picker\n\nPeople have too many ideas on how to set the time.\n\n## Demos\n\n```demo\ndate.vue\ndatetime.vue\ndatetimeformat.vue\ndaterange.vue\ndatetimerange.vue\nmonth.vue\nmonthrange.vue\nyear.vue\nyearrange.vue\nquarter.vue\nquarterrange.vue\nweek.vue\nsize.vue\ndefault-time.vue\ndisabled.vue\ndisabled-time.vue\nactions.vue\nshortcuts.vue\nevents.vue\nformat.vue\nfooterslot.vue\nupdate-on-close.vue\nfocus.vue\nstatus.vue\nicon.vue\npanel.vue\nclose-panel-on-select.vue\n```\n\n## API\n\n### General Props\n\n| Name | Type | Default | Description | Version |\n| --- | --- | --- | --- | --- |\n| calendar-day-format | `string` | `undefined` | Weekday format inside popup panel. | 2.40.2 |\n| calendar-header-year-format | `string` | `undefined` | Year format inside the header of popup panel's calendar. | 2.40.2 |\n| calendar-header-month-format | `string` | `undefined` | Month format inside the header of popup panel's calendar. | 2.40.2 |\n| calendar-header-month-before-year | `string` | `undefined` | Whether to show month before year inside the header of popup panel's calender. | 2.40.2 |\n| calendar-header-month-year-separator | `string` | `' '` | Separator between month and year inside the header of popup panel's calendar. | 2.40.2 |\n| clearable | `boolean` | `false` | Whether the date picker is clearable. |  |\n| date-format | `string` | `undefined` | Date input format inside popup panel. | 2.40.2 |\n| default-value | `number \\| [number, number] \\| null` | `undefined` | Date picker's default value. |  |\n| default-formatted-value | `string \\| [string, string] \\| null` | `undefined` | Date picker's default formatted value. | 2.24.0 |\n| disabled | `boolean` | `false` | Whether the date picker is disabled. |  |\n| first-day-of-week | `0 \\| 1 \\| 2 \\| 3 \\| 4 \\| 5 \\| 6` | `undefined` | The first day of a week on calendar, 0 means Monday. |  |\n| input-readonly | `boolean` | `false` | Set the `readonly` attribute of the input (avoids virtual keyboard on touch devices). |  |\n| month-format | `string` | `'M'` | Format of month item in the panel. See [format](https://date-fns.org/v2.23.0/docs/format). | 2.37.0 |\n| panel | `boolean` | `false` | Whether to use date-picker as panel. | 2.29.1 |\n| placement | `'top-start' \\| 'top' \\| 'top-end' \\| 'right-start' \\| 'right' \\| 'right-end' \\| 'bottom-start' \\| 'bottom' \\| 'bottom-end' \\| 'left-start' \\| 'left' \\| 'left-end'` | `'bottom-start'` | Panel's placement. | 2.25.0 |\n| quarter-format | `string` | `'Q'Q` | Format of quarter item in the panel. See [format](https://date-fns.org/v2.23.0/docs/format). | 2.37.0 |\n| shortcuts | `Record<string, number \\| (() => number)> \\| Record<string, [number, number] \\| (() => [number, number])>` | `undefined` | Shortcut button customizations. |  |\n| show | `boolean` | `undefined` | Whether to show panel. | 2.28.3 |\n| size | `'small' \\| 'medium' \\| 'large'` | `'medium'` | Date picker size. |  |\n| status | `'success' \\| 'warning' \\| 'error'` | `undefined` | Validation status. | 2.27.0 |\n| time-picker-format | `string \\| undefined` | `undefined` | Format of the binding value in time picker inside date picker of type `'datetime'` and `'datetimerange'`. See [format](https://date-fns.org/v2.23.0/docs/format). | 2.38.2 |\n| to | `string \\| HTMLElement \\| false` | `body` | Container node of the panel. `false` will keep it not detached. |  |\n| type | `'date' \\| 'datetime' \\| 'daterange' \\| 'datetimerange' \\| 'month' \\| 'monthrange' \\| 'year' \\| 'yearrange' \\| 'quarter' \\| 'quarterrange' \\| 'week'` | `'date'` | Date picker type. | `'quarter'` v2.22.0, `'monthrange'` 2.28.3 |\n| value | `number \\| [number, number] \\| null` | `undefined` | Value of the date picker when being manually set. |  |\n| value-format | `string` | Follow `format` prop | Format of the binding value. See [format](https://date-fns.org/v2.23.0/docs/format). | 2.24.0 |\n| year-format | `string` | `'y'` | Format of year item in the panel. See [format](https://date-fns.org/v2.23.0/docs/format). | 2.37.0 |\n| year-range | `[number, number]` | `[1901, 2100]` | Year range in month picker in panel. | 2.40.0 |\n| on-clear | `() => void` | `undefined` | On clear callback. | 2.28.3 |\n| on-confirm | `(value: number \\| [number, number] \\| null, formattedValue: string \\| [string, string] \\| null) => void` | `undefined` | On confirm callback. | 2.28.3 |\n| on-blur | `() => void` | `undefined` | On blur callback. |  |\n| on-focus | `() => void` | `undefined` | On focus callback. |  |\n| on-next-month | `() => void` | `undefined` | Callback when click next month button. | 2.37.0 |\n| on-next-year | `() => void` | `undefined` | Callback when click next year button. | 2.37.0 |\n| on-prev-month | `() => void` | `undefined` | Callback when click previous month button. | 2.37.0 |\n| on-prev-year | `() => void` | `undefined` | Callback when click previous year button. | 2.37.0 |\n| on-update:show | `(show: boolean) => void` | `undefined` | Callback when panel shows & hides. | 2.28.3 |\n\n### Date Type Props\n\n| Name | Type | Default | Description | Version |\n| --- | --- | --- | --- | --- |\n| actions | `Array<'clear' \\| 'now'> \\| null` | `['clear', 'now']` | Operations supported for the `date` type date picker. |  |\n| default-calendar-start-time | `number` | `undefined` | Default panel calendar start month timestamp. | 2.38.1 |\n| fast-year-select | `boolean` | `false` | Close year and month panel after selecting year. | 2.44.0 |\n| fast-month-select | `boolean` | `false` | Close year and month panel after selecting month. | 2.44.0 |\n| format | `string` | `'yyyy-MM-dd'` | Format of the input. For detail please see [format](https://date-fns.org/v2.23.0/docs/format). |  |\n| is-date-disabled | `(current: number, detail: { type: 'date', year: number, month: number, date: number } \\| { type: 'month', year: number, month: number } \\| { type: 'year', year: number } \\| { type: 'quarter',  year: number, quarter: number } \\| { type: 'input' }) => boolean` | `() => false` | Validator of the date. | `detail` 2.37.1 |\n| placeholder | `string` | `'Select Date'` | Placeholder. |  |\n| on-update:formatted-value | `(value: string \\| null, timestampValue: number \\| null) => void` | `undefined` | Date selected callback. | 2.24.0 |\n| on-update:value | `(value: number \\| null, formattedValue: string \\| null) => void` | `undefined` | Date selected callback. | `formattedValue` 2.24.0 |\n\n### DateTime Type Props\n\n| Name | Type | Default | Description | Version |\n| --- | --- | --- | --- | --- |\n| actions | `Array<'clear' \\| 'now' \\| 'confirm'> \\| null` | `['clear', 'now', 'confirm']` | Operations supported for the `datetime` type date picker. |  |\n| default-calendar-start-time | `number` | `undefined` | Default panel calendar start month timestamp. | 2.38.1 |\n| default-time | `string \\| (timestamp: number) => string` | `undefined` | Default time of the selected date. Can accept a function with a timestamp argument that returns a formatted string. It's format is `HH:mm:ss`. | 2.22.0, functional since 2.43.2 |\n| fast-year-select | `boolean` | `false` | Close year and month panel after selecting year. | 2.44.0 |\n| fast-month-select | `boolean` | `false` | Close year and month panel after selecting month. | 2.44.0 |\n| format | `string` | `'yyyy-MM-dd HH:mm:ss'` | Format of the input. For detail please see [format](https://date-fns.org/v2.23.0/docs/format). |  |\n| is-date-disabled | `(current: number, detail: { type: 'date', year: number, month: number, date: number } \\| { type: 'month', year: number, month: number } \\| { type: 'year', year: number } \\| { type: 'quarter',  year: number, quarter: number } \\| { type: 'input' }) => boolean` | `() => false` | Validator of the date. | `detail` 2.37.1 |\n| is-time-disabled | `(current: number) => { isHourDisabled?: () => boolean, isMinuteDisabled?: () => boolean, isSecondDisabled?: () => boolean }` | `undefined` | Validator of the time. |  |\n| placeholder | `string` | `'Select Date and Time'` | Placeholder. |  |\n| time-picker-props | `TimePickerProps` | `undefined` | Time picker props in the panel. | 2.27.0 |\n| update-value-on-close | `boolean` | `false` | Whether to update value on close. |  |\n| on-update:formatted-value | `(value: string \\| null, timestampValue: number \\| null) => void` | `undefined` | Date selected callback. | MEXT_VERSION |\n| on-update:value | `(value: number \\| null, formattedValue: string \\| null) => void` | `undefined` | Date selected callback. | `formattedValue` 2.24.0 |\n\n### DateRange Type Props\n\n| Name | Type | Default | Description | Version |\n| --- | --- | --- | --- | --- |\n| actions | `Array<'clear' \\| 'confirm'> \\| null` | `['clear', 'confirm']` | Operations supported for the `daterange` type date picker. |  |\n| bind-calendar-months | `boolean` | `false` | Whether months in panel calendar are consecutive. | 2.28.3 |\n| default-calendar-start-time | `number` | `undefined` | Default panel calendar start month timestamp. | 2.28.3 |\n| default-calendar-end-time | `number` | `undefined` | Default panel calendar end month timestamp. | 2.28.3 |\n| end-placeholder | `string` | `'End Date'` | Placeholder at end part of the input. |  |\n| fast-year-select | `boolean` | `false` | Close year and month panel after selecting year. | 2.44.0 |\n| fast-month-select | `boolean` | `false` | Close year and month panel after selecting month. | 2.44.0 |\n| format | `string` | `'yyyy-MM-dd'` | Format of the input. For detail please see [format](https://date-fns.org/v2.23.0/docs/format). |  |\n| is-date-disabled | `(current: number, phase: 'start' \\| 'end', value: [number, number] \\| null) => boolean` | `undefined` | Validator of the date. | `detail` 2.37.1 |\n| is-time-disabled | `(current: number, phase: 'start' \\| 'end', value: [number, number]) => { isHourDisabled?: (hour: number) => boolean, isMinuteDisabled?: (minute: number, hour: number \\| null) => boolean, isSecondDisabled?: (second: number, minute: number \\| null, hour: number \\| null) => boolean }` | `undefined` | Validator of the time. `null` in validators means value of picker is empty. |  |\n| close-on-select | `boolean` | `false` | Whether to close the panel after the user has selected a time range. |  |\n| separator | `string` | internal icon | The separator between the start input and the end input. |  |\n| start-placeholder | `string` | `'Start Date'` | The prompt information at the beginning of the input. |  |\n| update-value-on-close | `boolean` | `false` | Whether to update the value on close. |  |\n| on-update:formatted-value | `(value: [string, string] \\| null, timestampValue: [number, number] \\| null) => void` | `undefined` | Formatted range changed callback. | 2.24.0 |\n| on-update:value | `(value: [number, number] \\| null, formattedValue: [string, string] \\| null) => void` | `undefined` | Range changed callback. | `formattedValue` 2.24.0 |\n\n### DateTimeRange Type Props\n\n| Name | Type | Default | Description | Version |\n| --- | --- | --- | --- | --- |\n| actions | `Array<'clear' \\| 'confirm'> \\| null` | `['clear', 'confirm']` | Operations supported for the `datetimerange` type. |  |\n| bind-calendar-months | `boolean` | `false` | Whether months in panel calendar are consecutive. | 2.28.3 |\n| default-calendar-start-time | `number` | `undefined` | Default panel calendar start month timestamp. | 2.28.3 |\n| default-calendar-end-time | `number` | `undefined` | Default panel calendar end month timestamp. | 2.28.3 |\n| default-time | `string \\| Array<string \\| undefined> \\| (timestamp: number, position: \"start\" \\| \"end\", value: [number, number] \\| null) => string` | `undefined` | Default time of the selected date. Can accept a function with timestamp, position and value arguments that returns a formatted string. It's format is `HH:mm:ss`. | 2.22.0, functional since 2.43.2 |\n| end-placeholder | `string` | `'End Date and Time'` | Placeholder at end part of the input. |  |\n| fast-year-select | `boolean` | `false` | Close year and month panel after selecting year. | 2.44.0 |\n| fast-month-select | `boolean` | `false` | Close year and month panel after selecting month. | 2.44.0 |\n| format | `string` | `'yyyy-MM-dd HH:mm:ss'` | Format of the input. For detail please see [format](https://date-fns.org/v2.23.0/docs/format). |  |\n| is-date-disabled | `(current: number, phase: 'start' \\| 'end', value: [number, number] \\| null) => boolean` | `undefined` | Validator of the date. |  |\n| is-time-disabled | `(current: number, phase: 'start' \\| 'end', value: [number, number]) => { isHourDisabled?: (hour: number) => boolean, isMinuteDisabled?: (minute: number, hour: number \\| null) => boolean, isSecondDisabled?: (second: number, minute: number \\| null, hour: number \\| null) => boolean }` | `undefined` | Validator of the time. `null` in validators means value of picker is empty. |  |\n| separator | `string` | internal icon | The separator between the start input and the end input. |  |\n| start-placeholder | `string` | `'Start Date and Time'` | The prompt information at the beginning of the input. |  |\n| time-picker-props | `TimePickerProps \\| [TimePickerProps, TimePickerProps]` | `undefined` | Time picker props in the panel. | 2.27.0 |\n| update-value-on-close | `boolean` | `false` | Whether to update value on close. |  |\n| on-update:formatted-value | `(value: [string, string] \\| null, timestampValue: [number, number] \\| null) => void` | `undefined` | Formatted value changed callback. | 2.24.0 |\n| on-update:value | `(value: [number, number] \\| null, formattedValue: [string, string] \\| null) => void` | `undefined` | Value changed callback. | `formattedValue` 2.24.0 |\n\n### Month Type Props\n\n| Name | Type | Default | Description | Version |\n| --- | --- | --- | --- | --- |\n| actions | `Array<'clear' \\| 'now' \\| 'confirm'> \\| null` | `['clear', 'now']` | Operations supported for the `month` type date picker. |  |\n| format | `string` | `'yyyy-MM'` | Format of the input. For detail please see [format](https://date-fns.org/v2.23.0/docs/format). |  |\n| is-date-disabled | `(current: number, detail: { type: 'date', year: number, month: number, date: number } \\| { type: 'month', year: number, month: number } \\| { type: 'year', year: number } \\| { type: 'quarter',  year: number, quarter: number } \\| { type: 'input' }) => boolean` | `() => false` | Validator of the month. | `detail` 2.37.1 |\n| placeholder | `string` | `'Select Month'` | Placeholder. |  |\n| on-update:formatted-value | `(value: string \\| null, timestampValue: number \\| null) => void` | `undefined` | Formatted value changed callback. | 2.24.0 |\n| on-update:value | `(value: number \\| null, formattedValue: string \\| null) => void` | `undefined` | Value changed callback. | `formattedValue` 2.24.0 |\n\n### MonthRange, QuarterRange, YearRange Type Props\n\n| Name | Type | Default | Description | Version |\n| --- | --- | --- | --- | --- |\n| actions | `Array<'clear' \\| 'confirm'> \\| null` | `['clear', 'confirm']` | Operations supported for the `monthrange` type date picker. | 2.28.3 |\n| end-placeholder | `string` | `'End Month'` | Placeholder at end part of the input. | 2.28.3 |\n| format | `string` | `'yyyy-MM-dd'` | Format of the input. For detail please see [format](https://date-fns.org/v2.23.0/docs/format). | 2.28.3 |\n| close-on-select | `boolean` | `false` | Whether to close the panel after the user has selected a time range. | 2.28.3 |\n| separator | `string` | internal icon | The separator between the start input and the end input. | 2.28.3 |\n| start-placeholder | `string` | `'Start Month'` | The prompt information at the beginning of the input. | 2.28.3 |\n| update-value-on-close | `boolean` | `false` | Whether to update the value on close. | 2.28.3 |\n| on-update:formatted-value | `(value: [string, string] \\| null, timestampValue: [number, number] \\| null) => void` | `undefined` | Formatted range changed callback. | 2.28.3 |\n| on-update:value | `(value: [number, number] \\| null, formattedValue: [string, string] \\| null) => void` | `undefined` | Range changed callback. | 2.28.3 |\n\n### Year Type Props\n\n| Name | Type | Default | Description | Version |\n| --- | --- | --- | --- | --- |\n| actions | `Array<'clear' \\| 'now'> \\| null` | `['clear', 'now']` | Operations supported for the `year` type date picker. |  |\n| format | `string` | `'yyyy'` | Format of the input. For detail please see [format](https://date-fns.org/v2.23.0/docs/format). |  |\n| is-date-disabled | `(current: number, detail: { type: 'date', year: number, month: number, date: number } \\| { type: 'month', year: number, month: number } \\| { type: 'year', year: number } \\| { type: 'quarter',  year: number, quarter: number } \\| { type: 'input' }) => boolean` | `() => false` | Validator of the year. | `detail` 2.37.1 |\n| placeholder | `string` | `'Select Year'` | Placeholder. |  |\n| on-update:formatted-value | `(value: string \\| null, timestampValue: number \\| null) => void` | `undefined` | Formatted value changed callback. | 2.24.0 |\n| on-update:value | `(value: number \\| null, formattedValue: string \\| null) => void` | `undefined` | Value changed callback. | `formattedValue` 2.24.0 |\n\n### Week Type Props\n\n| Name | Type | Default | Description | Version |\n| --- | --- | --- | --- | --- |\n| actions | `Array<'clear' \\| 'now'> \\| null` | `['clear', 'now']` | Operations supported for the `week` type date picker. | 2.37.0 |\n| default-calendar-start-time | `number` | `undefined` | Default panel calendar start month timestamp. | 2.38.1 |\n| format | `string` | `'YYYY-w'` for en-US, Locale specific. | Format of the input. For detail please see [format](https://date-fns.org/v2.23.0/docs/format). | 2.37.0 |\n| placeholder | `string` | `'Select Week'` for en-US, Locale specific. | Placeholder. | 2.37.0 |\n| on-update:formatted-value | `(value: string \\| null, timestampValue: number \\| null) => void` | `undefined` | Formatted value changed callback. | 2.37.0 |\n| on-update:value | `(value: number \\| null, formattedValue: string \\| null) => void` | `undefined` | Value changed callback. | 2.37.0 |\n\n### DatePicker Slots\n\n| Name       | Parameters | Description                       | Version |\n| ---------- | ---------- | --------------------------------- | ------- |\n| date-icon  | `()`       | Date icon of the input box.       | 2.29.0  |\n| footer     | `()`       | Extra Footer.                     |         |\n| next-month | `()`       | Next icon of the date panel.      | 2.33.4  |\n| next-year  | `()`       | Fast next icon of the date panel. | 2.33.4  |\n| prev-month | `()`       | Prev icon of the date panel.      | 2.33.4  |\n| prev-year  | `()`       | Fast prev icon of the date panel. | 2.33.4  |\n| separator  | `()`       | Separator of range picker.        | 2.29.0  |\n\n### Date, Year, QuarterRange, Week Slots\n\n| 名称 | 参数 | 说明 | 版本 |\n| --- | --- | --- | --- |\n| clear | `(props: { onClear: () => void, text: string })` | Clear button of the panel. | 2.40.0 |\n| now | `(props: { onNow: () => void, text: string })` | Now button of the panel. | 2.40.0 |\n\n### DateRange, DateTimeRange, MonthRange, YearRange Slots\n\n| 名称 | 参数 | 说明 | 版本 |\n| --- | --- | --- | --- |\n| clear | `(props: { onClear: () => void, text: string })` | Clear button of the panel. | 2.40.0 |\n| confirm | `(props: { onConfirm: () => void, disabled: boolean, text: string })` | Confirm button of the panel. | 2.40.0 |\n\n### DateTime, Month, Quarter Slots\n\n| 名称 | 参数 | 说明 | 版本 |\n| --- | --- | --- | --- |\n| clear | `(props: { onClear: () => void, text: string })` | Clear button of the panel. | 2.40.0 |\n| confirm | `(props: { onConfirm: () => void, disabled: boolean, text: string })` | Confirm button of the panel. | 2.40.0 |\n| now | `(props: { onNow: () => void, text: string })` | Now button of the panel. | 2.40.0 |\n\n### DatePicker Methods\n\n| Name  | Type         | Description | Version |\n| ----- | ------------ | ----------- | ------- |\n| focus | `() => void` | Focus.      | 2.24.2  |\n| blur  | `() => void` | Blur.       | 2.24.2  |\n"
  },
  {
    "path": "src/date-picker/demos/enUS/month.demo.vue",
    "content": "<markdown>\n# Month\n\nUse `month-format` to format month item inside panel.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst timestamp = ref(1183135260000)\n</script>\n\n<template>\n  <n-space vertical>\n    <n-date-picker v-model:value=\"timestamp\" type=\"month\" clearable />\n    <n-date-picker\n      v-model:value=\"timestamp\"\n      type=\"month\"\n      format=\"y MMM\"\n      month-format=\"MMM\"\n      clearable\n    />\n    <pre>{{ JSON.stringify(timestamp) }}</pre>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/date-picker/demos/enUS/monthrange.demo.vue",
    "content": "<markdown>\n# Month range\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst timestamp = ref<[number, number]>([1183135260000, Date.now()])\n</script>\n\n<template>\n  <n-date-picker v-model:value=\"timestamp\" type=\"monthrange\" clearable />\n  <pre>{{ JSON.stringify(timestamp) }}</pre>\n</template>\n"
  },
  {
    "path": "src/date-picker/demos/enUS/panel.demo.vue",
    "content": "<markdown>\n# Use panel only\n\nIt may be useful sometimes.\n</markdown>\n\n<template>\n  <n-date-picker panel type=\"date\" />\n</template>\n"
  },
  {
    "path": "src/date-picker/demos/enUS/quarter.demo.vue",
    "content": "<markdown>\n# Quarter\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst timestamp = ref(1183135260000)\n</script>\n\n<template>\n  <n-date-picker v-model:value=\"timestamp\" type=\"quarter\" clearable />\n  <pre>{{ JSON.stringify(timestamp) }}</pre>\n</template>\n"
  },
  {
    "path": "src/date-picker/demos/enUS/quarterrange.demo.vue",
    "content": "<markdown>\n# Quarter range\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst timestamp = ref<[number, number]>([1183135260000, Date.now()])\n</script>\n\n<template>\n  <n-date-picker v-model:value=\"timestamp\" type=\"quarterrange\" clearable />\n  <pre>{{ JSON.stringify(timestamp) }}</pre>\n</template>\n"
  },
  {
    "path": "src/date-picker/demos/enUS/shortcuts.demo.vue",
    "content": "<markdown>\n# Shortcuts\n\nYou can customize some shorcut buttons.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst ts1 = ref(null)\nconst ts2 = ref(1183135260000)\nconst range1 = ref(null)\nconst range2 = ref(null)\nconst shortcuts = {\n  'Honey birthday': 1631203200000,\n  Yesterday: () => new Date().getTime() - 24 * 60 * 60 * 1000\n}\nconst rangeShortcuts = {\n  'Happy holiday': [1629216000000, 1631203200000] as const,\n  'Last 2 hours': () => {\n    const cur = new Date().getTime()\n    return [cur - 2 * 60 * 60 * 1000, cur] as const\n  }\n}\n</script>\n\n<template>\n  <n-space vertical>\n    <n-date-picker v-model:value=\"ts1\" type=\"date\" :shortcuts=\"shortcuts\" />\n    <n-date-picker v-model:value=\"ts2\" type=\"datetime\" :shortcuts=\"shortcuts\" />\n    <n-date-picker\n      v-model:value=\"range1\"\n      type=\"daterange\"\n      :shortcuts=\"rangeShortcuts\"\n    />\n    <n-date-picker\n      v-model:value=\"range2\"\n      type=\"datetimerange\"\n      :shortcuts=\"rangeShortcuts\"\n    />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/date-picker/demos/enUS/size.demo.vue",
    "content": "<markdown>\n# Size\n\nDate Picker can be `small`, `medium` or `large` sized.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst timestamp = ref(null)\n</script>\n\n<template>\n  <n-space vertical>\n    <n-date-picker v-model:value=\"timestamp\" size=\"small\" type=\"date\" />\n    <n-date-picker v-model:value=\"timestamp\" size=\"medium\" type=\"date\" />\n    <n-date-picker v-model:value=\"timestamp\" size=\"large\" type=\"date\" />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/date-picker/demos/enUS/status.demo.vue",
    "content": "<markdown>\n# Validation status\n\nValidation status can be applied outside form.\n</markdown>\n\n<template>\n  <n-space vertical>\n    <n-date-picker status=\"warning\" />\n    <n-date-picker status=\"error\" />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/date-picker/demos/enUS/update-on-close.demo.vue",
    "content": "<markdown>\n# Update value on close\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst updateValueOnClose = ref(true)\n</script>\n\n<template>\n  <n-space vertical>\n    <n-date-picker\n      type=\"datetime\"\n      :default-value=\"Date.now()\"\n      :update-value-on-close=\"updateValueOnClose\"\n    />\n    <n-date-picker\n      :default-value=\"[Date.now(), Date.now()]\"\n      :update-value-on-close=\"updateValueOnClose\"\n      type=\"daterange\"\n    />\n    <n-date-picker\n      :default-value=\"[Date.now(), Date.now()]\"\n      :update-value-on-close=\"updateValueOnClose\"\n      type=\"datetimerange\"\n    />\n    <n-switch v-model:value=\"updateValueOnClose\" />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/date-picker/demos/enUS/week.demo.vue",
    "content": "<markdown>\n# Week\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst timestamp = ref(1183135260000)\n</script>\n\n<template>\n  <n-date-picker v-model:value=\"timestamp\" type=\"week\" clearable />\n  <pre>{{ JSON.stringify(timestamp) }}</pre>\n</template>\n"
  },
  {
    "path": "src/date-picker/demos/enUS/year.demo.vue",
    "content": "<markdown>\n# Year\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst timestamp = ref(1183135260000)\n</script>\n\n<template>\n  <n-date-picker v-model:value=\"timestamp\" type=\"year\" clearable />\n  <pre>{{ JSON.stringify(timestamp) }}</pre>\n</template>\n"
  },
  {
    "path": "src/date-picker/demos/enUS/yearrange.demo.vue",
    "content": "<markdown>\n# Year range\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst timestamp = ref<[number, number]>([1183135260000, Date.now()])\n</script>\n\n<template>\n  <n-date-picker v-model:value=\"timestamp\" type=\"yearrange\" clearable />\n  <pre>{{ JSON.stringify(timestamp) }}</pre>\n</template>\n"
  },
  {
    "path": "src/date-picker/demos/zhCN/actions.demo.vue",
    "content": "<markdown>\n# 操作\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst ts1 = ref(null)\nconst ts2 = ref(1183135260000)\nconst range1 = ref(null)\nconst range2 = ref(null)\n</script>\n\n<template>\n  <n-space vertical>\n    <n-date-picker v-model:value=\"ts1\" type=\"date\" :actions=\"['now']\" />\n    <n-date-picker v-model:value=\"ts2\" type=\"datetime\" :actions=\"['now']\" />\n    <n-date-picker\n      v-model:value=\"range1\"\n      update-value-on-close\n      type=\"daterange\"\n      :actions=\"null\"\n    />\n    <n-date-picker\n      v-model:value=\"range2\"\n      update-value-on-close\n      type=\"datetimerange\"\n      :actions=\"['clear']\"\n    />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/date-picker/demos/zhCN/close-panel-on-select.demo.vue",
    "content": "<markdown>\n# 当选择年、月后，关闭年月面板\n\n通过使用 `fast-year-select` 和 `fast-month-select` 属性，可以实现当选择年、月后，关闭年月面板。\n</markdown>\n\n<script lang=\"ts\">\nimport { defineComponent, ref } from 'vue'\n\nexport default defineComponent({\n  setup() {\n    return {\n      timestamp: ref(1183135260000),\n      range: ref<[number, number]>([1183135260000, Date.now()])\n    }\n  }\n})\n</script>\n\n<template>\n  <NFlex vertical>\n    <n-date-picker\n      v-model:value=\"timestamp\"\n      type=\"date\"\n      fast-year-select\n      fast-month-select\n    />\n    <n-date-picker\n      v-model:value=\"timestamp\"\n      type=\"datetime\"\n      fast-year-select\n      fast-month-select\n    />\n    <n-date-picker\n      v-model:value=\"range\"\n      type=\"daterange\"\n      fast-year-select\n      fast-month-select\n    />\n    <n-date-picker\n      v-model:value=\"range\"\n      type=\"datetimerange\"\n      fast-year-select\n      fast-month-select\n    />\n    <pre>{{ JSON.stringify(timestamp) }}</pre>\n  </NFlex>\n</template>\n"
  },
  {
    "path": "src/date-picker/demos/zhCN/date.demo.vue",
    "content": "<markdown>\n# 日期\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst timestamp = ref(1183135260000)\n</script>\n\n<template>\n  <n-date-picker v-model:value=\"timestamp\" type=\"date\" />\n  <pre>{{ JSON.stringify(timestamp) }}</pre>\n</template>\n"
  },
  {
    "path": "src/date-picker/demos/zhCN/daterange.demo.vue",
    "content": "<markdown>\n# 日期范围\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst range = ref<[number, number]>([1183135260000, Date.now()])\n</script>\n\n<template>\n  <n-date-picker v-model:value=\"range\" type=\"daterange\" clearable />\n  <pre>{{ JSON.stringify(range) }}</pre>\n</template>\n"
  },
  {
    "path": "src/date-picker/demos/zhCN/datetime.demo.vue",
    "content": "<markdown>\n# 日期时间\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst timestamp = ref(1183135260000)\n</script>\n\n<template>\n  <n-date-picker v-model:value=\"timestamp\" type=\"datetime\" clearable />\n  <pre>{{ JSON.stringify(timestamp) }}</pre>\n</template>\n"
  },
  {
    "path": "src/date-picker/demos/zhCN/datetimeformat.demo.vue",
    "content": "<markdown>\n# 使用格式化的值\n\n实话说我不喜欢这个 feature，因为多数情况下，传递时间字符串不是个最佳实践。但是现实世界是复杂的，我希望这个功能能帮你解决一些棘手的问题，比如为了后端传过来的数据买账。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst formattedValue = ref('2007.06.30 12:08:55')\n</script>\n\n<template>\n  <pre>{{ formattedValue }}</pre>\n  <n-date-picker\n    v-model:formatted-value=\"formattedValue\"\n    value-format=\"yyyy.MM.dd HH:mm:ss\"\n    type=\"datetime\"\n    clearable\n  />\n</template>\n"
  },
  {
    "path": "src/date-picker/demos/zhCN/datetimerange.demo.vue",
    "content": "<markdown>\n# 日期时间范围\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst range = ref<[number, number]>([1183135260000, Date.now()])\n</script>\n\n<template>\n  <n-date-picker v-model:value=\"range\" type=\"datetimerange\" clearable />\n  <pre>{{ JSON.stringify(range) }}</pre>\n</template>\n"
  },
  {
    "path": "src/date-picker/demos/zhCN/default-time.demo.vue",
    "content": "<markdown>\n# 默认时间\n\n你可以设定选择某个日期后默认使用的时间。\n</markdown>\n\n<script setup lang=\"ts\">\nimport { format, isAfter, isToday } from 'date-fns'\n\nfunction getSingleDefaultTime(timestamp: number): string {\n  const now = new Date()\n\n  if (isToday(timestamp)) {\n    return format(new Date(), 'HH:mm:ss')\n  }\n  if (isAfter(now, timestamp)) {\n    return '23:59:59'\n  }\n  else {\n    return '00:00:00'\n  }\n}\n\nfunction getRangeDefaultTime(timestamp: number, position: 'start' | 'end'): string {\n  const now = new Date()\n\n  if (position === 'start') {\n    return '00:00:00'\n  }\n\n  if (isToday(timestamp)) {\n    return format(new Date(), 'HH:mm:ss')\n  }\n  if (isAfter(now, timestamp)) {\n    return '23:59:59'\n  }\n  else {\n    return '00:00:00'\n  }\n}\n</script>\n\n<template>\n  <n-space vertical>\n    <n-date-picker type=\"datetime\" clearable default-time=\"13:22:11\" />\n    <n-date-picker type=\"datetime\" clearable default-time=\"16:00:00\" />\n    <n-date-picker\n      type=\"datetime\"\n      clearable\n      :default-time=\"getSingleDefaultTime\"\n    />\n    <n-date-picker type=\"datetimerange\" clearable default-time=\"13:22:11\" />\n    <n-date-picker\n      type=\"datetimerange\"\n      clearable\n      :default-time=\"['16:00:00', undefined]\"\n    />\n    <n-date-picker\n      type=\"datetimerange\"\n      clearable\n      :default-time=\"['13:22:11', '16:00:00']\"\n    />\n    <n-date-picker\n      type=\"datetimerange\"\n      clearable\n      :default-time=\"getRangeDefaultTime\"\n    />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/date-picker/demos/zhCN/disabled-time.demo.vue",
    "content": "<markdown>\n# 禁用特定时间\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { startOfDay } from 'date-fns'\n\nconst d = 86400000\nconst h = 3600000\nconst m = 60000\nconst s = 1000\n\nfunction dateDisabled(ts: number) {\n  const date = new Date(ts).getDate()\n  return date < 15\n}\n\nfunction timeDisabled(ts: number) {\n  const date = new Date(ts).getDate()\n  return {\n    isHourDisabled: (hour: number) => {\n      return date >= 15 && hour < 12\n    }\n  }\n}\n\nfunction isRangeDateDisabled(\n  ts: number,\n  type: 'start' | 'end',\n  range: [number, number] | null\n) {\n  if (type === 'start' && range !== null) {\n    return startOfDay(range[1]).valueOf() - startOfDay(ts).valueOf() <= d * 6\n  }\n  if (type === 'end' && range !== null) {\n    return startOfDay(ts).valueOf() - startOfDay(range[0]).valueOf() <= d * 6\n  }\n  return false\n}\n\nfunction isRangeTimeDisabled(\n  current: number,\n  type: 'start' | 'end',\n  range: [number, number]\n) {\n  if (type === 'start') {\n    return {\n      isHourDisabled: (hour: number) => {\n        return range[1] - startOfDay(range[0]).valueOf() - hour * h < d * 7\n      },\n      isMinuteDisabled: (minute: number, hour: number | null) => {\n        if (hour === null)\n          return false\n        return (\n          range[1] - startOfDay(range[0]).valueOf() - hour * h - minute * m\n          < d * 7\n        )\n      },\n      isSecondDisabled: (\n        second: number,\n        minute: number | null,\n        hour: number | null\n      ) => {\n        if (hour === null || minute === null)\n          return false\n        return (\n          range[1]\n          - startOfDay(range[0]).valueOf()\n          - hour * h\n          - minute * m\n          - second * s\n          < d * 7\n        )\n      }\n    }\n  }\n  else {\n    return {\n      isHourDisabled: (hour: number) => {\n        return (\n          startOfDay(range[1]).valueOf() + hour * h + (h - s) - range[0] < d * 7\n        )\n      },\n      isMinuteDisabled: (minute: number, hour: number | null) => {\n        return (\n          startOfDay(range[1]).valueOf()\n          + Number(hour) * h\n          + minute * m\n          + (m - s)\n          - range[0]\n          < d * 7\n        )\n      },\n      isSecondDisabled: (\n        second: number,\n        minute: number | null,\n        hour: number | null\n      ) => {\n        if (hour === null || minute === null)\n          return false\n        return (\n          startOfDay(range[1]).valueOf()\n          + hour * h\n          + minute * m\n          + second * s\n          - range[0]\n          < d * 7\n        )\n      }\n    }\n  }\n}\n\nfunction disablePreviousDate(ts: number) {\n  return ts > Date.now()\n}\n</script>\n\n<template>\n  <n-space vertical>\n    禁用上半月\n    <n-date-picker\n      type=\"date\"\n      :default-value=\"Date.now()\"\n      :is-date-disabled=\"dateDisabled\"\n    />\n    禁用上半月 & 下半个月的上午\n    <n-date-picker\n      type=\"datetime\"\n      :default-value=\"Date.now()\"\n      :is-date-disabled=\"dateDisabled\"\n      :is-time-disabled=\"timeDisabled\"\n    />\n    间隔至少七天\n    <n-date-picker\n      type=\"daterange\"\n      :default-value=\"[Date.now(), Date.now() + 86400000]\"\n      :is-date-disabled=\"isRangeDateDisabled\"\n    />\n    间隔至少七天\n    <n-date-picker\n      type=\"datetimerange\"\n      :default-value=\"[Date.now(), Date.now() + 86400000]\"\n      :is-date-disabled=\"isRangeDateDisabled\"\n      :is-time-disabled=\"isRangeTimeDisabled\"\n    />\n    只能选过去的时间\n    <n-date-picker\n      type=\"daterange\"\n      :default-value=\"[Date.now(), Date.now() + 86400000]\"\n      :is-date-disabled=\"disablePreviousDate\"\n    />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/date-picker/demos/zhCN/disabled.demo.vue",
    "content": "<markdown>\n# 禁用\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst datetime = ref(null)\nconst date = ref(null)\nconst datetimerange = ref(null)\nconst daterange = ref(null)\nconst disabled = ref(true)\n</script>\n\n<template>\n  <n-space vertical>\n    <n-date-picker v-model:value=\"date\" type=\"date\" :disabled=\"disabled\" />\n    <n-date-picker\n      v-model:value=\"datetime\"\n      type=\"datetime\"\n      :disabled=\"disabled\"\n    />\n    <n-date-picker\n      v-model:value=\"daterange\"\n      :disabled=\"disabled\"\n      type=\"daterange\"\n    />\n    <n-date-picker\n      v-model:value=\"datetimerange\"\n      :disabled=\"disabled\"\n      type=\"datetimerange\"\n    />\n    <n-switch v-model:value=\"disabled\" />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/date-picker/demos/zhCN/events.demo.vue",
    "content": "<markdown>\n# 事件\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { useMessage } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst message = useMessage()\nconst datetime = ref(1183135260000)\nconst date = ref(null)\nconst datetimerange = ref(null)\nconst daterange = ref(null)\nconst disabled = ref(false)\n\nfunction onBlur1() {\n  message.info('Blur-1')\n}\n\nfunction onChange1(v: number) {\n  message.info(`Change-1 ${v}`)\n}\n\nfunction onBlur2() {\n  message.error('Blur-2')\n}\n\nfunction onChange2(v: number) {\n  message.error(`Change-2 ${v}`)\n}\n\nfunction onBlur3() {\n  message.warning('Blur-3')\n}\n\nfunction onChange3(v: number) {\n  message.warning(`Change-3 ${v}`)\n}\n\nfunction onBlur4() {\n  message.success('Blur-4')\n}\n\nfunction onChange4(v: number) {\n  message.success(`Change-4 ${v}`)\n}\n\nfunction onClear() {\n  message.info('Clear-5')\n}\n\nfunction onConfirm(v: number | number[] | null) {\n  message.info(`Confirm-5 ${v}`)\n}\n</script>\n\n<template>\n  <n-space vertical>\n    <n-date-picker\n      v-model:value=\"datetime\"\n      type=\"datetime\"\n      :disabled=\"disabled\"\n      @blur=\"onBlur1\"\n      @update:value=\"onChange1\"\n    />\n    <n-date-picker\n      v-model:value=\"date\"\n      type=\"date\"\n      :disabled=\"disabled\"\n      @blur=\"onBlur2\"\n      @update:value=\"onChange2\"\n    />\n    <n-date-picker\n      v-model:value=\"datetimerange\"\n      :disabled=\"disabled\"\n      type=\"datetimerange\"\n      @blur=\"onBlur3\"\n      @update:value=\"onChange3\"\n    />\n    <n-date-picker\n      v-model:value=\"daterange\"\n      :disabled=\"disabled\"\n      type=\"daterange\"\n      @blur=\"onBlur4\"\n      @update:value=\"onChange4\"\n    />\n    <n-date-picker\n      v-model:value=\"daterange\"\n      :disabled=\"disabled\"\n      type=\"daterange\"\n      @clear=\"onClear\"\n      @confirm=\"onConfirm\"\n    />\n    <n-switch v-model:value=\"disabled\" />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/date-picker/demos/zhCN/focus.demo.vue",
    "content": "<markdown>\n# 手动 focus & blur\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { DatePickerInst } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst datePickerInstRef = ref<DatePickerInst | null>(null)\n\nfunction handleClick() {\n  datePickerInstRef.value?.focus()\n  setTimeout(() => {\n    datePickerInstRef.value?.blur()\n  }, 1000)\n}\n</script>\n\n<template>\n  <n-space item-style=\"display: flex; align-item: center;\">\n    <n-button @click=\"handleClick\">\n      聚焦，一秒后失效\n    </n-button>\n    <n-date-picker ref=\"datePickerInstRef\" style=\"width: 200px\" />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/date-picker/demos/zhCN/footerslot.demo.vue",
    "content": "<markdown>\n# 额外内容\n</markdown>\n\n<template>\n  <n-space vertical>\n    <n-date-picker type=\"date\">\n      <template #footer>\n        extra footer\n      </template>\n    </n-date-picker>\n    <n-date-picker type=\"datetime\">\n      <template #footer>\n        extra footer\n      </template>\n    </n-date-picker>\n    <n-date-picker type=\"daterange\">\n      <template #footer>\n        extra footer\n      </template>\n    </n-date-picker>\n    <n-date-picker type=\"datetimerange\">\n      <template #footer>\n        extra footer\n      </template>\n    </n-date-picker>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/date-picker/demos/zhCN/form-debug.demo.vue",
    "content": "<markdown>\n# Form debug\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { FormRules } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst model = ref({\n  date: null\n})\n\nconst rules: FormRules = {\n  date: {\n    type: 'number',\n    required: true,\n    trigger: ['blur', 'change'],\n    message: '请选择日期'\n  }\n}\n</script>\n\n<template>\n  <n-form :model=\"model\" :rules=\"rules\">\n    <n-form-item :span=\"12\" label=\"产检时间\" path=\"date\">\n      <n-date-picker\n        v-model:value=\"model.date\"\n        style=\"width: 100%\"\n        type=\"date\"\n        clearable\n      />\n    </n-form-item>\n  </n-form>\n  <pre>{{ model.date }}</pre>\n</template>\n"
  },
  {
    "path": "src/date-picker/demos/zhCN/format.demo.vue",
    "content": "<markdown>\n# 格式化\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst timestamp = ref(null)\nconst timestamp2 = ref(1183135260000)\nconst format = 'yyyy/MM/dd - HH:mm'\n</script>\n\n<template>\n  <n-space vertical>\n    <n-date-picker\n      v-model:value=\"timestamp\"\n      type=\"datetime\"\n      clearable\n      :format=\"format\"\n    />\n    <n-date-picker\n      v-model:value=\"timestamp2\"\n      type=\"datetime\"\n      :format=\"format\"\n      clearable\n    />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/date-picker/demos/zhCN/icon.demo.vue",
    "content": "<markdown>\n# 图标\n</markdown>\n\n<script lang=\"ts\" setup>\nimport {\n  ChevronBackCircle,\n  ChevronBackCircleOutline,\n  ChevronForwardCircle,\n  ChevronForwardCircleOutline,\n  RocketOutline,\n  TrendingUpSharp\n} from '@vicons/ionicons5'\n</script>\n\n<template>\n  <n-space vertical>\n    <n-date-picker type=\"date\">\n      <template #date-icon>\n        <n-icon :size=\"16\" :component=\"RocketOutline\" />\n      </template>\n      <template #prev-year>\n        <n-icon :size=\"16\" :component=\"ChevronBackCircle\" />\n      </template>\n      <template #prev-month>\n        <n-icon :size=\"16\" :component=\"ChevronBackCircleOutline\" />\n      </template>\n      <template #next-month>\n        <n-icon :size=\"16\" :component=\"ChevronForwardCircleOutline\" />\n      </template>\n      <template #next-year>\n        <n-icon :size=\"16\" :component=\"ChevronForwardCircle\" />\n      </template>\n    </n-date-picker>\n    <n-date-picker type=\"daterange\">\n      <template #separator>\n        <n-icon :size=\"16\" :component=\"TrendingUpSharp\" />\n      </template>\n      <template #date-icon>\n        <n-icon :size=\"16\" :component=\"RocketOutline\" />\n      </template>\n    </n-date-picker>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/date-picker/demos/zhCN/index.demo-entry.md",
    "content": "# 日期选择器 Date Picker\n\n关于如何设定时间，大家总有很多种想法。\n\n## 演示\n\n```demo\ndate.vue\ndatetime.vue\ndatetimeformat.vue\ndaterange.vue\ndatetimerange.vue\nmonth.vue\nmonthrange.vue\nyear.vue\nyearrange.vue\nquarter.vue\nquarterrange.vue\nweek.vue\nsize.vue\ndefault-time.vue\ndisabled.vue\ndisabled-time.vue\nactions.vue\nshortcuts.vue\nevents.vue\nformat.vue\nfooterslot.vue\nstatus.vue\nicon.vue\npanel.vue\nclose-panel-on-select.vue\npanel-debug.vue\nform-debug.vue\n```\n\n## API\n\n### 通用的 Props\n\n| 名称 | 类型 | 默认值 | 说明 | 版本 |\n| --- | --- | --- | --- | --- |\n| calendar-day-format | `string` | `undefined` | 选择面板内部星期几的格式 | 2.40.2 |\n| calendar-header-year-format | `string` | `undefined` | 选择面板内部年的格式 | 2.40.2 |\n| calendar-header-month-format | `string` | `undefined` | 选择面板内部月的格式 | 2.40.2 |\n| calendar-header-month-before-year | `string` | `undefined` | 选择面板内部月是否显示在年的前面 | 2.40.2 |\n| calendar-header-month-year-separator | `string` | `' '` | 选择面板内部年和月的分隔字符 | 2.40.2 |\n| clearable | `boolean` | `false` | 是否支持清除 |  |\n| date-format | `string` | `undefined` | 选择面板内部日期输入框的日期格式 | 2.40.2 |\n| default-value | `number \\| [number, number] \\| null` | `undefined` | 默认被选中的日期的时间戳 |  |\n| default-formatted-value | `string \\| [string, string] \\| null` | `undefined` | Date Picker 格式化后的值 |  |\n| disabled | `boolean` | `false` | 是否禁用 |  |\n| first-day-of-week | `0 \\| 1 \\| 2 \\| 3 \\| 4 \\| 5 \\| 6` | `undefined` | 日历上一周的开始，0 代表周一 |  |\n| formatted-value | `string \\| [string, string] \\| null` | `undefined` | 格式化之后的值 | 2.24.0 |\n| input-readonly | `boolean` | `false` | 设置输入框为只读（避免在移动设备上打开虚拟键盘） |  |\n| month-format | `string` | `'M'` | 设置面板中月份的显示方式，详情见 [format](https://date-fns.org/v2.23.0/docs/format) | 2.37.0 |\n| panel | `boolean` | `false` | 是否只使用面板 | 2.29.1 |\n| placement | `'top-start' \\| 'top' \\| 'top-end' \\| 'right-start' \\| 'right' \\| 'right-end' \\| 'bottom-start' \\| 'bottom' \\| 'bottom-end' \\| 'left-start' \\| 'left' \\| 'left-end'` | `'bottom-start'` | 面板的弹出位置 | 2.25.0 |\n| quarter-format | `string` | `'Q'Q` | 设置面板中季度的显示方式，详情见 [format](https://date-fns.org/v2.23.0/docs/format) | 2.37.0 |\n| shortcuts | `Record<string, number \\| (() => number)> \\| Record<string, [number, number] \\| (() => [number, number])>` | `undefined` | 自定义快捷按钮 |  |\n| show | `boolean` | `undefined` | 是否展示面板 | 2.28.3 |\n| size | `'small' \\| 'medium' \\| 'large'` | `'medium'` | 尺寸 |  |\n| status | `'success' \\| 'warning' \\| 'error'` | `undefined` | 验证状态 | 2.27.0 |\n| time-picker-format | `string \\| undefined` | `undefined` | 日期面板内时间的显示方式，详情见 [format](https://date-fns.org/v2.23.0/docs/format) | 2.38.2 |\n| to | `string \\| HTMLElement \\| false` | `body` | 面板的容器节点，`false` 会待在原地 |  |\n| type | `'date' \\| 'datetime' \\| 'daterange' \\| 'datetimerange' \\| 'month' \\| 'monthrange' \\| 'year' \\| 'yearrange' \\| 'quarter' \\| 'quarterrange' \\| 'week'` | `'date'` | Date Picker 的类型 | `'quarter'` v2.22.0, `'monthrange'` 2.28.3 |\n| value | `number \\| [number, number] \\| null` | `undefined` | Date Picker 的值 |  |\n| value-format | `string` | 跟随 `format` 属性 | 绑定值的格式，详情见 [format](https://date-fns.org/v2.23.0/docs/format) |\n| year-format | `string` | `'y'` | 设置面板中年的显示方式，详情见 [format](https://date-fns.org/v2.23.0/docs/format) | 2.37.0 |\n| year-range | `[number, number]` | `[1901, 2100]` | 设置面板中的年份选择范围 | 2.40.0 |\n| on-clear | `() => void` | `undefined` | 用户 clear 时执行的回调 | 2.28.3 |\n| on-confirm | `(value: number \\| [number, number] \\| null, formattedValue: string \\| [string, string] \\| null) => void` | `undefined` | 用户 confirm 时执行的回调 | 2.28.3 |\n| on-blur | `() => void` | `undefined` | 用户 blur 时执行的回调 |  |\n| on-focus | `() => void` | `undefined` | 用户 focus 时执行的回调 |  |\n| on-next-month | `() => void` | `undefined` | 点击下一个月时的回调 | 2.37.0 |\n| on-prev-month | `() => void` | `undefined` | 点击上一个月时的回调 | 2.37.0 |\n| on-next-year | `() => void` | `undefined` | 点击下一年时的回调 | 2.37.0 |\n| on-prev-year | `() => void` | `undefined` | 点击上一年时的回调 | 2.37.0 |\n| on-update:show | `(show: boolean) => void` | `undefined` | 面板打开、关闭时的回调 | 2.28.3 |\n\n### Date 类型的 Props\n\n| 名称 | 类型 | 默认值 | 说明 | 版本 |\n| --- | --- | --- | --- | --- |\n| actions | `Array<'clear' \\| 'now'> \\| null` | `['clear', 'now']` | Date 类型的 Date Picker 中支持的操作 |  |\n| default-calendar-start-time | `number` | `undefined` | 面板日历默认开始的月份时间戳 | 2.38.1 |\n| fast-year-select | `boolean` | `false` | 为 `true` 时，选择年份后，关闭年月面板 | 2.44.0 |\n| fast-month-select | `boolean` | `false` | 为 `true` 时，选择月份后，关闭年月面板 | 2.44.0 |\n| format | `string` | `'yyyy-MM-dd'` | 时间格式化字符串，详情见 [format](https://date-fns.org/v2.23.0/docs/format) |  |\n| is-date-disabled | `(current: number, detail: { type: 'date', year: number, month: number, date: number } \\| { type: 'month', year: number, month: number } \\| { type: 'year', year: number } \\| { type: 'quarter',  year: number, quarter: number } \\| { type: 'input' }) => boolean` | `undefined` | 日期禁用的校验函数 | `detail` 2.37.1 |\n| placeholder | `string` | `'选择日期'` | 没有值时的占位信息 |  |\n| on-update:formatted-value | `(value: string \\| null, timestampValue: number \\| null) => void` | `undefined` | 受控数据更新时触发的回调函数 | 2.24.0 |\n| on-update:value | `(value: number \\| null, formattedValue: string \\| null) => void` | `undefined` | 受控数据更新时触发的回调函数 | `formattedValue` 2.24.0 |\n\n### DateTime 类型的 Props\n\n| 名称 | 类型 | 默认值 | 说明 | 版本 |\n| --- | --- | --- | --- | --- |\n| actions | `Array<'clear' \\| 'now' \\| 'confirm'> \\| null` | `['clear', 'now', 'confirm']` | DateTime 类型的 Date Picker 中支持的操作 |  |\n| default-calendar-start-time | `number` | `undefined` | 面板日历默认开始的月份时间戳 | 2.38.1 |\n| default-time | `string \\| (timestamp: number) => string` | `undefined` | 默认时间，可以接受一个参数为时间戳的函数，返回格式化的字符串，格式为 `HH:mm:ss` | 2.22.0，从 2.43.2 支持函数 |\n| fast-year-select | `boolean` | `false` | 为 `true` 时，选择年份后，关闭年月面板 | 2.44.0 |\n| fast-month-select | `boolean` | `false` | 为 `true` 时，选择月份后，关闭年月面板 | 2.44.0 |\n| format | `string` | `'yyyy-MM-dd HH:mm:ss'` | 时间格式化字符串，详情见 [format](https://date-fns.org/v2.23.0/docs/format) |  |\n| is-date-disabled | `(current: number, detail: { type: 'date', year: number, month: number, date: number } \\| { type: 'month', year: number, month: number } \\| { type: 'year', year: number } \\| { type: 'quarter',  year: number, quarter: number } \\| { type: 'input' }) => boolean` | `undefined` | 日期禁用的校验函数 | `detail` 2.37.1 |\n| is-time-disabled | `(current: number) => { isHourDisabled: boolean, isMinuteDisabled: boolean, isSecondDisabled: boolean }` | `undefined` | 时间禁用的校验函数 |  |\n| placeholder | `string` | `'选择日期时间'` | 提示信息 |  |\n| time-picker-props | `TimePickerProps` | `undefined` | 面板中时间选择器的属性 | 2.27.0 |\n| update-value-on-close | `boolean` | `false` | 关闭面板时更新值 |  |\n| on-update:formatted-value | `(value: string \\| null, timestampValue: number \\| null) => void` | `undefined` | 数据更新时触发的回调函数 | 2.24.0 |\n| on-update:value | `(value: number \\| null, formattedValue: string \\| null) => void` | `undefined` | 数据更新时触发的回调函数 | `formattedValue` 2.24.0 |\n\n### DateRange 类型的 Props\n\n| 名称 | 类型 | 默认值 | 说明 | 版本 |\n| --- | --- | --- | --- | --- |\n| actions | `Array<'clear' \\| 'confirm'> \\| null` | `['clear', 'confirm']` | DateRange 类型的 Date Picker 中支持的用户操作 |  |\n| bind-calendar-months | `boolean` | `false` | 面板月份是否连续 | 2.28.3 |\n| default-calendar-start-time | `number` | `undefined` | 面板日历默认开始的月份时间戳 | 2.28.3 |\n| default-calendar-end-time | `number` | `undefined` | 面板日历默认结束的月份时间戳 | 2.28.3 |\n| fast-year-select | `boolean` | `false` | 为 `true` 时，选择年份后，关闭年月面板 | 2.44.0 |\n| fast-month-select | `boolean` | `false` | 为 `true` 时，选择月份后，关闭年月面板 | 2.44.0 |\n| format | `string` | `'yyyy-MM-dd'` | 时间格式化字符串，详情见 [format](https://date-fns.org/v2.23.0/docs/format) |  |\n| is-date-disabled | `(current: number, phase: 'start' \\| 'end', value: [number, number] \\| null) => boolean` | `undefined` | 日期禁用的校验函数 |  |\n| is-time-disabled | `(current: number, phase: 'start' \\| 'end', value: [number, number]) => { isHourDisabled?: (hour: number) => boolean, isMinuteDisabled?: (minute: number, hour: number \\| null) => boolean, isSecondDisabled?: (second: number, minute: number \\| null, hour: number \\| null) => boolean }` | `undefined` | 时间禁用的校验函数，校验函数中的 `null` 表示当前没有选中值 |  |\n| close-on-select | `boolean` | `false` | 用户选择时间范围后是否自动关闭面板 |  |\n| separator | `string` | 内置图标 | start 选框与 end 选框之间的分隔符 |  |\n| start-placeholder | `string` | `'开始日期'` | DateRange 中 start 选框的提示信息 |  |\n| update-value-on-close | `boolean` | `false` | 关闭面板时是否更新值 |  |\n| on-update:formatted-value | `(value: [string, string] \\| null, timestampValue: [number, number] \\| null) => void` | `undefined` | 数据更新时触发的回调函数 | 2.24.0 |\n| on-update:value | `(value: [number, number] \\| null, formattedValue: [string, string] \\| null) => void` | `undefined` | 数据更新时触发的回调函数 | `formattedValue` 2.24.0 |\n\n### DateTimeRange 类型的 Props\n\n| 名称 | 类型 | 默认值 | 说明 | 版本 |\n| --- | --- | --- | --- | --- |\n| actions | `Array<'clear' \\| 'confirm'> \\| null` | `['clear', 'confirm']` | DateTimeRange 类型的 Date Picker 中支持的用户操作 |  |\n| bind-calendar-months | `boolean` | `false` | 面板月份是否连续 | 2.28.3 |\n| default-calendar-start-time | `number` | `undefined` | 面板日历默认开始的月份时间戳 | 2.28.3 |\n| default-calendar-end-time | `number` | `undefined` | 面板日历默认结束的月份时间戳 | 2.28.3 |\n| default-time | `string \\| Array<string \\| undefined> \\| (timestamp: number, position: \"start\" \\| \"end\", value: [number, number] \\| null) => string` | `undefined` | 默认时间，可以接受一个参数为时间戳、时间位置、和当前值的函数，返回一个格式化字符串，格式为 `HH:mm:ss` | 2.22.0，从 2.43.2 支持函数 |\n| end-placeholder | `string` | `'结束日期时间'` | DateTimeRange 中 end 选框的提示信息 |  |\n| fast-year-select | `boolean` | `false` | 为 `true` 时，选择年份后，关闭年月面板 | 2.44.0 |\n| fast-month-select | `boolean` | `false` | 为 `true` 时，选择月份后，关闭年月面板 | 2.44.0 |\n| format | `string` | `'yyyy-MM-dd HH:mm:ss'` | 时间格式化字符串，详情见 [format](https://date-fns.org/v2.23.0/docs/format) |  |\n| is-date-disabled | `(current: number, phase: 'start' \\| 'end', value: [number, number] \\| null) => boolean` | `undefined` | 日期禁用的校验函数 |  |\n| is-time-disabled | `(current: number, phase: 'start' \\| 'end', value: [number, number]) => { isHourDisabled?: (hour: number) => boolean, isMinuteDisabled?: (minute: number, hour: number \\| null) => boolean, isSecondDisabled?: (second: number, minute: number \\| null, hour: number \\| null) => boolean }` | `undefined` | 时间禁用的校验函数，校验函数中的 `null` 表示当前没有选中值 |  |\n| separator | `string` | 内置图标 | start 选框与 end 选框之间的分隔符 |  |\n| start-placeholder | `string` | `'开始日期时间'` | DateTimeRange 中 start 选框的提示信息 |  |\n| time-picker-props | `TimePickerProps \\| [TimePickerProps, TimePickerProps]` | `undefined` | 面板中时间选择器的属性 | 2.27.0 |\n| update-value-on-close | `boolean` | `false` | 关闭面板时是否更新值 |  |\n| on-update:formatted-value | `(value: [string, string] \\| null, timestampValue: [number, number] \\| null) => void` | `undefined` | 数据更新时触发的回调函数 | 2.24.0 |\n| on-update:value | `(value: [number, number] \\| null, formattedValue: [string, string] \\| null) => void` | `undefined` | 数据更新时触发的回调函数 | `formattedValue` 2.24.0 |\n\n### Month 类型的 Props\n\n| 名称 | 类型 | 默认值 | 说明 | 版本 |\n| --- | --- | --- | --- | --- |\n| actions | `Array<'clear' \\| 'now' \\| 'confirm'> \\| null` | `['clear', 'now']` | Month 类型的 Date Picker 中支持的操作 |  |\n| format | `string` | `'yyyy-MM'` | 时间格式化字符串，详情见 [format](https://date-fns.org/v2.23.0/docs/format) |  |\n| is-date-disabled | `(current: number, detail: { type: 'date', year: number, month: number, date: number } \\| { type: 'month', year: number, month: number } \\| { type: 'year', year: number } \\| { type: 'quarter',  year: number, quarter: number } \\| { type: 'input' }) => boolean` | `undefined` | 月份禁用的校验函数 | `detail` 2.37.1 |\n| placeholder | `string` | `'选择月份'` | 没有值时的占位信息 |  |\n| on-update:formatted-value | `(value: string \\| null, timestampValue: number \\| null) => void` | `undefined` | 受控数据更新时触发的回调函数 | 2.24.0 |\n| on-update:value | `(value: number \\| null, formattedValue: string \\| null) => void` | `undefined` | 受控数据更新时触发的回调函数 | `formattedValue` 2.24.0 |\n\n### MonthRange、QuarterRange、YearRange 类型的 Props\n\n| 名称 | 类型 | 默认值 | 说明 | 版本 |\n| --- | --- | --- | --- | --- |\n| actions | `Array<'clear' \\| 'confirm'> \\| null` | `['clear', 'confirm']` | MonthRange 类型的 Date Picker 中支持的用户操作 | 2.28.3 |\n| end-placeholder | `string` | `'结束月份'` | MonthRange 中 end 选框的提示信息 | 2.28.3 |\n| format | `string` | `'yyyy-MM-dd'` | 时间格式化字符串，详情见 [format](https://date-fns.org/v2.23.0/docs/format) | 2.28.3 |\n| close-on-select | `boolean` | `false` | 用户选择时间范围后是否自动关闭面板 | 2.28.3 |\n| separator | `string` | 内置图标 | start 选框与 end 选框之间的分隔符 | 2.28.3 |\n| start-placeholder | `string` | `'开始月份'` | MonthRange 中 start 选框的提示信息 | 2.28.3 |\n| update-value-on-close | `boolean` | `false` | 关闭面板时是否更新值 | 2.28.3 |\n| on-update:formatted-value | `(value: [string, string] \\| null, timestampValue: [number, number] \\| null) => void` | `undefined` | 数据更新时触发的回调函数 | 2.28.3 |\n| on-update:value | `(value: [number, number] \\| null, formattedValue: [string, string] \\| null) => void` | `undefined` | 数据更新时触发的回调函数 | 2.28.3 |\n\n### Year 类型的 Props\n\n| 名称 | 类型 | 默认值 | 说明 | 版本 |\n| --- | --- | --- | --- | --- |\n| actions | `Array<'clear' \\| 'now'> \\| null` | `['clear', 'now']` | Year 类型的 Date Picker 中支持的操作 |  |\n| format | `string` | `'yyyy'` | 时间格式化字符串，详情见 [format](https://date-fns.org/v2.23.0/docs/format) |  |\n| is-date-disabled | `(current: number, detail: { type: 'date', year: number, month: number, date: number } \\| { type: 'month', year: number, month: number } \\| { type: 'year', year: number } \\| { type: 'quarter',  year: number, quarter: number } \\| { type: 'input' }) => boolean` | `undefined` | 年份禁用的校验函数 | `detail` 2.37.1 |\n| placeholder | `string` | `'选择年份'` | 没有值时的占位信息 |  |\n| on-update:formatted-value | `(value: string \\| null, timestampValue: number \\| null) => void` | `undefined` | 受控数据更新时触发的回调函数 | 2.24.0 |\n| on-update:value | `(value: number \\| null, formattedValue: string \\| null) => void` | `undefined` | 受控数据更新时触发的回调函数 | `formattedValue` 2.24.0 |\n\n### Week 类型的 Props\n\n| 名称 | 类型 | 默认值 | 说明 | 版本 |\n| --- | --- | --- | --- | --- |\n| actions | `Array<'clear' \\| 'now'> \\| null` | `['clear', 'now']` | Week 类型的 Date Picker 中支持的操作 | 2.37.0 |\n| default-calendar-start-time | `number` | `undefined` | 面板日历默认开始的月份时间戳 | 2.38.1 |\n| format | `string` | 中文为 `'YYYY-w'`，随语言变化 | 时间格式化字符串，详情见 [format](https://date-fns.org/v2.23.0/docs/format) | 2.37.0 |\n| placeholder | `string` | 中文为 `'选择周'`，随语言变化 | 没有值时的占位信息 | 2.37.0 |\n| on-update:formatted-value | `(value: string \\| null, timestampValue: number \\| null) => void` | `undefined` | 受控数据更新时触发的回调函数 | 2.37.0 |\n| on-update:value | `(value: number \\| null, formattedValue: string \\| null) => void` | `undefined` | 受控数据更新时触发的回调函数 | 2.37.0 |\n\n### DatePicker Slots\n\n| 名称       | 参数 | 说明                         | 版本   |\n| ---------- | ---- | ---------------------------- | ------ |\n| date-icon  | `()` | 日期输入框的图标             | 2.29.0 |\n| footer     | `()` | 添加额外的页脚               |        |\n| next-month | `()` | 日期面板的 `下一个` 图标     | 2.33.4 |\n| next-year  | `()` | 日期面板的 `快速下一个` 图标 | 2.33.4 |\n| prev-month | `()` | 日期面板的 `上一个` 图标     | 2.33.4 |\n| prev-year  | `()` | 日期面板的 `快速上一个` 图标 | 2.33.4 |\n| separator  | `()` | 日期范围分隔符号             | 2.29.0 |\n\n### Date, Year, QuarterRange, Week Slots\n\n| 名称 | 参数 | 说明 | 版本 |\n| --- | --- | --- | --- |\n| clear | `(props: { onClear: () => void, text: string })` | 面板的清除按钮 | 2.40.0 |\n| now | `(props: { onNow: () => void, text: string })` | 面板的此刻按钮 | 2.40.0 |\n\n### DateRange, DateTimeRange, MonthRange, YearRange Slots\n\n| 名称 | 参数 | 说明 | 版本 |\n| --- | --- | --- | --- |\n| clear | `(props: { onClear: () => void, text: string })` | 面板的清除按钮 | 2.40.0 |\n| confirm | `(props: { onConfirm: () => void, disabled: boolean, text: string })` | 面板的确认按钮 | 2.40.0 |\n\n### DateTime, Month, Quarter Slots\n\n| 名称 | 参数 | 说明 | 版本 |\n| --- | --- | --- | --- |\n| clear | `(props: { onClear: () => void, text: string })` | 面板的清除按钮 | 2.40.0 |\n| confirm | `(props: { onConfirm: () => void, disabled: boolean, text: string })` | 面板的确认按钮 | 2.40.0 |\n| now | `(props: { onNow: () => void, text: string })` | 面板的此刻按钮 | 2.40.0 |\n\n### DatePicker Methods\n\n| 名称  | 类型         | 说明 | 版本   |\n| ----- | ------------ | ---- | ------ |\n| focus | `() => void` | 聚焦 | 2.24.2 |\n| blur  | `() => void` | 失焦 | 2.24.2 |\n"
  },
  {
    "path": "src/date-picker/demos/zhCN/month.demo.vue",
    "content": "<markdown>\n# 月份\n\n可以使用 `month-format` 属性指定面板中月份的显示方式。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst timestamp = ref(1183135260000)\n</script>\n\n<template>\n  <n-space vertical>\n    <n-date-picker v-model:value=\"timestamp\" type=\"month\" clearable />\n    <n-date-picker\n      v-model:value=\"timestamp\"\n      type=\"month\"\n      format=\"y年 M月\"\n      year-format=\"y年\"\n      month-format=\"M月\"\n      clearable\n    />\n    <pre>{{ JSON.stringify(timestamp) }}</pre>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/date-picker/demos/zhCN/monthrange.demo.vue",
    "content": "<markdown>\n# 月份范围\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst timestamp = ref<[number, number]>([1183135260000, Date.now()])\n</script>\n\n<template>\n  <n-date-picker v-model:value=\"timestamp\" type=\"monthrange\" clearable />\n  <pre>{{ JSON.stringify(timestamp) }}</pre>\n</template>\n"
  },
  {
    "path": "src/date-picker/demos/zhCN/panel-debug.demo.vue",
    "content": "<markdown>\n# 只使用面板 Debug\n</markdown>\n\n<script lang=\"ts\" setup>\nfunction log(...args: unknown[]) {\n  console.log('value', ...args)\n}\n\nconst rangeShortcuts = {\n  快乐假期: [1629216000000, 1631203200000] as const,\n  近2小时: () => {\n    const cur = new Date().getTime()\n    return [cur - 2 * 60 * 60 * 1000, cur] as const\n  }\n}\n</script>\n\n<template>\n  <n-space vertical>\n    <n-date-picker\n      panel\n      type=\"date\"\n      calendar-day-format=\"（eeeeee）\"\n      calendar-header-month-before-year\n      calendar-header-year-format=\"（yyyy）\"\n      calendar-header-month-format=\"（MM）\"\n      calendar-header-month-year-separator=\"~\"\n      @update:value=\"log\"\n    />\n    <n-date-picker\n      panel\n      type=\"datetime\"\n      calendar-day-format=\"（eeeeee）\"\n      calendar-header-month-before-year\n      calendar-header-year-format=\"（yyyy）\"\n      calendar-header-month-format=\"（MM）\"\n      calendar-header-month-year-separator=\"~\"\n      @update:value=\"log\"\n    />\n    <n-date-picker\n      panel\n      type=\"daterange\"\n      calendar-day-format=\"（eeeeee）\"\n      calendar-header-month-before-year\n      calendar-header-year-format=\"（yyyy）\"\n      calendar-header-month-format=\"（MM）\"\n      calendar-header-month-year-separator=\"~\"\n      @update:value=\"log\"\n    />\n    <n-date-picker\n      panel\n      type=\"datetimerange\"\n      calendar-day-format=\"（eeeeee）\"\n      calendar-header-month-before-year\n      calendar-header-year-format=\"（yyyy）\"\n      calendar-header-month-format=\"（MM）\"\n      calendar-header-month-year-separator=\"~\"\n      :default-time=\"['13:22:11', '16:00:00']\"\n      :shortcuts=\"rangeShortcuts\"\n      @update:value=\"log\"\n    />\n    <n-date-picker panel type=\"month\" @update:value=\"log\" />\n    <n-date-picker panel type=\"quarter\" @update:value=\"log\" />\n    <n-date-picker panel type=\"year\" @update:value=\"log\" />\n    <n-date-picker panel type=\"monthrange\" @update:value=\"log\" />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/date-picker/demos/zhCN/panel.demo.vue",
    "content": "<markdown>\n# 只使用面板\n\n这个功能或许有的时候能管点用，我实在不忍心看大家强行调样式。\n</markdown>\n\n<template>\n  <n-date-picker panel type=\"date\" />\n</template>\n"
  },
  {
    "path": "src/date-picker/demos/zhCN/quarter.demo.vue",
    "content": "<markdown>\n# 季度\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst timestamp = ref(1183135260000)\n</script>\n\n<template>\n  <n-date-picker v-model:value=\"timestamp\" type=\"quarter\" clearable />\n  <pre>{{ JSON.stringify(timestamp) }}</pre>\n</template>\n"
  },
  {
    "path": "src/date-picker/demos/zhCN/quarterrange.demo.vue",
    "content": "<markdown>\n# 季度范围\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst timestamp = ref<[number, number]>([1183135260000, Date.now()])\n</script>\n\n<template>\n  <n-date-picker v-model:value=\"timestamp\" type=\"quarterrange\" clearable />\n  <pre>{{ JSON.stringify(timestamp) }}</pre>\n</template>\n"
  },
  {
    "path": "src/date-picker/demos/zhCN/shortcuts.demo.vue",
    "content": "<markdown>\n# 快捷选项\n\n你可以自定义一些快捷按钮.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst ts1 = ref(null)\nconst ts2 = ref(1183135260000)\nconst range1 = ref(null)\nconst range2 = ref(null)\nconst shortcuts = {\n  亲爱的生日: 1631203200000,\n  派对日: 1629216000000,\n  昨天: () => new Date().getTime() - 24 * 60 * 60 * 1000\n}\nconst rangeShortcuts = {\n  快乐假期: [1629216000000, 1631203200000] as const,\n  近2小时: () => {\n    const cur = new Date().getTime()\n    return [cur - 2 * 60 * 60 * 1000, cur] as const\n  }\n}\n</script>\n\n<template>\n  <n-space vertical>\n    <n-date-picker v-model:value=\"ts1\" type=\"date\" :shortcuts=\"shortcuts\" />\n    <n-date-picker v-model:value=\"ts2\" type=\"datetime\" :shortcuts=\"shortcuts\" />\n    <n-date-picker\n      v-model:value=\"range1\"\n      type=\"daterange\"\n      :shortcuts=\"rangeShortcuts\"\n      :update-value-on-close=\"true\"\n    />\n    <n-date-picker\n      v-model:value=\"range2\"\n      type=\"datetimerange\"\n      :shortcuts=\"rangeShortcuts\"\n    />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/date-picker/demos/zhCN/size.demo.vue",
    "content": "<markdown>\n# 尺寸\n\n有 `small`、`medium` 和 `large` 尺寸。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst timestamp = ref(null)\n</script>\n\n<template>\n  <n-space vertical>\n    <n-date-picker v-model:value=\"timestamp\" size=\"small\" type=\"date\" />\n    <n-date-picker v-model:value=\"timestamp\" size=\"medium\" type=\"date\" />\n    <n-date-picker v-model:value=\"timestamp\" size=\"large\" type=\"date\" />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/date-picker/demos/zhCN/status.demo.vue",
    "content": "<markdown>\n# 验证状态\n\n输入的验证状态可以脱离表单使用。\n</markdown>\n\n<template>\n  <n-space vertical>\n    <n-date-picker status=\"warning\" />\n    <n-date-picker status=\"error\" />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/date-picker/demos/zhCN/update-on-close.demo.vue",
    "content": "<markdown>\n# 关闭时更新值\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst updateValueOnClose = ref(true)\n</script>\n\n<template>\n  <n-space vertical>\n    <n-date-picker\n      type=\"datetime\"\n      :default-value=\"Date.now()\"\n      :update-value-on-close=\"updateValueOnClose\"\n    />\n    <n-date-picker\n      :default-value=\"[Date.now(), Date.now()]\"\n      :update-value-on-close=\"updateValueOnClose\"\n      type=\"daterange\"\n    />\n    <n-date-picker\n      :default-value=\"[Date.now(), Date.now()]\"\n      :update-value-on-close=\"updateValueOnClose\"\n      type=\"datetimerange\"\n    />\n    <n-switch v-model:value=\"updateValueOnClose\" />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/date-picker/demos/zhCN/week.demo.vue",
    "content": "<markdown>\n# 周\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst timestamp = ref(1183135260000)\n</script>\n\n<template>\n  <n-date-picker v-model:value=\"timestamp\" type=\"week\" clearable />\n  <pre>{{ JSON.stringify(timestamp) }}</pre>\n</template>\n"
  },
  {
    "path": "src/date-picker/demos/zhCN/year.demo.vue",
    "content": "<markdown>\n# 年份\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst timestamp = ref(1183135260000)\n</script>\n\n<template>\n  <n-date-picker v-model:value=\"timestamp\" type=\"year\" clearable />\n  <pre>{{ JSON.stringify(timestamp) }}</pre>\n</template>\n"
  },
  {
    "path": "src/date-picker/demos/zhCN/yearrange.demo.vue",
    "content": "<markdown>\n# 年份范围\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst timestamp = ref<[number, number]>([1183135260000, Date.now()])\n</script>\n\n<template>\n  <n-date-picker v-model:value=\"timestamp\" type=\"yearrange\" clearable />\n  <pre>{{ JSON.stringify(timestamp) }}</pre>\n</template>\n"
  },
  {
    "path": "src/date-picker/index.ts",
    "content": "export { default as NDatePicker } from './src/DatePicker'\nexport type { DatePickerSlots } from './src/DatePicker'\nexport { datePickerProps } from './src/props'\nexport type * from './src/public-types'\n"
  },
  {
    "path": "src/date-picker/src/DatePicker.tsx",
    "content": "import type {\n  CSSProperties,\n  ExtractPropTypes,\n  Ref,\n  SlotsType,\n  VNode\n} from 'vue'\nimport type { InputInst, InputProps } from '../../input'\nimport type { TimePickerSize } from '../../time-picker/src/public-types'\nimport type {\n  FormattedValue,\n  OnConfirmImpl,\n  OnUpdateFormattedValueImpl,\n  OnUpdateValueImpl,\n  PanelRef,\n  Value\n} from './interface'\nimport type { UsePanelCommonProps } from './panel/use-panel-common'\nimport type { DatePickerInst, DatePickerSize } from './public-types'\nimport { format, getTime, isValid } from 'date-fns'\nimport { getPreciseEventTarget, happensIn } from 'seemly'\nimport { clickoutside } from 'vdirs'\nimport { useIsMounted, useMergedState } from 'vooks'\nimport {\n  computed,\n  defineComponent,\n  h,\n  provide,\n  ref,\n  toRef,\n  Transition,\n  watch,\n  watchEffect,\n  withDirectives\n} from 'vue'\nimport { VBinder, VFollower, VTarget } from 'vueuc'\nimport { NBaseIcon } from '../../_internal'\nimport { DateIcon, ToIcon } from '../../_internal/icons'\nimport {\n  useConfig,\n  useFormItem,\n  useLocale,\n  useTheme,\n  useThemeClass\n} from '../../_mixins'\nimport {\n  call,\n  createKey,\n  markEventEffectPerformed,\n  resolveSlot,\n  useAdjustedTo,\n  warn,\n  warnOnce\n} from '../../_utils'\nimport { NInput } from '../../input'\nimport { datePickerLight } from '../styles'\nimport { datePickerInjectionKey } from './interface'\nimport DatePanel from './panel/date'\nimport DaterangePanel from './panel/daterange'\nimport DatetimePanel from './panel/datetime'\nimport DatetimerangePanel from './panel/datetimerange'\nimport MonthPanel from './panel/month'\nimport MonthRangePanel from './panel/monthrange'\nimport { datePickerProps } from './props'\nimport style from './styles/index.cssr'\nimport { strictParse } from './utils'\nimport {\n  dualCalendarValidation,\n  uniCalendarValidation\n} from './validation-utils'\n\nexport type DatePickerSetupProps = ExtractPropTypes<typeof datePickerProps>\n\nexport interface DatePickerSlots {\n  'date-icon'?: () => VNode[]\n  footer?: () => VNode[]\n  'next-month'?: () => VNode[]\n  'next-year'?: () => VNode[]\n  'prev-month'?: () => VNode[]\n  'prev-year'?: () => VNode[]\n  separator?: () => VNode[]\n  confirm?: (props: {\n    onConfirm: () => void\n    disabled: boolean\n    text: string\n  }) => VNode[]\n  clear?: (props: { onClear: () => void, text: string }) => VNode[]\n  now?: (props: { onNow: () => void, text: string }) => VNode[]\n}\n\nexport default defineComponent({\n  name: 'DatePicker',\n  props: datePickerProps,\n  slots: Object as SlotsType<DatePickerSlots>,\n  setup(props, { slots }) {\n    if (__DEV__) {\n      watchEffect(() => {\n        if (props.onChange !== undefined) {\n          warnOnce(\n            'date-picker',\n            '`on-change` is deprecated, please use `on-update:value` instead.'\n          )\n        }\n      })\n    }\n    const { localeRef, dateLocaleRef } = useLocale('DatePicker')\n    const {\n      mergedComponentPropsRef,\n      mergedClsPrefixRef,\n      mergedBorderedRef,\n      namespaceRef,\n      inlineThemeDisabled\n    } = useConfig(props)\n    const formItem = useFormItem(props, {\n      mergedSize: (NFormItem) => {\n        const { size } = props\n        if (size)\n          return size\n        const { mergedSize: formItemSize } = NFormItem || {}\n        if (formItemSize?.value)\n          return formItemSize.value as DatePickerSize\n        const configSize = mergedComponentPropsRef?.value?.DatePicker?.size\n        if (configSize)\n          return configSize\n        return 'medium'\n      }\n    })\n    const { mergedSizeRef, mergedDisabledRef, mergedStatusRef } = formItem\n    const panelInstRef = ref<PanelRef | null>(null)\n    const triggerElRef = ref<HTMLElement | null>(null)\n    const inputInstRef = ref<InputInst | null>(null)\n    const uncontrolledShowRef = ref<boolean>(false)\n    const controlledShowRef = toRef(props, 'show')\n    const mergedShowRef = useMergedState(controlledShowRef, uncontrolledShowRef)\n    const dateFnsOptionsRef = computed(() => {\n      return {\n        locale: dateLocaleRef.value.locale,\n        useAdditionalWeekYearTokens: true\n      }\n    })\n\n    const mergedFormatRef = computed(() => {\n      const { format } = props\n      if (format)\n        return format\n      switch (props.type) {\n        case 'date':\n        case 'daterange':\n          return localeRef.value.dateFormat\n        case 'datetime':\n        case 'datetimerange':\n          return localeRef.value.dateTimeFormat\n        case 'year':\n        case 'yearrange':\n          return localeRef.value.yearTypeFormat\n        case 'month':\n        case 'monthrange':\n          return localeRef.value.monthTypeFormat\n        case 'quarter':\n        case 'quarterrange':\n          return localeRef.value.quarterFormat\n        case 'week':\n          return localeRef.value.weekFormat\n      }\n    })\n    const mergedValueFormatRef = computed(() => {\n      return props.valueFormat ?? mergedFormatRef.value\n    })\n\n    function getTimestampValue(value: FormattedValue | null): Value | null {\n      if (value === null)\n        return null\n      const { value: mergedValueFormat } = mergedValueFormatRef\n      const { value: dateFnsOptions } = dateFnsOptionsRef\n      if (Array.isArray(value)) {\n        return [\n          strictParse(\n            value[0],\n            mergedValueFormat,\n            new Date(),\n            dateFnsOptions\n          ).getTime(),\n          strictParse(\n            value[1],\n            mergedValueFormat,\n            new Date(),\n            dateFnsOptions\n          ).getTime()\n        ]\n      }\n      return strictParse(\n        value,\n        mergedValueFormat,\n        new Date(),\n        dateFnsOptions\n      ).getTime()\n    }\n\n    const { defaultFormattedValue, defaultValue } = props\n\n    const uncontrolledValueRef = ref(\n      (defaultFormattedValue !== undefined\n        ? getTimestampValue(defaultFormattedValue)\n        : defaultValue) ?? null\n    )\n    const controlledValueRef = computed(() => {\n      const { formattedValue } = props\n      if (formattedValue !== undefined) {\n        return getTimestampValue(formattedValue)\n      }\n      return props.value\n    })\n    const mergedValueRef = useMergedState(\n      controlledValueRef,\n      uncontrolledValueRef\n    )\n\n    // We don't change value unless blur or confirm is called\n    const pendingValueRef: Ref<Value | null> = ref(null)\n    watchEffect(() => {\n      pendingValueRef.value = mergedValueRef.value\n    })\n    const singleInputValueRef = ref('')\n    const rangeStartInputValueRef = ref('')\n    const rangeEndInputValueRef = ref('')\n    const themeRef = useTheme(\n      'DatePicker',\n      '-date-picker',\n      style,\n      datePickerLight,\n      props,\n      mergedClsPrefixRef\n    )\n    const timePickerSizeRef = computed<TimePickerSize>(() => {\n      return (\n        mergedComponentPropsRef?.value?.DatePicker?.timePickerSize || 'small'\n      )\n    })\n    const isRangeRef = computed(() => {\n      return [\n        'daterange',\n        'datetimerange',\n        'monthrange',\n        'quarterrange',\n        'yearrange'\n      ].includes(props.type)\n    })\n    const localizedPlacehoderRef = computed(() => {\n      const { placeholder } = props\n      if (placeholder === undefined) {\n        const { type } = props\n        switch (type) {\n          case 'date':\n            return localeRef.value.datePlaceholder\n          case 'datetime':\n            return localeRef.value.datetimePlaceholder\n          case 'month':\n            return localeRef.value.monthPlaceholder\n          case 'year':\n            return localeRef.value.yearPlaceholder\n          case 'quarter':\n            return localeRef.value.quarterPlaceholder\n          case 'week':\n            return localeRef.value.weekPlaceholder\n          default:\n            return ''\n        }\n      }\n      else {\n        return placeholder\n      }\n    })\n    const localizedStartPlaceholderRef = computed(() => {\n      if (props.startPlaceholder === undefined) {\n        if (props.type === 'daterange') {\n          return localeRef.value.startDatePlaceholder\n        }\n        else if (props.type === 'datetimerange') {\n          return localeRef.value.startDatetimePlaceholder\n        }\n        else if (props.type === 'monthrange') {\n          return localeRef.value.startMonthPlaceholder\n        }\n        return ''\n      }\n      else {\n        return props.startPlaceholder\n      }\n    })\n    const localizedEndPlaceholderRef = computed(() => {\n      if (props.endPlaceholder === undefined) {\n        if (props.type === 'daterange') {\n          return localeRef.value.endDatePlaceholder\n        }\n        else if (props.type === 'datetimerange') {\n          return localeRef.value.endDatetimePlaceholder\n        }\n        else if (props.type === 'monthrange') {\n          return localeRef.value.endMonthPlaceholder\n        }\n        return ''\n      }\n      else {\n        return props.endPlaceholder\n      }\n    })\n    const mergedActionsRef = computed(() => {\n      const { actions, type, clearable } = props\n      if (actions === null)\n        return []\n      if (actions !== undefined)\n        return actions\n      const result = clearable ? ['clear'] : []\n      switch (type) {\n        case 'date':\n        case 'week': {\n          result.push('now')\n          return result\n        }\n        case 'datetime': {\n          result.push('now', 'confirm')\n          return result\n        }\n        case 'daterange': {\n          result.push('confirm')\n          return result\n        }\n        case 'datetimerange': {\n          result.push('confirm')\n          return result\n        }\n        case 'month': {\n          result.push('now', 'confirm')\n          return result\n        }\n        case 'year': {\n          result.push('now')\n          return result\n        }\n        case 'quarter': {\n          result.push('now', 'confirm')\n          return result\n        }\n        case 'monthrange':\n        case 'yearrange':\n        case 'quarterrange': {\n          result.push('confirm')\n          return result\n        }\n        default: {\n          warn(\n            'date-picker',\n            'The type is wrong, n-date-picker\\'s type only supports `date`, `datetime`, `daterange` and `datetimerange`.'\n          )\n          break\n        }\n      }\n    })\n    function getFormattedValue(value: Value | null): FormattedValue | null {\n      if (value === null)\n        return null\n      if (Array.isArray(value)) {\n        const { value: mergedValueFormat } = mergedValueFormatRef\n        const { value: dateFnsOptions } = dateFnsOptionsRef\n        return [\n          format(value[0], mergedValueFormat, dateFnsOptions),\n          format(value[1], mergedValueFormat, dateFnsOptionsRef.value)\n        ]\n      }\n      else {\n        return format(\n          value,\n          mergedValueFormatRef.value,\n          dateFnsOptionsRef.value\n        )\n      }\n    }\n    function doUpdatePendingValue(value: Value | null): void {\n      pendingValueRef.value = value\n    }\n    function doUpdateFormattedValue(\n      value: FormattedValue | null,\n      timestampValue: Value | null\n    ): void {\n      const {\n        'onUpdate:formattedValue': _onUpdateFormattedValue,\n        onUpdateFormattedValue\n      } = props\n      if (_onUpdateFormattedValue) {\n        call(\n          _onUpdateFormattedValue as OnUpdateFormattedValueImpl,\n          value,\n          timestampValue\n        )\n      }\n      if (onUpdateFormattedValue) {\n        call(\n          onUpdateFormattedValue as OnUpdateFormattedValueImpl,\n          value,\n          timestampValue\n        )\n      }\n    }\n    function doUpdateValue(\n      value: Value | null,\n      options: {\n        doConfirm: boolean\n      }\n    ): void {\n      const {\n        'onUpdate:value': _onUpdateValue,\n        onUpdateValue,\n        onChange\n      } = props\n      const { nTriggerFormChange, nTriggerFormInput } = formItem\n      const formattedValue = getFormattedValue(value)\n      if (options.doConfirm) {\n        doConfirm(value, formattedValue)\n      }\n      if (onUpdateValue) {\n        call(onUpdateValue as OnUpdateValueImpl, value, formattedValue)\n      }\n      if (_onUpdateValue) {\n        call(_onUpdateValue as OnUpdateValueImpl, value, formattedValue)\n      }\n      if (onChange)\n        call(onChange as OnUpdateValueImpl, value, formattedValue)\n      uncontrolledValueRef.value = value\n\n      doUpdateFormattedValue(formattedValue, value)\n\n      nTriggerFormChange()\n      nTriggerFormInput()\n    }\n    function doClear(): void {\n      const { onClear } = props\n      onClear?.()\n    }\n    function doConfirm(\n      value: Value | null,\n      formattedValue: FormattedValue | null\n    ): void {\n      const { onConfirm } = props\n      if (onConfirm)\n        (onConfirm as OnConfirmImpl)(value, formattedValue)\n    }\n    function doFocus(e: FocusEvent): void {\n      const { onFocus } = props\n      const { nTriggerFormFocus } = formItem\n      if (onFocus)\n        call(onFocus, e)\n      nTriggerFormFocus()\n    }\n    function doBlur(e: FocusEvent): void {\n      const { onBlur } = props\n      const { nTriggerFormBlur } = formItem\n      if (onBlur)\n        call(onBlur, e)\n      nTriggerFormBlur()\n    }\n    function doUpdateShow(show: boolean): void {\n      const { 'onUpdate:show': _onUpdateShow, onUpdateShow } = props\n      if (_onUpdateShow)\n        call(_onUpdateShow, show)\n      if (onUpdateShow)\n        call(onUpdateShow, show)\n      uncontrolledShowRef.value = show\n    }\n    function handleKeydown(e: KeyboardEvent): void {\n      if (e.key === 'Escape') {\n        if (mergedShowRef.value) {\n          markEventEffectPerformed(e)\n          closeCalendar({\n            returnFocus: true\n          })\n        }\n      }\n      // We need to handle the conflict with normal date value input\n      // const { value: mergedValue } = mergedValueRef\n      // if (props.type === 'date' && !Array.isArray(mergedValue)) {\n      //   const nextValue = getDerivedTimeFromKeyboardEvent(mergedValue, e)\n      //   doUpdateValue(nextValue)\n      // }\n    }\n    function handleInputKeydown(e: KeyboardEvent): void {\n      if (e.key === 'Escape' && mergedShowRef.value) {\n        markEventEffectPerformed(e)\n        // closeCalendar will be called in handleDeactivated\n      }\n    }\n    function handleClear(): void {\n      doUpdateShow(false)\n      inputInstRef.value?.deactivate()\n      doClear()\n    }\n    function handlePanelClear(): void {\n      // close will be called inside panel\n      inputInstRef.value?.deactivate()\n      doClear()\n    }\n    function handlePanelTabOut(): void {\n      closeCalendar({\n        returnFocus: true\n      })\n    }\n    function handleClickOutside(e: MouseEvent): void {\n      if (\n        mergedShowRef.value\n        && !triggerElRef.value?.contains(getPreciseEventTarget(e) as Node | null)\n      ) {\n        closeCalendar({\n          returnFocus: false\n        })\n      }\n    }\n    function handlePanelClose(disableUpdateOnClose: boolean): void {\n      closeCalendar({\n        returnFocus: true,\n        disableUpdateOnClose\n      })\n    }\n\n    // --- Panel update value\n    function handlePanelUpdateValue(\n      value: Value | null,\n      doUpdate: boolean\n    ): void {\n      if (doUpdate) {\n        doUpdateValue(value, { doConfirm: false })\n      }\n      else {\n        doUpdatePendingValue(value)\n      }\n    }\n    function handlePanelConfirm(): void {\n      const pendingValue = pendingValueRef.value\n      doUpdateValue(\n        Array.isArray(pendingValue)\n          ? [pendingValue[0], pendingValue[1]]\n          : pendingValue,\n        { doConfirm: true }\n      )\n    }\n    // --- Refresh\n    function deriveInputState(): void {\n      const { value } = pendingValueRef\n      if (isRangeRef.value) {\n        if (Array.isArray(value) || value === null) {\n          deriveRangeInputState(value)\n        }\n      }\n      else {\n        if (!Array.isArray(value)) {\n          deriveSingleInputState(value)\n        }\n      }\n    }\n    function deriveSingleInputState(value: number | null): void {\n      if (value === null) {\n        singleInputValueRef.value = ''\n      }\n      else {\n        singleInputValueRef.value = format(\n          value,\n          mergedFormatRef.value,\n          dateFnsOptionsRef.value\n        )\n      }\n    }\n    function deriveRangeInputState(values: [number, number] | null): void {\n      if (values === null) {\n        rangeStartInputValueRef.value = ''\n        rangeEndInputValueRef.value = ''\n      }\n      else {\n        const dateFnsOptions = dateFnsOptionsRef.value\n        rangeStartInputValueRef.value = format(\n          values[0],\n          mergedFormatRef.value,\n          dateFnsOptions\n        )\n        rangeEndInputValueRef.value = format(\n          values[1],\n          mergedFormatRef.value,\n          dateFnsOptions\n        )\n      }\n    }\n    // --- Input deactivate & blur\n    function handleInputActivate(): void {\n      if (!mergedShowRef.value) {\n        openCalendar()\n      }\n    }\n    function handleInputBlur(e: FocusEvent): void {\n      if (!panelInstRef.value?.$el.contains(e.relatedTarget as Node)) {\n        doBlur(e)\n        deriveInputState()\n        closeCalendar({\n          returnFocus: false\n        })\n      }\n    }\n    function handleInputDeactivate(): void {\n      if (mergedDisabledRef.value)\n        return\n      deriveInputState()\n      closeCalendar({\n        returnFocus: false\n      })\n    }\n    // --- Input\n    function handleSingleUpdateValue(v: string): void {\n      // TODO, fix conflict with clear\n      if (v === '') {\n        doUpdateValue(null, { doConfirm: false })\n        pendingValueRef.value = null\n        singleInputValueRef.value = ''\n        return\n      }\n      const newSelectedDateTime = strictParse(\n        v,\n        mergedFormatRef.value,\n        new Date(),\n        dateFnsOptionsRef.value\n      )\n      if (isValid(newSelectedDateTime)) {\n        doUpdateValue(getTime(newSelectedDateTime), { doConfirm: false })\n        deriveInputState()\n      }\n      else {\n        singleInputValueRef.value = v\n      }\n    }\n    function handleRangeUpdateValue(\n      v: [string, string],\n      { source }: { source: 0 | 1 | 'clear' }\n    ): void {\n      if (v[0] === '' && v[1] === '') {\n        // clear or just delete all the inputs\n        doUpdateValue(null, { doConfirm: false })\n        pendingValueRef.value = null\n        rangeStartInputValueRef.value = ''\n        rangeEndInputValueRef.value = ''\n        return\n      }\n      const [startTime, endTime] = v\n      const newStartTime = strictParse(\n        startTime,\n        mergedFormatRef.value,\n        new Date(),\n        dateFnsOptionsRef.value\n      )\n      const newEndTime = strictParse(\n        endTime,\n        mergedFormatRef.value,\n        new Date(),\n        dateFnsOptionsRef.value\n      )\n      if (isValid(newStartTime) && isValid(newEndTime)) {\n        let newStartTs = getTime(newStartTime)\n        let newEndTs = getTime(newEndTime)\n        if (newEndTime < newStartTime) {\n          if (source === 0) {\n            newEndTs = newStartTs\n          }\n          else {\n            newStartTs = newEndTs\n          }\n        }\n        doUpdateValue([newStartTs, newEndTs], {\n          doConfirm: false\n        })\n        deriveInputState()\n      }\n      else {\n        ;[rangeStartInputValueRef.value, rangeEndInputValueRef.value] = v\n      }\n    }\n    // --- Click\n    function handleTriggerClick(e: MouseEvent): void {\n      if (mergedDisabledRef.value)\n        return\n      if (happensIn(e, 'clear'))\n        return\n      if (!mergedShowRef.value) {\n        openCalendar()\n      }\n    }\n    // --- Focus\n    function handleInputFocus(e: FocusEvent): void {\n      if (mergedDisabledRef.value)\n        return\n      doFocus(e)\n    }\n    // --- Calendar\n    function openCalendar(): void {\n      if (mergedDisabledRef.value || mergedShowRef.value)\n        return\n      doUpdateShow(true)\n    }\n    function closeCalendar({\n      returnFocus,\n      disableUpdateOnClose\n    }: {\n      returnFocus: boolean\n      disableUpdateOnClose?: boolean\n    }): void {\n      if (mergedShowRef.value) {\n        doUpdateShow(false)\n        if (\n          props.type !== 'date'\n          && props.updateValueOnClose\n          && !disableUpdateOnClose\n        ) {\n          handlePanelConfirm()\n        }\n        if (returnFocus) {\n          inputInstRef.value?.focus()\n        }\n      }\n    }\n    // If new value is valid, set calendarTime and refresh display strings.\n    // If new value is invalid, do nothing.\n    watch(pendingValueRef, () => {\n      deriveInputState()\n    })\n    // init\n    deriveInputState()\n\n    watch(mergedShowRef, (value) => {\n      if (!value) {\n        // close & restore original value\n        // it won't conflict with props.value change\n        // since when prop is passed, it is already\n        // up to date.\n        pendingValueRef.value = mergedValueRef.value\n      }\n    })\n\n    // use pending value to do validation\n    const uniVaidation = uniCalendarValidation(props, pendingValueRef)\n    const dualValidation = dualCalendarValidation(props, pendingValueRef)\n    provide(datePickerInjectionKey, {\n      mergedClsPrefixRef,\n      mergedThemeRef: themeRef,\n      timePickerSizeRef,\n      localeRef,\n      dateLocaleRef,\n      firstDayOfWeekRef: toRef(props, 'firstDayOfWeek'),\n      isDateDisabledRef: toRef(props, 'isDateDisabled'),\n      rangesRef: toRef(props, 'ranges'),\n      timePickerPropsRef: toRef(props, 'timePickerProps'),\n      closeOnSelectRef: toRef(props, 'closeOnSelect'),\n      updateValueOnCloseRef: toRef(props, 'updateValueOnClose'),\n      monthFormatRef: toRef(props, 'monthFormat'),\n      yearFormatRef: toRef(props, 'yearFormat'),\n      quarterFormatRef: toRef(props, 'quarterFormat'),\n      yearRangeRef: toRef(props, 'yearRange'),\n      ...uniVaidation,\n      ...dualValidation,\n      datePickerSlots: slots\n    })\n\n    const exposedMethods: DatePickerInst = {\n      focus: () => {\n        inputInstRef.value?.focus()\n      },\n      blur: () => {\n        inputInstRef.value?.blur()\n      }\n    }\n\n    const triggerCssVarsRef = computed(() => {\n      const {\n        common: { cubicBezierEaseInOut },\n        self: { iconColor, iconColorDisabled }\n      } = themeRef.value\n      return {\n        '--n-bezier': cubicBezierEaseInOut,\n        '--n-icon-color-override': iconColor,\n        '--n-icon-color-disabled-override': iconColorDisabled\n      }\n    })\n    const triggerThemeClassHandle = inlineThemeDisabled\n      ? useThemeClass(\n          'date-picker-trigger',\n          undefined,\n          triggerCssVarsRef,\n          props\n        )\n      : undefined\n\n    const cssVarsRef = computed(() => {\n      const { type } = props\n      const {\n        common: { cubicBezierEaseInOut },\n        self: {\n          calendarTitleFontSize,\n          calendarDaysFontSize,\n          itemFontSize,\n          itemTextColor,\n          itemColorDisabled,\n          itemColorIncluded,\n          itemColorHover,\n          itemColorActive,\n          itemBorderRadius,\n          itemTextColorDisabled,\n          itemTextColorActive,\n          panelColor,\n          panelTextColor,\n          arrowColor,\n          calendarTitleTextColor,\n          panelActionDividerColor,\n          panelHeaderDividerColor,\n          calendarDaysDividerColor,\n          panelBoxShadow,\n          panelBorderRadius,\n          calendarTitleFontWeight,\n          panelExtraFooterPadding,\n          panelActionPadding,\n          itemSize,\n          itemCellWidth,\n          itemCellHeight,\n          scrollItemWidth,\n          scrollItemHeight,\n          calendarTitlePadding,\n          calendarTitleHeight,\n          calendarDaysHeight,\n          calendarDaysTextColor,\n          arrowSize,\n          panelHeaderPadding,\n          calendarDividerColor,\n          calendarTitleGridTempateColumns,\n          iconColor,\n          iconColorDisabled,\n          scrollItemBorderRadius,\n          calendarTitleColorHover,\n          [createKey('calendarLeftPadding', type)]: calendarLeftPadding,\n          [createKey('calendarRightPadding', type)]: calendarRightPadding\n        }\n      } = themeRef.value\n      return {\n        '--n-bezier': cubicBezierEaseInOut,\n\n        '--n-panel-border-radius': panelBorderRadius,\n        '--n-panel-color': panelColor,\n        '--n-panel-box-shadow': panelBoxShadow,\n        '--n-panel-text-color': panelTextColor,\n\n        // panel header\n        '--n-panel-header-padding': panelHeaderPadding,\n        '--n-panel-header-divider-color': panelHeaderDividerColor,\n\n        // panel calendar\n        '--n-calendar-left-padding': calendarLeftPadding,\n        '--n-calendar-right-padding': calendarRightPadding,\n        '--n-calendar-title-color-hover': calendarTitleColorHover,\n        '--n-calendar-title-height': calendarTitleHeight,\n        '--n-calendar-title-padding': calendarTitlePadding,\n        '--n-calendar-title-font-size': calendarTitleFontSize,\n        '--n-calendar-title-font-weight': calendarTitleFontWeight,\n        '--n-calendar-title-text-color': calendarTitleTextColor,\n        '--n-calendar-title-grid-template-columns':\n          calendarTitleGridTempateColumns,\n        '--n-calendar-days-height': calendarDaysHeight,\n        '--n-calendar-days-divider-color': calendarDaysDividerColor,\n        '--n-calendar-days-font-size': calendarDaysFontSize,\n        '--n-calendar-days-text-color': calendarDaysTextColor,\n        '--n-calendar-divider-color': calendarDividerColor,\n\n        // panel action\n        '--n-panel-action-padding': panelActionPadding,\n        '--n-panel-extra-footer-padding': panelExtraFooterPadding,\n        '--n-panel-action-divider-color': panelActionDividerColor,\n\n        // panel item\n        '--n-item-font-size': itemFontSize,\n        '--n-item-border-radius': itemBorderRadius,\n        '--n-item-size': itemSize,\n        '--n-item-cell-width': itemCellWidth,\n        '--n-item-cell-height': itemCellHeight,\n        '--n-item-text-color': itemTextColor,\n        '--n-item-color-included': itemColorIncluded,\n        '--n-item-color-disabled': itemColorDisabled,\n        '--n-item-color-hover': itemColorHover,\n        '--n-item-color-active': itemColorActive,\n        '--n-item-text-color-disabled': itemTextColorDisabled,\n        '--n-item-text-color-active': itemTextColorActive,\n\n        // scroll item\n        '--n-scroll-item-width': scrollItemWidth,\n        '--n-scroll-item-height': scrollItemHeight,\n        '--n-scroll-item-border-radius': scrollItemBorderRadius,\n\n        // panel arrow\n        '--n-arrow-size': arrowSize,\n        '--n-arrow-color': arrowColor,\n\n        // icon in trigger\n        '--n-icon-color': iconColor,\n        '--n-icon-color-disabled': iconColorDisabled\n      }\n    })\n    const themeClassHandle = inlineThemeDisabled\n      ? useThemeClass(\n          'date-picker',\n          computed(() => {\n            return props.type\n          }),\n          cssVarsRef,\n          props\n        )\n      : undefined\n\n    return {\n      ...exposedMethods,\n      mergedStatus: mergedStatusRef,\n      mergedClsPrefix: mergedClsPrefixRef,\n      mergedBordered: mergedBorderedRef,\n      namespace: namespaceRef,\n      uncontrolledValue: uncontrolledValueRef,\n      pendingValue: pendingValueRef,\n      panelInstRef,\n      triggerElRef,\n      inputInstRef,\n      isMounted: useIsMounted(),\n      displayTime: singleInputValueRef,\n      displayStartTime: rangeStartInputValueRef,\n      displayEndTime: rangeEndInputValueRef,\n      mergedShow: mergedShowRef,\n      adjustedTo: useAdjustedTo(props),\n      isRange: isRangeRef,\n      localizedStartPlaceholder: localizedStartPlaceholderRef,\n      localizedEndPlaceholder: localizedEndPlaceholderRef,\n      mergedSize: mergedSizeRef,\n      mergedDisabled: mergedDisabledRef,\n      localizedPlacehoder: localizedPlacehoderRef,\n      isValueInvalid: uniVaidation.isValueInvalidRef,\n      isStartValueInvalid: dualValidation.isStartValueInvalidRef,\n      isEndValueInvalid: dualValidation.isEndValueInvalidRef,\n      handleInputKeydown,\n      handleClickOutside,\n      handleKeydown,\n      handleClear,\n      handlePanelClear,\n      handleTriggerClick,\n      handleInputActivate,\n      handleInputDeactivate,\n      handleInputFocus,\n      handleInputBlur,\n      handlePanelTabOut,\n      handlePanelClose,\n      handleRangeUpdateValue,\n      handleSingleUpdateValue,\n      handlePanelUpdateValue,\n      handlePanelConfirm,\n      mergedTheme: themeRef,\n      actions: mergedActionsRef,\n      triggerCssVars: inlineThemeDisabled ? undefined : triggerCssVarsRef,\n      triggerThemeClass: triggerThemeClassHandle?.themeClass,\n      triggerOnRender: triggerThemeClassHandle?.onRender,\n      cssVars: inlineThemeDisabled ? undefined : cssVarsRef,\n      themeClass: themeClassHandle?.themeClass,\n      onRender: themeClassHandle?.onRender,\n      onNextMonth: props.onNextMonth,\n      onPrevMonth: props.onPrevMonth,\n      onNextYear: props.onNextYear,\n      onPrevYear: props.onPrevYear\n    }\n  },\n  render() {\n    const { clearable, triggerOnRender, mergedClsPrefix, $slots } = this\n    const commonPanelProps: UsePanelCommonProps & {\n      ref: string\n      style: CSSProperties\n    } = {\n      onUpdateValue: this.handlePanelUpdateValue,\n      onTabOut: this.handlePanelTabOut,\n      onClose: this.handlePanelClose,\n      onClear: this.handlePanelClear,\n      onKeydown: this.handleKeydown,\n      onConfirm: this.handlePanelConfirm,\n      ref: 'panelInstRef',\n      value: this.pendingValue,\n      active: this.mergedShow,\n      actions: this.actions,\n      shortcuts: this.shortcuts,\n      style: this.cssVars as CSSProperties,\n      defaultTime: this.defaultTime,\n      themeClass: this.themeClass,\n      panel: this.panel,\n      inputReadonly: this.inputReadonly || this.mergedDisabled,\n      onRender: this.onRender,\n      onNextMonth: this.onNextMonth,\n      onPrevMonth: this.onPrevMonth,\n      onNextYear: this.onNextYear,\n      onPrevYear: this.onPrevYear,\n      timePickerFormat: this.timePickerFormat,\n      dateFormat: this.dateFormat,\n      fastYearSelect: this.fastYearSelect,\n      fastMonthSelect: this.fastMonthSelect,\n      calendarDayFormat: this.calendarDayFormat,\n      calendarHeaderYearFormat: this.calendarHeaderYearFormat,\n      calendarHeaderMonthFormat: this.calendarHeaderMonthFormat,\n      calendarHeaderMonthYearSeparator: this.calendarHeaderMonthYearSeparator,\n      calendarHeaderMonthBeforeYear: this.calendarHeaderMonthBeforeYear\n    }\n    const renderPanel = (): VNode => {\n      const { type } = this\n      return type === 'datetime' ? (\n        <DatetimePanel\n          {...commonPanelProps}\n          defaultCalendarStartTime={this.defaultCalendarStartTime}\n        >\n          {$slots}\n        </DatetimePanel>\n      ) : type === 'daterange' ? (\n        <DaterangePanel\n          {...commonPanelProps}\n          defaultCalendarStartTime={this.defaultCalendarStartTime}\n          defaultCalendarEndTime={this.defaultCalendarEndTime}\n          bindCalendarMonths={this.bindCalendarMonths}\n        >\n          {$slots}\n        </DaterangePanel>\n      ) : type === 'datetimerange' ? (\n        <DatetimerangePanel\n          {...commonPanelProps}\n          defaultCalendarStartTime={this.defaultCalendarStartTime}\n          defaultCalendarEndTime={this.defaultCalendarEndTime}\n          bindCalendarMonths={this.bindCalendarMonths}\n        >\n          {$slots}\n        </DatetimerangePanel>\n      ) : type === 'month' || type === 'year' || type === 'quarter' ? (\n        <MonthPanel {...commonPanelProps} type={type} key={type} />\n      ) : type === 'monthrange'\n        || type === 'yearrange'\n        || type === 'quarterrange' ? (\n            <MonthRangePanel {...commonPanelProps} type={type} />\n          ) : (\n            <DatePanel\n              {...commonPanelProps}\n              type={type}\n              defaultCalendarStartTime={this.defaultCalendarStartTime}\n            >\n              {$slots}\n            </DatePanel>\n          )\n    }\n    if (this.panel) {\n      return renderPanel()\n    }\n    triggerOnRender?.()\n    const commonInputProps: InputProps = {\n      bordered: this.mergedBordered,\n      size: this.mergedSize,\n      passivelyActivated: true,\n      disabled: this.mergedDisabled,\n      readonly: this.inputReadonly || this.mergedDisabled,\n      clearable,\n      onClear: this.handleClear,\n      onClick: this.handleTriggerClick,\n      onKeydown: this.handleInputKeydown,\n      onActivate: this.handleInputActivate,\n      onDeactivate: this.handleInputDeactivate,\n      onFocus: this.handleInputFocus,\n      onBlur: this.handleInputBlur\n    }\n    return (\n      <div\n        ref=\"triggerElRef\"\n        class={[\n          `${mergedClsPrefix}-date-picker`,\n          this.mergedDisabled && `${mergedClsPrefix}-date-picker--disabled`,\n          this.isRange && `${mergedClsPrefix}-date-picker--range`,\n          this.triggerThemeClass\n        ]}\n        style={this.triggerCssVars as CSSProperties}\n        onKeydown={this.handleKeydown}\n      >\n        <VBinder>\n          {{\n            default: () => [\n              <VTarget>\n                {{\n                  default: () =>\n                    this.isRange ? (\n                      <NInput\n                        ref=\"inputInstRef\"\n                        status={this.mergedStatus}\n                        value={[this.displayStartTime, this.displayEndTime]}\n                        placeholder={[\n                          this.localizedStartPlaceholder,\n                          this.localizedEndPlaceholder\n                        ]}\n                        textDecoration={[\n                          this.isStartValueInvalid ? 'line-through' : '',\n                          this.isEndValueInvalid ? 'line-through' : ''\n                        ]}\n                        pair\n                        onUpdateValue={this.handleRangeUpdateValue}\n                        theme={this.mergedTheme.peers.Input}\n                        themeOverrides={this.mergedTheme.peerOverrides.Input}\n                        internalForceFocus={this.mergedShow}\n                        internalDeactivateOnEnter\n                        {...commonInputProps}\n                      >\n                        {{\n                          separator: () =>\n                            this.separator === undefined\n                              ? resolveSlot($slots.separator, () => [\n                                  <NBaseIcon\n                                    clsPrefix={mergedClsPrefix}\n                                    class={`${mergedClsPrefix}-date-picker-icon`}\n                                  >\n                                    {{\n                                      default: () => <ToIcon />\n                                    }}\n                                  </NBaseIcon>\n                                ])\n                              : this.separator,\n                          [clearable ? 'clear-icon-placeholder' : 'suffix']:\n                            () =>\n                              resolveSlot($slots['date-icon'], () => [\n                                <NBaseIcon\n                                  clsPrefix={mergedClsPrefix}\n                                  class={`${mergedClsPrefix}-date-picker-icon`}\n                                >\n                                  {{\n                                    default: () => <DateIcon />\n                                  }}\n                                </NBaseIcon>\n                              ])\n                        }}\n                      </NInput>\n                    ) : (\n                      <NInput\n                        ref=\"inputInstRef\"\n                        status={this.mergedStatus}\n                        value={this.displayTime}\n                        placeholder={this.localizedPlacehoder}\n                        textDecoration={\n                          this.isValueInvalid && !this.isRange\n                            ? 'line-through'\n                            : ''\n                        }\n                        onUpdateValue={this.handleSingleUpdateValue}\n                        theme={this.mergedTheme.peers.Input}\n                        themeOverrides={this.mergedTheme.peerOverrides.Input}\n                        internalForceFocus={this.mergedShow}\n                        internalDeactivateOnEnter\n                        {...commonInputProps}\n                      >\n                        {{\n                          [clearable ? 'clear-icon-placeholder' : 'suffix']:\n                            () => (\n                              <NBaseIcon\n                                clsPrefix={mergedClsPrefix}\n                                class={`${mergedClsPrefix}-date-picker-icon`}\n                              >\n                                {{\n                                  default: () =>\n                                    resolveSlot($slots['date-icon'], () => [\n                                      <DateIcon />\n                                    ])\n                                }}\n                              </NBaseIcon>\n                            )\n                        }}\n                      </NInput>\n                    )\n                }}\n              </VTarget>,\n              <VFollower\n                show={this.mergedShow}\n                containerClass={this.namespace}\n                to={this.adjustedTo}\n                teleportDisabled={this.adjustedTo === useAdjustedTo.tdkey}\n                placement={this.placement}\n              >\n                {{\n                  default: () => (\n                    <Transition\n                      name=\"fade-in-scale-up-transition\"\n                      appear={this.isMounted}\n                    >\n                      {{\n                        default: () => {\n                          if (!this.mergedShow)\n                            return null\n                          return withDirectives(renderPanel(), [\n                            [\n                              clickoutside,\n                              this.handleClickOutside,\n                              undefined as unknown as string,\n                              { capture: true }\n                            ]\n                          ])\n                        }\n                      }}\n                    </Transition>\n                  )\n                }}\n              </VFollower>\n            ]\n          }}\n        </VBinder>\n      </div>\n    )\n  }\n})\n"
  },
  {
    "path": "src/date-picker/src/config.ts",
    "content": "// TODO: we need to remove it to make height customizable\nexport const MONTH_ITEM_HEIGHT = 40\n\nexport type DatePickerType\n  = | 'date'\n    | 'datetime'\n    | 'daterange'\n    | 'datetimerange'\n    | 'month'\n    | 'year'\n    | 'quarter'\n    | 'monthrange'\n    | 'quarterrange'\n    | 'yearrange'\n    | 'week'\n"
  },
  {
    "path": "src/date-picker/src/interface.ts",
    "content": "import type { Ref, UnwrapNestedRefs } from 'vue'\nimport type { VirtualListInst } from 'vueuc'\nimport type { ScrollbarInst } from '../../_internal'\nimport type { MergedTheme } from '../../_mixins'\nimport type { ButtonProps } from '../../button'\nimport type { NDateLocale, NLocale } from '../../locales'\nimport type {\n  IsHourDisabled,\n  IsMinuteDisabled,\n  IsSecondDisabled\n} from '../../time-picker/src/interface'\nimport type { TimePickerProps } from '../../time-picker/src/TimePicker'\nimport type { DatePickerTheme } from '../styles/light'\nimport type { DatePickerSlots } from './DatePicker'\nimport type {\n  dualCalendarValidation,\n  uniCalendarValidation\n} from './validation-utils'\nimport { createInjectionKey } from '../../_utils'\n\nexport type Value = number | [number, number]\n\nexport type DefaultTime\n  = | string\n    | [string | undefined, string | undefined]\n    | DatePickerGetDefaultTime\n    | DatePickerGetRangeDefaultTime\n\nexport type FormattedValue = string | [string, string]\n\nexport type NowButtonProps = Pick<ButtonProps, 'size' | 'onClick'>\n\nexport type ClearButtonProps = Pick<ButtonProps, 'size' | 'onClick'>\n\nexport type ConfirmButtonProps = Pick<\n  ButtonProps,\n  'size' | 'onClick' | 'type' | 'disabled'\n>\n\nexport type Shortcuts\n  = | Record<string, number | (() => number)>\n    | Record<\n      string,\n      | [number, number]\n      | readonly [number, number]\n      | (() => [number, number] | readonly [number, number])\n    >\n\nexport type OnUpdateValue = (\n  value: number\n    & (number | null)\n    & [number, number]\n    & ([number, number] | null),\n  formattedValue: string\n    & (string | null)\n    & [string, string]\n    & ([string, string] | null)\n) => void\n\nexport type OnConfirm = OnUpdateValue\n\nexport type OnConfirmImpl = OnUpdateValueImpl\n\nexport type OnUpdateFormattedValue = (\n  value: string\n    & (string | null)\n    & [string, string]\n    & ([string, string] | null),\n  timestampValue: number\n    & (number | null)\n    & [number, number]\n    & ([number, number] | null)\n) => void\n\nexport type OnUpdateFormattedValueImpl = (\n  value: string | [string, string] | null,\n  timestampValue: number | [number, number] | null\n) => void\n\nexport type OnUpdateValueImpl = (\n  value: Value | null,\n  formattedValue: string | [string, string] | null\n) => void\n\nexport type OnPanelUpdateValue = (\n  value: number\n    & (number | null)\n    & [number, number]\n    & ([number, number] | null),\n  doUpdate: boolean\n) => void\n\nexport type OnPanelUpdateValueImpl = (\n  value: Value | null,\n  doUpdate: boolean\n) => void\n\nexport type OnClose = (disableUpdateOnClose: boolean) => void\n\nexport interface RangePanelChildComponentRefs {\n  startYearScrollbarRef: Ref<ScrollbarInst | null>\n  endYearScrollbarRef: Ref<ScrollbarInst | null>\n  startMonthScrollbarRef: Ref<ScrollbarInst | null>\n  endMonthScrollbarRef: Ref<ScrollbarInst | null>\n  startYearVlRef: Ref<VirtualListInst | null>\n  endYearVlRef: Ref<VirtualListInst | null>\n}\n\nexport interface PanelChildComponentRefs {\n  monthScrollbarRef: Ref<ScrollbarInst | null> // Only exists when type is month\n  yearScrollbarRef: Ref<ScrollbarInst | null>\n  // year, virtual scroll\n  yearVlRef: Ref<VirtualListInst | null>\n}\n\nexport interface PanelRef\n  extends Partial<\n    UnwrapNestedRefs<PanelChildComponentRefs & RangePanelChildComponentRefs>\n  > {\n  $el: HTMLElement\n}\n\n// 0 is Monday\nexport type FirstDayOfWeek = 0 | 1 | 2 | 3 | 4 | 5 | 6\n\nexport type DatePickerInjection = {\n  mergedClsPrefixRef: Ref<string>\n  mergedThemeRef: Ref<MergedTheme<DatePickerTheme>>\n  timePickerSizeRef: Ref<'small' | 'medium' | 'large'>\n  timePickerPropsRef: Ref<\n    undefined | TimePickerProps | [TimePickerProps, TimePickerProps]\n  >\n  localeRef: Ref<NLocale['DatePicker']>\n  dateLocaleRef: Ref<NDateLocale>\n  isDateDisabledRef: Ref<IsDateDisabled | undefined>\n  rangesRef: Ref<Record<string, [number, number]> | undefined>\n  closeOnSelectRef: Ref<boolean>\n  updateValueOnCloseRef: Ref<boolean>\n  firstDayOfWeekRef: Ref<FirstDayOfWeek | undefined>\n  monthFormatRef: Ref<string>\n  yearFormatRef: Ref<string>\n  quarterFormatRef: Ref<string>\n  datePickerSlots: DatePickerSlots\n  yearRangeRef: Ref<[number, number]>\n} & ReturnType<typeof uniCalendarValidation>\n& ReturnType<typeof dualCalendarValidation>\n\nexport const datePickerInjectionKey\n  = createInjectionKey<DatePickerInjection>('n-date-picker')\n\nexport type IsDateDisabled = IsSingleDateDisabled | IsRangeDateDisabled\n\nexport type IsSingleDateDisabledDetail\n  = | {\n    type: 'date'\n    year: number\n    month: number\n    date: number\n  }\n  | {\n    type: 'month'\n    year: number\n    month: number\n  }\n  | {\n    type: 'year'\n    year: number\n  }\n  | {\n    type: 'quarter'\n    year: number\n    quarter: number\n  }\n  | {\n    type: 'input'\n  }\n\nexport type IsSingleDateDisabled = (\n  timestamp: number,\n  detail: IsSingleDateDisabledDetail\n) => boolean\nexport type IsRangeDateDisabled = (\n  timestamp: number,\n  position: 'start' | 'end',\n  value: [number, number] | null\n) => boolean\n\nexport interface TimeValidator {\n  isHourDisabled?: IsHourDisabled\n  isMinuteDisabled?: IsMinuteDisabled\n  isSecondDisabled?: IsSecondDisabled\n}\n\nexport type IsTimeDisabled = IsSingleTimeDisabled | IsRangeTimeDisabled\nexport type IsSingleTimeDisabled = (date: number) => TimeValidator\nexport type IsRangeTimeDisabled = (\n  date: number,\n  position: 'start' | 'end',\n  value: [number, number] // date must exist to have time validation\n) => TimeValidator\n\nexport type DatePickerGetDefaultTime = (timestamp: number) => string\nexport type DatePickerGetRangeDefaultTime = (\n  timestamp: number,\n  position: 'start' | 'end',\n  value: [number, number] | null\n) => string\n"
  },
  {
    "path": "src/date-picker/src/panel/date.tsx",
    "content": "import type { PropType } from 'vue'\nimport type {\n  DatePickerClearSlotProps,\n  DatePickerNowSlotProps\n} from '../public-types'\nimport { defineComponent, h, watchEffect } from 'vue'\nimport { NBaseFocusDetector } from '../../../_internal'\nimport {\n  BackwardIcon,\n  FastBackwardIcon,\n  FastForwardIcon,\n  ForwardIcon\n} from '../../../_internal/icons'\nimport {\n  resolveSlot,\n  resolveSlotWithTypedProps,\n  warnOnce\n} from '../../../_utils'\nimport { NButton, NxButton } from '../../../button'\nimport PanelHeader from './panelHeader'\nimport { useCalendar, useCalendarProps } from './use-calendar'\n\n/**\n * Date Panel\n * Update picker value on:\n * 1. item click\n * 2. clear click\n */\nexport default defineComponent({\n  name: 'DatePanel',\n  props: {\n    ...useCalendarProps,\n    type: {\n      type: String as PropType<'date' | 'week'>,\n      required: true\n    }\n  },\n  setup(props) {\n    if (__DEV__) {\n      watchEffect(() => {\n        if (props.actions?.includes('confirm')) {\n          warnOnce(\n            'date-picker',\n            'The `confirm` action is not supported for n-date-picker of `date` type'\n          )\n        }\n      })\n    }\n    return useCalendar(props, props.type)\n  },\n  render() {\n    const {\n      mergedClsPrefix,\n      mergedTheme,\n      shortcuts,\n      onRender,\n      datePickerSlots,\n      type\n    } = this\n    onRender?.()\n    return (\n      <div\n        ref=\"selfRef\"\n        tabindex={0}\n        class={[\n          `${mergedClsPrefix}-date-panel`,\n          `${mergedClsPrefix}-date-panel--${type}`,\n          !this.panel && `${mergedClsPrefix}-date-panel--shadow`,\n          this.themeClass\n        ]}\n        onFocus={this.handlePanelFocus}\n        onKeydown={this.handlePanelKeyDown}\n      >\n        <div class={`${mergedClsPrefix}-date-panel-calendar`}>\n          <div class={`${mergedClsPrefix}-date-panel-month`}>\n            <div\n              class={`${mergedClsPrefix}-date-panel-month__fast-prev`}\n              onClick={this.prevYear}\n            >\n              {resolveSlot(datePickerSlots['prev-year'], () => [\n                <FastBackwardIcon />\n              ])}\n            </div>\n            <div\n              class={`${mergedClsPrefix}-date-panel-month__prev`}\n              onClick={this.prevMonth}\n            >\n              {resolveSlot(datePickerSlots['prev-month'], () => [\n                <BackwardIcon />\n              ])}\n            </div>\n            <PanelHeader\n              fastYearSelect={this.fastYearSelect}\n              fastMonthSelect={this.fastMonthSelect}\n              monthYearSeparator={this.calendarHeaderMonthYearSeparator}\n              monthBeforeYear={this.calendarMonthBeforeYear}\n              value={this.calendarValue}\n              onUpdateValue={this.onUpdateCalendarValue}\n              mergedClsPrefix={mergedClsPrefix}\n              calendarMonth={this.calendarMonth}\n              calendarYear={this.calendarYear}\n            />\n            <div\n              class={`${mergedClsPrefix}-date-panel-month__next`}\n              onClick={this.nextMonth}\n            >\n              {resolveSlot(datePickerSlots['next-month'], () => [\n                <ForwardIcon />\n              ])}\n            </div>\n            <div\n              class={`${mergedClsPrefix}-date-panel-month__fast-next`}\n              onClick={this.nextYear}\n            >\n              {resolveSlot(datePickerSlots['next-year'], () => [\n                <FastForwardIcon />\n              ])}\n            </div>\n          </div>\n          <div class={`${mergedClsPrefix}-date-panel-weekdays`}>\n            {this.weekdays.map(weekday => (\n              <div\n                key={weekday}\n                class={`${mergedClsPrefix}-date-panel-weekdays__day`}\n              >\n                {weekday}\n              </div>\n            ))}\n          </div>\n          <div class={`${mergedClsPrefix}-date-panel-dates`}>\n            {this.dateArray.map((dateItem, i) => (\n              <div\n                data-n-date\n                key={i}\n                class={[\n                  `${mergedClsPrefix}-date-panel-date`,\n                  {\n                    [`${mergedClsPrefix}-date-panel-date--current`]:\n                      dateItem.isCurrentDate,\n                    [`${mergedClsPrefix}-date-panel-date--selected`]:\n                      dateItem.selected,\n                    [`${mergedClsPrefix}-date-panel-date--excluded`]:\n                      !dateItem.inCurrentMonth,\n                    [`${mergedClsPrefix}-date-panel-date--disabled`]:\n                      this.mergedIsDateDisabled(dateItem.ts, {\n                        type: 'date',\n                        year: dateItem.dateObject.year,\n                        month: dateItem.dateObject.month,\n                        date: dateItem.dateObject.date\n                      }),\n                    [`${mergedClsPrefix}-date-panel-date--week-hovered`]:\n                      this.isWeekHovered(dateItem),\n                    [`${mergedClsPrefix}-date-panel-date--week-selected`]:\n                      dateItem.inSelectedWeek\n                  }\n                ]}\n                onClick={() => {\n                  this.handleDateClick(dateItem)\n                }}\n                onMouseenter={() => {\n                  this.handleDateMouseEnter(dateItem)\n                }}\n              >\n                <div class={`${mergedClsPrefix}-date-panel-date__trigger`} />\n                {dateItem.dateObject.date}\n                {dateItem.isCurrentDate ? (\n                  <div class={`${mergedClsPrefix}-date-panel-date__sup`} />\n                ) : null}\n              </div>\n            ))}\n          </div>\n        </div>\n        {this.datePickerSlots.footer ? (\n          <div class={`${mergedClsPrefix}-date-panel-footer`}>\n            {this.datePickerSlots.footer()}\n          </div>\n        ) : null}\n        {this.actions?.length || shortcuts ? (\n          <div class={`${mergedClsPrefix}-date-panel-actions`}>\n            <div class={`${mergedClsPrefix}-date-panel-actions__prefix`}>\n              {shortcuts\n                && Object.keys(shortcuts).map((key) => {\n                  const shortcut = shortcuts[key]\n                  return Array.isArray(shortcut) ? null : (\n                    <NxButton\n                      size=\"tiny\"\n                      onMouseenter={() => {\n                        this.handleSingleShortcutMouseenter(shortcut)\n                      }}\n                      onClick={() => {\n                        this.handleSingleShortcutClick(shortcut)\n                      }}\n                      onMouseleave={() => {\n                        this.handleShortcutMouseleave()\n                      }}\n                    >\n                      {{ default: () => key }}\n                    </NxButton>\n                  )\n                })}\n            </div>\n            <div class={`${mergedClsPrefix}-date-panel-actions__suffix`}>\n              {this.actions?.includes('clear')\n                ? resolveSlotWithTypedProps(\n                    this.$slots.clear,\n                    {\n                      onClear: this.handleClearClick,\n                      text: this.locale.clear\n                    } satisfies DatePickerClearSlotProps,\n                    () => [\n                      <NButton\n                        theme={mergedTheme.peers.Button}\n                        themeOverrides={mergedTheme.peerOverrides.Button}\n                        size=\"tiny\"\n                        onClick={this.handleClearClick}\n                      >\n                        {{ default: () => this.locale.clear }}\n                      </NButton>\n                    ]\n                  )\n                : null}\n              {this.actions?.includes('now')\n                ? resolveSlotWithTypedProps(\n                    this.$slots.now,\n                    {\n                      onNow: this.handleNowClick,\n                      text: this.locale.now\n                    } satisfies DatePickerNowSlotProps,\n                    () => [\n                      <NButton\n                        theme={mergedTheme.peers.Button}\n                        themeOverrides={mergedTheme.peerOverrides.Button}\n                        size=\"tiny\"\n                        onClick={this.handleNowClick}\n                      >\n                        {{ default: () => this.locale.now }}\n                      </NButton>\n                    ]\n                  )\n                : null}\n              {/** we don't need a confirm button for date picking */}\n            </div>\n          </div>\n        ) : null}\n        <NBaseFocusDetector onFocus={this.handleFocusDetectorFocus} />\n      </div>\n    )\n  }\n})\n"
  },
  {
    "path": "src/date-picker/src/panel/daterange.tsx",
    "content": "import type {\n  DatePickerClearSlotProps,\n  DatePickerConfirmSlotProps\n} from '../public-types'\nimport { defineComponent, h, watchEffect } from 'vue'\nimport { NBaseFocusDetector } from '../../../_internal'\nimport {\n  BackwardIcon,\n  FastBackwardIcon,\n  FastForwardIcon,\n  ForwardIcon\n} from '../../../_internal/icons'\nimport {\n  resolveSlot,\n  resolveSlotWithTypedProps,\n  warnOnce\n} from '../../../_utils'\nimport { NButton, NxButton } from '../../../button'\nimport PanelHeader from './panelHeader'\nimport { useDualCalendar, useDualCalendarProps } from './use-dual-calendar'\n\nexport default defineComponent({\n  name: 'DateRangePanel',\n  props: useDualCalendarProps,\n  setup(props) {\n    if (__DEV__) {\n      watchEffect(() => {\n        if (props.actions?.includes('now')) {\n          warnOnce(\n            'date-picker',\n            'The `now` action is not supported for n-date-picker of `daterange` type'\n          )\n        }\n      })\n    }\n    return useDualCalendar(props, 'daterange')\n  },\n  render() {\n    const {\n      mergedClsPrefix,\n      mergedTheme,\n      shortcuts,\n      onRender,\n      datePickerSlots\n    } = this\n    onRender?.()\n\n    return (\n      <div\n        ref=\"selfRef\"\n        tabindex={0}\n        class={[\n          `${mergedClsPrefix}-date-panel`,\n          `${mergedClsPrefix}-date-panel--daterange`,\n          !this.panel && `${mergedClsPrefix}-date-panel--shadow`,\n          this.themeClass\n        ]}\n        onKeydown={this.handlePanelKeyDown}\n        onFocus={this.handlePanelFocus}\n      >\n        <div\n          ref=\"startDatesElRef\"\n          class={`${mergedClsPrefix}-date-panel-calendar ${mergedClsPrefix}-date-panel-calendar--start`}\n        >\n          <div class={`${mergedClsPrefix}-date-panel-month`}>\n            <div\n              class={`${mergedClsPrefix}-date-panel-month__fast-prev`}\n              onClick={this.startCalendarPrevYear}\n            >\n              {resolveSlot(datePickerSlots['prev-year'], () => [\n                <FastBackwardIcon />\n              ])}\n            </div>\n            <div\n              class={`${mergedClsPrefix}-date-panel-month__prev`}\n              onClick={this.startCalendarPrevMonth}\n            >\n              {resolveSlot(datePickerSlots['prev-month'], () => [\n                <BackwardIcon />\n              ])}\n            </div>\n            <PanelHeader\n              fastYearSelect={this.fastYearSelect}\n              fastMonthSelect={this.fastMonthSelect}\n              monthYearSeparator={this.calendarHeaderMonthYearSeparator}\n              monthBeforeYear={this.calendarMonthBeforeYear}\n              value={this.startCalendarDateTime}\n              onUpdateValue={this.onUpdateStartCalendarValue}\n              mergedClsPrefix={mergedClsPrefix}\n              calendarMonth={this.startCalendarMonth}\n              calendarYear={this.startCalendarYear}\n            />\n            <div\n              class={`${mergedClsPrefix}-date-panel-month__next`}\n              onClick={this.startCalendarNextMonth}\n            >\n              {resolveSlot(datePickerSlots['next-month'], () => [\n                <ForwardIcon />\n              ])}\n            </div>\n            <div\n              class={`${mergedClsPrefix}-date-panel-month__fast-next`}\n              onClick={this.startCalendarNextYear}\n            >\n              {resolveSlot(datePickerSlots['next-year'], () => [\n                <FastForwardIcon />\n              ])}\n            </div>\n          </div>\n          <div class={`${mergedClsPrefix}-date-panel-weekdays`}>\n            {this.weekdays.map(weekday => (\n              <div\n                key={weekday}\n                class={`${mergedClsPrefix}-date-panel-weekdays__day`}\n              >\n                {weekday}\n              </div>\n            ))}\n          </div>\n          <div class={`${mergedClsPrefix}-date-panel__divider`} />\n          <div class={`${mergedClsPrefix}-date-panel-dates`}>\n            {this.startDateArray.map((dateItem, i) => (\n              <div\n                data-n-date\n                key={i}\n                class={[\n                  `${mergedClsPrefix}-date-panel-date`,\n                  {\n                    [`${mergedClsPrefix}-date-panel-date--excluded`]:\n                      !dateItem.inCurrentMonth,\n                    [`${mergedClsPrefix}-date-panel-date--current`]:\n                      dateItem.isCurrentDate,\n                    [`${mergedClsPrefix}-date-panel-date--selected`]:\n                      dateItem.selected,\n                    [`${mergedClsPrefix}-date-panel-date--covered`]:\n                      dateItem.inSpan,\n                    [`${mergedClsPrefix}-date-panel-date--start`]:\n                      dateItem.startOfSpan,\n                    [`${mergedClsPrefix}-date-panel-date--end`]:\n                      dateItem.endOfSpan,\n                    [`${mergedClsPrefix}-date-panel-date--disabled`]:\n                      this.mergedIsDateDisabled(dateItem.ts)\n                  }\n                ]}\n                onClick={() => {\n                  this.handleDateClick(dateItem)\n                }}\n                onMouseenter={() => {\n                  this.handleDateMouseEnter(dateItem)\n                }}\n              >\n                <div class={`${mergedClsPrefix}-date-panel-date__trigger`} />\n                {dateItem.dateObject.date}\n                {dateItem.isCurrentDate ? (\n                  <div class={`${mergedClsPrefix}-date-panel-date__sup`} />\n                ) : null}\n              </div>\n            ))}\n          </div>\n        </div>\n        <div class={`${mergedClsPrefix}-date-panel__vertical-divider`} />\n        <div\n          ref=\"endDatesElRef\"\n          class={`${mergedClsPrefix}-date-panel-calendar ${mergedClsPrefix}-date-panel-calendar--end`}\n        >\n          <div class={`${mergedClsPrefix}-date-panel-month`}>\n            <div\n              class={`${mergedClsPrefix}-date-panel-month__fast-prev`}\n              onClick={this.endCalendarPrevYear}\n            >\n              {resolveSlot(datePickerSlots['prev-year'], () => [\n                <FastBackwardIcon />\n              ])}\n            </div>\n            <div\n              class={`${mergedClsPrefix}-date-panel-month__prev`}\n              onClick={this.endCalendarPrevMonth}\n            >\n              {resolveSlot(datePickerSlots['prev-month'], () => [\n                <BackwardIcon />\n              ])}\n            </div>\n            <PanelHeader\n              fastYearSelect={this.fastYearSelect}\n              fastMonthSelect={this.fastMonthSelect}\n              monthYearSeparator={this.calendarHeaderMonthYearSeparator}\n              monthBeforeYear={this.calendarMonthBeforeYear}\n              value={this.endCalendarDateTime}\n              onUpdateValue={this.onUpdateEndCalendarValue}\n              mergedClsPrefix={mergedClsPrefix}\n              calendarMonth={this.endCalendarMonth}\n              calendarYear={this.endCalendarYear}\n            />\n            <div\n              class={`${mergedClsPrefix}-date-panel-month__next`}\n              onClick={this.endCalendarNextMonth}\n            >\n              {resolveSlot(datePickerSlots['next-month'], () => [\n                <ForwardIcon />\n              ])}\n            </div>\n            <div\n              class={`${mergedClsPrefix}-date-panel-month__fast-next`}\n              onClick={this.endCalendarNextYear}\n            >\n              {resolveSlot(datePickerSlots['next-year'], () => [\n                <FastForwardIcon />\n              ])}\n            </div>\n          </div>\n          <div class={`${mergedClsPrefix}-date-panel-weekdays`}>\n            {this.weekdays.map(weekday => (\n              <div\n                key={weekday}\n                class={`${mergedClsPrefix}-date-panel-weekdays__day`}\n              >\n                {weekday}\n              </div>\n            ))}\n          </div>\n          <div class={`${mergedClsPrefix}-date-panel__divider`} />\n          <div class={`${mergedClsPrefix}-date-panel-dates`}>\n            {this.endDateArray.map((dateItem, i) => (\n              <div\n                data-n-date\n                key={i}\n                class={[\n                  `${mergedClsPrefix}-date-panel-date`,\n                  {\n                    [`${mergedClsPrefix}-date-panel-date--excluded`]:\n                      !dateItem.inCurrentMonth,\n                    [`${mergedClsPrefix}-date-panel-date--current`]:\n                      dateItem.isCurrentDate,\n                    [`${mergedClsPrefix}-date-panel-date--selected`]:\n                      dateItem.selected,\n                    [`${mergedClsPrefix}-date-panel-date--covered`]:\n                      dateItem.inSpan,\n                    [`${mergedClsPrefix}-date-panel-date--start`]:\n                      dateItem.startOfSpan,\n                    [`${mergedClsPrefix}-date-panel-date--end`]:\n                      dateItem.endOfSpan,\n                    [`${mergedClsPrefix}-date-panel-date--disabled`]:\n                      this.mergedIsDateDisabled(dateItem.ts)\n                  }\n                ]}\n                onClick={() => {\n                  this.handleDateClick(dateItem)\n                }}\n                onMouseenter={() => {\n                  this.handleDateMouseEnter(dateItem)\n                }}\n              >\n                <div class={`${mergedClsPrefix}-date-panel-date__trigger`} />\n                {dateItem.dateObject.date}\n                {dateItem.isCurrentDate ? (\n                  <div class={`${mergedClsPrefix}-date-panel-date__sup`} />\n                ) : null}\n              </div>\n            ))}\n          </div>\n        </div>\n        {this.datePickerSlots.footer ? (\n          <div class={`${mergedClsPrefix}-date-panel-footer`}>\n            {this.datePickerSlots.footer()}\n          </div>\n        ) : null}\n        {this.actions?.length || shortcuts ? (\n          <div class={`${mergedClsPrefix}-date-panel-actions`}>\n            <div class={`${mergedClsPrefix}-date-panel-actions__prefix`}>\n              {shortcuts\n                && Object.keys(shortcuts).map((key) => {\n                  const shortcut = shortcuts[key]\n                  return Array.isArray(shortcut)\n                    || typeof shortcut === 'function' ? (\n                        <NxButton\n                          size=\"tiny\"\n                          onMouseenter={() => {\n                            this.handleRangeShortcutMouseenter(shortcut)\n                          }}\n                          onClick={() => {\n                            this.handleRangeShortcutClick(shortcut)\n                          }}\n                          onMouseleave={() => {\n                            this.handleShortcutMouseleave()\n                          }}\n                        >\n                          {{ default: () => key }}\n                        </NxButton>\n                      ) : null\n                })}\n            </div>\n            <div class={`${mergedClsPrefix}-date-panel-actions__suffix`}>\n              {this.actions?.includes('clear')\n                ? resolveSlotWithTypedProps(\n                    datePickerSlots.clear,\n                    {\n                      onClear: this.handleClearClick,\n                      text: this.locale.clear\n                    } satisfies DatePickerClearSlotProps,\n                    () => [\n                      <NButton\n                        theme={mergedTheme.peers.Button}\n                        themeOverrides={mergedTheme.peerOverrides.Button}\n                        size=\"tiny\"\n                        onClick={this.handleClearClick}\n                      >\n                        {{ default: () => this.locale.clear }}\n                      </NButton>\n                    ]\n                  )\n                : null}\n              {this.actions?.includes('confirm')\n                ? resolveSlotWithTypedProps(\n                    datePickerSlots.confirm,\n                    {\n                      onConfirm: this.handleConfirmClick,\n                      disabled: this.isRangeInvalid || this.isSelecting,\n                      text: this.locale.confirm\n                    } satisfies DatePickerConfirmSlotProps,\n                    () => [\n                      <NButton\n                        theme={mergedTheme.peers.Button}\n                        themeOverrides={mergedTheme.peerOverrides.Button}\n                        size=\"tiny\"\n                        type=\"primary\"\n                        disabled={this.isRangeInvalid || this.isSelecting}\n                        onClick={this.handleConfirmClick}\n                      >\n                        {{ default: () => this.locale.confirm }}\n                      </NButton>\n                    ]\n                  )\n                : null}\n            </div>\n          </div>\n        ) : null}\n        <NBaseFocusDetector onFocus={this.handleFocusDetectorFocus} />\n      </div>\n    )\n  }\n})\n"
  },
  {
    "path": "src/date-picker/src/panel/datetime.tsx",
    "content": "import type {\n  DatePickerClearSlotProps,\n  DatePickerConfirmSlotProps,\n  DatePickerNowSlotProps\n} from '../public-types'\nimport { defineComponent, h } from 'vue'\nimport { NBaseFocusDetector } from '../../../_internal'\nimport {\n  BackwardIcon,\n  FastBackwardIcon,\n  FastForwardIcon,\n  ForwardIcon\n} from '../../../_internal/icons'\nimport { resolveSlot, resolveSlotWithTypedProps } from '../../../_utils'\nimport { NButton, NxButton } from '../../../button'\nimport { NInput } from '../../../input'\nimport { NTimePicker } from '../../../time-picker'\nimport PanelHeader from './panelHeader'\nimport { useCalendar, useCalendarProps } from './use-calendar'\n\n/**\n * DateTime Panel\n * Update picker value on:\n * 1. confirm click\n * 2. clear click\n */\nexport default defineComponent({\n  name: 'DateTimePanel',\n  props: useCalendarProps,\n  setup(props) {\n    return useCalendar(props, 'datetime')\n  },\n  render() {\n    const {\n      mergedClsPrefix,\n      mergedTheme,\n      shortcuts,\n      timePickerProps,\n      datePickerSlots,\n      onRender\n    } = this\n    onRender?.()\n\n    return (\n      <div\n        ref=\"selfRef\"\n        tabindex={0}\n        class={[\n          `${mergedClsPrefix}-date-panel`,\n          `${mergedClsPrefix}-date-panel--datetime`,\n          !this.panel && `${mergedClsPrefix}-date-panel--shadow`,\n          this.themeClass\n        ]}\n        onKeydown={this.handlePanelKeyDown}\n        onFocus={this.handlePanelFocus}\n      >\n        <div class={`${mergedClsPrefix}-date-panel-header`}>\n          <NInput\n            value={this.dateInputValue}\n            theme={mergedTheme.peers.Input}\n            themeOverrides={mergedTheme.peerOverrides.Input}\n            stateful={false}\n            size={this.timePickerSize}\n            readonly={this.inputReadonly}\n            class={`${mergedClsPrefix}-date-panel-date-input`}\n            textDecoration={this.isDateInvalid ? 'line-through' : ''}\n            placeholder={this.locale.selectDate}\n            onBlur={this.handleDateInputBlur}\n            onUpdateValue={this.handleDateInput}\n          />\n          <NTimePicker\n            size={this.timePickerSize}\n            placeholder={this.locale.selectTime}\n            format={this.timePickerFormat}\n            {...(Array.isArray(timePickerProps) ? undefined : timePickerProps)}\n            showIcon={false}\n            to={false}\n            theme={mergedTheme.peers.TimePicker}\n            themeOverrides={mergedTheme.peerOverrides.TimePicker}\n            value={Array.isArray(this.value) ? null : this.value}\n            isHourDisabled={this.isHourDisabled}\n            isMinuteDisabled={this.isMinuteDisabled}\n            isSecondDisabled={this.isSecondDisabled}\n            onUpdateValue={this.handleTimePickerChange}\n            stateful={false}\n          />\n        </div>\n        <div class={`${mergedClsPrefix}-date-panel-calendar`}>\n          <div class={`${mergedClsPrefix}-date-panel-month`}>\n            <div\n              class={`${mergedClsPrefix}-date-panel-month__fast-prev`}\n              onClick={this.prevYear}\n            >\n              {resolveSlot(datePickerSlots['prev-year'], () => [\n                <FastBackwardIcon />\n              ])}\n            </div>\n            <div\n              class={`${mergedClsPrefix}-date-panel-month__prev`}\n              onClick={this.prevMonth}\n            >\n              {resolveSlot(datePickerSlots['prev-month'], () => [\n                <BackwardIcon />\n              ])}\n            </div>\n            <PanelHeader\n              fastYearSelect={this.fastYearSelect}\n              fastMonthSelect={this.fastMonthSelect}\n              monthYearSeparator={this.calendarHeaderMonthYearSeparator}\n              monthBeforeYear={this.calendarMonthBeforeYear}\n              value={this.calendarValue}\n              onUpdateValue={this.onUpdateCalendarValue}\n              mergedClsPrefix={mergedClsPrefix}\n              calendarMonth={this.calendarMonth}\n              calendarYear={this.calendarYear}\n            />\n            <div\n              class={`${mergedClsPrefix}-date-panel-month__next`}\n              onClick={this.nextMonth}\n            >\n              {resolveSlot(datePickerSlots['next-month'], () => [\n                <ForwardIcon />\n              ])}\n            </div>\n            <div\n              class={`${mergedClsPrefix}-date-panel-month__fast-next`}\n              onClick={this.nextYear}\n            >\n              {resolveSlot(datePickerSlots['next-year'], () => [\n                <FastForwardIcon />\n              ])}\n            </div>\n          </div>\n          <div class={`${mergedClsPrefix}-date-panel-weekdays`}>\n            {this.weekdays.map(weekday => (\n              <div\n                key={weekday}\n                class={`${mergedClsPrefix}-date-panel-weekdays__day`}\n              >\n                {weekday}\n              </div>\n            ))}\n          </div>\n          <div class={`${mergedClsPrefix}-date-panel-dates`}>\n            {this.dateArray.map((dateItem, i) => (\n              <div\n                data-n-date\n                key={i}\n                class={[\n                  `${mergedClsPrefix}-date-panel-date`,\n                  {\n                    [`${mergedClsPrefix}-date-panel-date--current`]:\n                      dateItem.isCurrentDate,\n                    [`${mergedClsPrefix}-date-panel-date--selected`]:\n                      dateItem.selected,\n                    [`${mergedClsPrefix}-date-panel-date--excluded`]:\n                      !dateItem.inCurrentMonth,\n                    [`${mergedClsPrefix}-date-panel-date--disabled`]:\n                      this.mergedIsDateDisabled(dateItem.ts, {\n                        type: 'date',\n                        year: dateItem.dateObject.year,\n                        month: dateItem.dateObject.month,\n                        date: dateItem.dateObject.date\n                      })\n                  }\n                ]}\n                onClick={() => {\n                  this.handleDateClick(dateItem)\n                }}\n              >\n                <div class={`${mergedClsPrefix}-date-panel-date__trigger`} />\n                {dateItem.dateObject.date}\n                {dateItem.isCurrentDate ? (\n                  <div class={`${mergedClsPrefix}-date-panel-date__sup`} />\n                ) : null}\n              </div>\n            ))}\n          </div>\n        </div>\n        {this.datePickerSlots.footer ? (\n          <div class={`${mergedClsPrefix}-date-panel-footer`}>\n            {this.datePickerSlots.footer()}\n          </div>\n        ) : null}\n        {this.actions?.length || shortcuts ? (\n          <div class={`${mergedClsPrefix}-date-panel-actions`}>\n            <div class={`${mergedClsPrefix}-date-panel-actions__prefix`}>\n              {shortcuts\n                && Object.keys(shortcuts).map((key) => {\n                  const shortcut = shortcuts[key]\n                  return Array.isArray(shortcut) ? null : (\n                    <NxButton\n                      size=\"tiny\"\n                      onMouseenter={() => {\n                        this.handleSingleShortcutMouseenter(shortcut)\n                      }}\n                      onClick={() => {\n                        this.handleSingleShortcutClick(shortcut)\n                      }}\n                      onMouseleave={() => {\n                        this.handleShortcutMouseleave()\n                      }}\n                    >\n                      {{ default: () => key }}\n                    </NxButton>\n                  )\n                })}\n            </div>\n            <div class={`${mergedClsPrefix}-date-panel-actions__suffix`}>\n              {this.actions?.includes('clear')\n                ? resolveSlotWithTypedProps(\n                    this.datePickerSlots.clear,\n                    {\n                      onClear: this.clearSelectedDateTime,\n                      text: this.locale.clear\n                    } satisfies DatePickerClearSlotProps,\n                    () => [\n                      <NButton\n                        theme={mergedTheme.peers.Button}\n                        themeOverrides={mergedTheme.peerOverrides.Button}\n                        size=\"tiny\"\n                        onClick={this.clearSelectedDateTime}\n                      >\n                        {{ default: () => this.locale.clear }}\n                      </NButton>\n                    ]\n                  )\n                : null}\n              {this.actions?.includes('now')\n                ? resolveSlotWithTypedProps(\n                    datePickerSlots.now,\n                    {\n                      onNow: this.handleNowClick,\n                      text: this.locale.now\n                    } satisfies DatePickerNowSlotProps,\n                    () => [\n                      <NButton\n                        theme={mergedTheme.peers.Button}\n                        themeOverrides={mergedTheme.peerOverrides.Button}\n                        size=\"tiny\"\n                        onClick={this.handleNowClick}\n                      >\n                        {{ default: () => this.locale.now }}\n                      </NButton>\n                    ]\n                  )\n                : null}\n              {this.actions?.includes('confirm')\n                ? resolveSlotWithTypedProps(\n                    datePickerSlots.confirm,\n                    {\n                      onConfirm: this.handleConfirmClick,\n                      disabled: this.isDateInvalid,\n                      text: this.locale.confirm\n                    } satisfies DatePickerConfirmSlotProps,\n                    () => [\n                      <NButton\n                        theme={mergedTheme.peers.Button}\n                        themeOverrides={mergedTheme.peerOverrides.Button}\n                        size=\"tiny\"\n                        type=\"primary\"\n                        disabled={this.isDateInvalid}\n                        onClick={this.handleConfirmClick}\n                      >\n                        {{ default: () => this.locale.confirm }}\n                      </NButton>\n                    ]\n                  )\n                : null}\n            </div>\n          </div>\n        ) : null}\n        <NBaseFocusDetector onFocus={this.handleFocusDetectorFocus} />\n      </div>\n    )\n  }\n})\n"
  },
  {
    "path": "src/date-picker/src/panel/datetimerange.tsx",
    "content": "import type {\n  DatePickerClearSlotProps,\n  DatePickerConfirmSlotProps\n} from '../public-types'\nimport { defineComponent, h, watchEffect } from 'vue'\nimport { NBaseFocusDetector } from '../../../_internal'\nimport {\n  BackwardIcon,\n  FastBackwardIcon,\n  FastForwardIcon,\n  ForwardIcon\n} from '../../../_internal/icons'\nimport {\n  resolveSlot,\n  resolveSlotWithTypedProps,\n  warnOnce\n} from '../../../_utils'\nimport { NButton, NxButton } from '../../../button'\nimport { NInput } from '../../../input'\nimport { NTimePicker } from '../../../time-picker'\nimport PanelHeader from './panelHeader'\nimport { useDualCalendar, useDualCalendarProps } from './use-dual-calendar'\n\nexport default defineComponent({\n  name: 'DateTimeRangePanel',\n  props: useDualCalendarProps,\n  setup(props) {\n    if (__DEV__) {\n      watchEffect(() => {\n        if (props.actions?.includes('now')) {\n          warnOnce(\n            'date-picker',\n            'The `now` action is not supported for n-date-picker of `datetimerange` type'\n          )\n        }\n      })\n    }\n    return useDualCalendar(props, 'datetimerange')\n  },\n  render() {\n    const {\n      mergedClsPrefix,\n      mergedTheme,\n      shortcuts,\n      timePickerProps,\n      onRender,\n      datePickerSlots\n    } = this\n    onRender?.()\n\n    return (\n      <div\n        ref=\"selfRef\"\n        tabindex={0}\n        class={[\n          `${mergedClsPrefix}-date-panel`,\n          `${mergedClsPrefix}-date-panel--datetimerange`,\n          !this.panel && `${mergedClsPrefix}-date-panel--shadow`,\n          this.themeClass\n        ]}\n        onKeydown={this.handlePanelKeyDown}\n        onFocus={this.handlePanelFocus}\n      >\n        <div class={`${mergedClsPrefix}-date-panel-header`}>\n          <NInput\n            value={this.startDateDisplayString}\n            theme={mergedTheme.peers.Input}\n            themeOverrides={mergedTheme.peerOverrides.Input}\n            size={this.timePickerSize}\n            stateful={false}\n            readonly={this.inputReadonly}\n            class={`${mergedClsPrefix}-date-panel-date-input`}\n            textDecoration={this.isStartValueInvalid ? 'line-through' : ''}\n            placeholder={this.locale.selectDate}\n            onBlur={this.handleStartDateInputBlur}\n            onUpdateValue={this.handleStartDateInput}\n          />\n          <NTimePicker\n            placeholder={this.locale.selectTime}\n            format={this.timePickerFormat}\n            size={this.timePickerSize}\n            {...(Array.isArray(timePickerProps)\n              ? timePickerProps[0]\n              : timePickerProps)}\n            value={this.startTimeValue}\n            to={false}\n            showIcon={false}\n            disabled={this.isSelecting}\n            theme={mergedTheme.peers.TimePicker}\n            themeOverrides={mergedTheme.peerOverrides.TimePicker}\n            stateful={false}\n            isHourDisabled={this.isStartHourDisabled}\n            isMinuteDisabled={this.isStartMinuteDisabled}\n            isSecondDisabled={this.isStartSecondDisabled}\n            onUpdateValue={this.handleStartTimePickerChange}\n          />\n          <NInput\n            value={this.endDateInput}\n            theme={mergedTheme.peers.Input}\n            themeOverrides={mergedTheme.peerOverrides.Input}\n            stateful={false}\n            size={this.timePickerSize}\n            readonly={this.inputReadonly}\n            class={`${mergedClsPrefix}-date-panel-date-input`}\n            textDecoration={this.isEndValueInvalid ? 'line-through' : ''}\n            placeholder={this.locale.selectDate}\n            onBlur={this.handleEndDateInputBlur}\n            onUpdateValue={this.handleEndDateInput}\n          />\n          <NTimePicker\n            placeholder={this.locale.selectTime}\n            format={this.timePickerFormat}\n            size={this.timePickerSize}\n            {...(Array.isArray(timePickerProps)\n              ? timePickerProps[1]\n              : timePickerProps)}\n            disabled={this.isSelecting}\n            showIcon={false}\n            theme={mergedTheme.peers.TimePicker}\n            themeOverrides={mergedTheme.peerOverrides.TimePicker}\n            to={false}\n            stateful={false}\n            value={this.endTimeValue}\n            isHourDisabled={this.isEndHourDisabled}\n            isMinuteDisabled={this.isEndMinuteDisabled}\n            isSecondDisabled={this.isEndSecondDisabled}\n            onUpdateValue={this.handleEndTimePickerChange}\n          />\n        </div>\n        <div\n          ref=\"startDatesElRef\"\n          class={`${mergedClsPrefix}-date-panel-calendar ${mergedClsPrefix}-date-panel-calendar--start`}\n        >\n          <div class={`${mergedClsPrefix}-date-panel-month`}>\n            <div\n              class={`${mergedClsPrefix}-date-panel-month__fast-prev`}\n              onClick={this.startCalendarPrevYear}\n            >\n              {resolveSlot(datePickerSlots['prev-year'], () => [\n                <FastBackwardIcon />\n              ])}\n            </div>\n            <div\n              class={`${mergedClsPrefix}-date-panel-month__prev`}\n              onClick={this.startCalendarPrevMonth}\n            >\n              {resolveSlot(datePickerSlots['prev-month'], () => [\n                <BackwardIcon />\n              ])}\n            </div>\n            <PanelHeader\n              fastYearSelect={this.fastYearSelect}\n              fastMonthSelect={this.fastMonthSelect}\n              monthYearSeparator={this.calendarHeaderMonthYearSeparator}\n              monthBeforeYear={this.calendarMonthBeforeYear}\n              value={this.startCalendarDateTime}\n              onUpdateValue={this.onUpdateStartCalendarValue}\n              mergedClsPrefix={mergedClsPrefix}\n              calendarMonth={this.startCalendarMonth}\n              calendarYear={this.startCalendarYear}\n            />\n            <div\n              class={`${mergedClsPrefix}-date-panel-month__next`}\n              onClick={this.startCalendarNextMonth}\n            >\n              {resolveSlot(datePickerSlots['next-month'], () => [\n                <ForwardIcon />\n              ])}\n            </div>\n            <div\n              class={`${mergedClsPrefix}-date-panel-month__fast-next`}\n              onClick={this.startCalendarNextYear}\n            >\n              {resolveSlot(datePickerSlots['next-year'], () => [\n                <FastForwardIcon />\n              ])}\n            </div>\n          </div>\n          <div class={`${mergedClsPrefix}-date-panel-weekdays`}>\n            {this.weekdays.map(weekday => (\n              <div\n                key={weekday}\n                class={`${mergedClsPrefix}-date-panel-weekdays__day`}\n              >\n                {weekday}\n              </div>\n            ))}\n          </div>\n          <div class={`${mergedClsPrefix}-date-panel__divider`} />\n          <div class={`${mergedClsPrefix}-date-panel-dates`}>\n            {this.startDateArray.map((dateItem, i) => {\n              const disabled = this.mergedIsDateDisabled(dateItem.ts)\n              return (\n                <div\n                  data-n-date\n                  key={i}\n                  class={[\n                    `${mergedClsPrefix}-date-panel-date`,\n                    {\n                      [`${mergedClsPrefix}-date-panel-date--excluded`]:\n                        !dateItem.inCurrentMonth,\n                      [`${mergedClsPrefix}-date-panel-date--current`]:\n                        dateItem.isCurrentDate,\n                      [`${mergedClsPrefix}-date-panel-date--selected`]:\n                        dateItem.selected,\n                      [`${mergedClsPrefix}-date-panel-date--covered`]:\n                        dateItem.inSpan,\n                      [`${mergedClsPrefix}-date-panel-date--start`]:\n                        dateItem.startOfSpan,\n                      [`${mergedClsPrefix}-date-panel-date--end`]:\n                        dateItem.endOfSpan,\n                      [`${mergedClsPrefix}-date-panel-date--disabled`]: disabled\n                    }\n                  ]}\n                  onClick={\n                    disabled\n                      ? undefined\n                      : () => {\n                          this.handleDateClick(dateItem)\n                        }\n                  }\n                  onMouseenter={\n                    disabled\n                      ? undefined\n                      : () => {\n                          this.handleDateMouseEnter(dateItem)\n                        }\n                  }\n                >\n                  <div class={`${mergedClsPrefix}-date-panel-date__trigger`} />\n                  {dateItem.dateObject.date}\n                  {dateItem.isCurrentDate ? (\n                    <div class={`${mergedClsPrefix}-date-panel-date__sup`} />\n                  ) : null}\n                </div>\n              )\n            })}\n          </div>\n        </div>\n        <div class={`${mergedClsPrefix}-date-panel__vertical-divider`} />\n        <div\n          ref=\"endDatesElRef\"\n          class={`${mergedClsPrefix}-date-panel-calendar ${mergedClsPrefix}-date-panel-calendar--end`}\n        >\n          <div class={`${mergedClsPrefix}-date-panel-month`}>\n            <div\n              class={`${mergedClsPrefix}-date-panel-month__fast-prev`}\n              onClick={this.endCalendarPrevYear}\n            >\n              {resolveSlot(datePickerSlots['prev-year'], () => [\n                <FastBackwardIcon />\n              ])}\n            </div>\n            <div\n              class={`${mergedClsPrefix}-date-panel-month__prev`}\n              onClick={this.endCalendarPrevMonth}\n            >\n              {resolveSlot(datePickerSlots['prev-month'], () => [\n                <BackwardIcon />\n              ])}\n            </div>\n            <PanelHeader\n              fastYearSelect={this.fastYearSelect}\n              fastMonthSelect={this.fastMonthSelect}\n              monthBeforeYear={this.calendarMonthBeforeYear}\n              value={this.endCalendarDateTime}\n              onUpdateValue={this.onUpdateEndCalendarValue}\n              mergedClsPrefix={mergedClsPrefix}\n              monthYearSeparator={this.calendarHeaderMonthYearSeparator}\n              calendarMonth={this.endCalendarMonth}\n              calendarYear={this.endCalendarYear}\n            />\n            <div\n              class={`${mergedClsPrefix}-date-panel-month__next`}\n              onClick={this.endCalendarNextMonth}\n            >\n              {resolveSlot(datePickerSlots['next-month'], () => [\n                <ForwardIcon />\n              ])}\n            </div>\n            <div\n              class={`${mergedClsPrefix}-date-panel-month__fast-next`}\n              onClick={this.endCalendarNextYear}\n            >\n              {resolveSlot(datePickerSlots['next-year'], () => [\n                <FastForwardIcon />\n              ])}\n            </div>\n          </div>\n          <div class={`${mergedClsPrefix}-date-panel-weekdays`}>\n            {this.weekdays.map(weekday => (\n              <div\n                key={weekday}\n                class={`${mergedClsPrefix}-date-panel-weekdays__day`}\n              >\n                {weekday}\n              </div>\n            ))}\n          </div>\n          <div class={`${mergedClsPrefix}-date-panel__divider`} />\n          <div class={`${mergedClsPrefix}-date-panel-dates`}>\n            {this.endDateArray.map((dateItem, i) => {\n              const disabled = this.mergedIsDateDisabled(dateItem.ts)\n              return (\n                <div\n                  data-n-date\n                  key={i}\n                  class={[\n                    `${mergedClsPrefix}-date-panel-date`,\n                    {\n                      [`${mergedClsPrefix}-date-panel-date--excluded`]:\n                        !dateItem.inCurrentMonth,\n                      [`${mergedClsPrefix}-date-panel-date--current`]:\n                        dateItem.isCurrentDate,\n                      [`${mergedClsPrefix}-date-panel-date--selected`]:\n                        dateItem.selected,\n                      [`${mergedClsPrefix}-date-panel-date--covered`]:\n                        dateItem.inSpan,\n                      [`${mergedClsPrefix}-date-panel-date--start`]:\n                        dateItem.startOfSpan,\n                      [`${mergedClsPrefix}-date-panel-date--end`]:\n                        dateItem.endOfSpan,\n                      [`${mergedClsPrefix}-date-panel-date--disabled`]: disabled\n                    }\n                  ]}\n                  onClick={\n                    disabled\n                      ? undefined\n                      : () => {\n                          this.handleDateClick(dateItem)\n                        }\n                  }\n                  onMouseenter={\n                    disabled\n                      ? undefined\n                      : () => {\n                          this.handleDateMouseEnter(dateItem)\n                        }\n                  }\n                >\n                  <div class={`${mergedClsPrefix}-date-panel-date__trigger`} />\n                  {dateItem.dateObject.date}\n                  {dateItem.isCurrentDate ? (\n                    <div class={`${mergedClsPrefix}-date-panel-date__sup`} />\n                  ) : null}\n                </div>\n              )\n            })}\n          </div>\n        </div>\n        {this.datePickerSlots.footer ? (\n          <div class={`${mergedClsPrefix}-date-panel-footer`}>\n            {this.datePickerSlots.footer()}\n          </div>\n        ) : null}\n        {this.actions?.length || shortcuts ? (\n          <div class={`${mergedClsPrefix}-date-panel-actions`}>\n            <div class={`${mergedClsPrefix}-date-panel-actions__prefix`}>\n              {shortcuts\n                && Object.keys(shortcuts).map((key) => {\n                  const shortcut = shortcuts[key]\n                  return Array.isArray(shortcut)\n                    || typeof shortcut === 'function' ? (\n                        <NxButton\n                          size=\"tiny\"\n                          onMouseenter={() => {\n                            this.handleRangeShortcutMouseenter(shortcut)\n                          }}\n                          onClick={() => {\n                            this.handleRangeShortcutClick(shortcut)\n                          }}\n                          onMouseleave={() => {\n                            this.handleShortcutMouseleave()\n                          }}\n                        >\n                          {{ default: () => key }}\n                        </NxButton>\n                      ) : null\n                })}\n            </div>\n            <div class={`${mergedClsPrefix}-date-panel-actions__suffix`}>\n              {this.actions?.includes('clear')\n                ? resolveSlotWithTypedProps(\n                    datePickerSlots.clear,\n                    {\n                      onClear: this.handleClearClick,\n                      text: this.locale.clear\n                    } satisfies DatePickerClearSlotProps,\n                    () => [\n                      <NButton\n                        theme={mergedTheme.peers.Button}\n                        themeOverrides={mergedTheme.peerOverrides.Button}\n                        size=\"tiny\"\n                        onClick={this.handleClearClick}\n                      >\n                        {{ default: () => this.locale.clear }}\n                      </NButton>\n                    ]\n                  )\n                : null}\n              {this.actions?.includes('confirm')\n                ? resolveSlotWithTypedProps(\n                    datePickerSlots.confirm,\n                    {\n                      onConfirm: this.handleConfirmClick,\n                      disabled: this.isRangeInvalid || this.isSelecting,\n                      text: this.locale.confirm\n                    } satisfies DatePickerConfirmSlotProps,\n                    () => [\n                      <NButton\n                        theme={mergedTheme.peers.Button}\n                        themeOverrides={mergedTheme.peerOverrides.Button}\n                        size=\"tiny\"\n                        type=\"primary\"\n                        disabled={this.isRangeInvalid || this.isSelecting}\n                        onClick={this.handleConfirmClick}\n                      >\n                        {{ default: () => this.locale.confirm }}\n                      </NButton>\n                    ]\n                  )\n                : null}\n            </div>\n          </div>\n        ) : null}\n        <NBaseFocusDetector onFocus={this.handleFocusDetectorFocus} />\n      </div>\n    )\n  }\n})\n"
  },
  {
    "path": "src/date-picker/src/panel/month.tsx",
    "content": "import type { PropType, VNode } from 'vue'\nimport type { OnPanelUpdateValueImpl } from '../interface'\nimport type {\n  DatePickerClearSlotProps,\n  DatePickerConfirmSlotProps,\n  DatePickerNowSlotProps\n} from '../public-types'\nimport type { MonthItem, QuarterItem, YearItem } from '../utils'\nimport { defineComponent, h, onMounted } from 'vue'\nimport { VirtualList } from 'vueuc'\nimport { NBaseFocusDetector, NScrollbar } from '../../../_internal'\nimport { useLocale } from '../../../_mixins'\nimport { resolveSlotWithTypedProps, resolveWrappedSlot } from '../../../_utils'\nimport { NButton, NxButton } from '../../../button'\nimport { MONTH_ITEM_HEIGHT } from '../config'\nimport { getMonthString, getQuarterString, getYearString } from '../utils'\nimport { useCalendar, useCalendarProps } from './use-calendar'\n\n/**\n * Month Panel\n * Update picker value on:\n * 1. item click\n * 2. clear click\n */\nexport default defineComponent({\n  name: 'MonthPanel',\n  props: {\n    ...useCalendarProps,\n    type: {\n      type: String as PropType<'month' | 'year' | 'quarter'>,\n      required: true\n    },\n    // panelHeader prop\n    useAsQuickJump: Boolean\n  },\n  setup(props) {\n    const useCalendarRef = useCalendar(props, props.type)\n    const { dateLocaleRef } = useLocale('DatePicker')\n    const getRenderContent = (\n      item: YearItem | MonthItem | QuarterItem\n    ): number | string => {\n      switch (item.type) {\n        case 'year':\n          return getYearString(\n            item.dateObject.year,\n            item.yearFormat,\n            dateLocaleRef.value.locale\n          )\n        case 'month':\n          return getMonthString(\n            item.dateObject.month,\n            item.monthFormat,\n            dateLocaleRef.value.locale\n          )\n        case 'quarter':\n          return getQuarterString(\n            item.dateObject.quarter,\n            item.quarterFormat,\n            dateLocaleRef.value.locale\n          )\n      }\n    }\n    const { useAsQuickJump } = props\n    const renderItem = (\n      item: YearItem | MonthItem | QuarterItem,\n      i: number,\n      mergedClsPrefix: string\n    ): VNode => {\n      const { mergedIsDateDisabled, handleDateClick, handleQuickMonthClick }\n        = useCalendarRef\n      return (\n        <div\n          data-n-date\n          key={i}\n          class={[\n            `${mergedClsPrefix}-date-panel-month-calendar__picker-col-item`,\n            item.isCurrent\n            && `${mergedClsPrefix}-date-panel-month-calendar__picker-col-item--current`,\n            item.selected\n            && `${mergedClsPrefix}-date-panel-month-calendar__picker-col-item--selected`,\n            !useAsQuickJump\n            && mergedIsDateDisabled(\n              item.ts,\n              item.type === 'year'\n                ? {\n                    type: 'year',\n                    year: item.dateObject.year\n                  }\n                : item.type === 'month'\n                  ? {\n                      type: 'month',\n                      year: item.dateObject.year,\n                      month: item.dateObject.month\n                    }\n                  : item.type === 'quarter'\n                    ? {\n                        type: 'month',\n                        year: item.dateObject.year,\n                        month: item.dateObject.quarter\n                      }\n                    : (null as never)\n            )\n            && `${mergedClsPrefix}-date-panel-month-calendar__picker-col-item--disabled`\n          ]}\n          onClick={() => {\n            if (item.type === 'year') {\n              props.onSelectYear?.()\n            }\n            else if (item.type === 'month') {\n              props.onSelectMonth?.()\n            }\n\n            if (useAsQuickJump) {\n              handleQuickMonthClick(item, (value) => {\n                ;(props.onUpdateValue as OnPanelUpdateValueImpl)(value, false)\n              })\n            }\n            else {\n              handleDateClick(item)\n            }\n          }}\n        >\n          {getRenderContent(item)}\n        </div>\n      )\n    }\n    onMounted(() => {\n      useCalendarRef.justifyColumnsScrollState()\n    })\n    return { ...useCalendarRef, renderItem }\n  },\n  render() {\n    const {\n      mergedClsPrefix,\n      mergedTheme,\n      shortcuts,\n      actions,\n      renderItem,\n      type,\n      onRender\n    } = this\n    onRender?.()\n    return (\n      <div\n        ref=\"selfRef\"\n        tabindex={0}\n        class={[\n          `${mergedClsPrefix}-date-panel`,\n          `${mergedClsPrefix}-date-panel--month`,\n          !this.panel && `${mergedClsPrefix}-date-panel--shadow`,\n          this.themeClass\n        ]}\n        onFocus={this.handlePanelFocus}\n        onKeydown={this.handlePanelKeyDown}\n      >\n        <div class={`${mergedClsPrefix}-date-panel-month-calendar`}>\n          <NScrollbar\n            ref=\"yearScrollbarRef\"\n            class={`${mergedClsPrefix}-date-panel-month-calendar__picker-col`}\n            theme={mergedTheme.peers.Scrollbar}\n            themeOverrides={mergedTheme.peerOverrides.Scrollbar}\n            container={this.virtualListContainer}\n            content={this.virtualListContent}\n            horizontalRailStyle={{ zIndex: 1 }}\n            verticalRailStyle={{ zIndex: 1 }}\n          >\n            {{\n              default: () => (\n                <VirtualList\n                  ref=\"yearVlRef\"\n                  items={this.yearArray}\n                  itemSize={MONTH_ITEM_HEIGHT}\n                  showScrollbar={false}\n                  keyField=\"ts\"\n                  onScroll={this.handleVirtualListScroll}\n                  paddingBottom={4}\n                >\n                  {{\n                    default: ({\n                      item,\n                      index\n                    }: {\n                      item: YearItem\n                      index: number\n                    }) => {\n                      return renderItem(item, index, mergedClsPrefix)\n                    }\n                  }}\n                </VirtualList>\n              )\n            }}\n          </NScrollbar>\n          {type === 'month' || type === 'quarter' ? (\n            <div\n              class={`${mergedClsPrefix}-date-panel-month-calendar__picker-col`}\n            >\n              <NScrollbar\n                ref=\"monthScrollbarRef\"\n                theme={mergedTheme.peers.Scrollbar}\n                themeOverrides={mergedTheme.peerOverrides.Scrollbar}\n              >\n                {{\n                  default: () => [\n                    (type === 'month'\n                      ? this.monthArray\n                      : this.quarterArray\n                    ).map((item, i) => renderItem(item, i, mergedClsPrefix)),\n                    <div\n                      class={`${mergedClsPrefix}-date-panel-${type}-calendar__padding`}\n                    />\n                  ]\n                }}\n              </NScrollbar>\n            </div>\n          ) : null}\n        </div>\n        {resolveWrappedSlot(this.datePickerSlots.footer, (children) => {\n          return children ? (\n            <div class={`${mergedClsPrefix}-date-panel-footer`}>{children}</div>\n          ) : null\n        })}\n        {actions?.length || shortcuts ? (\n          <div class={`${mergedClsPrefix}-date-panel-actions`}>\n            <div class={`${mergedClsPrefix}-date-panel-actions__prefix`}>\n              {shortcuts\n                && Object.keys(shortcuts).map((key) => {\n                  const shortcut = shortcuts[key]\n                  return Array.isArray(shortcut) ? null : (\n                    <NxButton\n                      size=\"tiny\"\n                      onMouseenter={() => {\n                        this.handleSingleShortcutMouseenter(shortcut)\n                      }}\n                      onClick={() => {\n                        this.handleSingleShortcutClick(shortcut)\n                      }}\n                      onMouseleave={() => {\n                        this.handleShortcutMouseleave()\n                      }}\n                    >\n                      {{ default: () => key }}\n                    </NxButton>\n                  )\n                })}\n            </div>\n            <div class={`${mergedClsPrefix}-date-panel-actions__suffix`}>\n              {actions?.includes('clear')\n                ? resolveSlotWithTypedProps(\n                    this.datePickerSlots.clear,\n                    {\n                      onClear: this.handleClearClick,\n                      text: this.locale.clear\n                    } satisfies DatePickerClearSlotProps,\n                    () => [\n                      <NButton\n                        theme={mergedTheme.peers.Button}\n                        themeOverrides={mergedTheme.peerOverrides.Button}\n                        size=\"tiny\"\n                        onClick={this.handleClearClick}\n                      >\n                        {{ default: () => this.locale.clear }}\n                      </NButton>\n                    ]\n                  )\n                : null}\n              {actions?.includes('now')\n                ? resolveSlotWithTypedProps(\n                    this.datePickerSlots.now,\n                    {\n                      onNow: this.handleNowClick,\n                      text: this.locale.now\n                    } satisfies DatePickerNowSlotProps,\n                    () => [\n                      <NButton\n                        theme={mergedTheme.peers.Button}\n                        themeOverrides={mergedTheme.peerOverrides.Button}\n                        size=\"tiny\"\n                        onClick={this.handleNowClick}\n                      >\n                        {{ default: () => this.locale.now }}\n                      </NButton>\n                    ]\n                  )\n                : null}\n              {actions?.includes('confirm')\n                ? resolveSlotWithTypedProps(\n                    this.datePickerSlots.confirm,\n                    {\n                      onConfirm: this.handleConfirmClick,\n                      disabled: this.isDateInvalid,\n                      text: this.locale.confirm\n                    } satisfies DatePickerConfirmSlotProps,\n                    () => [\n                      <NButton\n                        theme={mergedTheme.peers.Button}\n                        themeOverrides={mergedTheme.peerOverrides.Button}\n                        size=\"tiny\"\n                        type=\"primary\"\n                        disabled={this.isDateInvalid}\n                        onClick={this.handleConfirmClick}\n                      >\n                        {{ default: () => this.locale.confirm }}\n                      </NButton>\n                    ]\n                  )\n                : null}\n            </div>\n          </div>\n        ) : null}\n        <NBaseFocusDetector onFocus={this.handleFocusDetectorFocus} />\n      </div>\n    )\n  }\n})\n"
  },
  {
    "path": "src/date-picker/src/panel/monthrange.tsx",
    "content": "import type { PropType, VNode } from 'vue'\nimport type {\n  DatePickerClearSlotProps,\n  DatePickerConfirmSlotProps\n} from '../public-types'\nimport type { MonthItem, QuarterItem, YearItem } from '../utils'\nimport { defineComponent, h, onMounted, watchEffect } from 'vue'\nimport { VirtualList } from 'vueuc'\nimport { NBaseFocusDetector, NScrollbar } from '../../../_internal'\nimport { useLocale } from '../../../_mixins'\nimport {\n  resolveSlotWithTypedProps,\n  resolveWrappedSlot,\n  warnOnce\n} from '../../../_utils'\nimport { NxButton } from '../../../button'\nimport { MONTH_ITEM_HEIGHT } from '../config'\nimport { getMonthString, getQuarterString, getYearString } from '../utils'\nimport { useDualCalendar, useDualCalendarProps } from './use-dual-calendar'\n\nexport default defineComponent({\n  name: 'MonthRangePanel',\n  props: {\n    ...useDualCalendarProps,\n    type: {\n      type: String as PropType<'monthrange' | 'yearrange' | 'quarterrange'>,\n      required: true\n    }\n  },\n  setup(props) {\n    if (__DEV__) {\n      watchEffect(() => {\n        if (props.actions?.includes('now')) {\n          warnOnce(\n            'date-picker',\n            'The `now` action is not supported for n-date-picker of '\n            + `${props.type}`\n            + 'type'\n          )\n        }\n      })\n    }\n    const useCalendarRef = useDualCalendar(props, props.type)\n    const { dateLocaleRef } = useLocale('DatePicker')\n    const renderItem = (\n      item: YearItem | MonthItem | QuarterItem,\n      i: number,\n      mergedClsPrefix: string,\n      type: 'start' | 'end'\n    ): VNode => {\n      const { handleColItemClick } = useCalendarRef\n      // TODO\n      const disabled = false\n      return (\n        <div\n          data-n-date\n          key={i}\n          class={[\n            `${mergedClsPrefix}-date-panel-month-calendar__picker-col-item`,\n            item.isCurrent\n            && `${mergedClsPrefix}-date-panel-month-calendar__picker-col-item--current`,\n            item.selected\n            && `${mergedClsPrefix}-date-panel-month-calendar__picker-col-item--selected`,\n            disabled\n            && `${mergedClsPrefix}-date-panel-month-calendar__picker-col-item--disabled`\n          ]}\n          onClick={\n            disabled\n              ? undefined\n              : () => {\n                  handleColItemClick(item, type)\n                }\n          }\n        >\n          {item.type === 'month'\n            ? getMonthString(\n                item.dateObject.month,\n                item.monthFormat,\n                dateLocaleRef.value.locale\n              )\n            : item.type === 'quarter'\n              ? getQuarterString(\n                  item.dateObject.quarter,\n                  item.quarterFormat,\n                  dateLocaleRef.value.locale\n                )\n              : getYearString(\n                  item.dateObject.year,\n                  item.yearFormat,\n                  dateLocaleRef.value.locale\n                )}\n        </div>\n      )\n    }\n    onMounted(() => {\n      useCalendarRef.justifyColumnsScrollState()\n    })\n    return { ...useCalendarRef, renderItem }\n  },\n  render() {\n    const {\n      mergedClsPrefix,\n      mergedTheme,\n      shortcuts,\n      type,\n      renderItem,\n      onRender\n    } = this\n    onRender?.()\n    return (\n      <div\n        ref=\"selfRef\"\n        tabindex={0}\n        class={[\n          `${mergedClsPrefix}-date-panel`,\n          `${mergedClsPrefix}-date-panel--daterange`,\n          !this.panel && `${mergedClsPrefix}-date-panel--shadow`,\n          this.themeClass\n        ]}\n        onKeydown={this.handlePanelKeyDown}\n        onFocus={this.handlePanelFocus}\n      >\n        <div\n          ref=\"startDatesElRef\"\n          class={`${mergedClsPrefix}-date-panel-calendar ${mergedClsPrefix}-date-panel-calendar--start`}\n        >\n          <div class={`${mergedClsPrefix}-date-panel-month-calendar`}>\n            <NScrollbar\n              ref=\"startYearScrollbarRef\"\n              class={`${mergedClsPrefix}-date-panel-month-calendar__picker-col`}\n              theme={mergedTheme.peers.Scrollbar}\n              themeOverrides={mergedTheme.peerOverrides.Scrollbar}\n              container={() => this.virtualListContainer('start')}\n              content={() => this.virtualListContent('start')}\n              horizontalRailStyle={{ zIndex: 1 }}\n              verticalRailStyle={{ zIndex: 1 }}\n            >\n              {{\n                default: () => (\n                  <VirtualList\n                    ref=\"startYearVlRef\"\n                    items={this.startYearArray}\n                    itemSize={MONTH_ITEM_HEIGHT}\n                    showScrollbar={false}\n                    keyField=\"ts\"\n                    onScroll={this.handleStartYearVlScroll}\n                    paddingBottom={4}\n                  >\n                    {{\n                      default: ({\n                        item,\n                        index\n                      }: {\n                        item: YearItem\n                        index: number\n                      }) => {\n                        return renderItem(item, index, mergedClsPrefix, 'start')\n                      }\n                    }}\n                  </VirtualList>\n                )\n              }}\n            </NScrollbar>\n            {type === 'monthrange' || type === 'quarterrange' ? (\n              <div\n                class={`${mergedClsPrefix}-date-panel-month-calendar__picker-col`}\n              >\n                <NScrollbar\n                  ref=\"startMonthScrollbarRef\"\n                  theme={mergedTheme.peers.Scrollbar}\n                  themeOverrides={mergedTheme.peerOverrides.Scrollbar}\n                >\n                  {{\n                    default: () => [\n                      (type === 'monthrange'\n                        ? this.startMonthArray\n                        : this.startQuarterArray\n                      ).map((item, i) =>\n                        renderItem(item, i, mergedClsPrefix, 'start')\n                      ),\n                      type === 'monthrange' && (\n                        <div\n                          class={`${mergedClsPrefix}-date-panel-month-calendar__padding`}\n                        />\n                      )\n                    ]\n                  }}\n                </NScrollbar>\n              </div>\n            ) : null}\n          </div>\n        </div>\n        <div class={`${mergedClsPrefix}-date-panel__vertical-divider`} />\n        <div\n          ref=\"endDatesElRef\"\n          class={`${mergedClsPrefix}-date-panel-calendar ${mergedClsPrefix}-date-panel-calendar--end`}\n        >\n          <div class={`${mergedClsPrefix}-date-panel-month-calendar`}>\n            <NScrollbar\n              ref=\"endYearScrollbarRef\"\n              class={`${mergedClsPrefix}-date-panel-month-calendar__picker-col`}\n              theme={mergedTheme.peers.Scrollbar}\n              themeOverrides={mergedTheme.peerOverrides.Scrollbar}\n              container={() => this.virtualListContainer('end')}\n              content={() => this.virtualListContent('end')}\n              horizontalRailStyle={{ zIndex: 1 }}\n              verticalRailStyle={{ zIndex: 1 }}\n            >\n              {{\n                default: () => (\n                  <VirtualList\n                    ref=\"endYearVlRef\"\n                    items={this.endYearArray}\n                    itemSize={MONTH_ITEM_HEIGHT}\n                    showScrollbar={false}\n                    keyField=\"ts\"\n                    onScroll={this.handleEndYearVlScroll}\n                    paddingBottom={4}\n                  >\n                    {{\n                      default: ({\n                        item,\n                        index\n                      }: {\n                        item: YearItem\n                        index: number\n                      }) => {\n                        return renderItem(item, index, mergedClsPrefix, 'end')\n                      }\n                    }}\n                  </VirtualList>\n                )\n              }}\n            </NScrollbar>\n            {type === 'monthrange' || type === 'quarterrange' ? (\n              <div\n                class={`${mergedClsPrefix}-date-panel-month-calendar__picker-col`}\n              >\n                <NScrollbar\n                  ref=\"endMonthScrollbarRef\"\n                  theme={mergedTheme.peers.Scrollbar}\n                  themeOverrides={mergedTheme.peerOverrides.Scrollbar}\n                >\n                  {{\n                    default: () => [\n                      (type === 'monthrange'\n                        ? this.endMonthArray\n                        : this.endQuarterArray\n                      ).map((item, i) =>\n                        renderItem(item, i, mergedClsPrefix, 'end')\n                      ),\n                      type === 'monthrange' && (\n                        <div\n                          class={`${mergedClsPrefix}-date-panel-month-calendar__padding`}\n                        />\n                      )\n                    ]\n                  }}\n                </NScrollbar>\n              </div>\n            ) : null}\n          </div>\n        </div>\n        {resolveWrappedSlot(this.datePickerSlots.footer, (children) => {\n          return children ? (\n            <div class={`${mergedClsPrefix}-date-panel-footer`}>{children}</div>\n          ) : null\n        })}\n        {this.actions?.length || shortcuts ? (\n          <div class={`${mergedClsPrefix}-date-panel-actions`}>\n            <div class={`${mergedClsPrefix}-date-panel-actions__prefix`}>\n              {shortcuts\n                && Object.keys(shortcuts).map((key) => {\n                  const shortcut = shortcuts[key]\n                  return Array.isArray(shortcut)\n                    || typeof shortcut === 'function' ? (\n                        <NxButton\n                          size=\"tiny\"\n                          onMouseenter={() => {\n                            this.handleRangeShortcutMouseenter(shortcut)\n                          }}\n                          onClick={() => {\n                            this.handleRangeShortcutClick(shortcut)\n                          }}\n                          onMouseleave={() => {\n                            this.handleShortcutMouseleave()\n                          }}\n                        >\n                          {{ default: () => key }}\n                        </NxButton>\n                      ) : null\n                })}\n            </div>\n            <div class={`${mergedClsPrefix}-date-panel-actions__suffix`}>\n              {this.actions?.includes('clear')\n                ? resolveSlotWithTypedProps(\n                    this.datePickerSlots.clear,\n                    {\n                      onClear: this.handleClearClick,\n                      text: this.locale.clear\n                    } satisfies DatePickerClearSlotProps,\n                    () => [\n                      <NxButton\n                        theme={mergedTheme.peers.Button}\n                        themeOverrides={mergedTheme.peerOverrides.Button}\n                        size=\"tiny\"\n                        onClick={this.handleClearClick}\n                      >\n                        {{ default: () => this.locale.clear }}\n                      </NxButton>\n                    ]\n                  )\n                : null}\n              {this.actions?.includes('confirm')\n                ? resolveSlotWithTypedProps(\n                    this.datePickerSlots.confirm,\n                    {\n                      disabled: this.isRangeInvalid,\n                      onConfirm: this.handleConfirmClick,\n                      text: this.locale.confirm\n                    } satisfies DatePickerConfirmSlotProps,\n                    () => [\n                      <NxButton\n                        theme={mergedTheme.peers.Button}\n                        themeOverrides={mergedTheme.peerOverrides.Button}\n                        size=\"tiny\"\n                        type=\"primary\"\n                        disabled={this.isRangeInvalid}\n                        onClick={this.handleConfirmClick}\n                      >\n                        {{ default: () => this.locale.confirm }}\n                      </NxButton>\n                    ]\n                  )\n                : null}\n            </div>\n          </div>\n        ) : null}\n        <NBaseFocusDetector onFocus={this.handleFocusDetectorFocus} />\n      </div>\n    )\n  }\n})\n"
  },
  {
    "path": "src/date-picker/src/panel/panelHeader.tsx",
    "content": "import type { PropType } from 'vue'\nimport { getPreciseEventTarget } from 'seemly'\nimport { clickoutside } from 'vdirs'\nimport { defineComponent, h, ref, Transition, withDirectives } from 'vue'\nimport { VBinder, VFollower, VTarget } from 'vueuc'\nimport MonthPanel from './month'\n\nexport default defineComponent({\n  props: {\n    mergedClsPrefix: {\n      type: String,\n      required: true\n    },\n    value: Number,\n    monthBeforeYear: {\n      type: Boolean,\n      required: true\n    },\n    monthYearSeparator: {\n      type: String,\n      required: true\n    },\n    fastYearSelect: Boolean,\n    fastMonthSelect: Boolean,\n    calendarMonth: {\n      type: String,\n      required: true\n    },\n    calendarYear: {\n      type: String,\n      required: true\n    },\n    onUpdateValue: {\n      type: Function as PropType<(value: number) => void>,\n      required: true\n    }\n  },\n  setup(props) {\n    const triggerRef = ref<HTMLElement | null>(null)\n    const monthPanelRef = ref<InstanceType<typeof MonthPanel> | null>(null)\n    const showRef = ref(false)\n    function toggleShow(): void {\n      showRef.value = !showRef.value\n    }\n    function handleSelectYear(): void {\n      if (props.fastYearSelect) {\n        toggleShow()\n      }\n    }\n    function handleSelectMonth(): void {\n      if (props.fastMonthSelect) {\n        toggleShow()\n      }\n    }\n    function handleClickOutside(e: MouseEvent): void {\n      if (\n        showRef.value\n        && !triggerRef.value?.contains(getPreciseEventTarget(e) as Node | null)\n      ) {\n        showRef.value = false\n      }\n    }\n    function handleHeaderClick(): void {\n      toggleShow()\n    }\n    return {\n      show: showRef,\n      triggerRef,\n      monthPanelRef,\n      handleSelectYear,\n      handleSelectMonth,\n      handleHeaderClick,\n      handleClickOutside\n    }\n  },\n  render() {\n    const { handleClickOutside, mergedClsPrefix } = this\n    return (\n      <div\n        class={`${mergedClsPrefix}-date-panel-month__month-year`}\n        ref=\"triggerRef\"\n      >\n        <VBinder>\n          {{\n            default: () => [\n              <VTarget>\n                {{\n                  default: () => (\n                    <div\n                      class={[\n                        `${mergedClsPrefix}-date-panel-month__text`,\n                        this.show\n                        && `${mergedClsPrefix}-date-panel-month__text--active`\n                      ]}\n                      onClick={this.handleHeaderClick}\n                    >\n                      {this.monthBeforeYear\n                        ? [\n                            this.calendarMonth,\n                            this.monthYearSeparator,\n                            this.calendarYear\n                          ]\n                        : [\n                            this.calendarYear,\n                            this.monthYearSeparator,\n                            this.calendarMonth\n                          ]}\n                    </div>\n                  )\n                }}\n              </VTarget>,\n              <VFollower show={this.show} teleportDisabled>\n                {{\n                  default: () => (\n                    <Transition name=\"fade-in-scale-up-transition\" appear>\n                      {{\n                        default: () =>\n                          this.show\n                            ? withDirectives(\n                                <MonthPanel\n                                  ref=\"monthPanelRef\"\n                                  onUpdateValue={this.onUpdateValue}\n                                  onSelectYear={this.handleSelectYear}\n                                  onSelectMonth={this.handleSelectMonth}\n                                  actions={[]}\n                                  calendarHeaderMonthYearSeparator={\n                                    this.monthYearSeparator\n                                  }\n                                  // month and year click show month type\n                                  type=\"month\"\n                                  key=\"month\"\n                                  useAsQuickJump\n                                  value={this.value}\n                                />,\n                                [\n                                  [\n                                    clickoutside,\n                                    handleClickOutside,\n                                    undefined as unknown as string,\n                                    { capture: true }\n                                  ]\n                                ]\n                              )\n                            : null\n                      }}\n                    </Transition>\n                  )\n                }}\n              </VFollower>\n            ]\n          }}\n        </VBinder>\n      </div>\n    )\n  }\n})\n"
  },
  {
    "path": "src/date-picker/src/panel/use-calendar.ts",
    "content": "import type { ExtractPropTypes, PropType } from 'vue'\nimport type { VirtualListInst } from 'vueuc'\nimport type { ScrollbarInst } from '../../../_internal'\nimport type {\n  DatePickerGetDefaultTime,\n  FirstDayOfWeek,\n  IsSingleDateDisabled,\n  IsSingleDateDisabledDetail,\n  PanelChildComponentRefs,\n  Shortcuts\n} from '../interface'\nimport type { DateItem, MonthItem, QuarterItem, YearItem } from '../utils'\nimport {\n  addMonths,\n  addYears,\n  format,\n  getDate,\n  getMonth,\n  getTime,\n  getYear,\n  isSameMonth,\n  isValid,\n  set,\n  setMonth,\n  setQuarter,\n  setYear,\n  startOfDay,\n  startOfMonth,\n  startOfQuarter,\n  startOfSecond,\n  startOfWeek,\n  startOfYear\n} from 'date-fns'\nimport { computed, inject, ref, watch } from 'vue'\nimport { MONTH_ITEM_HEIGHT } from '../config'\nimport { datePickerInjectionKey } from '../interface'\nimport {\n  dateArray,\n  extractSingleDefaultTime,\n  getDefaultTime,\n  monthArray,\n  quarterArray,\n  strictParse,\n  yearArray\n} from '../utils'\nimport { usePanelCommon, usePanelCommonProps } from './use-panel-common'\n\nconst useCalendarProps = {\n  ...usePanelCommonProps,\n  defaultCalendarStartTime: Number,\n  actions: {\n    type: Array as PropType<string[]>,\n    default: () => ['now', 'clear', 'confirm']\n  }\n} as const\n\nfunction useCalendar(\n  props: ExtractPropTypes<typeof useCalendarProps>,\n  type: 'date' | 'datetime' | 'month' | 'year' | 'quarter' | 'week'\n) {\n  const panelCommon = usePanelCommon(props)\n  const {\n    isValueInvalidRef,\n    isDateDisabledRef,\n    isDateInvalidRef,\n    isTimeInvalidRef,\n    isDateTimeInvalidRef,\n    isHourDisabledRef,\n    isMinuteDisabledRef,\n    isSecondDisabledRef,\n    localeRef,\n    firstDayOfWeekRef,\n    datePickerSlots,\n    yearFormatRef,\n    monthFormatRef,\n    quarterFormatRef,\n    yearRangeRef\n  } = inject(datePickerInjectionKey)!\n  const validation = {\n    isValueInvalid: isValueInvalidRef,\n    isDateDisabled: isDateDisabledRef,\n    isDateInvalid: isDateInvalidRef,\n    isTimeInvalid: isTimeInvalidRef,\n    isDateTimeInvalid: isDateTimeInvalidRef,\n    isHourDisabled: isHourDisabledRef,\n    isMinuteDisabled: isMinuteDisabledRef,\n    isSecondDisabled: isSecondDisabledRef\n  }\n  const mergedDateFormatRef = computed(\n    () => props.dateFormat || localeRef.value.dateFormat\n  )\n  const mergedDayFormatRef = computed(\n    () => props.calendarDayFormat || localeRef.value.dayFormat\n  )\n  const dateInputValueRef = ref(\n    props.value === null || Array.isArray(props.value)\n      ? ''\n      : format(props.value, mergedDateFormatRef.value)\n  )\n  const calendarValueRef = ref(\n    props.value === null || Array.isArray(props.value)\n      ? (props.defaultCalendarStartTime ?? Date.now())\n      : props.value\n  )\n  const yearVlRef = ref<VirtualListInst | null>(null)\n  const yearScrollbarRef = ref<ScrollbarInst | null>(null)\n  const monthScrollbarRef = ref<ScrollbarInst | null>(null)\n  const nowRef = ref(Date.now())\n  const dateArrayRef = computed(() => {\n    return dateArray(\n      calendarValueRef.value,\n      props.value,\n      nowRef.value,\n      firstDayOfWeekRef.value ?? localeRef.value.firstDayOfWeek,\n      false,\n      type === 'week'\n    )\n  })\n  const monthArrayRef = computed(() => {\n    const { value } = props\n    return monthArray(\n      calendarValueRef.value,\n      Array.isArray(value) ? null : value,\n      nowRef.value,\n      {\n        monthFormat: monthFormatRef.value\n      }\n    )\n  })\n  const yearArrayRef = computed(() => {\n    const { value } = props\n    return yearArray(\n      Array.isArray(value) ? null : value,\n      nowRef.value,\n      {\n        yearFormat: yearFormatRef.value\n      },\n      yearRangeRef\n    )\n  })\n  const quarterArrayRef = computed(() => {\n    const { value } = props\n    return quarterArray(\n      calendarValueRef.value,\n      Array.isArray(value) ? null : value,\n      nowRef.value,\n      {\n        quarterFormat: quarterFormatRef.value\n      }\n    )\n  })\n  const weekdaysRef = computed(() => {\n    return dateArrayRef.value.slice(0, 7).map((dateItem) => {\n      const { ts } = dateItem\n      return format(\n        ts,\n        mergedDayFormatRef.value,\n        panelCommon.dateFnsOptions.value\n      )\n    })\n  })\n  const calendarMonthRef = computed(() => {\n    return format(\n      calendarValueRef.value,\n      props.calendarHeaderMonthFormat || localeRef.value.monthFormat,\n      panelCommon.dateFnsOptions.value\n    )\n  })\n  const calendarYearRef = computed(() => {\n    return format(\n      calendarValueRef.value,\n      props.calendarHeaderYearFormat || localeRef.value.yearFormat,\n      panelCommon.dateFnsOptions.value\n    )\n  })\n  const calendarMonthBeforeYearRef = computed(() => {\n    return (\n      props.calendarHeaderMonthBeforeYear ?? localeRef.value.monthBeforeYear\n    )\n  })\n  watch(calendarValueRef, (value, oldValue) => {\n    if (type === 'date' || type === 'datetime') {\n      if (!isSameMonth(value, oldValue)) {\n        panelCommon.disableTransitionOneTick()\n      }\n    }\n  })\n  watch(\n    computed(() => props.value),\n    (value) => {\n      if (value !== null && !Array.isArray(value)) {\n        dateInputValueRef.value = format(\n          value,\n          mergedDateFormatRef.value,\n          panelCommon.dateFnsOptions.value\n        )\n        calendarValueRef.value = value\n      }\n      else {\n        dateInputValueRef.value = ''\n      }\n    }\n  )\n\n  function sanitizeValue(value: number): number {\n    if (type === 'datetime')\n      return getTime(startOfSecond(value))\n    if (type === 'month')\n      return getTime(startOfMonth(value))\n    if (type === 'year')\n      return getTime(startOfYear(value))\n    if (type === 'quarter')\n      return getTime(startOfQuarter(value))\n    if (type === 'week') {\n      // refer to makeWeekMatcher\n      const weekStartsOn = (((firstDayOfWeekRef.value\n        ?? localeRef.value.firstDayOfWeek)\n      + 1)\n    % 7) as FirstDayOfWeek\n      return getTime(\n        startOfWeek(value, {\n          weekStartsOn\n        })\n      )\n    }\n    return getTime(startOfDay(value))\n  }\n  function mergedIsDateDisabled(\n    ts: number,\n    detail: IsSingleDateDisabledDetail\n  ): boolean {\n    const {\n      isDateDisabled: { value: isDateDisabled }\n    } = validation\n    if (!isDateDisabled)\n      return false\n    return (isDateDisabled as IsSingleDateDisabled)(ts, detail)\n  }\n  function handleDateInput(value: string): void {\n    const date = strictParse(\n      value,\n      mergedDateFormatRef.value,\n      new Date(),\n      panelCommon.dateFnsOptions.value\n    )\n    if (isValid(date)) {\n      if (props.value === null) {\n        panelCommon.doUpdateValue(\n          getTime(sanitizeValue(Date.now())),\n          props.panel\n        )\n      }\n      else if (!Array.isArray(props.value)) {\n        const newDateTime = set(props.value, {\n          year: getYear(date),\n          month: getMonth(date),\n          date: getDate(date)\n        })\n        panelCommon.doUpdateValue(\n          getTime(sanitizeValue(getTime(newDateTime))),\n          props.panel\n        )\n      }\n    }\n    else {\n      dateInputValueRef.value = value\n    }\n  }\n  function handleDateInputBlur(): void {\n    const date = strictParse(\n      dateInputValueRef.value,\n      mergedDateFormatRef.value,\n      new Date(),\n      panelCommon.dateFnsOptions.value\n    )\n    if (isValid(date)) {\n      if (props.value === null) {\n        panelCommon.doUpdateValue(getTime(sanitizeValue(Date.now())), false)\n      }\n      else if (!Array.isArray(props.value)) {\n        const newDateTime = set(props.value, {\n          year: getYear(date),\n          month: getMonth(date),\n          date: getDate(date)\n        })\n        panelCommon.doUpdateValue(\n          getTime(sanitizeValue(getTime(newDateTime))),\n          false\n        )\n      }\n    }\n    else {\n      deriveDateInputValue()\n    }\n  }\n  function clearSelectedDateTime(): void {\n    panelCommon.doUpdateValue(null, true)\n    dateInputValueRef.value = ''\n    panelCommon.doClose(true)\n    panelCommon.handleClearClick()\n  }\n  function handleNowClick(): void {\n    panelCommon.doUpdateValue(getTime(sanitizeValue(Date.now())), true)\n    const now = Date.now()\n    calendarValueRef.value = now\n    panelCommon.doClose(true)\n    if (\n      props.panel\n      && (type === 'month' || type === 'quarter' || type === 'year')\n    ) {\n      panelCommon.disableTransitionOneTick()\n      justifyColumnsScrollState(now)\n    }\n  }\n  const hoveredWeekRef = ref<number | null>(null)\n  function handleDateMouseEnter(\n    dateItem: DateItem | MonthItem | YearItem | QuarterItem\n  ): void {\n    if (dateItem.type === 'date' && type === 'week') {\n      hoveredWeekRef.value = sanitizeValue(getTime(dateItem.ts))\n    }\n  }\n  function isWeekHovered(\n    dateItem: DateItem | MonthItem | YearItem | QuarterItem\n  ): boolean {\n    if (dateItem.type === 'date' && type === 'week') {\n      return sanitizeValue(getTime(dateItem.ts)) === hoveredWeekRef.value\n    }\n    return false\n  }\n  function handleDateClick(\n    dateItem: DateItem | MonthItem | YearItem | QuarterItem\n  ): void {\n    if (\n      mergedIsDateDisabled(\n        dateItem.ts,\n        dateItem.type === 'date'\n          ? {\n              type: 'date',\n              year: dateItem.dateObject.year,\n              month: dateItem.dateObject.month,\n              date: dateItem.dateObject.date\n            }\n          : dateItem.type === 'month'\n            ? {\n                type: 'month',\n                year: dateItem.dateObject.year,\n                month: dateItem.dateObject.month\n              }\n            : dateItem.type === 'year'\n              ? { type: 'year', year: dateItem.dateObject.year }\n              : {\n                  type: 'quarter',\n                  year: dateItem.dateObject.year,\n                  quarter: dateItem.dateObject.quarter\n                }\n      )\n    ) {\n      return\n    }\n    let newValue: number\n    if (props.value !== null && !Array.isArray(props.value)) {\n      newValue = props.value\n    }\n    else {\n      newValue = Date.now()\n    }\n    if (\n      type === 'datetime'\n      && props.defaultTime !== null\n      && !Array.isArray(props.defaultTime)\n    ) {\n      let time: { hours: number, minutes: number, seconds: number } | undefined\n\n      if (typeof props.defaultTime === 'function') {\n        time = extractSingleDefaultTime(\n          dateItem.ts,\n          props.defaultTime as DatePickerGetDefaultTime\n        )\n      }\n      else {\n        time = getDefaultTime(props.defaultTime)\n      }\n\n      if (time) {\n        newValue = getTime(set(newValue, time)) // setDate getTime(addMilliseconds(startOfDay(newValue), time))\n      }\n    }\n    newValue = getTime(\n      dateItem.type === 'quarter' && dateItem.dateObject.quarter\n        ? setQuarter(\n            setYear(newValue, dateItem.dateObject.year),\n            dateItem.dateObject.quarter\n          )\n        : set(newValue, dateItem.dateObject)\n    )\n    panelCommon.doUpdateValue(\n      sanitizeValue(newValue),\n      props.panel || type === 'date' || type === 'week' || type === 'year'\n    )\n    switch (type) {\n      case 'date':\n      case 'week':\n        panelCommon.doClose()\n        break\n      case 'year':\n        if (props.panel) {\n          panelCommon.disableTransitionOneTick()\n        }\n        panelCommon.doClose()\n        break\n      case 'month':\n        panelCommon.disableTransitionOneTick()\n        justifyColumnsScrollState(newValue)\n        break\n      case 'quarter':\n        panelCommon.disableTransitionOneTick()\n        justifyColumnsScrollState(newValue)\n        break\n    }\n  }\n\n  function handleQuickMonthClick(\n    dateItem: MonthItem | YearItem | QuarterItem,\n    updatePanelValue: (value: number) => void\n  ): void {\n    let newValue: number\n    if (props.value !== null && !Array.isArray(props.value)) {\n      newValue = props.value\n    }\n    else {\n      newValue = Date.now()\n    }\n    newValue = getTime(\n      dateItem.type === 'month'\n        ? setMonth(newValue, dateItem.dateObject.month)\n        : setYear(newValue, dateItem.dateObject.year)\n    )\n    updatePanelValue(newValue)\n    justifyColumnsScrollState(newValue)\n  }\n  function onUpdateCalendarValue(value: number): void {\n    calendarValueRef.value = value\n  }\n  function deriveDateInputValue(time?: number): void {\n    // If not selected, display nothing,\n    // else update datetime related string\n    if (props.value === null || Array.isArray(props.value)) {\n      dateInputValueRef.value = ''\n      return\n    }\n    if (time === undefined) {\n      time = props.value\n    }\n    dateInputValueRef.value = format(\n      time,\n      mergedDateFormatRef.value,\n      panelCommon.dateFnsOptions.value\n    )\n  }\n  function handleConfirmClick(): void {\n    if (validation.isDateInvalid.value || validation.isTimeInvalid.value) {\n      return\n    }\n    panelCommon.doConfirm()\n    closeCalendar()\n  }\n  function closeCalendar(): void {\n    if (props.active) {\n      panelCommon.doClose()\n    }\n  }\n  function nextYear(): void {\n    calendarValueRef.value = getTime(addYears(calendarValueRef.value, 1))\n    props.onNextYear?.()\n  }\n  function prevYear(): void {\n    calendarValueRef.value = getTime(addYears(calendarValueRef.value, -1))\n    props.onPrevYear?.()\n  }\n  function nextMonth(): void {\n    calendarValueRef.value = getTime(addMonths(calendarValueRef.value, 1))\n    props.onNextMonth?.()\n  }\n  function prevMonth(): void {\n    calendarValueRef.value = getTime(addMonths(calendarValueRef.value, -1))\n    props.onPrevMonth?.()\n  }\n  // For month type\n  function virtualListContainer(): HTMLElement | null {\n    const { value } = yearVlRef\n    return value?.listElRef || null\n  }\n  // For month type\n  function virtualListContent(): HTMLElement | null {\n    const { value } = yearVlRef\n    return value?.itemsElRef || null\n  }\n  // For month type\n  function handleVirtualListScroll(): void {\n    yearScrollbarRef.value?.sync()\n  }\n  function handleTimePickerChange(value: number | null): void {\n    if (value === null)\n      return\n    panelCommon.doUpdateValue(value, props.panel)\n  }\n  function handleSingleShortcutMouseenter(shortcut: Shortcuts[string]): void {\n    panelCommon.cachePendingValue()\n    const shortcutValue = panelCommon.getShortcutValue(shortcut)\n    if (typeof shortcutValue !== 'number')\n      return\n    panelCommon.doUpdateValue(shortcutValue, false)\n  }\n  function handleSingleShortcutClick(shortcut: Shortcuts[string]): void {\n    const shortcutValue = panelCommon.getShortcutValue(shortcut)\n    if (typeof shortcutValue !== 'number')\n      return\n    panelCommon.doUpdateValue(shortcutValue, props.panel)\n    panelCommon.clearPendingValue()\n    handleConfirmClick()\n  }\n\n  function justifyColumnsScrollState(value?: number): void {\n    const { value: mergedValue } = props\n    if (monthScrollbarRef.value) {\n      const monthIndex\n        = value === undefined\n          ? mergedValue === null\n            ? getMonth(Date.now())\n            : getMonth(mergedValue as number)\n          : getMonth(value)\n      monthScrollbarRef.value.scrollTo({ top: monthIndex * MONTH_ITEM_HEIGHT })\n    }\n    if (yearVlRef.value) {\n      const yearIndex\n        = (value === undefined\n          ? mergedValue === null\n            ? getYear(Date.now())\n            : getYear(mergedValue as number)\n          : getYear(value)) - yearRangeRef.value[0]\n      yearVlRef.value.scrollTo({ top: yearIndex * MONTH_ITEM_HEIGHT })\n    }\n  }\n\n  const childComponentRefs: PanelChildComponentRefs = {\n    monthScrollbarRef,\n    yearScrollbarRef,\n    yearVlRef\n  }\n  return {\n    dateArray: dateArrayRef,\n    monthArray: monthArrayRef,\n    yearArray: yearArrayRef,\n    quarterArray: quarterArrayRef,\n    calendarYear: calendarYearRef,\n    calendarMonth: calendarMonthRef,\n    weekdays: weekdaysRef,\n    calendarMonthBeforeYear: calendarMonthBeforeYearRef,\n    mergedIsDateDisabled,\n    nextYear,\n    prevYear,\n    nextMonth,\n    prevMonth,\n    handleNowClick,\n    handleConfirmClick,\n    handleSingleShortcutMouseenter,\n    handleSingleShortcutClick,\n    ...validation,\n    ...panelCommon,\n    ...childComponentRefs,\n    // datetime only\n    handleDateClick,\n    handleDateInputBlur,\n    handleDateInput,\n    handleDateMouseEnter,\n    isWeekHovered,\n    handleTimePickerChange,\n    clearSelectedDateTime,\n    virtualListContainer,\n    virtualListContent,\n    handleVirtualListScroll,\n    timePickerSize: panelCommon.timePickerSize,\n    dateInputValue: dateInputValueRef,\n    datePickerSlots,\n    handleQuickMonthClick,\n    justifyColumnsScrollState,\n    calendarValue: calendarValueRef,\n    onUpdateCalendarValue\n  }\n}\n\nexport { useCalendar, useCalendarProps }\n"
  },
  {
    "path": "src/date-picker/src/panel/use-dual-calendar.ts",
    "content": "import type { ExtractPropTypes, PropType } from 'vue'\nimport type { VirtualListInst } from 'vueuc'\nimport type { ScrollbarInst } from '../../../_internal'\nimport type {\n  IsRangeDateDisabled,\n  RangePanelChildComponentRefs,\n  Shortcuts\n} from '../interface'\nimport type { DateItem, MonthItem, QuarterItem, YearItem } from '../utils'\nimport {\n  addMonths,\n  format,\n  getDate,\n  getMonth,\n  getTime,\n  getYear,\n  isValid,\n  set,\n  startOfDay,\n  startOfMonth,\n  startOfQuarter,\n  startOfSecond\n} from 'date-fns'\nimport { computed, inject, ref, watch } from 'vue'\nimport { MONTH_ITEM_HEIGHT } from '../config'\nimport { datePickerInjectionKey } from '../interface'\nimport {\n  dateArray,\n  extractRangeDefaultTime,\n  getDefaultTime,\n  monthArray,\n  pluckValueFromRange,\n  quarterArray,\n  strictParse,\n  yearArray\n} from '../utils'\nimport { usePanelCommon, usePanelCommonProps } from './use-panel-common'\n\nconst useDualCalendarProps = {\n  ...usePanelCommonProps,\n  defaultCalendarStartTime: Number,\n  defaultCalendarEndTime: Number,\n  bindCalendarMonths: Boolean,\n  actions: {\n    type: Array as PropType<string[]>,\n    default: () => ['clear', 'confirm']\n  }\n} as const\n\nfunction useDualCalendar(\n  props: ExtractPropTypes<typeof useDualCalendarProps>,\n  type:\n    | 'daterange'\n    | 'datetimerange'\n    | 'monthrange'\n    | 'quarterrange'\n    | 'yearrange'\n) {\n  const {\n    isDateDisabledRef,\n    isStartHourDisabledRef,\n    isEndHourDisabledRef,\n    isStartMinuteDisabledRef,\n    isEndMinuteDisabledRef,\n    isStartSecondDisabledRef,\n    isEndSecondDisabledRef,\n    isStartDateInvalidRef,\n    isEndDateInvalidRef,\n    isStartTimeInvalidRef,\n    isEndTimeInvalidRef,\n    isStartValueInvalidRef,\n    isEndValueInvalidRef,\n    isRangeInvalidRef,\n    localeRef,\n    rangesRef,\n    closeOnSelectRef,\n    updateValueOnCloseRef,\n    firstDayOfWeekRef,\n    datePickerSlots,\n    monthFormatRef,\n    yearFormatRef,\n    quarterFormatRef,\n    yearRangeRef\n  } = inject(datePickerInjectionKey)!\n  const validation = {\n    isDateDisabled: isDateDisabledRef,\n    isStartHourDisabled: isStartHourDisabledRef,\n    isEndHourDisabled: isEndHourDisabledRef,\n    isStartMinuteDisabled: isStartMinuteDisabledRef,\n    isEndMinuteDisabled: isEndMinuteDisabledRef,\n    isStartSecondDisabled: isStartSecondDisabledRef,\n    isEndSecondDisabled: isEndSecondDisabledRef,\n    isStartDateInvalid: isStartDateInvalidRef,\n    isEndDateInvalid: isEndDateInvalidRef,\n    isStartTimeInvalid: isStartTimeInvalidRef,\n    isEndTimeInvalid: isEndTimeInvalidRef,\n    isStartValueInvalid: isStartValueInvalidRef,\n    isEndValueInvalid: isEndValueInvalidRef,\n    isRangeInvalid: isRangeInvalidRef\n  }\n  const panelCommon = usePanelCommon(props)\n  const startDatesElRef = ref<HTMLElement | null>(null)\n  const endDatesElRef = ref<HTMLElement | null>(null)\n  const startYearScrollbarRef = ref<ScrollbarInst | null>(null)\n  const endYearScrollbarRef = ref<ScrollbarInst | null>(null)\n  const startYearVlRef = ref<VirtualListInst | null>(null)\n  const endYearVlRef = ref<VirtualListInst | null>(null)\n  const startMonthScrollbarRef = ref<ScrollbarInst | null>(null)\n  const endMonthScrollbarRef = ref<ScrollbarInst | null>(null)\n  const { value } = props\n  const defaultCalendarStartTime\n    = props.defaultCalendarStartTime\n      ?? (Array.isArray(value) && typeof value[0] === 'number'\n        ? value[0]\n        : Date.now())\n  const startCalendarDateTimeRef = ref(defaultCalendarStartTime)\n  const endCalendarDateTimeRef = ref(\n    props.defaultCalendarEndTime\n    ?? (Array.isArray(value) && typeof value[1] === 'number'\n      ? value[1]\n      : getTime(addMonths(defaultCalendarStartTime, 1)))\n  )\n  adjustCalendarTimes(true)\n  const nowRef = ref(Date.now())\n  const isSelectingRef = ref(false)\n  const memorizedStartDateTimeRef = ref<number>(0)\n\n  const mergedDateFormatRef = computed(\n    () => props.dateFormat || localeRef.value.dateFormat\n  )\n\n  const mergedDayFormatRef = computed(\n    () => props.calendarDayFormat || localeRef.value.dayFormat\n  )\n\n  const startDateInput = ref(\n    Array.isArray(value)\n      ? format(\n          value[0],\n          mergedDateFormatRef.value,\n          panelCommon.dateFnsOptions.value\n        )\n      : ''\n  )\n  const endDateInputRef = ref(\n    Array.isArray(value)\n      ? format(\n          value[1],\n          mergedDateFormatRef.value,\n          panelCommon.dateFnsOptions.value\n        )\n      : ''\n  )\n\n  // derived computed\n  const selectingPhaseRef = computed(() => {\n    if (isSelectingRef.value)\n      return 'end'\n    else return 'start'\n  })\n  const startDateArrayRef = computed(() => {\n    return dateArray(\n      startCalendarDateTimeRef.value,\n      props.value,\n      nowRef.value,\n      firstDayOfWeekRef.value ?? localeRef.value.firstDayOfWeek\n    )\n  })\n  const endDateArrayRef = computed(() => {\n    return dateArray(\n      endCalendarDateTimeRef.value,\n      props.value,\n      nowRef.value,\n      firstDayOfWeekRef.value ?? localeRef.value.firstDayOfWeek\n    )\n  })\n  const weekdaysRef = computed(() => {\n    return startDateArrayRef.value.slice(0, 7).map((dateItem) => {\n      const { ts } = dateItem\n      return format(\n        ts,\n        mergedDayFormatRef.value,\n        panelCommon.dateFnsOptions.value\n      )\n    })\n  })\n  const startCalendarMonthRef = computed(() => {\n    return format(\n      startCalendarDateTimeRef.value,\n      props.calendarHeaderMonthFormat || localeRef.value.monthFormat,\n      panelCommon.dateFnsOptions.value\n    )\n  })\n  const endCalendarMonthRef = computed(() => {\n    return format(\n      endCalendarDateTimeRef.value,\n      props.calendarHeaderMonthFormat || localeRef.value.monthFormat,\n      panelCommon.dateFnsOptions.value\n    )\n  })\n  const startCalendarYearRef = computed(() => {\n    return format(\n      startCalendarDateTimeRef.value,\n      props.calendarHeaderYearFormat || localeRef.value.yearFormat,\n      panelCommon.dateFnsOptions.value\n    )\n  })\n  const endCalendarYearRef = computed(() => {\n    return format(\n      endCalendarDateTimeRef.value,\n      props.calendarHeaderYearFormat || localeRef.value.yearFormat,\n      panelCommon.dateFnsOptions.value\n    )\n  })\n  const startTimeValueRef = computed(() => {\n    const { value } = props\n    if (Array.isArray(value))\n      return value[0]\n    return null\n  })\n  const endTimeValueRef = computed(() => {\n    const { value } = props\n    if (Array.isArray(value))\n      return value[1]\n    return null\n  })\n  const shortcutsRef = computed(() => {\n    const { shortcuts } = props\n    return shortcuts || rangesRef.value\n  })\n  const startYearArrayRef = computed(() => {\n    return yearArray(\n      pluckValueFromRange(props.value, 'start'),\n      nowRef.value,\n      {\n        yearFormat: yearFormatRef.value\n      },\n      yearRangeRef\n    )\n  })\n  const endYearArrayRef = computed(() => {\n    return yearArray(\n      pluckValueFromRange(props.value, 'end'),\n      nowRef.value,\n      {\n        yearFormat: yearFormatRef.value\n      },\n      yearRangeRef\n    )\n  })\n  const startQuarterArrayRef = computed(() => {\n    const startValue = pluckValueFromRange(props.value, 'start')\n    return quarterArray(startValue ?? Date.now(), startValue, nowRef.value, {\n      quarterFormat: quarterFormatRef.value\n    })\n  })\n  const endQuarterArrayRef = computed(() => {\n    const endValue = pluckValueFromRange(props.value, 'end')\n    return quarterArray(endValue ?? Date.now(), endValue, nowRef.value, {\n      quarterFormat: quarterFormatRef.value\n    })\n  })\n  const startMonthArrayRef = computed(() => {\n    const startValue = pluckValueFromRange(props.value, 'start')\n    return monthArray(startValue ?? Date.now(), startValue, nowRef.value, {\n      monthFormat: monthFormatRef.value\n    })\n  })\n  const endMonthArrayRef = computed(() => {\n    const endValue = pluckValueFromRange(props.value, 'end')\n    return monthArray(endValue ?? Date.now(), endValue, nowRef.value, {\n      monthFormat: monthFormatRef.value\n    })\n  })\n  const calendarMonthBeforeYearRef = computed(() => {\n    return (\n      props.calendarHeaderMonthBeforeYear ?? localeRef.value.monthBeforeYear\n    )\n  })\n  watch(\n    computed(() => props.value),\n    (value) => {\n      if (value !== null && Array.isArray(value)) {\n        const [startMoment, endMoment] = value\n        startDateInput.value = format(\n          startMoment,\n          mergedDateFormatRef.value,\n          panelCommon.dateFnsOptions.value\n        )\n        endDateInputRef.value = format(\n          endMoment,\n          mergedDateFormatRef.value,\n          panelCommon.dateFnsOptions.value\n        )\n        if (!isSelectingRef.value) {\n          syncCalendarTimeWithValue(value)\n        }\n      }\n      else {\n        startDateInput.value = ''\n        endDateInputRef.value = ''\n      }\n    }\n  )\n  function handleCalendarChange(value: number, oldValue: number): void {\n    if (type === 'daterange' || type === 'datetimerange') {\n      if (\n        getYear(value) !== getYear(oldValue)\n        || getMonth(value) !== getMonth(oldValue)\n      ) {\n        panelCommon.disableTransitionOneTick()\n      }\n    }\n  }\n  watch(startCalendarDateTimeRef, handleCalendarChange)\n  watch(endCalendarDateTimeRef, handleCalendarChange)\n  // change calendar\n  function adjustCalendarTimes(byStartCalendarTime: boolean): void {\n    const startTime = startOfMonth(startCalendarDateTimeRef.value)\n    const endTime = startOfMonth(endCalendarDateTimeRef.value)\n    if (props.bindCalendarMonths || startTime >= endTime) {\n      if (byStartCalendarTime) {\n        endCalendarDateTimeRef.value = getTime(addMonths(startTime, 1))\n      }\n      else {\n        startCalendarDateTimeRef.value = getTime(addMonths(endTime, -1))\n      }\n    }\n  }\n  function startCalendarNextYear(): void {\n    startCalendarDateTimeRef.value = getTime(\n      addMonths(startCalendarDateTimeRef.value, 12)\n    )\n    adjustCalendarTimes(true)\n  }\n  function startCalendarPrevYear(): void {\n    startCalendarDateTimeRef.value = getTime(\n      addMonths(startCalendarDateTimeRef.value, -12)\n    )\n    adjustCalendarTimes(true)\n  }\n  function startCalendarNextMonth(): void {\n    startCalendarDateTimeRef.value = getTime(\n      addMonths(startCalendarDateTimeRef.value, 1)\n    )\n    adjustCalendarTimes(true)\n  }\n  function startCalendarPrevMonth(): void {\n    startCalendarDateTimeRef.value = getTime(\n      addMonths(startCalendarDateTimeRef.value, -1)\n    )\n    adjustCalendarTimes(true)\n  }\n  function endCalendarNextYear(): void {\n    endCalendarDateTimeRef.value = getTime(\n      addMonths(endCalendarDateTimeRef.value, 12)\n    )\n    adjustCalendarTimes(false)\n  }\n  function endCalendarPrevYear(): void {\n    endCalendarDateTimeRef.value = getTime(\n      addMonths(endCalendarDateTimeRef.value, -12)\n    )\n    adjustCalendarTimes(false)\n  }\n  function endCalendarNextMonth(): void {\n    endCalendarDateTimeRef.value = getTime(\n      addMonths(endCalendarDateTimeRef.value, 1)\n    )\n    adjustCalendarTimes(false)\n  }\n  function endCalendarPrevMonth(): void {\n    endCalendarDateTimeRef.value = getTime(\n      addMonths(endCalendarDateTimeRef.value, -1)\n    )\n    adjustCalendarTimes(false)\n  }\n  function onUpdateStartCalendarValue(value: number): void {\n    startCalendarDateTimeRef.value = value\n    adjustCalendarTimes(true)\n  }\n\n  function onUpdateEndCalendarValue(value: number): void {\n    endCalendarDateTimeRef.value = value\n    adjustCalendarTimes(false)\n  }\n\n  // The function is used on date panel, not the date-picker value validation\n  function mergedIsDateDisabled(ts: number): boolean {\n    const isDateDisabled = isDateDisabledRef.value\n    if (!isDateDisabled)\n      return false\n    if (!Array.isArray(props.value)) {\n      return (isDateDisabled as IsRangeDateDisabled)(ts, 'start', null)\n    }\n    if (selectingPhaseRef.value === 'start') {\n      // before you really start to select\n      return (isDateDisabled as IsRangeDateDisabled)(ts, 'start', null)\n    }\n    else {\n      const { value: memorizedStartDateTime } = memorizedStartDateTimeRef\n      // after you starting to select\n      if (ts < memorizedStartDateTimeRef.value) {\n        return (isDateDisabled as IsRangeDateDisabled)(ts, 'start', [\n          memorizedStartDateTime,\n          memorizedStartDateTime\n        ])\n      }\n      else {\n        return (isDateDisabled as IsRangeDateDisabled)(ts, 'end', [\n          memorizedStartDateTime,\n          memorizedStartDateTime\n        ])\n      }\n    }\n  }\n  function syncCalendarTimeWithValue(value: [number, number] | null): void {\n    if (value === null)\n      return\n    const [startMoment, endMoment] = value\n    startCalendarDateTimeRef.value = startMoment\n    if (startOfMonth(endMoment) <= startOfMonth(startMoment)) {\n      endCalendarDateTimeRef.value = getTime(\n        startOfMonth(addMonths(startMoment, 1))\n      )\n    }\n    else {\n      endCalendarDateTimeRef.value = getTime(startOfMonth(endMoment))\n    }\n  }\n  // for daterange & datetimerange\n  function handleDateClick(dateItem: DateItem): void {\n    if (!isSelectingRef.value) {\n      isSelectingRef.value = true\n      memorizedStartDateTimeRef.value = dateItem.ts\n      changeStartEndTime(dateItem.ts, dateItem.ts, 'done')\n    }\n    else {\n      isSelectingRef.value = false\n      const { value } = props\n      if (props.panel && Array.isArray(value)) {\n        changeStartEndTime(value[0], value[1], 'done')\n      }\n      else {\n        if (closeOnSelectRef.value && type === 'daterange') {\n          if (updateValueOnCloseRef.value) {\n            closeCalendar()\n          }\n          else {\n            handleConfirmClick()\n          }\n        }\n      }\n    }\n  }\n  function handleDateMouseEnter(dateItem: DateItem): void {\n    if (isSelectingRef.value) {\n      if (mergedIsDateDisabled(dateItem.ts))\n        return\n      if (dateItem.ts >= memorizedStartDateTimeRef.value) {\n        changeStartEndTime(\n          memorizedStartDateTimeRef.value,\n          dateItem.ts,\n          'wipPreview'\n        )\n      }\n      else {\n        changeStartEndTime(\n          dateItem.ts,\n          memorizedStartDateTimeRef.value,\n          'wipPreview'\n        )\n      }\n    }\n  }\n  function handleConfirmClick(): void {\n    if (isRangeInvalidRef.value) {\n      return\n    }\n    panelCommon.doConfirm()\n    closeCalendar()\n  }\n  function closeCalendar(): void {\n    isSelectingRef.value = false\n    if (props.active) {\n      panelCommon.doClose()\n    }\n  }\n  function changeStartDateTime(time: number): void {\n    if (typeof time !== 'number') {\n      time = getTime(time)\n    }\n    if (props.value === null) {\n      panelCommon.doUpdateValue([time, time], props.panel)\n    }\n    else if (Array.isArray(props.value)) {\n      panelCommon.doUpdateValue(\n        [time, Math.max(props.value[1], time)],\n        props.panel\n      )\n    }\n  }\n  function changeEndDateTime(time: number): void {\n    if (typeof time !== 'number') {\n      time = getTime(time)\n    }\n    if (props.value === null) {\n      panelCommon.doUpdateValue([time, time], props.panel)\n    }\n    else if (Array.isArray(props.value)) {\n      panelCommon.doUpdateValue(\n        [Math.min(props.value[0], time), time],\n        props.panel\n      )\n    }\n  }\n  function changeStartEndTime(\n    startTime: number,\n    endTime: number,\n    source: 'shortcutPreview' | 'wipPreview' | 'done' | 'shortcutDone'\n  ): void {\n    if (typeof startTime !== 'number') {\n      startTime = getTime(startTime)\n    }\n\n    if (source !== 'shortcutPreview' && source !== 'shortcutDone') {\n      let startDefaultTime:\n        | { hours: number, minutes: number, seconds: number }\n        | undefined\n      let endDefaultTime:\n        | { hours: number, minutes: number, seconds: number }\n        | undefined\n      if (type === 'datetimerange') {\n        const { defaultTime } = props\n        if (typeof defaultTime === 'function') {\n          startDefaultTime = extractRangeDefaultTime(\n            startTime,\n            defaultTime,\n            'start',\n            [startTime, endTime]\n          )\n          endDefaultTime = extractRangeDefaultTime(\n            endTime,\n            defaultTime,\n            'end',\n            [startTime, endTime]\n          )\n        }\n        else if (Array.isArray(defaultTime)) {\n          startDefaultTime = getDefaultTime(defaultTime[0])\n          endDefaultTime = getDefaultTime(defaultTime[1])\n        }\n        else {\n          startDefaultTime = getDefaultTime(defaultTime)\n          endDefaultTime = startDefaultTime\n        }\n      }\n      if (startDefaultTime) {\n        startTime = getTime(set(startTime, startDefaultTime))\n      }\n      if (endDefaultTime) {\n        endTime = getTime(set(endTime, endDefaultTime))\n      }\n    }\n\n    panelCommon.doUpdateValue(\n      [startTime, endTime],\n      props.panel && (source === 'done' || source === 'shortcutDone')\n    )\n  }\n  function sanitizeValue(datetime: number): number {\n    if (type === 'datetimerange') {\n      return getTime(startOfSecond(datetime))\n    }\n    else if (type === 'monthrange') {\n      return getTime(startOfMonth(datetime))\n    }\n    else {\n      // daterange\n      return getTime(startOfDay(datetime))\n    }\n  }\n  function handleStartDateInput(value: string): void {\n    const date = strictParse(\n      value,\n      mergedDateFormatRef.value,\n      new Date(),\n      panelCommon.dateFnsOptions.value\n    )\n    if (isValid(date)) {\n      if (!props.value) {\n        const newValue = set(new Date(), {\n          year: getYear(date),\n          month: getMonth(date),\n          date: getDate(date)\n        })\n        changeStartDateTime(sanitizeValue(getTime(newValue)))\n      }\n      else if (Array.isArray(props.value)) {\n        const newValue = set(props.value[0], {\n          year: getYear(date),\n          month: getMonth(date),\n          date: getDate(date)\n        })\n        changeStartDateTime(sanitizeValue(getTime(newValue)))\n      }\n    }\n    else {\n      startDateInput.value = value\n    }\n  }\n  function handleEndDateInput(value: string): void {\n    /** strict check when input */\n    const date = strictParse(\n      value,\n      mergedDateFormatRef.value,\n      new Date(),\n      panelCommon.dateFnsOptions.value\n    )\n    if (isValid(date)) {\n      if (props.value === null) {\n        const newValue = set(new Date(), {\n          year: getYear(date),\n          month: getMonth(date),\n          date: getDate(date)\n        })\n        changeEndDateTime(sanitizeValue(getTime(newValue)))\n      }\n      else if (Array.isArray(props.value)) {\n        const newValue = set(props.value[1], {\n          year: getYear(date),\n          month: getMonth(date),\n          date: getDate(date)\n        })\n        changeEndDateTime(sanitizeValue(getTime(newValue)))\n      }\n    }\n    else {\n      endDateInputRef.value = value\n    }\n  }\n  function handleStartDateInputBlur(): void {\n    const date = strictParse(\n      startDateInput.value,\n      mergedDateFormatRef.value,\n      new Date(),\n      panelCommon.dateFnsOptions.value\n    )\n    const { value } = props\n    if (isValid(date)) {\n      if (value === null) {\n        const newValue = set(new Date(), {\n          year: getYear(date),\n          month: getMonth(date),\n          date: getDate(date)\n        })\n        changeStartDateTime(sanitizeValue(getTime(newValue)))\n      }\n      else if (Array.isArray(value)) {\n        const newValue = set(value[0], {\n          year: getYear(date),\n          month: getMonth(date),\n          date: getDate(date)\n        })\n        changeStartDateTime(sanitizeValue(getTime(newValue)))\n      }\n    }\n    else {\n      refreshDisplayDateString()\n    }\n  }\n  function handleEndDateInputBlur(): void {\n    const date = strictParse(\n      endDateInputRef.value,\n      mergedDateFormatRef.value,\n      new Date(),\n      panelCommon.dateFnsOptions.value\n    )\n    const { value } = props\n    if (isValid(date)) {\n      if (value === null) {\n        const newValue = set(new Date(), {\n          year: getYear(date),\n          month: getMonth(date),\n          date: getDate(date)\n        })\n        changeEndDateTime(sanitizeValue(getTime(newValue)))\n      }\n      else if (Array.isArray(value)) {\n        const newValue = set(value[1], {\n          year: getYear(date),\n          month: getMonth(date),\n          date: getDate(date)\n        })\n        changeEndDateTime(sanitizeValue(getTime(newValue)))\n      }\n    }\n    else {\n      refreshDisplayDateString()\n    }\n  }\n  function refreshDisplayDateString(times?: [number, number]): void {\n    // If not selected, display nothing,\n    // else update datetime related string\n    const { value } = props\n    if (value === null || !Array.isArray(value)) {\n      startDateInput.value = ''\n      endDateInputRef.value = ''\n      return\n    }\n    if (times === undefined) {\n      times = value\n    }\n    startDateInput.value = format(\n      times[0],\n      mergedDateFormatRef.value,\n      panelCommon.dateFnsOptions.value\n    )\n    endDateInputRef.value = format(\n      times[1],\n      mergedDateFormatRef.value,\n      panelCommon.dateFnsOptions.value\n    )\n  }\n  function handleStartTimePickerChange(value: number | null): void {\n    if (value === null)\n      return\n    changeStartDateTime(value)\n  }\n  function handleEndTimePickerChange(value: number | null): void {\n    if (value === null)\n      return\n    changeEndDateTime(value)\n  }\n  function handleRangeShortcutMouseenter(shortcut: Shortcuts[string]): void {\n    panelCommon.cachePendingValue()\n    const shortcutValue = panelCommon.getShortcutValue(shortcut)\n    if (!Array.isArray(shortcutValue))\n      return\n    changeStartEndTime(shortcutValue[0], shortcutValue[1], 'shortcutPreview')\n  }\n  function handleRangeShortcutClick(shortcut: Shortcuts[string]): void {\n    const shortcutValue = panelCommon.getShortcutValue(shortcut)\n    if (!Array.isArray(shortcutValue))\n      return\n    changeStartEndTime(shortcutValue[0], shortcutValue[1], 'shortcutDone')\n    panelCommon.clearPendingValue()\n    handleConfirmClick()\n  }\n  function justifyColumnsScrollState(\n    value: [number, number],\n    type: 'start' | 'end'\n  ): void\n  function justifyColumnsScrollState(): void\n  function justifyColumnsScrollState(\n    value?: [number, number] | undefined,\n    type?: 'start' | 'end' | undefined\n  ): void {\n    const mergedValue = value === undefined ? props.value : value\n    if (value === undefined || type === 'start') {\n      if (startMonthScrollbarRef.value) {\n        const monthIndex = !Array.isArray(mergedValue)\n          ? getMonth(Date.now())\n          : getMonth(mergedValue[0])\n        startMonthScrollbarRef.value.scrollTo({\n          debounce: false,\n          index: monthIndex,\n          elSize: MONTH_ITEM_HEIGHT\n        })\n      }\n      if (startYearVlRef.value) {\n        const yearIndex\n          = (!Array.isArray(mergedValue)\n            ? getYear(Date.now())\n            : getYear(mergedValue[0])) - yearRangeRef.value[0]\n        startYearVlRef.value.scrollTo({ index: yearIndex, debounce: false })\n      }\n    }\n    if (value === undefined || type === 'end') {\n      if (endMonthScrollbarRef.value) {\n        const monthIndex = !Array.isArray(mergedValue)\n          ? getMonth(Date.now())\n          : getMonth(mergedValue[1])\n        endMonthScrollbarRef.value.scrollTo({\n          debounce: false,\n          index: monthIndex,\n          elSize: MONTH_ITEM_HEIGHT\n        })\n      }\n      if (endYearVlRef.value) {\n        const yearIndex\n          = (!Array.isArray(mergedValue)\n            ? getYear(Date.now())\n            : getYear(mergedValue[1])) - yearRangeRef.value[0]\n        endYearVlRef.value.scrollTo({ index: yearIndex, debounce: false })\n      }\n    }\n  }\n  // only for monthrange\n  function handleColItemClick(\n    dateItem: MonthItem | QuarterItem | YearItem,\n    clickType: 'start' | 'end'\n  ): void {\n    const { value } = props\n    const noCurrentValue = !Array.isArray(value)\n    const itemTs\n      = dateItem.type === 'year' && type !== 'yearrange'\n        ? noCurrentValue\n          ? set(dateItem.ts, {\n              month: getMonth(\n                type === 'quarterrange'\n                  ? startOfQuarter(new Date())\n                  : new Date()\n              )\n            }).valueOf()\n          : set(dateItem.ts, {\n              month: getMonth(\n                type === 'quarterrange'\n                  ? startOfQuarter(value[clickType === 'start' ? 0 : 1])\n                  : value[clickType === 'start' ? 0 : 1]\n              )\n            }).valueOf()\n        : dateItem.ts\n    if (noCurrentValue) {\n      const partialValue = sanitizeValue(itemTs)\n      const nextValue: [number, number] = [partialValue, partialValue]\n      panelCommon.doUpdateValue(nextValue, props.panel)\n      justifyColumnsScrollState(nextValue, 'start')\n      justifyColumnsScrollState(nextValue, 'end')\n      panelCommon.disableTransitionOneTick()\n      return\n    }\n    const nextValue: [number, number] = [value[0], value[1]]\n    let otherPartsChanged = false\n    if (clickType === 'start') {\n      nextValue[0] = sanitizeValue(itemTs)\n      if (nextValue[0] > nextValue[1]) {\n        nextValue[1] = nextValue[0]\n        otherPartsChanged = true\n      }\n    }\n    else {\n      nextValue[1] = sanitizeValue(itemTs)\n      if (nextValue[0] > nextValue[1]) {\n        nextValue[0] = nextValue[1]\n        otherPartsChanged = true\n      }\n    }\n    panelCommon.doUpdateValue(nextValue, props.panel)\n    switch (type) {\n      case 'monthrange':\n      case 'quarterrange':\n        panelCommon.disableTransitionOneTick()\n        if (otherPartsChanged) {\n          justifyColumnsScrollState(nextValue, 'start')\n          justifyColumnsScrollState(nextValue, 'end')\n        }\n        else {\n          justifyColumnsScrollState(nextValue, clickType)\n        }\n        break\n      case 'yearrange':\n        panelCommon.disableTransitionOneTick()\n        justifyColumnsScrollState(nextValue, 'start')\n        justifyColumnsScrollState(nextValue, 'end')\n    }\n  }\n  function handleStartYearVlScroll(): void {\n    startYearScrollbarRef.value?.sync()\n  }\n  function handleEndYearVlScroll(): void {\n    endYearScrollbarRef.value?.sync()\n  }\n  function virtualListContainer(type: 'start' | 'end'): HTMLElement | null {\n    if (type === 'start') {\n      return startYearVlRef.value?.listElRef || null\n    }\n    else {\n      return endYearVlRef.value?.listElRef || null\n    }\n  }\n  function virtualListContent(type: 'start' | 'end'): HTMLElement | null {\n    if (type === 'start') {\n      return startYearVlRef.value?.itemsElRef || null\n    }\n    else {\n      return endYearVlRef.value?.itemsElRef || null\n    }\n  }\n  const childComponentRefs: RangePanelChildComponentRefs = {\n    startYearVlRef,\n    endYearVlRef,\n    startMonthScrollbarRef,\n    endMonthScrollbarRef,\n    startYearScrollbarRef,\n    endYearScrollbarRef\n  }\n  return {\n    startDatesElRef,\n    endDatesElRef,\n    handleDateClick,\n    handleColItemClick,\n    handleDateMouseEnter,\n    handleConfirmClick,\n    startCalendarPrevYear,\n    startCalendarPrevMonth,\n    startCalendarNextYear,\n    startCalendarNextMonth,\n    endCalendarPrevYear,\n    endCalendarPrevMonth,\n    endCalendarNextMonth,\n    endCalendarNextYear,\n    mergedIsDateDisabled,\n    changeStartEndTime,\n    ranges: rangesRef,\n    calendarMonthBeforeYear: calendarMonthBeforeYearRef,\n    startCalendarMonth: startCalendarMonthRef,\n    startCalendarYear: startCalendarYearRef,\n    endCalendarMonth: endCalendarMonthRef,\n    endCalendarYear: endCalendarYearRef,\n    weekdays: weekdaysRef,\n    startDateArray: startDateArrayRef,\n    endDateArray: endDateArrayRef,\n    startYearArray: startYearArrayRef,\n    startMonthArray: startMonthArrayRef,\n    startQuarterArray: startQuarterArrayRef,\n    endYearArray: endYearArrayRef,\n    endMonthArray: endMonthArrayRef,\n    endQuarterArray: endQuarterArrayRef,\n    isSelecting: isSelectingRef,\n    handleRangeShortcutMouseenter,\n    handleRangeShortcutClick,\n    ...panelCommon,\n    ...validation,\n    ...childComponentRefs,\n    // datetimerangeonly\n    startDateDisplayString: startDateInput,\n    endDateInput: endDateInputRef,\n    timePickerSize: panelCommon.timePickerSize,\n    startTimeValue: startTimeValueRef,\n    endTimeValue: endTimeValueRef,\n    datePickerSlots,\n    shortcuts: shortcutsRef,\n    startCalendarDateTime: startCalendarDateTimeRef,\n    endCalendarDateTime: endCalendarDateTimeRef,\n    justifyColumnsScrollState,\n    handleFocusDetectorFocus: panelCommon.handleFocusDetectorFocus,\n    handleStartTimePickerChange,\n    handleEndTimePickerChange,\n    handleStartDateInput,\n    handleStartDateInputBlur,\n    handleEndDateInput,\n    handleEndDateInputBlur,\n    handleStartYearVlScroll,\n    handleEndYearVlScroll,\n    virtualListContainer,\n    virtualListContent,\n    onUpdateStartCalendarValue,\n    onUpdateEndCalendarValue\n  }\n}\n\nexport { useDualCalendar, useDualCalendarProps }\n"
  },
  {
    "path": "src/date-picker/src/panel/use-panel-common.ts",
    "content": "import type { ExtractPropTypes, PropType } from 'vue'\nimport type {\n  DefaultTime,\n  OnClose,\n  OnPanelUpdateValue,\n  OnPanelUpdateValueImpl,\n  Shortcuts,\n  Value\n} from '../interface'\nimport { useKeyboard } from 'vooks'\nimport { computed, inject, nextTick, ref } from 'vue'\nimport { datePickerInjectionKey } from '../interface'\n\nconst TIME_FORMAT = 'HH:mm:ss'\n\nconst usePanelCommonProps = {\n  active: Boolean,\n  dateFormat: String,\n  fastYearSelect: Boolean,\n  fastMonthSelect: Boolean,\n  calendarDayFormat: String,\n  calendarHeaderYearFormat: String,\n  calendarHeaderMonthFormat: String,\n  calendarHeaderMonthYearSeparator: { type: String, required: true },\n  calendarHeaderMonthBeforeYear: {\n    type: Boolean,\n    default: undefined\n  },\n  timePickerFormat: {\n    type: String,\n    value: TIME_FORMAT\n  },\n  value: {\n    type: [Array, Number] as PropType<Value | null>,\n    default: null\n  },\n  shortcuts: Object as PropType<Shortcuts>,\n  defaultTime: [Number, String, Array, Function] as PropType<DefaultTime>,\n  inputReadonly: Boolean,\n  onClear: Function,\n  onConfirm: Function as PropType<(value: Value | null) => void>,\n  onClose: Function as PropType<OnClose>,\n  onTabOut: Function,\n  onKeydown: Function,\n  actions: Array as PropType<string[]>,\n  onSelectYear: Function,\n  onSelectMonth: Function,\n  onUpdateValue: {\n    type: Function as PropType<OnPanelUpdateValue>,\n    required: true\n  },\n  themeClass: String,\n  onRender: Function as PropType<(() => void) | undefined>,\n  panel: Boolean,\n  onNextMonth: Function as PropType<() => void>,\n  onPrevMonth: Function as PropType<() => void>,\n  onNextYear: Function as PropType<() => void>,\n  onPrevYear: Function as PropType<() => void>\n} as const\n\nexport type UsePanelCommonProps = ExtractPropTypes<typeof usePanelCommonProps>\n\nfunction usePanelCommon(props: UsePanelCommonProps) {\n  const {\n    dateLocaleRef,\n    timePickerSizeRef,\n    timePickerPropsRef,\n    localeRef,\n    mergedClsPrefixRef,\n    mergedThemeRef\n  } = inject(datePickerInjectionKey)!\n  const dateFnsOptionsRef = computed(() => {\n    return {\n      locale: dateLocaleRef.value.locale\n    }\n  })\n  const selfRef = ref<HTMLElement | null>(null)\n  const keyboardState = useKeyboard()\n  function doClear(): void {\n    const { onClear } = props\n    if (onClear)\n      onClear()\n  }\n  function doConfirm(): void {\n    const { onConfirm, value } = props\n    if (onConfirm)\n      onConfirm(value)\n  }\n  function doUpdateValue(value: Value | null, doUpdate: boolean): void {\n    const { onUpdateValue } = props\n    ;(onUpdateValue as OnPanelUpdateValueImpl)(value, doUpdate)\n  }\n  function doClose(disableUpdateOnClose: boolean = false): void {\n    const { onClose } = props\n    if (onClose)\n      onClose(disableUpdateOnClose)\n  }\n  function doTabOut(): void {\n    const { onTabOut } = props\n    if (onTabOut)\n      onTabOut()\n  }\n  function handleClearClick(): void {\n    doUpdateValue(null, true)\n    doClose(true)\n    doClear()\n  }\n  function handleFocusDetectorFocus(): void {\n    doTabOut()\n  }\n  function disableTransitionOneTick(): void {\n    if (props.active || props.panel) {\n      void nextTick(() => {\n        const { value: selfEl } = selfRef\n        if (!selfEl)\n          return\n        const dateEls = selfEl.querySelectorAll('[data-n-date]')\n        dateEls.forEach((el) => {\n          el.classList.add('transition-disabled')\n        })\n        void selfEl.offsetWidth\n        dateEls.forEach((el) => {\n          el.classList.remove('transition-disabled')\n        })\n      })\n    }\n  }\n  function handlePanelKeyDown(e: KeyboardEvent): void {\n    if (e.key === 'Tab' && e.target === selfRef.value && keyboardState.shift) {\n      e.preventDefault()\n      doTabOut()\n    }\n  }\n  function handlePanelFocus(e: FocusEvent): void {\n    const { value: el } = selfRef\n    if (\n      keyboardState.tab\n      && e.target === el\n      && el?.contains(e.relatedTarget as Node)\n    ) {\n      doTabOut()\n    }\n  }\n  let cachedValue: Value | null = null\n  let cached = false\n  function cachePendingValue(): void {\n    cachedValue = props.value\n    cached = true\n  }\n  function clearPendingValue(): void {\n    cached = false\n  }\n  function restorePendingValue(): void {\n    if (cached) {\n      doUpdateValue(cachedValue, false)\n      cached = false\n    }\n  }\n  function getShortcutValue(\n    shortcut: Shortcuts[string]\n  ): number | [number, number] | readonly [number, number] {\n    if (typeof shortcut === 'function') {\n      return shortcut()\n    }\n    return shortcut\n  }\n\n  const showMonthYearPanel = ref(false)\n  function handleOpenQuickSelectMonthPanel(): void {\n    showMonthYearPanel.value = !showMonthYearPanel.value\n  }\n  return {\n    mergedTheme: mergedThemeRef,\n    mergedClsPrefix: mergedClsPrefixRef,\n    dateFnsOptions: dateFnsOptionsRef,\n    timePickerSize: timePickerSizeRef,\n    timePickerProps: timePickerPropsRef,\n    selfRef,\n    locale: localeRef,\n    doConfirm,\n    doClose,\n    doUpdateValue,\n    doTabOut,\n    handleClearClick,\n    handleFocusDetectorFocus,\n    disableTransitionOneTick,\n    handlePanelKeyDown,\n    handlePanelFocus,\n    cachePendingValue,\n    clearPendingValue,\n    restorePendingValue,\n    getShortcutValue,\n    handleShortcutMouseleave: restorePendingValue,\n    showMonthYearPanel,\n    handleOpenQuickSelectMonthPanel\n  }\n}\n\nexport { usePanelCommon, usePanelCommonProps }\n"
  },
  {
    "path": "src/date-picker/src/props.ts",
    "content": "import type { PropType } from 'vue'\nimport type { FollowerPlacement } from 'vueuc'\nimport type { ThemeProps } from '../../_mixins'\nimport type { MaybeArray } from '../../_utils'\nimport type { FormValidationStatus } from '../../form/src/public-types'\nimport type { TimePickerProps } from '../../time-picker'\nimport type { DatePickerTheme } from '../styles'\nimport type { DatePickerType } from './config'\nimport type {\n  DefaultTime,\n  FirstDayOfWeek,\n  FormattedValue,\n  IsDateDisabled,\n  IsTimeDisabled,\n  OnConfirm,\n  OnUpdateFormattedValue,\n  OnUpdateValue,\n  Shortcuts,\n  Value\n} from './interface'\nimport type { DatePickerSize } from './public-types'\nimport { useTheme } from '../../_mixins'\nimport { useAdjustedTo } from '../../_utils'\n\nexport const datePickerProps = {\n  ...(useTheme.props as ThemeProps<DatePickerTheme>),\n  to: useAdjustedTo.propTo,\n  bordered: {\n    type: Boolean as PropType<boolean | undefined>,\n    default: undefined\n  },\n  clearable: Boolean,\n  fastYearSelect: Boolean,\n  fastMonthSelect: Boolean,\n  updateValueOnClose: Boolean,\n  calendarDayFormat: String,\n  calendarHeaderYearFormat: String,\n  calendarHeaderMonthFormat: String,\n  calendarHeaderMonthYearSeparator: {\n    type: String,\n    default: ' '\n  },\n  calendarHeaderMonthBeforeYear: {\n    type: Boolean,\n    default: undefined\n  },\n  defaultValue: [Number, Array] as PropType<Value | null>,\n  defaultFormattedValue: [String, Array] as PropType<FormattedValue | null>,\n  defaultTime: [Number, String, Array, Function] as PropType<DefaultTime>,\n  disabled: {\n    type: Boolean as PropType<boolean | undefined>,\n    default: undefined\n  },\n  placement: {\n    type: String as PropType<FollowerPlacement>,\n    default: 'bottom-start'\n  },\n  value: [Number, Array] as PropType<Value | null>,\n  formattedValue: [String, Array] as PropType<FormattedValue | null>,\n  size: String as PropType<DatePickerSize>,\n  type: {\n    type: String as PropType<DatePickerType>,\n    default: 'date'\n  },\n  valueFormat: String,\n  separator: String,\n  placeholder: String,\n  startPlaceholder: String,\n  endPlaceholder: String,\n  format: String,\n  dateFormat: String,\n  timePickerFormat: String,\n  actions: Array as PropType<Array<'clear' | 'confirm' | 'now'> | null>,\n  shortcuts: Object as PropType<Shortcuts>,\n  isDateDisabled: Function as PropType<IsDateDisabled>,\n  isTimeDisabled: Function as PropType<IsTimeDisabled>,\n  show: {\n    type: Boolean as PropType<boolean | undefined>,\n    default: undefined\n  },\n  panel: Boolean,\n  ranges: Object as PropType<Record<string, [number, number]>>,\n  firstDayOfWeek: Number as PropType<FirstDayOfWeek>,\n  inputReadonly: Boolean,\n  closeOnSelect: Boolean,\n  status: String as PropType<FormValidationStatus>,\n  timePickerProps: [Object, Array] as PropType<\n    TimePickerProps | [TimePickerProps, TimePickerProps]\n  >,\n  onClear: Function as PropType<() => void>,\n  onConfirm: Function as PropType<OnConfirm>,\n  defaultCalendarStartTime: Number,\n  defaultCalendarEndTime: Number,\n  bindCalendarMonths: Boolean,\n  monthFormat: { type: String, default: 'M' },\n  yearFormat: { type: String, default: 'y' },\n  quarterFormat: { type: String, default: '\\'Q\\'Q' },\n  yearRange: {\n    type: Array as unknown as PropType<[number, number]>,\n    default: (): [number, number] => [1901, 2100]\n  },\n  'onUpdate:show': [Function, Array] as PropType<\n    MaybeArray<(show: boolean) => void>\n  >,\n  onUpdateShow: [Function, Array] as PropType<\n    MaybeArray<(show: boolean) => void>\n  >,\n  'onUpdate:formattedValue': [Function, Array] as PropType<\n    MaybeArray<OnUpdateFormattedValue>\n  >,\n  onUpdateFormattedValue: [Function, Array] as PropType<\n    MaybeArray<OnUpdateFormattedValue>\n  >,\n  'onUpdate:value': [Function, Array] as PropType<MaybeArray<OnUpdateValue>>,\n  onUpdateValue: [Function, Array] as PropType<MaybeArray<OnUpdateValue>>,\n  onFocus: [Function, Array] as PropType<(e: FocusEvent) => void>,\n  onBlur: [Function, Array] as PropType<(e: FocusEvent) => void>,\n  onNextMonth: Function as PropType<() => void>,\n  onPrevMonth: Function as PropType<() => void>,\n  onNextYear: Function as PropType<() => void>,\n  onPrevYear: Function as PropType<() => void>,\n  // deprecated\n  onChange: [Function, Array] as PropType<MaybeArray<OnUpdateValue>>\n} as const\n"
  },
  {
    "path": "src/date-picker/src/public-types.ts",
    "content": "import type { ExtractPublicPropTypes } from '../../_utils'\nimport type { datePickerProps } from './props'\n\nexport type DatePickerSize = 'small' | 'medium' | 'large'\n\nexport interface DatePickerInst {\n  focus: () => void\n  blur: () => void\n}\n\nexport type DatePickerProps = ExtractPublicPropTypes<typeof datePickerProps>\n\nexport type DatePickerClearSlotOnClear = () => void\nexport interface DatePickerClearSlotProps {\n  onClear: DatePickerClearSlotOnClear\n  text: string\n}\n\nexport type DatePickerNowSlotOnNow = () => void\nexport interface DatePickerNowSlotProps {\n  onNow: DatePickerNowSlotOnNow\n  text: string\n}\n\nexport type DatePickerConfirmSlotOnConfirm = () => void\nexport interface DatePickerConfirmSlotProps {\n  onConfirm: DatePickerConfirmSlotOnConfirm\n  disabled: boolean\n  text: string\n}\n"
  },
  {
    "path": "src/date-picker/src/styles/index.cssr.ts",
    "content": "import { fadeInScaleUpTransition } from '../../../_styles/transitions/fade-in-scale-up.cssr'\nimport { c, cB, cE, cM, cNotM } from '../../../_utils/cssr'\n\n// vars:\n// --n-bezier\n\n// --n-icon-color-override\n// --n-icon-color-disabled-override\n\n// --n-panel-border-radius\n// --n-panel-color\n// --n-panel-box-shadow\n// --n-panel-text-color\n\n// panel header\n// --n-panel-header-padding\n// --n-panel-header-divider-color\n\n// panel calendar\n// --n-calendar-left-padding\n// --n-calendar-right-padding\n// --n-calendar-title-color-hover\n// --n-calendar-title-height\n// --n-calendar-title-padding\n// --n-calendar-title-font-size\n// --n-calendar-title-text-color\n// --n-calendar-title-font-weight\n// --n-calendar-title-grid-template-columns\n// --n-calendar-days-height\n// --n-calendar-days-divider-color\n// --n-calendar-days-font-size\n// --n-calendar-days-text-color\n// --n-calendar-divider-color\n\n// panel action\n// --n-panel-action-padding\n// --n-panel-action-divider-color\n\n// panel item\n// --n-item-border-radius\n// --n-item-size\n// --n-item-cell-width\n// --n-item-cell-height\n// --n-item-text-color\n// --n-item-color-included\n// --n-item-color-disabled\n// --n-item-color-hover\n// --n-item-color-active\n// --n-item-font-size\n// --n-item-text-color-disabled\n// --n-item-text-color-active\n\n// scroll item\n// --n-scroll-item-width\n// --n-scroll-item-height\n// --n-scroll-item-border-radius\n\n// panel arrow\n// --n-arrow-size\n// --n-arrow-color\nexport default c([\n  cB('date-picker', `\n    position: relative;\n    z-index: auto;\n  `, [\n    cB('date-picker-icon', `\n      color: var(--n-icon-color-override);\n      transition: color .3s var(--n-bezier);\n    `),\n    cB('icon', `\n      color: var(--n-icon-color-override);\n      transition: color .3s var(--n-bezier);\n    `),\n    cM('disabled', [\n      cB('date-picker-icon', `\n        color: var(--n-icon-color-disabled-override);\n      `),\n      cB('icon', `\n        color: var(--n-icon-color-disabled-override);\n      `)\n    ])\n  ]),\n  cB('date-panel', `\n    width: fit-content;\n    outline: none;\n    margin: 4px 0;\n    display: grid;\n    grid-template-columns: 0fr;\n    border-radius: var(--n-panel-border-radius);\n    background-color: var(--n-panel-color);\n    color: var(--n-panel-text-color);\n    user-select: none;\n  `, [\n    fadeInScaleUpTransition(),\n    cM('shadow', `\n      box-shadow: var(--n-panel-box-shadow);\n    `),\n    cB('date-panel-calendar', {\n      padding: 'var(--n-calendar-left-padding)',\n      display: 'grid',\n      gridTemplateColumns: '1fr',\n      gridArea: 'left-calendar'\n    }, [\n      cM('end', {\n        padding: 'var(--n-calendar-right-padding)',\n        gridArea: 'right-calendar'\n      })\n    ]),\n    cB('date-panel-month-calendar', {\n      display: 'flex',\n      gridArea: 'left-calendar'\n    }, [\n      cE('picker-col', `\n        min-width: var(--n-scroll-item-width);\n        height: calc(var(--n-scroll-item-height) * 6);\n        user-select: none;\n        -webkit-user-select: none;\n      `, [\n        c('&:first-child', `\n          min-width: calc(var(--n-scroll-item-width) + 4px);\n        `, [\n          cE('picker-col-item', [\n            c('&::before', 'left: 4px;')\n          ])\n        ]),\n        cE('padding', `\n          height: calc(var(--n-scroll-item-height) * 5)\n        `)\n      ]),\n      cE('picker-col-item', `\n        z-index: 0;\n        cursor: pointer;\n        height: var(--n-scroll-item-height);\n        box-sizing: border-box;\n        padding-top: 4px;\n        display: flex;\n        align-items: center;\n        justify-content: center;\n        position: relative;\n        transition: \n          color .3s var(--n-bezier),\n          background-color .3s var(--n-bezier);\n        background: #0000;\n        color: var(--n-item-text-color);\n      `, [\n        c('&::before', `\n          z-index: -1;\n          content: \"\";\n          position: absolute;\n          left: 0;\n          right: 4px;\n          top: 4px;\n          bottom: 0;\n          border-radius: var(--n-scroll-item-border-radius);\n          transition: \n            background-color .3s var(--n-bezier);\n        `),\n        cNotM('disabled', [\n          c('&:hover::before', `\n            background-color: var(--n-item-color-hover);\n          `),\n          cM('selected', `\n            color: var(--n-item-color-active);\n          `, [\n            c('&::before', 'background-color: var(--n-item-color-hover);')\n          ])\n        ]),\n        cM('disabled', `\n          color: var(--n-item-text-color-disabled);\n          cursor: not-allowed;\n        `, [\n          cM('selected', [\n            c('&::before', `\n              background-color: var(--n-item-color-disabled);\n            `)\n          ])\n        ])\n      ])\n    ]),\n    cM('date', {\n      gridTemplateAreas: `\n        \"left-calendar\"\n        \"footer\"\n        \"action\"\n      `\n    }),\n    cM('week', {\n      gridTemplateAreas: `\n        \"left-calendar\"\n        \"footer\"\n        \"action\"\n      `\n    }),\n    cM('daterange', {\n      gridTemplateAreas: `\n        \"left-calendar divider right-calendar\"\n        \"footer footer footer\"\n        \"action action action\"\n      `\n    }),\n    cM('datetime', {\n      gridTemplateAreas: `\n        \"header\"\n        \"left-calendar\"\n        \"footer\"\n        \"action\"\n      `\n    }),\n    cM('datetimerange', {\n      gridTemplateAreas: `\n        \"header header header\"\n        \"left-calendar divider right-calendar\"\n        \"footer footer footer\"\n        \"action action action\"\n      `\n    }),\n    cM('month', {\n      gridTemplateAreas: `\n        \"left-calendar\"\n        \"footer\"\n        \"action\"\n      `\n    }),\n    cB('date-panel-footer', {\n      gridArea: 'footer'\n    }),\n    cB('date-panel-actions', {\n      gridArea: 'action'\n    }),\n    cB('date-panel-header', {\n      gridArea: 'header'\n    }),\n    cB('date-panel-header', `\n      box-sizing: border-box;\n      width: 100%;\n      align-items: center;\n      padding: var(--n-panel-header-padding);\n      display: flex;\n      justify-content: space-between;\n      border-bottom: 1px solid var(--n-panel-header-divider-color);\n    `, [\n      c('>', [\n        c('*:not(:last-child)', {\n          marginRight: '10px'\n        }),\n        c('*', {\n          flex: 1,\n          width: 0\n        }),\n        cB('time-picker', {\n          zIndex: 1\n        })\n      ])\n    ]),\n    cB('date-panel-month', `\n      box-sizing: border-box;\n      display: grid;\n      grid-template-columns: var(--n-calendar-title-grid-template-columns);\n      align-items: center;\n      justify-items: center;\n      padding: var(--n-calendar-title-padding);\n      height: var(--n-calendar-title-height);\n    `, [\n      cE('prev, next, fast-prev, fast-next', `\n        line-height: 0;\n        cursor: pointer;\n        width: var(--n-arrow-size);\n        height: var(--n-arrow-size);\n        color: var(--n-arrow-color);\n      `),\n      cE('month-year', `\n        user-select: none;\n        -webkit-user-select: none;\n        flex-grow: 1;\n        position: relative;\n      `, [\n        cE('text', `\n          font-size: var(--n-calendar-title-font-size);\n          line-height: var(--n-calendar-title-font-size);\n          font-weight: var(--n-calendar-title-font-weight);\n          padding: 6px 8px;\n          text-align: center;\n          color: var(--n-calendar-title-text-color);\n          cursor: pointer;\n          transition: background-color .3s var(--n-bezier);\n          border-radius: var(--n-panel-border-radius);\n        `, [\n          cM('active', `\n            background-color: var(--n-calendar-title-color-hover);\n          `),\n          c('&:hover', `\n            background-color: var(--n-calendar-title-color-hover);\n          `)\n        ])\n      ])\n    ]),\n    cB('date-panel-weekdays', `\n      display: grid;\n      margin: auto;\n      grid-template-columns: repeat(7, var(--n-item-cell-width));\n      grid-template-rows: repeat(1, var(--n-item-cell-height));\n      align-items: center;\n      justify-items: center;\n      margin-bottom: 4px;\n      border-bottom: 1px solid var(--n-calendar-days-divider-color);\n    `, [\n      cE('day', `\n        white-space: nowrap;\n        user-select: none;\n        -webkit-user-select: none;\n        line-height: 15px;\n        width: var(--n-item-size);\n        text-align: center;\n        font-size: var(--n-calendar-days-font-size);\n        color: var(--n-item-text-color);\n        display: flex;\n        align-items: center;\n        justify-content: center;\n      `)\n    ]),\n    cB('date-panel-dates', `\n      margin: auto;\n      display: grid;\n      grid-template-columns: repeat(7, var(--n-item-cell-width));\n      grid-template-rows: repeat(6, var(--n-item-cell-height));\n      align-items: center;\n      justify-items: center;\n      flex-wrap: wrap;\n    `, [\n      cB('date-panel-date', `\n        user-select: none;\n        -webkit-user-select: none;\n        position: relative;\n        width: var(--n-item-size);\n        height: var(--n-item-size);\n        line-height: var(--n-item-size);\n        text-align: center;\n        font-size: var(--n-item-font-size);\n        border-radius: var(--n-item-border-radius);\n        z-index: 0;\n        cursor: pointer;\n        transition:\n          background-color .2s var(--n-bezier),\n          color .2s var(--n-bezier);\n      `, [\n        cE('trigger', `\n          position: absolute;\n          left: calc(var(--n-item-size) / 2 - var(--n-item-cell-width) / 2);\n          top: calc(var(--n-item-size) / 2 - var(--n-item-cell-height) / 2);\n          width:  var(--n-item-cell-width);\n          height:  var(--n-item-cell-height);\n        `),\n        cM('current', [\n          cE('sup', `\n            position: absolute;\n            top: 2px;\n            right: 2px;\n            content: \"\";\n            height: 4px;\n            width: 4px;\n            border-radius: 2px;\n            background-color: var(--n-item-color-active);\n            transition:\n              background-color .2s var(--n-bezier);\n          `)\n        ]),\n        c('&::after', `\n          content: \"\";\n          z-index: -1;\n          position: absolute;\n          left: 0;\n          right: 0;\n          top: 0;\n          bottom: 0;\n          border-radius: inherit;\n          transition: background-color .3s var(--n-bezier);\n        `),\n        cM('covered, start, end', [\n          cNotM('excluded', [\n            c('&::before', `\n              content: \"\";\n              z-index: -2;\n              position: absolute;\n              left: calc((var(--n-item-size) - var(--n-item-cell-width)) / 2);\n              right: calc((var(--n-item-size) - var(--n-item-cell-width)) / 2);\n              top: 0;\n              bottom: 0;\n              background-color: var(--n-item-color-included);\n            `),\n            c('&:nth-child(7n + 1)::before', {\n              borderTopLeftRadius: 'var(--n-item-border-radius)',\n              borderBottomLeftRadius: 'var(--n-item-border-radius)'\n            }),\n            c('&:nth-child(7n + 7)::before', {\n              borderTopRightRadius: 'var(--n-item-border-radius)',\n              borderBottomRightRadius: 'var(--n-item-border-radius)'\n            })\n          ])\n        ]),\n        cM('selected', {\n          color: 'var(--n-item-text-color-active)'\n        }, [\n          c('&::after', {\n            backgroundColor: 'var(--n-item-color-active)'\n          }),\n          cM('start', [\n            c('&::before', {\n              left: '50%'\n            })\n          ]),\n          cM('end', [\n            c('&::before', {\n              right: '50%'\n            })\n          ]),\n          cE('sup', {\n            backgroundColor: 'var(--n-panel-color)'\n          })\n        ]),\n        cM('excluded', {\n          color: 'var(--n-item-text-color-disabled)'\n        }, [\n          cM('selected', [\n            c('&::after', {\n              backgroundColor: 'var(--n-item-color-disabled)'\n            })\n          ])\n        ]),\n        cM('disabled', {\n          cursor: 'not-allowed',\n          color: 'var(--n-item-text-color-disabled)'\n        }, [\n          cM('covered', [\n            c('&::before', {\n              backgroundColor: 'var(--n-item-color-disabled)'\n            })\n          ]),\n          cM('selected', [\n            c('&::before', {\n              backgroundColor: 'var(--n-item-color-disabled)'\n            }),\n            c('&::after', {\n              backgroundColor: 'var(--n-item-color-disabled)'\n            })\n          ])\n        ]),\n        cM('week-hovered', [\n          c('&::before', `\n            background-color: var(--n-item-color-included);\n          `),\n          c('&:nth-child(7n + 1)::before', `\n            border-top-left-radius: var(--n-item-border-radius);\n            border-bottom-left-radius: var(--n-item-border-radius);\n          `),\n          c('&:nth-child(7n + 7)::before', `\n            border-top-right-radius: var(--n-item-border-radius);\n            border-bottom-right-radius: var(--n-item-border-radius);\n          `)\n        ]),\n        cM('week-selected', `\n          color: var(--n-item-text-color-active)\n        `, [\n          c('&::before', `\n            background-color: var(--n-item-color-active);\n          `),\n          c('&:nth-child(7n + 1)::before', `\n            border-top-left-radius: var(--n-item-border-radius);\n            border-bottom-left-radius: var(--n-item-border-radius);\n          `),\n          c('&:nth-child(7n + 7)::before', `\n            border-top-right-radius: var(--n-item-border-radius);\n            border-bottom-right-radius: var(--n-item-border-radius);\n          `)\n        ])\n      ])\n    ]),\n    cNotM('week', [\n      cB('date-panel-dates', [\n        cB('date-panel-date', [\n          cNotM('disabled', [\n            cNotM('selected', [\n              c('&:hover', `\n                background-color: var(--n-item-color-hover);\n              `)\n            ])\n          ])\n        ])\n      ])\n    ]),\n    cM('week', [\n      cB('date-panel-dates', [\n        cB('date-panel-date', [\n          c('&::before', `\n            content: \"\";\n            z-index: -2;\n            position: absolute;\n            left: calc((var(--n-item-size) - var(--n-item-cell-width)) / 2);\n            right: calc((var(--n-item-size) - var(--n-item-cell-width)) / 2);\n            top: 0;\n            bottom: 0;\n            transition: background-color .3s var(--n-bezier);\n          `)\n        ])\n      ])\n    ]),\n    cE('vertical-divider', `\n      grid-area: divider;\n      height: 100%;\n      width: 1px;\n      background-color: var(--n-calendar-divider-color);\n    `),\n    cB('date-panel-footer', `\n      border-top: 1px solid var(--n-panel-action-divider-color);\n      padding: var(--n-panel-extra-footer-padding);\n    `),\n    cB('date-panel-actions', `\n      flex: 1;\n      padding: var(--n-panel-action-padding);\n      display: flex;\n      align-items: center;\n      justify-content: space-between;\n      border-top: 1px solid var(--n-panel-action-divider-color);\n    `, [\n      cE('prefix, suffix', `\n        display: flex;\n        margin-bottom: -8px;\n      `),\n      cE('suffix', `\n        align-self: flex-end;\n      `),\n      cE('prefix', `\n        flex-wrap: wrap;\n      `),\n      cB('button', `\n        margin-bottom: 8px;\n      `, [\n        c('&:not(:last-child)', `\n          margin-right: 8px;\n        `)\n      ])\n    ])\n  ]),\n  c('[data-n-date].transition-disabled', {\n    transition: 'none !important'\n  }, [\n    c('&::before, &::after', {\n      transition: 'none !important'\n    })\n  ])\n])\n"
  },
  {
    "path": "src/date-picker/src/utils.ts",
    "content": "import type { Ref } from 'vue'\nimport type { NDateLocale } from '../../locales'\nimport type {\n  DatePickerGetDefaultTime,\n  DatePickerGetRangeDefaultTime,\n  FirstDayOfWeek,\n  Value\n} from './interface'\nimport {\n  addDays,\n  addMonths,\n  addQuarters,\n  addYears,\n  format,\n  getDate,\n  getDay,\n  getMonth,\n  getQuarter,\n  getTime,\n  getYear,\n  isSameDay,\n  isSameMonth,\n  isSameQuarter,\n  isSameWeek,\n  isSameYear,\n  isValid,\n  parse,\n  setYear,\n  startOfMonth,\n  startOfYear\n} from 'date-fns'\n\nfunction getDerivedTimeFromKeyboardEvent(\n  prevValue: number | null,\n  event: KeyboardEvent\n): number {\n  const now = getTime(Date.now())\n  if (typeof prevValue !== 'number')\n    return now\n  switch (event.key) {\n    case 'ArrowUp':\n      return getTime(addDays(prevValue, -7))\n    case 'ArrowDown':\n      return getTime(addDays(prevValue, 7))\n    case 'ArrowRight':\n      return getTime(addDays(prevValue, 1))\n    case 'ArrowLeft':\n      return getTime(addDays(prevValue, -1))\n  }\n  return now\n}\n\nconst matcherMap = {\n  date: isSameDay,\n  month: isSameMonth,\n  year: isSameYear,\n  quarter: isSameQuarter\n} as const\n\nfunction makeWeekMatcher(firstDayOfWeek: FirstDayOfWeek) {\n  return (sourceTime: number, patternTime: number | Date) => {\n    // date-fns: 0 - Sunday\n    // naive-ui: 0 - Monday\n    const weekStartsOn = transformNaiveFirstDayOfWeekToDateFns(firstDayOfWeek)\n    return isSameWeek(sourceTime, patternTime, { weekStartsOn })\n  }\n}\n\nexport function transformNaiveFirstDayOfWeekToDateFns(\n  firstDayOfWeek: FirstDayOfWeek\n): FirstDayOfWeek {\n  return ((firstDayOfWeek + 1) % 7) as FirstDayOfWeek\n}\n\nfunction matchDate(\n  sourceTime: number,\n  patternTime: number | Date,\n  type: 'date' | 'month' | 'year' | 'quarter'\n): boolean\nfunction matchDate(\n  sourceTime: number,\n  patternTime: number | Date,\n  type: 'week',\n  firstDayOfWeek: FirstDayOfWeek\n): boolean\nfunction matchDate(\n  sourceTime: number,\n  patternTime: number | Date,\n  type: 'date' | 'month' | 'year' | 'quarter' | 'week',\n  firstDayOfWeek: FirstDayOfWeek = 0\n): boolean {\n  const matcher\n    = type === 'week' ? makeWeekMatcher(firstDayOfWeek) : matcherMap[type]\n  return matcher(sourceTime, patternTime)\n}\n\nexport interface DateItem {\n  type: 'date'\n  dateObject: {\n    date: number\n    month: number\n    year: number\n  }\n  inCurrentMonth: boolean\n  isCurrentDate: boolean\n  inSpan: boolean\n  startOfSpan: boolean\n  endOfSpan: boolean\n  selected: boolean\n  inSelectedWeek: boolean\n  ts: number\n}\n\nexport interface MonthItem {\n  type: 'month'\n  monthFormat: string\n  dateObject: {\n    month: number\n    year: number\n  }\n  isCurrent: boolean\n  selected: boolean\n  ts: number\n}\n\nexport interface YearItem {\n  type: 'year'\n  yearFormat: string\n  dateObject: {\n    year: number\n  }\n  isCurrent: boolean\n  selected: boolean\n  ts: number\n}\n\nexport interface QuarterItem {\n  type: 'quarter'\n  quarterFormat: string\n  dateObject: {\n    quarter: number\n    year: number\n  }\n  isCurrent: boolean\n  selected: boolean\n  ts: number\n}\n\nfunction dateOrWeekItem(\n  time: number,\n  monthTs: number,\n  valueTs: number | [number, number] | null,\n  currentTs: number,\n  mode: 'date' | 'week',\n  firstDayOfWeek: FirstDayOfWeek\n): DateItem {\n  if (mode === 'date') {\n    return dateItem(time, monthTs, valueTs, currentTs)\n  }\n  else {\n    return weekItem(time, monthTs, valueTs, currentTs, firstDayOfWeek)\n  }\n}\n\n// date item's valueTs can be a tuple since two date may show in one panel, so\n// any matched value would make it shown as selected\nfunction dateItem(\n  time: number,\n  monthTs: number,\n  valueTs: number | [number, number] | null,\n  currentTs: number\n): DateItem {\n  let inSpan = false\n  let startOfSpan = false\n  let endOfSpan = false\n  if (Array.isArray(valueTs)) {\n    if (valueTs[0] < time && time < valueTs[1]) {\n      inSpan = true\n    }\n    if (matchDate(valueTs[0], time, 'date'))\n      startOfSpan = true\n    if (matchDate(valueTs[1], time, 'date'))\n      endOfSpan = true\n  }\n  const selected\n    = valueTs !== null\n      && (Array.isArray(valueTs)\n        ? matchDate(valueTs[0], time, 'date')\n        || matchDate(valueTs[1], time, 'date')\n        : matchDate(valueTs, time, 'date'))\n  return {\n    type: 'date',\n    dateObject: {\n      date: getDate(time),\n      month: getMonth(time),\n      year: getYear(time)\n    },\n    inCurrentMonth: isSameMonth(time, monthTs),\n    isCurrentDate: matchDate(currentTs, time, 'date'),\n    inSpan,\n    inSelectedWeek: false,\n    startOfSpan,\n    endOfSpan,\n    selected,\n    ts: getTime(time)\n  }\n}\n\nfunction getMonthString(\n  month: number,\n  monthFormat: string,\n  locale: NDateLocale['locale']\n): string {\n  const date = new Date(2000, month, 1).getTime()\n  return format(date, monthFormat, { locale })\n}\n\nfunction getYearString(\n  year: number,\n  yearFormat: string,\n  locale: NDateLocale['locale']\n): string {\n  const date = new Date(year, 1, 1).getTime()\n  return format(date, yearFormat, { locale })\n}\n\nfunction getQuarterString(\n  quarter: number,\n  quarterFormat: string,\n  locale: NDateLocale['locale']\n): string {\n  const date = new Date(2000, quarter * 3 - 2, 1).getTime()\n  return format(date, quarterFormat, { locale })\n}\n\nfunction weekItem(\n  time: number,\n  monthTs: number,\n  valueTs: number | [number, number] | null,\n  currentTs: number,\n  firstDayOfWeek: FirstDayOfWeek\n): DateItem {\n  let inSpan = false\n  let startOfSpan = false\n  let endOfSpan = false\n  if (Array.isArray(valueTs)) {\n    if (valueTs[0] < time && time < valueTs[1]) {\n      inSpan = true\n    }\n    if (matchDate(valueTs[0], time, 'week', firstDayOfWeek))\n      startOfSpan = true\n    if (matchDate(valueTs[1], time, 'week', firstDayOfWeek))\n      endOfSpan = true\n  }\n  const inSelectedWeek\n    = valueTs !== null\n      && (Array.isArray(valueTs)\n        ? matchDate(valueTs[0], time, 'week', firstDayOfWeek)\n        || matchDate(valueTs[1], time, 'week', firstDayOfWeek)\n        : matchDate(valueTs, time, 'week', firstDayOfWeek))\n  return {\n    type: 'date',\n    dateObject: {\n      date: getDate(time),\n      month: getMonth(time),\n      year: getYear(time)\n    },\n    inCurrentMonth: isSameMonth(time, monthTs),\n    isCurrentDate: matchDate(currentTs, time, 'date'),\n    inSpan,\n    startOfSpan,\n    endOfSpan,\n    selected: false,\n    inSelectedWeek,\n    ts: getTime(time)\n  }\n}\n\nfunction monthItem(\n  monthTs: number,\n  valueTs: number | null,\n  currentTs: number,\n  {\n    monthFormat\n  }: {\n    monthFormat: string\n  }\n): MonthItem {\n  return {\n    type: 'month',\n    monthFormat,\n    dateObject: {\n      month: getMonth(monthTs),\n      year: getYear(monthTs)\n    },\n    isCurrent: isSameMonth(currentTs, monthTs),\n    selected: valueTs !== null && matchDate(valueTs, monthTs, 'month'),\n    ts: getTime(monthTs)\n  }\n}\n\nfunction yearItem(\n  yearTs: number,\n  valueTs: number | null,\n  currentTs: number,\n  {\n    yearFormat\n  }: {\n    yearFormat: string\n  }\n): YearItem {\n  return {\n    type: 'year',\n    yearFormat,\n    dateObject: {\n      year: getYear(yearTs)\n    },\n    isCurrent: isSameYear(currentTs, yearTs),\n    selected: valueTs !== null && matchDate(valueTs, yearTs, 'year'),\n    ts: getTime(yearTs)\n  }\n}\n\nfunction quarterItem(\n  quarterTs: number,\n  valueTs: number | null,\n  currentTs: number,\n  {\n    quarterFormat\n  }: {\n    quarterFormat: string\n  }\n): QuarterItem {\n  return {\n    type: 'quarter',\n    quarterFormat,\n    dateObject: {\n      quarter: getQuarter(quarterTs),\n      year: getYear(quarterTs)\n    },\n    isCurrent: isSameQuarter(currentTs, quarterTs),\n    selected: valueTs !== null && matchDate(valueTs, quarterTs, 'quarter'),\n    ts: getTime(quarterTs)\n  }\n}\n\n/**\n * Given time to display calendar, given the selected time, given current time,\n * return the date array of display time's month.\n */\nfunction dateArray(\n  monthTs: number,\n  valueTs: number | [number, number] | null,\n  currentTs: number,\n  startDay: 0 | 1 | 2 | 3 | 4 | 5 | 6,\n  strip: boolean = false,\n  weekMode: boolean = false\n): DateItem[] {\n  const granularity = weekMode ? 'week' : 'date'\n  const displayMonth = getMonth(monthTs)\n  // First day of current month\n  let displayMonthIterator = getTime(startOfMonth(monthTs))\n  // Last day of last month\n  let lastMonthIterator = getTime(addDays(displayMonthIterator, -1))\n  const calendarDays: DateItem[] = []\n  let protectLastMonthDateIsShownFlag = !strip\n  while (\n    getDay(lastMonthIterator) !== startDay\n    || protectLastMonthDateIsShownFlag\n  ) {\n    calendarDays.unshift(\n      dateOrWeekItem(\n        lastMonthIterator,\n        monthTs,\n        valueTs,\n        currentTs,\n        granularity,\n        startDay\n      )\n    )\n    lastMonthIterator = getTime(addDays(lastMonthIterator, -1))\n    protectLastMonthDateIsShownFlag = false\n  }\n  while (getMonth(displayMonthIterator) === displayMonth) {\n    calendarDays.push(\n      dateOrWeekItem(\n        displayMonthIterator,\n        monthTs,\n        valueTs,\n        currentTs,\n        granularity,\n        startDay\n      )\n    )\n    displayMonthIterator = getTime(addDays(displayMonthIterator, 1))\n  }\n  const endIndex = strip\n    ? calendarDays.length <= 28\n      ? 28\n      : calendarDays.length <= 35\n        ? 35\n        : 42\n    : 42\n  while (calendarDays.length < endIndex) {\n    calendarDays.push(\n      dateOrWeekItem(\n        displayMonthIterator,\n        monthTs,\n        valueTs,\n        currentTs,\n        granularity,\n        startDay\n      )\n    )\n    displayMonthIterator = getTime(addDays(displayMonthIterator, 1))\n  }\n  return calendarDays\n}\n\nfunction monthArray(\n  yearAnchorTs: number,\n  valueTs: number | null,\n  currentTs: number,\n  format: {\n    monthFormat: string\n  }\n): MonthItem[] {\n  const calendarMonths: MonthItem[] = []\n  const yearStart = startOfYear(yearAnchorTs)\n  for (let i = 0; i < 12; i++) {\n    calendarMonths.push(\n      monthItem(getTime(addMonths(yearStart, i)), valueTs, currentTs, format)\n    )\n  }\n  return calendarMonths\n}\n\nfunction quarterArray(\n  yearAnchorTs: number,\n  valueTs: number | null,\n  currentTs: number,\n  format: {\n    quarterFormat: string\n  }\n): QuarterItem[] {\n  const calendarQuarters: QuarterItem[] = []\n  const yearStart = startOfYear(yearAnchorTs)\n  for (let i = 0; i < 4; i++) {\n    calendarQuarters.push(\n      quarterItem(\n        getTime(addQuarters(yearStart, i)),\n        valueTs,\n        currentTs,\n        format\n      )\n    )\n  }\n  return calendarQuarters\n}\n\nfunction yearArray(\n  valueTs: number | null,\n  currentTs: number,\n  format: {\n    yearFormat: string\n  },\n  rangeRef: Ref<[number, number]>\n): YearItem[] {\n  const range = rangeRef.value\n  const calendarYears: YearItem[] = []\n  const startTime = startOfYear(setYear(new Date(), range[0]))\n  for (let i = 0; i < range[1] - range[0]; i++) {\n    calendarYears.push(\n      yearItem(getTime(addYears(startTime, i)), valueTs, currentTs, format)\n    )\n  }\n  return calendarYears\n}\n\nfunction strictParse(\n  string: string,\n  pattern: string,\n  backup: Date,\n  option: {\n    locale: NDateLocale['locale']\n  }\n): Date {\n  const result = parse(string, pattern, backup, option)\n  if (!isValid(result))\n    return result\n  else if (format(result, pattern, option) === string)\n    return result\n  else return new Date(Number.NaN)\n}\n\nfunction extractSingleDefaultTime(\n  timestamp: number,\n  defaultTimeExtractor: DatePickerGetDefaultTime\n):\n  | {\n    hours: number\n    minutes: number\n    seconds: number\n  }\n  | undefined {\n  const extractedTime = defaultTimeExtractor(timestamp)\n\n  return getDefaultTime(extractedTime as string)\n}\n\nfunction extractRangeDefaultTime(\n  timestamp: number,\n  defaultTimeExtractor: DatePickerGetRangeDefaultTime,\n  position: 'start' | 'end',\n  value: [number, number] | null\n):\n  | {\n    hours: number\n    minutes: number\n    seconds: number\n  }\n  | undefined {\n  const extractedTime = defaultTimeExtractor(timestamp, position, value)\n\n  return getDefaultTime(extractedTime as string)\n}\n\nfunction getDefaultTime(timeValue: string | undefined):\n  | {\n    hours: number\n    minutes: number\n    seconds: number\n  }\n  | undefined {\n  if (timeValue === undefined) {\n    return undefined\n  }\n  if (typeof timeValue === 'number') {\n    return timeValue\n  }\n  const [hour, minute, second] = timeValue.split(':')\n  return {\n    hours: Number(hour),\n    minutes: Number(minute),\n    seconds: Number(second)\n  }\n}\n\nfunction pluckValueFromRange(\n  value: Value | null,\n  type: 'start' | 'end'\n): number | null {\n  return Array.isArray(value) ? value[type === 'start' ? 0 : 1] : null\n}\n\nexport {\n  dateArray,\n  extractRangeDefaultTime,\n  extractSingleDefaultTime,\n  getDefaultTime,\n  getDerivedTimeFromKeyboardEvent,\n  getMonthString,\n  getQuarterString,\n  getYearString,\n  monthArray,\n  pluckValueFromRange,\n  quarterArray,\n  strictParse,\n  yearArray\n}\n"
  },
  {
    "path": "src/date-picker/src/validation-utils.ts",
    "content": "import type { Ref } from 'vue'\nimport type { DatePickerSetupProps } from './DatePicker'\nimport type {\n  IsRangeDateDisabled,\n  IsRangeTimeDisabled,\n  IsSingleDateDisabled,\n  IsSingleTimeDisabled\n} from './interface'\nimport { getHours, getMinutes, getSeconds } from 'date-fns'\nimport { computed } from 'vue'\n\nexport function uniCalendarValidation(\n  props: DatePickerSetupProps,\n  mergedValueRef: Ref<number | [number, number] | null>\n) {\n  // date, datetime\n  const timePickerValidatorRef = computed(() => {\n    const { isTimeDisabled } = props as {\n      isTimeDisabled?: IsSingleTimeDisabled\n    }\n    const { value } = mergedValueRef\n    if (value === null || Array.isArray(value))\n      return undefined\n    return isTimeDisabled?.(value)\n  })\n  const isHourDisabledRef = computed(() => {\n    return timePickerValidatorRef.value?.isHourDisabled\n  })\n  const isMinuteDisabledRef = computed(() => {\n    return timePickerValidatorRef.value?.isMinuteDisabled\n  })\n  const isSecondDisabledRef = computed(() => {\n    return timePickerValidatorRef.value?.isSecondDisabled\n  })\n  const isDateInvalidRef = computed(() => {\n    const { type, isDateDisabled } = props\n    const { value } = mergedValueRef\n    if (\n      value === null\n      || Array.isArray(value)\n      || !['date', 'datetime'].includes(type)\n      || !isDateDisabled\n    ) {\n      return false\n    }\n    return (isDateDisabled as IsSingleDateDisabled)(value, { type: 'input' })\n  })\n  const isTimeInvalidRef = computed(() => {\n    const { type } = props\n    const { value } = mergedValueRef\n    if (value === null || !(type !== 'datetime') || Array.isArray(value)) {\n      return false\n    }\n    const time = new Date(value)\n    const hour = time.getHours()\n    const minute = time.getMinutes()\n    const second = time.getMinutes()\n    return (\n      (isHourDisabledRef.value ? isHourDisabledRef.value(hour) : false)\n      || (isMinuteDisabledRef.value\n        ? isMinuteDisabledRef.value(minute, hour)\n        : false)\n      || (isSecondDisabledRef.value\n        ? isSecondDisabledRef.value(second, minute, hour)\n        : false)\n    )\n  })\n  const isDateTimeInvalidRef = computed(() => {\n    return isDateInvalidRef.value || isTimeInvalidRef.value\n  })\n  const isValueInvalidRef = computed(() => {\n    const { type } = props\n    if (type === 'date')\n      return isDateInvalidRef.value\n    if (type === 'datetime')\n      return isDateTimeInvalidRef.value\n    return false\n  })\n  return {\n    // date & datetime\n    isValueInvalidRef,\n    isDateInvalidRef,\n    // datetime only\n    isTimeInvalidRef,\n    isDateTimeInvalidRef,\n    isHourDisabledRef,\n    isMinuteDisabledRef,\n    isSecondDisabledRef\n  }\n}\n\nexport function dualCalendarValidation(\n  props: DatePickerSetupProps,\n  mergedValueRef: Ref<number | [number, number] | null>\n) {\n  // daterange, datetimerange\n  const timePickerValidatorRef = computed(() => {\n    const { isTimeDisabled } = props as { isTimeDisabled?: IsRangeTimeDisabled }\n    const { value } = mergedValueRef\n    if (!Array.isArray(value) || !isTimeDisabled) {\n      return [undefined, undefined]\n    }\n    return [\n      isTimeDisabled?.(value[0], 'start', value),\n      isTimeDisabled?.(value[1], 'end', value)\n    ]\n  })\n  const timeValidator = {\n    isStartHourDisabledRef: computed(\n      () => timePickerValidatorRef.value[0]?.isHourDisabled\n    ),\n    isEndHourDisabledRef: computed(\n      () => timePickerValidatorRef.value[1]?.isHourDisabled\n    ),\n    isStartMinuteDisabledRef: computed(\n      () => timePickerValidatorRef.value[0]?.isMinuteDisabled\n    ),\n    isEndMinuteDisabledRef: computed(\n      () => timePickerValidatorRef.value[1]?.isMinuteDisabled\n    ),\n    isStartSecondDisabledRef: computed(\n      () => timePickerValidatorRef.value[0]?.isSecondDisabled\n    ),\n    isEndSecondDisabledRef: computed(\n      () => timePickerValidatorRef.value[1]?.isSecondDisabled\n    )\n  }\n  const isStartDateInvalidRef = computed(() => {\n    const { type, isDateDisabled } = props\n    const { value } = mergedValueRef\n    if (\n      value === null\n      || !Array.isArray(value)\n      || !['daterange', 'datetimerange'].includes(type)\n      || !isDateDisabled\n    ) {\n      return false\n    }\n    return (isDateDisabled as IsRangeDateDisabled)(value[0], 'start', value)\n  })\n  const isEndDateInvalidRef = computed(() => {\n    const { type, isDateDisabled } = props\n    const { value } = mergedValueRef\n    if (\n      value === null\n      || !Array.isArray(value)\n      || !['daterange', 'datetimerange'].includes(type)\n      || !isDateDisabled\n    ) {\n      return false\n    }\n    return (isDateDisabled as IsRangeDateDisabled)(value[1], 'end', value)\n  })\n  const isStartTimeInvalidRef = computed(() => {\n    const { type } = props\n    const { value } = mergedValueRef\n    if (value === null || !Array.isArray(value) || type !== 'datetimerange') {\n      return false\n    }\n    const startHours = getHours(value[0])\n    const startMinutes = getMinutes(value[0])\n    const startSeconds = getSeconds(value[0])\n    const {\n      isStartHourDisabledRef,\n      isStartMinuteDisabledRef,\n      isStartSecondDisabledRef\n    } = timeValidator\n    const startTimeInvalid\n      = (isStartHourDisabledRef.value\n        ? isStartHourDisabledRef.value(startHours)\n        : false)\n      || (isStartMinuteDisabledRef.value\n        ? isStartMinuteDisabledRef.value(startMinutes, startHours)\n        : false)\n      || (isStartSecondDisabledRef.value\n        ? isStartSecondDisabledRef.value(startSeconds, startMinutes, startHours)\n        : false)\n    return startTimeInvalid\n  })\n  const isEndTimeInvalidRef = computed(() => {\n    const { type } = props\n    const { value } = mergedValueRef\n    if (value === null || !Array.isArray(value) || type !== 'datetimerange') {\n      return false\n    }\n    const endHours = getHours(value[1])\n    const endMinutes = getMinutes(value[1])\n    const endSeconds = getSeconds(value[1])\n    const {\n      isEndHourDisabledRef,\n      isEndMinuteDisabledRef,\n      isEndSecondDisabledRef\n    } = timeValidator\n    const endTimeInvalid\n      = (isEndHourDisabledRef.value\n        ? isEndHourDisabledRef.value(endHours)\n        : false)\n      || (isEndMinuteDisabledRef.value\n        ? isEndMinuteDisabledRef.value(endMinutes, endHours)\n        : false)\n      || (isEndSecondDisabledRef.value\n        ? isEndSecondDisabledRef.value(endSeconds, endMinutes, endHours)\n        : false)\n    return endTimeInvalid\n  })\n  const isStartValueInvalidRef = computed(() => {\n    return isStartDateInvalidRef.value || isStartTimeInvalidRef.value\n  })\n  const isEndValueInvalidRef = computed(() => {\n    return isEndDateInvalidRef.value || isEndTimeInvalidRef.value\n  })\n  const isRangeInvalidRef = computed(() => {\n    return isStartValueInvalidRef.value || isEndValueInvalidRef.value\n  })\n  return {\n    ...timeValidator,\n    isStartDateInvalidRef,\n    isEndDateInvalidRef,\n    isStartTimeInvalidRef,\n    isEndTimeInvalidRef,\n    isStartValueInvalidRef,\n    isEndValueInvalidRef,\n    isRangeInvalidRef\n  }\n}\n"
  },
  {
    "path": "src/date-picker/styles/_common.ts",
    "content": "export default {\n  itemSize: '24px',\n  itemCellWidth: '38px',\n  itemCellHeight: '32px',\n  scrollItemWidth: '80px',\n  scrollItemHeight: '40px',\n  panelExtraFooterPadding: '8px 12px',\n  panelActionPadding: '8px 12px',\n  calendarTitlePadding: '0',\n  calendarTitleHeight: '28px',\n  arrowSize: '14px',\n  panelHeaderPadding: '8px 12px',\n  calendarDaysHeight: '32px',\n  calendarTitleGridTempateColumns: '28px 28px 1fr 28px 28px',\n  // type\n  calendarLeftPaddingDate: '6px 12px 4px 12px',\n  calendarLeftPaddingDatetime: '4px 12px',\n  calendarLeftPaddingDaterange: '6px 12px 4px 12px',\n  calendarLeftPaddingDatetimerange: '4px 12px',\n  calendarLeftPaddingMonth: '0', // TODO: make it actually effective\n  calendarLeftPaddingYear: '0',\n  calendarLeftPaddingQuarter: '0',\n  calendarLeftPaddingMonthrange: '0',\n  calendarLeftPaddingQuarterrange: '0',\n  calendarLeftPaddingYearrange: '0',\n  calendarLeftPaddingWeek: '6px 12px 4px 12px',\n  calendarRightPaddingDate: '6px 12px 4px 12px',\n  calendarRightPaddingDatetime: '4px 12px',\n  calendarRightPaddingDaterange: '6px 12px 4px 12px',\n  calendarRightPaddingDatetimerange: '4px 12px',\n  calendarRightPaddingMonth: '0',\n  calendarRightPaddingYear: '0',\n  calendarRightPaddingQuarter: '0',\n  calendarRightPaddingMonthrange: '0',\n  calendarRightPaddingQuarterrange: '0',\n  calendarRightPaddingYearrange: '0',\n  calendarRightPaddingWeek: '0'\n}\n"
  },
  {
    "path": "src/date-picker/styles/dark.ts",
    "content": "import type { DatePickerTheme } from './light'\nimport { changeColor, composite } from 'seemly'\nimport { scrollbarDark } from '../../_internal/scrollbar/styles'\nimport { commonDark } from '../../_styles/common'\nimport { buttonDark } from '../../button/styles'\nimport { inputDark } from '../../input/styles'\nimport { timePickerDark } from '../../time-picker/styles'\nimport { self } from './light'\n\nconst datePickerDark: DatePickerTheme = {\n  name: 'DatePicker',\n  common: commonDark,\n  peers: {\n    Input: inputDark,\n    Button: buttonDark,\n    TimePicker: timePickerDark,\n    Scrollbar: scrollbarDark\n  },\n  self(vars) {\n    const { popoverColor, hoverColor, primaryColor } = vars\n    const commonSelf = self(vars)\n    commonSelf.itemColorDisabled = composite(popoverColor, hoverColor)\n    commonSelf.itemColorIncluded = changeColor(primaryColor, { alpha: 0.15 })\n    commonSelf.itemColorHover = composite(popoverColor, hoverColor)\n    return commonSelf\n  }\n}\n\nexport default datePickerDark\n"
  },
  {
    "path": "src/date-picker/styles/index.ts",
    "content": "export { default as datePickerDark } from './dark'\nexport { default as datePickerLight } from './light'\nexport type { DatePickerTheme, DatePickerThemeVars } from './light'\n"
  },
  {
    "path": "src/date-picker/styles/light.ts",
    "content": "import type { ThemeCommonVars } from '../../_styles/common'\nimport { changeColor } from 'seemly'\nimport { scrollbarLight } from '../../_internal/scrollbar/styles'\nimport { createTheme } from '../../_mixins'\nimport { commonLight } from '../../_styles/common'\nimport { buttonLight } from '../../button/styles'\nimport { inputLight } from '../../input/styles'\nimport { timePickerLight } from '../../time-picker/styles'\nimport commonVars from './_common'\n\nexport function self(vars: ThemeCommonVars) {\n  const {\n    hoverColor,\n    fontSize,\n    textColor2,\n    textColorDisabled,\n    popoverColor,\n    primaryColor,\n    borderRadiusSmall,\n    iconColor,\n    iconColorDisabled,\n    textColor1,\n    dividerColor,\n    boxShadow2,\n    borderRadius,\n    fontWeightStrong\n  } = vars\n  return {\n    ...commonVars,\n    itemFontSize: fontSize,\n    calendarDaysFontSize: fontSize,\n    calendarTitleFontSize: fontSize,\n    itemTextColor: textColor2,\n    itemTextColorDisabled: textColorDisabled,\n    itemTextColorActive: popoverColor,\n    itemTextColorCurrent: primaryColor,\n    itemColorIncluded: changeColor(primaryColor, { alpha: 0.1 }),\n    itemColorHover: hoverColor,\n    itemColorDisabled: hoverColor,\n    itemColorActive: primaryColor,\n    itemBorderRadius: borderRadiusSmall,\n    panelColor: popoverColor,\n    panelTextColor: textColor2,\n    arrowColor: iconColor,\n    calendarTitleTextColor: textColor1,\n    calendarTitleColorHover: hoverColor,\n    calendarDaysTextColor: textColor2,\n    panelHeaderDividerColor: dividerColor,\n    calendarDaysDividerColor: dividerColor,\n    calendarDividerColor: dividerColor,\n    panelActionDividerColor: dividerColor,\n    panelBoxShadow: boxShadow2,\n    panelBorderRadius: borderRadius,\n    calendarTitleFontWeight: fontWeightStrong,\n    scrollItemBorderRadius: borderRadius,\n    iconColor,\n    iconColorDisabled\n  }\n}\n\nexport type DatePickerThemeVars = ReturnType<typeof self>\n\nconst datePickerLight = createTheme({\n  name: 'DatePicker',\n  common: commonLight,\n  peers: {\n    Input: inputLight,\n    Button: buttonLight,\n    TimePicker: timePickerLight,\n    Scrollbar: scrollbarLight\n  },\n  self\n})\n\nexport default datePickerLight\nexport type DatePickerTheme = typeof datePickerLight\n"
  },
  {
    "path": "src/date-picker/tests/DatePicker.spec.tsx",
    "content": "import type { Value } from '../src/interface'\nimport { mount } from '@vue/test-utils'\nimport { format } from 'date-fns'\nimport { ref } from 'vue'\nimport { dateEnUS } from '../../locales'\nimport { NDatePicker } from '../index'\n\ndescribe('n-date-picker', () => {\n  it('should work with import on demand', () => {\n    mount(NDatePicker).unmount()\n  })\n\n  it('date type should work with shortcuts prop', async () => {\n    const test = ref<[number, number]>([0, 0])\n    const wrapper = mount(NDatePicker, {\n      props: {\n        value: test.value,\n        type: 'date',\n        onUpdateValue: (value: [number, number]) => {\n          test.value = value\n        },\n        shortcuts: {\n          'Honey birthday': 1631203200000\n        }\n      }\n    })\n    await wrapper.find('.n-input').trigger('click')\n    const button: HTMLElement = document\n      .querySelector('.n-date-panel-actions')\n      ?.querySelector('.n-button') as HTMLElement\n    button.click()\n    expect(test.value).toEqual(1631203200000)\n    test.value = [0, 0]\n    await wrapper.setProps({\n      type: 'datetime'\n    })\n    await wrapper.find('.n-input').trigger('click')\n    const timeButton: HTMLElement = document\n      .querySelector('.n-date-panel-actions')\n      ?.querySelector('.n-button') as HTMLElement\n    timeButton.click()\n    expect(test.value).toEqual(1631203200000)\n    wrapper.unmount()\n  })\n\n  it('range type should work with shortcuts prop', async () => {\n    const test = ref<Value>(0)\n    const wrapper = mount(NDatePicker, {\n      props: {\n        value: test.value,\n        type: 'daterange',\n        onUpdateValue: (value: Value) => {\n          test.value = value\n        },\n        shortcuts: {\n          'Honey birthday': [1629216000000, 1631203200000]\n        }\n      }\n    })\n    await wrapper.find('.n-input').trigger('click')\n    const button: HTMLElement = document\n      .querySelector('.n-date-panel-actions')\n      ?.querySelector('.n-button') as HTMLElement\n    button.click()\n    expect(test.value).toEqual([1629216000000, 1631203200000])\n    test.value = 0\n    await wrapper.setProps({\n      type: 'datetimerange'\n    })\n    await wrapper.find('.n-input').trigger('click')\n    const rangeButton: HTMLElement = document\n      .querySelector('.n-date-panel-actions')\n      ?.querySelector('.n-button') as HTMLElement\n    rangeButton.click()\n    expect(test.value).toEqual([1629216000000, 1631203200000])\n    wrapper.unmount()\n  })\n\n  it('date type should work with shortcuts prop with function value', async () => {\n    const test = ref<Value>(0)\n    const wrapper = mount(NDatePicker, {\n      props: {\n        value: test.value,\n        type: 'date',\n        onUpdateValue: (value: Value) => {\n          test.value = value\n        },\n        shortcuts: {\n          'Honey birthday': () => 1631203200000\n        }\n      }\n    })\n    await wrapper.find('.n-input').trigger('click')\n    const button: HTMLElement = document\n      .querySelector('.n-date-panel-actions')\n      ?.querySelector('.n-button') as HTMLElement\n    button.click()\n    expect(test.value).toEqual(1631203200000)\n    test.value = 0\n    await wrapper.setProps({\n      type: 'datetime'\n    })\n    await wrapper.find('.n-input').trigger('click')\n    const timeButton: HTMLElement = document\n      .querySelector('.n-date-panel-actions')\n      ?.querySelector('.n-button') as HTMLElement\n    timeButton.click()\n    expect(test.value).toEqual(1631203200000)\n    wrapper.unmount()\n  })\n\n  it('range type should work with shortcuts prop with function value', async () => {\n    const test = ref<[number, number]>([0, 0])\n\n    const wrapper = mount(NDatePicker, {\n      props: {\n        value: test.value,\n        type: 'daterange',\n        onUpdateValue: (value: [number, number]) => {\n          test.value = value\n        },\n        shortcuts: {\n          'Honey birthday': () =>\n            [1629216000000, 1631203200000] as [number, number]\n        }\n      }\n    })\n    await wrapper.find('.n-input').trigger('click')\n    const button: HTMLElement = document\n      .querySelector('.n-date-panel-actions')\n      ?.querySelector('.n-button') as HTMLElement\n    button.click()\n    expect(test.value).toEqual([1629216000000, 1631203200000])\n    test.value = [0, 0]\n    await wrapper.setProps({\n      type: 'datetimerange'\n    })\n    await wrapper.find('.n-input').trigger('click')\n    const rangeButton: HTMLElement = document\n      .querySelector('.n-date-panel-actions')\n      ?.querySelector('.n-button') as HTMLElement\n    rangeButton.click()\n    expect(test.value).toEqual([1629216000000, 1631203200000])\n    wrapper.unmount()\n  })\n\n  it('should work with `inputReadonly` prop', async () => {\n    const wrapper = mount(NDatePicker)\n    expect(wrapper.find('input').attributes('readonly')).not.toBe('')\n    await wrapper.setProps({\n      inputReadonly: true\n    })\n    expect(wrapper.find('input').attributes('readonly')).toBe('')\n    await wrapper.setProps({\n      type: 'datetime',\n      panel: true,\n      inputReadonly: true\n    })\n    expect(wrapper.find('input').attributes('readonly')).toBe('')\n    await wrapper.setProps({\n      type: 'datetimerange',\n      panel: true,\n      inputReadonly: true\n    })\n    expect(wrapper.find('input').attributes('readonly')).toBe('')\n    wrapper.unmount()\n  })\n\n  it('should work with `clearable` prop', async () => {\n    const wrapper = mount(NDatePicker)\n    expect(wrapper.find('.n-base-clear').exists()).not.toBe(true)\n    await wrapper.setProps({\n      clearable: true\n    })\n    expect(wrapper.find('.n-base-clear').exists()).toBe(true)\n    wrapper.unmount()\n  })\n\n  it('should work with `disabled` prop', async () => {\n    const wrapper = mount(NDatePicker)\n    expect(wrapper.find('.n-input').attributes('class')).not.toContain(\n      'n-input--disabled'\n    )\n    await wrapper.setProps({\n      disabled: true\n    })\n    expect(wrapper.find('.n-input').attributes('class')).toContain(\n      'n-input--disabled'\n    )\n    wrapper.unmount()\n  })\n\n  it('should work with `size` prop', async () => {\n    ;(['small', 'medium', 'large'] as const).forEach((item) => {\n      const wrapper = mount(NDatePicker, { props: { size: item } })\n      expect(wrapper.find('.n-input').attributes('style')).toMatchSnapshot()\n      wrapper.unmount()\n    })\n  })\n\n  it('should work with `placeholder` prop', async () => {\n    const wrapper = mount(NDatePicker)\n    expect(wrapper.find('input').attributes('placeholder')).toBe('Select Date')\n    await wrapper.setProps({\n      placeholder: 'test-placeholder'\n    })\n    expect(wrapper.find('input').attributes('placeholder')).toBe(\n      'test-placeholder'\n    )\n    wrapper.unmount()\n  })\n\n  it('should work with `defaultValue` prop', async () => {\n    const wrapper = mount(NDatePicker, {\n      props: {\n        defaultValue: 1183135260000\n      }\n    })\n\n    const inputEl = wrapper.find('.n-input__input').find('input')\n    expect(inputEl.element.value).toEqual(\n      format(1183135260000, 'yyyy-MM-dd', {\n        locale: dateEnUS.locale\n      })\n    )\n    wrapper.unmount()\n  })\n\n  it('should work with `firstDayOfWeek` prop', async () => {\n    const wrapper = mount(NDatePicker, {\n      attachTo: document.body,\n      props: {\n        firstDayOfWeek: 1\n      }\n    })\n\n    await wrapper.find('.n-input__input').trigger('click')\n    expect(\n      document.querySelectorAll('.n-date-panel-weekdays__day')[0].textContent\n    ).toBe('Tu')\n\n    wrapper.unmount()\n  })\n\n  it('should work with `type` prop', async () => {\n    const wrapper = mount(NDatePicker, {\n      attachTo: document.body,\n      props: { type: 'date' }\n    })\n\n    await wrapper.find('.n-input__input').trigger('click')\n    expect(document.querySelector('.n-date-panel--date')).not.toEqual(null)\n\n    await wrapper.setProps({ type: 'datetime' })\n    await wrapper.find('.n-input__input').trigger('click')\n    expect(document.querySelector('.n-date-panel--datetime')).not.toEqual(null)\n\n    await wrapper.setProps({ type: 'daterange' })\n    await wrapper.find('.n-input__input').trigger('click')\n    expect(document.querySelector('.n-date-panel--daterange')).not.toEqual(null)\n\n    await wrapper.setProps({ type: 'datetimerange' })\n    await wrapper.find('.n-input__input').trigger('click')\n    expect(document.querySelector('.n-date-panel--datetimerange')).not.toEqual(\n      null\n    )\n\n    await wrapper.setProps({ type: 'month' })\n    await wrapper.find('.n-input__input').trigger('click')\n    expect(document.querySelector('.n-date-panel--month')).not.toEqual(null)\n\n    wrapper.unmount()\n  })\n\n  it('should work with `onBlur` prop', async () => {\n    const onBlur = vi.fn()\n    const wrapper = mount(NDatePicker, {\n      props: { onBlur }\n    })\n\n    await wrapper.find('input').trigger('focus')\n    await wrapper.find('input').trigger('blur')\n    expect(onBlur).toHaveBeenCalled()\n\n    wrapper.unmount()\n  })\n\n  it('should work with `onFocus` prop', async () => {\n    const onFocus = vi.fn()\n    const wrapper = mount(NDatePicker, {\n      props: { onFocus }\n    })\n\n    await wrapper.find('input').trigger('focus')\n    expect(onFocus).toHaveBeenCalled()\n\n    wrapper.unmount()\n  })\n\n  it('should work with `separator` prop', async () => {\n    const wrapper = mount(NDatePicker, {\n      props: { separator: '07akioni', type: 'daterange' }\n    })\n    expect(wrapper.text().includes('07akioni')).toBe(true)\n    await wrapper.setProps({ separator: '08akioni', type: 'datetimerange' })\n    expect(wrapper.text().includes('08akioni')).toBe(true)\n    wrapper.unmount()\n  })\n\n  it('should work with `status` prop', async () => {\n    ;(['success', 'warning', 'error'] as const).forEach((status) => {\n      const wrapper = mount(NDatePicker, {\n        props: { status }\n      })\n      expect(wrapper.find('.n-input').classes()).toContain(\n        `n-input--${status}-status`\n      )\n      wrapper.unmount()\n    })\n  })\n\n  it('should work with `monthStringType` prop', async () => {\n    const wrapper = mount(NDatePicker, {\n      attachTo: document.body,\n      props: {\n        type: 'month',\n        monthFormat: 'M'\n      }\n    })\n\n    await wrapper.find('.n-input__input').trigger('click')\n    expect(\n      document.querySelectorAll(\n        '.n-date-panel-month-calendar__picker-col-item'\n      )[0].textContent\n    ).toBe('1')\n\n    await wrapper.setProps({ monthFormat: 'MM' })\n    await wrapper.find('.n-input__input').trigger('click')\n    expect(\n      document.querySelectorAll(\n        '.n-date-panel-month-calendar__picker-col-item'\n      )[0].textContent\n    ).toBe('01')\n\n    await wrapper.setProps({ monthFormat: 'MMMM' })\n    await wrapper.find('.n-input__input').trigger('click')\n    expect(\n      document.querySelectorAll(\n        '.n-date-panel-month-calendar__picker-col-item'\n      )[0].textContent\n    ).toBe('January')\n\n    await wrapper.setProps({ monthFormat: 'MMM' })\n    await wrapper.find('.n-input__input').trigger('click')\n    expect(\n      document.querySelectorAll(\n        '.n-date-panel-month-calendar__picker-col-item'\n      )[0].textContent\n    ).toBe('Jan')\n\n    await wrapper.setProps({ monthFormat: 'MMMMM' })\n    await wrapper.find('.n-input__input').trigger('click')\n    expect(\n      document.querySelectorAll(\n        '.n-date-panel-month-calendar__picker-col-item'\n      )[0].textContent\n    ).toBe('J')\n\n    wrapper.unmount()\n  })\n})\n"
  },
  {
    "path": "src/date-picker/tests/__snapshots__/DatePicker.spec.tsx.snap",
    "content": "// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html\n\nexports[`n-date-picker > should work with \\`size\\` prop 1`] = `\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-count-text-color: rgb(118, 124, 130); --n-count-text-color-disabled: rgba(194, 194, 194, 1); --n-color: rgba(255, 255, 255, 1); --n-font-size: 14px; --n-font-weight: 400; --n-border-radius: 3px; --n-height: 28px; --n-padding-left: 10px; --n-padding-right: 10px; --n-text-color: rgb(51, 54, 57); --n-caret-color: #18a058; --n-text-decoration-color: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-focus: 1px solid #36ad6a; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-icon-size: 16px; --n-line-height-textarea: 1.6; --n-color-disabled: rgb(250, 250, 252); --n-color-focus: rgba(255, 255, 255, 1); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-loading-color: #18a058; --n-caret-color-warning: #f0a020; --n-color-focus-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-loading-color-warning: #f0a020; --n-caret-color-error: #d03050; --n-color-focus-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-loading-color-error: #d03050; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-size: 16px; --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-icon-color-hover: rgba(146, 146, 146, 1); --n-icon-color-pressed: rgba(175, 175, 175, 1); --n-icon-color-disabled: rgba(209, 209, 209, 1); --n-suffix-text-color: rgb(51, 54, 57);\"`;\n\nexports[`n-date-picker > should work with \\`size\\` prop 2`] = `\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-count-text-color: rgb(118, 124, 130); --n-count-text-color-disabled: rgba(194, 194, 194, 1); --n-color: rgba(255, 255, 255, 1); --n-font-size: 14px; --n-font-weight: 400; --n-border-radius: 3px; --n-height: 34px; --n-padding-left: 12px; --n-padding-right: 12px; --n-text-color: rgb(51, 54, 57); --n-caret-color: #18a058; --n-text-decoration-color: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-focus: 1px solid #36ad6a; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-icon-size: 16px; --n-line-height-textarea: 1.6; --n-color-disabled: rgb(250, 250, 252); --n-color-focus: rgba(255, 255, 255, 1); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-loading-color: #18a058; --n-caret-color-warning: #f0a020; --n-color-focus-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-loading-color-warning: #f0a020; --n-caret-color-error: #d03050; --n-color-focus-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-loading-color-error: #d03050; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-size: 16px; --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-icon-color-hover: rgba(146, 146, 146, 1); --n-icon-color-pressed: rgba(175, 175, 175, 1); --n-icon-color-disabled: rgba(209, 209, 209, 1); --n-suffix-text-color: rgb(51, 54, 57);\"`;\n\nexports[`n-date-picker > should work with \\`size\\` prop 3`] = `\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-count-text-color: rgb(118, 124, 130); --n-count-text-color-disabled: rgba(194, 194, 194, 1); --n-color: rgba(255, 255, 255, 1); --n-font-size: 15px; --n-font-weight: 400; --n-border-radius: 3px; --n-height: 40px; --n-padding-left: 14px; --n-padding-right: 14px; --n-text-color: rgb(51, 54, 57); --n-caret-color: #18a058; --n-text-decoration-color: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-focus: 1px solid #36ad6a; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-icon-size: 16px; --n-line-height-textarea: 1.6; --n-color-disabled: rgb(250, 250, 252); --n-color-focus: rgba(255, 255, 255, 1); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-loading-color: #18a058; --n-caret-color-warning: #f0a020; --n-color-focus-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-loading-color-warning: #f0a020; --n-caret-color-error: #d03050; --n-color-focus-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-loading-color-error: #d03050; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-size: 16px; --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-icon-color-hover: rgba(146, 146, 146, 1); --n-icon-color-pressed: rgba(175, 175, 175, 1); --n-icon-color-disabled: rgba(209, 209, 209, 1); --n-suffix-text-color: rgb(51, 54, 57);\"`;\n"
  },
  {
    "path": "src/date-picker/tests/server.spec.tsx",
    "content": "import { setup } from '@css-render/vue3-ssr'\nimport { renderToString } from '@vue/server-renderer'\n/**\n * @vitest-environment node\n */\nimport { createSSRApp, h } from 'vue'\nimport { NDatePicker } from '../..'\n\ndescribe('server side rendering', () => {\n  it('works', async () => {\n    const app = createSSRApp(() => <NDatePicker />)\n    setup(app)\n    try {\n      await renderToString(app)\n    }\n    catch (e) {\n      expect(e).not.toBeTruthy()\n    }\n  })\n})\n"
  },
  {
    "path": "src/descriptions/demos/enUS/basic.demo.vue",
    "content": "<markdown>\n# Basic\n</markdown>\n\n<template>\n  <n-descriptions label-placement=\"top\" title=\"Description\">\n    <n-descriptions-item>\n      <template #label>\n        Breakfast\n      </template>\n      Apple\n    </n-descriptions-item>\n    <n-descriptions-item label=\"Brunch\">\n      Apple\n    </n-descriptions-item>\n    <n-descriptions-item label=\"Lunch\">\n      Apple\n    </n-descriptions-item>\n    <n-descriptions-item label=\"Supper\" :span=\"2\">\n      Two<br>\n      Apples\n    </n-descriptions-item>\n    <n-descriptions-item label=\"Midnight Snack\">\n      Apple\n    </n-descriptions-item>\n  </n-descriptions>\n</template>\n"
  },
  {
    "path": "src/descriptions/demos/enUS/bordered.demo.vue",
    "content": "<markdown>\n# Bordered\n\nIf there are too many multiple line fields, you can set it to `bordered`.\n</markdown>\n\n<template>\n  <n-space vertical :size=\"12\">\n    <n-descriptions bordered>\n      <n-descriptions-item>\n        <template #label>\n          Breakfast\n        </template>\n        Apple\n      </n-descriptions-item>\n      <n-descriptions-item label=\"Lunch\">\n        Apple\n      </n-descriptions-item>\n      <n-descriptions-item label=\"Supper\">\n        Apple\n      </n-descriptions-item>\n      <n-descriptions-item label=\"Why Long\">\n        Why<br>\n        Long<br>\n        Long<br>\n        Long<br>\n        Long<br>\n        Long\n      </n-descriptions-item>\n      <n-descriptions-item label=\"Why Long\">\n        Why<br>\n        Long<br>\n        Long<br>\n        Long<br>\n        Long<br>\n        Long\n      </n-descriptions-item>\n      <n-descriptions-item label=\"Why Long\">\n        Why<br>\n        Long<br>\n        Long<br>\n        Long<br>\n        Long<br>\n        Long\n      </n-descriptions-item>\n    </n-descriptions>\n    <n-descriptions label-placement=\"left\" bordered>\n      <n-descriptions-item>\n        <template #label>\n          Breakfast\n        </template>\n        Apple\n      </n-descriptions-item>\n      <n-descriptions-item label=\"Lunch\">\n        Apple\n      </n-descriptions-item>\n      <n-descriptions-item label=\"Supper\">\n        Apple\n      </n-descriptions-item>\n      <n-descriptions-item label=\"Why Long\">\n        Why<br>\n        Long<br>\n        Long<br>\n        Long<br>\n        Long<br>\n        Long\n      </n-descriptions-item>\n      <n-descriptions-item label=\"Why Long\">\n        Why<br>\n        Long<br>\n        Long<br>\n        Long<br>\n        Long<br>\n        Long\n      </n-descriptions-item>\n      <n-descriptions-item label=\"Why Long\">\n        Why<br>\n        Long<br>\n        Long<br>\n        Long<br>\n        Long<br>\n        Long\n      </n-descriptions-item>\n    </n-descriptions>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/descriptions/demos/enUS/columns.demo.vue",
    "content": "<markdown>\n# Columns\n\nYou can adjust items per row by set column of descriptions.\n</markdown>\n\n<template>\n  <n-descriptions label-placement=\"top\" :column=\"4\">\n    <n-descriptions-item>\n      <template #label>\n        Breakfast\n      </template>\n      Apple\n    </n-descriptions-item>\n    <n-descriptions-item label=\"Brunch\">\n      Apple\n    </n-descriptions-item>\n    <n-descriptions-item label=\"Lunch\">\n      Apple\n    </n-descriptions-item>\n    <n-descriptions-item label=\"Supper\">\n      Apple\n    </n-descriptions-item>\n    <n-descriptions-item label=\"Midnight Snack\">\n      Apple\n    </n-descriptions-item>\n  </n-descriptions>\n</template>\n"
  },
  {
    "path": "src/descriptions/demos/enUS/index.demo-entry.md",
    "content": "# Descriptions\n\n<!--single-column-->\n\nDisplay items of content easily.\n\n## Demos\n\n```demo\nbasic.vue\ncolumns.vue\nspan.vue\nplacement.vue\nbordered.vue\nsize.vue\n```\n\n## API\n\n### Descriptions Props\n\n| Name | Type | Default | Description | Version |\n| --- | --- | --- | --- | --- |\n| bordered | `boolean` | `false` | Whether to display border. |  |\n| column | `number` | `3` | Total columns. |  |\n| content-class | `string` | `undefined` | Class of the item content. | 2.36.0 |\n| content-style | `Object \\| string` | `undefined` | Style of the item content. |  |\n| label-align | `'center' \\| 'left' \\| 'right'` | `'left'` | Label align. |  |\n| label-placement | `'top' \\| 'left'` | `'top'` | Label placement. |  |\n| label-class | `string` | `undefined` | Class of the item label. | 2.36.0 |\n| label-style | `Object \\| string` | `undefined` | Style of the item label. |  |\n| separator | `string` | `':'` | Separator, only work when `label-placement` is `left` and `bordered` is `false`. |  |\n| size | `'small' \\| 'medium' \\| 'large'` | `'medium'` | Size of the description. |  |\n| title | `string` | `undefined` | Title of the description. |  |\n\n### DescriptionItem Props\n\n| Name | Type | Default | Description |\n| --- | --- | --- | --- |\n| content-class | `string` | `undefined` | Class of the item content. |\n| content-style | `Object \\| string` | `undefined` | Style of the item content. |\n| label | `string` | `undefined` | Label of the item. |\n| label-class | `string` | `undefined` | Class of the item label. |\n| label-style | `Object \\| string` | `undefined` | Style of the item label. |\n| span | `number` | `1` | Column span of the item. |\n\n### Descriptions Slots\n\n| Name    | Parameters | Description     |\n| ------- | ---------- | --------------- |\n| default | `()`       | Content.        |\n| header  | `()`       | Header content. |\n\n### DescriptionItem Slots\n\n| Name    | Parameters | Description   |\n| ------- | ---------- | ------------- |\n| default | `()`       | Item content. |\n| label   | `()`       | Item label.   |\n"
  },
  {
    "path": "src/descriptions/demos/enUS/placement.demo.vue",
    "content": "<markdown>\n# Label placement\n\nYou can set label placement to `top` or `left`.\n</markdown>\n\n<template>\n  <n-descriptions label-placement=\"left\" title=\"Description\">\n    <n-descriptions-item>\n      <template #label>\n        Breakfast\n      </template>\n      Apple\n    </n-descriptions-item>\n    <n-descriptions-item label=\"Brunch\">\n      Apple\n    </n-descriptions-item>\n    <n-descriptions-item label=\"Lunch\">\n      Apple\n    </n-descriptions-item>\n    <n-descriptions-item label=\"Supper\">\n      Apple\n    </n-descriptions-item>\n    <n-descriptions-item label=\"Midnight Snack\">\n      Apple\n    </n-descriptions-item>\n  </n-descriptions>\n</template>\n"
  },
  {
    "path": "src/descriptions/demos/enUS/size.demo.vue",
    "content": "<markdown>\n# Size\n\nDescription support `small`, `medium` and `large` size.\n</markdown>\n\n<template>\n  <n-space vertical :size=\"12\">\n    <n-descriptions label-placement=\"left\" title=\"Description\" size=\"small\">\n      <n-descriptions-item>\n        <template #label>\n          Breakfast\n        </template>\n        Apple\n      </n-descriptions-item>\n      <n-descriptions-item label=\"Brunch\">\n        Apple\n      </n-descriptions-item>\n      <n-descriptions-item label=\"Lunch\">\n        Apple\n      </n-descriptions-item>\n      <n-descriptions-item label=\"Supper\" :span=\"2\">\n        Two<br>\n        Apples\n      </n-descriptions-item>\n      <n-descriptions-item label=\"Midnight Snack\">\n        Apple\n      </n-descriptions-item>\n    </n-descriptions>\n    <n-descriptions label-placement=\"left\" title=\"Description\" size=\"medium\">\n      <n-descriptions-item>\n        <template #label>\n          Breakfast\n        </template>\n        Apple\n      </n-descriptions-item>\n      <n-descriptions-item label=\"Brunch\">\n        Apple\n      </n-descriptions-item>\n      <n-descriptions-item label=\"Lunch\">\n        Apple\n      </n-descriptions-item>\n      <n-descriptions-item label=\"Supper\" :span=\"2\">\n        Two<br>\n        Apples\n      </n-descriptions-item>\n      <n-descriptions-item label=\"Midnight Snack\">\n        Apple\n      </n-descriptions-item>\n    </n-descriptions>\n    <n-descriptions label-placement=\"left\" title=\"Description\" size=\"large\">\n      <n-descriptions-item>\n        <template #label>\n          Breakfast\n        </template>\n        Apple\n      </n-descriptions-item>\n      <n-descriptions-item label=\"Brunch\">\n        Apple\n      </n-descriptions-item>\n      <n-descriptions-item label=\"Lunch\">\n        Apple\n      </n-descriptions-item>\n      <n-descriptions-item label=\"Supper\" :span=\"2\">\n        Two<br>\n        Apples\n      </n-descriptions-item>\n      <n-descriptions-item label=\"Midnight Snack\">\n        Apple\n      </n-descriptions-item>\n    </n-descriptions>\n    <n-descriptions label-placement=\"top\" title=\"Description\" size=\"small\">\n      <n-descriptions-item>\n        <template #label>\n          Breakfast\n        </template>\n        Apple\n      </n-descriptions-item>\n      <n-descriptions-item label=\"Brunch\">\n        Apple\n      </n-descriptions-item>\n      <n-descriptions-item label=\"Lunch\">\n        Apple\n      </n-descriptions-item>\n      <n-descriptions-item label=\"Supper\" :span=\"2\">\n        Two<br>\n        Apples\n      </n-descriptions-item>\n      <n-descriptions-item label=\"Midnight Snack\">\n        Apple\n      </n-descriptions-item>\n    </n-descriptions>\n    <n-descriptions label-placement=\"top\" title=\"Description\" size=\"medium\">\n      <n-descriptions-item>\n        <template #label>\n          Breakfast\n        </template>\n        Apple\n      </n-descriptions-item>\n      <n-descriptions-item label=\"Brunch\">\n        Apple\n      </n-descriptions-item>\n      <n-descriptions-item label=\"Lunch\">\n        Apple\n      </n-descriptions-item>\n      <n-descriptions-item label=\"Supper\" :span=\"2\">\n        Two<br>\n        Apples\n      </n-descriptions-item>\n      <n-descriptions-item label=\"Midnight Snack\">\n        Apple\n      </n-descriptions-item>\n    </n-descriptions>\n    <n-descriptions label-placement=\"top\" title=\"Description\" size=\"large\">\n      <n-descriptions-item>\n        <template #label>\n          Breakfast\n        </template>\n        Apple\n      </n-descriptions-item>\n      <n-descriptions-item label=\"Brunch\">\n        Apple\n      </n-descriptions-item>\n      <n-descriptions-item label=\"Lunch\">\n        Apple\n      </n-descriptions-item>\n      <n-descriptions-item label=\"Supper\" :span=\"2\">\n        Two<br>\n        Apples\n      </n-descriptions-item>\n      <n-descriptions-item label=\"Midnight Snack\">\n        Apple\n      </n-descriptions-item>\n    </n-descriptions>\n    <n-descriptions\n      label-placement=\"top\"\n      title=\"Description\"\n      size=\"small\"\n      bordered\n    >\n      <n-descriptions-item>\n        <template #label>\n          Breakfast\n        </template>\n        Apple\n      </n-descriptions-item>\n      <n-descriptions-item label=\"Brunch\">\n        Apple\n      </n-descriptions-item>\n      <n-descriptions-item label=\"Lunch\">\n        Apple\n      </n-descriptions-item>\n      <n-descriptions-item label=\"Supper\" :span=\"2\">\n        Two<br>\n        Apples\n      </n-descriptions-item>\n      <n-descriptions-item label=\"Midnight Snack\">\n        Apple\n      </n-descriptions-item>\n    </n-descriptions>\n    <n-descriptions\n      label-placement=\"top\"\n      title=\"Description\"\n      size=\"medium\"\n      bordered\n    >\n      <n-descriptions-item>\n        <template #label>\n          Breakfast\n        </template>\n        Apple\n      </n-descriptions-item>\n      <n-descriptions-item label=\"Brunch\">\n        Apple\n      </n-descriptions-item>\n      <n-descriptions-item label=\"Lunch\">\n        Apple\n      </n-descriptions-item>\n      <n-descriptions-item label=\"Supper\" :span=\"2\">\n        Two<br>\n        Apples\n      </n-descriptions-item>\n      <n-descriptions-item label=\"Midnight Snack\">\n        Apple\n      </n-descriptions-item>\n    </n-descriptions>\n    <n-descriptions\n      label-placement=\"top\"\n      title=\"Description\"\n      size=\"large\"\n      bordered\n    >\n      <n-descriptions-item>\n        <template #label>\n          Breakfast\n        </template>\n        Apple\n      </n-descriptions-item>\n      <n-descriptions-item label=\"Brunch\">\n        Apple\n      </n-descriptions-item>\n      <n-descriptions-item label=\"Lunch\">\n        Apple\n      </n-descriptions-item>\n      <n-descriptions-item label=\"Supper\" :span=\"2\">\n        Two<br>\n        Apples\n      </n-descriptions-item>\n      <n-descriptions-item label=\"Midnight Snack\">\n        Apple\n      </n-descriptions-item>\n    </n-descriptions>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/descriptions/demos/enUS/span.demo.vue",
    "content": "<markdown>\n# Span\n\nYou can set span for each item.\n</markdown>\n\n<template>\n  <n-descriptions label-placement=\"top\" bordered :column=\"6\">\n    <n-descriptions-item>\n      <template #label>\n        Breakfast\n      </template>\n      Apple\n    </n-descriptions-item>\n    <n-descriptions-item label=\"Brunch\">\n      Apple\n    </n-descriptions-item>\n    <n-descriptions-item label=\"Lunch\">\n      Apple\n    </n-descriptions-item>\n    <n-descriptions-item label=\"Supper\">\n      Apple\n    </n-descriptions-item>\n    <n-descriptions-item label=\"Dinner\">\n      Apple\n    </n-descriptions-item>\n    <n-descriptions-item label=\"Midnight Snack\">\n      Apple\n    </n-descriptions-item>\n    <n-descriptions-item label=\"Apple\">\n      Apple\n    </n-descriptions-item>\n    <n-descriptions-item label=\"Apple\" :span=\"2\">\n      Apple\n    </n-descriptions-item>\n    <n-descriptions-item label=\"Apple\" :span=\"3\">\n      Apple\n    </n-descriptions-item>\n  </n-descriptions>\n</template>\n"
  },
  {
    "path": "src/descriptions/demos/zhCN/basic.demo.vue",
    "content": "<markdown>\n# 基础用法\n</markdown>\n\n<template>\n  <n-descriptions label-placement=\"top\" title=\"描述\">\n    <n-descriptions-item>\n      <template #label>\n        早餐\n      </template>\n      苹果\n    </n-descriptions-item>\n    <n-descriptions-item label=\"早午餐\">\n      苹果\n    </n-descriptions-item>\n    <n-descriptions-item label=\"午餐\">\n      苹果\n    </n-descriptions-item>\n    <n-descriptions-item label=\"晚餐\" :span=\"2\">\n      两个<br>\n      苹果\n    </n-descriptions-item>\n    <n-descriptions-item label=\"夜宵\">\n      苹果\n    </n-descriptions-item>\n  </n-descriptions>\n</template>\n"
  },
  {
    "path": "src/descriptions/demos/zhCN/bordered.demo.vue",
    "content": "<markdown>\n# 边框\n\n如果有很多多行的信息，你可以把它设为 `bordered`。\n</markdown>\n\n<template>\n  <n-space vertical :size=\"12\">\n    <n-descriptions bordered>\n      <n-descriptions-item>\n        <template #label>\n          早餐\n        </template>\n        苹果\n      </n-descriptions-item>\n      <n-descriptions-item label=\"午餐\">\n        苹果\n      </n-descriptions-item>\n      <n-descriptions-item label=\"晚餐\">\n        苹果\n      </n-descriptions-item>\n      <n-descriptions-item label=\"为什么长\">\n        为什么<br>长<br>长<br>长<br>长<br>长\n      </n-descriptions-item>\n      <n-descriptions-item label=\"为什么长\">\n        为什么<br>长<br>长<br>长<br>长<br>长\n      </n-descriptions-item>\n      <n-descriptions-item label=\"为什么长\">\n        为什么<br>长<br>长<br>长<br>长<br>长\n      </n-descriptions-item>\n    </n-descriptions>\n    <n-descriptions label-placement=\"left\" bordered>\n      <n-descriptions-item>\n        <template #label>\n          Breakfast\n        </template>\n        苹果\n      </n-descriptions-item>\n      <n-descriptions-item label=\"午餐\">\n        苹果\n      </n-descriptions-item>\n      <n-descriptions-item label=\"晚餐\">\n        苹果\n      </n-descriptions-item>\n      <n-descriptions-item label=\"为什么长\">\n        为什么<br>长<br>长<br>长<br>长<br>长\n      </n-descriptions-item>\n      <n-descriptions-item label=\"为什么长\">\n        为什么<br>长<br>长<br>长<br>长<br>长\n      </n-descriptions-item>\n      <n-descriptions-item label=\"为什么长\">\n        为什么<br>长<br>长<br>长<br>长<br>长\n      </n-descriptions-item>\n    </n-descriptions>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/descriptions/demos/zhCN/columns.demo.vue",
    "content": "<markdown>\n# 列数\n\n可以通过列数来控制每行显示的内容数量。\n</markdown>\n\n<template>\n  <n-descriptions label-placement=\"top\" :column=\"4\">\n    <n-descriptions-item>\n      <template #label>\n        早餐\n      </template>\n      苹果\n    </n-descriptions-item>\n    <n-descriptions-item label=\"早午餐\">\n      苹果\n    </n-descriptions-item>\n    <n-descriptions-item label=\"午餐\">\n      苹果\n    </n-descriptions-item>\n    <n-descriptions-item label=\"晚餐\">\n      苹果\n    </n-descriptions-item>\n    <n-descriptions-item label=\"夜宵\">\n      苹果\n    </n-descriptions-item>\n  </n-descriptions>\n</template>\n"
  },
  {
    "path": "src/descriptions/demos/zhCN/index.demo-entry.md",
    "content": "# 描述 Descriptions\n\n<!--single-column-->\n\n简单的列出信息。\n\n## 演示\n\n```demo\nbasic.vue\ncolumns.vue\nspan.vue\nplacement.vue\nbordered.vue\nsize.vue\nsingle-line-debug.vue\n```\n\n## API\n\n### Descriptions Props\n\n| 名称 | 类型 | 默认值 | 说明 | 版本 |\n| --- | --- | --- | --- | --- |\n| bordered | `boolean` | `false` | 是否显示 border |  |\n| column | `number` | `3` | 设置的总列数 |  |\n| content-class | `string` | `undefined` | 内容的类名 | 2.36.0 |\n| content-style | `Object \\| string` | `undefined` | 内容的样式 |  |\n| label-align | `'center' \\| 'left' \\| 'right'` | `'left'` | label 对齐方式 |  |\n| label-placement | `'top' \\| 'left'` | `'top'` | label 显示位置 |  |\n| label-class | `string` | `undefined` | label 的类名 | 2.36.0 |\n| label-style | `Object \\| string` | `undefined` | label 的样式 |  |\n| separator | `string` | `':'` | 分隔符，`label-placement` 为 `left` 并且 `bordered` 为 `false` 时生效 |  |\n| size | `'small' \\| 'medium' \\| 'large'` | `'medium'` | 尺寸 |  |\n| title | `string` | `undefined` | 标题 |  |\n\n### DescriptionItem Props\n\n| 名称          | 类型               | 默认值      | 说明            |\n| ------------- | ------------------ | ----------- | --------------- |\n| content-class | `string`           | `undefined` | 内容的类名      |\n| content-style | `Object \\| string` | `undefined` | 内容的样式      |\n| label         | `string`           | `undefined` | 显示的 label 值 |\n| label-class   | `string`           | `undefined` | label 的类名    |\n| label-style   | `Object \\| string` | `undefined` | label 的样式    |\n| span          | `number`           | `1`         | 所占的单元格数  |\n\n### Descriptions Slots\n\n| 名称    | 参数 | 说明        |\n| ------- | ---- | ----------- |\n| default | `()` | 描述的内容  |\n| header  | `()` | header 内容 |\n\n### DescriptionItem Slots\n\n| 名称    | 参数 | 说明                |\n| ------- | ---- | ------------------- |\n| default | `()` | 描述项的内容        |\n| label   | `()` | 描述项的 label 信息 |\n"
  },
  {
    "path": "src/descriptions/demos/zhCN/placement.demo.vue",
    "content": "<markdown>\n# 标签位置\n\n标签位置可以在 `top` 或者 `left`。\n</markdown>\n\n<template>\n  <n-descriptions label-placement=\"left\" title=\"描述\">\n    <n-descriptions-item>\n      <template #label>\n        早餐\n      </template>\n      苹果\n    </n-descriptions-item>\n    <n-descriptions-item label=\"早午餐\">\n      苹果\n    </n-descriptions-item>\n    <n-descriptions-item label=\"午餐\">\n      苹果\n    </n-descriptions-item>\n    <n-descriptions-item label=\"晚餐\">\n      苹果\n    </n-descriptions-item>\n    <n-descriptions-item label=\"夜宵\">\n      苹果\n    </n-descriptions-item>\n  </n-descriptions>\n</template>\n"
  },
  {
    "path": "src/descriptions/demos/zhCN/single-line-debug.demo.vue",
    "content": "<markdown>\n# Single line debug\n</markdown>\n\n<template>\n  <n-descriptions label-placement=\"top\" bordered :column=\"6\">\n    <n-descriptions-item label=\"苹果\">\n      苹果\n    </n-descriptions-item>\n    <n-descriptions-item label=\"苹果\" :span=\"2\">\n      苹果\n    </n-descriptions-item>\n    <n-descriptions-item label=\"苹果\" :span=\"3\">\n      苹果\n    </n-descriptions-item>\n  </n-descriptions>\n</template>\n"
  },
  {
    "path": "src/descriptions/demos/zhCN/size.demo.vue",
    "content": "<markdown>\n# 尺寸\n\n有 `small`、`medium`、`large` 尺寸。\n</markdown>\n\n<template>\n  <n-space vertical :size=\"12\">\n    <n-descriptions label-placement=\"left\" title=\"描述\" size=\"small\">\n      <n-descriptions-item>\n        <template #label>\n          早餐\n        </template>\n        苹果\n      </n-descriptions-item>\n      <n-descriptions-item label=\"早午餐\">\n        苹果\n      </n-descriptions-item>\n      <n-descriptions-item label=\"午餐\">\n        苹果\n      </n-descriptions-item>\n      <n-descriptions-item label=\"晚餐\" :span=\"2\">\n        两个<br>\n        苹果\n      </n-descriptions-item>\n      <n-descriptions-item label=\"宵夜\">\n        苹果\n      </n-descriptions-item>\n    </n-descriptions>\n    <n-descriptions label-placement=\"left\" title=\"描述\" size=\"medium\">\n      <n-descriptions-item>\n        <template #label>\n          早餐\n        </template>\n        苹果\n      </n-descriptions-item>\n      <n-descriptions-item label=\"早午餐\">\n        苹果\n      </n-descriptions-item>\n      <n-descriptions-item label=\"午餐\">\n        苹果\n      </n-descriptions-item>\n      <n-descriptions-item label=\"晚餐\" :span=\"2\">\n        两个<br>\n        苹果\n      </n-descriptions-item>\n      <n-descriptions-item label=\"宵夜\">\n        苹果\n      </n-descriptions-item>\n    </n-descriptions>\n    <n-descriptions label-placement=\"left\" title=\"描述\" size=\"large\">\n      <n-descriptions-item>\n        <template #label>\n          早餐\n        </template>\n        苹果\n      </n-descriptions-item>\n      <n-descriptions-item label=\"早午餐\">\n        苹果\n      </n-descriptions-item>\n      <n-descriptions-item label=\"午餐\">\n        苹果\n      </n-descriptions-item>\n      <n-descriptions-item label=\"晚餐\" :span=\"2\">\n        两个<br>\n        苹果\n      </n-descriptions-item>\n      <n-descriptions-item label=\"宵夜\">\n        苹果\n      </n-descriptions-item>\n    </n-descriptions>\n    <n-descriptions label-placement=\"top\" title=\"描述\" size=\"small\">\n      <n-descriptions-item>\n        <template #label>\n          早餐\n        </template>\n        苹果\n      </n-descriptions-item>\n      <n-descriptions-item label=\"早午餐\">\n        苹果\n      </n-descriptions-item>\n      <n-descriptions-item label=\"午餐\">\n        苹果\n      </n-descriptions-item>\n      <n-descriptions-item label=\"晚餐\" :span=\"2\">\n        两个<br>\n        苹果\n      </n-descriptions-item>\n      <n-descriptions-item label=\"宵夜\">\n        苹果\n      </n-descriptions-item>\n    </n-descriptions>\n    <n-descriptions label-placement=\"top\" title=\"描述\" size=\"medium\">\n      <n-descriptions-item>\n        <template #label>\n          早餐\n        </template>\n        苹果\n      </n-descriptions-item>\n      <n-descriptions-item label=\"早午餐\">\n        苹果\n      </n-descriptions-item>\n      <n-descriptions-item label=\"午餐\">\n        苹果\n      </n-descriptions-item>\n      <n-descriptions-item label=\"晚餐\" :span=\"2\">\n        两个<br>\n        苹果\n      </n-descriptions-item>\n      <n-descriptions-item label=\"宵夜\">\n        苹果\n      </n-descriptions-item>\n    </n-descriptions>\n    <n-descriptions label-placement=\"top\" title=\"描述\" size=\"large\">\n      <n-descriptions-item>\n        <template #label>\n          早餐\n        </template>\n        苹果\n      </n-descriptions-item>\n      <n-descriptions-item label=\"早午餐\">\n        苹果\n      </n-descriptions-item>\n      <n-descriptions-item label=\"午餐\">\n        苹果\n      </n-descriptions-item>\n      <n-descriptions-item label=\"晚餐\" :span=\"2\">\n        两个<br>\n        苹果\n      </n-descriptions-item>\n      <n-descriptions-item label=\"宵夜\">\n        苹果\n      </n-descriptions-item>\n    </n-descriptions>\n    <n-descriptions label-placement=\"top\" title=\"描述\" size=\"small\" bordered>\n      <n-descriptions-item>\n        <template #label>\n          早餐\n        </template>\n        苹果\n      </n-descriptions-item>\n      <n-descriptions-item label=\"早午餐\">\n        苹果\n      </n-descriptions-item>\n      <n-descriptions-item label=\"午餐\">\n        苹果\n      </n-descriptions-item>\n      <n-descriptions-item label=\"晚餐\" :span=\"2\">\n        两个<br>\n        苹果\n      </n-descriptions-item>\n      <n-descriptions-item label=\"宵夜\">\n        苹果\n      </n-descriptions-item>\n    </n-descriptions>\n    <n-descriptions label-placement=\"top\" title=\"描述\" size=\"medium\" bordered>\n      <n-descriptions-item>\n        <template #label>\n          早餐\n        </template>\n        苹果\n      </n-descriptions-item>\n      <n-descriptions-item label=\"早午餐\">\n        苹果\n      </n-descriptions-item>\n      <n-descriptions-item label=\"午餐\">\n        苹果\n      </n-descriptions-item>\n      <n-descriptions-item label=\"晚餐\" :span=\"2\">\n        两个<br>\n        苹果\n      </n-descriptions-item>\n      <n-descriptions-item label=\"宵夜\">\n        苹果\n      </n-descriptions-item>\n    </n-descriptions>\n    <n-descriptions label-placement=\"top\" title=\"描述\" size=\"large\" bordered>\n      <n-descriptions-item>\n        <template #label>\n          早餐\n        </template>\n        苹果\n      </n-descriptions-item>\n      <n-descriptions-item label=\"早午餐\">\n        苹果\n      </n-descriptions-item>\n      <n-descriptions-item label=\"午餐\">\n        苹果\n      </n-descriptions-item>\n      <n-descriptions-item label=\"晚餐\" :span=\"2\">\n        两个<br>\n        苹果\n      </n-descriptions-item>\n      <n-descriptions-item label=\"宵夜\">\n        苹果\n      </n-descriptions-item>\n    </n-descriptions>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/descriptions/demos/zhCN/span.demo.vue",
    "content": "<markdown>\n# 跨度\n\n每个描述项都可以设定跨度。\n</markdown>\n\n<template>\n  <n-descriptions label-placement=\"top\" bordered :column=\"6\">\n    <n-descriptions-item>\n      <template #label>\n        早餐\n      </template>\n      苹果\n    </n-descriptions-item>\n    <n-descriptions-item label=\"早午餐\">\n      苹果\n    </n-descriptions-item>\n    <n-descriptions-item label=\"午餐\">\n      苹果\n    </n-descriptions-item>\n    <n-descriptions-item label=\"晚餐\">\n      苹果\n    </n-descriptions-item>\n    <n-descriptions-item label=\"正餐\">\n      苹果\n    </n-descriptions-item>\n    <n-descriptions-item label=\"夜宵\">\n      苹果\n    </n-descriptions-item>\n    <n-descriptions-item label=\"苹果\">\n      苹果\n    </n-descriptions-item>\n    <n-descriptions-item label=\"苹果\" :span=\"2\">\n      苹果\n    </n-descriptions-item>\n    <n-descriptions-item label=\"苹果\" :span=\"3\">\n      苹果\n    </n-descriptions-item>\n  </n-descriptions>\n</template>\n"
  },
  {
    "path": "src/descriptions/index.ts",
    "content": "export { descriptionsProps, default as NDescriptions } from './src/Descriptions'\nexport type {\n  DescriptionProps,\n  DescriptionsProps,\n  DescriptionsSlots\n} from './src/Descriptions'\nexport {\n  descriptionsItemProps,\n  default as NDescriptionsItem\n} from './src/DescriptionsItem'\nexport type {\n  DescriptionItemProps,\n  DescriptionItemSlots\n} from './src/DescriptionsItem'\nexport type * from './src/public-types'\n"
  },
  {
    "path": "src/descriptions/src/Descriptions.tsx",
    "content": "import type { CSSProperties, PropType, SlotsType, VNode } from 'vue'\nimport type { ThemeProps } from '../../_mixins'\nimport type { ExtractPublicPropTypes } from '../../_utils'\nimport type { DescriptionsTheme } from '../styles'\nimport type { DescriptionsSize } from './public-types'\nimport { repeat } from 'seemly'\nimport { useCompitable } from 'vooks'\nimport { computed, defineComponent, h } from 'vue'\nimport { useConfig, useTheme, useThemeClass } from '../../_mixins'\nimport {\n  createKey,\n  flatten,\n  getSlot,\n  getVNodeChildren,\n  warn\n} from '../../_utils'\nimport { descriptionsLight } from '../styles'\nimport style from './styles/index.cssr'\nimport { isDescriptionsItem } from './utils'\n\nexport const descriptionsProps = {\n  ...(useTheme.props as ThemeProps<DescriptionsTheme>),\n  title: String,\n  column: {\n    type: Number,\n    default: 3\n  },\n  columns: Number,\n  labelPlacement: {\n    type: String as PropType<'left' | 'top'>,\n    default: 'top'\n  },\n  labelAlign: {\n    type: String as PropType<'left' | 'right' | 'center'>,\n    default: 'left'\n  },\n  separator: {\n    type: String,\n    default: ':'\n  },\n  size: String as PropType<DescriptionsSize>,\n  bordered: Boolean,\n  labelClass: String,\n  labelStyle: [Object, String] as PropType<string | CSSProperties>,\n  contentClass: String,\n  contentStyle: [Object, String] as PropType<string | CSSProperties>\n} as const\n\nexport type DescriptionsProps = ExtractPublicPropTypes<typeof descriptionsProps>\n/** @deprecated You should use `DescriptionsProps` */\nexport type DescriptionProps = DescriptionsProps\n\nexport interface DescriptionsSlots {\n  default?: () => VNode[]\n  header?: () => VNode[]\n}\n\nexport default defineComponent({\n  name: 'Descriptions',\n  props: descriptionsProps,\n  slots: Object as SlotsType<DescriptionsSlots>,\n  setup(props) {\n    const { mergedClsPrefixRef, inlineThemeDisabled, mergedComponentPropsRef }\n      = useConfig(props)\n    const mergedSizeRef = computed(() => {\n      return (\n        props.size\n        || mergedComponentPropsRef?.value?.Descriptions?.size\n        || 'medium'\n      )\n    })\n    const themeRef = useTheme(\n      'Descriptions',\n      '-descriptions',\n      style,\n      descriptionsLight,\n      props,\n      mergedClsPrefixRef\n    )\n    const cssVarsRef = computed(() => {\n      const { bordered } = props\n      const mergedSize = mergedSizeRef.value\n      const {\n        common: { cubicBezierEaseInOut },\n        self: {\n          titleTextColor,\n          thColor,\n          thColorModal,\n          thColorPopover,\n          thTextColor,\n          thFontWeight,\n          tdTextColor,\n          tdColor,\n          tdColorModal,\n          tdColorPopover,\n          borderColor,\n          borderColorModal,\n          borderColorPopover,\n          borderRadius,\n          lineHeight,\n          [createKey('fontSize', mergedSize)]: fontSize,\n          [createKey(bordered ? 'thPaddingBordered' : 'thPadding', mergedSize)]:\n            thPadding,\n          [createKey(bordered ? 'tdPaddingBordered' : 'tdPadding', mergedSize)]:\n            tdPadding\n        }\n      } = themeRef.value\n      return {\n        '--n-title-text-color': titleTextColor,\n        '--n-th-padding': thPadding,\n        '--n-td-padding': tdPadding,\n        '--n-font-size': fontSize,\n        '--n-bezier': cubicBezierEaseInOut,\n        '--n-th-font-weight': thFontWeight,\n        '--n-line-height': lineHeight,\n        '--n-th-text-color': thTextColor,\n        '--n-td-text-color': tdTextColor,\n        '--n-th-color': thColor,\n        '--n-th-color-modal': thColorModal,\n        '--n-th-color-popover': thColorPopover,\n        '--n-td-color': tdColor,\n        '--n-td-color-modal': tdColorModal,\n        '--n-td-color-popover': tdColorPopover,\n        '--n-border-radius': borderRadius,\n        '--n-border-color': borderColor,\n        '--n-border-color-modal': borderColorModal,\n        '--n-border-color-popover': borderColorPopover\n      }\n    })\n    const themeClassHandle = inlineThemeDisabled\n      ? useThemeClass(\n          'descriptions',\n          computed(() => {\n            let hash = ''\n            const { bordered } = props\n            if (bordered)\n              hash += 'a'\n            hash += mergedSizeRef.value[0]\n            return hash\n          }),\n          cssVarsRef,\n          props\n        )\n      : undefined\n    return {\n      mergedClsPrefix: mergedClsPrefixRef,\n      cssVars: inlineThemeDisabled ? undefined : cssVarsRef,\n      themeClass: themeClassHandle?.themeClass,\n      onRender: themeClassHandle?.onRender,\n      compitableColumn: useCompitable(props, ['columns', 'column']),\n      inlineThemeDisabled,\n      mergedSize: mergedSizeRef\n    }\n  },\n  render() {\n    const defaultSlots = this.$slots.default\n    const children = defaultSlots ? flatten(defaultSlots()) : []\n    const memorizedLength = children.length\n    const {\n      contentClass,\n      labelClass,\n      compitableColumn,\n      labelPlacement,\n      labelAlign,\n      mergedSize,\n      bordered,\n      title,\n      cssVars,\n      mergedClsPrefix,\n      separator,\n      onRender\n    } = this\n    onRender?.()\n    const filteredChildren: VNode[] = children.filter(child =>\n      isDescriptionsItem(child)\n    )\n    if (__DEV__ && memorizedLength !== filteredChildren.length) {\n      warn(\n        'descriptions',\n        '`n-descriptions` only takes `n-descriptions-item` as children.'\n      )\n    }\n    const defaultState: {\n      span: number\n      row: VNode[]\n      secondRow: VNode[]\n      rows: VNode[][]\n    } = {\n      span: 0,\n      row: [],\n      secondRow: [],\n      rows: []\n    }\n    const itemState = filteredChildren.reduce((state, vNode, index) => {\n      const props = vNode.props || {}\n      const isLastIteration = filteredChildren.length - 1 === index\n      const itemLabel = [\n        'label' in props ? props.label : getVNodeChildren(vNode, 'label')\n      ]\n      const itemChildren = [getVNodeChildren(vNode)]\n      const itemSpan = (props.span as number) || 1\n      const memorizedSpan = state.span\n      state.span += itemSpan\n      const labelStyle\n        = props.labelStyle || props['label-style'] || this.labelStyle\n      const contentStyle\n        = props.contentStyle || props['content-style'] || this.contentStyle\n      if (labelPlacement === 'left') {\n        if (bordered) {\n          state.row.push(\n            <th\n              class={[\n                `${mergedClsPrefix}-descriptions-table-header`,\n                labelClass\n              ]}\n              colspan={1}\n              style={labelStyle}\n            >\n              {itemLabel}\n            </th>,\n            <td\n              class={[\n                `${mergedClsPrefix}-descriptions-table-content`,\n                contentClass\n              ]}\n              colspan={\n                isLastIteration\n                  ? (compitableColumn - memorizedSpan) * 2 + 1\n                  : itemSpan * 2 - 1\n              }\n              style={contentStyle}\n            >\n              {itemChildren}\n            </td>\n          )\n        }\n        else {\n          state.row.push(\n            <td\n              class={`${mergedClsPrefix}-descriptions-table-content`}\n              colspan={\n                isLastIteration\n                  ? (compitableColumn - memorizedSpan) * 2\n                  : itemSpan * 2\n              }\n            >\n              <span\n                class={[\n                  `${mergedClsPrefix}-descriptions-table-content__label`,\n                  labelClass\n                ]}\n                style={labelStyle}\n              >\n                {[\n                  ...itemLabel,\n                  separator && (\n                    <span class={`${mergedClsPrefix}-descriptions-separator`}>\n                      {separator}\n                    </span>\n                  )\n                ]}\n              </span>\n              <span\n                class={[\n                  `${mergedClsPrefix}-descriptions-table-content__content`,\n                  contentClass\n                ]}\n                style={contentStyle}\n              >\n                {itemChildren}\n              </span>\n            </td>\n          )\n        }\n      }\n      else {\n        const colspan = isLastIteration\n          ? (compitableColumn - memorizedSpan) * 2\n          : itemSpan * 2\n        state.row.push(\n          <th\n            class={[`${mergedClsPrefix}-descriptions-table-header`, labelClass]}\n            colspan={colspan}\n            style={labelStyle}\n          >\n            {itemLabel}\n          </th>\n        )\n        state.secondRow.push(\n          <td\n            class={[\n              `${mergedClsPrefix}-descriptions-table-content`,\n              contentClass\n            ]}\n            colspan={colspan}\n            style={contentStyle}\n          >\n            {itemChildren}\n          </td>\n        )\n      }\n      if (state.span >= compitableColumn || isLastIteration) {\n        state.span = 0\n        if (state.row.length) {\n          state.rows.push(state.row)\n          state.row = []\n        }\n        if (labelPlacement !== 'left') {\n          if (state.secondRow.length) {\n            state.rows.push(state.secondRow)\n            state.secondRow = []\n          }\n        }\n      }\n      return state\n    }, defaultState)\n    const rows = itemState.rows.map(row => (\n      <tr class={`${mergedClsPrefix}-descriptions-table-row`}>{row}</tr>\n    ))\n    return (\n      <div\n        style={cssVars as any}\n        class={[\n          `${mergedClsPrefix}-descriptions`,\n          this.themeClass,\n          `${mergedClsPrefix}-descriptions--${labelPlacement}-label-placement`,\n          `${mergedClsPrefix}-descriptions--${labelAlign}-label-align`,\n          `${mergedClsPrefix}-descriptions--${mergedSize}-size`,\n          bordered && `${mergedClsPrefix}-descriptions--bordered`\n        ]}\n      >\n        {title || this.$slots.header ? (\n          <div class={`${mergedClsPrefix}-descriptions-header`}>\n            {title || getSlot(this, 'header')}\n          </div>\n        ) : null}\n        <div class={`${mergedClsPrefix}-descriptions-table-wrapper`}>\n          <table class={`${mergedClsPrefix}-descriptions-table`}>\n            <tbody>\n              {labelPlacement === 'top' && (\n                <tr\n                  class={`${mergedClsPrefix}-descriptions-table-row`}\n                  style={{\n                    visibility: 'collapse'\n                  }}\n                >\n                  {repeat(compitableColumn * 2, <td />)}\n                </tr>\n              )}\n              {rows}\n            </tbody>\n          </table>\n        </div>\n      </div>\n    )\n  }\n})\n"
  },
  {
    "path": "src/descriptions/src/DescriptionsItem.ts",
    "content": "import type { CSSProperties, PropType, SlotsType, VNode } from 'vue'\nimport type { ExtractPublicPropTypes } from '../../_utils'\nimport { defineComponent } from 'vue'\nimport { DESCRIPTION_ITEM_FLAG } from './utils'\n\nexport const descriptionsItemProps = {\n  label: String,\n  span: {\n    type: Number,\n    default: 1\n  },\n  labelClass: String,\n  labelStyle: [Object, String] as PropType<string | CSSProperties>,\n  contentClass: String,\n  contentStyle: [Object, String] as PropType<string | CSSProperties>\n} as const\n\nexport type DescriptionItemProps = ExtractPublicPropTypes<\n  typeof descriptionsItemProps\n>\n\nexport interface DescriptionItemSlots {\n  default?: () => VNode[]\n  label?: () => VNode[]\n}\n\nexport default defineComponent({\n  name: 'DescriptionsItem',\n  [DESCRIPTION_ITEM_FLAG]: true,\n  props: descriptionsItemProps,\n  slots: Object as SlotsType<DescriptionItemSlots>,\n  render() {\n    return null\n  }\n})\n"
  },
  {
    "path": "src/descriptions/src/public-types.ts",
    "content": "export type DescriptionsSize = 'small' | 'medium' | 'large'\n"
  },
  {
    "path": "src/descriptions/src/styles/index.cssr.ts",
    "content": "import { c, cB, cE, cM, cNotM, insideModal, insidePopover } from '../../../_utils/cssr'\n\n// vars:\n// --n-th-padding\n// --n-td-padding\n// --n-font-size\n// --n-bezier\n// --n-th-font-weight\n// --n-line-height\n// --n-th-text-color\n// --n-td-text-color\n// --n-th-color\n// --n-th-color-modal\n// --n-th-color-popover\n// --n-td-color\n// --n-td-color-modal\n// --n-td-color-popover\n// --n-border-radius\n// --n-border-color\n// --n-border-color-modal\n// --n-border-color-popover\n// --n-title-text-color\nexport default c([\n  cB('descriptions', {\n    fontSize: 'var(--n-font-size)'\n  }, [\n    cB('descriptions-separator', `\n      display: inline-block;\n      margin: 0 8px 0 2px;\n    `),\n    cB('descriptions-table-wrapper', [\n      cB('descriptions-table', [\n        cB('descriptions-table-row', [\n          cB('descriptions-table-header', {\n            padding: 'var(--n-th-padding)'\n          }),\n          cB('descriptions-table-content', {\n            padding: 'var(--n-td-padding)'\n          })\n        ])\n      ])\n    ]),\n    cNotM('bordered', [\n      cB('descriptions-table-wrapper', [\n        cB('descriptions-table', [\n          cB('descriptions-table-row', [\n            c('&:last-child', [\n              cB('descriptions-table-content', {\n                paddingBottom: 0\n              })\n            ])\n          ])\n        ])\n      ])\n    ]),\n    cM('left-label-placement', [\n      cB('descriptions-table-content', [\n        c('> *', {\n          verticalAlign: 'top'\n        })\n      ])\n    ]),\n    cM('left-label-align', [\n      c('th', {\n        textAlign: 'left'\n      })\n    ]),\n    cM('center-label-align', [\n      c('th', {\n        textAlign: 'center'\n      })\n    ]),\n    cM('right-label-align', [\n      c('th', {\n        textAlign: 'right'\n      })\n    ]),\n    cM('bordered', [\n      cB('descriptions-table-wrapper', `\n        border-radius: var(--n-border-radius);\n        overflow: hidden;\n        background: var(--n-merged-td-color);\n        border: 1px solid var(--n-merged-border-color);\n      `, [\n        cB('descriptions-table', [\n          cB('descriptions-table-row', [\n            c('&:not(:last-child)', [\n              cB('descriptions-table-content', {\n                borderBottom: '1px solid var(--n-merged-border-color)'\n              }),\n              cB('descriptions-table-header', {\n                borderBottom: '1px solid var(--n-merged-border-color)'\n              })\n            ]),\n            cB('descriptions-table-header', `\n              font-weight: 400;\n              background-clip: padding-box;\n              background-color: var(--n-merged-th-color);\n            `, [\n              c('&:not(:last-child)', {\n                borderRight: '1px solid var(--n-merged-border-color)'\n              })\n            ]),\n            cB('descriptions-table-content', [\n              c('&:not(:last-child)', {\n                borderRight: '1px solid var(--n-merged-border-color)'\n              })\n            ])\n          ])\n        ])\n      ])\n    ]),\n    cB('descriptions-header', `\n      font-weight: var(--n-th-font-weight);\n      font-size: 18px;\n      transition: color .3s var(--n-bezier);\n      line-height: var(--n-line-height);\n      margin-bottom: 16px;\n      color: var(--n-title-text-color);\n    `),\n    cB('descriptions-table-wrapper', `\n      transition:\n        background-color .3s var(--n-bezier),\n        border-color .3s var(--n-bezier);\n    `, [\n      cB('descriptions-table', `\n        width: 100%;\n        border-collapse: separate;\n        border-spacing: 0;\n        box-sizing: border-box;\n      `, [\n        cB('descriptions-table-row', `\n          box-sizing: border-box;\n          transition: border-color .3s var(--n-bezier);\n        `, [\n          cB('descriptions-table-header', `\n            font-weight: var(--n-th-font-weight);\n            line-height: var(--n-line-height);\n            display: table-cell;\n            box-sizing: border-box;\n            color: var(--n-th-text-color);\n            transition:\n              color .3s var(--n-bezier),\n              background-color .3s var(--n-bezier),\n              border-color .3s var(--n-bezier);\n          `),\n          cB('descriptions-table-content', `\n            vertical-align: top;\n            line-height: var(--n-line-height);\n            display: table-cell;\n            box-sizing: border-box;\n            color: var(--n-td-text-color);\n            transition:\n              color .3s var(--n-bezier),\n              background-color .3s var(--n-bezier),\n              border-color .3s var(--n-bezier);\n          `, [\n            cE('content', `\n              transition: color .3s var(--n-bezier);\n              display: inline-block;\n              color: var(--n-td-text-color);\n            `)\n          ]),\n          cE('label', `\n            font-weight: var(--n-th-font-weight);\n            transition: color .3s var(--n-bezier);\n            display: inline-block;\n            margin-right: 14px;\n            color: var(--n-th-text-color);\n          `)\n        ])\n      ])\n    ])\n  ]),\n  cB('descriptions-table-wrapper', `\n    --n-merged-th-color: var(--n-th-color);\n    --n-merged-td-color: var(--n-td-color);\n    --n-merged-border-color: var(--n-border-color);\n  `),\n  insideModal(\n    cB('descriptions-table-wrapper', `\n      --n-merged-th-color: var(--n-th-color-modal);\n      --n-merged-td-color: var(--n-td-color-modal);\n      --n-merged-border-color: var(--n-border-color-modal);\n    `)\n  ),\n  insidePopover(\n    cB('descriptions-table-wrapper', `\n      --n-merged-th-color: var(--n-th-color-popover);\n      --n-merged-td-color: var(--n-td-color-popover);\n      --n-merged-border-color: var(--n-border-color-popover);\n    `)\n  )\n])\n"
  },
  {
    "path": "src/descriptions/src/utils.ts",
    "content": "import type { VNodeChild } from 'vue'\n\nexport const DESCRIPTION_ITEM_FLAG = 'DESCRIPTION_ITEM_FLAG'\n\nexport function isDescriptionsItem(vNode: VNodeChild): boolean {\n  if (typeof vNode === 'object' && vNode && !Array.isArray(vNode)) {\n    return vNode.type && (vNode.type as any)[DESCRIPTION_ITEM_FLAG]\n  }\n  return false\n}\n"
  },
  {
    "path": "src/descriptions/styles/_common.ts",
    "content": "export default {\n  thPaddingBorderedSmall: '8px 12px',\n  thPaddingBorderedMedium: '12px 16px',\n  thPaddingBorderedLarge: '16px 24px',\n  thPaddingSmall: '0',\n  thPaddingMedium: '0',\n  thPaddingLarge: '0',\n  tdPaddingBorderedSmall: '8px 12px',\n  tdPaddingBorderedMedium: '12px 16px',\n  tdPaddingBorderedLarge: '16px 24px',\n  tdPaddingSmall: '0 0 8px 0',\n  tdPaddingMedium: '0 0 12px 0',\n  tdPaddingLarge: '0 0 16px 0'\n}\n"
  },
  {
    "path": "src/descriptions/styles/dark.ts",
    "content": "import type { DescriptionsTheme } from './light'\nimport { commonDark } from '../../_styles/common'\nimport { self } from './light'\n\nconst descriptionsDark: DescriptionsTheme = {\n  name: 'Descriptions',\n  common: commonDark,\n  self\n}\n\nexport default descriptionsDark\n"
  },
  {
    "path": "src/descriptions/styles/index.ts",
    "content": "export { default as descriptionsDark } from './dark'\nexport { default as descriptionsLight } from './light'\nexport type { DescriptionsTheme, DescriptionsThemeVars } from './light'\n"
  },
  {
    "path": "src/descriptions/styles/light.ts",
    "content": "import type { Theme } from '../../_mixins/use-theme'\nimport type { ThemeCommonVars } from '../../_styles/common'\nimport { composite } from 'seemly'\nimport { commonLight } from '../../_styles/common'\nimport commonVariables from './_common'\n\nexport function self(vars: ThemeCommonVars) {\n  const {\n    tableHeaderColor,\n    textColor2,\n    textColor1,\n    cardColor,\n    modalColor,\n    popoverColor,\n    dividerColor,\n    borderRadius,\n    fontWeightStrong,\n    lineHeight,\n    fontSizeSmall,\n    fontSizeMedium,\n    fontSizeLarge\n  } = vars\n  return {\n    ...commonVariables,\n    lineHeight,\n    fontSizeSmall,\n    fontSizeMedium,\n    fontSizeLarge,\n    titleTextColor: textColor1,\n    thColor: composite(cardColor, tableHeaderColor),\n    thColorModal: composite(modalColor, tableHeaderColor),\n    thColorPopover: composite(popoverColor, tableHeaderColor),\n    thTextColor: textColor1,\n    thFontWeight: fontWeightStrong,\n    tdTextColor: textColor2,\n    tdColor: cardColor,\n    tdColorModal: modalColor,\n    tdColorPopover: popoverColor,\n    borderColor: composite(cardColor, dividerColor),\n    borderColorModal: composite(modalColor, dividerColor),\n    borderColorPopover: composite(popoverColor, dividerColor),\n    borderRadius\n  }\n}\n\nexport type DescriptionsThemeVars = ReturnType<typeof self>\n\nconst descriptionsLight: Theme<'Descriptions', DescriptionsThemeVars> = {\n  name: 'Descriptions',\n  common: commonLight,\n  self\n}\n\nexport default descriptionsLight\nexport type DescriptionsTheme = typeof descriptionsLight\n"
  },
  {
    "path": "src/descriptions/tests/Descriptions.spec.ts",
    "content": "import type { VNode } from 'vue'\nimport { mount } from '@vue/test-utils'\nimport { h } from 'vue'\nimport { NDescriptions, NDescriptionsItem } from '../index'\n\nfunction getDescriptionsItemList(): VNode[] {\n  return (['早餐', '午餐', '晚餐', '夜宵'] as const).map((item) => {\n    return h(NDescriptionsItem, { label: item }, { default: () => item })\n  })\n}\n\ndescribe('n-descriptions', () => {\n  it('should work with import on demand', () => {\n    mount(NDescriptions)\n  })\n\n  it('should work with slots', async () => {\n    let wrapper = mount(NDescriptions, {\n      slots: { default: () => getDescriptionsItemList(), header: () => 'test' }\n    })\n    expect(wrapper.findAll('.n-descriptions-table-header').length).toBe(4)\n    expect(wrapper.findAll('.n-descriptions-table-content').length).toBe(4)\n\n    expect(wrapper.find('.n-descriptions-header').exists()).toBe(true)\n    expect(wrapper.find('.n-descriptions-header').text()).toBe('test')\n\n    wrapper = mount(NDescriptions, {\n      slots: {\n        default: () =>\n          h(NDescriptionsItem, null, {\n            default: () => 'test-default',\n            label: () => 'test-label'\n          })\n      }\n    })\n\n    expect(wrapper.find('.n-descriptions-table-header').text()).toBe(\n      'test-label'\n    )\n    expect(wrapper.find('.n-descriptions-table-content').text()).toBe(\n      'test-default'\n    )\n    wrapper.unmount()\n  })\n\n  it('should work with `bordered` prop', async () => {\n    const wrapper = mount(NDescriptions)\n    expect(wrapper.find('.n-descriptions').classes()).not.toContain(\n      'n-descriptions--bordered'\n    )\n\n    await wrapper.setProps({ bordered: true })\n    expect(wrapper.find('.n-descriptions').classes()).toContain(\n      'n-descriptions--bordered'\n    )\n    wrapper.unmount()\n  })\n\n  it('should work with `column` prop', async () => {\n    const wrapper = mount(NDescriptions, {\n      slots: { default: () => getDescriptionsItemList() }\n    })\n    expect(\n      wrapper.find('.n-descriptions-table-row').element.childNodes.length\n    ).toBe(6) // 3 * 2\n\n    await wrapper.setProps({ column: 4 })\n    expect(\n      wrapper.find('.n-descriptions-table-row').element.childNodes.length\n    ).toBe(8) // 4 * 2\n    wrapper.unmount()\n  })\n\n  it('should work with `label-align` prop', async () => {\n    const wrapper = mount(NDescriptions, {\n      slots: { default: () => getDescriptionsItemList() }\n    })\n    expect(wrapper.find('.n-descriptions').classes()).toContain(\n      'n-descriptions--left-label-align'\n    )\n\n    await wrapper.setProps({ labelAlign: 'center' })\n    expect(wrapper.find('.n-descriptions').classes()).toContain(\n      'n-descriptions--center-label-align'\n    )\n\n    await wrapper.setProps({ labelAlign: 'right' })\n    expect(wrapper.find('.n-descriptions').classes()).toContain(\n      'n-descriptions--right-label-align'\n    )\n    wrapper.unmount()\n  })\n\n  it('should work with `label-placement` prop', async () => {\n    const wrapper = mount(NDescriptions, {\n      slots: { default: () => getDescriptionsItemList() }\n    })\n    expect(wrapper.find('.n-descriptions').classes()).toContain(\n      'n-descriptions--top-label-placement'\n    )\n\n    await wrapper.setProps({ labelPlacement: 'left' })\n    expect(wrapper.find('.n-descriptions').classes()).toContain(\n      'n-descriptions--left-label-placement'\n    )\n    wrapper.unmount()\n  })\n\n  it('should work with `size` prop', async () => {\n    const wrapper = mount(NDescriptions, {\n      slots: { default: () => getDescriptionsItemList() }\n    })\n    expect(wrapper.find('.n-descriptions').classes()).toContain(\n      'n-descriptions--medium-size'\n    )\n\n    await wrapper.setProps({ size: 'small' })\n    expect(wrapper.find('.n-descriptions').classes()).toContain(\n      'n-descriptions--small-size'\n    )\n\n    await wrapper.setProps({ size: 'large' })\n    expect(wrapper.find('.n-descriptions').classes()).toContain(\n      'n-descriptions--large-size'\n    )\n    wrapper.unmount()\n  })\n\n  it('should work with `title` prop', async () => {\n    const wrapper = mount(NDescriptions, {\n      slots: { default: () => getDescriptionsItemList() }\n    })\n    expect(wrapper.find('.n-descriptions-header').exists()).not.toBe(true)\n\n    await wrapper.setProps({ title: 'test' })\n    expect(wrapper.find('.n-descriptions-header').exists()).toBe(true)\n    expect(wrapper.find('.n-descriptions-header').text()).toBe('test')\n    wrapper.unmount()\n  })\n\n  it('should work with `separator` prop', async () => {\n    const wrapper = mount(NDescriptions, {\n      props: {\n        labelPlacement: 'left'\n      },\n      slots: { default: () => getDescriptionsItemList() }\n    })\n    expect(wrapper.find('.n-descriptions-separator').text()).toEqual(':')\n\n    await wrapper.setProps({ separator: '/' })\n    expect(wrapper.find('.n-descriptions-separator').text()).toEqual('/')\n    wrapper.unmount()\n  })\n\n  it('should work with `content-style` prop', () => {\n    const wrapper = mount(NDescriptions, {\n      props: {\n        contentStyle: { backgroundColor: 'red' }\n      },\n      slots: {\n        default: () => h(NDescriptionsItem, {}, 'test')\n      }\n    })\n\n    expect(\n      wrapper.find('.n-descriptions-table-content').attributes('style')\n    ).toBe('background-color: red;')\n    wrapper.unmount()\n  })\n\n  it('should work with `label-style` prop', () => {\n    const wrapper = mount(NDescriptions, {\n      props: {\n        labelStyle: { fontSize: '30px' }\n      },\n      slots: {\n        default: () => h(NDescriptionsItem, {}, 'test')\n      }\n    })\n\n    expect(\n      wrapper.find('.n-descriptions-table-header').attributes('style')\n    ).toBe('font-size: 30px;')\n    wrapper.unmount()\n  })\n})\n"
  },
  {
    "path": "src/descriptions/tests/server.spec.tsx",
    "content": "import { setup } from '@css-render/vue3-ssr'\nimport { renderToString } from '@vue/server-renderer'\n/**\n * @vitest-environment node\n */\nimport { createSSRApp, h } from 'vue'\nimport { NDescriptions } from '../..'\n\ndescribe('server side rendering', () => {\n  it('works', async () => {\n    const app = createSSRApp(() => <NDescriptions />)\n    setup(app)\n    try {\n      await renderToString(app)\n    }\n    catch (e) {\n      expect(e).not.toBeTruthy()\n    }\n  })\n})\n"
  },
  {
    "path": "src/dialog/demos/enUS/action.demo.vue",
    "content": "<markdown>\n# Customize action\n\nSometimes you may want to customize `action` and `content` .\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { useDialog } from 'naive-ui'\n\nconst dialog = useDialog()\n\nfunction handleConfirm() {\n  dialog.warning({\n    title: 'Use Render Function',\n    content: () => 'Content',\n    action: () => 'Action'\n  })\n}\n</script>\n\n<template>\n  <n-space>\n    <n-button @click=\"handleConfirm\">\n      Use Render Function\n    </n-button>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/dialog/demos/enUS/async.demo.vue",
    "content": "<markdown>\n# Async\n\nDialog can be async.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { useDialog } from 'naive-ui'\n\nconst sleep = () => new Promise(resolve => setTimeout(resolve, 1000))\nconst countDown = (second: number) => `Count down ${second} second`\n\nconst dialog = useDialog()\n\nfunction handleClick() {\n  const d = dialog.success({\n    title: 'Async',\n    content: 'Click and count down 3 second',\n    positiveText: 'Confirm',\n    onPositiveClick: () => {\n      d.loading = true\n      return new Promise((resolve) => {\n        sleep()\n          .then(() => {\n            d.content = countDown(2)\n            return sleep()\n          })\n          .then(() => {\n            d.content = countDown(1)\n            return sleep()\n          })\n          .then(() => {\n            d.content = countDown(0)\n          })\n          .then(resolve)\n      })\n    }\n  })\n}\n</script>\n\n<template>\n  <n-button @click=\"handleClick\">\n    Success\n  </n-button>\n</template>\n"
  },
  {
    "path": "src/dialog/demos/enUS/basic.demo.vue",
    "content": "<markdown>\n# Basic\n\nInject `dialog` to create a dialog.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { useDialog, useMessage } from 'naive-ui'\n\nconst message = useMessage()\nconst dialog = useDialog()\n\nfunction handleConfirm() {\n  dialog.warning({\n    title: 'Confirm',\n    content: 'Are you sure?',\n    positiveText: 'Sure',\n    negativeText: 'Not Sure',\n    draggable: true,\n    onPositiveClick: () => {\n      message.success('Sure')\n    },\n    onNegativeClick: () => {\n      message.error('Not Sure')\n    }\n  })\n}\n\nfunction handleSuccess() {\n  dialog.success({\n    title: 'Success',\n    content: 'Cool',\n    positiveText: 'Wow!',\n    onPositiveClick: () => {\n      message.success('Great!')\n    }\n  })\n}\n\nfunction handleError() {\n  dialog.error({\n    title: 'Error',\n    content: 'A mistake.',\n    positiveText: 'Ahhh!',\n    onPositiveClick: () => {\n      message.success('I knew it...')\n    }\n  })\n}\n</script>\n\n<template>\n  <n-space>\n    <n-button @click=\"handleConfirm\">\n      Confirm\n    </n-button>\n    <n-button @click=\"handleSuccess\">\n      Success\n    </n-button>\n    <n-button @click=\"handleError\">\n      Error\n    </n-button>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/dialog/demos/enUS/index.demo-entry.md",
    "content": "# Dialog\n\nBefore taking action, please confirm.\n\n<n-alert title=\"Prerequisite\" type=\"warning\" :bordered=\"false\">\n  If you want to use dialog, you need to wrap the component where you call related methods inside <n-text code>n-dialog-provider</n-text> and use <n-text code>useDialog</n-text> to get the API.\n</n-alert>\n\nFor example:\n\n```html\n<!-- App.vue -->\n<n-dialog-provider>\n  <content />\n</n-dialog-provider>\n```\n\n```js\nimport { useDialog } from 'naive-ui'\nimport { defineComponent } from 'vue'\n\n// content\nexport default defineComponent({\n  setup() {\n    const dialog = useDialog()\n    return {\n      warning() {\n        dialog.warning(options)\n      }\n    }\n  }\n})\n```\n\n## Demos\n\n```demo\nbasic.vue\nasync.vue\nuse-component.vue\nmask.vue\naction.vue\nuse-dialog-reactive-list.vue\n```\n\n## API\n\n### useDialog API\n\n| Name | Type | Description |\n| --- | --- | --- |\n| destroyAll | `() => void` | Destroy all popup dialogs. |\n| create | `(options: DialogOptions) => DialogReactive` | Create a dialog. |\n| error | `(options: DialogOptions) => DialogReactive` | Use `error` type dialog. |\n| info | `(options: DialogOptions) => DialogReactive` | Use `info` type dialog. |\n| success | `(options: DialogOptions) => DialogReactive` | Use `success` type dialog. |\n| warning | `(options: DialogOptions) => DialogReactive` | Use `warning` type dialog. |\n\n### useDialogReactiveList API\n\n`() => Ref<readonly DialogReactive[]>`\n\n### DialogOptions Properties\n\n| Name | Type | Default | Description | Version |\n| --- | --- | --- | --- | --- |\n| action | `() => VNodeChild` | `undefined` | Content of the operation area, must be a render function. |  |\n| actionClass | `string` | `undefined` | The class name of the action area. | 2.38.2 |\n| actionStyle | `Object \\| string` | `undefined` | The style of the action area. | 2.38.2 |\n| autoFocus | `boolean` | `true` | Whether to focus the first focusable element inside modal. | 2.28.3 |\n| blockScroll | `boolean` | `true` | Whether to disabled body scrolling when it's active. | 2.28.3 |\n| bordered | `boolean` | `false` | Whether to show `border`. |  |\n| class | `any` | `undefined` | Class name of the dialog. | 2.33.0 |\n| closable | `boolean` | `true` | Whether to show `close` icon. |  |\n| closeFocusable | `boolean` | `false` | Whether the close button is focusable. | 2.43.0 |\n| closeOnEsc | `boolean` | `true` | Whether to close the dialog when the Esc key is pressed | 2.26.4 |\n| content | `string \\| (() => VNodeChild)` | `undefined` | Content, can be a render function. |  |\n| contentClass | `string` | `undefined` | The class name of the content. | 2.38.2 |\n| contentStyle | `Object \\| string` | `undefined` | The style of the content. | 2.38.2 |\n| draggable | `boolean \\| { bounds?: 'none' }` | `false` | Whether it is draggable. | 2.41.0 |\n| iconPlacement | `'left' \\| 'top'` | `'left'` | Icon placement. |  |\n| icon | `() => VNodeChild` | `undefined` | `Render` function of `icon`. |  |\n| loading | `boolean` | `false` | Whether to display `loading` status. |  |\n| maskClosable | `boolean` | `true` | Whether the dialog can be closed by clicking the `mask`. |  |\n| negativeButtonProps | `ButtonProps` | `undefined` | Cancel button's DOM props | 2.27.0 |\n| negativeText | `string` | `undefined` | Cancel button text. Corresponding button won't show if not set. |  |\n| positiveButtonProps | `ButtonProps` | `undefined` | Confirm button's DOM props | 2.27.0 |\n| positiveText | `string` | `undefined` | Confirm button text. Corresponding button won't show if not set. |  |\n| showIcon | `boolean` | `true` | Whether to show `icon`. |  |\n| style | `string \\| Object` | `undefined` | Style of the dialog. |  |\n| title | `string \\| (() => VNodeChild)` | `undefined` | Title, can be a render function. |  |\n| titleClass | `string` | `undefined` | The class name of the content. | 2.38.2 |\n| titleStyle | `Object \\| string` | `undefined` | The style of the content. | 2.38.2 |\n| transformOrigin | `'mouse' \\| 'center'` | `'mouse'` | The transform origin of the dialog's display animation. | 2.34.0 |\n| type | `'error \\| 'success' \\| 'warning'` | `'warning'` | Dialog type. |  |\n| zIndex | `number` | `undefined` | Z index of the dialog. | 2.43.0 |\n| onAfterEnter | `() => void` | `undefined` | Callback on enter animation ends. | 2.33.0 |\n| onAfterLeave | `() => void` | `undefined` | Callback on leave animation ends. | 2.33.3 |\n| onClose | `() => boolean \\| Promise<boolean> \\| any` | `undefined` | The default behavior is closing the confirm. Return `false` or resolve `false` or `Promise rejected` will prevent the default behavior. |  |\n| onNegativeClick | `(e: MouseEvent) => boolean \\| Promise<boolean> \\| any` | `undefined` | The default behavior is closing the confirm. Return `false` or resolve `false` or `Promise rejected` will prevent the default behavior. |  |\n| onPositiveClick | `(e: MouseEvent) => boolean \\| Promise<boolean> \\| any` | `undefined` | The default behavior is closing the confirm. Return `false` or resolve `false` or `Promise rejected` will prevent the default behavior. |  |\n| onMaskClick | `() => void` | `undefined` | Callback triggered when click the mask. |  |\n\n### DialogReactive API\n\n#### DialogReactive Properties\n\nAll the properties can be modified dynamically.\n\n| Name | Type | Description | Version |\n| --- | --- | --- | --- |\n| actionClass | `string` | The class name of the action area. | 2.38.2 |\n| actionStyle | `Object \\| string` | The style of the action area. | 2.38.2 |\n| bordered | `boolean` | Whether to show `border`. |  |\n| class | `any` | Class name of the dialog. | 2.33.0 |\n| closable | `boolean` | Whether to show `close` icon. |  |\n| closeFocusable | `boolean` | Whether the close button is focusable. | 2.43.0 |\n| closeOnEsc | `boolean` | Whether to close dialog on Esc is pressed. | 2.26.4 |\n| content | `string \\| (() => VNodeChild)` | Content, can be a render function. |  |\n| contentClass | `string` | The class name of the content. | 2.38.2 |\n| contentStyle | `Object \\| string` | The style of the content. | 2.38.2 |\n| iconPlacement | `'left' \\| 'top'` | Icon placement. |  |\n| icon | `() => VNodeChild` | `Render` function of `icon`. |  |\n| loading | `boolean` | Whether to display `loading` status. |  |\n| maskClosable | `boolean` | Whether the dialog can be closed by clicking the `mask`. |  |\n| negativeButtonProps | `ButtonProps` | Cancel button's DOM props | 2.27.0 |\n| negativeText | `string` | Corresponding button won't show if not set. |  |\n| positiveButtonProps | `ButtonProps` | Confirm button's DOM props | 2.27.0 |\n| positiveText | `string` | Corresponding button won't show if not set. |  |\n| show-icon | `boolean` | Whether to show `icon`. |  |\n| style | `string \\| Object` | Style of the dialog. |  |\n| title | `string \\| (() => VNodeChild)` | Can be a render function. |  |\n| titleClass | `string` | The class name of the content. | 2.38.2 |\n| titleStyle | `Object \\| string` | The style of the content. | 2.38.2 |\n| transformOrigin | `'mouse' \\| 'center'` | The transform origin of the dialog's display animation. | 2.34.0 |\n| type | `'error \\| 'success' \\| 'warning'` | Dialog type. |  |\n| onAfterEnter | `() => void \\| undefined` | Callback on enter animation ends. | 2.33.0 |\n| onAfterLeave | `() => void \\| undefined` | Callback on leave animation ends. | 2.33.3 |\n| onClose | `() => boolean \\| Promise<boolean> \\| any` | The default behavior is closing the confirm. Return `false` or `resolve false` or `Promise rejected` will prevent the default behavior. |  |\n| onEsc | `() => void` | Callback fired when the escape key is pressed and focus is within dialog. | 2.32.0 |\n| onNegativeClick | `(e: MouseEvent) => boolean \\| Promise<boolean> \\| any` | The default behavior is closing the confirm. Return `false` or `resolve false` or `Promise rejected` will prevent the default behavior. |  |\n| onPositiveClick | `(e: MouseEvent) => boolean \\| Promise<boolean> \\| any` | The default behavior is closing the confirm. Return `false` or `resolve false` or `Promise rejected` will prevent the default behavior. |  |\n\n#### DialogReactive Methods\n\n| Name    | Type | Description     |\n| ------- | ---- | --------------- |\n| destroy | `()` | Close `dialog`. |\n\n### Dialog Props\n\n| Name | Type | Default | Description | Version |\n| --- | --- | --- | --- | --- |\n| action-class | `string` | `undefined` | The class name of the action area. | 2.38.2 |\n| action-style | `Object \\| string` | `undefined` | The style of the action area. | 2.38.2 |\n| bordered | `boolean` | `false` | Whether to show `border`. |  |\n| closable | `boolean` | `true` | Whether to show `close` icon. |  |\n| close-focusable | `boolean` | `false` | Whether the close button is focusable. | 2.43.0 |\n| content | `string \\| (() => VNodeChild)` | `undefined` | Can be a render function. |  |\n| content-class | `string` | `undefined` | The class name of the content. | 2.38.2 |\n| content-style | `Object \\| string` | `undefined` | The style of the content. | 2.38.2 |\n| icon-placement | `'left' \\| 'top'` | `'left'` | Icon placement. |  |\n| icon | `() => VNodeChild` | `undefined` | `Render` function of icon. |  |\n| loading | `boolean` | `false` | Whether to display `loading` status. |  |\n| negative-button-props | `ButtonProps` | `undefined` | Cancel button's DOM props | 2.27.0 |\n| negative-text | `string` | `undefined` | Corresponding button won't show if not set. |  |\n| positive-button-props | `ButtonProps` | `undefined` | Confirm button's DOM props | 2.27.0 |\n| positive-text | `string` | `undefined` | Corresponding button won't show if not set. |  |\n| show-icon | `boolean` | `true` | Whether to display the `icon`. |  |\n| title | `string \\| (() => VNodeChild)` | `undefined` | Title, can be a render function. |  |\n| title-class | `string` | `undefined` | The class name of the content. | 2.38.2 |\n| title-style | `Object \\| string` | `undefined` | The style of the content. | 2.38.2 |\n| type | `'error \\| 'success' \\| 'warning' \\| 'info'` | `'warning'` | Dialog type. |  |\n| on-close | `() => void` | `undefined` | Calback on close button clicked. |  |\n| on-negative-click | `(e: MouseEvent) => void` | `undefined` | Callback on positive button clicked. |  |\n| on-positive-click | `(e: MouseEvent) => void` | `undefined` | Callback on negative button clicked. |  |\n\n### Dialog Slots\n\n| Name    | Parameters | Description       | Version |\n| ------- | ---------- | ----------------- | ------- |\n| action  | `()`       | `Action` content. |         |\n| default | `()`       | Dialog content.   |         |\n| header  | `()`       | `Header` content. |         |\n| icon    | `()`       | `Icon` content.   |         |\n| close   | `()`       | `Close` content.  | 2.36.0  |\n"
  },
  {
    "path": "src/dialog/demos/enUS/mask.demo.vue",
    "content": "<markdown>\n# Click on mask\n\nI think user is smart enough that they know if nothing happens after mask is clicked, they should click at confirm or cancel button.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { useDialog, useMessage } from 'naive-ui'\n\nconst message = useMessage()\nconst dialog = useDialog()\n\nfunction handleButtonClick() {\n  dialog.success({\n    title: 'Close',\n    content: 'Are you sure?',\n    positiveText: 'Sure',\n    negativeText: 'Not Sure',\n    maskClosable: false,\n    onMaskClick: () => {\n      message.success('cannot close')\n    },\n    onEsc: () => {\n      message.success('close by esc')\n    }\n  })\n}\n</script>\n\n<template>\n  <n-button @click=\"handleButtonClick\">\n    Callback on Mask Clicked\n  </n-button>\n</template>\n"
  },
  {
    "path": "src/dialog/demos/enUS/use-component.demo.vue",
    "content": "<markdown>\n# Use as a component\n\nSometimes you may want to use a component.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { useMessage } from 'naive-ui'\n\nconst message = useMessage()\n\nfunction handleNegativeClick() {\n  message.warning('Cancel')\n}\n\nfunction handlePositiveClick() {\n  message.success('Confirm')\n}\n</script>\n\n<template>\n  <n-dialog\n    title=\"Dialog\"\n    content=\"Are you sure?\"\n    negative-text=\"Cancel\"\n    positive-text=\"Submit\"\n    @positive-click=\"handlePositiveClick\"\n    @negative-click=\"handleNegativeClick\"\n  />\n</template>\n"
  },
  {
    "path": "src/dialog/demos/enUS/use-dialog-reactive-list.demo.vue",
    "content": "<markdown>\n# Access all dialog instances\n\nYou can use `useDialogReactiveList` to access all dialog reactive inside `n-dialog-provider`.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { useDialogReactiveList } from 'naive-ui'\n\nconst dialogReactiveList = useDialogReactiveList()\n</script>\n\n<template>\n  There is {{ dialogReactiveList.length }} dialog in the current page.\n</template>\n"
  },
  {
    "path": "src/dialog/demos/zhCN/action.demo.vue",
    "content": "<markdown>\n# 自定义 Action\n\n有的时候你想自定义 `action` 和 `content`。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { useDialog } from 'naive-ui'\n\nconst dialog = useDialog()\n\nfunction handleButtonClick() {\n  dialog.warning({\n    title: '使用渲染函数',\n    content: () => 'Content',\n    action: () => 'Action'\n  })\n}\n</script>\n\n<template>\n  <n-space>\n    <n-button @click=\"handleButtonClick\">\n      使用渲染函数\n    </n-button>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/dialog/demos/zhCN/async.demo.vue",
    "content": "<markdown>\n# 异步\n\n对话框可以异步。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { useDialog } from 'naive-ui'\n\nconst sleep = () => new Promise(resolve => setTimeout(resolve, 1000))\nconst countDown = (second: number) => `倒计时 ${second} 秒`\n\nconst dialog = useDialog()\n\nfunction handleClick() {\n  const d = dialog.success({\n    title: '异步',\n    content: '点击，倒计时 3 秒',\n    positiveText: '确认',\n    onPositiveClick: () => {\n      d.loading = true\n      return new Promise((resolve) => {\n        sleep()\n          .then(() => {\n            d.content = countDown(2)\n            return sleep()\n          })\n          .then(() => {\n            d.content = countDown(1)\n            return sleep()\n          })\n          .then(() => {\n            d.content = countDown(0)\n          })\n          .then(resolve)\n      })\n    }\n  })\n}\n</script>\n\n<template>\n  <n-button @click=\"handleClick\">\n    成功\n  </n-button>\n</template>\n"
  },
  {
    "path": "src/dialog/demos/zhCN/basic.demo.vue",
    "content": "<markdown>\n# 基础用法\n\n注入 `dialog` 来创建一个弹框。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { useDialog, useMessage } from 'naive-ui'\n\nconst message = useMessage()\nconst dialog = useDialog()\n\nfunction handleConfirm() {\n  dialog.warning({\n    title: '警告',\n    content: '你确定？',\n    positiveText: '确定',\n    negativeText: '不确定',\n    draggable: true,\n    onPositiveClick: () => {\n      message.success('确定')\n    },\n    onNegativeClick: () => {\n      message.error('不确定')\n    }\n  })\n}\n\nfunction handleSuccess() {\n  dialog.success({\n    title: '成功',\n    content: '厉害',\n    positiveText: '哇',\n    onPositiveClick: () => {\n      message.success('耶！')\n    }\n  })\n}\n\nfunction handleError() {\n  dialog.error({\n    title: '错误',\n    content: '错了',\n    positiveText: '啊',\n    onPositiveClick: () => {\n      message.success('我就知道')\n    }\n  })\n}\n</script>\n\n<template>\n  <n-space>\n    <n-button @click=\"handleConfirm\">\n      警告\n    </n-button>\n    <n-button @click=\"handleSuccess\">\n      成功\n    </n-button>\n    <n-button @click=\"handleError\">\n      错误\n    </n-button>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/dialog/demos/zhCN/focus-debug.demo.vue",
    "content": "<markdown>\n# Focus debug\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { NTimePicker, useDialog } from 'naive-ui'\nimport { h } from 'vue'\n\nconst dialog = useDialog()\n\nfunction handleClick() {\n  dialog.info({\n    title: 'test',\n    content: () => h('div', [h(NTimePicker), h(NTimePicker)])\n  })\n}\n</script>\n\n<template>\n  <n-button @click=\"handleClick\">\n    Click me\n  </n-button>\n</template>\n"
  },
  {
    "path": "src/dialog/demos/zhCN/index.demo-entry.md",
    "content": "# 对话框 Dialog\n\n执行之前，请确认。\n\n<n-alert title=\"使用前提\" type=\"warning\" :bordered=\"false\">\n  如果你想使用对话框，你需要把调用其方法的组件放在 <n-text code>n-dialog-provider</n-text> 内部并且使用 <n-text code>useDialog</n-text> 去获取 API。\n</n-alert>\n\n例如：\n\n```html\n<!-- App.vue -->\n<n-dialog-provider>\n  <content />\n</n-dialog-provider>\n```\n\n```js\nimport { useDialog } from 'naive-ui'\nimport { defineComponent } from 'vue'\n\n// content\nexport default defineComponent({\n  setup() {\n    const dialog = useDialog()\n    return {\n      warning() {\n        dialog.warning(options)\n      }\n    }\n  }\n})\n```\n\n## 演示\n\n```demo\nbasic.vue\nasync.vue\nuse-component.vue\nmask.vue\naction.vue\nuse-dialog-reactive-list.vue\nfocus-debug.vue\nrtl-debug.vue\n```\n\n## API\n\n### useDialog API\n\n| 名称 | 类型 | 说明 |\n| --- | --- | --- |\n| destroyAll | `() => void` | 销毁所有弹出的对话框 |\n| create | `(options: DialogOptions) => DialogReactive` | 创建对话框 |\n| error | `(options: DialogOptions) => DialogReactive` | 调用 `error` 类型的对话框 |\n| info | `(options: DialogOptions) => DialogReactive` | 调用 `info` 类型的对话框 |\n| success | `(options: DialogOptions) => DialogReactive` | 调用 `success` 类型的对话框 |\n| warning | `(options: DialogOptions) => DialogReactive` | 调用 `warning` 类型的对话框 |\n\n### useDialogReactiveList API\n\n`() => Ref<readonly DialogReactive[]>`\n\n### DialogOptions Properties\n\n| 名称 | 类型 | 默认值 | 说明 | 版本 |\n| --- | --- | --- | --- | --- |\n| action | `() => VNodeChild` | `undefined` | 操作区域的内容，需要是渲染函数 |  |\n| actionClass | `string` | `undefined` | 操作区域的类名 | 2.38.2 |\n| actionStyle | `Object \\| string` | `undefined` | 操作区域的样式 | 2.38.2 |\n| autoFocus | `boolean` | `true` | 是否自动聚焦 Modal 第一个可聚焦的元素 | 2.28.3 |\n| blockScroll | `boolean` | `true` | 是否在打开时禁用 body 滚动 | 2.28.3 |\n| bordered | `boolean` | `false` | 是否显示 `border` |  |\n| class | `any` | `undefined` | 类名 | 2.33.0 |\n| closable | `boolean` | `true` | 是否显示 `close` 图标 |  |\n| closeFocusable | `boolean` | `false` | 关闭按钮是否可以聚焦 | 2.43.0 |\n| closeOnEsc | `boolean` | `true` | 是否在摁下 Esc 键的时候关闭对话框 | 2.26.4 |\n| content | `string \\| (() => VNodeChild)` | `undefined` | 对话框内容，可以是渲染函数 |  |\n| contentClass | `string` | `undefined` | 内容的类名 | 2.38.2 |\n| contentStyle | `Object \\| string` | `undefined` | 内容的样式 | 2.38.2 |\n| draggable | `boolean \\| { bounds?: 'none' }` | `false` | 是否可拖拽 | 2.41.0 |\n| iconPlacement | `'left' \\| 'top'` | `'left'` | 图标的位置 |  |\n| icon | `() => VNodeChild` | `undefined` | 对话框 `icon`, 需要是渲染函数 |  |\n| loading | `boolean` | `false` | 是否显示 `loading` 状态 |  |\n| maskClosable | `boolean` | `true` | 是否可以通过点击 `mask` 关闭对话框 |  |\n| negativeButtonProps | `ButtonProps` | `undefined` | 取消按钮的属性 | 2.27.0 |\n| negativeText | `string` | `undefined` | 取消按钮的文字，不填对应的按钮不会出现 |  |\n| positiveButtonProps | `ButtonProps` | `undefined` | 确认按钮的属性 | 2.27.0 |\n| positiveText | `string` | `undefined` | 确认按钮的文字，不填对应的按钮不会出现 |  |\n| showIcon | `boolean` | `true` | 是否显示 `icon` |  |\n| style | `string \\| Object` | `undefined` | 样式 |  |\n| title | `string \\| (() => VNodeChild)` | `undefined` | 标题，可以是渲染函数 |  |\n| titleClass | `string` | `undefined` | 标题的类名 | 2.38.2 |\n| titleStyle | `Object \\| string` | `undefined` | 标题的样式 | 2.38.2 |\n| transformOrigin | `'mouse' \\| 'center'` | `'mouse'` | 对话框动画出现的位置 | 2.34.0 |\n| type | `'error \\| 'success' \\| 'warning'` | `'warning'` | 对话框类型 |  |\n| zIndex | `number` | `undefined` | Dialog 的 z-index | 2.43.0 |\n| onAfterEnter | `() => void` | `undefined` | 出现动画完成执行的回调 | 2.33.0 |\n| onAfterLeave | `() => void` | `undefined` | 关闭动画完成执行的回调 | 2.33.3 |\n| onClose | `() => boolean \\| Promise<boolean> \\| any` | `undefined` | 默认行为是关闭确认框。返回 `false` 或者 `resolve false` 或者 `Promise` 被 `reject` 会避免默认行为 |  |\n| onNegativeClick | `(e: MouseEvent) => boolean \\| Promise<boolean> \\| any` | `undefined` | 默认行为是关闭确认框。返回 `false` 或者 `resolve false` 或者 `Promise` 被 `reject` 会避免默认行为 |  |\n| onPositiveClick | `(e: MouseEvent) => boolean \\| Promise<boolean> \\| any` | `undefined` | 默认行为是关闭确认框。返回 `false` 或者 `resolve false` 或者 `Promise` 被 `reject` 会避免默认行为 |  |\n| onMaskClick | `() => void` | `undefined` | 点击蒙层后执行的回调 |  |\n\n### DialogReactive API\n\n#### DialogReactive Properties\n\n下列属性都可以被动态修改。\n\n| 名称 | 类型 | 说明 | 版本 |\n| --- | --- | --- | --- |\n| actionClass | `string` | 操作区域的类名 | 2.38.2 |\n| actionStyle | `Object \\| string` | 操作区域的样式 | 2.38.2 |\n| bordered | `boolean` | 是否显示 `border` |  |\n| class | `any` | 类名 | 2.33.0 |\n| closable | `boolean` | 是否显示 `close` 图标 |  |\n| closeFocusable | `boolean` | 关闭按钮是否可以聚焦 | 2.43.0 |\n| closeOnEsc | `boolean` | 是否在摁下 Esc 键的时候关闭对话框 | 2.26.4 |\n| content | `string \\| (() => VNodeChild)` | 对话框内容，可以是渲染函数 |  |\n| contentClass | `string` | 内容的类名 | 2.38.2 |\n| contentStyle | `Object \\| string` | 内容的样式 | 2.38.2 |\n| iconPlacement | `'left' \\| 'top'` | 图标的位置 |  |\n| icon | `() => VNodeChild` | 对话框 `icon`，需要是渲染函数 |  |\n| loading | `boolean` | 是否显示 `loading` 状态 |  |\n| maskClosable | `boolean` | 是否可以通过点击 `mask` 关闭对话框 |  |\n| negativeButtonProps | `ButtonProps` | 取消按钮的属性 | 2.27.0 |\n| negativeText | `string` | 取消按钮的文字，不填对应的按钮不会出现 |  |\n| positiveButtonProps | `ButtonProps` | 确认按钮的属性 | 2.27.0 |\n| positiveText | `string` | 确认按钮的文字，不填对应的按钮不会出现 |  |\n| showIcon | `boolean` | 是否显示 `icon` |  |\n| style | `string \\| Object` | 样式 |  |\n| title | `string \\| (() => VNodeChild)` | 可以是渲染函数 |  |\n| titleClass | `string` | 标题的类名 | 2.38.2 |\n| titleStyle | `Object \\| string` | 标题的样式 | 2.38.2 |\n| transformOrigin | `'mouse' \\| 'center'` | 对话框动画出现的位置 | 2.34.0 |\n| type | `'error \\| 'success' \\| 'warning'` | 对话框类型 |  |\n| onAfterEnter | `() => void \\| undefined` | 出现动画完成执行的回调 | 2.33.0 |\n| onAfterLeave | `() => void \\| undefined` | 关闭动画完成执行的回调 | 2.33.3 |\n| onClose | `() => boolean \\| Promise<boolean> \\| any` | 默认行为是关闭确认框。返回 `false` 或者 resolve `false` 或者 `Promise` 被 `reject` 会避免默认行为 |  |\n| onEsc | `() => void` | 焦点在 dialog 内部时按下 Esc 键的回调 | 2.32.0 |\n| onNegativeClick | `(e: MouseEvent) => boolean \\| Promise<boolean> \\| any` | 默认行为是关闭确认框。返回 `false` 或者 resolve `false` 或者 `Promise` 被 `reject` 会避免默认行为 |  |\n| onPositiveClick | `(e: MouseEvent) => boolean \\| Promise<boolean> \\| any` | 默认行为是关闭确认框。返回 `false` 或者 resolve `false` 或者 `Promise` 被 `reject` 会避免默认行为 |  |\n\n#### DialogReactive Methods\n\n| 名称    | 类型 | 说明          |\n| ------- | ---- | ------------- |\n| destroy | `()` | 关闭 `Dialog` |\n\n### Dialog Props\n\n| 名称 | 类型 | 默认值 | 说明 | 版本 |\n| --- | --- | --- | --- | --- |\n| action-class | `string` | `undefined` | 操作区域的类名 | 2.38.2 |\n| action-style | `Object \\| string` | `undefined` | 操作区域的样式 | 2.38.2 |\n| bordered | `boolean` | `false` | 是否显示 `border` |  |\n| closable | `boolean` | `true` | 是否显示 `close` 图标 |  |\n| close-focusable | `boolean` | `false` | 关闭按钮是否可以聚焦 | 2.43.0 |\n| content | `string \\| (() => VNodeChild)` | `undefined` | 对话框内容，可以是渲染函数 |  |\n| content-class | `string` | `undefined` | 内容的类名 | 2.38.2 |\n| content-style | `Object \\| string` | `undefined` | 内容的样式 | 2.38.2 |\n| icon-placement | `'left' \\| 'top'` | `'left'` | 图标放置的位置 |  |\n| icon | `() => VNodeChild` | `undefined` | 需要是渲染函数 |  |\n| loading | `boolean` | `false` | 是否显示 `loading` 状态 |  |\n| negative-button-props | `ButtonProps` | `undefined` | 取消按钮的属性 | 2.27.0 |\n| negative-text | `string` | `undefined` | 取消按钮的文字，不填对应的按钮不会出现 |  |\n| positive-button-props | `ButtonProps` | `undefined` | 确认按钮的属性 | 2.27.0 |\n| positive-text | `string` | `undefined` | 确认按钮的文字，不填对应的按钮不会出现 |  |\n| show-icon | `boolean` | `true` | 是否显示 `icon` |  |\n| title | `string \\| (() => VNodeChild)` | `undefined` | 对话框标题，可以是渲染函数 |  |\n| title-class | `string` | `undefined` | 标题的类名 | 2.38.2 |\n| title-style | `Object \\| string` | `undefined` | 标题的样式 | 2.38.2 |\n| type | `'error \\| 'success' \\| 'warning' \\| 'info'` | `'warning'` | 对话框类型 |  |\n| on-close | `() => void` | `undefined` | 点击关闭时执行的回调函数 |  |\n| on-negative-click | `(e: MouseEvent) => void` | `undefined` | 执行 `negative` 时执行的回调函数 |  |\n| on-positive-click | `(e: MouseEvent) => void` | `undefined` | 执行 `positive` 时执行的回调函数 |  |\n\n### Dialog Slots\n\n| 名称    | 参数 | 说明          | 版本   |\n| ------- | ---- | ------------- | ------ |\n| action  | `()` | `action` 内容 |        |\n| default | `()` | 对话框内容    |        |\n| header  | `()` | `header` 内容 |        |\n| icon    | `()` | `icon` 内容   |        |\n| close   | `()` | `close` 内容  | 2.36.0 |\n"
  },
  {
    "path": "src/dialog/demos/zhCN/mask.demo.vue",
    "content": "<markdown>\n# 点击遮罩\n\n我觉得用户应该聪明到点遮罩没用的时候就去点确认了。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { useDialog, useMessage } from 'naive-ui'\n\nconst message = useMessage()\nconst dialog = useDialog()\n\nfunction handleButtonClick() {\n  dialog.success({\n    title: '关闭',\n    content: '你确定？',\n    positiveText: '确定',\n    negativeText: '不确定',\n    maskClosable: false,\n    onMaskClick: () => {\n      message.success('不能关闭')\n    },\n    onEsc: () => {\n      message.success('通过 esc 关闭')\n    }\n  })\n}\n</script>\n\n<template>\n  <n-button @click=\"handleButtonClick\">\n    点击遮罩的事件\n  </n-button>\n</template>\n"
  },
  {
    "path": "src/dialog/demos/zhCN/rtl-debug.demo.vue",
    "content": "<markdown>\n# Rtl Debug\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { NButton, unstableDialogRtl, useDialog, useMessage } from 'naive-ui'\nimport { defineComponent, h, ref } from 'vue'\n\nconst DialogButton = defineComponent({\n  setup() {\n    const message = useMessage()\n    const dialog = useDialog()\n    return {\n      message,\n      dialog\n    }\n  },\n  render() {\n    return h(\n      NButton,\n      {\n        onClick: () => {\n          this.dialog.warning({\n            title: '警告',\n            content: '你确定？',\n            positiveText: '确定',\n            negativeText: '不确定',\n            onPositiveClick: () => {\n              this.message.success('确定')\n            },\n            onNegativeClick: () => {\n              this.message.error('不确定')\n            }\n          })\n        }\n      },\n      { default: () => 'Show some message' }\n    )\n  }\n})\n\nconst rtlEnabled = ref(true)\nconst rtlStyles = [unstableDialogRtl]\n</script>\n\n<template>\n  <n-space><n-switch v-model:value=\"rtlEnabled\" />Rtl</n-space>\n  <n-space>\n    <n-config-provider :rtl=\"rtlEnabled ? rtlStyles : undefined\">\n      <n-dialog-provider>\n        <DialogButton />\n      </n-dialog-provider>\n    </n-config-provider>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/dialog/demos/zhCN/use-component.demo.vue",
    "content": "<markdown>\n# 使用组件\n\n有的时候你可能想把它用作一个组件。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { useMessage } from 'naive-ui'\n\nconst message = useMessage()\n\nfunction handleNegativeClick() {\n  message.warning('取消')\n}\n\nfunction handlePositiveClick() {\n  message.success('确认')\n}\n</script>\n\n<template>\n  <n-dialog\n    title=\"确认\"\n    content=\"你确定\"\n    negative-text=\"不确认\"\n    positive-text=\"确认\"\n    @positive-click=\"handlePositiveClick\"\n    @negative-click=\"handleNegativeClick\"\n  />\n</template>\n"
  },
  {
    "path": "src/dialog/demos/zhCN/use-dialog-reactive-list.demo.vue",
    "content": "<markdown>\n# 访问全部 Dialog 实例\n\n你可以使用 `useDialogReactiveList` 去访问当前 `n-dialog-provider` 下的所有对话框。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { useDialogReactiveList } from 'naive-ui'\n\nconst dialogReactiveList = useDialogReactiveList()\n</script>\n\n<template>\n  目前页面中共有 {{ dialogReactiveList.length }} 个对话框。\n</template>\n"
  },
  {
    "path": "src/dialog/index.ts",
    "content": "export { useDialog, useDialogReactiveList } from './src/composables'\nexport { NDialog } from './src/Dialog'\nexport type { DialogSlots } from './src/Dialog'\nexport { dialogProps } from './src/dialogProps'\nexport type { DialogProps } from './src/dialogProps'\nexport { dialogProviderProps, NDialogProvider } from './src/DialogProvider'\nexport type {\n  DialogApiInjection as DialogApi,\n  DialogOptions,\n  DialogProviderInst,\n  DialogProviderProps,\n  DialogReactive\n} from './src/DialogProvider'\n"
  },
  {
    "path": "src/dialog/src/Dialog.tsx",
    "content": "import type { CSSProperties, SlotsType, VNode } from 'vue'\nimport type { ThemeProps } from '../../_mixins'\nimport type { DialogTheme } from '../styles'\nimport { getMargin } from 'seemly'\nimport { computed, defineComponent, h } from 'vue'\nimport { NBaseClose, NBaseIcon } from '../../_internal'\nimport {\n  ErrorIcon,\n  InfoIcon,\n  SuccessIcon,\n  WarningIcon\n} from '../../_internal/icons'\nimport { useConfig, useRtl, useTheme, useThemeClass } from '../../_mixins'\nimport {\n  createKey,\n  render,\n  resolveSlot,\n  resolveWrappedSlot\n} from '../../_utils'\nimport { NButton } from '../../button'\nimport { dialogLight } from '../styles'\nimport { dialogProps } from './dialogProps'\nimport style from './styles/index.cssr'\n\nconst iconRenderMap = {\n  default: () => <InfoIcon />,\n  info: () => <InfoIcon />,\n  success: () => <SuccessIcon />,\n  warning: () => <WarningIcon />,\n  error: () => <ErrorIcon />\n}\n\nexport interface DialogSlots {\n  action?: () => VNode[]\n  default?: () => VNode[]\n  header?: () => VNode[]\n  icon?: () => VNode[]\n  close?: () => VNode[]\n}\n\nexport const NDialog = defineComponent({\n  name: 'Dialog',\n  alias: [\n    'NimbusConfirmCard', // deprecated\n    'Confirm' // deprecated\n  ],\n  props: {\n    ...(useTheme.props as ThemeProps<DialogTheme>),\n    ...dialogProps\n  },\n  slots: Object as SlotsType<DialogSlots>,\n  setup(props) {\n    const {\n      mergedComponentPropsRef,\n      mergedClsPrefixRef,\n      inlineThemeDisabled,\n      mergedRtlRef\n    } = useConfig(props)\n    const rtlEnabledRef = useRtl('Dialog', mergedRtlRef, mergedClsPrefixRef)\n    const mergedIconPlacementRef = computed(() => {\n      const { iconPlacement } = props\n      return (\n        iconPlacement\n        || mergedComponentPropsRef?.value?.Dialog?.iconPlacement\n        || 'left'\n      )\n    })\n    function handlePositiveClick(e: MouseEvent): void {\n      const { onPositiveClick } = props\n      if (onPositiveClick)\n        onPositiveClick(e)\n    }\n    function handleNegativeClick(e: MouseEvent): void {\n      const { onNegativeClick } = props\n      if (onNegativeClick)\n        onNegativeClick(e)\n    }\n    function handleCloseClick(): void {\n      const { onClose } = props\n      if (onClose)\n        onClose()\n    }\n    const themeRef = useTheme(\n      'Dialog',\n      '-dialog',\n      style,\n      dialogLight,\n      props,\n      mergedClsPrefixRef\n    )\n    const cssVarsRef = computed(() => {\n      const { type } = props\n      const iconPlacement = mergedIconPlacementRef.value\n      const {\n        common: { cubicBezierEaseInOut },\n        self: {\n          fontSize,\n          lineHeight,\n          border,\n          titleTextColor,\n          textColor,\n          color,\n          closeBorderRadius,\n          closeColorHover,\n          closeColorPressed,\n          closeIconColor,\n          closeIconColorHover,\n          closeIconColorPressed,\n          closeIconSize,\n          borderRadius,\n          titleFontWeight,\n          titleFontSize,\n          padding,\n          iconSize,\n          actionSpace,\n          contentMargin,\n          closeSize,\n          [iconPlacement === 'top' ? 'iconMarginIconTop' : 'iconMargin']:\n            iconMargin,\n          [iconPlacement === 'top' ? 'closeMarginIconTop' : 'closeMargin']:\n            closeMargin,\n          [createKey('iconColor', type)]: iconColor\n        }\n      } = themeRef.value\n      const iconMarginDiscrete = getMargin(iconMargin)\n      return {\n        '--n-font-size': fontSize,\n        '--n-icon-color': iconColor,\n        '--n-bezier': cubicBezierEaseInOut,\n        '--n-close-margin': closeMargin,\n        '--n-icon-margin-top': iconMarginDiscrete.top,\n        '--n-icon-margin-right': iconMarginDiscrete.right,\n        '--n-icon-margin-bottom': iconMarginDiscrete.bottom,\n        '--n-icon-margin-left': iconMarginDiscrete.left,\n        '--n-icon-size': iconSize,\n        '--n-close-size': closeSize,\n        '--n-close-icon-size': closeIconSize,\n        '--n-close-border-radius': closeBorderRadius,\n        '--n-close-color-hover': closeColorHover,\n        '--n-close-color-pressed': closeColorPressed,\n        '--n-close-icon-color': closeIconColor,\n        '--n-close-icon-color-hover': closeIconColorHover,\n        '--n-close-icon-color-pressed': closeIconColorPressed,\n        '--n-color': color,\n        '--n-text-color': textColor,\n        '--n-border-radius': borderRadius,\n        '--n-padding': padding,\n        '--n-line-height': lineHeight,\n        '--n-border': border,\n        '--n-content-margin': contentMargin,\n        '--n-title-font-size': titleFontSize,\n        '--n-title-font-weight': titleFontWeight,\n        '--n-title-text-color': titleTextColor,\n        '--n-action-space': actionSpace\n      }\n    })\n    const themeClassHandle = inlineThemeDisabled\n      ? useThemeClass(\n          'dialog',\n          computed(() => `${props.type[0]}${mergedIconPlacementRef.value[0]}`),\n          cssVarsRef,\n          props\n        )\n      : undefined\n    return {\n      mergedClsPrefix: mergedClsPrefixRef,\n      rtlEnabled: rtlEnabledRef,\n      mergedIconPlacement: mergedIconPlacementRef,\n      mergedTheme: themeRef,\n      handlePositiveClick,\n      handleNegativeClick,\n      handleCloseClick,\n      cssVars: inlineThemeDisabled ? undefined : cssVarsRef,\n      themeClass: themeClassHandle?.themeClass,\n      onRender: themeClassHandle?.onRender\n    }\n  },\n  render() {\n    const {\n      bordered,\n      mergedIconPlacement,\n      cssVars,\n      closable,\n      showIcon,\n      title,\n      content,\n      action,\n      negativeText,\n      positiveText,\n      positiveButtonProps,\n      negativeButtonProps,\n      handlePositiveClick,\n      handleNegativeClick,\n      mergedTheme,\n      loading,\n      type,\n      mergedClsPrefix\n    } = this\n\n    this.onRender?.()\n\n    const icon = showIcon ? (\n      <NBaseIcon\n        clsPrefix={mergedClsPrefix}\n        class={`${mergedClsPrefix}-dialog__icon`}\n      >\n        {{\n          default: () =>\n            resolveWrappedSlot(\n              this.$slots.icon,\n              children =>\n                children\n                || (this.icon ? render(this.icon) : iconRenderMap[this.type]())\n            )\n        }}\n      </NBaseIcon>\n    ) : null\n\n    const actionNode = resolveWrappedSlot(this.$slots.action, children =>\n      children || positiveText || negativeText || action ? (\n        <div\n          class={[`${mergedClsPrefix}-dialog__action`, this.actionClass]}\n          style={this.actionStyle}\n        >\n          {children\n            || (action\n              ? [render(action)]\n              : [\n                  this.negativeText && (\n                    <NButton\n                      theme={mergedTheme.peers.Button}\n                      themeOverrides={mergedTheme.peerOverrides.Button}\n                      ghost\n                      size=\"small\"\n                      onClick={handleNegativeClick}\n                      {...negativeButtonProps}\n                    >\n                      {{\n                        default: () => render(this.negativeText)\n                      }}\n                    </NButton>\n                  ),\n                  this.positiveText && (\n                    <NButton\n                      theme={mergedTheme.peers.Button}\n                      themeOverrides={mergedTheme.peerOverrides.Button}\n                      size=\"small\"\n                      type={type === 'default' ? 'primary' : type}\n                      disabled={loading}\n                      loading={loading}\n                      onClick={handlePositiveClick}\n                      {...positiveButtonProps}\n                    >\n                      {{\n                        default: () => render(this.positiveText)\n                      }}\n                    </NButton>\n                  )\n                ])}\n        </div>\n      ) : null)\n\n    return (\n      <div\n        class={[\n          `${mergedClsPrefix}-dialog`,\n          this.themeClass,\n          this.closable && `${mergedClsPrefix}-dialog--closable`,\n          `${mergedClsPrefix}-dialog--icon-${mergedIconPlacement}`,\n          bordered && `${mergedClsPrefix}-dialog--bordered`,\n          this.rtlEnabled && `${mergedClsPrefix}-dialog--rtl`\n        ]}\n        style={cssVars as CSSProperties}\n        role=\"dialog\"\n      >\n        {closable\n          ? resolveWrappedSlot(this.$slots.close, (node) => {\n              const classNames = [\n                `${mergedClsPrefix}-dialog__close`,\n                this.rtlEnabled && `${mergedClsPrefix}-dialog--rtl`\n              ]\n              return node ? (\n                <div class={classNames}>{node}</div>\n              ) : (\n                <NBaseClose\n                  focusable={this.closeFocusable}\n                  clsPrefix={mergedClsPrefix}\n                  class={classNames}\n                  onClick={this.handleCloseClick}\n                />\n              )\n            })\n          : null}\n        {showIcon && mergedIconPlacement === 'top' ? (\n          <div class={`${mergedClsPrefix}-dialog-icon-container`}>{icon}</div>\n        ) : null}\n        <div\n          class={[`${mergedClsPrefix}-dialog__title`, this.titleClass]}\n          style={this.titleStyle}\n        >\n          {showIcon && mergedIconPlacement === 'left' ? icon : null}\n          {resolveSlot(this.$slots.header, () => [render(title)])}\n        </div>\n        <div\n          class={[\n            `${mergedClsPrefix}-dialog__content`,\n            actionNode ? '' : `${mergedClsPrefix}-dialog__content--last`,\n            this.contentClass\n          ]}\n          style={this.contentStyle}\n        >\n          {resolveSlot(this.$slots.default, () => [render(content)])}\n        </div>\n        {actionNode}\n      </div>\n    )\n  }\n})\n"
  },
  {
    "path": "src/dialog/src/DialogEnvironment.tsx",
    "content": "import type { CSSProperties, PropType } from 'vue'\nimport type { ModalDraggableOptions } from '../../modal/src/interface'\n// use absolute path to make sure no circular ref of style\n// this -> modal-index -> modal-style\nimport { defineComponent, h, normalizeClass, ref } from 'vue'\nimport { keep } from '../../_utils'\nimport NModal from '../../modal/src/Modal'\nimport { NDialog } from './Dialog'\nimport { dialogPropKeys, dialogProps } from './dialogProps'\n\nexport const exposedDialogEnvProps = {\n  ...dialogProps,\n  onAfterEnter: Function as PropType<() => void>,\n  onAfterLeave: Function as PropType<() => void>,\n  transformOrigin: String as PropType<'center' | 'mouse'>,\n  blockScroll: { type: Boolean, default: true },\n  closeOnEsc: { type: Boolean, default: true },\n  onEsc: Function as PropType<() => void>,\n  autoFocus: {\n    type: Boolean,\n    default: true\n  },\n  internalStyle: [String, Object] as PropType<string | CSSProperties>,\n  maskClosable: {\n    type: Boolean,\n    default: true\n  },\n  zIndex: Number,\n  onPositiveClick: Function as PropType<\n    (e: MouseEvent) => Promise<unknown> | unknown\n  >,\n  onNegativeClick: Function as PropType<\n    (e: MouseEvent) => Promise<unknown> | unknown\n  >,\n  onClose: Function as PropType<() => Promise<unknown> | unknown>,\n  onMaskClick: Function as PropType<(e: MouseEvent) => void>,\n  draggable: [Boolean, Object] as PropType<boolean | ModalDraggableOptions>\n} as const\n\nexport const NDialogEnvironment = defineComponent({\n  name: 'DialogEnvironment',\n  props: {\n    ...exposedDialogEnvProps,\n    internalKey: {\n      type: String,\n      required: true\n    },\n    to: [String, Object] as PropType<string | HTMLElement>,\n    // private\n    onInternalAfterLeave: {\n      type: Function as PropType<(key: string) => void>,\n      required: true\n    }\n  },\n  setup(props) {\n    const showRef = ref(true)\n    function handleAfterLeave(): void {\n      const { onInternalAfterLeave, internalKey, onAfterLeave } = props\n      if (onInternalAfterLeave)\n        onInternalAfterLeave(internalKey)\n      if (onAfterLeave)\n        onAfterLeave()\n    }\n    function handlePositiveClick(e: MouseEvent): void {\n      const { onPositiveClick } = props\n      if (onPositiveClick) {\n        void Promise.resolve(onPositiveClick(e)).then((result) => {\n          if (result === false)\n            return\n          hide()\n        })\n      }\n      else {\n        hide()\n      }\n    }\n    function handleNegativeClick(e: MouseEvent): void {\n      const { onNegativeClick } = props\n      if (onNegativeClick) {\n        void Promise.resolve(onNegativeClick(e)).then((result) => {\n          if (result === false)\n            return\n          hide()\n        })\n      }\n      else {\n        hide()\n      }\n    }\n    function handleCloseClick(): void {\n      const { onClose } = props\n      if (onClose) {\n        void Promise.resolve(onClose()).then((result) => {\n          if (result === false)\n            return\n          hide()\n        })\n      }\n      else {\n        hide()\n      }\n    }\n    function handleMaskClick(e: MouseEvent): void {\n      const { onMaskClick, maskClosable } = props\n      if (onMaskClick) {\n        onMaskClick(e)\n        if (maskClosable) {\n          hide()\n        }\n      }\n    }\n    function handleEsc(): void {\n      const { onEsc } = props\n      if (onEsc) {\n        onEsc()\n      }\n    }\n    function hide(): void {\n      showRef.value = false\n    }\n    function handleUpdateShow(value: boolean): void {\n      showRef.value = value\n    }\n    return {\n      show: showRef,\n      hide,\n      handleUpdateShow,\n      handleAfterLeave,\n      handleCloseClick,\n      handleNegativeClick,\n      handlePositiveClick,\n      handleMaskClick,\n      handleEsc\n    }\n  },\n  render() {\n    const {\n      handlePositiveClick,\n      handleUpdateShow,\n      handleNegativeClick,\n      handleCloseClick,\n      handleAfterLeave,\n      handleMaskClick,\n      handleEsc,\n      to,\n      zIndex,\n      maskClosable,\n      show\n    } = this\n    return (\n      <NModal\n        show={show}\n        onUpdateShow={handleUpdateShow}\n        onMaskClick={handleMaskClick}\n        onEsc={handleEsc}\n        to={to}\n        zIndex={zIndex}\n        maskClosable={maskClosable}\n        onAfterEnter={this.onAfterEnter}\n        onAfterLeave={handleAfterLeave}\n        closeOnEsc={this.closeOnEsc}\n        blockScroll={this.blockScroll}\n        autoFocus={this.autoFocus}\n        transformOrigin={this.transformOrigin}\n        draggable={this.draggable}\n        internalAppear\n        internalDialog\n      >\n        {{\n          default: ({ draggableClass }: { draggableClass: string }) => (\n            <NDialog\n              {...keep(this.$props, dialogPropKeys)}\n              titleClass={normalizeClass([this.titleClass, draggableClass])}\n              style={this.internalStyle}\n              onClose={handleCloseClick}\n              onNegativeClick={handleNegativeClick}\n              onPositiveClick={handlePositiveClick}\n            />\n          )\n        }}\n      </NModal>\n    )\n  }\n})\n"
  },
  {
    "path": "src/dialog/src/DialogProvider.ts",
    "content": "import type { CSSProperties, ExtractPropTypes, PropType, Ref } from 'vue'\nimport type { ExtractPublicPropTypes, Mutable } from '../../_utils'\nimport type { exposedDialogEnvProps } from './DialogEnvironment'\nimport { createId } from 'seemly'\nimport { useClicked, useClickPosition } from 'vooks'\nimport { defineComponent, Fragment, h, provide, reactive, ref } from 'vue'\nimport { omit } from '../../_utils'\nimport {\n  dialogApiInjectionKey,\n  dialogProviderInjectionKey,\n  dialogReactiveListInjectionKey\n} from './context'\nimport { NDialogEnvironment } from './DialogEnvironment'\n\nexport type DialogOptions = Mutable<\n  Omit<\n    Partial<ExtractPropTypes<typeof exposedDialogEnvProps>>,\n    'internalStyle'\n  > & {\n    class?: any\n    style?: string | CSSProperties\n  }\n>\n\nexport type DialogReactive = {\n  readonly key: string\n  readonly destroy: () => void\n} & DialogOptions\n\n// FIXME\n// If style is used as CSSProperties, typescript 4.4.2 will throw tons of errors\n// Fxxx\ntype TypeSafeDialogReactive = DialogReactive & {\n  class?: any\n  style?: any\n}\n\nexport interface DialogApiInjection {\n  destroyAll: () => void\n  create: (options: DialogOptions) => DialogReactive\n  success: (options: DialogOptions) => DialogReactive\n  warning: (options: DialogOptions) => DialogReactive\n  error: (options: DialogOptions) => DialogReactive\n  info: (options: DialogOptions) => DialogReactive\n}\n\nexport interface DialogProviderInjection {\n  clickedRef: Ref<boolean>\n  clickedPositionRef: Ref<{ x: number, y: number } | null>\n}\n\nexport type DialogReactiveListInjection = Ref<DialogReactive[]>\n\ninterface DialogInst {\n  hide: () => void\n}\n\nexport type DialogProviderInst = DialogApiInjection\n\nexport const dialogProviderProps = {\n  injectionKey: String,\n  to: [String, Object] as PropType<string | HTMLElement>\n}\n\nexport type DialogProviderProps = ExtractPublicPropTypes<\n  typeof dialogProviderProps\n>\n\nexport const NDialogProvider = defineComponent({\n  name: 'DialogProvider',\n  props: dialogProviderProps,\n  setup() {\n    const dialogListRef = ref<TypeSafeDialogReactive[]>([])\n    const dialogInstRefs: Record<string, DialogInst | undefined> = {}\n    function create(options: DialogOptions = {}): DialogReactive {\n      const key = createId()\n      const dialogReactive = reactive({\n        ...options,\n        key,\n        destroy: () => {\n          dialogInstRefs[`n-dialog-${key}`]?.hide()\n        }\n      })\n      dialogListRef.value.push(dialogReactive)\n      return dialogReactive\n    }\n    const typedApi = (\n      ['info', 'success', 'warning', 'error'] as Array<\n        'info' | 'success' | 'warning' | 'error'\n      >\n    ).map(type => (options: DialogOptions): DialogReactive => {\n      return create({ ...options, type })\n    })\n\n    function handleAfterLeave(key: string): void {\n      const { value: dialogList } = dialogListRef\n      dialogList.splice(\n        dialogList.findIndex(dialog => dialog.key === key),\n        1\n      )\n    }\n\n    function destroyAll(): void {\n      Object.values(dialogInstRefs).forEach((dialogInstRef) => {\n        dialogInstRef?.hide()\n      })\n    }\n\n    const api = {\n      create,\n      destroyAll,\n      info: typedApi[0],\n      success: typedApi[1],\n      warning: typedApi[2],\n      error: typedApi[3]\n    }\n    provide(dialogApiInjectionKey, api)\n    provide(dialogProviderInjectionKey, {\n      clickedRef: useClicked(64),\n      clickedPositionRef: useClickPosition()\n    })\n    provide(dialogReactiveListInjectionKey, dialogListRef)\n    return {\n      ...api,\n      dialogList: dialogListRef,\n      dialogInstRefs,\n      handleAfterLeave\n    }\n  },\n  render() {\n    return h(Fragment, null, [\n      this.dialogList.map(dialog =>\n        h(\n          NDialogEnvironment,\n          omit(dialog, ['destroy', 'style'], {\n            internalStyle: dialog.style,\n            to: this.to,\n            ref: ((inst: DialogInst | null) => {\n              if (inst === null) {\n                delete this.dialogInstRefs[`n-dialog-${dialog.key}`]\n              }\n              else {\n                this.dialogInstRefs[`n-dialog-${dialog.key}`] = inst\n              }\n            }) as any,\n            internalKey: dialog.key,\n            onInternalAfterLeave: this.handleAfterLeave\n          })\n        )\n      ),\n      this.$slots.default?.()\n    ])\n  }\n})\n"
  },
  {
    "path": "src/dialog/src/composables.ts",
    "content": "import type { Ref } from 'vue'\nimport type { DialogApiInjection, DialogReactive } from './DialogProvider'\nimport { inject } from 'vue'\nimport { throwError } from '../../_utils'\nimport {\n  dialogApiInjectionKey,\n  dialogReactiveListInjectionKey\n} from './context'\n\nexport function useDialog(): DialogApiInjection {\n  const dialog = inject(dialogApiInjectionKey, null)\n  if (dialog === null) {\n    throwError('use-dialog', 'No outer <n-dialog-provider /> founded.')\n  }\n  return dialog\n}\n\nexport function useDialogReactiveList(): Ref<readonly DialogReactive[]> {\n  const dialogReactiveList = inject(dialogReactiveListInjectionKey, null)\n  if (dialogReactiveList === null) {\n    throwError(\n      'use-dialog-reactive-list',\n      'No outer <n-dialog-provider /> founded.'\n    )\n  }\n  return dialogReactiveList\n}\n"
  },
  {
    "path": "src/dialog/src/context.ts",
    "content": "import type {\n  DialogApiInjection,\n  DialogProviderInjection,\n  DialogReactiveListInjection\n} from './DialogProvider'\nimport { createInjectionKey } from '../../_utils'\n\nexport const dialogProviderInjectionKey\n  = createInjectionKey<DialogProviderInjection>('n-dialog-provider')\n\nexport const dialogApiInjectionKey\n  = createInjectionKey<DialogApiInjection>('n-dialog-api')\n\nexport const dialogReactiveListInjectionKey\n  = createInjectionKey<DialogReactiveListInjection>('n-dialog-reactive-list')\n"
  },
  {
    "path": "src/dialog/src/dialogProps.ts",
    "content": "import type { CSSProperties, PropType, VNodeChild } from 'vue'\nimport type { ExtractPublicPropTypes } from '../../_utils'\nimport type { ButtonProps } from '../../button'\nimport type { IconPlacement } from './interface'\nimport { keysOf } from '../../_utils'\n\nconst dialogProps = {\n  icon: Function as PropType<() => VNodeChild>,\n  type: {\n    type: String as PropType<\n      'info' | 'success' | 'warning' | 'error' | 'default'\n    >,\n    default: 'default'\n  },\n  title: [String, Function] as PropType<string | (() => VNodeChild)>,\n  closable: {\n    type: Boolean,\n    default: true\n  },\n  negativeText: String,\n  positiveText: String,\n  positiveButtonProps: Object as PropType<ButtonProps>,\n  negativeButtonProps: Object as PropType<ButtonProps>,\n  content: [String, Function] as PropType<string | (() => VNodeChild)>,\n  action: Function as PropType<() => VNodeChild>,\n  showIcon: {\n    type: Boolean,\n    default: true\n  },\n  loading: Boolean,\n  bordered: Boolean,\n  iconPlacement: String as PropType<IconPlacement>,\n  titleClass: [String, Array] as PropType<string | Array<string | undefined>>,\n  titleStyle: [String, Object] as PropType<string | CSSProperties>,\n  contentClass: [String, Array] as PropType<string | Array<string | undefined>>,\n  contentStyle: [String, Object] as PropType<string | CSSProperties>,\n  actionClass: [String, Array] as PropType<string | Array<string | undefined>>,\n  actionStyle: [String, Object] as PropType<string | CSSProperties>,\n  onPositiveClick: Function as PropType<(e: MouseEvent) => void>,\n  onNegativeClick: Function as PropType<(e: MouseEvent) => void>,\n  onClose: Function as PropType<() => void>,\n  closeFocusable: Boolean\n} as const\n\nexport type DialogProps = ExtractPublicPropTypes<typeof dialogProps>\nexport { dialogProps }\nexport const dialogPropKeys = keysOf(dialogProps)\n"
  },
  {
    "path": "src/dialog/src/interface.ts",
    "content": "export type IconPlacement = 'left' | 'top'\n"
  },
  {
    "path": "src/dialog/src/styles/index.cssr.ts",
    "content": "import { asModal, c, cB, cE, cM, insideModal } from '../../../_utils/cssr'\n\n// vars:\n// --n-icon-color\n// --n-bezier\n// --n-icon-margin-top\n// --n-icon-margin-right\n// --n-icon-margin-bottom\n// --n-icon-margin-left\n// --n-icon-size\n// --n-close-border-radius\n// --n-close-margin\n// --n-close-size\n// --n-close-color-hover\n// --n-close-color-pressed\n// --n-close-icon-color\n// --n-close-icon-color-hover\n// --n-close-icon-color-pressed\n// --n-color\n// --n-text-color\n// --n-border-radius\n// --n-padding\n// --n-line-height\n// --n-border\n// --n-content-margin\n// --n-title-font-size\n// --n-title-font-weight\n// --n-title-text-color\n// --n-action-space\nexport default c([\n  cB('dialog', `\n    --n-icon-margin: var(--n-icon-margin-top) var(--n-icon-margin-right) var(--n-icon-margin-bottom) var(--n-icon-margin-left);\n    word-break: break-word;\n    line-height: var(--n-line-height);\n    position: relative;\n    background: var(--n-color);\n    color: var(--n-text-color);\n    box-sizing: border-box;\n    margin: auto;\n    border-radius: var(--n-border-radius);\n    padding: var(--n-padding);\n    transition: \n      border-color .3s var(--n-bezier),\n      background-color .3s var(--n-bezier),\n      color .3s var(--n-bezier);\n  `, [\n    cE('icon', `\n      color: var(--n-icon-color);\n    `),\n    cM('bordered', `\n      border: var(--n-border);\n    `),\n    cM('icon-top', [\n      cE('close', `\n        margin: var(--n-close-margin);\n      `),\n      cE('icon', `\n        margin: var(--n-icon-margin);\n      `),\n      cE('content', `\n        text-align: center;\n      `),\n      cE('title', `\n        justify-content: center;\n      `),\n      cE('action', `\n        justify-content: center;\n      `)\n    ]),\n    cM('icon-left', [\n      cE('icon', `\n        margin: var(--n-icon-margin);\n      `),\n      cM('closable', [\n        cE('title', `\n          padding-right: calc(var(--n-close-size) + 6px);\n        `)\n      ])\n    ]),\n    cE('close', `\n      position: absolute;\n      right: 0;\n      top: 0;\n      margin: var(--n-close-margin);\n      transition:\n        background-color .3s var(--n-bezier),\n        color .3s var(--n-bezier);\n      z-index: 1;\n    `),\n    cE('content', `\n      font-size: var(--n-font-size);\n      margin: var(--n-content-margin);\n      position: relative;\n      word-break: break-word;\n    `, [\n      cM('last', 'margin-bottom: 0;')\n    ]),\n    cE('action', `\n      display: flex;\n      justify-content: flex-end;\n    `, [\n      c('> *:not(:last-child)', `\n        margin-right: var(--n-action-space);\n      `)\n    ]),\n    cE('icon', `\n      font-size: var(--n-icon-size);\n      transition: color .3s var(--n-bezier);\n    `),\n    cE('title', `\n      transition: color .3s var(--n-bezier);\n      display: flex;\n      align-items: center;\n      font-size: var(--n-title-font-size);\n      font-weight: var(--n-title-font-weight);\n      color: var(--n-title-text-color);\n    `),\n    cB('dialog-icon-container', `\n      display: flex;\n      justify-content: center;\n    `)\n  ]),\n  insideModal(\n    cB('dialog', `\n      width: 446px;\n      max-width: calc(100vw - 32px);\n    `)\n  ),\n  cB('dialog', [\n    asModal(`\n      width: 446px;\n      max-width: calc(100vw - 32px);\n    `)\n  ])\n])\n"
  },
  {
    "path": "src/dialog/src/styles/rtl.cssr.ts",
    "content": "import { c, cB, cE, cM } from '../../../_utils/cssr'\n\nexport default cB('dialog', [\n  cM('rtl', `\n    --n-icon-margin: var(--n-icon-margin-top) var(--n-icon-margin-left) var(--n-icon-margin-bottom) var(--n-icon-margin-right);\n    direction: rtl;\n  `, [\n    cE('close', `\n      right: unset;\n      left: 0;\n      margin-left: 1.8rem;\n    `),\n    cE('action', `\n      direction: rtl;\n      display: flex;\n    `, [\n      c('> *:not(:first-child)', `\n        margin-right: var(--n-action-space);\n      `),\n      c('> *', `\n        margin-right: 0;\n      `)\n    ]),\n    cM('icon-left', [\n      cM('closable', [\n        cE('title', `\n          padding-right: unset;\n        `)\n      ])\n    ])\n  ])\n])\n"
  },
  {
    "path": "src/dialog/styles/_common.ts",
    "content": "export default {\n  titleFontSize: '18px',\n  padding: '16px 28px 20px 28px',\n  iconSize: '28px',\n  actionSpace: '12px',\n  contentMargin: '8px 0 16px 0',\n  iconMargin: '0 4px 0 0',\n  iconMarginIconTop: '4px 0 8px 0',\n  closeSize: '22px',\n  closeIconSize: '18px',\n  closeMargin: '20px 26px 0 0',\n  closeMarginIconTop: '10px 16px 0 0'\n}\n"
  },
  {
    "path": "src/dialog/styles/dark.ts",
    "content": "import type { DialogTheme } from './light'\nimport { commonDark } from '../../_styles/common'\nimport { buttonDark } from '../../button/styles'\nimport { self } from './light'\n\nconst dialogDark: DialogTheme = {\n  name: 'Dialog',\n  common: commonDark,\n  peers: {\n    Button: buttonDark\n  },\n  self\n}\n\nexport default dialogDark\n"
  },
  {
    "path": "src/dialog/styles/index.ts",
    "content": "export { default as dialogDark } from './dark'\nexport { default as dialogLight } from './light'\nexport type { DialogTheme, DialogThemeVars } from './light'\nexport { dialogRtl } from './rtl'\n"
  },
  {
    "path": "src/dialog/styles/light.ts",
    "content": "import type { ThemeCommonVars } from '../../_styles/common'\nimport { createTheme } from '../../_mixins'\nimport { commonLight } from '../../_styles/common'\nimport { buttonLight } from '../../button/styles'\nimport commonVars from './_common'\n\nexport function self(vars: ThemeCommonVars) {\n  const {\n    textColor1,\n    textColor2,\n    modalColor,\n    closeIconColor,\n    closeIconColorHover,\n    closeIconColorPressed,\n    closeColorHover,\n    closeColorPressed,\n    infoColor,\n    successColor,\n    warningColor,\n    errorColor,\n    primaryColor,\n    dividerColor,\n    borderRadius,\n    fontWeightStrong,\n    lineHeight,\n    fontSize\n  } = vars\n  return {\n    ...commonVars,\n    fontSize,\n    lineHeight,\n    border: `1px solid ${dividerColor}`,\n    titleTextColor: textColor1,\n    textColor: textColor2,\n    color: modalColor,\n    closeColorHover,\n    closeColorPressed,\n    closeIconColor,\n    closeIconColorHover,\n    closeIconColorPressed,\n    closeBorderRadius: borderRadius,\n    iconColor: primaryColor,\n    iconColorInfo: infoColor,\n    iconColorSuccess: successColor,\n    iconColorWarning: warningColor,\n    iconColorError: errorColor,\n    borderRadius,\n    titleFontWeight: fontWeightStrong\n  }\n}\n\nexport type DialogThemeVars = ReturnType<typeof self>\n\nconst dialogLight = createTheme({\n  name: 'Dialog',\n  common: commonLight,\n  peers: {\n    Button: buttonLight\n  },\n  self\n})\n\nexport default dialogLight\nexport type DialogTheme = typeof dialogLight\n"
  },
  {
    "path": "src/dialog/styles/rtl.ts",
    "content": "import type { RtlItem } from '../../config-provider/src/internal-interface'\nimport rtlStyle from '../src/styles/rtl.cssr'\n\nexport const dialogRtl: RtlItem = {\n  name: 'Dialog',\n  style: rtlStyle\n}\n"
  },
  {
    "path": "src/dialog/tests/Dialog.spec.tsx",
    "content": "import type { DialogProps } from '../index'\nimport { mount } from '@vue/test-utils'\nimport { defineComponent, h, nextTick } from 'vue'\nimport { NDialog, NDialogProvider, useDialog } from '../index'\n\nconst Provider = defineComponent({\n  render() {\n    return <NDialogProvider>{this.$slots}</NDialogProvider>\n  }\n})\n\nfunction createTestComponent(\n  type: 'create' | 'error' | 'info' | 'success' | 'warning',\n  dialogProps?: DialogProps\n): any {\n  return defineComponent({\n    setup() {\n      const dialog = useDialog()\n      dialog[type]({\n        title: 'test dialog type',\n        ...dialogProps\n      })\n    },\n    render() {\n      return null\n    }\n  })\n}\n\ndescribe('n-dialog', () => {\n  it('should work with import on demand', () => {\n    mount(NDialogProvider)\n  })\n\n  it('should have correct type', () => {\n    const Test = defineComponent({\n      setup() {\n        const dialog = useDialog()\n        const dialogReactive = dialog.success({\n          title: 'Test success',\n          content: 'Content'\n        })\n        dialogReactive.style = 'color: red;'\n      },\n      render() {\n        return null\n      }\n    })\n    const dialogProvider = mount(() => (\n      <Provider>{{ default: () => <Test /> }}</Provider>\n    ))\n    dialogProvider.unmount()\n  })\n\n  it('can be a component', () => {\n    const dialog = mount(NDialog, {\n      attachTo: document.body,\n      props: {\n        title: 'Test success',\n        content: 'success'\n      }\n    })\n    expect(document.querySelector('.n-dialog__content')?.textContent).toEqual(\n      'success'\n    )\n    dialog.unmount()\n  })\n\n  it('shouldn\\'t useDialog display button if no text is set', () => {\n    const wrapper = mount(NDialog)\n    expect(wrapper.find('.n-button').exists()).toEqual(false)\n    wrapper.unmount()\n  })\n\n  it('loading', async () => {\n    const Test = defineComponent({\n      setup() {\n        const dialog = useDialog()\n        dialog.success({\n          title: 'Loading',\n          content: 'Content',\n          positiveText: '确认',\n          loading: true\n        })\n      },\n      render() {\n        return null\n      }\n    })\n    const wrapper = mount(() => (\n      <Provider>{{ default: () => <Test /> }}</Provider>\n    ))\n    await nextTick()\n    expect(document.querySelector('.n-button__icon')).not.toEqual(null)\n    wrapper.unmount()\n  })\n\n  it('maskClosable', async () => {\n    const Test = defineComponent({\n      setup() {\n        const dialog = useDialog()\n        dialog.success({\n          title: 'Close by mask',\n          content: 'Content',\n          maskClosable: false\n        })\n      },\n      render() {\n        return null\n      }\n    })\n    const wrapper = mount(() => (\n      <Provider>{{ default: () => <Test /> }}</Provider>\n    ))\n    document\n      .querySelector('.n-modal-mask')\n      ?.dispatchEvent(new MouseEvent('click', { bubbles: true }))\n    await nextTick()\n    expect(document.querySelector('.n-dialog')).not.toBeNull()\n    wrapper.unmount()\n  })\n\n  it('onMaskClick', async () => {\n    const onMaskClick = vi.fn()\n    const Test = defineComponent({\n      setup() {\n        const dialog = useDialog()\n        dialog.success({\n          title: 'Close by mask',\n          content: 'Content',\n          onMaskClick\n        })\n      },\n      render() {\n        return null\n      }\n    })\n    const wrapper = mount(() => (\n      <Provider>{{ default: () => <Test /> }}</Provider>\n    ))\n    await nextTick()\n    document\n      .querySelector('.n-modal-mask')\n      ?.dispatchEvent(new MouseEvent('click', { bubbles: true }))\n    expect(onMaskClick).toHaveBeenCalled()\n    wrapper.unmount()\n  })\n\n  it('should work with `style` option', async () => {\n    const Test = defineComponent({\n      setup() {\n        const dialog = useDialog()\n        dialog.warning({\n          title: 'Custom style',\n          content: 'Content',\n          style: {\n            color: 'rgb(79, 178, 51)'\n          }\n        })\n      },\n      render() {\n        return null\n      }\n    })\n    const wrapper = mount(() => (\n      <Provider>{{ default: () => <Test /> }}</Provider>\n    ))\n    await nextTick()\n    expect(\n      document.querySelector('.n-dialog')?.getAttribute('style')\n    ).toContain('color: rgb(79, 178, 51);')\n    wrapper.unmount()\n  })\n\n  it('dialog type', async () => {\n    const TestCreate = createTestComponent('create')\n    const TestError = createTestComponent('error')\n    const TestInfo = createTestComponent('info')\n    const TestSuccess = createTestComponent('success')\n    const TestWarning = createTestComponent('warning')\n\n    const wrapperCreate = mount(() => (\n      <Provider>{{ default: () => <TestCreate /> }}</Provider>\n    ))\n    await nextTick()\n    expect(\n      document.querySelector('.n-dialog')?.getAttribute('style')\n    ).toContain('--n-icon-color: #18a058;')\n    wrapperCreate.unmount()\n\n    const wrapperError = mount(() => (\n      <Provider>{{ default: () => <TestError /> }}</Provider>\n    ))\n    await nextTick()\n    expect(\n      document.querySelector('.n-dialog')?.getAttribute('style')\n    ).toContain('--n-icon-color: #d03050;')\n    wrapperError.unmount()\n\n    const wrapperInfo = mount(() => (\n      <Provider>{{ default: () => <TestInfo /> }}</Provider>\n    ))\n    await nextTick()\n    expect(\n      document.querySelector('.n-dialog')?.getAttribute('style')\n    ).toContain('--n-icon-color: #2080f0;')\n    wrapperInfo.unmount()\n\n    const wrapperSuccess = mount(() => (\n      <Provider>{{ default: () => <TestSuccess /> }}</Provider>\n    ))\n    await nextTick()\n    expect(\n      document.querySelector('.n-dialog')?.getAttribute('style')\n    ).toContain('--n-icon-color: #18a058;')\n    wrapperSuccess.unmount()\n\n    const wrapperWarning = mount(() => (\n      <Provider>{{ default: () => <TestWarning /> }}</Provider>\n    ))\n    await nextTick()\n    expect(\n      document.querySelector('.n-dialog')?.getAttribute('style')\n    ).toContain('--n-icon-color: #f0a020;')\n    wrapperWarning.unmount()\n  })\n\n  it('should work with `bordered` option', async () => {\n    const Test = createTestComponent('info', { bordered: true })\n    const wrapper = mount(() => (\n      <Provider>{{ default: () => <Test /> }}</Provider>\n    ))\n    await nextTick()\n    expect(document.querySelector('.n-dialog--bordered')).not.toEqual(null)\n    wrapper.unmount()\n  })\n\n  it('should work with `closable` option', async () => {\n    const Test = createTestComponent('info', { closable: false })\n    const wrapper = mount(() => (\n      <Provider>{{ default: () => <Test /> }}</Provider>\n    ))\n    await nextTick()\n    expect(document.querySelector('.n-base-icon')).not.toEqual(null)\n    wrapper.unmount()\n  })\n\n  it('should work with `icon-placement` option', async () => {\n    const TestLeft = createTestComponent('info', { iconPlacement: 'left' })\n    const TestTop = createTestComponent('info', { iconPlacement: 'top' })\n\n    const wrapperLeft = mount(() => (\n      <Provider>{{ default: () => <TestLeft /> }}</Provider>\n    ))\n    const wrapperTop = mount(() => (\n      <Provider>{{ default: () => <TestTop /> }}</Provider>\n    ))\n    await nextTick()\n    expect(document.querySelector('.n-dialog--icon-left')).not.toEqual(null)\n    wrapperLeft.unmount()\n    expect(document.querySelector('.n-dialog--icon-top')).not.toEqual(null)\n    wrapperTop.unmount()\n  })\n\n  it('should work with `negative-text` option', async () => {\n    const Test = createTestComponent('info', { negativeText: 'test1' })\n    const wrapper = mount(() => (\n      <Provider>{{ default: () => <Test /> }}</Provider>\n    ))\n    await nextTick()\n    expect(document.querySelector('.n-button__content')?.textContent).toBe(\n      'test1'\n    )\n    wrapper.unmount()\n  })\n\n  it('should work with `positive-text` option', async () => {\n    const Test = createTestComponent('info', { positiveText: 'test2' })\n    const wrapper = mount(() => (\n      <Provider>{{ default: () => <Test /> }}</Provider>\n    ))\n    await nextTick()\n    expect(document.querySelector('.n-button__content')?.textContent).toBe(\n      'test2'\n    )\n    wrapper.unmount()\n  })\n})\n"
  },
  {
    "path": "src/dialog/tests/server.spec.tsx",
    "content": "import { setup } from '@css-render/vue3-ssr'\nimport { renderToString } from '@vue/server-renderer'\n/**\n * @vitest-environment node\n */\nimport { createSSRApp, h } from 'vue'\nimport { NDialog } from '../..'\n\ndescribe('server side rendering', () => {\n  it('works', async () => {\n    const app = createSSRApp(() => <NDialog />)\n    setup(app)\n    try {\n      await renderToString(app)\n    }\n    catch (e) {\n      expect(e).not.toBeTruthy()\n    }\n  })\n})\n"
  },
  {
    "path": "src/discrete/demos/enUS/basic.demo.vue",
    "content": "<markdown>\n# Basic\n\nUse `createDiscreteApi` to create series of API.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { ConfigProviderProps } from 'naive-ui'\nimport { createDiscreteApi, darkTheme, lightTheme } from 'naive-ui'\nimport { computed, ref } from 'vue'\n\nconst theme = ref<'light' | 'dark'>('light')\nconst configProviderPropsRef = computed<ConfigProviderProps>(() => ({\n  theme: theme.value === 'light' ? lightTheme : darkTheme\n}))\n\nconst { message, notification, dialog, loadingBar, modal } = createDiscreteApi(\n  ['message', 'dialog', 'notification', 'loadingBar', 'modal'],\n  {\n    configProviderProps: configProviderPropsRef\n  }\n)\n\nfunction handleThemeChangeClick() {\n  if (theme.value === 'light')\n    theme.value = 'dark'\n  else theme.value = 'light'\n}\n\nfunction handleMessageTriggerClick() {\n  message.info('Message')\n}\n\nfunction handleNotificationTriggerClick() {\n  notification.create({ title: 'Notification' })\n}\n\nfunction handleDialogTriggerClick() {\n  dialog.info({ title: 'Dialog' })\n}\n\nfunction handleModalTriggerClick() {\n  modal.create({\n    preset: 'card',\n    title: 'Modal'\n  })\n}\n\nfunction handleLoadingBarTriggerClick() {\n  loadingBar.start()\n  setTimeout(() => {\n    loadingBar.finish()\n  }, 1000)\n}\n</script>\n\n<template>\n  <n-space>\n    <n-button @click=\"handleThemeChangeClick\">\n      theme: {{ theme }}\n    </n-button>\n    <n-button @click=\"handleMessageTriggerClick\">\n      message\n    </n-button>\n    <n-button @click=\"handleNotificationTriggerClick\">\n      notification\n    </n-button>\n    <n-button @click=\"handleDialogTriggerClick\">\n      dialog\n    </n-button>\n    <n-button @click=\"handleLoadingBarTriggerClick\">\n      loadingBar\n    </n-button>\n    <n-button @click=\"handleModalTriggerClick\">\n      modal\n    </n-button>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/discrete/demos/enUS/index.demo-entry.md",
    "content": "# Discrete API（v2.29.0)\n\nIf you want to use `useDialog`, `useMessage`, `useNotification`, `useLoadingBar`, `useModal` outside `setup`, you can use `createDiscreteApi` to create corresponding API.\n\n<n-alert title=\"Caveat\" type=\"warning\" :bordered=\"false\">\n1. Discrete API won't be affected by <n-text code>n-xxx-provider</n-text> in current app. If you need to share config, you should sync them manually. Also, you'd better not using discrete API and normal API together. 2. Do not call <n-text code>createDiscreteApi</n-text> in <n-text code>setup</n-text> since it may cause some unexpected behaviors.\n</n-alert>\n\n## Demo\n\n```demo\nbasic.vue\n```\n\n## API\n\n### createDiscreteApi\n\n```ts\nfunction createDiscreteApi(\n  includes: Array<'message' | 'dialog' | 'notification' | 'loadingBar'>,\n  options: {\n    configProviderProps: Ref<ConfigProviderProps> | ConfigProviderProps\n    messageProviderProps: Ref<MessageProviderProps> | MessageProviderProps\n    dialogProviderProps: Ref<DialogProviderProps> | DialogProviderProps\n    notificationProviderProps:\n      | Ref<NotificationProviderProps>\n      | NotificationProviderProps\n    modalProviderProps: Ref<ModalProviderProps> | ModalProviderProps\n    loadingBarProviderProps:\n      | Ref<LoadingBarProviderProps>\n      | LoadingBarProviderProps\n  }\n): {\n  // only API specified in `includes` will be created\n  message: MessageApi\n  dialog: DialogApi\n  notification: NotificationApi\n  loadingBar: LoadingBarApi\n  modal: ModalApi\n  // Vue app\n  app: App\n  unmount: () => void\n} {}\n```\n"
  },
  {
    "path": "src/discrete/demos/zhCN/basic.demo.vue",
    "content": "<markdown>\n# 基础用法\n\n使用 `createDiscreteApi` 来创建一系列 API。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { ConfigProviderProps } from 'naive-ui'\nimport { createDiscreteApi, darkTheme, lightTheme } from 'naive-ui'\nimport { computed, ref } from 'vue'\n\nconst theme = ref<'light' | 'dark'>('light')\nconst configProviderPropsRef = computed<ConfigProviderProps>(() => ({\n  theme: theme.value === 'light' ? lightTheme : darkTheme\n}))\n\nconst { message, notification, dialog, loadingBar, modal } = createDiscreteApi(\n  ['message', 'dialog', 'notification', 'loadingBar', 'modal'],\n  {\n    configProviderProps: configProviderPropsRef\n  }\n)\n\nfunction handleThemeChangeClick() {\n  if (theme.value === 'light')\n    theme.value = 'dark'\n  else theme.value = 'light'\n}\n\nfunction handleMessageTriggerClick() {\n  message.info('Message')\n}\n\nfunction handleNotificationTriggerClick() {\n  notification.create({ title: 'Notification' })\n}\n\nfunction handleDialogTriggerClick() {\n  dialog.info({ title: 'Dialog' })\n}\n\nfunction handleModalTriggerClick() {\n  modal.create({\n    preset: 'card',\n    title: 'Modal'\n  })\n}\n\nfunction handleLoadingBarTriggerClick() {\n  loadingBar.start()\n  setTimeout(() => {\n    loadingBar.finish()\n  }, 1000)\n}\n</script>\n\n<template>\n  <n-space>\n    <n-button @click=\"handleThemeChangeClick\">\n      theme: {{ theme }}\n    </n-button>\n    <n-button @click=\"handleMessageTriggerClick\">\n      message\n    </n-button>\n    <n-button @click=\"handleNotificationTriggerClick\">\n      notification\n    </n-button>\n    <n-button @click=\"handleDialogTriggerClick\">\n      dialog\n    </n-button>\n    <n-button @click=\"handleLoadingBarTriggerClick\">\n      loadingBar\n    </n-button>\n    <n-button @click=\"handleModalTriggerClick\">\n      modal\n    </n-button>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/discrete/demos/zhCN/index.demo-entry.md",
    "content": "# 脱离上下文的 API（v2.29.0）\n\n如果你想在 `setup` 外使用 `useDialog`、`useMessage`、`useNotification`、`useLoadingBar`，`useModal`，可以通过 `createDiscreteApi` 来构建对应的 API。\n\n<n-alert title=\"注意\" type=\"warning\" :bordered=\"false\">\n  1. 脱离上下文的 API 不会受 <n-text code>n-xxx-provider</n-text> 的影响，并且和应用上下文中对应组件会使用不同的 DOM 容器。如果需要的话，你需要手动同步这些信息。并且最好不要混用两类 API。2. 不要在 <n-text code>setup</n-text> 中调用 <n-text code>createDiscreteApi</n-text>，可能会有一些意外的问题出现。\n</n-alert>\n\n## 演示\n\n```demo\nbasic.vue\n```\n\n## API\n\n### createDiscreteApi\n\n```ts\nfunction createDiscreteApi(\n  includes: Array<'message' | 'dialog' | 'notification' | 'loadingBar'>,\n  options: {\n    configProviderProps: Ref<ConfigProviderProps> | ConfigProviderProps\n    messageProviderProps: Ref<MessageProviderProps> | MessageProviderProps\n    dialogProviderProps: Ref<DialogProviderProps> | DialogProviderProps\n    notificationProviderProps: Ref<NotificationProps> | NotificationProps\n    loadingBarProviderProps:\n      | Ref<LoadingBarProviderProps>\n      | LoadingBarProviderProps\n  }\n): {\n  // 只有 includes 中包含的 API 才会被创建\n  message: MessageApi\n  dialog: DialogApi\n  notification: NotificationApi\n  loadingBar: LoadingBarApi\n  // Vue app\n  app: App\n  unmount: () => void\n} {}\n```\n"
  },
  {
    "path": "src/discrete/index.ts",
    "content": "export { createDiscreteApi } from './src/discrete'\nexport type { DiscreteApi, DiscreteApiOptions } from './src/interface'\n"
  },
  {
    "path": "src/discrete/src/InjectionExtractor.tsx",
    "content": "import type { PropType } from 'vue'\nimport { defineComponent } from 'vue'\n\nexport const NInjectionExtractor = defineComponent({\n  name: 'InjectionExtractor',\n  props: {\n    onSetup: Function as PropType<() => void>\n  },\n  setup(props, { slots }) {\n    props.onSetup?.()\n    return () => slots.default?.()\n  }\n})\n"
  },
  {
    "path": "src/discrete/src/discrete.ts",
    "content": "import type { Component } from 'vue'\nimport type {\n  DiscreteApi,\n  DiscreteApiOptions,\n  DiscreteApiType\n} from './interface'\nimport { NDialogProvider } from '../../dialog'\nimport { NLoadingBarProvider } from '../../loading-bar'\nimport { NMessageProvider } from '../../message'\nimport { NModalProvider } from '../../modal/src/ModalProvider'\nimport { NNotificationProvider } from '../../notification'\nimport { createDiscreteApp } from './discreteApp'\n\nexport function createDiscreteApi<T extends DiscreteApiType>(\n  includes: T[],\n  {\n    configProviderProps,\n    messageProviderProps,\n    dialogProviderProps,\n    notificationProviderProps,\n    loadingBarProviderProps,\n    modalProviderProps\n  }: DiscreteApiOptions = {}\n): DiscreteApi<T> {\n  const providersAndProps: Array<{\n    type: DiscreteApiType\n    Provider: Component\n    props: any\n  }> = []\n\n  includes.forEach((type) => {\n    switch (type) {\n      case 'message':\n        providersAndProps.push({\n          type,\n          Provider: NMessageProvider,\n          props: messageProviderProps\n        })\n        break\n      case 'notification':\n        providersAndProps.push({\n          type,\n          Provider: NNotificationProvider,\n          props: notificationProviderProps\n        })\n        break\n      case 'dialog':\n        providersAndProps.push({\n          type,\n          Provider: NDialogProvider,\n          props: dialogProviderProps\n        })\n        break\n      case 'loadingBar':\n        providersAndProps.push({\n          type,\n          Provider: NLoadingBarProvider,\n          props: loadingBarProviderProps\n        })\n        break\n      case 'modal':\n        providersAndProps.push({\n          type,\n          Provider: NModalProvider,\n          props: modalProviderProps\n        })\n    }\n  })\n\n  const discreteApp = createDiscreteApp({\n    providersAndProps,\n    configProviderProps\n  })\n\n  return discreteApp as any\n}\n"
  },
  {
    "path": "src/discrete/src/discreteApp.ts",
    "content": "import type { App, Component, VNode } from 'vue'\nimport type { ConfigProviderProps } from '../../config-provider'\nimport type { DialogApi } from '../../dialog'\nimport type { LoadingBarApi } from '../../loading-bar'\nimport type { MessageApi } from '../../message'\nimport type { ModalApi } from '../../modal'\nimport type { NotificationApi } from '../../notification'\nimport type { DiscreteApiType, MaybeRef } from './interface'\nimport { createApp, h, unref } from 'vue'\nimport { isBrowser, warn } from '../../_utils'\nimport { NConfigProvider } from '../../config-provider'\nimport { useDialog } from '../../dialog'\nimport { useLoadingBar } from '../../loading-bar'\nimport { useMessage } from '../../message'\nimport { useModal } from '../../modal'\nimport { useNotification } from '../../notification'\nimport { NInjectionExtractor } from './InjectionExtractor'\n\nexport type Provider<P = any> = new (...args: any[]) => { $props: P }\n\nexport type ProviderProps<C> = C extends Provider<infer P> ? P : unknown\n\nexport interface DiscreteAppOptions {\n  providersAndProps: Array<{\n    type: DiscreteApiType\n    Provider: Component\n    props: any\n  }>\n  configProviderProps?: MaybeRef<ConfigProviderProps>\n}\n\nexport interface DiscreteApp {\n  unmount: () => void\n  app: App\n  message?: MessageApi\n  notification?: NotificationApi\n  dialog?: DialogApi\n  loadingBar?: LoadingBarApi\n  modal?: ModalApi\n}\n\nconst injectionFactoryMap: Record<DiscreteApiType, any> = {\n  message: useMessage,\n  notification: useNotification,\n  loadingBar: useLoadingBar,\n  dialog: useDialog,\n  modal: useModal\n}\n\nexport function createDiscreteApp({\n  providersAndProps,\n  configProviderProps\n}: DiscreteAppOptions): DiscreteApp {\n  let app: App<Element> | null = createApp(App)\n  const extractedApi: Omit<DiscreteApp, 'unmount'> = {\n    app\n  }\n  function App(): VNode {\n    return h(NConfigProvider, unref(configProviderProps), {\n      default: () =>\n        providersAndProps.map(({ type, Provider, props }) => {\n          return h(Provider, unref(props), {\n            default: () =>\n              h(NInjectionExtractor, {\n                onSetup: () =>\n                  (extractedApi[type] = injectionFactoryMap[type]())\n              })\n          })\n        })\n    })\n  }\n\n  let hostEl: Element | null\n  if (isBrowser) {\n    hostEl = document.createElement('div')\n    document.body.appendChild(hostEl)\n\n    app.mount(hostEl)\n  }\n\n  const unmount = (): void => {\n    if (app === null || hostEl === null) {\n      warn(\n        'discrete',\n        'unmount call no need because discrete app has been unmounted'\n      )\n      return\n    }\n    app.unmount()\n    hostEl.parentNode?.removeChild(hostEl)\n    hostEl = null\n    app = null\n  }\n\n  return { unmount, ...extractedApi }\n}\n"
  },
  {
    "path": "src/discrete/src/interface.ts",
    "content": "import type { App, Ref } from 'vue'\nimport type { ConfigProviderProps } from '../../config-provider'\nimport type { DialogApi, DialogProviderProps } from '../../dialog'\nimport type { LoadingBarApi, LoadingBarProviderProps } from '../../loading-bar'\nimport type { MessageApi, MessageProviderProps } from '../../message'\nimport type { ModalApi } from '../../modal'\nimport type { ModalProviderProps } from '../../modal/src/ModalProvider'\nimport type {\n  NotificationApi,\n  NotificationProviderProps\n} from '../../notification'\n\nexport type MaybeRef<T> = Ref<T> | T\n\nexport interface DiscreteApiOptions {\n  configProviderProps?: MaybeRef<ConfigProviderProps>\n  messageProviderProps?: MaybeRef<MessageProviderProps>\n  dialogProviderProps?: MaybeRef<DialogProviderProps>\n  notificationProviderProps?: MaybeRef<NotificationProviderProps>\n  loadingBarProviderProps?: MaybeRef<LoadingBarProviderProps>\n  modalProviderProps?: MaybeRef<ModalProviderProps>\n}\n\nexport type DiscreteApiType\n  = | 'message'\n    | 'notification'\n    | 'loadingBar'\n    | 'dialog'\n    | 'modal'\n\nexport type DiscreteApi<T extends DiscreteApiType = DiscreteApiType> = {\n  unmount: () => void\n  app: App\n} & ('message' extends T ? { message: MessageApi } : Record<string, unknown>)\n& ('notification' extends T\n  ? { notification: NotificationApi }\n  : Record<string, unknown>)\n& ('dialog' extends T ? { dialog: DialogApi } : Record<string, unknown>)\n& ('loadingBar' extends T\n  ? { loadingBar: LoadingBarApi }\n  : Record<string, unknown>)\n& ('modal' extends T ? { modal: ModalApi } : Record<string, unknown>)\n"
  },
  {
    "path": "src/divider/demos/enUS/basic.demo.vue",
    "content": "<markdown>\n# Basic\n</markdown>\n\n<template>\n  Oops\n  <n-divider />\n  Oops\n</template>\n"
  },
  {
    "path": "src/divider/demos/enUS/content.demo.vue",
    "content": "<markdown>\n# Title\n</markdown>\n\n<template>\n  Oops\n  <n-divider title-placement=\"left\">\n    Left\n  </n-divider>\n  Oops\n  <n-divider title-placement=\"right\">\n    Right\n  </n-divider>\n  Oops\n  <n-divider dashed>\n    Dashed\n  </n-divider>\n  Oops\n</template>\n"
  },
  {
    "path": "src/divider/demos/enUS/index.demo-entry.md",
    "content": "# Divider\n\nDivide something.\n\n## Demos\n\n```demo\nbasic.vue\ncontent.vue\nvertical.vue\n```\n\n## API\n\n### Divider Props\n\n| Name | Type | Default | Description |\n| --- | --- | --- | --- |\n| dashed | `boolean` | `false` | Whether to show dashed line. |\n| title-placement | `'left' \\| 'right' \\| 'center'` | `'center'` | Title placement. |\n| vertical | `boolean` | `false` | Whether to show vertical direction. |\n\n### Divider Slots\n\n| Name    | Parameters | Description           |\n| ------- | ---------- | --------------------- |\n| default | `()`       | The title of divider. |\n"
  },
  {
    "path": "src/divider/demos/enUS/vertical.demo.vue",
    "content": "<markdown>\n# Vertical\n</markdown>\n\n<template>\n  It is<n-divider vertical />not clear<n-divider vertical />to see, emmm...\n</template>\n"
  },
  {
    "path": "src/divider/demos/zhCN/basic.demo.vue",
    "content": "<markdown>\n# 基础\n</markdown>\n\n<template>\n  啊\n  <n-divider />\n  啊\n</template>\n"
  },
  {
    "path": "src/divider/demos/zhCN/content.demo.vue",
    "content": "<markdown>\n# 标题\n</markdown>\n\n<template>\n  啊\n  <n-divider title-placement=\"left\">\n    左\n  </n-divider>\n  啊\n  <n-divider title-placement=\"right\">\n    右\n  </n-divider>\n  啊\n  <n-divider dashed>\n    虚线\n  </n-divider>\n  啊\n</template>\n"
  },
  {
    "path": "src/divider/demos/zhCN/index.demo-entry.md",
    "content": "# 分割线 Divider\n\n分割一些内容。\n\n## 演示\n\n```demo\nbasic.vue\ncontent.vue\nvertical.vue\n```\n\n## API\n\n### Divider Props\n\n| 名称 | 类型 | 默认值 | 说明 |\n| --- | --- | --- | --- |\n| dashed | `boolean` | `false` | 是否使用虚线分割 |\n| title-placement | `'left' \\| 'right' \\| 'center'` | `'center'` | 标题的位置 |\n| vertical | `boolean` | `false` | 是否垂直分隔 |\n\n### Divider Slots\n\n| 名称    | 参数 | 说明         |\n| ------- | ---- | ------------ |\n| default | `()` | 分割线的标题 |\n"
  },
  {
    "path": "src/divider/demos/zhCN/vertical.demo.vue",
    "content": "<markdown>\n# 垂直\n</markdown>\n\n<template>\n  这个<n-divider vertical />看起来<n-divider vertical />好像不是很显眼，额...\n</template>\n"
  },
  {
    "path": "src/divider/index.ts",
    "content": "export { dividerProps, default as NDivider } from './src/Divider'\nexport type { DividerProps } from './src/Divider'\n"
  },
  {
    "path": "src/divider/src/Divider.tsx",
    "content": "import type { CSSProperties, PropType } from 'vue'\nimport type { ThemeProps } from '../../_mixins'\nimport type { ExtractPublicPropTypes } from '../../_utils'\nimport type { DividerTheme } from '../styles'\nimport { computed, defineComponent, Fragment, h } from 'vue'\nimport { useConfig, useTheme, useThemeClass } from '../../_mixins'\nimport { dividerLight } from '../styles'\nimport style from './styles/index.cssr'\n\nexport const dividerProps = {\n  ...(useTheme.props as ThemeProps<DividerTheme>),\n  titlePlacement: {\n    type: String as PropType<'left' | 'center' | 'right'>,\n    default: 'center'\n  },\n  dashed: Boolean,\n  vertical: Boolean\n} as const\n\nexport type DividerProps = ExtractPublicPropTypes<typeof dividerProps>\n\nexport default defineComponent({\n  name: 'Divider',\n  props: dividerProps,\n  setup(props) {\n    const { mergedClsPrefixRef, inlineThemeDisabled } = useConfig(props)\n    const themeRef = useTheme(\n      'Divider',\n      '-divider',\n      style,\n      dividerLight,\n      props,\n      mergedClsPrefixRef\n    )\n    const cssVarsRef = computed(() => {\n      const {\n        common: { cubicBezierEaseInOut },\n        self: { color, textColor, fontWeight }\n      } = themeRef.value\n      return {\n        '--n-bezier': cubicBezierEaseInOut,\n        '--n-color': color,\n        '--n-text-color': textColor,\n        '--n-font-weight': fontWeight\n      }\n    })\n    const themeClassHandle = inlineThemeDisabled\n      ? useThemeClass('divider', undefined, cssVarsRef, props)\n      : undefined\n    return {\n      mergedClsPrefix: mergedClsPrefixRef,\n      cssVars: inlineThemeDisabled ? undefined : cssVarsRef,\n      themeClass: themeClassHandle?.themeClass,\n      onRender: themeClassHandle?.onRender\n    }\n  },\n  render() {\n    const {\n      $slots,\n      titlePlacement,\n      vertical,\n      dashed,\n      cssVars,\n      mergedClsPrefix\n    } = this\n    this.onRender?.()\n    return (\n      <div\n        role=\"separator\"\n        class={[\n          `${mergedClsPrefix}-divider`,\n          this.themeClass,\n          {\n            [`${mergedClsPrefix}-divider--vertical`]: vertical,\n            [`${mergedClsPrefix}-divider--no-title`]: !$slots.default,\n            [`${mergedClsPrefix}-divider--dashed`]: dashed,\n            [`${mergedClsPrefix}-divider--title-position-${titlePlacement}`]:\n              $slots.default && titlePlacement\n          }\n        ]}\n        style={cssVars as CSSProperties}\n      >\n        {!vertical ? (\n          <div\n            class={`${mergedClsPrefix}-divider__line ${mergedClsPrefix}-divider__line--left`}\n          />\n        ) : null}\n        {!vertical && $slots.default ? (\n          <>\n            <div class={`${mergedClsPrefix}-divider__title`}>{this.$slots}</div>\n            <div\n              class={`${mergedClsPrefix}-divider__line ${mergedClsPrefix}-divider__line--right`}\n            />\n          </>\n        ) : null}\n      </div>\n    )\n  }\n})\n"
  },
  {
    "path": "src/divider/src/styles/index.cssr.ts",
    "content": "import { cB, cE, cM, cNotM } from '../../../_utils/cssr'\n\n// vars:\n// --n-bezier\n// --n-color\n// --n-text-color\n// --n-font-weight\nexport default cB('divider', `\n  position: relative;\n  display: flex;\n  width: 100%;\n  box-sizing: border-box;\n  font-size: 16px;\n  color: var(--n-text-color);\n  transition:\n    color .3s var(--n-bezier),\n    background-color .3s var(--n-bezier);\n`, [\n  cNotM('vertical', `\n    margin-top: 24px;\n    margin-bottom: 24px;\n  `, [\n    cNotM('no-title', `\n      display: flex;\n      align-items: center;\n    `)\n  ]),\n  cE('title', `\n    display: flex;\n    align-items: center;\n    margin-left: 12px;\n    margin-right: 12px;\n    white-space: nowrap;\n    font-weight: var(--n-font-weight);\n  `),\n  cM('title-position-left', [\n    cE('line', [\n      cM('left', {\n        width: '28px'\n      })\n    ])\n  ]),\n  cM('title-position-right', [\n    cE('line', [\n      cM('right', {\n        width: '28px'\n      })\n    ])\n  ]),\n  cM('dashed', [\n    cE('line', `\n      background-color: #0000;\n      height: 0px;\n      width: 100%;\n      border-style: dashed;\n      border-width: 1px 0 0;\n    `)\n  ]),\n  cM('vertical', `\n    display: inline-block;\n    height: 1em;\n    margin: 0 8px;\n    vertical-align: middle;\n    width: 1px;\n  `),\n  cE('line', `\n    border: none;\n    transition: background-color .3s var(--n-bezier), border-color .3s var(--n-bezier);\n    height: 1px;\n    width: 100%;\n    margin: 0;\n  `),\n  cNotM('dashed', [\n    cE('line', {\n      backgroundColor: 'var(--n-color)'\n    })\n  ]),\n  cM('dashed', [\n    cE('line', {\n      borderColor: 'var(--n-color)'\n    })\n  ]),\n  cM('vertical', {\n    backgroundColor: 'var(--n-color)'\n  })\n])\n"
  },
  {
    "path": "src/divider/styles/dark.ts",
    "content": "import type { DividerTheme } from './light'\nimport { commonDark } from '../../_styles/common'\nimport { self } from './light'\n\nconst dividerDark: DividerTheme = {\n  name: 'Divider',\n  common: commonDark,\n  self\n}\n\nexport default dividerDark\n"
  },
  {
    "path": "src/divider/styles/index.ts",
    "content": "export { default as dividerDark } from './dark'\nexport { default as dividerLight } from './light'\nexport type { DividerTheme, DividerThemeVars } from './light'\n"
  },
  {
    "path": "src/divider/styles/light.ts",
    "content": "import type { Theme } from '../../_mixins'\nimport type { ThemeCommonVars } from '../../_styles/common'\nimport { commonLight } from '../../_styles/common'\n\nexport function self(vars: ThemeCommonVars) {\n  const { textColor1, dividerColor, fontWeightStrong } = vars\n  return {\n    textColor: textColor1,\n    color: dividerColor,\n    fontWeight: fontWeightStrong\n  }\n}\n\nexport type DividerThemeVars = ReturnType<typeof self>\n\nconst dividerLight: Theme<'Divider', DividerThemeVars> = {\n  name: 'Divider',\n  common: commonLight,\n  self\n}\n\nexport default dividerLight\nexport type DividerTheme = typeof dividerLight\n"
  },
  {
    "path": "src/divider/tests/Divider.spec.ts",
    "content": "import { mount } from '@vue/test-utils'\nimport { NDivider } from '../index'\n\ndescribe('n-divider', () => {\n  it('should work with import on demand', () => {\n    mount(NDivider)\n  })\n\n  it('default slot', () => {\n    const str = 'star kirby'\n    const wrapper = mount(NDivider, {\n      slots: {\n        default: () => str\n      }\n    })\n    wrapper.text().includes(str)\n    wrapper.unmount()\n  })\n\n  it('should work with `title-placement` prop', async () => {\n    const wrapper = mount(NDivider, {\n      props: { titlePlacement: 'left' },\n      slots: { default: () => 'test' }\n    })\n    expect(wrapper.find('.n-divider').classes()).toContain(\n      'n-divider--title-position-left'\n    )\n\n    await wrapper.setProps({ titlePlacement: 'right' })\n    expect(wrapper.find('.n-divider').classes()).toContain(\n      'n-divider--title-position-right'\n    )\n    wrapper.unmount()\n  })\n\n  it('should work with `dashed` prop', async () => {\n    const wrapper = mount(NDivider)\n\n    await wrapper.setProps({ dashed: true })\n    expect(wrapper.find('.n-divider').classes()).toContain('n-divider--dashed')\n    expect(wrapper.find('.n-divider').classes()).toContain(\n      'n-divider--no-title'\n    )\n    wrapper.unmount()\n  })\n\n  it('should work with `vertical` prop', async () => {\n    const wrapper = mount(NDivider, {\n      props: { vertical: true }\n    })\n\n    expect(wrapper.find('.n-divider').classes()).toContain(\n      'n-divider--vertical'\n    )\n    wrapper.unmount()\n  })\n})\n"
  },
  {
    "path": "src/divider/tests/server.spec.tsx",
    "content": "import { setup } from '@css-render/vue3-ssr'\nimport { renderToString } from '@vue/server-renderer'\n/**\n * @vitest-environment node\n */\nimport { createSSRApp, h } from 'vue'\nimport { NDivider } from '../..'\n\ndescribe('server side rendering', () => {\n  it('works', async () => {\n    const app = createSSRApp(() => <NDivider />)\n    setup(app)\n    try {\n      await renderToString(app)\n    }\n    catch (e) {\n      expect(e).not.toBeTruthy()\n    }\n  })\n})\n"
  },
  {
    "path": "src/drawer/demos/enUS/basic.demo.vue",
    "content": "<markdown>\n# Basic\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { DrawerPlacement } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst active = ref(false)\nconst placement = ref<DrawerPlacement>('right')\nfunction activate(place: DrawerPlacement) {\n  active.value = true\n  placement.value = place\n}\n</script>\n\n<template>\n  <n-button-group>\n    <n-button @click=\"activate('top')\">\n      Top\n    </n-button>\n    <n-button @click=\"activate('right')\">\n      Right\n    </n-button>\n    <n-button @click=\"activate('bottom')\">\n      Bottom\n    </n-button>\n    <n-button @click=\"activate('left')\">\n      Left\n    </n-button>\n  </n-button-group>\n  <n-drawer v-model:show=\"active\" :width=\"502\" :placement=\"placement\">\n    <n-drawer-content title=\"Stoner\">\n      Stoner is a 1965 novel by the American writer John Williams.\n    </n-drawer-content>\n  </n-drawer>\n</template>\n"
  },
  {
    "path": "src/drawer/demos/enUS/closable.demo.vue",
    "content": "<markdown>\n# Closable\n\nSet `closable` on `n-drawer-content`.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst show = ref(false)\n</script>\n\n<template>\n  <n-button @click=\"show = true\">\n    Open\n  </n-button>\n  <n-drawer v-model:show=\"show\" :width=\"502\">\n    <n-drawer-content title=\"Stoner\" closable>\n      Stoner is a 1965 novel by the American writer John Williams.\n    </n-drawer-content>\n  </n-drawer>\n</template>\n"
  },
  {
    "path": "src/drawer/demos/enUS/index.demo-entry.md",
    "content": "# Drawer\n\nI think it is similar with modal, with a bit difference on placement.\n\n<n-alert title=\"Caveat\" type=\"warning\" :bordered=\"false\">\n  If you need to use <n-text code>n-drawer-content</n-text>, you should keep <n-text code>n-drawer</n-text>'s <n-text code>native-scrollbar</n-text> prop as <n-text code>true</n-text>.\n</n-alert>\n\n## Demos\n\n```demo\nbasic.vue\nmultiple.vue\nclosable.vue\ntarget.vue\nslot.vue\nscroll.vue\nresizable.vue\n```\n\n## API\n\n### Drawer Props\n\n| Name | Parameters | Default | Description | Version |\n| --- | --- | --- | --- | --- |\n| auto-focus | `boolean` | `true` | Whether to focus the first focusable element inside drawer. | 2.24.2 |\n| block-scroll | `boolean` | `true` | Whether to disabled body scrolling when it's active. | 2.28.3 |\n| close-on-esc | `boolean` | `true` | Whether to close drawer on Esc is pressed. | 2.24.2 |\n| content-class | `string` | `undefined` | Class of drawer's scrollable content node. | 2.37.0 |\n| content-style | `string \\| Object` | `undefined` | Style of drawer's scrollable content node. |  |\n| default-width | `number \\| string` | `251` | Default width of the drawer, works when placement is `left` and `right`. | 2.31.0 |\n| default-height | `number \\| string` | `251` | Default height of the drawer, works when placement is `top` and `bottom`. | 2.31.0 |\n| display-directive | `'if' \\| 'show'` | `'if'` | The display directive to use when `n-drawer` is rendered. `'if'` corresponds to `v-if` and `'show'` corresponds to `v-show`. |  |\n| height | `number \\| string` | `undefined` | Works when placement is `top` and `bottom`. |  |\n| native-scrollbar | `boolean` | `true` | Whether to use native scrollbar on drawer. |  |\n| mask-closable | `boolean` | `true` | Whether to emit `hide` event when click mask. |  |\n| max-width | `number` | `undefined` | Max width of draggable drawer. | 2.35.0 |\n| max-height | `number` | `undefined` | Max height of draggable drawer. | 2.35.0 |\n| min-width | `number` | `undefined` | Min width of draggable drawer. | 2.35.0 |\n| min-height | `number` | `undefined` | Max height of draggable drawer. | 2.35.0 |\n| placement | `'top' \\| 'right' \\| 'bottom' \\| 'left'` | `'right'` | Drawer placement. |  |\n| resizable | `boolean` | `false` | Whether to resize the width / height of drawer. | 2.31.0 |\n| scrollbar-props | `ScrollbarProps` | `undefined` | See [Scrollbar props](scrollbar#Scrollbar-Props). |  |\n| show | `boolean` | `false` | Whether to show drawer. |  |\n| show-mask | `boolean` | `true` | Whether to show mask. If set to `'transparent'`, transparent mask would be shown. If set to false, `trap-focus` will be disabled. | 2.28.3 |\n| to | `string \\| HTMLElement` | `'body'` | Container node of the drawer. |  |\n| trap-focus | `boolean` | `true` | Whether to trap focus inside drawer. | 2.24.2 |\n| width | `number \\| string` | `undefined` | Works when placement is `left` and `right`. |  |\n| z-index | `number` | `undefined` | Z index of the drawer. | 2.24.0 |\n| on-after-enter | `() => void` | `undefined` | Callback after drawer is opened. | 2.28.0 |\n| on-after-leave | `() => void` | `undefined` | Callback after drawer is closed. | 2.28.0 |\n| on-esc | `() => void` | `undefined` | Callback fired when the escape key is pressed and focus is within drawer. | 2.24.2 |\n| on-mask-click | `(e: MouseEvent) => void` | `undefined` | Callback triggered on mask clicked. |  |\n| on-update:height | `(height: number) => void` | `undefined` | Callback trigger on drawer height change. | 2.31.0 |\n| on-update:show | `(show: boolean) => void` | `undefined` | Callback triggered on drawer display status would change. |  |\n| on-update:width | `(width: number) => void` | `undefined` | Callback trigger on drawer width change. | 2.31.0 |\n\n### DrawerContent Props\n\n| Name | Parameters | Default | Description | Version |\n| --- | --- | --- | --- | --- |\n| body-class | `string` | `undefined` | Drawer content's body class. | 2.37.0 |\n| body-style | `string \\| Object` | `undefined` | Drawer content's body style. |  |\n| body-content-class | `string` | `undefined` | Class of body's scrollable content node. |  |\n| body-content-style | `string \\| Object` | `undefined` | Style of body's scrollable content node. | 2.37.0 |\n| closable | `boolean` | `false` | Whether the drawer content is closable. |  |\n| footer-class | `string` | `undefined` | Drawer content's footer class. | 2.37.0 |\n| footer-style | `string \\| Object` | `undefined` | Drawer content's footer style. |  |\n| header-class | `string` | `undefined` | Drawer content's header class. | 2.37.0 |\n| header-style | `string \\| Object` | `undefined` | Drawer content's header style. |  |\n| native-scrollbar | `boolean` | `true` | Whether to use native scrollbar on body part. |  |\n| title | `string` | `undefined` | Drawer content title. |  |\n| scrollbar-props | `ScrollbarProps` | `undefined` | See [Scrollbar props](scrollbar#Scrollbar-Props). |  |\n\n### Drawer Slots\n\n| Name    | Parameters | Description                |\n| ------- | ---------- | -------------------------- |\n| default | `()`       | The content of the drawer. |\n\n### DrawerContent Slots\n\n| Name    | Parameters | Description                        |\n| ------- | ---------- | ---------------------------------- |\n| default | `()`       | The content of the drawer content. |\n| footer  | `()`       | The footer of the drawer content.  |\n| header  | `()`       | The header of the drawer content.  |\n"
  },
  {
    "path": "src/drawer/demos/enUS/multiple.demo.vue",
    "content": "<markdown>\n# Multiple drawers\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst showOuter = ref(false)\nconst showInner = ref(false)\n\nfunction doShowOuter() {\n  showOuter.value = true\n}\n\nfunction doShowInner() {\n  showInner.value = true\n}\n</script>\n\n<template>\n  <n-button @click=\"doShowOuter\">\n    Come on!\n  </n-button>\n  <n-drawer v-model:show=\"showOuter\" :width=\"502\">\n    <n-drawer-content title=\"Stoner\">\n      Stoner is a 1965 novel by the American writer John Williams.\n      <template #footer>\n        <n-button @click=\"doShowInner\">\n          Come on Again!\n        </n-button>\n      </template>\n    </n-drawer-content>\n    <n-drawer v-model:show=\"showInner\" :width=\"251\">\n      <n-drawer-content title=\"Stoner\">\n        Stoner is a 1965 novel by the American writer John Williams.\n      </n-drawer-content>\n    </n-drawer>\n  </n-drawer>\n</template>\n"
  },
  {
    "path": "src/drawer/demos/enUS/resizable.demo.vue",
    "content": "<markdown>\n# Resizable drawer\n\nRemeber to use `default-width` or `default-height` with `resizable`.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { DrawerPlacement } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst active = ref(false)\nconst placement = ref<DrawerPlacement>('right')\nfunction activate(place: DrawerPlacement) {\n  active.value = true\n  placement.value = place\n}\n</script>\n\n<template>\n  <n-button-group>\n    <n-button @click=\"activate('top')\">\n      Top\n    </n-button>\n    <n-button @click=\"activate('right')\">\n      Right\n    </n-button>\n    <n-button @click=\"activate('bottom')\">\n      Bottom\n    </n-button>\n    <n-button @click=\"activate('left')\">\n      Left\n    </n-button>\n  </n-button-group>\n  <n-drawer\n    v-model:show=\"active\"\n    :default-width=\"502\"\n    :placement=\"placement\"\n    resizable\n  >\n    <n-drawer-content title=\"Stoner\">\n      Stoner is a 1965 novel by the American writer John Williams.\n    </n-drawer-content>\n  </n-drawer>\n</template>\n"
  },
  {
    "path": "src/drawer/demos/enUS/scroll.demo.vue",
    "content": "<markdown>\n# Scroll content\n\nA demo with long scroll content.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst show = ref(false)\n</script>\n\n<template>\n  <n-button @click=\"show = !show\">\n    Come on!\n  </n-button>\n  <n-drawer v-model:show=\"show\" :width=\"480\">\n    <n-drawer-content title=\"Stoner\" :native-scrollbar=\"false\" :width=\"996\">\n      William Stoner is born on a small farm in 1891. One day his father\n      suggests he should attend the University of Missouri to study agriculture.\n      Stoner agrees but, while studying a compulsory literature course, he\n      quickly falls in love with literary studies. Without telling his parents,\n      Stoner quits the agriculture program and studies only the humanities. He\n      completes his MA in English and begins teaching. In graduate school, he is\n      friendly with fellow students Gordon Finch and Dave Masters. World War I\n      begins, and Gordon and Dave enlist. Despite pressure from Gordon, Stoner\n      decides to remain in school during the war. Masters is killed in France,\n      while Finch sees action and becomes an officer. At a faculty party, Stoner\n      meets and becomes infatuated with a young woman named Edith, who is\n      staying with an aunt for a few weeks. Stoner woos Edith, and she agrees to\n      marry him. Stoner's marriage to Edith is bad from the start. It gradually\n      becomes clear that Edith has profound emotional problems. Significantly,\n      she is bitter about having cancelled a trip to Europe with her aunt to\n      marry Stoner. After three years of marriage, Edith suddenly informs Stoner\n      that she wants a baby. She suddenly becomes passionate sexually, but this\n      period is brief. When their daughter Grace is born, Edith remains\n      bedridden for nearly a year, and Stoner largely cares for their child\n      alone. He grows close with his young daughter, who spends most of her time\n      with him in his study. Stoner gradually realizes that Edith is waging a\n      campaign to separate him from his daughter emotionally. For the most part,\n      Stoner accepts Edith's mistreatment. He begins to teach with more\n      enthusiasm, but still, year in and year out, his marriage with Edith\n      remains perpetually unsatisfactory and fraught. Grace becomes an unhappy,\n      secretive child who smiles and laughs often but is emotionally hollow. At\n      the University, Finch becomes the acting dean of the faculty. Stoner feels\n      compelled by his conscience to fail a student named Charles Walker. He is\n      a close protégé of a colleague, Professor Hollis Lomax, and like him is\n      physically disabled. The student is clearly dishonest and cannot fulfil\n      the requirements of Stoner's course but, despite this, the decision to\n      expel or retain Walker is put on hold. After his promotion to head of the\n      department, Lomax takes every opportunity to exact revenge upon Stoner\n      throughout the rest of his career. A collaboration between Stoner and a\n      younger instructor in the department, Katherine Driscoll, develops into a\n      romantic love affair. Ironically, after the affair begins, Stoner's\n      relationships with Edith and Grace also improve. At some point, Edith\n      finds out about the affair, but does not seem to mind it. When Lomax\n      learns about it, however, he begins to put pressure on Katherine, who also\n      teaches in the English department. Stoner and Driscoll agree it best to\n      end the affair so as not to derail the academic work they both feel called\n      to follow. Katherine quietly slips out of town, never to be seen by him\n      again. Eventually, Stoner, older now and hard of hearing, is beginning to\n      become a legendary figure in the English department despite Lomax's\n      opposition. He begins to spend more time at home, ignoring Edith's signs\n      of displeasure at his presence. Entering adulthood, Grace enrolls at the\n      University of Missouri. The following year, Grace announces she is\n      pregnant and marries the father of her child. Grace's husband enlists in\n      the army and dies before the baby is born. Grace goes to St. Louis with\n      the baby to live with her husband's parents. She visits Stoner and Edith\n      occasionally, and Stoner realizes that Grace has developed a drinking\n      problem. As Stoner's life is coming to an end, his daughter Grace comes to\n      visit him. Deeply unhappy and addicted to alcohol, Grace halfheartedly\n      tries to reconcile with Stoner, and he sees that his daughter, like her\n      mother, will never be happy. When Grace leaves, Stoner feels as though the\n      young child that he loved died long ago. Stoner thinks back over his life.\n      He thinks about where he failed, and wonders if he could have been more\n      loving to Edith, if he could have been stronger, or if he could have\n      helped her more. Later, he believes that he is wrong to think of himself\n      as a failure. During an afternoon when he is alone, he sees various young\n      students passing by on their way to class outside his window, and he dies,\n      dropping his copy of the one book that he published years earlier as a\n      young professor.\n    </n-drawer-content>\n  </n-drawer>\n</template>\n"
  },
  {
    "path": "src/drawer/demos/enUS/slot.demo.vue",
    "content": "<markdown>\n# Custom header and bottom content\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst active = ref(false)\nfunction activate() {\n  active.value = true\n}\n</script>\n\n<template>\n  <n-button-group>\n    <n-button @click=\"activate\">\n      Open\n    </n-button>\n  </n-button-group>\n  <n-drawer v-model:show=\"active\" :width=\"502\">\n    <n-drawer-content>\n      <template #header>\n        Header\n      </template>\n      <template #footer>\n        <n-button>Footer</n-button>\n      </template>\n    </n-drawer-content>\n  </n-drawer>\n</template>\n"
  },
  {
    "path": "src/drawer/demos/enUS/target.demo.vue",
    "content": "<markdown>\n# Customize display area\n\nYou can customize display area by `to` prop. Remember to set `:trap-focus=\"false\"` and `:block-scroll=\"false\"`, otherwise content outside drawer won't be focusable and body won't be scrollable.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { DrawerPlacement } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst active = ref(false)\nconst placement = ref<DrawerPlacement>('right')\nfunction activate(place: DrawerPlacement) {\n  active.value = true\n  placement.value = place\n}\n</script>\n\n<template>\n  <n-button-group>\n    <n-button @click=\"activate('top')\">\n      Top\n    </n-button>\n    <n-button @click=\"activate('right')\">\n      Right\n    </n-button>\n    <n-button @click=\"activate('bottom')\">\n      Bottom\n    </n-button>\n    <n-button @click=\"activate('left')\">\n      Left\n    </n-button>\n  </n-button-group>\n  <div\n    id=\"drawer-target\"\n    style=\"\n      position: relative;\n      width: 100%;\n      height: 300px;\n      border: 1px solid rgba(128, 128, 128, 0.2);\n      margin-top: 10px;\n      display: flex;\n      align-items: center;\n      justify-content: center;\n      overflow: hidden;\n    \"\n  >\n    Target Area\n  </div>\n  <n-drawer\n    v-model:show=\"active\"\n    :width=\"200\"\n    :height=\"200\"\n    :placement=\"placement\"\n    :trap-focus=\"false\"\n    to=\"#drawer-target\"\n  >\n    <n-drawer-content title=\"Stoner\">\n      Stoner is a 1965 novel by the American writer John Williams.\n    </n-drawer-content>\n  </n-drawer>\n</template>\n"
  },
  {
    "path": "src/drawer/demos/zhCN/a11y-debug.demo.vue",
    "content": "<markdown>\n# A11y debug\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst active = ref(false)\n\nfunction handleClick() {\n  active.value = !active.value\n}\n</script>\n\n<template>\n  <n-button @click=\"handleClick\">\n    Trigger\n  </n-button>\n  <n-drawer v-model:show=\"active\" :width=\"502\">\n    <n-input />\n    <n-input />\n    <n-input />\n  </n-drawer>\n</template>\n"
  },
  {
    "path": "src/drawer/demos/zhCN/basic.demo.vue",
    "content": "<markdown>\n# 基础用法\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { DrawerPlacement } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst active = ref(false)\nconst placement = ref<DrawerPlacement>('right')\nfunction activate(place: DrawerPlacement) {\n  active.value = true\n  placement.value = place\n}\n</script>\n\n<template>\n  <n-button-group>\n    <n-button @click=\"activate('top')\">\n      上\n    </n-button>\n    <n-button @click=\"activate('right')\">\n      右\n    </n-button>\n    <n-button @click=\"activate('bottom')\">\n      下\n    </n-button>\n    <n-button @click=\"activate('left')\">\n      左\n    </n-button>\n  </n-button-group>\n  <n-drawer v-model:show=\"active\" :width=\"502\" :placement=\"placement\">\n    <n-drawer-content title=\"斯通纳\">\n      《斯通纳》是美国作家约翰·威廉姆斯在 1965 年出版的小说。\n    </n-drawer-content>\n  </n-drawer>\n</template>\n"
  },
  {
    "path": "src/drawer/demos/zhCN/closable.demo.vue",
    "content": "<markdown>\n# 可关闭\n\n在 `n-drawer-content` 设定 `closable`。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst show = ref(false)\n</script>\n\n<template>\n  <n-button @click=\"show = true\">\n    打开\n  </n-button>\n  <n-drawer v-model:show=\"show\" :width=\"502\">\n    <n-drawer-content title=\"斯通纳\" closable>\n      《斯通纳》是美国作家约翰·威廉姆斯在 1965 年出版的小说。\n    </n-drawer-content>\n  </n-drawer>\n</template>\n"
  },
  {
    "path": "src/drawer/demos/zhCN/custom-style-debug.demo.vue",
    "content": "<markdown>\n# Style Debug\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { DrawerPlacement } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst active = ref(false)\nconst placement = ref<DrawerPlacement>('right')\n\nfunction activate(place: DrawerPlacement) {\n  active.value = true\n  placement.value = place\n}\n</script>\n\n<template>\n  <n-button-group>\n    <n-button @click=\"activate('top')\">\n      上\n    </n-button>\n    <n-button @click=\"activate('right')\">\n      右\n    </n-button>\n    <n-button @click=\"activate('bottom')\">\n      下\n    </n-button>\n    <n-button @click=\"activate('left')\">\n      左\n    </n-button>\n  </n-button-group>\n  <n-drawer\n    v-model:show=\"active\"\n    :placement=\"placement\"\n    style=\"border: 2px solid red\"\n    content-style=\"border: 2px solid green;\"\n  >\n    <n-drawer-content title=\"斯通纳\">\n      《斯通纳》是美国作家约翰·威廉姆斯在 1965 年出版的小说。\n    </n-drawer-content>\n  </n-drawer>\n</template>\n"
  },
  {
    "path": "src/drawer/demos/zhCN/dark-1-debug.demo.vue",
    "content": "<markdown>\n# Dark Debug 1\n</markdown>\n\n<script lang=\"ts\">\nimport type { FormInst, FormProps, FormRules } from 'naive-ui'\nimport { useMessage } from 'naive-ui'\nimport { defineComponent } from 'vue'\n\nexport default defineComponent({\n  setup() {\n    return {\n      message: useMessage()\n    }\n  },\n  data() {\n    return {\n      modalActive: false,\n      size: 'medium' as FormProps['size'],\n      model: {\n        inputValue: null,\n        textareaValue: null,\n        selectValue: null,\n        multipleSelectValue: null,\n        datetimeValue: null,\n        nestedValue: {\n          path1: null,\n          path2: null\n        },\n        switchValue: false,\n        checkboxGroupValue: null,\n        radioGroupValue: null,\n        radioButtonGroupValue: null,\n        inputNumberValue: null,\n        timePickerValue: null,\n        sliderValue: 0,\n        transferValue: null\n      },\n      generalOptions: ['groode', 'veli good', 'emazing', 'lidiculous'].map(\n        v => ({\n          label: v,\n          value: v\n        })\n      ),\n      cascaderOptions: [\n        {\n          label: 'groode',\n          value: 'groode',\n          children: [\n            {\n              label: 'veli good',\n              value: 'veli good'\n            }\n          ]\n        }\n      ],\n      rules: {\n        inputValue: {\n          required: true,\n          trigger: ['blur', 'input'],\n          message: '请输入 inputValue'\n        },\n        textareaValue: {\n          required: true,\n          trigger: ['blur', 'input'],\n          message: '请输入 textareaValue'\n        },\n        selectValue: {\n          required: true,\n          trigger: ['blur', 'change'],\n          message: '请选择 selectValue'\n        },\n        multipleSelectValue: {\n          type: 'array',\n          required: true,\n          trigger: ['blur', 'change'],\n          message: '请选择 multipleSelectValue'\n        },\n        datetimeValue: {\n          type: 'number',\n          required: true,\n          trigger: ['blur', 'change'],\n          message: '请输入 datetimeValue'\n        },\n        nestedValue: {\n          path1: {\n            required: true,\n            trigger: ['blur', 'input'],\n            message: '请输入 nestedValue.path1'\n          },\n          path2: {\n            required: true,\n            trigger: ['blur', 'change'],\n            message: '请输入 nestedValue.path2'\n          }\n        },\n        checkboxGroupValue: {\n          type: 'array',\n          required: true,\n          trigger: 'change',\n          message: '请选择 checkboxGroupValue'\n        },\n        radioGroupValue: {\n          required: true,\n          trigger: 'change',\n          message: '请选择 radioGroupValue'\n        },\n        radioButtonGroupValue: {\n          required: true,\n          trigger: 'change',\n          message: '请选择 radioButtonGroupValue'\n        },\n        inputNumberValue: {\n          type: 'number',\n          required: true,\n          trigger: ['blur', 'change'],\n          message: '请输入 inputNumberValue'\n        },\n        timePickerValue: {\n          type: 'number',\n          required: true,\n          trigger: ['blur', 'change'],\n          message: '请输入 timePickerValue'\n        },\n        sliderValue: 0,\n        transferValue: {\n          type: 'array',\n          required: true,\n          trigger: 'change',\n          message: '请输入 transferValue'\n        }\n      } as FormRules\n    }\n  },\n  methods: {\n    handleValidateButtonClick(e: MouseEvent) {\n      e.preventDefault()\n      ;(this.$refs.form as FormInst).validate((errors) => {\n        if (!errors) {\n          this.message.success('验证成功')\n        }\n        else {\n          console.log(errors)\n          this.message.error('验证失败')\n        }\n      })\n    }\n  }\n})\n</script>\n\n<template>\n  <n-button @click=\"modalActive = !modalActive\">\n    Toggle\n  </n-button>\n  <n-drawer v-model:show=\"modalActive\" width=\"800\">\n    <n-drawer-content :native-scrollbar=\"false\">\n      <template #header>\n        Header\n      </template>\n      <template #footer>\n        Footer\n      </template>\n      <n-radio-group\n        v-model:value=\"size\"\n        name=\"top-size\"\n        style=\"margin-bottom: 12px\"\n      >\n        <n-radio-button value=\"small\">\n          小\n        </n-radio-button>\n        <n-radio-button value=\"medium\">\n          中\n        </n-radio-button>\n        <n-radio-button value=\"large\">\n          大\n        </n-radio-button>\n      </n-radio-group>\n      <n-form\n        ref=\"form\"\n        :model=\"model\"\n        :rules=\"rules\"\n        :size=\"size\"\n        label-placement=\"top\"\n      >\n        <n-row :gutter=\"24\">\n          <n-form-item-col :span=\"12\" label=\"Input\" path=\"inputValue\">\n            <n-input v-model:value=\"model.inputValue\" placeholder=\"Input\" />\n          </n-form-item-col>\n          <n-form-item-col :span=\"12\" label=\"Textarea\" path=\"textareaValue\">\n            <n-input\n              v-model:value=\"model.textareaValue\"\n              placeholder=\"Textarea\"\n              type=\"textarea\"\n              :autosize=\"{\n                minRows: 3,\n                maxRows: 5,\n              }\"\n            />\n          </n-form-item-col>\n        </n-row>\n        <n-row :gutter=\"24\">\n          <n-form-item-col :span=\"12\" label=\"Select\" path=\"selectValue\">\n            <n-select\n              v-model:value=\"model.selectValue\"\n              placeholder=\"Select\"\n              :options=\"generalOptions\"\n            />\n          </n-form-item-col>\n          <n-form-item-col\n            :span=\"12\"\n            label=\"Multiple Select\"\n            path=\"multipleSelectValue\"\n          >\n            <n-select\n              v-model:value=\"model.multipleSelectValue\"\n              placeholder=\"Select\"\n              :options=\"generalOptions\"\n              multiple\n            />\n          </n-form-item-col>\n        </n-row>\n        <n-row :gutter=\"24\">\n          <n-form-item-col :span=\"12\" label=\"Datetime\" path=\"datetimeValue\">\n            <n-date-picker\n              v-model:value=\"model.datetimeValue\"\n              type=\"datetime\"\n            />\n          </n-form-item-col>\n          <n-form-item-col :span=\"12\" label=\"Switch\" path=\"switchValue\">\n            <n-switch v-model:value=\"model.switchValue\" />\n          </n-form-item-col>\n        </n-row>\n        <n-row :gutter=\"24\">\n          <n-form-item-col\n            :span=\"12\"\n            label=\"Checkbox Group\"\n            path=\"checkboxGroupValue\"\n          >\n            <n-checkbox-group v-model:value=\"model.checkboxGroupValue\">\n              <n-checkbox value=\"Option 1\">\n                Option 1\n              </n-checkbox>\n              <n-checkbox value=\"Option 2\">\n                Option 2\n              </n-checkbox>\n              <n-checkbox value=\"Option 3\">\n                Option 3\n              </n-checkbox>\n            </n-checkbox-group>\n          </n-form-item-col>\n          <n-form-item-col\n            :span=\"12\"\n            label=\"Radio Group\"\n            path=\"radioGroupValue\"\n          >\n            <n-radio-group\n              v-model:value=\"model.radioGroupValue\"\n              name=\"radiogroup1\"\n            >\n              <n-radio value=\"Radio 1\">\n                Radio 1\n              </n-radio>\n              <n-radio value=\"Radio 2\">\n                Radio 2\n              </n-radio>\n              <n-radio value=\"Radio 3\">\n                Radio 3\n              </n-radio>\n            </n-radio-group>\n          </n-form-item-col>\n        </n-row>\n        <n-row :gutter=\"24\">\n          <n-form-item-col\n            :span=\"12\"\n            label=\"Radio Button Group\"\n            path=\"radioGroupValue\"\n          >\n            <n-radio-group\n              v-model:value=\"model.radioGroupValue\"\n              name=\"radiogroup2\"\n            >\n              <n-radio-button value=\"Radio 1\">\n                Radio 1\n              </n-radio-button>\n              <n-radio-button value=\"Radio 2\">\n                Radio 2\n              </n-radio-button>\n              <n-radio-button value=\"Radio 3\">\n                Radio 3\n              </n-radio-button>\n            </n-radio-group>\n          </n-form-item-col>\n          <n-form-item-col\n            :span=\"12\"\n            label=\"Input Number\"\n            path=\"inputNumberValue\"\n          >\n            <n-input-number v-model:value=\"model.inputNumberValue\" />\n          </n-form-item-col>\n        </n-row>\n        <n-row :gutter=\"24\">\n          <n-form-item-col\n            :span=\"12\"\n            label=\"Time Picker\"\n            path=\"timePickerValue\"\n          >\n            <n-time-picker v-model:value=\"model.timePickerValue\" />\n          </n-form-item-col>\n          <n-form-item-col :span=\"12\" label=\"Slider\" path=\"sliderValue\">\n            <n-slider v-model:value=\"model.sliderValue\" :step=\"5\" />\n          </n-form-item-col>\n        </n-row>\n        <n-row :gutter=\"24\">\n          <n-form-item-col :span=\"14\" label=\"Transfer\" path=\"transferValue\">\n            <n-transfer\n              v-model:value=\"model.transferValue\"\n              style=\"width: 100%\"\n              :options=\"generalOptions\"\n            />\n          </n-form-item-col>\n          <n-form-item-col\n            :span=\"5\"\n            label=\"Nested Path\"\n            path=\"nestedValue.path1\"\n          >\n            <n-cascader\n              v-model:value=\"model.nestedValue.path1\"\n              placeholder=\"Nested Path 1\"\n              :options=\"cascaderOptions\"\n            />\n          </n-form-item-col>\n          <n-form-item-col :span=\"5\" path=\"nestedValue.path2\">\n            <n-select\n              v-model:value=\"model.nestedValue.path2\"\n              placeholder=\"Nested Path 2\"\n              :options=\"generalOptions\"\n            />\n          </n-form-item-col>\n        </n-row>\n        <n-row>\n          <n-col :span=\"24\">\n            <div style=\"display: flex; justify-content: flex-end\">\n              <n-button round type=\"primary\" @click=\"handleValidateButtonClick\">\n                验证\n              </n-button>\n            </div>\n          </n-col>\n        </n-row>\n      </n-form>\n    </n-drawer-content>\n  </n-drawer>\n</template>\n"
  },
  {
    "path": "src/drawer/demos/zhCN/dark-2-debug.demo.vue",
    "content": "<markdown>\n# Dark Debug 2\n</markdown>\n\n<script lang=\"ts\">\nimport { defineComponent } from 'vue'\n\nexport default defineComponent({\n  data() {\n    return {\n      modalActive: false\n    }\n  }\n})\n</script>\n\n<template>\n  <n-button @click=\"modalActive = !modalActive\">\n    Toggle\n  </n-button>\n  <n-drawer v-model:show=\"modalActive\" width=\"800\">\n    <n-table :bordered=\"false\" :single-line=\"false\">\n      <thead>\n        <tr>\n          <th>Abandon</th>\n          <th>Abnormal</th>\n          <th>Abolish</th>\n          <th>...</th>\n          <th>It's hard to learn words</th>\n        </tr>\n      </thead>\n      <tbody>\n        <tr>\n          <td>放弃</td>\n          <td>反常的</td>\n          <td>彻底废除</td>\n          <td>...</td>\n          <td>Damn it! I can't remember those words.</td>\n        </tr>\n        <tr>\n          <td>...</td>\n          <td>...</td>\n          <td>...</td>\n          <td>...</td>\n          <td>...</td>\n        </tr>\n      </tbody>\n    </n-table>\n    <n-list>\n      <template #header>\n        hhh\n      </template>\n      <template #footer>\n        fff\n      </template>\n      <n-list-item>\n        <template #prefix>\n          <n-button>Prefix</n-button>\n        </template>\n        <template #suffix>\n          <n-button>Suffix</n-button>\n        </template>\n        <n-thing title=\"Thing\" title-extra=\"extra\" description=\"description\">\n          Biu<br>\n          Biu<br>\n          Biu<br>\n        </n-thing>\n      </n-list-item>\n      <n-list-item>\n        <n-thing title=\"Thing\" title-extra=\"extra\" description=\"description\">\n          Biu<br>\n          Biu<br>\n          Biu<br>\n        </n-thing>\n        <template #suffix>\n          <n-button>Suffix</n-button>\n        </template>\n      </n-list-item>\n    </n-list>\n    <n-list bordered>\n      <template #header>\n        hhh\n      </template>\n      <template #footer>\n        fff\n      </template>\n      <n-list-item>\n        <template #prefix>\n          <n-button>Prefix</n-button>\n        </template>\n        <template #suffix>\n          <n-button>Suffix</n-button>\n        </template>\n        <n-thing title=\"Thing\" title-extra=\"extra\" description=\"description\">\n          Biu<br>\n          Biu<br>\n          Biu<br>\n        </n-thing>\n      </n-list-item>\n      <n-list-item>\n        <n-thing title=\"Thing\" title-extra=\"extra\" description=\"description\">\n          Biu<br>\n          Biu<br>\n          Biu<br>\n        </n-thing>\n        <template #suffix>\n          <n-button>Suffix</n-button>\n        </template>\n      </n-list-item>\n    </n-list>\n    <n-descriptions bordered>\n      <n-descriptions-item>\n        <template #label>\n          Breakfast\n        </template>\n        Apple\n      </n-descriptions-item>\n      <n-descriptions-item label=\"Lunch\">\n        Apple\n      </n-descriptions-item>\n      <n-descriptions-item label=\"Supper\">\n        Apple\n      </n-descriptions-item>\n      <n-descriptions-item label=\"Why Long\">\n        Why <br>\n        Long <br>\n        Long <br>\n        Long <br>\n        Long <br>\n        Long\n      </n-descriptions-item>\n      <n-descriptions-item label=\"Why Long\">\n        Why <br>\n        Long <br>\n        Long <br>\n        Long <br>\n        Long <br>\n        Long\n      </n-descriptions-item>\n      <n-descriptions-item label=\"Why Long\">\n        Why <br>\n        Long <br>\n        Long <br>\n        Long <br>\n        Long <br>\n        Long\n      </n-descriptions-item>\n    </n-descriptions>\n    <n-descriptions label-placement=\"left\" bordered>\n      <n-descriptions-item>\n        <template #label>\n          Breakfast\n        </template>\n        Apple\n      </n-descriptions-item>\n      <n-descriptions-item label=\"Lunch\">\n        Apple\n      </n-descriptions-item>\n      <n-descriptions-item label=\"Supper\">\n        Apple\n      </n-descriptions-item>\n      <n-descriptions-item label=\"Why Long\">\n        Why <br>\n        Long <br>\n        Long <br>\n        Long <br>\n        Long <br>\n        Long\n      </n-descriptions-item>\n      <n-descriptions-item label=\"Why Long\">\n        Why <br>\n        Long <br>\n        Long <br>\n        Long <br>\n        Long <br>\n        Long\n      </n-descriptions-item>\n      <n-descriptions-item label=\"Why Long\">\n        Why <br>\n        Long <br>\n        Long <br>\n        Long <br>\n        Long <br>\n        Long\n      </n-descriptions-item>\n    </n-descriptions>\n    <n-descriptions>\n      <n-descriptions-item>\n        <template #label>\n          Breakfast\n        </template>\n        Apple\n      </n-descriptions-item>\n      <n-descriptions-item label=\"Lunch\">\n        Apple\n      </n-descriptions-item>\n      <n-descriptions-item label=\"Supper\">\n        Apple\n      </n-descriptions-item>\n      <n-descriptions-item label=\"Why Long\">\n        Why <br>\n        Long <br>\n        Long <br>\n        Long <br>\n        Long <br>\n        Long\n      </n-descriptions-item>\n      <n-descriptions-item label=\"Why Long\">\n        Why <br>\n        Long <br>\n        Long <br>\n        Long <br>\n        Long <br>\n        Long\n      </n-descriptions-item>\n      <n-descriptions-item label=\"Why Long\">\n        Why <br>\n        Long <br>\n        Long <br>\n        Long <br>\n        Long <br>\n        Long\n      </n-descriptions-item>\n    </n-descriptions>\n    <n-descriptions label-placement=\"left\">\n      <n-descriptions-item>\n        <template #label>\n          Breakfast\n        </template>\n        Apple\n      </n-descriptions-item>\n      <n-descriptions-item label=\"Lunch\">\n        Apple\n      </n-descriptions-item>\n      <n-descriptions-item label=\"Supper\">\n        Apple\n      </n-descriptions-item>\n      <n-descriptions-item label=\"Why Long\">\n        Why <br>\n        Long <br>\n        Long <br>\n        Long <br>\n        Long <br>\n        Long\n      </n-descriptions-item>\n      <n-descriptions-item label=\"Why Long\">\n        Why <br>\n        Long <br>\n        Long <br>\n        Long <br>\n        Long <br>\n        Long\n      </n-descriptions-item>\n      <n-descriptions-item label=\"Why Long\">\n        Why <br>\n        Long <br>\n        Long <br>\n        Long <br>\n        Long <br>\n        Long\n      </n-descriptions-item>\n    </n-descriptions>\n  </n-drawer>\n</template>\n"
  },
  {
    "path": "src/drawer/demos/zhCN/dark-3-debug.demo.vue",
    "content": "<markdown>\n# Dark Debug 3\n</markdown>\n\n<script lang=\"ts\">\nimport type { DataTableColumns } from 'naive-ui'\nimport { defineComponent, h } from 'vue'\n\nconst columns: DataTableColumns = [\n  {\n    title: 'Name',\n    key: 'name',\n    width: 200,\n    fixed: 'left',\n    filter: 'default',\n    filterOptions: [\n      {\n        label: 'Edward King 0',\n        value: 'Edward King 0'\n      },\n      {\n        label: 'Edward King 1',\n        value: 'Edward King 1'\n      },\n      {\n        label: 'Edward King 2',\n        value: 'Edward King 2'\n      },\n      {\n        label: 'Edward King 3',\n        value: 'Edward King 3'\n      }\n    ]\n  },\n  {\n    title: 'Age',\n    key: 'age',\n    width: 100\n  },\n  {\n    title: 'Row',\n    key: 'row',\n    render(row, index) {\n      return h('span', ['row ', index])\n    }\n  },\n  {\n    title: 'Row1',\n    key: 'row1',\n    render(row, index) {\n      return h('span', ['row ', index])\n    }\n  },\n  {\n    title: 'Row2',\n    key: 'row2',\n    render(row, index) {\n      return h('span', ['row ', index])\n    }\n  },\n  {\n    title: 'Address',\n    key: 'address',\n    width: 200,\n    fixed: 'right'\n  }\n]\n\nconst data = Array.from({ length: 46 }).map((_, index) => ({\n  key: index,\n  name: `Edward King ${index % 4}`,\n  age: 32 + (index % 3),\n  address: `London, Park Lane no. ${index}`\n}))\n\nexport default defineComponent({\n  data() {\n    return {\n      modalActive: false,\n      data,\n      columns\n    }\n  },\n  computed: {\n    pagination() {\n      return { pageSize: 10 }\n    }\n  }\n})\n</script>\n\n<template>\n  <n-button @click=\"modalActive = !modalActive\">\n    Toggle\n  </n-button>\n  <n-drawer v-model:show=\"modalActive\" width=\"800\">\n    <n-data-table\n      :columns=\"columns\"\n      :data=\"data\"\n      :pagination=\"pagination\"\n      :max-height=\"250\"\n      :scroll-x=\"1800\"\n    />\n  </n-drawer>\n</template>\n"
  },
  {
    "path": "src/drawer/demos/zhCN/dark-4-debug.demo.vue",
    "content": "<markdown>\n# Dark Debug 4\n</markdown>\n\n<script lang=\"ts\">\nimport { defineComponent } from 'vue'\n\nexport default defineComponent({\n  data() {\n    return {\n      modalActive: false\n    }\n  }\n})\n</script>\n\n<template>\n  <n-button @click=\"modalActive = !modalActive\">\n    Toggle\n  </n-button>\n  <n-drawer v-model:show=\"modalActive\" width=\"800\">\n    <n-popover trigger=\"click\">\n      <template #trigger>\n        <n-button style=\"margin: 0\">\n          悬浮\n        </n-button>\n      </template>\n      <span>或许不想知道你的花园长得咋样</span>\n    </n-popover>\n  </n-drawer>\n</template>\n"
  },
  {
    "path": "src/drawer/demos/zhCN/index.demo-entry.md",
    "content": "# 抽屉 Drawer\n\n我感觉和 Modal 功能差不太多，位置有点差别。\n\n<n-alert title=\"提示\" type=\"warning\" :bordered=\"false\">\n  如果你需要使用 <n-text code>n-drawer-content</n-text>，<n-text code>n-drawer</n-text> 的 <n-text code>native-scrollbar</n-text> 需要保持为 <n-text code>true</n-text>。\n</n-alert>\n\n## 演示\n\n```demo\nbasic.vue\nmultiple.vue\nclosable.vue\ntarget.vue\nslot.vue\nscroll.vue\na11y-debug.vue\ncustom-style-debug.vue\ndark-1-debug.vue\ndark-2-debug.vue\ndark-3-debug.vue\ndark-4-debug.vue\nresizable.vue\nrtl-debug.vue\n```\n\n## API\n\n### Drawer Props\n\n| 名称 | 类型 | 默认值 | 说明 | 版本 |\n| --- | --- | --- | --- | --- |\n| auto-focus | `boolean` | `true` | 是否自动聚焦 Drawer 第一个可聚焦的元素 | 2.24.2 |\n| block-scroll | `boolean` | `true` | 是否在打开时禁用 body 滚动 | 2.28.3 |\n| close-on-esc | `boolean` | `true` | 是否在摁下 Esc 键的时候关闭 Drawer | 2.24.2 |\n| content-class | `string` | `undefined` | 抽屉可滚动内容节点的类名 | 2.37.0 |\n| content-style | `string \\| Object` | `undefined` | 抽屉可滚动内容节点的样式 |  |\n| default-width | `number \\| string` | `251` | 抽屉的默认宽度，在位置是 `left` 和 `right` 时生效 | 2.31.0 |\n| default-height | `number \\| string` | `251` | 抽屉的默认高度，在位置是 `top` 和 `bottom` 时生效 | 2.31.0 |\n| display-directive | `'if' \\| 'show'` | `'if'` | `n-drawer` 在控制内容是否渲染时使用的指令，`'if'` 对应 `v-if`，`'show'` 对应 `v-show` |  |\n| height | `number \\| string` | `undefined` | 抽屉的高度，在位置是 `top` 和 `bottom` 时生效 |  |\n| mask-closable | `boolean` | `true` | 点击遮罩时是否发出 `update:show` 事件 |  |\n| max-width | `number` | `undefined` | 拖动时的最大宽度 | 2.35.0 |\n| max-height | `number` | `undefined` | 拖动时的最大高度 | 2.35.0 |\n| min-width | `number` | `undefined` | 拖动时的最小宽度 | 2.35.0 |\n| min-height | `number` | `undefined` | 拖动时的最小高度 | 2.35.0 |\n| native-scrollbar | `boolean` | `true` | 是否使用原生滚动 |  |\n| placement | `'top' \\| 'right' \\| 'bottom' \\| 'left'` | `'right'` | 抽屉展示的位置 |  |\n| resizable | `boolean` | `false` | 抽屉是否可以调整宽度、高度 | 2.31.0 |\n| scrollbar-props | `ScrollbarProps` | `undefined` | 属性参考 [Scrollbar props](scrollbar#Scrollbar-Props) |  |\n| show | `boolean` | `false` | 是否展示抽屉 |  |\n| show-mask | `boolean \\| 'transparent'` | `true` | 是否显示遮罩，如果设为 `'transparent'` 会展示透明遮罩，如果设为 `false` 会禁用 `trap-focus` | 2.28.3 |\n| to | `string \\| HTMLElement` | `'body'` | 抽屉出现的区域 |  |\n| trap-focus | `boolean` | `true` | 是否将焦点锁定在 Drawer 内部 | 2.24.2 |\n| width | `number \\| string` | `undefined` | 抽屉的宽度，在位置是 `left` 和 `right` 时生效 |  |\n| z-index | `number` | `undefined` | 抽屉的 z-index | 2.24.0 |\n| on-after-enter | `() => void` | `undefined` | Drawer 出现后的回调 | 2.28.0 |\n| on-after-leave | `() => void` | `undefined` | Drawer 关闭后的回调 | 2.28.0 |\n| on-esc | `() => void` | `undefined` | 焦点在 Drawer 内部时按下 Esc 键的回调 | 2.24.2 |\n| on-mask-click | `(e: MouseEvent) => void` | `undefined` | 点击遮罩的回调 |  |\n| on-update:height | `(height: number) => void` | `undefined` | 抽屉高度改变时执行的回调函数 | 2.31.0 |\n| on-update:show | `(show: boolean) => void` | `undefined` | 抽屉显示状态改变时执行的回调函数 |  |\n| on-update:width | `(width: number) => void` | `undefined` | 抽屉宽度改变时执行的回调函数 | 2.31.0 |\n\n### DrawerContent Props\n\n| 名称 | 类型 | 默认值 | 说明 | 版本 |\n| --- | --- | --- | --- | --- |\n| body-class | `string` | `undefined` | 主体 body 的类名 | 2.37.0 |\n| body-style | `string \\| Object` | `undefined` | 主体 body 的样式 |  |\n| body-content-class | `string` | `undefined` | 主体可滚动内容节点的类名 | 2.37.0 |\n| body-content-style | `string \\| Object` | `undefined` | 主体可滚动内容节点的样式 |  |\n| closable | `boolean` | `false` | 是否可关闭 |  |\n| footer-class | `string` | `undefined` | 主体 footer 的类名 | 2.37.0 |\n| footer-style | `string \\| Object` | `undefined` | 主体 footer 的样式 |  |\n| header-class | `string` | `undefined` | 主体 header 的类名 | 2.37.0 |\n| header-style | `string \\| Object` | `undefined` | 主体 header 的样式 |  |\n| native-scrollbar | `boolean` | `true` | 主体部分是否使用原生滚动条 |  |\n| scrollbar-props | `ScrollbarProps` | `undefined` | 属性参考 [Scrollbar props](scrollbar#Scrollbar-Props) |  |\n| title | `string` | `undefined` | 主体的标题 |  |\n\n### Drawer Slots\n\n| 名称    | 参数 | 说明       |\n| ------- | ---- | ---------- |\n| default | `()` | 抽屉的内容 |\n\n### DrawerContent Slots\n\n| 名称    | 参数 | 说明                   |\n| ------- | ---- | ---------------------- |\n| default | `()` | 抽屉主体的内容         |\n| footer  | `()` | 抽屉主体 footer 的内容 |\n| header  | `()` | 抽屉主体 header 的内容 |\n"
  },
  {
    "path": "src/drawer/demos/zhCN/multiple.demo.vue",
    "content": "<markdown>\n# 多个抽屉\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst showOuter = ref(false)\nconst showInner = ref(false)\n\nfunction doShowOuter() {\n  showOuter.value = true\n}\n\nfunction doShowInner() {\n  showInner.value = true\n}\n</script>\n\n<template>\n  <n-button @click=\"doShowOuter\">\n    来一个！\n  </n-button>\n  <n-drawer v-model:show=\"showOuter\" :width=\"502\">\n    <n-drawer-content title=\"斯通纳\">\n      《斯通纳》是美国作家约翰·威廉姆斯在 1965 年出版的小说。\n      <template #footer>\n        <n-button @click=\"doShowInner\">\n          再来一个！\n        </n-button>\n      </template>\n    </n-drawer-content>\n    <n-drawer v-model:show=\"showInner\" :width=\"251\">\n      <n-drawer-content title=\"斯通纳\">\n        《斯通纳》是美国作家约翰·威廉姆斯在 1965 年出版的小说。\n      </n-drawer-content>\n    </n-drawer>\n  </n-drawer>\n</template>\n"
  },
  {
    "path": "src/drawer/demos/zhCN/resizable.demo.vue",
    "content": "<markdown>\n# 可调整宽高的抽屉\n\n记得使用 `resizable` 的时候配合 `default-width` 或者 `default-height`。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { DrawerPlacement } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst active = ref(false)\nconst placement = ref<DrawerPlacement>('right')\nfunction activate(place: DrawerPlacement) {\n  active.value = true\n  placement.value = place\n}\n</script>\n\n<template>\n  <n-button-group>\n    <n-button @click=\"activate('top')\">\n      上\n    </n-button>\n    <n-button @click=\"activate('right')\">\n      右\n    </n-button>\n    <n-button @click=\"activate('bottom')\">\n      下\n    </n-button>\n    <n-button @click=\"activate('left')\">\n      左\n    </n-button>\n  </n-button-group>\n  <n-drawer\n    v-model:show=\"active\"\n    :default-width=\"502\"\n    :placement=\"placement\"\n    resizable\n  >\n    <n-drawer-content title=\"斯通纳\">\n      《斯通纳》是美国作家约翰·威廉姆斯在 1965 年出版的小说。\n    </n-drawer-content>\n  </n-drawer>\n</template>\n"
  },
  {
    "path": "src/drawer/demos/zhCN/rtl-debug.demo.vue",
    "content": "<markdown>\n# Rtl Debug\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { unstableDrawerRtl } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst rtlEnabled = ref(false)\nconst rtlStyles = [unstableDrawerRtl]\nconst show = ref(false)\n</script>\n\n<template>\n  <n-space vertical>\n    <n-space><n-switch v-model:value=\"rtlEnabled\" />Rtl</n-space>\n    <n-config-provider :rtl=\"rtlEnabled ? rtlStyles : undefined\">\n      <n-button @click=\"show = true\">\n        Open\n      </n-button>\n      <n-drawer v-model:show=\"show\" :width=\"502\">\n        <n-drawer-content title=\"Stoner\" closable>\n          Stoner is a 1965 novel by the American writer John Williams.\n        </n-drawer-content>\n      </n-drawer>\n    </n-config-provider>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/drawer/demos/zhCN/scroll.demo.vue",
    "content": "<markdown>\n# 滚动内容\n\n这是一个滚动内容的演示。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst show = ref(false)\n</script>\n\n<template>\n  <n-button @click=\"show = !show\">\n    打开\n  </n-button>\n  <n-drawer v-model:show=\"show\" :width=\"480\">\n    <n-drawer-content title=\"Stoner\" :native-scrollbar=\"false\">\n      William Stoner is born on a small farm in 1891. One day his father\n      suggests he should attend the University of Missouri to study agriculture.\n      Stoner agrees but, while studying a compulsory literature course, he\n      quickly falls in love with literary studies. Without telling his parents,\n      Stoner quits the agriculture program and studies only the humanities. He\n      completes his MA in English and begins teaching. In graduate school, he is\n      friendly with fellow students Gordon Finch and Dave Masters. World War I\n      begins, and Gordon and Dave enlist. Despite pressure from Gordon, Stoner\n      decides to remain in school during the war. Masters is killed in France,\n      while Finch sees action and becomes an officer. At a faculty party, Stoner\n      meets and becomes infatuated with a young woman named Edith, who is\n      staying with an aunt for a few weeks. Stoner woos Edith, and she agrees to\n      marry him. Stoner's marriage to Edith is bad from the start. It gradually\n      becomes clear that Edith has profound emotional problems. Significantly,\n      she is bitter about having cancelled a trip to Europe with her aunt to\n      marry Stoner. After three years of marriage, Edith suddenly informs Stoner\n      that she wants a baby. She suddenly becomes passionate sexually, but this\n      period is brief. When their daughter Grace is born, Edith remains\n      bedridden for nearly a year, and Stoner largely cares for their child\n      alone. He grows close with his young daughter, who spends most of her time\n      with him in his study. Stoner gradually realizes that Edith is waging a\n      campaign to separate him from his daughter emotionally. For the most part,\n      Stoner accepts Edith's mistreatment. He begins to teach with more\n      enthusiasm, but still, year in and year out, his marriage with Edith\n      remains perpetually unsatisfactory and fraught. Grace becomes an unhappy,\n      secretive child who smiles and laughs often but is emotionally hollow. At\n      the University, Finch becomes the acting dean of the faculty. Stoner feels\n      compelled by his conscience to fail a student named Charles Walker. He is\n      a close protégé of a colleague, Professor Hollis Lomax, and like him is\n      physically disabled. The student is clearly dishonest and cannot fulfil\n      the requirements of Stoner's course but, despite this, the decision to\n      expel or retain Walker is put on hold. After his promotion to head of the\n      department, Lomax takes every opportunity to exact revenge upon Stoner\n      throughout the rest of his career. A collaboration between Stoner and a\n      younger instructor in the department, Katherine Driscoll, develops into a\n      romantic love affair. Ironically, after the affair begins, Stoner's\n      relationships with Edith and Grace also improve. At some point, Edith\n      finds out about the affair, but does not seem to mind it. When Lomax\n      learns about it, however, he begins to put pressure on Katherine, who also\n      teaches in the English department. Stoner and Driscoll agree it best to\n      end the affair so as not to derail the academic work they both feel called\n      to follow. Katherine quietly slips out of town, never to be seen by him\n      again. Eventually, Stoner, older now and hard of hearing, is beginning to\n      become a legendary figure in the English department despite Lomax's\n      opposition. He begins to spend more time at home, ignoring Edith's signs\n      of displeasure at his presence. Entering adulthood, Grace enrolls at the\n      University of Missouri. The following year, Grace announces she is\n      pregnant and marries the father of her child. Grace's husband enlists in\n      the army and dies before the baby is born. Grace goes to St. Louis with\n      the baby to live with her husband's parents. She visits Stoner and Edith\n      occasionally, and Stoner realizes that Grace has developed a drinking\n      problem. As Stoner's life is coming to an end, his daughter Grace comes to\n      visit him. Deeply unhappy and addicted to alcohol, Grace halfheartedly\n      tries to reconcile with Stoner, and he sees that his daughter, like her\n      mother, will never be happy. When Grace leaves, Stoner feels as though the\n      young child that he loved died long ago. Stoner thinks back over his life.\n      He thinks about where he failed, and wonders if he could have been more\n      loving to Edith, if he could have been stronger, or if he could have\n      helped her more. Later, he believes that he is wrong to think of himself\n      as a failure. During an afternoon when he is alone, he sees various young\n      students passing by on their way to class outside his window, and he dies,\n      dropping his copy of the one book that he published years earlier as a\n      young professor.\n    </n-drawer-content>\n  </n-drawer>\n</template>\n"
  },
  {
    "path": "src/drawer/demos/zhCN/slot.demo.vue",
    "content": "<markdown>\n# 自定义头部和底部内容\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst active = ref(false)\nfunction activate() {\n  active.value = true\n}\n</script>\n\n<template>\n  <n-button-group>\n    <n-button @click=\"activate\">\n      打开\n    </n-button>\n  </n-button-group>\n  <n-drawer v-model:show=\"active\" :width=\"502\">\n    <n-drawer-content>\n      <template #header>\n        Header\n      </template>\n      <template #footer>\n        <n-button>Footer</n-button>\n      </template>\n    </n-drawer-content>\n  </n-drawer>\n</template>\n"
  },
  {
    "path": "src/drawer/demos/zhCN/target.demo.vue",
    "content": "<markdown>\n# 显示在指定区域\n\n你可以通过设定 `to` 属性来自定义显示区域。记得要设定 `:trap-focus=\"false\"` 和 `:block-scroll=\"false\"`，否则 drawer 外的内容将无法被聚焦，body 也将无法滚动。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { DrawerPlacement } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst active = ref(false)\nconst placement = ref<DrawerPlacement>('right')\nfunction activate(place: DrawerPlacement) {\n  active.value = true\n  placement.value = place\n}\n</script>\n\n<template>\n  <n-button-group>\n    <n-button @click=\"activate('top')\">\n      上\n    </n-button>\n    <n-button @click=\"activate('right')\">\n      右\n    </n-button>\n    <n-button @click=\"activate('bottom')\">\n      下\n    </n-button>\n    <n-button @click=\"activate('left')\">\n      左\n    </n-button>\n  </n-button-group>\n  <div\n    id=\"drawer-target\"\n    style=\"\n      position: relative;\n      width: 100%;\n      height: 300px;\n      border: 1px solid rgba(128, 128, 128, 0.2);\n      margin-top: 10px;\n      display: flex;\n      align-items: center;\n      justify-content: center;\n      overflow: hidden;\n    \"\n  >\n    显示区域\n  </div>\n  <n-drawer\n    v-model:show=\"active\"\n    :width=\"200\"\n    :height=\"200\"\n    :placement=\"placement\"\n    :trap-focus=\"false\"\n    :block-scroll=\"false\"\n    to=\"#drawer-target\"\n  >\n    <n-drawer-content title=\"斯通纳\">\n      《斯通纳》是美国作家约翰·威廉姆斯在 1965 年出版的小说。\n    </n-drawer-content>\n  </n-drawer>\n</template>\n"
  },
  {
    "path": "src/drawer/index.ts",
    "content": "export { drawerProps, default as NDrawer } from './src/Drawer'\nexport type { DrawerProps } from './src/Drawer'\nexport type { Placement as DrawerPlacement } from './src/DrawerBodyWrapper'\nexport {\n  drawerContentProps,\n  default as NDrawerContent\n} from './src/DrawerContent'\nexport type {\n  DrawerContentProps,\n  DrawerContentSlots\n} from './src/DrawerContent'\n"
  },
  {
    "path": "src/drawer/src/Drawer.tsx",
    "content": "import type { CSSProperties, PropType } from 'vue'\nimport type { ScrollbarProps } from '../../_internal'\nimport type { ThemeProps } from '../../_mixins'\nimport type { ExtractPublicPropTypes, MaybeArray } from '../../_utils'\nimport type { DrawerTheme } from '../styles'\nimport type { Placement } from './DrawerBodyWrapper'\nimport { zindexable } from 'vdirs'\nimport { useIsMounted, useMergedState } from 'vooks'\nimport {\n  computed,\n  defineComponent,\n  h,\n  provide,\n  ref,\n  toRef,\n  Transition,\n  watchEffect,\n  withDirectives\n} from 'vue'\nimport { VLazyTeleport } from 'vueuc'\nimport { useConfig, useTheme, useThemeClass } from '../../_mixins'\nimport {\n  call,\n  eventEffectNotPerformed,\n  formatLength,\n  useIsComposing,\n  warnOnce\n} from '../../_utils'\nimport { drawerLight } from '../styles'\nimport NDrawerBodyWrapper from './DrawerBodyWrapper'\nimport { drawerInjectionKey } from './interface'\nimport style from './styles/index.cssr'\n\nexport const drawerProps = {\n  ...(useTheme.props as ThemeProps<DrawerTheme>),\n  show: Boolean,\n  width: [Number, String] as PropType<string | number>,\n  height: [Number, String] as PropType<string | number>,\n  placement: {\n    type: String as PropType<Placement>,\n    default: 'right'\n  },\n  maskClosable: {\n    type: Boolean,\n    default: true\n  },\n  showMask: {\n    type: [Boolean, String] as PropType<boolean | 'transparent'>,\n    default: true\n  },\n  to: [String, Object] as PropType<string | HTMLElement>,\n  displayDirective: {\n    type: String as PropType<'if' | 'show'>,\n    default: 'if'\n  },\n  nativeScrollbar: {\n    type: Boolean,\n    default: true\n  },\n  zIndex: Number,\n  onMaskClick: Function as PropType<(e: MouseEvent) => void>,\n  scrollbarProps: Object as PropType<ScrollbarProps>,\n  contentClass: String,\n  contentStyle: [Object, String] as PropType<string | CSSProperties>,\n  trapFocus: {\n    type: Boolean,\n    default: true\n  },\n  onEsc: Function as PropType<() => void>,\n  autoFocus: {\n    type: Boolean,\n    default: true\n  },\n  closeOnEsc: {\n    type: Boolean,\n    default: true\n  },\n  blockScroll: {\n    type: Boolean,\n    default: true\n  },\n  maxWidth: Number,\n  maxHeight: Number,\n  minWidth: Number,\n  minHeight: Number,\n  resizable: Boolean,\n  defaultWidth: {\n    type: [Number, String] as PropType<string | number>,\n    default: 251\n  },\n  defaultHeight: {\n    type: [Number, String] as PropType<string | number>,\n    default: 251\n  },\n  onUpdateWidth: [Function, Array] as PropType<\n    MaybeArray<(value: number) => void>\n  >,\n  onUpdateHeight: [Function, Array] as PropType<\n    MaybeArray<(value: number) => void>\n  >,\n  'onUpdate:width': [Function, Array] as PropType<\n    MaybeArray<(value: number) => void>\n  >,\n  'onUpdate:height': [Function, Array] as PropType<\n    MaybeArray<(value: number) => void>\n  >,\n  'onUpdate:show': [Function, Array] as PropType<\n    MaybeArray<(value: boolean) => void>\n  >,\n  onUpdateShow: [Function, Array] as PropType<\n    MaybeArray<(value: boolean) => void>\n  >,\n  onAfterEnter: Function as PropType<() => void>,\n  onAfterLeave: Function as PropType<() => void>,\n  /** @deprecated */\n  drawerStyle: [String, Object] as PropType<string | CSSProperties>,\n  drawerClass: String,\n  target: null,\n  onShow: Function as PropType<(value: boolean) => void>,\n  onHide: Function as PropType<(value: boolean) => void>\n} as const\n\nexport type DrawerProps = ExtractPublicPropTypes<typeof drawerProps>\n\nexport default defineComponent({\n  name: 'Drawer',\n  inheritAttrs: false,\n  props: drawerProps,\n  setup(props) {\n    if (__DEV__) {\n      watchEffect(() => {\n        if (props.drawerStyle !== undefined) {\n          warnOnce(\n            'drawer',\n            '`drawer-style` is deprecated, please use `style` instead.'\n          )\n        }\n        if (props.drawerClass !== undefined) {\n          warnOnce(\n            'drawer',\n            '`drawer-class` is deprecated, please use `class` instead.'\n          )\n        }\n        if (props.target !== undefined) {\n          warnOnce('drawer', '`target` is deprecated, please use `to` instead.')\n        }\n        if (props.onShow !== undefined) {\n          warnOnce(\n            'drawer',\n            '`on-show` is deprecated, please use `on-update:show` instead.'\n          )\n        }\n        if (props.onHide !== undefined) {\n          warnOnce(\n            'drawer',\n            '`on-hide` is deprecated, please use `on-update:show` instead.'\n          )\n        }\n      })\n    }\n    const { mergedClsPrefixRef, namespaceRef, inlineThemeDisabled }\n      = useConfig(props)\n    const isMountedRef = useIsMounted()\n    const themeRef = useTheme(\n      'Drawer',\n      '-drawer',\n      style,\n      drawerLight,\n      props,\n      mergedClsPrefixRef\n    )\n\n    const uncontrolledWidthRef = ref<string | number>(props.defaultWidth)\n    const uncontrolledHeightRef = ref<string | number>(props.defaultHeight)\n\n    const mergedWidthRef = useMergedState(\n      toRef(props, 'width'),\n      uncontrolledWidthRef\n    )\n    const mergedHeightRef = useMergedState(\n      toRef(props, 'height'),\n      uncontrolledHeightRef\n    )\n\n    const styleWidthRef = computed(() => {\n      const { placement } = props\n      if (placement === 'top' || placement === 'bottom')\n        return ''\n      return formatLength(mergedWidthRef.value)\n    })\n\n    const styleHeightRef = computed(() => {\n      const { placement } = props\n      if (placement === 'left' || placement === 'right')\n        return ''\n      return formatLength(mergedHeightRef.value)\n    })\n\n    const doUpdateWidth = (value: number): void => {\n      const { onUpdateWidth, 'onUpdate:width': _onUpdateWidth } = props\n      if (onUpdateWidth)\n        call(onUpdateWidth, value)\n      if (_onUpdateWidth)\n        call(_onUpdateWidth, value)\n      uncontrolledWidthRef.value = value\n    }\n    const doUpdateHeight = (value: number): void => {\n      const { onUpdateHeight, 'onUpdate:width': _onUpdateHeight } = props\n      if (onUpdateHeight)\n        call(onUpdateHeight, value)\n      if (_onUpdateHeight)\n        call(_onUpdateHeight, value)\n      uncontrolledHeightRef.value = value\n    }\n\n    const mergedBodyStyleRef = computed<Array<CSSProperties | string>>(() => {\n      return [\n        {\n          width: styleWidthRef.value,\n          height: styleHeightRef.value\n        },\n        props.drawerStyle || ''\n      ]\n    })\n\n    function handleMaskClick(e: MouseEvent): void {\n      const { onMaskClick, maskClosable } = props\n      if (maskClosable) {\n        doUpdateShow(false)\n      }\n      if (onMaskClick)\n        onMaskClick(e)\n    }\n\n    function handleOutsideClick(e: MouseEvent): void {\n      handleMaskClick(e)\n    }\n\n    const isComposingRef = useIsComposing()\n\n    function handleEsc(e: KeyboardEvent): void {\n      props.onEsc?.()\n      if (props.show && props.closeOnEsc && eventEffectNotPerformed(e)) {\n        if (!isComposingRef.value) {\n          doUpdateShow(false)\n        }\n      }\n    }\n    function doUpdateShow(show: boolean): void {\n      const { onHide, onUpdateShow, 'onUpdate:show': _onUpdateShow } = props\n      if (onUpdateShow)\n        call(onUpdateShow, show)\n      if (_onUpdateShow)\n        call(_onUpdateShow, show)\n      // deprecated\n      if (onHide && !show)\n        call(onHide, show)\n    }\n    provide(drawerInjectionKey, {\n      isMountedRef,\n      mergedThemeRef: themeRef,\n      mergedClsPrefixRef,\n      doUpdateShow,\n      doUpdateHeight,\n      doUpdateWidth\n    })\n    const cssVarsRef = computed(() => {\n      const {\n        common: { cubicBezierEaseInOut, cubicBezierEaseIn, cubicBezierEaseOut },\n        self: {\n          color,\n          textColor,\n          boxShadow,\n          lineHeight,\n          headerPadding,\n          footerPadding,\n          borderRadius,\n          bodyPadding,\n          titleFontSize,\n          titleTextColor,\n          titleFontWeight,\n          headerBorderBottom,\n          footerBorderTop,\n          closeIconColor,\n          closeIconColorHover,\n          closeIconColorPressed,\n          closeColorHover,\n          closeColorPressed,\n          closeIconSize,\n          closeSize,\n          closeBorderRadius,\n          resizableTriggerColorHover\n        }\n      } = themeRef.value\n      return {\n        '--n-line-height': lineHeight,\n        '--n-color': color,\n        '--n-border-radius': borderRadius,\n        '--n-text-color': textColor,\n        '--n-box-shadow': boxShadow,\n        '--n-bezier': cubicBezierEaseInOut,\n        '--n-bezier-out': cubicBezierEaseOut,\n        '--n-bezier-in': cubicBezierEaseIn,\n        '--n-header-padding': headerPadding,\n        '--n-body-padding': bodyPadding,\n        '--n-footer-padding': footerPadding,\n        '--n-title-text-color': titleTextColor,\n        '--n-title-font-size': titleFontSize,\n        '--n-title-font-weight': titleFontWeight,\n        '--n-header-border-bottom': headerBorderBottom,\n        '--n-footer-border-top': footerBorderTop,\n        '--n-close-icon-color': closeIconColor,\n        '--n-close-icon-color-hover': closeIconColorHover,\n        '--n-close-icon-color-pressed': closeIconColorPressed,\n        '--n-close-size': closeSize,\n        '--n-close-color-hover': closeColorHover,\n        '--n-close-color-pressed': closeColorPressed,\n        '--n-close-icon-size': closeIconSize,\n        '--n-close-border-radius': closeBorderRadius,\n        '--n-resize-trigger-color-hover': resizableTriggerColorHover\n      }\n    })\n    const themeClassHandle = inlineThemeDisabled\n      ? useThemeClass('drawer', undefined, cssVarsRef, props)\n      : undefined\n    return {\n      mergedClsPrefix: mergedClsPrefixRef,\n      namespace: namespaceRef,\n      mergedBodyStyle: mergedBodyStyleRef,\n      handleOutsideClick,\n      handleMaskClick,\n      handleEsc,\n      mergedTheme: themeRef,\n      cssVars: inlineThemeDisabled ? undefined : cssVarsRef,\n      themeClass: themeClassHandle?.themeClass,\n      onRender: themeClassHandle?.onRender,\n      isMounted: isMountedRef\n    }\n  },\n  render() {\n    const { mergedClsPrefix } = this\n    return (\n      <VLazyTeleport to={this.to} show={this.show}>\n        {{\n          default: () => {\n            this.onRender?.()\n            return withDirectives(\n              <div\n                class={[\n                  `${mergedClsPrefix}-drawer-container`,\n                  this.namespace,\n                  this.themeClass\n                ]}\n                style={this.cssVars as CSSProperties}\n                role=\"none\"\n              >\n                {this.showMask ? (\n                  <Transition name=\"fade-in-transition\" appear={this.isMounted}>\n                    {{\n                      default: () =>\n                        this.show ? (\n                          <div\n                            aria-hidden\n                            class={[\n                              `${mergedClsPrefix}-drawer-mask`,\n                              this.showMask === 'transparent'\n                              && `${mergedClsPrefix}-drawer-mask--invisible`\n                            ]}\n                            onClick={this.handleMaskClick}\n                          />\n                        ) : null\n                    }}\n                  </Transition>\n                ) : null}\n                <NDrawerBodyWrapper\n                  {...this.$attrs}\n                  class={[this.drawerClass, this.$attrs.class]}\n                  style={[this.mergedBodyStyle, this.$attrs.style]}\n                  blockScroll={this.blockScroll}\n                  contentStyle={this.contentStyle}\n                  contentClass={this.contentClass}\n                  placement={this.placement}\n                  scrollbarProps={this.scrollbarProps}\n                  show={this.show}\n                  displayDirective={this.displayDirective}\n                  nativeScrollbar={this.nativeScrollbar}\n                  onAfterEnter={this.onAfterEnter}\n                  onAfterLeave={this.onAfterLeave}\n                  trapFocus={this.trapFocus}\n                  autoFocus={this.autoFocus}\n                  resizable={this.resizable}\n                  maxHeight={this.maxHeight}\n                  minHeight={this.minHeight}\n                  maxWidth={this.maxWidth}\n                  minWidth={this.minWidth}\n                  showMask={this.showMask}\n                  onEsc={this.handleEsc}\n                  onClickoutside={this.handleOutsideClick}\n                >\n                  {this.$slots}\n                </NDrawerBodyWrapper>\n              </div>,\n              [[zindexable, { zIndex: this.zIndex, enabled: this.show }]]\n            )\n          }\n        }}\n      </VLazyTeleport>\n    )\n  }\n})\n"
  },
  {
    "path": "src/drawer/src/DrawerBodyWrapper.tsx",
    "content": "import type { CSSProperties, DirectiveArguments, PropType } from 'vue'\nimport type { ScrollbarProps } from '../../_internal'\nimport { clickoutside } from 'vdirs'\nimport {\n  computed,\n  defineComponent,\n  h,\n  inject,\n  mergeProps,\n  onBeforeUnmount,\n  provide,\n  ref,\n  Transition,\n  vShow,\n  watch,\n  watchEffect,\n  withDirectives\n} from 'vue'\nimport { VFocusTrap } from 'vueuc'\nimport { NScrollbar } from '../../_internal'\nimport { useConfig, useRtl } from '../../_mixins'\nimport { useLockHtmlScroll } from '../../_utils'\nimport { modalBodyInjectionKey } from '../../modal/src/interface'\nimport { popoverBodyInjectionKey } from '../../popover/src/interface'\nimport { drawerBodyInjectionKey, drawerInjectionKey } from './interface'\n\nexport type Placement = 'left' | 'right' | 'top' | 'bottom'\n\nexport default defineComponent({\n  name: 'NDrawerContent',\n  inheritAttrs: false,\n  props: {\n    blockScroll: Boolean,\n    show: {\n      type: Boolean as PropType<boolean | undefined>,\n      default: undefined\n    },\n    displayDirective: {\n      type: String as PropType<'if' | 'show'>,\n      required: true\n    },\n    placement: {\n      type: String as PropType<Placement>,\n      required: true\n    },\n    contentClass: String,\n    contentStyle: [Object, String] as PropType<string | CSSProperties>,\n    nativeScrollbar: {\n      type: Boolean,\n      required: true\n    },\n    scrollbarProps: Object as PropType<ScrollbarProps>,\n    trapFocus: {\n      type: Boolean,\n      default: true\n    },\n    autoFocus: {\n      type: Boolean,\n      default: true\n    },\n    showMask: {\n      type: [Boolean, String] as PropType<boolean | 'transparent'>,\n      required: true\n    },\n    maxWidth: Number,\n    maxHeight: Number,\n    minWidth: Number,\n    minHeight: Number,\n    resizable: Boolean,\n    onClickoutside: Function as PropType<(e: MouseEvent) => void>,\n    onAfterLeave: Function as PropType<() => void>,\n    onAfterEnter: Function as PropType<() => void>,\n    onEsc: Function as PropType<(e: KeyboardEvent) => void>\n  },\n  setup(props) {\n    const displayedRef = ref(!!props.show)\n    const bodyRef = ref<HTMLElement | null>(null) // used for detached content\n    const NDrawer = inject(drawerInjectionKey)!\n\n    let startPosition = 0\n    let memoizedBodyStyleCursor = ''\n    let hoverTimerId: number | null = null\n    const isHoverOnResizeTriggerRef = ref(false)\n    const isDraggingRef = ref(false)\n\n    const isVertical = computed<boolean>(() => {\n      return props.placement === 'top' || props.placement === 'bottom'\n    })\n    const { mergedClsPrefixRef, mergedRtlRef } = useConfig(props)\n\n    const rtlEnabledRef = useRtl('Drawer', mergedRtlRef, mergedClsPrefixRef)\n\n    const handleBodyMouseleave = handleBodyMouseup\n\n    const handleMousedownResizeTrigger = (e: MouseEvent): void => {\n      isDraggingRef.value = true\n      startPosition = isVertical.value ? e.clientY : e.clientX\n      memoizedBodyStyleCursor = document.body.style.cursor\n      document.body.style.cursor = isVertical.value ? 'ns-resize' : 'ew-resize'\n      document.body.addEventListener('mousemove', handleBodyMousemove)\n      document.body.addEventListener('mouseleave', handleBodyMouseleave)\n      document.body.addEventListener('mouseup', handleBodyMouseup)\n    }\n\n    const handleMouseenterResizeTrigger = (): void => {\n      if (hoverTimerId !== null) {\n        window.clearTimeout(hoverTimerId)\n        hoverTimerId = null\n      }\n      if (isDraggingRef.value) {\n        isHoverOnResizeTriggerRef.value = true\n      }\n      else {\n        hoverTimerId = window.setTimeout(() => {\n          isHoverOnResizeTriggerRef.value = true\n        }, 300)\n      }\n    }\n\n    const handleMouseleaveResizeTrigger = (): void => {\n      if (hoverTimerId !== null) {\n        window.clearTimeout(hoverTimerId)\n        hoverTimerId = null\n      }\n      isHoverOnResizeTriggerRef.value = false\n    }\n\n    const { doUpdateHeight, doUpdateWidth } = NDrawer\n\n    const regulateWidth = (size: number): number => {\n      const { maxWidth } = props\n      if (maxWidth && size > maxWidth)\n        return maxWidth\n      const { minWidth } = props\n      if (minWidth && size < minWidth)\n        return minWidth\n      return size\n    }\n\n    const regulateHeight = (size: number): number => {\n      const { maxHeight } = props\n      if (maxHeight && size > maxHeight)\n        return maxHeight\n      const { minHeight } = props\n      if (minHeight && size < minHeight)\n        return minHeight\n      return size\n    }\n\n    function handleBodyMousemove(e: MouseEvent): void {\n      if (isDraggingRef.value) {\n        if (isVertical.value) {\n          let height = bodyRef.value?.offsetHeight || 0\n          const increment = startPosition - e.clientY\n          height += props.placement === 'bottom' ? increment : -increment\n          height = regulateHeight(height)\n          doUpdateHeight(height)\n          startPosition = e.clientY\n        }\n        else {\n          let width = bodyRef.value?.offsetWidth || 0\n          const increment = startPosition - e.clientX\n          width += props.placement === 'right' ? increment : -increment\n          width = regulateWidth(width)\n          doUpdateWidth(width)\n          startPosition = e.clientX\n        }\n      }\n    }\n\n    function handleBodyMouseup(): void {\n      if (isDraggingRef.value) {\n        startPosition = 0\n        isDraggingRef.value = false\n        document.body.style.cursor = memoizedBodyStyleCursor\n        document.body.removeEventListener('mousemove', handleBodyMousemove)\n        document.body.removeEventListener('mouseup', handleBodyMouseup)\n        document.body.removeEventListener('mouseleave', handleBodyMouseleave)\n      }\n    }\n\n    watchEffect(() => {\n      if (props.show)\n        displayedRef.value = true\n    })\n    watch(\n      () => props.show,\n      (value) => {\n        if (!value) {\n          handleBodyMouseup()\n        }\n      }\n    )\n    onBeforeUnmount(() => {\n      handleBodyMouseup()\n    })\n    const bodyDirectivesRef = computed<DirectiveArguments>(() => {\n      const { show } = props\n      const directives: DirectiveArguments = [[vShow, show]]\n      if (!props.showMask) {\n        directives.push([\n          clickoutside,\n          props.onClickoutside,\n          undefined as unknown as string,\n          { capture: true }\n        ])\n      }\n      return directives\n    })\n    function handleAfterLeave(): void {\n      displayedRef.value = false\n      props.onAfterLeave?.()\n    }\n    useLockHtmlScroll(computed(() => props.blockScroll && displayedRef.value))\n    provide(drawerBodyInjectionKey, bodyRef)\n    provide(popoverBodyInjectionKey, null)\n    provide(modalBodyInjectionKey, null)\n    return {\n      bodyRef,\n      rtlEnabled: rtlEnabledRef,\n      mergedClsPrefix: NDrawer.mergedClsPrefixRef,\n      isMounted: NDrawer.isMountedRef,\n      mergedTheme: NDrawer.mergedThemeRef,\n      displayed: displayedRef,\n      transitionName: computed(() => {\n        return {\n          right: 'slide-in-from-right-transition',\n          left: 'slide-in-from-left-transition',\n          top: 'slide-in-from-top-transition',\n          bottom: 'slide-in-from-bottom-transition'\n        }[props.placement]\n      }),\n      handleAfterLeave,\n      bodyDirectives: bodyDirectivesRef,\n      handleMousedownResizeTrigger,\n      handleMouseenterResizeTrigger,\n      handleMouseleaveResizeTrigger,\n      isDragging: isDraggingRef,\n      isHoverOnResizeTrigger: isHoverOnResizeTriggerRef\n    }\n  },\n  render() {\n    const { $slots, mergedClsPrefix } = this\n    return this.displayDirective === 'show' || this.displayed || this.show\n      ? withDirectives(\n          /* Keep the wrapper dom. Make sure the drawer has a host.\n          Nor the detached content will disappear without transition */\n          <div role=\"none\">\n            <VFocusTrap\n              disabled={!this.showMask || !this.trapFocus}\n              active={this.show}\n              autoFocus={this.autoFocus}\n              onEsc={this.onEsc}\n            >\n              {{\n                default: () => (\n                  <Transition\n                    name={this.transitionName}\n                    appear={this.isMounted}\n                    onAfterEnter={this.onAfterEnter}\n                    onAfterLeave={this.handleAfterLeave}\n                  >\n                    {{\n                      default: () =>\n                        withDirectives(\n                          h(\n                            'div',\n                            mergeProps(this.$attrs, {\n                              role: 'dialog',\n                              ref: 'bodyRef',\n                              'aria-modal': 'true',\n                              class: [\n                                `${mergedClsPrefix}-drawer`,\n                                this.rtlEnabled\n                                && `${mergedClsPrefix}-drawer--rtl`,\n                                `${mergedClsPrefix}-drawer--${this.placement}-placement`,\n                                /**\n                                 * When the mouse is pressed to resize the drawer,\n                                 * disable text selection\n                                 */\n                                this.isDragging\n                                && `${mergedClsPrefix}-drawer--unselectable`,\n                                this.nativeScrollbar\n                                && `${mergedClsPrefix}-drawer--native-scrollbar`\n                              ]\n                            }),\n                            [\n                              this.resizable ? (\n                                <div\n                                  class={[\n                                    `${mergedClsPrefix}-drawer__resize-trigger`,\n                                    (this.isDragging\n                                      || this.isHoverOnResizeTrigger)\n                                    && `${mergedClsPrefix}-drawer__resize-trigger--hover`\n                                  ]}\n                                  onMouseenter={\n                                    this.handleMouseenterResizeTrigger\n                                  }\n                                  onMouseleave={\n                                    this.handleMouseleaveResizeTrigger\n                                  }\n                                  onMousedown={\n                                    this.handleMousedownResizeTrigger\n                                  }\n                                />\n                              ) : null,\n                              this.nativeScrollbar ? (\n                                <div\n                                  class={[\n                                    `${mergedClsPrefix}-drawer-content-wrapper`,\n                                    this.contentClass\n                                  ]}\n                                  style={this.contentStyle}\n                                  role=\"none\"\n                                >\n                                  {$slots}\n                                </div>\n                              ) : (\n                                <NScrollbar\n                                  {...this.scrollbarProps}\n                                  contentStyle={this.contentStyle}\n                                  contentClass={[\n                                    `${mergedClsPrefix}-drawer-content-wrapper`,\n                                    this.contentClass\n                                  ]}\n                                  theme={this.mergedTheme.peers.Scrollbar}\n                                  themeOverrides={\n                                    this.mergedTheme.peerOverrides.Scrollbar\n                                  }\n                                >\n                                  {$slots}\n                                </NScrollbar>\n                              )\n                            ]\n                          ),\n                          this.bodyDirectives\n                        )\n                    }}\n                  </Transition>\n                )\n              }}\n            </VFocusTrap>\n          </div>,\n          [\n            [\n              vShow,\n              this.displayDirective === 'if' || this.displayed || this.show\n            ]\n          ]\n        )\n      : null\n  }\n})\n"
  },
  {
    "path": "src/drawer/src/DrawerContent.tsx",
    "content": "import type { CSSProperties, PropType, SlotsType, VNode } from 'vue'\nimport type { ScrollbarProps } from '../../_internal'\nimport type { ExtractPublicPropTypes } from '../../_utils'\nimport { defineComponent, h, inject } from 'vue'\nimport { NBaseClose, NScrollbar } from '../../_internal'\nimport { throwError } from '../../_utils'\nimport { drawerInjectionKey } from './interface'\n\nexport const drawerContentProps = {\n  title: String,\n  headerClass: String,\n  headerStyle: [Object, String] as PropType<string | CSSProperties>,\n  footerClass: String,\n  footerStyle: [Object, String] as PropType<string | CSSProperties>,\n  bodyClass: String,\n  bodyStyle: [Object, String] as PropType<string | CSSProperties>,\n  bodyContentClass: String,\n  bodyContentStyle: [Object, String] as PropType<string | CSSProperties>,\n  nativeScrollbar: { type: Boolean, default: true },\n  scrollbarProps: Object as PropType<ScrollbarProps>,\n  closable: Boolean\n}\n\nexport type DrawerContentProps = ExtractPublicPropTypes<\n  typeof drawerContentProps\n>\n\nexport interface DrawerContentSlots {\n  default?: () => VNode[]\n  header?: () => VNode[]\n  footer?: () => VNode[]\n}\n\nexport default defineComponent({\n  name: 'DrawerContent',\n  props: drawerContentProps,\n  slots: Object as SlotsType<DrawerContentSlots>,\n  setup() {\n    const NDrawer = inject(drawerInjectionKey, null)\n    if (!NDrawer) {\n      throwError(\n        'drawer-content',\n        '`n-drawer-content` must be placed inside `n-drawer`.'\n      )\n    }\n    const { doUpdateShow } = NDrawer\n    function handleCloseClick(): void {\n      doUpdateShow(false)\n    }\n    return {\n      handleCloseClick,\n      mergedTheme: NDrawer.mergedThemeRef,\n      mergedClsPrefix: NDrawer.mergedClsPrefixRef\n    }\n  },\n  render() {\n    const {\n      title,\n      mergedClsPrefix,\n      nativeScrollbar,\n      mergedTheme,\n      bodyClass,\n      bodyStyle,\n      bodyContentClass,\n      bodyContentStyle,\n      headerClass,\n      headerStyle,\n      footerClass,\n      footerStyle,\n      scrollbarProps,\n      closable,\n      $slots\n    } = this\n    return (\n      <div\n        role=\"none\"\n        class={[\n          `${mergedClsPrefix}-drawer-content`,\n          nativeScrollbar\n          && `${mergedClsPrefix}-drawer-content--native-scrollbar`\n        ]}\n      >\n        {$slots.header || title || closable ? (\n          <div\n            class={[`${mergedClsPrefix}-drawer-header`, headerClass]}\n            style={headerStyle}\n            role=\"none\"\n          >\n            <div\n              class={`${mergedClsPrefix}-drawer-header__main`}\n              role=\"heading\"\n              aria-level=\"1\"\n            >\n              {$slots.header !== undefined ? $slots.header() : title}\n            </div>\n            {closable && (\n              <NBaseClose\n                onClick={this.handleCloseClick}\n                clsPrefix={mergedClsPrefix}\n                class={`${mergedClsPrefix}-drawer-header__close`}\n                absolute\n              />\n            )}\n          </div>\n        ) : null}\n        {nativeScrollbar ? (\n          <div\n            class={[`${mergedClsPrefix}-drawer-body`, bodyClass]}\n            style={bodyStyle}\n            role=\"none\"\n          >\n            <div\n              class={[\n                `${mergedClsPrefix}-drawer-body-content-wrapper`,\n                bodyContentClass\n              ]}\n              style={bodyContentStyle}\n              role=\"none\"\n            >\n              {$slots}\n            </div>\n          </div>\n        ) : (\n          <NScrollbar\n            themeOverrides={mergedTheme.peerOverrides.Scrollbar}\n            theme={mergedTheme.peers.Scrollbar}\n            {...scrollbarProps}\n            class={`${mergedClsPrefix}-drawer-body`}\n            contentClass={[\n              `${mergedClsPrefix}-drawer-body-content-wrapper`,\n              bodyContentClass\n            ]}\n            contentStyle={bodyContentStyle}\n          >\n            {$slots}\n          </NScrollbar>\n        )}\n        {$slots.footer ? (\n          <div\n            class={[`${mergedClsPrefix}-drawer-footer`, footerClass]}\n            style={footerStyle}\n            role=\"none\"\n          >\n            {$slots.footer()}\n          </div>\n        ) : null}\n      </div>\n    )\n  }\n})\n"
  },
  {
    "path": "src/drawer/src/interface.ts",
    "content": "import type { Ref } from 'vue'\nimport type { MergedTheme } from '../../_mixins'\nimport type { DrawerTheme } from '../styles'\nimport { createInjectionKey } from '../../_utils/vue/create-injection-key'\n\nexport type DrawerBodyInjection = Ref<HTMLElement | null> | null\nexport const drawerBodyInjectionKey\n  = createInjectionKey<DrawerBodyInjection>('n-drawer-body')\n\nexport interface DrawerInjection {\n  isMountedRef: Ref<boolean>\n  mergedThemeRef: Ref<MergedTheme<DrawerTheme>>\n  mergedClsPrefixRef: Ref<string>\n  doUpdateShow: (show: boolean) => void\n  doUpdateWidth: (value: number) => void\n  doUpdateHeight: (value: number) => void\n}\nexport const drawerInjectionKey\n  = createInjectionKey<DrawerInjection>('n-drawer')\n"
  },
  {
    "path": "src/drawer/src/styles/index.cssr.ts",
    "content": "import { fadeInTransition } from '../../../_styles/transitions/fade-in.cssr'\nimport { slideInFromBottomTransition } from '../../../_styles/transitions/slide-in-from-bottom'\nimport { slideInFromLeftTransition } from '../../../_styles/transitions/slide-in-from-left'\nimport { slideInFromRightTransition } from '../../../_styles/transitions/slide-in-from-right'\nimport { slideInFromTopTransition } from '../../../_styles/transitions/slide-in-from-top'\nimport { c, cB, cE, cM } from '../../../_utils/cssr'\n\n// vars:\n// --n-line-height\n// --n-color\n// --n-border-radius\n// --n-text-color\n// --n-box-shadow\n// --n-bezier\n// --n-bezier-out\n// --n-bezier-in\n// --n-body-padding\n// --n-header-padding\n// --n-footer-padding\n// --n-title-font-size\n// --n-title-text-color\n// --n-title-font-weight\n// --n-header-border-bottom\n// --n-footer-border-top\n// --n-close-border-radius\n// --n-close-color-hover\n// --n-close-color-pressed\n// --n-close-icon-color\n// --n-close-icon-color-hover\n// --n-close-icon-color-pressed\n// --n-close-size\n// --n-close-icon-size\nexport default c([\n  cB('drawer', `\n    word-break: break-word;\n    line-height: var(--n-line-height);\n    position: absolute;\n    pointer-events: all;\n    box-shadow: var(--n-box-shadow);\n    transition:\n      background-color .3s var(--n-bezier),\n      color .3s var(--n-bezier);\n    background-color: var(--n-color);\n    color: var(--n-text-color);\n    box-sizing: border-box;\n  `, [\n    slideInFromRightTransition(),\n    slideInFromLeftTransition(),\n    slideInFromTopTransition(),\n    slideInFromBottomTransition(),\n    cM('unselectable', `\n      user-select: none; \n      -webkit-user-select: none;\n    `),\n    cM('native-scrollbar', [\n      cB('drawer-content-wrapper', `\n        overflow: auto;\n        height: 100%;\n      `)\n    ]),\n    cE('resize-trigger', `\n      position: absolute;\n      background-color: #0000;\n      transition: background-color .3s var(--n-bezier);\n    `, [\n      cM('hover', `\n        background-color: var(--n-resize-trigger-color-hover);\n      `)\n    ]),\n    cB('drawer-content-wrapper', `\n      box-sizing: border-box;\n    `),\n    cB('drawer-content', `\n      height: 100%;\n      display: flex;\n      flex-direction: column;\n    `, [\n      cM('native-scrollbar', [\n        cB('drawer-body-content-wrapper', `\n          height: 100%;\n          overflow: auto;\n        `)\n      ]),\n      cB('drawer-body', `\n        flex: 1 0 0;\n        overflow: hidden;\n      `),\n      cB('drawer-body-content-wrapper', `\n        box-sizing: border-box;\n        padding: var(--n-body-padding);\n      `),\n      cB('drawer-header', `\n        font-weight: var(--n-title-font-weight);\n        line-height: 1;\n        font-size: var(--n-title-font-size);\n        color: var(--n-title-text-color);\n        padding: var(--n-header-padding);\n        transition: border .3s var(--n-bezier);\n        border-bottom: 1px solid var(--n-divider-color);\n        border-bottom: var(--n-header-border-bottom);\n        display: flex;\n        justify-content: space-between;\n        align-items: center;\n      `, [\n        cE('main', `\n          flex: 1;\n        `),\n        cE('close', `\n          margin-left: 6px;\n          transition:\n            background-color .3s var(--n-bezier),\n            color .3s var(--n-bezier);\n        `)\n      ]),\n      cB('drawer-footer', `\n        display: flex;\n        justify-content: flex-end;\n        border-top: var(--n-footer-border-top);\n        transition: border .3s var(--n-bezier);\n        padding: var(--n-footer-padding);\n      `)\n    ]),\n    cM('right-placement', `\n      top: 0;\n      bottom: 0;\n      right: 0;\n      border-top-left-radius: var(--n-border-radius);\n      border-bottom-left-radius: var(--n-border-radius);\n    `, [\n      cE('resize-trigger', `\n        width: 3px;\n        height: 100%;\n        top: 0;\n        left: 0;\n        transform: translateX(-1.5px);\n        cursor: ew-resize;\n      `)\n    ]),\n    cM('left-placement', `\n      top: 0;\n      bottom: 0;\n      left: 0;\n      border-top-right-radius: var(--n-border-radius);\n      border-bottom-right-radius: var(--n-border-radius);\n    `, [\n      cE('resize-trigger', `\n        width: 3px;\n        height: 100%;\n        top: 0;\n        right: 0;\n        transform: translateX(1.5px);\n        cursor: ew-resize;\n      `)\n    ]),\n    cM('top-placement', `\n      top: 0;\n      left: 0;\n      right: 0;\n      border-bottom-left-radius: var(--n-border-radius);\n      border-bottom-right-radius: var(--n-border-radius);\n    `, [\n      cE('resize-trigger', `\n        width: 100%;\n        height: 3px;\n        bottom: 0;\n        left: 0;\n        transform: translateY(1.5px);\n        cursor: ns-resize;\n      `)\n    ]),\n    cM('bottom-placement', `\n      left: 0;\n      bottom: 0;\n      right: 0;\n      border-top-left-radius: var(--n-border-radius);\n      border-top-right-radius: var(--n-border-radius);\n    `, [\n      cE('resize-trigger', `\n        width: 100%;\n        height: 3px;\n        top: 0;\n        left: 0;\n        transform: translateY(-1.5px);\n        cursor: ns-resize;\n      `)\n    ])\n  ]),\n  c('body', [\n    c('>', [\n      cB('drawer-container', `\n        position: fixed;\n      `)\n    ])\n  ]),\n  cB('drawer-container', `\n    position: relative;\n    position: absolute;\n    left: 0;\n    right: 0;\n    top: 0;\n    bottom: 0;\n    pointer-events: none;\n  `, [\n    c('> *', `\n      pointer-events: all;\n    `)\n  ]),\n  cB('drawer-mask', `\n    background-color: rgba(0, 0, 0, .3);\n    position: absolute;\n    left: 0;\n    right: 0;\n    top: 0;\n    bottom: 0;\n  `, [\n    cM('invisible', `\n      background-color: rgba(0, 0, 0, 0)\n    `),\n    fadeInTransition({\n      enterDuration: '0.2s',\n      leaveDuration: '0.2s',\n      enterCubicBezier: 'var(--n-bezier-in)',\n      leaveCubicBezier: 'var(--n-bezier-out)'\n    })\n  ])\n])\n"
  },
  {
    "path": "src/drawer/src/styles/rtl.cssr.ts",
    "content": "import { cB, cE, cM } from '../../../_utils/cssr'\n\nexport default cB('drawer', [\n  cM('rtl', `\n    direction: rtl;\n    text-align: right;\n  `, [\n    cB('drawer-content', [\n      cB('drawer-header', [\n        cE('close', `\n          margin-left: 0;\n          margin-right: 6px;\n        `)\n      ])\n    ])\n  ])\n])\n"
  },
  {
    "path": "src/drawer/styles/dark.ts",
    "content": "import type { DrawerTheme } from './light'\nimport { scrollbarDark } from '../../_internal/scrollbar/styles'\nimport { commonDark } from '../../_styles/common'\nimport { self } from './light'\n\nconst drawerDark: DrawerTheme = {\n  name: 'Drawer',\n  common: commonDark,\n  peers: {\n    Scrollbar: scrollbarDark\n  },\n  self\n}\n\nexport default drawerDark\n"
  },
  {
    "path": "src/drawer/styles/index.ts",
    "content": "export { default as drawerDark } from './dark'\nexport { default as drawerLight } from './light'\nexport type { DrawerTheme, DrawerThemeVars } from './light'\nexport { default as drawerRtl } from './rtl'\n"
  },
  {
    "path": "src/drawer/styles/light.ts",
    "content": "import type { ThemeCommonVars } from '../../_styles/common'\nimport { scrollbarLight } from '../../_internal/scrollbar/styles'\nimport { createTheme } from '../../_mixins'\nimport { commonLight } from '../../_styles/common'\n\nexport function self(vars: ThemeCommonVars) {\n  const {\n    modalColor,\n    textColor1,\n    textColor2,\n    boxShadow3,\n    lineHeight,\n    fontWeightStrong,\n    dividerColor,\n    closeColorHover,\n    closeColorPressed,\n    closeIconColor,\n    closeIconColorHover,\n    closeIconColorPressed,\n    borderRadius,\n    primaryColorHover\n  } = vars\n  return {\n    bodyPadding: '16px 24px',\n    borderRadius,\n    headerPadding: '16px 24px',\n    footerPadding: '16px 24px',\n    color: modalColor,\n    textColor: textColor2,\n    titleTextColor: textColor1,\n    titleFontSize: '18px',\n    titleFontWeight: fontWeightStrong,\n    boxShadow: boxShadow3,\n    lineHeight,\n    headerBorderBottom: `1px solid ${dividerColor}`,\n    footerBorderTop: `1px solid ${dividerColor}`,\n    closeIconColor,\n    closeIconColorHover,\n    closeIconColorPressed,\n    closeSize: '22px',\n    closeIconSize: '18px',\n    closeColorHover,\n    closeColorPressed,\n    closeBorderRadius: borderRadius,\n    resizableTriggerColorHover: primaryColorHover\n  }\n}\n\nexport type DrawerThemeVars = ReturnType<typeof self>\n\nconst drawerLight = createTheme({\n  name: 'Drawer',\n  common: commonLight,\n  peers: {\n    Scrollbar: scrollbarLight\n  },\n  self\n})\n\nexport default drawerLight\nexport type DrawerTheme = typeof drawerLight\n"
  },
  {
    "path": "src/drawer/styles/rtl.ts",
    "content": "import type { RtlItem } from '../../config-provider/src/internal-interface'\nimport { scrollbarRtl } from '../../_internal/scrollbar/styles/rtl'\nimport rtlStyle from '../src/styles/rtl.cssr'\n\nexport const drawerRtl: RtlItem = {\n  name: 'Drawer',\n  style: rtlStyle,\n  peers: [scrollbarRtl]\n}\n\nexport default drawerRtl\n"
  },
  {
    "path": "src/drawer/tests/Drawer.spec.tsx",
    "content": "import type { DrawerContentProps, DrawerProps } from '../index'\nimport { mount } from '@vue/test-utils'\nimport { defineComponent, h, nextTick, ref } from 'vue'\nimport { NButton } from '../../button'\nimport { NDrawer, NDrawerContent } from '../index'\n\n// It seems due to special handling of transition in naive-ui, the drawer's DOM\n// won't disappear even if its `show` prop is false. No time to find out the\n// exact reason, so I create a util here.\nfunction expectDrawerExists(): void {\n  const drawer = document.querySelector('.n-drawer')\n  if (drawer !== null)\n    return\n  expect(\n    (document.querySelector('.n-drawer') as HTMLElement).style.display\n  ).toEqual('none')\n}\n\nfunction mountDrawer({\n  drawerProps,\n  drawerContentProps,\n  hasOnUpdateShow,\n  show\n}: {\n  drawerProps?: DrawerProps\n  drawerContentProps?: DrawerContentProps\n  hasOnUpdateShow?: boolean\n  show?: boolean\n}) {\n  return mount(\n    defineComponent({\n      setup() {\n        return {\n          show: ref(!!show)\n        }\n      },\n      render() {\n        return [\n          <NButton\n            onClick={() => {\n              this.show = true\n            }}\n          >\n            {{ default: () => 'Show' }}\n          </NButton>,\n          <NDrawer\n            show={this.show}\n            onUpdateShow={\n              hasOnUpdateShow\n                ? drawerProps?.onUpdateShow\n                : (show) => {\n                    this.show = show\n                  }\n            }\n            {...drawerProps}\n          >\n            {{\n              default: () => (\n                <NDrawerContent {...drawerContentProps}></NDrawerContent>\n              )\n            }}\n          </NDrawer>\n        ]\n      }\n    }),\n    {\n      attachTo: document.body\n    }\n  )\n}\n\ndescribe('n-drawer', () => {\n  it('should work with import on demand', () => {\n    mount(NDrawer)\n  })\n\n  it('closable', async () => {\n    const wrapper = mountDrawer({ drawerContentProps: { closable: true } })\n    expect(document.querySelector('.n-drawer')).toEqual(null)\n    await wrapper.find('button').trigger('click')\n    expect(document.querySelector('.n-drawer')).not.toEqual(null)\n    document\n      .querySelector('.n-base-close')\n      ?.dispatchEvent(new MouseEvent('click'))\n    await nextTick()\n    expectDrawerExists()\n    wrapper.unmount()\n  })\n\n  it('should work with `placement` prop', async () => {\n    let wrapper = mountDrawer({ drawerProps: { placement: 'top' } })\n    await wrapper.find('button').trigger('click')\n    expect(document.querySelector('.n-drawer')?.className).toContain(\n      'n-drawer--top-placement'\n    )\n    expectDrawerExists()\n    wrapper.unmount()\n\n    wrapper = mountDrawer({ drawerProps: { placement: 'right' } })\n    await wrapper.find('button').trigger('click')\n    expect(document.querySelector('.n-drawer')?.className).toContain(\n      'n-drawer--right-placement'\n    )\n    expectDrawerExists()\n    wrapper.unmount()\n\n    wrapper = mountDrawer({ drawerProps: { placement: 'bottom' } })\n    await wrapper.find('button').trigger('click')\n    expect(document.querySelector('.n-drawer')?.className).toContain(\n      'n-drawer--bottom-placement'\n    )\n    expectDrawerExists()\n    wrapper.unmount()\n\n    wrapper = mountDrawer({ drawerProps: { placement: 'left' } })\n    await wrapper.find('button').trigger('click')\n    expect(document.querySelector('.n-drawer')?.className).toContain(\n      'n-drawer--left-placement'\n    )\n    expectDrawerExists()\n    wrapper.unmount()\n  })\n\n  it('should work with `show` prop', async () => {\n    const wrapper1 = mountDrawer({\n      show: false\n    })\n    expect(document.querySelector('.n-drawer')).toEqual(null)\n    wrapper1.unmount()\n    const wrapper2 = mountDrawer({\n      show: true\n    })\n    expect(document.querySelector('.n-drawer')).not.toEqual(null)\n    wrapper2.unmount()\n  })\n\n  it('should work with `on-update:show` prop', async () => {\n    const onUpdate = vi.fn()\n    const wrapper = mountDrawer({\n      hasOnUpdateShow: true,\n      drawerProps: { onUpdateShow: onUpdate },\n      drawerContentProps: { closable: true }\n    })\n    await wrapper.find('button').trigger('click')\n    expect(onUpdate).not.toHaveBeenCalled()\n    document\n      .querySelector('.n-base-close')\n      ?.dispatchEvent(new MouseEvent('click'))\n    await nextTick()\n    expect(onUpdate).toHaveBeenCalledWith(false)\n    wrapper.unmount()\n  })\n\n  it('should work with `mask-closable` prop', async () => {\n    const onUpdate = vi.fn()\n    const wrapper = mountDrawer({\n      show: true,\n      hasOnUpdateShow: true,\n      drawerProps: { onUpdateShow: onUpdate },\n      drawerContentProps: { closable: true }\n    })\n    document\n      .querySelector('.n-drawer-mask')\n      ?.dispatchEvent(new MouseEvent('click', { bubbles: true }))\n    await nextTick()\n    expect(onUpdate).toHaveBeenCalledWith(false)\n    wrapper.unmount()\n  })\n\n  it('should work with `header-style` prop', async () => {\n    const wrapper = mountDrawer({\n      drawerContentProps: {\n        title: 'test',\n        headerStyle: { backgroundColor: 'red' }\n      },\n      show: true\n    })\n\n    expect(\n      (document.querySelector('.n-drawer-header') as HTMLElement).style\n        .backgroundColor\n    ).toEqual('red')\n\n    wrapper.unmount()\n  })\n\n  it('should work with `body-style` prop', async () => {\n    const wrapper = mountDrawer({\n      drawerContentProps: {\n        title: 'test',\n        bodyStyle: { backgroundColor: 'red' }\n      },\n      show: true\n    })\n\n    expect(\n      (document.querySelector('.n-drawer-body') as HTMLElement).style\n        .backgroundColor\n    ).toEqual('red')\n\n    wrapper.unmount()\n  })\n\n  it('should work with `resizable` prop', async () => {\n    const originalOffsetHeight = Object.getOwnPropertyDescriptor(\n      HTMLElement.prototype,\n      'offsetHeight'\n    )\n    const originalOffsetWidth = Object.getOwnPropertyDescriptor(\n      HTMLElement.prototype,\n      'offsetWidth'\n    )\n\n    Object.defineProperty(HTMLElement.prototype, 'offsetHeight', {\n      configurable: true,\n      value: 251\n    })\n    Object.defineProperty(HTMLElement.prototype, 'offsetWidth', {\n      configurable: true,\n      value: 251\n    })\n    // placement top\n    let wrapper = mountDrawer({\n      show: true,\n      drawerProps: { placement: 'top', resizable: true, defaultHeight: 251 }\n    })\n    expect(document.querySelector('.n-drawer')?.className).toContain(\n      'n-drawer--top-placement'\n    )\n    expect(document.querySelector('.n-drawer__resize-trigger')).not.toEqual(\n      null\n    )\n\n    let mousedownEvent = new MouseEvent('mousedown', {\n      bubbles: true,\n      clientX: 0,\n      clientY: 251\n    })\n    let mousemoveEvent = new MouseEvent('mousemove', {\n      bubbles: true,\n      clientX: 0,\n      clientY: 600\n    })\n    let mouseupEvent = new MouseEvent('mouseup', { bubbles: true })\n\n    document\n      .querySelector('.n-drawer__resize-trigger')\n      ?.dispatchEvent(mousedownEvent)\n    document.body.dispatchEvent(mousemoveEvent)\n    document.body.dispatchEvent(mouseupEvent)\n\n    await nextTick()\n    expect(document.querySelector('.n-drawer')?.getAttribute('style')).toBe(\n      'height: 600px;'\n    )\n\n    wrapper.unmount()\n\n    // placement bottom\n    wrapper = mountDrawer({\n      show: true,\n      drawerProps: { placement: 'bottom', resizable: true, defaultHeight: 251 }\n    })\n    expect(document.querySelector('.n-drawer')?.className).toContain(\n      'n-drawer--bottom-placement'\n    )\n    expect(document.querySelector('.n-drawer__resize-trigger')).not.toEqual(\n      null\n    )\n\n    mousedownEvent = new MouseEvent('mousedown', {\n      bubbles: true,\n      clientX: 0,\n      clientY: 600\n    })\n    mousemoveEvent = new MouseEvent('mousemove', {\n      bubbles: true,\n      clientX: 0,\n      clientY: 251\n    })\n    mouseupEvent = new MouseEvent('mouseup', { bubbles: true })\n\n    document\n      .querySelector('.n-drawer__resize-trigger')\n      ?.dispatchEvent(mousedownEvent)\n    document.body.dispatchEvent(mousemoveEvent)\n    document.body.dispatchEvent(mouseupEvent)\n\n    await nextTick()\n    expect(document.querySelector('.n-drawer')?.getAttribute('style')).toBe(\n      'height: 600px;'\n    )\n\n    wrapper.unmount()\n\n    // placement left\n    wrapper = mountDrawer({\n      show: true,\n      drawerProps: { placement: 'left', resizable: true, defaultWidth: 251 }\n    })\n    expect(document.querySelector('.n-drawer')?.className).toContain(\n      'n-drawer--left-placement'\n    )\n    expect(document.querySelector('.n-drawer__resize-trigger')).not.toEqual(\n      null\n    )\n\n    mousedownEvent = new MouseEvent('mousedown', {\n      bubbles: true,\n      clientX: 251,\n      clientY: 0\n    })\n    mousemoveEvent = new MouseEvent('mousemove', {\n      bubbles: true,\n      clientX: 600,\n      clientY: 0\n    })\n    mouseupEvent = new MouseEvent('mouseup', { bubbles: true })\n\n    document\n      .querySelector('.n-drawer__resize-trigger')\n      ?.dispatchEvent(mousedownEvent)\n    document.body.dispatchEvent(mousemoveEvent)\n    document.body.dispatchEvent(mouseupEvent)\n\n    await nextTick()\n    expect(document.querySelector('.n-drawer')?.getAttribute('style')).toBe(\n      'width: 600px;'\n    )\n\n    wrapper.unmount()\n\n    // placement right\n    wrapper = mountDrawer({\n      show: true,\n      drawerProps: { placement: 'right', resizable: true, defaultWidth: 251 }\n    })\n    expect(document.querySelector('.n-drawer')?.className).toContain(\n      'n-drawer--right-placement'\n    )\n    expect(document.querySelector('.n-drawer__resize-trigger')).not.toEqual(\n      null\n    )\n\n    mousedownEvent = new MouseEvent('mousedown', {\n      bubbles: true,\n      clientX: 600,\n      clientY: 0\n    })\n    mousemoveEvent = new MouseEvent('mousemove', {\n      bubbles: true,\n      clientX: 251,\n      clientY: 0\n    })\n    mouseupEvent = new MouseEvent('mouseup', { bubbles: true })\n\n    document\n      .querySelector('.n-drawer__resize-trigger')\n      ?.dispatchEvent(mousedownEvent)\n    document.body.dispatchEvent(mousemoveEvent)\n    document.body.dispatchEvent(mouseupEvent)\n\n    await nextTick()\n    expect(document.querySelector('.n-drawer')?.getAttribute('style')).toBe(\n      'width: 600px;'\n    )\n\n    wrapper.unmount()\n\n    Object.defineProperty(\n      HTMLElement.prototype,\n      'offsetHeight',\n      originalOffsetHeight!\n    )\n    Object.defineProperty(\n      HTMLElement.prototype,\n      'offsetWidth',\n      originalOffsetWidth!\n    )\n  })\n})\n"
  },
  {
    "path": "src/drawer/tests/server.spec.tsx",
    "content": "import { setup } from '@css-render/vue3-ssr'\nimport { renderToString } from '@vue/server-renderer'\n/**\n * @vitest-environment node\n */\nimport { createSSRApp, h } from 'vue'\nimport { NDrawer } from '../..'\n\ndescribe('server side rendering', () => {\n  it('works', async () => {\n    const app = createSSRApp(() => <NDrawer />)\n    setup(app)\n    try {\n      await renderToString(app)\n    }\n    catch (e) {\n      expect(e).not.toBeTruthy()\n    }\n  })\n})\n"
  },
  {
    "path": "src/dropdown/demos/enUS/arrow.demo.vue",
    "content": "<markdown>\n# Arrow\n\nShow an arrow with the dropdown.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { useMessage } from 'naive-ui'\n\nconst message = useMessage()\nconst options = [\n  {\n    label: 'Marina Bay Sands',\n    key: 'marina bay sands',\n    disabled: true\n  },\n  {\n    label: 'Brown\\'s Hotel, London',\n    key: 'brown\\'s hotel, london'\n  },\n  {\n    label: 'Atlantis Bahamas, Nassau',\n    key: 'atlantis nahamas, nassau'\n  },\n  {\n    label: 'The Beverly Hills Hotel, Los Angeles',\n    key: 'the beverly hills hotel, los angeles'\n  }\n]\n\nfunction handleSelect(key: string | number) {\n  message.info(String(key))\n}\n</script>\n\n<template>\n  <n-dropdown\n    trigger=\"click\"\n    :options=\"options\"\n    :show-arrow=\"true\"\n    @select=\"handleSelect\"\n  >\n    <n-button>Go For a Trip</n-button>\n  </n-dropdown>\n</template>\n"
  },
  {
    "path": "src/dropdown/demos/enUS/basic.demo.vue",
    "content": "<markdown>\n# Basic\n\nA basic dropdown.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { useMessage } from 'naive-ui'\n\nconst message = useMessage()\nconst options = [\n  {\n    label: 'Marina Bay Sands',\n    key: 'marina bay sands',\n    disabled: true\n  },\n  {\n    label: 'Brown\\'s Hotel, London',\n    key: 'brown\\'s hotel, london'\n  },\n  {\n    label: 'Atlantis Bahamas, Nassau',\n    key: 'atlantis nahamas, nassau'\n  },\n  {\n    label: 'The Beverly Hills Hotel, Los Angeles',\n    key: 'the beverly hills hotel, los angeles'\n  }\n]\n\nfunction handleSelect(key: string | number) {\n  message.info(String(key))\n}\n</script>\n\n<template>\n  <n-dropdown trigger=\"hover\" :options=\"options\" @select=\"handleSelect\">\n    <n-button>Go For a Trip</n-button>\n  </n-dropdown>\n</template>\n"
  },
  {
    "path": "src/dropdown/demos/enUS/batch-render.demo.vue",
    "content": "<markdown>\n# Batch Render\n\nNote: `render-label` works for group type label, which can be set in `option.type`.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { DropdownOption } from 'naive-ui'\nimport type { VNodeChild } from 'vue'\nimport { CashOutline as CashIcon } from '@vicons/ionicons5'\nimport { NIcon } from 'naive-ui'\nimport { h } from 'vue'\n\nconst options = [\n  {\n    type: 'group',\n    label: 'People & Food',\n    key: 'main',\n    children: [\n      {\n        label: 'Jay Gatsby',\n        key: 'jay gatsby'\n      },\n      {\n        label: 'Daisy Buchanan',\n        key: 'daisy buchanan'\n      },\n      {\n        label: 'Nick Carraway',\n        key: 'nick carraway'\n      },\n      {\n        label: 'Food',\n        key: 'food',\n        children: [\n          {\n            label: 'Chicken',\n            key: 'chicken'\n          },\n          {\n            label: 'Beef',\n            key: 'beef'\n          }\n        ]\n      }\n    ]\n  }\n]\n\nfunction renderDropdownLabel(option: DropdownOption) {\n  if (option.type === 'group') {\n    return option.label as VNodeChild\n  }\n  return h(\n    'a',\n    {\n      href: '',\n      target: '_blank'\n    },\n    {\n      default: () => option.label as VNodeChild\n    }\n  )\n}\n\nfunction renderDropdownIcon() {\n  return h(NIcon, null, {\n    default: () => h(CashIcon)\n  })\n}\n</script>\n\n<template>\n  <n-dropdown\n    :options=\"options\"\n    placement=\"bottom-start\"\n    trigger=\"click\"\n    :render-label=\"renderDropdownLabel\"\n    :render-icon=\"renderDropdownIcon\"\n  >\n    <n-button>Batch Rendered</n-button>\n  </n-dropdown>\n</template>\n"
  },
  {
    "path": "src/dropdown/demos/enUS/cascade.demo.vue",
    "content": "<markdown>\n# Cascade\n\nDropdown can be cascaded.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { CashOutline as CashIcon } from '@vicons/ionicons5'\nimport { NIcon, useMessage } from 'naive-ui'\nimport { h } from 'vue'\n\nconst options = [\n  {\n    label: 'Jay Gatsby',\n    key: 'jay gatsby'\n  },\n  {\n    label: 'Daisy Buchanan',\n    icon() {\n      return h(NIcon, null, {\n        default: () => h(CashIcon)\n      })\n    },\n    key: 'daisy buchanan'\n  },\n  {\n    type: 'divider',\n    key: 'd1'\n  },\n  {\n    label: 'Nick Carraway',\n    key: 'nick carraway'\n  },\n  {\n    label: 'Others',\n    key: 'others1',\n    children: [\n      {\n        label: 'Jordan Baker',\n        key: 'jordan baker'\n      },\n      {\n        label: 'Tom Buchanan',\n        key: 'tom buchanan'\n      },\n      {\n        label: 'Others',\n        key: 'others2',\n        disabled: true,\n        children: [\n          {\n            label: 'Chicken',\n            key: 'chicken'\n          },\n          {\n            label: 'Beef',\n            key: 'beef'\n          }\n        ]\n      }\n    ]\n  }\n]\n\nconst message = useMessage()\nfunction handleSelect(key: string | number) {\n  message.info(String(key))\n}\n</script>\n\n<template>\n  <n-dropdown\n    :options=\"options\"\n    placement=\"bottom-start\"\n    trigger=\"click\"\n    @select=\"handleSelect\"\n  >\n    <n-button>People & Food</n-button>\n  </n-dropdown>\n</template>\n"
  },
  {
    "path": "src/dropdown/demos/enUS/icon.demo.vue",
    "content": "<markdown>\n# Icon\n\nDropdown options can also have icons!\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { Component } from 'vue'\nimport {\n  Pencil as EditIcon,\n  LogOutOutline as LogoutIcon,\n  PersonCircleOutline as UserIcon\n} from '@vicons/ionicons5'\nimport { NIcon } from 'naive-ui'\nimport { h } from 'vue'\n\nfunction renderIcon(icon: Component) {\n  return () => {\n    return h(NIcon, null, {\n      default: () => h(icon)\n    })\n  }\n}\n\nconst options = [\n  {\n    label: 'User Profile',\n    key: 'profile',\n    icon: renderIcon(UserIcon)\n  },\n  {\n    label: 'Edit Profile',\n    key: 'editProfile',\n    icon: renderIcon(EditIcon)\n  },\n  {\n    label: 'Logout',\n    key: 'logout',\n    icon: renderIcon(LogoutIcon)\n  }\n]\n</script>\n\n<template>\n  <n-dropdown :options=\"options\">\n    <n-button>User Profile</n-button>\n  </n-dropdown>\n</template>\n"
  },
  {
    "path": "src/dropdown/demos/enUS/index.demo-entry.md",
    "content": "# Dropdown\n\nWhen you have some functions to trigger.\n\n## Demos\n\n```demo\nbasic.vue\nicon.vue\ntrigger.vue\ncascade.vue\narrow.vue\nplacement.vue\nsize.vue\nbatch-render.vue\nmanual-position.vue\nrender.vue\noption-props.vue\nrender-option.vue\n```\n\n## API\n\n### Dropdown Props\n\n| Name | Type | Default | Description | Version |\n| --- | --- | --- | --- | --- |\n| animated | `boolean` | `true` | Use an animation when showing options. |  |\n| inverted | `boolean` | `false` | Use the inverted style. |  |\n| children-field | `string` | `'children'` | Field name of children. |  |\n| keyboard | `boolean` | `true` | Whether the component supports keyboard operation. (Be careful about the potential conflicts with other components keyboard operations) |  |\n| key-field | `string` | `'key'` | Field name of key. |  |\n| label-field | `string` | `'label'` | Field name of label. |  |\n| node-props | `(option: DropdownOption \\| DropdownGroupOption) => HTMLAttributes` | `undefined` | Option HTML attributes generator. | 2.29.1 |\n| menu-props | `(option: DropdownOption \\| undefined, options: (DropdownOption \\| DropdownGroupOption)[]) => HTMLAttributes` | `undefined` | Menu HTML attributes generator. | 2.31.0 |\n| options | `Array<DropdownOption \\| DropdownGroupOption \\| DropdownDividerOption \\| DropdownRenderOption>` | `[]` | Dropdown options. |  |\n| render-icon | `(option: DropdownOption) => VNodeChild` | `undefined` | Render function that renders option icons. |  |\n| render-label | `(option: DropdownOption) => VNodeChild` | `undefined` | Render function that renders option labels. |  |\n| render-option | `(props: { node: VNode, option: DropdownOption \\| DropdownGroupOption }) => VNodeChild` | `undefined` | Render function that renders option itself. | 2.29.1 |\n| size | `'small'\\|'medium'\\|'large'\\|'huge'` | `'medium'` | Dropdown size. |  |\n| on-clickoutside | `(e: MouseEvent) => void` | `undefined` | Callback function triggered when there is a click outside of the component. |  |\n| on-select | `(key: string \\| number, option: DropdownOption) => void` | `undefined` | Callback function for after an option is selected. |  |\n\nFor other props, for example `placement`, please see [Popover Props](popover#Popover-Props). Note that `raw` is not available.\n\n#### DropdownOption Type\n\n| Property | Type | Description | Version |\n| --- | --- | --- | --- |\n| children? | `Array<DropdownOption \\| DropdownDividerOption \\| DropdownGroupOption>` | Child options. |  |\n| disabled? | `boolean` | Whether to disable the option. |  |\n| icon? | `() => VNodeChild` | Custom render function of an option icon. |  |\n| key? | `string \\| number` | Option ID (should be unique). |  |\n| label? | `string \\| () => VNodeChild` | Displayed label value. |  |\n| props? | `HTMLAttributes` | Customize option props. |  |\n| show? | `boolean` | Whether to show the option. | 2.33.3 |\n\n#### DropdownDividerOption Type\n\n| Property | Type | Description | Version |\n| --- | --- | --- | --- |\n| key? | `string \\| number` | Divider ID (should be unique). |  |\n| show? | `boolean` | Whether to show the option. | 2.33.3 |\n| type | `'divider'` | The type of the DropdownDividerOption. |  |\n\n#### DropdownGroupOption Type\n\n| Property | Type | Description | Version |\n| --- | --- | --- | --- |\n| children? | `Array<DropdownOption \\| DropdownDividerOption>` | Children options of DropdownGroupOption. |  |\n| icon? | `() => VNodeChild` | Custom rendering function of the group icon. |  |\n| label? | `string` | Group label value. |  |\n| key? | `string \\| number` | Group ID (should be unique). |  |\n| show? | `boolean` | Whether to show the option. | 2.33.3 |\n| type | `'group'` | The type of the DropdownGroupOption. |  |\n\n#### DropdownRenderOption Type\n\n| Property | Type | Description | Version |\n| --- | --- | --- | --- |\n| key? | `string \\| number` | Render option ID (should be unique). |  |\n| render? | `() => VNodeChild` | Render function of the option content. |  |\n| show? | `boolean` | Whether to show the option. | 2.33.3 |\n| type | `'render'` | The type of the DropdownRenderOption. |  |\n"
  },
  {
    "path": "src/dropdown/demos/enUS/manual-position.demo.vue",
    "content": "<markdown>\n# Manual Position\n\nNote: When using manual position, `trigger` must be set to `'manual'`. In addition, you need to listen to the update:show callback to update the value of show, ensuring that shortcut operations such as the Esc key can close the menu normally.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { useMessage } from 'naive-ui'\nimport { nextTick, ref } from 'vue'\n\nconst options = [\n  {\n    label: 'Jay Gatsby',\n    key: 'jay gatsby'\n  },\n  {\n    label: 'Daisy Buchanan',\n    key: 'daisy buchanan'\n  },\n  {\n    type: 'divider',\n    key: 'd1'\n  },\n  {\n    label: 'Nick Carraway',\n    key: 'nick carraway'\n  },\n  {\n    label: 'Others',\n    key: 'others1',\n    children: [\n      {\n        label: 'Jordan Baker',\n        key: 'jordan baker'\n      },\n      {\n        label: 'Tom Buchanan',\n        key: 'tom buchanan'\n      },\n      {\n        label: 'Others',\n        key: 'others2',\n        children: [\n          {\n            label: 'Chicken',\n            key: 'chicken'\n          },\n          {\n            label: 'Beef',\n            key: 'beef'\n          }\n        ]\n      }\n    ]\n  }\n]\n\nconst message = useMessage()\n\nconst showDropdown = ref(false)\nconst x = ref(0)\nconst y = ref(0)\n\nfunction handleSelect(key: string | number) {\n  showDropdown.value = false\n  message.info(String(key))\n}\n\nfunction handleContextMenu(e: MouseEvent) {\n  e.preventDefault()\n  showDropdown.value = false\n  nextTick().then(() => {\n    showDropdown.value = true\n    x.value = e.clientX\n    y.value = e.clientY\n  })\n}\n\nfunction onClickoutside() {\n  message.info('clickoutside')\n  showDropdown.value = false\n}\n\nfunction handleUpdateShow(show: boolean) {\n  showDropdown.value = show\n}\n</script>\n\n<template>\n  <div\n    style=\"width: 200px; height: 200px; background-color: rgba(0, 128, 0, 0.5)\"\n    @contextmenu=\"handleContextMenu\"\n  >\n    Right Click\n  </div>\n  <n-dropdown\n    placement=\"bottom-start\"\n    trigger=\"manual\"\n    :x=\"x\"\n    :y=\"y\"\n    :options=\"options\"\n    :show=\"showDropdown\"\n    :on-clickoutside=\"onClickoutside\"\n    @update:show=\"handleUpdateShow\"\n    @select=\"handleSelect\"\n  />\n</template>\n"
  },
  {
    "path": "src/dropdown/demos/enUS/option-props.demo.vue",
    "content": "<markdown>\n# Custom Option Props\n\nBind anything you want.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { useMessage } from 'naive-ui'\n\nconst message = useMessage()\nconst options = [\n  {\n    label: 'Marina Bay Sands',\n    key: 'marina bay sands',\n    props: {\n      onClick: () => {\n        message.success('Good!')\n      }\n    }\n  },\n  {\n    label: 'Brown\\'s Hotel, London',\n    key: 'brown\\'s hotel, london',\n    children: [\n      {\n        label: 'Chicken',\n        key: 'chicken',\n        disabled: true,\n        props: {\n          onClick: () => {\n            message.info('Okay')\n          }\n        }\n      },\n      {\n        label: 'Beef',\n        key: 'beef'\n      }\n    ]\n  },\n  {\n    label: 'Atlantis Bahamas, Nassau',\n    key: 'atlantis nahamas, nassau',\n    props: {\n      onMousedown: () => {\n        message.warning('Key down')\n      }\n    }\n  }\n]\n\nfunction handleSelect(key: string | number) {\n  message.info(String(key))\n}\n</script>\n\n<template>\n  <n-dropdown trigger=\"hover\" :options=\"options\" @select=\"handleSelect\">\n    <n-button>Go For a Trip</n-button>\n  </n-dropdown>\n</template>\n"
  },
  {
    "path": "src/dropdown/demos/enUS/placement.demo.vue",
    "content": "<markdown>\n# Placement\n\nDropdown options can be aligned using the `placement` property.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { useMessage } from 'naive-ui'\n\nconst message = useMessage()\nconst options = [\n  {\n    label: 'Marina Bay Sands',\n    key: 'marina bay sands'\n  },\n  {\n    label: 'Brown\\'s Hotel, London',\n    key: 'brown\\'s hotel, london'\n  },\n  {\n    label: 'Atlantis Bahamas, Nassau',\n    key: 'atlantis bahamas, nassau'\n  },\n  {\n    label: 'The Beverly Hills Hotel, Los Angeles',\n    key: 'the beverly hills hotel, los angeles'\n  }\n]\n\nfunction handleSelect(key: string | number) {\n  message.info(String(key))\n}\n</script>\n\n<template>\n  <n-dropdown\n    trigger=\"hover\"\n    placement=\"bottom-start\"\n    :options=\"options\"\n    @select=\"handleSelect\"\n  >\n    <n-button>Go For a Trip</n-button>\n  </n-dropdown>\n</template>\n"
  },
  {
    "path": "src/dropdown/demos/enUS/render-option.demo.vue",
    "content": "<markdown>\n# Add Tooltip for Option\n\nYou can use `render-option` to add tooltip for an option.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { DropdownGroupOption, DropdownOption } from 'naive-ui'\nimport type { VNode } from 'vue'\nimport { NTooltip, useMessage } from 'naive-ui'\nimport { h } from 'vue'\n\nconst message = useMessage()\n\nfunction renderOption({\n  node,\n  option\n}: {\n  node: VNode\n  option: DropdownOption | DropdownGroupOption\n}) {\n  return h(\n    NTooltip,\n    { keepAliveOnHover: false, style: { width: 'max-content' } },\n    {\n      trigger: () => [node],\n      default: () => option.key\n    }\n  )\n}\n\nconst options = [\n  {\n    label: 'Marina Bay Sands',\n    key: 'marina bay sands',\n    disabled: true\n  },\n  {\n    label: 'Brown\\'s Hotel, London',\n    key: 'brown\\'s hotel, london'\n  },\n  {\n    label: 'Atlantis Bahamas, Nassau',\n    key: 'atlantis nahamas, nassau'\n  },\n  {\n    label: 'The Beverly Hills Hotel, Los Angeles',\n    key: 'the beverly hills hotel, los angeles'\n  }\n]\n\nfunction handleSelect(key: string | number) {\n  message.info(String(key))\n}\n</script>\n\n<template>\n  <n-dropdown\n    trigger=\"hover\"\n    :options=\"options\"\n    :render-option=\"renderOption\"\n    @select=\"handleSelect\"\n  >\n    <n-button>Go For a Trip</n-button>\n  </n-dropdown>\n</template>\n"
  },
  {
    "path": "src/dropdown/demos/enUS/render.demo.vue",
    "content": "<markdown>\n# Pure Render Content\n\nYou can simply render some content unrelated to option data. In this case, you can add an option with `type='render'`.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { NAvatar, NText, useMessage } from 'naive-ui'\nimport { h } from 'vue'\n\nfunction renderCustomHeader() {\n  return h(\n    'div',\n    {\n      style: 'display: flex; align-items: center; padding: 8px 12px;'\n    },\n    [\n      h(NAvatar, {\n        round: true,\n        style: 'margin-right: 12px;',\n        src: 'https://07akioni.oss-cn-beijing.aliyuncs.com/demo1.JPG'\n      }),\n      h('div', null, [\n        h('div', null, [\n          h(NText, { depth: 2 }, { default: () => 'Office Worker' })\n        ]),\n        h('div', { style: 'font-size: 12px;' }, [\n          h(\n            NText,\n            { depth: 3 },\n            {\n              default: () =>\n                'No doubt, you are the brightest star in the office'\n            }\n          )\n        ])\n      ])\n    ]\n  )\n}\n\nconst message = useMessage()\nconst options = [\n  {\n    key: 'header',\n    type: 'render',\n    render: renderCustomHeader\n  },\n  {\n    key: 'header-divider',\n    type: 'divider'\n  },\n  {\n    label: 'Processed 342 group messages',\n    key: 'stmt1'\n  },\n  {\n    label: 'Mentioned 58 times',\n    key: 'stmt2'\n  },\n  {\n    label: 'Joined 17 groups',\n    key: 'stmt3'\n  }\n]\n\nfunction handleSelect(key: string | number) {\n  message.info(String(key))\n}\n</script>\n\n<template>\n  <n-dropdown trigger=\"hover\" :options=\"options\" @select=\"handleSelect\">\n    <n-button>2021 Week 36</n-button>\n  </n-dropdown>\n</template>\n"
  },
  {
    "path": "src/dropdown/demos/enUS/size.demo.vue",
    "content": "<markdown>\n# Size\n\nA dropdown has different sizes.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { useMessage } from 'naive-ui'\n\nconst options = [\n  {\n    label: 'Jay Gatsby',\n    key: 'jay gatsby'\n  },\n  {\n    label: 'Daisy Buchanan',\n    key: 'daisy buchanan'\n  },\n  {\n    type: 'divider',\n    key: 'd1'\n  },\n  {\n    label: 'Nick Carraway',\n    key: 'nick carraway'\n  },\n  {\n    label: 'Others',\n    key: 'others1',\n    children: [\n      {\n        label: 'Jordan Baker',\n        key: 'jordan baker'\n      },\n      {\n        label: 'Tom Buchanan',\n        key: 'tom buchanan'\n      },\n      {\n        label: 'Others',\n        key: 'others2',\n        children: [\n          {\n            label: 'Chicken',\n            key: 'chicken'\n          },\n          {\n            label: 'Beef',\n            key: 'beef'\n          }\n        ]\n      }\n    ]\n  }\n]\n\nconst message = useMessage()\nfunction handleSelect(key: string | number) {\n  message.info(String(key))\n}\n</script>\n\n<template>\n  <n-space>\n    <n-dropdown\n      placement=\"bottom-start\"\n      trigger=\"click\"\n      size=\"small\"\n      :options=\"options\"\n      @select=\"handleSelect\"\n    >\n      <n-button>Small</n-button>\n    </n-dropdown>\n    <n-dropdown\n      placement=\"bottom-start\"\n      trigger=\"click\"\n      size=\"medium\"\n      :options=\"options\"\n      @select=\"handleSelect\"\n    >\n      <n-button>Medium</n-button>\n    </n-dropdown>\n    <n-dropdown\n      placement=\"bottom-start\"\n      trigger=\"click\"\n      size=\"large\"\n      :options=\"options\"\n      @select=\"handleSelect\"\n    >\n      <n-button>Large</n-button>\n    </n-dropdown>\n    <n-dropdown\n      placement=\"bottom-start\"\n      trigger=\"click\"\n      size=\"huge\"\n      :options=\"options\"\n      @select=\"handleSelect\"\n    >\n      <n-button>Huge</n-button>\n    </n-dropdown>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/dropdown/demos/enUS/trigger.demo.vue",
    "content": "<markdown>\n# Trigger\n\nDifferent trigger methods for dropdown.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { useMessage } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst message = useMessage()\nconst showDropdown = ref(false)\n\nconst options = [\n  {\n    label: 'Marina Bay Sands',\n    key: 'marina bay sands',\n    disabled: true\n  },\n  {\n    label: 'Brown\\'s Hotel, London',\n    key: 'brown\\'s hotel, london'\n  },\n  {\n    label: 'Atlantis Bahamas, Nassau',\n    key: 'atlantis nahamas, nassau'\n  },\n  {\n    label: 'The Beverly Hills Hotel, Los Angeles',\n    key: 'the beverly hills hotel, los angeles'\n  }\n]\n\nfunction handleSelect(key: string | number) {\n  message.info(String(key))\n}\n\nfunction handleClick() {\n  showDropdown.value = !showDropdown.value\n}\n</script>\n\n<template>\n  <n-space>\n    <n-dropdown trigger=\"hover\" :options=\"options\" @select=\"handleSelect\">\n      <n-button>Hover!</n-button>\n    </n-dropdown>\n    <n-dropdown trigger=\"click\" :options=\"options\" @select=\"handleSelect\">\n      <n-button>Click!</n-button>\n    </n-dropdown>\n    <n-dropdown :show=\"showDropdown\" :options=\"options\" @select=\"handleSelect\">\n      <n-button @click=\"handleClick\">\n        Oh! I'll Handle it Manually!\n      </n-button>\n    </n-dropdown>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/dropdown/demos/zhCN/arrow.demo.vue",
    "content": "<markdown>\n# 显示箭头\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { useMessage } from 'naive-ui'\n\nconst message = useMessage()\nconst options = [\n  {\n    label: '滨海湾金沙，新加坡',\n    key: 'marina bay sands',\n    disabled: true\n  },\n  {\n    label: '布朗酒店，伦敦',\n    key: 'brown\\'s hotel, london'\n  },\n  {\n    label: '亚特兰蒂斯巴哈马，拿骚',\n    key: 'atlantis nahamas, nassau'\n  },\n  {\n    label: '比佛利山庄酒店，洛杉矶',\n    key: 'the beverly hills hotel, los angeles'\n  }\n]\n\nfunction handleSelect(key: string | number) {\n  message.info(String(key))\n}\n</script>\n\n<template>\n  <n-dropdown\n    trigger=\"click\"\n    :options=\"options\"\n    :show-arrow=\"true\"\n    @select=\"handleSelect\"\n  >\n    <n-button>找个地方休息</n-button>\n  </n-dropdown>\n</template>\n"
  },
  {
    "path": "src/dropdown/demos/zhCN/basic.demo.vue",
    "content": "<markdown>\n# 基础用法\n\n下拉菜单的基础用法。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { useMessage } from 'naive-ui'\n\nconst message = useMessage()\nconst options = [\n  {\n    label: '滨海湾金沙，新加坡',\n    key: 'marina bay sands',\n    disabled: true\n  },\n  {\n    label: '布朗酒店，伦敦',\n    key: 'brown\\'s hotel, london'\n  },\n  {\n    label: '亚特兰蒂斯巴哈马，拿骚',\n    key: 'atlantis nahamas, nassau'\n  },\n  {\n    label: '比佛利山庄酒店，洛杉矶',\n    key: 'the beverly hills hotel, los angeles'\n  }\n]\n\nfunction handleSelect(key: string | number) {\n  message.info(String(key))\n}\n</script>\n\n<template>\n  <n-dropdown trigger=\"hover\" :options=\"options\" @select=\"handleSelect\">\n    <n-button>找个地方休息</n-button>\n  </n-dropdown>\n</template>\n"
  },
  {
    "path": "src/dropdown/demos/zhCN/batch-render.demo.vue",
    "content": "<markdown>\n# 批量渲染\n\n注意：`render-label` 会对 group 类型的标签生效，可通过 `option.type` 进行设置。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { DropdownOption } from 'naive-ui'\nimport type { VNodeChild } from 'vue'\nimport { CashOutline as CashIcon } from '@vicons/ionicons5'\nimport { NIcon } from 'naive-ui'\nimport { h } from 'vue'\n\nconst options = [\n  {\n    type: 'group',\n    label: '主角和吃的',\n    key: 'main',\n    children: [\n      {\n        label: '杰·盖茨比',\n        key: 'jay gatsby'\n      },\n      {\n        label: '黛西·布坎南',\n        key: 'daisy buchanan'\n      },\n      {\n        label: '尼克·卡拉威',\n        key: 'nick carraway'\n      },\n      {\n        label: '吃的',\n        key: 'food',\n        children: [\n          {\n            label: '鸡肉',\n            key: 'chicken'\n          },\n          {\n            label: '牛肉',\n            key: 'beef'\n          }\n        ]\n      }\n    ]\n  }\n]\n\nfunction renderDropdownLabel(option: DropdownOption) {\n  if (option.type === 'group') {\n    return option.label as VNodeChild\n  }\n  return h(\n    'a',\n    {\n      href: '',\n      target: '_blank'\n    },\n    {\n      default: () => option.label as VNodeChild\n    }\n  )\n}\n\nfunction renderDropdownIcon() {\n  return h(NIcon, null, {\n    default: () => h(CashIcon)\n  })\n}\n</script>\n\n<template>\n  <n-dropdown\n    :options=\"options\"\n    placement=\"bottom-start\"\n    trigger=\"click\"\n    :render-label=\"renderDropdownLabel\"\n    :render-icon=\"renderDropdownIcon\"\n  >\n    <n-button>我是批量渲染</n-button>\n  </n-dropdown>\n</template>\n"
  },
  {
    "path": "src/dropdown/demos/zhCN/cascade.demo.vue",
    "content": "<markdown>\n# 多级\n\n下拉菜单可以是多级的。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { CashOutline as CashIcon } from '@vicons/ionicons5'\nimport { NIcon, useMessage } from 'naive-ui'\nimport { h } from 'vue'\n\nconst options = [\n  {\n    label: '杰·盖茨比',\n    key: 'jay gatsby'\n  },\n  {\n    label: '黛西·布坎南',\n    icon() {\n      return h(NIcon, null, {\n        default: () => h(CashIcon)\n      })\n    },\n    key: 'daisy buchanan'\n  },\n  {\n    type: 'divider',\n    key: 'd1'\n  },\n  {\n    label: '尼克·卡拉威',\n    key: 'nick carraway'\n  },\n  {\n    label: '其他',\n    key: 'others1',\n    children: [\n      {\n        label: '乔丹·贝克',\n        key: 'jordan baker'\n      },\n      {\n        label: '汤姆·布坎南',\n        key: 'tom buchanan'\n      },\n      {\n        label: '其他',\n        key: 'others2',\n        disabled: true,\n        children: [\n          {\n            label: '鸡肉',\n            key: 'chicken'\n          },\n          {\n            label: '牛肉',\n            key: 'beef'\n          }\n        ]\n      }\n    ]\n  }\n]\n\nconst message = useMessage()\nfunction handleSelect(key: string | number) {\n  message.info(String(key))\n}\n</script>\n\n<template>\n  <n-dropdown\n    :options=\"options\"\n    placement=\"bottom-start\"\n    trigger=\"click\"\n    @select=\"handleSelect\"\n  >\n    <n-button>人物和食物</n-button>\n  </n-dropdown>\n</template>\n"
  },
  {
    "path": "src/dropdown/demos/zhCN/group-debug.demo.vue",
    "content": "<markdown>\n# 成组\n\n弄个选项组。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { CashOutline as CashIcon } from '@vicons/ionicons5'\nimport { NIcon, useMessage } from 'naive-ui'\nimport { h } from 'vue'\n\nconst options = [\n  {\n    type: 'group',\n    label: '主角和吃的',\n    key: 'main',\n    children: [\n      {\n        label: '杰·盖茨比',\n        key: 'jay gatsby'\n      },\n      {\n        label: '黛西·布坎南',\n        icon() {\n          return h(NIcon, null, {\n            default: () => h(CashIcon)\n          })\n        },\n        key: 'daisy buchanan'\n      },\n      {\n        label: '尼克·卡拉威',\n        key: 'nick carraway'\n      },\n      {\n        label: '吃的',\n        key: 'food',\n        children: [\n          {\n            label: '鸡肉',\n            key: 'chicken'\n          },\n          {\n            label: '牛肉',\n            key: 'beef'\n          }\n        ]\n      }\n    ]\n  },\n  {\n    type: 'divider',\n    key: 'd1'\n  },\n  {\n    label: '其他角色',\n    key: 'others1',\n    children: [\n      {\n        label: '乔丹·贝克',\n        key: 'jordan baker'\n      },\n      {\n        label: '汤姆·布坎南',\n        key: 'tom buchanan'\n      }\n    ]\n  }\n]\n\nconst message = useMessage()\nfunction handleSelect(key: string | number) {\n  message.info(String(key))\n}\n</script>\n\n<template>\n  <n-dropdown\n    :options=\"options\"\n    placement=\"bottom-start\"\n    trigger=\"click\"\n    @select=\"handleSelect\"\n  >\n    <n-button>里面有组</n-button>\n  </n-dropdown>\n</template>\n"
  },
  {
    "path": "src/dropdown/demos/zhCN/icon.demo.vue",
    "content": "<markdown>\n# 图标\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { Component } from 'vue'\nimport {\n  Pencil as EditIcon,\n  LogOutOutline as LogoutIcon,\n  PersonCircleOutline as UserIcon\n} from '@vicons/ionicons5'\nimport { NIcon } from 'naive-ui'\nimport { h } from 'vue'\n\nfunction renderIcon(icon: Component) {\n  return () => {\n    return h(NIcon, null, {\n      default: () => h(icon)\n    })\n  }\n}\n\nconst options = [\n  {\n    label: '用户资料',\n    key: 'profile',\n    icon: renderIcon(UserIcon)\n  },\n  {\n    label: '编辑用户资料',\n    key: 'editProfile',\n    icon: renderIcon(EditIcon)\n  },\n  {\n    label: '退出登录',\n    key: 'logout',\n    icon: renderIcon(LogoutIcon)\n  }\n]\n</script>\n\n<template>\n  <n-dropdown :options=\"options\">\n    <n-button>用户资料</n-button>\n  </n-dropdown>\n</template>\n"
  },
  {
    "path": "src/dropdown/demos/zhCN/index.demo-entry.md",
    "content": "# 下拉菜单 Dropdown\n\n当你想触发一些操作的时候。\n\n## 演示\n\n```demo\nbasic.vue\nicon.vue\ntrigger.vue\ncascade.vue\narrow.vue\nplacement.vue\nsize.vue\ngroup-debug.vue\nbatch-render.vue\nmanual-position.vue\nrender.vue\noption-props.vue\nrender-option.vue\nscrollable-debug.vue\n```\n\n## API\n\n### Dropdown Props\n\n| 名称 | 类型 | 默认值 | 说明 | 版本 |\n| --- | --- | --- | --- | --- |\n| animated | `boolean` | `true` | 弹出弹窗时使用动画 |  |\n| inverted | `boolean` | `false` | 使用反转样式 |  |\n| children-field | `string` | `'children'` | children 的字段名 |  |\n| keyboard | `boolean` | `true` | 是否支持键盘操作（注意和其他内容键盘操作可能的冲突） |  |\n| key-field | `string` | `'key'` | key 的字段名 |  |\n| label-field | `string` | `'label'` | label 的字段名 |  |\n| node-props | `(option: DropdownOption \\| DropdownGroupOption) => HTMLAttributes` | `undefined` | 批量处理下拉菜单选项的 HTML 属性 | 2.29.1 |\n| menu-props | `(option: DropdownOption \\| undefined, options: (DropdownOption \\| DropdownGroupOption)[]) => HTMLAttributes` | `undefined` | 批量处理下拉菜单的 HTML 属性 | 2.31.0 |\n| options | `Array<DropdownOption \\| DropdownGroupOption \\| DropdownDividerOption \\| DropdownRenderOption>` | `[]` | 下拉菜单传入的 options |  |\n| render-icon | `(option: DropdownOption) => VNodeChild` | `undefined` | 批量处理下拉菜单图标渲染 |  |\n| render-label | `(option: DropdownOption) => VNodeChild` | `undefined` | 批量处理下拉菜单标签渲染 |  |\n| render-option | `(props: { node: VNode, option: DropdownOption \\| DropdownGroupOption }) => VNodeChild` | `undefined` | 批量处理下拉菜单渲染 | 2.29.1 |\n| size | `'small'\\|'medium'\\|'large'\\|'huge'` | `'medium'` | 下拉菜单的尺寸大小 |  |\n| on-clickoutside | `(e: MouseEvent) => void` | `undefined` | clickoutside 的时候触发的回调函数 |  |\n| on-select | `(key: string \\| number, option: DropdownOption) => void` | `undefined` | select 选中时触发的回调函数 |  |\n\n对于其他 Props，例如 `placement`，请参考 [Popover Props](popover#Popover-Props)。注意 `raw` 属性不可用。\n\n#### DropdownOption Type\n\n| 属性 | 类型 | 说明 | 版本 |\n| --- | --- | --- | --- |\n| children? | `Array<DropdownOption \\| DropdownDividerOption \\| DropdownGroupOption>` | 子菜单的 children 项 |  |\n| disabled? | `boolean` | 是否禁用 |  |\n| icon? | `() => VNodeChild` | 支持通过 render 方法自定义 icon |  |\n| key? | `string \\| number` | 需要唯一 |  |\n| label? | `string \\| () => VNodeChild` | 显示的 label 值 |  |\n| props? | `HTMLAttributes` | 自定义选项属性 |  |\n| show? | `boolean` | 是否展示选项 | 2.33.3 |\n\n#### DropdownDividerOption Type\n\n| 属性  | 类型               | 说明         | 版本   |\n| ----- | ------------------ | ------------ | ------ |\n| key?  | `string \\| number` | 需要唯一     |        |\n| show? | `boolean`          | 是否展示选项 | 2.33.3 |\n| type  | `'divider'`        | 分割线的类型 |        |\n\n#### DropdownGroupOption Type\n\n| 属性 | 类型 | 说明 | 版本 |\n| --- | --- | --- | --- |\n| children? | `Array<DropdownOption \\| DropdownDividerOption>` | `DropdownGroupOption` 的 children 项 |  |\n| icon? | `() => VNodeChild` | 支持通过 render 方法自定义 icon |  |\n| key? | `string \\| number` | 需要唯一 |  |\n| label? | `string` | 显示的 label 值 |  |\n| show? | `boolean` | 是否展示选项 | 2.33.3 |\n| type | `'group'` | `DropdownGroupOption` 的类型 |  |\n\n#### DropdownRenderOption Type\n\n| 属性    | 类型               | 说明                          | 版本   |\n| ------- | ------------------ | ----------------------------- | ------ |\n| key?    | `string \\| number` | 渲染选项 ID（应该是唯一的）   |        |\n| render? | `() => VNodeChild` | 选项内容的渲染功能            |        |\n| show?   | `boolean`          | 是否展示选项                  | 2.33.3 |\n| type    | `'render'`         | `DropdownRenderOption` 的类型 |        |\n"
  },
  {
    "path": "src/dropdown/demos/zhCN/manual-position.demo.vue",
    "content": "<markdown>\n# 手动定位\n\n注意：手动定位时，`trigger` 属性必须为 `'manual'`。此外，你需要监听 `update:show` 回调来更新 `show` 值，以确保 `Esc` 键等快捷操作能正常关闭菜单。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { useMessage } from 'naive-ui'\nimport { nextTick, ref } from 'vue'\n\nconst options = [\n  {\n    label: '杰·盖茨比',\n    key: 'jay gatsby'\n  },\n  {\n    label: '黛西·布坎南',\n    key: 'daisy buchanan'\n  },\n  {\n    type: 'divider',\n    key: 'd1'\n  },\n  {\n    label: '尼克·卡拉威',\n    key: 'nick carraway'\n  },\n  {\n    label: '其他',\n    key: 'others1',\n    children: [\n      {\n        label: '乔丹·贝克',\n        key: 'jordan baker'\n      },\n      {\n        label: '汤姆·布坎南',\n        key: 'tom buchanan'\n      },\n      {\n        label: '其他',\n        key: 'others2',\n        children: [\n          {\n            label: '鸡肉',\n            key: 'chicken'\n          },\n          {\n            label: '牛肉',\n            key: 'beef'\n          }\n        ]\n      }\n    ]\n  }\n]\n\nconst message = useMessage()\n\nconst showDropdown = ref(false)\nconst x = ref(0)\nconst y = ref(0)\n\nfunction handleSelect(key: string | number) {\n  showDropdown.value = false\n  message.info(String(key))\n}\n\nfunction handleContextMenu(e: MouseEvent) {\n  e.preventDefault()\n  showDropdown.value = false\n  nextTick().then(() => {\n    showDropdown.value = true\n    x.value = e.clientX\n    y.value = e.clientY\n  })\n}\n\nfunction onClickoutside() {\n  message.info('clickoutside')\n  showDropdown.value = false\n}\n\nfunction handleUpdateShow(show: boolean) {\n  showDropdown.value = show\n}\n</script>\n\n<template>\n  <div\n    style=\"width: 200px; height: 200px; background-color: rgba(0, 128, 0, 0.5)\"\n    @contextmenu=\"handleContextMenu\"\n  >\n    右击\n  </div>\n  <n-dropdown\n    placement=\"bottom-start\"\n    trigger=\"manual\"\n    :x=\"x\"\n    :y=\"y\"\n    :options=\"options\"\n    :show=\"showDropdown\"\n    :on-clickoutside=\"onClickoutside\"\n    @update:show=\"handleUpdateShow\"\n    @select=\"handleSelect\"\n  />\n</template>\n"
  },
  {
    "path": "src/dropdown/demos/zhCN/option-props.demo.vue",
    "content": "<markdown>\n# 自定义选项属性\n\n爱绑啥绑啥。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { useMessage } from 'naive-ui'\n\nconst message = useMessage()\nconst options = [\n  {\n    label: '滨海湾金沙，新加坡',\n    key: 'marina bay sands',\n    props: {\n      onClick: () => {\n        message.success('Good!')\n      }\n    }\n  },\n  {\n    label: '布朗酒店，伦敦',\n    key: 'brown\\'s hotel, london',\n    children: [\n      {\n        label: '鸡肉',\n        key: 'chicken',\n        disabled: true,\n        props: {\n          onClick: () => {\n            message.info('Okay')\n          }\n        }\n      },\n      {\n        label: '牛肉',\n        key: 'beef'\n      }\n    ]\n  },\n  {\n    label: '亚特兰蒂斯巴哈马，拿骚',\n    key: 'atlantis nahamas, nassau',\n    props: {\n      onMousedown: () => {\n        message.warning('Key down')\n      }\n    }\n  }\n]\n\nfunction handleSelect(key: string | number) {\n  message.info(String(key))\n}\n</script>\n\n<template>\n  <n-dropdown trigger=\"hover\" :options=\"options\" @select=\"handleSelect\">\n    <n-button>找个地方休息</n-button>\n  </n-dropdown>\n</template>\n"
  },
  {
    "path": "src/dropdown/demos/zhCN/placement.demo.vue",
    "content": "<markdown>\n# 弹出位置\n\n使用不同的弹出位置。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { useMessage } from 'naive-ui'\n\nconst message = useMessage()\nconst options = [\n  {\n    label: '滨海湾金沙，新加坡',\n    key: 'marina bay sands'\n  },\n  {\n    label: '布朗酒店，伦敦',\n    key: 'brown\\'s hotel, london'\n  },\n  {\n    label: '亚特兰蒂斯巴哈马，拿骚',\n    key: 'atlantis bahamas, nassau'\n  },\n  {\n    label: '比佛利山庄酒店，洛杉矶',\n    key: 'the beverly hills hotel, los angeles'\n  }\n]\n\nfunction handleSelect(key: string | number) {\n  message.info(String(key))\n}\n</script>\n\n<template>\n  <n-dropdown\n    trigger=\"hover\"\n    placement=\"bottom-start\"\n    :options=\"options\"\n    @select=\"handleSelect\"\n  >\n    <n-button> 找个地方休息 </n-button>\n  </n-dropdown>\n</template>\n"
  },
  {
    "path": "src/dropdown/demos/zhCN/render-option.demo.vue",
    "content": "<markdown>\n# 为选项增加 Tooltip\n\n你可以通过 `render-option` 为选项增添 Tooltip。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { DropdownGroupOption, DropdownOption } from 'naive-ui'\nimport type { VNode } from 'vue'\nimport { NTooltip, useMessage } from 'naive-ui'\nimport { h } from 'vue'\n\nconst message = useMessage()\n\nfunction renderOption({\n  node,\n  option\n}: {\n  node: VNode\n  option: DropdownOption | DropdownGroupOption\n}) {\n  return h(\n    NTooltip,\n    { keepAliveOnHover: false, style: { width: 'max-content' } },\n    {\n      trigger: () => [node],\n      default: () => option.key\n    }\n  )\n}\n\nconst options = [\n  {\n    label: '滨海湾金沙，新加坡',\n    key: 'marina bay sands',\n    disabled: true\n  },\n  {\n    label: '布朗酒店，伦敦',\n    key: 'brown\\'s hotel, london'\n  },\n  {\n    label: '亚特兰蒂斯巴哈马，拿骚',\n    key: 'atlantis nahamas, nassau'\n  },\n  {\n    label: '比佛利山庄酒店，洛杉矶',\n    key: 'the beverly hills hotel, los angeles'\n  }\n]\n\nfunction handleSelect(key: string | number) {\n  message.info(String(key))\n}\n</script>\n\n<template>\n  <n-dropdown\n    trigger=\"hover\"\n    :options=\"options\"\n    :render-option=\"renderOption\"\n    @select=\"handleSelect\"\n  >\n    <n-button>找个地方休息</n-button>\n  </n-dropdown>\n</template>\n"
  },
  {
    "path": "src/dropdown/demos/zhCN/render.demo.vue",
    "content": "<markdown>\n# 纯渲染的内容\n\n你可以单纯的只是想渲染一些内容，和选项数据无关。此时你可以加入 `type='render'` 的选项。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { NAvatar, NText, useMessage } from 'naive-ui'\nimport { h } from 'vue'\n\nfunction renderCustomHeader() {\n  return h(\n    'div',\n    {\n      style: 'display: flex; align-items: center; padding: 8px 12px;'\n    },\n    [\n      h(NAvatar, {\n        round: true,\n        style: 'margin-right: 12px;',\n        src: 'https://07akioni.oss-cn-beijing.aliyuncs.com/demo1.JPG'\n      }),\n      h('div', null, [\n        h('div', null, [h(NText, { depth: 2 }, { default: () => '打工仔' })]),\n        h('div', { style: 'font-size: 12px;' }, [\n          h(\n            NText,\n            { depth: 3 },\n            { default: () => '毫无疑问，你是办公室里最亮的星' }\n          )\n        ])\n      ])\n    ]\n  )\n}\n\nconst message = useMessage()\nconst options = [\n  {\n    key: 'header',\n    type: 'render',\n    render: renderCustomHeader\n  },\n  {\n    key: 'header-divider',\n    type: 'divider'\n  },\n  {\n    label: '处理群消息 342 条',\n    key: 'stmt1'\n  },\n  {\n    label: '被 @ 58 次',\n    key: 'stmt2'\n  },\n  {\n    label: '加入群 17 个',\n    key: 'stmt3'\n  }\n]\n\nfunction handleSelect(key: string | number) {\n  message.info(String(key))\n}\n</script>\n\n<template>\n  <n-dropdown trigger=\"hover\" :options=\"options\" @select=\"handleSelect\">\n    <n-button>2021年 第36周</n-button>\n  </n-dropdown>\n</template>\n"
  },
  {
    "path": "src/dropdown/demos/zhCN/scrollable-debug.demo.vue",
    "content": "<markdown>\n# Scrollable debug\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { DropdownMenuProps } from 'naive-ui'\n\nconst options = [\n  {\n    label: '1',\n    key: '1'\n  },\n  {\n    label: '2',\n    key: '2'\n  },\n  {\n    label: '3',\n    key: '3'\n  },\n  {\n    label: '4',\n    key: '4'\n  },\n  {\n    label: '5',\n    key: '5'\n  },\n  {\n    label: '6',\n    key: '6'\n  },\n  {\n    label: '7',\n    key: '7',\n    children: [\n      {\n        label: '11',\n        key: '11'\n      },\n      {\n        label: '12',\n        key: '12'\n      },\n      {\n        label: '13',\n        key: '13'\n      },\n      {\n        label: '14',\n        key: '14'\n      },\n      {\n        label: '15',\n        key: '15'\n      },\n      {\n        label: '16',\n        key: '16'\n      },\n      {\n        label: '17',\n        key: '17',\n        children: [\n          {\n            label: '21',\n            key: '21'\n          },\n          {\n            label: '22',\n            key: '22'\n          },\n          {\n            label: '23',\n            key: '23'\n          },\n          {\n            label: '24',\n            key: '24'\n          },\n          {\n            label: '25',\n            key: '25'\n          },\n          {\n            label: '26',\n            key: '26'\n          },\n          {\n            label: '27',\n            key: '27'\n          }\n        ]\n      }\n    ]\n  }\n]\n\nconst menuProps: DropdownMenuProps = (option, options) => {\n  console.log(option, options)\n  return { style: 'max-height: 200px;' }\n}\n</script>\n\n<template>\n  <n-dropdown\n    :options=\"options\"\n    placement=\"bottom-start\"\n    trigger=\"click\"\n    scrollable\n    :menu-props=\"menuProps\"\n  >\n    <n-button>Scrollable</n-button>\n  </n-dropdown>\n</template>\n"
  },
  {
    "path": "src/dropdown/demos/zhCN/size.demo.vue",
    "content": "<markdown>\n# 尺寸\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { useMessage } from 'naive-ui'\n\nconst options = [\n  {\n    label: '杰·盖茨比',\n    key: 'jay gatsby'\n  },\n  {\n    label: '黛西·布坎南',\n    key: 'daisy buchanan'\n  },\n  {\n    type: 'divider',\n    key: 'd1'\n  },\n  {\n    label: '尼克·卡拉威',\n    key: 'nick carraway'\n  },\n  {\n    label: '其他',\n    key: 'others1',\n    children: [\n      {\n        label: '乔丹·贝克',\n        key: 'jordan baker'\n      },\n      {\n        label: '汤姆·布坎南',\n        key: 'tom buchanan'\n      },\n      {\n        label: '其他',\n        key: 'others2',\n        children: [\n          {\n            label: '鸡肉',\n            key: 'chicken'\n          },\n          {\n            label: '牛肉',\n            key: 'beef'\n          }\n        ]\n      }\n    ]\n  }\n]\n\nconst message = useMessage()\nfunction handleSelect(key: string | number) {\n  message.info(String(key))\n}\n</script>\n\n<template>\n  <n-space>\n    <n-dropdown\n      placement=\"bottom-start\"\n      trigger=\"click\"\n      size=\"small\"\n      :options=\"options\"\n      @select=\"handleSelect\"\n    >\n      <n-button>小号</n-button>\n    </n-dropdown>\n    <n-dropdown\n      placement=\"bottom-start\"\n      trigger=\"click\"\n      size=\"medium\"\n      :options=\"options\"\n      @select=\"handleSelect\"\n    >\n      <n-button>中号</n-button>\n    </n-dropdown>\n    <n-dropdown\n      placement=\"bottom-start\"\n      trigger=\"click\"\n      size=\"large\"\n      :options=\"options\"\n      @select=\"handleSelect\"\n    >\n      <n-button>大号</n-button>\n    </n-dropdown>\n    <n-dropdown\n      placement=\"bottom-start\"\n      trigger=\"click\"\n      size=\"huge\"\n      :options=\"options\"\n      @select=\"handleSelect\"\n    >\n      <n-button>巨大号</n-button>\n    </n-dropdown>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/dropdown/demos/zhCN/trigger.demo.vue",
    "content": "<markdown>\n# 触发\n\n下拉菜单不同的触发方式。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { useMessage } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst message = useMessage()\nconst showDropdown = ref(false)\n\nconst options = [\n  {\n    label: '滨海湾金沙，新加坡',\n    key: 'marina bay sands',\n    disabled: true\n  },\n  {\n    label: '布朗酒店，伦敦',\n    key: 'brown\\'s hotel, london'\n  },\n  {\n    label: '亚特兰蒂斯巴哈马，拿骚',\n    key: 'atlantis nahamas, nassau'\n  },\n  {\n    label: '比佛利山庄酒店，洛杉矶',\n    key: 'the beverly hills hotel, los angeles'\n  }\n]\n\nfunction handleSelect(key: string | number) {\n  message.info(String(key))\n}\n\nfunction handleClick() {\n  showDropdown.value = !showDropdown.value\n}\n</script>\n\n<template>\n  <n-space>\n    <n-dropdown trigger=\"hover\" :options=\"options\" @select=\"handleSelect\">\n      <n-button>悬浮！</n-button>\n    </n-dropdown>\n    <n-dropdown trigger=\"click\" :options=\"options\" @select=\"handleSelect\">\n      <n-button>点击！</n-button>\n    </n-dropdown>\n    <n-dropdown :show=\"showDropdown\" :options=\"options\" @select=\"handleSelect\">\n      <n-button @click=\"handleClick\">\n        噢！我要自己手动！\n      </n-button>\n    </n-dropdown>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/dropdown/index.ts",
    "content": "export { dropdownProps, default as NDropdown } from './src/Dropdown'\nexport type { DropdownProps } from './src/Dropdown'\nexport type {\n  DropdownDividerOption,\n  DropdownGroupOption,\n  DropdownMenuProps,\n  NodeProps as DropdownNodeProps,\n  DropdownOption,\n  DropdownRenderOption\n} from './src/interface'\nexport type * from './src/public-types'\n"
  },
  {
    "path": "src/dropdown/src/Dropdown.tsx",
    "content": "import type { Key, TreeNode } from 'treemate'\nimport type { PropType, Ref } from 'vue'\nimport type { FollowerPlacement } from 'vueuc'\nimport type { ThemeProps } from '../../_mixins'\nimport type { ExtractPublicPropTypes, MaybeArray } from '../../_utils'\nimport type { InternalRenderBody } from '../../popover/src/interface'\nimport type { PopoverInternalProps } from '../../popover/src/Popover'\nimport type { DropdownTheme } from '../styles'\nimport type {\n  DropdownGroupOption,\n  DropdownIgnoredOption,\n  DropdownMenuProps,\n  DropdownMixedOption,\n  DropdownOption,\n  DropdownRenderOption,\n  NodeProps,\n  OnUpdateValue,\n  OnUpdateValueImpl,\n  RenderIcon,\n  RenderIconImpl,\n  RenderLabel,\n  RenderLabelImpl,\n  RenderOption,\n  RenderOptionImpl\n} from './interface'\nimport type { DropdownSize } from './public-types'\nimport { createTreeMate } from 'treemate'\nimport { useKeyboard, useMemo, useMergedState } from 'vooks'\nimport {\n  computed,\n  defineComponent,\n  h,\n  mergeProps,\n  provide,\n  ref,\n  toRef,\n  watch\n} from 'vue'\nimport { useConfig, useTheme, useThemeClass } from '../../_mixins'\nimport { call, createKey, createRefSetter, keep } from '../../_utils'\nimport { NPopover } from '../../popover'\nimport { popoverBaseProps } from '../../popover/src/Popover'\nimport { dropdownLight } from '../styles'\nimport { dropdownInjectionKey } from './context'\nimport NDropdownMenu from './DropdownMenu'\nimport style from './styles/index.cssr'\n\nexport interface DropdownInjection {\n  renderLabelRef: Ref<RenderLabelImpl | undefined>\n  renderIconRef: Ref<RenderIconImpl | undefined>\n  renderOptionRef: Ref<RenderOptionImpl | undefined>\n  menuPropsRef: Ref<DropdownMenuProps | undefined>\n  nodePropsRef: Ref<NodeProps | undefined>\n  hoverKeyRef: Ref<Key | null>\n  keyboardKeyRef: Ref<Key | null>\n  lastToggledSubmenuKeyRef: Ref<Key | null>\n  pendingKeyPathRef: Ref<Key[]>\n  activeKeyPathRef: Ref<Key[]>\n  animatedRef: Ref<boolean>\n  mergedShowRef: Ref<boolean>\n  labelFieldRef: Ref<string>\n  childrenFieldRef: Ref<string>\n  doSelect: OnUpdateValueImpl\n  doUpdateShow: (value: boolean) => void\n}\n\nconst dropdownBaseProps = {\n  animated: {\n    type: Boolean,\n    default: true\n  },\n  keyboard: {\n    type: Boolean,\n    default: true\n  },\n  size: String as PropType<DropdownSize>,\n  inverted: Boolean,\n  placement: {\n    type: String as PropType<FollowerPlacement>,\n    default: 'bottom'\n  },\n  onSelect: [Function, Array] as PropType<MaybeArray<OnUpdateValue>>,\n  options: {\n    type: Array as PropType<DropdownMixedOption[]>,\n    default: () => []\n  },\n  menuProps: Function as PropType<DropdownMenuProps>,\n  showArrow: Boolean,\n  renderLabel: Function as PropType<RenderLabel>,\n  renderIcon: Function as PropType<RenderIcon>,\n  renderOption: Function as PropType<RenderOption>,\n  nodeProps: Function as PropType<NodeProps>,\n  labelField: {\n    type: String,\n    default: 'label'\n  },\n  keyField: {\n    type: String,\n    default: 'key'\n  },\n  childrenField: {\n    type: String,\n    default: 'children'\n  },\n  // for menu, not documented\n  value: [String, Number] as PropType<Key | null>\n} as const\n\nconst popoverPropKeys = Object.keys(popoverBaseProps) as Array<\n  keyof typeof popoverBaseProps\n>\n\nexport const dropdownProps = {\n  ...popoverBaseProps,\n  ...dropdownBaseProps,\n  ...(useTheme.props as ThemeProps<DropdownTheme>)\n} as const\n\nexport type DropdownProps = ExtractPublicPropTypes<typeof dropdownProps>\n\nexport default defineComponent({\n  name: 'Dropdown',\n  inheritAttrs: false,\n  props: dropdownProps,\n  setup(props) {\n    const uncontrolledShowRef = ref(false)\n    const mergedShowRef = useMergedState(\n      toRef(props, 'show'),\n      uncontrolledShowRef\n    )\n    const treemateRef = computed(() => {\n      const { keyField, childrenField } = props\n      return createTreeMate<\n        DropdownOption | DropdownRenderOption,\n        DropdownGroupOption,\n        DropdownIgnoredOption\n      >(props.options, {\n        getKey(node) {\n          return node[keyField] as any\n        },\n        getDisabled(node) {\n          return node.disabled === true\n        },\n        getIgnored(node) {\n          return node.type === 'divider' || node.type === 'render'\n        },\n        getChildren(node) {\n          return node[childrenField] as any\n        }\n      })\n    })\n    const tmNodesRef = computed(() => {\n      return treemateRef.value.treeNodes\n    })\n\n    const hoverKeyRef = ref<Key | null>(null)\n    const keyboardKeyRef = ref<Key | null>(null)\n    const lastToggledSubmenuKeyRef = ref<Key | null>(null)\n    const pendingKeyRef = computed(() => {\n      return (\n        hoverKeyRef.value\n        ?? keyboardKeyRef.value\n        ?? lastToggledSubmenuKeyRef.value\n        ?? null\n      )\n    })\n\n    const pendingKeyPathRef = computed(\n      () => treemateRef.value.getPath(pendingKeyRef.value).keyPath\n    )\n\n    const activeKeyPathRef = computed(\n      () => treemateRef.value.getPath(props.value).keyPath\n    )\n\n    const keyboardEnabledRef = useMemo(() => {\n      return props.keyboard && mergedShowRef.value\n    })\n\n    useKeyboard(\n      {\n        keydown: {\n          ArrowUp: {\n            prevent: true,\n            handler: handleKeydownUp\n          },\n          ArrowRight: {\n            prevent: true,\n            handler: handleKeydownRight\n          },\n          ArrowDown: {\n            prevent: true,\n            handler: handleKeydownDown\n          },\n          ArrowLeft: {\n            prevent: true,\n            handler: handleKeydownLeft\n          },\n          Enter: {\n            prevent: true,\n            handler: handleKeydownEnter\n          },\n          Escape: handleKeydownEsc\n        }\n      },\n      keyboardEnabledRef\n    )\n\n    const { mergedClsPrefixRef, inlineThemeDisabled, mergedComponentPropsRef }\n      = useConfig(props)\n    const mergedSizeRef = computed(() => {\n      return (\n        props.size || mergedComponentPropsRef?.value?.Dropdown?.size || 'medium'\n      )\n    })\n\n    const themeRef = useTheme(\n      'Dropdown',\n      '-dropdown',\n      style,\n      dropdownLight,\n      props,\n      mergedClsPrefixRef\n    )\n\n    provide(dropdownInjectionKey, {\n      labelFieldRef: toRef(props, 'labelField'),\n      childrenFieldRef: toRef(props, 'childrenField'),\n      renderLabelRef: toRef(props, 'renderLabel') as Ref<\n        RenderLabelImpl | undefined\n      >,\n      renderIconRef: toRef(props, 'renderIcon') as Ref<\n        RenderIconImpl | undefined\n      >,\n      hoverKeyRef,\n      keyboardKeyRef,\n      lastToggledSubmenuKeyRef,\n      pendingKeyPathRef,\n      activeKeyPathRef,\n      animatedRef: toRef(props, 'animated'),\n      mergedShowRef,\n      nodePropsRef: toRef(props, 'nodeProps'),\n      renderOptionRef: toRef(props, 'renderOption') as Ref<\n        RenderOptionImpl | undefined\n      >,\n      menuPropsRef: toRef(props, 'menuProps'),\n      doSelect,\n      doUpdateShow\n    })\n    // watch\n    watch(mergedShowRef, (value) => {\n      if (!props.animated && !value) {\n        clearPendingState()\n      }\n    })\n    // methods\n    function doSelect(key: Key, node: DropdownOption): void {\n      const { onSelect } = props\n      if (onSelect)\n        call(onSelect as OnUpdateValueImpl, key, node)\n    }\n    function doUpdateShow(value: boolean): void {\n      const { 'onUpdate:show': _onUpdateShow, onUpdateShow } = props\n      if (_onUpdateShow)\n        call(_onUpdateShow, value)\n      if (onUpdateShow)\n        call(onUpdateShow, value)\n      uncontrolledShowRef.value = value\n    }\n    function clearPendingState(): void {\n      hoverKeyRef.value = null\n      keyboardKeyRef.value = null\n      lastToggledSubmenuKeyRef.value = null\n    }\n    function handleKeydownEsc(): void {\n      doUpdateShow(false)\n    }\n    function handleKeydownLeft(): void {\n      handleKeydown('left')\n    }\n    function handleKeydownRight(): void {\n      handleKeydown('right')\n    }\n    function handleKeydownUp(): void {\n      handleKeydown('up')\n    }\n    function handleKeydownDown(): void {\n      handleKeydown('down')\n    }\n    function handleKeydownEnter(): void {\n      const pendingNode = getPendingNode()\n      if (pendingNode?.isLeaf && mergedShowRef.value) {\n        doSelect(pendingNode.key, pendingNode.rawNode)\n        doUpdateShow(false)\n      }\n    }\n    function getPendingNode(): TreeNode<DropdownOption> | null {\n      const { value: treeMate } = treemateRef\n      const { value: pendingKey } = pendingKeyRef\n      if (!treeMate || pendingKey === null)\n        return null\n      return treeMate.getNode(pendingKey) ?? null\n    }\n    function handleKeydown(direction: 'up' | 'right' | 'down' | 'left'): void {\n      const { value: pendingKey } = pendingKeyRef\n      const {\n        value: { getFirstAvailableNode }\n      } = treemateRef\n      let nextKeyboardKey: Key | null = null\n      if (pendingKey === null) {\n        const firstNode = getFirstAvailableNode()\n        if (firstNode !== null) {\n          nextKeyboardKey = firstNode.key\n        }\n      }\n      else {\n        const currentNode = getPendingNode()\n        if (currentNode) {\n          let nextNode\n          switch (direction) {\n            case 'down':\n              nextNode = currentNode.getNext()\n              break\n            case 'up':\n              nextNode = currentNode.getPrev()\n              break\n            case 'right':\n              nextNode = currentNode.getChild()\n              break\n            case 'left':\n              nextNode = currentNode.getParent()\n              break\n          }\n          if (nextNode)\n            nextKeyboardKey = nextNode.key\n        }\n      }\n      if (nextKeyboardKey !== null) {\n        hoverKeyRef.value = null\n        keyboardKeyRef.value = nextKeyboardKey\n      }\n    }\n    const cssVarsRef = computed(() => {\n      const { inverted } = props\n      const size = mergedSizeRef.value\n      const {\n        common: { cubicBezierEaseInOut },\n        self\n      } = themeRef.value\n      const {\n        padding,\n        dividerColor,\n        borderRadius,\n        optionOpacityDisabled,\n        [createKey('optionIconSuffixWidth', size)]: optionIconSuffixWidth,\n        [createKey('optionSuffixWidth', size)]: optionSuffixWidth,\n        [createKey('optionIconPrefixWidth', size)]: optionIconPrefixWidth,\n        [createKey('optionPrefixWidth', size)]: optionPrefixWidth,\n        [createKey('fontSize', size)]: fontSize,\n        [createKey('optionHeight', size)]: optionHeight,\n        [createKey('optionIconSize', size)]: optionIconSize\n      } = self\n      const vars: any = {\n        '--n-bezier': cubicBezierEaseInOut,\n        '--n-font-size': fontSize,\n        '--n-padding': padding,\n        '--n-border-radius': borderRadius,\n        '--n-option-height': optionHeight,\n        '--n-option-prefix-width': optionPrefixWidth,\n        '--n-option-icon-prefix-width': optionIconPrefixWidth,\n        '--n-option-suffix-width': optionSuffixWidth,\n        '--n-option-icon-suffix-width': optionIconSuffixWidth,\n        '--n-option-icon-size': optionIconSize,\n        '--n-divider-color': dividerColor,\n        '--n-option-opacity-disabled': optionOpacityDisabled\n      }\n      // writing like this is the fastest method\n      if (inverted) {\n        vars['--n-color'] = self.colorInverted\n        vars['--n-option-color-hover'] = self.optionColorHoverInverted\n        vars['--n-option-color-active'] = self.optionColorActiveInverted\n        vars['--n-option-text-color'] = self.optionTextColorInverted\n        vars['--n-option-text-color-hover'] = self.optionTextColorHoverInverted\n        vars['--n-option-text-color-active']\n          = self.optionTextColorActiveInverted\n        vars['--n-option-text-color-child-active']\n          = self.optionTextColorChildActiveInverted\n        vars['--n-prefix-color'] = self.prefixColorInverted\n        vars['--n-suffix-color'] = self.suffixColorInverted\n        vars['--n-group-header-text-color'] = self.groupHeaderTextColorInverted\n      }\n      else {\n        vars['--n-color'] = self.color\n        vars['--n-option-color-hover'] = self.optionColorHover\n        vars['--n-option-color-active'] = self.optionColorActive\n        vars['--n-option-text-color'] = self.optionTextColor\n        vars['--n-option-text-color-hover'] = self.optionTextColorHover\n        vars['--n-option-text-color-active'] = self.optionTextColorActive\n        vars['--n-option-text-color-child-active']\n          = self.optionTextColorChildActive\n        vars['--n-prefix-color'] = self.prefixColor\n        vars['--n-suffix-color'] = self.suffixColor\n        vars['--n-group-header-text-color'] = self.groupHeaderTextColor\n      }\n      return vars\n    })\n    const themeClassHandle = inlineThemeDisabled\n      ? useThemeClass(\n          'dropdown',\n          computed(\n            () => `${mergedSizeRef.value[0]}${props.inverted ? 'i' : ''}`\n          ),\n          cssVarsRef,\n          props\n        )\n      : undefined\n    return {\n      mergedClsPrefix: mergedClsPrefixRef,\n      mergedTheme: themeRef,\n      mergedSize: mergedSizeRef,\n      // data\n      tmNodes: tmNodesRef,\n      // show\n      mergedShow: mergedShowRef,\n      // methods\n      handleAfterLeave: () => {\n        if (!props.animated)\n          return\n        clearPendingState()\n      },\n      doUpdateShow,\n      cssVars: inlineThemeDisabled ? undefined : cssVarsRef,\n      themeClass: themeClassHandle?.themeClass,\n      onRender: themeClassHandle?.onRender\n    }\n  },\n  render() {\n    const renderPopoverBody: InternalRenderBody = (\n      className,\n      ref,\n      style,\n      onMouseenter,\n      onMouseleave\n    ) => {\n      const { mergedClsPrefix, menuProps } = this\n      this.onRender?.()\n      const menuNodeProps\n        = menuProps?.(\n          undefined,\n          this.tmNodes.map(v => v.rawNode)\n        ) || {}\n      const dropdownProps = {\n        ref: createRefSetter(ref),\n        class: [\n          className,\n          `${mergedClsPrefix}-dropdown`,\n          `${mergedClsPrefix}-dropdown--${this.mergedSize}-size`,\n          this.themeClass\n        ],\n        clsPrefix: mergedClsPrefix,\n        tmNodes: this.tmNodes,\n        style: [...style, this.cssVars],\n        showArrow: this.showArrow,\n        arrowStyle: this.arrowStyle,\n        scrollable: this.scrollable,\n        onMouseenter,\n        onMouseleave\n      }\n      return h(\n        NDropdownMenu,\n        mergeProps(\n          this.$attrs,\n          dropdownProps,\n          menuNodeProps\n        ) as typeof dropdownProps\n      )\n    }\n    const { mergedTheme } = this\n    const popoverProps: PopoverInternalProps = {\n      show: this.mergedShow,\n      theme: mergedTheme.peers.Popover,\n      themeOverrides: mergedTheme.peerOverrides.Popover,\n      internalOnAfterLeave: this.handleAfterLeave,\n      internalRenderBody: renderPopoverBody,\n      onUpdateShow: this.doUpdateShow,\n      'onUpdate:show': undefined\n    }\n    return (\n      <NPopover {...keep(this.$props, popoverPropKeys)} {...popoverProps}>\n        {{\n          trigger: () => this.$slots.default?.()\n        }}\n      </NPopover>\n    )\n  }\n})\n"
  },
  {
    "path": "src/dropdown/src/DropdownDivider.tsx",
    "content": "import { defineComponent, h } from 'vue'\n\nexport default defineComponent({\n  name: 'DropdownDivider',\n  props: {\n    clsPrefix: {\n      type: String,\n      required: true\n    }\n  },\n  render() {\n    return <div class={`${this.clsPrefix}-dropdown-divider`} />\n  }\n})\n"
  },
  {
    "path": "src/dropdown/src/DropdownGroup.tsx",
    "content": "import type { TreeNode } from 'treemate'\nimport type { PropType } from 'vue'\nimport type {\n  DropdownGroupOption,\n  DropdownIgnoredOption,\n  DropdownOption\n} from './interface'\nimport { defineComponent, Fragment, h } from 'vue'\n\nimport { warn } from '../../_utils'\nimport NDropdownDivider from './DropdownDivider'\nimport NDropdownGroupHeader from './DropdownGroupHeader'\nimport NDropdownOption from './DropdownOption'\nimport { isDividerNode } from './utils'\n\nexport default defineComponent({\n  name: 'NDropdownGroup',\n  props: {\n    clsPrefix: {\n      type: String,\n      required: true\n    },\n    tmNode: {\n      type: Object as PropType<\n        TreeNode<DropdownOption, DropdownGroupOption, DropdownIgnoredOption>\n      >,\n      required: true\n    },\n    parentKey: {\n      type: [String, Number] as PropType<string | number | null>,\n      default: null\n    }\n  },\n  render() {\n    const { tmNode, parentKey, clsPrefix } = this\n    const { children } = tmNode\n    return (\n      <>\n        <NDropdownGroupHeader\n          clsPrefix={clsPrefix}\n          tmNode={tmNode}\n          key={tmNode.key}\n        />\n        {children?.map((child) => {\n          const { rawNode } = child\n          if (rawNode.show === false)\n            return null\n          if (isDividerNode(rawNode)) {\n            return h(NDropdownDivider, {\n              clsPrefix,\n              key: child.key\n            })\n          }\n          if (child.isGroup) {\n            warn(\n              'dropdown',\n              '`group` node is not allowed to be put in `group` node.'\n            )\n            return null\n          }\n          return (\n            <NDropdownOption\n              clsPrefix={clsPrefix}\n              tmNode={child}\n              parentKey={parentKey}\n              key={child.key}\n            />\n          )\n        })}\n      </>\n    )\n  }\n})\n"
  },
  {
    "path": "src/dropdown/src/DropdownGroupHeader.tsx",
    "content": "import type { DropdownMixedOption } from './interface'\nimport { defineComponent, h, inject } from 'vue'\nimport { render } from '../../_utils'\nimport { dropdownInjectionKey, dropdownMenuInjectionKey } from './context'\n\nexport default defineComponent({\n  name: 'DropdownGroupHeader',\n  props: {\n    clsPrefix: {\n      type: String,\n      required: true\n    },\n    tmNode: {\n      type: Object,\n      required: true\n    }\n  },\n  setup() {\n    const { showIconRef, hasSubmenuRef } = inject(dropdownMenuInjectionKey)!\n\n    const { renderLabelRef, labelFieldRef, nodePropsRef, renderOptionRef }\n      = inject(dropdownInjectionKey)!\n\n    return {\n      labelField: labelFieldRef,\n      showIcon: showIconRef,\n      hasSubmenu: hasSubmenuRef,\n      renderLabel: renderLabelRef,\n      nodeProps: nodePropsRef,\n      renderOption: renderOptionRef\n    }\n  },\n  render() {\n    const {\n      clsPrefix,\n      hasSubmenu,\n      showIcon,\n      nodeProps,\n      renderLabel,\n      renderOption\n    } = this\n    const { rawNode } = this.tmNode\n    const node = (\n      <div\n        class={`${clsPrefix}-dropdown-option`}\n        {...nodeProps?.(rawNode as DropdownMixedOption)}\n      >\n        <div\n          class={`${clsPrefix}-dropdown-option-body ${clsPrefix}-dropdown-option-body--group`}\n        >\n          <div\n            data-dropdown-option\n            class={[\n              `${clsPrefix}-dropdown-option-body__prefix`,\n              showIcon && `${clsPrefix}-dropdown-option-body__prefix--show-icon`\n            ]}\n          >\n            {render(rawNode.icon)}\n          </div>\n          <div\n            class={`${clsPrefix}-dropdown-option-body__label`}\n            data-dropdown-option\n          >\n            {renderLabel\n              ? renderLabel(rawNode as DropdownMixedOption)\n              : render(rawNode.title ?? rawNode[this.labelField])}\n          </div>\n          <div\n            class={[\n              `${clsPrefix}-dropdown-option-body__suffix`,\n              hasSubmenu\n              && `${clsPrefix}-dropdown-option-body__suffix--has-submenu`\n            ]}\n            data-dropdown-option\n          />\n        </div>\n      </div>\n    )\n    if (renderOption) {\n      return renderOption({ node, option: rawNode })\n    }\n    return node\n  }\n})\n"
  },
  {
    "path": "src/dropdown/src/DropdownMenu.tsx",
    "content": "import type { TreeNode } from 'treemate'\nimport type { CSSProperties, PropType, Ref } from 'vue'\nimport type {\n  DropdownGroupOption,\n  DropdownIgnoredOption,\n  DropdownOption,\n  DropdownRenderOption\n} from './interface'\nimport { computed, defineComponent, h, inject, provide, ref } from 'vue'\nimport { NxScrollbar } from '../../_internal/scrollbar'\nimport { drawerBodyInjectionKey } from '../../drawer/src/interface'\nimport { modalBodyInjectionKey } from '../../modal/src/interface'\nimport { popoverBodyInjectionKey } from '../../popover/src/interface'\nimport { renderArrow } from '../../popover/src/PopoverBody'\n\nimport { dropdownInjectionKey, dropdownMenuInjectionKey } from './context'\n\nimport NDropdownDivider from './DropdownDivider'\nimport NDropdownGroup from './DropdownGroup'\nimport NDropdownOption from './DropdownOption'\nimport NDropdownRenderOption from './DropdownRenderOption'\nimport {\n  isDividerNode,\n  isGroupNode,\n  isRenderNode,\n  isSubmenuNode\n} from './utils'\n\nexport interface NDropdownMenuInjection {\n  showIconRef: Ref<boolean>\n  hasSubmenuRef: Ref<boolean>\n}\n\nexport default defineComponent({\n  name: 'DropdownMenu',\n  props: {\n    scrollable: Boolean,\n    showArrow: Boolean,\n    arrowStyle: [String, Object] as PropType<string | CSSProperties>,\n    clsPrefix: {\n      type: String,\n      required: true\n    },\n    tmNodes: {\n      type: Array as PropType<\n        Array<\n          TreeNode<DropdownOption, DropdownGroupOption, DropdownIgnoredOption>\n        >\n      >,\n      default: () => []\n    },\n    parentKey: {\n      type: [String, Number],\n      default: null\n    }\n  },\n  setup(props) {\n    const { renderIconRef, childrenFieldRef } = inject(dropdownInjectionKey)!\n    provide(dropdownMenuInjectionKey, {\n      showIconRef: computed(() => {\n        const renderIcon = renderIconRef.value\n        return props.tmNodes.some((tmNode) => {\n          if (tmNode.isGroup) {\n            return tmNode.children?.some(({ rawNode: rawChild }) =>\n              renderIcon ? renderIcon(rawChild) : rawChild.icon\n            )\n          }\n          const { rawNode } = tmNode\n          return renderIcon ? renderIcon(rawNode) : rawNode.icon\n        })\n      }),\n      hasSubmenuRef: computed(() => {\n        const { value: childrenField } = childrenFieldRef\n        return props.tmNodes.some((tmNode) => {\n          if (tmNode.isGroup) {\n            return tmNode.children?.some(({ rawNode: rawChild }) =>\n              isSubmenuNode(rawChild, childrenField)\n            )\n          }\n          const { rawNode } = tmNode\n          return isSubmenuNode(rawNode, childrenField)\n        })\n      })\n    })\n    const bodyRef = ref<HTMLElement | null>(null)\n    provide(modalBodyInjectionKey, null)\n    provide(drawerBodyInjectionKey, null)\n    provide(popoverBodyInjectionKey, bodyRef)\n    return {\n      bodyRef\n    }\n  },\n  render() {\n    const { parentKey, clsPrefix, scrollable } = this\n    const menuOptionsNode = this.tmNodes.map((tmNode) => {\n      const { rawNode } = tmNode\n      if (rawNode.show === false)\n        return null\n      if (isRenderNode(rawNode)) {\n        return (\n          <NDropdownRenderOption\n            tmNode={tmNode as unknown as TreeNode<DropdownRenderOption>}\n            key={tmNode.key}\n          />\n        )\n      }\n      if (isDividerNode(rawNode)) {\n        return <NDropdownDivider clsPrefix={clsPrefix} key={tmNode.key} />\n      }\n      if (isGroupNode(rawNode)) {\n        return (\n          <NDropdownGroup\n            clsPrefix={clsPrefix}\n            tmNode={tmNode}\n            parentKey={parentKey}\n            key={tmNode.key}\n          />\n        )\n      }\n      return (\n        <NDropdownOption\n          clsPrefix={clsPrefix}\n          tmNode={tmNode}\n          parentKey={parentKey}\n          key={tmNode.key}\n          props={rawNode.props}\n          scrollable={scrollable}\n        />\n      )\n    })\n    return (\n      <div\n        class={[\n          `${clsPrefix}-dropdown-menu`,\n          scrollable && `${clsPrefix}-dropdown-menu--scrollable`\n        ]}\n        ref=\"bodyRef\"\n      >\n        {scrollable ? (\n          <NxScrollbar contentClass={`${clsPrefix}-dropdown-menu__content`}>\n            {{\n              default: () => menuOptionsNode\n            }}\n          </NxScrollbar>\n        ) : (\n          menuOptionsNode\n        )}\n        {this.showArrow\n          ? renderArrow({\n              clsPrefix,\n              arrowStyle: this.arrowStyle,\n              arrowClass: undefined,\n              arrowWrapperClass: undefined,\n              arrowWrapperStyle: undefined\n            })\n          : null}\n      </div>\n    )\n  }\n})\n"
  },
  {
    "path": "src/dropdown/src/DropdownOption.tsx",
    "content": "import type { TreeNode } from 'treemate'\nimport type { HTMLAttributes, PropType, Ref, VNodeChild } from 'vue'\nimport type { FollowerPlacement } from 'vueuc'\nimport type {\n  MenuGroupOption,\n  MenuOptionSharedPart\n} from '../../menu/src/interface'\nimport type {\n  DropdownGroupOption,\n  DropdownIgnoredOption,\n  DropdownOption\n} from './interface'\nimport { happensIn } from 'seemly'\nimport { useMemo } from 'vooks'\nimport {\n  computed,\n  defineComponent,\n  h,\n  inject,\n  mergeProps,\n  provide,\n  ref,\n  Transition\n} from 'vue'\nimport { VBinder, VFollower, VTarget } from 'vueuc'\nimport { ChevronRightIcon } from '../../_internal/icons'\nimport { render, useDeferredTrue } from '../../_utils'\n\nimport { NIcon } from '../../icon'\nimport { popoverBodyInjectionKey } from '../../popover/src/interface'\nimport {\n  dropdownInjectionKey,\n  dropdownMenuInjectionKey,\n  dropdownOptionInjectionKey\n} from './context'\nimport NDropdownMenu from './DropdownMenu'\nimport { isSubmenuNode } from './utils'\n\nexport interface NDropdownOptionInjection {\n  enteringSubmenuRef: Ref<boolean>\n}\n\nexport default defineComponent({\n  name: 'DropdownOption',\n  props: {\n    clsPrefix: {\n      type: String,\n      required: true\n    },\n    tmNode: {\n      type: Object as PropType<\n        TreeNode<DropdownOption, DropdownGroupOption, DropdownIgnoredOption>\n      >,\n      required: true\n    },\n    parentKey: {\n      type: [String, Number] as PropType<string | number | null>,\n      default: null\n    },\n    placement: {\n      type: String as PropType<FollowerPlacement>,\n      default: 'right-start'\n    },\n    props: Object as PropType<HTMLAttributes>,\n    scrollable: Boolean\n  },\n  setup(props) {\n    const NDropdown = inject(dropdownInjectionKey)!\n    const {\n      hoverKeyRef,\n      keyboardKeyRef,\n      lastToggledSubmenuKeyRef,\n      pendingKeyPathRef,\n      activeKeyPathRef,\n      animatedRef,\n      mergedShowRef,\n      renderLabelRef,\n      renderIconRef,\n      labelFieldRef,\n      childrenFieldRef,\n      renderOptionRef,\n      nodePropsRef,\n      menuPropsRef\n    } = NDropdown\n    const NDropdownOption = inject(dropdownOptionInjectionKey, null)\n    const NDropdownMenu = inject(dropdownMenuInjectionKey)!\n    const NPopoverBody = inject(popoverBodyInjectionKey)!\n    const rawNodeRef = computed(() => props.tmNode.rawNode)\n    const hasSubmenuRef = computed(() => {\n      const { value: childrenField } = childrenFieldRef\n      return isSubmenuNode(props.tmNode.rawNode, childrenField)\n    })\n    const mergedDisabledRef = computed(() => {\n      const { disabled } = props.tmNode\n      return disabled\n    })\n    const showSubmenuRef = computed(() => {\n      if (!hasSubmenuRef.value)\n        return false\n      const { key, disabled } = props.tmNode\n      if (disabled)\n        return false\n      const { value: hoverKey } = hoverKeyRef\n      const { value: keyboardKey } = keyboardKeyRef\n      const { value: lastToggledSubmenuKey } = lastToggledSubmenuKeyRef\n      const { value: pendingKeyPath } = pendingKeyPathRef\n      if (hoverKey !== null)\n        return pendingKeyPath.includes(key)\n      if (keyboardKey !== null) {\n        return (\n          pendingKeyPath.includes(key)\n          && pendingKeyPath[pendingKeyPath.length - 1] !== key\n        )\n      }\n      if (lastToggledSubmenuKey !== null)\n        return pendingKeyPath.includes(key)\n      return false\n    })\n    const shouldDelayRef = computed(() => {\n      return keyboardKeyRef.value === null && !animatedRef.value\n    })\n    const deferredShowSubmenuRef = useDeferredTrue(\n      showSubmenuRef,\n      300,\n      shouldDelayRef\n    )\n    const parentEnteringSubmenuRef = computed(() => {\n      return !!NDropdownOption?.enteringSubmenuRef.value\n    })\n    const enteringSubmenuRef = ref(false)\n    provide(dropdownOptionInjectionKey, {\n      enteringSubmenuRef\n    })\n    // methods\n    function handleSubmenuBeforeEnter(): void {\n      enteringSubmenuRef.value = true\n    }\n    function handleSubmenuAfterEnter(): void {\n      enteringSubmenuRef.value = false\n    }\n    function handleMouseEnter(): void {\n      const { parentKey, tmNode } = props\n      if (tmNode.disabled)\n        return\n      if (!mergedShowRef.value)\n        return\n      lastToggledSubmenuKeyRef.value = parentKey\n      keyboardKeyRef.value = null\n      hoverKeyRef.value = tmNode.key\n    }\n    function handleMouseMove(): void {\n      const { tmNode } = props\n      if (tmNode.disabled)\n        return\n      if (!mergedShowRef.value)\n        return\n      if (hoverKeyRef.value === tmNode.key)\n        return\n      handleMouseEnter()\n    }\n    function handleMouseLeave(e: MouseEvent): void {\n      if (props.tmNode.disabled)\n        return\n      if (!mergedShowRef.value)\n        return\n      const { relatedTarget } = e\n      if (\n        relatedTarget\n        && !happensIn({ target: relatedTarget }, 'dropdownOption')\n        && !happensIn({ target: relatedTarget }, 'scrollbarRail')\n      ) {\n        hoverKeyRef.value = null\n      }\n    }\n    function handleClick(): void {\n      const { value: hasSubmenu } = hasSubmenuRef\n      const { tmNode } = props\n      if (!mergedShowRef.value)\n        return\n      if (!hasSubmenu && !tmNode.disabled) {\n        NDropdown.doSelect(\n          tmNode.key,\n          (tmNode as unknown as TreeNode<DropdownOption>).rawNode\n        )\n        NDropdown.doUpdateShow(false)\n      }\n    }\n\n    return {\n      labelField: labelFieldRef,\n      renderLabel: renderLabelRef,\n      renderIcon: renderIconRef,\n      siblingHasIcon: NDropdownMenu.showIconRef,\n      siblingHasSubmenu: NDropdownMenu.hasSubmenuRef,\n      menuProps: menuPropsRef,\n      popoverBody: NPopoverBody,\n      animated: animatedRef,\n      mergedShowSubmenu: computed(() => {\n        return deferredShowSubmenuRef.value && !parentEnteringSubmenuRef.value\n      }),\n      rawNode: rawNodeRef,\n      hasSubmenu: hasSubmenuRef,\n      pending: useMemo(() => {\n        const { value: pendingKeyPath } = pendingKeyPathRef\n        const { key } = props.tmNode\n        return pendingKeyPath.includes(key)\n      }),\n      childActive: useMemo(() => {\n        const { value: activeKeyPath } = activeKeyPathRef\n        const { key } = props.tmNode\n        const index = activeKeyPath.findIndex(k => key === k)\n        if (index === -1)\n          return false\n        return index < activeKeyPath.length - 1\n      }),\n      active: useMemo(() => {\n        const { value: activeKeyPath } = activeKeyPathRef\n        const { key } = props.tmNode\n        const index = activeKeyPath.findIndex(k => key === k)\n        if (index === -1)\n          return false\n        return index === activeKeyPath.length - 1\n      }),\n      mergedDisabled: mergedDisabledRef,\n      renderOption: renderOptionRef,\n      nodeProps: nodePropsRef,\n      handleClick,\n      handleMouseMove,\n      handleMouseEnter,\n      handleMouseLeave,\n      handleSubmenuBeforeEnter,\n      handleSubmenuAfterEnter\n    }\n  },\n  render() {\n    const {\n      animated,\n      rawNode,\n      mergedShowSubmenu,\n      clsPrefix,\n      siblingHasIcon,\n      siblingHasSubmenu,\n      renderLabel,\n      renderIcon,\n      renderOption,\n      nodeProps,\n      props,\n      scrollable\n    } = this\n    let submenuVNode: VNodeChild = null\n    if (mergedShowSubmenu) {\n      const submenuNodeProps = this.menuProps?.(\n        rawNode,\n        rawNode.children as Array<MenuOptionSharedPart | MenuGroupOption>\n      )\n      submenuVNode = (\n        <NDropdownMenu\n          {...submenuNodeProps}\n          clsPrefix={clsPrefix}\n          scrollable={this.scrollable}\n          tmNodes={this.tmNode.children}\n          parentKey={this.tmNode.key}\n        />\n      )\n    }\n\n    const builtinProps: HTMLAttributes = {\n      class: [\n        `${clsPrefix}-dropdown-option-body`,\n        this.pending && `${clsPrefix}-dropdown-option-body--pending`,\n        this.active && `${clsPrefix}-dropdown-option-body--active`,\n        this.childActive && `${clsPrefix}-dropdown-option-body--child-active`,\n        this.mergedDisabled && `${clsPrefix}-dropdown-option-body--disabled`\n      ],\n      onMousemove: this.handleMouseMove,\n      onMouseenter: this.handleMouseEnter,\n      onMouseleave: this.handleMouseLeave,\n      onClick: this.handleClick\n    }\n    const optionNodeProps = nodeProps?.(rawNode)\n    const node = (\n      <div\n        class={[`${clsPrefix}-dropdown-option`, optionNodeProps?.class]}\n        data-dropdown-option\n        {...optionNodeProps}\n      >\n        {h(\n          'div',\n          mergeProps(\n            builtinProps as Record<string, any>,\n            props as Record<string, any>\n          ),\n          [\n            <div\n              class={[\n                `${clsPrefix}-dropdown-option-body__prefix`,\n                siblingHasIcon\n                && `${clsPrefix}-dropdown-option-body__prefix--show-icon`\n              ]}\n            >\n              {[renderIcon ? renderIcon(rawNode) : render(rawNode.icon)]}\n            </div>,\n            <div\n              data-dropdown-option\n              class={`${clsPrefix}-dropdown-option-body__label`}\n            >\n              {/* TODO: Workaround, menu compatible */}\n              {renderLabel\n                ? renderLabel(rawNode)\n                : render(rawNode[this.labelField] ?? rawNode.title)}\n            </div>,\n            <div\n              data-dropdown-option\n              class={[\n                `${clsPrefix}-dropdown-option-body__suffix`,\n                siblingHasSubmenu\n                && `${clsPrefix}-dropdown-option-body__suffix--has-submenu`\n              ]}\n            >\n              {this.hasSubmenu ? (\n                <NIcon>\n                  {{\n                    default: () => <ChevronRightIcon />\n                  }}\n                </NIcon>\n              ) : null}\n            </div>\n          ]\n        )}\n        {this.hasSubmenu ? (\n          <VBinder>\n            {{\n              default: () => [\n                <VTarget>\n                  {{\n                    default: () => (\n                      <div class={`${clsPrefix}-dropdown-offset-container`}>\n                        <VFollower\n                          show={this.mergedShowSubmenu}\n                          placement={this.placement}\n                          to={\n                            scrollable\n                              ? this.popoverBody || undefined\n                              : undefined\n                          }\n                          teleportDisabled={!scrollable}\n                        >\n                          {{\n                            default: () => {\n                              return (\n                                <div\n                                  class={`${clsPrefix}-dropdown-menu-wrapper`}\n                                >\n                                  {animated ? (\n                                    <Transition\n                                      onBeforeEnter={\n                                        this.handleSubmenuBeforeEnter\n                                      }\n                                      onAfterEnter={\n                                        this.handleSubmenuAfterEnter\n                                      }\n                                      name=\"fade-in-scale-up-transition\"\n                                      appear\n                                    >\n                                      {{\n                                        default: () => submenuVNode\n                                      }}\n                                    </Transition>\n                                  ) : (\n                                    submenuVNode\n                                  )}\n                                </div>\n                              )\n                            }\n                          }}\n                        </VFollower>\n                      </div>\n                    )\n                  }}\n                </VTarget>\n              ]\n            }}\n          </VBinder>\n        ) : null}\n      </div>\n    )\n    if (renderOption) {\n      return renderOption({ node, option: rawNode })\n    }\n    return node\n  }\n})\n"
  },
  {
    "path": "src/dropdown/src/DropdownRenderOption.tsx",
    "content": "import type { TreeNode } from 'treemate'\nimport type { PropType } from 'vue'\nimport type { DropdownRenderOption } from './interface'\nimport { defineComponent, h } from 'vue'\n\nexport default defineComponent({\n  name: 'DropdownRenderOption',\n  props: {\n    tmNode: {\n      type: Object as PropType<TreeNode<DropdownRenderOption>>,\n      required: true\n    }\n  },\n  render() {\n    const {\n      rawNode: { render, props }\n    } = this.tmNode\n    return h('div', props, [render?.()])\n  }\n})\n"
  },
  {
    "path": "src/dropdown/src/context.ts",
    "content": "import type { DropdownInjection } from './Dropdown'\nimport type { NDropdownMenuInjection } from './DropdownMenu'\nimport type { NDropdownOptionInjection } from './DropdownOption'\nimport { createInjectionKey } from '../../_utils'\n\nexport const dropdownMenuInjectionKey\n  = createInjectionKey<NDropdownMenuInjection>('n-dropdown-menu')\n\nexport const dropdownInjectionKey\n  = createInjectionKey<DropdownInjection>('n-dropdown')\n\nexport const dropdownOptionInjectionKey\n  = createInjectionKey<NDropdownOptionInjection>('n-dropdown-option')\n"
  },
  {
    "path": "src/dropdown/src/interface.ts",
    "content": "import type { TreeNode } from 'treemate'\nimport type { HTMLAttributes, VNode, VNodeChild } from 'vue'\nimport type {\n  MenuDividerOption,\n  MenuGroupOption,\n  MenuIgnoredOption,\n  MenuNodeProps,\n  MenuOption,\n  MenuRenderOption\n} from '../../menu/src/interface'\n\nexport type Key = string | number\n\n// Aligned with MenuOption props, has some redundant fields\nexport type DropdownOption = MenuOption\nexport type DropdownGroupOption = MenuGroupOption\nexport type DropdownDividerOption = MenuDividerOption\nexport type DropdownRenderOption = MenuRenderOption\nexport type DropdownMixedOption\n  = | DropdownOption\n    | DropdownGroupOption\n    | DropdownDividerOption\n    | DropdownRenderOption\n\nexport type DropdownIgnoredOption = MenuIgnoredOption\n\nexport type DropdownIntersectionOption = DropdownOption & DropdownGroupOption\n\nexport type TmNode = TreeNode<\n  DropdownOption,\n  DropdownGroupOption,\n  DropdownIgnoredOption\n>\n\nexport type OnUpdateValue = <T extends string & number & (string | number)>(\n  value: T,\n  option: DropdownOption\n) => void\n\nexport type OnUpdateKeys = <\n  T extends string[] & number[] & Array<string | number>\n>(\n  keys: T\n) => void\n\nexport type OnUpdateValueImpl = <T extends string | number | (string | number)>(\n  value: T,\n  option: DropdownOption\n) => void\n\nexport type OnUpdateKeysImpl = <\n  T extends string[] | number[] | Array<string | number>\n>(\n  keys: T\n) => void\n\nexport type RenderLabelImpl = (option: DropdownMixedOption) => VNodeChild\n\nexport type RenderLabel = (option: DropdownIntersectionOption) => VNodeChild\n\nexport type RenderIconImpl = (option: DropdownMixedOption) => VNodeChild\n\nexport type RenderIcon = (option: DropdownIntersectionOption) => VNodeChild\n\nexport type RenderOption = (info: {\n  node: VNode\n  option: DropdownOption & DropdownGroupOption\n}) => VNodeChild\n\nexport type RenderOptionImpl = (info: {\n  node: VNode\n  option: DropdownOption | DropdownGroupOption\n}) => VNodeChild\n\nexport type NodeProps = MenuNodeProps\nexport type DropdownMenuProps = (\n  option: DropdownOption | undefined,\n  options: Array<DropdownOption | DropdownGroupOption>\n) => HTMLAttributes & Record<string, string | number | undefined>\n"
  },
  {
    "path": "src/dropdown/src/public-types.ts",
    "content": "export type DropdownSize = 'small' | 'medium' | 'large' | 'huge'\n"
  },
  {
    "path": "src/dropdown/src/styles/index.cssr.ts",
    "content": "import { fadeInScaleUpTransition } from '../../../_styles/transitions/fade-in-scale-up.cssr'\nimport { c, cB, cE, cM, cNotM } from '../../../_utils/cssr'\n\n// vars:\n// --n-bezier\n// --n-font-size\n// --n-padding\n// --n-border-radius\n// --n-option-height\n// --n-option-prefix-width\n// --n-option-icon-prefix-width\n// --n-option-suffix-width\n// --n-option-icon-suffix-width\n// --n-color\n// --n-option-color-hover\n// --n-option-color-active\n// --n-divider-color\n// --n-option-text-color\n// --n-option-text-color-hover\n// --n-option-text-color-active\n// --n-option-text-color-child-active\n// --n-prefix-color\n// --n-suffix-color\n// --n-option-icon-size\n// --n-option-opacity-disabled\n\n// shared with popover\n// --n-box-shadow\n\nexport default cB('dropdown-menu', `\n  transform-origin: var(--v-transform-origin);\n  background-color: var(--n-color);\n  border-radius: var(--n-border-radius);\n  box-shadow: var(--n-box-shadow);\n  position: relative;\n  transition:\n    background-color .3s var(--n-bezier),\n    box-shadow .3s var(--n-bezier);\n`, [\n  fadeInScaleUpTransition(),\n  cB('dropdown-option', `\n    position: relative;\n  `, [\n    c('a', `\n      text-decoration: none;\n      color: inherit;\n      outline: none;\n    `, [\n      c('&::before', `\n        content: \"\";\n        position: absolute;\n        left: 0;\n        right: 0;\n        top: 0;\n        bottom: 0;\n      `)\n    ]),\n    cB('dropdown-option-body', `\n      display: flex;\n      cursor: pointer;\n      position: relative;\n      height: var(--n-option-height);\n      line-height: var(--n-option-height);\n      font-size: var(--n-font-size);\n      color: var(--n-option-text-color);\n      transition: color .3s var(--n-bezier);\n    `, [\n      c('&::before', `\n        content: \"\";\n        position: absolute;\n        top: 0;\n        bottom: 0;\n        left: 4px;\n        right: 4px;\n        transition: background-color .3s var(--n-bezier);\n        border-radius: var(--n-border-radius);\n      `),\n      cNotM('disabled', [\n        cM('pending', `\n          color: var(--n-option-text-color-hover);\n        `, [\n          cE('prefix, suffix', `\n            color: var(--n-option-text-color-hover);\n          `),\n          c('&::before', 'background-color: var(--n-option-color-hover);')\n        ]),\n        cM('active', `\n          color: var(--n-option-text-color-active);\n        `, [\n          cE('prefix, suffix', `\n            color: var(--n-option-text-color-active);\n          `),\n          c('&::before', 'background-color: var(--n-option-color-active);')\n        ]),\n        cM('child-active', `\n          color: var(--n-option-text-color-child-active);\n        `, [\n          cE('prefix, suffix', `\n            color: var(--n-option-text-color-child-active);\n          `)\n        ])\n      ]),\n      cM('disabled', `\n        cursor: not-allowed;\n        opacity: var(--n-option-opacity-disabled);\n      `),\n      cM('group', `\n        font-size: calc(var(--n-font-size) - 1px);\n        color: var(--n-group-header-text-color);\n      `, [\n        cE('prefix', `\n          width: calc(var(--n-option-prefix-width) / 2);\n        `, [\n          cM('show-icon', `\n            width: calc(var(--n-option-icon-prefix-width) / 2);\n          `)\n        ])\n      ]),\n      cE('prefix', `\n        width: var(--n-option-prefix-width);\n        display: flex;\n        justify-content: center;\n        align-items: center;\n        color: var(--n-prefix-color);\n        transition: color .3s var(--n-bezier);\n        z-index: 1;\n      `, [\n        cM('show-icon', `\n          width: var(--n-option-icon-prefix-width);\n        `),\n        cB('icon', `\n          font-size: var(--n-option-icon-size);\n        `)\n      ]),\n      cE('label', `\n        white-space: nowrap;\n        flex: 1;\n        z-index: 1;\n      `),\n      cE('suffix', `\n        box-sizing: border-box;\n        flex-grow: 0;\n        flex-shrink: 0;\n        display: flex;\n        justify-content: flex-end;\n        align-items: center;\n        min-width: var(--n-option-suffix-width);\n        padding: 0 8px;\n        transition: color .3s var(--n-bezier);\n        color: var(--n-suffix-color);\n        z-index: 1;\n      `, [\n        cM('has-submenu', `\n          width: var(--n-option-icon-suffix-width);\n        `),\n        cB('icon', `\n          font-size: var(--n-option-icon-size);\n        `)\n      ]),\n      cB('dropdown-menu', 'pointer-events: all;')\n    ]),\n    cB('dropdown-offset-container', `\n      pointer-events: none;\n      position: absolute;\n      left: 0;\n      right: 0;\n      top: -4px;\n      bottom: -4px;\n    `)\n  ]),\n  cB('dropdown-divider', `\n    transition: background-color .3s var(--n-bezier);\n    background-color: var(--n-divider-color);\n    height: 1px;\n    margin: 4px 0;\n  `),\n  cB('dropdown-menu-wrapper', `\n    transform-origin: var(--v-transform-origin);\n    width: fit-content;\n  `),\n  c('>', [\n    cB('scrollbar', `\n      height: inherit;\n      max-height: inherit;\n    `)\n  ]),\n  cNotM('scrollable', `\n    padding: var(--n-padding);\n  `),\n  cM('scrollable', [\n    cE('content', `\n      padding: var(--n-padding);\n    `)\n  ])\n])\n"
  },
  {
    "path": "src/dropdown/src/utils.ts",
    "content": "import type { DropdownMixedOption, DropdownRenderOption } from './interface'\n\nexport function isSubmenuNode(\n  rawNode: DropdownMixedOption,\n  childrenField: string\n): boolean {\n  return (\n    rawNode.type === 'submenu'\n    || (rawNode.type === undefined && rawNode[childrenField] !== undefined)\n  )\n}\n\nexport function isGroupNode(rawNode: DropdownMixedOption): boolean {\n  return rawNode.type === 'group'\n}\n\nexport function isDividerNode(rawNode: DropdownMixedOption): boolean {\n  return rawNode.type === 'divider'\n}\n\nexport function isRenderNode(\n  rawNode: DropdownMixedOption\n): rawNode is DropdownRenderOption {\n  return rawNode.type === 'render'\n}\n"
  },
  {
    "path": "src/dropdown/styles/_common.ts",
    "content": "export default {\n  padding: '4px 0',\n  optionIconSizeSmall: '14px',\n  optionIconSizeMedium: '16px',\n  optionIconSizeLarge: '16px',\n  optionIconSizeHuge: '18px',\n  optionSuffixWidthSmall: '14px',\n  optionSuffixWidthMedium: '14px',\n  optionSuffixWidthLarge: '16px',\n  optionSuffixWidthHuge: '16px',\n  optionIconSuffixWidthSmall: '32px',\n  optionIconSuffixWidthMedium: '32px',\n  optionIconSuffixWidthLarge: '36px',\n  optionIconSuffixWidthHuge: '36px',\n  optionPrefixWidthSmall: '14px',\n  optionPrefixWidthMedium: '14px',\n  optionPrefixWidthLarge: '16px',\n  optionPrefixWidthHuge: '16px',\n  optionIconPrefixWidthSmall: '36px',\n  optionIconPrefixWidthMedium: '36px',\n  optionIconPrefixWidthLarge: '40px',\n  optionIconPrefixWidthHuge: '40px'\n}\n"
  },
  {
    "path": "src/dropdown/styles/dark.ts",
    "content": "import type { DropdownTheme } from './light'\nimport { changeColor } from 'seemly'\nimport { commonDark } from '../../_styles/common'\nimport { popoverDark } from '../../popover/styles'\nimport { self } from './light'\n\nconst dropdownDark: DropdownTheme = {\n  name: 'Dropdown',\n  common: commonDark,\n  peers: {\n    Popover: popoverDark\n  },\n  self(vars) {\n    const { primaryColorSuppl, primaryColor, popoverColor } = vars\n    const commonSelf = self(vars)\n    commonSelf.colorInverted = popoverColor\n    commonSelf.optionColorActive = changeColor(primaryColor, { alpha: 0.15 })\n    commonSelf.optionColorActiveInverted = primaryColorSuppl\n    commonSelf.optionColorHoverInverted = primaryColorSuppl\n    return commonSelf\n  }\n}\n\nexport default dropdownDark\n"
  },
  {
    "path": "src/dropdown/styles/index.ts",
    "content": "export { default as dropdownDark } from './dark'\nexport { default as dropdownLight } from './light'\nexport type { DropdownTheme, DropdownThemeVars } from './light'\n"
  },
  {
    "path": "src/dropdown/styles/light.ts",
    "content": "import type { ThemeCommonVars } from '../../_styles/common'\nimport { changeColor } from 'seemly'\nimport { createTheme } from '../../_mixins/use-theme'\nimport { commonLight } from '../../_styles/common'\nimport { popoverLight } from '../../popover/styles'\nimport commonVariables from './_common'\n\nexport function self(vars: ThemeCommonVars) {\n  const {\n    primaryColor,\n    textColor2,\n    dividerColor,\n    hoverColor,\n    popoverColor,\n    invertedColor,\n    borderRadius,\n    fontSizeSmall,\n    fontSizeMedium,\n    fontSizeLarge,\n    fontSizeHuge,\n    heightSmall,\n    heightMedium,\n    heightLarge,\n    heightHuge,\n    textColor3,\n    opacityDisabled\n  } = vars\n  return {\n    ...commonVariables,\n    optionHeightSmall: heightSmall,\n    optionHeightMedium: heightMedium,\n    optionHeightLarge: heightLarge,\n    optionHeightHuge: heightHuge,\n    borderRadius,\n    fontSizeSmall,\n    fontSizeMedium,\n    fontSizeLarge,\n    fontSizeHuge,\n    // non-inverted\n    optionTextColor: textColor2,\n    optionTextColorHover: textColor2,\n    optionTextColorActive: primaryColor,\n    optionTextColorChildActive: primaryColor,\n    color: popoverColor,\n    dividerColor,\n    suffixColor: textColor2,\n    prefixColor: textColor2,\n    optionColorHover: hoverColor,\n    optionColorActive: changeColor(primaryColor, { alpha: 0.1 }),\n    groupHeaderTextColor: textColor3,\n    // inverted\n    optionTextColorInverted: '#BBB',\n    optionTextColorHoverInverted: '#FFF',\n    optionTextColorActiveInverted: '#FFF',\n    optionTextColorChildActiveInverted: '#FFF',\n    colorInverted: invertedColor,\n    dividerColorInverted: '#BBB',\n    suffixColorInverted: '#BBB',\n    prefixColorInverted: '#BBB',\n    optionColorHoverInverted: primaryColor,\n    optionColorActiveInverted: primaryColor,\n    groupHeaderTextColorInverted: '#AAA',\n    optionOpacityDisabled: opacityDisabled\n  }\n}\n\nexport type DropdownThemeVars = ReturnType<typeof self>\n\nconst dropdownLight = createTheme({\n  name: 'Dropdown',\n  common: commonLight,\n  peers: {\n    Popover: popoverLight\n  },\n  self\n})\n\nexport type DropdownTheme = typeof dropdownLight\nexport default dropdownLight\n"
  },
  {
    "path": "src/dropdown/tests/Dropdown.spec.tsx",
    "content": "import type { VueWrapper } from '@vue/test-utils'\nimport type { ComponentPublicInstance, VNodeChild } from 'vue'\nimport type { DropdownProps } from '../index'\nimport type { DropdownMixedOption } from '../src/interface'\nimport { CashOutline as CashIcon } from '@vicons/ionicons5'\nimport { mount } from '@vue/test-utils'\nimport { h, nextTick } from 'vue'\nimport { NIcon } from '../../icon'\nimport { NDropdown } from '../index'\n\nconst pendingOptionClassName\n  = 'n-dropdown-option-body n-dropdown-option-body--pending'\nconst optionBodySelector = '.n-dropdown-option-body'\nconst options = [\n  {\n    type: 'group',\n    label: '主角和吃的',\n    key: 'main',\n    children: [\n      {\n        label: '杰·盖茨比',\n        key: 'jay gatsby'\n      },\n      {\n        type: 'divider',\n        key: 'd1'\n      },\n      {\n        label: '黛西·布坎南',\n        icon() {\n          return h(NIcon, null, {\n            default: () => h(CashIcon)\n          })\n        },\n        key: 'daisy buchanan',\n        disabled: true\n      }\n    ]\n  },\n  {\n    type: 'divider',\n    key: 'd1'\n  },\n  {\n    label: '其他角色',\n    key: 'others1',\n    children: [\n      {\n        label: '乔丹·贝克',\n        key: 'jordan baker'\n      }\n    ]\n  }\n]\n\nfunction mountDropdown({\n  onSelect,\n  inverted = false,\n  onClickoutside = undefined,\n  options: data = options,\n  show = undefined,\n  renderLabel = undefined,\n  renderIcon = undefined\n}: DropdownProps = {}): VueWrapper<ComponentPublicInstance> {\n  return mount(NDropdown, {\n    attachTo: document.body,\n    props: {\n      options: data,\n      trigger: 'click',\n      onSelect,\n      inverted,\n      onClickoutside,\n      show,\n      renderLabel,\n      renderIcon\n    },\n    slots: {\n      default: () => 'star kirby'\n    }\n  })\n}\n\ndescribe('n-dropdown', () => {\n  it('should work with import on demand', () => {\n    const wrapper = mount(NDropdown, {\n      slots: {\n        default: () => 'star kirby'\n      }\n    })\n    wrapper.unmount()\n  })\n\n  it('shows menu after click', async () => {\n    const wrapper = mountDropdown()\n\n    const triggerNodeWrapper = wrapper.find('span')\n    expect(triggerNodeWrapper.exists()).toBe(true)\n    await triggerNodeWrapper.trigger('click')\n\n    expect(document.querySelector('.n-dropdown')).toMatchSnapshot()\n    wrapper.unmount()\n  })\n\n  it('shows arrow', async () => {\n    const wrapper = mountDropdown()\n\n    const triggerNodeWrapper = wrapper.find('span')\n    expect(triggerNodeWrapper.exists()).toBe(true)\n    await triggerNodeWrapper.trigger('click')\n\n    expect(document.querySelector('.n-popover-arrow-wrapper')).toMatchSnapshot()\n    wrapper.unmount()\n  })\n\n  it('inverted style', async () => {\n    const wrapper = mountDropdown({ inverted: true })\n\n    const triggerNodeWrapper = wrapper.find('span')\n    expect(triggerNodeWrapper.exists()).toBe(true)\n    await triggerNodeWrapper.trigger('click')\n\n    expect(document.querySelector('.n-dropdown')).toMatchSnapshot()\n    wrapper.unmount()\n  })\n\n  it('keyboard event', async () => {\n    const onSelect = vi.fn()\n    let wrapper = mountDropdown({ onSelect })\n\n    let triggerNodeWrapper = wrapper.find('span')\n    await triggerNodeWrapper.trigger('click')\n\n    await triggerNodeWrapper.trigger('keydown', {\n      key: 'ArrowDown'\n    })\n    let options = document.querySelectorAll(optionBodySelector)\n    expect(options[1].className).toEqual(pendingOptionClassName)\n\n    await triggerNodeWrapper.trigger('keydown', {\n      key: 'ArrowDown'\n    })\n    await triggerNodeWrapper.trigger('keydown', {\n      key: 'ArrowRight'\n    })\n    options = document.querySelectorAll(optionBodySelector)\n    expect(options.length).toBe(5)\n    expect(options[3].className).toEqual(pendingOptionClassName)\n    expect(options[4].className).toEqual(pendingOptionClassName)\n\n    await triggerNodeWrapper.trigger('keydown', {\n      key: 'ArrowLeft'\n    })\n    options = document.querySelectorAll(optionBodySelector)\n    expect(options.length).toBe(4)\n\n    await triggerNodeWrapper.trigger('keydown', {\n      key: 'ArrowUp'\n    })\n    expect(options[1].className).toEqual(pendingOptionClassName)\n    await triggerNodeWrapper.trigger('keydown', {\n      key: 'Enter'\n    })\n    expect(onSelect).toHaveBeenCalledWith('jay gatsby', {\n      key: 'jay gatsby',\n      label: '杰·盖茨比'\n    })\n\n    wrapper.unmount()\n    wrapper = mountDropdown({ onSelect })\n\n    triggerNodeWrapper = wrapper.find('span')\n    await triggerNodeWrapper.trigger('click')\n    await triggerNodeWrapper.trigger('keydown', {\n      key: 'Escape'\n    })\n    expect(document.querySelector('.n-dropdown')).toBeNull()\n\n    wrapper.unmount()\n  })\n\n  it('option mouse event', async () => {\n    const onSelect = vi.fn()\n    const wrapper = mountDropdown({ onSelect })\n\n    const triggerNodeWrapper = wrapper.find('span')\n    expect(triggerNodeWrapper.exists()).toBe(true)\n    await triggerNodeWrapper.trigger('click')\n\n    const options = document.querySelectorAll(optionBodySelector)\n\n    const mouseEnter = new Event('mouseenter')\n    options[1].dispatchEvent(mouseEnter)\n    await nextTick(() => {\n      expect(options[1].className).toEqual(pendingOptionClassName)\n    })\n\n    const mouseMove = new Event('mousemove')\n    options[3].dispatchEvent(mouseMove)\n    await nextTick(() => {\n      expect(options[1].className).not.toEqual(pendingOptionClassName)\n      expect(options[3].className).toEqual(pendingOptionClassName)\n    })\n    ;(options[3] as HTMLDivElement).click()\n    expect(onSelect).not.toHaveBeenCalledWith()\n\n    const mouseLeave = new Event('mouseleave')\n    Object.defineProperty(mouseLeave, 'relatedTarget', {\n      writable: false,\n      value: options[1]\n    })\n    options[1].dispatchEvent(mouseEnter)\n    options[3].dispatchEvent(mouseLeave)\n    await nextTick(() => {\n      expect(options[3].className).not.toEqual(pendingOptionClassName)\n    })\n    wrapper.unmount()\n  })\n\n  it('dropdown disabled', async () => {\n    const onSelect = vi.fn()\n    const wrapper = mountDropdown({ onSelect })\n\n    const triggerNodeWrapper = wrapper.find('span')\n    expect(triggerNodeWrapper.exists()).toBe(true)\n    await triggerNodeWrapper.trigger('click')\n\n    const disabledMenu = document.querySelector(\n      '.n-dropdown-option-body--disabled'\n    ) as HTMLDivElement\n\n    expect(disabledMenu).not.toEqual(null)\n\n    disabledMenu.click()\n\n    expect(onSelect).not.toHaveBeenCalledWith()\n\n    wrapper.unmount()\n  })\n\n  it('dropdown clickoutside', async () => {\n    const mousedownEvent = new MouseEvent('mousedown', { bubbles: true })\n    const mouseupEvent = new MouseEvent('mouseup', { bubbles: true })\n\n    const onClickoutside = vi.fn()\n    const wrapper = mountDropdown({ onClickoutside })\n\n    const triggerNodeWrapper = wrapper.find('span')\n    expect(triggerNodeWrapper.exists()).toBe(true)\n    await triggerNodeWrapper.trigger('click')\n    expect(document.querySelector('.n-dropdown')).toMatchSnapshot()\n    document.body.dispatchEvent(mousedownEvent)\n    document.body.dispatchEvent(mouseupEvent)\n    await nextTick(() => {\n      const nextOptions = document.querySelectorAll(optionBodySelector)\n      expect(nextOptions.length).toBe(0)\n    })\n    expect(onClickoutside).toHaveBeenCalled()\n  })\n\n  it('should work with `render-label` props', async () => {\n    const renderDropdownLabel = (option: DropdownMixedOption): VNodeChild => {\n      return h(\n        'a',\n        {\n          href: 'renderLabel'\n        },\n        { default: () => option.label }\n      )\n    }\n    const wrapper = mountDropdown({\n      renderLabel: renderDropdownLabel\n    })\n    const triggerNodeWrapper = wrapper.find('span')\n    await triggerNodeWrapper.trigger('click')\n    expect(document.querySelector('.n-dropdown')).toMatchSnapshot()\n    expect(\n      document.querySelectorAll('.n-dropdown a[href=\"renderLabel\"]').length\n    ).toBe(4)\n    wrapper.unmount()\n  })\n\n  it('should work with `render-icon` props', async () => {\n    const renderDropdownIcon = (): VNodeChild => {\n      return h(NIcon, null, {\n        default: () => h(CashIcon)\n      })\n    }\n    const wrapper = mountDropdown({\n      renderIcon: renderDropdownIcon\n    })\n    const triggerNodeWrapper = wrapper.find('span')\n    await triggerNodeWrapper.trigger('click')\n    expect(document.querySelector('.n-dropdown')).toMatchSnapshot()\n    expect(\n      document.querySelectorAll('.n-dropdown i[class=\"n-icon\"]').length\n    ).toBe(4)\n    wrapper.unmount()\n  })\n\n  it('should accept empty object in type-checking phase', () => {\n    ;<NDropdown options={[{}]} />\n  })\n})\n"
  },
  {
    "path": "src/dropdown/tests/__snapshots__/Dropdown.spec.tsx.snap",
    "content": "// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html\n\nexports[`n-dropdown > dropdown clickoutside 1`] = `\n<div\n  class=\"n-dropdown-menu n-popover-shared n-dropdown n-dropdown--medium-size\"\n  style=\"--n-box-shadow: 0 3px 6px -4px rgba(0, 0, 0, .12), 0 6px 16px 0 rgba(0, 0, 0, .08), 0 9px 28px 8px rgba(0, 0, 0, .05); --n-bezier: cubic-bezier(.4, 0, .2, 1); --n-bezier-ease-in: cubic-bezier(.4, 0, 1, 1); --n-bezier-ease-out: cubic-bezier(0, 0, .2, 1); --n-font-size: 14px; --n-text-color: rgb(51, 54, 57); --n-color: #fff; --n-divider-color: rgb(239, 239, 245); --n-border-radius: 3px; --n-arrow-height: 6px; --n-arrow-offset: 10px; --n-arrow-offset-vertical: 10px; --n-padding: 4px 0; --n-space: 6px; --n-space-arrow: 10px; --n-option-height: 34px; --n-option-prefix-width: 14px; --n-option-icon-prefix-width: 36px; --n-option-suffix-width: 14px; --n-option-icon-suffix-width: 32px; --n-option-icon-size: 16px; --n-option-opacity-disabled: 0.5; --n-option-color-hover: rgb(243, 243, 245); --n-option-color-active: rgba(24, 160, 88, 0.1); --n-option-text-color: rgb(51, 54, 57); --n-option-text-color-hover: rgb(51, 54, 57); --n-option-text-color-active: #18a058; --n-option-text-color-child-active: #18a058; --n-prefix-color: rgb(51, 54, 57); --n-suffix-color: rgb(51, 54, 57); --n-group-header-text-color: rgb(118, 124, 130);\"\n>\n  \n  \n  <div\n    class=\"n-dropdown-option\"\n  >\n    <div\n      class=\"n-dropdown-option-body n-dropdown-option-body--group\"\n    >\n      <div\n        class=\"n-dropdown-option-body__prefix n-dropdown-option-body__prefix--show-icon\"\n        data-dropdown-option=\"true\"\n      />\n      <div\n        class=\"n-dropdown-option-body__label\"\n        data-dropdown-option=\"true\"\n      >\n        主角和吃的\n      </div>\n      <div\n        class=\"n-dropdown-option-body__suffix n-dropdown-option-body__suffix--has-submenu\"\n        data-dropdown-option=\"true\"\n      />\n    </div>\n  </div>\n  \n  <div\n    class=\"n-dropdown-option\"\n    data-dropdown-option=\"true\"\n  >\n    <div\n      class=\"n-dropdown-option-body\"\n    >\n      <div\n        class=\"n-dropdown-option-body__prefix n-dropdown-option-body__prefix--show-icon\"\n      >\n        <!---->\n      </div>\n      <div\n        class=\"n-dropdown-option-body__label\"\n        data-dropdown-option=\"true\"\n      >\n        杰·盖茨比\n      </div>\n      <div\n        class=\"n-dropdown-option-body__suffix n-dropdown-option-body__suffix--has-submenu\"\n        data-dropdown-option=\"true\"\n      />\n    </div>\n    <!---->\n  </div>\n  <div\n    class=\"n-dropdown-divider\"\n  />\n  <div\n    class=\"n-dropdown-option\"\n    data-dropdown-option=\"true\"\n  >\n    <div\n      class=\"n-dropdown-option-body n-dropdown-option-body--disabled\"\n    >\n      <div\n        class=\"n-dropdown-option-body__prefix n-dropdown-option-body__prefix--show-icon\"\n      >\n        <i\n          class=\"n-icon\"\n          role=\"img\"\n          style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1);\"\n        >\n          <svg\n            viewBox=\"0 0 512 512\"\n            xmlns=\"http://www.w3.org/2000/svg\"\n            xmlns:xlink=\"http://www.w3.org/1999/xlink\"\n          >\n            <rect\n              fill=\"none\"\n              height=\"256\"\n              rx=\"16\"\n              ry=\"16\"\n              stroke=\"currentColor\"\n              stroke-linejoin=\"round\"\n              stroke-width=\"32\"\n              transform=\"rotate(180 256 208)\"\n              width=\"448\"\n              x=\"32\"\n              y=\"80\"\n            />\n            <path\n              d=\"M64 384h384\"\n              fill=\"none\"\n              stroke=\"currentColor\"\n              stroke-linecap=\"round\"\n              stroke-linejoin=\"round\"\n              stroke-width=\"32\"\n            />\n            <path\n              d=\"M96 432h320\"\n              fill=\"none\"\n              stroke=\"currentColor\"\n              stroke-linecap=\"round\"\n              stroke-linejoin=\"round\"\n              stroke-width=\"32\"\n            />\n            <circle\n              cx=\"256\"\n              cy=\"208\"\n              fill=\"none\"\n              r=\"80\"\n              stroke=\"currentColor\"\n              stroke-linecap=\"round\"\n              stroke-linejoin=\"round\"\n              stroke-width=\"32\"\n            />\n            <path\n              d=\"M480 160a80 80 0 0 1-80-80\"\n              fill=\"none\"\n              stroke=\"currentColor\"\n              stroke-linecap=\"round\"\n              stroke-linejoin=\"round\"\n              stroke-width=\"32\"\n            />\n            <path\n              d=\"M32 160a80 80 0 0 0 80-80\"\n              fill=\"none\"\n              stroke=\"currentColor\"\n              stroke-linecap=\"round\"\n              stroke-linejoin=\"round\"\n              stroke-width=\"32\"\n            />\n            <path\n              d=\"M480 256a80 80 0 0 0-80 80\"\n              fill=\"none\"\n              stroke=\"currentColor\"\n              stroke-linecap=\"round\"\n              stroke-linejoin=\"round\"\n              stroke-width=\"32\"\n            />\n            <path\n              d=\"M32 256a80 80 0 0 1 80 80\"\n              fill=\"none\"\n              stroke=\"currentColor\"\n              stroke-linecap=\"round\"\n              stroke-linejoin=\"round\"\n              stroke-width=\"32\"\n            />\n          </svg>\n        </i>\n      </div>\n      <div\n        class=\"n-dropdown-option-body__label\"\n        data-dropdown-option=\"true\"\n      >\n        黛西·布坎南\n      </div>\n      <div\n        class=\"n-dropdown-option-body__suffix n-dropdown-option-body__suffix--has-submenu\"\n        data-dropdown-option=\"true\"\n      />\n    </div>\n    <!---->\n  </div>\n  \n  \n  <div\n    class=\"n-dropdown-divider\"\n  />\n  <div\n    class=\"n-dropdown-option\"\n    data-dropdown-option=\"true\"\n  >\n    <div\n      class=\"n-dropdown-option-body\"\n    >\n      <div\n        class=\"n-dropdown-option-body__prefix n-dropdown-option-body__prefix--show-icon\"\n      >\n        <!---->\n      </div>\n      <div\n        class=\"n-dropdown-option-body__label\"\n        data-dropdown-option=\"true\"\n      >\n        其他角色\n      </div>\n      <div\n        class=\"n-dropdown-option-body__suffix n-dropdown-option-body__suffix--has-submenu\"\n        data-dropdown-option=\"true\"\n      >\n        <i\n          class=\"n-icon\"\n          role=\"img\"\n          style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1);\"\n        >\n          <svg\n            fill=\"none\"\n            viewBox=\"0 0 16 16\"\n            xmlns=\"http://www.w3.org/2000/svg\"\n          >\n            <path\n              d=\"M5.64645 3.14645C5.45118 3.34171 5.45118 3.65829 5.64645 3.85355L9.79289 8L5.64645 12.1464C5.45118 12.3417 5.45118 12.6583 5.64645 12.8536C5.84171 13.0488 6.15829 13.0488 6.35355 12.8536L10.8536 8.35355C11.0488 8.15829 11.0488 7.84171 10.8536 7.64645L6.35355 3.14645C6.15829 2.95118 5.84171 2.95118 5.64645 3.14645Z\"\n              fill=\"currentColor\"\n            />\n          </svg>\n        </i>\n      </div>\n    </div>\n    \n    <div\n      class=\"n-dropdown-offset-container\"\n    >\n      <!---->\n    </div>\n    \n  </div>\n  \n  <!---->\n</div>\n`;\n\nexports[`n-dropdown > inverted style 1`] = `\n<div\n  class=\"n-dropdown-menu n-popover-shared n-dropdown n-dropdown--medium-size\"\n  style=\"--n-box-shadow: 0 3px 6px -4px rgba(0, 0, 0, .12), 0 6px 16px 0 rgba(0, 0, 0, .08), 0 9px 28px 8px rgba(0, 0, 0, .05); --n-bezier: cubic-bezier(.4, 0, .2, 1); --n-bezier-ease-in: cubic-bezier(.4, 0, 1, 1); --n-bezier-ease-out: cubic-bezier(0, 0, .2, 1); --n-font-size: 14px; --n-text-color: rgb(51, 54, 57); --n-color: rgb(0, 20, 40); --n-divider-color: rgb(239, 239, 245); --n-border-radius: 3px; --n-arrow-height: 6px; --n-arrow-offset: 10px; --n-arrow-offset-vertical: 10px; --n-padding: 4px 0; --n-space: 6px; --n-space-arrow: 10px; --n-option-height: 34px; --n-option-prefix-width: 14px; --n-option-icon-prefix-width: 36px; --n-option-suffix-width: 14px; --n-option-icon-suffix-width: 32px; --n-option-icon-size: 16px; --n-option-opacity-disabled: 0.5; --n-option-color-hover: #18a058; --n-option-color-active: #18a058; --n-option-text-color: #BBB; --n-option-text-color-hover: #FFF; --n-option-text-color-active: #FFF; --n-option-text-color-child-active: #FFF; --n-prefix-color: #BBB; --n-suffix-color: #BBB; --n-group-header-text-color: #AAA;\"\n>\n  \n  \n  <div\n    class=\"n-dropdown-option\"\n  >\n    <div\n      class=\"n-dropdown-option-body n-dropdown-option-body--group\"\n    >\n      <div\n        class=\"n-dropdown-option-body__prefix n-dropdown-option-body__prefix--show-icon\"\n        data-dropdown-option=\"true\"\n      />\n      <div\n        class=\"n-dropdown-option-body__label\"\n        data-dropdown-option=\"true\"\n      >\n        主角和吃的\n      </div>\n      <div\n        class=\"n-dropdown-option-body__suffix n-dropdown-option-body__suffix--has-submenu\"\n        data-dropdown-option=\"true\"\n      />\n    </div>\n  </div>\n  \n  <div\n    class=\"n-dropdown-option\"\n    data-dropdown-option=\"true\"\n  >\n    <div\n      class=\"n-dropdown-option-body\"\n    >\n      <div\n        class=\"n-dropdown-option-body__prefix n-dropdown-option-body__prefix--show-icon\"\n      >\n        <!---->\n      </div>\n      <div\n        class=\"n-dropdown-option-body__label\"\n        data-dropdown-option=\"true\"\n      >\n        杰·盖茨比\n      </div>\n      <div\n        class=\"n-dropdown-option-body__suffix n-dropdown-option-body__suffix--has-submenu\"\n        data-dropdown-option=\"true\"\n      />\n    </div>\n    <!---->\n  </div>\n  <div\n    class=\"n-dropdown-divider\"\n  />\n  <div\n    class=\"n-dropdown-option\"\n    data-dropdown-option=\"true\"\n  >\n    <div\n      class=\"n-dropdown-option-body n-dropdown-option-body--disabled\"\n    >\n      <div\n        class=\"n-dropdown-option-body__prefix n-dropdown-option-body__prefix--show-icon\"\n      >\n        <i\n          class=\"n-icon\"\n          role=\"img\"\n          style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1);\"\n        >\n          <svg\n            viewBox=\"0 0 512 512\"\n            xmlns=\"http://www.w3.org/2000/svg\"\n            xmlns:xlink=\"http://www.w3.org/1999/xlink\"\n          >\n            <rect\n              fill=\"none\"\n              height=\"256\"\n              rx=\"16\"\n              ry=\"16\"\n              stroke=\"currentColor\"\n              stroke-linejoin=\"round\"\n              stroke-width=\"32\"\n              transform=\"rotate(180 256 208)\"\n              width=\"448\"\n              x=\"32\"\n              y=\"80\"\n            />\n            <path\n              d=\"M64 384h384\"\n              fill=\"none\"\n              stroke=\"currentColor\"\n              stroke-linecap=\"round\"\n              stroke-linejoin=\"round\"\n              stroke-width=\"32\"\n            />\n            <path\n              d=\"M96 432h320\"\n              fill=\"none\"\n              stroke=\"currentColor\"\n              stroke-linecap=\"round\"\n              stroke-linejoin=\"round\"\n              stroke-width=\"32\"\n            />\n            <circle\n              cx=\"256\"\n              cy=\"208\"\n              fill=\"none\"\n              r=\"80\"\n              stroke=\"currentColor\"\n              stroke-linecap=\"round\"\n              stroke-linejoin=\"round\"\n              stroke-width=\"32\"\n            />\n            <path\n              d=\"M480 160a80 80 0 0 1-80-80\"\n              fill=\"none\"\n              stroke=\"currentColor\"\n              stroke-linecap=\"round\"\n              stroke-linejoin=\"round\"\n              stroke-width=\"32\"\n            />\n            <path\n              d=\"M32 160a80 80 0 0 0 80-80\"\n              fill=\"none\"\n              stroke=\"currentColor\"\n              stroke-linecap=\"round\"\n              stroke-linejoin=\"round\"\n              stroke-width=\"32\"\n            />\n            <path\n              d=\"M480 256a80 80 0 0 0-80 80\"\n              fill=\"none\"\n              stroke=\"currentColor\"\n              stroke-linecap=\"round\"\n              stroke-linejoin=\"round\"\n              stroke-width=\"32\"\n            />\n            <path\n              d=\"M32 256a80 80 0 0 1 80 80\"\n              fill=\"none\"\n              stroke=\"currentColor\"\n              stroke-linecap=\"round\"\n              stroke-linejoin=\"round\"\n              stroke-width=\"32\"\n            />\n          </svg>\n        </i>\n      </div>\n      <div\n        class=\"n-dropdown-option-body__label\"\n        data-dropdown-option=\"true\"\n      >\n        黛西·布坎南\n      </div>\n      <div\n        class=\"n-dropdown-option-body__suffix n-dropdown-option-body__suffix--has-submenu\"\n        data-dropdown-option=\"true\"\n      />\n    </div>\n    <!---->\n  </div>\n  \n  \n  <div\n    class=\"n-dropdown-divider\"\n  />\n  <div\n    class=\"n-dropdown-option\"\n    data-dropdown-option=\"true\"\n  >\n    <div\n      class=\"n-dropdown-option-body\"\n    >\n      <div\n        class=\"n-dropdown-option-body__prefix n-dropdown-option-body__prefix--show-icon\"\n      >\n        <!---->\n      </div>\n      <div\n        class=\"n-dropdown-option-body__label\"\n        data-dropdown-option=\"true\"\n      >\n        其他角色\n      </div>\n      <div\n        class=\"n-dropdown-option-body__suffix n-dropdown-option-body__suffix--has-submenu\"\n        data-dropdown-option=\"true\"\n      >\n        <i\n          class=\"n-icon\"\n          role=\"img\"\n          style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1);\"\n        >\n          <svg\n            fill=\"none\"\n            viewBox=\"0 0 16 16\"\n            xmlns=\"http://www.w3.org/2000/svg\"\n          >\n            <path\n              d=\"M5.64645 3.14645C5.45118 3.34171 5.45118 3.65829 5.64645 3.85355L9.79289 8L5.64645 12.1464C5.45118 12.3417 5.45118 12.6583 5.64645 12.8536C5.84171 13.0488 6.15829 13.0488 6.35355 12.8536L10.8536 8.35355C11.0488 8.15829 11.0488 7.84171 10.8536 7.64645L6.35355 3.14645C6.15829 2.95118 5.84171 2.95118 5.64645 3.14645Z\"\n              fill=\"currentColor\"\n            />\n          </svg>\n        </i>\n      </div>\n    </div>\n    \n    <div\n      class=\"n-dropdown-offset-container\"\n    >\n      <!---->\n    </div>\n    \n  </div>\n  \n  <!---->\n</div>\n`;\n\nexports[`n-dropdown > should work with \\`render-icon\\` props 1`] = `\n<div\n  class=\"n-dropdown-menu n-popover-shared n-dropdown n-dropdown--medium-size\"\n  style=\"--n-box-shadow: 0 3px 6px -4px rgba(0, 0, 0, .12), 0 6px 16px 0 rgba(0, 0, 0, .08), 0 9px 28px 8px rgba(0, 0, 0, .05); --n-bezier: cubic-bezier(.4, 0, .2, 1); --n-bezier-ease-in: cubic-bezier(.4, 0, 1, 1); --n-bezier-ease-out: cubic-bezier(0, 0, .2, 1); --n-font-size: 14px; --n-text-color: rgb(51, 54, 57); --n-color: #fff; --n-divider-color: rgb(239, 239, 245); --n-border-radius: 3px; --n-arrow-height: 6px; --n-arrow-offset: 10px; --n-arrow-offset-vertical: 10px; --n-padding: 4px 0; --n-space: 6px; --n-space-arrow: 10px; --n-option-height: 34px; --n-option-prefix-width: 14px; --n-option-icon-prefix-width: 36px; --n-option-suffix-width: 14px; --n-option-icon-suffix-width: 32px; --n-option-icon-size: 16px; --n-option-opacity-disabled: 0.5; --n-option-color-hover: rgb(243, 243, 245); --n-option-color-active: rgba(24, 160, 88, 0.1); --n-option-text-color: rgb(51, 54, 57); --n-option-text-color-hover: rgb(51, 54, 57); --n-option-text-color-active: #18a058; --n-option-text-color-child-active: #18a058; --n-prefix-color: rgb(51, 54, 57); --n-suffix-color: rgb(51, 54, 57); --n-group-header-text-color: rgb(118, 124, 130);\"\n>\n  \n  \n  <div\n    class=\"n-dropdown-option\"\n  >\n    <div\n      class=\"n-dropdown-option-body n-dropdown-option-body--group\"\n    >\n      <div\n        class=\"n-dropdown-option-body__prefix n-dropdown-option-body__prefix--show-icon\"\n        data-dropdown-option=\"true\"\n      />\n      <div\n        class=\"n-dropdown-option-body__label\"\n        data-dropdown-option=\"true\"\n      >\n        主角和吃的\n      </div>\n      <div\n        class=\"n-dropdown-option-body__suffix n-dropdown-option-body__suffix--has-submenu\"\n        data-dropdown-option=\"true\"\n      />\n    </div>\n  </div>\n  \n  <div\n    class=\"n-dropdown-option\"\n    data-dropdown-option=\"true\"\n  >\n    <div\n      class=\"n-dropdown-option-body\"\n    >\n      <div\n        class=\"n-dropdown-option-body__prefix n-dropdown-option-body__prefix--show-icon\"\n      >\n        <i\n          class=\"n-icon\"\n          role=\"img\"\n          style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1);\"\n        >\n          <svg\n            viewBox=\"0 0 512 512\"\n            xmlns=\"http://www.w3.org/2000/svg\"\n            xmlns:xlink=\"http://www.w3.org/1999/xlink\"\n          >\n            <rect\n              fill=\"none\"\n              height=\"256\"\n              rx=\"16\"\n              ry=\"16\"\n              stroke=\"currentColor\"\n              stroke-linejoin=\"round\"\n              stroke-width=\"32\"\n              transform=\"rotate(180 256 208)\"\n              width=\"448\"\n              x=\"32\"\n              y=\"80\"\n            />\n            <path\n              d=\"M64 384h384\"\n              fill=\"none\"\n              stroke=\"currentColor\"\n              stroke-linecap=\"round\"\n              stroke-linejoin=\"round\"\n              stroke-width=\"32\"\n            />\n            <path\n              d=\"M96 432h320\"\n              fill=\"none\"\n              stroke=\"currentColor\"\n              stroke-linecap=\"round\"\n              stroke-linejoin=\"round\"\n              stroke-width=\"32\"\n            />\n            <circle\n              cx=\"256\"\n              cy=\"208\"\n              fill=\"none\"\n              r=\"80\"\n              stroke=\"currentColor\"\n              stroke-linecap=\"round\"\n              stroke-linejoin=\"round\"\n              stroke-width=\"32\"\n            />\n            <path\n              d=\"M480 160a80 80 0 0 1-80-80\"\n              fill=\"none\"\n              stroke=\"currentColor\"\n              stroke-linecap=\"round\"\n              stroke-linejoin=\"round\"\n              stroke-width=\"32\"\n            />\n            <path\n              d=\"M32 160a80 80 0 0 0 80-80\"\n              fill=\"none\"\n              stroke=\"currentColor\"\n              stroke-linecap=\"round\"\n              stroke-linejoin=\"round\"\n              stroke-width=\"32\"\n            />\n            <path\n              d=\"M480 256a80 80 0 0 0-80 80\"\n              fill=\"none\"\n              stroke=\"currentColor\"\n              stroke-linecap=\"round\"\n              stroke-linejoin=\"round\"\n              stroke-width=\"32\"\n            />\n            <path\n              d=\"M32 256a80 80 0 0 1 80 80\"\n              fill=\"none\"\n              stroke=\"currentColor\"\n              stroke-linecap=\"round\"\n              stroke-linejoin=\"round\"\n              stroke-width=\"32\"\n            />\n          </svg>\n        </i>\n      </div>\n      <div\n        class=\"n-dropdown-option-body__label\"\n        data-dropdown-option=\"true\"\n      >\n        杰·盖茨比\n      </div>\n      <div\n        class=\"n-dropdown-option-body__suffix n-dropdown-option-body__suffix--has-submenu\"\n        data-dropdown-option=\"true\"\n      />\n    </div>\n    <!---->\n  </div>\n  <div\n    class=\"n-dropdown-divider\"\n  />\n  <div\n    class=\"n-dropdown-option\"\n    data-dropdown-option=\"true\"\n  >\n    <div\n      class=\"n-dropdown-option-body n-dropdown-option-body--disabled\"\n    >\n      <div\n        class=\"n-dropdown-option-body__prefix n-dropdown-option-body__prefix--show-icon\"\n      >\n        <i\n          class=\"n-icon\"\n          role=\"img\"\n          style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1);\"\n        >\n          <svg\n            viewBox=\"0 0 512 512\"\n            xmlns=\"http://www.w3.org/2000/svg\"\n            xmlns:xlink=\"http://www.w3.org/1999/xlink\"\n          >\n            <rect\n              fill=\"none\"\n              height=\"256\"\n              rx=\"16\"\n              ry=\"16\"\n              stroke=\"currentColor\"\n              stroke-linejoin=\"round\"\n              stroke-width=\"32\"\n              transform=\"rotate(180 256 208)\"\n              width=\"448\"\n              x=\"32\"\n              y=\"80\"\n            />\n            <path\n              d=\"M64 384h384\"\n              fill=\"none\"\n              stroke=\"currentColor\"\n              stroke-linecap=\"round\"\n              stroke-linejoin=\"round\"\n              stroke-width=\"32\"\n            />\n            <path\n              d=\"M96 432h320\"\n              fill=\"none\"\n              stroke=\"currentColor\"\n              stroke-linecap=\"round\"\n              stroke-linejoin=\"round\"\n              stroke-width=\"32\"\n            />\n            <circle\n              cx=\"256\"\n              cy=\"208\"\n              fill=\"none\"\n              r=\"80\"\n              stroke=\"currentColor\"\n              stroke-linecap=\"round\"\n              stroke-linejoin=\"round\"\n              stroke-width=\"32\"\n            />\n            <path\n              d=\"M480 160a80 80 0 0 1-80-80\"\n              fill=\"none\"\n              stroke=\"currentColor\"\n              stroke-linecap=\"round\"\n              stroke-linejoin=\"round\"\n              stroke-width=\"32\"\n            />\n            <path\n              d=\"M32 160a80 80 0 0 0 80-80\"\n              fill=\"none\"\n              stroke=\"currentColor\"\n              stroke-linecap=\"round\"\n              stroke-linejoin=\"round\"\n              stroke-width=\"32\"\n            />\n            <path\n              d=\"M480 256a80 80 0 0 0-80 80\"\n              fill=\"none\"\n              stroke=\"currentColor\"\n              stroke-linecap=\"round\"\n              stroke-linejoin=\"round\"\n              stroke-width=\"32\"\n            />\n            <path\n              d=\"M32 256a80 80 0 0 1 80 80\"\n              fill=\"none\"\n              stroke=\"currentColor\"\n              stroke-linecap=\"round\"\n              stroke-linejoin=\"round\"\n              stroke-width=\"32\"\n            />\n          </svg>\n        </i>\n      </div>\n      <div\n        class=\"n-dropdown-option-body__label\"\n        data-dropdown-option=\"true\"\n      >\n        黛西·布坎南\n      </div>\n      <div\n        class=\"n-dropdown-option-body__suffix n-dropdown-option-body__suffix--has-submenu\"\n        data-dropdown-option=\"true\"\n      />\n    </div>\n    <!---->\n  </div>\n  \n  \n  <div\n    class=\"n-dropdown-divider\"\n  />\n  <div\n    class=\"n-dropdown-option\"\n    data-dropdown-option=\"true\"\n  >\n    <div\n      class=\"n-dropdown-option-body\"\n    >\n      <div\n        class=\"n-dropdown-option-body__prefix n-dropdown-option-body__prefix--show-icon\"\n      >\n        <i\n          class=\"n-icon\"\n          role=\"img\"\n          style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1);\"\n        >\n          <svg\n            viewBox=\"0 0 512 512\"\n            xmlns=\"http://www.w3.org/2000/svg\"\n            xmlns:xlink=\"http://www.w3.org/1999/xlink\"\n          >\n            <rect\n              fill=\"none\"\n              height=\"256\"\n              rx=\"16\"\n              ry=\"16\"\n              stroke=\"currentColor\"\n              stroke-linejoin=\"round\"\n              stroke-width=\"32\"\n              transform=\"rotate(180 256 208)\"\n              width=\"448\"\n              x=\"32\"\n              y=\"80\"\n            />\n            <path\n              d=\"M64 384h384\"\n              fill=\"none\"\n              stroke=\"currentColor\"\n              stroke-linecap=\"round\"\n              stroke-linejoin=\"round\"\n              stroke-width=\"32\"\n            />\n            <path\n              d=\"M96 432h320\"\n              fill=\"none\"\n              stroke=\"currentColor\"\n              stroke-linecap=\"round\"\n              stroke-linejoin=\"round\"\n              stroke-width=\"32\"\n            />\n            <circle\n              cx=\"256\"\n              cy=\"208\"\n              fill=\"none\"\n              r=\"80\"\n              stroke=\"currentColor\"\n              stroke-linecap=\"round\"\n              stroke-linejoin=\"round\"\n              stroke-width=\"32\"\n            />\n            <path\n              d=\"M480 160a80 80 0 0 1-80-80\"\n              fill=\"none\"\n              stroke=\"currentColor\"\n              stroke-linecap=\"round\"\n              stroke-linejoin=\"round\"\n              stroke-width=\"32\"\n            />\n            <path\n              d=\"M32 160a80 80 0 0 0 80-80\"\n              fill=\"none\"\n              stroke=\"currentColor\"\n              stroke-linecap=\"round\"\n              stroke-linejoin=\"round\"\n              stroke-width=\"32\"\n            />\n            <path\n              d=\"M480 256a80 80 0 0 0-80 80\"\n              fill=\"none\"\n              stroke=\"currentColor\"\n              stroke-linecap=\"round\"\n              stroke-linejoin=\"round\"\n              stroke-width=\"32\"\n            />\n            <path\n              d=\"M32 256a80 80 0 0 1 80 80\"\n              fill=\"none\"\n              stroke=\"currentColor\"\n              stroke-linecap=\"round\"\n              stroke-linejoin=\"round\"\n              stroke-width=\"32\"\n            />\n          </svg>\n        </i>\n      </div>\n      <div\n        class=\"n-dropdown-option-body__label\"\n        data-dropdown-option=\"true\"\n      >\n        其他角色\n      </div>\n      <div\n        class=\"n-dropdown-option-body__suffix n-dropdown-option-body__suffix--has-submenu\"\n        data-dropdown-option=\"true\"\n      >\n        <i\n          class=\"n-icon\"\n          role=\"img\"\n          style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1);\"\n        >\n          <svg\n            fill=\"none\"\n            viewBox=\"0 0 16 16\"\n            xmlns=\"http://www.w3.org/2000/svg\"\n          >\n            <path\n              d=\"M5.64645 3.14645C5.45118 3.34171 5.45118 3.65829 5.64645 3.85355L9.79289 8L5.64645 12.1464C5.45118 12.3417 5.45118 12.6583 5.64645 12.8536C5.84171 13.0488 6.15829 13.0488 6.35355 12.8536L10.8536 8.35355C11.0488 8.15829 11.0488 7.84171 10.8536 7.64645L6.35355 3.14645C6.15829 2.95118 5.84171 2.95118 5.64645 3.14645Z\"\n              fill=\"currentColor\"\n            />\n          </svg>\n        </i>\n      </div>\n    </div>\n    \n    <div\n      class=\"n-dropdown-offset-container\"\n    >\n      <!---->\n    </div>\n    \n  </div>\n  \n  <!---->\n</div>\n`;\n\nexports[`n-dropdown > should work with \\`render-label\\` props 1`] = `\n<div\n  class=\"n-dropdown-menu n-popover-shared n-dropdown n-dropdown--medium-size\"\n  style=\"--n-box-shadow: 0 3px 6px -4px rgba(0, 0, 0, .12), 0 6px 16px 0 rgba(0, 0, 0, .08), 0 9px 28px 8px rgba(0, 0, 0, .05); --n-bezier: cubic-bezier(.4, 0, .2, 1); --n-bezier-ease-in: cubic-bezier(.4, 0, 1, 1); --n-bezier-ease-out: cubic-bezier(0, 0, .2, 1); --n-font-size: 14px; --n-text-color: rgb(51, 54, 57); --n-color: #fff; --n-divider-color: rgb(239, 239, 245); --n-border-radius: 3px; --n-arrow-height: 6px; --n-arrow-offset: 10px; --n-arrow-offset-vertical: 10px; --n-padding: 4px 0; --n-space: 6px; --n-space-arrow: 10px; --n-option-height: 34px; --n-option-prefix-width: 14px; --n-option-icon-prefix-width: 36px; --n-option-suffix-width: 14px; --n-option-icon-suffix-width: 32px; --n-option-icon-size: 16px; --n-option-opacity-disabled: 0.5; --n-option-color-hover: rgb(243, 243, 245); --n-option-color-active: rgba(24, 160, 88, 0.1); --n-option-text-color: rgb(51, 54, 57); --n-option-text-color-hover: rgb(51, 54, 57); --n-option-text-color-active: #18a058; --n-option-text-color-child-active: #18a058; --n-prefix-color: rgb(51, 54, 57); --n-suffix-color: rgb(51, 54, 57); --n-group-header-text-color: rgb(118, 124, 130);\"\n>\n  \n  \n  <div\n    class=\"n-dropdown-option\"\n  >\n    <div\n      class=\"n-dropdown-option-body n-dropdown-option-body--group\"\n    >\n      <div\n        class=\"n-dropdown-option-body__prefix n-dropdown-option-body__prefix--show-icon\"\n        data-dropdown-option=\"true\"\n      />\n      <div\n        class=\"n-dropdown-option-body__label\"\n        data-dropdown-option=\"true\"\n      >\n        <a\n          href=\"renderLabel\"\n        >\n          主角和吃的\n        </a>\n      </div>\n      <div\n        class=\"n-dropdown-option-body__suffix n-dropdown-option-body__suffix--has-submenu\"\n        data-dropdown-option=\"true\"\n      />\n    </div>\n  </div>\n  \n  <div\n    class=\"n-dropdown-option\"\n    data-dropdown-option=\"true\"\n  >\n    <div\n      class=\"n-dropdown-option-body\"\n    >\n      <div\n        class=\"n-dropdown-option-body__prefix n-dropdown-option-body__prefix--show-icon\"\n      >\n        <!---->\n      </div>\n      <div\n        class=\"n-dropdown-option-body__label\"\n        data-dropdown-option=\"true\"\n      >\n        <a\n          href=\"renderLabel\"\n        >\n          杰·盖茨比\n        </a>\n      </div>\n      <div\n        class=\"n-dropdown-option-body__suffix n-dropdown-option-body__suffix--has-submenu\"\n        data-dropdown-option=\"true\"\n      />\n    </div>\n    <!---->\n  </div>\n  <div\n    class=\"n-dropdown-divider\"\n  />\n  <div\n    class=\"n-dropdown-option\"\n    data-dropdown-option=\"true\"\n  >\n    <div\n      class=\"n-dropdown-option-body n-dropdown-option-body--disabled\"\n    >\n      <div\n        class=\"n-dropdown-option-body__prefix n-dropdown-option-body__prefix--show-icon\"\n      >\n        <i\n          class=\"n-icon\"\n          role=\"img\"\n          style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1);\"\n        >\n          <svg\n            viewBox=\"0 0 512 512\"\n            xmlns=\"http://www.w3.org/2000/svg\"\n            xmlns:xlink=\"http://www.w3.org/1999/xlink\"\n          >\n            <rect\n              fill=\"none\"\n              height=\"256\"\n              rx=\"16\"\n              ry=\"16\"\n              stroke=\"currentColor\"\n              stroke-linejoin=\"round\"\n              stroke-width=\"32\"\n              transform=\"rotate(180 256 208)\"\n              width=\"448\"\n              x=\"32\"\n              y=\"80\"\n            />\n            <path\n              d=\"M64 384h384\"\n              fill=\"none\"\n              stroke=\"currentColor\"\n              stroke-linecap=\"round\"\n              stroke-linejoin=\"round\"\n              stroke-width=\"32\"\n            />\n            <path\n              d=\"M96 432h320\"\n              fill=\"none\"\n              stroke=\"currentColor\"\n              stroke-linecap=\"round\"\n              stroke-linejoin=\"round\"\n              stroke-width=\"32\"\n            />\n            <circle\n              cx=\"256\"\n              cy=\"208\"\n              fill=\"none\"\n              r=\"80\"\n              stroke=\"currentColor\"\n              stroke-linecap=\"round\"\n              stroke-linejoin=\"round\"\n              stroke-width=\"32\"\n            />\n            <path\n              d=\"M480 160a80 80 0 0 1-80-80\"\n              fill=\"none\"\n              stroke=\"currentColor\"\n              stroke-linecap=\"round\"\n              stroke-linejoin=\"round\"\n              stroke-width=\"32\"\n            />\n            <path\n              d=\"M32 160a80 80 0 0 0 80-80\"\n              fill=\"none\"\n              stroke=\"currentColor\"\n              stroke-linecap=\"round\"\n              stroke-linejoin=\"round\"\n              stroke-width=\"32\"\n            />\n            <path\n              d=\"M480 256a80 80 0 0 0-80 80\"\n              fill=\"none\"\n              stroke=\"currentColor\"\n              stroke-linecap=\"round\"\n              stroke-linejoin=\"round\"\n              stroke-width=\"32\"\n            />\n            <path\n              d=\"M32 256a80 80 0 0 1 80 80\"\n              fill=\"none\"\n              stroke=\"currentColor\"\n              stroke-linecap=\"round\"\n              stroke-linejoin=\"round\"\n              stroke-width=\"32\"\n            />\n          </svg>\n        </i>\n      </div>\n      <div\n        class=\"n-dropdown-option-body__label\"\n        data-dropdown-option=\"true\"\n      >\n        <a\n          href=\"renderLabel\"\n        >\n          黛西·布坎南\n        </a>\n      </div>\n      <div\n        class=\"n-dropdown-option-body__suffix n-dropdown-option-body__suffix--has-submenu\"\n        data-dropdown-option=\"true\"\n      />\n    </div>\n    <!---->\n  </div>\n  \n  \n  <div\n    class=\"n-dropdown-divider\"\n  />\n  <div\n    class=\"n-dropdown-option\"\n    data-dropdown-option=\"true\"\n  >\n    <div\n      class=\"n-dropdown-option-body\"\n    >\n      <div\n        class=\"n-dropdown-option-body__prefix n-dropdown-option-body__prefix--show-icon\"\n      >\n        <!---->\n      </div>\n      <div\n        class=\"n-dropdown-option-body__label\"\n        data-dropdown-option=\"true\"\n      >\n        <a\n          href=\"renderLabel\"\n        >\n          其他角色\n        </a>\n      </div>\n      <div\n        class=\"n-dropdown-option-body__suffix n-dropdown-option-body__suffix--has-submenu\"\n        data-dropdown-option=\"true\"\n      >\n        <i\n          class=\"n-icon\"\n          role=\"img\"\n          style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1);\"\n        >\n          <svg\n            fill=\"none\"\n            viewBox=\"0 0 16 16\"\n            xmlns=\"http://www.w3.org/2000/svg\"\n          >\n            <path\n              d=\"M5.64645 3.14645C5.45118 3.34171 5.45118 3.65829 5.64645 3.85355L9.79289 8L5.64645 12.1464C5.45118 12.3417 5.45118 12.6583 5.64645 12.8536C5.84171 13.0488 6.15829 13.0488 6.35355 12.8536L10.8536 8.35355C11.0488 8.15829 11.0488 7.84171 10.8536 7.64645L6.35355 3.14645C6.15829 2.95118 5.84171 2.95118 5.64645 3.14645Z\"\n              fill=\"currentColor\"\n            />\n          </svg>\n        </i>\n      </div>\n    </div>\n    \n    <div\n      class=\"n-dropdown-offset-container\"\n    >\n      <!---->\n    </div>\n    \n  </div>\n  \n  <!---->\n</div>\n`;\n\nexports[`n-dropdown > shows arrow 1`] = `null`;\n\nexports[`n-dropdown > shows menu after click 1`] = `\n<div\n  class=\"n-dropdown-menu n-popover-shared n-dropdown n-dropdown--medium-size\"\n  style=\"--n-box-shadow: 0 3px 6px -4px rgba(0, 0, 0, .12), 0 6px 16px 0 rgba(0, 0, 0, .08), 0 9px 28px 8px rgba(0, 0, 0, .05); --n-bezier: cubic-bezier(.4, 0, .2, 1); --n-bezier-ease-in: cubic-bezier(.4, 0, 1, 1); --n-bezier-ease-out: cubic-bezier(0, 0, .2, 1); --n-font-size: 14px; --n-text-color: rgb(51, 54, 57); --n-color: #fff; --n-divider-color: rgb(239, 239, 245); --n-border-radius: 3px; --n-arrow-height: 6px; --n-arrow-offset: 10px; --n-arrow-offset-vertical: 10px; --n-padding: 4px 0; --n-space: 6px; --n-space-arrow: 10px; --n-option-height: 34px; --n-option-prefix-width: 14px; --n-option-icon-prefix-width: 36px; --n-option-suffix-width: 14px; --n-option-icon-suffix-width: 32px; --n-option-icon-size: 16px; --n-option-opacity-disabled: 0.5; --n-option-color-hover: rgb(243, 243, 245); --n-option-color-active: rgba(24, 160, 88, 0.1); --n-option-text-color: rgb(51, 54, 57); --n-option-text-color-hover: rgb(51, 54, 57); --n-option-text-color-active: #18a058; --n-option-text-color-child-active: #18a058; --n-prefix-color: rgb(51, 54, 57); --n-suffix-color: rgb(51, 54, 57); --n-group-header-text-color: rgb(118, 124, 130);\"\n>\n  \n  \n  <div\n    class=\"n-dropdown-option\"\n  >\n    <div\n      class=\"n-dropdown-option-body n-dropdown-option-body--group\"\n    >\n      <div\n        class=\"n-dropdown-option-body__prefix n-dropdown-option-body__prefix--show-icon\"\n        data-dropdown-option=\"true\"\n      />\n      <div\n        class=\"n-dropdown-option-body__label\"\n        data-dropdown-option=\"true\"\n      >\n        主角和吃的\n      </div>\n      <div\n        class=\"n-dropdown-option-body__suffix n-dropdown-option-body__suffix--has-submenu\"\n        data-dropdown-option=\"true\"\n      />\n    </div>\n  </div>\n  \n  <div\n    class=\"n-dropdown-option\"\n    data-dropdown-option=\"true\"\n  >\n    <div\n      class=\"n-dropdown-option-body\"\n    >\n      <div\n        class=\"n-dropdown-option-body__prefix n-dropdown-option-body__prefix--show-icon\"\n      >\n        <!---->\n      </div>\n      <div\n        class=\"n-dropdown-option-body__label\"\n        data-dropdown-option=\"true\"\n      >\n        杰·盖茨比\n      </div>\n      <div\n        class=\"n-dropdown-option-body__suffix n-dropdown-option-body__suffix--has-submenu\"\n        data-dropdown-option=\"true\"\n      />\n    </div>\n    <!---->\n  </div>\n  <div\n    class=\"n-dropdown-divider\"\n  />\n  <div\n    class=\"n-dropdown-option\"\n    data-dropdown-option=\"true\"\n  >\n    <div\n      class=\"n-dropdown-option-body n-dropdown-option-body--disabled\"\n    >\n      <div\n        class=\"n-dropdown-option-body__prefix n-dropdown-option-body__prefix--show-icon\"\n      >\n        <i\n          class=\"n-icon\"\n          role=\"img\"\n          style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1);\"\n        >\n          <svg\n            viewBox=\"0 0 512 512\"\n            xmlns=\"http://www.w3.org/2000/svg\"\n            xmlns:xlink=\"http://www.w3.org/1999/xlink\"\n          >\n            <rect\n              fill=\"none\"\n              height=\"256\"\n              rx=\"16\"\n              ry=\"16\"\n              stroke=\"currentColor\"\n              stroke-linejoin=\"round\"\n              stroke-width=\"32\"\n              transform=\"rotate(180 256 208)\"\n              width=\"448\"\n              x=\"32\"\n              y=\"80\"\n            />\n            <path\n              d=\"M64 384h384\"\n              fill=\"none\"\n              stroke=\"currentColor\"\n              stroke-linecap=\"round\"\n              stroke-linejoin=\"round\"\n              stroke-width=\"32\"\n            />\n            <path\n              d=\"M96 432h320\"\n              fill=\"none\"\n              stroke=\"currentColor\"\n              stroke-linecap=\"round\"\n              stroke-linejoin=\"round\"\n              stroke-width=\"32\"\n            />\n            <circle\n              cx=\"256\"\n              cy=\"208\"\n              fill=\"none\"\n              r=\"80\"\n              stroke=\"currentColor\"\n              stroke-linecap=\"round\"\n              stroke-linejoin=\"round\"\n              stroke-width=\"32\"\n            />\n            <path\n              d=\"M480 160a80 80 0 0 1-80-80\"\n              fill=\"none\"\n              stroke=\"currentColor\"\n              stroke-linecap=\"round\"\n              stroke-linejoin=\"round\"\n              stroke-width=\"32\"\n            />\n            <path\n              d=\"M32 160a80 80 0 0 0 80-80\"\n              fill=\"none\"\n              stroke=\"currentColor\"\n              stroke-linecap=\"round\"\n              stroke-linejoin=\"round\"\n              stroke-width=\"32\"\n            />\n            <path\n              d=\"M480 256a80 80 0 0 0-80 80\"\n              fill=\"none\"\n              stroke=\"currentColor\"\n              stroke-linecap=\"round\"\n              stroke-linejoin=\"round\"\n              stroke-width=\"32\"\n            />\n            <path\n              d=\"M32 256a80 80 0 0 1 80 80\"\n              fill=\"none\"\n              stroke=\"currentColor\"\n              stroke-linecap=\"round\"\n              stroke-linejoin=\"round\"\n              stroke-width=\"32\"\n            />\n          </svg>\n        </i>\n      </div>\n      <div\n        class=\"n-dropdown-option-body__label\"\n        data-dropdown-option=\"true\"\n      >\n        黛西·布坎南\n      </div>\n      <div\n        class=\"n-dropdown-option-body__suffix n-dropdown-option-body__suffix--has-submenu\"\n        data-dropdown-option=\"true\"\n      />\n    </div>\n    <!---->\n  </div>\n  \n  \n  <div\n    class=\"n-dropdown-divider\"\n  />\n  <div\n    class=\"n-dropdown-option\"\n    data-dropdown-option=\"true\"\n  >\n    <div\n      class=\"n-dropdown-option-body\"\n    >\n      <div\n        class=\"n-dropdown-option-body__prefix n-dropdown-option-body__prefix--show-icon\"\n      >\n        <!---->\n      </div>\n      <div\n        class=\"n-dropdown-option-body__label\"\n        data-dropdown-option=\"true\"\n      >\n        其他角色\n      </div>\n      <div\n        class=\"n-dropdown-option-body__suffix n-dropdown-option-body__suffix--has-submenu\"\n        data-dropdown-option=\"true\"\n      >\n        <i\n          class=\"n-icon\"\n          role=\"img\"\n          style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1);\"\n        >\n          <svg\n            fill=\"none\"\n            viewBox=\"0 0 16 16\"\n            xmlns=\"http://www.w3.org/2000/svg\"\n          >\n            <path\n              d=\"M5.64645 3.14645C5.45118 3.34171 5.45118 3.65829 5.64645 3.85355L9.79289 8L5.64645 12.1464C5.45118 12.3417 5.45118 12.6583 5.64645 12.8536C5.84171 13.0488 6.15829 13.0488 6.35355 12.8536L10.8536 8.35355C11.0488 8.15829 11.0488 7.84171 10.8536 7.64645L6.35355 3.14645C6.15829 2.95118 5.84171 2.95118 5.64645 3.14645Z\"\n              fill=\"currentColor\"\n            />\n          </svg>\n        </i>\n      </div>\n    </div>\n    \n    <div\n      class=\"n-dropdown-offset-container\"\n    >\n      <!---->\n    </div>\n    \n  </div>\n  \n  <!---->\n</div>\n`;\n"
  },
  {
    "path": "src/dropdown/tests/server.spec.tsx",
    "content": "import { setup } from '@css-render/vue3-ssr'\nimport { renderToString } from '@vue/server-renderer'\n/**\n * @vitest-environment node\n */\nimport { createSSRApp, h } from 'vue'\nimport { NDropdown } from '../..'\n\ndescribe('server side rendering', () => {\n  it('works', async () => {\n    const app = createSSRApp(() => (\n      <NDropdown>{{ default: () => 'foo' }}</NDropdown>\n    ))\n    setup(app)\n    try {\n      await renderToString(app)\n    }\n    catch (e) {\n      expect(e).not.toBeTruthy()\n    }\n  })\n})\n"
  },
  {
    "path": "src/dynamic-input/demos/enUS/basic.demo.vue",
    "content": "<markdown>\n# Use input preset\n\nBy default, the preset element of `n-dynamic-input` is `input`.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst value = ref(['', '', ''])\n</script>\n\n<template>\n  <n-dynamic-input\n    v-model:value=\"value\"\n    placeholder=\"Please type here\"\n    :min=\"3\"\n    :max=\"6\"\n  />\n  <pre>{{ JSON.stringify(value, null, 2) }}</pre>\n</template>\n"
  },
  {
    "path": "src/dynamic-input/demos/enUS/custom-action.demo.vue",
    "content": "<markdown>\n# Customizing action\n</markdown>\n\n<script lang=\"ts\" setup>\nimport {\n  BagAddOutline as AddIcon,\n  ChevronDownCircleOutline as DownIcon,\n  BagRemoveOutline as RemoveIcon,\n  ChevronUpCircleOutline as UpIcon\n} from '@vicons/ionicons5'\nimport { ref } from 'vue'\n\nconst value = ref(['Vue', 'Vue3', 'React'])\n</script>\n\n<template>\n  <n-dynamic-input\n    v-model:value=\"value\"\n    placeholder=\"Come on\"\n    :min=\"3\"\n    :max=\"6\"\n  >\n    <template #action=\"{ index, create, remove, move }\">\n      <n-space style=\"margin-left: 20px\">\n        <n-button @click=\"() => create(index)\">\n          <n-icon>\n            <AddIcon />\n          </n-icon>\n        </n-button>\n        <n-button disabled @click=\"() => remove(index)\">\n          <n-icon>\n            <RemoveIcon />\n          </n-icon>\n        </n-button>\n        <n-button @click=\"() => move('up', index)\">\n          <n-icon>\n            <UpIcon />\n          </n-icon>\n        </n-button>\n        <n-button @click=\"() => move('down', index)\">\n          <n-icon>\n            <DownIcon />\n          </n-icon>\n        </n-button>\n      </n-space>\n    </template>\n  </n-dynamic-input>\n  <pre>{{ JSON.stringify(value, null, 2) }}</pre>\n</template>\n"
  },
  {
    "path": "src/dynamic-input/demos/enUS/custom.demo.vue",
    "content": "<markdown>\n# Customizing input content\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst customValue = ref([\n  {\n    isCheck: true,\n    num: 1,\n    string: 'A String'\n  }\n])\n\nfunction onCreate() {\n  return {\n    isCheck: false,\n    num: 1,\n    string: 'A String'\n  }\n}\n</script>\n\n<template>\n  <n-dynamic-input v-model:value=\"customValue\" :on-create=\"onCreate\">\n    <template #create-button-default>\n      Add whatever you want\n    </template>\n    <template #default=\"{ value }\">\n      <div style=\"display: flex; align-items: center; width: 100%\">\n        <n-checkbox\n          v-model:checked=\"value.isCheck\"\n          style=\"margin-right: 12px\"\n        />\n        <n-input-number\n          v-model:value=\"value.num\"\n          style=\"margin-right: 12px; width: 160px\"\n        />\n        <n-input v-model:value=\"value.string\" type=\"text\" />\n      </div>\n    </template>\n  </n-dynamic-input>\n  <pre>{{ JSON.stringify(customValue, null, 2) }}</pre>\n</template>\n"
  },
  {
    "path": "src/dynamic-input/demos/enUS/form.demo.vue",
    "content": "<markdown>\n# Using it in a form\n\n`n-dynamic-input` itself cannot be verified. If you need to verify the input of `n-dynamic-input`, you can pass `n-form-item` in the custom content to complete the verification. Here is a complete example.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst dynamicInputRule = {\n  trigger: 'input',\n  validator(rule: unknown, value: string) {\n    if (value.length >= 5)\n      return new Error('Input up to 4 characters')\n    return true\n  }\n}\n\nconst model = ref({\n  dynamicInputValue: [{ value: '', name: '' }]\n})\n\nfunction onCreate() {\n  return {\n    name: '',\n    value: ''\n  }\n}\n</script>\n\n<template>\n  <n-form :model=\"model\">\n    <n-dynamic-input\n      v-model:value=\"model.dynamicInputValue\"\n      item-style=\"margin-bottom: 0;\"\n      :on-create=\"onCreate\"\n      #=\"{ index }\"\n    >\n      <div style=\"display: flex\">\n        <!--\n          Usually, the path change will cause the form-item verification content\n          or rules to be changed, so naive-ui will clear the existing\n          verification effect. But this example is a special case, as we know\n          the changes in path will not change form-item verification result and\n          rules, so set ignore-path-change on form-item\n        -->\n        <n-form-item\n          ignore-path-change\n          :show-label=\"false\"\n          :path=\"`dynamicInputValue[${index}].name`\"\n          :rule=\"dynamicInputRule\"\n        >\n          <n-input\n            v-model:value=\"model.dynamicInputValue[index].name\"\n            placeholder=\"Name\"\n            @keydown.enter.prevent\n          />\n          <!--\n           Since pressing enter on the input element will cause the button in the form to be clicked, the default behavior is prevented\n          -->\n        </n-form-item>\n        <div style=\"height: 34px; line-height: 34px; margin: 0 8px\">\n          =\n        </div>\n        <n-form-item\n          ignore-path-change\n          :show-label=\"false\"\n          :path=\"`dynamicInputValue[${index}].value`\"\n          :rule=\"dynamicInputRule\"\n        >\n          <n-input\n            v-model:value=\"model.dynamicInputValue[index].value\"\n            placeholder=\"Value\"\n            @keydown.enter.prevent\n          />\n        </n-form-item>\n      </div>\n    </n-dynamic-input>\n  </n-form>\n  <pre>{{ JSON.stringify(model.dynamicInputValue, null, 2) }}</pre>\n</template>\n"
  },
  {
    "path": "src/dynamic-input/demos/enUS/index.demo-entry.md",
    "content": "# Dynamic Input\n\n<!--single-column-->\n\nThis component's name has been changed so many times.\n\nIn the beginning, it was created for entering environment variables.\n\nIf you find the component doesn't look like what you want, I recommend you to write a new one. It's probably easier than using this one.\n\n## Demos\n\n```demo\nbasic.vue\npair.vue\ncustom.vue\nform.vue\nmove.vue\ncustom-action.vue\n```\n\n## API\n\n### DynamicInput Props\n\n| Name | Type | Default | Description | Version |\n| --- | --- | --- | --- | --- |\n| create-button-props | `ButtonProps` | `undefined` | Props of create item button. | 2.25.0 |\n| default-value | `unknown[]` | `[]` | Default value. |  |\n| disabled | `boolean` | `false` | Whether to disable the dynamic-input. It won't work for custom content. | 2.34.4 |\n| item-class | `string` | `undefined` | The class of each item of the dynamic input. | 2.36.0 |\n| item-style | `string \\| Object` | `undefined` | The style of each item of the dynamic input. |  |\n| key-field | `string` | `undefined` | The key of each item that should be used in the rendering of the list. |  |\n| min | `number` | `0` | Minimum number of items. |  |\n| max | `number` | `undefined` | Maximum number of items. |  |\n| preset | `'input' \\| 'pair'` | `'input'` | The preset of `n-dynamic-input`, it work when `$slots.default` is not set. |  |\n| show-sort-button | `boolean` | `false` | Whether to show sort button. | 2.25.0 |\n| value | `unknown[]` | `undefined` | Value in controlled mode. |  |\n| on-create | `(index: number) => void` | `undefined` | Add button (+) click callback. If set, the return value will be used as the initial value of the new item. `index` is the the new item's corresponding index in the value array, which starts from 1 (the second item). |  |\n| on-remove | `(index: number) => void` | `undefined` | Remove button (-) callback. |  |\n| on-update:value | `(value: any) => void` | `undefined` | On value changed callback. |  |\n\n### DynamicInput Props (Input Preset)\n\n| Name        | Type            | Default  | Description                    |\n| ----------- | --------------- | -------- | ------------------------------ |\n| value       | `Array<string>` | required | Value when being set manually. |\n| placeholder | `string`        | `''`     | Placeholder for each item.     |\n\n### DynamicInput Props (Pair Preset)\n\n| Name | Type | Default | Description |\n| --- | --- | --- | --- |\n| value | `Array<{ key: string, value: string }>` | required | Value when being set manually. |\n| key-placeholder | `string` | `''` | The placeholder of each item's key. |\n| value-placeholder | `string` | `''` | The placeholder of each item's value. |\n\n### DynamicInput Slots\n\n| Name | Parameters | Description | Version |\n| --- | --- | --- | --- |\n| action | `(options: { value: any, index: number, create: (index: number) => void, remove: (index: number) => void, move: (type: 'up' \\| 'down', index: number) => void })` | Customizing action; `value` and `index` are the value and index of the current item. | 2.34.4 |\n| default | `(options: { value: any, index: number })` | The content of each item; `value` and `index` are the value and index of the current item. |  |\n| create-button-default | `()` | Content of create button. | 2.25.0 |\n| create-button-icon | `()` | Icon of create button. | 2.25.0 |\n"
  },
  {
    "path": "src/dynamic-input/demos/enUS/move.demo.vue",
    "content": "<markdown>\n# Show sort button\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst value = ref(['', '', ''])\n</script>\n\n<template>\n  <n-dynamic-input\n    v-model:value=\"value\"\n    placeholder=\"Come on\"\n    show-sort-button\n  />\n  <pre>{{ JSON.stringify(value, null, 2) }}</pre>\n</template>\n"
  },
  {
    "path": "src/dynamic-input/demos/enUS/pair.demo.vue",
    "content": "<markdown>\n# Using pair preset\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst value = ref([\n  {\n    key: '',\n    value: ''\n  }\n])\n</script>\n\n<template>\n  <n-dynamic-input\n    v-model:value=\"value\"\n    preset=\"pair\"\n    key-placeholder=\"Please input the key\"\n    value-placeholder=\"Please input the value\"\n  />\n  <pre>{{ JSON.stringify(value, null, 2) }}</pre>\n</template>\n"
  },
  {
    "path": "src/dynamic-input/demos/zhCN/basic.demo.vue",
    "content": "<markdown>\n# 使用输入预设\n\n默认状况下，`n-dynamic-input` 的预设是 `input`。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst value = ref(['', '', ''])\n</script>\n\n<template>\n  <n-dynamic-input\n    v-model:value=\"value\"\n    placeholder=\"请输入\"\n    :min=\"3\"\n    :max=\"6\"\n  />\n  <pre>{{ JSON.stringify(value, null, 2) }}</pre>\n</template>\n"
  },
  {
    "path": "src/dynamic-input/demos/zhCN/create-debug.demo.vue",
    "content": "<markdown>\n# Create debug\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst options = ref<string[]>([])\n\nfunction onCreate(index: number) {\n  options.value.splice(index, 0, `insert-at-index: ${index}`)\n  console.log('create', index)\n}\n\nfunction onRemove(index: number) {\n  options.value.splice(index, 1)\n  console.log('remove', index)\n}\n</script>\n\n<template>\n  <n-dynamic-input :value=\"options\" @create=\"onCreate\" @remove=\"onRemove\">\n    <template #default=\"{ index, value }\">\n      index: {{ index }} - {{ value }}\n    </template>\n  </n-dynamic-input>\n</template>\n"
  },
  {
    "path": "src/dynamic-input/demos/zhCN/custom-action.demo.vue",
    "content": "<markdown>\n# 自定义操作\n</markdown>\n\n<script lang=\"ts\" setup>\nimport {\n  BagAddOutline as AddIcon,\n  ChevronDownCircleOutline as DownIcon,\n  BagRemoveOutline as RemoveIcon,\n  ChevronUpCircleOutline as UpIcon\n} from '@vicons/ionicons5'\nimport { ref } from 'vue'\n\nconst value = ref(['Vue', 'Vue3', 'React'])\n</script>\n\n<template>\n  <n-dynamic-input\n    v-model:value=\"value\"\n    placeholder=\"让知识来的更猛烈些\"\n    :min=\"3\"\n    :max=\"6\"\n  >\n    <template #action=\"{ index, create, remove, move }\">\n      <n-space style=\"margin-left: 20px\">\n        <n-button @click=\"() => create(index)\">\n          <n-icon>\n            <AddIcon />\n          </n-icon>\n        </n-button>\n        <n-button disabled @click=\"() => remove(index)\">\n          <n-icon>\n            <RemoveIcon />\n          </n-icon>\n        </n-button>\n        <n-button @click=\"() => move('up', index)\">\n          <n-icon>\n            <UpIcon />\n          </n-icon>\n        </n-button>\n        <n-button @click=\"() => move('down', index)\">\n          <n-icon>\n            <DownIcon />\n          </n-icon>\n        </n-button>\n      </n-space>\n    </template>\n  </n-dynamic-input>\n  <pre>{{ JSON.stringify(value, null, 2) }}</pre>\n</template>\n"
  },
  {
    "path": "src/dynamic-input/demos/zhCN/custom.demo.vue",
    "content": "<markdown>\n# 自定义内容\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst customValue = ref([\n  {\n    isCheck: true,\n    num: 1,\n    string: '一个字符串'\n  }\n])\n\nfunction onCreate() {\n  return {\n    isCheck: false,\n    num: 1,\n    string: '一个字符串'\n  }\n}\n</script>\n\n<template>\n  <n-dynamic-input v-model:value=\"customValue\" :on-create=\"onCreate\">\n    <template #create-button-default>\n      随便搞点啥\n    </template>\n    <template #default=\"{ value }\">\n      <div style=\"display: flex; align-items: center; width: 100%\">\n        <n-checkbox\n          v-model:checked=\"value.isCheck\"\n          style=\"margin-right: 12px\"\n        />\n        <n-input-number\n          v-model:value=\"value.num\"\n          style=\"margin-right: 12px; width: 160px\"\n        />\n        <n-input v-model:value=\"value.string\" type=\"text\" />\n      </div>\n    </template>\n  </n-dynamic-input>\n  <pre>{{ JSON.stringify(customValue, null, 2) }}</pre>\n</template>\n"
  },
  {
    "path": "src/dynamic-input/demos/zhCN/form.demo.vue",
    "content": "<markdown>\n# 在表单中使用\n\n`n-dynamic-input` 并不能作为一个单独的表项检验，如果你需要检验 `n-dynamic-input` 里面的内容，可以在自定义内容中传入 `n-form-item` 来完成数据的检验。下面是一个完整的例子。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst dynamicInputRule = {\n  trigger: 'input',\n  validator(rule: unknown, value: string) {\n    if (value.length >= 5)\n      return new Error('最多输入四个字符')\n    return true\n  }\n}\n\nconst model = ref({\n  dynamicInputValue: [{ value: '', name: '' }]\n})\n\nfunction onCreate() {\n  return {\n    name: '',\n    value: ''\n  }\n}\n</script>\n\n<template>\n  <n-form :model=\"model\">\n    <n-dynamic-input\n      v-model:value=\"model.dynamicInputValue\"\n      item-style=\"margin-bottom: 0;\"\n      :on-create=\"onCreate\"\n      #=\"{ index }\"\n    >\n      <div style=\"display: flex\">\n        <!--\n          通常，path 的变化会导致 form-item 验证内容或规则的改变，所以 naive-ui 会清理掉\n          表项已有的验证信息。但是这个例子是个特殊情况，我们明确的知道，path 的改变不会导致\n          form-item 验证内容和规则的变化，所以就 ignore-path-change\n        -->\n        <n-form-item\n          ignore-path-change\n          :show-label=\"false\"\n          :path=\"`dynamicInputValue[${index}].name`\"\n          :rule=\"dynamicInputRule\"\n        >\n          <n-input\n            v-model:value=\"model.dynamicInputValue[index].name\"\n            placeholder=\"Name\"\n            @keydown.enter.prevent\n          />\n          <!--\n            由于在 input 元素里按回车会导致 form 里面的 button 被点击，所以阻止了默认行为\n          -->\n        </n-form-item>\n        <div style=\"height: 34px; line-height: 34px; margin: 0 8px\">\n          =\n        </div>\n        <n-form-item\n          ignore-path-change\n          :show-label=\"false\"\n          :path=\"`dynamicInputValue[${index}].value`\"\n          :rule=\"dynamicInputRule\"\n        >\n          <n-input\n            v-model:value=\"model.dynamicInputValue[index].value\"\n            placeholder=\"Value\"\n            @keydown.enter.prevent\n          />\n        </n-form-item>\n      </div>\n    </n-dynamic-input>\n  </n-form>\n  <pre>{{ JSON.stringify(model.dynamicInputValue, null, 2) }}</pre>\n</template>\n"
  },
  {
    "path": "src/dynamic-input/demos/zhCN/index.demo-entry.md",
    "content": "# 动态录入 Dynamic Input\n\n<!--single-column-->\n\n这个组件的名字改过很多次。\n\n一开始它被造出来是为了输入环境变量。\n\n如果你觉得这个组件和你预想差的太多，建议新写一个，大概率比调整这个简单。\n\n## 演示\n\n```demo\nbasic.vue\npair.vue\ncustom.vue\nform.vue\nmove.vue\ncustom-action.vue\nrtl-debug.vue\ncreate-debug.vue\n```\n\n## API\n\n### DynamicInput Props\n\n| 名称 | 类型 | 默认值 | 说明 | 版本 |\n| --- | --- | --- | --- | --- |\n| create-button-props | `ButtonProps` | `undefined` | 新建项按钮的属性 | 2.25.0 |\n| default-value | `unknown[]` | `[]` | 非受控模式下的默认值 |  |\n| disabled | `boolean` | `false` | 是否禁用，对自定义内容无效 | 2.34.4 |\n| item-class | `string` | `undefined` | 动态录入中每项的类名 | 2.36.0 |\n| item-style | `string \\| Object` | `undefined` | 动态录入中每项的样式 |  |\n| key-field | `string` | `undefined` | 每一项的 key 值，会被用于列表渲染中 |  |\n| min | `number` | `0` | 最少有几项内容 |  |\n| max | `number` | `undefined` | 最多有几项内容 |  |\n| preset | `'input' \\| 'pair'` | `'input'` | 动态录入使用的预设，在不设定 `$slots.default` 的时候生效 |  |\n| show-sort-button | `boolean` | `false` | 是否显示排序按钮 | 2.25.0 |\n| value | `unknown[]` | `undefined` | 受控模式下的值 |  |\n| on-create | `(index: number) => void` | `undefined` | 点击添加按钮时的回调，如果设定则返回值会被用作新添加的初始值。其中 `index` 是创建内容将要被放置到的位置对应的数组索引，从 1（第二项）开始计算 |  |\n| on-remove | `(index: number) => void` | `undefined` | 点击第 index 项删除按钮的回调 |  |\n| on-update:value | `(value: any) => void` | `undefined` | 组件值发生变化的回调 |  |\n\n### DynamicInput Props(Input Preset)\n\n| 名称        | 类型            | 默认值   | 说明                 |\n| ----------- | --------------- | -------- | -------------------- |\n| value       | `Array<string>` | required | Input 预设模式下的值 |\n| placeholder | `string`        | `''`     | 每项的提示信息       |\n\n### DynamicInput Props(Pair Preset)\n\n| 名称 | 类型 | 默认值 | 说明 |\n| --- | --- | --- | --- |\n| value | `Array<{ key: string, value: string }>` | required | Pair 预设模式下的值 |\n| key-placeholder | `string` | `''` | 每项的 `key` 的提示信息 |\n| value-placeholder | `string` | `''` | 每项的 `value` 的提示信息 |\n\n### DynamicInput Slots\n\n| 名称 | 参数 | 说明 | 版本 |\n| --- | --- | --- | --- |\n| action | `(options: { value: any, index: number, create: (index: number) => void, remove: (index: number) => void, move: (type: 'up' \\| 'down', index: number) => void })` | 自定义操作，其中 `value` 为该项对应的数组值，`index` 为该项对应的数组索引 | 2.34.4 |\n| default | `(options: { value: any, index: number })` | 每一项的渲染方式，其中 `value` 为该项对应的数组值，`index` 为该项对应的数组索引 |  |\n| create-button-default | `()` | 新建项按钮的内容 | 2.25.0 |\n| create-button-icon | `()` | 新建项按钮的图标 | 2.25.0 |\n"
  },
  {
    "path": "src/dynamic-input/demos/zhCN/move.demo.vue",
    "content": "<markdown>\n# 显示排序按钮\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst value = ref(['', '', ''])\n</script>\n\n<template>\n  <n-dynamic-input\n    v-model:value=\"value\"\n    show-sort-button\n    placeholder=\"请输入\"\n  />\n  <pre>{{ JSON.stringify(value, null, 2) }}</pre>\n</template>\n"
  },
  {
    "path": "src/dynamic-input/demos/zhCN/pair.demo.vue",
    "content": "<markdown>\n# 使用键值对预设\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst value = ref([\n  {\n    key: '',\n    value: ''\n  }\n])\n</script>\n\n<template>\n  <n-dynamic-input\n    v-model:value=\"value\"\n    preset=\"pair\"\n    key-placeholder=\"环境变量名\"\n    value-placeholder=\"环境变量值\"\n  />\n  <pre>{{ JSON.stringify(value, null, 2) }}</pre>\n</template>\n"
  },
  {
    "path": "src/dynamic-input/demos/zhCN/rtl-debug.demo.vue",
    "content": "<markdown>\n# Rtl Debug\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { unstableDynamicInputRtl } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst rtlEnabled = ref(false)\nconst rtlStyles = [unstableDynamicInputRtl]\nconst value = ref(['', '', ''])\n</script>\n\n<template>\n  <n-space vertical>\n    <n-space><n-switch v-model:value=\"rtlEnabled\" />Rtl</n-space>\n    <n-config-provider :rtl=\"rtlEnabled ? rtlStyles : undefined\">\n      <n-dynamic-input\n        v-model:value=\"value\"\n        placeholder=\"请输入\"\n        :min=\"3\"\n        :max=\"6\"\n      />\n      <pre>{{ JSON.stringify(value, null, 2) }}</pre>\n    </n-config-provider>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/dynamic-input/index.ts",
    "content": "export { dynamicInputProps, default as NDynamicInput } from './src/DynamicInput'\nexport type { DynamicInputProps, DynamicInputSlots } from './src/DynamicInput'\nexport type {\n  DynamicInputActionSlotProps,\n  DynamicInputDefaultSlotProps\n} from './src/interface'\n"
  },
  {
    "path": "src/dynamic-input/src/DynamicInput.tsx",
    "content": "import type { CSSProperties, PropType, VNode } from 'vue'\nimport type { ThemeProps } from '../../_mixins'\nimport type { ExtractPublicPropTypes, MaybeArray } from '../../_utils'\nimport type { ButtonProps } from '../../button'\nimport type { DynamicInputTheme } from '../styles'\nimport type {\n  DynamicInputActionSlotProps,\n  DynamicInputDefaultSlotProps,\n  OnUpdateValue\n} from './interface'\nimport { createId } from 'seemly'\nimport { useMergedState } from 'vooks'\nimport {\n  computed,\n  defineComponent,\n  h,\n  inject,\n  isProxy,\n  provide,\n  ref,\n  toRaw,\n  toRef,\n  watchEffect\n} from 'vue'\nimport { NBaseIcon } from '../../_internal'\nimport {\n  AddIcon,\n  ArrowDownIcon,\n  ArrowUpIcon,\n  RemoveIcon\n} from '../../_internal/icons'\nimport { useConfig, useLocale, useTheme, useThemeClass } from '../../_mixins'\nimport { formItemInjectionKey } from '../../_mixins/use-form-item'\nimport { useRtl } from '../../_mixins/use-rtl'\nimport {\n  call,\n  resolveSlot,\n  resolveSlotWithTypedProps,\n  warnOnce\n} from '../../_utils'\nimport { NButton } from '../../button'\nimport { NButtonGroup } from '../../button-group'\nimport { dynamicInputLight } from '../styles'\nimport NDynamicInputInputPreset from './InputPreset'\nimport { dynamicInputInjectionKey } from './interface'\nimport NDynamicInputPairPreset from './PairPreset'\nimport style from './styles/index.cssr'\n\nconst globalDataKeyMap = new WeakMap()\n\nexport const dynamicInputProps = {\n  ...(useTheme.props as ThemeProps<DynamicInputTheme>),\n  max: Number,\n  min: {\n    type: Number,\n    default: 0\n  },\n  value: Array as PropType<any[]>,\n  // TODO: make it robust for different types\n  defaultValue: {\n    type: Array as PropType<any[]>,\n    default: () => []\n  },\n  preset: {\n    type: String as PropType<'input' | 'pair'>,\n    default: 'input'\n  },\n  keyField: String,\n  itemClass: String,\n  itemStyle: [String, Object] as PropType<string | CSSProperties>,\n  // for preset pair\n  keyPlaceholder: {\n    type: String,\n    default: ''\n  },\n  valuePlaceholder: {\n    type: String,\n    default: ''\n  },\n  // for preset input\n  placeholder: {\n    type: String,\n    default: ''\n  },\n  disabled: Boolean,\n  showSortButton: Boolean,\n  createButtonProps: Object as PropType<ButtonProps>,\n  onCreate: Function as PropType<(index: number) => any>,\n  onRemove: Function as PropType<(index: number) => void>,\n  'onUpdate:value': [Function, Array] as PropType<MaybeArray<OnUpdateValue>>,\n  onUpdateValue: [Function, Array] as PropType<MaybeArray<OnUpdateValue>>,\n  // deprecated\n  onClear: Function as PropType<() => void>,\n  onInput: [Function, Array] as PropType<MaybeArray<OnUpdateValue>>\n} as const\n\nexport type DynamicInputProps = ExtractPublicPropTypes<typeof dynamicInputProps>\n\nexport interface DynamicInputSlots {\n  action?: (props: DynamicInputActionSlotProps) => VNode[]\n  default?: (props: DynamicInputDefaultSlotProps) => VNode[]\n  'create-button-default'?: () => VNode[]\n  'create-button-icon'?: () => VNode[]\n}\n\nexport default defineComponent({\n  name: 'DynamicInput',\n  props: dynamicInputProps,\n  setup(props, { slots }) {\n    if (__DEV__) {\n      watchEffect(() => {\n        if (props.onClear !== undefined) {\n          warnOnce(\n            'dynamic-input',\n            '`on-clear` is deprecated, it is out of usage anymore.'\n          )\n        }\n        if (props.onInput !== undefined) {\n          warnOnce(\n            'dynamic-input',\n            '`on-input` is deprecated, please use `on-update:value` instead.'\n          )\n        }\n      })\n    }\n    const {\n      mergedComponentPropsRef,\n      mergedClsPrefixRef,\n      mergedRtlRef,\n      inlineThemeDisabled\n    } = useConfig()\n    const NFormItem = inject(formItemInjectionKey, null)\n    const uncontrolledValueRef = ref(props.defaultValue)\n    const controlledValueRef = toRef(props, 'value')\n    const mergedValueRef = useMergedState(\n      controlledValueRef,\n      uncontrolledValueRef\n    )\n    const themeRef = useTheme(\n      'DynamicInput',\n      '-dynamic-input',\n      style,\n      dynamicInputLight,\n      props,\n      mergedClsPrefixRef\n    )\n    const insertionDisabledRef = computed(() => {\n      const { value: mergedValue } = mergedValueRef\n      if (Array.isArray(mergedValue)) {\n        const { max } = props\n        return max !== undefined && mergedValue.length >= max\n      }\n      return false\n    })\n    const removeDisabledRef = computed(() => {\n      const { value: mergedValue } = mergedValueRef\n      if (Array.isArray(mergedValue))\n        return mergedValue.length <= props.min\n      return true\n    })\n    const buttonSizeRef = computed(() => {\n      return mergedComponentPropsRef?.value?.DynamicInput?.buttonSize\n    })\n    function doUpdateValue(value: any[]): void {\n      const { onInput, 'onUpdate:value': _onUpdateValue, onUpdateValue } = props\n      if (onInput)\n        call(onInput, value)\n      if (_onUpdateValue)\n        call(_onUpdateValue, value)\n      if (onUpdateValue)\n        call(onUpdateValue, value)\n      uncontrolledValueRef.value = value\n    }\n    function ensureKey(value: any, index: number): string | number {\n      if (value === undefined || value === null)\n        return index\n      if (typeof value !== 'object')\n        return index\n      const rawValue = isProxy(value) ? toRaw(value) : value\n      let key = globalDataKeyMap.get(rawValue as WeakKey)\n      if (key === undefined) {\n        globalDataKeyMap.set(rawValue as WeakKey, (key = createId()))\n      }\n      return key\n    }\n    function handleValueChange(index: number, value: any): void {\n      const { value: mergedValue } = mergedValueRef\n      const newValue = Array.from(mergedValue ?? [])\n      const originalItem = newValue[index]\n      newValue[index] = value\n      // update dataKeyMap\n      if (\n        originalItem\n        && value\n        && typeof originalItem === 'object'\n        && typeof value === 'object'\n      ) {\n        const rawOriginal = isProxy(originalItem)\n          ? toRaw(originalItem)\n          : originalItem\n        const rawNew = isProxy(value) ? toRaw(value) : value\n        // inherit key is value position is not change\n        const originalKey = globalDataKeyMap.get(rawOriginal as WeakKey)\n        if (originalKey !== undefined) {\n          globalDataKeyMap.set(rawNew as WeakKey, originalKey)\n        }\n      }\n      doUpdateValue(newValue)\n    }\n    function handleCreateClick(): void {\n      createItem(-1)\n    }\n    function createItem(index: number): void {\n      const { value: mergedValue } = mergedValueRef\n      const { onCreate } = props\n      const newValue = Array.from(mergedValue ?? [])\n      if (onCreate) {\n        newValue.splice(index + 1, 0, onCreate(index + 1))\n        doUpdateValue(newValue)\n      }\n      else if (slots.default) {\n        newValue.splice(index + 1, 0, null)\n        doUpdateValue(newValue)\n      }\n      else {\n        switch (props.preset) {\n          case 'input':\n            newValue.splice(index + 1, 0, '')\n            doUpdateValue(newValue)\n            break\n          case 'pair':\n            newValue.splice(index + 1, 0, { key: '', value: '' })\n            doUpdateValue(newValue)\n            break\n        }\n      }\n    }\n    function remove(index: number): void {\n      const { value: mergedValue } = mergedValueRef\n      if (!Array.isArray(mergedValue))\n        return\n      const { min } = props\n      if (mergedValue.length <= min)\n        return\n      const { onRemove } = props\n      if (onRemove) {\n        onRemove(index)\n      }\n      const newValue = Array.from(mergedValue)\n      newValue.splice(index, 1)\n      doUpdateValue(newValue)\n    }\n    function swap(\n      array: any[],\n      currentIndex: number,\n      targetIndex: number\n    ): void {\n      if (\n        currentIndex < 0\n        || targetIndex < 0\n        || currentIndex >= array.length\n        || targetIndex >= array.length\n      ) {\n        return\n      }\n      if (currentIndex === targetIndex)\n        return\n      const currentItem = array[currentIndex]\n      array[currentIndex] = array[targetIndex]\n      array[targetIndex] = currentItem\n    }\n    function move(type: 'up' | 'down', index: number): void {\n      const { value: mergedValue } = mergedValueRef\n      if (!Array.isArray(mergedValue))\n        return\n      const newValue = Array.from(mergedValue)\n      if (type === 'up') {\n        swap(newValue, index, index - 1)\n      }\n      if (type === 'down') {\n        swap(newValue, index, index + 1)\n      }\n      doUpdateValue(newValue)\n    }\n    provide(dynamicInputInjectionKey, {\n      mergedThemeRef: themeRef,\n      keyPlaceholderRef: toRef(props, 'keyPlaceholder'),\n      valuePlaceholderRef: toRef(props, 'valuePlaceholder'),\n      placeholderRef: toRef(props, 'placeholder')\n    })\n    const rtlEnabledRef = useRtl(\n      'DynamicInput',\n      mergedRtlRef,\n      mergedClsPrefixRef\n    )\n    const cssVarsRef = computed(() => {\n      const {\n        self: { actionMargin, actionMarginRtl }\n      } = themeRef.value\n      return {\n        '--action-margin': actionMargin,\n        '--action-margin-rtl': actionMarginRtl\n      }\n    })\n    const themeClassHandle = inlineThemeDisabled\n      ? useThemeClass('dynamic-input', undefined, cssVarsRef, props)\n      : undefined\n\n    return {\n      locale: useLocale('DynamicInput').localeRef,\n      rtlEnabled: rtlEnabledRef,\n      buttonSize: buttonSizeRef,\n      mergedClsPrefix: mergedClsPrefixRef,\n      NFormItem,\n      uncontrolledValue: uncontrolledValueRef,\n      mergedValue: mergedValueRef,\n      insertionDisabled: insertionDisabledRef,\n      removeDisabled: removeDisabledRef,\n      handleCreateClick,\n      ensureKey,\n      handleValueChange,\n      remove,\n      move,\n      createItem,\n      mergedTheme: themeRef,\n      cssVars: inlineThemeDisabled ? undefined : cssVarsRef,\n      themeClass: themeClassHandle?.themeClass,\n      onRender: themeClassHandle?.onRender\n    }\n  },\n  render() {\n    const {\n      $slots,\n      itemClass,\n      buttonSize,\n      mergedClsPrefix,\n      mergedValue,\n      locale,\n      mergedTheme,\n      keyField,\n      itemStyle,\n      preset,\n      showSortButton,\n      NFormItem,\n      ensureKey,\n      handleValueChange,\n      remove,\n      createItem,\n      move,\n      onRender,\n      disabled\n    } = this\n    onRender?.()\n    return (\n      <div\n        class={[\n          `${mergedClsPrefix}-dynamic-input`,\n          this.rtlEnabled && `${mergedClsPrefix}-dynamic-input--rtl`,\n          this.themeClass\n        ]}\n        style={this.cssVars as CSSProperties}\n      >\n        {!Array.isArray(mergedValue) || mergedValue.length === 0 ? (\n          <NButton\n            block\n            ghost\n            dashed\n            size={buttonSize}\n            {...this.createButtonProps}\n            disabled={this.insertionDisabled || disabled}\n            theme={mergedTheme.peers.Button}\n            themeOverrides={mergedTheme.peerOverrides.Button}\n            onClick={this.handleCreateClick}\n          >\n            {{\n              default: () =>\n                resolveSlot($slots['create-button-default'], () => [\n                  locale.create\n                ]),\n              icon: () =>\n                resolveSlot($slots['create-button-icon'], () => [\n                  <NBaseIcon clsPrefix={mergedClsPrefix}>\n                    {{ default: () => <AddIcon /> }}\n                  </NBaseIcon>\n                ])\n            }}\n          </NButton>\n        ) : (\n          mergedValue.map((_, index) => (\n            <div\n              key={keyField ? _[keyField] : ensureKey(_, index)}\n              data-key={keyField ? _[keyField] : ensureKey(_, index)}\n              class={[`${mergedClsPrefix}-dynamic-input-item`, itemClass]}\n              style={itemStyle}\n            >\n              {resolveSlotWithTypedProps(\n                $slots.default,\n                {\n                  value: mergedValue[index],\n                  index\n                },\n                () => {\n                  return [\n                    preset === 'input' ? (\n                      <NDynamicInputInputPreset\n                        disabled={disabled}\n                        clsPrefix={mergedClsPrefix}\n                        value={mergedValue[index]}\n                        parentPath={\n                          NFormItem ? NFormItem.path.value : undefined\n                        }\n                        path={\n                          NFormItem?.path.value\n                            ? `${NFormItem.path.value}[${index}]`\n                            : undefined\n                        }\n                        onUpdateValue={(v) => {\n                          handleValueChange(index, v)\n                        }}\n                      />\n                    ) : preset === 'pair' ? (\n                      <NDynamicInputPairPreset\n                        disabled={disabled}\n                        clsPrefix={mergedClsPrefix}\n                        value={mergedValue[index]}\n                        parentPath={\n                          NFormItem ? NFormItem.path.value : undefined\n                        }\n                        path={\n                          NFormItem?.path.value\n                            ? `${NFormItem.path.value}[${index}]`\n                            : undefined\n                        }\n                        onUpdateValue={(v) => {\n                          handleValueChange(index, v)\n                        }}\n                      />\n                    ) : null\n                  ]\n                }\n              )}\n              {resolveSlotWithTypedProps(\n                $slots.action,\n                {\n                  value: mergedValue[index],\n                  index,\n                  create: createItem,\n                  remove,\n                  move\n                },\n                () => [\n                  <div class={`${mergedClsPrefix}-dynamic-input-item__action`}>\n                    <NButtonGroup size={buttonSize}>\n                      {{\n                        default: () => [\n                          <NButton\n                            disabled={this.removeDisabled || disabled}\n                            theme={mergedTheme.peers.Button}\n                            themeOverrides={mergedTheme.peerOverrides.Button}\n                            circle\n                            onClick={() => {\n                              remove(index)\n                            }}\n                          >\n                            {{\n                              icon: () => (\n                                <NBaseIcon clsPrefix={mergedClsPrefix}>\n                                  {{ default: () => <RemoveIcon /> }}\n                                </NBaseIcon>\n                              )\n                            }}\n                          </NButton>,\n                          <NButton\n                            disabled={this.insertionDisabled || disabled}\n                            circle\n                            theme={mergedTheme.peers.Button}\n                            themeOverrides={mergedTheme.peerOverrides.Button}\n                            onClick={() => {\n                              createItem(index)\n                            }}\n                          >\n                            {{\n                              icon: () => (\n                                <NBaseIcon clsPrefix={mergedClsPrefix}>\n                                  {{ default: () => <AddIcon /> }}\n                                </NBaseIcon>\n                              )\n                            }}\n                          </NButton>,\n                          showSortButton ? (\n                            <NButton\n                              disabled={index === 0 || disabled}\n                              circle\n                              theme={mergedTheme.peers.Button}\n                              themeOverrides={mergedTheme.peerOverrides.Button}\n                              onClick={() => {\n                                move('up', index)\n                              }}\n                            >\n                              {{\n                                icon: () => (\n                                  <NBaseIcon clsPrefix={mergedClsPrefix}>\n                                    {{\n                                      default: () => <ArrowUpIcon />\n                                    }}\n                                  </NBaseIcon>\n                                )\n                              }}\n                            </NButton>\n                          ) : null,\n                          showSortButton ? (\n                            <NButton\n                              disabled={\n                                index === mergedValue.length - 1 || disabled\n                              }\n                              circle\n                              theme={mergedTheme.peers.Button}\n                              themeOverrides={mergedTheme.peerOverrides.Button}\n                              onClick={() => {\n                                move('down', index)\n                              }}\n                            >\n                              {{\n                                icon: () => (\n                                  <NBaseIcon clsPrefix={mergedClsPrefix}>\n                                    {{ default: () => <ArrowDownIcon /> }}\n                                  </NBaseIcon>\n                                )\n                              }}\n                            </NButton>\n                          ) : null\n                        ]\n                      }}\n                    </NButtonGroup>\n                  </div>\n                ]\n              )}\n            </div>\n          ))\n        )}\n      </div>\n    )\n  }\n})\n"
  },
  {
    "path": "src/dynamic-input/src/InputPreset.tsx",
    "content": "import type { PropType } from 'vue'\nimport { defineComponent, h, inject } from 'vue'\nimport { NInput } from '../../input'\nimport { dynamicInputInjectionKey } from './interface'\n\nexport default defineComponent({\n  name: 'DynamicInputInputPreset',\n  props: {\n    clsPrefix: {\n      type: String,\n      required: true\n    },\n    value: {\n      type: String,\n      default: ''\n    },\n    disabled: Boolean,\n    parentPath: String,\n    path: String,\n    onUpdateValue: {\n      type: Function as PropType<(value: string) => void>,\n      required: true\n    }\n  },\n  setup() {\n    const { mergedThemeRef, placeholderRef } = inject(dynamicInputInjectionKey)!\n    return {\n      mergedTheme: mergedThemeRef,\n      placeholder: placeholderRef\n    }\n  },\n  render() {\n    const {\n      mergedTheme,\n      placeholder,\n      value,\n      clsPrefix,\n      onUpdateValue,\n      disabled\n    } = this\n    return (\n      <div class={`${clsPrefix}-dynamic-input-preset-input`}>\n        <NInput\n          theme={mergedTheme.peers.Input}\n          theme-overrides={mergedTheme.peerOverrides.Input}\n          value={value}\n          placeholder={placeholder}\n          onUpdateValue={onUpdateValue}\n          disabled={disabled}\n        />\n      </div>\n    )\n  }\n})\n"
  },
  {
    "path": "src/dynamic-input/src/PairPreset.tsx",
    "content": "import type { PropType } from 'vue'\nimport { defineComponent, h, inject } from 'vue'\nimport { NInput } from '../../input'\nimport { dynamicInputInjectionKey } from './interface'\n\nexport default defineComponent({\n  name: 'DynamicInputPairPreset',\n  props: {\n    clsPrefix: {\n      type: String,\n      required: true\n    },\n    value: {\n      type: Object as PropType<{ key: string, value: string }>,\n      default: () => ({\n        key: '',\n        value: ''\n      })\n    },\n    disabled: Boolean,\n    parentPath: String,\n    path: String,\n    onUpdateValue: {\n      type: Function as PropType<\n        (data: { key: string, value: string }) => void\n      >,\n      required: true\n    }\n  },\n  setup(props) {\n    const { mergedThemeRef, keyPlaceholderRef, valuePlaceholderRef } = inject(\n      dynamicInputInjectionKey\n    )!\n    return {\n      mergedTheme: mergedThemeRef,\n      keyPlaceholder: keyPlaceholderRef,\n      valuePlaceholder: valuePlaceholderRef,\n      handleKeyInput(key: string) {\n        props.onUpdateValue({\n          key,\n          value: props.value.value\n        })\n      },\n      handleValueInput(value: string) {\n        props.onUpdateValue({\n          key: props.value.key,\n          value\n        })\n      }\n    }\n  },\n  render() {\n    const {\n      mergedTheme,\n      keyPlaceholder,\n      valuePlaceholder,\n      value,\n      clsPrefix,\n      disabled\n    } = this\n    return (\n      <div class={`${clsPrefix}-dynamic-input-preset-pair`}>\n        <NInput\n          theme={mergedTheme.peers.Input}\n          theme-overrides={mergedTheme.peerOverrides.Input}\n          value={value.key}\n          class={`${clsPrefix}-dynamic-input-pair-input`}\n          placeholder={keyPlaceholder}\n          onUpdateValue={this.handleKeyInput}\n          disabled={disabled}\n        />\n        <NInput\n          theme={mergedTheme.peers.Input}\n          theme-overrides={mergedTheme.peerOverrides.Input}\n          value={value.value}\n          class={`${clsPrefix}-dynamic-input-pair-input`}\n          placeholder={valuePlaceholder}\n          onUpdateValue={this.handleValueInput}\n          disabled={disabled}\n        />\n      </div>\n    )\n  }\n})\n"
  },
  {
    "path": "src/dynamic-input/src/interface.ts",
    "content": "import type { Ref } from 'vue'\nimport type { MergedTheme } from '../../_mixins'\nimport type { DynamicInputTheme } from '../styles'\nimport { createInjectionKey } from '../../_utils'\n\nexport interface DynamicInputInjection {\n  mergedThemeRef: Ref<MergedTheme<DynamicInputTheme>>\n  keyPlaceholderRef: Ref<string | undefined>\n  valuePlaceholderRef: Ref<string | undefined>\n  placeholderRef: Ref<string | undefined>\n}\n\nexport const dynamicInputInjectionKey\n  = createInjectionKey<DynamicInputInjection>('n-dynamic-input')\n\nexport type OnUpdateValue = <T>(value: T[]) => void\n\nexport interface DynamicInputDefaultSlotProps {\n  value: any\n  index: number\n}\n\nexport interface DynamicInputActionSlotProps {\n  value: any\n  index: number\n  create: (index: number) => void\n  remove: (index: number) => void\n  move: (type: 'up' | 'down', index: number) => void\n}\n"
  },
  {
    "path": "src/dynamic-input/src/styles/index.cssr.ts",
    "content": "import { c, cB, cE, cM } from '../../../_utils/cssr'\n\n// vars:\n// --action-margin\nexport default cB('dynamic-input', {\n  width: '100%'\n}, [\n  cB('dynamic-input-item', `\n    margin-bottom: 10px;\n    display: flex;\n    flex-wrap: nowrap;\n  `, [\n    cB('dynamic-input-preset-input', {\n      flex: 1,\n      alignItems: 'center'\n    }),\n    cB('dynamic-input-preset-pair', `\n      flex: 1;\n      display: flex;\n      align-items: center;\n    `, [\n      cB('dynamic-input-pair-input', [\n        c('&:first-child', {\n          'margin-right': '12px'\n        })\n      ])\n    ]),\n    cE('action', `\n      align-self: flex-start;\n      display: flex;\n      justify-content: flex-end;\n      flex-shrink: 0;\n      flex-grow: 0;\n      margin: var(--action-margin);\n    `, [\n      cM('icon', {\n        cursor: 'pointer'\n      })\n    ]),\n    c('&:last-child', {\n      marginBottom: 0\n    })\n  ]),\n  cB('form-item', `\n    padding-top: 0 !important;\n    margin-right: 0 !important;\n  `, [\n    cB('form-item-blank', {\n      paddingTop: '0 !important'\n    })\n  ])\n])\n"
  },
  {
    "path": "src/dynamic-input/src/styles/rtl.cssr.ts",
    "content": "import { c, cB, cE, cM } from '../../../_utils/cssr'\n\nexport default cB('dynamic-input', [\n  cM('rtl', `\n    direction: rtl;\n  `, [\n    cB('dynamic-input-preset-pair', [\n      cB('dynamic-input-pair-input', [\n        c('&:first-child', {\n          'margin-left': '12px',\n          'margin-right': '0'\n        })\n      ])\n    ]),\n    cB('dynamic-input-item', [\n      cE('action', `\n        margin: var(--action-margin-rtl);\n      `)\n    ])\n  ])\n])\n"
  },
  {
    "path": "src/dynamic-input/styles/_common.ts",
    "content": "export default {\n  actionMargin: '0 0 0 20px',\n  actionMarginRtl: '0 20px 0 0'\n}\n"
  },
  {
    "path": "src/dynamic-input/styles/dark.ts",
    "content": "import type { DynamicInputTheme } from './light'\nimport { commonDark } from '../../_styles/common'\nimport { buttonDark } from '../../button/styles'\nimport { inputDark } from '../../input/styles'\nimport commonVariables from './_common'\n\nconst dynamicInputDark: DynamicInputTheme = {\n  name: 'DynamicInput',\n  common: commonDark,\n  peers: {\n    Input: inputDark,\n    Button: buttonDark\n  },\n  self() {\n    return commonVariables\n  }\n}\n\nexport default dynamicInputDark\n"
  },
  {
    "path": "src/dynamic-input/styles/index.ts",
    "content": "export { default as dynamicInputDark } from './dark'\nexport { default as dynamicInputLight } from './light'\nexport type { DynamicInputTheme, DynamicInputThemeVars } from './light'\nexport { dynamicInputRtl } from './rtl'\n"
  },
  {
    "path": "src/dynamic-input/styles/light.ts",
    "content": "import { createTheme } from '../../_mixins'\nimport { commonLight } from '../../_styles/common'\nimport { buttonLight } from '../../button/styles'\nimport { inputLight } from '../../input/styles'\nimport commonVariables from './_common'\n\nfunction self() {\n  return commonVariables\n}\n\nexport type DynamicInputThemeVars = ReturnType<typeof self>\n\nconst dynamicInputLight = createTheme({\n  name: 'DynamicInput',\n  common: commonLight,\n  peers: {\n    Input: inputLight,\n    Button: buttonLight\n  },\n  self\n})\n\nexport default dynamicInputLight\nexport type DynamicInputTheme = typeof dynamicInputLight\n"
  },
  {
    "path": "src/dynamic-input/styles/rtl.ts",
    "content": "import type { RtlItem } from '../../config-provider/src/internal-interface'\nimport { buttonGroupRtl } from '../../button-group/styles/rtl'\nimport { buttonRtl } from '../../button/styles/rtl'\nimport { checkboxRtl } from '../../checkbox/styles/rtl'\nimport { inputNumberRtl } from '../../input-number/styles/rtl'\nimport { inputRtl } from '../../input/styles/rtl'\nimport rtlStyle from '../src/styles/rtl.cssr'\n\nexport const dynamicInputRtl: RtlItem = {\n  name: 'DynamicInput',\n  style: rtlStyle,\n  peers: [inputRtl, buttonRtl, buttonGroupRtl, checkboxRtl, inputNumberRtl]\n}\n"
  },
  {
    "path": "src/dynamic-input/tests/DynamicInput.spec.ts",
    "content": "import { mount } from '@vue/test-utils'\nimport { NDynamicInput } from '../index'\n\ndescribe('n-dynamic-input', () => {\n  it('should work with import on demand', () => {\n    mount(NDynamicInput)\n  })\n\n  it('should work with `value`', async () => {\n    const wrapper = mount(NDynamicInput, {\n      props: {\n        value: ['aaa']\n      }\n    })\n\n    const inputEl = wrapper.find('input')\n    expect(inputEl.element.value).toEqual('aaa')\n    expect(wrapper.html()).toContain('data-key=\"0\"')\n    wrapper.unmount()\n  })\n\n  it('should work with `create-button-props` props', async () => {\n    const wrapper = mount(NDynamicInput, {\n      props: {\n        value: [],\n        createButtonProps: {\n          dashed: true\n        }\n      }\n    })\n\n    expect(wrapper.find('.n-button').classes()).toContain('n-button--dashed')\n    wrapper.unmount()\n  })\n\n  it('should work with `preset` props', async () => {\n    const wrapper = mount(NDynamicInput, {\n      props: {\n        value: ['aaa']\n      }\n    })\n    expect(wrapper.find('.n-dynamic-input-preset-input').exists()).toBe(true)\n    expect(wrapper.find('.n-dynamic-input-preset-pair').exists()).toBe(false)\n\n    await wrapper.setProps({\n      preset: 'pair',\n      value: [\n        {\n          key: 'key',\n          value: 'value'\n        }\n      ]\n    })\n    expect(wrapper.find('.n-dynamic-input-preset-input').exists()).toBe(false)\n    expect(wrapper.find('.n-dynamic-input-preset-pair').exists()).toBe(true)\n    wrapper.unmount()\n  })\n\n  it('should work with `show-sort-button` props', async () => {\n    const wrapper = mount(NDynamicInput, {\n      props: {\n        value: ['aaa'],\n        showSortButton: true\n      }\n    })\n\n    expect(wrapper.findAll('button').length).toBe(4)\n    wrapper.unmount()\n  })\n\n  it('should work with `item-style` prop', async () => {\n    const wrapper = mount(NDynamicInput, {\n      props: {\n        value: ['aaa'],\n        itemStyle: { color: 'green' }\n      }\n    })\n\n    expect(\n      wrapper.findAll('.n-dynamic-input-item')[0].attributes('style')\n    ).toBe('color: green;')\n    wrapper.unmount()\n  })\n\n  it('should work with `min` `max` prop', async () => {\n    const wrapper = mount(NDynamicInput, {\n      props: {\n        value: ['', '', ''],\n        min: 2,\n        max: 4\n      }\n    })\n    expect(wrapper.find('.n-button--disabled').exists()).toBe(false)\n\n    await wrapper.setProps({ value: ['', ''] })\n    expect(wrapper.findAll('button')[0].classes()).toContain(\n      'n-button--disabled'\n    )\n\n    await wrapper.setProps({ value: ['', '', '', ''] })\n    expect(wrapper.findAll('button')[1].classes()).toContain(\n      'n-button--disabled'\n    )\n    wrapper.unmount()\n  })\n\n  it('should work with `placeholder` prop', async () => {\n    const wrapper = mount(NDynamicInput, {\n      props: {\n        value: [''],\n        placeholder: 'test'\n      }\n    })\n\n    expect(wrapper.find('input').attributes('placeholder')).toBe('test')\n    wrapper.unmount()\n  })\n\n  it('should work with `key-placeholder` prop', async () => {\n    const wrapper = mount(NDynamicInput, {\n      props: {\n        preset: 'pair',\n        value: [\n          {\n            key: '',\n            value: ''\n          }\n        ],\n        keyPlaceholder: 'test-key-placeholder'\n      }\n    })\n\n    expect(wrapper.findAll('input')[0].attributes('placeholder')).toBe(\n      'test-key-placeholder'\n    )\n    wrapper.unmount()\n  })\n\n  it('should work with `on-create` prop', async () => {\n    const onCreate = vi.fn()\n    const wrapper = mount(NDynamicInput, {\n      props: {\n        value: [''],\n        onCreate\n      }\n    })\n\n    await wrapper.findAll('button')[1].trigger('click')\n    expect(onCreate).toHaveBeenCalled()\n    wrapper.unmount()\n  })\n\n  it('should work with `on-remove` prop', async () => {\n    const onRemove = vi.fn()\n    const wrapper = mount(NDynamicInput, {\n      props: {\n        value: [''],\n        onRemove\n      }\n    })\n\n    await wrapper.findAll('button')[0].trigger('click')\n    expect(onRemove).toHaveBeenCalled()\n    wrapper.unmount()\n  })\n\n  it('should work with `create-button-default` prop', async () => {\n    const wrapper = mount(NDynamicInput, {\n      props: {\n        value: []\n      },\n      slots: {\n        'create-button-default': () => 'test-content'\n      }\n    })\n\n    expect(wrapper.find('.n-button__content').text()).toBe('test-content')\n    wrapper.unmount()\n  })\n\n  it('should work with `create-button-icon` prop', async () => {\n    const wrapper = mount(NDynamicInput, {\n      props: {\n        value: []\n      },\n      slots: {\n        'create-button-icon': () => 'test-icon'\n      }\n    })\n\n    expect(wrapper.find('.n-icon-slot').text()).toBe('test-icon')\n    wrapper.unmount()\n  })\n})\n"
  },
  {
    "path": "src/dynamic-input/tests/server.spec.tsx",
    "content": "import { setup } from '@css-render/vue3-ssr'\nimport { renderToString } from '@vue/server-renderer'\n/**\n * @vitest-environment node\n */\nimport { createSSRApp, h } from 'vue'\nimport { NDynamicInput } from '../..'\n\ndescribe('server side rendering', () => {\n  it('works', async () => {\n    const app = createSSRApp(() => <NDynamicInput />)\n    setup(app)\n    try {\n      await renderToString(app)\n    }\n    catch (e) {\n      expect(e).not.toBeTruthy()\n    }\n  })\n})\n"
  },
  {
    "path": "src/dynamic-tags/demos/enUS/basic.demo.vue",
    "content": "<markdown>\n# Basic\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst tags = ref(['teacher', 'programmer'])\n</script>\n\n<template>\n  <n-dynamic-tags v-model:value=\"tags\" />\n</template>\n"
  },
  {
    "path": "src/dynamic-tags/demos/enUS/form.demo.vue",
    "content": "<markdown>\n# Use in form\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst model = ref({\n  tags: ['teacher', 'programmer']\n})\n\nconst rules = {\n  tags: {\n    trigger: ['change'],\n    validator(rule: unknown, value: string[]) {\n      if (value.length >= 5)\n        return new Error('Up to 4 tags')\n      return true\n    }\n  }\n}\n</script>\n\n<template>\n  <n-form :model=\"model\" :rules=\"rules\">\n    <n-form-item path=\"tags\" :show-label=\"false\">\n      <n-dynamic-tags v-model:value=\"model.tags\" />\n    </n-form-item>\n  </n-form>\n</template>\n"
  },
  {
    "path": "src/dynamic-tags/demos/enUS/index.demo-entry.md",
    "content": "# Dynamic Tags\n\nTurn tags to inputs and back again.\n\n## Demos\n\n```demo\nbasic.vue\nmax.vue\nform.vue\nslot.vue\nrender-tag.vue\noption-format.vue\non-create.vue\n```\n\n## API\n\n### DynamicTags Props\n\n| Name | Type | Default | Description | Version |\n| --- | --- | --- | --- | --- |\n| closable | `boolean` | `true` | Whether the tag is closable. |  |\n| color | `{ color?: string, borderColor?: string, textColor?: string }` | `undefined` | Color of the tag. Note: it will override the color set by `type`. |  |\n| default-value | `string[]` | `[]` | Default value. |  |\n| disabled | `boolean` | `false` | Whether the tag is disabled. |  |\n| input-props | `InputProps` | `undefined` | Props of internal `n-input`. | 2.25.0 |\n| input-class | `string` | `undefined` | Customize the class of the input. | 2.36.0 |\n| input-style | `string \\| Object` | `undefined` | Customize the style of the input. |  |\n| max | `number` | `undefined` | Maximum number of tags. |  |\n| round | `boolean` | `false` | Whether the tag has rounded corners. |  |\n| render-tag | `((tag: string, index: number) => VNodeChild) \\| ((tag: { label: string, value: string }, index: number) => VNodeChild)` | `undefined` | custom render tag. | 2.27.0 |\n| size | `'small' \\| 'medium' \\| 'large'` | `'medium'` | Size of the tag. |  |\n| tag-class | `string` | `undefined` | Customize the class of the tag. | 2.36.0 |\n| tag-style | `string \\| Object` | `undefined` | Customize the style of the tag. |  |\n| type | `'default' \\| 'primary' \\| 'info' \\| 'success' \\| 'warning' \\| 'error'` | `'default'` | Type of the tag. |  |\n| value | `string[]` | `undefined` | Value if manually set. |  |\n| on-create | `((label: string) => string) \\| ((label: string) => ({ label: string, value: string }))` | `label => label` | Create derived value from input. | 2.30.4 |\n| on-update:value | `((value: string[]) => void) \\| ((value: DynamicTagsOption[]) => void)` | `undefined` | Callback when the component's value changes. |  |\n\n#### DynamicTagsOption Type\n\n```ts\nexport interface DynamicTagsOption {\n  label: string\n  value: string\n}\n```\n\n### DynamicTags Slots\n\n| Name | Parameters | Description | Version |\n| --- | --- | --- | --- |\n| input | `(info: { submit: (value: any) => void, deactivate: () => void })` | Custom element(s) to replace the regular input. | `deactivate` 2.26.2 |\n| trigger | `(info: { activate: () => void, disabled: boolean })` | The element or component that triggers the tag to switch to an input. |  |\n"
  },
  {
    "path": "src/dynamic-tags/demos/enUS/max.demo.vue",
    "content": "<markdown>\n# Max tag count\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst tags = ref(['teacher', 'programmer'])\n</script>\n\n<template>\n  <n-dynamic-tags v-model:value=\"tags\" :max=\"3\" />\n</template>\n"
  },
  {
    "path": "src/dynamic-tags/demos/enUS/on-create.demo.vue",
    "content": "<markdown>\n# Custom tag creation\n\nUse `on-create` to custom tags.\n</markdown>\n\n<script lang=\"ts\" setup>\nfunction handleCreate(label: string) {\n  return (\n    {\n      0: '赋能',\n      1: '打通',\n      2: '闭环'\n    }[Math.floor(Math.random() * 3)] + label\n  )\n}\n</script>\n\n<template>\n  <n-dynamic-tags @create=\"handleCreate\" />\n</template>\n"
  },
  {
    "path": "src/dynamic-tags/demos/enUS/option-format.demo.vue",
    "content": "<markdown>\n# Use object formatted value\n\nYou can use `@create` to produce `{ label, value }` formatted value. Don't mess it up with `string` typed value.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst value = ref([\n  {\n    label: 'Dig It',\n    value: 'hello world 1'\n  },\n  { label: 'Maggie Mae', value: 'hello world 2' },\n  {\n    label: 'I Me Mine',\n    value: 'hello world 3'\n  },\n  {\n    label: 'I\\'ve Got a Feeling',\n    value: 'hello world 4'\n  }\n])\n\nfunction onCreate(label: string) {\n  return {\n    label,\n    value: `v${label}`\n  }\n}\n</script>\n\n<template>\n  <n-dynamic-tags v-model:value=\"value\" @create=\"onCreate\" />\n</template>\n"
  },
  {
    "path": "src/dynamic-tags/demos/enUS/render-tag.demo.vue",
    "content": "<markdown>\n# Custom render for each tag\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { NTag } from 'naive-ui'\nimport { h, ref } from 'vue'\n\nconst tags = ref(['teacher', 'programmer'])\n\nfunction renderTag(tag: string, index: number) {\n  return h(\n    NTag,\n    {\n      type: index < 3 ? 'success' : 'error',\n      disabled: index > 3,\n      closable: true,\n      onClose: () => {\n        tags.value.splice(index, 1)\n      }\n    },\n    {\n      default: () => tag\n    }\n  )\n}\n</script>\n\n<template>\n  <n-dynamic-tags v-model:value=\"tags\" :render-tag=\"renderTag\" />\n</template>\n"
  },
  {
    "path": "src/dynamic-tags/demos/enUS/slot.demo.vue",
    "content": "<markdown>\n# Customizing input or trigger element\n\nYou can replace a dynamic-tags input or trigger element with another component.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { AutoCompleteInst } from 'naive-ui'\nimport { Add } from '@vicons/ionicons5'\nimport { computed, nextTick, ref, watch } from 'vue'\n\nconst autoCompleteInstRef = ref<AutoCompleteInst | null>(null)\nwatch(autoCompleteInstRef, (value) => {\n  if (value)\n    nextTick(() => value.focus())\n})\n\nconst inputValue = ref('')\nconst options = computed(() => {\n  if (inputValue.value === null) {\n    return []\n  }\n  const prefix = inputValue.value.split('@')[0]\n  const inputSuffix = inputValue.value.split('@')[1]\n  if (inputSuffix) {\n    return [\n      {\n        label: `${prefix}@${inputSuffix}`,\n        value: `${prefix}@${inputSuffix}`\n      }\n    ]\n  }\n  return ['@gmail.com', '@163.com', '@qq.com'].map((suffix) => {\n    return {\n      label: prefix + suffix,\n      value: prefix + suffix\n    }\n  })\n})\n\nconst tags = ref(['Teacher', 'Programmer'])\n</script>\n\n<template>\n  <n-dynamic-tags v-model:value=\"tags\">\n    <template #input=\"{ submit, deactivate }\">\n      <n-auto-complete\n        ref=\"autoCompleteInstRef\"\n        v-model:value=\"inputValue\"\n        size=\"small\"\n        :options=\"options\"\n        placeholder=\"Email\"\n        :clear-after-select=\"true\"\n        @select=\"submit($event)\"\n        @blur=\"deactivate\"\n      />\n    </template>\n    <template #trigger=\"{ activate, disabled }\">\n      <n-button\n        size=\"small\"\n        type=\"primary\"\n        dashed\n        :disabled=\"disabled\"\n        @click=\"activate()\"\n      >\n        <template #icon>\n          <n-icon>\n            <Add />\n          </n-icon>\n        </template>\n        New Tag\n      </n-button>\n    </template>\n  </n-dynamic-tags>\n</template>\n"
  },
  {
    "path": "src/dynamic-tags/demos/zhCN/basic.demo.vue",
    "content": "<markdown>\n# 基础用法\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst tags = ref(['教师', '程序员'])\n</script>\n\n<template>\n  <n-dynamic-tags v-model:value=\"tags\" />\n</template>\n"
  },
  {
    "path": "src/dynamic-tags/demos/zhCN/form.demo.vue",
    "content": "<markdown>\n# 在表单中使用\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst model = ref({\n  tags: ['教师', '程序员']\n})\n\nconst rules = {\n  tags: {\n    trigger: ['change'],\n    validator(rule: unknown, value: string[]) {\n      if (value.length >= 5)\n        return new Error('不得超过四个标签')\n      return true\n    }\n  }\n}\n</script>\n\n<template>\n  <n-form :model=\"model\" :rules=\"rules\">\n    <n-form-item path=\"tags\" :show-label=\"false\">\n      <n-dynamic-tags v-model:value=\"model.tags\" />\n    </n-form-item>\n  </n-form>\n</template>\n"
  },
  {
    "path": "src/dynamic-tags/demos/zhCN/index.demo-entry.md",
    "content": "# 动态标签 Dynamic Tags\n\n把标签变得可以输入。\n\n## 演示\n\n```demo\nbasic.vue\nmax.vue\nform.vue\nslot.vue\nrender-tag.vue\noption-format.vue\non-create.vue\n```\n\n## API\n\n### DynamicTags Props\n\n| 名称 | 类型 | 默认值 | 说明 | 版本 |\n| --- | --- | --- | --- | --- |\n| closable | `boolean` | `true` | 是否可关闭 |  |\n| color | `{ color?: string, borderColor?: string, textColor?: string }` | `undefined` | 标签颜色，设置该项后 `type` 无效 |  |\n| default-value | `string[] \\| Array<{ label: string, value: string }>` | `[]` | 非受控模式下的默认值 |  |\n| disabled | `boolean` | `false` | 是否禁用 |  |\n| input-props | `InputProps` | `undefined` | 内部 `n-input` 组件的属性 | 2.25.0 |\n| input-class | `string` | `undefined` | 自定义输入框的类名 | 2.36.0 |\n| input-style | `string \\| Object` | `undefined` | 自定义输入框的样式 |  |\n| max | `number` | `undefined` | tag 的最大数量 |  |\n| round | `boolean` | `false` | 是否圆角 |  |\n| render-tag | `((tag: string, index: number) => VNodeChild) \\| ((tag: { label: string, value: string }, index: number) => VNodeChild)` | `undefined` | 自定义渲染 tag | 2.27.0 |\n| size | `'small' \\| 'medium' \\| 'large'` | `'medium'` | 尺寸大小 |  |\n| tag-class | `string` | `undefined` | 自定义标签的类名 | 2.36.0 |\n| tag-style | `string \\| Object` | `undefined` | 自定义标签的样式 |  |\n| type | `'default' \\| 'primary' \\| 'info' \\| 'success' \\| 'warning' \\| 'error'` | `'default'` | 标签类型 |  |\n| value | `string[] \\| Array<{ label: string, value: string }>` | `undefined` | 受控模式下的值 |  |\n| on-create | `((label: string) => string) \\| ((label: string) => ({ label: string, value: string }))` | `label => label` | 根据输入的值创造对应的选项 | 2.30.4 |\n| on-update:value | `((value: string[]) => void) \\| ((value: DynamicTagsOption[]) => void)` | `undefined` | 组件值发生变化时的回调 |  |\n\n#### DynamicTagsOption Type\n\n```ts\nexport interface DynamicTagsOption {\n  label: string\n  value: string\n}\n```\n\n### DynamicTags Slots\n\n| 名称 | 参数 | 说明 | 版本 |\n| --- | --- | --- | --- |\n| input | `(info: { submit: (value: any) => void, deactivate: () => void })` | 自定义输入元素，由用户填充 | `deactivate` 2.26.2 |\n| trigger | `(info: { activate: () => void, disabled: boolean })` | 触发输入标签的组件或元素 |  |\n"
  },
  {
    "path": "src/dynamic-tags/demos/zhCN/max.demo.vue",
    "content": "<markdown>\n# 最大标签数量\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst tags = ref(['教师', '程序员'])\n</script>\n\n<template>\n  <n-dynamic-tags v-model:value=\"tags\" :max=\"3\" />\n</template>\n"
  },
  {
    "path": "src/dynamic-tags/demos/zhCN/on-create.demo.vue",
    "content": "<markdown>\n# 自定义创建逻辑\n\n使用 `on-create` 属性控制创建标签的逻辑。\n</markdown>\n\n<script lang=\"ts\" setup>\nfunction handleCreate(label: string) {\n  return (\n    {\n      0: '赋能',\n      1: '打通',\n      2: '闭环'\n    }[Math.floor(Math.random() * 3)] + label\n  )\n}\n</script>\n\n<template>\n  <n-dynamic-tags @create=\"handleCreate\" />\n</template>\n"
  },
  {
    "path": "src/dynamic-tags/demos/zhCN/option-format.demo.vue",
    "content": "<markdown>\n# 使用对象格式的值\n\n你可以配置 `@create` 来产生 `{ label, value }` 格式的值，注意不要和 `string` 类型混用。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst value = ref([\n  { label: '你没见过不等于没有', value: 'hello world 1' },\n  {\n    label: '不要给自己设限',\n    value: 'hello world 2'\n  },\n  {\n    label: '不要说连升两级',\n    value: 'hello world 3'\n  },\n  {\n    label: '直接升到 CEO 都是有可能的',\n    value: 'hello world 4'\n  }\n])\n\nfunction onCreate(label: string) {\n  return {\n    label,\n    value: `v${label}`\n  }\n}\n</script>\n\n<template>\n  <n-dynamic-tags v-model:value=\"value\" @create=\"onCreate\" />\n</template>\n"
  },
  {
    "path": "src/dynamic-tags/demos/zhCN/render-tag.demo.vue",
    "content": "<markdown>\n# 自定义渲染每一个 tag\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { NTag } from 'naive-ui'\nimport { h, ref } from 'vue'\n\nconst tags = ref(['教师', '程序员'])\n\nfunction renderTag(tag: string, index: number) {\n  return h(\n    NTag,\n    {\n      type: index < 3 ? 'success' : 'error',\n      disabled: index > 3,\n      closable: true,\n      onClose: () => {\n        tags.value.splice(index, 1)\n      }\n    },\n    {\n      default: () => tag\n    }\n  )\n}\n</script>\n\n<template>\n  <n-dynamic-tags v-model:value=\"tags\" :render-tag=\"renderTag\" />\n</template>\n"
  },
  {
    "path": "src/dynamic-tags/demos/zhCN/slot.demo.vue",
    "content": "<markdown>\n# 自定义输入或触发元素\n\n你可以替换 `dynamic-tags` 的输入或触发元素。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { AutoCompleteInst } from 'naive-ui'\nimport { Add } from '@vicons/ionicons5'\nimport { computed, nextTick, ref, watch } from 'vue'\n\nconst autoCompleteInstRef = ref<AutoCompleteInst | null>(null)\nwatch(autoCompleteInstRef, (value) => {\n  if (value)\n    nextTick(() => value.focus())\n})\n\nconst inputValue = ref('')\nconst options = computed(() => {\n  if (inputValue.value === null) {\n    return []\n  }\n  const prefix = inputValue.value.split('@')[0]\n  const inputSuffix = inputValue.value.split('@')[1]\n  if (inputSuffix) {\n    return [\n      {\n        label: `${prefix}@${inputSuffix}`,\n        value: `${prefix}@${inputSuffix}`\n      }\n    ]\n  }\n  return ['@gmail.com', '@163.com', '@qq.com'].map((suffix) => {\n    return {\n      label: prefix + suffix,\n      value: prefix + suffix\n    }\n  })\n})\n\nconst tags = ref(['教师', '程序员'])\n</script>\n\n<template>\n  <n-dynamic-tags v-model:value=\"tags\" :max=\"3\">\n    <template #input=\"{ submit, deactivate }\">\n      <n-auto-complete\n        ref=\"autoCompleteInstRef\"\n        v-model:value=\"inputValue\"\n        size=\"small\"\n        :options=\"options\"\n        placeholder=\"邮箱\"\n        :clear-after-select=\"true\"\n        @select=\"submit($event)\"\n        @blur=\"deactivate\"\n      />\n    </template>\n    <template #trigger=\"{ activate, disabled }\">\n      <n-button\n        size=\"small\"\n        type=\"primary\"\n        dashed\n        :disabled=\"disabled\"\n        @click=\"activate()\"\n      >\n        <template #icon>\n          <n-icon>\n            <Add />\n          </n-icon>\n        </template>\n        添加\n      </n-button>\n    </template>\n  </n-dynamic-tags>\n</template>\n"
  },
  {
    "path": "src/dynamic-tags/index.ts",
    "content": "export { dynamicTagsProps, default as NDynamicTags } from './src/DynamicTags'\nexport type { DynamicTagsProps, DynamicTagsSlots } from './src/DynamicTags'\nexport type {\n  DynamicTagsInputSlotProps,\n  DynamicTagsOption,\n  DynamicTagsTriggerSlotProps\n} from './src/interface'\nexport type * from './src/public-types'\n"
  },
  {
    "path": "src/dynamic-tags/src/DynamicTags.tsx",
    "content": "import type { CSSProperties, PropType, SlotsType, VNode, VNodeChild } from 'vue'\nimport type { ThemeProps } from '../../_mixins'\nimport type { ExtractPublicPropTypes, MaybeArray } from '../../_utils'\nimport type { InputInst, InputProps } from '../../input'\nimport type { DynamicTagsTheme } from '../styles'\nimport type {\n  DynamicTagsInputSlotProps,\n  DynamicTagsOption,\n  DynamicTagsTriggerSlotProps,\n  OnCreate,\n  OnUpdateValue,\n  OnUpdateValueImpl\n} from './interface'\nimport type { DynamicTagsSize } from './public-types'\nimport { useMergedState } from 'vooks'\nimport {\n  computed,\n  defineComponent,\n  h,\n  nextTick,\n  ref,\n  toRef,\n  watchEffect\n} from 'vue'\nimport { NBaseIcon } from '../../_internal'\nimport { AddIcon } from '../../_internal/icons'\nimport {\n  useConfig,\n  useFormItem,\n  useLocale,\n  useTheme,\n  useThemeClass\n} from '../../_mixins'\nimport { call, smallerSize, warnOnce } from '../../_utils'\nimport { NButton } from '../../button'\nimport { NInput } from '../../input'\nimport { NSpace } from '../../space'\nimport { NTag } from '../../tag'\nimport commonProps from '../../tag/src/common-props'\nimport { dynamicTagsLight } from '../styles'\nimport style from './styles/index.cssr'\n\nexport const dynamicTagsProps = {\n  ...(useTheme.props as ThemeProps<DynamicTagsTheme>),\n  ...commonProps,\n  size: String as PropType<DynamicTagsSize>,\n  closable: {\n    type: Boolean,\n    default: true\n  },\n  defaultValue: {\n    type: Array as PropType<Array<string | DynamicTagsOption>>,\n    default: () => []\n  },\n  value: Array as PropType<Array<string | DynamicTagsOption>>,\n  inputClass: String,\n  inputStyle: [String, Object] as PropType<string | CSSProperties>,\n  inputProps: Object as PropType<InputProps>,\n  max: Number as PropType<number>,\n  tagClass: String,\n  tagStyle: [String, Object] as PropType<string | CSSProperties>,\n  renderTag: Function as PropType<\n    | ((tag: string, index: number) => VNodeChild)\n    | ((tag: DynamicTagsOption, index: number) => VNodeChild)\n  >,\n  onCreate: {\n    type: Function as PropType<OnCreate>,\n    default: (label: string) => label\n  },\n  'onUpdate:value': [Function, Array] as PropType<MaybeArray<OnUpdateValue>>,\n  onUpdateValue: [Function, Array] as PropType<MaybeArray<OnUpdateValue>>,\n  // deprecated\n  onChange: [Function, Array] as PropType<MaybeArray<OnUpdateValue> | undefined>\n}\n\nexport type DynamicTagsProps = ExtractPublicPropTypes<typeof dynamicTagsProps>\n\nexport interface DynamicTagsSlots {\n  input?: (props: DynamicTagsInputSlotProps) => VNode[]\n  trigger?: (props: DynamicTagsTriggerSlotProps) => VNode[]\n  default?: () => VNode[]\n}\n\nexport default defineComponent({\n  name: 'DynamicTags',\n  props: dynamicTagsProps,\n  slots: Object as SlotsType<DynamicTagsSlots>,\n  setup(props) {\n    if (__DEV__) {\n      watchEffect(() => {\n        if (props.onChange !== undefined) {\n          warnOnce(\n            'dynamic-tags',\n            '`on-change` is deprecated, please use `on-update:value` instead.'\n          )\n        }\n      })\n    }\n    const { mergedClsPrefixRef, inlineThemeDisabled, mergedComponentPropsRef }\n      = useConfig(props)\n    const mergedSizeRef = computed(() => {\n      return (\n        props.size\n        || mergedComponentPropsRef?.value?.DynamicTags?.size\n        || 'medium'\n      )\n    })\n    const { localeRef } = useLocale('DynamicTags')\n    const formItem = useFormItem(props)\n    const { mergedDisabledRef } = formItem\n    const inputValueRef = ref('')\n    const showInputRef = ref(false)\n    const inputForceFocusedRef = ref(true)\n    const inputInstRef = ref<InputInst | null>(null)\n    const themeRef = useTheme(\n      'DynamicTags',\n      '-dynamic-tags',\n      style,\n      dynamicTagsLight,\n      props,\n      mergedClsPrefixRef\n    )\n    const uncontrolledValueRef = ref(props.defaultValue)\n    const controlledValueRef = toRef(props, 'value')\n    const mergedValueRef = useMergedState(\n      controlledValueRef,\n      uncontrolledValueRef\n    )\n    const localizedAddRef = computed(() => {\n      return localeRef.value.add\n    })\n    const inputSizeRef = computed(() => {\n      return smallerSize(mergedSizeRef.value)\n    })\n    const triggerDisabledRef = computed(() => {\n      return (\n        mergedDisabledRef.value\n        || (!!props.max && mergedValueRef.value.length >= props.max)\n      )\n    })\n    function doChange(value: Array<string | DynamicTagsOption>): void {\n      const {\n        onChange,\n        'onUpdate:value': _onUpdateValue,\n        onUpdateValue\n      } = props\n      const { nTriggerFormInput, nTriggerFormChange } = formItem\n      if (onChange)\n        call(onChange as OnUpdateValueImpl, value)\n      if (onUpdateValue)\n        call(onUpdateValue as OnUpdateValueImpl, value)\n      if (_onUpdateValue)\n        call(_onUpdateValue as OnUpdateValueImpl, value)\n      uncontrolledValueRef.value = value\n      nTriggerFormInput()\n      nTriggerFormChange()\n    }\n    function handleCloseClick(index: number): void {\n      const tags = mergedValueRef.value.slice(0)\n      tags.splice(index, 1)\n      doChange(tags)\n    }\n    function handleInputKeyDown(e: KeyboardEvent): void {\n      switch (e.key) {\n        case 'Enter':\n          handleInputConfirm()\n      }\n    }\n    function handleInputConfirm(externalValue?: string): void {\n      const nextValue = externalValue ?? inputValueRef.value\n      if (nextValue) {\n        const tags = mergedValueRef.value.slice(0)\n        tags.push(props.onCreate(nextValue))\n        doChange(tags)\n      }\n      showInputRef.value = false\n      inputForceFocusedRef.value = true\n      inputValueRef.value = ''\n    }\n    function handleInputBlur(): void {\n      handleInputConfirm()\n    }\n    function handleAddClick(): void {\n      showInputRef.value = true\n      void nextTick(() => {\n        inputInstRef.value?.focus()\n        inputForceFocusedRef.value = false\n      })\n    }\n    const cssVarsRef = computed(() => {\n      const {\n        self: { inputWidth }\n      } = themeRef.value\n      return {\n        '--n-input-width': inputWidth\n      }\n    })\n    const themeClassHandle = inlineThemeDisabled\n      ? useThemeClass('dynamic-tags', undefined, cssVarsRef, props)\n      : undefined\n    return {\n      mergedClsPrefix: mergedClsPrefixRef,\n      inputInstRef,\n      localizedAdd: localizedAddRef,\n      inputSize: inputSizeRef,\n      mergedSize: mergedSizeRef,\n      inputValue: inputValueRef,\n      showInput: showInputRef,\n      inputForceFocused: inputForceFocusedRef,\n      mergedValue: mergedValueRef,\n      mergedDisabled: mergedDisabledRef,\n      triggerDisabled: triggerDisabledRef,\n      handleInputKeyDown,\n      handleAddClick,\n      handleInputBlur,\n      handleCloseClick,\n      handleInputConfirm,\n      mergedTheme: themeRef,\n      cssVars: inlineThemeDisabled ? undefined : cssVarsRef,\n      themeClass: themeClassHandle?.themeClass,\n      onRender: themeClassHandle?.onRender\n    }\n  },\n  render() {\n    const { mergedTheme, cssVars, mergedClsPrefix, onRender, renderTag } = this\n    onRender?.()\n    return (\n      <NSpace\n        class={[`${mergedClsPrefix}-dynamic-tags`, this.themeClass]}\n        size=\"small\"\n        style={cssVars as any}\n        theme={mergedTheme.peers.Space}\n        themeOverrides={mergedTheme.peerOverrides.Space}\n        itemStyle=\"display: flex;\"\n      >\n        {{\n          default: () => {\n            const {\n              mergedTheme,\n              tagClass,\n              tagStyle,\n              type,\n              round,\n              mergedSize,\n              color,\n              closable,\n              mergedDisabled,\n              showInput,\n              inputValue,\n              inputClass,\n              inputStyle,\n              inputSize,\n              inputForceFocused,\n              triggerDisabled,\n              handleInputKeyDown,\n              handleInputBlur,\n              handleAddClick,\n              handleCloseClick,\n              handleInputConfirm,\n              $slots\n            } = this\n            return this.mergedValue\n              .map((tag, index) =>\n                renderTag ? (\n                  renderTag(tag as string & DynamicTagsOption, index)\n                ) : (\n                  <NTag\n                    key={index}\n                    theme={mergedTheme.peers.Tag}\n                    themeOverrides={mergedTheme.peerOverrides.Tag}\n                    class={tagClass}\n                    style={tagStyle}\n                    type={type}\n                    round={round}\n                    size={mergedSize}\n                    color={color}\n                    closable={closable}\n                    disabled={mergedDisabled}\n                    onClose={() => {\n                      handleCloseClick(index)\n                    }}\n                  >\n                    {{\n                      default: () => (typeof tag === 'string' ? tag : tag.label)\n                    }}\n                  </NTag>\n                )\n              )\n              .concat(\n                showInput ? (\n                  $slots.input ? (\n                    $slots.input({\n                      submit: handleInputConfirm,\n                      deactivate: handleInputBlur\n                    })\n                  ) : (\n                    <NInput\n                      placeholder=\"\"\n                      size={inputSize}\n                      style={inputStyle}\n                      class={inputClass}\n                      autosize\n                      {...this.inputProps}\n                      ref=\"inputInstRef\"\n                      value={inputValue}\n                      onUpdateValue={(v) => {\n                        this.inputValue = v\n                      }}\n                      theme={mergedTheme.peers.Input}\n                      themeOverrides={mergedTheme.peerOverrides.Input}\n                      onKeydown={handleInputKeyDown}\n                      onBlur={handleInputBlur}\n                      internalForceFocus={inputForceFocused}\n                    />\n                  )\n                ) : $slots.trigger ? (\n                  $slots.trigger({\n                    activate: handleAddClick,\n                    disabled: triggerDisabled\n                  })\n                ) : (\n                  <NButton\n                    dashed\n                    disabled={triggerDisabled}\n                    theme={mergedTheme.peers.Button}\n                    themeOverrides={mergedTheme.peerOverrides.Button}\n                    size={inputSize}\n                    onClick={handleAddClick}\n                  >\n                    {{\n                      icon: () => (\n                        <NBaseIcon clsPrefix={mergedClsPrefix}>\n                          {{ default: () => <AddIcon /> }}\n                        </NBaseIcon>\n                      )\n                    }}\n                  </NButton>\n                )\n              )\n          }\n        }}\n      </NSpace>\n    )\n  }\n})\n"
  },
  {
    "path": "src/dynamic-tags/src/interface.ts",
    "content": "export type OnUpdateValue\n  = | ((value: string[]) => void)\n    | ((value: DynamicTagsOption[]) => void)\n\nexport type OnUpdateValueImpl = (\n  value: Array<string | DynamicTagsOption>\n) => void\n\nexport type OnCreate = (label: string) =>\n  | {\n    label: string\n    value: string\n  }\n  | string\n\nexport interface DynamicTagsOption {\n  label: string\n  value: string\n}\n\nexport interface DynamicTagsInputSlotProps {\n  submit: (value: any) => void\n  deactivate: () => void\n}\n\nexport interface DynamicTagsTriggerSlotProps {\n  activate: () => void\n  disabled: boolean\n}\n"
  },
  {
    "path": "src/dynamic-tags/src/public-types.ts",
    "content": "export type DynamicTagsSize = 'small' | 'medium' | 'large'\n"
  },
  {
    "path": "src/dynamic-tags/src/styles/index.cssr.ts",
    "content": "import { cB } from '../../../_utils/cssr'\n\n// vars:\n// --input-width\nexport default cB('dynamic-tags', [\n  cB('input', {\n    minWidth: 'var(--n-input-width)'\n  })\n])\n"
  },
  {
    "path": "src/dynamic-tags/styles/dark.ts",
    "content": "import type { DynamicTagsTheme } from './light'\nimport { commonDark } from '../../_styles/common'\nimport { buttonDark } from '../../button/styles'\nimport { inputDark } from '../../input/styles'\nimport { spaceDark } from '../../space/styles'\nimport { tagDark } from '../../tag/styles'\n\nconst dynamicTagsDark: DynamicTagsTheme = {\n  name: 'DynamicTags',\n  common: commonDark,\n  peers: {\n    Input: inputDark,\n    Button: buttonDark,\n    Tag: tagDark,\n    Space: spaceDark\n  },\n  self() {\n    return {\n      inputWidth: '64px'\n    }\n  }\n}\n\nexport default dynamicTagsDark\n"
  },
  {
    "path": "src/dynamic-tags/styles/index.ts",
    "content": "export { default as dynamicTagsDark } from './dark'\nexport { default as dynamicTagsLight } from './light'\nexport type { DynamicTagsTheme, DynamicTagsThemeVars } from './light'\n"
  },
  {
    "path": "src/dynamic-tags/styles/light.ts",
    "content": "import { createTheme } from '../../_mixins'\nimport { commonLight } from '../../_styles/common'\nimport { buttonLight } from '../../button/styles'\nimport { inputLight } from '../../input/styles'\nimport { spaceLight } from '../../space/styles'\nimport { tagLight } from '../../tag/styles'\n\nconst dynamicTagsLight = createTheme({\n  name: 'DynamicTags',\n  common: commonLight,\n  peers: {\n    Input: inputLight,\n    Button: buttonLight,\n    Tag: tagLight,\n    Space: spaceLight\n  },\n  self() {\n    return {\n      inputWidth: '64px'\n    }\n  }\n})\n\nexport default dynamicTagsLight\nexport interface DynamicTagsThemeVars {}\nexport type DynamicTagsTheme = typeof dynamicTagsLight\n"
  },
  {
    "path": "src/dynamic-tags/tests/DynamicTags.spec.ts",
    "content": "import { mount } from '@vue/test-utils'\nimport { h } from 'vue'\nimport { NAutoComplete } from '../../auto-complete/index'\nimport { NButton } from '../../button/index'\nimport { NTag } from '../../tag'\nimport { NDynamicTags } from '../index'\n\ndescribe('n-dynamic-tags', () => {\n  it('should work with import on demand', () => {\n    mount(NDynamicTags)\n  })\n\n  it('should work with `closable` prop', async () => {\n    const wrapper = mount(NDynamicTags, {\n      props: {\n        defaultValue: ['教师', '程序员']\n      }\n    })\n    expect(wrapper.find('.n-tag__close').exists()).toBe(true)\n    await wrapper.setProps({ closable: false })\n    expect(wrapper.find('.n-tag__close').exists()).toBe(false)\n    wrapper.unmount()\n  })\n\n  it('should work with `color` prop', async () => {\n    const wrapper = mount(NDynamicTags, {\n      props: {\n        color: {\n          color: '#ccc',\n          textColor: '#555',\n          borderColor: 'rgb(85, 85, 85)'\n        },\n        defaultValue: ['教师', '程序员']\n      }\n    })\n    expect(wrapper.find('.n-tag').attributes('style')).toContain(\n      '--n-color: #ccc;'\n    )\n    expect(wrapper.find('.n-tag').attributes('style')).toContain(\n      '--n-text-color: #555;'\n    )\n    expect(wrapper.find('.n-tag__border').attributes('style')).toContain(\n      'border-color: rgb(85, 85, 85);'\n    )\n    wrapper.unmount()\n  })\n\n  it('should work with `disabled` prop', async () => {\n    const onClose = vi.fn()\n    const wrapper = mount(NDynamicTags, {\n      props: {\n        disabled: true,\n        closable: true,\n        defaultValue: ['教师', '程序员'],\n        onClose\n      }\n    })\n\n    expect(wrapper.find('.n-tag').classes()).toContain('n-tag--disabled')\n    wrapper.find('.n-tag__close').trigger('click')\n    expect(onClose).not.toHaveBeenCalled()\n    expect(wrapper.find('.n-button').classes()).toContain('n-button--disabled')\n    wrapper.unmount()\n  })\n\n  it('should work with `max` prop', async () => {\n    const wrapper = mount(NDynamicTags, {\n      props: {\n        max: 2,\n        value: ['教师']\n      }\n    })\n\n    expect(wrapper.find('.n-button').classes()).not.toContain(\n      'n-button--disabled'\n    )\n    await wrapper.setProps({ value: ['教师', '程序员'] })\n    expect(wrapper.find('.n-button').classes()).toContain('n-button--disabled')\n    wrapper.unmount()\n  })\n\n  it('should work with `round` prop', async () => {\n    const wrapper = mount(NDynamicTags, {\n      props: {\n        round: true,\n        defaultValue: ['教师']\n      }\n    })\n    expect(wrapper.find('.n-tag').classes()).toContain('n-tag--round')\n    await wrapper.setProps({ round: false })\n    expect(wrapper.find('.n-tag').classes()).not.toContain('n-tag--round')\n    wrapper.unmount()\n  })\n\n  it('should work with `size` prop', async () => {\n    const wrapper = mount(NDynamicTags, {\n      props: {\n        size: 'small',\n        defaultValue: ['教师']\n      }\n    })\n    expect(wrapper.find('.n-tag').attributes('style')).toMatchSnapshot()\n    await wrapper.setProps({ size: 'medium' })\n    expect(wrapper.find('.n-tag').attributes('style')).toMatchSnapshot()\n    await wrapper.setProps({ size: 'large' })\n    expect(wrapper.find('.n-tag').attributes('style')).toMatchSnapshot()\n    wrapper.unmount()\n  })\n\n  it('should work with `type` prop', async () => {\n    const wrapper = mount(NDynamicTags, {\n      props: {\n        size: 'small',\n        defaultValue: ['教师']\n      }\n    })\n    expect(wrapper.find('.n-tag').attributes('style')).toMatchSnapshot()\n\n    await wrapper.setProps({ type: 'info' })\n    expect(wrapper.find('.n-tag').attributes('style')).toMatchSnapshot()\n\n    await wrapper.setProps({ type: 'success' })\n    expect(wrapper.find('.n-tag').attributes('style')).toMatchSnapshot()\n\n    await wrapper.setProps({ type: 'warning' })\n    expect(wrapper.find('.n-tag').attributes('style')).toMatchSnapshot()\n\n    await wrapper.setProps({ type: 'error' })\n    expect(wrapper.find('.n-tag').attributes('style')).toMatchSnapshot()\n    wrapper.unmount()\n  })\n\n  it('should work with `tag-style` prop', async () => {\n    const wrapper = mount(NDynamicTags, {\n      props: {\n        tagStyle: {\n          color: 'rgb(79, 178, 51)'\n        },\n        defaultValue: ['教师']\n      }\n    })\n    expect(wrapper.find('.n-tag').attributes('style')).toContain(\n      'color: rgb(79, 178, 51);'\n    )\n    await wrapper.setProps({ tagStyle: { width: '100px' } })\n    expect(wrapper.find('.n-tag').attributes('style')).toContain(\n      'width: 100px;'\n    )\n    wrapper.unmount()\n  })\n\n  it('should work with `on-update:value` prop', () => {\n    const onUpdateValue = vi.fn()\n    const wrapper = mount(NDynamicTags, {\n      props: {\n        value: ['教师', '程序员'],\n        onUpdateValue\n      }\n    })\n    wrapper.find('.n-tag__close').trigger('click')\n    expect(onUpdateValue).toHaveBeenCalled()\n    wrapper.unmount()\n  })\n\n  it('should work with `input-props` prop', async () => {\n    const wrapper = mount(NDynamicTags, {\n      props: {\n        defaultValue: ['教师']\n      }\n    })\n    await wrapper.find('.n-button').trigger('click')\n    expect(wrapper.find('.n-input').classes()).not.toContain(\n      'n-input--disabled'\n    )\n\n    await wrapper.setProps({ inputProps: { disabled: true } })\n    expect(wrapper.find('.n-input').classes()).toContain('n-input--disabled')\n    wrapper.unmount()\n  })\n\n  it('should work with `input-style` prop', async () => {\n    const wrapper = mount(NDynamicTags, {\n      props: {\n        defaultValue: ['教师']\n      }\n    })\n    await wrapper.find('.n-button').trigger('click')\n    expect(wrapper.find('.n-input').attributes('style')).not.toContain(\n      'color: red'\n    )\n\n    await wrapper.setProps({ inputStyle: { color: 'red' } })\n    expect(wrapper.find('.n-input').attributes('style')).toContain('color: red')\n    wrapper.unmount()\n  })\n\n  it('should work with `render-tag` prop', async () => {\n    const wrapper = mount(NDynamicTags, {\n      props: {\n        value: ['教师'],\n        renderTag: (tag: string) =>\n          h(NTag, null, {\n            default: () => `test-${tag}`\n          })\n      }\n    })\n\n    expect(wrapper.find('.n-tag__content').text()).toContain('test-教师')\n    wrapper.unmount()\n  })\n\n  it('should work with `input` slot', async () => {\n    const wrapper = mount(NDynamicTags, {\n      props: {\n        value: ['教师', '程序员']\n      },\n      slots: {\n        input: () => h(NAutoComplete)\n      }\n    })\n    await wrapper.find('.n-button').trigger('click')\n    expect(wrapper.find('.n-auto-complete').exists()).toBe(true)\n    wrapper.unmount()\n  })\n\n  it('should work with `trigger` slot', async () => {\n    const wrapper = mount(NDynamicTags, {\n      props: {\n        value: ['教师', '程序员']\n      },\n      slots: {\n        trigger: () =>\n          h(NButton, null, {\n            default: () => '添加'\n          })\n      }\n    })\n    expect(wrapper.find('.n-button__content').text()).toEqual('添加')\n    wrapper.unmount()\n  })\n})\n"
  },
  {
    "path": "src/dynamic-tags/tests/__snapshots__/DynamicTags.spec.ts.snap",
    "content": "// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html\n\nexports[`n-dynamic-tags > should work with \\`size\\` prop 1`] = `\"--n-font-weight-strong: 500; --n-avatar-size-override: calc(22px - 8px); --n-bezier: cubic-bezier(.4, 0, .2, 1); --n-border-radius: 2px; --n-border: 1px solid rgb(224, 224, 230); --n-close-icon-size: 12px; --n-close-color-pressed: rgba(0, 0, 0, .13); --n-close-color-hover: rgba(0, 0, 0, .09); --n-close-border-radius: 2px; --n-close-icon-color: rgba(102, 102, 102, 1); --n-close-icon-color-hover: rgba(102, 102, 102, 1); --n-close-icon-color-pressed: rgba(102, 102, 102, 1); --n-close-icon-color-disabled: rgba(102, 102, 102, 1); --n-close-margin-top: 0; --n-close-margin-right: 0; --n-close-margin-bottom: 0; --n-close-margin-left: 4px; --n-close-size: 16px; --n-color: rgb(250, 250, 252); --n-color-checkable: #0000; --n-color-checked: #18a058; --n-color-checked-hover: #36ad6a; --n-color-checked-pressed: #0c7a43; --n-color-hover-checkable: rgba(46, 51, 56, .09); --n-color-pressed-checkable: rgba(46, 51, 56, .13); --n-font-size: 12px; --n-height: 22px; --n-opacity-disabled: 0.5; --n-padding: 0 7px; --n-text-color: rgb(51, 54, 57); --n-text-color-checkable: rgb(51, 54, 57); --n-text-color-checked: #FFF; --n-text-color-hover-checkable: rgb(51, 54, 57); --n-text-color-pressed-checkable: rgb(51, 54, 57);\"`;\n\nexports[`n-dynamic-tags > should work with \\`size\\` prop 2`] = `\"--n-font-weight-strong: 500; --n-avatar-size-override: calc(28px - 8px); --n-bezier: cubic-bezier(.4, 0, .2, 1); --n-border-radius: 2px; --n-border: 1px solid rgb(224, 224, 230); --n-close-icon-size: 14px; --n-close-color-pressed: rgba(0, 0, 0, .13); --n-close-color-hover: rgba(0, 0, 0, .09); --n-close-border-radius: 2px; --n-close-icon-color: rgba(102, 102, 102, 1); --n-close-icon-color-hover: rgba(102, 102, 102, 1); --n-close-icon-color-pressed: rgba(102, 102, 102, 1); --n-close-icon-color-disabled: rgba(102, 102, 102, 1); --n-close-margin-top: 0; --n-close-margin-right: 0; --n-close-margin-bottom: 0; --n-close-margin-left: 4px; --n-close-size: 18px; --n-color: rgb(250, 250, 252); --n-color-checkable: #0000; --n-color-checked: #18a058; --n-color-checked-hover: #36ad6a; --n-color-checked-pressed: #0c7a43; --n-color-hover-checkable: rgba(46, 51, 56, .09); --n-color-pressed-checkable: rgba(46, 51, 56, .13); --n-font-size: 14px; --n-height: 28px; --n-opacity-disabled: 0.5; --n-padding: 0 7px; --n-text-color: rgb(51, 54, 57); --n-text-color-checkable: rgb(51, 54, 57); --n-text-color-checked: #FFF; --n-text-color-hover-checkable: rgb(51, 54, 57); --n-text-color-pressed-checkable: rgb(51, 54, 57);\"`;\n\nexports[`n-dynamic-tags > should work with \\`size\\` prop 3`] = `\"--n-font-weight-strong: 500; --n-avatar-size-override: calc(34px - 8px); --n-bezier: cubic-bezier(.4, 0, .2, 1); --n-border-radius: 2px; --n-border: 1px solid rgb(224, 224, 230); --n-close-icon-size: 14px; --n-close-color-pressed: rgba(0, 0, 0, .13); --n-close-color-hover: rgba(0, 0, 0, .09); --n-close-border-radius: 2px; --n-close-icon-color: rgba(102, 102, 102, 1); --n-close-icon-color-hover: rgba(102, 102, 102, 1); --n-close-icon-color-pressed: rgba(102, 102, 102, 1); --n-close-icon-color-disabled: rgba(102, 102, 102, 1); --n-close-margin-top: 0; --n-close-margin-right: 0; --n-close-margin-bottom: 0; --n-close-margin-left: 4px; --n-close-size: 18px; --n-color: rgb(250, 250, 252); --n-color-checkable: #0000; --n-color-checked: #18a058; --n-color-checked-hover: #36ad6a; --n-color-checked-pressed: #0c7a43; --n-color-hover-checkable: rgba(46, 51, 56, .09); --n-color-pressed-checkable: rgba(46, 51, 56, .13); --n-font-size: 14px; --n-height: 34px; --n-opacity-disabled: 0.5; --n-padding: 0 7px; --n-text-color: rgb(51, 54, 57); --n-text-color-checkable: rgb(51, 54, 57); --n-text-color-checked: #FFF; --n-text-color-hover-checkable: rgb(51, 54, 57); --n-text-color-pressed-checkable: rgb(51, 54, 57);\"`;\n\nexports[`n-dynamic-tags > should work with \\`type\\` prop 1`] = `\"--n-font-weight-strong: 500; --n-avatar-size-override: calc(22px - 8px); --n-bezier: cubic-bezier(.4, 0, .2, 1); --n-border-radius: 2px; --n-border: 1px solid rgb(224, 224, 230); --n-close-icon-size: 12px; --n-close-color-pressed: rgba(0, 0, 0, .13); --n-close-color-hover: rgba(0, 0, 0, .09); --n-close-border-radius: 2px; --n-close-icon-color: rgba(102, 102, 102, 1); --n-close-icon-color-hover: rgba(102, 102, 102, 1); --n-close-icon-color-pressed: rgba(102, 102, 102, 1); --n-close-icon-color-disabled: rgba(102, 102, 102, 1); --n-close-margin-top: 0; --n-close-margin-right: 0; --n-close-margin-bottom: 0; --n-close-margin-left: 4px; --n-close-size: 16px; --n-color: rgb(250, 250, 252); --n-color-checkable: #0000; --n-color-checked: #18a058; --n-color-checked-hover: #36ad6a; --n-color-checked-pressed: #0c7a43; --n-color-hover-checkable: rgba(46, 51, 56, .09); --n-color-pressed-checkable: rgba(46, 51, 56, .13); --n-font-size: 12px; --n-height: 22px; --n-opacity-disabled: 0.5; --n-padding: 0 7px; --n-text-color: rgb(51, 54, 57); --n-text-color-checkable: rgb(51, 54, 57); --n-text-color-checked: #FFF; --n-text-color-hover-checkable: rgb(51, 54, 57); --n-text-color-pressed-checkable: rgb(51, 54, 57);\"`;\n\nexports[`n-dynamic-tags > should work with \\`type\\` prop 2`] = `\"--n-font-weight-strong: 500; --n-avatar-size-override: calc(22px - 8px); --n-bezier: cubic-bezier(.4, 0, .2, 1); --n-border-radius: 2px; --n-border: 1px solid rgba(32, 128, 240, 0.3); --n-close-icon-size: 12px; --n-close-color-pressed: rgba(32, 128, 240, 0.18); --n-close-color-hover: rgba(32, 128, 240, 0.12); --n-close-border-radius: 2px; --n-close-icon-color: #2080f0; --n-close-icon-color-hover: #2080f0; --n-close-icon-color-pressed: #2080f0; --n-close-icon-color-disabled: #2080f0; --n-close-margin-top: 0; --n-close-margin-right: 0; --n-close-margin-bottom: 0; --n-close-margin-left: 4px; --n-close-size: 16px; --n-color: rgba(32, 128, 240, 0.1); --n-color-checkable: #0000; --n-color-checked: #18a058; --n-color-checked-hover: #36ad6a; --n-color-checked-pressed: #0c7a43; --n-color-hover-checkable: rgba(46, 51, 56, .09); --n-color-pressed-checkable: rgba(46, 51, 56, .13); --n-font-size: 12px; --n-height: 22px; --n-opacity-disabled: 0.5; --n-padding: 0 7px; --n-text-color: #2080f0; --n-text-color-checkable: rgb(51, 54, 57); --n-text-color-checked: #FFF; --n-text-color-hover-checkable: rgb(51, 54, 57); --n-text-color-pressed-checkable: rgb(51, 54, 57);\"`;\n\nexports[`n-dynamic-tags > should work with \\`type\\` prop 3`] = `\"--n-font-weight-strong: 500; --n-avatar-size-override: calc(22px - 8px); --n-bezier: cubic-bezier(.4, 0, .2, 1); --n-border-radius: 2px; --n-border: 1px solid rgba(24, 160, 88, 0.3); --n-close-icon-size: 12px; --n-close-color-pressed: rgba(24, 160, 88, 0.18); --n-close-color-hover: rgba(24, 160, 88, 0.12); --n-close-border-radius: 2px; --n-close-icon-color: #18a058; --n-close-icon-color-hover: #18a058; --n-close-icon-color-pressed: #18a058; --n-close-icon-color-disabled: #18a058; --n-close-margin-top: 0; --n-close-margin-right: 0; --n-close-margin-bottom: 0; --n-close-margin-left: 4px; --n-close-size: 16px; --n-color: rgba(24, 160, 88, 0.1); --n-color-checkable: #0000; --n-color-checked: #18a058; --n-color-checked-hover: #36ad6a; --n-color-checked-pressed: #0c7a43; --n-color-hover-checkable: rgba(46, 51, 56, .09); --n-color-pressed-checkable: rgba(46, 51, 56, .13); --n-font-size: 12px; --n-height: 22px; --n-opacity-disabled: 0.5; --n-padding: 0 7px; --n-text-color: #18a058; --n-text-color-checkable: rgb(51, 54, 57); --n-text-color-checked: #FFF; --n-text-color-hover-checkable: rgb(51, 54, 57); --n-text-color-pressed-checkable: rgb(51, 54, 57);\"`;\n\nexports[`n-dynamic-tags > should work with \\`type\\` prop 4`] = `\"--n-font-weight-strong: 500; --n-avatar-size-override: calc(22px - 8px); --n-bezier: cubic-bezier(.4, 0, .2, 1); --n-border-radius: 2px; --n-border: 1px solid rgba(240, 160, 32, 0.35); --n-close-icon-size: 12px; --n-close-color-pressed: rgba(240, 160, 32, 0.18); --n-close-color-hover: rgba(240, 160, 32, 0.12); --n-close-border-radius: 2px; --n-close-icon-color: #f0a020; --n-close-icon-color-hover: #f0a020; --n-close-icon-color-pressed: #f0a020; --n-close-icon-color-disabled: #f0a020; --n-close-margin-top: 0; --n-close-margin-right: 0; --n-close-margin-bottom: 0; --n-close-margin-left: 4px; --n-close-size: 16px; --n-color: rgba(240, 160, 32, 0.12); --n-color-checkable: #0000; --n-color-checked: #18a058; --n-color-checked-hover: #36ad6a; --n-color-checked-pressed: #0c7a43; --n-color-hover-checkable: rgba(46, 51, 56, .09); --n-color-pressed-checkable: rgba(46, 51, 56, .13); --n-font-size: 12px; --n-height: 22px; --n-opacity-disabled: 0.5; --n-padding: 0 7px; --n-text-color: #f0a020; --n-text-color-checkable: rgb(51, 54, 57); --n-text-color-checked: #FFF; --n-text-color-hover-checkable: rgb(51, 54, 57); --n-text-color-pressed-checkable: rgb(51, 54, 57);\"`;\n\nexports[`n-dynamic-tags > should work with \\`type\\` prop 5`] = `\"--n-font-weight-strong: 500; --n-avatar-size-override: calc(22px - 8px); --n-bezier: cubic-bezier(.4, 0, .2, 1); --n-border-radius: 2px; --n-border: 1px solid rgba(208, 48, 80, 0.23); --n-close-icon-size: 12px; --n-close-color-pressed: rgba(208, 48, 80, 0.18); --n-close-color-hover: rgba(208, 48, 80, 0.12); --n-close-border-radius: 2px; --n-close-icon-color: #d03050; --n-close-icon-color-hover: #d03050; --n-close-icon-color-pressed: #d03050; --n-close-icon-color-disabled: #d03050; --n-close-margin-top: 0; --n-close-margin-right: 0; --n-close-margin-bottom: 0; --n-close-margin-left: 4px; --n-close-size: 16px; --n-color: rgba(208, 48, 80, 0.08); --n-color-checkable: #0000; --n-color-checked: #18a058; --n-color-checked-hover: #36ad6a; --n-color-checked-pressed: #0c7a43; --n-color-hover-checkable: rgba(46, 51, 56, .09); --n-color-pressed-checkable: rgba(46, 51, 56, .13); --n-font-size: 12px; --n-height: 22px; --n-opacity-disabled: 0.5; --n-padding: 0 7px; --n-text-color: #d03050; --n-text-color-checkable: rgb(51, 54, 57); --n-text-color-checked: #FFF; --n-text-color-hover-checkable: rgb(51, 54, 57); --n-text-color-pressed-checkable: rgb(51, 54, 57);\"`;\n"
  },
  {
    "path": "src/dynamic-tags/tests/server.spec.tsx",
    "content": "import { setup } from '@css-render/vue3-ssr'\nimport { renderToString } from '@vue/server-renderer'\n/**\n * @vitest-environment node\n */\nimport { createSSRApp, h } from 'vue'\nimport { NDynamicTags } from '../..'\n\ndescribe('server side rendering', () => {\n  it('works', async () => {\n    const app = createSSRApp(() => <NDynamicTags />)\n    setup(app)\n    try {\n      await renderToString(app)\n    }\n    catch (e) {\n      expect(e).not.toBeTruthy()\n    }\n  })\n})\n"
  },
  {
    "path": "src/element/demos/enUS/basic.demo.vue",
    "content": "<markdown>\n# Basic\n\nYou can use CSS variables from it. If you need to use those variables in JS, please see [useThemeVars](../docs/theme#use-theme-vars).\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { darkTheme } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst theme = ref<typeof darkTheme | null>(null)\n</script>\n\n<template>\n  <n-space vertical>\n    <n-space>\n      <n-button @click=\"theme = darkTheme\">\n        Dark\n      </n-button>\n      <n-button @click=\"theme = null\">\n        Light\n      </n-button>\n    </n-space>\n    <n-config-provider :theme=\"theme\">\n      <n-card>\n        <n-el\n          tag=\"span\"\n          style=\"\n            color: var(--primary-color);\n            transition: 0.3s var(--cubic-bezier-ease-in-out);\n          \"\n        >\n          I am a Span.\n        </n-el>\n      </n-card>\n    </n-config-provider>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/element/demos/enUS/index.demo-entry.md",
    "content": "# Element\n\nElement has many theme variables provided by Naive UI.\n\n## Demos\n\n```demo\nbasic.vue\n```\n\n## API\n\n### Element Props\n\n| Name | Type     | Default | Description                                |\n| ---- | -------- | ------- | ------------------------------------------ |\n| tag  | `string` | `'div'` | The tag `n-element` should be rendered as. |\n\n### Element Slots\n\n| Name    | Parameters | Description                 |\n| ------- | ---------- | --------------------------- |\n| default | `()`       | The content of the element. |\n"
  },
  {
    "path": "src/element/demos/zhCN/basic.demo.vue",
    "content": "<markdown>\n# 基础\n\n你可以使用上面的 CSS 变量。如果你需要在 JS 中使用这些变量，请使用 [useThemeVars](../docs/theme#use-theme-vars)。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { darkTheme } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst theme = ref<typeof darkTheme | null>(null)\n</script>\n\n<template>\n  <n-space vertical>\n    <n-space>\n      <n-button @click=\"theme = darkTheme\">\n        深色\n      </n-button>\n      <n-button @click=\"theme = null\">\n        浅色\n      </n-button>\n    </n-space>\n    <n-config-provider :theme=\"theme\">\n      <n-card>\n        <n-el\n          tag=\"span\"\n          style=\"\n            color: var(--primary-color);\n            transition: 0.3s var(--cubic-bezier-ease-in-out);\n          \"\n        >\n          我是个 span 标签\n        </n-el>\n      </n-card>\n    </n-config-provider>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/element/demos/zhCN/index.demo-entry.md",
    "content": "# 元素 Element\n\nElement 上面有很多 Naive UI 提供的主题变量。\n\n## 演示\n\n```demo\nbasic.vue\n```\n\n## API\n\n### Element Props\n\n| 名称 | 类型     | 默认值  | 说明                           |\n| ---- | -------- | ------- | ------------------------------ |\n| tag  | `string` | `'div'` | `n-element` 需要渲染为什么元素 |\n\n### Element Slots\n\n| 名称    | 参数 | 说明     |\n| ------- | ---- | -------- |\n| default | `()` | 元素内容 |\n"
  },
  {
    "path": "src/element/index.ts",
    "content": "export { elementProps, default as NElement } from './src/Element'\nexport { default as NEl } from './src/Element'\nexport type { ElementProps } from './src/Element'\n"
  },
  {
    "path": "src/element/src/Element.ts",
    "content": "import type { ThemeProps } from '../../_mixins'\nimport type { ExtractPublicPropTypes } from '../../_utils'\nimport type { ElementTheme } from '../styles'\nimport { kebabCase } from 'lodash-es'\nimport { computed, defineComponent, h } from 'vue'\nimport { useConfig, useTheme, useThemeClass } from '../../_mixins'\nimport { elementLight } from '../styles'\n\nexport const elementProps = {\n  ...(useTheme.props as ThemeProps<ElementTheme>),\n  tag: {\n    type: String,\n    default: 'div'\n  }\n} as const\n\nexport type ElementProps = ExtractPublicPropTypes<typeof elementProps>\n\nexport default defineComponent({\n  name: 'Element',\n  alias: ['El'],\n  props: elementProps,\n  setup(props) {\n    const { mergedClsPrefixRef, inlineThemeDisabled } = useConfig(props)\n    const themeRef = useTheme(\n      'Element',\n      '-element',\n      undefined,\n      elementLight,\n      props,\n      mergedClsPrefixRef\n    )\n    const cssVarsRef = computed(() => {\n      const { common } = themeRef.value\n      return (\n        Object.keys(common) as unknown as Array<keyof typeof common>\n      ).reduce<Record<string, string>>((prevValue, key) => {\n        prevValue[`--${kebabCase(key)}`] = common[key]\n        return prevValue\n      }, {})\n    })\n    const themeClassHandle = inlineThemeDisabled\n      ? useThemeClass('element', undefined, cssVarsRef, props)\n      : undefined\n    return {\n      mergedClsPrefix: mergedClsPrefixRef,\n      cssVars: inlineThemeDisabled ? undefined : cssVarsRef,\n      themeClass: themeClassHandle?.themeClass,\n      onRender: themeClassHandle?.onRender\n    }\n  },\n  render() {\n    const { tag, mergedClsPrefix, cssVars, themeClass, onRender, $slots } = this\n    onRender?.()\n    return h(\n      tag,\n      {\n        role: 'none',\n        class: [`${mergedClsPrefix}-element`, themeClass],\n        style: cssVars\n      },\n      $slots.default?.()\n    )\n  }\n})\n"
  },
  {
    "path": "src/element/styles/dark.ts",
    "content": "import type { ElementTheme } from './light'\nimport { commonDark } from '../../_styles/common'\n\nconst elementDark: ElementTheme = {\n  name: 'Element',\n  common: commonDark\n}\n\nexport default elementDark\n"
  },
  {
    "path": "src/element/styles/index.ts",
    "content": "export { default as elementDark } from './dark'\nexport { default as elementLight } from './light'\nexport type { ElementTheme } from './light'\n"
  },
  {
    "path": "src/element/styles/light.ts",
    "content": "import type { Theme } from '../../_mixins'\nimport { commonLight } from '../../_styles/common'\n\nconst elementLight: Theme<'Element'> = {\n  name: 'Element',\n  common: commonLight\n}\n\nexport default elementLight\nexport type ElementTheme = typeof elementLight\n"
  },
  {
    "path": "src/element/tests/Element.spec.ts",
    "content": "import { mount } from '@vue/test-utils'\nimport { NElement } from '../index'\n\ndescribe('n-element', () => {\n  it('should work with import on demand', () => {\n    mount(NElement)\n  })\n  it('should work with `tag` prop', () => {\n    const wrapper = mount(NElement, {\n      props: {\n        tag: 'span'\n      },\n      slots: {\n        default: () => 'element'\n      }\n    })\n    expect(wrapper.find('span').exists()).toBe(true)\n    expect(wrapper.find('span').text()).toBe('element')\n    wrapper.unmount()\n  })\n})\n"
  },
  {
    "path": "src/element/tests/server.spec.tsx",
    "content": "import { setup } from '@css-render/vue3-ssr'\nimport { renderToString } from '@vue/server-renderer'\n/**\n * @vitest-environment node\n */\nimport { createSSRApp, h } from 'vue'\nimport { NElement } from '../..'\n\ndescribe('server side rendering', () => {\n  it('works', async () => {\n    const app = createSSRApp(() => <NElement />)\n    setup(app)\n    try {\n      await renderToString(app)\n    }\n    catch (e) {\n      expect(e).not.toBeTruthy()\n    }\n  })\n})\n"
  },
  {
    "path": "src/ellipsis/demos/enUS/basic.demo.vue",
    "content": "<markdown>\n# Basic\n\nBasic single line ellipsis with tooltip.\n</markdown>\n\n<template>\n  <n-ellipsis style=\"max-width: 240px\">\n    Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium\n    doloremque laudantium, totam rem aperiam\n  </n-ellipsis>\n</template>\n"
  },
  {
    "path": "src/ellipsis/demos/enUS/custom-tooltip.demo.vue",
    "content": "<markdown>\n# Customize tooltip content\n\nUse the `tooltip` slot to customize the tooltip content.\n</markdown>\n\n<template>\n  <n-ellipsis style=\"max-width: 240px\">\n    Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium\n    doloremque laudantium, totam rem aperiam\n    <template #tooltip>\n      <div style=\"text-align: center\">\n        <i>Lorem Ipsum</i><br>\n        Sed ut perspiciatis unde omnis<br>\n        iste natus error sit voluptatem accusantium doloremque laudantium,<br>\n        totam rem aperiam\n      </div>\n    </template>\n  </n-ellipsis>\n</template>\n"
  },
  {
    "path": "src/ellipsis/demos/enUS/expand-trigger.demo.vue",
    "content": "<markdown>\n# Expand trigger\n\nUse `expand-trigger=\"click\"` with the `line-clamp` parameter to achieve the function of clicking the abbreviated text to expand the complete text.\n</markdown>\n\n<template>\n  <n-ellipsis expand-trigger=\"click\" line-clamp=\"2\" :tooltip=\"false\">\n    Lorem ipsum dolor sit amet,<br>\n    consectetur adipiscing elit,<br>\n    sed do eiusmod tempor incididunt<br>\n    ut labore et dolore magna aliqua.<br>\n    Ut enim ad minim veniam,<br>\n    quis nostrud exercitation ullamco\n  </n-ellipsis>\n</template>\n"
  },
  {
    "path": "src/ellipsis/demos/enUS/index.demo-entry.md",
    "content": "# Ellipsis\n\nComplexity has to live somewhere.\n\nWhen you hear somebody talk about a subtle concept, keep alert.\n\n## Demos\n\n```demo\nbasic.vue\nline-clamp.vue\nexpand-trigger.vue\ncustom-tooltip.vue\nperformant-ellipsis.vue\n```\n\n## API\n\n### Ellipsis, PerformantEllipsis Props\n\n`n-performant-ellipsis` since 2.35.0.\n\n| Name | Type | Default | Description | Version |\n| --- | --- | --- | --- | --- |\n| expand-trigger | `'click'` | `undefined` | Abbreviated content trigger event to expand to the full text. | 2.1.0 |\n| line-clamp | `number \\| string` | `undefined` | Maximum lines. | 2.1.0 |\n| tooltip | `boolean \\| TooltipProps` | `true` | Tooltip properties. | 2.1.0 |\n\n### Ellipsis Slots\n\n| Name    | Parameters | Description                           |\n| ------- | ---------- | ------------------------------------- |\n| default | `()`       | The content of the ellipsis.          |\n| tooltip | `()`       | The content of the ellipsis' tooltip. |\n"
  },
  {
    "path": "src/ellipsis/demos/enUS/line-clamp.demo.vue",
    "content": "<markdown>\n# Line clamp\n\nSee [caniuse](https://caniuse.com/?search=line-clamp) for compatibility.\n</markdown>\n\n<template>\n  <n-ellipsis :line-clamp=\"2\">\n    Lorem ipsum dolor sit amet,<br>\n    consectetur adipiscing elit,<br>\n    sed do eiusmod tempor incididunt<br>\n    ut labore et dolore magna aliqua.<br>\n    Ut enim ad minim veniam,<br>\n    quis nostrud exercitation ullamco\n  </n-ellipsis>\n</template>\n"
  },
  {
    "path": "src/ellipsis/demos/enUS/performant-ellipsis.demo.vue",
    "content": "<markdown>\n# Better render performance\n\nIn most case, normal ellipsis is fast enough. However, if you have a huge amount ellipsis to render, you may use `n-performant-ellipsis` in place of `n-ellipsis`. It has better render performance with some caveats: Inner component may be unmounted and remouted again. Use it carefully.\n</markdown>\n\n<template>\n  <n-performant-ellipsis style=\"max-width: 240px\">\n    Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium\n    doloremque laudantium, totam rem aperiam\n  </n-performant-ellipsis>\n</template>\n"
  },
  {
    "path": "src/ellipsis/demos/zhCN/basic.demo.vue",
    "content": "<markdown>\n# 基础\n\n带弹出提示基本的单行省略。\n</markdown>\n\n<template>\n  <n-ellipsis style=\"max-width: 240px\">\n    住在我心里孤独的 孤独的海怪 痛苦之王 开始厌倦 深海的光 停滞的海浪\n  </n-ellipsis>\n</template>\n"
  },
  {
    "path": "src/ellipsis/demos/zhCN/custom-tooltip.demo.vue",
    "content": "<markdown>\n# 定制 Tooltip 内容\n\n使用 `tooltip` slot 定制 tooltip 内容。\n</markdown>\n\n<template>\n  <n-ellipsis style=\"max-width: 240px\">\n    住在我心里孤独的 孤独的海怪 痛苦之王 开始厌倦 深海的光 停滞的海浪\n    <template #tooltip>\n      <div style=\"text-align: center\">\n        《秦皇岛》<br>住在我心里孤独的<br>孤独的海怪 痛苦之王<br>开始厌倦\n        深海的光 停滞的海浪\n      </div>\n    </template>\n  </n-ellipsis>\n</template>\n"
  },
  {
    "path": "src/ellipsis/demos/zhCN/dynamic-debug.demo.vue",
    "content": "<markdown>\n# Dynamic Debug\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst text = ref(\n  '住在我心里孤独的 孤独的海怪 痛苦之王 开始厌倦 深海的光 停滞的海浪'\n)\n\nfunction toogleText() {\n  if (text.value.length > 10) {\n    text.value = '住在我心里孤独的'\n  }\n  else {\n    text.value\n      = '住在我心里孤独的 孤独的海怪 痛苦之王 开始厌倦 深海的光 停滞的海浪'\n  }\n}\n</script>\n\n<template>\n  <p>测试：：：：</p>\n\n  <n-ellipsis style=\"max-width: 240px\">\n    {{ text }}\n  </n-ellipsis>\n  <br>\n  <br>\n  <br>\n  <n-button type=\"primary\" @click=\"toogleText\">\n    测试动态文字\n  </n-button>\n</template>\n"
  },
  {
    "path": "src/ellipsis/demos/zhCN/expand-trigger.demo.vue",
    "content": "<markdown>\n# 展开方式\n\n使用 `expand-trigger=\"click\"` 搭配 `line-clamp` 参数可以实现点击缩略文本展开完整文本的功能。\n</markdown>\n\n<template>\n  <n-ellipsis expand-trigger=\"click\" line-clamp=\"2\" :tooltip=\"false\">\n    电灯熄灭 物换星移 泥牛入海<br>\n    黑暗好像 一颗巨石 按在胸口<br>\n    独脚大盗 百万富翁 摸爬滚打<br>\n    黑暗好像 一颗巨石 按在胸口\n  </n-ellipsis>\n</template>\n"
  },
  {
    "path": "src/ellipsis/demos/zhCN/index.demo-entry.md",
    "content": "# 文本省略 Ellipsis\n\n复杂度不会消失，只会转移。\n\n当你听到一些人对于精致的概念模型侃侃而谈，请保持清醒。\n\n## 演示\n\n```demo\nbasic.vue\nline-clamp.vue\nexpand-trigger.vue\ncustom-tooltip.vue\nperformant-ellipsis.vue\ndynamic-debug.vue\nwidth-debug.vue\n```\n\n## API\n\n### Ellipsis, PerformantEllipsis Props\n\n`n-performant-ellipsis` 从 2.35.0 开始提供。\n\n| 名称 | 类型 | 默认值 | 说明 | 版本 |\n| --- | --- | --- | --- | --- |\n| expand-trigger | `'click'` | `undefined` | 展开的触发方式 | 2.1.0 |\n| line-clamp | `number \\| string` | `undefined` | 最大行数 | 2.1.0 |\n| tooltip | `boolean \\| TooltipProps` | `true` | Tooltip 的属性 | 2.1.0 |\n\n### Ellipsis Slots\n\n| 名称    | 参数 | 说明           |\n| ------- | ---- | -------------- |\n| default | `()` | 文本省略的内容 |\n| tooltip | `()` | tooltip 的内容 |\n"
  },
  {
    "path": "src/ellipsis/demos/zhCN/line-clamp.demo.vue",
    "content": "<markdown>\n# 最大行数\n\nnaive-ui 提供基于 `-webkit-line-clamp` 的多行省略。兼容性参见 [caniuse](https://caniuse.com/?search=line-clamp)。\n</markdown>\n\n<template>\n  <n-ellipsis :line-clamp=\"2\">\n    电灯熄灭 物换星移 泥牛入海<br>黑暗好像 一颗巨石 按在胸口<br>独脚大盗\n    百万富翁 摸爬滚打<br>黑暗好像 一颗巨石 按在胸口\n  </n-ellipsis>\n</template>\n"
  },
  {
    "path": "src/ellipsis/demos/zhCN/performant-ellipsis.demo.vue",
    "content": "<markdown>\n# 渲染性能更好的省略\n\n通常情况下，普通的省略已经能满足性能需求，但是在大量渲染的情况下，你可以使用 `n-performant-ellipsis` 来替代普通的 `n-ellipsis`。它具备更好的性能，但是也存在一些问题：内部的组件有可能被卸载再重新挂载，所以请谨慎使用。\n</markdown>\n\n<template>\n  <n-performant-ellipsis style=\"max-width: 240px\">\n    住在我心里孤独的 孤独的海怪 痛苦之王 开始厌倦 深海的光 停滞的海浪\n  </n-performant-ellipsis>\n</template>\n"
  },
  {
    "path": "src/ellipsis/demos/zhCN/width-debug.demo.vue",
    "content": "<markdown>\n# Width debug\n</markdown>\n\n<template>\n  <n-ellipsis style=\"width: 70px; font-family: 'Helvetica Neue'\">\n    624748504\n  </n-ellipsis>\n</template>\n"
  },
  {
    "path": "src/ellipsis/index.ts",
    "content": "export { ellipsisProps, default as NEllipsis } from './src/Ellipsis'\nexport type { EllipsisProps, EllipsisSlots } from './src/Ellipsis'\nexport { NPerformantEllipsis } from './src/PerformantEllipsis'\n"
  },
  {
    "path": "src/ellipsis/src/Ellipsis.tsx",
    "content": "import type { PropType, SlotsType, VNode } from 'vue'\nimport type { ThemeProps } from '../../_mixins'\nimport type { ExtractPublicPropTypes } from '../../_utils'\nimport type { PopoverProps } from '../../popover/src/Popover'\nimport type { TooltipInst } from '../../tooltip/src/Tooltip'\nimport type { EllipsisTheme } from '../styles'\nimport {\n  computed,\n  defineComponent,\n  h,\n  mergeProps,\n  onDeactivated,\n  ref\n} from 'vue'\nimport { useTheme } from '../../_mixins'\nimport { useMergedClsPrefix } from '../../_mixins/use-config'\nimport { NTooltip } from '../../tooltip'\nimport { ellipsisLight } from '../styles'\nimport style from './styles/index.cssr'\n\nexport function createLineClampClass(clsPrefix: string): string {\n  return `${clsPrefix}-ellipsis--line-clamp`\n}\n\nexport function createCursorClass(clsPrefix: string, cursor: string): string {\n  return `${clsPrefix}-ellipsis--cursor-${cursor}`\n}\n\nexport const ellipsisProps = {\n  ...(useTheme.props as ThemeProps<EllipsisTheme>),\n  expandTrigger: String as PropType<'click'>,\n  lineClamp: [Number, String] as PropType<string | number>,\n  tooltip: {\n    type: [Boolean, Object] as PropType<PopoverProps | boolean>,\n    default: true\n  }\n} as const\n\nexport type EllipsisProps = ExtractPublicPropTypes<typeof ellipsisProps>\n\nexport interface EllipsisSlots {\n  default?: () => VNode[]\n  tooltip?: () => VNode[]\n}\n\nexport default defineComponent({\n  name: 'Ellipsis',\n  inheritAttrs: false,\n  props: ellipsisProps,\n  slots: Object as SlotsType<EllipsisSlots>,\n  setup(props, { slots, attrs }) {\n    const mergedClsPrefixRef = useMergedClsPrefix()\n    const mergedTheme = useTheme(\n      'Ellipsis',\n      '-ellipsis',\n      style,\n      ellipsisLight,\n      props,\n      mergedClsPrefixRef\n    )\n    const triggerRef = ref<HTMLElement | null>(null)\n    const triggerInnerRef = ref<HTMLElement | null>(null)\n    const tooltipRef = ref<TooltipInst | null>(null)\n    const expandedRef = ref(false)\n    const ellipsisStyleRef = computed(() => {\n      const { lineClamp } = props\n      const { value: expanded } = expandedRef\n      if (lineClamp !== undefined) {\n        return {\n          textOverflow: '',\n          '-webkit-line-clamp': expanded ? '' : lineClamp\n        }\n      }\n      else {\n        return {\n          textOverflow: expanded ? '' : 'ellipsis',\n          '-webkit-line-clamp': ''\n        }\n      }\n    })\n    function getTooltipDisabled(): boolean {\n      let tooltipDisabled = false\n      const { value: expanded } = expandedRef\n      if (expanded)\n        return true\n      const { value: trigger } = triggerRef\n      if (trigger) {\n        const { lineClamp } = props\n        // we need to apply style here, since the dom may be updated in\n        // nextTick, measure dom size will derive wrong result\n        syncEllipsisStyle(trigger)\n        if (lineClamp !== undefined) {\n          tooltipDisabled = trigger.scrollHeight <= trigger.offsetHeight\n        }\n        else {\n          const { value: triggerInner } = triggerInnerRef\n          if (triggerInner) {\n            tooltipDisabled\n              = triggerInner.getBoundingClientRect().width\n                <= trigger.getBoundingClientRect().width\n          }\n        }\n        syncCursorStyle(trigger, tooltipDisabled)\n      }\n      return tooltipDisabled\n    }\n    const handleClickRef = computed(() => {\n      return props.expandTrigger === 'click'\n        ? () => {\n            const { value: expanded } = expandedRef\n            if (expanded) {\n              tooltipRef.value?.setShow(false)\n            }\n            expandedRef.value = !expanded\n          }\n        : undefined\n    })\n    onDeactivated(() => {\n      if (props.tooltip) {\n        tooltipRef.value?.setShow(false)\n      }\n    })\n    const renderTrigger = (): JSX.Element => (\n      <span\n        {...mergeProps(attrs, {\n          class: [\n            `${mergedClsPrefixRef.value}-ellipsis`,\n            props.lineClamp !== undefined\n              ? createLineClampClass(mergedClsPrefixRef.value)\n              : undefined,\n            props.expandTrigger === 'click'\n              ? createCursorClass(mergedClsPrefixRef.value, 'pointer')\n              : undefined\n          ],\n          style: ellipsisStyleRef.value\n        })}\n        ref=\"triggerRef\"\n        onClick={handleClickRef.value}\n        onMouseenter={\n          // get tooltip disabled will derive cursor style\n          props.expandTrigger === 'click' ? getTooltipDisabled : undefined\n        }\n      >\n        {props.lineClamp ? slots : <span ref=\"triggerInnerRef\">{slots}</span>}\n      </span>\n    )\n    function syncEllipsisStyle(trigger: HTMLElement): void {\n      if (!trigger)\n        return\n      const latestStyle = ellipsisStyleRef.value\n      const lineClampClass = createLineClampClass(mergedClsPrefixRef.value)\n      if (props.lineClamp !== undefined) {\n        syncTriggerClass(trigger, lineClampClass, 'add')\n      }\n      else {\n        syncTriggerClass(trigger, lineClampClass, 'remove')\n      }\n      for (const key in latestStyle) {\n        // guard can make it a little faster\n        if ((trigger.style as any)[key] !== (latestStyle as any)[key]) {\n          ;(trigger.style as any)[key] = (latestStyle as any)[key]\n        }\n      }\n    }\n    function syncCursorStyle(\n      trigger: HTMLElement,\n      tooltipDisabled: boolean\n    ): void {\n      const cursorClass = createCursorClass(mergedClsPrefixRef.value, 'pointer')\n      if (props.expandTrigger === 'click' && !tooltipDisabled) {\n        syncTriggerClass(trigger, cursorClass, 'add')\n      }\n      else {\n        syncTriggerClass(trigger, cursorClass, 'remove')\n      }\n    }\n    function syncTriggerClass(\n      trigger: HTMLElement,\n      styleClass: string,\n      action: 'add' | 'remove'\n    ): void {\n      if (action === 'add') {\n        if (!trigger.classList.contains(styleClass)) {\n          trigger.classList.add(styleClass)\n        }\n      }\n      else {\n        if (trigger.classList.contains(styleClass)) {\n          trigger.classList.remove(styleClass)\n        }\n      }\n    }\n    return {\n      mergedTheme,\n      triggerRef,\n      triggerInnerRef,\n      tooltipRef,\n      handleClick: handleClickRef,\n      renderTrigger,\n      getTooltipDisabled\n    }\n  },\n  render() {\n    const { tooltip, renderTrigger, $slots } = this\n    if (tooltip) {\n      const { mergedTheme } = this\n      return (\n        <NTooltip\n          ref=\"tooltipRef\"\n          placement=\"top\"\n          {...(tooltip as PopoverProps)}\n          getDisabled={this.getTooltipDisabled}\n          theme={mergedTheme.peers.Tooltip}\n          themeOverrides={mergedTheme.peerOverrides.Tooltip}\n        >\n          {{\n            trigger: renderTrigger,\n            default: $slots.tooltip ?? $slots.default\n          }}\n        </NTooltip>\n      )\n    }\n    else {\n      return renderTrigger()\n    }\n  }\n})\n"
  },
  {
    "path": "src/ellipsis/src/PerformantEllipsis.tsx",
    "content": "import { defineComponent, h, mergeProps, ref } from 'vue'\nimport { useStyle } from '../../_mixins'\nimport { useMergedClsPrefix } from '../../_mixins/use-config'\nimport Ellipsis, {\n  createCursorClass,\n  createLineClampClass,\n  ellipsisProps\n} from './Ellipsis'\nimport style from './styles/index.cssr'\n\nexport const NPerformantEllipsis = defineComponent({\n  name: 'PerformantEllipsis',\n  props: ellipsisProps,\n  inheritAttrs: false,\n  setup(props, { attrs, slots }) {\n    const mouseEnteredRef = ref(false)\n    const mergedClsPrefixRef = useMergedClsPrefix()\n    useStyle('-ellipsis', style, mergedClsPrefixRef)\n    // Modified from Ellipsis.tsx\n    const renderTrigger = (): JSX.Element => {\n      const { lineClamp } = props\n      const mergedClsPrefix = mergedClsPrefixRef.value\n      return (\n        <span\n          {...mergeProps(attrs, {\n            class: [\n              `${mergedClsPrefix}-ellipsis`,\n              lineClamp !== undefined\n                ? createLineClampClass(mergedClsPrefix)\n                : undefined,\n              props.expandTrigger === 'click'\n                ? createCursorClass(mergedClsPrefix, 'pointer')\n                : undefined\n            ],\n            style:\n              lineClamp === undefined\n                ? {\n                    textOverflow: 'ellipsis'\n                  }\n                : {\n                    '-webkit-line-clamp': lineClamp\n                  }\n          })}\n          onMouseenter={() => {\n            mouseEnteredRef.value = true\n          }}\n        >\n          {lineClamp ? slots : <span>{slots}</span>}\n        </span>\n      )\n    }\n    return {\n      mouseEntered: mouseEnteredRef,\n      renderTrigger\n    }\n  },\n  render() {\n    if (this.mouseEntered) {\n      return h(Ellipsis, mergeProps({}, this.$attrs, this.$props), this.$slots)\n    }\n    else {\n      return this.renderTrigger()\n    }\n  }\n})\n"
  },
  {
    "path": "src/ellipsis/src/styles/index.cssr.ts",
    "content": "import { cB, cM, cNotM } from '../../../_utils/cssr'\n\nexport default cB('ellipsis', {\n  overflow: 'hidden'\n}, [\n  cNotM('line-clamp', `\n    white-space: nowrap;\n    display: inline-block;\n    vertical-align: bottom;\n    max-width: 100%;\n  `),\n  cM('line-clamp', `\n    display: -webkit-inline-box;\n    -webkit-box-orient: vertical;\n  `),\n  cM('cursor-pointer', `\n    cursor: pointer;\n  `)\n])\n"
  },
  {
    "path": "src/ellipsis/styles/dark.ts",
    "content": "import type { EllipsisTheme } from './light'\nimport { commonDark } from '../../_styles/common'\nimport { tooltipDark } from '../../tooltip/styles'\n\nconst ellipsisDark: EllipsisTheme = {\n  name: 'Ellipsis',\n  common: commonDark,\n  peers: {\n    Tooltip: tooltipDark\n  }\n}\n\nexport default ellipsisDark\n"
  },
  {
    "path": "src/ellipsis/styles/index.ts",
    "content": "export { default as ellipsisDark } from './dark'\nexport { default as ellipsisLight } from './light'\nexport type { EllipsisTheme } from './light'\n"
  },
  {
    "path": "src/ellipsis/styles/light.ts",
    "content": "import { createTheme } from '../../_mixins'\nimport { commonLight } from '../../_styles/common'\nimport { tooltipLight } from '../../tooltip/styles'\n\nconst ellipsisLight = createTheme({\n  name: 'Ellipsis',\n  common: commonLight,\n  peers: {\n    Tooltip: tooltipLight\n  }\n})\n\nexport default ellipsisLight\nexport type EllipsisTheme = typeof ellipsisLight\n"
  },
  {
    "path": "src/ellipsis/tests/Ellipsis.spec.tsx",
    "content": "import { mount } from '@vue/test-utils'\nimport { h } from 'vue'\nimport { NEllipsis } from '../index'\n\ndescribe('n-ellipsis', () => {\n  it('should work with import on demand', () => {\n    mount(NEllipsis)\n  })\n\n  it('should work with base', async () => {\n    const wrapper = mount(NEllipsis, {\n      props: { style: 'max-width: 10px;' },\n      slots: { default: () => 'test n-ellipsis' }\n    })\n\n    expect(wrapper.find('.n-ellipsis').exists()).toBe(true)\n    expect(wrapper.find('.n-ellipsis').attributes('style')).toContain(\n      'text-overflow: ellipsis;'\n    )\n    wrapper.unmount()\n  })\n\n  it('should work with `line-clamp` prop', async () => {\n    const wrapper = mount(NEllipsis, {\n      props: { lineClamp: 2 },\n      slots: {\n        default: () => (\n          <div>\n            电灯熄灭 物换星移 泥牛入海\n            <br />\n            黑暗好像 一颗巨石 按在胸口\n            <br />\n            独脚大盗 百万富翁 摸爬滚打\n          </div>\n        )\n      }\n    })\n\n    expect(wrapper.find('.n-ellipsis').classes()).toContain(\n      'n-ellipsis--line-clamp'\n    )\n    wrapper.unmount()\n  })\n\n  it('should work with `expand-trigger` prop', async () => {\n    const wrapper = mount(NEllipsis, {\n      props: {\n        expandTrigger: 'click',\n        tooltip: false\n      },\n      slots: { default: () => 'test n-ellipsis' }\n    })\n\n    await wrapper.trigger('click')\n    expect(wrapper.find('.n-ellipsis').attributes('style')).not.toContain(\n      'text-overflow: ellipsis;'\n    )\n\n    await wrapper.trigger('click')\n    expect(wrapper.find('.n-ellipsis').attributes('style')).toContain(\n      'text-overflow: ellipsis;'\n    )\n    wrapper.unmount()\n  })\n})\n"
  },
  {
    "path": "src/ellipsis/tests/server.spec.tsx",
    "content": "import { setup } from '@css-render/vue3-ssr'\nimport { renderToString } from '@vue/server-renderer'\n/**\n * @vitest-environment node\n */\nimport { createSSRApp, h } from 'vue'\nimport { NEllipsis } from '../..'\n\ndescribe('server side rendering', () => {\n  it('works', async () => {\n    const app = createSSRApp(() => (\n      <NEllipsis>\n        {{\n          trigger: () => 'kirby'\n        }}\n      </NEllipsis>\n    ))\n    setup(app)\n    try {\n      await renderToString(app)\n    }\n    catch (e) {\n      expect(e).not.toBeTruthy()\n    }\n  })\n})\n"
  },
  {
    "path": "src/empty/demos/enUS/basic.demo.vue",
    "content": "<markdown>\n# Basic\n</markdown>\n\n<template>\n  <n-empty description=\"You can't find anything\">\n    <template #extra>\n      <n-button size=\"small\">\n        Find Something New\n      </n-button>\n    </template>\n  </n-empty>\n</template>\n"
  },
  {
    "path": "src/empty/demos/enUS/icon.demo.vue",
    "content": "<markdown>\n# Icon\n\nCustomize icon in empty.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { IosAirplane } from '@vicons/ionicons4'\n</script>\n\n<template>\n  <n-empty description=\"Custom your icon\">\n    <template #icon>\n      <n-icon>\n        <IosAirplane />\n      </n-icon>\n    </template>\n    <template #extra>\n      <n-button size=\"small\">\n        Find Something New\n      </n-button>\n    </template>\n  </n-empty>\n</template>\n"
  },
  {
    "path": "src/empty/demos/enUS/index.demo-entry.md",
    "content": "# Empty\n\nE<span style=\"opacity: 0;\">mpt</span>y.\n\n## Demos\n\n```demo\nbasic.vue\nicon.vue\nsize.vue\n```\n\n## API\n\n### Empty Props\n\n| Name | Type | Default | Description | Version |\n| --- | --- | --- | --- | --- |\n| description | `string` | `'No Data'` | Description of the empty. |  |\n| show-description | `boolean` | `true` | Whether to show description of empty. |  |\n| show-icon | `boolean` | `true` | Whether to show icon of empty. |  |\n| size | `'tiny' \\| 'small' \\| 'medium' \\| 'large' \\| 'huge'` | `'medium'` | Empty's size. | 2.40.0 |\n\n### Empty Slots\n\n| Name    | Parameters | Description                  |\n| ------- | ---------- | ---------------------------- |\n| default | `()`       | In place of description prop |\n| extra   | `()`       | Extra content.               |\n| icon    | `()`       | Custom icon.                 |\n"
  },
  {
    "path": "src/empty/demos/enUS/locale-debug.demo.vue",
    "content": "<markdown>\n# Locale Debug\n</markdown>\n\n<template>\n  <n-empty />\n</template>\n"
  },
  {
    "path": "src/empty/demos/enUS/size.demo.vue",
    "content": "<markdown>\n# Size\n\nEmpty can be `tiny`, `small`, `medium`, `large` and `huge` size.\n</markdown>\n\n<template>\n  <n-empty size=\"large\" description=\"can be large\">\n    <template #extra>\n      <n-button size=\"small\">\n        Find Something New\n      </n-button>\n    </template>\n  </n-empty>\n</template>\n"
  },
  {
    "path": "src/empty/demos/zhCN/basic.demo.vue",
    "content": "<markdown>\n# 基础用法\n</markdown>\n\n<template>\n  <n-empty description=\"你什么也找不到\">\n    <template #extra>\n      <n-button size=\"small\">\n        看看别的\n      </n-button>\n    </template>\n  </n-empty>\n</template>\n"
  },
  {
    "path": "src/empty/demos/zhCN/icon.demo.vue",
    "content": "<markdown>\n# 图标\n\n自定义图标。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { IosAirplane } from '@vicons/ionicons4'\n</script>\n\n<template>\n  <n-empty description=\"是一个飞机\">\n    <template #icon>\n      <n-icon>\n        <IosAirplane />\n      </n-icon>\n    </template>\n    <template #extra>\n      <n-button size=\"small\">\n        看看别的\n      </n-button>\n    </template>\n  </n-empty>\n</template>\n"
  },
  {
    "path": "src/empty/demos/zhCN/index.demo-entry.md",
    "content": "# 无内容 Empty\n\n空<span style=\"opacity: 0;\">空如</span>也。\n\n## 演示\n\n```demo\nbasic.vue\nicon.vue\nsize.vue\n```\n\n## API\n\n### Empty Props\n\n| 名称 | 类型 | 默认值 | 说明 | 版本 |\n| --- | --- | --- | --- | --- |\n| description | `string` | `'无数据'` | 描述信息 |  |\n| show-description | `boolean` | `true` | 是否展示描述信息 |  |\n| show-icon | `boolean` | `true` | 是否展示图标 |  |\n| size | `'tiny' \\| 'small' \\| 'medium' \\| 'large' \\| 'huge'` | `'medium'` | 尺寸大小 | 2.40.0 |\n\n### Empty Slots\n\n| 名称    | 参数 | 说明             |\n| ------- | ---- | ---------------- |\n| default | `()` | 代替 description |\n| extra   | `()` | 扩展的内容       |\n| icon    | `()` | 自定义图标       |\n"
  },
  {
    "path": "src/empty/demos/zhCN/locale-debug.demo.vue",
    "content": "<markdown>\n# Locale Debug\n</markdown>\n\n<template>\n  <n-empty />\n</template>\n"
  },
  {
    "path": "src/empty/demos/zhCN/size.demo.vue",
    "content": "<markdown>\n# 尺寸\n\n有 `tiny`、 `small`、`medium`、`large` 和 `huge` 尺寸。\n</markdown>\n\n<template>\n  <n-empty size=\"large\" description=\"可以是大的\">\n    <template #extra>\n      <n-button size=\"small\">\n        看看别的\n      </n-button>\n    </template>\n  </n-empty>\n</template>\n"
  },
  {
    "path": "src/empty/index.ts",
    "content": "export { emptyProps, default as NEmpty } from './src/Empty'\nexport type { EmptyProps, EmptySlots } from './src/Empty'\n"
  },
  {
    "path": "src/empty/src/Empty.tsx",
    "content": "import type { PropType, SlotsType, VNode, VNodeChild } from 'vue'\nimport type { ThemeProps } from '../../_mixins'\nimport type { ExtractPublicPropTypes } from '../../_utils'\nimport type { EmptyTheme } from '../styles'\nimport { computed, defineComponent, h } from 'vue'\nimport { NBaseIcon } from '../../_internal/icon'\nimport { EmptyIcon } from '../../_internal/icons'\nimport { useConfig, useLocale, useTheme, useThemeClass } from '../../_mixins'\nimport { createKey } from '../../_utils'\nimport { emptyLight } from '../styles'\nimport style from './styles/index.cssr'\n\nexport const emptyProps = {\n  ...(useTheme.props as ThemeProps<EmptyTheme>),\n  description: String,\n  showDescription: {\n    type: Boolean,\n    default: true\n  },\n  showIcon: {\n    type: Boolean,\n    default: true\n  },\n  size: {\n    type: String as PropType<'tiny' | 'small' | 'medium' | 'large' | 'huge'>,\n    default: 'medium'\n  },\n  renderIcon: Function as PropType<() => VNodeChild>\n}\n\nexport type EmptyProps = ExtractPublicPropTypes<typeof emptyProps>\n\nexport interface EmptySlots {\n  default?: () => VNode[]\n  extra?: () => VNode[]\n  icon?: () => VNode[]\n}\n\nexport default defineComponent({\n  name: 'Empty',\n  props: emptyProps,\n  slots: Object as SlotsType<EmptySlots>,\n  setup(props) {\n    const { mergedClsPrefixRef, inlineThemeDisabled, mergedComponentPropsRef }\n      = useConfig(props)\n    const themeRef = useTheme(\n      'Empty',\n      '-empty',\n      style,\n      emptyLight,\n      props,\n      mergedClsPrefixRef\n    )\n    const { localeRef } = useLocale('Empty')\n    const mergedDescriptionRef = computed(() => {\n      return (\n        props.description ?? mergedComponentPropsRef?.value?.Empty?.description\n      )\n    })\n    const mergedRenderIconRef = computed(\n      () =>\n        mergedComponentPropsRef?.value?.Empty?.renderIcon\n        || (() => <EmptyIcon />)\n    )\n    const cssVarsRef = computed(() => {\n      const { size } = props\n      const {\n        common: { cubicBezierEaseInOut },\n        self: {\n          [createKey('iconSize', size)]: iconSize,\n          [createKey('fontSize', size)]: fontSize,\n          textColor,\n          iconColor,\n          extraTextColor\n        }\n      } = themeRef.value\n      return {\n        '--n-icon-size': iconSize,\n        '--n-font-size': fontSize,\n        '--n-bezier': cubicBezierEaseInOut,\n        '--n-text-color': textColor,\n        '--n-icon-color': iconColor,\n        '--n-extra-text-color': extraTextColor\n      }\n    })\n    const themeClassHandle = inlineThemeDisabled\n      ? useThemeClass(\n          'empty',\n          computed(() => {\n            let hash = ''\n            const { size } = props\n            hash += size[0]\n            return hash\n          }),\n          cssVarsRef,\n          props\n        )\n      : undefined\n    return {\n      mergedClsPrefix: mergedClsPrefixRef,\n      mergedRenderIcon: mergedRenderIconRef,\n      localizedDescription: computed(() => {\n        return mergedDescriptionRef.value || localeRef.value.description\n      }),\n      cssVars: inlineThemeDisabled ? undefined : cssVarsRef,\n      themeClass: themeClassHandle?.themeClass,\n      onRender: themeClassHandle?.onRender\n    }\n  },\n  render() {\n    const { $slots, mergedClsPrefix, onRender } = this\n    onRender?.()\n    return (\n      <div\n        class={[`${mergedClsPrefix}-empty`, this.themeClass]}\n        style={this.cssVars as any}\n      >\n        {this.showIcon ? (\n          <div class={`${mergedClsPrefix}-empty__icon`}>\n            {$slots.icon ? (\n              $slots.icon()\n            ) : (\n              <NBaseIcon clsPrefix={mergedClsPrefix}>\n                {{ default: this.mergedRenderIcon }}\n              </NBaseIcon>\n            )}\n          </div>\n        ) : null}\n        {this.showDescription ? (\n          <div class={`${mergedClsPrefix}-empty__description`}>\n            {$slots.default ? $slots.default() : this.localizedDescription}\n          </div>\n        ) : null}\n        {$slots.extra ? (\n          <div class={`${mergedClsPrefix}-empty__extra`}>{$slots.extra()}</div>\n        ) : null}\n      </div>\n    )\n  }\n})\n"
  },
  {
    "path": "src/empty/src/styles/index.cssr.ts",
    "content": "import { c, cB, cE } from '../../../_utils/cssr'\n\n// vars:\n// --n-font-size\n// --n-icon-size\n// --n-icon-color\n// --n-bezier\n// --n-text-color\n// --n-extra-text-color\nexport default cB('empty', `\n  display: flex;\n  flex-direction: column;\n  align-items: center;\n  font-size: var(--n-font-size);\n`, [\n  cE('icon', `\n    width: var(--n-icon-size);\n    height: var(--n-icon-size);\n    font-size: var(--n-icon-size);\n    line-height: var(--n-icon-size);\n    color: var(--n-icon-color);\n    transition:\n      color .3s var(--n-bezier);\n  `, [\n    c('+', [\n      cE('description', `\n        margin-top: 8px;\n      `)\n    ])\n  ]),\n  cE('description', `\n    transition: color .3s var(--n-bezier);\n    color: var(--n-text-color);\n  `),\n  cE('extra', `\n    text-align: center;\n    transition: color .3s var(--n-bezier);\n    margin-top: 12px;\n    color: var(--n-extra-text-color);\n  `)\n])\n"
  },
  {
    "path": "src/empty/styles/_common.ts",
    "content": "export default {\n  iconSizeTiny: '28px',\n  iconSizeSmall: '34px',\n  iconSizeMedium: '40px',\n  iconSizeLarge: '46px',\n  iconSizeHuge: '52px'\n}\n"
  },
  {
    "path": "src/empty/styles/dark.ts",
    "content": "import type { EmptyTheme } from './light'\nimport { commonDark } from '../../_styles/common'\nimport { self } from './light'\n\nconst emptyDark: EmptyTheme = {\n  name: 'Empty',\n  common: commonDark,\n  self\n}\n\nexport default emptyDark\n"
  },
  {
    "path": "src/empty/styles/index.ts",
    "content": "export { default as emptyDark } from './dark'\nexport { default as emptyLight } from './light'\nexport type { EmptyTheme, EmptyThemeVars } from './light'\n"
  },
  {
    "path": "src/empty/styles/light.ts",
    "content": "import type { Theme } from '../../_mixins'\nimport type { ThemeCommonVars } from '../../_styles/common'\nimport { commonLight } from '../../_styles/common'\nimport commonVars from './_common'\n\nexport function self(vars: ThemeCommonVars) {\n  const {\n    textColorDisabled,\n    iconColor,\n    textColor2,\n    fontSizeTiny,\n    fontSizeSmall,\n    fontSizeMedium,\n    fontSizeLarge,\n    fontSizeHuge\n  } = vars\n  return {\n    ...commonVars,\n    fontSizeTiny,\n    fontSizeSmall,\n    fontSizeMedium,\n    fontSizeLarge,\n    fontSizeHuge,\n    textColor: textColorDisabled,\n    iconColor,\n    extraTextColor: textColor2\n  }\n}\n\nexport type EmptyThemeVars = ReturnType<typeof self>\n\nconst emptyLight: Theme<'Empty', EmptyThemeVars> = {\n  name: 'Empty',\n  common: commonLight,\n  self\n}\n\nexport default emptyLight\nexport type EmptyTheme = typeof emptyLight\n"
  },
  {
    "path": "src/empty/tests/Empty.spec.ts",
    "content": "import { mount } from '@vue/test-utils'\nimport { NEmpty } from '../index'\n\ndescribe('n-empty', () => {\n  it('should work with import on demand', () => {\n    mount(NEmpty)\n  })\n\n  it('should work with slots', () => {\n    const wrapper = mount(NEmpty, {\n      slots: {\n        default: () => 'test-description',\n        icon: () => 'test-icon',\n        extra: () => 'test-extra'\n      }\n    })\n\n    expect(wrapper.find('.n-empty__description').exists()).toBe(true)\n    expect(wrapper.find('.n-empty__description').text()).toBe(\n      'test-description'\n    )\n    expect(wrapper.find('.n-empty__icon').exists()).toBe(true)\n    expect(wrapper.find('.n-empty__icon').text()).toBe('test-icon')\n    expect(wrapper.find('.n-empty__extra').exists()).toBe(true)\n    expect(wrapper.find('.n-empty__extra').text()).toBe('test-extra')\n    wrapper.unmount()\n  })\n  it('should work with `description` prop', () => {\n    const wrapper = mount(NEmpty, {\n      props: {\n        description: 'test-description'\n      }\n    })\n\n    expect(wrapper.find('.n-empty__description').exists()).toBe(true)\n    expect(wrapper.find('.n-empty__description').text()).toContain(\n      'test-description'\n    )\n    wrapper.unmount()\n  })\n\n  it('should work with `show-description` prop', async () => {\n    const wrapper = mount(NEmpty)\n    expect(wrapper.find('.n-empty__description').exists()).toBe(true)\n\n    await wrapper.setProps({ showDescription: false })\n    expect(wrapper.find('.n-empty__description').exists()).toBe(false)\n    wrapper.unmount()\n  })\n\n  it('should work with `show-icon` prop', async () => {\n    const wrapper = mount(NEmpty)\n    expect(wrapper.find('.n-empty__icon').exists()).toBe(true)\n\n    await wrapper.setProps({ showIcon: false })\n    expect(wrapper.find('.n-empty__icon').exists()).toBe(false)\n    wrapper.unmount()\n  })\n\n  it('should work with `size` prop', async () => {\n    const wrapper = mount(NEmpty)\n\n    expect(wrapper.find('.n-empty').attributes('style')).toMatchSnapshot()\n\n    await wrapper.setProps({ size: 'small' })\n    expect(wrapper.find('.n-empty').attributes('style')).toMatchSnapshot()\n\n    await wrapper.setProps({ size: 'large' })\n    expect(wrapper.find('.n-empty').attributes('style')).toMatchSnapshot()\n\n    await wrapper.setProps({ size: 'huge' })\n    expect(wrapper.find('.n-empty').attributes('style')).toMatchSnapshot()\n    wrapper.unmount()\n  })\n})\n"
  },
  {
    "path": "src/empty/tests/__snapshots__/Empty.spec.ts.snap",
    "content": "// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html\n\nexports[`n-empty > should work with \\`size\\` prop 1`] = `\"--n-icon-size: 40px; --n-font-size: 14px; --n-bezier: cubic-bezier(.4, 0, .2, 1); --n-text-color: rgba(194, 194, 194, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-extra-text-color: rgb(51, 54, 57);\"`;\n\nexports[`n-empty > should work with \\`size\\` prop 2`] = `\"--n-icon-size: 34px; --n-font-size: 14px; --n-bezier: cubic-bezier(.4, 0, .2, 1); --n-text-color: rgba(194, 194, 194, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-extra-text-color: rgb(51, 54, 57);\"`;\n\nexports[`n-empty > should work with \\`size\\` prop 3`] = `\"--n-icon-size: 46px; --n-font-size: 15px; --n-bezier: cubic-bezier(.4, 0, .2, 1); --n-text-color: rgba(194, 194, 194, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-extra-text-color: rgb(51, 54, 57);\"`;\n\nexports[`n-empty > should work with \\`size\\` prop 4`] = `\"--n-icon-size: 52px; --n-font-size: 16px; --n-bezier: cubic-bezier(.4, 0, .2, 1); --n-text-color: rgba(194, 194, 194, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-extra-text-color: rgb(51, 54, 57);\"`;\n"
  },
  {
    "path": "src/empty/tests/server.spec.tsx",
    "content": "import { setup } from '@css-render/vue3-ssr'\nimport { renderToString } from '@vue/server-renderer'\n/**\n * @vitest-environment node\n */\nimport { createSSRApp, h } from 'vue'\nimport { NEmpty } from '../..'\n\ndescribe('server side rendering', () => {\n  it('works', async () => {\n    const app = createSSRApp(() => <NEmpty />)\n    setup(app)\n    try {\n      await renderToString(app)\n    }\n    catch (e) {\n      expect(e).not.toBeTruthy()\n    }\n  })\n})\n"
  },
  {
    "path": "src/equation/demos/enUS/basic.demo.vue",
    "content": "<markdown>\n# Basic usage\n</markdown>\n\n<script lang=\"ts\" setup>\nimport katex from 'katex'\n\nconst equation = '\\\\displaystyle= \\\\frac{k(k+1)}{2}+k+1'\n</script>\n\n<template>\n  <n-config-provider :katex=\"katex\">\n    <n-equation :value=\"equation\" />\n  </n-config-provider>\n</template>\n"
  },
  {
    "path": "src/equation/demos/enUS/index.demo-entry.md",
    "content": "# Equation\n\nNo one will think of that a component library should have this component. However a friend of me need this.\n\n<n-alert title=\"Note\" type=\"warning\" style=\"margin-bottom: 16px;\" :bordered=\"false\">\n  Due to package size, Naive UI doesn't include katex. If you want to use Equation, make sure you have setup katex before using it.\n</n-alert>\n\nThe following code shows how to setup katex for Equation.\n\n```html\n<template>\n  <n-config-provider :katex=\"katex\">\n    <my-app />\n  </n-config-provider>\n</template>\n\n<script>\n  import { defineComponent } from 'vue'\n  import katex from 'katex'\n  import 'katex/dist/katex.css'\n\n  export default defineComponent({\n    setup() {\n      return {\n        katex\n      }\n    }\n  })\n</script>\n```\n\n## Demos\n\n```demo\nbasic.vue\nkatex-options.vue\n```\n\n## API\n\n### Equation Props\n\n| Name | Type | Default | Description | Version |\n| --- | --- | --- | --- | --- |\n| katex | `object` | `undefined` | Katex | 2.34.0 |\n| katex-options | `object` | `undefined` | Katex options for the equation. | 2.34.0 |\n| value | `string` | `undefined` | Latex expression of the equation. | 2.34.0 |\n"
  },
  {
    "path": "src/equation/demos/enUS/katex-options.demo.vue",
    "content": "<markdown>\n# Using katex options\n</markdown>\n\n<script lang=\"ts\" setup>\nimport katex from 'katex'\n\nconst equation = `\\\\f\\\\relax{x} = \\\\int_{-\\\\infty}^\\\\infty\n    \\\\f\\\\hat\\\\xi\\\\,e^{2 \\\\pi i \\\\xi x}\n    \\\\,d\\\\xi`\n\nconst katexOptions = {\n  displayMode: true,\n  fleqn: true,\n  macros: {\n    '\\\\f': '#1f(#2)'\n  }\n}\n</script>\n\n<template>\n  <n-config-provider :katex=\"katex\">\n    <n-equation :value=\"equation\" :katex-options=\"katexOptions\" />\n  </n-config-provider>\n</template>\n"
  },
  {
    "path": "src/equation/demos/zhCN/basic.demo.vue",
    "content": "<markdown>\n# 基础用法\n</markdown>\n\n<script lang=\"ts\" setup>\nimport katex from 'katex'\n\nconst equation = '\\\\displaystyle= \\\\frac{k(k+1)}{2}+k+1'\n</script>\n\n<template>\n  <n-config-provider :katex=\"katex\">\n    <n-equation :value=\"equation\" />\n  </n-config-provider>\n</template>\n"
  },
  {
    "path": "src/equation/demos/zhCN/index.demo-entry.md",
    "content": "# 公式 Equation\n\n没有人会想到一个组件库会有这种组件，但是作者的一位朋友需要这个。\n\n<n-alert title=\"注意\" type=\"warning\" style=\"margin-bottom: 16px;\" :bordered=\"false\">\n  由于包体积原因，Naive UI 不内置 katex。如果你需要使用公式组件，请确保你在使用之前已经设定了 katex。\n</n-alert>\n\n下面的代码展示了如何为 Equation 设定 katex。\n\n```html\n<template>\n  <n-config-provider :katex=\"katex\">\n    <my-app />\n  </n-config-provider>\n</template>\n\n<script>\n  import { defineComponent } from 'vue'\n  import katex from 'katex'\n  import 'katex/dist/katex.css'\n\n  export default defineComponent({\n    setup() {\n      return {\n        katex\n      }\n    }\n  })\n</script>\n```\n\n## 演示\n\n```demo\nbasic.vue\nkatex-options.vue\n```\n\n## API\n\n### Equation Props\n\n| 名称          | 类型     | 默认值      | 说明                   | 版本   |\n| ------------- | -------- | ----------- | ---------------------- | ------ |\n| katex         | `object` | `undefined` | Katex                  | 2.34.0 |\n| katex-options | `object` | `undefined` | Katex 公式的配置       | 2.34.0 |\n| value         | `string` | `undefined` | Latex 格式的公式表达式 | 2.34.0 |\n"
  },
  {
    "path": "src/equation/demos/zhCN/katex-options.demo.vue",
    "content": "<markdown>\n# 使用 katex 配置\n</markdown>\n\n<script lang=\"ts\" setup>\nimport katex from 'katex'\n\nconst equation = `\\\\f\\\\relax{x} = \\\\int_{-\\\\infty}^\\\\infty\n    \\\\f\\\\hat\\\\xi\\\\,e^{2 \\\\pi i \\\\xi x}\n    \\\\,d\\\\xi`\n\nconst katexOptions = {\n  displayMode: true,\n  fleqn: true,\n  macros: {\n    '\\\\f': '#1f(#2)'\n  }\n}\n</script>\n\n<template>\n  <n-config-provider :katex=\"katex\">\n    <n-equation :value=\"equation\" :katex-options=\"katexOptions\" />\n  </n-config-provider>\n</template>\n"
  },
  {
    "path": "src/equation/index.ts",
    "content": "export { equationProps, Equation as NEquation } from './src/Equation'\nexport type { EquationProps } from './src/Equation'\n"
  },
  {
    "path": "src/equation/src/Equation.tsx",
    "content": "import type { KatexOptions } from 'katex'\nimport type { PropType } from 'vue'\nimport type { ExtractPublicPropTypes } from '../../_utils'\nimport type { Katex } from '../../config-provider/src/katex'\nimport { computed, defineComponent, h, inject } from 'vue'\nimport { configProviderInjectionKey } from '../../config-provider/src/context'\n\nexport const equationProps = {\n  value: String,\n  katex: Object as PropType<Katex>,\n  katexOptions: Object as PropType<KatexOptions>\n} as const\n\nexport type EquationProps = ExtractPublicPropTypes<typeof equationProps>\n\nexport const Equation = defineComponent({\n  name: 'Equation',\n  props: equationProps,\n  setup(props) {\n    const configProviderContext = inject(configProviderInjectionKey)\n    const extractedHtmlInfo = computed(() => {\n      const outerHtml\n        = (\n          props.katex || configProviderContext?.mergedKatexRef.value\n        )?.renderToString(props.value || '', {\n          throwOnError: false,\n          ...props.katexOptions\n        }) || 'no katex provided'\n      const matchResult = outerHtml.match(\n        /^<([a-z]+)[^>]+class=\"([^\"]+)\"[^>]*>/\n      )\n      const wrapperTag = matchResult?.[1] || 'span'\n      const wrapperClass = matchResult?.[2]\n      const innerHtml = outerHtml\n        .replace(/^<[a-z]+[^>]*>/, '')\n        .replace(/<\\/[a-z]+>$/, '')\n      return { wrapperTag, innerHtml, wrapperClass }\n    })\n    return () => {\n      const { innerHtml, wrapperClass, wrapperTag } = extractedHtmlInfo.value\n      return h(wrapperTag, { class: wrapperClass, innerHTML: innerHtml })\n    }\n  }\n})\n"
  },
  {
    "path": "src/equation/styles/dark.ts",
    "content": "import type { EquationTheme } from './light'\nimport { commonDark } from '../../_styles/common'\nimport { self } from './light'\n\nconst equationDark: EquationTheme = {\n  name: 'Equation',\n  common: commonDark,\n  self\n}\n\nexport default equationDark\n"
  },
  {
    "path": "src/equation/styles/index.ts",
    "content": "export { default as equationDark } from './dark'\nexport { default as equationLight } from './light'\nexport type { EquationTheme, EquationThemeVars } from './light'\n"
  },
  {
    "path": "src/equation/styles/light.ts",
    "content": "import type { Theme } from '../../_mixins'\nimport { commonLight } from '../../_styles/common'\n\nexport const self = () => ({})\n\nexport type EquationThemeVars = ReturnType<typeof self>\n\nconst equationLight: Theme<'Equation', EquationThemeVars> = {\n  name: 'Equation',\n  common: commonLight,\n  self\n}\n\nexport default equationLight\nexport type EquationTheme = typeof equationLight\n"
  },
  {
    "path": "src/flex/demos/enUS/basic.demo.vue",
    "content": "<markdown>\n# Basic\n</markdown>\n\n<template>\n  <n-flex>\n    <n-button>Oops!</n-button>\n    <n-button>Oops!</n-button>\n    <n-button>Oops!</n-button>\n    <n-button>Long! Long! Cross the line!</n-button>\n  </n-flex>\n</template>\n"
  },
  {
    "path": "src/flex/demos/enUS/center.demo.vue",
    "content": "<markdown>\n# From Center\n</markdown>\n\n<template>\n  <n-flex justify=\"center\">\n    <n-button>Oops!</n-button>\n    <n-button>Oops!</n-button>\n    <n-button>Oops!</n-button>\n  </n-flex>\n</template>\n"
  },
  {
    "path": "src/flex/demos/enUS/from-end.demo.vue",
    "content": "<markdown>\n# From End\n</markdown>\n\n<template>\n  <n-flex justify=\"end\">\n    <n-button>Oops!</n-button>\n    <n-button>Oops!</n-button>\n    <n-button>Oops!</n-button>\n  </n-flex>\n</template>\n"
  },
  {
    "path": "src/flex/demos/enUS/index.demo-entry.md",
    "content": "# Flex\n\nAvailable since `2.37.0`.\n\nFrankly saying, it functions similarly to `n-space`. However use `n-flex` if possible.\n\n`n-flex` utilizes the flex layout, and note that the gap property might have compatibility issues with some older browsers.\n\nOn the other hand, `n-space` involves operations at the `VNode` level, which could lead to rendering issues in certain specific use cases.\n\n## Demos\n\n```demo\nbasic.vue\nvertical.vue\nfrom-end.vue\nspace-between.vue\nspace-around.vue\ncenter.vue\n```\n\n## API\n\n### Flex Props\n\n| Name | Type | Default | Description | Version |\n| --- | --- | --- | --- | --- |\n| align | `string` | `undefined` | Way to align items, see [align-items](https://developer.mozilla.org/zh-CN/docs/Web/CSS/align-items). | 2.37.0 |\n| inline | `boolean` | `false` | Whether it's display is `inline-flex`. | 2.37.0 |\n| justify | `string` | `'start'` | Way to justify content, see [justify-content](https://developer.mozilla.org/zh-CN/docs/Web/CSS/justify-content). | 2.37.0 |\n| size | `'small' \\| 'medium' \\| 'large' \\| number \\| [number, number]` | `'medium'` | When it's a number, it will be used as vertical and horizontal gap, or it is `[horizontalGap, verticalGap]`. | 2.37.0 |\n| vertical | `boolean` | `false` | Whether to layout content vertically. | 2.37.0 |\n| wrap | `boolean` | `true` | Whether to wrap content if `n-flex`'s width is exceeded. | 2.37.0 |\n\n### Flex Slots\n\n| Name    | Parameters | Description      | Version |\n| ------- | ---------- | ---------------- | ------- |\n| default | `()`       | Spacing content. | 2.37.0  |\n"
  },
  {
    "path": "src/flex/demos/enUS/space-around.demo.vue",
    "content": "<markdown>\n# Space Around\n</markdown>\n\n<template>\n  <n-flex justify=\"space-around\" size=\"large\">\n    <n-button>Oops!</n-button>\n    <n-button>Oops!</n-button>\n    <n-button>Oops!</n-button>\n  </n-flex>\n</template>\n"
  },
  {
    "path": "src/flex/demos/enUS/space-between.demo.vue",
    "content": "<markdown>\n# Space Between\n</markdown>\n\n<template>\n  <n-flex justify=\"space-between\">\n    <n-button>Oops!</n-button>\n    <n-button>Oops!</n-button>\n    <n-button>Oops!</n-button>\n  </n-flex>\n</template>\n"
  },
  {
    "path": "src/flex/demos/enUS/vertical.demo.vue",
    "content": "<markdown>\n# Vertical\n</markdown>\n\n<template>\n  <n-flex vertical>\n    <n-button>Oops!</n-button>\n    <n-button>Oops!</n-button>\n    <n-button>Oops!</n-button>\n  </n-flex>\n</template>\n"
  },
  {
    "path": "src/flex/demos/zhCN/basic.demo.vue",
    "content": "<markdown>\n# 基础用法\n</markdown>\n\n<template>\n  <n-flex>\n    <n-button>Oops!</n-button>\n    <n-button>Oops!</n-button>\n    <n-button>Oops!</n-button>\n    <n-button>Long! Long! Cross the line!</n-button>\n  </n-flex>\n</template>\n"
  },
  {
    "path": "src/flex/demos/zhCN/center.demo.vue",
    "content": "<markdown>\n# 从中间\n</markdown>\n\n<template>\n  <n-flex justify=\"center\">\n    <n-button>Oops!</n-button>\n    <n-button>Oops!</n-button>\n    <n-button>Oops!</n-button>\n  </n-flex>\n</template>\n"
  },
  {
    "path": "src/flex/demos/zhCN/from-end.demo.vue",
    "content": "<markdown>\n# 从尾部\n</markdown>\n\n<template>\n  <n-flex justify=\"end\">\n    <n-button>Oops!</n-button>\n    <n-button>Oops!</n-button>\n    <n-button>Oops!</n-button>\n  </n-flex>\n</template>\n"
  },
  {
    "path": "src/flex/demos/zhCN/grid-debug.demo.vue",
    "content": "<markdown>\n# Grid Debug\n</markdown>\n\n<template>\n  <n-flex vertical>\n    <div class=\"grid-list\">\n      <div class=\"item\" />\n      <div class=\"item\" />\n      <div class=\"item\" />\n    </div>\n    <div class=\"grid-list\">\n      <div class=\"item\" />\n      <div class=\"item\" />\n      <div class=\"item\" />\n    </div>\n  </n-flex>\n</template>\n\n<style>\n.grid-list {\n  display: grid;\n  grid-template-columns: repeat(auto-fill, 100px);\n  gap: 20px;\n}\n.item {\n  background-color: tomato;\n  height: 100px;\n}\n</style>\n"
  },
  {
    "path": "src/flex/demos/zhCN/index.demo-entry.md",
    "content": "# 弹性布局 Flex\n\n自 `2.37.0` 开始提供。\n\n实话讲用起来和 `n-space` 差不多，但是能用 `n-flex` 就不要用 `n-space`。\n\n`n-flex` 使用 `flex` 布局，其中 `gap` 属性可能对某些老浏览器兼容性不好。\n\n`n-space` 会进行 `VNode` 级别的操作，可能在某些特殊用例下出现一些渲染问题。\n\n## 演示\n\n```demo\nbasic.vue\nvertical.vue\nfrom-end.vue\nspace-between.vue\nspace-around.vue\ncenter.vue\ngrid-debug.vue\nrtl-debug.vue\n```\n\n## API\n\n### Flex Props\n\n| 名称 | 类型 | 默认值 | 说明 | 版本 |\n| --- | --- | --- | --- | --- |\n| align | `string` | `undefined` | 垂直排列方式，参考 [align-items](https://developer.mozilla.org/zh-CN/docs/Web/CSS/align-items) | 2.37.0 |\n| inline | `boolean` | `false` | 是否为行内元素 | 2.37.0 |\n| justify | `string` | `'start'` | 水平排列方式，参考 [justify-content](https://developer.mozilla.org/zh-CN/docs/Web/CSS/justify-content) | 2.37.0 |\n| size | `'small' \\| 'medium' \\| 'large' \\| number \\| [number, number]` | `'medium'` | 为数字时，是水平和垂直间距；为数组时，是 [水平间距, 垂直间距] | 2.37.0 |\n| vertical | `boolean` | `false` | 是否垂直布局 | 2.37.0 |\n| wrap | `boolean` | `true` | 是否超出换行 | 2.37.0 |\n\n### Flex Slots\n\n| 名称    | 参数 | 说明 | 版本   |\n| ------- | ---- | ---- | ------ |\n| default | `()` | 内容 | 2.37.0 |\n"
  },
  {
    "path": "src/flex/demos/zhCN/rtl-debug.demo.vue",
    "content": "<markdown>\n# Rtl Debug\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { unstableSpaceRtl } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst rtlEnabled = ref(false)\nconst rtlStyles = [unstableSpaceRtl]\n</script>\n\n<template>\n  <n-flex vertical>\n    <n-flex><n-switch v-model:value=\"rtlEnabled\" />Rtl</n-flex>\n    <n-config-provider :rtl=\"rtlEnabled ? rtlStyles : undefined\">\n      <n-flex>\n        <n-button>Oops!</n-button>\n        <n-button>Oops!</n-button>\n        <n-button>Long! Long! Cross the line!</n-button>\n      </n-flex>\n    </n-config-provider>\n  </n-flex>\n</template>\n"
  },
  {
    "path": "src/flex/demos/zhCN/space-around.demo.vue",
    "content": "<markdown>\n# 空间围绕\n</markdown>\n\n<template>\n  <n-flex justify=\"space-around\" size=\"large\">\n    <n-button>Oops!</n-button>\n    <n-button>Oops!</n-button>\n    <n-button>Oops!</n-button>\n  </n-flex>\n</template>\n"
  },
  {
    "path": "src/flex/demos/zhCN/space-between.demo.vue",
    "content": "<markdown>\n# 间隙\n</markdown>\n\n<template>\n  <n-flex justify=\"space-between\">\n    <n-button>Oops!</n-button>\n    <n-button>Oops!</n-button>\n    <n-button>Oops!</n-button>\n  </n-flex>\n</template>\n"
  },
  {
    "path": "src/flex/demos/zhCN/vertical.demo.vue",
    "content": "<markdown>\n# 垂直\n</markdown>\n\n<template>\n  <n-flex vertical>\n    <n-button>Oops!</n-button>\n    <n-button>Oops!</n-button>\n    <n-button>Oops!</n-button>\n  </n-flex>\n</template>\n"
  },
  {
    "path": "src/flex/index.ts",
    "content": "export { flexProps, default as NFlex } from './src/Flex'\nexport type { FlexProps } from './src/Flex'\nexport type { FlexAlign, FlexJustify } from './src/type'\n"
  },
  {
    "path": "src/flex/src/Flex.tsx",
    "content": "import type { PropType } from 'vue'\nimport type { ThemeProps } from '../../_mixins'\nimport type { ExtractPublicPropTypes } from '../../_utils'\nimport type { FlexTheme } from '../styles'\nimport type { FlexAlign, FlexJustify } from './type'\nimport { depx, getGap } from 'seemly'\nimport { computed, defineComponent, h } from 'vue'\nimport { useConfig, useTheme } from '../../_mixins'\nimport { useRtl } from '../../_mixins/use-rtl'\nimport { createKey, flatten, getSlot } from '../../_utils'\nimport { flexLight } from '../styles'\n\nexport const flexProps = {\n  ...(useTheme.props as ThemeProps<FlexTheme>),\n  align: String as PropType<FlexAlign>,\n  justify: {\n    type: String as PropType<FlexJustify>,\n    default: 'start'\n  },\n  inline: Boolean,\n  vertical: Boolean,\n  reverse: Boolean,\n  size: {\n    type: [String, Number, Array] as PropType<\n      'small' | 'medium' | 'large' | number | [number, number]\n    >,\n    default: 'medium'\n  },\n  wrap: {\n    type: Boolean,\n    default: true\n  }\n} as const\n\nexport type FlexProps = ExtractPublicPropTypes<typeof flexProps>\n\nexport default defineComponent({\n  name: 'Flex',\n  props: flexProps,\n  setup(props) {\n    const { mergedClsPrefixRef, mergedRtlRef } = useConfig(props)\n    const themeRef = useTheme(\n      'Flex',\n      '-flex',\n      undefined,\n      flexLight,\n      props,\n      mergedClsPrefixRef\n    )\n    const rtlEnabledRef = useRtl('Flex', mergedRtlRef, mergedClsPrefixRef)\n    return {\n      rtlEnabled: rtlEnabledRef,\n      mergedClsPrefix: mergedClsPrefixRef,\n      margin: computed<{ horizontal: number, vertical: number }>(() => {\n        const { size } = props\n        if (Array.isArray(size)) {\n          return {\n            horizontal: size[0],\n            vertical: size[1]\n          }\n        }\n        if (typeof size === 'number') {\n          return {\n            horizontal: size,\n            vertical: size\n          }\n        }\n        const {\n          self: { [createKey('gap', size)]: gap }\n        } = themeRef.value\n        const { row, col } = getGap(gap)\n        return {\n          horizontal: depx(col),\n          vertical: depx(row)\n        }\n      })\n    }\n  },\n  render() {\n    const {\n      vertical,\n      reverse,\n      align,\n      inline,\n      justify,\n      margin,\n      wrap,\n      mergedClsPrefix,\n      rtlEnabled\n    } = this\n    const children = flatten(getSlot(this), false)\n    if (!children.length)\n      return null\n    return (\n      <div\n        role=\"none\"\n        class={[\n          `${mergedClsPrefix}-flex`,\n          rtlEnabled && `${mergedClsPrefix}-flex--rtl`\n        ]}\n        style={{\n          display: inline ? 'inline-flex' : 'flex',\n          flexDirection: (() => {\n            if (vertical && !reverse)\n              return 'column'\n            if (vertical && reverse)\n              return 'column-reverse'\n            if (!vertical && reverse)\n              return 'row-reverse'\n            else return 'row'\n          })(),\n          justifyContent: justify,\n          flexWrap: !wrap || vertical ? 'nowrap' : 'wrap',\n          alignItems: align,\n          gap: `${margin.vertical}px ${margin.horizontal}px`\n        }}\n      >\n        {children}\n      </div>\n    )\n  }\n})\n"
  },
  {
    "path": "src/flex/src/styles/rtl.cssr.ts",
    "content": "import { cB, cM } from '../../../_utils/cssr'\n\nexport default cB('space', [\n  cM('rtl', `\n    direction: rtl;\n  `)\n])\n"
  },
  {
    "path": "src/flex/src/type.ts",
    "content": "import type { Property } from 'csstype'\n\nexport type FlexAlign = Property.AlignItems\n\nexport type FlexJustify = Property.JustifyContent\n"
  },
  {
    "path": "src/flex/styles/_common.ts",
    "content": "export default {\n  gapSmall: '4px 8px',\n  gapMedium: '8px 12px',\n  gapLarge: '12px 16px'\n}\n"
  },
  {
    "path": "src/flex/styles/dark.ts",
    "content": "import type { FlexTheme } from './light'\nimport commonVars from './_common'\n\nconst flexDark: FlexTheme = {\n  name: 'Flex',\n  self() {\n    return commonVars\n  }\n}\n\nexport default flexDark\n"
  },
  {
    "path": "src/flex/styles/index.ts",
    "content": "export { default as flexDark } from './dark'\nexport { default as flexLight } from './light'\nexport type { FlexTheme, FlexThemeVars } from './light'\nexport { flexRtl } from './rtl'\n"
  },
  {
    "path": "src/flex/styles/light.ts",
    "content": "import type { Theme } from '../../_mixins'\nimport commonVars from './_common'\n\nfunction self() {\n  return commonVars\n}\n\nexport type FlexThemeVars = ReturnType<typeof self>\n\nconst flexLight: Theme<'Flex', FlexThemeVars> = {\n  name: 'Flex',\n  self\n}\n\nexport default flexLight\nexport type FlexTheme = typeof flexLight\n"
  },
  {
    "path": "src/flex/styles/rtl.ts",
    "content": "import type { RtlItem } from '../../config-provider/src/internal-interface'\nimport rtlStyle from '../src/styles/rtl.cssr'\n\nexport const flexRtl: RtlItem = {\n  name: 'Flex',\n  style: rtlStyle\n}\n"
  },
  {
    "path": "src/flex/tests/Flex.spec.tsx",
    "content": "import type { VueWrapper } from '@vue/test-utils'\nimport { mount } from '@vue/test-utils'\nimport { createCommentVNode, Fragment, h } from 'vue'\nimport { NFlex } from '../index'\n\nfunction getChildrenNode(wrapper: VueWrapper<any>): any[] {\n  return Array.from(wrapper.find('.n-flex').element.childNodes)\n}\n\ndescribe('n-flex', () => {\n  it('should work with import on demand', () => {\n    mount(NFlex)\n  })\n\n  it('render empty children', () => {\n    const wrapper = mount({\n      render() {\n        return <NFlex />\n      }\n    })\n    expect(wrapper.find('.n-flex').exists()).toBe(false)\n    expect(wrapper.html()).toMatchSnapshot()\n    wrapper.unmount()\n  })\n\n  it('render flex string size', () => {\n    const wrapper = mount({\n      render() {\n        return <NFlex size=\"large\">{{ default: () => 'kirby' }}</NFlex>\n      }\n    })\n    expect(wrapper.attributes('style')).toContain('gap')\n    expect(wrapper.html()).toMatchSnapshot()\n    wrapper.unmount()\n  })\n\n  it('render vertical flex', () => {\n    const wrapper = mount({\n      render() {\n        return (\n          <NFlex vertical>\n            {{\n              default: () => [<div>1</div>, <div>2</div>]\n            }}\n          </NFlex>\n        )\n      }\n    })\n    expect(wrapper.attributes('style')).toContain('flex-direction: column;')\n    expect(wrapper.html()).toMatchSnapshot()\n    wrapper.unmount()\n  })\n\n  it('should work with `inline` prop', () => {\n    const wrapper = mount(NFlex, {\n      props: {\n        inline: true\n      },\n      slots: {\n        default: () => '07akioni'\n      }\n    })\n\n    expect(wrapper.attributes('style')).toContain('display: inline-flex;')\n    wrapper.unmount()\n  })\n\n  it('should render with invalidElement', () => {\n    const wrapper = mount({\n      render() {\n        return (\n          <NFlex>\n            {{\n              default: () => (\n                <>\n                  text1\n                  <span>text1</span>\n                  text1\n                </>\n              )\n            }}\n          </NFlex>\n        )\n      }\n    })\n\n    const childNodes = getChildrenNode(wrapper)\n    expect(childNodes.length).toBe(3)\n    expect(wrapper.html()).toMatchSnapshot()\n    wrapper.unmount()\n  })\n\n  it('should not render comment node', () => {\n    const wrapper = mount({\n      render() {\n        return <NFlex>{{ default: () => false && 'div' }}</NFlex>\n      }\n    })\n    expect(wrapper.html()).toMatchSnapshot()\n    const childNodes = getChildrenNode(wrapper)\n    expect(childNodes.length).toEqual(1) // Comment node\n  })\n\n  it('should work with `wrap` prop', async () => {\n    const wrapper = mount(NFlex, {\n      slots: { default: () => [<div>1</div>, <div>2</div>] }\n    })\n    expect(wrapper.find('.n-flex').attributes('style')).toContain(\n      'flex-wrap: wrap'\n    )\n\n    await wrapper.setProps({ wrap: false })\n    expect(wrapper.find('.n-flex').attributes('style')).toContain(\n      'flex-wrap: nowrap'\n    )\n    wrapper.unmount()\n  })\n\n  it('should render while slot is Comment', () => {\n    const wrapper = mount({\n      render() {\n        return (\n          <NFlex>\n            {{\n              default: () => createCommentVNode('random comment text')\n            }}\n          </NFlex>\n        )\n      }\n    })\n    const childNodes = getChildrenNode(wrapper)\n    expect(childNodes.length).toEqual(1)\n    expect(wrapper.html()).toMatchSnapshot()\n    wrapper.unmount()\n  })\n})\n"
  },
  {
    "path": "src/flex/tests/__snapshots__/Flex.spec.tsx.snap",
    "content": "// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html\n\nexports[`n-flex > render empty children 1`] = `\"\"`;\n\nexports[`n-flex > render flex string size 1`] = `\"<div role=\"none\" class=\"n-flex\" style=\"display: flex; flex-direction: row; justify-content: start; flex-wrap: wrap; gap: 12px 16px;\">kirby</div>\"`;\n\nexports[`n-flex > render vertical flex 1`] = `\n\"<div role=\"none\" class=\"n-flex\" style=\"display: flex; flex-direction: column; justify-content: start; flex-wrap: nowrap; gap: 8px 12px;\">\n  <div>1</div>\n  <div>2</div>\n</div>\"\n`;\n\nexports[`n-flex > should not render comment node 1`] = `\n\"<div role=\"none\" class=\"n-flex\" style=\"display: flex; flex-direction: row; justify-content: start; flex-wrap: wrap; gap: 8px 12px;\">\n  <!---->\n</div>\"\n`;\n\nexports[`n-flex > should render while slot is Comment 1`] = `\n\"<div role=\"none\" class=\"n-flex\" style=\"display: flex; flex-direction: row; justify-content: start; flex-wrap: wrap; gap: 8px 12px;\">\n  <!--random comment text-->\n</div>\"\n`;\n\nexports[`n-flex > should render with invalidElement 1`] = `\"<div role=\"none\" class=\"n-flex\" style=\"display: flex; flex-direction: row; justify-content: start; flex-wrap: wrap; gap: 8px 12px;\">text1<span>text1</span>text1</div>\"`;\n"
  },
  {
    "path": "src/flex/tests/server.spec.tsx",
    "content": "import { setup } from '@css-render/vue3-ssr'\nimport { renderToString } from '@vue/server-renderer'\n/**\n * @vitest-environment node\n */\nimport { createSSRApp, h } from 'vue'\nimport { NFlex } from '../..'\n\ndescribe('server side rendering', () => {\n  it('works', async () => {\n    const app = createSSRApp(() => <NFlex />)\n    setup(app)\n    try {\n      await renderToString(app)\n    }\n    catch (e) {\n      expect(e).not.toBeTruthy()\n    }\n  })\n})\n"
  },
  {
    "path": "src/float-button/demos/enUS/badge.demo.vue",
    "content": "<markdown>\n# Badge\n\nYou can put a hover button with the number of badges on any element.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { AlarmOutline as AlarmOutlineIcon } from '@vicons/ionicons5'\n</script>\n\n<template>\n  <n-flex>\n    <n-float-button position=\"relative\">\n      <n-badge :value=\"9\" :offset=\"[6, -8]\">\n        <n-icon>\n          <AlarmOutlineIcon />\n        </n-icon>\n      </n-badge>\n    </n-float-button>\n    <n-float-button position=\"relative\">\n      <n-badge :value=\"100\" :max=\"99\" :offset=\"[6, -8]\">\n        <n-icon>\n          <AlarmOutlineIcon />\n        </n-icon>\n      </n-badge>\n    </n-float-button>\n    <n-float-button position=\"relative\">\n      <n-badge dot :offset=\"[4, -4]\">\n        <n-icon>\n          <AlarmOutlineIcon />\n        </n-icon>\n      </n-badge>\n    </n-float-button>\n    <n-float-button position=\"relative\">\n      <n-badge dot :offset=\"[4, -4]\">\n        <n-icon>\n          <AlarmOutlineIcon />\n        </n-icon>\n      </n-badge>\n    </n-float-button>\n    <n-float-button position=\"relative\">\n      <n-badge value=\"新\" :offset=\"[6, -6]\">\n        <n-icon>\n          <AlarmOutlineIcon />\n        </n-icon>\n      </n-badge>\n    </n-float-button>\n    <n-float-button position=\"relative\">\n      <n-badge :value=\"9\" :offset=\"[6, -8]\">\n        <n-icon>\n          <AlarmOutlineIcon />\n        </n-icon>\n      </n-badge>\n    </n-float-button>\n  </n-flex>\n</template>\n"
  },
  {
    "path": "src/float-button/demos/enUS/basic.demo.vue",
    "content": "<markdown>\n# Basic\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { CashOutline as CashIcon } from '@vicons/ionicons5'\n</script>\n\n<template>\n  <div style=\"height: 200px; transform: translate(0)\">\n    <n-float-button :right=\"0\" :bottom=\"0\" shape=\"square\">\n      <n-icon>\n        <CashIcon />\n      </n-icon>\n    </n-float-button>\n    <n-float-button :left=\"0\" :bottom=\"0\" shape=\"square\">\n      <n-icon>\n        <CashIcon />\n      </n-icon>\n    </n-float-button>\n    <n-float-button :right=\"0\" :top=\"0\">\n      <n-icon>\n        <CashIcon />\n      </n-icon>\n    </n-float-button>\n    <n-float-button :left=\"0\" :top=\"0\">\n      <n-icon>\n        <CashIcon />\n      </n-icon>\n    </n-float-button>\n  </div>\n</template>\n"
  },
  {
    "path": "src/float-button/demos/enUS/custom.demo.vue",
    "content": "<markdown>\n# Description\n\nShow description on float button.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { Document as DocumentIcon } from '@vicons/ionicons5'\n</script>\n\n<template>\n  <div style=\"height: 120px; transform: translate(0)\">\n    <n-float-button shape=\"square\">\n      <n-icon>\n        <DocumentIcon />\n      </n-icon>\n      <template #description>\n        Docs\n      </template>\n    </n-float-button>\n    <n-float-button :left=\"60\" shape=\"square\">\n      <template #description>\n        Docs\n      </template>\n    </n-float-button>\n    <n-float-button :left=\"120\" shape=\"square\">\n      <n-icon>\n        <DocumentIcon />\n      </n-icon>\n      <template #description>\n        Long Long Docs\n      </template>\n    </n-float-button>\n  </div>\n</template>\n"
  },
  {
    "path": "src/float-button/demos/enUS/group.demo.vue",
    "content": "<markdown>\n  # Float Button Group\n\n  Elements can be arbitrarily combined to achieve more functionality.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { CashOutline as CashIcon } from '@vicons/ionicons5'\n</script>\n\n<template>\n  <n-flex align=\"flex-start\">\n    <n-float-button-group shape=\"square\" position=\"relative\">\n      <n-float-button>\n        <n-icon><CashIcon /></n-icon>\n      </n-float-button>\n      <n-float-button>\n        <n-icon><CashIcon /></n-icon>\n      </n-float-button>\n      <n-float-button>\n        <n-icon><CashIcon /></n-icon>\n      </n-float-button>\n      <n-float-button>\n        <n-icon><CashIcon /></n-icon>\n      </n-float-button>\n    </n-float-button-group>\n    <n-float-button-group position=\"relative\">\n      <n-float-button>\n        <n-icon><CashIcon /></n-icon>\n      </n-float-button>\n      <n-float-button>\n        <n-icon><CashIcon /></n-icon>\n      </n-float-button>\n      <n-float-button>\n        <n-icon><CashIcon /></n-icon>\n      </n-float-button>\n      <n-float-button>\n        <n-icon><CashIcon /></n-icon>\n      </n-float-button>\n    </n-float-button-group>\n    <n-float-button-group />\n  </n-flex>\n</template>\n"
  },
  {
    "path": "src/float-button/demos/enUS/index.demo-entry.md",
    "content": "# Float Button\n\nLike `BackTop` but with more appearance level, more interaction.\n\nAvailable since `2.38.0`.\n\n## Demos\n\n```demo\nbasic.vue\nbadge.vue\ntooltip.vue\ncustom.vue\ngroup.vue\nmenu.vue\n```\n\n## API\n\n### FloatButton Props\n\n| Name | Type | Default | Description | Version |\n| --- | --- | --- | --- | --- |\n| bottom | `number \\| string` | `40` | CSS `bottom` property of the button group. | 2.38.0 |\n| height | `number \\| string` | `40` | CSS `height` property of the button group. | 2.38.0 |\n| left | `number \\| string` | `undefined` | CSS `left` property of the button group. | 2.38.0 |\n| menu-trigger | `'click' \\| 'hover'` | `undefined` | Trigger action to show submenu. | 2.38.0 |\n| position | `'relative' \\| 'absolute' \\| 'fixed'` | `'fixed'` | CSS `position` property of the button group. | 2.38.0 |\n| right | `number \\| string` | `undefined` | CSS `right` property of the button group. | 2.38.0 |\n| shape | `'circle' \\| 'square'` | `'circle'` | Shape of the button. | 2.38.0 |\n| show-menu | `boolean` | `undefined` | Whether submenu of the button is shown. | 2.38.0 |\n| top | `number \\| string` | `undefined` | CSS `top` property of the button group. | 2.38.0 |\n| type | `'default' \\| 'primary'` | `'default'` | Type of the button. | 2.38.0 |\n| width | `number \\| string` | `undefined` |  | 2.38.0 |\n| on-update:show-menu | `(value: boolean) => void` | `undefined` | Callback when the menu is opened or closed. | 2.38.0 |\n\n### FloatButtonGroup Props\n\n| Name | Type | Default | Description | Version |\n| --- | --- | --- | --- | --- |\n| bottom | `number \\| string` | `undefined` | CSS `bottom` property of the button group. | 2.38.0 |\n| left | `number \\| string` | `undefined` | CSS `left` property of the button group. | 2.38.0 |\n| position | `'relative' \\| 'absolute' \\| 'fixed'` | `'fixed'` | CSS `position` property of the button group. | 2.38.0 |\n| right | `number \\| string` | `undefined` | CSS `right` property of the button group. | 2.38.0 |\n| shape | `'circle' \\| 'square'` | `'circle'` | Shape of the button group. | 2.38.0 |\n| top | `number \\| string` | `undefined` | CSS `top` property of the button group. | 2.38.0 |\n\n### FloatButton Slots\n\n| Name        | Parameters | Description                  | Version |\n| ----------- | ---------- | ---------------------------- | ------- |\n| description | `()`       | Description for the button.  | 2.38.0  |\n| menu        | `()`       | Submenu of the float button. | 2.38.0  |\n"
  },
  {
    "path": "src/float-button/demos/enUS/menu.demo.vue",
    "content": "<markdown>\n# Show menu\n\nAfter `menu-trigger` is set, more `n-float-button` can be folded into one `n-float-button`.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { CashOutline as CashIcon } from '@vicons/ionicons5'\n</script>\n\n<template>\n  <n-flex>\n    <n-float-button position=\"relative\" type=\"primary\" menu-trigger=\"hover\">\n      <n-icon>\n        <CashIcon />\n      </n-icon>\n      <template #menu>\n        <n-float-button shape=\"square\" type=\"primary\">\n          <n-icon>\n            <CashIcon />\n          </n-icon>\n        </n-float-button>\n        <n-float-button>\n          <n-icon>\n            <CashIcon />\n          </n-icon>\n        </n-float-button>\n        <n-float-button>\n          <n-icon>\n            <CashIcon />\n          </n-icon>\n        </n-float-button>\n      </template>\n    </n-float-button>\n    <n-float-button position=\"relative\" type=\"primary\" menu-trigger=\"click\">\n      <n-icon>\n        <CashIcon />\n      </n-icon>\n      <template #menu>\n        <n-float-button shape=\"square\" type=\"primary\">\n          <n-icon>\n            <CashIcon />\n          </n-icon>\n        </n-float-button>\n        <n-float-button>\n          <n-icon>\n            <CashIcon />\n          </n-icon>\n        </n-float-button>\n        <n-float-button>\n          <n-icon>\n            <CashIcon />\n          </n-icon>\n        </n-float-button>\n      </template>\n    </n-float-button>\n  </n-flex>\n</template>\n"
  },
  {
    "path": "src/float-button/demos/enUS/tooltip.demo.vue",
    "content": "<markdown>\n# Tooltip\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { CashOutline as CashIcon } from '@vicons/ionicons5'\n</script>\n\n<template>\n  <n-tooltip trigger=\"hover\" placement=\"right\">\n    <template #trigger>\n      <n-float-button position=\"relative\">\n        <n-icon>\n          <CashIcon />\n        </n-icon>\n      </n-float-button>\n    </template>\n    Lpsum\n  </n-tooltip>\n</template>\n"
  },
  {
    "path": "src/float-button/demos/zhCN/badge.demo.vue",
    "content": "<markdown>\n  # 徽章\n\n  带有徽章数的悬浮按钮\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { AlarmOutline as AlarmOutlineIcon } from '@vicons/ionicons5'\n</script>\n\n<template>\n  <n-flex>\n    <n-float-button position=\"relative\">\n      <n-badge :value=\"9\" :offset=\"[6, -8]\">\n        <n-icon>\n          <AlarmOutlineIcon />\n        </n-icon>\n      </n-badge>\n    </n-float-button>\n    <n-float-button position=\"relative\">\n      <n-badge :value=\"100\" :max=\"99\" :offset=\"[6, -8]\">\n        <n-icon>\n          <AlarmOutlineIcon />\n        </n-icon>\n      </n-badge>\n    </n-float-button>\n    <n-float-button position=\"relative\">\n      <n-badge dot :offset=\"[4, -4]\">\n        <n-icon>\n          <AlarmOutlineIcon />\n        </n-icon>\n      </n-badge>\n    </n-float-button>\n    <n-float-button position=\"relative\">\n      <n-badge dot :offset=\"[4, -4]\">\n        <n-icon>\n          <AlarmOutlineIcon />\n        </n-icon>\n      </n-badge>\n    </n-float-button>\n    <n-float-button position=\"relative\">\n      <n-badge value=\"新\" :offset=\"[6, -6]\">\n        <n-icon>\n          <AlarmOutlineIcon />\n        </n-icon>\n      </n-badge>\n    </n-float-button>\n    <n-float-button position=\"relative\">\n      <n-badge :value=\"9\" :offset=\"[6, -8]\">\n        <n-icon>\n          <AlarmOutlineIcon />\n        </n-icon>\n      </n-badge>\n    </n-float-button>\n  </n-flex>\n</template>\n"
  },
  {
    "path": "src/float-button/demos/zhCN/basic.demo.vue",
    "content": "<markdown>\n  # 基础用法\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { CashOutline as CashIcon } from '@vicons/ionicons5'\n</script>\n\n<template>\n  <div style=\"height: 200px; transform: translate(0)\">\n    <n-float-button :right=\"0\" :bottom=\"0\" shape=\"square\">\n      <n-icon>\n        <CashIcon />\n      </n-icon>\n    </n-float-button>\n    <n-float-button :left=\"0\" :bottom=\"0\" shape=\"square\" type=\"primary\">\n      <n-icon>\n        <CashIcon />\n      </n-icon>\n    </n-float-button>\n    <n-float-button :right=\"0\" :top=\"0\">\n      <n-icon>\n        <CashIcon />\n      </n-icon>\n    </n-float-button>\n    <n-float-button :left=\"0\" :top=\"0\" type=\"primary\">\n      <n-icon>\n        <CashIcon />\n      </n-icon>\n    </n-float-button>\n  </div>\n</template>\n"
  },
  {
    "path": "src/float-button/demos/zhCN/custom.demo.vue",
    "content": "<markdown>\n# 描述\n\n在 `n-float-button` 上展示描述信息。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { Document as DocumentIcon } from '@vicons/ionicons5'\n</script>\n\n<template>\n  <div style=\"height: 120px; transform: translate(0)\">\n    <n-float-button shape=\"square\">\n      <n-icon>\n        <DocumentIcon />\n      </n-icon>\n      <template #description>\n        文档\n      </template>\n    </n-float-button>\n    <n-float-button :left=\"60\" shape=\"square\">\n      <template #description>\n        文档\n      </template>\n    </n-float-button>\n    <n-float-button :left=\"120\" shape=\"square\">\n      <n-icon>\n        <DocumentIcon />\n      </n-icon>\n      <template #description>\n        很长很长的文档\n      </template>\n    </n-float-button>\n  </div>\n</template>\n"
  },
  {
    "path": "src/float-button/demos/zhCN/group.demo.vue",
    "content": "<markdown>\n  # 浮动按钮组\n\n  可以任意组合元素，实现更多的功能。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { CashOutline as CashIcon } from '@vicons/ionicons5'\n</script>\n\n<template>\n  <n-flex align=\"flex-start\">\n    <n-float-button-group shape=\"square\" position=\"relative\">\n      <n-float-button>\n        <n-icon><CashIcon /></n-icon>\n      </n-float-button>\n      <n-float-button>\n        <n-icon><CashIcon /></n-icon>\n      </n-float-button>\n      <n-float-button>\n        <n-icon><CashIcon /></n-icon>\n      </n-float-button>\n      <n-float-button>\n        <n-icon><CashIcon /></n-icon>\n      </n-float-button>\n    </n-float-button-group>\n    <n-float-button-group position=\"relative\">\n      <n-float-button>\n        <n-icon><CashIcon /></n-icon>\n      </n-float-button>\n      <n-float-button>\n        <n-icon><CashIcon /></n-icon>\n      </n-float-button>\n      <n-float-button>\n        <n-icon><CashIcon /></n-icon>\n      </n-float-button>\n      <n-float-button>\n        <n-icon><CashIcon /></n-icon>\n      </n-float-button>\n    </n-float-button-group>\n  </n-flex>\n</template>\n"
  },
  {
    "path": "src/float-button/demos/zhCN/index.demo-entry.md",
    "content": "# 浮动按钮 Float Button\n\n跟 `Back Top` 很像，多一份颜值，多一份互动。\n\n自 `2.38.0` 开始提供。\n\n## 演示\n\n```demo\nbasic.vue\nbadge.vue\ntooltip.vue\ncustom.vue\ngroup.vue\nmenu.vue\n```\n\n## API\n\n### FloatButton Props\n\n| 名称 | 类型 | 默认值 | 说明 | 版本 |\n| --- | --- | --- | --- | --- |\n| bottom | `number \\| string` | `40` | 按钮的 CSS `bottom` 属性 | 2.38.0 |\n| height | `number \\| string` | `40` | 按钮的 CSS `height` 属性 | 2.38.0 |\n| left | `number \\| string` | `undefined` | 按钮的 CSS `left` 属性 | 2.38.0 |\n| menu-trigger | `'click' \\| 'hover'` | `undefined` | 触发菜单显示的方式 | 2.38.0 |\n| position | `'relative' \\| 'absolute' \\| 'fixed'` | `'fixed'` | 按钮组的定位方式 | 2.38.0 |\n| right | `number \\| string` | `undefined` | 按钮的 CSS `right` 属性 | 2.38.0 |\n| shape | `'circle' \\| 'square'` | `'circle'` | 按钮的形状 | 2.38.0 |\n| show-menu | `boolean` | `undefined` | 是否打开菜单 | 2.38.0 |\n| top | `number \\| string` | `undefined` | 按钮的 CSS `top` 属性 | 2.38.0 |\n| type | `'default' \\| 'primary'` | `'default'` | 按钮的类型 | 2.38.0 |\n| width | `number \\| string` | `undefined` | 按钮的 CSS `width` 属性 | 2.38.0 |\n| on-update:show-menu | `(value: boolean) => void` | `undefined` | 菜单打开或者关闭的回调 | 2.38.0 |\n\n### FloatButtonGroup Props\n\n| 名称 | 类型 | 默认值 | 说明 | 版本 |\n| --- | --- | --- | --- | --- |\n| bottom | `number \\| string` | `undefined` | 按钮组的 CSS `bottom` 属性 | 2.38.0 |\n| left | `number \\| string` | `undefined` | 按钮组的 CSS `left` 属性 | 2.38.0 |\n| position | `'relative' \\| 'absolute' \\| 'fixed'` | `'fixed'` | 按钮组的定位方式 | 2.38.0 |\n| right | `number \\| string` | `undefined` | 按钮组的 CSS `right` 属性 | 2.38.0 |\n| shape | `'circle' \\| 'square'` | `'circle'` | 按钮组的形状 | 2.38.0 |\n| top | `number \\| string` | `undefined` | 按钮组的 CSS `top` 属性 | 2.38.0 |\n\n### FloatButton Slots\n\n| 名称        | 参数 | 说明               | 版本   |\n| ----------- | ---- | ------------------ | ------ |\n| description | `()` | 按钮中的描述信息   | 2.38.0 |\n| menu        | `()` | 按钮会触发的子菜单 | 2.38.0 |\n"
  },
  {
    "path": "src/float-button/demos/zhCN/menu.demo.vue",
    "content": "<markdown>\n# 菜单显示\n\n设定 `menu-trigger` 后，更多的 `n-float-button` 可被折叠于一个 `n-float-button` 中。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { CashOutline as CashIcon } from '@vicons/ionicons5'\n</script>\n\n<template>\n  <n-flex>\n    <n-float-button position=\"relative\" type=\"primary\" menu-trigger=\"hover\">\n      <n-icon>\n        <CashIcon />\n      </n-icon>\n      <template #menu>\n        <n-float-button shape=\"square\" type=\"primary\">\n          <n-icon>\n            <CashIcon />\n          </n-icon>\n        </n-float-button>\n        <n-float-button>\n          <n-icon>\n            <CashIcon />\n          </n-icon>\n        </n-float-button>\n        <n-float-button>\n          <n-icon>\n            <CashIcon />\n          </n-icon>\n        </n-float-button>\n      </template>\n    </n-float-button>\n    <n-float-button position=\"relative\" type=\"primary\" menu-trigger=\"click\">\n      <n-icon>\n        <CashIcon />\n      </n-icon>\n      <template #menu>\n        <n-float-button shape=\"square\" type=\"primary\">\n          <n-icon>\n            <CashIcon />\n          </n-icon>\n        </n-float-button>\n        <n-float-button>\n          <n-icon>\n            <CashIcon />\n          </n-icon>\n        </n-float-button>\n        <n-float-button>\n          <n-icon>\n            <CashIcon />\n          </n-icon>\n        </n-float-button>\n      </template>\n    </n-float-button>\n  </n-flex>\n</template>\n"
  },
  {
    "path": "src/float-button/demos/zhCN/tooltip.demo.vue",
    "content": "<markdown>\n# 气泡提示\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { CashOutline as CashIcon } from '@vicons/ionicons5'\n</script>\n\n<template>\n  <n-tooltip trigger=\"hover\" placement=\"right\">\n    <template #trigger>\n      <n-float-button position=\"relative\">\n        <n-icon>\n          <CashIcon />\n        </n-icon>\n      </n-float-button>\n    </template>\n    这个故事还没有完结\n  </n-tooltip>\n</template>\n"
  },
  {
    "path": "src/float-button/index.ts",
    "content": "export { floatButtonProps, default as NFloatButton } from './src/FloatButton'\nexport type { FloatButtonProps, FloatButtonSlots } from './src/FloatButton'\n"
  },
  {
    "path": "src/float-button/src/FloatButton.tsx",
    "content": "import type { CSSProperties, PropType, SlotsType, VNode } from 'vue'\nimport type { ThemeProps } from '../../_mixins'\nimport type { ExtractPublicPropTypes, MaybeArray } from '../../_utils'\nimport type { FloatButtonTheme } from '../styles'\nimport { off, on } from 'evtd'\nimport { useMergedState } from 'vooks'\nimport {\n  computed,\n  defineComponent,\n  h,\n  inject,\n  onBeforeUnmount,\n  onMounted,\n  ref,\n  toRef\n} from 'vue'\nimport { NBaseIcon } from '../../_internal'\nimport { CloseIcon } from '../../_internal/icons'\nimport { useTheme, useThemeClass } from '../../_mixins'\nimport useConfig from '../../_mixins/use-config'\nimport {\n  call,\n  formatLength,\n  resolveSlot,\n  resolveWrappedSlot\n} from '../../_utils'\nimport { floatButtonGroupInjectionKey } from '../../float-button-group/src/FloatButtonGroup'\nimport { floatButtonLight } from '../styles'\nimport style from './styles/index.cssr'\n\nexport const floatButtonProps = {\n  ...(useTheme.props as ThemeProps<FloatButtonTheme>),\n  width: { type: [Number, String] as PropType<string | number>, default: 40 },\n  height: { type: [Number, String] as PropType<string | number>, default: 40 },\n  left: [Number, String] as PropType<string | number>,\n  right: [Number, String] as PropType<string | number>,\n  top: [Number, String] as PropType<string | number>,\n  bottom: [Number, String] as PropType<string | number>,\n  shape: {\n    type: String as PropType<'square' | 'circle'>,\n    default: 'circle'\n  },\n  position: {\n    type: String as PropType<'relative' | 'absolute' | 'fixed'>,\n    default: 'fixed'\n  },\n  type: {\n    type: String as PropType<'default' | 'primary'>,\n    default: 'default'\n  },\n  menuTrigger: String as PropType<'hover' | 'click'>,\n  showMenu: {\n    type: Boolean,\n    default: undefined\n  },\n  onUpdateShowMenu: {\n    type: [Function, Array] as PropType<MaybeArray<(value: boolean) => void>>,\n    default: undefined\n  },\n  'onUpdate:showMenu': {\n    type: [Function, Array] as PropType<MaybeArray<(value: boolean) => void>>,\n    default: undefined\n  }\n} as const\n\nexport type FloatButtonProps = ExtractPublicPropTypes<typeof floatButtonProps>\n\nexport interface FloatButtonSlots {\n  default?: () => VNode[]\n  description?: () => VNode[]\n  menu?: () => VNode[]\n}\n\nexport default defineComponent({\n  name: 'FloatButton',\n  props: floatButtonProps,\n  slots: Object as SlotsType<FloatButtonSlots>,\n  setup(props) {\n    const { mergedClsPrefixRef, inlineThemeDisabled } = useConfig(props)\n\n    const selfElRef = ref<HTMLDivElement | null>(null)\n\n    const themeRef = useTheme(\n      'FloatButton',\n      '-float-button',\n      style,\n      floatButtonLight,\n      props,\n      mergedClsPrefixRef\n    )\n\n    const floatButtonGroupInjection = inject(floatButtonGroupInjectionKey, null)\n\n    const uncontrolledShowMenuRef = ref(false)\n    const controlledShoeMenuRef = toRef(props, 'showMenu')\n    const mergedShowMenuRef = useMergedState(\n      controlledShoeMenuRef,\n      uncontrolledShowMenuRef\n    )\n\n    function doUpdateShowMenu(value: boolean): void {\n      const { onUpdateShowMenu, 'onUpdate:showMenu': _onUpdateShowMenu } = props\n      uncontrolledShowMenuRef.value = value\n      if (onUpdateShowMenu) {\n        call(onUpdateShowMenu, value)\n      }\n      if (_onUpdateShowMenu) {\n        call(_onUpdateShowMenu, value)\n      }\n    }\n\n    const cssVarsRef = computed<Record<string, string>>(() => {\n      const {\n        self: {\n          color,\n          textColor,\n          boxShadow,\n          boxShadowHover,\n          boxShadowPressed,\n          colorHover,\n          colorPrimary,\n          colorPrimaryHover,\n          textColorPrimary,\n          borderRadiusSquare,\n          colorPressed,\n          colorPrimaryPressed\n        },\n        common: { cubicBezierEaseInOut }\n      } = themeRef.value\n      const { type } = props\n      return {\n        '--n-bezier': cubicBezierEaseInOut,\n        '--n-box-shadow': boxShadow,\n        '--n-box-shadow-hover': boxShadowHover,\n        '--n-box-shadow-pressed': boxShadowPressed,\n        '--n-color': type === 'primary' ? colorPrimary : color,\n        '--n-text-color': type === 'primary' ? textColorPrimary : textColor,\n        '--n-color-hover': type === 'primary' ? colorPrimaryHover : colorHover,\n        '--n-color-pressed':\n          type === 'primary' ? colorPrimaryPressed : colorPressed,\n        '--n-border-radius-square': borderRadiusSquare\n      }\n    })\n    const inlineStyle = computed<CSSProperties>(() => {\n      const { width, height } = props\n      return {\n        position: floatButtonGroupInjection ? undefined : props.position,\n        width: formatLength(width),\n        minHeight: formatLength(height),\n        ...(floatButtonGroupInjection\n          ? null\n          : {\n              left: formatLength(props.left),\n              right: formatLength(props.right),\n              top: formatLength(props.top),\n              bottom: formatLength(props.bottom)\n            })\n      }\n    })\n\n    const mergedShapeRef = computed(() => {\n      return floatButtonGroupInjection\n        ? floatButtonGroupInjection.shapeRef.value\n        : props.shape\n    })\n\n    const Mouseenter = (): void => {\n      if (props.menuTrigger === 'hover') {\n        doUpdateShowMenu(true)\n      }\n    }\n\n    const handleMouseleave = (): void => {\n      if (props.menuTrigger === 'hover' && mergedShowMenuRef.value) {\n        doUpdateShowMenu(false)\n      }\n    }\n\n    const handleClick = (): void => {\n      if (props.menuTrigger === 'click') {\n        doUpdateShowMenu(!mergedShowMenuRef.value)\n      }\n    }\n\n    const themeClassHandle = inlineThemeDisabled\n      ? useThemeClass(\n          'float-button',\n          computed(() => props.type[0]),\n          cssVarsRef,\n          props\n        )\n      : undefined\n\n    onMounted(() => {\n      const selfEl = selfElRef.value\n      if (selfEl) {\n        on('mousemoveoutside', selfEl, handleMouseleave)\n      }\n    })\n\n    onBeforeUnmount(() => {\n      const selfEl = selfElRef.value\n      if (selfEl) {\n        off('mousemoveoutside', selfEl, handleMouseleave)\n      }\n    })\n\n    return {\n      inlineStyle,\n      selfElRef,\n      cssVars: inlineThemeDisabled ? undefined : cssVarsRef,\n      mergedClsPrefix: mergedClsPrefixRef,\n      mergedShape: mergedShapeRef,\n      mergedShowMenu: mergedShowMenuRef,\n      themeClass: themeClassHandle?.themeClass,\n      onRender: themeClassHandle?.onRender,\n      Mouseenter,\n      handleMouseleave,\n      handleClick\n    }\n  },\n\n  render() {\n    const {\n      mergedClsPrefix,\n      cssVars,\n      mergedShape,\n      type,\n      menuTrigger,\n      mergedShowMenu,\n      themeClass,\n      $slots,\n      inlineStyle,\n      onRender\n    } = this\n    onRender?.()\n    return (\n      <div\n        ref=\"selfElRef\"\n        class={[\n          `${mergedClsPrefix}-float-button`,\n          `${mergedClsPrefix}-float-button--${mergedShape}-shape`,\n          `${mergedClsPrefix}-float-button--${type}-type`,\n          mergedShowMenu && `${mergedClsPrefix}-float-button--show-menu`,\n          themeClass\n        ]}\n        style={[cssVars as CSSProperties, inlineStyle]}\n        onMouseenter={this.Mouseenter}\n        onMouseleave={this.handleMouseleave}\n        onClick={this.handleClick}\n        role=\"button\"\n      >\n        <div class={`${mergedClsPrefix}-float-button__fill`} aria-hidden></div>\n        <div class={`${mergedClsPrefix}-float-button__body`}>\n          {$slots.default?.()}\n          {resolveWrappedSlot($slots.description, (children) => {\n            if (children) {\n              return (\n                <div class={`${mergedClsPrefix}-float-button__description`}>\n                  {children}\n                </div>\n              )\n            }\n            return null\n          })}\n        </div>\n        {menuTrigger ? (\n          <div class={`${mergedClsPrefix}-float-button__close`}>\n            <NBaseIcon clsPrefix={mergedClsPrefix}>\n              {{ default: () => <CloseIcon /> }}\n            </NBaseIcon>\n          </div>\n        ) : null}\n        {menuTrigger ? (\n          <div\n            onClick={(e) => {\n              e.stopPropagation()\n            }}\n            data-float-button-menu\n            class={`${mergedClsPrefix}-float-button__menu`}\n          >\n            {resolveSlot($slots.menu, () => [])}\n          </div>\n        ) : null}\n      </div>\n    )\n  }\n})\n"
  },
  {
    "path": "src/float-button/src/styles/index.cssr.ts",
    "content": "import { c, cB, cE, cM } from '../../../_utils/cssr'\n\n// vars:\n// --n-bezier\n// --n-box-shadow\n// --n-box-shadow-hover\n// --n-box-shadow-pressed\n// --n-color\n// --n-text-color\n// --n-color-hover\n// --n-color-pressed\n// --n-border-radius-square\nexport default cB('float-button', `\n  user-select: none;\n  cursor: pointer;\n  color: var(--n-text-color);\n  background-color: var(--n-color);\n  font-size: 18px;\n  transition:\n    color .3s var(--n-bezier),\n    border-color .3s var(--n-bezier),\n    box-shadow .3s var(--n-bezier),\n    background-color .3s var(--n-bezier);\n  box-shadow: var(--n-box-shadow);\n  display: flex;\n  align-items: stretch;\n  box-sizing: border-box;\n`, [\n  cM('circle-shape', `\n    border-radius: 4096px;\n  `),\n  cM('square-shape', `\n    border-radius: var(--n-border-radius-square);\n  `),\n  cE('fill', `\n    position: absolute;\n    top: 0;\n    right: 0;\n    bottom: 0\n    left: 0;\n    transition: background-color .3s var(--n-bezier);\n    border-radius: inherit;\n  `),\n  cE('body', `\n    position: relative;\n    flex-grow: 1;\n    display: flex;\n    align-items: center;\n    justify-content: center;\n    transition: transform .3s var(--n-bezier), opacity .3s var(--n-bezier);\n    border-radius: inherit;\n    flex-direction: column;\n    box-sizing: border-box;\n    padding: 2px 4px;\n    gap: 2px;\n    transform: scale(1);\n  `, [\n    cE('description', `\n      font-size: 12px;\n      text-align: center;\n      line-height: 14px;\n    `)\n  ]),\n  c('&:hover', 'box-shadow: var(--n-box-shadow-hover);', [\n    c('>', [\n      cE('fill', `\n        background-color: var(--n-color-hover);\n      `)\n    ])\n  ]),\n  c('&:active', 'box-shadow: var(--n-box-shadow-pressed);', [\n    c('>', [\n      cE('fill', `\n        background-color: var(--n-color-pressed);\n      `)\n    ])\n  ]),\n  cM('show-menu', [\n    c('>', [\n      cE('menu', `\n        pointer-events: all;\n        bottom: 100%;\n        opacity: 1;\n      `),\n      cE('close', `\n        transform: scale(1);\n        opacity: 1;\n      `),\n      cE('body', `\n        transform: scale(0.75);\n        opacity: 0;\n      `)\n    ])\n  ]),\n  cE('close', `\n    opacity: 0;\n    transform: scale(0.75);\n    position: absolute;\n    top: 0;\n    right: 0;\n    bottom: 0;\n    left: 0;\n    display: flex;\n    align-items: center;\n    justify-content: center;\n    transition: transform .3s var(--n-bezier), opacity .3s var(--n-bezier);\n  `),\n  cE('menu', `\n    position: absolute;\n    bottom: calc(100% - 8px);\n    display: flex;\n    flex-direction: column;\n    opacity: 0;\n    pointer-events: none;\n    transition:\n      opacity .3s var(--n-bezier),\n      bottom .3s var(--n-bezier); \n  `, [\n    c('> *', `\n      margin-bottom: 16px;\n    `),\n    cB('float-button', `\n      position: relative !important;\n    `)\n  ])\n])\n"
  },
  {
    "path": "src/float-button/styles/dark.ts",
    "content": "import type { FloatButtonTheme } from './light'\nimport { commonDark } from '../../_styles/common'\n\nconst floatButtonDark: FloatButtonTheme = {\n  name: 'FloatButton',\n  common: commonDark,\n  self(vars) {\n    const {\n      popoverColor,\n      textColor2,\n      buttonColor2Hover,\n      buttonColor2Pressed,\n      primaryColor,\n      primaryColorHover,\n      primaryColorPressed,\n      baseColor,\n      borderRadius\n    } = vars\n    return {\n      color: popoverColor,\n      textColor: textColor2,\n      boxShadow: '0 2px 8px 0px rgba(0, 0, 0, .12)',\n      boxShadowHover: '0 2px 12px 0px rgba(0, 0, 0, .18)',\n      boxShadowPressed: '0 2px 12px 0px rgba(0, 0, 0, .18)',\n      colorHover: buttonColor2Hover,\n      colorPressed: buttonColor2Pressed,\n      colorPrimary: primaryColor,\n      colorPrimaryHover: primaryColorHover,\n      colorPrimaryPressed: primaryColorPressed,\n      textColorPrimary: baseColor,\n      borderRadiusSquare: borderRadius\n    }\n  }\n}\n\nexport default floatButtonDark\n"
  },
  {
    "path": "src/float-button/styles/index.ts",
    "content": "export { default as floatButtonDark } from './dark'\nexport { default as floatButtonLight } from './light'\nexport type { FloatButtonTheme, FloatButtonThemeVars } from './light'\n"
  },
  {
    "path": "src/float-button/styles/light.ts",
    "content": "import type { Theme } from '../../_mixins'\nimport type { ThemeCommonVars } from '../../_styles/common'\nimport { commonLight } from '../../_styles/common'\n\nfunction self(vars: ThemeCommonVars) {\n  const {\n    popoverColor,\n    textColor2,\n    buttonColor2Hover,\n    buttonColor2Pressed,\n    primaryColor,\n    primaryColorHover,\n    primaryColorPressed,\n    borderRadius\n  } = vars\n  return {\n    color: popoverColor,\n    colorHover: buttonColor2Hover,\n    colorPressed: buttonColor2Pressed,\n    colorPrimary: primaryColor,\n    colorPrimaryHover: primaryColorHover,\n    colorPrimaryPressed: primaryColorPressed,\n    textColor: textColor2,\n    boxShadow: '0 2px 8px 0px rgba(0, 0, 0, .16)',\n    boxShadowHover: '0 2px 12px 0px rgba(0, 0, 0, .24)',\n    boxShadowPressed: '0 2px 12px 0px rgba(0, 0, 0, .24)',\n    textColorPrimary: '#fff',\n    borderRadiusSquare: borderRadius\n  }\n}\n\nexport type FloatButtonThemeVars = ReturnType<typeof self>\n\nconst themeLight: Theme<'FloatButton', FloatButtonThemeVars> = {\n  name: 'FloatButton',\n  common: commonLight,\n  self\n}\n\nexport default themeLight\nexport type FloatButtonTheme = typeof themeLight\n"
  },
  {
    "path": "src/float-button/tests/FloatButton.spec.tsx",
    "content": "import { mount } from '@vue/test-utils'\nimport { h } from 'vue'\nimport { NFloatButton } from '../index'\n\ndescribe('n-float-button', () => {\n  it('should work with import on demand', () => {\n    mount(NFloatButton)\n  })\n\n  it('render empty children', () => {\n    const wrapper = mount({\n      render() {\n        return <NFloatButton />\n      }\n    })\n    expect(wrapper.html()).toMatchSnapshot()\n    wrapper.unmount()\n  })\n})\n"
  },
  {
    "path": "src/float-button/tests/__snapshots__/FloatButton.spec.tsx.snap",
    "content": "// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html\n\nexports[`n-float-button > render empty children 1`] = `\n\"<div class=\"n-float-button n-float-button--circle-shape n-float-button--default-type\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-box-shadow: 0 2px 8px 0px rgba(0, 0, 0, .16); --n-box-shadow-hover: 0 2px 12px 0px rgba(0, 0, 0, .24); --n-box-shadow-pressed: 0 2px 12px 0px rgba(0, 0, 0, .24); --n-color: #fff; --n-text-color: rgb(51, 54, 57); --n-color-hover: rgba(46, 51, 56, .09); --n-color-pressed: rgba(46, 51, 56, .13); --n-border-radius-square: 3px; position: fixed; width: 40px; min-height: 40px;\" role=\"button\">\n  <div class=\"n-float-button__fill\" aria-hidden=\"true\"></div>\n  <div class=\"n-float-button__body\">\n    <!---->\n    <!---->\n  </div>\n  <!---->\n  <!---->\n</div>\"\n`;\n"
  },
  {
    "path": "src/float-button/tests/server.spec.tsx",
    "content": "import { setup } from '@css-render/vue3-ssr'\nimport { renderToString } from '@vue/server-renderer'\n/**\n * @vitest-environment node\n */\nimport { createSSRApp, h } from 'vue'\nimport { NFloatButton } from '../..'\n\ndescribe('server side rendering', () => {\n  it('works', async () => {\n    const app = createSSRApp(() => <NFloatButton />)\n    setup(app)\n    try {\n      await renderToString(app)\n    }\n    catch (e) {\n      expect(e).not.toBeTruthy()\n    }\n  })\n})\n"
  },
  {
    "path": "src/float-button-group/index.ts",
    "content": "export {\n  floatButtonGroupProps,\n  default as NFloatButtonGroup\n} from './src/FloatButtonGroup'\nexport type { FloatButtonGroupProps } from './src/FloatButtonGroup'\n"
  },
  {
    "path": "src/float-button-group/src/FloatButtonGroup.tsx",
    "content": "import type { CSSProperties, PropType, Ref } from 'vue'\nimport type { ThemeProps } from '../../_mixins'\nimport type { ExtractPublicPropTypes } from '../../_utils'\nimport type { FloatButtonGroupTheme } from '../styles/light'\nimport { computed, defineComponent, h, provide, toRef } from 'vue'\nimport { useConfig, useTheme, useThemeClass } from '../../_mixins'\nimport { createInjectionKey, formatLength } from '../../_utils'\nimport floatButtonGroupLight from '../styles/light'\nimport style from './styles/index.cssr'\n\nexport interface ButtonGroupInjection {\n  shapeRef: Ref<'circle' | 'square'>\n}\n\nexport const floatButtonGroupProps = {\n  ...(useTheme.props as ThemeProps<FloatButtonGroupTheme>),\n  left: [Number, String] as PropType<string | number>,\n  right: [Number, String] as PropType<string | number>,\n  top: [Number, String] as PropType<string | number>,\n  bottom: [Number, String] as PropType<string | number>,\n  shape: {\n    type: String as PropType<'square' | 'circle'>,\n    default: 'circle'\n  },\n  position: {\n    type: String as PropType<'relative' | 'absolute' | 'fixed'>,\n    default: 'fixed'\n  }\n} as const\n\nexport type FloatButtonGroupProps = ExtractPublicPropTypes<\n  typeof floatButtonGroupProps\n>\n\nexport const floatButtonGroupInjectionKey\n  = createInjectionKey<ButtonGroupInjection>('n-float-button-group')\n\nexport default defineComponent({\n  name: 'FloatButtonGroup',\n  props: floatButtonGroupProps,\n  setup(props) {\n    const { mergedClsPrefixRef, inlineThemeDisabled } = useConfig(props)\n    const themeRef = useTheme(\n      'FloatButtonGroup',\n      '-float-button-group',\n      style,\n      floatButtonGroupLight,\n      props,\n      mergedClsPrefixRef\n    )\n    const cssVarsRef = computed<Record<string, string>>(() => {\n      const {\n        self: { color, boxShadow, buttonBorderColor, borderRadiusSquare },\n        common: { cubicBezierEaseInOut }\n      } = themeRef.value\n      return {\n        '--n-bezier': cubicBezierEaseInOut,\n        '--n-box-shadow': boxShadow,\n        '--n-color': color,\n        '--n-button-border-color': buttonBorderColor,\n        '--n-border-radius-square': borderRadiusSquare,\n        position: props.position,\n        left: formatLength(props.left) || '',\n        right: formatLength(props.right) || '',\n        top: formatLength(props.top) || '',\n        bottom: formatLength(props.bottom) || ''\n      }\n    })\n\n    provide(floatButtonGroupInjectionKey, {\n      shapeRef: toRef(props, 'shape')\n    })\n\n    const themeClassHandle = inlineThemeDisabled\n      ? useThemeClass('float-button', undefined, cssVarsRef, props)\n      : undefined\n\n    return {\n      cssVars: inlineThemeDisabled ? undefined : cssVarsRef,\n      mergedClsPrefix: mergedClsPrefixRef,\n      themeClass: themeClassHandle?.themeClass,\n      onRender: themeClassHandle?.onRender\n    }\n  },\n  render() {\n    const { mergedClsPrefix, cssVars, shape } = this\n    return (\n      <div\n        class={[\n          `${mergedClsPrefix}-float-button-group`,\n          `${mergedClsPrefix}-float-button-group--${shape}-shape`\n        ]}\n        style={cssVars as CSSProperties}\n        role=\"group\"\n      >\n        {this.$slots}\n      </div>\n    )\n  }\n})\n"
  },
  {
    "path": "src/float-button-group/src/styles/index.cssr.ts",
    "content": "import { c, cB, cE, cM } from '../../../_utils/cssr/index'\n\n// --n-border-radius-square\nexport default cB('float-button-group', [\n  cB('float-button', `\n    position: relative;\n  `),\n  cM('square-shape', `\n    background-color: var(--n-color);\n    cursor: pointer;\n    display: flex;\n    width: fit-content;\n    align-items: center;\n    justify-content: center;\n    border-radius: var(--n-border-radius-square);\n    flex-direction: column;\n    box-shadow: var(--n-box-shadow);\n    transition:\n      color .3s var(--n-bezier),\n      box-shadow .3s var(--n-bezier),\n      background-color .3s var(--n-bezier);\n  `, [\n    cB('float-button', `\n      background-color: unset;\n      border-radius: 0;\n      box-shadow: none;\n      box-sizing: content-box;\n    `, [\n      c('&:not(:last-child)', `\n        border-bottom: 1px solid var(--n-button-border-color);    \n      `),\n      c('&:first-child', `\n        border-top-left-radius: 4px;\n        border-top-right-radius: 4px;\n      `),\n      c('&:last-child', `\n        border-bottom-left-radius: 4px;\n        border-bottom-right-radius: 4px;\n      `),\n      cE('fill', `\n        top: 4px;\n        right: 4px;\n        bottom: 4px;\n        left: 4px;\n        border-radius: var(--n-border-radius-square);  \n      `)\n    ])\n  ]),\n  cM('circle-shape', [\n    c('>:not(:last-child)', `\n      margin-bottom: 16px;\n    `)\n  ])\n])\n"
  },
  {
    "path": "src/float-button-group/styles/dark.ts",
    "content": "import type { FloatButtonGroupTheme } from './light'\nimport { commonDark } from '../../_styles/common'\n\nconst floatButtonGroupDark: FloatButtonGroupTheme = {\n  name: 'FloatButtonGroup',\n  common: commonDark,\n  self(vars) {\n    const { popoverColor, dividerColor, borderRadius } = vars\n    return {\n      color: popoverColor,\n      buttonBorderColor: dividerColor,\n      borderRadiusSquare: borderRadius,\n      boxShadow: '0 2px 8px 0px rgba(0, 0, 0, .12)'\n    }\n  }\n}\n\nexport default floatButtonGroupDark\n"
  },
  {
    "path": "src/float-button-group/styles/index.ts",
    "content": "export { default as floatButtonGroupDark } from './dark'\nexport { default as floatButtonGroupLight } from './light'\nexport type { FloatButtonGroupTheme } from './light'\n"
  },
  {
    "path": "src/float-button-group/styles/light.ts",
    "content": "import type { Theme } from '../../_mixins'\nimport type { ThemeCommonVars } from '../../config-provider'\nimport { commonLight } from '../../styles'\n\nfunction self(vars: ThemeCommonVars) {\n  const { popoverColor, dividerColor, borderRadius } = vars\n  return {\n    color: popoverColor,\n    buttonBorderColor: dividerColor,\n    borderRadiusSquare: borderRadius,\n    boxShadow: '0 2px 8px 0px rgba(0, 0, 0, .12)'\n  }\n}\n\nexport type FloatButtonGroupThemeVars = ReturnType<typeof self>\n\nconst themeLight: Theme<'FloatButtonGroup', FloatButtonGroupThemeVars> = {\n  name: 'FloatButtonGroup',\n  common: commonLight,\n  self\n}\n\nexport default themeLight\nexport type FloatButtonGroupTheme = typeof themeLight\n"
  },
  {
    "path": "src/float-button-group/tests/NFloatButtonGroup.spec.tsx",
    "content": "import { mount } from '@vue/test-utils'\nimport { h } from 'vue'\nimport { NFloatButtonGroup } from '../index'\n\ndescribe('n-float-button-group', () => {\n  it('should work with import on demand', () => {\n    mount(NFloatButtonGroup)\n  })\n\n  it('render empty children', () => {\n    const wrapper = mount({\n      render() {\n        return <NFloatButtonGroup />\n      }\n    })\n    expect(wrapper.html()).toMatchSnapshot()\n    wrapper.unmount()\n  })\n})\n"
  },
  {
    "path": "src/float-button-group/tests/__snapshots__/NFloatButtonGroup.spec.tsx.snap",
    "content": "// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html\n\nexports[`n-float-button-group > render empty children 1`] = `\"<div class=\"n-float-button-group n-float-button-group--circle-shape\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-box-shadow: 0 2px 8px 0px rgba(0, 0, 0, .12); --n-color: #fff; --n-button-border-color: rgb(239, 239, 245); --n-border-radius-square: 3px; position: fixed;\" role=\"group\"></div>\"`;\n"
  },
  {
    "path": "src/float-button-group/tests/server.spec.tsx",
    "content": "import { setup } from '@css-render/vue3-ssr'\nimport { renderToString } from '@vue/server-renderer'\n/**\n * @vitest-environment node\n */\nimport { createSSRApp, h } from 'vue'\nimport { NFloatButtonGroup } from '../..'\n\ndescribe('server side rendering', () => {\n  it('works', async () => {\n    const app = createSSRApp(() => <NFloatButtonGroup />)\n    setup(app)\n    try {\n      await renderToString(app)\n    }\n    catch (e) {\n      expect(e).not.toBeTruthy()\n    }\n  })\n})\n"
  },
  {
    "path": "src/form/demos/enUS/abnormal-warning.demo.vue",
    "content": "<markdown>\n# Abnormal warning\n\nYou may want to display warnings to the user for values that may be abnormal, but do not want the validate method to throw an exception. In this case, `FormItemRule`'s `level` attribute can help you (`level: 'warning'`).\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { FormInst, FormItemRule, FormRules } from 'naive-ui'\nimport { useMessage } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst formRef = ref<FormInst | null>(null)\nconst message = useMessage()\nconst formValue = ref({\n  count: undefined\n})\n\nconst rules = {\n  count: [\n    {\n      required: true,\n      message: 'Try to answer?',\n      type: 'number',\n      trigger: ['input', 'blur']\n    },\n    {\n      trigger: ['input', 'blur'],\n      level: 'warning',\n      validator(_rule: FormItemRule, value: number) {\n        if (value !== 3) {\n          return new Error('How about three-humped camel? when it\\'s pregnant.')\n        }\n        return true\n      }\n    }\n  ]\n} satisfies FormRules\n\nfunction handleValidateClick(e: MouseEvent) {\n  e.preventDefault()\n  formRef.value?.validate((errors, { warnings }) => {\n    if (errors) {\n      console.error(errors)\n      message.error('Invalid.')\n    }\n    else if (warnings) {\n      message.warning('Valid but be aware of warnings.')\n      console.warn(warnings)\n    }\n    else {\n      message.success('Perfect.')\n    }\n  })\n}\n</script>\n\n<template>\n  <n-form ref=\"formRef\" inline :model=\"formValue\" :rules=\"rules\">\n    <n-form-item label=\"How many humps can a camel have at most?\" path=\"count\">\n      <n-input-number v-model:value=\"formValue.count\" />\n    </n-form-item>\n    <n-form-item>\n      <n-button attr-type=\"button\" @click=\"handleValidateClick\">\n        Submit Answer\n      </n-button>\n    </n-form-item>\n  </n-form>\n</template>\n"
  },
  {
    "path": "src/form/demos/enUS/async.demo.vue",
    "content": "<markdown>\n# Async validation\n\nSupports async when the provided validator returns a `Promise`.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { FormInst, FormItemRule, FormValidationError } from 'naive-ui'\nimport { useMessage } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst formRef = ref<FormInst | null>(null)\nconst message = useMessage()\nconst formValue = ref({\n  user: {\n    name: 'name',\n    age: '15',\n    address: '0'\n  },\n  phone: '1251550092'\n})\n\nconst rules = {\n  user: {\n    name: {\n      required: true,\n      trigger: 'blur',\n      validator: (rule: FormItemRule, value: string) => {\n        return new Promise<void>((resolve, reject) => {\n          if (value !== 'testName') {\n            reject(new Error('error name')) // reject with error message\n          }\n          else {\n            resolve()\n          }\n        })\n      }\n    },\n    age: {\n      required: true,\n      trigger: 'input',\n      validator: (rule: FormItemRule, value: number) => {\n        return new Promise<void>((resolve, reject) => {\n          setTimeout(() => {\n            if (value <= 16) {\n              reject(new Error('error age'))\n            }\n            else {\n              resolve()\n            }\n          }, 3000)\n        })\n      }\n    }\n  },\n  phone: {\n    required: true,\n    trigger: ['input'],\n    validator: (rule: FormItemRule, value: string) => {\n      return /^[1]+[3,8]+\\d{9}$/.test(value)\n    }\n  }\n}\n\nfunction handleValidateClick(e: MouseEvent) {\n  e.preventDefault()\n  const messageReactive = message.loading('Verifying', {\n    duration: 0\n  })\n  formRef.value?.validate((errors: Array<FormValidationError> | undefined) => {\n    if (!errors) {\n      message.success('Valid')\n    }\n    else {\n      message.error('Invalid')\n      console.log('errors', errors)\n    }\n    messageReactive.destroy()\n  })\n}\n</script>\n\n<template>\n  <n-form\n    ref=\"formRef\"\n    inline\n    :label-width=\"80\"\n    :model=\"formValue\"\n    :rules=\"rules\"\n  >\n    <n-form-item label=\"Name\" path=\"user.name\">\n      <n-input v-model:value=\"formValue.user.name\" placeholder=\"Input Name\" />\n    </n-form-item>\n    <n-form-item label=\"Age\" path=\"user.age\">\n      <n-input v-model:value=\"formValue.user.age\" placeholder=\"Input Age\" />\n    </n-form-item>\n    <n-form-item label=\"Address\" path=\"user.address\">\n      <n-input\n        v-model:value=\"formValue.user.address\"\n        placeholder=\"Input Address\"\n      />\n    </n-form-item>\n    <n-form-item label=\"Phone\" path=\"phone\">\n      <n-input v-model:value=\"formValue.phone\" placeholder=\"Phone Number\" />\n    </n-form-item>\n    <n-form-item v-model:value=\"formValue.phone\">\n      <n-button @click=\"handleValidateClick\">\n        Validate\n      </n-button>\n    </n-form-item>\n  </n-form>\n\n  <pre>{{ JSON.stringify(formValue, null, 2) }}\n</pre>\n</template>\n"
  },
  {
    "path": "src/form/demos/enUS/custom-messages.demo.vue",
    "content": "<markdown>\n# Custom messages\n\nYou can define custom messages that are used instead of the standard ones.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { FormInst } from 'naive-ui'\nimport { useMessage } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst formRef = ref<FormInst | null>(null)\nconst message = useMessage()\nconst formValue = ref({\n  user: {\n    name: ''\n  }\n})\n\nconst messages = {\n  required: '%s is really really required'\n}\n\nconst rules = {\n  user: {\n    name: {\n      required: true,\n      trigger: 'blur'\n    }\n  }\n}\n\nfunction handleValidateClick(e: MouseEvent) {\n  e.preventDefault()\n  formRef.value?.validate((errors) => {\n    if (!errors) {\n      message.success('Valid')\n    }\n    else {\n      console.log(errors)\n      message.error('Invalid')\n    }\n  })\n}\n</script>\n\n<template>\n  <n-form\n    ref=\"formRef\"\n    :model=\"formValue\"\n    :rules=\"rules\"\n    :validate-messages=\"messages\"\n  >\n    <n-form-item label=\"Name\" path=\"user.name\">\n      <n-input v-model:value=\"formValue.user.name\" placeholder=\"Input Name\" />\n    </n-form-item>\n    <n-form-item>\n      <n-button @click=\"handleValidateClick\">\n        Validate\n      </n-button>\n    </n-form-item>\n  </n-form>\n\n  <pre>{{ JSON.stringify(formValue, null, 2) }}\n</pre>\n</template>\n"
  },
  {
    "path": "src/form/demos/enUS/custom-rule.demo.vue",
    "content": "<markdown>\n# Customizing rules\n\nSometimes builtin triggers don't meet your needs. You can customize these validations by setting a custom trigger in the rules and manually triggering the validation.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type {\n  FormInst,\n  FormItemInst,\n  FormItemRule,\n  FormRules,\n  FormValidationError\n} from 'naive-ui'\nimport { useMessage } from 'naive-ui'\nimport { ref } from 'vue'\n\ninterface ModelType {\n  age: string | null\n  password: string | null\n  reenteredPassword: string | null\n}\n\nconst formRef = ref<FormInst | null>(null)\nconst rPasswordFormItemRef = ref<FormItemInst | null>(null)\nconst message = useMessage()\nconst modelRef = ref<ModelType>({\n  age: null,\n  password: null,\n  reenteredPassword: null\n})\n\nfunction validatePasswordStartWith(rule: FormItemRule, value: string): boolean {\n  return (\n    !!modelRef.value.password\n    && modelRef.value.password.startsWith(value)\n    && modelRef.value.password.length >= value.length\n  )\n}\n\nfunction validatePasswordSame(rule: FormItemRule, value: string): boolean {\n  return value === modelRef.value.password\n}\n\nconst rules: FormRules = {\n  age: [\n    {\n      required: true,\n      validator(rule: FormItemRule, value: string) {\n        if (!value) {\n          return new Error('Age is required')\n        }\n        else if (!/^\\d*$/.test(value)) {\n          return new Error('Age should be an integer')\n        }\n        else if (Number(value) < 18) {\n          return new Error('Age should be above 18')\n        }\n        return true\n      },\n      trigger: ['input', 'blur']\n    }\n  ],\n  password: [\n    {\n      required: true,\n      message: 'Password is required'\n    }\n  ],\n  reenteredPassword: [\n    {\n      required: true,\n      message: 'Re-entered password is required',\n      trigger: ['input', 'blur']\n    },\n    {\n      validator: validatePasswordStartWith,\n      message: 'Password is not same as re-entered password!',\n      trigger: 'input'\n    },\n    {\n      validator: validatePasswordSame,\n      message: 'Password is not same as re-entered password!',\n      trigger: ['blur', 'password-input']\n    }\n  ]\n}\n\nfunction handlePasswordInput() {\n  if (modelRef.value.reenteredPassword) {\n    rPasswordFormItemRef.value?.validate({ trigger: 'password-input' })\n  }\n}\n\nfunction handleValidateButtonClick(e: MouseEvent) {\n  e.preventDefault()\n  formRef.value?.validate((errors: Array<FormValidationError> | undefined) => {\n    if (!errors) {\n      message.success('Valid')\n    }\n    else {\n      console.log(errors)\n      message.error('Invalid')\n    }\n  })\n}\n</script>\n\n<template>\n  <n-form ref=\"formRef\" :model=\"modelRef\" :rules=\"rules\">\n    <n-form-item path=\"age\" label=\"Age\">\n      <n-input v-model:value=\"modelRef.age\" @keydown.enter.prevent />\n    </n-form-item>\n    <n-form-item path=\"password\" label=\"Password\">\n      <n-input\n        v-model:value=\"modelRef.password\"\n        type=\"password\"\n        @input=\"handlePasswordInput\"\n        @keydown.enter.prevent\n      />\n    </n-form-item>\n    <n-form-item\n      ref=\"rPasswordFormItemRef\"\n      first\n      path=\"reenteredPassword\"\n      label=\"Re-enter Password\"\n    >\n      <n-input\n        v-model:value=\"modelRef.reenteredPassword\"\n        :disabled=\"!modelRef.password\"\n        type=\"password\"\n        @keydown.enter.prevent\n      />\n    </n-form-item>\n    <n-row :gutter=\"[0, 24]\">\n      <n-col :span=\"24\">\n        <div style=\"display: flex; justify-content: flex-end\">\n          <n-button\n            :disabled=\"modelRef.age === null\"\n            round\n            type=\"primary\"\n            @click=\"handleValidateButtonClick\"\n          >\n            Validate\n          </n-button>\n        </div>\n      </n-col>\n    </n-row>\n  </n-form>\n\n  <pre>{{ JSON.stringify(modelRef, null, 2) }}\n</pre>\n</template>\n"
  },
  {
    "path": "src/form/demos/enUS/custom-validation.demo.vue",
    "content": "<markdown>\n# Custom validation\n\nIf you need to customize the timing and effect of a validation, use `validation-status` and `feedback`. In this case, there's usually no need for providing a `path` for the form item.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { computed, ref } from 'vue'\n\nfunction createStatus(value: string) {\n  switch (value) {\n    case '10:30':\n      return undefined\n    case '10:29':\n      return 'warning'\n    default:\n      return 'error'\n  }\n}\n\nfunction createFeedback(value: string) {\n  switch (value) {\n    case '10:30':\n      return 'The plane of 10:30 has arrived.'\n    case '10:29':\n      return 'Almost there, please set the time to 10:30'\n    default:\n      return 'Please set the time to 10:30'\n  }\n}\n\nfunction createTimeForNumber(num: number) {\n  return `${Number.parseInt(String(num / 100), 10)}:${num % 100}`\n}\n\nconst inputValueRef = ref('10:29')\nconst inputNumberValueRef = ref(1029)\nconst selectValueRef = ref('10:29')\n\nconst selectOptions = [\n  {\n    label: '10:28',\n    value: '10:28'\n  },\n  {\n    label: '10:29',\n    value: '10:29'\n  },\n  {\n    label: '10:30',\n    value: '10:30'\n  }\n]\n\nconst inputValidationStatus = computed(() => {\n  return createStatus(inputValueRef.value)\n})\n\nconst inputFeedback = computed(() => {\n  return createFeedback(inputValueRef.value)\n})\n\nconst inputNumberValidationStatus = computed(() => {\n  return createStatus(createTimeForNumber(inputNumberValueRef.value))\n})\n\nconst inputNumberFeedback = computed(() => {\n  return createFeedback(createTimeForNumber(inputNumberValueRef.value))\n})\n\nconst selectValidationStatus = computed(() => {\n  return createStatus(selectValueRef.value)\n})\n\nconst selectFeedback = computed(() => {\n  return createFeedback(selectValueRef.value)\n})\n</script>\n\n<template>\n  <n-form>\n    <n-form-item\n      label=\"Airports\"\n      :validation-status=\"inputValidationStatus\"\n      :feedback=\"inputFeedback\"\n    >\n      <n-input v-model:value=\"inputValueRef\" clearable />\n    </n-form-item>\n    <n-form-item\n      label=\"Airports\"\n      :validation-status=\"inputNumberValidationStatus\"\n    >\n      <n-input-number v-model:value=\"inputNumberValueRef\" />\n      <template #feedback>\n        {{ inputNumberFeedback }}\n      </template>\n    </n-form-item>\n    <n-form-item\n      label=\"Airports\"\n      :validation-status=\"selectValidationStatus\"\n      :feedback=\"selectFeedback\"\n    >\n      <n-select\n        v-model:value=\"selectValueRef\"\n        debug\n        :options=\"selectOptions\"\n        clearable\n      />\n    </n-form-item>\n  </n-form>\n</template>\n"
  },
  {
    "path": "src/form/demos/enUS/disabled.demo.vue",
    "content": "<markdown>\n# Disabled form\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { computed, ref } from 'vue'\n\nfunction genOptions(depth = 2, iterator = 1, prefix = ''): any {\n  const length = 12\n  const options = []\n  for (let i = 1; i <= length; ++i) {\n    if (iterator === 1) {\n      options.push({\n        value: `${i}`,\n        label: `${i}`,\n        disabled: i % 5 === 0,\n        children: genOptions(depth, iterator + 1, `${i}`)\n      })\n    }\n    else if (iterator === depth) {\n      options.push({\n        value: `${prefix}-${i}`,\n        label: `${prefix}-${i}`,\n        disabled: i % 5 === 0\n      })\n    }\n    else {\n      options.push({\n        value: `${prefix}-${i}`,\n        label: `${prefix}-${i}`,\n        disabled: i % 5 === 0,\n        children: genOptions(depth, iterator + 1, `${prefix}-${i}`)\n      })\n    }\n  }\n  return options\n}\n\nconst model = ref({\n  inputValue: null,\n  selectValue: null,\n  autoCompleteValue: '',\n  dynamicTagsValue: ['teacher', 'frontend'],\n  cascaderValue: null,\n  datetimeValue: null,\n  switchValue: false,\n  checkboxValue: false,\n  checkboxGroupValue: null,\n  radioValue: 'Definitely Maybe',\n  radioGroupValue: null,\n  radioButtonGroupValue: null,\n  inputNumberValue: null,\n  timePickerValue: null,\n  colorValue: null,\n  sliderValue: 0,\n  transferValue: null\n})\n\nconst updateDisabled = ref(false)\nconst generalOptions = ['groode', 'veli good', 'emazing', 'lidiculous'].map(\n  v => ({\n    label: v,\n    value: v\n  })\n)\nconst options = genOptions()\nconst treeSelectOptions = [\n  {\n    label: 'Rubber Soul',\n    key: 'Rubber Soul',\n    children: [\n      {\n        label: 'Drive My Car',\n        key: 'Drive My Car'\n      },\n      {\n        label: 'Michelle',\n        key: 'Michelle'\n      }\n    ]\n  }\n]\nconst autoCompleteOptions = computed(() => {\n  return ['@gmail.com', '@163.com', '@qq.com'].map((suffix) => {\n    const prefix = model.value.autoCompleteValue.split('@')[0]\n    return {\n      label: prefix + suffix,\n      value: prefix + suffix\n    }\n  })\n})\n</script>\n\n<template>\n  <n-space vertical>\n    <n-switch v-model:value=\"updateDisabled\" />\n    <n-form\n      :model=\"model\"\n      label-placement=\"left\"\n      :label-width=\"160\"\n      :disabled=\"updateDisabled\"\n      :style=\"{\n        maxWidth: '640px',\n      }\"\n    >\n      <n-form-item label=\"Input\" path=\"inputValue\">\n        <n-input v-model:value=\"model.inputValue\" placeholder=\"Input\" />\n      </n-form-item>\n      <n-form-item label=\"Select\" path=\"selectValue\">\n        <n-select\n          v-model:value=\"model.selectValue\"\n          placeholder=\"Select\"\n          :options=\"generalOptions\"\n        />\n      </n-form-item>\n      <n-form-item label=\"Upload\" path=\"uploadValue\">\n        <n-upload>\n          <n-button>Upload file</n-button>\n        </n-upload>\n      </n-form-item>\n      <n-form-item label=\"Auto Complete\" path=\"autoCompleteValue\">\n        <n-auto-complete\n          v-model:value=\"model.autoCompleteValue\"\n          :options=\"autoCompleteOptions\"\n          placeholder=\"Email\"\n        />\n      </n-form-item>\n      <n-form-item label=\"Dynamic Tags\" path=\"dynamicTagsValue\">\n        <n-dynamic-tags v-model:value=\"model.dynamicTagsValue\" />\n      </n-form-item>\n      <n-form-item label=\"Tree Select\" path=\"treeSelectValue\">\n        <n-tree-select\n          :options=\"treeSelectOptions\"\n          default-value=\"Drive My Car\"\n        />\n      </n-form-item>\n      <n-form-item label=\"Cascader\" path=\"cascaderValue\">\n        <n-cascader\n          v-model:value=\"model.cascaderValue\"\n          placeholder=\"Cascader\"\n          :options=\"options\"\n          check-strategy=\"child\"\n          size=\"medium\"\n        />\n      </n-form-item>\n      <n-form-item label=\"Datetime\" path=\"datetimeValue\">\n        <n-date-picker v-model:value=\"model.datetimeValue\" type=\"datetime\" />\n      </n-form-item>\n      <n-form-item label=\"Switch\" path=\"switchValue\">\n        <n-switch v-model:value=\"model.switchValue\" />\n      </n-form-item>\n      <n-form-item label=\"Checkbox\" path=\"checkboxValue\">\n        <n-checkbox v-model:checked=\"model.checkboxValue\">\n          Checkbox\n        </n-checkbox>\n      </n-form-item>\n      <n-form-item label=\"Checkbox Group\" path=\"checkboxGroupValue\">\n        <n-checkbox-group v-model:value=\"model.checkboxGroupValue\">\n          <n-space>\n            <n-checkbox value=\"Option 1\">\n              Option 1\n            </n-checkbox>\n            <n-checkbox value=\"Option 2\">\n              Option 2\n            </n-checkbox>\n            <n-checkbox value=\"Option 3\">\n              Option 3\n            </n-checkbox>\n          </n-space>\n        </n-checkbox-group>\n      </n-form-item>\n      <n-form-item label=\"Radio\" path=\"radioValue\">\n        <n-radio\n          :checked=\"model.radioValue === 'Definitely Maybe'\"\n          value=\"Definitely Maybe\"\n          name=\"basic-demo\"\n        >\n          Definitely Maybe\n        </n-radio>\n      </n-form-item>\n      <n-form-item label=\"Radio Group\" path=\"radioGroupValue\">\n        <n-radio-group v-model:value=\"model.radioGroupValue\" name=\"radiogroup2\">\n          <n-radio value=\"Radio 1\">\n            Radio 1\n          </n-radio>\n          <n-radio value=\"Radio 2\">\n            Radio 2\n          </n-radio>\n          <n-radio value=\"Radio 3\">\n            Radio 3\n          </n-radio>\n        </n-radio-group>\n      </n-form-item>\n      <n-form-item label=\"Radio Button Group\" path=\"radioGroupValue\">\n        <n-radio-group v-model:value=\"model.radioGroupValue\" name=\"radiogroup2\">\n          <n-radio-button value=\"Radio 1\">\n            Radio 1\n          </n-radio-button>\n          <n-radio-button value=\"Radio 2\">\n            Radio 2\n          </n-radio-button>\n          <n-radio-button value=\"Radio 3\">\n            Radio 3\n          </n-radio-button>\n        </n-radio-group>\n      </n-form-item>\n      <n-form-item label=\"Input Number\" path=\"inputNumberValue\">\n        <n-input-number v-model:value=\"model.inputNumberValue\" />\n      </n-form-item>\n      <n-form-item label=\"Time Picker\" path=\"timePickerValue\">\n        <n-time-picker v-model:value=\"model.timePickerValue\" />\n      </n-form-item>\n      <n-form-item label=\"Color Picker\" path=\"colorValue\">\n        <n-color-picker v-model:value=\"model.colorValue\" />\n      </n-form-item>\n      <n-form-item label=\"Slider\" path=\"sliderValue\">\n        <n-slider v-model:value=\"model.sliderValue\" :step=\"5\" />\n      </n-form-item>\n      <n-form-item label=\"Transfer\" path=\"transferValue\">\n        <n-transfer\n          v-model:value=\"model.transferValue\"\n          :options=\"generalOptions\"\n        />\n      </n-form-item>\n    </n-form>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/form/demos/enUS/dynamic.demo.vue",
    "content": "<markdown>\n# Dynamic form\n\nDelete or add form items dynamically.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { FormInst } from 'naive-ui'\nimport { reactive, ref } from 'vue'\n\nconst formRef = ref<FormInst | null>(null)\n\nconst dynamicForm = reactive({\n  name: '',\n  hobbies: [{ hobby: '' }]\n})\n\nfunction removeItem(index: number) {\n  dynamicForm.hobbies.splice(index, 1)\n}\n\nfunction addItem() {\n  dynamicForm.hobbies.push({ hobby: '' })\n}\n\nfunction handleValidateClick() {\n  formRef.value?.validate((errors) => {\n    if (!errors) {\n      console.log('success')\n    }\n    else {\n      console.log(errors)\n    }\n  })\n}\n</script>\n\n<template>\n  <n-form ref=\"formRef\" :model=\"dynamicForm\" :style=\"{ maxWidth: '640px' }\">\n    <n-form-item\n      label=\"name\"\n      path=\"name\"\n      :rule=\"{\n        required: true,\n        message: 'Please input Name',\n        trigger: ['input', 'blur'],\n      }\"\n    >\n      <n-input v-model:value=\"dynamicForm.name\" clearable />\n    </n-form-item>\n\n    <n-form-item\n      v-for=\"(item, index) in dynamicForm.hobbies\"\n      :key=\"index\"\n      :label=\"`hobby${index + 1}`\"\n      :path=\"`hobbies[${index}].hobby`\"\n      :rule=\"{\n        required: true,\n        message: `Please input hobby${index + 1}`,\n        trigger: ['input', 'blur'],\n      }\"\n    >\n      <n-input v-model:value=\"item.hobby\" clearable />\n      <n-button style=\"margin-left: 12px\" @click=\"removeItem(index)\">\n        Remove\n      </n-button>\n    </n-form-item>\n\n    <n-form-item>\n      <n-space>\n        <n-button attr-type=\"button\" @click=\"handleValidateClick\">\n          Validate\n        </n-button>\n        <n-button attr-type=\"button\" @click=\"addItem\">\n          New hobby\n        </n-button>\n      </n-space>\n    </n-form-item>\n  </n-form>\n</template>\n"
  },
  {
    "path": "src/form/demos/enUS/feedback-style.demo.vue",
    "content": "<markdown>\n# Custom feedback style\n\nUsing `feedback-style` and `feedback-class` to custom feedback.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { reactive } from 'vue'\n\ninterface FormValue {\n  input: string | null\n}\n\nconst formValue: FormValue = reactive({\n  input: null\n})\n</script>\n\n<template>\n  <n-form :model=\"formValue\">\n    <n-form-item\n      :rule=\"{\n        required: true,\n        message: 'Centered feedback',\n        type: 'string',\n        trigger: ['input', 'blur'],\n      }\"\n      label=\"Centered feedback\"\n      path=\"input\"\n      feedback-style=\"text-align: center;\"\n    >\n      <n-input v-model:value=\"formValue.input\" />\n    </n-form-item>\n  </n-form>\n</template>\n"
  },
  {
    "path": "src/form/demos/enUS/i18n.demo.vue",
    "content": "<markdown>\n# I18n\n\nForm's rule supports `renderMessage`. You can use it to render your message.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { FormRules } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst localeRef = ref('English')\nconst rules: FormRules = {\n  input: {\n    required: true,\n    trigger: ['focus', 'input'],\n    renderMessage: () => {\n      return localeRef.value === 'Chinese' ? '中文错误' : 'English error'\n    }\n  }\n}\nconst modelRef = ref({\n  input: ''\n})\n</script>\n\n<template>\n  <n-space vertical>\n    <n-radio-group v-model:value=\"localeRef\">\n      <n-space>\n        <n-radio label=\"English\" value=\"English\" />\n        <n-radio label=\"Chinese\" value=\"Chinese\" />\n      </n-space>\n    </n-radio-group>\n    <n-form :model=\"modelRef\" :rules=\"rules\">\n      <n-form-item label=\"Input something to remove error\" path=\"input\">\n        <n-input v-model:value=\"modelRef.input\" />\n      </n-form-item>\n    </n-form>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/form/demos/enUS/index.demo-entry.md",
    "content": "# Form\n\n<!--single-column-->\n\nThe element to collect and validate data.\n\n<n-alert type=\"warning\" title=\"Caveat\" :bordered=\"false\">\n  If you want to apply required rule for a form item with number typed value, you need to set <n-text code>`type: 'number'`</n-text> in the rule object.\n</n-alert>\n\n## Demos\n\n```demo\ninline.vue\ncustom-rule.vue\nabnormal-warning.vue\ncustom-validation.vue\ni18n.vue\ntop.vue\nleft.vue\nitem-only.vue\nasync.vue\ndisabled.vue\nshow-label.vue\npartially-apply-rules.vue\ncustom-messages.vue\ndynamic.vue\nfeedback-style.vue\n```\n\n## API\n\n### Form Props\n\n| Name | Type | Default | Description | Version |\n| --- | --- | --- | --- | --- |\n| disabled | `boolean` | `false` | Whether to disable the form. |  |\n| inline | `boolean` | `false` | Whether to display as an inline form. |  |\n| label-width | `number \\| string \\| 'auto'` | `undefined` | The width of label. Particularly useful when `label-placement` is set to `'left'`,`'auto'` means label width will be auto adjusted. |  |\n| label-align | `'left' \\| 'right'` | `-` | Label text alignment. |  |\n| label-placement | `'left' \\| 'top'` | `'top'` | Label placement. |  |\n| model | `Object` | `{}` | The object to get/set form item values. |  |\n| rules | `type FormRules = { [itemValidatePath: string]: FormItemRule \\| Array<FormItemRule> \\| FormRules }` | `{}` | The rules to validate form items. |  |\n| show-feedback | `boolean` | `true` | Whether to show the feedback area. |  |\n| show-label | `boolean` | `true` | Whether to show the label. |  |\n| show-require-mark | `boolean` | `-` | Whether to show a required symbol when a form item is required. |  |\n| require-mark-placement | `'left' \\| 'right' \\| 'right-hanging'` | `'right'` | Require mark placement | `'right-hanging'` 2.24.0 |\n| size | `'small' \\| 'medium' \\| 'large'` | `'medium'` | Size. |  |\n| validate-messages | `FormValidateMessages` | `undefined` | Validation messages of `async-validator`. | 2.27.0 |\n\n#### FormItemRule Type\n\n<n-alert title=\"Caveat\" type=\"warning\" style=\"margin-bottom: 16px;\" :bordered=\"false\">\n  The follow table doesn't demostrate all props of rules. If you want to know all the usages, please see <n-a href=\"https://github.com/yiminghe/async-validator\" target=\"_blank\">async-validator</n-a>.\n</n-alert>\n\n| Property | Type | Default | Description | Version |\n| --- | --- | --- | --- | --- |\n| asyncValidator | `(rule: FormItemRule, value: any, callback: (error?: Error) => void) => void` | `undefined` | Asynchronous validation in the form of a callback. |  |\n| key | `string` | `undefined` | Unique key of this rule, which can be used to apply partial rules. See [Apply partial rules](form#partially-apply-rules.vue) example. |  |\n| level | `'error'` \\| `'warning'` | `undefined` | Validation level. If there are already errors, `'warning'` level validation would be skipped. |  |\n| message | `string` | `undefined` | Text to show when validation fails. |  |\n| renderMessage | `() => VNodeChild` | `undefined` | Render function or message. | 2.29.1 |\n| required | `boolean` | `undefined` | Is it required. |  |\n| trigger | `string \\| Array<string>` | `undefined` | Trigger type. |  |\n| validator | `(rule: FormItemRule, value: any) => boolean \\| Error` | `undefined` | Validation rule. |  |\n\n#### FormValidateMessages Type\n\n<n-alert title=\"Caveat\" type=\"warning\" style=\"margin-bottom: 16px;\">\n  Please see the default messages defined in <n-a href=\"https://github.com/yiminghe/async-validator/blob/master/src/messages.ts\" target=\"_blank\">async-validator</n-a> in order to see which messages you can override.\n</n-alert>\n\n### FormItem Props\n\n| Name | Type | Default | Description | Version |\n| --- | --- | --- | --- | --- |\n| content-class | `string` | `undefined` | The class name of the content. | 2.43.0 |\n| content-style | `string \\| object` | `undefined` | The style of the content. | 2.43.0 |\n| feedback | `string` | `undefined` | The feedback message of the form item. If set, it will replace any result of rule-based validation. |  |\n| feedback-class | `string` | `undefined` | Feedback check vertical display positioning | 2.38.2 |\n| feedback-style | `string \\| object` | `undefined` | Feedback check horizontal display positioning | 2.38.2 |\n| first | `boolean` | `false` | Whether to only show the first validation error message. |  |\n| ignore-path-change | `boolean` | `false` | Usually, changing `path` will cause a re-render and naive-ui will clear the validation result. Setting `ignore-path-change` to `true` will disable that behavior. |  |\n| label | `string` | `undefined` | Label. |  |\n| label-align | `'left' \\| 'right'` | `undefined` | Text alignment inside the label. If not set, it will inherit the parent form's `label-align`. |  |\n| label-placement | `'left' \\| 'top'` | `undefined` | If not set, it will inherit the parent form's `label-placement`. |  |\n| label-props | `LabelHTMLAttributes` | `undefined` | HTML attributes of the label element inside form item. | 2.24.0 |\n| label-style | `CSSProperties \\| string` | `undefined` | Label style. |  |\n| label-width | `number \\| string \\| 'auto'` | `undefined` | If not set, it will inherit the parent form's `label-width`,`'auto'` means label width will be auto adjusted. |  |\n| path | `string` | `undefined` | The path to use in the parent form's model object. |  |\n| required | `boolean` | `false` | Whether to show the \"required\" symbol. Note: a required rule has higher priority than this prop & this prop **won't** have any effect on validation. Validation still depends on rules. |  |\n| rule | `FormItemRule \\| Array<FormItemRule>` | `undefined` | The rule to validate this form item. It will be merged with the rules acquired by `rule-path` from the parent form's rules. It's recommended to set all rules on the parent form. |  |\n| rule-path | `string` | `undefined` | The path to get rules from the parent form's rule object. If not set, it will use the path of the parent form item instead. |  |\n| show-feedback | `boolean` | `true` | Whether to show the feedback area. |  |\n| show-label | `boolean` | `true` | Whether to show a label. If not set, it will inherit `show-label` from the parent form. |  |\n| show-require-mark | `boolean` | `-` | Whether to show required symbol. If not set, it will use `show-require-mark` from the parent form. |\n| require-mark-placement | `'left' \\| 'right' \\| 'right-hanging'` | `'right'` | Require mark placement. If not set, it will use `require-mark-placement` from the parent form. | `'right-hanging'` 2.24.0 |\n| size | `'small' \\| 'medium' \\| 'large'` | `'medium'` | Size. |  |\n| validation-status | `'error' \\| 'success' \\| 'warning'` | `undefined` | The validation status of the form item. If set, it will replace the result of the rule-based validation. |  |\n\n### FormItemGi Props\n\nAccept all props from FormItem & [GridItem](grid#GridItem-Props)\n\n### Form Methods\n\n<n-alert type=\"warning\" title=\"Caveat on Validate Method\" style=\"margin-bottom: 16px;\" :bordered=\"false\">\n  By default, validation will use all rules regardless of the triggers of the rules.\n</n-alert>\n\n| Name | Type | Description | Version |\n| --- | --- | --- | --- |\n| validate | `(validateCallback?: (errors: Array<FormValidationError> \\| undefined, extra: { warnings: Array<FormValidationError> \\| undefined }) => void, shouldRuleBeApplied?: FormItemRule => boolean) => Promise<{ warnings: Array<FormValidationError> \\| undefined }>` | Validate the form. The rejection value type of returned promise is `Array<FormValidationError>`. | `warnings` `2.37.1` |\n| restoreValidation | `() => void` | Restore validate. |  |\n| invalidateLabelWidth | `() => void` | Recalculate label widths of all form items. Useful when using `label-width=\"auto\"` and the label content changes dynamically. | NEXT_VESION |\n\n### FormItem, FormItemGi Methods\n\n| Name | Type | Description | Version |\n| --- | --- | --- | --- |\n| validate | `(options: { trigger?: string, callback?: (errors: FormValidationError \\| undefined, extra: { warnings: FormValidationError \\| undefined }) => void, shouldRuleBeApplied?: FormItemRule => boolean, options?: AsyncValidatorOptions }) => Promise<{ warnings: FormValidationError \\| undefined }>` | Validate the form item. The rejection value type of returned promise is `FormValidationError`. If trigger is not set, all rules of the item will be applied. `shouldRuleBeApplied` can filter rules after they are filtered by the trigger. | `warnings` `2.37.1` |\n| restoreValidation | `() => void` | Restore validate. |  |\n| invalidateLabelWidth | `() => void` | Recalculate the label width of this form item. Useful when using `label-width=\"auto\"` and the label content changes dynamically. | NEXT_VESION |\n\nTo find out more about AsyncValidatorOptions, see <n-a href=\"https://github.com/yiminghe/async-validator\" target=\"_blank\">async-validator</n-a>.\n\n### Form Slots\n\n| Name    | Parameters | Description |\n| ------- | ---------- | ----------- |\n| default | `()`       | Content.    |\n\n### FormItem, FormItemGi Slots\n\n| Name     | Parameters | Description    | Version |\n| -------- | ---------- | -------------- | ------- |\n| default  | `()`       | Content.       |\n| feedback | `()`       | Feedback.      | 2.24.0  |\n| label    | `()`       | Label content. |         |\n"
  },
  {
    "path": "src/form/demos/enUS/inline.demo.vue",
    "content": "<markdown>\n# Inline form\n\nAn example of an inline form.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { FormInst } from 'naive-ui'\nimport { useMessage } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst formRef = ref<FormInst | null>(null)\nconst message = useMessage()\nconst size = ref<'small' | 'medium' | 'large'>('medium')\nconst formValue = ref({\n  user: {\n    name: '',\n    age: ''\n  },\n  phone: ''\n})\n\nconst rules = {\n  user: {\n    name: {\n      required: true,\n      message: 'Please input your name',\n      trigger: 'blur'\n    },\n    age: {\n      required: true,\n      message: 'Please input your age',\n      trigger: ['input', 'blur']\n    }\n  },\n  phone: {\n    required: true,\n    message: 'Please input your number',\n    trigger: ['input']\n  }\n}\n\nfunction handleValidateClick(e: MouseEvent) {\n  e.preventDefault()\n  formRef.value?.validate((errors) => {\n    if (!errors) {\n      message.success('Valid')\n    }\n    else {\n      console.log(errors)\n      message.error('Invalid')\n    }\n  })\n}\n</script>\n\n<template>\n  <n-radio-group\n    v-model:value=\"size\"\n    name=\"left-size\"\n    style=\"margin-bottom: 12px\"\n  >\n    <n-radio-button value=\"small\">\n      Small\n    </n-radio-button>\n    <n-radio-button value=\"medium\">\n      Medium\n    </n-radio-button>\n    <n-radio-button value=\"large\">\n      Large\n    </n-radio-button>\n  </n-radio-group>\n  <n-form\n    ref=\"formRef\"\n    inline\n    :label-width=\"80\"\n    :model=\"formValue\"\n    :rules=\"rules\"\n    :size=\"size\"\n  >\n    <n-form-item label=\"Name\" path=\"user.name\">\n      <n-input v-model:value=\"formValue.user.name\" placeholder=\"Input Name\" />\n    </n-form-item>\n    <n-form-item label=\"Age\" path=\"user.age\">\n      <n-input v-model:value=\"formValue.user.age\" placeholder=\"Input Age\" />\n    </n-form-item>\n    <n-form-item label=\"Phone\" path=\"phone\">\n      <n-input v-model:value=\"formValue.phone\" placeholder=\"Phone Number\" />\n    </n-form-item>\n    <n-form-item>\n      <n-button @click=\"handleValidateClick\">\n        Validate\n      </n-button>\n    </n-form-item>\n  </n-form>\n\n  <pre>{{ JSON.stringify(formValue, null, 2) }}\n</pre>\n</template>\n"
  },
  {
    "path": "src/form/demos/enUS/item-only.demo.vue",
    "content": "<markdown>\n# Use form item alone\n\nYou can also use `n-form-item` outside of an `n-form` element.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst message = 'It is not in a Form'\nconst valueRef = ref(message)\n\nconst rule = {\n  trigger: ['input', 'blur'],\n  validator() {\n    if (valueRef.value !== message) {\n      return new Error(message)\n    }\n  }\n}\n</script>\n\n<template>\n  <n-form-item label=\"This is a FormItem\" :rule=\"rule\">\n    <n-input v-model:value=\"valueRef\" />\n  </n-form-item>\n</template>\n"
  },
  {
    "path": "src/form/demos/enUS/left.demo.vue",
    "content": "<markdown>\n# Label placement left\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { FormInst, FormItemRule, FormRules, FormSize } from 'naive-ui'\nimport { useMessage } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst formRef = ref<FormInst | null>(null)\nconst message = useMessage()\nconst size = ref<FormSize | undefined>('medium')\nconst model = ref({\n  inputValue: null,\n  textareaValue: null,\n  selectValue: null,\n  multipleSelectValue: null,\n  datetimeValue: null,\n  nestedValue: {\n    path1: null,\n    path2: null\n  },\n  switchValue: false,\n  checkboxGroupValue: null,\n  radioGroupValue: null,\n  radioButtonGroupValue: null,\n  inputNumberValue: null,\n  timePickerValue: null,\n  sliderValue: 0,\n  transferValue: null\n})\n\nconst generalOptions = ['groode', 'veli good', 'emazing', 'lidiculous'].map(\n  v => ({\n    label: v,\n    value: v\n  })\n)\n\nconst rules: FormRules = {\n  inputValue: {\n    required: true,\n    trigger: ['blur', 'input'],\n    message: 'Please input inputValue'\n  },\n  textareaValue: {\n    required: true,\n    trigger: ['blur', 'input'],\n    message: 'Please input textareaValue'\n  },\n  selectValue: {\n    required: true,\n    trigger: ['blur', 'change'],\n    message: 'Please select selectValue'\n  },\n  multipleSelectValue: {\n    type: 'array',\n    required: true,\n    trigger: ['blur', 'change'],\n    message: 'Please select multipleSelectValue'\n  },\n  datetimeValue: {\n    type: 'number',\n    required: true,\n    trigger: ['blur', 'change'],\n    message: 'Please input datetimeValue'\n  },\n  nestedValue: {\n    path1: {\n      required: true,\n      trigger: ['blur', 'input'],\n      message: 'Please input nestedValue.path1'\n    },\n    path2: {\n      required: true,\n      trigger: ['blur', 'change'],\n      message: 'Please input nestedValue.path2'\n    }\n  },\n  checkboxGroupValue: {\n    type: 'array',\n    required: true,\n    trigger: 'change',\n    message: 'Please select checkboxGroupValue'\n  },\n  radioGroupValue: {\n    required: true,\n    trigger: 'change',\n    message: 'Please select radioGroupValue'\n  },\n  radioButtonGroupValue: {\n    required: true,\n    trigger: 'change',\n    message: 'Please select radioButtonGroupValue'\n  },\n  inputNumberValue: {\n    type: 'number',\n    required: true,\n    trigger: ['blur', 'change'],\n    message: 'Please input inputNumberValue'\n  },\n  timePickerValue: {\n    type: 'number',\n    required: true,\n    trigger: ['blur', 'change'],\n    message: 'Please input timePickerValue'\n  },\n  sliderValue: {\n    validator(rule: FormItemRule, value: number) {\n      return value > 50\n    },\n    trigger: ['blur', 'change'],\n    message: 'sliderValue should be larger tha 50'\n  },\n  transferValue: {\n    type: 'array',\n    required: true,\n    trigger: 'change',\n    message: 'Please input transferValue'\n  }\n}\n\nfunction handleValidateButtonClick(e: MouseEvent) {\n  e.preventDefault()\n  formRef.value?.validate((errors) => {\n    if (!errors) {\n      message.success('Valid')\n    }\n    else {\n      console.log(errors)\n      message.error('Invalid')\n    }\n  })\n}\n</script>\n\n<template>\n  <n-radio-group\n    v-model:value=\"size\"\n    name=\"left-size\"\n    style=\"margin-bottom: 12px\"\n  >\n    <n-radio-button value=\"small\">\n      Small\n    </n-radio-button>\n    <n-radio-button value=\"medium\">\n      Medium\n    </n-radio-button>\n    <n-radio-button value=\"large\">\n      Large\n    </n-radio-button>\n  </n-radio-group>\n  <n-form\n    ref=\"formRef\"\n    :model=\"model\"\n    :rules=\"rules\"\n    label-placement=\"left\"\n    require-mark-placement=\"right-hanging\"\n    :size=\"size\"\n    label-width=\"auto\"\n    :style=\"{\n      maxWidth: '640px',\n    }\"\n  >\n    <n-form-item label=\"Input\" path=\"inputValue\">\n      <n-input v-model:value=\"model.inputValue\" placeholder=\"Input\" />\n    </n-form-item>\n    <n-form-item label=\"Textarea\" path=\"textareaValue\">\n      <n-input\n        v-model:value=\"model.textareaValue\"\n        placeholder=\"Textarea\"\n        type=\"textarea\"\n        :autosize=\"{\n          minRows: 3,\n          maxRows: 5,\n        }\"\n      />\n    </n-form-item>\n    <n-form-item label=\"Select\" path=\"selectValue\">\n      <n-select\n        v-model:value=\"model.selectValue\"\n        placeholder=\"Select\"\n        :options=\"generalOptions\"\n      />\n    </n-form-item>\n    <n-form-item label=\"Multiple Select\" path=\"multipleSelectValue\">\n      <n-select\n        v-model:value=\"model.multipleSelectValue\"\n        placeholder=\"Select\"\n        :options=\"generalOptions\"\n        multiple\n      />\n    </n-form-item>\n    <n-form-item label=\"Datetime\" path=\"datetimeValue\">\n      <n-date-picker v-model:value=\"model.datetimeValue\" type=\"datetime\" />\n    </n-form-item>\n    <n-form-item label=\"Switch\" path=\"switchValue\">\n      <n-switch v-model:value=\"model.switchValue\" />\n    </n-form-item>\n    <n-form-item label=\"Checkbox Group\" path=\"checkboxGroupValue\">\n      <n-checkbox-group v-model:value=\"model.checkboxGroupValue\">\n        <n-space>\n          <n-checkbox value=\"Option 1\">\n            Option 1\n          </n-checkbox>\n          <n-checkbox value=\"Option 2\">\n            Option 2\n          </n-checkbox>\n          <n-checkbox value=\"Option 3\">\n            Option 3\n          </n-checkbox>\n        </n-space>\n      </n-checkbox-group>\n    </n-form-item>\n    <n-form-item label=\"Radio Group\" path=\"radioGroupValue\">\n      <n-radio-group v-model:value=\"model.radioGroupValue\" name=\"radiogroup1\">\n        <n-space>\n          <n-radio value=\"Radio 1\">\n            Radio 1\n          </n-radio>\n          <n-radio value=\"Radio 2\">\n            Radio 2\n          </n-radio>\n          <n-radio value=\"Radio 3\">\n            Radio 3\n          </n-radio>\n        </n-space>\n      </n-radio-group>\n    </n-form-item>\n    <n-form-item label=\"Radio Button Group\" path=\"radioGroupValue\">\n      <n-radio-group v-model:value=\"model.radioGroupValue\" name=\"radiogroup2\">\n        <n-radio-button value=\"Radio 1\">\n          Radio 1\n        </n-radio-button>\n        <n-radio-button value=\"Radio 2\">\n          Radio 2\n        </n-radio-button>\n        <n-radio-button value=\"Radio 3\">\n          Radio 3\n        </n-radio-button>\n      </n-radio-group>\n    </n-form-item>\n    <n-form-item label=\"Input Number\" path=\"inputNumberValue\">\n      <n-input-number v-model:value=\"model.inputNumberValue\" />\n    </n-form-item>\n    <n-form-item label=\"Time Picker\" path=\"timePickerValue\">\n      <n-time-picker v-model:value=\"model.timePickerValue\" />\n    </n-form-item>\n    <n-form-item label=\"Slider\" path=\"sliderValue\">\n      <n-slider v-model:value=\"model.sliderValue\" :step=\"5\" />\n    </n-form-item>\n    <n-form-item label=\"Transfer\" path=\"transferValue\">\n      <n-transfer\n        v-model:value=\"model.transferValue\"\n        :options=\"generalOptions\"\n      />\n    </n-form-item>\n    <n-form-item label=\"Nested Path\" :show-feedback=\"false\">\n      <n-grid :cols=\"2\" :x-gap=\"24\">\n        <n-form-item-gi path=\"nestedValue.path1\">\n          <n-input\n            v-model:value=\"model.nestedValue.path1\"\n            placeholder=\"Nested Path 1\"\n          />\n        </n-form-item-gi>\n        <n-form-item-gi path=\"nestedValue.path2\">\n          <n-select\n            v-model:value=\"model.nestedValue.path2\"\n            placeholder=\"Nested Path 2\"\n            :options=\"generalOptions\"\n          />\n        </n-form-item-gi>\n      </n-grid>\n    </n-form-item>\n    <div style=\"display: flex; justify-content: flex-end\">\n      <n-button round type=\"primary\" @click=\"handleValidateButtonClick\">\n        Validate\n      </n-button>\n    </div>\n  </n-form>\n\n  <pre>{{ JSON.stringify(model, null, 2) }}\n</pre>\n</template>\n"
  },
  {
    "path": "src/form/demos/enUS/partially-apply-rules.demo.vue",
    "content": "<markdown>\n# Apply partial rules\n\nDuring the validation, you may not want to validate all items. You can use the second parameter of `form.validate` to control which rules to be applied.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { FormInst } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst formInstRef = ref<FormInst | null>(null)\nconst model = ref({\n  fieldA: '',\n  fieldB: ''\n})\n\nconst rules = {\n  fieldA: {\n    key: 'a',\n    required: true,\n    min: 3,\n    message: 'Min length is 3'\n  },\n  fieldB: {\n    required: true,\n    min: 2,\n    message: 'Min length is 2'\n  }\n}\n\nfunction clear() {\n  formInstRef.value?.restoreValidation()\n}\n\nfunction validateAll() {\n  formInstRef.value?.validate((errors) => {\n    if (errors) {\n      console.error(errors)\n    }\n  })\n}\n\nfunction validatePartial() {\n  formInstRef.value?.validate(\n    (errors) => {\n      if (errors) {\n        console.error(errors)\n      }\n    },\n    (rule) => {\n      return rule?.key === 'a'\n    }\n  )\n}\n</script>\n\n<template>\n  <n-space vertical>\n    <n-space>\n      <n-button @click=\"validatePartial\">\n        Check first field\n      </n-button>\n      <n-button @click=\"validateAll\">\n        Check all fields\n      </n-button>\n      <n-button @click=\"clear\">\n        Restore validation\n      </n-button>\n    </n-space>\n    <n-form ref=\"formInstRef\" :model=\"model\" :rules=\"rules\">\n      <n-form-item label=\"Min length 3\" path=\"fieldA\">\n        <n-input v-model:value=\"model.fieldA\" />\n      </n-form-item>\n      <n-form-item label=\"Min length 2\" path=\"fieldB\">\n        <n-input v-model:value=\"model.fieldB\" />\n      </n-form-item>\n    </n-form>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/form/demos/enUS/show-label.demo.vue",
    "content": "<markdown>\n# Show / hide label\n\nIf `show-label` will default to `true` if not set and inherit `n-form`'s `show-label`.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst formShowLabel = ref(true)\nconst formItemShowLabel = ref(true)\nconst formValue = ref({\n  user: {\n    name: '',\n    age: ''\n  },\n  phone: ''\n})\n</script>\n\n<template>\n  <n-space vertical>\n    <n-space>Form:<n-switch v-model:value=\"formShowLabel\" /></n-space>\n    <n-space>Form Item:<n-switch v-model:value=\"formItemShowLabel\" /></n-space>\n    <n-form :model=\"formValue\" :show-label=\"formShowLabel\">\n      <n-form-item\n        label=\"Name\"\n        path=\"user.name\"\n        :show-label=\"formItemShowLabel\"\n      >\n        <n-input v-model:value=\"formValue.user.name\" placeholder=\"Input Name\" />\n      </n-form-item>\n      <n-form-item label=\"Age\" path=\"user.age\">\n        <n-input v-model:value=\"formValue.user.age\" placeholder=\"Input Age\" />\n      </n-form-item>\n      <n-form-item label=\"Phone\" path=\"user.phone\">\n        <n-input v-model:value=\"formValue.phone\" placeholder=\"Input Phone\" />\n      </n-form-item>\n    </n-form>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/form/demos/enUS/top.demo.vue",
    "content": "<markdown>\n# Label placement top\n\nUse `n-grid` and `n-form-item-gi` (grid item) to style the form more exactly.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { FormInst, FormItemRule, FormRules, FormSize } from 'naive-ui'\nimport { useMessage } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst formRef = ref<FormInst | null>(null)\nconst message = useMessage()\nconst size = ref<FormSize>('medium')\nconst model = ref({\n  inputValue: null,\n  textareaValue: null,\n  selectValue: null,\n  multipleSelectValue: null,\n  datetimeValue: null,\n  nestedValue: {\n    path1: null,\n    path2: null\n  },\n  switchValue: false,\n  checkboxGroupValue: null,\n  radioGroupValue: null,\n  radioButtonGroupValue: null,\n  inputNumberValue: null,\n  timePickerValue: null,\n  sliderValue: 0,\n  transferValue: null\n})\n\nconst generalOptions = ['groode', 'veli good', 'emazing', 'lidiculous'].map(\n  v => ({\n    label: v,\n    value: v\n  })\n)\n\nconst cascaderOptions = [\n  {\n    label: 'groode',\n    value: 'groode',\n    children: [\n      {\n        label: 'veli good',\n        value: 'veli good'\n      }\n    ]\n  }\n]\n\nconst rules: FormRules = {\n  inputValue: {\n    required: true,\n    trigger: ['blur', 'input'],\n    message: 'Please input inputValue'\n  },\n  textareaValue: {\n    required: true,\n    trigger: ['blur', 'input'],\n    message: 'Please input textareaValue'\n  },\n  selectValue: {\n    required: true,\n    trigger: ['blur', 'change'],\n    message: 'Please select selectValue'\n  },\n  multipleSelectValue: {\n    type: 'array',\n    required: true,\n    trigger: ['blur', 'change'],\n    message: 'Please select multipleSelectValue'\n  },\n  datetimeValue: {\n    type: 'number',\n    required: true,\n    trigger: ['blur', 'change'],\n    message: 'Please input datetimeValue'\n  },\n  nestedValue: {\n    path1: {\n      required: true,\n      trigger: ['blur', 'input'],\n      message: 'Please input nestedValue.path1'\n    },\n    path2: {\n      required: true,\n      trigger: ['blur', 'change'],\n      message: 'Please input nestedValue.path2'\n    }\n  },\n  checkboxGroupValue: {\n    type: 'array',\n    required: true,\n    trigger: 'change',\n    message: 'Please select checkboxGroupValue'\n  },\n  radioGroupValue: {\n    required: true,\n    trigger: 'change',\n    message: 'Please select radioGroupValue'\n  },\n  radioButtonGroupValue: {\n    required: true,\n    trigger: 'change',\n    message: 'Please select radioButtonGroupValue'\n  },\n  inputNumberValue: {\n    type: 'number',\n    required: true,\n    trigger: ['blur', 'change'],\n    message: 'Please input inputNumberValue'\n  },\n  timePickerValue: {\n    type: 'number',\n    required: true,\n    trigger: ['blur', 'change'],\n    message: 'Please input timePickerValue'\n  },\n  sliderValue: {\n    validator(rule: FormItemRule, value: number) {\n      return value > 50\n    },\n    trigger: ['blur', 'change'],\n    message: 'sliderValue should be larger than 50'\n  },\n  transferValue: {\n    type: 'array',\n    required: true,\n    trigger: 'change',\n    message: 'Please input transferValue'\n  }\n}\n\nfunction handleValidateButtonClick(e: MouseEvent) {\n  e.preventDefault()\n  formRef.value?.validate((errors) => {\n    if (!errors) {\n      message.success('Valid')\n    }\n    else {\n      console.log(errors)\n      message.error('Invalid')\n    }\n  })\n}\n</script>\n\n<template>\n  <n-radio-group\n    v-model:value=\"size\"\n    name=\"left-size\"\n    style=\"margin-bottom: 12px\"\n  >\n    <n-radio-button value=\"small\">\n      Small\n    </n-radio-button>\n    <n-radio-button value=\"medium\">\n      Medium\n    </n-radio-button>\n    <n-radio-button value=\"large\">\n      Large\n    </n-radio-button>\n  </n-radio-group>\n  <n-form\n    ref=\"formRef\"\n    :model=\"model\"\n    :rules=\"rules\"\n    :size=\"size\"\n    label-placement=\"top\"\n  >\n    <n-grid :span=\"24\" :x-gap=\"24\">\n      <n-form-item-gi :span=\"12\" label=\"Input\" path=\"inputValue\">\n        <n-input v-model:value=\"model.inputValue\" placeholder=\"Input\" />\n      </n-form-item-gi>\n      <n-form-item-gi :span=\"12\" label=\"Textarea\" path=\"textareaValue\">\n        <n-input\n          v-model:value=\"model.textareaValue\"\n          placeholder=\"Textarea\"\n          type=\"textarea\"\n          :autosize=\"{\n            minRows: 3,\n            maxRows: 5,\n          }\"\n        />\n      </n-form-item-gi>\n      <n-form-item-gi :span=\"12\" label=\"Select\" path=\"selectValue\">\n        <n-select\n          v-model:value=\"model.selectValue\"\n          placeholder=\"Select\"\n          :options=\"generalOptions\"\n        />\n      </n-form-item-gi>\n      <n-form-item-gi\n        :span=\"12\"\n        label=\"Multiple Select\"\n        path=\"multipleSelectValue\"\n      >\n        <n-select\n          v-model:value=\"model.multipleSelectValue\"\n          placeholder=\"Select\"\n          :options=\"generalOptions\"\n          multiple\n        />\n      </n-form-item-gi>\n      <n-form-item-gi :span=\"12\" label=\"Datetime\" path=\"datetimeValue\">\n        <n-date-picker v-model:value=\"model.datetimeValue\" type=\"datetime\" />\n      </n-form-item-gi>\n      <n-form-item-gi :span=\"12\" label=\"Switch\" path=\"switchValue\">\n        <n-switch v-model:value=\"model.switchValue\" />\n      </n-form-item-gi>\n      <n-form-item-gi\n        :span=\"12\"\n        label=\"Checkbox Group\"\n        path=\"checkboxGroupValue\"\n      >\n        <n-checkbox-group v-model:value=\"model.checkboxGroupValue\">\n          <n-space>\n            <n-checkbox value=\"Option 1\">\n              Option 1\n            </n-checkbox>\n            <n-checkbox value=\"Option 2\">\n              Option 2\n            </n-checkbox>\n            <n-checkbox value=\"Option 3\">\n              Option 3\n            </n-checkbox>\n          </n-space>\n        </n-checkbox-group>\n      </n-form-item-gi>\n      <n-form-item-gi :span=\"12\" label=\"Radio Group\" path=\"radioGroupValue\">\n        <n-radio-group v-model:value=\"model.radioGroupValue\" name=\"radiogroup1\">\n          <n-space>\n            <n-radio value=\"Radio 1\">\n              Radio 1\n            </n-radio>\n            <n-radio value=\"Radio 2\">\n              Radio 2\n            </n-radio>\n            <n-radio value=\"Radio 3\">\n              Radio 3\n            </n-radio>\n          </n-space>\n        </n-radio-group>\n      </n-form-item-gi>\n      <n-form-item-gi\n        :span=\"12\"\n        label=\"Radio Button Group\"\n        path=\"radioGroupValue\"\n      >\n        <n-radio-group v-model:value=\"model.radioGroupValue\" name=\"radiogroup2\">\n          <n-radio-button value=\"Radio 1\">\n            Radio 1\n          </n-radio-button>\n          <n-radio-button value=\"Radio 2\">\n            Radio 2\n          </n-radio-button>\n          <n-radio-button value=\"Radio 3\">\n            Radio 3\n          </n-radio-button>\n        </n-radio-group>\n      </n-form-item-gi>\n      <n-form-item-gi :span=\"12\" label=\"Input Number\" path=\"inputNumberValue\">\n        <n-input-number v-model:value=\"model.inputNumberValue\" />\n      </n-form-item-gi>\n      <n-form-item-gi :span=\"12\" label=\"Time Picker\" path=\"timePickerValue\">\n        <n-time-picker v-model:value=\"model.timePickerValue\" />\n      </n-form-item-gi>\n      <n-form-item-gi :span=\"12\" label=\"Slider\" path=\"sliderValue\">\n        <n-slider v-model:value=\"model.sliderValue\" :step=\"5\" />\n      </n-form-item-gi>\n      <n-form-item-gi :span=\"14\" label=\"Transfer\" path=\"transferValue\">\n        <n-transfer\n          v-model:value=\"model.transferValue\"\n          style=\"width: 100%\"\n          :options=\"generalOptions\"\n        />\n      </n-form-item-gi>\n      <n-form-item-gi :span=\"5\" label=\"Nested Path\" path=\"nestedValue.path1\">\n        <n-cascader\n          v-model:value=\"model.nestedValue.path1\"\n          placeholder=\"Nested Path 1\"\n          :options=\"cascaderOptions\"\n        />\n      </n-form-item-gi>\n      <n-form-item-gi :span=\"5\" path=\"nestedValue.path2\">\n        <n-select\n          v-model:value=\"model.nestedValue.path2\"\n          placeholder=\"Nested Path 2\"\n          :options=\"generalOptions\"\n        />\n      </n-form-item-gi>\n      <n-gi :span=\"24\">\n        <div style=\"display: flex; justify-content: flex-end\">\n          <n-button round type=\"primary\" @click=\"handleValidateButtonClick\">\n            Validate\n          </n-button>\n        </div>\n      </n-gi>\n    </n-grid>\n  </n-form>\n\n  <pre>{{ JSON.stringify(model, null, 2) }}\n</pre>\n</template>\n"
  },
  {
    "path": "src/form/demos/zhCN/abnormal-warning.demo.vue",
    "content": "<markdown>\n# 异常值警告\n\n你可能需要对可能异常的值向用户显示警告，但是不希望 `validate` 方法抛出异常， 这种情况下 `FormItemRule` 的 `level` 属性可以帮到你（`level: 'warning'`）。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { FormInst, FormItemRule, FormRules } from 'naive-ui'\nimport { useMessage } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst formRef = ref<FormInst | null>(null)\nconst message = useMessage()\nconst formValue = ref({\n  count: undefined\n})\n\nconst rules = {\n  count: [\n    {\n      required: true,\n      message: '请作答',\n      type: 'number',\n      trigger: ['input', 'blur']\n    },\n    {\n      trigger: ['input', 'blur'],\n      level: 'warning',\n      validator(_rule: FormItemRule, value: number) {\n        if (value !== 4) {\n          return new Error('你确定吗？')\n        }\n        return true\n      }\n    }\n  ]\n} satisfies FormRules\n\nfunction handleValidateClick(e: MouseEvent) {\n  e.preventDefault()\n  formRef.value?.validate((errors, { warnings }) => {\n    if (errors) {\n      console.error(errors)\n      message.error('校验未通过')\n    }\n    else if (warnings) {\n      message.warning('校验通过但是留意还有警告')\n      console.warn(warnings)\n    }\n    else {\n      message.success('完美')\n    }\n  })\n}\n</script>\n\n<template>\n  <n-form ref=\"formRef\" inline :model=\"formValue\" :rules=\"rules\">\n    <n-form-item label=\"茴香豆的回有几种写法？\" path=\"count\">\n      <n-input-number v-model:value=\"formValue.count\" />\n    </n-form-item>\n    <n-form-item>\n      <n-button attr-type=\"button\" @click=\"handleValidateClick\">\n        作答\n      </n-button>\n    </n-form-item>\n  </n-form>\n</template>\n"
  },
  {
    "path": "src/form/demos/zhCN/async.demo.vue",
    "content": "<markdown>\n# 异步验证\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { FormInst, FormItemRule } from 'naive-ui'\nimport { useMessage } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst formRef = ref<FormInst | null>(null)\nconst message = useMessage()\nconst formValue = ref({\n  user: {\n    name: 'name',\n    age: '15',\n    address: '0'\n  },\n  phone: '1251550092'\n})\n\nconst rules = {\n  user: {\n    name: {\n      required: true,\n      trigger: 'blur',\n      validator: (rule: FormItemRule, value: string) => {\n        return new Promise<void>((resolve, reject) => {\n          if (value !== 'testName') {\n            reject(new Error('非正确名字')) // reject with error message\n          }\n          else {\n            resolve()\n          }\n        })\n      }\n    },\n    age: {\n      required: true,\n      trigger: 'input',\n      validator: (rule: FormItemRule, value: number) => {\n        return new Promise<void>((resolve, reject) => {\n          setTimeout(() => {\n            if (value <= 16) {\n              reject(new Error('非正确年龄'))\n            }\n            else {\n              resolve()\n            }\n          }, 3000)\n        })\n      }\n    }\n  },\n  phone: {\n    required: true,\n    trigger: ['input'],\n    validator: (rule: FormItemRule, value: string) => {\n      return /^[1]+[3,8]+\\d{9}$/.test(value)\n    }\n  }\n}\n\nfunction handleValidateClick(e: MouseEvent) {\n  e.preventDefault()\n  const messageReactive = message.loading('Verifying', {\n    duration: 0\n  })\n  formRef.value?.validate((errors) => {\n    if (!errors) {\n      message.success('Valid')\n    }\n    else {\n      message.error('Invalid')\n      console.log('errors', errors)\n    }\n    messageReactive.destroy()\n  })\n}\n</script>\n\n<template>\n  <n-form\n    ref=\"formRef\"\n    inline\n    :label-width=\"80\"\n    :model=\"formValue\"\n    :rules=\"rules\"\n  >\n    <n-form-item label=\"Name\" path=\"user.name\">\n      <n-input v-model:value=\"formValue.user.name\" placeholder=\"Input Name\" />\n    </n-form-item>\n    <n-form-item label=\"Age\" path=\"user.age\">\n      <n-input v-model:value=\"formValue.user.age\" placeholder=\"Input Age\" />\n    </n-form-item>\n    <n-form-item label=\"Adress\" path=\"user.address\">\n      <n-input\n        v-model:value=\"formValue.user.address\"\n        placeholder=\"Input Address\"\n      />\n    </n-form-item>\n    <n-form-item label=\"Phone\" path=\"phone\">\n      <n-input v-model:value=\"formValue.phone\" placeholder=\"Phone Number\" />\n    </n-form-item>\n    <n-form-item>\n      <n-button @click=\"handleValidateClick\">\n        Validate\n      </n-button>\n    </n-form-item>\n  </n-form>\n\n  <pre>{{ JSON.stringify(formValue, null, 2) }}</pre>\n</template>\n"
  },
  {
    "path": "src/form/demos/zhCN/custom-messages.demo.vue",
    "content": "<markdown>\n# 自定义默认验证信息\n\n你可以自定义 `async-validator` 的默认验证信息，不过考虑这个信息和代码耦合很严重，估计对于中文的页面没什么价值。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { FormInst } from 'naive-ui'\nimport { useMessage } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst formRef = ref<FormInst | null>(null)\nconst message = useMessage()\nconst formValue = ref({\n  user: {\n    name: ''\n  }\n})\n\nconst messages = {\n  required: '我们非常需要 %s'\n}\n\nconst rules = {\n  user: {\n    name: {\n      required: true,\n      trigger: 'blur'\n    }\n  }\n}\n\nfunction handleValidateClick(e: MouseEvent) {\n  e.preventDefault()\n  formRef.value?.validate((errors) => {\n    if (!errors) {\n      message.success('好')\n    }\n    else {\n      console.log(errors)\n      message.error('不好')\n    }\n  })\n}\n</script>\n\n<template>\n  <n-form\n    ref=\"formRef\"\n    :model=\"formValue\"\n    :rules=\"rules\"\n    :validate-messages=\"messages\"\n  >\n    <n-form-item label=\"Name\" path=\"user.name\">\n      <n-input v-model:value=\"formValue.user.name\" placeholder=\"Input Name\" />\n    </n-form-item>\n    <n-form-item>\n      <n-button @click=\"handleValidateClick\">\n        验证\n      </n-button>\n    </n-form-item>\n  </n-form>\n  <pre>{{ JSON.stringify(formValue, null, 2) }}</pre>\n</template>\n"
  },
  {
    "path": "src/form/demos/zhCN/custom-rule.demo.vue",
    "content": "<markdown>\n# 自定义规则\n\n有时候内置的 trigger 无法满足验证的需要。你可以通过设定自定的 trigger 然后手动触发它来控制验证。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { FormInst, FormItemInst, FormItemRule, FormRules } from 'naive-ui'\nimport { useMessage } from 'naive-ui'\nimport { ref } from 'vue'\n\ninterface ModelType {\n  age: string | null\n  password: string | null\n  reenteredPassword: string | null\n}\n\nconst formRef = ref<FormInst | null>(null)\nconst rPasswordFormItemRef = ref<FormItemInst | null>(null)\nconst message = useMessage()\nconst modelRef = ref<ModelType>({\n  age: null,\n  password: null,\n  reenteredPassword: null\n})\n\nfunction validatePasswordStartWith(rule: FormItemRule, value: string): boolean {\n  return (\n    !!modelRef.value.password\n    && modelRef.value.password.startsWith(value)\n    && modelRef.value.password.length >= value.length\n  )\n}\n\nfunction validatePasswordSame(rule: FormItemRule, value: string): boolean {\n  return value === modelRef.value.password\n}\n\nconst rules: FormRules = {\n  age: [\n    {\n      required: true,\n      validator(rule: FormItemRule, value: string) {\n        if (!value) {\n          return new Error('需要年龄')\n        }\n        else if (!/^\\d*$/.test(value)) {\n          return new Error('年龄应该为整数')\n        }\n        else if (Number(value) < 18) {\n          return new Error('年龄应该超过十八岁')\n        }\n        return true\n      },\n      trigger: ['input', 'blur']\n    }\n  ],\n  password: [\n    {\n      required: true,\n      message: '请输入密码'\n    }\n  ],\n  reenteredPassword: [\n    {\n      required: true,\n      message: '请再次输入密码',\n      trigger: ['input', 'blur']\n    },\n    {\n      validator: validatePasswordStartWith,\n      message: '两次密码输入不一致',\n      trigger: 'input'\n    },\n    {\n      validator: validatePasswordSame,\n      message: '两次密码输入不一致',\n      trigger: ['blur', 'password-input']\n    }\n  ]\n}\n\nfunction handlePasswordInput() {\n  if (modelRef.value.reenteredPassword) {\n    rPasswordFormItemRef.value?.validate({ trigger: 'password-input' })\n  }\n}\n\nfunction handleValidateButtonClick(e: MouseEvent) {\n  e.preventDefault()\n  formRef.value?.validate((errors) => {\n    if (!errors) {\n      message.success('验证成功')\n    }\n    else {\n      console.log(errors)\n      message.error('验证失败')\n    }\n  })\n}\n</script>\n\n<template>\n  <n-form ref=\"formRef\" :model=\"modelRef\" :rules=\"rules\">\n    <n-form-item path=\"age\" label=\"年龄\">\n      <n-input v-model:value=\"modelRef.age\" @keydown.enter.prevent />\n    </n-form-item>\n    <n-form-item path=\"password\" label=\"密码\">\n      <n-input\n        v-model:value=\"modelRef.password\"\n        type=\"password\"\n        @input=\"handlePasswordInput\"\n        @keydown.enter.prevent\n      />\n    </n-form-item>\n    <n-form-item\n      ref=\"rPasswordFormItemRef\"\n      first\n      path=\"reenteredPassword\"\n      label=\"重复密码\"\n    >\n      <n-input\n        v-model:value=\"modelRef.reenteredPassword\"\n        :disabled=\"!modelRef.password\"\n        type=\"password\"\n        @keydown.enter.prevent\n      />\n    </n-form-item>\n    <n-row :gutter=\"[0, 24]\">\n      <n-col :span=\"24\">\n        <div style=\"display: flex; justify-content: flex-end\">\n          <n-button\n            :disabled=\"modelRef.age === null\"\n            round\n            type=\"primary\"\n            @click=\"handleValidateButtonClick\"\n          >\n            验证\n          </n-button>\n        </div>\n      </n-col>\n    </n-row>\n  </n-form>\n\n  <pre>{{ JSON.stringify(modelRef, null, 2) }}</pre>\n</template>\n"
  },
  {
    "path": "src/form/demos/zhCN/custom-validation.demo.vue",
    "content": "<markdown>\n# 自定义验证\n\n你可能需要自定义验证的时机和效果，使用 `validation-status` 和 `feedback` 来控制表项的验证效果。在这种情况下通常不需要提供 `path`。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { computed, ref } from 'vue'\n\nfunction createStatus(value: string) {\n  switch (value) {\n    case '10:30':\n      return undefined\n    case '10:29':\n      return 'warning'\n    default:\n      return 'error'\n  }\n}\n\nfunction createFeedback(value: string) {\n  switch (value) {\n    case '10:30':\n      return '十点半的飞机已经到了'\n    case '10:29':\n      return '虽然差不多了，请把时间调到 10:30'\n    default:\n      return '请把时间调到 10:30'\n  }\n}\n\nfunction createTimeForNumber(num: number) {\n  return `${Number.parseInt(String(num / 100), 10)}:${num % 100}`\n}\n\nconst inputValueRef = ref('10:29')\nconst inputNumberValueRef = ref(1029)\nconst selectValueRef = ref('10:29')\n\nconst selectOptions = [\n  {\n    label: '10:28',\n    value: '10:28'\n  },\n  {\n    label: '10:29',\n    value: '10:29'\n  },\n  {\n    label: '10:30',\n    value: '10:30'\n  }\n]\n\nconst inputValidationStatus = computed(() => {\n  return createStatus(inputValueRef.value)\n})\n\nconst inputFeedback = computed(() => {\n  return createFeedback(inputValueRef.value)\n})\n\nconst inputNumberValidationStatus = computed(() => {\n  return createStatus(createTimeForNumber(inputNumberValueRef.value))\n})\n\nconst inputNumberFeedback = computed(() => {\n  return createFeedback(createTimeForNumber(inputNumberValueRef.value))\n})\n\nconst selectValidationStatus = computed(() => {\n  return createStatus(selectValueRef.value)\n})\n\nconst selectFeedback = computed(() => {\n  return createFeedback(selectValueRef.value)\n})\n</script>\n\n<template>\n  <n-form>\n    <n-form-item\n      label=\"飞机场的\"\n      :validation-status=\"inputValidationStatus\"\n      :feedback=\"inputFeedback\"\n    >\n      <n-input v-model:value=\"inputValueRef\" clearable />\n    </n-form-item>\n    <n-form-item\n      label=\"飞机场的\"\n      :validation-status=\"inputNumberValidationStatus\"\n    >\n      <n-input-number v-model:value=\"inputNumberValueRef\" />\n      <template #feedback>\n        {{ inputNumberFeedback }}\n      </template>\n    </n-form-item>\n    <n-form-item\n      label=\"飞机场的\"\n      :validation-status=\"selectValidationStatus\"\n      :feedback=\"selectFeedback\"\n    >\n      <n-select\n        v-model:value=\"selectValueRef\"\n        :options=\"selectOptions\"\n        clearable\n      />\n    </n-form-item>\n  </n-form>\n</template>\n"
  },
  {
    "path": "src/form/demos/zhCN/disabled.demo.vue",
    "content": "<markdown>\n# 表单禁用\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { computed, ref } from 'vue'\n\nfunction genOptions(depth = 2, iterator = 1, prefix = ''): any {\n  const length = 12\n  const options = []\n  for (let i = 1; i <= length; ++i) {\n    if (iterator === 1) {\n      options.push({\n        value: `${i}`,\n        label: `${i}`,\n        disabled: i % 5 === 0,\n        children: genOptions(depth, iterator + 1, `${i}`)\n      })\n    }\n    else if (iterator === depth) {\n      options.push({\n        value: `${prefix}-${i}`,\n        label: `${prefix}-${i}`,\n        disabled: i % 5 === 0\n      })\n    }\n    else {\n      options.push({\n        value: `${prefix}-${i}`,\n        label: `${prefix}-${i}`,\n        disabled: i % 5 === 0,\n        children: genOptions(depth, iterator + 1, `${prefix}-${i}`)\n      })\n    }\n  }\n  return options\n}\n\nconst model = ref({\n  inputValue: null,\n  selectValue: null,\n  autoCompleteValue: '',\n  dynamicTagsValue: ['teacher', 'frontend'],\n  cascaderValue: null,\n  datetimeValue: null,\n  switchValue: false,\n  checkboxValue: false,\n  checkboxGroupValue: null,\n  radioValue: 'Definitely Maybe',\n  radioGroupValue: null,\n  radioButtonGroupValue: null,\n  inputNumberValue: null,\n  timePickerValue: null,\n  colorValue: null,\n  sliderValue: 0,\n  transferValue: null\n})\n\nconst updateDisabled = ref(false)\n\nconst generalOptions = ['groode', 'veli good', 'emazing', 'lidiculous'].map(\n  v => ({\n    label: v,\n    value: v\n  })\n)\n\nconst options = genOptions()\n\nconst treeSelectOptions = [\n  {\n    label: 'Rubber Soul',\n    key: 'Rubber Soul',\n    children: [\n      {\n        label: 'Drive My Car',\n        key: 'Drive My Car'\n      },\n      {\n        label: 'Michelle',\n        key: 'Michelle'\n      }\n    ]\n  }\n]\n\nconst autoCompleteOptions = computed(() => {\n  return ['@gmail.com', '@163.com', '@qq.com'].map((suffix) => {\n    const prefix = model.value.autoCompleteValue.split('@')[0]\n    return {\n      label: prefix + suffix,\n      value: prefix + suffix\n    }\n  })\n})\n</script>\n\n<template>\n  <n-space vertical>\n    <n-switch v-model:value=\"updateDisabled\" />\n    <n-form\n      :model=\"model\"\n      label-placement=\"left\"\n      :label-width=\"160\"\n      :disabled=\"updateDisabled\"\n      :style=\"{\n        maxWidth: '640px',\n      }\"\n    >\n      <n-form-item label=\"Input\" path=\"inputValue\">\n        <n-input v-model:value=\"model.inputValue\" placeholder=\"Input\" />\n      </n-form-item>\n      <n-form-item label=\"Select\" path=\"selectValue\">\n        <n-select\n          v-model:value=\"model.selectValue\"\n          placeholder=\"Select\"\n          :options=\"generalOptions\"\n        />\n      </n-form-item>\n      <n-form-item label=\"Upload\" path=\"uploadValue\">\n        <n-upload>\n          <n-button>Upload file</n-button>\n        </n-upload>\n      </n-form-item>\n      <n-form-item label=\"Auto Complete\" path=\"autoCompleteValue\">\n        <n-auto-complete\n          v-model:value=\"model.autoCompleteValue\"\n          :options=\"autoCompleteOptions\"\n          placeholder=\"Email\"\n        />\n      </n-form-item>\n      <n-form-item label=\"Dynamic Tags\" path=\"dynamicTagsValue\">\n        <n-dynamic-tags v-model:value=\"model.dynamicTagsValue\" />\n      </n-form-item>\n      <n-form-item label=\"Tree Select\" path=\"treeSelectValue\">\n        <n-tree-select\n          :options=\"treeSelectOptions\"\n          default-value=\"Drive My Car\"\n        />\n      </n-form-item>\n      <n-form-item label=\"Cascader\" path=\"cascaderValue\">\n        <n-cascader\n          v-model:value=\"model.cascaderValue\"\n          placeholder=\"Cascader\"\n          :options=\"options\"\n          check-strategy=\"child\"\n          size=\"medium\"\n        />\n      </n-form-item>\n      <n-form-item label=\"Datetime\" path=\"datetimeValue\">\n        <n-date-picker v-model:value=\"model.datetimeValue\" type=\"datetime\" />\n      </n-form-item>\n      <n-form-item label=\"Switch\" path=\"switchValue\">\n        <n-switch v-model:value=\"model.switchValue\" />\n      </n-form-item>\n      <n-form-item label=\"Checkbox\" path=\"checkboxValue\">\n        <n-checkbox v-model:checked=\"model.checkboxValue\">\n          Checkbox\n        </n-checkbox>\n      </n-form-item>\n      <n-form-item label=\"Checkbox Group\" path=\"checkboxGroupValue\">\n        <n-checkbox-group v-model:value=\"model.checkboxGroupValue\">\n          <n-space>\n            <n-checkbox value=\"Option 1\">\n              Option 1\n            </n-checkbox>\n            <n-checkbox value=\"Option 2\">\n              Option 2\n            </n-checkbox>\n            <n-checkbox value=\"Option 3\">\n              Option 3\n            </n-checkbox>\n          </n-space>\n        </n-checkbox-group>\n      </n-form-item>\n      <n-form-item label=\"Radio\" path=\"radioValue\">\n        <n-radio\n          :checked=\"model.radioValue === 'Definitely Maybe'\"\n          value=\"Definitely Maybe\"\n          name=\"basic-demo\"\n        >\n          Definitely Maybe\n        </n-radio>\n      </n-form-item>\n      <n-form-item label=\"Radio Group\" path=\"radioGroupValue\">\n        <n-radio-group v-model:value=\"model.radioGroupValue\" name=\"radiogroup2\">\n          <n-radio value=\"Radio 1\">\n            Radio 1\n          </n-radio>\n          <n-radio value=\"Radio 2\">\n            Radio 2\n          </n-radio>\n          <n-radio value=\"Radio 3\">\n            Radio 3\n          </n-radio>\n        </n-radio-group>\n      </n-form-item>\n      <n-form-item label=\"Radio Button Group\" path=\"radioGroupValue\">\n        <n-radio-group v-model:value=\"model.radioGroupValue\" name=\"radiogroup2\">\n          <n-radio-button value=\"Radio 1\">\n            Radio 1\n          </n-radio-button>\n          <n-radio-button value=\"Radio 2\">\n            Radio 2\n          </n-radio-button>\n          <n-radio-button value=\"Radio 3\">\n            Radio 3\n          </n-radio-button>\n        </n-radio-group>\n      </n-form-item>\n      <n-form-item label=\"Input Number\" path=\"inputNumberValue\">\n        <n-input-number v-model:value=\"model.inputNumberValue\" />\n      </n-form-item>\n      <n-form-item label=\"Time Picker\" path=\"timePickerValue\">\n        <n-time-picker v-model:value=\"model.timePickerValue\" />\n      </n-form-item>\n      <n-form-item label=\"Color Picker\" path=\"colorValue\">\n        <n-color-picker v-model:value=\"model.colorValue\" />\n      </n-form-item>\n      <n-form-item label=\"Slider\" path=\"sliderValue\">\n        <n-slider v-model:value=\"model.sliderValue\" :step=\"5\" />\n      </n-form-item>\n      <n-form-item label=\"Transfer\" path=\"transferValue\">\n        <n-transfer\n          v-model:value=\"model.transferValue\"\n          :options=\"generalOptions\"\n        />\n      </n-form-item>\n    </n-form>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/form/demos/zhCN/dynamic.demo.vue",
    "content": "<markdown>\n# 动态表单\n\n动态增加、删除表单项。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { FormInst } from 'naive-ui'\nimport { reactive, ref } from 'vue'\n\nconst formRef = ref<FormInst | null>(null)\n\nconst dynamicForm = reactive({\n  name: '',\n  hobbies: [{ hobby: '' }]\n})\n\nfunction removeItem(index: number) {\n  dynamicForm.hobbies.splice(index, 1)\n}\n\nfunction addItem() {\n  dynamicForm.hobbies.push({ hobby: '' })\n}\n\nfunction handleValidateClick() {\n  formRef.value?.validate((errors) => {\n    if (!errors) {\n      console.log('验证通过')\n    }\n    else {\n      console.log(errors)\n    }\n  })\n}\n</script>\n\n<template>\n  <n-form ref=\"formRef\" :model=\"dynamicForm\" :style=\"{ maxWidth: '640px' }\">\n    <n-form-item\n      label=\"姓名\"\n      path=\"name\"\n      :rule=\"{\n        required: true,\n        message: '请输入姓名',\n        trigger: ['input', 'blur'],\n      }\"\n    >\n      <n-input v-model:value=\"dynamicForm.name\" clearable />\n    </n-form-item>\n\n    <n-form-item\n      v-for=\"(item, index) in dynamicForm.hobbies\"\n      :key=\"index\"\n      :label=\"`爱好${index + 1}`\"\n      :path=\"`hobbies[${index}].hobby`\"\n      :rule=\"{\n        required: true,\n        message: `请输入爱好${index + 1}`,\n        trigger: ['input', 'blur'],\n      }\"\n    >\n      <n-input v-model:value=\"item.hobby\" clearable />\n      <n-button style=\"margin-left: 12px\" @click=\"removeItem(index)\">\n        删除\n      </n-button>\n    </n-form-item>\n\n    <n-form-item>\n      <n-space>\n        <n-button attr-type=\"button\" @click=\"handleValidateClick\">\n          验证\n        </n-button>\n        <n-button attr-type=\"button\" @click=\"addItem\">\n          增加\n        </n-button>\n      </n-space>\n    </n-form-item>\n  </n-form>\n</template>\n"
  },
  {
    "path": "src/form/demos/zhCN/feedback-style.demo.vue",
    "content": "<markdown>\n# 自定义反馈样式\n\n使用 `feedback-style` 和 `feedback-class` 可以自定义反馈信息的样式。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { reactive } from 'vue'\n\ninterface FormValue {\n  input: string | null\n}\n\nconst formValue: FormValue = reactive({\n  input: null\n})\n</script>\n\n<template>\n  <n-form :model=\"formValue\">\n    <n-form-item\n      :rule=\"{\n        required: true,\n        message: '居中的 feedback',\n        type: 'string',\n        trigger: ['input', 'blur'],\n      }\"\n      label=\"Feedback 居中\"\n      path=\"input\"\n      feedback-style=\"text-align: center;\"\n    >\n      <n-input v-model:value=\"formValue.input\" />\n    </n-form-item>\n  </n-form>\n</template>\n"
  },
  {
    "path": "src/form/demos/zhCN/i18n.demo.vue",
    "content": "<markdown>\n# 国际化\n\n表单的规则支持 `renderMessage`，你可以利用它来完成验证信息的国际化。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { FormRules } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst localeRef = ref('语言1')\nconst rules: FormRules = {\n  input: {\n    required: true,\n    trigger: ['focus', 'input'],\n    renderMessage: () => {\n      return localeRef.value === '语言1'\n        ? '抽离透传归因分析作为抓手为产品赋能'\n        : '方法论是组合拳达到平台化标准'\n    }\n  }\n}\nconst modelRef = ref({\n  input: ''\n})\n</script>\n\n<template>\n  <n-space vertical>\n    <n-radio-group v-model:value=\"localeRef\">\n      <n-space>\n        <n-radio label=\"语言1\" value=\"语言1\" />\n        <n-radio label=\"语言2\" value=\"语言2\" />\n      </n-space>\n    </n-radio-group>\n    <n-form :model=\"modelRef\" :rules=\"rules\">\n      <n-form-item label=\"输入点什么去掉 error\" path=\"input\">\n        <n-input v-model:value=\"modelRef.input\" />\n      </n-form-item>\n    </n-form>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/form/demos/zhCN/index.demo-entry.md",
    "content": "# 表单 Form\n\n<!--single-column-->\n\n收集、验证信息。\n\n<n-alert type=\"warning\" title=\"注意\" :bordered=\"false\">\n  如果你需要为一个值为 number 类型的表项设定 required，你需要在 rule 对象中设定 <n-text code>`type: 'number'`</n-text>。\n</n-alert>\n\n## 演示\n\n```demo\ninline.vue\ncustom-rule.vue\nabnormal-warning.vue\ncustom-validation.vue\ni18n.vue\ntop.vue\nleft.vue\nitem-only.vue\nasync.vue\ndisabled.vue\nshow-label.vue\npartially-apply-rules.vue\ncustom-messages.vue\ndynamic.vue\nfeedback-style.vue\n```\n\n## API\n\n### Form Props\n\n| 名称 | 类型 | 默认值 | 说明 | 版本 |\n| --- | --- | --- | --- | --- |\n| disabled | `boolean` | `false` | 是否禁用 |  |\n| inline | `boolean` | `false` | 是否展示为行内表单 |  |\n| label-width | `number \\| string \\| 'auto'` | `undefined` | 标签的宽度，在 `label-placement` 是 `'left'` 的时候可能会有用，`'auto'` 意味着 label width 会被自动调整 |  |\n| label-align | `'left' \\| 'right'` | `-` | 标签的文本对齐方式 |  |\n| label-placement | `'left' \\| 'top'` | `'top'` | 标签显示的位置 |  |\n| model | `Object` | `{}` | 获取表项中收集到的值的对象 |  |\n| rules | `type FormRules = { [itemValidatePath: string]: FormItemRule \\| Array<FormItemRule> \\| FormRules }` | `{}` | 验证表项的规则 |  |\n| show-feedback | `boolean` | `true` | 是否展示校验反馈 |  |\n| show-label | `boolean` | `true` | 是否展示标签 |  |\n| show-require-mark | `boolean` | `-` | 是否展示必填的星号 |  |\n| require-mark-placement | `'left' \\| 'right' \\| 'right-hanging'` | `'right'` | 必填星号的位置 | `'right-hanging'` 2.24.0 |\n| size | `'small' \\| 'medium' \\| 'large'` | `'medium'` | 尺寸 |  |\n| validate-messages | `FormValidateMessages` | `undefined` | `async-validator` 的默认验证信息 | 2.27.0 |\n\n#### FormItemRule Type\n\n<n-alert title=\"注意\" type=\"warning\" style=\"margin-bottom: 16px;\" :bordered=\"false\">\n  以下并不是规则的全部用法，如果你想了解更多的用法，请参考 <n-a href=\"https://github.com/yiminghe/async-validator\" target=\"_blank\">async-validator</n-a>。\n</n-alert>\n\n| 属性 | 类型 | 默认值 | 说明 | 版本 |\n| --- | --- | --- | --- | --- |\n| asyncValidator | `(rule: FormItemRule, value: any, callback: (error?: Error) => void) => void` | `undefined` | 异步校验，支持定义回调函数 |  |\n| key | `string` | `undefined` | 规则的唯一 key，可用于只执行部分规则验证。参考示例 [只执行部分规则](form#partially-apply-rules.vue) |  |\n| level | `'error'` \\| `'warning'` | `undefined` | 验证级别。如果存在 `error` 级别错误，则会跳过 `warning` 级别验证 |  |\n| message | `string` | `undefined` | 校验失败时展示的信息 |  |\n| renderMessage | `() => VNodeChild` | `undefined` | 信息的渲染函数 | 2.29.1 |\n| required | `boolean` | `undefined` | 是否必填 |  |\n| trigger | `string \\| Array<string>` | `undefined` | 触发方式 |  |\n| validator | `(rule: FormItemRule, value: any) => boolean \\| Error` | `undefined` | 校验规则 |  |\n\n### FormItem Props\n\n| 名称 | 类型 | 默认值 | 说明 | 版本 |\n| --- | --- | --- | --- | --- |\n| content-class | `string` | `undefined` | 内容的类名 | 2.43.0 |\n| content-style | `string \\| object` | `undefined` | 内容的样式 | 2.43.0 |\n| feedback | `string` | `undefined` | 表项的反馈信息。不设为 `undefined` 时，会覆盖规则验证的结果 |  |\n| feedback-class | `string` | `undefined` | 反馈校验竖向展示定位 | 2.38.2 |\n| feedback-style | `string \\| object` | `undefined` | 反馈校验横向展示定位 | 2.38.2 |\n| first | `boolean` | `false` | 是否只展示首个出错信息 |  |\n| ignore-path-change | `boolean` | `false` | 通常 `path` 的改变会导致数据来源的变化，所以 naive-ui 会清空验证信息。如果不期望这个行为，可以将其置为 `true` |  |\n| label | `string` | `undefined` | 标签信息 |  |\n| label-align | `'left' \\| 'right'` | `undefined` | 标签的文本对齐方式。如果没有被设定，使用外层表单的 `label-align` |  |\n| label-placement | `'left' \\| 'top'` | `undefined` | 如果没有被设定，使用外层表单的 `label-placement` |  |\n| label-style | `CSSProperties \\| string` | `undefined` | 标签的样式 |  |\n| label-props | `LabelHTMLAttributes` | `undefined` | 标签元素的属性 | 2.24.0 |\n| label-width | `number \\| string \\| 'auto'` | `undefined` | 如果没有被设定，使用外层表单的 `label-width`，`'auto'` 意味着 label width 会被自动调整 |  |\n| path | `string` | `undefined` | 将值收集到外层表单 `model` 对象的路径 |  |\n| rule | `FormItemRule \\| Array<FormItemRule>` | `undefined` | 验证表项的规则，它会被通过 `rule-path` 从外层表单获取的规则合并来作为表项的验证规则。推荐还是在外层表单设置所有规则 |  |\n| rule-path | `string` | `undefined` | 从外层表单的 `rules` 对象获取规则的路径。如果没有设定，使用表项的 `path` 代替 |  |\n| show-feedback | `boolean` | `true` | 是否展示校验反馈 |  |\n| show-label | `boolean` | `true` | 是否展示标签。如果没有被设定，使用外层 `n-form` 的 `show-label` |  |\n| show-require-mark | `boolean` | `-` | 是否展示必填的星号。如果没有被设定，使用外层 `n-form` 的 `show-require-mark` |  |\n| require-mark-placement | `'left' \\| 'right' \\| 'right-hanging'` | `'right'` | 必填的星号的位置。如果没有被设定，使用外层 `n-form` 的 `require-mark-placement` | `'right-hanging'` 2.24.0 |\n| size | `'small' \\| 'medium' \\| 'large'` | `'medium'` | 尺寸 |  |\n| validation-status | `'error' \\| 'success' \\| 'warning'` | `undefined` | 表单的验证状态。不设为 `undefined`时，会覆盖规则验证的结果 |  |\n\n### FormItemGi Props\n\n接受 FormItem & [GridItem](grid#GridItem-Props) 所有的 Props。\n\n### Form Methods\n\n<n-alert type=\"warning\" title=\"Validate 方法的注意事项\" style=\"margin-bottom: 16px;\" :bordered=\"false\">\n  默认情况下，验证将会在合法表项的所有规则上进行，不管规则的 trigger 是什么\n</n-alert>\n\n| 名称 | 类型 | 说明 | 版本 |\n| --- | --- | --- | --- |\n| validate | `(validateCallback?: (errors: Array<FormValidationError> \\| undefined, extra: { warnings: Array<FormValidationError> \\| undefined }) => void, shouldRuleBeApplied?: FormItemRule => boolean) => Promise<{ warnings: Array<FormValidationError> \\| undefined }>` | 验证表单，Promise rejection 的返回值类型是 `Array<FormValidationError>` | `warnings` `2.37.1` |\n| restoreValidation | `() => void` | 还原到未校验的状态 |  |\n| invalidateLabelWidth | `() => void` | 重新计算所有表项的标签宽度。在使用 `label-width=\"auto\"` 且标签内容动态变化时有用 | NEXT_VESION |\n\n### FormItem, FormItemGi Methods\n\n| 名称 | 类型 | 说明 | 版本 |\n| --- | --- | --- | --- |\n| validate | `(options: { trigger?: string, callback?: (errors: FormValidationError \\| undefined, extra: { warnings: FormValidationError \\| undefined }) => void, shouldRuleBeApplied?: FormItemRule => boolean, options?: AsyncValidatorOptions }) => Promise<{ warnings: FormValidationError \\| undefined }>` | 验证表项，Promise rejection 的返回值类型是 `FormValidationError`。如果不设定 `trigger`，这一个表项全部的规则都会被使用。`shouldRuleBeApplied` 可以用来进一步过滤已经经过 `trigger` 筛选的规则 | `warnings` `2.37.1` |\n| restoreValidation | `() => void` | 还原到未校验的状态 |  |\n| invalidateLabelWidth | `() => void` | 重新计算该表项的标签宽度。在使用 `label-width=\"auto\"` 且标签内容动态变化时有用 | NEXT_VESION |\n\n关于 AsyncValidatorOptions，参考 <n-a href=\"https://github.com/yiminghe/async-validator\" target=\"_blank\">async-validator</n-a>。\n\n### Form Slots\n\n| 名称    | 参数 | 说明 |\n| ------- | ---- | ---- |\n| default | `()` | 内容 |\n\n### FormItem, FormItemGi Slots\n\n| 名称     | 参数 | 说明           | 版本   |\n| -------- | ---- | -------------- | ------ |\n| default  | `()` | 内容           |\n| feedback | `()` | 表项的反馈信息 | 2.24.0 |\n| label    | `()` | 标签内容       |        |\n"
  },
  {
    "path": "src/form/demos/zhCN/inline.demo.vue",
    "content": "<markdown>\n# 行内表单\n\n一个行内表单的例子。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { FormInst } from 'naive-ui'\nimport { useMessage } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst formRef = ref<FormInst | null>(null)\nconst message = useMessage()\nconst size = ref<'small' | 'medium' | 'large'>('medium')\nconst formValue = ref({\n  user: {\n    name: '',\n    age: ''\n  },\n  phone: ''\n})\n\nconst rules = {\n  user: {\n    name: {\n      required: true,\n      message: '请输入姓名',\n      trigger: 'blur'\n    },\n    age: {\n      required: true,\n      message: '请输入年龄',\n      trigger: ['input', 'blur']\n    }\n  },\n  phone: {\n    required: true,\n    message: '请输入电话号码',\n    trigger: ['input']\n  }\n}\n\nfunction handleValidateClick(e: MouseEvent) {\n  e.preventDefault()\n  formRef.value?.validate((errors) => {\n    if (!errors) {\n      message.success('Valid')\n    }\n    else {\n      console.log(errors)\n      message.error('Invalid')\n    }\n  })\n}\n</script>\n\n<template>\n  <n-radio-group\n    v-model:value=\"size\"\n    name=\"left-size\"\n    style=\"margin-bottom: 12px\"\n  >\n    <n-radio-button value=\"small\">\n      小\n    </n-radio-button>\n    <n-radio-button value=\"medium\">\n      中\n    </n-radio-button>\n    <n-radio-button value=\"large\">\n      大\n    </n-radio-button>\n  </n-radio-group>\n  <n-form\n    ref=\"formRef\"\n    inline\n    :label-width=\"80\"\n    :model=\"formValue\"\n    :rules=\"rules\"\n    :size=\"size\"\n  >\n    <n-form-item label=\"姓名\" path=\"user.name\">\n      <n-input v-model:value=\"formValue.user.name\" placeholder=\"输入姓名\" />\n    </n-form-item>\n    <n-form-item label=\"年龄\" path=\"user.age\">\n      <n-input v-model:value=\"formValue.user.age\" placeholder=\"输入年龄\" />\n    </n-form-item>\n    <n-form-item label=\"电话号码\" path=\"phone\">\n      <n-input v-model:value=\"formValue.phone\" placeholder=\"电话号码\" />\n    </n-form-item>\n    <n-form-item>\n      <n-button attr-type=\"button\" @click=\"handleValidateClick\">\n        验证\n      </n-button>\n    </n-form-item>\n  </n-form>\n\n  <pre>{{ JSON.stringify(formValue, null, 2) }}</pre>\n</template>\n"
  },
  {
    "path": "src/form/demos/zhCN/item-only.demo.vue",
    "content": "<markdown>\n# 只使用 FormItem\n\n你可以单独使用 `n-form-item`，不在 `n-form` 中验证表项。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst message = '它不在 Form 里面'\nconst valueRef = ref(message)\n\nconst rule = {\n  trigger: ['input', 'blur'],\n  validator() {\n    if (valueRef.value !== message) {\n      return new Error(message)\n    }\n  }\n}\n</script>\n\n<template>\n  <n-form-item label=\"这是个 FormItem\" :rule=\"rule\">\n    <n-input v-model:value=\"valueRef\" />\n  </n-form-item>\n</template>\n"
  },
  {
    "path": "src/form/demos/zhCN/left.demo.vue",
    "content": "<markdown>\n# 标签左置\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { FormInst, FormItemRule, FormRules, FormSize } from 'naive-ui'\nimport { useMessage } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst formRef = ref<FormInst | null>(null)\nconst message = useMessage()\nconst size = ref<FormSize | undefined>('medium')\nconst model = ref({\n  inputValue: null,\n  textareaValue: null,\n  selectValue: null,\n  multipleSelectValue: null,\n  datetimeValue: null,\n  nestedValue: {\n    path1: null,\n    path2: null\n  },\n  switchValue: false,\n  checkboxGroupValue: null,\n  radioGroupValue: null,\n  radioButtonGroupValue: null,\n  inputNumberValue: null,\n  timePickerValue: null,\n  sliderValue: 0,\n  transferValue: null\n})\n\nconst generalOptions = ['groode', 'veli good', 'emazing', 'lidiculous'].map(\n  v => ({\n    label: v,\n    value: v\n  })\n)\n\nconst rules: FormRules = {\n  inputValue: {\n    required: true,\n    trigger: ['blur', 'input'],\n    message: '请输入 inputValue'\n  },\n  textareaValue: {\n    required: true,\n    trigger: ['blur', 'input'],\n    message: '请输入 textareaValue'\n  },\n  selectValue: {\n    required: true,\n    trigger: ['blur', 'change'],\n    message: '请选择 selectValue'\n  },\n  multipleSelectValue: {\n    type: 'array',\n    required: true,\n    trigger: ['blur', 'change'],\n    message: '请选择 multipleSelectValue'\n  },\n  datetimeValue: {\n    type: 'number',\n    required: true,\n    trigger: ['blur', 'change'],\n    message: '请输入 datetimeValue'\n  },\n  nestedValue: {\n    path1: {\n      required: true,\n      trigger: ['blur', 'input'],\n      message: '请输入 nestedValue.path1'\n    },\n    path2: {\n      required: true,\n      trigger: ['blur', 'change'],\n      message: '请输入 nestedValue.path2'\n    }\n  },\n  checkboxGroupValue: {\n    type: 'array',\n    required: true,\n    trigger: 'change',\n    message: '请选择 checkboxGroupValue'\n  },\n  radioGroupValue: {\n    required: true,\n    trigger: 'change',\n    message: '请选择 radioGroupValue'\n  },\n  radioButtonGroupValue: {\n    required: true,\n    trigger: 'change',\n    message: '请选择 radioButtonGroupValue'\n  },\n  inputNumberValue: {\n    type: 'number',\n    required: true,\n    trigger: ['blur', 'change'],\n    message: '请输入 inputNumberValue'\n  },\n  timePickerValue: {\n    type: 'number',\n    required: true,\n    trigger: ['blur', 'change'],\n    message: '请输入 timePickerValue'\n  },\n  sliderValue: {\n    validator(rule: FormItemRule, value: number) {\n      return value > 50\n    },\n    trigger: ['blur', 'change'],\n    message: 'sliderValue 需要大于 50'\n  },\n  transferValue: {\n    type: 'array',\n    required: true,\n    trigger: 'change',\n    message: '请输入 transferValue'\n  }\n}\n\nfunction handleValidateButtonClick(e: MouseEvent) {\n  e.preventDefault()\n  formRef.value?.validate((errors) => {\n    if (!errors) {\n      message.success('验证成功')\n    }\n    else {\n      console.log(errors)\n      message.error('验证失败')\n    }\n  })\n}\n</script>\n\n<template>\n  <n-radio-group\n    v-model:value=\"size\"\n    name=\"left-size\"\n    style=\"margin-bottom: 12px\"\n  >\n    <n-radio-button value=\"small\">\n      小\n    </n-radio-button>\n    <n-radio-button value=\"medium\">\n      中\n    </n-radio-button>\n    <n-radio-button value=\"large\">\n      大\n    </n-radio-button>\n  </n-radio-group>\n  <n-form\n    ref=\"formRef\"\n    :model=\"model\"\n    :rules=\"rules\"\n    label-placement=\"left\"\n    label-width=\"auto\"\n    require-mark-placement=\"right-hanging\"\n    :size=\"size\"\n    :style=\"{\n      maxWidth: '640px',\n    }\"\n  >\n    <n-form-item label=\"Input\" path=\"inputValue\">\n      <n-input v-model:value=\"model.inputValue\" placeholder=\"Input\" />\n    </n-form-item>\n    <n-form-item label=\"Textarea\" path=\"textareaValue\">\n      <n-input\n        v-model:value=\"model.textareaValue\"\n        placeholder=\"Textarea\"\n        type=\"textarea\"\n        :autosize=\"{\n          minRows: 3,\n          maxRows: 5,\n        }\"\n      />\n    </n-form-item>\n    <n-form-item label=\"Select\" path=\"selectValue\">\n      <n-select\n        v-model:value=\"model.selectValue\"\n        placeholder=\"Select\"\n        :options=\"generalOptions\"\n      />\n    </n-form-item>\n    <n-form-item label=\"Multiple Select\" path=\"multipleSelectValue\">\n      <n-select\n        v-model:value=\"model.multipleSelectValue\"\n        placeholder=\"Select\"\n        :options=\"generalOptions\"\n        multiple\n      />\n    </n-form-item>\n    <n-form-item label=\"Datetime\" path=\"datetimeValue\">\n      <n-date-picker v-model:value=\"model.datetimeValue\" type=\"datetime\" />\n    </n-form-item>\n    <n-form-item label=\"Switch\" path=\"switchValue\">\n      <n-switch v-model:value=\"model.switchValue\" />\n    </n-form-item>\n    <n-form-item label=\"Checkbox Group\" path=\"checkboxGroupValue\">\n      <n-checkbox-group v-model:value=\"model.checkboxGroupValue\">\n        <n-space>\n          <n-checkbox value=\"Option 1\">\n            Option 1\n          </n-checkbox>\n          <n-checkbox value=\"Option 2\">\n            Option 2\n          </n-checkbox>\n          <n-checkbox value=\"Option 3\">\n            Option 3\n          </n-checkbox>\n        </n-space>\n      </n-checkbox-group>\n    </n-form-item>\n    <n-form-item label=\"Radio Group\" path=\"radioGroupValue\">\n      <n-radio-group v-model:value=\"model.radioGroupValue\" name=\"radiogroup1\">\n        <n-space>\n          <n-radio value=\"Radio 1\">\n            Radio 1\n          </n-radio>\n          <n-radio value=\"Radio 2\">\n            Radio 2\n          </n-radio>\n          <n-radio value=\"Radio 3\">\n            Radio 3\n          </n-radio>\n        </n-space>\n      </n-radio-group>\n    </n-form-item>\n    <n-form-item label=\"Radio Button Group\" path=\"radioGroupValue\">\n      <n-radio-group v-model:value=\"model.radioGroupValue\" name=\"radiogroup2\">\n        <n-radio-button value=\"Radio 1\">\n          Radio 1\n        </n-radio-button>\n        <n-radio-button value=\"Radio 2\">\n          Radio 2\n        </n-radio-button>\n        <n-radio-button value=\"Radio 3\">\n          Radio 3\n        </n-radio-button>\n      </n-radio-group>\n    </n-form-item>\n    <n-form-item label=\"Input Number\" path=\"inputNumberValue\">\n      <n-input-number v-model:value=\"model.inputNumberValue\" />\n    </n-form-item>\n    <n-form-item label=\"Time Picker\" path=\"timePickerValue\">\n      <n-time-picker v-model:value=\"model.timePickerValue\" />\n    </n-form-item>\n    <n-form-item label=\"Slider\" path=\"sliderValue\">\n      <n-slider v-model:value=\"model.sliderValue\" :step=\"5\" />\n    </n-form-item>\n    <n-form-item label=\"Transfer\" path=\"transferValue\">\n      <n-transfer\n        v-model:value=\"model.transferValue\"\n        :options=\"generalOptions\"\n      />\n    </n-form-item>\n    <n-form-item label=\"Nested Path\" :show-feedback=\"false\">\n      <n-grid :cols=\"2\" :x-gap=\"24\">\n        <n-form-item-gi path=\"nestedValue.path1\">\n          <n-input\n            v-model:value=\"model.nestedValue.path1\"\n            placeholder=\"Nested Path 1\"\n          />\n        </n-form-item-gi>\n        <n-form-item-gi path=\"nestedValue.path2\">\n          <n-select\n            v-model:value=\"model.nestedValue.path2\"\n            placeholder=\"Nested Path 2\"\n            :options=\"generalOptions\"\n          />\n        </n-form-item-gi>\n      </n-grid>\n    </n-form-item>\n    <div style=\"display: flex; justify-content: flex-end\">\n      <n-button round type=\"primary\" @click=\"handleValidateButtonClick\">\n        验证\n      </n-button>\n    </div>\n  </n-form>\n\n  <pre>{{ JSON.stringify(model, null, 2) }}</pre>\n</template>\n"
  },
  {
    "path": "src/form/demos/zhCN/partially-apply-rules.demo.vue",
    "content": "<markdown>\n# 只执行部分规则\n\n在验证的过程中，你可能并不总想验证全部的表单项，你可以使用 `form.validate` 的第二个参数控制应用的规则。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { FormInst } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst formInstRef = ref<FormInst | null>(null)\nconst model = ref({\n  fieldA: '',\n  fieldB: ''\n})\n\nconst rules = {\n  fieldA: {\n    key: 'a',\n    required: true,\n    min: 3,\n    message: '最短长度为 3'\n  },\n  fieldB: {\n    required: true,\n    min: 2,\n    message: '最短长度为 2'\n  }\n}\n\nfunction clear() {\n  formInstRef.value?.restoreValidation()\n}\n\nfunction validateAll() {\n  formInstRef.value?.validate((errors) => {\n    if (errors) {\n      console.error(errors)\n    }\n  })\n}\n\nfunction validatePartial() {\n  formInstRef.value?.validate(\n    (errors) => {\n      if (errors) {\n        console.error(errors)\n      }\n    },\n    (rule) => {\n      return rule?.key === 'a'\n    }\n  )\n}\n</script>\n\n<template>\n  <n-space vertical>\n    <n-space>\n      <n-button @click=\"validatePartial\">\n        检查第一个字段\n      </n-button>\n      <n-button @click=\"validateAll\">\n        执行全部规则\n      </n-button>\n      <n-button @click=\"clear\">\n        清空验证\n      </n-button>\n    </n-space>\n    <n-form ref=\"formInstRef\" :model=\"model\" :rules=\"rules\">\n      <n-form-item label=\"最短长度为 3\" path=\"fieldA\">\n        <n-input v-model:value=\"model.fieldA\" />\n      </n-form-item>\n      <n-form-item label=\"最短长度为 2\" path=\"fieldB\">\n        <n-input v-model:value=\"model.fieldB\" />\n      </n-form-item>\n    </n-form>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/form/demos/zhCN/render-feedback.demo.vue",
    "content": "<markdown>\n# 自定义 n-form-item 的渲染方式\n\n可是为什么不在 rule 里面定义呢？\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { h, ref } from 'vue'\n\nconst message = '它不在 Form 里面'\nconst valueRef = ref(message)\n\nfunction formatFeedback(raw: string | undefined) {\n  return h('div', { style: 'color: green' }, [`${raw}而且是绿的`])\n}\n\nconst rule = {\n  trigger: ['input', 'blur'],\n  validator() {\n    if (valueRef.value !== message) {\n      return new Error(message)\n    }\n  }\n}\n</script>\n\n<template>\n  <n-form-item\n    :render-feedback=\"formatFeedback\"\n    label=\"这是个 FormItem\"\n    :rule=\"rule\"\n  >\n    <n-input v-model:value=\"valueRef\" />\n  </n-form-item>\n</template>\n"
  },
  {
    "path": "src/form/demos/zhCN/show-label.demo.vue",
    "content": "<markdown>\n# 显示/隐藏标签\n\n若 `show-label` 在 `n-form-item` 上未被设定，则会继承 `n-form` 的 `show-label`，默认为 `true`。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst formShowLabel = ref(true)\nconst formItemShowLabel = ref(true)\nconst formValue = ref({\n  user: {\n    name: '',\n    age: ''\n  },\n  phone: ''\n})\n</script>\n\n<template>\n  <n-space vertical>\n    <n-space>Form:<n-switch v-model:value=\"formShowLabel\" /></n-space>\n    <n-space>Form Item:<n-switch v-model:value=\"formItemShowLabel\" /></n-space>\n    <n-form :model=\"formValue\" :show-label=\"formShowLabel\">\n      <n-form-item\n        label=\"姓名\"\n        path=\"user.name\"\n        :show-label=\"formItemShowLabel\"\n      >\n        <n-input v-model:value=\"formValue.user.name\" placeholder=\"输入姓名\" />\n      </n-form-item>\n      <n-form-item label=\"年龄\" path=\"user.age\">\n        <n-input v-model:value=\"formValue.user.age\" placeholder=\"输入年龄\" />\n      </n-form-item>\n      <n-form-item label=\"电话号码\" path=\"user.phone\">\n        <n-input v-model:value=\"formValue.phone\" placeholder=\"电话号码\" />\n      </n-form-item>\n    </n-form>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/form/demos/zhCN/top.demo.vue",
    "content": "<markdown>\n# 标签上置\n\n使用 `n-grid` 和 `n-form-item-gi`（grid item）轻松写表单。\n</markdown>\n\n<script setup lang=\"ts\">\nimport type { FormInst, FormItemRule, FormRules, FormSize } from 'naive-ui'\nimport { useMessage } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst formRef = ref<FormInst | null>(null)\nconst message = useMessage()\nconst size = ref<FormSize>('medium')\n\nconst model = ref({\n  inputValue: null,\n  textareaValue: null,\n  selectValue: null,\n  multipleSelectValue: null,\n  datetimeValue: null,\n  nestedValue: {\n    path1: null,\n    path2: null\n  },\n  switchValue: false,\n  checkboxGroupValue: null,\n  radioGroupValue: null,\n  radioButtonGroupValue: null,\n  inputNumberValue: null,\n  timePickerValue: null,\n  sliderValue: 0,\n  transferValue: null\n})\n\nconst generalOptions = ['groode', 'veli good', 'emazing', 'lidiculous'].map(\n  (v) => {\n    return {\n      label: v,\n      value: v\n    }\n  }\n)\n\nconst cascaderOptions = [\n  {\n    label: 'groode',\n    value: 'groode',\n    children: [\n      {\n        label: 'veli good',\n        value: 'veli good'\n      }\n    ]\n  }\n]\n\nconst rules = {\n  inputValue: {\n    required: true,\n    trigger: ['blur', 'input'],\n    message: '请输入 inputValue'\n  },\n  textareaValue: {\n    required: true,\n    trigger: ['blur', 'input'],\n    message: '请输入 textareaValue'\n  },\n  selectValue: {\n    required: true,\n    trigger: ['blur', 'change'],\n    message: '请选择 selectValue'\n  },\n  multipleSelectValue: {\n    type: 'array',\n    required: true,\n    trigger: ['blur', 'change'],\n    message: '请选择 multipleSelectValue'\n  } as FormItemRule,\n  datetimeValue: {\n    type: 'number',\n    required: true,\n    trigger: ['blur', 'change'],\n    message: '请输入 datetimeValue'\n  } as FormItemRule,\n  nestedValue: {\n    path1: {\n      required: true,\n      trigger: ['blur', 'input'],\n      message: '请输入 nestedValue.path1'\n    },\n    path2: {\n      required: true,\n      trigger: ['blur', 'change'],\n      message: '请输入 nestedValue.path2'\n    }\n  } as FormRules,\n  checkboxGroupValue: {\n    type: 'array',\n    required: true,\n    trigger: 'change',\n    message: '请选择 checkboxGroupValue'\n  } as FormItemRule,\n  radioGroupValue: {\n    required: true,\n    trigger: 'change',\n    message: '请选择 radioGroupValue'\n  },\n  radioButtonGroupValue: {\n    required: true,\n    trigger: 'change',\n    message: '请选择 radioButtonGroupValue'\n  },\n  inputNumberValue: {\n    type: 'number',\n    required: true,\n    trigger: ['blur', 'change'],\n    message: '请输入 inputNumberValue'\n  } as FormItemRule,\n  timePickerValue: {\n    type: 'number',\n    required: true,\n    trigger: ['blur', 'change'],\n    message: '请输入 timePickerValue'\n  } as FormItemRule,\n  sliderValue: {\n    validator(rule: FormItemRule, value: number) {\n      return value > 50\n    },\n    trigger: ['blur', 'change'],\n    message: 'sliderValue 需要大于 50'\n  },\n  transferValue: {\n    type: 'array',\n    required: true,\n    trigger: 'change',\n    message: '请输入 transferValue'\n  } as FormItemRule\n} as FormRules\n\nfunction handleValidateButtonClick(e: MouseEvent) {\n  e.preventDefault()\n  formRef.value?.validate((errors) => {\n    if (!errors) {\n      message.success('验证成功')\n    }\n    else {\n      console.log(errors)\n      message.error('验证失败')\n    }\n  })\n}\n</script>\n\n<template>\n  <n-radio-group\n    v-model:value=\"size\"\n    name=\"top-size\"\n    style=\"margin-bottom: 12px\"\n  >\n    <n-radio-button value=\"small\">\n      小\n    </n-radio-button>\n    <n-radio-button value=\"medium\">\n      中\n    </n-radio-button>\n    <n-radio-button value=\"large\">\n      大\n    </n-radio-button>\n  </n-radio-group>\n  <n-form\n    ref=\"formRef\"\n    :model=\"model\"\n    :rules=\"rules\"\n    :size=\"size\"\n    label-placement=\"top\"\n  >\n    <n-grid :cols=\"24\" :x-gap=\"24\">\n      <n-form-item-gi :span=\"12\" label=\"Input\" path=\"inputValue\">\n        <n-input v-model:value=\"model.inputValue\" placeholder=\"Input\" />\n      </n-form-item-gi>\n      <n-form-item-gi :span=\"12\" label=\"Textarea\" path=\"textareaValue\">\n        <n-input\n          v-model:value=\"model.textareaValue\"\n          placeholder=\"Textarea\"\n          type=\"textarea\"\n          :autosize=\"{\n            minRows: 3,\n            maxRows: 5,\n          }\"\n        />\n      </n-form-item-gi>\n      <n-form-item-gi :span=\"12\" label=\"Select\" path=\"selectValue\">\n        <n-select\n          v-model:value=\"model.selectValue\"\n          placeholder=\"Select\"\n          :options=\"generalOptions\"\n        />\n      </n-form-item-gi>\n      <n-form-item-gi\n        :span=\"12\"\n        label=\"Multiple Select\"\n        path=\"multipleSelectValue\"\n      >\n        <n-select\n          v-model:value=\"model.multipleSelectValue\"\n          placeholder=\"Select\"\n          :options=\"generalOptions\"\n          multiple\n        />\n      </n-form-item-gi>\n      <n-form-item-gi :span=\"12\" label=\"Datetime\" path=\"datetimeValue\">\n        <n-date-picker v-model:value=\"model.datetimeValue\" type=\"datetime\" />\n      </n-form-item-gi>\n      <n-form-item-gi :span=\"12\" label=\"Switch\" path=\"switchValue\">\n        <n-switch v-model:value=\"model.switchValue\" />\n      </n-form-item-gi>\n      <n-form-item-gi\n        :span=\"12\"\n        label=\"Checkbox Group\"\n        path=\"checkboxGroupValue\"\n      >\n        <n-checkbox-group v-model:value=\"model.checkboxGroupValue\">\n          <n-space>\n            <n-checkbox value=\"Option 1\">\n              Option 1\n            </n-checkbox>\n            <n-checkbox value=\"Option 2\">\n              Option 2\n            </n-checkbox>\n            <n-checkbox value=\"Option 3\">\n              Option 3\n            </n-checkbox>\n          </n-space>\n        </n-checkbox-group>\n      </n-form-item-gi>\n      <n-form-item-gi :span=\"12\" label=\"Radio Group\" path=\"radioGroupValue\">\n        <n-radio-group v-model:value=\"model.radioGroupValue\" name=\"radiogroup1\">\n          <n-space>\n            <n-radio value=\"Radio 1\">\n              Radio 1\n            </n-radio>\n            <n-radio value=\"Radio 2\">\n              Radio 2\n            </n-radio>\n            <n-radio value=\"Radio 3\">\n              Radio 3\n            </n-radio>\n          </n-space>\n        </n-radio-group>\n      </n-form-item-gi>\n      <n-form-item-gi\n        :span=\"12\"\n        label=\"Radio Button Group\"\n        path=\"radioGroupValue\"\n      >\n        <n-radio-group v-model:value=\"model.radioGroupValue\" name=\"radiogroup2\">\n          <n-radio-button value=\"Radio 1\">\n            Radio 1\n          </n-radio-button>\n          <n-radio-button value=\"Radio 2\">\n            Radio 2\n          </n-radio-button>\n          <n-radio-button value=\"Radio 3\">\n            Radio 3\n          </n-radio-button>\n        </n-radio-group>\n      </n-form-item-gi>\n      <n-form-item-gi :span=\"12\" label=\"Input Number\" path=\"inputNumberValue\">\n        <n-input-number v-model:value=\"model.inputNumberValue\" />\n      </n-form-item-gi>\n      <n-form-item-gi :span=\"12\" label=\"Time Picker\" path=\"timePickerValue\">\n        <n-time-picker v-model:value=\"model.timePickerValue\" />\n      </n-form-item-gi>\n      <n-form-item-gi :span=\"12\" label=\"Slider\" path=\"sliderValue\">\n        <n-slider v-model:value=\"model.sliderValue\" :step=\"5\" />\n      </n-form-item-gi>\n      <n-form-item-gi :span=\"14\" label=\"Transfer\" path=\"transferValue\">\n        <n-transfer\n          v-model:value=\"model.transferValue\"\n          style=\"width: 100%\"\n          :options=\"generalOptions\"\n        />\n      </n-form-item-gi>\n      <n-form-item-gi :span=\"5\" label=\"Nested Path\" path=\"nestedValue.path1\">\n        <n-cascader\n          v-model:value=\"model.nestedValue.path1\"\n          placeholder=\"Nested Path 1\"\n          :options=\"cascaderOptions\"\n        />\n      </n-form-item-gi>\n      <n-form-item-gi :span=\"5\" path=\"nestedValue.path2\">\n        <n-select\n          v-model:value=\"model.nestedValue.path2\"\n          placeholder=\"Nested Path 2\"\n          :options=\"generalOptions\"\n        />\n      </n-form-item-gi>\n      <n-gi :span=\"24\">\n        <div style=\"display: flex; justify-content: flex-end\">\n          <n-button round type=\"primary\" @click=\"handleValidateButtonClick\">\n            验证\n          </n-button>\n        </div>\n      </n-gi>\n    </n-grid>\n  </n-form>\n\n  <pre>{{ JSON.stringify(model, null, 2) }}</pre>\n</template>\n"
  },
  {
    "path": "src/form/index.ts",
    "content": "export { formProps, default as NForm } from './src/Form'\nexport type { FormProps } from './src/Form'\nexport { formItemProps, default as NFormItem } from './src/FormItem'\nexport type { FormItemProps } from './src/FormItem'\n// deprecated\nexport { default as NFormItemCol } from './src/FormItemCol'\nexport type { FormItemColProps } from './src/FormItemCol'\nexport {\n  formItemGiProps,\n  formItemGiProps as formItemGridItemProps,\n  default as NFormItemGi,\n  default as NFormItemGridItem\n} from './src/FormItemGridItem'\n\nexport type {\n  FormItemGiProps,\n  FormItemGiProps as FormItemGridItemProps\n} from './src/FormItemGridItem'\nexport { default as NFormItemRow } from './src/FormItemRow'\nexport type { FormItemRowProps } from './src/FormItemRow'\nexport type {\n  FormInst,\n  FormItemInst,\n  FormItemRule,\n  FormRules,\n  FormValidationError\n} from './src/interface'\n\nexport type * from './src/public-types'\n"
  },
  {
    "path": "src/form/src/Form.tsx",
    "content": "import type { ValidateError } from 'async-validator'\nimport type { ExtractPropTypes, PropType } from 'vue'\nimport type { ThemeProps } from '../../_mixins'\nimport type { ExtractPublicPropTypes } from '../../_utils'\nimport type { FormTheme } from '../styles'\nimport type {\n  FormInst,\n  FormItemInst,\n  FormItemInternalValidateResult,\n  FormRules,\n  FormValidateCallback,\n  FormValidateMessages,\n  LabelAlign,\n  LabelPlacement,\n  ShouldRuleBeApplied\n} from './interface'\nimport type { FormSize } from './public-types'\nimport { defineComponent, h, provide, ref } from 'vue'\nimport { useConfig, useTheme } from '../../_mixins'\nimport { keysOf } from '../../_utils'\nimport { formLight } from '../styles'\nimport { formInjectionKey, formItemInstsInjectionKey } from './context'\nimport style from './styles/form.cssr'\n\nexport const formProps = {\n  ...(useTheme.props as ThemeProps<FormTheme>),\n  inline: Boolean,\n  labelWidth: [Number, String] as PropType<number | string>,\n  labelAlign: String as PropType<LabelAlign>,\n  labelPlacement: {\n    type: String as PropType<LabelPlacement>,\n    default: 'top'\n  },\n  model: {\n    type: Object as PropType<Record<string, any>>,\n    default: () => {}\n  },\n  rules: Object as PropType<FormRules>,\n  disabled: Boolean,\n  size: String as PropType<FormSize>,\n  showRequireMark: {\n    type: Boolean as PropType<boolean | undefined>,\n    default: undefined\n  },\n  requireMarkPlacement: String as PropType<'left' | 'right' | 'right-hanging'>,\n  showFeedback: {\n    type: Boolean,\n    default: true\n  },\n  onSubmit: {\n    type: Function as PropType<(e: Event) => void>,\n    default: (e: Event) => {\n      e.preventDefault()\n    }\n  },\n  showLabel: {\n    type: Boolean as PropType<boolean | undefined>,\n    default: undefined\n  },\n  validateMessages: Object as PropType<Partial<FormValidateMessages>>\n} as const\n\nexport type FormSetupProps = ExtractPropTypes<typeof formProps>\nexport type FormProps = ExtractPublicPropTypes<typeof formProps>\n\nexport default defineComponent({\n  name: 'Form',\n  props: formProps,\n  setup(props) {\n    const { mergedClsPrefixRef } = useConfig(props)\n    useTheme('Form', '-form', style, formLight, props, mergedClsPrefixRef)\n    // from path to form-item\n    const formItems: Record<string, FormItemInst[]> = {}\n    // for label-width = 'auto'\n    const maxChildLabelWidthRef = ref<number | undefined>(undefined)\n    const deriveMaxChildLabelWidth = (currentWidth: number): void => {\n      const currentMaxChildLabelWidth = maxChildLabelWidthRef.value\n      if (\n        currentMaxChildLabelWidth === undefined\n        || currentWidth >= currentMaxChildLabelWidth\n      ) {\n        maxChildLabelWidthRef.value = currentWidth\n      }\n    }\n    function invalidateLabelWidth(): void {\n      for (const key of keysOf(formItems)) {\n        const formItemInstances = formItems[key]\n        for (const formItemInstance of formItemInstances) {\n          formItemInstance.invalidateLabelWidth?.()\n        }\n      }\n    }\n    async function validate(\n      validateCallback?: FormValidateCallback,\n      shouldRuleBeApplied: ShouldRuleBeApplied = () => true\n    ): Promise<{ warnings: ValidateError[][] | undefined }> {\n      return await new Promise<{ warnings: ValidateError[][] | undefined }>(\n        (resolve, reject) => {\n          const formItemValidationPromises: Array<\n            Promise<FormItemInternalValidateResult>\n          > = []\n          for (const key of keysOf(formItems)) {\n            const formItemInstances = formItems[key]\n            for (const formItemInstance of formItemInstances) {\n              if (formItemInstance.path) {\n                formItemValidationPromises.push(\n                  formItemInstance.internalValidate(null, shouldRuleBeApplied)\n                )\n              }\n            }\n          }\n          void Promise.all(formItemValidationPromises).then((results) => {\n            const formInvalid = results.some(result => !result.valid)\n            const errors: ValidateError[][] = []\n            const warnings: ValidateError[][] = []\n            results.forEach((result) => {\n              if (result.errors?.length) {\n                errors.push(result.errors)\n              }\n              if (result.warnings?.length) {\n                warnings.push(result.warnings)\n              }\n            })\n            if (validateCallback) {\n              validateCallback(errors.length ? errors : undefined, {\n                warnings: warnings.length ? warnings : undefined\n              })\n            }\n            if (formInvalid) {\n              reject(errors.length ? errors : undefined)\n            }\n            else {\n              resolve({\n                warnings: warnings.length ? warnings : undefined\n              })\n            }\n          })\n        }\n      )\n    }\n    function restoreValidation(): void {\n      for (const key of keysOf(formItems)) {\n        const formItemInstances = formItems[key]\n        for (const formItemInstance of formItemInstances) {\n          formItemInstance.restoreValidation()\n        }\n      }\n    }\n    provide(formInjectionKey, {\n      props,\n      maxChildLabelWidthRef,\n      deriveMaxChildLabelWidth\n    })\n    provide(formItemInstsInjectionKey, { formItems })\n    const formExposedMethod: FormInst = {\n      validate,\n      restoreValidation,\n      invalidateLabelWidth\n    }\n    return Object.assign(formExposedMethod, {\n      mergedClsPrefix: mergedClsPrefixRef\n    })\n  },\n  render() {\n    const { mergedClsPrefix } = this\n    return (\n      <form\n        class={[\n          `${mergedClsPrefix}-form`,\n          this.inline && `${mergedClsPrefix}-form--inline`\n        ]}\n        onSubmit={this.onSubmit}\n      >\n        {this.$slots}\n      </form>\n    )\n  }\n})\n"
  },
  {
    "path": "src/form/src/FormItem.tsx",
    "content": "import type { RuleItem, ValidateError, ValidateOption } from 'async-validator'\nimport type {\n  CSSProperties,\n  ExtractPropTypes,\n  LabelHTMLAttributes,\n  PropType,\n  Slot,\n  SlotsType,\n  VNodeChild\n} from 'vue'\nimport type { ThemeProps } from '../../_mixins'\nimport type { ExtractPublicPropTypes } from '../../_utils'\nimport type { FormTheme } from '../styles'\nimport type {\n  FormItemInst,\n  FormItemInternalValidate,\n  FormItemInternalValidateResult,\n  FormItemRule,\n  FormItemRuleValidator,\n  FormItemRuleValidatorParams,\n  FormItemSlots,\n  FormItemValidateOptions,\n  LabelAlign,\n  LabelPlacement,\n  ShouldRuleBeApplied,\n  ValidateCallback,\n  ValidationTrigger\n} from './interface'\nimport Schema from 'async-validator'\nimport { get } from 'lodash-es'\nimport { createId } from 'seemly'\nimport {\n  computed,\n  defineComponent,\n  h,\n  inject,\n  onMounted,\n  provide,\n  ref,\n  toRef,\n  Transition,\n  watch\n} from 'vue'\nimport { useConfig, useTheme, useThemeClass } from '../../_mixins'\nimport { formItemInjectionKey } from '../../_mixins/use-form-item'\nimport {\n  createKey,\n  keysOf,\n  resolveWrappedSlot,\n  useInjectionInstanceCollection,\n  warn\n} from '../../_utils'\nimport { formLight } from '../styles'\nimport { formInjectionKey, formItemInstsInjectionKey } from './context'\nimport style from './styles/form-item.cssr'\nimport { formItemMisc, formItemRule, formItemSize } from './utils'\n\nexport const formItemProps = {\n  ...(useTheme.props as ThemeProps<FormTheme>),\n  label: String,\n  labelWidth: [Number, String] as PropType<string | number>,\n  labelStyle: [String, Object] as PropType<CSSProperties | string>,\n  labelAlign: String as PropType<LabelAlign>,\n  labelPlacement: String as PropType<LabelPlacement>,\n  path: String,\n  first: Boolean,\n  rulePath: String,\n  required: Boolean,\n  showRequireMark: {\n    type: Boolean as PropType<boolean | undefined>,\n    default: undefined\n  },\n  requireMarkPlacement: String as PropType<'left' | 'right' | 'right-hanging'>,\n  showFeedback: {\n    type: Boolean as PropType<boolean | undefined>,\n    default: undefined\n  },\n  rule: [Object, Array] as PropType<FormItemRule | FormItemRule[]>,\n  size: String as PropType<'small' | 'medium' | 'large'>,\n  ignorePathChange: Boolean,\n  validationStatus: String as PropType<'error' | 'warning' | 'success'>,\n  feedback: String,\n  feedbackClass: String,\n  feedbackStyle: [String, Object] as PropType<string | CSSProperties>,\n  showLabel: {\n    type: Boolean as PropType<boolean | undefined>,\n    default: undefined\n  },\n  labelProps: Object as PropType<LabelHTMLAttributes>,\n  contentClass: String,\n  contentStyle: [String, Object] as PropType<string | CSSProperties>\n} as const\n\nexport type FormItemSetupProps = ExtractPropTypes<typeof formItemProps>\nexport type FormItemProps = ExtractPublicPropTypes<typeof formItemProps>\nexport const formItemPropKeys = keysOf(formItemProps)\n\n// Wrapped Validator is to be passed into async-validator\n// In their source code, validator can be a asyncValidator.\n// asyncValidator will non-promise return value will be ignored.\n// We need to deal with some type quirks.\ntype WrappedValidator = (\n  ...args: FormItemRuleValidatorParams\n) => boolean | Error | Error[] | Promise<void> | undefined\n\n// wrap sync validator\nfunction wrapValidator(\n  validator: FormItemRuleValidator,\n  async: boolean\n): WrappedValidator {\n  return (...args: Parameters<FormItemRuleValidator>) => {\n    try {\n      const validateResult = validator(...args)\n      if (\n        (!async\n          && (typeof validateResult === 'boolean'\n            || validateResult instanceof Error\n            || Array.isArray(validateResult))) // Error[]\n            || (validateResult as any)?.then\n      ) {\n        return validateResult as any\n      }\n      else if (validateResult === undefined) {\n        return true\n      }\n      else {\n        warn(\n          'form-item/validate',\n          `You return a ${typeof validateResult} `\n          + `typed value in the validator method, which is not recommended. Please use ${\n            async ? '`Promise`' : '`boolean`, `Error` or `Promise`'\n          } typed value instead.`\n        )\n        return true\n      }\n    }\n    catch (err) {\n      warn(\n        'form-item/validate',\n        'An error is catched in the validation, '\n        + 'so the validation won\\'t be done. Your callback in `validate` method of '\n        + '`n-form` or `n-form-item` won\\'t be called in this validation.'\n      )\n      console.error(err)\n      // If returns undefined, async-validator won't trigger callback\n      // so the result will be abandoned, which means not true and not false\n      return undefined\n    }\n  }\n}\n\nexport default defineComponent({\n  name: 'FormItem',\n  props: formItemProps,\n  slots: Object as SlotsType<FormItemSlots>,\n  setup(props) {\n    useInjectionInstanceCollection(\n      formItemInstsInjectionKey,\n      'formItems',\n      toRef(props, 'path')\n    )\n    const { mergedClsPrefixRef, inlineThemeDisabled } = useConfig(props)\n    const NForm = inject(formInjectionKey, null)\n    const formItemSizeRefs = formItemSize(props)\n    const formItemMiscRefs = formItemMisc(props)\n    const {\n      validationErrored: validationErroredRef,\n      validationWarned: validationWarnedRef\n    } = formItemMiscRefs\n    const { mergedRequired: mergedRequiredRef, mergedRules: mergedRulesRef }\n      = formItemRule(props)\n    const { mergedSize: mergedSizeRef } = formItemSizeRefs\n    const {\n      mergedLabelPlacement: labelPlacementRef,\n      mergedLabelAlign: labelTextAlignRef,\n      mergedRequireMarkPlacement: mergedRequireMarkPlacementRef\n    } = formItemMiscRefs\n    const renderExplainsRef = ref<\n      Array<{\n        key: string\n        render: () => VNodeChild\n      }>\n    >([])\n    const feedbackIdRef = ref(createId())\n    const labelElementRef = ref<null | HTMLLabelElement>(null)\n    const mergedDisabledRef = NForm\n      ? toRef(NForm.props, 'disabled')\n      : ref(false)\n    const themeRef = useTheme(\n      'Form',\n      '-form-item',\n      style,\n      formLight,\n      props,\n      mergedClsPrefixRef\n    )\n    watch(toRef(props, 'path'), () => {\n      if (props.ignorePathChange)\n        return\n      restoreValidation()\n    })\n    function invalidateLabelWidth(): void {\n      if (!formItemMiscRefs.isAutoLabelWidth.value)\n        return\n      const labelElement = labelElementRef.value\n      if (labelElement !== null) {\n        const memoizedWhitespace = labelElement.style.whiteSpace\n        labelElement.style.whiteSpace = 'nowrap'\n        labelElement.style.width = ''\n        NForm?.deriveMaxChildLabelWidth(\n          Number(getComputedStyle(labelElement).width.slice(0, -2))\n        )\n        labelElement.style.whiteSpace = memoizedWhitespace\n      }\n    }\n    function restoreValidation(): void {\n      renderExplainsRef.value = []\n      validationErroredRef.value = false\n      validationWarnedRef.value = false\n      if (props.feedback) {\n        feedbackIdRef.value = createId()\n      }\n    }\n    const internalValidate: FormItemInternalValidate = async (\n      trigger: ValidationTrigger | string | null = null,\n      shouldRuleBeApplied: ShouldRuleBeApplied = () => true,\n      options: ValidateOption = {\n        suppressWarning: true\n      }\n    ) => {\n      const { path } = props\n      if (!options) {\n        options = {}\n      }\n      else {\n        if (!options.first)\n          options.first = props.first\n      }\n      const { value: rules } = mergedRulesRef\n      const value = NForm ? get(NForm.props.model, path || '') : undefined\n      const messageRenderers: Record<string, () => VNodeChild> = {}\n      const originalMessageRendersMessage: Record<string, any> = {}\n      const activeRules = (\n        !trigger\n          ? rules\n          : rules.filter((rule) => {\n              if (Array.isArray(rule.trigger)) {\n                return rule.trigger.includes(trigger)\n              }\n              else {\n                return rule.trigger === trigger\n              }\n            })\n      )\n        .filter(shouldRuleBeApplied)\n        .map((rule, i) => {\n          const shallowClonedRule = Object.assign({}, rule)\n          if (shallowClonedRule.validator) {\n            shallowClonedRule.validator = wrapValidator(\n              shallowClonedRule.validator,\n              false\n            )\n          }\n          if (shallowClonedRule.asyncValidator) {\n            shallowClonedRule.asyncValidator = wrapValidator(\n              shallowClonedRule.asyncValidator,\n              true\n            ) as any\n          }\n          if (shallowClonedRule.renderMessage) {\n            const rendererKey = `__renderMessage__${i}`\n            originalMessageRendersMessage[rendererKey]\n              = shallowClonedRule.message\n            shallowClonedRule.message = rendererKey\n            messageRenderers[rendererKey] = shallowClonedRule.renderMessage\n          }\n          return shallowClonedRule\n        })\n      const activeErrorRules = activeRules.filter(r => r.level !== 'warning')\n      const activeWarningRules = activeRules.filter(\n        r => r.level === 'warning'\n      )\n\n      const validationResult: FormItemInternalValidateResult = {\n        valid: true,\n        errors: undefined,\n        warnings: undefined\n      }\n      if (!activeRules.length)\n        return validationResult\n\n      const mergedPath = path ?? '__n_no_path__'\n      const validator = new Schema({\n        [mergedPath]: activeErrorRules as RuleItem[]\n      })\n      const warningValidator = new Schema({\n        [mergedPath]: activeWarningRules as RuleItem[]\n      })\n      const { validateMessages } = NForm?.props || {}\n      if (validateMessages) {\n        validator.messages(validateMessages)\n        warningValidator.messages(validateMessages)\n      }\n\n      const renderMessages = (errors: ValidateError[]): void => {\n        renderExplainsRef.value = errors.map((error: ValidateError) => {\n          const transformedMessage = error?.message || ''\n          return {\n            key: transformedMessage,\n            render: () => {\n              if (transformedMessage.startsWith('__renderMessage__')) {\n                return messageRenderers[transformedMessage]()\n              }\n              return transformedMessage\n            }\n          }\n        })\n        errors.forEach((error) => {\n          if (error.message?.startsWith('__renderMessage__')) {\n            error.message = originalMessageRendersMessage[error.message]\n          }\n        })\n      }\n\n      if (activeErrorRules.length) {\n        const errors = await new Promise<ValidateError[] | null>((resolve) => {\n          void validator.validate({ [mergedPath]: value }, options, resolve)\n        })\n        if (errors?.length) {\n          validationResult.valid = false\n          validationResult.errors = errors\n          renderMessages(errors)\n        }\n      }\n\n      // if there are already errors, warning check can be skipped\n      if (activeWarningRules.length && !validationResult.errors) {\n        const warnings = await new Promise<ValidateError[] | null>(\n          (resolve) => {\n            void warningValidator.validate(\n              { [mergedPath]: value },\n              options,\n              resolve\n            )\n          }\n        )\n        if (warnings?.length) {\n          renderMessages(warnings)\n          validationResult.warnings = warnings\n        }\n      }\n\n      if (!validationResult.errors && !validationResult.warnings) {\n        restoreValidation()\n      }\n      else {\n        validationErroredRef.value = !!validationResult.errors\n        validationWarnedRef.value = !!validationResult.warnings\n      }\n\n      return validationResult\n    }\n    function handleContentBlur(): void {\n      void internalValidate('blur')\n    }\n    function handleContentChange(): void {\n      void internalValidate('change')\n    }\n    function handleContentFocus(): void {\n      void internalValidate('focus')\n    }\n    function handleContentInput(): void {\n      void internalValidate('input')\n    }\n    // Resolve : ()\n    // Reject  : (errors: AsyncValidator.ValidateError[])\n    async function validate(options: FormItemValidateOptions): Promise<{\n      warnings: ValidateError[] | undefined\n    }>\n    async function validate(\n      trigger?: string | null,\n      callback?: ValidateCallback\n    ): Promise<{\n      warnings: ValidateError[] | undefined\n    }>\n    async function validate(\n      options?: string | null | FormItemValidateOptions,\n      callback?: ValidateCallback\n    ): Promise<{\n      warnings: ValidateError[] | undefined\n    }> {\n      /** the following code is for compatibility */\n      let trigger: ValidationTrigger | string | undefined\n      let validateCallback: ValidateCallback | undefined\n      let shouldRuleBeApplied: ShouldRuleBeApplied | undefined\n      let asyncValidatorOptions: Record<string, any> | undefined\n      if (typeof options === 'string') {\n        trigger = options\n        validateCallback = callback\n      }\n      else if (options !== null && typeof options === 'object') {\n        trigger = options.trigger\n        validateCallback = options.callback\n        shouldRuleBeApplied = options.shouldRuleBeApplied\n        asyncValidatorOptions = options.options\n      }\n      return await new Promise<{\n        warnings: ValidateError[] | undefined\n      }>((resolve, reject) => {\n        void internalValidate(\n          trigger,\n          shouldRuleBeApplied,\n          asyncValidatorOptions\n        ).then(({ valid, errors, warnings }) => {\n          if (valid) {\n            if (validateCallback) {\n              validateCallback(undefined, { warnings })\n            }\n            resolve({ warnings })\n          }\n          else {\n            if (validateCallback) {\n              validateCallback(errors, { warnings })\n            }\n            reject(errors)\n          }\n        })\n      })\n    }\n\n    provide(formItemInjectionKey, {\n      path: toRef(props, 'path'),\n      disabled: mergedDisabledRef,\n      mergedSize: formItemSizeRefs.mergedSize,\n      mergedValidationStatus: formItemMiscRefs.mergedValidationStatus,\n      restoreValidation,\n      handleContentBlur,\n      handleContentChange,\n      handleContentFocus,\n      handleContentInput\n    })\n    const exposedRef: FormItemInst = {\n      validate,\n      restoreValidation,\n      internalValidate,\n      invalidateLabelWidth\n    }\n    onMounted(invalidateLabelWidth)\n    const cssVarsRef = computed(() => {\n      const { value: size } = mergedSizeRef\n      const { value: labelPlacement } = labelPlacementRef\n      const direction: 'vertical' | 'horizontal'\n        = labelPlacement === 'top' ? 'vertical' : 'horizontal'\n      const {\n        common: { cubicBezierEaseInOut },\n        self: {\n          labelTextColor,\n          asteriskColor,\n          lineHeight,\n          feedbackTextColor,\n          feedbackTextColorWarning,\n          feedbackTextColorError,\n          feedbackPadding,\n          labelFontWeight,\n          [createKey('labelHeight', size)]: labelHeight,\n          [createKey('blankHeight', size)]: blankHeight,\n          [createKey('feedbackFontSize', size)]: feedbackFontSize,\n          [createKey('feedbackHeight', size)]: feedbackHeight,\n          [createKey('labelPadding', direction)]: labelPadding,\n          [createKey('labelTextAlign', direction)]: labelTextAlign,\n          [createKey(createKey('labelFontSize', labelPlacement), size)]:\n            labelFontSize\n        }\n      } = themeRef.value\n\n      let mergedLabelTextAlign = labelTextAlignRef.value ?? labelTextAlign\n      if (labelPlacement === 'top') {\n        mergedLabelTextAlign\n          = mergedLabelTextAlign === 'right' ? 'flex-end' : 'flex-start'\n      }\n\n      const cssVars = {\n        '--n-bezier': cubicBezierEaseInOut,\n        '--n-line-height': lineHeight,\n        '--n-blank-height': blankHeight,\n        '--n-label-font-size': labelFontSize,\n        '--n-label-text-align': mergedLabelTextAlign,\n        '--n-label-height': labelHeight,\n        '--n-label-padding': labelPadding,\n        '--n-label-font-weight': labelFontWeight,\n        '--n-asterisk-color': asteriskColor,\n        '--n-label-text-color': labelTextColor,\n        '--n-feedback-padding': feedbackPadding,\n        '--n-feedback-font-size': feedbackFontSize,\n        '--n-feedback-height': feedbackHeight,\n        '--n-feedback-text-color': feedbackTextColor,\n        '--n-feedback-text-color-warning': feedbackTextColorWarning,\n        '--n-feedback-text-color-error': feedbackTextColorError\n      }\n      return cssVars\n    })\n    const themeClassHandle = inlineThemeDisabled\n      ? useThemeClass(\n          'form-item',\n          computed(() => {\n            return `${mergedSizeRef.value[0]}${labelPlacementRef.value[0]}${\n              labelTextAlignRef.value?.[0] || ''\n            }`\n          }),\n          cssVarsRef,\n          props\n        )\n      : undefined\n    const reverseColSpaceRef = computed(() => {\n      // label placement left\n      // require-mark-placement | label align | areas (1fr auto)\n      // left                   | left        | mark text (need reverse)\n      // left                   | right       | mark text (okay)\n      // right                  | left        | mark text (okay)\n      // right                  | right       | mark text (okay)\n      // right-hanging          | left        | text mark (okay)\n      // right-hanging          | right       | text mark (okay)\n      return (\n        labelPlacementRef.value === 'left'\n        && mergedRequireMarkPlacementRef.value === 'left'\n        && labelTextAlignRef.value === 'left'\n      )\n    })\n    return {\n      labelElementRef,\n      mergedClsPrefix: mergedClsPrefixRef,\n      mergedRequired: mergedRequiredRef,\n      feedbackId: feedbackIdRef,\n      renderExplains: renderExplainsRef,\n      reverseColSpace: reverseColSpaceRef,\n      ...formItemMiscRefs,\n      ...formItemSizeRefs,\n      ...exposedRef,\n      cssVars: inlineThemeDisabled ? undefined : cssVarsRef,\n      themeClass: themeClassHandle?.themeClass,\n      onRender: themeClassHandle?.onRender\n    }\n  },\n  render() {\n    const {\n      $slots,\n      mergedClsPrefix,\n      mergedShowLabel,\n      mergedShowRequireMark,\n      mergedRequireMarkPlacement,\n      onRender\n    } = this\n    const renderedShowRequireMark\n      = mergedShowRequireMark !== undefined\n        ? mergedShowRequireMark\n        : this.mergedRequired\n    onRender?.()\n\n    const renderLabel = (): JSX.Element | null => {\n      const labelText = this.$slots.label ? this.$slots.label() : this.label\n      if (!labelText)\n        return null\n      const textNode = (\n        <span class={`${mergedClsPrefix}-form-item-label__text`}>\n          {labelText}\n        </span>\n      )\n      const markNode = renderedShowRequireMark ? (\n        <span class={`${mergedClsPrefix}-form-item-label__asterisk`}>\n          {mergedRequireMarkPlacement !== 'left' ? '\\u00A0*' : '*\\u00A0'}\n        </span>\n      ) : (\n        mergedRequireMarkPlacement === 'right-hanging' && (\n          <span\n            class={`${mergedClsPrefix}-form-item-label__asterisk-placeholder`}\n          >\n            {'\\u00A0*'}\n          </span>\n        )\n      )\n      const { labelProps } = this\n      return (\n        <label\n          {...labelProps}\n          class={[\n            labelProps?.class,\n            `${mergedClsPrefix}-form-item-label`,\n            `${mergedClsPrefix}-form-item-label--${mergedRequireMarkPlacement}-mark`,\n            this.reverseColSpace\n            && `${mergedClsPrefix}-form-item-label--reverse-columns-space`\n          ]}\n          style={this.mergedLabelStyle as any}\n          ref=\"labelElementRef\"\n        >\n          {mergedRequireMarkPlacement === 'left'\n            ? [markNode, textNode]\n            : [textNode, markNode]}\n        </label>\n      )\n    }\n\n    return (\n      <div\n        class={[\n          `${mergedClsPrefix}-form-item`,\n          this.themeClass,\n          `${mergedClsPrefix}-form-item--${this.mergedSize}-size`,\n          `${mergedClsPrefix}-form-item--${this.mergedLabelPlacement}-labelled`,\n          this.isAutoLabelWidth\n          && `${mergedClsPrefix}-form-item--auto-label-width`,\n          !mergedShowLabel && `${mergedClsPrefix}-form-item--no-label`\n        ]}\n        style={this.cssVars as CSSProperties}\n      >\n        {mergedShowLabel && renderLabel()}\n        <div\n          class={[\n            `${mergedClsPrefix}-form-item-blank`,\n            this.contentClass,\n            this.mergedValidationStatus\n            && `${mergedClsPrefix}-form-item-blank--${this.mergedValidationStatus}`\n          ]}\n          style={this.contentStyle}\n        >\n          {$slots}\n        </div>\n        {this.mergedShowFeedback ? (\n          <div\n            key={this.feedbackId}\n            style={this.feedbackStyle}\n            class={[\n              `${mergedClsPrefix}-form-item-feedback-wrapper`,\n              this.feedbackClass\n            ]}\n          >\n            <Transition name=\"fade-down-transition\" mode=\"out-in\">\n              {{\n                default: () => {\n                  const { mergedValidationStatus } = this\n                  return resolveWrappedSlot(\n                    $slots.feedback as Slot | undefined,\n                    (children) => {\n                      const { feedback } = this\n                      const feedbackNodes\n                        = children || feedback ? (\n                          <div\n                            key=\"__feedback__\"\n                            class={`${mergedClsPrefix}-form-item-feedback__line`}\n                          >\n                            {children || feedback}\n                          </div>\n                        ) : this.renderExplains.length ? (\n                          this.renderExplains?.map(({ key, render }) => (\n                            <div\n                              key={key}\n                              class={`${mergedClsPrefix}-form-item-feedback__line`}\n                            >\n                              {render()}\n                            </div>\n                          ))\n                        ) : null\n                      return feedbackNodes ? (\n                        mergedValidationStatus === 'warning' ? (\n                          <div\n                            key=\"controlled-warning\"\n                            class={`${mergedClsPrefix}-form-item-feedback ${mergedClsPrefix}-form-item-feedback--warning`}\n                          >\n                            {feedbackNodes}\n                          </div>\n                        ) : mergedValidationStatus === 'error' ? (\n                          <div\n                            key=\"controlled-error\"\n                            class={`${mergedClsPrefix}-form-item-feedback ${mergedClsPrefix}-form-item-feedback--error`}\n                          >\n                            {feedbackNodes}\n                          </div>\n                        ) : mergedValidationStatus === 'success' ? (\n                          <div\n                            key=\"controlled-success\"\n                            class={`${mergedClsPrefix}-form-item-feedback ${mergedClsPrefix}-form-item-feedback--success`}\n                          >\n                            {feedbackNodes}\n                          </div>\n                        ) : (\n                          <div\n                            key=\"controlled-default\"\n                            class={`${mergedClsPrefix}-form-item-feedback`}\n                          >\n                            {feedbackNodes}\n                          </div>\n                        )\n                      ) : null\n                    }\n                  )\n                }\n              }}\n            </Transition>\n          </div>\n        ) : null}\n      </div>\n    )\n  }\n})\n"
  },
  {
    "path": "src/form/src/FormItemCol.ts",
    "content": "import type { ExtractPublicPropTypes } from '../../_utils'\nimport type { FormItemInst } from './interface'\nimport { defineComponent, h, ref } from 'vue'\nimport { keep, keysOf } from '../../_utils'\nimport NCol, { colPropKeys, colProps } from '../../legacy-grid/src/Col'\nimport NFormItem, { formItemPropKeys, formItemProps } from './FormItem'\n\nexport const formItemColProps = {\n  ...colProps,\n  ...formItemProps\n} as const\n\nexport const formItemColPropKeys = keysOf(formItemColProps)\n\nexport type FormItemColProps = ExtractPublicPropTypes<typeof formItemColProps>\n\nexport default defineComponent({\n  name: 'FormItemCol',\n  props: formItemColProps,\n  setup() {\n    const formItemInstRef = ref<FormItemInst | null>(null)\n    const validate = ((...args: any[]) => {\n      const { value } = formItemInstRef\n      if (value) {\n        return value.validate(...args)\n      }\n    }) as FormItemInst['validate']\n    const restoreValidation: FormItemInst['restoreValidation'] = () => {\n      const { value } = formItemInstRef\n      if (value) {\n        value.restoreValidation()\n      }\n    }\n    return {\n      formItemInstRef,\n      validate,\n      restoreValidation\n    }\n  },\n  render() {\n    return h(NCol, keep(this.$props, colPropKeys), {\n      default: () => {\n        const itemProps = keep(this.$props, formItemPropKeys)\n        return h(\n          NFormItem,\n          {\n            ref: 'formItemInstRef',\n            ...itemProps\n          },\n          this.$slots\n        )\n      }\n    })\n  }\n})\n"
  },
  {
    "path": "src/form/src/FormItemGridItem.ts",
    "content": "import type { SlotsType } from 'vue'\nimport type { ExtractPublicPropTypes } from '../../_utils'\nimport type { FormItemInst, FormItemSlots } from './interface'\nimport { defineComponent, h, ref } from 'vue'\nimport { keep, keysOf } from '../../_utils'\nimport NGridItem, {\n  gridItemPropKeys,\n  gridItemProps\n} from '../../grid/src/GridItem'\nimport NFormItem, { formItemPropKeys, formItemProps } from './FormItem'\n\nexport const formItemGiProps = {\n  ...gridItemProps,\n  ...formItemProps\n} as const\n\nexport const formItemGiPropKeys = keysOf(formItemGiProps)\n\nexport type FormItemGiProps = ExtractPublicPropTypes<typeof formItemGiProps>\n\nexport default defineComponent({\n  __GRID_ITEM__: true,\n  name: 'FormItemGridItem',\n  alias: ['FormItemGi'],\n  props: formItemGiProps,\n  slots: Object as SlotsType<FormItemSlots>,\n  setup() {\n    const formItemInstRef = ref<FormItemInst | null>(null)\n    const validate = ((...args: any[]) => {\n      const { value } = formItemInstRef\n      if (value) {\n        return value.validate(...args)\n      }\n    }) as FormItemInst['validate']\n    const restoreValidation: FormItemInst['restoreValidation'] = () => {\n      const { value } = formItemInstRef\n      if (value) {\n        value.restoreValidation()\n      }\n    }\n    return {\n      formItemInstRef,\n      validate,\n      restoreValidation\n    }\n  },\n  render() {\n    return h(NGridItem, keep(this.$.vnode.props || {}, gridItemPropKeys), {\n      default: () => {\n        const itemProps = keep(this.$props, formItemPropKeys)\n        return h(\n          NFormItem,\n          {\n            ref: 'formItemInstRef',\n            ...itemProps\n          },\n          this.$slots\n        )\n      }\n    })\n  }\n})\n"
  },
  {
    "path": "src/form/src/FormItemRow.ts",
    "content": "import type { ExtractPublicPropTypes } from '../../_utils'\nimport type { FormItemColRef } from './interface'\nimport { defineComponent, h, ref } from 'vue'\nimport { keep } from '../../_utils'\nimport NRow, { rowPropKeys, rowProps } from '../../legacy-grid/src/Row'\nimport NFormItemCol, {\n  formItemColPropKeys,\n  formItemColProps\n} from './FormItemCol'\n\nexport const formItemRowProps = {\n  ...rowProps,\n  ...formItemColProps\n}\n\nexport type FormItemRowProps = ExtractPublicPropTypes<typeof formItemRowProps>\n\nexport default defineComponent({\n  name: 'FormItemRow',\n  props: formItemRowProps,\n  setup() {\n    const formItemColInstRef = ref<FormItemColRef | null>(null)\n    const validate = ((...args: any[]) => {\n      const { value } = formItemColInstRef\n      if (value) {\n        return value.validate(...args)\n      }\n    }) as FormItemColRef['validate']\n    const restoreValidation: FormItemColRef['restoreValidation'] = () => {\n      const { value } = formItemColInstRef\n      if (value) {\n        value.restoreValidation()\n      }\n    }\n    return {\n      formItemColInstRef,\n      validate,\n      restoreValidation\n    }\n  },\n  render() {\n    return h(NRow, keep(this.$props, rowPropKeys), {\n      default: () => {\n        const colProps = keep(this.$props, formItemColPropKeys)\n        return h(\n          NFormItemCol,\n          {\n            ref: 'formItemColInstRef',\n            ...colProps,\n            span: 24\n          },\n          this.$slots\n        )\n      }\n    })\n  }\n})\n"
  },
  {
    "path": "src/form/src/context.ts",
    "content": "import type { FormInjection } from './interface'\nimport { createInjectionKey } from '../../_utils'\n\nexport const formInjectionKey = createInjectionKey<FormInjection>('n-form')\nexport const formItemInstsInjectionKey\n  = createInjectionKey<unknown>('n-form-item-insts')\n"
  },
  {
    "path": "src/form/src/interface.ts",
    "content": "import type {\n  RuleItem,\n  ValidateError,\n  ValidateMessages,\n  ValidateOption\n} from 'async-validator'\nimport type { Ref, VNode, VNodeChild } from 'vue'\nimport type { FormSetupProps } from './Form'\n\nexport interface FormRules {\n  [path: string]: FormRules | FormItemRule | FormItemRule[]\n}\n\ntype SetRule<T, R> = T extends (rule: any, ...args: infer K) => infer P\n  ? (rule: R, ...args: K) => P\n  : never\n\nexport type FormItemRuleValidatorParams = Parameters<\n  SetRule<NonNullable<RuleItem['validator']>, FormItemRule>\n>\n\nexport type FormItemRuleValidator = (\n  ...args: FormItemRuleValidatorParams\n) => boolean | Error | Error[] | Promise<void> | undefined\n\n// In src of async-validator, any non-promise of asyncValidator will be abandoned\nexport type FormItemRuleAsyncValidator = (\n  ...args: FormItemRuleValidatorParams\n) => Promise<void> | undefined\n\nexport type FormItemRule = Omit<RuleItem, 'validator' | 'asyncValidator'> & {\n  key?: string\n  trigger?: ValidationTrigger | string | Array<ValidationTrigger | string>\n  validator?: FormItemRuleValidator\n  asyncValidator?: FormItemRuleAsyncValidator\n  renderMessage?: () => VNodeChild\n  level?: 'warning' | 'error'\n}\n\nexport interface FormItemValidateOptions {\n  trigger?: ValidationTrigger | string\n  callback?: ValidateCallback\n  shouldRuleBeApplied?: ShouldRuleBeApplied\n  options?: ValidateOption\n}\n\nexport interface FormItemInternalValidateResult {\n  valid: boolean\n  errors: ValidateError[] | undefined\n  warnings: ValidateError[] | undefined\n}\n\nexport type FormItemInternalValidate = (\n  trigger: ValidationTrigger | string | null | undefined,\n  shouldRuleBeApplied?: ShouldRuleBeApplied,\n  options?: ValidateOption\n) => Promise<FormItemInternalValidateResult>\n\nexport type FormItemValidate = ((options: FormItemValidateOptions) => Promise<{\n  warnings: ValidateError[] | undefined\n}>)\n& ((\n  trigger?: string,\n  callback?: ValidateCallback\n) => Promise<{ warnings: ValidateError[] | undefined }>)\n\nexport interface FormItemInst {\n  validate: FormItemValidate\n  restoreValidation: () => void\n  invalidateLabelWidth: () => void\n  path?: string\n  internalValidate: FormItemInternalValidate\n}\n\nexport type FormItemColRef = FormItemInst\nexport type FormItemRowRef = FormItemInst\n\nexport interface FormInjection {\n  props: FormSetupProps\n  maxChildLabelWidthRef: Ref<number | undefined>\n  deriveMaxChildLabelWidth: (currentWidth: number) => void\n}\n\nexport type LabelAlign = 'left' | 'center' | 'right'\nexport type LabelPlacement = 'left' | 'top'\n\nexport type ValidationTrigger = 'input' | 'change' | 'blur' | 'focus'\n\nexport type ShouldRuleBeApplied = (rule: FormItemRule) => boolean\nexport type ValidateCallback = (\n  errors: ValidateError[] | undefined,\n  extra: {\n    warnings: ValidateError[] | undefined\n  }\n) => void\n\nexport type FormValidateCallback = (\n  errors: ValidateError[][] | undefined,\n  extra: {\n    warnings: ValidateError[][] | undefined\n  }\n) => void\nexport type FormValidate = (\n  callback?: FormValidateCallback,\n  shouldRuleBeApplied?: ShouldRuleBeApplied\n) => Promise<{\n  warnings: ValidateError[][] | undefined\n}>\n\nexport type FormValidationError = ValidateError[]\n\nexport interface FormInst {\n  validate: FormValidate\n  restoreValidation: () => void\n  invalidateLabelWidth: () => void\n}\n\nexport interface FormValidateMessages extends ValidateMessages {}\n\nexport interface FormItemSlots {\n  default?: () => VNode[]\n  feedback?: () => VNode[]\n  label?: () => VNode[]\n}\n"
  },
  {
    "path": "src/form/src/public-types.ts",
    "content": "export type FormSize = 'small' | 'medium' | 'large'\nexport type FormItemSize = 'small' | 'medium' | 'large'\nexport type FormValidationStatus = 'success' | 'error' | 'warning'\n"
  },
  {
    "path": "src/form/src/styles/form-item.cssr.ts",
    "content": "import { fadeDownTransition } from '../../../_styles/transitions/fade-down.cssr'\nimport { c, cB, cE, cM } from '../../../_utils/cssr'\n\n// vars:\n// --n-line-height\n// --n-blank-height\n// --n-feedback-padding\n// --n-feedback-font-size\n// --n-label-font-size-left\n// --n-label-font-size-top\n// --n-label-height\n// --n-label-padding\n// --n-asterisk-color\n// --n-label-text-color\n// --n-bezier\n// --n-feedback-text-color\n// --n-feedback-text-color-warning\n// --n-feedback-text-color-error\n// --n-label-text-align\n// --n-label-padding\nexport default cB('form-item', `\n  display: grid;\n  line-height: var(--n-line-height);\n`, [\n  cB('form-item-label', `\n    grid-area: label;\n    align-items: center;\n    line-height: 1.25;\n    text-align: var(--n-label-text-align);\n    font-size: var(--n-label-font-size);\n    min-height: var(--n-label-height);\n    padding: var(--n-label-padding);\n    color: var(--n-label-text-color);\n    transition: color .3s var(--n-bezier);\n    box-sizing: border-box;\n    font-weight: var(--n-label-font-weight);\n  `, [\n    cE('asterisk', `\n      white-space: nowrap;\n      user-select: none;\n      -webkit-user-select: none;\n      color: var(--n-asterisk-color);\n      transition: color .3s var(--n-bezier);\n    `),\n    cE('asterisk-placeholder', `\n      grid-area: mark;\n      user-select: none;\n      -webkit-user-select: none;\n      visibility: hidden;      \n    `)\n  ]),\n  cB('form-item-blank', `\n    grid-area: blank;\n    min-height: var(--n-blank-height);\n  `),\n  cM('auto-label-width', [\n    cB('form-item-label', 'white-space: nowrap;')\n  ]),\n  cM('left-labelled', `\n    grid-template-areas:\n      \"label blank\"\n      \"label feedback\";\n    grid-template-columns: auto minmax(0, 1fr);\n    grid-template-rows: auto 1fr;\n    align-items: flex-start;\n  `, [\n    cB('form-item-label', `\n      display: grid;\n      grid-template-columns: 1fr auto;\n      min-height: var(--n-blank-height);\n      height: auto;\n      box-sizing: border-box;\n      flex-shrink: 0;\n      flex-grow: 0;\n    `, [\n      cM('reverse-columns-space', `\n        grid-template-columns: auto 1fr;\n      `),\n      cM('left-mark', `\n        grid-template-areas:\n          \"mark text\"\n          \".    text\";\n      `),\n      cM('right-mark', `\n        grid-template-areas: \n          \"text mark\"\n          \"text .\";\n      `),\n      cM('right-hanging-mark', `\n        grid-template-areas: \n          \"text mark\"\n          \"text .\";\n      `),\n      cE('text', `\n        grid-area: text;      \n      `),\n      cE('asterisk', `\n        grid-area: mark;      \n        align-self: end;\n      `)\n    ])\n  ]),\n  cM('top-labelled', `\n    grid-template-areas:\n      \"label\"\n      \"blank\"\n      \"feedback\";\n    grid-template-rows: minmax(var(--n-label-height), auto) 1fr;\n    grid-template-columns: minmax(0, 100%);\n  `, [\n    cM('no-label', `\n      grid-template-areas:\n        \"blank\"\n        \"feedback\";\n        grid-template-rows: 1fr;\n    `),\n    cB('form-item-label', `\n      display: flex;\n      align-items: flex-start;\n      justify-content: var(--n-label-text-align);\n    `)\n  ]),\n  cB('form-item-blank', `\n    box-sizing: border-box;\n    display: flex;\n    align-items: center;\n    position: relative;\n  `),\n  cB('form-item-feedback-wrapper', `\n    grid-area: feedback;\n    box-sizing: border-box;\n    min-height: var(--n-feedback-height);\n    font-size: var(--n-feedback-font-size);\n    line-height: 1.25;\n    transform-origin: top left;\n  `, [\n    c('&:not(:empty)', `\n      padding: var(--n-feedback-padding);\n    `),\n    cB('form-item-feedback', {\n      transition: 'color .3s var(--n-bezier)',\n      color: 'var(--n-feedback-text-color)'\n    }, [\n      cM('warning', {\n        color: 'var(--n-feedback-text-color-warning)'\n      }),\n      cM('error', {\n        color: 'var(--n-feedback-text-color-error)'\n      }),\n      fadeDownTransition({\n        fromOffset: '-3px',\n        enterDuration: '.3s',\n        leaveDuration: '.2s'\n      })\n    ])\n  ])\n])\n"
  },
  {
    "path": "src/form/src/styles/form.cssr.ts",
    "content": "import { c, cB, cM } from '../../../_utils/cssr'\n\nexport default cB('form', [\n  cM('inline', `\n    width: 100%;\n    display: inline-flex;\n    align-items: flex-start;\n    align-content: space-around;\n  `, [\n    cB('form-item', {\n      width: 'auto',\n      marginRight: '18px'\n    }, [\n      c('&:last-child', {\n        marginRight: 0\n      })\n    ])\n  ])\n])\n"
  },
  {
    "path": "src/form/src/utils.ts",
    "content": "import type { ComputedRef } from 'vue'\nimport type { FormItemSetupProps } from './FormItem'\nimport type { FormItemRule } from './interface'\nimport type { FormItemSize } from './public-types'\nimport { get } from 'lodash-es'\nimport { computed, inject, ref } from 'vue'\nimport { useConfig } from '../../_mixins'\nimport { formatLength } from '../../_utils'\nimport { formInjectionKey } from './context'\n\nexport function formItemSize(props: FormItemSetupProps): {\n  mergedSize: ComputedRef<FormItemSize>\n} {\n  const NForm = inject(formInjectionKey, null)\n  const { mergedComponentPropsRef } = useConfig(props)\n  return {\n    mergedSize: computed(() => {\n      if (props.size !== undefined)\n        return props.size\n\n      if (NForm?.props.size !== undefined)\n        return NForm.props.size\n\n      const configSize = mergedComponentPropsRef?.value?.Form?.size\n      if (configSize)\n        return configSize\n\n      return 'medium'\n    })\n  }\n}\n\nexport function formItemMisc(props: FormItemSetupProps) {\n  const NForm = inject(formInjectionKey, null)\n  const mergedLabelPlacementRef = computed(() => {\n    const { labelPlacement } = props\n    if (labelPlacement !== undefined)\n      return labelPlacement\n    if (NForm?.props.labelPlacement)\n      return NForm.props.labelPlacement\n    return 'top'\n  })\n  const isAutoLabelWidthRef = computed(() => {\n    return (\n      mergedLabelPlacementRef.value === 'left'\n      && (props.labelWidth === 'auto' || NForm?.props.labelWidth === 'auto')\n    )\n  })\n  const mergedLabelWidthRef = computed(() => {\n    if (mergedLabelPlacementRef.value === 'top')\n      return\n    const { labelWidth } = props\n\n    if (labelWidth !== undefined && labelWidth !== 'auto') {\n      return formatLength(labelWidth)\n    }\n\n    if (isAutoLabelWidthRef.value) {\n      const autoComputedWidth = NForm?.maxChildLabelWidthRef.value\n      if (autoComputedWidth !== undefined) {\n        return formatLength(autoComputedWidth)\n      }\n      else {\n        return undefined\n      }\n    }\n\n    if (NForm?.props.labelWidth !== undefined) {\n      return formatLength(NForm.props.labelWidth)\n    }\n    return undefined\n  })\n  const mergedLabelAlignRef = computed(() => {\n    const { labelAlign } = props\n    if (labelAlign)\n      return labelAlign\n    if (NForm?.props.labelAlign)\n      return NForm.props.labelAlign\n    return undefined\n  })\n  const mergedLabelStyleRef = computed(() => {\n    return [\n      props.labelProps?.style,\n      props.labelStyle,\n      {\n        width: mergedLabelWidthRef.value\n      }\n    ]\n  })\n  const mergedShowRequireMarkRef = computed(() => {\n    const { showRequireMark } = props\n    if (showRequireMark !== undefined)\n      return showRequireMark\n    return NForm?.props.showRequireMark\n  })\n  const mergedRequireMarkPlacementRef = computed(() => {\n    const { requireMarkPlacement } = props\n    if (requireMarkPlacement !== undefined)\n      return requireMarkPlacement\n    return NForm?.props.requireMarkPlacement || 'right'\n  })\n  const validationErroredRef = ref(false)\n  const validationWarnedRef = ref(false)\n  const mergedValidationStatusRef = computed(() => {\n    const { validationStatus } = props\n    if (validationStatus !== undefined)\n      return validationStatus\n    if (validationErroredRef.value)\n      return 'error'\n    if (validationWarnedRef.value)\n      return 'warning'\n    return undefined\n  })\n  const mergedShowFeedbackRef = computed(() => {\n    const { showFeedback } = props\n    if (showFeedback !== undefined)\n      return showFeedback\n    if (NForm?.props.showFeedback !== undefined)\n      return NForm.props.showFeedback\n    return true\n  })\n  const mergedShowLabelRef = computed(() => {\n    const { showLabel } = props\n    if (showLabel !== undefined)\n      return showLabel\n    if (NForm?.props.showLabel !== undefined)\n      return NForm.props.showLabel\n    return true\n  })\n  return {\n    validationErrored: validationErroredRef,\n    validationWarned: validationWarnedRef,\n    mergedLabelStyle: mergedLabelStyleRef,\n    mergedLabelPlacement: mergedLabelPlacementRef,\n    mergedLabelAlign: mergedLabelAlignRef,\n    mergedShowRequireMark: mergedShowRequireMarkRef,\n    mergedRequireMarkPlacement: mergedRequireMarkPlacementRef,\n    mergedValidationStatus: mergedValidationStatusRef,\n    mergedShowFeedback: mergedShowFeedbackRef,\n    mergedShowLabel: mergedShowLabelRef,\n    isAutoLabelWidth: isAutoLabelWidthRef\n  }\n}\n\nexport function formItemRule(props: FormItemSetupProps) {\n  const NForm = inject(formInjectionKey, null)\n  const compatibleRulePathRef = computed(() => {\n    const { rulePath } = props\n    if (rulePath !== undefined)\n      return rulePath\n    const { path } = props\n    if (path !== undefined)\n      return path\n    return undefined\n  })\n  const mergedRulesRef = computed(() => {\n    const rules: FormItemRule[] = []\n    const { rule } = props\n    if (rule !== undefined) {\n      if (Array.isArray(rule))\n        rules.push(...rule)\n      else rules.push(rule)\n    }\n    if (NForm) {\n      const { rules: formRules } = NForm.props\n      const { value: rulePath } = compatibleRulePathRef\n      if (formRules !== undefined && rulePath !== undefined) {\n        const formRule = get(formRules, rulePath)\n        if (formRule !== undefined) {\n          if (Array.isArray(formRule)) {\n            rules.push(...formRule)\n          }\n          else {\n            // terminate object must be a form item rule\n            rules.push(formRule as FormItemRule)\n          }\n        }\n      }\n    }\n    return rules\n  })\n  const hasRequiredRuleRef = computed(() => {\n    return mergedRulesRef.value.some(rule => rule.required)\n  })\n  // deprecated\n  const mergedRequiredRef = computed(() => {\n    return hasRequiredRuleRef.value || props.required\n  })\n  return {\n    mergedRules: mergedRulesRef,\n    mergedRequired: mergedRequiredRef\n  }\n}\n"
  },
  {
    "path": "src/form/styles/_common.ts",
    "content": "export default {\n  feedbackPadding: '4px 0 0 2px',\n  feedbackHeightSmall: '24px',\n  feedbackHeightMedium: '24px',\n  feedbackHeightLarge: '26px',\n  feedbackFontSizeSmall: '13px',\n  feedbackFontSizeMedium: '14px',\n  feedbackFontSizeLarge: '14px',\n  labelFontSizeLeftSmall: '14px',\n  labelFontSizeLeftMedium: '14px',\n  labelFontSizeLeftLarge: '15px',\n  labelFontSizeTopSmall: '13px',\n  labelFontSizeTopMedium: '14px',\n  labelFontSizeTopLarge: '14px',\n  labelHeightSmall: '24px',\n  labelHeightMedium: '26px',\n  labelHeightLarge: '28px',\n  labelPaddingVertical: '0 0 6px 2px',\n  labelPaddingHorizontal: '0 12px 0 0',\n  labelTextAlignVertical: 'left',\n  labelTextAlignHorizontal: 'right',\n  labelFontWeight: '400'\n}\n"
  },
  {
    "path": "src/form/styles/dark.ts",
    "content": "import type { FormTheme } from './light'\nimport { commonDark } from '../../_styles/common'\nimport { self } from './light'\n\nconst formItemDark: FormTheme = {\n  name: 'Form',\n  common: commonDark,\n  self\n}\n\nexport default formItemDark\n"
  },
  {
    "path": "src/form/styles/index.ts",
    "content": "export { default as formDark } from './dark'\nexport { default as formLight } from './light'\nexport type { FormTheme, FormThemeVars } from './light'\n"
  },
  {
    "path": "src/form/styles/light.ts",
    "content": "import type { Theme } from '../../_mixins'\nimport type { ThemeCommonVars } from '../../_styles/common'\nimport { commonLight } from '../../_styles/common'\nimport commonVariables from './_common'\n\nexport function self(vars: ThemeCommonVars) {\n  const {\n    heightSmall,\n    heightMedium,\n    heightLarge,\n    textColor1,\n    errorColor,\n    warningColor,\n    lineHeight,\n    textColor3\n  } = vars\n  return {\n    ...commonVariables,\n    blankHeightSmall: heightSmall,\n    blankHeightMedium: heightMedium,\n    blankHeightLarge: heightLarge,\n    lineHeight,\n    labelTextColor: textColor1,\n    asteriskColor: errorColor,\n    feedbackTextColorError: errorColor,\n    feedbackTextColorWarning: warningColor,\n    feedbackTextColor: textColor3\n  }\n}\n\nexport type FormThemeVars = ReturnType<typeof self>\n\nconst formLight: Theme<'Form', FormThemeVars> = {\n  name: 'Form',\n  common: commonLight,\n  self\n}\n\nexport default formLight\nexport type FormTheme = typeof formLight\n"
  },
  {
    "path": "src/form/tests/Form.spec.tsx",
    "content": "import type { FormInst } from '../index'\n/* eslint-disable unused-imports/no-unused-vars */\nimport type { FormValidateCallback } from '../src/interface'\nimport { mount } from '@vue/test-utils'\nimport { defineComponent, h, ref } from 'vue'\nimport { NInput } from '../../input'\nimport { NForm, NFormItem } from '../index'\n\ndescribe('n-form', () => {\n  it('should work with import on demand', () => {\n    mount(NForm)\n  })\n  describe('require mark', () => {\n    it('doesn\\'t show by default', () => {\n      const wrapper = mount(() => (\n        <NForm>\n          {{\n            default: () => {\n              return (\n                <NFormItem label=\"star kirby\">\n                  {{\n                    default: () => <NInput />\n                  }}\n                </NFormItem>\n              )\n            }\n          }}\n        </NForm>\n      ))\n      expect(wrapper.find('.n-form-item-label__asterisk').exists()).toEqual(\n        false\n      )\n      wrapper.unmount()\n    })\n    it('shows when props.showRequireMark is set', () => {\n      const wrapper = mount(() => (\n        <NForm>\n          {{\n            default: () => {\n              return (\n                <NFormItem showRequireMark label=\"star kirby\">\n                  {{\n                    default: () => <NInput />\n                  }}\n                </NFormItem>\n              )\n            }\n          }}\n        </NForm>\n      ))\n      expect(wrapper.find('.n-form-item-label__asterisk').exists()).toEqual(\n        true\n      )\n      wrapper.unmount()\n    })\n    it('shows when required rule is set in form', () => {\n      const wrapper = mount(() => (\n        <NForm rules={{ starKirby: { required: true } }}>\n          {{\n            default: () => {\n              return (\n                <NFormItem label=\"star kirby\" path=\"starKirby\">\n                  {{\n                    default: () => <NInput />\n                  }}\n                </NFormItem>\n              )\n            }\n          }}\n        </NForm>\n      ))\n      expect(wrapper.find('.n-form-item-label__asterisk').exists()).toEqual(\n        true\n      )\n      wrapper.unmount()\n    })\n    it('shows when required rule is set in form item', () => {\n      const wrapper = mount(() => (\n        <NForm>\n          {{\n            default: () => {\n              return (\n                <NFormItem label=\"star kirby\" rule={{ required: true }}>\n                  {{\n                    default: () => <NInput />\n                  }}\n                </NFormItem>\n              )\n            }\n          }}\n        </NForm>\n      ))\n      expect(wrapper.find('.n-form-item-label__asterisk').exists()).toEqual(\n        true\n      )\n      wrapper.unmount()\n    })\n    it('show require mark placement left when set require-mark-placement is \"left\"', () => {\n      const wrapper = mount(() => (\n        <NForm showRequireMark={true} requireMarkPlacement=\"left\">\n          {{\n            default: () => {\n              return (\n                <NFormItem label=\"star kirby\">\n                  {{\n                    default: () => <NInput />\n                  }}\n                </NFormItem>\n              )\n            }\n          }}\n        </NForm>\n      ))\n      const requireMark = wrapper.find('.n-form-item-label__asterisk')\n      const nextSibling = requireMark.element.nextSibling as HTMLElement\n      expect(nextSibling.textContent).toEqual('star kirby')\n      wrapper.unmount()\n    })\n\n    it('show require mark placement left when set require-mark-placement is \"right\"', () => {\n      const wrapper = mount(() => (\n        <NForm showRequireMark={true} requireMarkPlacement=\"right\">\n          {{\n            default: () => {\n              return (\n                <NFormItem label=\"star kirby\">\n                  {{\n                    default: () => <NInput />\n                  }}\n                </NFormItem>\n              )\n            }\n          }}\n        </NForm>\n      ))\n      const requireMark = wrapper.find('.n-form-item-label__asterisk')\n      const previousSibling = requireMark.element.previousSibling as HTMLElement\n      expect(previousSibling.textContent).toEqual('star kirby')\n      wrapper.unmount()\n    })\n\n    it('show require mark placement left when set require-mark-placement is \"right\" in form-item', () => {\n      const wrapper = mount(() => (\n        <NForm showRequireMark={true} requireMarkPlacement=\"left\">\n          {{\n            default: () => {\n              return (\n                <NFormItem label=\"star kirby\" requireMarkPlacement=\"right\">\n                  {{\n                    default: () => <NInput />\n                  }}\n                </NFormItem>\n              )\n            }\n          }}\n        </NForm>\n      ))\n      const requireMark = wrapper.find('.n-form-item-label__asterisk')\n      const previousSibling = requireMark.element.previousSibling as HTMLElement\n      expect(previousSibling.textContent).toEqual('star kirby')\n      wrapper.unmount()\n    })\n  })\n\n  it('should work with `show-label` prop', async () => {\n    let wrapper = mount(NForm, {\n      slots: {\n        default: () =>\n          [1, 2, 3].map(num => (\n            <NFormItem label={`label${num}`}>\n              {{\n                default: () => <NInput />\n              }}\n            </NFormItem>\n          ))\n      }\n    })\n    // show-label default is true in component\n    expect(wrapper.findAll('.n-form-item-label').length).toBe(3)\n    expect(wrapper.findAll('.n-form-item--no-label').length).toBe(0)\n\n    await wrapper.setProps({ showLabel: true })\n    expect(wrapper.findAll('.n-form-item-label').length).toBe(3)\n    expect(wrapper.findAll('.n-form-item--no-label').length).toBe(0)\n\n    await wrapper.setProps({ showLabel: false })\n    expect(wrapper.findAll('.n-form-item-label').length).toBe(0)\n    const noLabelItem = wrapper\n      .findAll('.n-form-item')\n      .filter(w => w.classes().includes('n-form-item--no-label'))\n    expect(noLabelItem).toHaveLength(3)\n\n    // The NFormItem show-label has a higher weight than the NForm\n    wrapper = mount(NForm, {\n      props: { showLabel: true },\n      slots: {\n        default: () => (\n          <NFormItem label=\"label\" show-label={false}>\n            {{\n              default: () => <NInput />\n            }}\n          </NFormItem>\n        )\n      }\n    })\n    expect(\n      wrapper.find('.n-form-item').classes().includes('n-form-item--no-label')\n    ).toBe(true)\n    expect(wrapper.findAll('.n-form-item-label').length).toBe(0)\n    wrapper.unmount()\n  })\n\n  it('includes `for` attribute in label', () => {\n    const wrapper = mount(() => (\n      <NForm>\n        {{\n          default: () => {\n            return (\n              <NFormItem label=\"star kirby\" labelProps={{ for: 'input' }}>\n                {{\n                  default: () => <NInput />\n                }}\n              </NFormItem>\n            )\n          }\n        }}\n      </NForm>\n    ))\n    expect(wrapper.find('.n-form-item-label').attributes('for')).toBe('input')\n    wrapper.unmount()\n  })\n\n  describe('form validation', () => {\n    it('should form validation work with `level: \\'warning\\'` by async/await`', async () => {\n      const wrapper = mount(\n        defineComponent({\n          setup() {\n            return {\n              formRef: ref<FormInst>(),\n              formData: ref({\n                warningOnly: '',\n                throwException: ''\n              })\n            }\n          },\n          render() {\n            return (\n              <NForm\n                ref=\"formRef\"\n                model={this.formData}\n                rules={{\n                  warningOnly: {\n                    required: true,\n                    level: 'warning',\n                    message: 'warning!'\n                  },\n                  throwException: {\n                    required: true,\n                    message: 'error!'\n                  }\n                }}\n              >\n                {{\n                  default: () => {\n                    return [\n                      <NFormItem label=\"warningOnly\" path=\"warningOnly\">\n                        {{\n                          default: () => (\n                            <NInput\n                              ref=\"warningInputRef\"\n                              value={this.formData.warningOnly}\n                              onUpdateValue={(v) => {\n                                this.formData.warningOnly = v\n                              }}\n                            />\n                          )\n                        }}\n                      </NFormItem>,\n                      <NFormItem label=\"throwException\" path=\"throwException\">\n                        {{\n                          default: () => (\n                            <NInput\n                              ref=\"errorInputRef\"\n                              value={this.formData.throwException}\n                              onUpdateValue={(v) => {\n                                this.formData.throwException = v\n                              }}\n                            />\n                          )\n                        }}\n                      </NFormItem>\n                    ]\n                  }\n                }}\n              </NForm>\n            )\n          }\n        })\n      )\n\n      const formRef = wrapper.vm.$refs.formRef as FormInst\n      const validationError = [\n        [\n          {\n            field: 'throwException',\n            fieldValue: '',\n            message: 'error!'\n          }\n        ]\n      ]\n\n      // show warning and error feedback, validate method rejected while empty form fields\n      await expect(formRef.validate()).rejects.toMatchObject(validationError)\n\n      expect(\n        wrapper.find('.n-form-item-feedback.n-form-item-feedback--error').text()\n      ).toBe('error!')\n\n      expect(\n        wrapper\n          .find('.n-form-item-feedback.n-form-item-feedback--warning')\n          .text()\n      ).toBe('warning!')\n\n      // only warning is shown, validate method resolved while error filed got value.\n      await wrapper\n        .findComponent({ ref: 'errorInputRef' })\n        .find('input')\n        .setValue('value')\n\n      await expect(formRef.validate()).resolves.toMatchObject({\n        warnings: [\n          [{ field: 'warningOnly', fieldValue: '', message: 'warning!' }]\n        ]\n      })\n      expect(\n        wrapper\n          .find('.n-form-item-feedback.n-form-item-feedback--warning')\n          .text()\n      ).toBe('warning!')\n\n      expect(\n        wrapper\n          .find('.n-form-item-feedback.n-form-item-feedback--error')\n          .exists()\n      ).toBe(false)\n\n      // either error nor warning was shown, validate method resolve while form filled.\n      await wrapper\n        .findComponent({ ref: 'warningInputRef' })\n        .find('input')\n        .setValue('value')\n\n      await expect(formRef.validate()).resolves.toMatchObject({\n        warnings: undefined\n      })\n      expect(\n        wrapper\n          .find('.n-form-item-feedback.n-form-item-feedback--warning')\n          .exists()\n      ).toBe(false)\n\n      expect(\n        wrapper\n          .find('.n-form-item-feedback.n-form-item-feedback--error')\n          .exists()\n      ).toBe(false)\n\n      wrapper.unmount()\n    })\n\n    it('should form validation work with `warningOnly` by callback', async () => {\n      const wrapper = mount(\n        defineComponent({\n          setup() {\n            return {\n              formRef: ref<FormInst>(),\n              formData: ref({\n                warningOnly: '',\n                throwException: ''\n              })\n            }\n          },\n          render() {\n            return (\n              <NForm\n                ref=\"formRef\"\n                model={this.formData}\n                rules={{\n                  warningOnly: {\n                    required: true,\n                    level: 'warning',\n                    message: 'warning!'\n                  },\n                  throwException: {\n                    required: true,\n                    message: 'error!'\n                  }\n                }}\n              >\n                {{\n                  default: () => {\n                    return [\n                      <NFormItem label=\"warningOnly\" path=\"warningOnly\">\n                        {{\n                          default: () => (\n                            <NInput\n                              ref=\"warningInputRef\"\n                              value={this.formData.warningOnly}\n                              onUpdateValue={(v) => {\n                                this.formData.warningOnly = v\n                              }}\n                            />\n                          )\n                        }}\n                      </NFormItem>,\n                      <NFormItem label=\"throwException\" path=\"throwException\">\n                        {{\n                          default: () => (\n                            <NInput\n                              ref=\"errorInputRef\"\n                              value={this.formData.throwException}\n                              onUpdateValue={(v) => {\n                                this.formData.throwException = v\n                              }}\n                            />\n                          )\n                        }}\n                      </NFormItem>\n                    ]\n                  }\n                }}\n              </NForm>\n            )\n          }\n        })\n      )\n\n      const formRef = wrapper.vm.$refs.formRef as FormInst\n      const validationError = [\n        [\n          {\n            field: 'throwException',\n            fieldValue: '',\n            message: 'error!'\n          }\n        ]\n      ]\n      const validationWarning = [\n        [\n          {\n            field: 'warningOnly',\n            fieldValue: '',\n            message: 'warning!'\n          }\n        ]\n      ]\n\n      async function validate(): Promise<Parameters<FormValidateCallback>> {\n        return await new Promise<Parameters<FormValidateCallback>>(\n          (resolve) => {\n            void formRef\n              .validate((errs, { warnings }) => {\n                resolve([errs, { warnings }])\n              })\n              .catch(() => {})\n          }\n        )\n      }\n      // show warning and error feedback, validate method rejected while empty form fields\n      expect(await validate()).toMatchObject([\n        validationError,\n        { warnings: validationWarning }\n      ])\n\n      expect(\n        wrapper.find('.n-form-item-feedback.n-form-item-feedback--error').text()\n      ).toBe('error!')\n\n      expect(\n        wrapper\n          .find('.n-form-item-feedback.n-form-item-feedback--warning')\n          .text()\n      ).toBe('warning!')\n\n      // only warning is shown, validate method resolved while error filed got value.\n      await wrapper\n        .findComponent({ ref: 'errorInputRef' })\n        .find('input')\n        .setValue('value')\n\n      // show warning and error feedback, validate method rejected while empty form fields\n      expect(await validate()).toMatchObject([\n        undefined,\n        { warnings: validationWarning }\n      ])\n      expect(\n        wrapper\n          .find('.n-form-item-feedback.n-form-item-feedback--warning')\n          .text()\n      ).toBe('warning!')\n\n      expect(\n        wrapper\n          .find('.n-form-item-feedback.n-form-item-feedback--error')\n          .exists()\n      ).toBe(false)\n\n      // either error nor warning was shown, validate method resolve while form filled.\n      await wrapper\n        .findComponent({ ref: 'warningInputRef' })\n        .find('input')\n        .setValue('value')\n\n      expect(await validate()).toMatchObject([\n        undefined,\n        { warnings: undefined }\n      ])\n\n      expect(\n        wrapper\n          .find('.n-form-item-feedback.n-form-item-feedback--warning')\n          .exists()\n      ).toBe(false)\n\n      expect(\n        wrapper\n          .find('.n-form-item-feedback.n-form-item-feedback--error')\n          .exists()\n      ).toBe(false)\n\n      wrapper.unmount()\n    })\n\n    /** @see https://github.com/tusen-ai/naive-ui/issues/6068 */\n    it('the validation status should be updated correctly', async () => {\n      const wrapper = mount(\n        defineComponent({\n          setup() {\n            return {\n              formRef: ref<FormInst>(),\n              formData: ref({\n                input: 'other'\n              })\n            }\n          },\n          render() {\n            return (\n              <NForm\n                ref=\"formRef\"\n                model={this.formData}\n                rules={{\n                  input: [\n                    {\n                      level: 'error',\n                      validator(rule, value) {\n                        if (value !== 'target') {\n                          return new Error('error')\n                        }\n                        return true\n                      }\n                    },\n                    {\n                      level: 'warning',\n                      validator(rule, value) {\n                        return new Error('warning')\n                      }\n                    }\n                  ]\n                }}\n              >\n                {{\n                  default: () => (\n                    <NFormItem path=\"input\">\n                      {{\n                        default: () => (\n                          <NInput\n                            ref=\"inputRef\"\n                            value={this.formData.input}\n                            onUpdateValue={(v) => {\n                              this.formData.input = v\n                            }}\n                          />\n                        )\n                      }}\n                    </NFormItem>\n                  )\n                }}\n              </NForm>\n            )\n          }\n        })\n      )\n\n      const formRef = wrapper.vm.$refs.formRef as FormInst\n      async function validate(): Promise<Parameters<FormValidateCallback>> {\n        return await new Promise<Parameters<FormValidateCallback>>(\n          (resolve) => {\n            void formRef\n              .validate((errs, { warnings }) => {\n                resolve([errs, { warnings }])\n              })\n              .catch(() => {})\n          }\n        )\n      }\n\n      await validate()\n      expect(\n        wrapper\n          .find('.n-form-item-feedback.n-form-item-feedback--error')\n          .exists()\n      ).toBe(true)\n\n      await wrapper\n        .findComponent({ ref: 'inputRef' })\n        .find('input')\n        .setValue('target')\n\n      await validate()\n      expect(\n        wrapper\n          .find('.n-form-item-feedback.n-form-item-feedback--warning')\n          .exists()\n      ).toBe(true)\n\n      wrapper.unmount()\n    })\n  })\n})\n"
  },
  {
    "path": "src/form/tests/server.spec.tsx",
    "content": "import { setup } from '@css-render/vue3-ssr'\nimport { renderToString } from '@vue/server-renderer'\n/**\n * @vitest-environment node\n */\nimport { createSSRApp, h } from 'vue'\nimport { NForm } from '../..'\n\ndescribe('server side rendering', () => {\n  it('works', async () => {\n    const app = createSSRApp(() => <NForm />)\n    setup(app)\n    try {\n      await renderToString(app)\n    }\n    catch (e) {\n      expect(e).not.toBeTruthy()\n    }\n  })\n})\n"
  },
  {
    "path": "src/global-style/demos/enUS/index.demo-entry.md",
    "content": "# Global Style\n\nFor the following reasons, you may need to set some styles on `document.body`\n\n1. Naive-ui will mount some global style that is unresponsive (to theme, not media query). For example `font-family`. The style works fine by default, however they won't change when theme is changed.\n2. `n-config-provider` can't sync global style (for example, body's background color) outside it.\n\nYou can use `n-global-style` to sync common global style to the body element. In the following example, `n-global-style` will sync the theme provided by `n-config-provider` to `document.body`.\n\n## Usage\n\n```html\n// follow config-provider's theme\n<n-config-provider>\n  <n-global-style />\n  ...\n</n-config-provider>\n```\n"
  },
  {
    "path": "src/global-style/demos/zhCN/index.demo-entry.md",
    "content": "# 全局样式 Global Style\n\n出于以下原因，你可能需要将某些样式设定在 `document.body` 上。\n\n1. naive-ui 会设定一些非响应式的全局样式（例如字体），它们在默认状况下工作良好，但是不能响应主题的变化。\n2. `n-config-provider` 无法将全局样式同步到它以外的地方（例如 body 背景色）。\n\n通过使用 `n-global-style` 可以将常见的全局样式同步到 body 上。在下面的例子中，`n-global-style` 会将 `n-config-provider` 提供的主题同步到 `document.body` 上。\n\n## 用法\n\n```html\n// 跟随 n-config-provider 的主题\n<n-config-provider>\n  <n-global-style />\n  ...\n</n-config-provider>\n```\n"
  },
  {
    "path": "src/global-style/index.ts",
    "content": "export { default as NGlobalStyle } from './src/GlobalStyle'\n"
  },
  {
    "path": "src/global-style/src/GlobalStyle.ts",
    "content": "import { merge } from 'lodash-es'\nimport {\n  defineComponent,\n  inject,\n  onBeforeMount,\n  onUnmounted,\n  watchEffect\n} from 'vue'\nimport { commonLight } from '../../_styles/common'\nimport { warn } from '../../_utils'\nimport { configProviderInjectionKey } from '../../config-provider/src/context'\n\nexport default defineComponent({\n  name: 'GlobalStyle',\n  setup() {\n    if (typeof document === 'undefined')\n      return // TODO: inject style for SSR\n    const NConfigProvider = inject(configProviderInjectionKey, null)\n    const { body } = document\n    const { style } = body\n    let styleApplied = false\n    let firstApply = true\n    onBeforeMount(() => {\n      watchEffect(() => {\n        const {\n          textColor2,\n          fontSize,\n          fontFamily,\n          bodyColor,\n          cubicBezierEaseInOut,\n          lineHeight\n        } = NConfigProvider\n          ? merge(\n              {},\n              NConfigProvider.mergedThemeRef.value?.common || commonLight,\n              NConfigProvider.mergedThemeOverridesRef.value?.common\n            )\n          : commonLight\n        if (styleApplied || !body.hasAttribute('n-styled')) {\n          style.setProperty('-webkit-text-size-adjust', '100%')\n          style.setProperty('-webkit-tap-highlight-color', 'transparent')\n          style.padding = '0'\n          style.margin = '0'\n          style.backgroundColor = bodyColor\n          style.color = textColor2\n          style.fontSize = fontSize\n          style.fontFamily = fontFamily\n          style.lineHeight = lineHeight\n          const transition = `color .3s ${cubicBezierEaseInOut}, background-color .3s ${cubicBezierEaseInOut}`\n          if (firstApply) {\n            setTimeout(() => {\n              style.transition = transition\n            }, 0)\n          }\n          else {\n            style.transition = transition\n          }\n          body.setAttribute('n-styled', '')\n          styleApplied = true\n          firstApply = false\n        }\n        else if (__DEV__) {\n          warn(\n            'global-style',\n            'More than one n-global-style exist in the document.body. Only the first mounted one will work.'\n          )\n        }\n      })\n    })\n    onUnmounted(() => {\n      if (styleApplied) {\n        body.removeAttribute('n-styled')\n      }\n    })\n  },\n  render() {\n    return null\n  }\n})\n"
  },
  {
    "path": "src/global-style/tests/server.spec.tsx",
    "content": "import { setup } from '@css-render/vue3-ssr'\nimport { renderToString } from '@vue/server-renderer'\n/**\n * @vitest-environment node\n */\nimport { createSSRApp, h } from 'vue'\nimport { NGlobalStyle } from '../..'\n\ndescribe('server side rendering', () => {\n  it('works', async () => {\n    const app = createSSRApp(() => <NGlobalStyle />)\n    setup(app)\n    try {\n      await renderToString(app)\n    }\n    catch (e) {\n      expect(e).not.toBeTruthy()\n    }\n  })\n})\n"
  },
  {
    "path": "src/global.d.ts",
    "content": "export {}\n\ndeclare global {\n  const __DEV__: boolean\n}\n"
  },
  {
    "path": "src/gradient-text/demos/enUS/basic.demo.vue",
    "content": "<markdown>\n# Type\n\nA gradient text component can have different types.\n</markdown>\n\n<template>\n  <n-gradient-text type=\"error\">\n    Boom!\n  </n-gradient-text>\n  <br>\n  <n-gradient-text type=\"info\">\n    Emmm\n  </n-gradient-text>\n  <br>\n  <n-gradient-text type=\"warning\">\n    Oops!\n  </n-gradient-text>\n  <br>\n  <n-gradient-text type=\"success\">\n    Haha!\n  </n-gradient-text>\n</template>\n"
  },
  {
    "path": "src/gradient-text/demos/enUS/custom.demo.vue",
    "content": "<markdown>\n# Customizing gradient\n\nDesign it yourself.\n</markdown>\n\n<template>\n  <n-gradient-text\n    :gradient=\"{\n      from: 'rgb(85, 85, 85)',\n      to: 'rgb(170, 170, 170)',\n    }\"\n  >\n    Custom Color\n  </n-gradient-text>\n  <br>\n  <n-gradient-text\n    :gradient=\"{\n      deg: 180,\n      from: 'rgb(85, 85, 85)',\n      to: 'rgb(170, 170, 170)',\n    }\"\n  >\n    Custom Color\n  </n-gradient-text>\n  <br>\n  <n-gradient-text\n    gradient=\"linear-gradient(90deg, red 0%, green 50%, blue 100%)\"\n  >\n    A Scribbled Color\n  </n-gradient-text>\n</template>\n\n<style>\n.n-gradient-text {\n  font-size: 24px;\n}\n</style>\n"
  },
  {
    "path": "src/gradient-text/demos/enUS/index.demo-entry.md",
    "content": "# Gradient Text\n\nIt doesn't seem very useful... In fact it isn't.\n\n## Demos\n\n```demo\nbasic.vue\nsize.vue\ncustom.vue\n```\n\n## API\n\n### GradientText Props\n\n| Name | Type | Default | Description |\n| --- | --- | --- | --- |\n| gradient | `string \\| { from: string, to: string, deg: number \\| string }` | `undefined` | Text gradient color parameters. |\n| size | `number \\| string` | `undefined` | Text size (when the unit is not specified the default unit will be `px`). |\n| type | `'primary' \\| 'info' \\| 'success' \\| 'warning' \\| 'error'` | `'primary'` | Gradient Text type. |\n\n### GradientText Slots\n\n| Name    | Parameters | Description                       |\n| ------- | ---------- | --------------------------------- |\n| default | `()`       | The content of the gradient text. |\n"
  },
  {
    "path": "src/gradient-text/demos/enUS/size.demo.vue",
    "content": "<markdown>\n# Size\n\n`font-size` CSS also works, but can be overridden by setting the size (if just a number is used, it's taken as pixels).\n</markdown>\n\n<template>\n  <n-gradient-text type=\"info\">\n    Live Forever\n  </n-gradient-text>\n  <n-gradient-text type=\"danger\">\n    Live Forever\n  </n-gradient-text>\n  <br>\n  <n-gradient-text :size=\"24\" type=\"warning\">\n    Married with Children\n  </n-gradient-text>\n  <br>\n  <n-gradient-text :size=\"24\" type=\"success\">\n    Back in the USSR\n  </n-gradient-text>\n</template>\n\n<style>\n.n-gradient-text {\n  font-size: 36px;\n}\n</style>\n"
  },
  {
    "path": "src/gradient-text/demos/zhCN/basic.demo.vue",
    "content": "<markdown>\n# 基础用法\n\n它有不同的类型。\n</markdown>\n\n<template>\n  <n-gradient-text type=\"error\">\n    炸了\n  </n-gradient-text>\n  <br>\n  <n-gradient-text type=\"info\">\n    噢\n  </n-gradient-text>\n  <br>\n  <n-gradient-text type=\"warning\">\n    注意\n  </n-gradient-text>\n  <br>\n  <n-gradient-text type=\"success\">\n    成了\n  </n-gradient-text>\n</template>\n"
  },
  {
    "path": "src/gradient-text/demos/zhCN/custom.demo.vue",
    "content": "<markdown>\n# 定制\n\n靠你了。\n</markdown>\n\n<template>\n  <n-gradient-text\n    :gradient=\"{\n      from: 'rgb(85, 85, 85)',\n      to: 'rgb(170, 170, 170)',\n    }\"\n  >\n    定制颜色\n  </n-gradient-text>\n  <br>\n  <n-gradient-text\n    :gradient=\"{\n      deg: 180,\n      from: 'rgb(85, 85, 85)',\n      to: 'rgb(170, 170, 170)',\n    }\"\n  >\n    定制颜色\n  </n-gradient-text>\n  <br>\n  <n-gradient-text\n    gradient=\"linear-gradient(90deg, red 0%, green 50%, blue 100%)\"\n  >\n    瞎写的颜色\n  </n-gradient-text>\n</template>\n\n<style>\n.n-gradient-text {\n  font-size: 24px;\n}\n</style>\n"
  },
  {
    "path": "src/gradient-text/demos/zhCN/index.demo-entry.md",
    "content": "# 渐变文字 Gradient Text\n\n这个东西看起来没啥用，实际上确实没啥用。\n\n## 演示\n\n```demo\nbasic.vue\nsize.vue\ncustom.vue\n```\n\n## API\n\n### GradientText Props\n\n| 名称 | 类型 | 默认值 | 说明 |\n| --- | --- | --- | --- |\n| gradient | `string \\| { from: string, to: string, deg: number \\| string }` | `undefined` | 文字渐变色参数 |\n| size | `number \\| string` | `undefined` | 文字大小（当不指定单位时，默认单位: `px`） |\n| type | `'primary' \\| 'info' \\| 'success' \\| 'warning' \\| 'error'` | `'primary'` | 渐变文字的类型 |\n\n### GradientText Slots\n\n| 名称    | 参数 | 说明           |\n| ------- | ---- | -------------- |\n| default | `()` | 渐变文字的内容 |\n"
  },
  {
    "path": "src/gradient-text/demos/zhCN/size.demo.vue",
    "content": "<markdown>\n# 尺寸\n\n其实用 CSS 也挺方便的。\n</markdown>\n\n<template>\n  <n-gradient-text type=\"info\">\n    Live Forever\n  </n-gradient-text>\n  <n-gradient-text type=\"danger\">\n    Live Forever\n  </n-gradient-text>\n  <br>\n  <n-gradient-text :size=\"24\" type=\"warning\">\n    Married with Children\n  </n-gradient-text>\n  <br>\n  <n-gradient-text :size=\"24\" type=\"success\">\n    Back in the USSR\n  </n-gradient-text>\n</template>\n\n<style>\n.n-gradient-text {\n  font-size: 36px;\n}\n</style>\n"
  },
  {
    "path": "src/gradient-text/index.ts",
    "content": "export { gradientTextProps, default as NGradientText } from './src/GradientText'\nexport type { GradientTextProps } from './src/GradientText'\n"
  },
  {
    "path": "src/gradient-text/src/GradientText.tsx",
    "content": "import type { PropType } from 'vue'\nimport type { ThemeProps } from '../../_mixins'\nimport type { ExtractPublicPropTypes } from '../../_utils'\nimport type { GradientTextTheme } from '../styles'\nimport { computed, defineComponent, h } from 'vue'\nimport { useConfig, useTheme, useThemeClass } from '../../_mixins'\nimport { createKey, formatLength, useHoudini } from '../../_utils'\nimport { gradientTextLight } from '../styles'\nimport style from './styles/index.cssr'\n\ntype Gradient\n  = | string\n    | {\n      deg?: string | number\n      from: string\n      to: string\n    }\n\nexport const gradientTextProps = {\n  ...(useTheme.props as ThemeProps<GradientTextTheme>),\n  size: [String, Number] as PropType<string | number>,\n  fontSize: [String, Number] as PropType<string | number>,\n  type: {\n    type: String as PropType<\n      'info' | 'success' | 'warning' | 'error' | 'primary' | 'danger'\n    >,\n    default: 'primary'\n  },\n  color: [Object, String] as PropType<Gradient>,\n  gradient: [Object, String] as PropType<Gradient>\n} as const\n\nexport type GradientTextProps = ExtractPublicPropTypes<typeof gradientTextProps>\n\nexport default defineComponent({\n  name: 'GradientText',\n  props: gradientTextProps,\n  setup(props) {\n    useHoudini()\n    const { mergedClsPrefixRef, inlineThemeDisabled } = useConfig(props)\n    const compatibleTypeRef = computed<\n      'info' | 'success' | 'warning' | 'error' | 'primary'\n    >(() => {\n      const { type } = props\n      if (type === 'danger')\n        return 'error'\n      return type\n    })\n    const styleFontSizeRef = computed(() => {\n      let fontSize = props.size || props.fontSize\n      if (fontSize)\n        fontSize = formatLength(fontSize)\n      return fontSize || undefined\n    })\n    const styleBgImageRef = computed(() => {\n      const gradient = props.color || props.gradient\n      if (typeof gradient === 'string') {\n        return gradient\n      }\n      else if (gradient) {\n        const deg = gradient.deg || 0\n        const from = gradient.from\n        const to = gradient.to\n        return `linear-gradient(${deg}deg, ${from} 0%, ${to} 100%)`\n      }\n      return undefined\n    })\n    const themeRef = useTheme(\n      'GradientText',\n      '-gradient-text',\n      style,\n      gradientTextLight,\n      props,\n      mergedClsPrefixRef\n    )\n    const cssVarsRef = computed(() => {\n      const { value: type } = compatibleTypeRef\n      const {\n        common: { cubicBezierEaseInOut },\n        self: {\n          rotate,\n          [createKey('colorStart', type)]: colorStart,\n          [createKey('colorEnd', type)]: colorEnd,\n          fontWeight\n        }\n      } = themeRef.value\n      return {\n        '--n-bezier': cubicBezierEaseInOut,\n        '--n-rotate': rotate,\n        '--n-color-start': colorStart,\n        '--n-color-end': colorEnd,\n        '--n-font-weight': fontWeight\n      }\n    })\n    const themeClassHandle = inlineThemeDisabled\n      ? useThemeClass(\n          'gradient-text',\n          computed(() => compatibleTypeRef.value[0]),\n          cssVarsRef,\n          props\n        )\n      : undefined\n    return {\n      mergedClsPrefix: mergedClsPrefixRef,\n      compatibleType: compatibleTypeRef,\n      styleFontSize: styleFontSizeRef,\n      styleBgImage: styleBgImageRef,\n      cssVars: inlineThemeDisabled ? undefined : cssVarsRef,\n      themeClass: themeClassHandle?.themeClass,\n      onRender: themeClassHandle?.onRender\n    }\n  },\n  render() {\n    const { mergedClsPrefix, onRender } = this\n    onRender?.()\n    return (\n      <span\n        class={[\n          `${mergedClsPrefix}-gradient-text`,\n          `${mergedClsPrefix}-gradient-text--${this.compatibleType}-type`,\n          this.themeClass\n        ]}\n        style={[\n          {\n            fontSize: this.styleFontSize,\n            backgroundImage: this.styleBgImage\n          },\n          this.cssVars as any\n        ]}\n      >\n        {this.$slots}\n      </span>\n    )\n  }\n})\n"
  },
  {
    "path": "src/gradient-text/src/styles/index.cssr.ts",
    "content": "import { cB } from '../../../_utils/cssr'\n\n// vars:\n// --n-font-weight\n// --n-rotate\n// --n-bezier\n// --n-color-start\n// --n-color-end\nexport default cB('gradient-text', `\n  display: inline-block;\n  font-weight: var(--n-font-weight);\n  -webkit-background-clip: text;\n  background-clip: text;\n  color: #0000;\n  white-space: nowrap;\n  background-image: linear-gradient(var(--n-rotate), var(--n-color-start) 0%, var(--n-color-end) 100%);\n  transition:\n    --n-color-start .3s var(--n-bezier),\n    --n-color-end .3s var(--n-bezier);\n`)\n"
  },
  {
    "path": "src/gradient-text/styles/dark.ts",
    "content": "import type { GradientTextTheme } from './light'\nimport { commonDark } from '../../_styles/common'\n\nconst gradientTextDark: GradientTextTheme = {\n  name: 'GradientText',\n  common: commonDark,\n  self(vars) {\n    const {\n      primaryColor,\n      successColor,\n      warningColor,\n      errorColor,\n      infoColor,\n      primaryColorSuppl,\n      successColorSuppl,\n      warningColorSuppl,\n      errorColorSuppl,\n      infoColorSuppl,\n      fontWeightStrong\n    } = vars\n    return {\n      fontWeight: fontWeightStrong,\n      rotate: '252deg',\n      colorStartPrimary: primaryColor,\n      colorEndPrimary: primaryColorSuppl,\n      colorStartInfo: infoColor,\n      colorEndInfo: infoColorSuppl,\n      colorStartWarning: warningColor,\n      colorEndWarning: warningColorSuppl,\n      colorStartError: errorColor,\n      colorEndError: errorColorSuppl,\n      colorStartSuccess: successColor,\n      colorEndSuccess: successColorSuppl\n    }\n  }\n}\n\nexport default gradientTextDark\n"
  },
  {
    "path": "src/gradient-text/styles/index.ts",
    "content": "export { default as gradientTextDark } from './dark'\nexport { default as gradientTextLight } from './light'\nexport type { GradientTextTheme, GradientTextThemeVars } from './light'\n"
  },
  {
    "path": "src/gradient-text/styles/light.ts",
    "content": "import type { Theme } from '../../_mixins'\nimport type { ThemeCommonVars } from '../../_styles/common'\nimport { changeColor } from 'seemly'\nimport { commonLight } from '../../_styles/common'\n\nfunction self(vars: ThemeCommonVars) {\n  const {\n    primaryColor,\n    successColor,\n    warningColor,\n    errorColor,\n    infoColor,\n    fontWeightStrong\n  } = vars\n  return {\n    fontWeight: fontWeightStrong,\n    rotate: '252deg',\n    colorStartPrimary: changeColor(primaryColor, { alpha: 0.6 }),\n    colorEndPrimary: primaryColor,\n    colorStartInfo: changeColor(infoColor, { alpha: 0.6 }),\n    colorEndInfo: infoColor,\n    colorStartWarning: changeColor(warningColor, { alpha: 0.6 }),\n    colorEndWarning: warningColor,\n    colorStartError: changeColor(errorColor, { alpha: 0.6 }),\n    colorEndError: errorColor,\n    colorStartSuccess: changeColor(successColor, { alpha: 0.6 }),\n    colorEndSuccess: successColor\n  }\n}\n\nexport type GradientTextThemeVars = ReturnType<typeof self>\n\nconst gradientTextLight: Theme<'GradientText', GradientTextThemeVars> = {\n  name: 'GradientText',\n  common: commonLight,\n  self\n}\n\nexport default gradientTextLight\nexport type GradientTextTheme = typeof gradientTextLight\n"
  },
  {
    "path": "src/gradient-text/tests/GradientText.spec.ts",
    "content": "import { mount } from '@vue/test-utils'\nimport { NGradientText } from '../index'\n\ndescribe('n-gradient-text', () => {\n  it('should work with import on demand', () => {\n    mount(NGradientText)\n  })\n\n  it('should work with `type` prop', async () => {\n    const wrapper = mount(NGradientText, { slots: { default: () => 'test' } })\n    expect(wrapper.find('.n-gradient-text').text()).toContain('test')\n\n    await wrapper.setProps({ type: 'danger' })\n    expect(wrapper.find('.n-gradient-text').classes()).toContain(\n      'n-gradient-text--error-type'\n    )\n    wrapper.unmount()\n\n    const typeArray = [\n      'error',\n      'info',\n      'warning',\n      'success',\n      'primary'\n    ] as const\n    typeArray.forEach((item) => {\n      const wrapper = mount(NGradientText, {\n        props: { type: item },\n        slots: { default: () => 'test' }\n      })\n      expect(wrapper.find('.n-gradient-text').classes()).toContain(\n        `n-gradient-text--${item}-type`\n      )\n      wrapper.unmount()\n    })\n  })\n\n  it('should work with `size` prop', async () => {\n    const wrapper = mount(NGradientText, { slots: { default: () => 'test' } })\n    expect(wrapper.find('.n-gradient-text').attributes('style')).not.toContain(\n      'font-size'\n    )\n\n    await wrapper.setProps({ size: '24' })\n    expect(wrapper.find('.n-gradient-text').attributes('style')).toContain(\n      'font-size: 24px;'\n    )\n    wrapper.unmount()\n  })\n\n  it('should work with `gradient` prop', async () => {\n    const wrapper = mount(NGradientText, { slots: { default: () => 'test' } })\n\n    await wrapper.setProps({\n      gradient: { from: 'rgb(85, 85, 85)', to: 'rgb(170, 170, 170)' }\n    })\n    expect(\n      wrapper.find('.n-gradient-text').attributes('style')\n    ).toMatchSnapshot()\n\n    await wrapper.setProps({\n      gradient: 'linear-gradient(90deg, red 0%, green 50%, blue 100%)'\n    })\n    expect(\n      wrapper.find('.n-gradient-text').attributes('style')\n    ).toMatchSnapshot()\n    wrapper.unmount()\n  })\n})\n"
  },
  {
    "path": "src/gradient-text/tests/__snapshots__/GradientText.spec.ts.snap",
    "content": "// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html\n\nexports[`n-gradient-text > should work with \\`gradient\\` prop 1`] = `\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-rotate: 252deg; --n-color-start: rgba(24, 160, 88, 0.6); --n-color-end: #18a058; --n-font-weight: 500; background-image: linear-gradient(0deg, rgb(85, 85, 85) 0%, rgb(170, 170, 170) 100%);\"`;\n\nexports[`n-gradient-text > should work with \\`gradient\\` prop 2`] = `\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-rotate: 252deg; --n-color-start: rgba(24, 160, 88, 0.6); --n-color-end: #18a058; --n-font-weight: 500; background-image: linear-gradient(90deg, red 0%, green 50%, blue 100%);\"`;\n"
  },
  {
    "path": "src/gradient-text/tests/server.spec.tsx",
    "content": "import { setup } from '@css-render/vue3-ssr'\nimport { renderToString } from '@vue/server-renderer'\n/**\n * @vitest-environment node\n */\nimport { createSSRApp, h } from 'vue'\nimport { NGradientText } from '../..'\n\ndescribe('server side rendering', () => {\n  it('works', async () => {\n    const app = createSSRApp(() => <NGradientText />)\n    setup(app)\n    try {\n      await renderToString(app)\n    }\n    catch (e) {\n      expect(e).not.toBeTruthy()\n    }\n  })\n})\n"
  },
  {
    "path": "src/grid/demos/enUS/basic.demo.vue",
    "content": "<markdown>\n# Basic\n\n`n-grid-item` has an alias called `n-gi`.\n</markdown>\n\n<template>\n  <n-grid x-gap=\"12\" :cols=\"4\">\n    <n-gi>\n      <div class=\"light-green\" />\n    </n-gi>\n    <n-gi>\n      <div class=\"green\" />\n    </n-gi>\n    <n-gi>\n      <div class=\"light-green\" />\n    </n-gi>\n    <n-gi>\n      <div class=\"green\" />\n    </n-gi>\n  </n-grid>\n</template>\n\n<style>\n.light-green {\n  height: 108px;\n  background-color: rgba(0, 128, 0, 0.12);\n}\n.green {\n  height: 108px;\n  background-color: rgba(0, 128, 0, 0.24);\n}\n</style>\n"
  },
  {
    "path": "src/grid/demos/enUS/collapse.demo.vue",
    "content": "<markdown>\n# Collapse\n\nCollapsing works in responsive layout.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst gridCollapsed = ref(false)\nconst gridCollapsedRows = ref(1)\nconst gridItemCount = ref(4)\nconst showSuffix = ref(true)\n</script>\n\n<template>\n  <n-grid :cols=\"2\">\n    <n-form-item-gi label=\"Item Count\">\n      <n-input-number v-model:value=\"gridItemCount\" :min=\"1\" />\n    </n-form-item-gi>\n    <n-form-item-gi label=\"Max Rows After Collapsed\">\n      <n-input-number v-model:value=\"gridCollapsedRows\" :min=\"1\" />\n    </n-form-item-gi>\n    <n-form-item-gi label=\"Show Suffix Node\">\n      <n-switch v-model:value=\"showSuffix\" />\n    </n-form-item-gi>\n    <n-form-item-gi label=\"Grid Collapsed\">\n      <n-switch v-model:value=\"gridCollapsed\" />\n    </n-form-item-gi>\n  </n-grid>\n  <n-grid\n    :cols=\"5\"\n    :collapsed=\"gridCollapsed\"\n    :collapsed-rows=\"gridCollapsedRows\"\n  >\n    <n-gi\n      v-for=\"i in gridItemCount\"\n      :key=\"i\"\n      :class=\"i % 2 ? 'green' : 'light-green'\"\n    >\n      {{ i }}\n    </n-gi>\n    <n-gi v-if=\"showSuffix\" suffix class=\"suffix\" #=\"{ overflow }\">\n      {{ overflow ? 'Node Overflows Exists' : 'No Node Overflows' }}\n    </n-gi>\n  </n-grid>\n</template>\n\n<style>\n.suffix {\n  height: 108px;\n  border: 1px solid rgba(0, 128, 0, 0.36);\n  box-sizing: border-box;\n  display: flex;\n  align-items: center;\n  justify-content: center;\n}\n.light-green {\n  height: 108px;\n  background-color: rgba(0, 128, 0, 0.12);\n  box-sizing: border-box;\n  display: flex;\n  align-items: center;\n  justify-content: center;\n}\n.green {\n  height: 108px;\n  background-color: rgba(0, 128, 0, 0.24);\n  box-sizing: border-box;\n  display: flex;\n  align-items: center;\n  justify-content: center;\n}\n</style>\n"
  },
  {
    "path": "src/grid/demos/enUS/gap.demo.vue",
    "content": "<markdown>\n# Gap\n\nSet x gap & y gap.\n</markdown>\n\n<template>\n  <n-grid :x-gap=\"12\" :y-gap=\"8\" :cols=\"4\">\n    <n-grid-item>\n      <div class=\"light-green\" />\n    </n-grid-item>\n    <n-grid-item>\n      <div class=\"green\" />\n    </n-grid-item>\n    <n-grid-item>\n      <div class=\"light-green\" />\n    </n-grid-item>\n    <n-grid-item>\n      <div class=\"green\" />\n    </n-grid-item>\n    <n-grid-item>\n      <div class=\"light-green\" />\n    </n-grid-item>\n    <n-grid-item>\n      <div class=\"green\" />\n    </n-grid-item>\n    <n-grid-item>\n      <div class=\"light-green\" />\n    </n-grid-item>\n    <n-grid-item>\n      <div class=\"green\" />\n    </n-grid-item>\n  </n-grid>\n</template>\n\n<style>\n.light-green {\n  height: 108px;\n  background-color: rgba(0, 128, 0, 0.12);\n}\n.green {\n  height: 108px;\n  background-color: rgba(0, 128, 0, 0.24);\n}\n</style>\n"
  },
  {
    "path": "src/grid/demos/enUS/index.demo-entry.md",
    "content": "# Grid\n\n<!--single-column-->\n\nBased on CSS Grid. Responsive. Keep away from IE.\n\n<n-alert type=\"warning\" title=\"Caveats\" :bordered=\"false\">\nDue to technical limitation, <n-text code>n-grid-item</n-text> can't be encapsulated in another component.\n</n-alert>\n\n## Demos\n\n```demo\nbasic.vue\ngap.vue\noffset.vue\nresponsive.vue\nresponsive-item.vue\ncollapse.vue\nlayout-shift-disabled.vue\n```\n\n## API\n\n### Grid Props\n\n| Name | Type | Default | Description | Version |\n| --- | --- | --- | --- | --- |\n| cols | `number \\| ResponsiveDescription` | `24` | Number of grids displayed. |  |\n| collapsed | `boolean` | `false` | Whether to fold by default. |  |\n| collapsed-rows | `number` | `1` | The number of rows displayed by default. |  |\n| layout-shift-disabled | `boolean` | `false` | By default, `n-grid` will compute grid content based on window size and container size. This would cause 2 side effects: Content may shift in SSR mode; Render items has layout shift and it would influence performance slightly. If you don't need any responsive functionality, you can use `layout-shift-disabled` to get rid of side effects of it. Please note that set `layout-shift-disabled` will disabled all responsive functionality of `n-grid` and `suffix`, `offset` of `n-grid-item`. | 2.32.2 |\n| responsive | `'self' \\| 'screen'` | `'self'` | `'self'` triggers responsive layout by its own width. `'screen'` triggers responsive layout by viewport's width. |  |\n| item-responsive | `boolean` | `false` | Whether the grid item is responsive. |  |\n| x-gap | `number \\| ResponsiveDescription` | `0` | Horizontal gap. |  |\n| y-gap | `number \\| ResponsiveDescription` | `0` | Vertical gap. |  |\n\n### GridItem Props\n\n| Name | Type | Default | Description |\n| --- | --- | --- | --- |\n| offset | `number \\| ResponsiveDescription` | `0` | The number of intervals to the left of the grid. |\n| span | `number \\| ResponsiveDescription` | `1` | The number of columns occupied by the grid. The grid item would be hidden if it's 0. |\n| suffix | `boolean` | `false` | Grid suffix. |\n\n### Grid Slots\n\n| Name    | Parameters | Description   |\n| ------- | ---------- | ------------- |\n| default | `()`       | Grid content. |\n\n### GridItem Slots\n\n| Name    | Parameters                | Description        |\n| ------- | ------------------------- | ------------------ |\n| default | `({ overflow: boolean })` | Grid item content. |\n"
  },
  {
    "path": "src/grid/demos/enUS/layout-shift-disabled.demo.vue",
    "content": "<markdown>\n# Avoid SSR layout shift\n\nBy default, `n-grid` will compute grid content based on window size and container size. This would cause 2 side effects: Content may shift in SSR mode; Render items has layout shift and it would influence performance slightly.\n\nIf you don't need any responsive functionality, you can use `layout-shift-disabled` to get rid of side effects of it.\n\nPlease note that set `layout-shift-disabled` will disabled all responsive functionality of `n-grid` and `suffix`, `offset` of `n-grid-item`.\n</markdown>\n\n<template>\n  <n-grid :x-gap=\"12\" :y-gap=\"12\" :cols=\"4\" layout-shift-disabled>\n    <n-gi>\n      <div class=\"light-green\" />\n    </n-gi>\n    <n-gi :span=\"2\">\n      <div class=\"green\" />\n    </n-gi>\n    <n-gi>\n      <div class=\"light-green\" />\n    </n-gi>\n    <n-gi>\n      <div class=\"green\" />\n    </n-gi>\n  </n-grid>\n</template>\n\n<style>\n.light-green {\n  height: 108px;\n  background-color: rgba(0, 128, 0, 0.12);\n}\n.green {\n  height: 108px;\n  background-color: rgba(0, 128, 0, 0.24);\n}\n</style>\n"
  },
  {
    "path": "src/grid/demos/enUS/offset.demo.vue",
    "content": "<markdown>\n# Offset\n</markdown>\n\n<template>\n  <n-grid :x-gap=\"12\" :cols=\"4\">\n    <n-grid-item :offset=\"1\">\n      <div class=\"light-green\" />\n    </n-grid-item>\n    <n-grid-item :offset=\"1\">\n      <div class=\"green\" />\n    </n-grid-item>\n  </n-grid>\n</template>\n\n<style>\n.light-green {\n  height: 108px;\n  background-color: rgba(0, 128, 0, 0.12);\n}\n.green {\n  height: 108px;\n  background-color: rgba(0, 128, 0, 0.24);\n}\n</style>\n"
  },
  {
    "path": "src/grid/demos/enUS/responsive-item.demo.vue",
    "content": "<markdown>\n# Responsive grid item\n\nWhen `span` is 0, `n-grid-item` won't be displayed.\n</markdown>\n\n<template>\n  <n-divider>Self Responsive</n-divider>\n  <n-grid cols=\"4\" item-responsive>\n    <n-grid-item span=\"0 400:1 600:2 800:3\">\n      <div class=\"light-green\">\n        0 ~ 400px: hidden<br>\n        400 ~ 600px: span 1<br>\n        600 ~ 800px: span 2<br>\n        800px +: span 3\n      </div>\n    </n-grid-item>\n    <n-grid-item>\n      <div class=\"green\">\n        2\n      </div>\n    </n-grid-item>\n  </n-grid>\n  <n-divider>Screen Responsive</n-divider>\n  <n-grid cols=\"4\" item-responsive responsive=\"screen\">\n    <n-grid-item span=\"0 m:1 l:2\">\n      <div class=\"light-green\">\n        m-: hidden<br>\n        m ~ l: span 1<br>\n        l+: span 2\n      </div>\n    </n-grid-item>\n    <n-grid-item>\n      <div class=\"green\">\n        2\n      </div>\n    </n-grid-item>\n  </n-grid>\n</template>\n\n<style>\n.light-green {\n  display: flex;\n  align-items: center;\n  justify-content: center;\n  height: 200px;\n  background-color: rgba(0, 128, 0, 0.12);\n}\n.green {\n  display: flex;\n  align-items: center;\n  justify-content: center;\n  height: 200px;\n  background-color: rgba(0, 128, 0, 0.24);\n}\n</style>\n"
  },
  {
    "path": "src/grid/demos/enUS/responsive.demo.vue",
    "content": "<markdown>\n# Responsive columns\n\nYou can customize [breakpoints](config-provider#API) in `n-config-provider`.\n</markdown>\n\n<template>\n  <n-divider>Self Responsive</n-divider>\n  <n-grid cols=\"2 400:4 600:6\">\n    <n-grid-item>\n      <div class=\"light-green\">\n        1\n      </div>\n    </n-grid-item>\n    <n-grid-item>\n      <div class=\"green\">\n        2\n      </div>\n    </n-grid-item>\n    <n-grid-item>\n      <div class=\"light-green\">\n        3\n      </div>\n    </n-grid-item>\n    <n-grid-item>\n      <div class=\"green\">\n        4\n      </div>\n    </n-grid-item>\n    <n-grid-item>\n      <div class=\"light-green\">\n        5\n      </div>\n    </n-grid-item>\n    <n-grid-item>\n      <div class=\"green\">\n        6\n      </div>\n    </n-grid-item>\n  </n-grid>\n  <n-divider>Screen Responsive</n-divider>\n  <n-grid cols=\"2 s:3 m:4 l:5 xl:6 2xl:7\" responsive=\"screen\">\n    <n-grid-item>\n      <div class=\"light-green\">\n        1\n      </div>\n    </n-grid-item>\n    <n-grid-item>\n      <div class=\"green\">\n        2\n      </div>\n    </n-grid-item>\n    <n-grid-item>\n      <div class=\"light-green\">\n        3\n      </div>\n    </n-grid-item>\n    <n-grid-item>\n      <div class=\"green\">\n        4\n      </div>\n    </n-grid-item>\n    <n-grid-item>\n      <div class=\"light-green\">\n        5\n      </div>\n    </n-grid-item>\n    <n-grid-item>\n      <div class=\"green\">\n        6\n      </div>\n    </n-grid-item>\n    <n-grid-item>\n      <div class=\"light-green\">\n        7\n      </div>\n    </n-grid-item>\n  </n-grid>\n</template>\n\n<style>\n.light-green {\n  height: 108px;\n  background-color: rgba(0, 128, 0, 0.12);\n  display: flex;\n  align-items: center;\n  justify-content: center;\n}\n.green {\n  height: 108px;\n  background-color: rgba(0, 128, 0, 0.24);\n  display: flex;\n  align-items: center;\n  justify-content: center;\n}\n</style>\n"
  },
  {
    "path": "src/grid/demos/zhCN/basic.demo.vue",
    "content": "<markdown>\n# 基础用法\n\n`n-grid-item` 可以被简写为 `n-gi`。\n</markdown>\n\n<template>\n  <n-grid x-gap=\"12\" :cols=\"4\">\n    <n-gi>\n      <div class=\"light-green\" />\n    </n-gi>\n    <n-gi>\n      <div class=\"green\" />\n    </n-gi>\n    <n-gi>\n      <div class=\"light-green\" />\n    </n-gi>\n    <n-gi>\n      <div class=\"green\" />\n    </n-gi>\n  </n-grid>\n</template>\n\n<style>\n.light-green {\n  height: 108px;\n  background-color: rgba(0, 128, 0, 0.12);\n}\n.green {\n  height: 108px;\n  background-color: rgba(0, 128, 0, 0.24);\n}\n</style>\n"
  },
  {
    "path": "src/grid/demos/zhCN/collapse.demo.vue",
    "content": "<markdown>\n# 折叠\n\n折叠在响应式布局下依然生效。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst gridCollapsed = ref(false)\nconst gridCollapsedRows = ref(1)\nconst gridItemCount = ref(4)\nconst showSuffix = ref(true)\n</script>\n\n<template>\n  <n-grid :cols=\"2\">\n    <n-form-item-gi label=\"数量\">\n      <n-input-number v-model:value=\"gridItemCount\" :min=\"1\" />\n    </n-form-item-gi>\n    <n-form-item-gi label=\"折叠后行数\">\n      <n-input-number v-model:value=\"gridCollapsedRows\" :min=\"1\" />\n    </n-form-item-gi>\n    <n-form-item-gi label=\"打开后缀节点\">\n      <n-switch v-model:value=\"showSuffix\" />\n    </n-form-item-gi>\n    <n-form-item-gi label=\"折叠栅格\">\n      <n-switch v-model:value=\"gridCollapsed\" />\n    </n-form-item-gi>\n  </n-grid>\n  <n-grid\n    :cols=\"5\"\n    :collapsed=\"gridCollapsed\"\n    :collapsed-rows=\"gridCollapsedRows\"\n  >\n    <n-gi\n      v-for=\"i in gridItemCount\"\n      :key=\"i\"\n      :class=\"i % 2 ? 'green' : 'light-green'\"\n    >\n      {{ i }}\n    </n-gi>\n    <n-gi v-if=\"showSuffix\" suffix class=\"suffix\" #=\"{ overflow }\">\n      {{ overflow ? '存在溢出' : '不存在溢出' }}\n    </n-gi>\n  </n-grid>\n</template>\n\n<style>\n.suffix {\n  height: 108px;\n  border: 1px solid rgba(0, 128, 0, 0.36);\n  box-sizing: border-box;\n  display: flex;\n  align-items: center;\n  justify-content: center;\n}\n.light-green {\n  height: 108px;\n  background-color: rgba(0, 128, 0, 0.12);\n  box-sizing: border-box;\n  display: flex;\n  align-items: center;\n  justify-content: center;\n}\n.green {\n  height: 108px;\n  background-color: rgba(0, 128, 0, 0.24);\n  box-sizing: border-box;\n  display: flex;\n  align-items: center;\n  justify-content: center;\n}\n</style>\n"
  },
  {
    "path": "src/grid/demos/zhCN/gap.demo.vue",
    "content": "<markdown>\n# 间隔\n\n设定水平、垂直间隔。\n</markdown>\n\n<template>\n  <n-grid :x-gap=\"12\" :y-gap=\"8\" :cols=\"4\">\n    <n-grid-item>\n      <div class=\"light-green\" />\n    </n-grid-item>\n    <n-grid-item>\n      <div class=\"green\" />\n    </n-grid-item>\n    <n-grid-item>\n      <div class=\"light-green\" />\n    </n-grid-item>\n    <n-grid-item>\n      <div class=\"green\" />\n    </n-grid-item>\n    <n-grid-item>\n      <div class=\"light-green\" />\n    </n-grid-item>\n    <n-grid-item>\n      <div class=\"green\" />\n    </n-grid-item>\n    <n-grid-item>\n      <div class=\"light-green\" />\n    </n-grid-item>\n    <n-grid-item>\n      <div class=\"green\" />\n    </n-grid-item>\n  </n-grid>\n</template>\n\n<style>\n.light-green {\n  height: 108px;\n  background-color: rgba(0, 128, 0, 0.12);\n}\n.green {\n  height: 108px;\n  background-color: rgba(0, 128, 0, 0.24);\n}\n</style>\n"
  },
  {
    "path": "src/grid/demos/zhCN/grid-basic-debug.demo.vue",
    "content": "<markdown>\n# Grid Basic\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst collapsed = ref(true)\n</script>\n\n<template>\n  <n-grid\n    cols=\"3 400:4 500:5 600:6 700:7\"\n    :x-gap=\"12\"\n    :y-gap=\"8\"\n    :collapsed=\"collapsed\"\n    :collapsed-rows=\"3\"\n    style=\"align-items: center\"\n  >\n    <n-grid-item span=\"10\">\n      <div class=\"light-green\">\n        0\n      </div>\n    </n-grid-item>\n    <n-grid-item span=\"0\">\n      <div class=\"light-green\">\n        0.5\n      </div>\n    </n-grid-item>\n    <n-grid-item :span=\"2\" offset=\"0 400:1 500:2 600:3\">\n      <div class=\"green\">\n        1\n      </div>\n    </n-grid-item>\n    <n-grid-item span=\"0\">\n      <div class=\"light-green\">\n        1.5\n      </div>\n    </n-grid-item>\n    <n-grid-item :span=\"2\">\n      <div class=\"light-green\">\n        2\n      </div>\n    </n-grid-item>\n    <n-grid-item>\n      <div class=\"green\">\n        3\n      </div>\n    </n-grid-item>\n    <n-grid-item>\n      <div class=\"light-green\">\n        4\n      </div>\n    </n-grid-item>\n    <n-grid-item>\n      <div class=\"green\">\n        5\n      </div>\n    </n-grid-item>\n    <n-grid-item>\n      <div class=\"light-green\">\n        6\n      </div>\n    </n-grid-item>\n    <n-grid-item>\n      <div class=\"green\">\n        7\n      </div>\n    </n-grid-item>\n    <n-grid-item>\n      <div class=\"light-green\">\n        6\n      </div>\n    </n-grid-item>\n    <n-grid-item>\n      <div class=\"green\">\n        7\n      </div>\n    </n-grid-item>\n    <n-grid-item>\n      <div class=\"light-green\">\n        8\n      </div>\n    </n-grid-item>\n    <n-grid-item>\n      <div class=\"green\">\n        9\n      </div>\n    </n-grid-item><n-grid-item>\n      <div class=\"light-green\">\n        10\n      </div>\n    </n-grid-item>\n    <n-grid-item>\n      <div class=\"green\">\n        11\n      </div>\n    </n-grid-item>\n    <n-grid-item suffix style=\"justify-self: end\">\n      <n-button @click=\"collapsed = !collapsed\">\n        <template v-if=\"collapsed\">\n          Expand\n        </template>\n        <template v-else>\n          Collapse\n        </template>\n      </n-button>\n    </n-grid-item>\n  </n-grid>\n</template>\n\n<style>\n.light-green {\n  height: 108px;\n  background-color: rgba(0, 128, 0, 0.12);\n}\n.green {\n  height: 108px;\n  background-color: rgba(0, 128, 0, 0.24);\n}\n</style>\n"
  },
  {
    "path": "src/grid/demos/zhCN/index.demo-entry.md",
    "content": "# 栅格 Grid\n\n<!--single-column-->\n\n基于 CSS Grid，响应式，远离 IE。\n\n<n-alert type=\"warning\" title=\"注意\" :bordered=\"false\">\n  由于技术限制，<n-text code>n-grid-item</n-text> 是无法被二次封装的。\n</n-alert>\n\n## 演示\n\n```demo\nbasic.vue\ngap.vue\noffset.vue\nresponsive.vue\nresponsive-item.vue\ncollapse.vue\nlayout-shift-disabled.vue\ngrid-basic-debug.vue\n```\n\n## API\n\n### Grid Props\n\n| 名称 | 类型 | 默认值 | 说明 | 版本 |\n| --- | --- | --- | --- | --- |\n| cols | `number \\| ResponsiveDescription` | `24` | 显示的栅格数量 |  |\n| collapsed | `boolean` | `false` | 是否默认折叠 |  |\n| collapsed-rows | `number` | `1` | 默认展示的行数 |  |\n| layout-shift-disabled | `boolean` | `false` | 默认情况下，`n-grid` 会基于窗口宽度和容器宽度计算栅格内容，这会有两个副作用：在进行 SSR 的时候可能会出现内容闪烁；渲染时会出现 Layout Shift，这会略微影响渲染性能。但是如果你不需要响应式功能，你可以通过 `layout-shift-disabled` 规避删格的副作用。需要注意的是，打开这个选项会禁用 `n-grid` 的一切响应式功能和 `n-grid-item` 的 `suffix`、`offset` | 2.32.2 |\n| responsive | `'self' \\| 'screen'` | `'self'` | `'self'` 根据自身宽度进行响应式布局，`'screen'` 根据屏幕断点进行响应式布局 |  |\n| item-responsive | `boolean` | `false` | 子元素是否可具有响应式宽度 |  |\n| x-gap | `number \\| ResponsiveDescription` | `0` | 横向间隔槽 |  |\n| y-gap | `number \\| ResponsiveDescription` | `0` | 纵向间隔槽 |  |\n\n### GridItem Props\n\n| 名称 | 类型 | 默认值 | 说明 |\n| --- | --- | --- | --- |\n| offset | `number \\| ResponsiveDescription` | `0` | 栅格左侧的间隔格数， |\n| span | `number \\| ResponsiveDescription` | `1` | 栅格占据的列数，为 0 的时候会隐藏 |\n| suffix | `boolean` | `false` | 栅格后缀 |\n\n### Grid Slots\n\n| 名称    | 参数 | 说明     |\n| ------- | ---- | -------- |\n| default | `()` | 栅格内容 |\n\n### GridItem Slots\n\n| 名称    | 参数                      | 说明         |\n| ------- | ------------------------- | ------------ |\n| default | `({ overflow: boolean })` | 栅格节点内容 |\n"
  },
  {
    "path": "src/grid/demos/zhCN/layout-shift-disabled.demo.vue",
    "content": "<markdown>\n# 避免 SSR Layout Shift\n\n默认情况下，`n-grid` 会基于窗口宽度和容器宽度计算栅格内容，这会有两个副作用：在进行 SSR 的时候可能会出现内容闪烁；渲染时会出现 Layout Shift，这会略微影响渲染性能。\n\n但是如果你不需要响应式功能，你可以通过 `layout-shift-disabled` 规避删格的副作用。\n\n需要注意的是，打开这个选项会禁用 `n-grid` 的一切响应式功能和 `n-grid-item` 的 `suffix`、`offset`。\n</markdown>\n\n<template>\n  <n-grid :x-gap=\"12\" :y-gap=\"12\" :cols=\"4\" layout-shift-disabled>\n    <n-gi>\n      <div class=\"light-green\" />\n    </n-gi>\n    <n-gi :span=\"2\">\n      <div class=\"green\" />\n    </n-gi>\n    <n-gi>\n      <div class=\"light-green\" />\n    </n-gi>\n    <n-gi>\n      <div class=\"green\" />\n    </n-gi>\n  </n-grid>\n</template>\n\n<style>\n.light-green {\n  height: 108px;\n  background-color: rgba(0, 128, 0, 0.12);\n}\n.green {\n  height: 108px;\n  background-color: rgba(0, 128, 0, 0.24);\n}\n</style>\n"
  },
  {
    "path": "src/grid/demos/zhCN/offset.demo.vue",
    "content": "<markdown>\n# 偏移\n</markdown>\n\n<template>\n  <n-grid :x-gap=\"12\" :cols=\"4\">\n    <n-grid-item :offset=\"1\">\n      <div class=\"light-green\" />\n    </n-grid-item>\n    <n-grid-item :offset=\"1\">\n      <div class=\"green\" />\n    </n-grid-item>\n  </n-grid>\n</template>\n\n<style>\n.light-green {\n  height: 108px;\n  background-color: rgba(0, 128, 0, 0.12);\n}\n.green {\n  height: 108px;\n  background-color: rgba(0, 128, 0, 0.24);\n}\n</style>\n"
  },
  {
    "path": "src/grid/demos/zhCN/responsive-item.demo.vue",
    "content": "<markdown>\n# 响应式栅格项\n\n当 `span` 为 0 的时候，`n-grid-item` 不会被显示。\n</markdown>\n\n<template>\n  <n-divider>Self 响应式</n-divider>\n  <n-grid cols=\"4\" item-responsive>\n    <n-grid-item span=\"0 400:1 600:2 800:3\">\n      <div class=\"light-green\">\n        0～400px：不显示<br>\n        400～600px：占据空间 1<br>\n        600～800px：占据空间 2<br>\n        800px 以上：占据空间 3\n      </div>\n    </n-grid-item>\n    <n-grid-item>\n      <div class=\"green\">\n        2\n      </div>\n    </n-grid-item>\n  </n-grid>\n  <n-divider>Screen 响应式</n-divider>\n  <n-grid cols=\"4\" item-responsive responsive=\"screen\">\n    <n-grid-item span=\"0 m:1 l:2\">\n      <div class=\"light-green\">\n        m 以下：不显示<br>\n        m 到 l：占据空间 1<br>\n        l 以上：占据空间 2\n      </div>\n    </n-grid-item>\n    <n-grid-item>\n      <div class=\"green\">\n        2\n      </div>\n    </n-grid-item>\n  </n-grid>\n</template>\n\n<style>\n.light-green {\n  display: flex;\n  align-items: center;\n  justify-content: center;\n  height: 200px;\n  background-color: rgba(0, 128, 0, 0.12);\n}\n.green {\n  display: flex;\n  align-items: center;\n  justify-content: center;\n  height: 200px;\n  background-color: rgba(0, 128, 0, 0.24);\n}\n</style>\n"
  },
  {
    "path": "src/grid/demos/zhCN/responsive.demo.vue",
    "content": "<markdown>\n# 响应式列数\n\n你可以在 `n-config-provider` 定制 [breakpoints](config-provider#API)。\n</markdown>\n\n<template>\n  <n-divider>Self 响应式</n-divider>\n  <n-grid cols=\"2 400:4 600:6\">\n    <n-grid-item>\n      <div class=\"light-green\">\n        1\n      </div>\n    </n-grid-item>\n    <n-grid-item>\n      <div class=\"green\">\n        2\n      </div>\n    </n-grid-item>\n    <n-grid-item>\n      <div class=\"light-green\">\n        3\n      </div>\n    </n-grid-item>\n    <n-grid-item>\n      <div class=\"green\">\n        4\n      </div>\n    </n-grid-item>\n    <n-grid-item>\n      <div class=\"light-green\">\n        5\n      </div>\n    </n-grid-item>\n    <n-grid-item>\n      <div class=\"green\">\n        6\n      </div>\n    </n-grid-item>\n  </n-grid>\n  <n-divider>Screen 响应式</n-divider>\n  <n-grid cols=\"2 s:3 m:4 l:5 xl:6 2xl:7\" responsive=\"screen\">\n    <n-grid-item>\n      <div class=\"light-green\">\n        1\n      </div>\n    </n-grid-item>\n    <n-grid-item>\n      <div class=\"green\">\n        2\n      </div>\n    </n-grid-item>\n    <n-grid-item>\n      <div class=\"light-green\">\n        3\n      </div>\n    </n-grid-item>\n    <n-grid-item>\n      <div class=\"green\">\n        4\n      </div>\n    </n-grid-item>\n    <n-grid-item>\n      <div class=\"light-green\">\n        5\n      </div>\n    </n-grid-item>\n    <n-grid-item>\n      <div class=\"green\">\n        6\n      </div>\n    </n-grid-item>\n    <n-grid-item>\n      <div class=\"light-green\">\n        7\n      </div>\n    </n-grid-item>\n  </n-grid>\n</template>\n\n<style>\n.light-green {\n  height: 108px;\n  background-color: rgba(0, 128, 0, 0.12);\n  display: flex;\n  align-items: center;\n  justify-content: center;\n}\n.green {\n  height: 108px;\n  background-color: rgba(0, 128, 0, 0.24);\n  display: flex;\n  align-items: center;\n  justify-content: center;\n}\n</style>\n"
  },
  {
    "path": "src/grid/demos/zhCN/vshow-debug.demo.vue",
    "content": "<markdown>\n# Vshow debug\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { reactive } from 'vue'\n\n// 表单值，默认选择框的值为null\nconst formValue = reactive({ select: null })\n// 选择框选项\nconst selectOptions = [\n  {\n    label: '值为1',\n    value: 1\n  },\n  {\n    label: '值为2',\n    value: 2\n  }\n]\n</script>\n\n<template>\n  <n-form :model=\"formValue\" label-placement=\"left\" :style=\"{ margin: '30px' }\">\n    <n-grid :col=\"24\" x-gap=\"24\">\n      <n-form-item-gi :span=\"8\" label=\"选择框\">\n        <n-select\n          v-model:value=\"formValue.select\"\n          :style=\"{ width: '100%' }\"\n          :options=\"selectOptions\"\n          clearable\n        />\n      </n-form-item-gi>\n      <!-- 当选择框的值为2时显示，通过v-show控制是否显示 -->\n      <n-form-item-gi v-show=\"formValue.select === 2\" :span=\"8\" label=\"输入框1\">\n        <n-input value=\"我只有在选择框的值为2时才应该显示！\" />\n      </n-form-item-gi>\n      <!-- 当v-show作用在input中就无此问题 -->\n      <!-- <n-form-item-gi :span=\"8\" label=\"输入框2\">\n        <n-input value=\"我只有在选择框的值为2时才应该显示！\" v-show=\"formValue.select === 2\"/>\n      </n-form-item-gi> -->\n    </n-grid>\n  </n-form>\n  <!-- 问题总结 -->\n  <n-h2 prefix=\"bar\" align-text type=\"info\" :style=\"{ margin: '30px' }\">\n    期望：当选择框值为2时，显示输入框\n  </n-h2>\n  <n-h2 prefix=\"bar\" align-text type=\"error\" :style=\"{ margin: '30px' }\">\n    问题：当选择框值从null变为1时，依然显示了输入框，不符合预期\n  </n-h2>\n  <n-h2 prefix=\"bar\" align-text type=\"error\" :style=\"{ margin: '30px' }\">\n    问题：当选择框值从1变为null时，依然显示了输入框，不符合预期\n  </n-h2>\n</template>\n"
  },
  {
    "path": "src/grid/index.ts",
    "content": "export { gridProps, default as NGrid } from './src/Grid'\nexport type { GridProps } from './src/Grid'\nexport { gridItemProps, default as NGridItem } from './src/GridItem'\nexport { gridItemProps as giProps, default as NGi } from './src/GridItem'\nexport type { GridItemProps } from './src/GridItem'\n"
  },
  {
    "path": "src/grid/src/Grid.tsx",
    "content": "import type { CSSProperties, PropType, Ref, VNode } from 'vue'\nimport type { VResizeObserverOnResize } from 'vueuc'\nimport type { ExtractPublicPropTypes } from '../../_utils'\nimport { beforeNextFrameOnce, parseResponsivePropValue, pxfy } from 'seemly'\nimport { useBreakpoints, useMemo } from 'vooks'\nimport {\n  cloneVNode,\n  computed,\n  defineComponent,\n  h,\n  mergeProps,\n  onMounted,\n  provide,\n  ref,\n  toRef,\n  vShow\n} from 'vue'\nimport { VResizeObserver } from 'vueuc'\nimport { useConfig } from '../../_mixins'\nimport { flatten, getSlot, isBrowser, isNodeVShowFalse } from '../../_utils'\nimport { defaultBreakpoints } from '../../config-provider/src/config'\nimport { defaultSpan, gridInjectionKey } from './config'\n\nconst defaultCols = 24\n\nconst SSR_ATTR_NAME = '__ssr__'\n\nexport const gridProps = {\n  layoutShiftDisabled: Boolean,\n  responsive: {\n    type: [String, Boolean] as PropType<'self' | 'screen'>,\n    default: 'self'\n  },\n  cols: {\n    type: [Number, String] as PropType<number | string>,\n    default: defaultCols\n  },\n  itemResponsive: Boolean,\n  collapsed: Boolean,\n  // may create grid rows < collapsedRows since a item may take all the row\n  collapsedRows: {\n    type: Number,\n    default: 1\n  },\n  itemStyle: [Object, String] as PropType<CSSProperties | string>,\n  xGap: {\n    type: [Number, String] as PropType<number | string>,\n    default: 0\n  },\n  yGap: {\n    type: [Number, String] as PropType<number | string>,\n    default: 0\n  }\n} as const\n\nexport interface NGridInjection {\n  isSsrRef: Ref<boolean>\n  itemStyleRef: Ref<CSSProperties | string | undefined>\n  xGapRef: Ref<string | undefined>\n  overflowRef: Ref<boolean>\n  layoutShiftDisabledRef: Ref<boolean>\n}\n\nexport type GridProps = ExtractPublicPropTypes<typeof gridProps>\n\nexport default defineComponent({\n  name: 'Grid',\n  inheritAttrs: false,\n  props: gridProps,\n  setup(props) {\n    const { mergedClsPrefixRef, mergedBreakpointsRef } = useConfig(props)\n    const numRegex = /^\\d+$/\n    const widthRef = ref<number | undefined>(undefined)\n    const breakpointsRef = useBreakpoints(\n      mergedBreakpointsRef?.value || defaultBreakpoints\n    )\n    const isResponsiveRef = useMemo(() => {\n      if (props.itemResponsive)\n        return true\n      if (!numRegex.test(props.cols.toString()))\n        return true\n      if (!numRegex.test(props.xGap.toString()))\n        return true\n      if (!numRegex.test(props.yGap.toString()))\n        return true\n      return false\n    })\n    const responsiveQueryRef = computed(() => {\n      if (!isResponsiveRef.value)\n        return undefined\n      return props.responsive === 'self' ? widthRef.value : breakpointsRef.value\n    })\n    const responsiveColsRef = useMemo(() => {\n      return (\n        Number(\n          parseResponsivePropValue(\n            props.cols.toString(),\n            responsiveQueryRef.value\n          )\n        ) ?? defaultCols\n      )\n    })\n    const responsiveXGapRef = useMemo(() =>\n      parseResponsivePropValue(props.xGap.toString(), responsiveQueryRef.value)\n    )\n    const responsiveYGapRef = useMemo(() =>\n      parseResponsivePropValue(props.yGap.toString(), responsiveQueryRef.value)\n    )\n    const handleResize: VResizeObserverOnResize = (entry) => {\n      widthRef.value = entry.contentRect.width\n    }\n    const handleResizeRaf: VResizeObserverOnResize = (entry) => {\n      beforeNextFrameOnce(handleResize, entry)\n    }\n    const overflowRef = ref(false)\n    const handleResizeRef = computed<VResizeObserverOnResize | undefined>(\n      () => {\n        if (props.responsive === 'self') {\n          return handleResizeRaf\n        }\n        return undefined\n      }\n    )\n\n    // for SSR, fix bug https://github.com/tusen-ai/naive-ui/issues/2462\n    const isSsrRef = ref(false)\n    const contentElRef = ref<HTMLElement>()\n    onMounted(() => {\n      const { value: contentEl } = contentElRef\n      if (contentEl) {\n        if (contentEl.hasAttribute(SSR_ATTR_NAME)) {\n          contentEl.removeAttribute(SSR_ATTR_NAME)\n          isSsrRef.value = true\n        }\n      }\n    })\n\n    provide(gridInjectionKey, {\n      layoutShiftDisabledRef: toRef(props, 'layoutShiftDisabled'),\n      isSsrRef,\n      itemStyleRef: toRef(props, 'itemStyle'),\n      xGapRef: responsiveXGapRef,\n      overflowRef\n    })\n\n    return {\n      isSsr: !isBrowser,\n      contentEl: contentElRef,\n      mergedClsPrefix: mergedClsPrefixRef,\n      style: computed<CSSProperties>(() => {\n        if (props.layoutShiftDisabled) {\n          return {\n            width: '100%',\n            display: 'grid',\n            gridTemplateColumns: `repeat(${props.cols}, minmax(0, 1fr))`,\n            columnGap: pxfy(props.xGap),\n            rowGap: pxfy(props.yGap)\n          }\n        }\n        return {\n          width: '100%',\n          display: 'grid',\n          gridTemplateColumns: `repeat(${responsiveColsRef.value}, minmax(0, 1fr))`,\n          columnGap: pxfy(responsiveXGapRef.value),\n          rowGap: pxfy(responsiveYGapRef.value)\n        }\n      }),\n      isResponsive: isResponsiveRef,\n      responsiveQuery: responsiveQueryRef,\n      responsiveCols: responsiveColsRef,\n      handleResize: handleResizeRef,\n      overflow: overflowRef\n    }\n  },\n  render() {\n    if (this.layoutShiftDisabled) {\n      return h(\n        'div',\n        mergeProps(\n          {\n            ref: 'contentEl',\n            class: `${this.mergedClsPrefix}-grid`,\n            style: this.style\n          },\n          this.$attrs\n        ),\n        this.$slots\n      )\n    }\n\n    const renderContent = (): VNode => {\n      this.overflow = false\n\n      // render will be called twice when mounted, I can't figure out why\n      // 2 jobs will be pushed into job queues with same id, and then be flushed\n      const rawChildren = flatten(getSlot(this))\n\n      const childrenAndRawSpan: Array<{\n        child: VNode\n        rawChildSpan: number\n      }> = []\n\n      const { collapsed, collapsedRows, responsiveCols, responsiveQuery } = this\n\n      rawChildren.forEach((child) => {\n        if ((child?.type as any)?.__GRID_ITEM__ !== true)\n          return\n\n        if (isNodeVShowFalse(child)) {\n          const clonedNode = cloneVNode(child)\n          if (clonedNode.props) {\n            clonedNode.props.privateShow = false\n          }\n          else {\n            clonedNode.props = { privateShow: false }\n          }\n          childrenAndRawSpan.push({\n            child: clonedNode,\n            rawChildSpan: 0\n          })\n          return\n        }\n\n        // We don't want v-show to control display, so we need to stripe it\n        // here, nor it may mess child's style\n        child.dirs = child.dirs?.filter(({ dir }) => dir !== vShow) || null\n\n        if (child.dirs?.length === 0) {\n          child.dirs = null\n        }\n        const clonedChild = cloneVNode(child)\n\n        const rawChildSpan = Number(\n          parseResponsivePropValue(\n            clonedChild.props?.span as string | number | undefined,\n            responsiveQuery\n          ) ?? defaultSpan\n        )\n\n        if (rawChildSpan === 0)\n          return\n        childrenAndRawSpan.push({\n          child: clonedChild,\n          rawChildSpan\n        })\n      })\n\n      let suffixSpan = 0\n      const maybeSuffixNode\n        = childrenAndRawSpan[childrenAndRawSpan.length - 1]?.child\n      if (maybeSuffixNode?.props) {\n        const suffixPropValue = maybeSuffixNode.props?.suffix\n        if (suffixPropValue !== undefined && suffixPropValue !== false) {\n          suffixSpan = Number(\n            parseResponsivePropValue(\n              maybeSuffixNode.props?.span as string | number | null | undefined,\n              responsiveQuery\n            ) ?? defaultSpan\n          )\n          maybeSuffixNode.props.privateSpan = suffixSpan\n          maybeSuffixNode.props.privateColStart\n            = responsiveCols + 1 - suffixSpan\n          maybeSuffixNode.props.privateShow\n            = maybeSuffixNode.props.privateShow ?? true\n        }\n      }\n\n      let spanCounter = 0\n      let done = false\n      for (const { child, rawChildSpan } of childrenAndRawSpan) {\n        if (done) {\n          this.overflow = true\n        }\n\n        if (!done) {\n          const childOffset = Number(\n            parseResponsivePropValue(\n              child.props?.offset as string | number | undefined,\n              responsiveQuery\n            ) ?? 0\n          )\n          // it could be 0 sometimes (v-show = false)\n          const childSpan = Math.min(rawChildSpan + childOffset, responsiveCols)\n          if (!child.props) {\n            child.props = {\n              privateSpan: childSpan,\n              privateOffset: childOffset\n            }\n          }\n          else {\n            child.props.privateSpan = childSpan\n            child.props.privateOffset = childOffset\n          }\n          if (collapsed) {\n            const remainder = spanCounter % responsiveCols\n            if (childSpan + remainder > responsiveCols) {\n              spanCounter += responsiveCols - remainder\n            }\n            if (\n              childSpan + spanCounter + suffixSpan\n              > collapsedRows * responsiveCols\n            ) {\n              done = true\n            }\n            else {\n              spanCounter += childSpan\n            }\n          }\n        }\n        if (done) {\n          if (child.props) {\n            // suffix node's privateShow may be true\n            if (child.props.privateShow !== true) {\n              child.props.privateShow = false\n            }\n          }\n          else {\n            child.props = {\n              privateShow: false\n            }\n          }\n        }\n      }\n      return h(\n        'div',\n        mergeProps(\n          {\n            ref: 'contentEl',\n            class: `${this.mergedClsPrefix}-grid`,\n            style: this.style,\n            [SSR_ATTR_NAME]: this.isSsr || undefined\n          },\n          this.$attrs\n        ),\n        childrenAndRawSpan.map(({ child }) => child)\n      )\n    }\n    return this.isResponsive && this.responsive === 'self' ? (\n      <VResizeObserver onResize={this.handleResize}>\n        {{\n          default: renderContent\n        }}\n      </VResizeObserver>\n    ) : (\n      renderContent()\n    )\n  }\n})\n"
  },
  {
    "path": "src/grid/src/GridItem.tsx",
    "content": "import type { PropType } from 'vue'\nimport type { ExtractPublicPropTypes } from '../../_utils'\nimport { pxfy } from 'seemly'\nimport { computed, defineComponent, getCurrentInstance, h, inject } from 'vue'\nimport { keysOf } from '../../_utils'\nimport { gridInjectionKey } from './config'\n\nexport const defaultSpan = 1\n\ninterface GridItemVNodeProps {\n  privateOffset?: number\n  privateSpan?: number\n  privateColStart?: number\n  privateShow?: boolean\n}\n\nexport const gridItemProps = {\n  span: {\n    type: [Number, String] as PropType<string | number>,\n    default: defaultSpan\n  },\n  offset: {\n    type: [Number, String] as PropType<string | number>,\n    default: 0\n  },\n  suffix: Boolean,\n  // private props\n  privateOffset: Number,\n  privateSpan: Number,\n  privateColStart: Number,\n  privateShow: {\n    type: Boolean,\n    default: true\n  }\n} as const\n\nexport const gridItemPropKeys = keysOf(gridItemProps)\n\nexport type GridItemProps = ExtractPublicPropTypes<typeof gridItemProps>\n\nexport default defineComponent({\n  __GRID_ITEM__: true,\n  name: 'GridItem',\n  alias: ['Gi'],\n  props: gridItemProps,\n  setup() {\n    const {\n      isSsrRef,\n      xGapRef,\n      itemStyleRef,\n      overflowRef,\n      layoutShiftDisabledRef\n    } = inject(gridInjectionKey)!\n    const self = getCurrentInstance()\n    return {\n      overflow: overflowRef,\n      itemStyle: itemStyleRef,\n      layoutShiftDisabled: layoutShiftDisabledRef,\n      mergedXGap: computed(() => {\n        return pxfy(xGapRef.value || 0)\n      }),\n      deriveStyle: () => {\n        void isSsrRef.value\n        // Here is quite a hack, I hope there is a better way to solve it\n        const {\n          privateSpan = defaultSpan,\n          privateShow = true,\n          privateColStart = undefined,\n          privateOffset = 0\n        } = self!.vnode.props as GridItemVNodeProps\n        const { value: xGap } = xGapRef\n        const mergedXGap = pxfy(xGap || 0)\n        return {\n          display: !privateShow ? 'none' : '',\n          gridColumn: `${\n            privateColStart ?? `span ${privateSpan}`\n          } / span ${privateSpan}`,\n          marginLeft: privateOffset\n            ? `calc((100% - (${privateSpan} - 1) * ${mergedXGap}) / ${privateSpan} * ${privateOffset} + ${mergedXGap} * ${privateOffset})`\n            : ''\n        }\n      }\n    }\n  },\n  render() {\n    if (this.layoutShiftDisabled) {\n      const { span, offset, mergedXGap } = this\n      return (\n        <div\n          style={{\n            gridColumn: `span ${span} / span ${span}`,\n            marginLeft: offset\n              ? `calc((100% - (${span} - 1) * ${mergedXGap}) / ${span} * ${offset} + ${mergedXGap} * ${offset})`\n              : ''\n          }}\n        >\n          {this.$slots}\n        </div>\n      )\n    }\n    return (\n      <div style={[this.itemStyle as any, this.deriveStyle()]}>\n        {this.$slots.default?.({ overflow: this.overflow })}\n      </div>\n    )\n  }\n})\n"
  },
  {
    "path": "src/grid/src/config.ts",
    "content": "import type { NGridInjection } from './Grid'\nimport { createInjectionKey } from '../../_utils'\n\nexport const defaultSpan = 1\nexport const gridInjectionKey = createInjectionKey<NGridInjection>('n-grid')\n"
  },
  {
    "path": "src/grid/tests/Grid.spec.tsx",
    "content": "import { mount } from '@vue/test-utils'\nimport { defineComponent, h } from 'vue'\nimport { NGi, NGrid, NGridItem } from '../index'\n\nconst renderNGi = Array.from({ length: 6 })\n  .fill(1)\n  .map((v, i) => {\n    return h(NGi, null, { default: () => i })\n  })\n\ndescribe('n-grid', () => {\n  it('should work with import on demand', () => {\n    mount(\n      defineComponent({\n        render() {\n          return (\n            <NGrid>\n              {{\n                default: () => [<NGridItem />]\n              }}\n            </NGrid>\n          )\n        }\n      })\n    )\n  })\n\n  it('should work with import on demand 2', () => {\n    mount(\n      defineComponent({\n        render() {\n          return (\n            <NGrid>\n              {{\n                default: () => [<NGi />]\n              }}\n            </NGrid>\n          )\n        }\n      })\n    )\n  })\n\n  it('should work with `gap` prop', async () => {\n    const wrapper = mount(NGrid, {\n      props: {\n        'x-gap': 10,\n        'y-gap': 20\n      },\n      slots: {\n        default: () => [\n          h(NGi, null, { default: () => 'test1' }),\n          h(NGridItem, null, { default: () => 'test2' })\n        ]\n      }\n    })\n    expect(wrapper.find('.n-grid').attributes('style')).toContain(\n      'column-gap: 10px; row-gap: 20px;'\n    )\n    wrapper.unmount()\n  })\n\n  it('should work with `offset` prop', async () => {\n    const wrapper = mount(NGrid, {\n      slots: {\n        default: () => [\n          h(NGi, { offset: 2 }, { default: () => 'test1' }),\n          h(NGridItem, { offset: 1 }, { default: () => 'test2' })\n        ]\n      }\n    })\n    expect(\n      wrapper.find('.n-grid').element.children[0].getAttribute('style')\n    ).toContain('grid-column: span 3 / span 3;')\n    expect(\n      wrapper.find('.n-grid').element.children[1].getAttribute('style')\n    ).toContain('grid-column: span 2 / span 2;')\n    wrapper.unmount()\n  })\n\n  it('should work with `collapsed` prop', async () => {\n    const wrapper = mount(NGrid, {\n      slots: {\n        default: () => renderNGi\n      },\n      props: {\n        cols: 4,\n        collapsed: false\n      }\n    })\n    const children = wrapper.find('.n-grid').element.children\n    let len = 0\n    for (let i = 0; i < children.length; i++) {\n      if (\n        children[i]\n          .getAttribute('style')\n          ?.includes('grid-column: span 1 / span 1;')\n      ) {\n        len++\n      }\n    }\n    expect(len).toBe(6)\n    await wrapper.setProps({ collapsed: true })\n    let len1 = 0\n    for (let i = 0; i < children.length; i++) {\n      if (\n        children[i]\n          .getAttribute('style')\n          ?.includes('grid-column: span 1 / span 1; display: none;')\n      ) {\n        len1++\n      }\n    }\n    expect(len1).toBe(2)\n    wrapper.unmount()\n  })\n\n  it('should work with `suffix` prop', async () => {\n    const wrapper = mount(NGrid, {\n      slots: {\n        default: () => [\n          renderNGi,\n          h(NGi, { suffix: true }, { default: () => 'suffix' })\n        ]\n      },\n      props: {\n        cols: 4,\n        collapsed: false\n      }\n    })\n    const children = wrapper.find('.n-grid').element.children\n    let len = 0\n    for (let i = 0; i < children.length; i++) {\n      if (\n        children[i]\n          .getAttribute('style')\n          ?.includes('grid-column: span 1 / span 1;')\n      ) {\n        len++\n      }\n    }\n    expect(len).toBe(6)\n    await wrapper.setProps({ collapsed: true })\n    let len1 = 0\n    for (let i = 0; i < children.length; i++) {\n      if (\n        children[i]\n          .getAttribute('style')\n          ?.includes('grid-column: span 1 / span 1; display: none;')\n      ) {\n        len1++\n      }\n    }\n    expect(len1).toBe(3)\n    wrapper.unmount()\n  })\n\n  it('should work with `item-responsive` prop', async () => {\n    const wrapper = mount(NGrid, {\n      slots: {\n        default: () => [\n          <NGi class=\"n-gi-1\" span=\"0 400:2 600:3 800:4\">\n            {{\n              default: () => <div>1</div>\n            }}\n          </NGi>,\n          <NGi class=\"n-gi-2\">\n            {{\n              default: () => <div>2</div>\n            }}\n          </NGi>\n        ]\n      },\n      props: {\n        cols: 4,\n        responsive: 'self',\n        itemResponsive: true\n      }\n    })\n\n    expect(wrapper.find('.n-gi-1').exists()).toBeFalsy()\n\n    const instance = wrapper.getCurrentComponent().proxy\n    ;(instance as any).handleResize({ contentRect: { width: 500 } })\n    await new Promise(resolve => requestAnimationFrame(resolve))\n\n    expect(wrapper.find('.n-gi-1').element.getAttribute('style')).toContain(\n      'grid-column: span 2 / span 2;'\n    )\n    wrapper.unmount()\n  })\n})\n"
  },
  {
    "path": "src/grid/tests/server.spec.tsx",
    "content": "import { setup } from '@css-render/vue3-ssr'\nimport { renderToString } from '@vue/server-renderer'\n/**\n * @vitest-environment node\n */\nimport { createSSRApp, h } from 'vue'\nimport { NGrid, NGridItem } from '../..'\n\ndescribe('server side rendering', () => {\n  it('works 1', async () => {\n    const app = createSSRApp(() => <NGrid />)\n    setup(app)\n    try {\n      await renderToString(app)\n    }\n    catch (e) {\n      expect(e).not.toBeTruthy()\n    }\n  })\n  it('works 2', async () => {\n    const app = createSSRApp(() => (\n      <NGrid>{{ default: () => <NGridItem /> }}</NGrid>\n    ))\n    setup(app)\n    try {\n      await renderToString(app)\n    }\n    catch (e) {\n      expect(e).not.toBeTruthy()\n    }\n  })\n})\n"
  },
  {
    "path": "src/heatmap/demos/enUS/basic.demo.vue",
    "content": "<markdown>\n# Basic\n\nEvery square is a piece of persistence, and blanks are the rhythm of life.\n</markdown>\n\n<script setup lang=\"ts\">\nimport type { HeatmapFirstDayOfWeek } from 'naive-ui'\nimport { heatmapMockData } from 'naive-ui'\nimport { computed, ref } from 'vue'\n\nconst value = ref<'recent' | number>('recent')\nconst dateRanges = [\n  {\n    value: 'recent',\n    label: 'Recent Year'\n  },\n  {\n    value: 2025,\n    label: 2025\n  },\n  {\n    value: 2024,\n    label: 2024\n  },\n  {\n    value: 2023,\n    label: 2023\n  },\n  {\n    value: 2022,\n    label: 2022\n  }\n].map((r) => {\n  return {\n    ...r,\n    label: r.label.toString()\n  }\n}) as {\n  value: 'recent' | number\n  label: string\n}[]\n\nconst yearData = computed(() => {\n  return heatmapMockData(value.value)\n})\n\nconst dataStats = computed(() => {\n  const data = yearData.value\n  const total = data.length\n  const zeros = data.filter(d => d.value === 0).length\n  const maxValue = Math.max(...data.map(d => d.value ?? 0))\n  const avgValue\n    = Math.round(\n      (data.reduce((sum, d) => sum + (d.value ?? 0), 0) / total) * 100\n    ) / 100\n\n  return {\n    total,\n    zeros,\n    maxValue,\n    avgValue,\n    zeroPercent: Math.round((zeros / total) * 100)\n  }\n})\n\nconst showWeekLabels = ref(true)\nconst showMonthLabels = ref(true)\nconst showColorIndicator = ref(true)\nconst loading = ref(false)\nconst firstDayOfWeek = ref<HeatmapFirstDayOfWeek>(0)\nconst size = ref<'small' | 'medium' | 'large'>('medium')\n\nconst weekStartOptions = [\n  { label: 'Sunday', value: 0 },\n  { label: 'Monday', value: 1 },\n  { label: 'Tuesday', value: 2 },\n  { label: 'Wednesday', value: 3 },\n  { label: 'Thursday', value: 4 },\n  { label: 'Friday', value: 5 },\n  { label: 'Saturday', value: 6 }\n]\n\nconst sizeOptions = [\n  { label: 'Small', value: 'small' },\n  { label: 'Medium', value: 'medium' },\n  { label: 'Large', value: 'large' }\n]\n</script>\n\n<template>\n  <n-flex vertical>\n    <n-flex align=\"center\" justify=\"start\">\n      <n-switch v-model:value=\"showWeekLabels\">\n        <template #checked>\n          Show Week Labels\n        </template>\n        <template #unchecked>\n          Hide Week Labels\n        </template>\n      </n-switch>\n      <n-switch v-model:value=\"showMonthLabels\">\n        <template #checked>\n          Show Month Labels\n        </template>\n        <template #unchecked>\n          Hide Month Labels\n        </template>\n      </n-switch>\n      <n-switch v-model:value=\"showColorIndicator\">\n        <template #checked>\n          Show Color Indicator\n        </template>\n        <template #unchecked>\n          Hide Color Indicator\n        </template>\n      </n-switch>\n      <n-switch v-model:value=\"loading\">\n        <template #checked>\n          Loading\n        </template>\n        <template #unchecked>\n          Normal\n        </template>\n      </n-switch>\n      <n-divider vertical />\n      <span>Week Starts On:</span>\n      <n-select\n        v-model:value=\"firstDayOfWeek\"\n        :options=\"weekStartOptions\"\n        style=\"width: 120px\"\n      />\n      <n-divider vertical />\n    </n-flex>\n    <n-flex>\n      <n-radio-group v-model:value=\"size\" name=\"size\">\n        <n-radio-button\n          v-for=\"option in sizeOptions\"\n          :key=\"option.value\"\n          :value=\"option.value\"\n          :label=\"option.label\"\n        />\n      </n-radio-group>\n      <n-divider vertical />\n      <n-radio-group v-model:value=\"value\" name=\"year\">\n        <n-radio-button\n          v-for=\"range in dateRanges\"\n          :key=\"range.value\"\n          :value=\"range.value\"\n          :label=\"range.label\"\n        />\n      </n-radio-group>\n    </n-flex>\n    <n-alert type=\"success\" title=\"Data Statistics\">\n      <n-flex>\n        <n-tag round type=\"info\">\n          Total Days: {{ dataStats.total }}\n        </n-tag>\n        <n-tag round type=\"warning\">\n          Empty Days: {{ dataStats.zeros }} ({{ dataStats.zeroPercent }}%)\n        </n-tag>\n        <n-tag round type=\"success\">\n          Max Value: {{ dataStats.maxValue }}\n        </n-tag>\n        <n-tag round type=\"primary\">\n          Average: {{ dataStats.avgValue }}\n        </n-tag>\n      </n-flex>\n    </n-alert>\n    <n-scrollbar x-scrollable style=\"max-width: 100%\">\n      <n-heatmap\n        :data=\"yearData\"\n        :loading-data=\"yearData\"\n        :first-day-of-week=\"firstDayOfWeek\"\n        :loading=\"loading\"\n        :size=\"size\"\n        unit=\"commits\"\n        :show-week-labels=\"showWeekLabels\"\n        :show-month-labels=\"showMonthLabels\"\n        :show-color-indicator=\"showColorIndicator\"\n        :fill-calendar-leading=\"value === 'recent'\"\n      />\n    </n-scrollbar>\n  </n-flex>\n</template>\n"
  },
  {
    "path": "src/heatmap/demos/enUS/colors.demo.vue",
    "content": "<markdown>\n# Custom Colors\n\nEach color has its own temperature.\n</markdown>\n\n<script setup lang=\"ts\">\nimport { heatmapMockData } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst data = heatmapMockData()\n\nconst customActiveColors = ref(['#9be9a8', '#40c463', '#30a14e', '#216e39'])\n\nconst minimumColor = ref('#ebedf0')\n\nconst colorLabels = ['Low', 'Medium', 'High', 'Very High']\n</script>\n\n<template>\n  <n-flex justify=\"space-around\">\n    <div>\n      <n-flex vertical align=\"center\">\n        <span>Minimum Color</span>\n        <n-color-picker\n          v-model:value=\"minimumColor\"\n          :show-alpha=\"false\"\n          size=\"small\"\n          :modes=\"['hex']\"\n          style=\"width: 100px\"\n        />\n      </n-flex>\n    </div>\n    <div v-for=\"(_, index) in customActiveColors\" :key=\"index\">\n      <n-flex vertical align=\"center\">\n        <span>{{ colorLabels[index] }}</span>\n        <n-color-picker\n          v-model:value=\"customActiveColors[index]\"\n          :show-alpha=\"false\"\n          size=\"small\"\n          :modes=\"['hex']\"\n          style=\"width: 100px\"\n        />\n      </n-flex>\n    </div>\n  </n-flex>\n  <n-divider />\n  <n-scrollbar x-scrollable style=\"max-width: 100%\">\n    <n-heatmap\n      :data=\"data\"\n      unit=\"commits\"\n      :active-colors=\"customActiveColors\"\n      :minimum-color=\"minimumColor\"\n    />\n  </n-scrollbar>\n</template>\n"
  },
  {
    "path": "src/heatmap/demos/enUS/index.demo-entry.md",
    "content": "<!--single-column-->\n\n# Heatmap\n\nDigital workers have their own wall to paint.\n\nAvailable from `2.43.0`.\n\n<n-alert type=\"info\" title=\"Usage Prerequisites\" :bordered=\"false\">\n  <n-text>\n    Color-related properties <n-text code>active-colors</n-text> and <n-text code>minimum-color</n-text> have higher priority than <n-text code>color-theme</n-text>. If these three properties are set simultaneously, <n-text code>active-colors</n-text> and <n-text code>minimum-color</n-text> will be used. It is recommended not to set them at the same time.\n  </n-text>\n  <br />\n  <n-text>\n    When none are set, the default value built into Naive UI is used - a GitHub-style theme.\n  </n-text>\n</n-alert>\n\n## Demos\n\n```demo\nbasic.vue\nthemes.vue\ncolors.vue\nslots.vue\n```\n\n## API\n\n### Heatmap Props\n\nType `HeatmapProps`\n\n| Name | Type | Related Type | Default | Description | Version |\n| --- | --- | --- | --- | --- | --- |\n| active-colors | `string[]` | - | `undefined` | Color array arranged from light to dark, higher priority than `color-theme`. | 2.43.0 |\n| color-theme | `'green' \\| 'blue' \\| 'orange' \\| 'purple' \\| 'red'` | `HeatmapColorTheme` | `undefined` | Built-in color theme. | 2.43.0 |\n| data | `Array<{ timestamp: number, value?: number \\| null }>` | `HeatmapData`, `HeatmapDataItem` | `[]` | Heatmap data containing timestamp and value. | 2.43.0 |\n| first-day-of-week | `0 \\| 1 \\| 2 \\| 3 \\| 4 \\| 5 \\| 6` | `HeatmapFirstDayOfWeek` | `0` | Start day of the week, 0 for Monday, 6 for Sunday. | 2.43.0 |\n| fill-calendar-leading | `boolean` | - | `false` | Whether to fill the leading of calendar grid, suitable for GitHub style recent year view. | 2.43.0 |\n| loading | `boolean` | - | `false` | Whether to show loading state. | 2.43.0 |\n| loading-data | `Array<{ timestamp: number, value?: number \\| null }>` | `HeatmapData`, `HeatmapDataItem` | `undefined` | Data to display in loading status. If item's `value` is `null`, cell is hidden but will occupy place. If. item's `value` is anything but `null`, cell will show loading status. | 2.43.0 |\n| minimum-color | `string` | - | `undefined` | Minimum color for the heatmap, defaults to the first color in `active-colors`. | 2.43.0 |\n| show-color-indicator | `boolean` | - | `true` | Whether to show the color level indicator at the bottom | 2.43.0 |\n| show-month-labels | `boolean` | - | `true` | Whether to show month labels. | 2.43.0 |\n| show-week-labels | `boolean` | - | `true` | Whether to show week labels. | 2.43.0 |\n| size | `'small' \\| 'medium' \\| 'large'` | - | `'medium'` | Heatmap size. | 2.43.0 |\n| tooltip | `boolean \\| TooltipProps` | - | `false` | Tooltip configuration, `false` to disable, object for `TooltipProps`. | 2.43.0 |\n| x-gap | `number \\| string` | - | `undefined` | Horizontal gap | 2.43.0 |\n| y-gap | `number \\| string` | - | `undefined` | Vertical gap | 2.43.0 |\n\n### Heatmap Slots\n\nType `HeatmapSlots`\n\n| Name | Parameters | Related Type | Description | Version |\n| --- | --- | --- | --- | --- |\n| footer | `()` | - | Left footer slot, aligned with the left side of heatmap table | 2.43.0 |\n| indicator | `()` | - | Right footer indicator slot, aligned with the right side of heatmap table | 2.43.0 |\n| indicator-leading-text | `()` | - | Leading text for the color level indicator | 2.43.0 |\n| indicator-trailing-text | `()` | - | Trailing text for the color level indicator | 2.43.0 |\n| tooltip | `(props: { timestamp: number, value?: number \\| null })` | `HeatmapTooltipSlotProps` | Custom tooltip content | 2.43.0 |\n\n### Others\n\n1. `import { heatmapMockData } from 'naive-ui'`, `function heatmapMockData(year?: 'recent' | number): HeatmapData`\n"
  },
  {
    "path": "src/heatmap/demos/enUS/slots.demo.vue",
    "content": "<markdown>\n# Slots\n\nCustomize footer area with `footer` slot and `indicator` slot. Also supports custom `tooltip` content and indicator text slots.\n</markdown>\n\n<script setup lang=\"ts\">\nimport { heatmapMockData } from 'naive-ui'\n\nconst yearData = heatmapMockData()\n</script>\n\n<template>\n  <n-flex vertical>\n    <n-scrollbar x-scrollable style=\"max-width: 100%\">\n      <n-heatmap :data=\"yearData\" :show-color-indicator=\"false\">\n        <template #footer>\n          <n-text depth=\"3\">\n            Left footer slot\n          </n-text>\n        </template>\n        <template #indicator>\n          <n-text depth=\"3\">\n            Right indicator slot\n          </n-text>\n        </template>\n        <template #tooltip=\"{ timestamp: date, value: tooltipValue }\">\n          <div>\n            <div>\n              <strong>Date:</strong> {{ new Date(date).toLocaleDateString() }}\n            </div>\n            <div><strong>Value:</strong> {{ tooltipValue ?? 0 }}</div>\n            <div v-if=\"tooltipValue != null && tooltipValue > 5\">\n              <n-tag type=\"success\" size=\"small\">\n                High Activity\n              </n-tag>\n            </div>\n          </div>\n        </template>\n      </n-heatmap>\n    </n-scrollbar>\n    <n-divider />\n    <h4>Custom Indicator Text</h4>\n    <n-scrollbar x-scrollable style=\"max-width: 100%\">\n      <n-heatmap :data=\"yearData\">\n        <template #indicator-leading-text>\n          <n-text depth=\"3\" style=\"font-style: italic\">\n            Less\n          </n-text>\n        </template>\n        <template #indicator-trailing-text>\n          <n-text depth=\"3\" style=\"font-style: italic\">\n            More\n          </n-text>\n        </template>\n      </n-heatmap>\n    </n-scrollbar>\n    <n-divider />\n    <h4>Custom Tooltip Configuration</h4>\n    <n-scrollbar x-scrollable style=\"max-width: 100%\">\n      <n-heatmap\n        :data=\"yearData\"\n        unit=\"activities\"\n        :tooltip=\"{ placement: 'bottom', delay: 500 }\"\n      >\n        <template #footer>\n          <n-text depth=\"3\">\n            Tooltip shown at bottom with 500ms delay\n          </n-text>\n        </template>\n        <template #tooltip=\"{ timestamp: date, value: tooltipValue }\">\n          Activity Details<br>\n          <div>{{ new Date(date).toLocaleDateString() }}</div>\n          <div>{{ tooltipValue ?? 0 }}</div>\n        </template>\n      </n-heatmap>\n    </n-scrollbar>\n  </n-flex>\n</template>\n"
  },
  {
    "path": "src/heatmap/demos/enUS/themes.demo.vue",
    "content": "<markdown>\n# Built-in Themes\n\nUse the `color-theme` prop to apply built-in color themes. Available themes: `green`, `blue`, `orange`, `purple`, `red`.\n</markdown>\n\n<script setup lang=\"ts\">\nimport { heatmapMockData } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst data = ref(heatmapMockData())\n\nconst themes = [\n  { name: 'Green', value: 'green' },\n  { name: 'Blue', value: 'blue' },\n  { name: 'Orange', value: 'orange' },\n  { name: 'Purple', value: 'purple' },\n  { name: 'Red', value: 'red' }\n] as const\n</script>\n\n<template>\n  <n-flex vertical size=\"large\">\n    <div v-for=\"theme in themes\" :key=\"theme.value\">\n      <n-divider title-placement=\"left\">\n        {{ theme.name }}\n      </n-divider>\n      <n-heatmap :data=\"data\" unit=\"commits\" :color-theme=\"theme.value\" />\n    </div>\n  </n-flex>\n</template>\n"
  },
  {
    "path": "src/heatmap/demos/zhCN/basic.demo.vue",
    "content": "<markdown>\n# 基础用法\n\n每个方块都是一份坚持，空白也是生活的节拍。\n</markdown>\n\n<script setup lang=\"ts\">\nimport type { HeatmapFirstDayOfWeek } from 'naive-ui'\nimport { heatmapMockData } from 'naive-ui'\nimport { computed, ref } from 'vue'\n\nconst value = ref<'recent' | number>('recent')\nconst dateRanges = [\n  {\n    value: 'recent',\n    label: '最近一年'\n  },\n  {\n    value: 2025,\n    label: 2025\n  },\n  {\n    value: 2024,\n    label: 2024\n  },\n  {\n    value: 2023,\n    label: 2023\n  },\n  {\n    value: 2022,\n    label: 2022\n  }\n].map((r) => {\n  return {\n    ...r,\n    label: r.label.toString()\n  }\n}) as {\n  value: 'recent' | number\n  label: string\n}[]\n\nconst yearData = computed(() => {\n  return heatmapMockData(value.value)\n})\n\nconst dataStats = computed(() => {\n  const data = yearData.value\n  const total = data.length\n  const zeros = data.filter(d => d.value === 0).length\n  const maxValue = Math.max(...data.map(d => d.value ?? 0))\n  const avgValue\n    = Math.round(\n      (data.reduce((sum, d) => sum + (d.value ?? 0), 0) / total) * 100\n    ) / 100\n\n  return {\n    total,\n    zeros,\n    maxValue,\n    avgValue,\n    zeroPercent: Math.round((zeros / total) * 100)\n  }\n})\n\nconst showWeekLabels = ref(true)\nconst showMonthLabels = ref(true)\nconst showColorIndicator = ref(true)\nconst loading = ref(false)\nconst firstDayOfWeek = ref<HeatmapFirstDayOfWeek>(0)\nconst size = ref<'small' | 'medium' | 'large'>('medium')\n\nconst weekStartOptions = [\n  { label: '周一', value: 0 },\n  { label: '周二', value: 1 },\n  { label: '周三', value: 2 },\n  { label: '周四', value: 3 },\n  { label: '周五', value: 4 },\n  { label: '周六', value: 5 },\n  { label: '周日', value: 6 }\n]\n\nconst sizeOptions = [\n  { label: '小', value: 'small' },\n  { label: '中', value: 'medium' },\n  { label: '大', value: 'large' }\n]\n</script>\n\n<template>\n  <n-flex vertical>\n    <n-flex align=\"center\" justify=\"start\">\n      <n-switch v-model:value=\"showWeekLabels\">\n        <template #checked>\n          显示周标签\n        </template>\n        <template #unchecked>\n          隐藏周标签\n        </template>\n      </n-switch>\n      <n-switch v-model:value=\"showMonthLabels\">\n        <template #checked>\n          显示月份标签\n        </template>\n        <template #unchecked>\n          隐藏月份标签\n        </template>\n      </n-switch>\n      <n-switch v-model:value=\"showColorIndicator\">\n        <template #checked>\n          显示颜色指示器\n        </template>\n        <template #unchecked>\n          隐藏颜色指示器\n        </template>\n      </n-switch>\n      <n-switch v-model:value=\"loading\">\n        <template #checked>\n          加载中\n        </template>\n        <template #unchecked>\n          正常显示\n        </template>\n      </n-switch>\n      <n-divider vertical />\n      <span>周开始日：</span>\n      <n-select\n        v-model:value=\"firstDayOfWeek\"\n        :options=\"weekStartOptions\"\n        style=\"width: 120px\"\n      />\n      <n-divider vertical />\n    </n-flex>\n    <n-flex>\n      <n-radio-group v-model:value=\"size\" name=\"size\">\n        <n-radio-button\n          v-for=\"option in sizeOptions\"\n          :key=\"option.value\"\n          :value=\"option.value\"\n          :label=\"option.label\"\n        />\n      </n-radio-group>\n      <n-divider vertical />\n      <n-radio-group v-model:value=\"value\" name=\"year\">\n        <n-radio-button\n          v-for=\"range in dateRanges\"\n          :key=\"range.value\"\n          :value=\"range.value\"\n          :label=\"range.label\"\n        />\n      </n-radio-group>\n    </n-flex>\n    <n-alert type=\"success\" title=\"数据统计\">\n      <n-flex>\n        <n-tag round type=\"info\">\n          总天数: {{ dataStats.total }}\n        </n-tag>\n        <n-tag round type=\"warning\">\n          空白天: {{ dataStats.zeros }} ({{ dataStats.zeroPercent }}%)\n        </n-tag>\n        <n-tag round type=\"success\">\n          最大值: {{ dataStats.maxValue }}\n        </n-tag>\n        <n-tag round type=\"primary\">\n          平均值: {{ dataStats.avgValue }}\n        </n-tag>\n      </n-flex>\n    </n-alert>\n    <n-scrollbar x-scrollable style=\"max-width: 100%\">\n      <n-heatmap\n        :data=\"yearData\"\n        :loading-data=\"yearData\"\n        :first-day-of-week=\"firstDayOfWeek\"\n        :loading=\"loading\"\n        :size=\"size\"\n        :show-week-labels=\"showWeekLabels\"\n        :show-month-labels=\"showMonthLabels\"\n        :show-color-indicator=\"showColorIndicator\"\n        :fill-calendar-leading=\"value === 'recent'\"\n      />\n    </n-scrollbar>\n  </n-flex>\n</template>\n"
  },
  {
    "path": "src/heatmap/demos/zhCN/colors.demo.vue",
    "content": "<markdown>\n# 自定义颜色\n\n每一种颜色都有它的温度。\n\n通过 `active-colors` 和 `minimum-color` 属性自定义热力图的颜色。\n\n`active-colors` 是一个颜色数组，按从浅到深的顺序排列，优先级高于内置主题。`minimum-color` 用于设置最小值的颜色。\n</markdown>\n\n<script setup lang=\"ts\">\nimport { heatmapMockData } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst data = heatmapMockData()\n\nconst customActiveColors = ref(['#9be9a8', '#40c463', '#30a14e', '#216e39'])\n\nconst minimumColor = ref('#ebedf0')\n\nconst colorLabels = ['低活跃', '中活跃', '高活跃', '极高活跃']\n</script>\n\n<template>\n  <n-flex justify=\"space-around\">\n    <div>\n      <n-flex vertical align=\"center\">\n        <span>最小颜色</span>\n        <n-color-picker\n          v-model:value=\"minimumColor\"\n          :show-alpha=\"false\"\n          size=\"small\"\n          :modes=\"['hex']\"\n          style=\"width: 100px\"\n        />\n      </n-flex>\n    </div>\n    <div v-for=\"(_, index) in customActiveColors\" :key=\"index\">\n      <n-flex vertical align=\"center\">\n        <span>{{ colorLabels[index] }}</span>\n        <n-color-picker\n          v-model:value=\"customActiveColors[index]\"\n          :show-alpha=\"false\"\n          size=\"small\"\n          :modes=\"['hex']\"\n          style=\"width: 100px\"\n        />\n      </n-flex>\n    </div>\n  </n-flex>\n  <n-divider />\n  <n-scrollbar x-scrollable style=\"max-width: 100%\">\n    <n-heatmap\n      :data=\"data\"\n      :active-colors=\"customActiveColors\"\n      :minimum-color=\"minimumColor\"\n    />\n  </n-scrollbar>\n</template>\n"
  },
  {
    "path": "src/heatmap/demos/zhCN/index.demo-entry.md",
    "content": "<!--single-column-->\n\n# 热力图 Heatmap\n\n数字民工有属于自己的墙要刷。\n\n自 `2.43.0` 开始提供。\n\n<n-alert type=\"info\" title=\"使用前提\" :bordered=\"false\">\n  <n-text>\n    颜色相关的属性 <n-text code>active-colors</n-text> 和 <n-text code>minimum-color</n-text> 的优先级高于 <n-text code>color-theme</n-text>，如果同时设置了这三个属性，则使用 <n-text code>active-colors</n-text> 和 <n-text code>minimum-color</n-text>建议不要同时设置。\n  </n-text>\n  <br />\n  <n-text>\n    都不设置时，使用 Naive 内置的默认值 类 GitHub 的一套主题。\n  </n-text>\n</n-alert>\n\n## 演示\n\n```demo\nbasic.vue\nthemes.vue\ncolors.vue\nslots.vue\n```\n\n## API\n\n### Heatmap Props\n\n类型 `HeatmapProps`\n\n| 名称 | 类型 | 相关类型 | 默认值 | 说明 | 版本 |\n| --- | --- | --- | --- | --- | --- |\n| active-colors | `string[]` | - | `undefined` | 颜色数组，按从浅到深的顺序排列，优先级高于 `color-theme` | 2.43.0 |\n| color-theme | `'green' \\| 'blue' \\| 'orange' \\| 'purple' \\| 'red'` | `HeatmapColorTheme` | `undefined` | 内置颜色主题 | 2.43.0 |\n| data | `Array<{ timestamp: number, value?: number \\| null }>` | `HeatmapData`, `HeatmapDataItem` | `[]` | 热力图数据，包含日期和数值 | 2.43.0 |\n| first-day-of-week | `0 \\| 1 \\| 2 \\| 3 \\| 4 \\| 5 \\| 6` | `HeatmapFirstDayOfWeek` | `0` | 一周的开始日，`0` 表示周一，6 表示周日 | 2.43.0 |\n| fill-calendar-leading | `boolean` | - | `false` | 是否填满日历网格的头部，适用于 GitHub 风格的最近一年视图 | 2.43.0 |\n| loading | `boolean` | - | `false` | 是否显示加载状态 | 2.43.0 |\n| loading-data | `Array<{ timestamp: number, value?: number \\| null }>` | `HeatmapData`, `HeatmapDataItem` | `undefined` | 加载状态下展示的数据，如果单元格的 `value` 为 `null` 不展示 cell，但占位，如果单元格的 `value` 设为任意非 `null` 值，则展示加载状态 | 2.43.0 |\n| minimum-color | `string` | - | `undefined` | 热力图最小颜色，默认为 `active-colors` 中的第一个颜色 | 2.43.0 |\n| show-color-indicator | `boolean` | - | `true` | 是否显示底部的颜色层级指示器 | 2.43.0 |\n| show-month-labels | `boolean` | - | `true` | 是否显示月份标签 | 2.43.0 |\n| show-week-labels | `boolean` | - | `true` | 是否显示周标签 | 2.43.0 |\n| size | `'small' \\| 'medium' \\| 'large'` | - | `'medium'` | 热力图尺寸 | 2.43.0 |\n| tooltip | `boolean \\| TooltipProps` | - | `false` | tooltip 配置，`false` 为禁用，对象为 `TooltipProps` | 2.43.0 |\n| x-gap | `number \\| string` | - | `undefined` | 水平方向间距 | 2.43.0 |\n| y-gap | `number \\| string` | - | `undefined` | 垂直方向间距 | 2.43.0 |\n\n### Heatmap Slots\n\n类型 `HeatmapSlots`\n\n| 名称 | 参数 | 相关类型 | 说明 | 版本 |\n| --- | --- | --- | --- | --- |\n| footer | `()` | - | 底部左侧信息插槽，与 heatmap table 左边对齐 | 2.43.0 |\n| indicator | `()` | - | 底部右侧指示器插槽，与 heatmap table 右边对齐 | 2.43.0 |\n| indicator-leading-text | `()` | - | 颜色层级指示器的前置文字 | 2.43.0 |\n| indicator-trailing-text | `()` | - | 颜色层级指示器的后置文字 | 2.43.0 |\n| tooltip | `(props: { timestamp: number, value?: number \\| null })` | `HeatmapTooltipSlotProps` | 自定义 tooltip 内容 | 2.43.0 |\n\n### Others\n\n1. `import { heatmapMockData } from 'naive-ui'`，`function heatmapMockData(year?: 'recent' | number): HeatmapData`\n"
  },
  {
    "path": "src/heatmap/demos/zhCN/slots.demo.vue",
    "content": "<markdown>\n# 插槽用法\n\n自定义 footer 区域，支持 `footer` 插槽和 `indicator` 插槽。同时支持自定义 `tooltip` 内容，以及指示器文本插槽。\n</markdown>\n\n<script setup lang=\"ts\">\nimport { heatmapMockData } from 'naive-ui'\n\nconst yearData = heatmapMockData()\n</script>\n\n<template>\n  <n-flex vertical>\n    <n-scrollbar x-scrollable style=\"max-width: 100%\">\n      <n-heatmap :data=\"yearData\" :show-color-indicator=\"false\">\n        <template #footer>\n          <n-text depth=\"3\">\n            左侧信息插槽\n          </n-text>\n        </template>\n        <template #indicator>\n          <n-text depth=\"3\">\n            右侧指示器插槽\n          </n-text>\n        </template>\n        <template #tooltip=\"{ timestamp: date, value: tooltipValue }\">\n          <div>\n            <div>\n              <strong>日期:</strong> {{ new Date(date).toLocaleDateString() }}\n            </div>\n            <div><strong>数值:</strong> {{ tooltipValue ?? 0 }}</div>\n            <div v-if=\"tooltipValue != null && tooltipValue > 5\">\n              <n-tag type=\"success\" size=\"small\">\n                高活跃度\n              </n-tag>\n            </div>\n          </div>\n        </template>\n      </n-heatmap>\n    </n-scrollbar>\n    <n-divider />\n    <h4>自定义指示器文本</h4>\n    <n-scrollbar x-scrollable style=\"max-width: 100%\">\n      <n-heatmap :data=\"yearData\">\n        <template #indicator-leading-text>\n          <n-text depth=\"3\" style=\"font-style: italic\">\n            较少\n          </n-text>\n        </template>\n        <template #indicator-trailing-text>\n          <n-text depth=\"3\" style=\"font-style: italic\">\n            较多\n          </n-text>\n        </template>\n      </n-heatmap>\n    </n-scrollbar>\n    <n-divider />\n    <h4>自定义 Tooltip 配置</h4>\n    <n-scrollbar x-scrollable style=\"max-width: 100%\">\n      <n-heatmap\n        :data=\"yearData\"\n        unit=\"activities\"\n        :tooltip=\"{ placement: 'bottom', delay: 500 }\"\n      >\n        <template #footer>\n          <n-text depth=\"3\">\n            底部显示 tooltip，延迟 500ms\n          </n-text>\n        </template>\n        <template #tooltip=\"{ timestamp: date, value: tooltipValue }\">\n          活动详情<br>\n          <div>{{ new Date(date).toLocaleDateString() }}</div>\n          <div>{{ tooltipValue ?? 0 }}</div>\n        </template>\n      </n-heatmap>\n    </n-scrollbar>\n  </n-flex>\n</template>\n"
  },
  {
    "path": "src/heatmap/demos/zhCN/themes.demo.vue",
    "content": "<markdown>\n# 内置主题\n\n使用 `color-theme` 属性应用内置的颜色主题。可用主题：`green`、`blue`、`orange`、`purple`、`red`。\n</markdown>\n\n<script setup lang=\"ts\">\nimport { heatmapMockData } from 'naive-ui'\n\nconst data = heatmapMockData()\n\nconst themes = [\n  { name: '绿色', value: 'green' },\n  { name: '蓝色', value: 'blue' },\n  { name: '橙色', value: 'orange' },\n  { name: '紫色', value: 'purple' },\n  { name: '红色', value: 'red' }\n] as const\n</script>\n\n<template>\n  <n-flex vertical size=\"large\">\n    <div v-for=\"theme in themes\" :key=\"theme.value\">\n      <n-divider title-placement=\"left\">\n        {{ theme.name }}\n      </n-divider>\n      <n-heatmap :data=\"data\" :color-theme=\"theme.value\" />\n    </div>\n  </n-flex>\n</template>\n"
  },
  {
    "path": "src/heatmap/index.ts",
    "content": "export { default as NHeatmap } from './src/Heatmap'\nexport { heatmapProps } from './src/Heatmap'\nexport type { HeatmapProps } from './src/Heatmap'\nexport type * from './src/public-types'\nexport { heatmapMockData } from './src/utils'\nexport * from './styles'\n"
  },
  {
    "path": "src/heatmap/src/ColorIndicator.tsx",
    "content": "import type { PropType, SlotsType, VNode } from 'vue'\nimport { defineComponent, h } from 'vue'\n\ninterface HeatmapColorIndicatorSlots {\n  'leading-text'?: () => VNode[]\n  'trailing-text'?: () => VNode[]\n}\n\nexport default defineComponent({\n  name: 'HeatmapColorIndicator',\n  slots: Object as SlotsType<HeatmapColorIndicatorSlots>,\n  props: {\n    colors: {\n      type: Array as PropType<string[]>,\n      required: true\n    },\n    clsPrefix: {\n      type: String,\n      required: true\n    }\n  },\n  setup(props, { slots }) {\n    return () => {\n      const { colors, clsPrefix } = props\n      return (\n        <div class={`${clsPrefix}-heatmap-color-indicator`}>\n          <span class={`${clsPrefix}-heatmap-color-indicator__label`}>\n            {slots['leading-text']?.()}\n          </span>\n          <div class={`${clsPrefix}-heatmap-color-indicator__cells`}>\n            {colors.map((color: string, index: number) => (\n              <div\n                key={index}\n                class={`${clsPrefix}-heatmap-color-indicator__cell`}\n                style={{ backgroundColor: color }}\n              />\n            ))}\n          </div>\n          <span class={`${clsPrefix}-heatmap-color-indicator__label`}>\n            {slots['trailing-text']?.()}\n          </span>\n        </div>\n      )\n    }\n  }\n})\n"
  },
  {
    "path": "src/heatmap/src/Heatmap.tsx",
    "content": "import type { PropType, SlotsType } from 'vue'\nimport type { ThemeProps } from '../../_mixins'\nimport type { ExtractPublicPropTypes } from '../../_utils'\nimport type { TooltipProps } from '../../tooltip'\nimport type { HeatmapTheme } from '../styles/light'\nimport type { DayRect } from './interface'\nimport type {\n  HeatmapData,\n  HeatmapFirstDayOfWeek,\n  HeatmapSlots\n} from './public-types'\nimport type { HeatmapColorTheme } from './theme'\nimport { addDays, format, parseISO, startOfWeek } from 'date-fns'\nimport { groupBy, mapValues, maxBy } from 'lodash-es'\nimport { pxfy } from 'seemly'\nimport { computed, defineComponent, h } from 'vue'\nimport {\n  useConfig,\n  useLocale,\n  useRtl,\n  useTheme,\n  useThemeClass\n} from '../../_mixins'\nimport { createKey, resolveSlot, resolveWrappedSlot } from '../../_utils'\nimport { transformNaiveFirstDayOfWeekToDateFns } from '../../date-picker/src/utils'\nimport heatmapLight from '../styles/light'\nimport { useLoadingStyleClass } from './animationStyle'\nimport HeatmapColorIndicator from './ColorIndicator'\nimport Rect from './Rect'\nimport style from './styles/index.cssr'\nimport { heatmapColorThemes } from './theme'\nimport {\n  completeDataGaps,\n  createDayRect,\n  createLoadingMatrix,\n  createSparseMatrix\n} from './utils'\n\ninterface Col {\n  week: number\n  month: string\n}\n\nexport const heatmapProps = {\n  ...(useTheme.props as ThemeProps<HeatmapTheme>),\n  activeColors: Array as PropType<string[]>,\n  colorTheme: String as PropType<HeatmapColorTheme>,\n  data: Array as PropType<HeatmapData>,\n  loadingData: Object as PropType<HeatmapData>,\n  fillCalendarLeading: Boolean,\n  firstDayOfWeek: {\n    type: Number as PropType<HeatmapFirstDayOfWeek>,\n    default: 0\n  },\n  loading: Boolean,\n  minimumColor: String,\n  showColorIndicator: {\n    type: Boolean,\n    default: true\n  },\n  showWeekLabels: {\n    type: Boolean,\n    default: true\n  },\n  showMonthLabels: {\n    type: Boolean,\n    default: true\n  },\n  size: {\n    type: String as PropType<'small' | 'medium' | 'large'>,\n    default: 'medium'\n  },\n  tooltip: {\n    type: [Boolean, Object] as PropType<TooltipProps | boolean>,\n    default: false\n  },\n  xGap: [Number, String] as PropType<number | string>,\n  yGap: [Number, String] as PropType<number | string>\n} as const\n\nexport type HeatmapProps = ExtractPublicPropTypes<typeof heatmapProps>\n\nexport default defineComponent({\n  name: 'Heatmap',\n  slots: Object as SlotsType<HeatmapSlots>,\n  props: heatmapProps,\n  setup(props) {\n    const { mergedClsPrefixRef, mergedRtlRef, inlineThemeDisabled }\n      = useConfig(props)\n    const { localeRef, dateLocaleRef } = useLocale('Heatmap')\n    const themeRef = useTheme(\n      'Heatmap',\n      '-heatmap',\n      style,\n      heatmapLight,\n      props,\n      mergedClsPrefixRef\n    )\n    const rtlEnabledRef = useRtl('Heatmap', mergedRtlRef, mergedClsPrefixRef)\n    const cssVarsRef = computed(() => {\n      const { xGap, yGap, size } = props\n      const {\n        common: { cubicBezierEaseInOut },\n        self: {\n          fontWeight,\n          textColor,\n          borderColor,\n          loadingColorStart,\n          [createKey('rectSize', size)]: rectSize,\n          [createKey('borderRadius', size)]: sizeBorderRadius,\n          [createKey('xGap', size)]: defaultXGap,\n          [createKey('yGap', size)]: defaultYGap,\n          [createKey('fontSize', size)]: fontSize\n        }\n      } = themeRef.value\n      const cssVars = {\n        '--n-bezier': cubicBezierEaseInOut,\n        '--n-font-size': fontSize,\n        '--n-font-weight': fontWeight,\n        '--n-text-color': textColor,\n        '--n-border-radius': sizeBorderRadius,\n        '--n-border-color': borderColor,\n        '--n-loading-color-start': loadingColorStart,\n        '--n-rect-size': rectSize,\n        '--n-x-gap':\n          xGap !== undefined\n            ? typeof xGap === 'number'\n              ? pxfy(xGap)\n              : xGap\n            : defaultXGap,\n        '--n-y-gap':\n          yGap !== undefined\n            ? typeof yGap === 'number'\n              ? pxfy(yGap)\n              : yGap\n            : defaultYGap\n      }\n\n      return cssVars\n    })\n    const themeClassHandle = inlineThemeDisabled\n      ? useThemeClass(\n          'heatmap',\n          computed(() => {\n            const { size } = props\n            return size[0]\n          }),\n          cssVarsRef,\n          props\n        )\n      : undefined\n    const mergedColorsRef = computed(() => {\n      const {\n        mininumColor: builtInMinimumColor,\n        activeColors: builtInActiveColors\n      } = themeRef.value.self\n      const mergedMininumColor = props.minimumColor || builtInMinimumColor\n      const theme = props.colorTheme && heatmapColorThemes[props.colorTheme]\n      const mergedActiveColors\n        = props.activeColors || theme || builtInActiveColors\n\n      return [mergedMininumColor, ...mergedActiveColors]\n    })\n\n    const normalizedDataRef = computed(() => {\n      if (!props.data || props.data.length === 0) {\n        return []\n      }\n      return completeDataGaps(\n        props.data,\n        transformNaiveFirstDayOfWeekToDateFns(props.firstDayOfWeek),\n        props.fillCalendarLeading\n      )\n    })\n\n    const normalizedLoadingDataRef = computed(() => {\n      if (!props.loadingData || props.loadingData.length === 0) {\n        return []\n      }\n      return completeDataGaps(\n        props.loadingData,\n        transformNaiveFirstDayOfWeekToDateFns(props.firstDayOfWeek),\n        props.fillCalendarLeading\n      )\n    })\n\n    const maxValueRef = computed(() => {\n      const validData = normalizedDataRef.value.filter(d => d.value !== null)\n      return maxBy(validData, d => d.value!)?.value ?? 0\n    })\n\n    const heatmapMatrixRef = computed(() => {\n      const data = normalizedDataRef.value\n      const loadingData = normalizedLoadingDataRef.value\n      if (props.loading && !loadingData.length) {\n        return createLoadingMatrix(\n          transformNaiveFirstDayOfWeekToDateFns(props.firstDayOfWeek)\n        )\n      }\n\n      const finalData = props.loading ? loadingData : data\n      if (!finalData.length)\n        return []\n\n      const maxValue = maxValueRef.value\n      const colors = mergedColorsRef.value\n      const calendarStartDate = finalData[0].timestamp\n\n      const dayRects = finalData.map(item =>\n        createDayRect(\n          item,\n          calendarStartDate,\n          transformNaiveFirstDayOfWeekToDateFns(props.firstDayOfWeek),\n          colors,\n          maxValue\n        )\n      )\n\n      return createSparseMatrix(\n        7,\n        dayRects,\n        dayRect => dayRect.rowIndex,\n        dayRect => dayRect.colIndex\n      )\n    })\n\n    const weekLabelsRef = computed(() => {\n      const { weekdayFormat } = localeRef.value\n      const { locale } = dateLocaleRef.value\n\n      const baseDate = startOfWeek(new Date(), {\n        weekStartsOn: transformNaiveFirstDayOfWeekToDateFns(\n          props.firstDayOfWeek\n        )\n      })\n\n      return Array.from({ length: 7 }, (_, i) => {\n        return {\n          label: format(addDays(baseDate, i), weekdayFormat, { locale }),\n          visible: i % 2 !== 0\n        }\n      })\n    })\n\n    const loadingMonthLabelsRef = computed(() => {\n      const { monthFormat } = localeRef.value\n      const { locale } = dateLocaleRef.value\n      const currentYear = new Date().getFullYear()\n      // for more consistent month label widths\n      const colSpans = [5, 4, 5, 4, 5, 4, 5, 4, 4, 5, 4, 4]\n      return Array.from({ length: 12 }, (_, i) => {\n        const monthDate = new Date(currentYear, i, 1)\n        return {\n          name: format(monthDate, monthFormat, { locale }),\n          colSpan: colSpans[i]\n        }\n      })\n    })\n\n    function getColsMonth(matrix: DayRect[][]): Col[] {\n      const cols = matrix[0].length\n      const res: Col[] = []\n      for (let col = 0; col < cols; col++) {\n        for (let row = 0; row < matrix.length; row++) {\n          const cell = matrix[row][col]\n          if (cell?.value !== null) {\n            res.push({\n              week: col,\n              month: format(cell.timestamp, 'yyyy-MM')\n            })\n            break\n          }\n        }\n      }\n      return res\n    }\n\n    const dataMonthLabelsRef = computed(() => {\n      const { monthFormat } = localeRef.value\n      const { locale } = dateLocaleRef.value\n      const matrix = heatmapMatrixRef.value\n      if (!matrix || matrix.length === 0 || !matrix[0]) {\n        return []\n      }\n      const colsWithMonth = getColsMonth(matrix)\n      const monthStats = mapValues(\n        groupBy(colsWithMonth, 'month'),\n        (entries) => {\n          const weekNumbers = entries.map(e => e.week)\n          return {\n            weekCount: entries.length,\n            start: Math.min(...weekNumbers),\n            end: Math.max(...weekNumbers)\n          }\n        }\n      )\n\n      return Object.entries(monthStats)\n        .filter(([, stats]) => stats.weekCount >= 3) // ensure have enough space\n        .sort(([a], [b]) => a.localeCompare(b))\n        .map(([month, stats]) => {\n          const monthDate = new Date(parseISO(`${month}-01`))\n          return {\n            name: format(monthDate, monthFormat, { locale }),\n            colSpan: stats.end - stats.start + 1\n          }\n        })\n    })\n\n    const monthLabelsRef = computed(() => {\n      return props.loading && !props.loadingData\n        ? loadingMonthLabelsRef.value\n        : dataMonthLabelsRef.value\n    })\n\n    const loadingClassRef = useLoadingStyleClass(props, themeRef)\n\n    return {\n      weekLabels: weekLabelsRef,\n      monthLabels: monthLabelsRef,\n      mergedColors: mergedColorsRef,\n      mergedClsPrefix: mergedClsPrefixRef,\n      rtlEnabled: rtlEnabledRef,\n      locale: localeRef,\n      cssVars: inlineThemeDisabled ? undefined : cssVarsRef,\n      themeClass: themeClassHandle?.themeClass,\n      onRender: themeClassHandle?.onRender,\n      heatmapMatrix: heatmapMatrixRef,\n      loadingClass: loadingClassRef\n    }\n  },\n  render() {\n    const {\n      loading,\n      showWeekLabels,\n      showMonthLabels,\n      showColorIndicator,\n      mergedClsPrefix,\n      themeClass,\n      cssVars,\n      rtlEnabled,\n      locale,\n      weekLabels,\n      monthLabels,\n      mergedColors,\n      $slots,\n      heatmapMatrix,\n      loadingClass,\n      onRender\n    } = this\n    onRender?.()\n    return (\n      <div\n        class={[\n          themeClass,\n          `${mergedClsPrefix}-heatmap`,\n          rtlEnabled && `${mergedClsPrefix}-heatmap--rtl`\n        ]}\n        style={cssVars}\n      >\n        <div class={`${mergedClsPrefix}-heatmap__content`}>\n          <table class={`${mergedClsPrefix}-heatmap__calendar-table`}>\n            {showMonthLabels && (\n              <thead>\n                <tr>\n                  {showWeekLabels && (\n                    <th\n                      class={`${mergedClsPrefix}-heatmap__week-header-cell`}\n                    />\n                  )}\n                  {monthLabels.map((monthLabel, index) => (\n                    <th\n                      key={`month-${index}`}\n                      colspan={monthLabel.colSpan}\n                      class={`${mergedClsPrefix}-heatmap__month-label-cell`}\n                    >\n                      {monthLabel.name}\n                    </th>\n                  ))}\n                </tr>\n              </thead>\n            )}\n            <tbody>\n              {weekLabels.map((weekLabel, rowIdx) => {\n                return (\n                  <tr key={`row-${rowIdx}`}>\n                    {showWeekLabels && (\n                      <td class={`${mergedClsPrefix}-heatmap__week-label-cell`}>\n                        {weekLabel.visible ? weekLabel.label : null}\n                      </td>\n                    )}\n                    {(heatmapMatrix[rowIdx] || []).map(\n                      (day: DayRect, weekIdx: number) => {\n                        return day.value !== null ? (\n                          <td\n                            key={`day-${rowIdx}-${weekIdx}`}\n                            class={`${mergedClsPrefix}-heatmap__day-cell`}\n                          >\n                            <Rect\n                              mergedClsPrefix={mergedClsPrefix}\n                              data={day}\n                              color={day.color}\n                              tooltip={this.tooltip}\n                              loading={loading}\n                              loadingClass={loadingClass}\n                            >\n                              {{\n                                tooltip: () => $slots.tooltip?.(day)\n                              }}\n                            </Rect>\n                          </td>\n                        ) : (\n                          <td\n                            key={`empty-${rowIdx}-${weekIdx}`}\n                            class={`${mergedClsPrefix}-heatmap__day-cell`}\n                          >\n                            <div\n                              class={`${mergedClsPrefix}-heatmap__empty-cell`}\n                            />\n                          </td>\n                        )\n                      }\n                    )}\n                  </tr>\n                )\n              })}\n            </tbody>\n          </table>\n        </div>\n        <div class={`${mergedClsPrefix}-heatmap__footer`}>\n          {resolveWrappedSlot(\n            $slots.footer,\n            children =>\n              children && (\n                <div class={`${mergedClsPrefix}-heatmap__footer`}>\n                  {children}\n                </div>\n              )\n          )}\n          <div class={`${mergedClsPrefix}-heatmap__indicator`}>\n            {resolveSlot($slots.indicator, () => [\n              showColorIndicator && (\n                <HeatmapColorIndicator\n                  colors={mergedColors}\n                  clsPrefix={mergedClsPrefix}\n                >\n                  {{\n                    'leading-text': () =>\n                      resolveSlot($slots['indicator-leading-text'], () => [\n                        locale.less\n                      ]),\n                    'trailing-text': () =>\n                      resolveSlot($slots['indicator-trailing-text'], () => [\n                        locale.more\n                      ])\n                  }}\n                </HeatmapColorIndicator>\n              )\n            ])}\n          </div>\n        </div>\n      </div>\n    )\n  }\n})\n"
  },
  {
    "path": "src/heatmap/src/Rect.tsx",
    "content": "import type { PropType, SlotsType, VNode } from 'vue'\nimport type { PopoverProps } from '../../popover/src/Popover'\nimport type { HeatmapDataItem } from './public-types'\nimport { computed, defineComponent, h } from 'vue'\nimport { resolveSlotWithTypedProps } from '../../_utils'\nimport Tooltip from '../../tooltip/src/Tooltip'\n\nexport interface RectSlots {\n  tooltip?: (props: HeatmapDataItem) => VNode[]\n}\n\nexport default defineComponent({\n  name: 'HeatmapRect',\n  slots: Object as SlotsType<RectSlots>,\n  props: {\n    mergedClsPrefix: {\n      type: String,\n      required: true\n    },\n    data: {\n      type: Object as PropType<HeatmapDataItem>,\n      required: true\n    },\n    color: {\n      type: String,\n      required: true\n    },\n    style: Object,\n    loading: Boolean,\n    loadingClass: String,\n    tooltip: {\n      type: [Boolean, Object] as PropType<PopoverProps | boolean>,\n      default: true\n    }\n  },\n  setup(props) {\n    const cssVarsRef = computed(() => ({\n      '--n-rect-color': props.color\n    }))\n\n    const tooltipPropsRef = computed(() => {\n      return typeof props.tooltip === 'object' ? props.tooltip : {}\n    })\n\n    const defaultTooltipContentRef = computed(() => {\n      const date = new Date(props.data.timestamp).toLocaleDateString()\n      return props.data.value !== null ? `${date} ${props.data.value}` : date\n    })\n\n    return {\n      cssVars: cssVarsRef,\n      tooltipProps: tooltipPropsRef,\n      defaultTooltipContent: defaultTooltipContentRef\n    }\n  },\n  render() {\n    const {\n      mergedClsPrefix,\n      style,\n      cssVars,\n      tooltip,\n      tooltipProps,\n      defaultTooltipContent,\n      loading,\n      data\n    } = this\n    const triggerNode = (\n      <div\n        class={[\n          `${mergedClsPrefix}-heatmap-rect`,\n          loading && `${mergedClsPrefix}-heatmap-rect--loading`,\n          loading && this.loadingClass\n        ]}\n        style={[cssVars, style]}\n      />\n    )\n\n    return tooltip === false || loading ? (\n      triggerNode\n    ) : (\n      <Tooltip trigger=\"hover\" {...tooltipProps}>\n        {{\n          default: () =>\n            resolveSlotWithTypedProps(this.$slots.tooltip, data, () => [\n              <div>{defaultTooltipContent}</div>\n            ]),\n          trigger: () => triggerNode\n        }}\n      </Tooltip>\n    )\n  }\n})\n"
  },
  {
    "path": "src/heatmap/src/animationStyle.ts",
    "content": "import type { ComputedRef, Ref } from 'vue'\nimport type { MergedTheme, Theme } from '../../_mixins'\nimport type { HeatmapThemeVars } from '../styles'\nimport { useSsrAdapter } from '@css-render/vue3-ssr'\nimport { hash } from 'css-render'\nimport { inject, onMounted, ref, watchEffect } from 'vue'\nimport { c } from '../../_utils/cssr'\nimport { configProviderInjectionKey } from '../../config-provider/src/context'\n\nexport function useLoadingStyleClass(\n  props: { loading?: boolean },\n  themeRef: ComputedRef<MergedTheme<Theme<'Heatmap', HeatmapThemeVars, any>>>\n): Ref<string> {\n  const loadingClassRef = ref('')\n  const adapter = useSsrAdapter()\n  const NConfigProvider = inject(configProviderInjectionKey, null)\n  const styleMountTarget = NConfigProvider?.styleMountTarget\n  onMounted(() => {\n    watchEffect(() => {\n      if (!props.loading) {\n        return\n      }\n      const {\n        self: { loadingColorStart, loadingColorEnd }\n      } = themeRef.value\n      const loadingColorHash = hash(loadingColorStart) + hash(loadingColorEnd)\n      const className = `heatmap-loading-${loadingColorHash}`\n      const animationName = `heatmap-loading-animation-${loadingColorHash}`\n      loadingClassRef.value = className\n      const cnode = c([\n        c(\n          `.${className}`,\n          `\n          animation: 2s ${animationName} infinite cubic-bezier(0.36, 0, 0.64, 1);\n        `\n        ),\n        c(\n          `@keyframes ${animationName}`,\n          `\n          0% {\n            background: ${loadingColorStart};\n          }\n          40% {\n            background: ${loadingColorEnd};\n          }\n          80% {\n            background: ${loadingColorStart};\n          }\n          100% {\n            background: ${loadingColorStart};\n          }\n        `\n        )\n      ])\n      // We don't unmount it since we didn't know its mount count\n      cnode.mount({\n        id: loadingColorHash,\n        ssr: adapter,\n        parent: styleMountTarget\n      })\n    })\n  })\n  return loadingClassRef\n}\n"
  },
  {
    "path": "src/heatmap/src/interface.ts",
    "content": "import type { HeatmapDataItem } from './public-types'\n\nexport interface DayRect extends HeatmapDataItem {\n  color: string\n  dayOfWeek: number // 0 = Sunday\n  rowIndex: number // 0 = first row, relative to weekStartOn\n  colIndex: number // column index in the matrix\n}\n"
  },
  {
    "path": "src/heatmap/src/public-types.ts",
    "content": "import type { VNode } from 'vue'\n\nexport type HeatmapData = HeatmapDataItem[]\nexport interface HeatmapDataItem {\n  timestamp: number\n  value?: number | null\n}\n\nexport type HeatmapTooltipSlotProps = HeatmapDataItem\n\nexport interface HeatmapSlots {\n  footer?: () => VNode[]\n  indicator?: () => VNode[]\n  'indicator-leading-text'?: () => VNode[]\n  'indicator-trailing-text'?: () => VNode[]\n  tooltip?: (props: HeatmapTooltipSlotProps) => VNode[]\n}\n\nexport type HeatmapFirstDayOfWeek = 0 | 1 | 2 | 3 | 4 | 5 | 6\n\nexport type { HeatmapColorTheme } from './theme'\n"
  },
  {
    "path": "src/heatmap/src/styles/index.cssr.ts",
    "content": "import { c, cB, cE, cM } from '../../../_utils/cssr'\n\n// vars:\n// --n-font-size\n// --n-font-weight\n// --n-text-color\n// --n-border-radius\n// --n-x-gap\n// --n-y-gap\n// --n-rect-size\n// --n-rect-color (for individual rect background color)\n// --n-bezier\n\nexport default c([\n  cB('heatmap', `\n    display: flex;\n    flex-direction: column;\n    max-width: fit-content;\n    font-size: var(--n-font-size);\n  `, [\n    cE('content', `\n      display: block;\n    `),\n    cE('calendar-table', `\n      border-collapse: separate;\n      border-spacing: var(--n-y-gap) var(--n-x-gap);\n      font-size: var(--n-font-size);\n    `),\n    cE('week-header-cell', `\n      width: 27px;\n      padding: 0;\n      border: none;\n      font-size: var(--n-font-size);\n    `),\n    cE('month-label-cell', `\n      font-size: var(--n-font-size);\n      color: var(--n-text-color);\n      text-align: left;\n      height: 15px;\n      line-height: 15px;\n      font-weight: var(--n-font-weight);\n      padding: 0 2px 8px;\n      vertical-align: bottom;\n      transition: color .3s var(--n-bezier);\n    `),\n    cE('week-label-cell', `\n      font-size: var(--n-font-size);\n      color: var(--n-text-color);\n      text-align: right;\n      width: 27px;\n      height: 11px;\n      line-height: 11px;\n      padding: 0 4px 0 0;\n      border: none;\n      vertical-align: middle;\n      white-space: nowrap;\n      font-weight: var(--n-font-weight);\n      transition: color .3s var(--n-bezier);\n    `),\n    cE('day-cell', `\n      width: var(--n-rect-size);\n      height: var(--n-rect-size);\n      padding: 0;\n      border: none;\n      vertical-align: middle;\n      transition: color .3s var(--n-bezier);\n    `),\n    cE('empty-cell', `\n      width: var(--n-rect-size);\n      height: var(--n-rect-size);\n      border-radius: var(--n-border-radius);\n    `),\n    cE('footer', `\n      display: flex;\n      justify-content: space-between;\n      margin-left: 17px;\n      align-items: center;\n      margin-top: 8px;\n      &:has(> :only-child) {\n        justify-content: flex-end;\n      }\n    `),\n    cE('indicator', `\n      display: flex;\n      align-items: center;\n      justify-content: flex-end;\n    `)\n  ]),\n  cB('heatmap-rect', `\n    width: var(--n-rect-size);\n    height: var(--n-rect-size);\n    border-radius: var(--n-border-radius);\n    background-color: var(--n-rect-color);\n    transition: background-color .3s var(--n-bezier);\n  `, [\n    cM('loading', `\n      cursor: default;\n      background: var(--n-loading-color-start);\n    `)\n  ]),\n  cB('heatmap-color-indicator', `\n    display: flex;\n    align-items: center;\n    justify-content: flex-end;\n    gap: 4px;\n    font-size: var(--n-font-size);\n  `, [\n    cE('cells', `\n      display: flex;\n      gap: var(--n-x-gap);\n    `),\n    cE('cell', `\n      width: var(--n-rect-size);\n      height: var(--n-rect-size);\n      border-radius: var(--n-border-radius);\n      transition: background-color .3s var(--n-bezier);\n    `),\n    cE('label', `\n      font-size: var(--n-font-size);\n      color: var(--n-text-color);\n      transition: color .3s var(--n-bezier);\n    `)\n  ])\n])\n"
  },
  {
    "path": "src/heatmap/src/styles/rtl.cssr.ts",
    "content": "import { cB, cM } from '../../../_utils/cssr'\n\nexport default cB('heatmap', [\n  cM('rtl', `\n    direction: rtl;\n  `)\n])\n"
  },
  {
    "path": "src/heatmap/src/theme.ts",
    "content": "export const heatmapColorThemes = {\n  green: ['#c6e48b', '#7bc96f', '#239a3b', '#196127'],\n  blue: ['#c0e7ff', '#73b3ff', '#0969da', '#0550ae'],\n  orange: ['#fed7aa', '#fb923c', '#ea580c', '#c2410c'],\n  purple: ['#e9d5ff', '#c084fc', '#9333ea', '#7c3aed'],\n  red: ['#fecaca', '#f87171', '#dc2626', '#b91c1c']\n}\n\nexport type HeatmapColorTheme = keyof typeof heatmapColorThemes\n"
  },
  {
    "path": "src/heatmap/src/utils/index.ts",
    "content": "import type { DayRect } from '../interface'\nimport type {\n  HeatmapData,\n  HeatmapDataItem,\n  HeatmapFirstDayOfWeek\n} from '../public-types'\nimport {\n  differenceInCalendarDays,\n  eachDayOfInterval,\n  endOfWeek,\n  endOfYear,\n  getDay,\n  isWithinInterval,\n  startOfDay,\n  startOfWeek,\n  startOfYear,\n  subYears\n} from 'date-fns'\nimport { groupBy } from 'lodash-es'\n\n/** get color by value/maxValue */\nexport function calcColorByValue(\n  colors: string[],\n  value: number | null | undefined,\n  maxValue: number\n): string {\n  if (maxValue === 0 || value === null || value === undefined || value <= 0) {\n    return colors[0]\n  }\n\n  const ratio = Math.min(value / maxValue, 1)\n  const maxLevel = colors.length - 1\n  const level = Math.min(Math.ceil(ratio * maxLevel), maxLevel)\n\n  return colors[level]\n}\n\n/**\n * fill gaps for the given data\n *\n * fill gaps `[firstDate,lastDate]` with value `0`\n *\n * fill `[firstCalendarDate,firstDate]` and `[lastDate,lastCalendarDate]` with value `null` by default\n *\n * fill `[firstCalendarDate,firstDate]` with value `0` when `fillCalendarLeading` is `true`\n */\nexport function completeDataGaps(\n  data: HeatmapData,\n  firstDayOfWeek: HeatmapFirstDayOfWeek,\n  fillCalendarLeading: boolean\n): HeatmapData {\n  const sortedData = [...data].sort((a, b) => a.timestamp - b.timestamp)\n  const firstDate = sortedData[0].timestamp\n  const lastDate = sortedData[sortedData.length - 1].timestamp\n\n  const firstCalendarDate = startOfWeek(firstDate, {\n    weekStartsOn: firstDayOfWeek\n  })\n  const lastCalendarEndDate = endOfWeek(lastDate, {\n    weekStartsOn: firstDayOfWeek\n  })\n\n  const dataMap = new Map(\n    sortedData.map(d => [startOfDay(d.timestamp).getTime(), d])\n  )\n\n  const allCalendarDates = eachDayOfInterval({\n    start: firstCalendarDate,\n    end: lastCalendarEndDate\n  })\n\n  const startDate = fillCalendarLeading ? firstCalendarDate : firstDate\n  return allCalendarDates.map((date) => {\n    const key = startOfDay(date).getTime()\n    const dateValue = dataMap.get(key)\n\n    if (dateValue) {\n      return dateValue\n    }\n\n    const value = isWithinInterval(date, { start: startDate, end: lastDate })\n      ? 0\n      : null\n\n    return { timestamp: date.getTime(), value }\n  })\n}\n\n/**\n * Create a DayRect object with position information\n */\nexport function createDayRect(\n  item: HeatmapDataItem,\n  calendarStartDate: number,\n  weekStartOn: number,\n  colors: string[],\n  maxValue: number\n): DayRect {\n  const daysFromGridStart = differenceInCalendarDays(\n    item.timestamp,\n    calendarStartDate\n  )\n\n  const colIndex = Math.floor(daysFromGridStart / 7)\n  const dayOfWeek = getDay(item.timestamp)\n  const rowIndex = (dayOfWeek - weekStartOn + 7) % 7\n\n  return {\n    timestamp: item.timestamp,\n    value: item.value,\n    color: calcColorByValue(colors, item.value, maxValue),\n    dayOfWeek,\n    rowIndex,\n    colIndex\n  }\n}\n\n/**\n * Create a sparse matrix from items with position information\n */\nexport function createSparseMatrix<T>(\n  rows: number,\n  items: T[],\n  getRowIndex: (item: T) => number,\n  getColIndex: (item: T) => number\n): T[][] {\n  const groupedByRow = groupBy(items, getRowIndex)\n\n  return Array.from({ length: rows }, (_, rowIndex) => {\n    const rowData = groupedByRow[rowIndex] || []\n    const row: T[] = []\n    rowData.forEach((item) => {\n      row[getColIndex(item)] = item\n    })\n    return row\n  })\n}\n\n/**\n * This creates a 7x53 matrix (typical year layout) filled with loading cells\n */\nexport function createLoadingMatrix(\n  firstDayOfWeek: HeatmapFirstDayOfWeek\n): DayRect[][] {\n  const rows = 7\n  const cols = 53\n  const currentTimestamp = Date.now()\n\n  return Array.from({ length: rows }, (_, row) =>\n    Array.from({ length: cols }, (_, col) => ({\n      timestamp: currentTimestamp,\n      value: 0,\n      color: '#000000',\n      dayOfWeek: (firstDayOfWeek + row) % 7,\n      rowIndex: row,\n      colIndex: col\n    })))\n}\n\n/**\n * Generate heatmap data for mock purposes.\n * This function generates random data and the result is not stable.\n * @param range - 'recent' for last year, or a specific year number\n */\nexport function heatmapMockData(year?: 'recent' | number): HeatmapData {\n  let start: Date\n  let end: Date\n\n  if (year === undefined || year === 'recent') {\n    end = new Date()\n    start = subYears(end, 1)\n  }\n  else {\n    const _year = Number(year)\n    start = startOfYear(new Date(_year, 0, 1))\n    end = endOfYear(new Date(_year, 11, 31))\n  }\n\n  const allDays = eachDayOfInterval({ start, end })\n\n  return allDays.map((day) => {\n    const dayOfWeek = day.getDay()\n    const isWeekend = dayOfWeek === 0 || dayOfWeek === 6\n\n    if (isWeekend && Math.random() < 0.7) {\n      return { timestamp: day.getTime(), value: 0 }\n    }\n\n    if (!isWeekend && Math.random() < 0.15) {\n      return { timestamp: day.getTime(), value: 0 }\n    }\n\n    const value = Math.floor(Math.random() ** 2 * 40) + 1\n\n    return { timestamp: day.getTime(), value }\n  })\n}\n"
  },
  {
    "path": "src/heatmap/styles/dark.ts",
    "content": "import type { HeatmapTheme } from './light'\nimport { commonDark } from '../../_styles/common'\nimport { self } from './light'\n\nconst HeatmapDark: HeatmapTheme = {\n  name: 'Heatmap',\n  common: commonDark,\n  self(vars) {\n    const lightSelf = self(vars)\n    return {\n      ...lightSelf,\n      activeColors: ['#0d4429', '#006d32', '#26a641', '#39d353'],\n      mininumColor: 'rgba(255, 255, 255, 0.1)',\n      loadingColorStart: 'rgba(255, 255, 255, 0.12)',\n      loadingColorEnd: 'rgba(255, 255, 255, 0.18)'\n    }\n  }\n}\n\nexport default HeatmapDark\n"
  },
  {
    "path": "src/heatmap/styles/index.ts",
    "content": "export { default as heatmapDark } from './dark'\nexport { default as heatmapLight } from './light'\nexport type { HeatmapTheme, HeatmapThemeVars } from './light'\n"
  },
  {
    "path": "src/heatmap/styles/light.ts",
    "content": "import type { Theme } from '../../_mixins'\nimport type { ThemeCommonVars } from '../../_styles/common'\nimport { createTheme } from '../../_mixins'\nimport { commonLight } from '../../_styles/common'\n\nexport function self(vars: ThemeCommonVars) {\n  const {\n    borderRadius,\n    fontSizeMini,\n    fontSizeTiny,\n    fontSizeSmall,\n    fontWeight,\n    textColor2,\n    cardColor,\n    buttonColor2Hover\n  } = vars\n  return {\n    activeColors: ['#9be9a8', '#40c463', '#30a14e', '#216e39'],\n    borderRadius,\n    borderColor: cardColor,\n    textColor: textColor2,\n    mininumColor: buttonColor2Hover,\n    fontWeight,\n    loadingColorStart: 'rgba(0, 0, 0, 0.06)',\n    loadingColorEnd: 'rgba(0, 0, 0, 0.12)',\n    rectSizeSmall: '10px',\n    rectSizeMedium: '11px',\n    rectSizeLarge: '12px',\n    borderRadiusSmall: '2px',\n    borderRadiusMedium: '2px',\n    borderRadiusLarge: '2px',\n    xGapSmall: '2px',\n    xGapMedium: '3px',\n    xGapLarge: '3px',\n    yGapSmall: '2px',\n    yGapMedium: '3px',\n    yGapLarge: '3px',\n    fontSizeSmall: fontSizeTiny,\n    fontSizeMedium: fontSizeMini,\n    fontSizeLarge: fontSizeSmall\n  }\n}\n\nexport type HeatmapThemeVars = ReturnType<typeof self>\n\nconst heatmapLight: Theme<'Heatmap', HeatmapThemeVars> = createTheme({\n  name: 'Heatmap',\n  common: commonLight,\n  self\n})\n\nexport default heatmapLight\nexport type HeatmapTheme = typeof heatmapLight\n"
  },
  {
    "path": "src/heatmap/styles/rtl.ts",
    "content": "import type { RtlItem } from '../../config-provider/src/internal-interface'\nimport rtlStyle from '../src/styles/rtl.cssr'\n\nexport const heatmapRtl: RtlItem = {\n  name: 'Heatmap',\n  style: rtlStyle\n}\n"
  },
  {
    "path": "src/heatmap/tests/Heatmap.spec.tsx",
    "content": "import type { HeatmapData } from '../index'\nimport { mount } from '@vue/test-utils'\nimport { h } from 'vue'\nimport { heatmapMockData, NHeatmap } from '../index'\n\ndescribe('n-heatmap', () => {\n  it('should work with import on demand', () => {\n    mount(NHeatmap)\n  })\n\n  it('should work with `data` prop', () => {\n    const data: HeatmapData = [\n      { timestamp: new Date('2024-01-01').getTime(), value: 5 },\n      { timestamp: new Date('2024-01-02').getTime(), value: 3 }\n    ]\n    const wrapper = mount(NHeatmap, { props: { data } })\n    expect(wrapper.find('.n-heatmap').exists()).toBe(true)\n    expect(wrapper.find('.n-heatmap__calendar-table').exists()).toBe(true)\n    wrapper.unmount()\n  })\n\n  it('should work with `loading` prop', async () => {\n    const wrapper = mount(NHeatmap, { props: { loading: false } })\n\n    await wrapper.setProps({ loading: true })\n    expect(wrapper.find('.n-heatmap').exists()).toBe(true)\n    wrapper.unmount()\n  })\n\n  it('should work with `showWeekLabels` prop', async () => {\n    const data = heatmapMockData()\n    const wrapper = mount(NHeatmap, { props: { data, showWeekLabels: true } })\n    expect(wrapper.find('.n-heatmap__week-label-cell').exists()).toBe(true)\n\n    await wrapper.setProps({ showWeekLabels: false })\n    expect(wrapper.find('.n-heatmap__week-label-cell').exists()).toBe(false)\n    wrapper.unmount()\n  })\n\n  it('should work with `showMonthLabels` prop', async () => {\n    const data = heatmapMockData()\n    const wrapper = mount(NHeatmap, { props: { data, showMonthLabels: true } })\n    expect(wrapper.find('.n-heatmap__month-label-cell').exists()).toBe(true)\n\n    await wrapper.setProps({ showMonthLabels: false })\n    expect(wrapper.find('.n-heatmap__month-label-cell').exists()).toBe(false)\n    wrapper.unmount()\n  })\n\n  it('should work with `showColorIndicator` prop', async () => {\n    const data = heatmapMockData()\n    const wrapper = mount(NHeatmap, {\n      props: { data, showColorIndicator: true }\n    })\n    expect(wrapper.find('.n-heatmap-color-indicator').exists()).toBe(true)\n\n    await wrapper.setProps({ showColorIndicator: false })\n    expect(wrapper.find('.n-heatmap-color-indicator').exists()).toBe(false)\n    wrapper.unmount()\n  })\n\n  it('should work with `colorTheme` prop', () => {\n    ;(['orange', 'blue', 'green'] as const).forEach((theme) => {\n      const data = heatmapMockData()\n      const wrapper = mount(NHeatmap, { props: { data, colorTheme: theme } })\n      expect(wrapper.find('.n-heatmap').exists()).toBe(true)\n      wrapper.unmount()\n    })\n  })\n\n  it('should work with `size` prop', () => {\n    ;(['small', 'medium', 'large'] as const).forEach((size) => {\n      const data = heatmapMockData()\n      const wrapper = mount(NHeatmap, { props: { data, size } })\n      expect(wrapper.find('.n-heatmap').exists()).toBe(true)\n      wrapper.unmount()\n    })\n  })\n\n  it('should work with `weekStartsOn` prop', () => {\n    ;([0, 1, 6] as const).forEach((weekStartsOn) => {\n      const data = heatmapMockData()\n      const wrapper = mount(NHeatmap, { props: { data, weekStartsOn } })\n      expect(wrapper.find('.n-heatmap').exists()).toBe(true)\n      wrapper.unmount()\n    })\n  })\n\n  it('should work with footer slot', () => {\n    const data = heatmapMockData()\n    const wrapper = mount(NHeatmap, {\n      props: { data },\n      slots: {\n        footer: () => h('div', { class: 'custom-footer' }, 'Custom Footer')\n      }\n    })\n    expect(wrapper.find('.custom-footer').exists()).toBe(true)\n    expect(wrapper.find('.custom-footer').text()).toBe('Custom Footer')\n    wrapper.unmount()\n  })\n\n  it('should work with indicator slot', () => {\n    const data = heatmapMockData()\n    const wrapper = mount(NHeatmap, {\n      props: { data, showColorIndicator: false },\n      slots: {\n        indicator: () =>\n          h('div', { class: 'custom-indicator' }, 'Custom Indicator')\n      }\n    })\n    expect(wrapper.find('.custom-indicator').exists()).toBe(true)\n    expect(wrapper.find('.custom-indicator').text()).toBe('Custom Indicator')\n    wrapper.unmount()\n  })\n})\n"
  },
  {
    "path": "src/heatmap/tests/server.spec.tsx",
    "content": "import { setup } from '@css-render/vue3-ssr'\nimport { renderToString } from '@vue/server-renderer'\n/**\n * @vitest-environment node\n */\nimport { createSSRApp, h } from 'vue'\nimport { NHeatmap } from '../..'\n\ndescribe('server side rendering', () => {\n  it('works', async () => {\n    const app = createSSRApp(() => <NHeatmap />)\n    setup(app)\n    try {\n      await renderToString(app)\n    }\n    catch (e) {\n      expect(e).not.toBeTruthy()\n    }\n  })\n})\n"
  },
  {
    "path": "src/highlight/demos/enUS/basic.demo.vue",
    "content": "<markdown>\n# Basic\n</markdown>\n\n<script lang=\"ts\" setup>\nconst text\n  = 'Naive UI is a Vue3 component library, it is relatively complete, tunable themes, written in TypeScript, fast.'\nconst patterns = ['Naive UI', 'Vue3', 'TypeScript', 'fast']\n</script>\n\n<template>\n  <n-highlight :text=\"text\" :patterns=\"patterns\" />\n</template>\n"
  },
  {
    "path": "src/highlight/demos/enUS/case-sensitive.demo.vue",
    "content": "<markdown>\n# Case sensitive\n\nBy default, highlighting is case-sensitive, which you can turn on using the `case-sensitive` property.\n</markdown>\n\n<script lang=\"ts\" setup>\nconst text\n  = 'Naive UI is written in full TypeScript and works seamlessly with your TypeScript projects'\nconst patterns = ['Naive UI', 'typeScript']\n</script>\n\n<template>\n  <n-highlight :text=\"text\" :patterns=\"patterns\" :case-sensitive=\"true\" />\n</template>\n"
  },
  {
    "path": "src/highlight/demos/enUS/component.demo.vue",
    "content": "<markdown>\n# Highlight Tag\n\nThe `highlight-tag` property allows you to specify tag for highlighted text.\n</markdown>\n\n<script lang=\"ts\" setup>\nconst text\n  = 'Naive UI is a Vue3 component library, it is relatively complete, tunable themes, written in TypeScript, fast.'\nconst patterns = ['Naive UI', 'Vue3', 'TypeScript', 'fast']\n</script>\n\n<template>\n  <n-highlight\n    :text=\"text\"\n    highlight-tag=\"span\"\n    :patterns=\"patterns\"\n    highlight-style=\"text-decoration: underline\"\n  />\n</template>\n"
  },
  {
    "path": "src/highlight/demos/enUS/index.demo-entry.md",
    "content": "# Highlight\n\nIf you've used a search engine, you should know what it is.\n\nAvailable since `2.40.0`.\n\n## Demos\n\n```demo\nbasic.vue\nstyle.vue\ncase-sensitive.vue\ncomponent.vue\n```\n\n## API\n\n### Highlight Props\n\n| Name | Type | Default | Description | Version |\n| --- | --- | --- | --- | --- |\n| auto-escape | `boolean` | `true` | Whether to escape `patterns` automatically. By default, elements in `patterns` will be converted into regular expressions for matching, and this process includes automatic escaping, so that the regular expressions will match the literal content of the elements. For example, `\\(` will match `\\(`. If you need the n-highlight component to match using regular expressions constructed from the elements in `patterns` themselves (e.g., `\\(` matches `(`), you can set this to false. If you do not understand these details, do not change this setting. | 2.40.0 |\n| case-sensitive | `boolean` | `false` | Case sensitive or not. | 2.40.0 |\n| highlight-class | `string` | `undefined` | Class name of the highlight content. | 2.40.0 |\n| highlight-style | `Object \\| string` | `undefined` | Style of the highlight content. | 2.40.0 |\n| highlight-tag | `string` | `'mark'` | HTML element tag of the highlight content. | 2.40.0 |\n| patterns | `string[]` | `undefined` | Highlight text. | 2.40.0 |\n| text | `string` | `undefined` | Text. | 2.40.0 |\n"
  },
  {
    "path": "src/highlight/demos/enUS/style.demo.vue",
    "content": "<markdown>\n# Style\n\nChange the style to make the highlight more striking.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { useThemeVars } from 'naive-ui'\n\nconst themeVars = useThemeVars()\nconst text\n  = 'Naive UI is written in full TypeScript and works seamlessly with your TypeScript projects'\nconst patterns = ['Naive UI', 'typeScript']\n</script>\n\n<template>\n  <n-highlight\n    :text=\"text\"\n    :patterns=\"patterns\"\n    :highlight-style=\"{\n      padding: '0 6px',\n      borderRadius: themeVars.borderRadius,\n      display: 'inline-block',\n      color: themeVars.baseColor,\n      background: themeVars.primaryColor,\n      transition: `all .3s ${themeVars.cubicBezierEaseInOut}`,\n    }\"\n  />\n</template>\n"
  },
  {
    "path": "src/highlight/demos/zhCN/basic.demo.vue",
    "content": "<markdown>\n  # 基础\n</markdown>\n\n<script lang=\"ts\" setup>\nconst text\n  = 'Naive UI 是一个 Vue3 的组件库，它比较完整，主题可调，用 TypeScript 写的，快。'\nconst patterns = ['Naive UI', 'Vue3', 'TypeScript', '快']\n</script>\n\n<template>\n  <n-highlight :text=\"text\" :patterns=\"patterns\" />\n</template>\n"
  },
  {
    "path": "src/highlight/demos/zhCN/case-sensitive.demo.vue",
    "content": "<markdown>\n# 区分大小写\n\n默认情况下，高亮是不区分大小写，你可以通过 `case-sensitive` 属性来开启区分大小写模式。\n</markdown>\n\n<script lang=\"ts\" setup>\nconst text = 'Naive UI 全量使用 TypeScript 编写，和你的 TypeScript 项目无缝衔接'\nconst patterns = ['Naive UI', 'typeScript']\n</script>\n\n<template>\n  <n-highlight :text=\"text\" :patterns=\"patterns\" :case-sensitive=\"true\" />\n</template>\n"
  },
  {
    "path": "src/highlight/demos/zhCN/component.demo.vue",
    "content": "<markdown>\n# 高亮标签\n\n通过 `highlight-tag` 属性可以指定高亮文本的标签。\n</markdown>\n\n<script lang=\"ts\" setup>\nconst text\n  = 'Naive UI 是一个 Vue3 的组件库，它比较完整，主题可调，用 TypeScript 写的，快。'\nconst patterns = ['Naive UI', 'Vue3', 'TypeScript', '快']\n</script>\n\n<template>\n  <n-highlight\n    :text=\"text\"\n    highlight-tag=\"span\"\n    :patterns=\"patterns\"\n    highlight-style=\"text-decoration: underline\"\n  />\n</template>\n"
  },
  {
    "path": "src/highlight/demos/zhCN/index.demo-entry.md",
    "content": "# 高亮文本 Highlight\n\n用过搜索引擎的都知道这个是做什么的。\n\n自 `2.40.0` 开始提供。\n\n## 演示\n\n```demo\nbasic.vue\nstyle.vue\ncase-sensitive.vue\ncomponent.vue\n```\n\n## API\n\n### Highlight Props\n\n| 名称 | 类型 | 默认值 | 说明 | 版本 |\n| --- | --- | --- | --- | --- |\n| auto-espace | `boolean` | `true` | 自动转义。默认情况下，`patterns` 中的元素会被转化为正则表达式进行匹配，这个过程中需要进行自动转义，正则表达式最终匹配的是元素的字面内容，例如 `\\(` 匹配的就是 `\\(`。如果你需要 `n-highlight` 组件去匹配使用 `patterns` 中元素本身构造的正则表达式，例如 `\\(` 匹配的是 `(`，则可以设为 `false`。如果你看不懂这些，不要改这个设置。 | 2.40.0 |\n| case-sensitive | `boolean` | `false` | 区分大小写 | 2.40.0 |\n| highlight-class | `string` | `undefined` | 高亮内容的类名 | 2.40.0 |\n| highlight-style | `Object \\| string` | `undefined` | 高亮内容的样式 | 2.40.0 |\n| highlight-tag | `string` | `'mark'` | 高亮内容的 HTML 元素类型 | 2.40.0 |\n| patterns | `string[]` | `undefined` | 需要高亮的文本内容 | 2.40.0 |\n| text | `string` | `undefined` | 文本 | 2.40.0 |\n"
  },
  {
    "path": "src/highlight/demos/zhCN/style.demo.vue",
    "content": "<markdown>\n  # 样式\n\n  换个样式，让高亮更加醒目。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { useThemeVars } from 'naive-ui'\n\nconst themeVars = useThemeVars()\nconst text = 'Naive UI 全量使用 TypeScript 编写，和你的 TypeScript 项目无缝衔接'\nconst patterns = ['Naive UI', 'TypeScript']\n</script>\n\n<template>\n  <n-highlight\n    :text=\"text\"\n    :patterns=\"patterns\"\n    :highlight-style=\"{\n      padding: '0 6px',\n      borderRadius: themeVars.borderRadius,\n      display: 'inline-block',\n      color: themeVars.baseColor,\n      background: themeVars.primaryColor,\n      transition: `all .3s ${themeVars.cubicBezierEaseInOut}`,\n    }\"\n  />\n</template>\n"
  },
  {
    "path": "src/highlight/index.ts",
    "content": "export { highlightProps, default as NHighlight } from './src/Highlight'\nexport type * from './src/public-types'\n"
  },
  {
    "path": "src/highlight/src/Highlight.tsx",
    "content": "import type { CSSProperties, PropType, VNode, VNodeChild } from 'vue'\nimport { computed, defineComponent, h } from 'vue'\nimport { useConfig } from '../../_mixins'\nimport { splitAndMarkByRegex } from './utils'\n\nexport const highlightProps = {\n  highlightTag: {\n    type: String,\n    default: 'mark'\n  },\n  caseSensitive: Boolean,\n  autoEscape: {\n    type: Boolean,\n    default: true\n  },\n  text: String,\n  patterns: {\n    type: Array as PropType<string[]>,\n    default: () => []\n  },\n  highlightClass: String,\n  highlightStyle: [Object, String] as PropType<CSSProperties | string>\n} as const\n\nexport default defineComponent({\n  name: 'Highlight',\n  props: highlightProps,\n  setup(props) {\n    const { mergedClsPrefixRef } = useConfig()\n\n    const escapeRegExp = (text: string): string =>\n      text.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&')\n\n    const highlightedNodeRef = computed<VNode>(() => {\n      const mergedClsPrefix = mergedClsPrefixRef.value\n\n      let children: VNodeChild[] = []\n\n      const { patterns, text } = props\n\n      if (patterns.length === 0 || !text) {\n        children = [text]\n      }\n      else {\n        const {\n          highlightTag,\n          caseSensitive,\n          autoEscape,\n          highlightClass,\n          highlightStyle\n        } = props\n\n        const pattern = patterns\n          .map(word => (autoEscape ? escapeRegExp(word) : word))\n          .join('|')\n        const regex = new RegExp(`(${pattern})`, caseSensitive ? 'g' : 'gi')\n\n        const splitItems = splitAndMarkByRegex(text, regex)\n\n        children = splitItems.map(({ text, isMatch }) => {\n          if (isMatch) {\n            return h(\n              highlightTag,\n              {\n                class: [`${mergedClsPrefix}-highlight__mark`, highlightClass],\n                style: highlightStyle\n              },\n              text\n            )\n          }\n          return text\n        })\n      }\n\n      return h(\n        'span',\n        {\n          class: `${mergedClsPrefix}-highlight`\n        },\n        children\n      )\n    })\n\n    return {\n      highlightedNode: highlightedNodeRef,\n      mergedClsPrefix: mergedClsPrefixRef\n    }\n  },\n  render() {\n    return this.highlightedNode\n  }\n})\n"
  },
  {
    "path": "src/highlight/src/public-types.ts",
    "content": "import type { ExtractPublicPropTypes } from '../../_utils'\nimport type { highlightProps } from './Highlight'\n\nexport type HighlightProps = ExtractPublicPropTypes<typeof highlightProps>\n"
  },
  {
    "path": "src/highlight/src/utils.ts",
    "content": "export function splitAndMarkByRegex(\n  str: string,\n  regex: RegExp\n): Array<{\n  text: string\n  isMatch: boolean\n}> {\n  if (!regex.global) {\n    throw new Error(\n      'splitAndMarkByRegex requires a global regex (with \"g\" flag)'\n    )\n  }\n\n  const result = []\n  let lastIndex = 0\n  for (const match of str.matchAll(regex)) {\n    const { index } = match\n    if (index > lastIndex) {\n      result.push({ text: str.slice(lastIndex, index), isMatch: false })\n    }\n\n    result.push({ text: match[0], isMatch: true })\n\n    lastIndex = index + match[0].length\n  }\n\n  if (lastIndex < str.length) {\n    result.push({ text: str.slice(lastIndex), isMatch: false })\n  }\n\n  return result\n}\n"
  },
  {
    "path": "src/highlight/tests/utils.spec.ts",
    "content": "import { splitAndMarkByRegex } from '../src/utils'\n\ndescribe('splitAndMarkByRegex', () => {\n  it('should split text by regex and mark matches correctly', () => {\n    const text = 'Hello world, hello again'\n    const regex = /hello/gi\n    const result = splitAndMarkByRegex(text, regex)\n\n    expect(result).toEqual([\n      { text: 'Hello', isMatch: true },\n      { text: ' world, ', isMatch: false },\n      { text: 'hello', isMatch: true },\n      { text: ' again', isMatch: false }\n    ])\n  })\n\n  it('should handle case sensitive matching', () => {\n    const text = 'Hello world, hello again'\n    const regex = /hello/g\n    const result = splitAndMarkByRegex(text, regex)\n\n    expect(result).toEqual([\n      { text: 'Hello world, ', isMatch: false },\n      { text: 'hello', isMatch: true },\n      { text: ' again', isMatch: false }\n    ])\n  })\n\n  it('should handle empty string', () => {\n    const text = ''\n    const regex = /test/g\n    const result = splitAndMarkByRegex(text, regex)\n\n    expect(result).toEqual([])\n  })\n\n  it('should handle no matches', () => {\n    const text = 'Hello world'\n    const regex = /xyz/g\n    const result = splitAndMarkByRegex(text, regex)\n\n    expect(result).toEqual([{ text: 'Hello world', isMatch: false }])\n  })\n\n  it('should handle regex that matches entire string', () => {\n    const text = 'hello'\n    const regex = /hello/g\n    const result = splitAndMarkByRegex(text, regex)\n\n    expect(result).toEqual([{ text: 'hello', isMatch: true }])\n  })\n\n  it('should handle regex with multiple word patterns', () => {\n    const text = 'The quick brown fox jumps over the lazy dog'\n    const regex = /(quick|fox|lazy)/g\n    const result = splitAndMarkByRegex(text, regex)\n\n    expect(result).toEqual([\n      { text: 'The ', isMatch: false },\n      { text: 'quick', isMatch: true },\n      { text: ' brown ', isMatch: false },\n      { text: 'fox', isMatch: true },\n      { text: ' jumps over the ', isMatch: false },\n      { text: 'lazy', isMatch: true },\n      { text: ' dog', isMatch: false }\n    ])\n  })\n\n  it('should handle consecutive matches', () => {\n    const text = 'aaa bbb'\n    const regex = /a/g\n    const result = splitAndMarkByRegex(text, regex)\n\n    expect(result).toEqual([\n      { text: 'a', isMatch: true },\n      { text: 'a', isMatch: true },\n      { text: 'a', isMatch: true },\n      { text: ' bbb', isMatch: false }\n    ])\n  })\n\n  it('should handle regex with special characters', () => {\n    const text = 'Price: $100.99'\n    const regex = /\\$\\d+\\.\\d+/g\n    const result = splitAndMarkByRegex(text, regex)\n\n    expect(result).toEqual([\n      { text: 'Price: ', isMatch: false },\n      { text: '$100.99', isMatch: true }\n    ])\n  })\n\n  it('should handle regex that matches at the beginning', () => {\n    const text = 'hello world'\n    const regex = /hello/g\n    const result = splitAndMarkByRegex(text, regex)\n\n    expect(result).toEqual([\n      { text: 'hello', isMatch: true },\n      { text: ' world', isMatch: false }\n    ])\n  })\n\n  it('should handle regex that matches at the end', () => {\n    const text = 'hello world'\n    const regex = /world/g\n    const result = splitAndMarkByRegex(text, regex)\n\n    expect(result).toEqual([\n      { text: 'hello ', isMatch: false },\n      { text: 'world', isMatch: true }\n    ])\n  })\n\n  it('should throw error for non-global regex', () => {\n    const text = 'hello world hello again'\n    const regex = /hello/i\n\n    expect(() => splitAndMarkByRegex(text, regex)).toThrow(\n      'splitAndMarkByRegex requires a global regex (with \"g\" flag)'\n    )\n  })\n\n  it('should throw error for regex without global flag', () => {\n    const text = 'test string'\n    const regex = /test/\n\n    expect(() => splitAndMarkByRegex(text, regex)).toThrow(\n      'splitAndMarkByRegex requires a global regex (with \"g\" flag)'\n    )\n  })\n\n  it('should handle regex with capturing groups', () => {\n    const text = 'foo123bar456'\n    const regex = /(\\d+)/g\n    const result = splitAndMarkByRegex(text, regex)\n\n    expect(result).toEqual([\n      { text: 'foo', isMatch: false },\n      { text: '123', isMatch: true },\n      { text: 'bar', isMatch: false },\n      { text: '456', isMatch: true }\n    ])\n  })\n\n  it('should handle complex regex patterns', () => {\n    const text = 'Email: user@example.com, Phone: +1-234-567-8900'\n    const regex = /[\\w.-]+@[\\w.-]+\\.\\w+|\\+\\d{1,3}-\\d{3}-\\d{3}-\\d{4}/g\n    const result = splitAndMarkByRegex(text, regex)\n\n    expect(result).toEqual([\n      { text: 'Email: ', isMatch: false },\n      { text: 'user@example.com', isMatch: true },\n      { text: ', Phone: ', isMatch: false },\n      { text: '+1-234-567-8900', isMatch: true }\n    ])\n  })\n\n  it('should handle single character matches', () => {\n    const text = 'a1b2c3'\n    const regex = /\\d/g\n    const result = splitAndMarkByRegex(text, regex)\n\n    expect(result).toEqual([\n      { text: 'a', isMatch: false },\n      { text: '1', isMatch: true },\n      { text: 'b', isMatch: false },\n      { text: '2', isMatch: true },\n      { text: 'c', isMatch: false },\n      { text: '3', isMatch: true }\n    ])\n  })\n\n  it('should handle unicode characters', () => {\n    const text = '你好世界 hello world'\n    const regex = /你好|hello/g\n    const result = splitAndMarkByRegex(text, regex)\n\n    expect(result).toEqual([\n      { text: '你好', isMatch: true },\n      { text: '世界 ', isMatch: false },\n      { text: 'hello', isMatch: true },\n      { text: ' world', isMatch: false }\n    ])\n  })\n})\n"
  },
  {
    "path": "src/icon/demos/enUS/basic.demo.vue",
    "content": "<markdown>\n# Basic\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { GameController, GameControllerOutline } from '@vicons/ionicons5'\n</script>\n\n<template>\n  <n-icon size=\"40\">\n    <GameControllerOutline />\n  </n-icon>\n  <n-icon size=\"40\" color=\"#0e7a0d\">\n    <GameController />\n  </n-icon>\n  <n-icon size=\"40\" :component=\"GameController\" />\n</template>\n"
  },
  {
    "path": "src/icon/demos/enUS/custom-icon.demo.vue",
    "content": "<markdown>\n# Customize icon\n\n(Make sure SVG's viewBox attribute is set)\n</markdown>\n\n<template>\n  <n-icon size=\"40\">\n    <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 512 512\">\n      <path\n        d=\"M368.5 240H272v-96.5c0-8.8-7.2-16-16-16s-16 7.2-16 16V240h-96.5c-8.8 0-16 7.2-16 16 0 4.4 1.8 8.4 4.7 11.3 2.9 2.9 6.9 4.7 11.3 4.7H240v96.5c0 4.4 1.8 8.4 4.7 11.3 2.9 2.9 6.9 4.7 11.3 4.7 8.8 0 16-7.2 16-16V272h96.5c8.8 0 16-7.2 16-16s-7.2-16-16-16z\"\n      />\n    </svg>\n  </n-icon>\n</template>\n"
  },
  {
    "path": "src/icon/demos/enUS/depth.demo.vue",
    "content": "<markdown>\n# Depth\n\nTo match different text color levels, icon provides a `depth` property.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { CashOutline } from '@vicons/ionicons5'\n</script>\n\n<template>\n  <n-icon :component=\"CashOutline\" size=\"40\" :depth=\"1\" />\n  <n-icon :component=\"CashOutline\" size=\"40\" :depth=\"2\" />\n  <n-icon :component=\"CashOutline\" size=\"40\" :depth=\"3\" />\n  <n-icon :component=\"CashOutline\" size=\"40\" :depth=\"4\" />\n  <n-icon :component=\"CashOutline\" size=\"40\" :depth=\"5\" />\n</template>\n"
  },
  {
    "path": "src/icon/demos/enUS/icon-wrapper.demo.vue",
    "content": "<markdown>\n# Icon with background\n\nSometimes it looks better with a background.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport Checkmark16Filled from '@vicons/fluent/Checkmark16Filled'\n</script>\n\n<template>\n  <n-icon-wrapper :size=\"24\" :border-radius=\"10\">\n    <n-icon :size=\"18\" :component=\"Checkmark16Filled\" />\n  </n-icon-wrapper>\n</template>\n"
  },
  {
    "path": "src/icon/demos/enUS/index.demo-entry.md",
    "content": "# Icon\n\nIt is recommend to use [xicons](https://www.xicons.org) as your icon library.\n\n## Demos\n\n```demo\nbasic.vue\ncustom-icon.vue\ndepth.vue\nicon-wrapper.vue\n```\n\n## API\n\n### Icon Props\n\n| Name | Type | Default | Description | Version |\n| --- | --- | --- | --- | --- |\n| color | `string` | `undefined` | Icon color. |  |\n| depth | `1 \\| 2 \\| 3 \\| 4 \\| 5` | `undefined` | Icon depth. |  |\n| size | `number \\| string` | `undefined` | Icon size (when the unit is not specified the default unit is `px`). |  |\n| component | `Component` | `undefined` | Icon component to display. | 2.24.6 |\n\n### IconWrapper Props\n\n| Name          | Type     | Default     | Description    | Version |\n| ------------- | -------- | ----------- | -------------- | ------- |\n| border-radius | `number` | `6`         | Border radius. | 2.25.0  |\n| color         | `string` | `undefined` | Color.         | 2.25.0  |\n| icon-color    | `string` | `undefined` | Icon color.    | 2.25.0  |\n| size          | `number` | `24`        | Size.          | 2.25.0  |\n\n### Icon Slots\n\n| Name    | Parameters | Description              |\n| ------- | ---------- | ------------------------ |\n| default | `()`       | The content of the icon. |\n"
  },
  {
    "path": "src/icon/demos/zhCN/basic.demo.vue",
    "content": "<markdown>\n# 基础用法\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { GameController, GameControllerOutline } from '@vicons/ionicons5'\n</script>\n\n<template>\n  <n-icon size=\"40\">\n    <GameControllerOutline />\n  </n-icon>\n  <n-icon size=\"40\" color=\"#0e7a0d\">\n    <GameController />\n  </n-icon>\n  <n-icon size=\"40\" :component=\"GameController\" />\n</template>\n"
  },
  {
    "path": "src/icon/demos/zhCN/custom-icon.demo.vue",
    "content": "<markdown>\n# 自定义图标\n\n将自定义 SVG 放入图标。（确保设定了 SVG 的 viewBox 属性）\n</markdown>\n\n<template>\n  <n-icon size=\"40\">\n    <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 512 512\">\n      <path\n        d=\"M368.5 240H272v-96.5c0-8.8-7.2-16-16-16s-16 7.2-16 16V240h-96.5c-8.8 0-16 7.2-16 16 0 4.4 1.8 8.4 4.7 11.3 2.9 2.9 6.9 4.7 11.3 4.7H240v96.5c0 4.4 1.8 8.4 4.7 11.3 2.9 2.9 6.9 4.7 11.3 4.7 8.8 0 16-7.2 16-16V272h96.5c8.8 0 16-7.2 16-16s-7.2-16-16-16z\"\n      />\n    </svg>\n  </n-icon>\n</template>\n"
  },
  {
    "path": "src/icon/demos/zhCN/depth.demo.vue",
    "content": "<markdown>\n# 深度\n\n为了搭配不同级的文字颜色，图标提供 `depth` 选项。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { CashOutline } from '@vicons/ionicons5'\n</script>\n\n<template>\n  <n-icon :component=\"CashOutline\" size=\"40\" :depth=\"1\" />\n  <n-icon :component=\"CashOutline\" size=\"40\" :depth=\"2\" />\n  <n-icon :component=\"CashOutline\" size=\"40\" :depth=\"3\" />\n  <n-icon :component=\"CashOutline\" size=\"40\" :depth=\"4\" />\n  <n-icon :component=\"CashOutline\" size=\"40\" :depth=\"5\" />\n</template>\n"
  },
  {
    "path": "src/icon/demos/zhCN/icon-wrapper.demo.vue",
    "content": "<markdown>\n# 带背景色的图标\n\n有的时候加个背景显得没那么单调。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport Checkmark16Filled from '@vicons/fluent/Checkmark16Filled'\n</script>\n\n<template>\n  <n-icon-wrapper :size=\"24\" :border-radius=\"10\">\n    <n-icon :size=\"18\" :component=\"Checkmark16Filled\" />\n  </n-icon-wrapper>\n</template>\n"
  },
  {
    "path": "src/icon/demos/zhCN/index.demo-entry.md",
    "content": "# 图标 Icon\n\nnaive-ui 推荐使用 [xicons](https://xicons.org) 作为图标库。\n\n## 演示\n\n```demo\nbasic.vue\ncustom-icon.vue\ndepth.vue\nicon-wrapper.vue\n```\n\n## API\n\n### Icon Props\n\n| 名称 | 类型 | 默认值 | 说明 | 版本 |\n| --- | --- | --- | --- | --- |\n| color | `string` | `undefined` | 图标颜色 |\n| depth | `1 \\| 2 \\| 3 \\| 4 \\| 5` | `undefined` | 图标深度 |\n| size | `number \\| string` | `undefined` | 图标大小（当不指定单位时，默认单位: `px`） |\n| component | `Component` | `undefined` | 要展示的图标组件 | 2.24.6 |\n\n### IconWrapper Props\n\n| 名称          | 类型     | 默认值      | 说明         | 版本   |\n| ------------- | -------- | ----------- | ------------ | ------ |\n| border-radius | `number` | `6`         | 边框圆角大小 | 2.25.0 |\n| color         | `string` | `undefined` | 颜色         | 2.25.0 |\n| icon-color    | `string` | `undefined` | 图标颜色     | 2.25.0 |\n| size          | `number` | `24`        | 尺寸         | 2.25.0 |\n\n### Icon Slots\n\n| 名称    | 参数 | 说明       |\n| ------- | ---- | ---------- |\n| default | `()` | 图标的内容 |\n"
  },
  {
    "path": "src/icon/index.ts",
    "content": "export { iconProps, NIcon } from './src/Icon'\nexport type { IconProps } from './src/Icon'\n"
  },
  {
    "path": "src/icon/src/Icon.ts",
    "content": "import type { Component, PropType } from 'vue'\nimport type { ThemeProps } from '../../_mixins'\nimport type { ExtractPublicPropTypes } from '../../_utils'\nimport type { IconTheme } from '../styles'\nimport { computed, defineComponent, h, mergeProps } from 'vue'\nimport { useConfig, useTheme, useThemeClass } from '../../_mixins'\nimport { formatLength, warn } from '../../_utils'\nimport { iconLight } from '../styles'\nimport style from './styles/index.cssr'\n\nexport type Depth = 1 | 2 | 3 | 4 | 5 | '1' | '2' | '3' | '4' | '5' | undefined\n\nexport const iconProps = {\n  ...(useTheme.props as ThemeProps<IconTheme>),\n  depth: [String, Number] as PropType<Depth>,\n  size: [Number, String] as PropType<number | string>,\n  color: String,\n  component: [Object, Function] as PropType<Component>\n} as const\n\nexport type IconProps = ExtractPublicPropTypes<typeof iconProps>\n\nexport const NIcon = defineComponent({\n  _n_icon__: true,\n  name: 'Icon',\n  inheritAttrs: false,\n  props: iconProps,\n  setup(props) {\n    const { mergedClsPrefixRef, inlineThemeDisabled } = useConfig(props)\n    const themeRef = useTheme(\n      'Icon',\n      '-icon',\n      style,\n      iconLight,\n      props,\n      mergedClsPrefixRef\n    )\n    const cssVarsRef = computed(() => {\n      const { depth } = props\n      const {\n        common: { cubicBezierEaseInOut },\n        self\n      } = themeRef.value\n      if (depth !== undefined) {\n        const { color, [`opacity${depth}Depth` as const]: opacity } = self\n        return {\n          '--n-bezier': cubicBezierEaseInOut,\n          '--n-color': color,\n          '--n-opacity': opacity\n        }\n      }\n      return {\n        '--n-bezier': cubicBezierEaseInOut,\n        '--n-color': '',\n        '--n-opacity': ''\n      }\n    })\n    const themeClassHandle = inlineThemeDisabled\n      ? useThemeClass(\n          'icon',\n          computed(() => `${props.depth || 'd'}`),\n          cssVarsRef,\n          props\n        )\n      : undefined\n    return {\n      mergedClsPrefix: mergedClsPrefixRef,\n      mergedStyle: computed(() => {\n        const { size, color } = props\n        return {\n          fontSize: formatLength(size),\n          color\n        }\n      }),\n      cssVars: inlineThemeDisabled ? undefined : cssVarsRef,\n      themeClass: themeClassHandle?.themeClass,\n      onRender: themeClassHandle?.onRender\n    }\n  },\n  render() {\n    const { $parent, depth, mergedClsPrefix, component, onRender, themeClass }\n      = this\n    if ($parent?.$options?._n_icon__) {\n      warn('icon', 'don\\'t wrap `n-icon` inside `n-icon`')\n    }\n    onRender?.()\n    return h(\n      'i',\n      mergeProps(this.$attrs, {\n        role: 'img',\n        class: [\n          `${mergedClsPrefix}-icon`,\n          themeClass,\n          {\n            [`${mergedClsPrefix}-icon--depth`]: depth,\n            [`${mergedClsPrefix}-icon--color-transition`]: depth !== undefined\n          }\n        ],\n        style: [this.cssVars, this.mergedStyle]\n      }),\n      component ? h(component) : this.$slots\n    )\n  }\n})\n"
  },
  {
    "path": "src/icon/src/styles/index.cssr.ts",
    "content": "import { c, cB, cM } from '../../../_utils/cssr'\n\n// vars:\n// --n-bezier\n// --n-color\n// --n-opacity\nexport default cB('icon', `\n  height: 1em;\n  width: 1em;\n  line-height: 1em;\n  text-align: center;\n  display: inline-block;\n  position: relative;\n  fill: currentColor;\n`, [\n  cM('color-transition', {\n    transition: 'color .3s var(--n-bezier)'\n  }),\n  cM('depth', {\n    color: 'var(--n-color)'\n  }, [\n    c('svg', {\n      opacity: 'var(--n-opacity)',\n      transition: 'opacity .3s var(--n-bezier)'\n    })\n  ]),\n  c('svg', {\n    height: '1em',\n    width: '1em'\n  })\n])\n"
  },
  {
    "path": "src/icon/styles/dark.ts",
    "content": "import type { IconTheme } from './light'\nimport { commonDark } from '../../_styles/common'\nimport { self } from './light'\n\nconst iconDark: IconTheme = {\n  name: 'Icon',\n  common: commonDark,\n  self\n}\n\nexport default iconDark\n"
  },
  {
    "path": "src/icon/styles/index.ts",
    "content": "export { default as iconDark } from './dark'\nexport { default as iconLight } from './light'\nexport type { IconTheme, IconThemeVars } from './light'\n"
  },
  {
    "path": "src/icon/styles/light.ts",
    "content": "import type { Theme } from '../../_mixins'\nimport type { ThemeCommonVars } from '../../_styles/common'\nimport { commonLight } from '../../_styles/common'\n\nexport function self(vars: ThemeCommonVars) {\n  const { textColorBase, opacity1, opacity2, opacity3, opacity4, opacity5 }\n    = vars\n  return {\n    color: textColorBase,\n    opacity1Depth: opacity1,\n    opacity2Depth: opacity2,\n    opacity3Depth: opacity3,\n    opacity4Depth: opacity4,\n    opacity5Depth: opacity5\n  }\n}\n\nexport type IconThemeVars = ReturnType<typeof self>\n\nconst iconLight: Theme<'Icon', IconThemeVars> = {\n  name: 'Icon',\n  common: commonLight,\n  self\n}\n\nexport default iconLight\nexport type IconTheme = typeof iconLight\n"
  },
  {
    "path": "src/icon/tests/Icon.spec.ts",
    "content": "import { mount } from '@vue/test-utils'\nimport { h } from 'vue'\nimport { NIcon } from '../index'\n\ndescribe('n-icon', () => {\n  it('should work with import on demand', () => {\n    mount(NIcon)\n  })\n\n  it('should work with `size` prop', async () => {\n    const wrapper = mount(NIcon, { props: { size: 40 } })\n    expect(wrapper.find('[role=\"img\"]').classes()).toContain('n-icon')\n    expect(wrapper.find('[role=\"img\"]').attributes('style')).toContain(\n      'font-size: 40px;'\n    )\n\n    await wrapper.setProps({ size: 80 })\n    expect(wrapper.find('[role=\"img\"]').attributes('style')).toContain(\n      'font-size: 80px;'\n    )\n    wrapper.unmount()\n  })\n\n  it('should work with `color` prop', async () => {\n    const wrapper = mount(NIcon, { props: { color: 'rgb(14, 122, 13)' } })\n    expect(wrapper.find('[role=\"img\"]').attributes('style')).toContain(\n      'color: rgb(14, 122, 13);'\n    )\n    wrapper.unmount()\n  })\n\n  it('should work with `depth` prop', async () => {\n    const wrapper = mount(NIcon, { props: { depth: 5 } })\n    expect(wrapper.find('[role=\"img\"]').classes()).toContain('n-icon--depth')\n    expect(wrapper.find('[role=\"img\"]').attributes('style')).toMatchSnapshot()\n    wrapper.unmount()\n  })\n\n  it('should work with customize icon', async () => {\n    const customize = h(\n      'svg',\n      { xmlns: 'http://www.w3.org/2000/svg', viewBox: '0 0 512 512' },\n      {\n        default: () =>\n          h('path', {\n            d: 'M368.5 240H272v-96.5c0-8.8-7.2-16-16-16s-16 7.2-16 16V240h-96.5c-8.8 0-16 7.2-16 16 0 4.4 1.8 8.4 4.7 11.3 2.9 2.9 6.9 4.7 11.3 4.7H240v96.5c0 4.4 1.8 8.4 4.7 11.3 2.9 2.9 6.9 4.7 11.3 4.7 8.8 0 16-7.2 16-16V272h96.5c8.8 0 16-7.2 16-16s-7.2-16-16-16z'\n          })\n      }\n    )\n    const wrapper = mount(NIcon, { slots: { default: () => customize } })\n    expect(wrapper.find('svg').exists()).toBe(true)\n    wrapper.unmount()\n  })\n\n  it('should work with `component` prop', async () => {\n    const wrapper = mount(NIcon, {\n      props: {\n        component: h(\n          'div',\n          { class: 'test-component' },\n          { default: () => 'test-component' }\n        )\n      }\n    })\n    expect(wrapper.find('.test-component').exists()).toBe(true)\n    wrapper.unmount()\n  })\n})\n"
  },
  {
    "path": "src/icon/tests/__snapshots__/Icon.spec.ts.snap",
    "content": "// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html\n\nexports[`n-icon > should work with \\`depth\\` prop 1`] = `\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-color: #000; --n-opacity: 0.18;\"`;\n"
  },
  {
    "path": "src/icon/tests/server.spec.tsx",
    "content": "import { setup } from '@css-render/vue3-ssr'\nimport { renderToString } from '@vue/server-renderer'\n/**\n * @vitest-environment node\n */\nimport { createSSRApp, h } from 'vue'\nimport { NIcon } from '../..'\n\ndescribe('server side rendering', () => {\n  it('works', async () => {\n    const app = createSSRApp(() => <NIcon />)\n    setup(app)\n    try {\n      await renderToString(app)\n    }\n    catch (e) {\n      expect(e).not.toBeTruthy()\n    }\n  })\n})\n"
  },
  {
    "path": "src/icon-wrapper/index.ts",
    "content": "export { iconWrapperProps, NIconWrapper } from './src/IconWrapper'\nexport type { IconWrapperProps } from './src/IconWrapper'\n"
  },
  {
    "path": "src/icon-wrapper/src/IconWrapper.tsx",
    "content": "import type { ThemeProps } from '../../_mixins'\nimport type { ExtractPublicPropTypes } from '../../_utils'\nimport type { IconWrapperTheme } from '../styles'\nimport { computed, defineComponent, h } from 'vue'\nimport { useConfig, useTheme, useThemeClass } from '../../_mixins'\nimport { formatLength } from '../../_utils'\nimport { iconWrapperLight } from '../styles'\nimport style from './styles/index.cssr'\n\nexport const iconWrapperProps = {\n  ...(useTheme.props as ThemeProps<IconWrapperTheme>),\n  size: {\n    type: Number,\n    default: 24\n  },\n  borderRadius: {\n    type: Number,\n    default: 6\n  },\n  color: String,\n  iconColor: String\n} as const\n\nexport type IconWrapperProps = ExtractPublicPropTypes<typeof iconWrapperProps>\n\nexport const NIconWrapper = defineComponent({\n  name: 'IconWrapper',\n  props: iconWrapperProps,\n  setup(props, { slots }) {\n    const { mergedClsPrefixRef, inlineThemeDisabled } = useConfig(props)\n    const themeRef = useTheme(\n      'IconWrapper',\n      '-icon-wrapper',\n      style,\n      iconWrapperLight,\n      props,\n      mergedClsPrefixRef\n    )\n    const cssVarsRef = computed(() => {\n      const {\n        common: { cubicBezierEaseInOut },\n        self: { color, iconColor }\n      } = themeRef.value\n      return {\n        '--n-bezier': cubicBezierEaseInOut,\n        '--n-color': color,\n        '--n-icon-color': iconColor\n      }\n    })\n    const themeClassHandle = inlineThemeDisabled\n      ? useThemeClass('icon-wrapper', undefined, cssVarsRef, props)\n      : undefined\n    return () => {\n      const size = formatLength(props.size)\n      themeClassHandle?.onRender()\n      return (\n        <div\n          class={[\n            `${mergedClsPrefixRef.value}-icon-wrapper`,\n            themeClassHandle?.themeClass.value\n          ]}\n          style={[\n            cssVarsRef?.value as any,\n            {\n              height: size,\n              width: size,\n              borderRadius: formatLength(props.borderRadius),\n              backgroundColor: props.color,\n              color: props.iconColor\n            }\n          ]}\n        >\n          {slots}\n        </div>\n      )\n    }\n  }\n})\n"
  },
  {
    "path": "src/icon-wrapper/src/styles/index.cssr.ts",
    "content": "import { cB } from '../../../_utils/cssr'\n\n// vars:\n// --n-bezier\n// --n-border-radius\n// --n-color\n// --n-icon-color\nexport default cB('icon-wrapper', `\n  transition:\n    color .3s var(--n-bezier),\n    background-color .3s var(--n-bezier);\n  background-color: var(--n-color);\n  display: inline-flex;\n  align-items: center;\n  justify-content: center;\n  color: var(--n-icon-color);\n`)\n"
  },
  {
    "path": "src/icon-wrapper/styles/dark.ts",
    "content": "import type { IconWrapperTheme } from './light'\nimport { commonDark } from '../../_styles/common'\nimport { self } from './light'\n\nconst iconDark: IconWrapperTheme = {\n  name: 'IconWrapper',\n  common: commonDark,\n  self\n}\n\nexport default iconDark\n"
  },
  {
    "path": "src/icon-wrapper/styles/index.ts",
    "content": "export { default as iconWrapperDark } from './dark'\nexport { default as iconWrapperLight } from './light'\nexport type { IconWrapperTheme, IconWrapperThemeVars } from './light'\n"
  },
  {
    "path": "src/icon-wrapper/styles/light.ts",
    "content": "import type { Theme } from '../../_mixins'\nimport type { ThemeCommonVars } from '../../_styles/common'\nimport { commonLight } from '../../_styles/common'\n\nexport function self(vars: ThemeCommonVars) {\n  const { primaryColor, baseColor } = vars\n  return {\n    color: primaryColor,\n    iconColor: baseColor\n  }\n}\n\nexport type IconWrapperThemeVars = ReturnType<typeof self>\n\nconst iconWrapperLight: Theme<'IconWrapper', IconWrapperThemeVars> = {\n  name: 'IconWrapper',\n  common: commonLight,\n  self\n}\n\nexport default iconWrapperLight\nexport type IconWrapperTheme = typeof iconWrapperLight\n"
  },
  {
    "path": "src/icon-wrapper/tests/IconWrapper.spec.ts",
    "content": "import { mount } from '@vue/test-utils'\nimport { NIconWrapper } from '../index'\n\ndescribe('n-icon-wrapper', () => {\n  it('should work with import on demand', () => {\n    mount(NIconWrapper)\n  })\n\n  it('should work with `border-radius` prop', async () => {\n    const wrapper = mount(NIconWrapper)\n    expect(wrapper.find('.n-icon-wrapper').attributes('style')).toContain(\n      'border-radius: 6px'\n    )\n\n    await wrapper.setProps({ borderRadius: 10 })\n    expect(wrapper.find('.n-icon-wrapper').attributes('style')).toContain(\n      'border-radius: 10px'\n    )\n    wrapper.unmount()\n  })\n\n  it('should work with `color` prop', async () => {\n    const wrapper = mount(NIconWrapper)\n    expect(wrapper.find('.n-icon-wrapper').attributes('style')).not.toContain(\n      'background-color: red'\n    )\n\n    await wrapper.setProps({ color: 'red' })\n    expect(wrapper.find('.n-icon-wrapper').attributes('style')).toContain(\n      'background-color: red'\n    )\n    wrapper.unmount()\n  })\n\n  it('should work with `icon-color` prop', async () => {\n    const wrapper = mount(NIconWrapper)\n    expect(wrapper.find('.n-icon-wrapper').attributes('style')).not.toContain(\n      'color: red'\n    )\n\n    await wrapper.setProps({ iconColor: 'red' })\n    expect(wrapper.find('.n-icon-wrapper').attributes('style')).toContain(\n      'color: red'\n    )\n    wrapper.unmount()\n  })\n\n  it('should work with `size` prop', async () => {\n    const wrapper = mount(NIconWrapper)\n    expect(wrapper.find('.n-icon-wrapper').attributes('style')).toContain(\n      'height: 24px; width: 24px;'\n    )\n\n    await wrapper.setProps({ size: 18 })\n    expect(wrapper.find('.n-icon-wrapper').attributes('style')).toContain(\n      'height: 18px; width: 18px;'\n    )\n    wrapper.unmount()\n  })\n})\n"
  },
  {
    "path": "src/icon-wrapper/tests/server.spec.tsx",
    "content": "import { setup } from '@css-render/vue3-ssr'\nimport { renderToString } from '@vue/server-renderer'\n/**\n * @vitest-environment node\n */\nimport { createSSRApp, h } from 'vue'\nimport { NIconWrapper } from '../..'\n\ndescribe('server side rendering', () => {\n  it('works', async () => {\n    const app = createSSRApp(() => <NIconWrapper />)\n    setup(app)\n    try {\n      await renderToString(app)\n    }\n    catch (e) {\n      expect(e).not.toBeTruthy()\n    }\n  })\n})\n"
  },
  {
    "path": "src/image/demos/enUS/basic.demo.vue",
    "content": "<markdown>\n# Basic\n</markdown>\n\n<template>\n  <n-image\n    width=\"100\"\n    src=\"https://07akioni.oss-cn-beijing.aliyuncs.com/07akioni.jpeg\"\n  />\n</template>\n"
  },
  {
    "path": "src/image/demos/enUS/component-preview-group.demo.vue",
    "content": "<markdown>\n# Multi-image preview\n\nUse `src-list` of `<n-image-group />` to preview images without `<n-image />`.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { useMessage } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst currentIndex = ref(0)\n\nconst showRef = ref(false)\nfunction onClick() {\n  showRef.value = true\n}\n\nconst message = useMessage()\nfunction handleUpdateShow(value: boolean) {\n  message.info(`${value}`)\n}\n\nfunction handleUpdateCurrent(current: number) {\n  message.info(`${current}`)\n}\n</script>\n\n<template>\n  <n-button type=\"primary\" @click=\"onClick\">\n    Click me to preview multiple image\n  </n-button>\n  <n-image-group\n    v-model:show=\"showRef\"\n    v-model:current=\"currentIndex\"\n    :src-list=\"[\n      'https://07akioni.oss-cn-beijing.aliyuncs.com/07akioni.jpeg',\n      'https://gw.alipayobjects.com/zos/antfincdn/aPkFc8Sj7n/method-draw-image.svg',\n      'https://picsum.photos/id/1/100/100',\n      'https://picsum.photos/id/2/100/100',\n      'https://picsum.photos/id/3/100/100',\n      'https://picsum.photos/id/4/100/100',\n      'https://picsum.photos/id/5/100/100',\n      'https://picsum.photos/id/7/100/100',\n      'https://picsum.photos/id/8/100/100',\n      'https://picsum.photos/id/9/100/100',\n      'https://picsum.photos/id/10/100/100',\n    ]\"\n    @update:show=\"handleUpdateShow\"\n    @update:current=\"handleUpdateCurrent\"\n  />\n  <pre>currentIndex: {{ currentIndex }}</pre>\n</template>\n"
  },
  {
    "path": "src/image/demos/enUS/component-preview.demo.vue",
    "content": "<markdown>\n# Use Preview alone\n\n`n-image-preview` can be used alone。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { useMessage } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst showRef = ref(false)\nfunction onClick() {\n  showRef.value = true\n}\n\nconst message = useMessage()\n\nfunction handleUpdateShow(value: boolean) {\n  message.info(`${value}`)\n}\n\nfunction handleClose() {\n  message.info('close')\n}\n</script>\n\n<template>\n  <n-button type=\"primary\" @click=\"onClick\">\n    Click me to preview image\n  </n-button>\n  <n-image-preview\n    v-model:show=\"showRef\"\n    src=\"https://07akioni.oss-cn-beijing.aliyuncs.com/07akioni.jpeg\"\n    @update:show=\"handleUpdateShow\"\n    @close=\"handleClose\"\n  />\n</template>\n"
  },
  {
    "path": "src/image/demos/enUS/custom-error.demo.vue",
    "content": "<markdown>\n# Error slot\n\nYou can use `error` slot to custom loading error display.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ImageOutline as ImageOutlineIcon } from '@vicons/ionicons5'\nimport { ref } from 'vue'\n\nconst url = ref('blablabla')\nfunction refresh() {\n  url.value = 'https://07akioni.oss-cn-beijing.aliyuncs.com/07akioni.jpeg'\n}\nfunction reloadError() {\n  url.value = 'blablabla'\n}\n</script>\n\n<template>\n  <n-flex vertical inline>\n    <n-flex>\n      <n-button type=\"error\" @click=\"reloadError\">\n        Load Fail\n      </n-button>\n      <n-button type=\"primary\" @click=\"refresh\">\n        Refresh\n      </n-button>\n    </n-flex>\n    <n-image width=\"100\" :src=\"url\">\n      <template #error>\n        <n-icon :size=\"100\" color=\"lightGrey\">\n          <ImageOutlineIcon />\n        </n-icon>\n      </template>\n    </n-image>\n  </n-flex>\n</template>\n"
  },
  {
    "path": "src/image/demos/enUS/custom-toolbar.demo.vue",
    "content": "<markdown>\n# Custom Toolbar\n\nYou can customize the toolbar using `render-toolbar`.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { ImageRenderToolbarProps } from 'naive-ui'\nimport { ClipboardOutline, OpenOutline } from '@vicons/ionicons5'\nimport { NButton, useMessage } from 'naive-ui'\nimport { h, ref } from 'vue'\n\nconst message = useMessage()\n\nconst url = ref('https://picsum.photos/id/10/100/100')\n\nfunction renderToolbar({ nodes }: ImageRenderToolbarProps) {\n  return [\n    nodes.prev,\n    nodes.next,\n    h(\n      NButton,\n      {\n        circle: true,\n        type: 'primary',\n        style: { marginLeft: '12px' },\n        onClick: () => {\n          window.open(url.value)\n        }\n      },\n      {\n        icon: () => h(OpenOutline)\n      }\n    ),\n    h(\n      NButton,\n      {\n        circle: true,\n        type: 'primary',\n        style: { marginLeft: '12px' },\n        onClick: async () => {\n          await navigator.clipboard.writeText(url.value)\n          message.success('Copied to clipboard')\n        }\n      },\n      {\n        icon: () => h(ClipboardOutline)\n      }\n    )\n  ]\n}\n</script>\n\n<template>\n  <n-image\n    width=\"100\"\n    src=\"https://07akioni.oss-cn-beijing.aliyuncs.com/07akioni.jpeg\"\n    :render-toolbar=\"renderToolbar\"\n  />\n</template>\n"
  },
  {
    "path": "src/image/demos/enUS/custom.demo.vue",
    "content": "<markdown>\n# Customizing toolbar by theme variables\n\nThe default style of toolbar may not meet your demand, let's make some configuration.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { GlobalThemeOverrides } from 'naive-ui'\nimport { useThemeVars } from 'naive-ui'\nimport { computed } from 'vue'\n\nconst imageGroupThemeOverrides = computed(() => {\n  const { popoverColor, boxShadow2, textColor2, borderRadius }\n    = useThemeVars().value\n  const themeOverrides: NonNullable<GlobalThemeOverrides['Image']> = {\n    toolbarColor: popoverColor,\n    toolbarBoxShadow: boxShadow2,\n    toolbarIconColor: textColor2,\n    toolbarBorderRadius: borderRadius\n  }\n  return themeOverrides\n})\n</script>\n\n<template>\n  <n-image-group :theme-overrides=\"imageGroupThemeOverrides\">\n    <n-space>\n      <n-image\n        width=\"100\"\n        src=\"https://07akioni.oss-cn-beijing.aliyuncs.com/07akioni.jpeg\"\n      />\n      <n-image\n        width=\"100\"\n        src=\"https://gw.alipayobjects.com/zos/antfincdn/aPkFc8Sj7n/method-draw-image.svg\"\n      />\n    </n-space>\n  </n-image-group>\n</template>\n"
  },
  {
    "path": "src/image/demos/enUS/error.demo.vue",
    "content": "<markdown>\n# Fail to load\n\nUse `fallback-src` to set an fallback image on error, or you can use `error` slot in the next demo.\n</markdown>\n\n<template>\n  <n-image\n    width=\"100\"\n    src=\"blablabla\"\n    fallback-src=\"https://07akioni.oss-cn-beijing.aliyuncs.com/07akioni.jpeg\"\n  />\n</template>\n"
  },
  {
    "path": "src/image/demos/enUS/group.demo.vue",
    "content": "<markdown>\n# Image group\n</markdown>\n\n<template>\n  <n-image-group>\n    <n-space>\n      <n-image\n        width=\"100\"\n        src=\"https://07akioni.oss-cn-beijing.aliyuncs.com/07akioni.jpeg\"\n      />\n      <n-image\n        width=\"100\"\n        src=\"https://gw.alipayobjects.com/zos/antfincdn/aPkFc8Sj7n/method-draw-image.svg\"\n      />\n    </n-space>\n  </n-image-group>\n</template>\n"
  },
  {
    "path": "src/image/demos/enUS/index.demo-entry.md",
    "content": "# Image\n\nPreview it.\n\n## Demos\n\n```demo\nbasic.vue\ngroup.vue\nerror.vue\ncustom-error.vue\npreview-disabled.vue\ncustom-toolbar.vue\ncustom.vue\ntooltip.vue\nlazy.vue\npreviewed-img-props.vue\nmanually-open-preview.vue\ncomponent-preview.vue\ncomponent-preview-group.vue\n```\n\n## API\n\n### Image Props\n\n| Name | Type | Default | Description | Version |\n| --- | --- | --- | --- | --- |\n| alt | `string` | `undefined` | Image alt information. |  |\n| fallback-src | `string` | `undefined` | URL to show when the image fails to load. |  |\n| height | `string \\| number` | `undefined` | Image height. |  |\n| img-props | `ImgHTMLAttributes` | `undefined` | The props of the img element inside the component. |  |\n| lazy | `boolean` | `false` | Load image after it enters viewport. When used alone, it will be assigned the property value of [HTMLImageElement.loading](https://developer.mozilla.org/en-US/docs/Web/API/HTMLImageElement/loading). Alternatively, it can be used in conjunction with the `intersection-observer-options` configuration to achieve lazy loading. | 2.30.5 |\n| intersection-observer-options | `{ root?: Element \\| Document \\| string \\| null, rootMargin?: string, threshold?: number \\| number[]; }` | `undefined` | Intersection observer's config to be applied when `lazy=true`. | 2.30.5 |\n| object-fit | `'fill' \\| 'contain' \\| 'cover' \\| 'none' \\| 'scale-down'` | `fill` | Object-fit type of the image in the container. |  |\n| preview-src | `string` | `undefined` | Source of preview image. |  |\n| preview-disabled | `boolean` | `false` | Whether clicking image preview is disabled. |  |\n| previewed-img-props | `HTMLAttributes` | `undefined` | DOM attributes of img element in preview mode. | 2.34.0 |\n| render-toolbar | `(props: { nodes: { prev: VNode, next: VNode, rotateCounterclockwise: VNode, rotateClockwise: VNode, resizeToOriginalSize: VNode, zoomOut: VNode, zoomIn: VNode, download: VNode, close: VNode } }) => VNodeChild` | `undefined` | Toolbar rendering function. | `2.38.2` |\n| show-toolbar | `boolean` | `true` | Whether to show the bottom toolbar when the image enlarge. |  |\n| show-toolbar-tooltip | `boolean` | `false` | Whether to show toolbar buttons' tooltip. | 2.24.0 |\n| src | `string` | `undefined` | Image source. |  |\n| width | `string \\| number` | `undefined` | Image width. |  |\n| on-error | `(e: Event) => void` | `undefined` | Callback executed when the image fails to load. |  |\n| on-load | `(e: Event) => void` | `undefined` | Callback executed after the image is loaded. |  |\n\n### ImageGroup Props\n\n| Name | Type | Default | Description | Version |\n| --- | --- | --- | --- | --- |\n| current | `number` | `undefined` | The subscript of the currently displayed image. | 2.43.0 |\n| default-current | `number` | `0` | The subscript of the default displayed image. | 2.43.0 |\n| default-show | `boolean` | `false` | Whether to show the preview big image by default. | 2.43.0 |\n| render-toolbar | `(props: { nodes: { prev: VNode, next: VNode, rotateCounterclockwise: VNode, rotateClockwise: VNode, resizeToOriginalSize: VNode, zoomOut: VNode, zoomIn: VNode, download: VNode, close: VNode } }) => VNodeChild` | `undefined` | Toolbar rendering function. | `2.38.2` |\n| show | `boolean` | `undefined` | Whether to the show preview big image. | 2.43.0 |\n| show-toolbar | `boolean` | `true` | Whether to show the bottom toolbar when the image enlarge. |  |\n| show-toolbar-tooltip | `boolean` | `false` | Whether to show toolbar buttons' tooltip. | 2.24.0 |\n| src-list | `string[]` | `undefined` | Picture src list. | 2.43.0 |\n| on-preview-next | `() => void` | `undefined` | Click the callback on the next slide. |\n| on-preview-prev | `() => void` | `undefined` | Click the callback from the previous slide. |  |\n| on-update:current | `(value: number) => void` | `undefined` | Callback on currently displayed image changes. | 2.43.0 |\n| on-update:show | `(value: boolean) => void` | `undefined` | Callback on show status changes. | 2.43.0 |\n\n### ImagePreview Props\n\n| Name | Type | Default | Description | Version |\n| --- | --- | --- | --- | --- |\n| default-show | `boolean` | `false` | Whether to show the preview big image by default. | 2.43.0 |\n| render-toolbar | `(props: { nodes: { prev: VNode, next: VNode, rotateCounterclockwise: VNode, rotateClockwise: VNode, resizeToOriginalSize: VNode, zoomOut: VNode, zoomIn: VNode, download: VNode, close: VNode } }) => VNodeChild` | `undefined` | Toolbar rendering function. | 2.43.0 |\n| show | `boolean` | `undefined` | Whether to the show preview big image. | 2.43.0 |\n| show-toolbar | `boolean` | `true` | Whether to show the bottom toolbar when the image enlarge. | 2.43.0 |\n| show-toolbar-tooltip | `boolean` | `false` | Whether to show toolbar buttons' tooltip. | 2.43.0 |\n| src | `string` | `undefined` | Image source. | 2.43.0 |\n| on-close | `() => void` | `undefined` | Callback when close the preview of the image. | 2.43.0 |\n| on-update:show | `(value: boolean) => void` | `undefined` | Callback on show status changes. | 2.43.0 |\n\n### Image Slots\n\n| Name | Parameters | Description | Version |\n| --- | --- | --- | --- |\n| error | `()` | The content when the image fails to load. | 2.40.2 |\n| placeholder | `()` | Placeholder shown when image is not loaded. | 2.30.5 |\n\n### ImageGroup Slots\n\n| Name    | Parameters | Description                             |\n| ------- | ---------- | --------------------------------------- |\n| default | `()`       | The default content of the image group. |\n\n### Image Methods\n\n| Name        | Type         | Description                          | Version |\n| ----------- | ------------ | ------------------------------------ | ------- |\n| showPreview | `() => void` | Show preview interface of the image. | 2.43.0  |\n"
  },
  {
    "path": "src/image/demos/enUS/lazy.demo.vue",
    "content": "<markdown>\n# Lazy load\n\nLoad the images only after they enter the viewport. There are two ways to use it: one is to use the `lazy` property alone, which will be set to the value of the [HTMLImageElement.loading](https://developer.mozilla.org/en-US/docs/Web/API/HTMLImageElement/loading) property, and the other is to use `lazy` together with the `intersection-observer-options` configuration to implement lazy loading using the [IntersectionObserver](https://developer.mozilla.org/en-US/docs/Web/API/IntersectionObserver) API.\n</markdown>\n\n<script lang=\"ts\" setup>\nconst srcList = [\n  'https://picsum.photos/id/1/100/100',\n  'https://picsum.photos/id/2/100/100',\n  'https://picsum.photos/id/3/100/100',\n  'https://picsum.photos/id/4/100/100',\n  'https://picsum.photos/id/5/100/100',\n  'https://picsum.photos/id/6/100/100',\n  'https://picsum.photos/id/7/100/100',\n  'https://picsum.photos/id/8/100/100',\n  'https://picsum.photos/id/9/100/100',\n  'https://picsum.photos/id/10/100/100'\n]\n</script>\n\n<template>\n  <n-p>\n    use<n-text code>\n      lazy\n    </n-text> along\n  </n-p>\n  <n-image\n    lazy\n    width=\"100\"\n    src=\"https://07akioni.oss-cn-beijing.aliyuncs.com/07akioni.jpeg\"\n  />\n  <n-p>\n    use <n-text code>\n      lazy\n    </n-text> with\n    <n-text code>\n      intersection-observer-options\n    </n-text>\n  </n-p>\n  <div\n    id=\"image-scroll-container\"\n    style=\"\n      overflow: auto;\n      height: 100px;\n      display: flex;\n      flex-direction: column;\n      gap: 8px;\n    \"\n  >\n    <n-image\n      v-for=\"(src, index) in srcList\"\n      :key=\"index\"\n      width=\"100\"\n      height=\"100\"\n      lazy\n      :src=\"src\"\n      :intersection-observer-options=\"{\n        root: '#image-scroll-container',\n      }\"\n    >\n      <template #placeholder>\n        <div\n          style=\"\n            width: 100px;\n            height: 100px;\n            display: flex;\n            align-items: center;\n            justify-content: center;\n            background-color: #8882;\n          \"\n        >\n          Loading\n        </div>\n      </template>\n    </n-image>\n  </div>\n</template>\n"
  },
  {
    "path": "src/image/demos/enUS/manually-open-preview.demo.vue",
    "content": "<markdown>\n# Manually Open Preview\n\nToggle big image preview by calling `showPreview` method.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { ImageInst } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst imageRef = ref<ImageInst>()\nfunction handleClick() {\n  imageRef.value?.showPreview()\n}\n</script>\n\n<template>\n  <n-space vertical>\n    <n-button type=\"primary\" @click=\"handleClick\">\n      Show image preview\n    </n-button>\n    <n-image\n      ref=\"imageRef\"\n      width=\"100\"\n      src=\"https://07akioni.oss-cn-beijing.aliyuncs.com/07akioni.jpeg\"\n    />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/image/demos/enUS/preview-disabled.demo.vue",
    "content": "<markdown>\n# Disable preview\n\nYou can use `preview-disabled` to disable preview.\n</markdown>\n\n<template>\n  <n-image\n    width=\"100\"\n    src=\"https://07akioni.oss-cn-beijing.aliyuncs.com/07akioni.jpeg\"\n    preview-disabled\n  />\n</template>\n"
  },
  {
    "path": "src/image/demos/enUS/previewed-img-props.demo.vue",
    "content": "<markdown>\n# Previewed image props\n\nYou can use `previewed-img-props` to set DOM attributes of previewed image.\n</markdown>\n\n<template>\n  <n-image\n    width=\"100\"\n    src=\"https://07akioni.oss-cn-beijing.aliyuncs.com/07akioni.jpeg\"\n    :previewed-img-props=\"{ style: { border: '8px solid white' } }\"\n  />\n</template>\n"
  },
  {
    "path": "src/image/demos/enUS/tooltip.demo.vue",
    "content": "<markdown>\n# Toolbar tooltip\n\nSome users doesn't know how keyboard operation works. You can show tooltip by setting `show-toolbar-tooltip`.\n</markdown>\n\n<template>\n  <n-image-group show-toolbar-tooltip>\n    <n-space>\n      <n-image\n        width=\"100\"\n        src=\"https://07akioni.oss-cn-beijing.aliyuncs.com/07akioni.jpeg\"\n      />\n      <n-image\n        width=\"100\"\n        src=\"https://gw.alipayobjects.com/zos/antfincdn/aPkFc8Sj7n/method-draw-image.svg\"\n      />\n    </n-space>\n  </n-image-group>\n</template>\n"
  },
  {
    "path": "src/image/demos/zhCN/basic.demo.vue",
    "content": "<markdown>\n# 基础用法\n</markdown>\n\n<template>\n  <n-image\n    width=\"100\"\n    src=\"https://07akioni.oss-cn-beijing.aliyuncs.com/07akioni.jpeg\"\n  />\n</template>\n"
  },
  {
    "path": "src/image/demos/zhCN/component-preview-group-debug.demo.vue",
    "content": "<markdown>\n# debug preview group\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst currentIndex = ref(0)\nconst showRef = ref(false)\nfunction onClick() {\n  showRef.value = true\n}\n\nconst currentIndex2 = ref(0)\nconst showRef2 = ref(false)\nfunction onClick2() {\n  showRef2.value = true\n}\n</script>\n\n<template>\n  <n-space vertical>\n    <p>src-list && n-image</p>\n    <n-button type=\"primary\" @click=\"onClick\">\n      Click me to preview multiple image\n    </n-button>\n    <n-image-group\n      v-model:show=\"showRef\"\n      v-model:current=\"currentIndex\"\n      :src-list=\"[\n        'https://picsum.photos/id/1/100/100',\n        'https://picsum.photos/id/2/100/100',\n        'https://picsum.photos/id/3/100/100',\n        'https://picsum.photos/id/4/100/100',\n        'https://picsum.photos/id/5/100/100',\n        'https://picsum.photos/id/7/100/100',\n        'https://picsum.photos/id/8/100/100',\n        'https://picsum.photos/id/9/100/100',\n        'https://picsum.photos/id/10/100/100',\n      ]\"\n    >\n      <!-- <n-image\n        width=\"100\"\n        src=\"https://07akioni.oss-cn-beijing.aliyuncs.com/07akioni.jpeg\"\n      />\n      <n-image\n        width=\"100\"\n        src=\"https://gw.alipayobjects.com/zos/antfincdn/aPkFc8Sj7n/method-draw-image.svg\"\n      /> -->\n    </n-image-group>\n    <pre>currentIndex: {{ currentIndex }}</pre>\n\n    <p>n-image</p>\n    <n-button type=\"primary\" @click=\"onClick2\">\n      Click me to preview multiple image\n    </n-button>\n    <n-image-group v-model:show=\"showRef2\" v-model:current=\"currentIndex2\">\n      <n-space>\n        <n-image\n          width=\"100\"\n          src=\"https://07akioni.oss-cn-beijing.aliyuncs.com/07akioni.jpeg\"\n        />\n        <n-image\n          width=\"100\"\n          src=\"https://gw.alipayobjects.com/zos/antfincdn/aPkFc8Sj7n/method-draw-image.svg\"\n        />\n      </n-space>\n    </n-image-group>\n    <pre>currentIndex: {{ currentIndex2 }}</pre>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/image/demos/zhCN/component-preview-group.demo.vue",
    "content": "<markdown>\n# 单独使用多图预览组件\n\n使用 `<n-image-group />` 的 `src-list` 属性预览多张图片，无需使用 `<n-image />`。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { useMessage } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst currentIndex = ref(0)\n\nconst showRef = ref(false)\nfunction onClick() {\n  showRef.value = true\n}\n\nconst message = useMessage()\nfunction handleUpdateShow(value: boolean) {\n  message.info(`${value}`)\n}\n\nfunction handleUpdateCurrent(current: number) {\n  message.info(`${current}`)\n}\n</script>\n\n<template>\n  <n-button type=\"primary\" @click=\"onClick\">\n    点击预览多图\n  </n-button>\n  <n-image-group\n    v-model:show=\"showRef\"\n    v-model:current=\"currentIndex\"\n    :src-list=\"[\n      'https://07akioni.oss-cn-beijing.aliyuncs.com/07akioni.jpeg',\n      'https://gw.alipayobjects.com/zos/antfincdn/aPkFc8Sj7n/method-draw-image.svg',\n      'https://picsum.photos/id/1/100/100',\n      'https://picsum.photos/id/2/100/100',\n      'https://picsum.photos/id/3/100/100',\n      'https://picsum.photos/id/4/100/100',\n      'https://picsum.photos/id/5/100/100',\n      'https://picsum.photos/id/7/100/100',\n      'https://picsum.photos/id/8/100/100',\n      'https://picsum.photos/id/9/100/100',\n      'https://picsum.photos/id/10/100/100',\n    ]\"\n    @update:show=\"handleUpdateShow\"\n    @update:current=\"handleUpdateCurrent\"\n  />\n  <pre>currentIndex: {{ currentIndex }}</pre>\n</template>\n"
  },
  {
    "path": "src/image/demos/zhCN/component-preview.demo.vue",
    "content": "<markdown>\n# 单独使用预览组件\n\n`n-image-preview` 可单独使用。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { useMessage } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst showRef = ref(false)\nfunction onClick() {\n  showRef.value = true\n}\n\nconst message = useMessage()\n\nfunction handleUpdateShow(value: boolean) {\n  message.info(`${value}`)\n}\n\nfunction handleClose() {\n  message.info('close')\n}\n</script>\n\n<template>\n  <n-button type=\"primary\" @click=\"onClick\">\n    点击预览图片\n  </n-button>\n  <n-image-preview\n    v-model:show=\"showRef\"\n    src=\"https://07akioni.oss-cn-beijing.aliyuncs.com/07akioni.jpeg\"\n    @update:show=\"handleUpdateShow\"\n    @close=\"handleClose\"\n  />\n</template>\n"
  },
  {
    "path": "src/image/demos/zhCN/custom-error.demo.vue",
    "content": "<markdown>\n# 加载失败的插槽\n\n你可以使用 `error` slot 来自定义加载失败时的内容。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ImageOutline as ImageOutlineIcon } from '@vicons/ionicons5'\nimport { ref } from 'vue'\n\nconst url = ref('人生嘛，失败总是难免的')\nfunction refresh() {\n  url.value = 'https://07akioni.oss-cn-beijing.aliyuncs.com/07akioni.jpeg'\n}\nfunction reloadError() {\n  url.value = '人生嘛，失败总是难免的'\n}\n</script>\n\n<template>\n  <n-flex vertical inline>\n    <n-flex>\n      <n-button type=\"error\" @click=\"reloadError\">\n        加载失败\n      </n-button>\n      <n-button type=\"primary\" @click=\"refresh\">\n        刷新\n      </n-button>\n    </n-flex>\n    <n-image width=\"100\" :src=\"url\">\n      <template #error>\n        <n-icon :size=\"100\" color=\"lightGrey\">\n          <ImageOutlineIcon />\n        </n-icon>\n      </template>\n    </n-image>\n  </n-flex>\n</template>\n"
  },
  {
    "path": "src/image/demos/zhCN/custom-toolbar.demo.vue",
    "content": "<markdown>\n# 自定义工具栏\n\n你可以使用 `render-toolbar` 来自定义工具栏。\n  </markdown>\n\n<script lang=\"ts\" setup>\nimport type { ImageRenderToolbarProps } from 'naive-ui'\nimport { ClipboardOutline, OpenOutline } from '@vicons/ionicons5'\nimport { NButton, useMessage } from 'naive-ui'\nimport { h, ref } from 'vue'\n\nconst message = useMessage()\n\nconst url = ref('https://picsum.photos/id/10/100/100')\n\nfunction renderToolbar({ nodes }: ImageRenderToolbarProps) {\n  return [\n    nodes.prev,\n    nodes.next,\n    h(\n      NButton,\n      {\n        circle: true,\n        type: 'primary',\n        style: { marginLeft: '12px' },\n        onClick: () => {\n          window.open(url.value)\n        }\n      },\n      {\n        icon: () => h(OpenOutline)\n      }\n    ),\n    h(\n      NButton,\n      {\n        circle: true,\n        type: 'primary',\n        style: { marginLeft: '12px' },\n        onClick: async () => {\n          await navigator.clipboard.writeText(url.value)\n          message.success('已复制到剪贴板')\n        }\n      },\n      {\n        icon: () => h(ClipboardOutline)\n      }\n    )\n  ]\n}\n</script>\n\n<template>\n  <n-image\n    width=\"100\"\n    src=\"https://07akioni.oss-cn-beijing.aliyuncs.com/07akioni.jpeg\"\n    :render-toolbar=\"renderToolbar\"\n  />\n</template>\n"
  },
  {
    "path": "src/image/demos/zhCN/custom.demo.vue",
    "content": "<markdown>\n# 使用主题变量自定义工具栏样式\n\n默认的工具栏样式不一定符合你的需求，我们来调整一下。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { GlobalThemeOverrides } from 'naive-ui'\nimport { useThemeVars } from 'naive-ui'\nimport { computed } from 'vue'\n\nconst imageGroupThemeOverrides = computed(() => {\n  const { popoverColor, boxShadow2, textColor2, borderRadius }\n    = useThemeVars().value\n  const themeOverrides: NonNullable<GlobalThemeOverrides['Image']> = {\n    toolbarColor: popoverColor,\n    toolbarBoxShadow: boxShadow2,\n    toolbarIconColor: textColor2,\n    toolbarBorderRadius: borderRadius\n  }\n  return themeOverrides\n})\n</script>\n\n<template>\n  <n-image-group :theme-overrides=\"imageGroupThemeOverrides\">\n    <n-space>\n      <n-image\n        width=\"100\"\n        src=\"https://07akioni.oss-cn-beijing.aliyuncs.com/07akioni.jpeg\"\n      />\n      <n-image\n        width=\"100\"\n        src=\"https://gw.alipayobjects.com/zos/antfincdn/aPkFc8Sj7n/method-draw-image.svg\"\n      />\n    </n-space>\n  </n-image-group>\n</template>\n"
  },
  {
    "path": "src/image/demos/zhCN/error.demo.vue",
    "content": "<markdown>\n# 加载失败\n\n使用 `fallback-src` 设定失败时的图像。或者你可以使用下一个例子里的 `error` slot。\n</markdown>\n\n<template>\n  <n-image\n    width=\"100\"\n    src=\"人生嘛，失败总是难免的\"\n    fallback-src=\"https://07akioni.oss-cn-beijing.aliyuncs.com/07akioni.jpeg\"\n  />\n</template>\n"
  },
  {
    "path": "src/image/demos/zhCN/full-debug.demo.vue",
    "content": "<markdown>\n# 原始尺寸展示图片 Debug\n</markdown>\n\n<template>\n  <n-image\n    width=\"100\"\n    src=\"https://tva1.sinaimg.cn/large/9448bbf8gy1h2mzox08tlj20g45xyh0q.jpg\"\n  />\n</template>\n"
  },
  {
    "path": "src/image/demos/zhCN/group.demo.vue",
    "content": "<markdown>\n# 成组使用\n</markdown>\n\n<template>\n  <n-image-group>\n    <n-space>\n      <n-image\n        width=\"100\"\n        src=\"https://07akioni.oss-cn-beijing.aliyuncs.com/07akioni.jpeg\"\n      />\n      <n-image\n        width=\"100\"\n        src=\"https://gw.alipayobjects.com/zos/antfincdn/aPkFc8Sj7n/method-draw-image.svg\"\n      />\n    </n-space>\n  </n-image-group>\n</template>\n"
  },
  {
    "path": "src/image/demos/zhCN/index.demo-entry.md",
    "content": "# 图像 Image\n\n预览一下。\n\n## 演示\n\n```demo\nbasic.vue\ngroup.vue\nerror.vue\ncustom-error.vue\npreview-disabled.vue\ncustom-toolbar.vue\ncustom.vue\ntooltip.vue\nfull-debug.vue\nlazy.vue\npreviewed-img-props.vue\nmanually-open-preview.vue\ncomponent-preview.vue\ncomponent-preview-group.vue\ncomponent-preview-group-debug.vue\n```\n\n## API\n\n### Image Props\n\n| 名称 | 类型 | 默认值 | 说明 | 版本 |\n| --- | --- | --- | --- | --- |\n| alt | `string` | `undefined` | 图片说明 |  |\n| fallback-src | `string` | `undefined` | 图片加载失败时显示的地址 |  |\n| height | `string \\| number` | `undefined` | 图片高度 |  |\n| img-props | `ImgHTMLAttributes` | `undefined` | 组件中 img 元素的属性 |  |\n| lazy | `boolean` | `false` | 是否让图片进入视口再加载，单独使用将设置为[HTMLImageElement.loading](https://developer.mozilla.org/en-US/docs/Web/API/HTMLImageElement/loading) 的属性值；也可配合 `intersection-observer-options` 配置实现懒加载 | 2.30.5 |\n| intersection-observer-options | `{ root?: Element \\| Document \\| string \\| null, rootMargin?: string, threshold?: number \\| number[]; }` | `undefined` | `lazy=true` 时 intersection observer 观测的配置 | 2.30.5 |\n| object-fit | `'fill' \\| 'contain' \\| 'cover' \\| 'none' \\| 'scale-down'` | `'fill'` | 图片在容器内的的适应类型 |  |\n| preview-src | `string` | `undefined` | 预览图片的图片地址 |  |\n| preview-disabled | `boolean` | `false` | 是否禁用单击图像预览 |  |\n| previewed-img-props | `HTMLAttributes` | `undefined` | 预览图片时 img 元素的属性 | 2.34.0 |\n| render-toolbar | `(props: { nodes: { prev: VNode, next: VNode, rotateCounterclockwise: VNode, rotateClockwise: VNode, resizeToOriginalSize: VNode, zoomOut: VNode, zoomIn: VNode, download: VNode, close: VNode } }) => VNodeChild` | `undefined` | 工具栏的渲染函数 | `2.38.2` |\n| show-toolbar | `boolean` | `true` | 图片放大后是否展示底部工具栏 |  |\n| show-toolbar-tooltip | `boolean` | `false` | 是否展示工具栏的提示 | 2.24.0 |\n| src | `string` | `undefined` | 图片来源 |  |\n| width | `string \\| number` | `undefined` | 图片宽度 |  |\n| on-error | `(e: Event) => void` | `undefined` | 图片加载失败执行的回调 |  |\n| on-load | `(e: Event) => void` | `undefined` | 图片加载完成执行的回调 |  |\n\n### ImageGroup Props\n\n| 名称 | 类型 | 默认值 | 说明 | 版本 |\n| --- | --- | --- | --- | --- |\n| current | `number` | `undefined` | 当前展示的图片的下标 | 2.43.0 |\n| default-current | `number` | `0` | 默认展示的图片的下标 | 2.43.0 |\n| default-show | `boolean` | `false` | 默认展示大图预览 | 2.43.0 |\n| render-toolbar | `(props: { nodes: { prev: VNode, next: VNode, rotateCounterclockwise: VNode, rotateClockwise: VNode, resizeToOriginalSize: VNode, zoomOut: VNode, zoomIn: VNode, download: VNode, close: VNode } }) => VNodeChild` | `undefined` | 工具栏的渲染函数 | `2.38.2` |\n| show | `boolean` | `undefined` | 是否展示大图预览 | 2.43.0 |\n| show-toolbar | `boolean` | `true` | 图片放大后是否展示底部工具栏 |  |\n| show-toolbar-tooltip | `boolean` | `false` | 是否展示工具栏的提示 | 2.24.0 |\n| src-list | `string[]` | `undefined` | 图片列表 | 2.43.0 |\n| on-preview-next | `() => void` | `undefined` | 点击下一张的回调 |  |\n| on-preview-prev | `() => void` | `undefined` | 点击上一张的回调 |  |\n| on-update:current | `(value: number) => void` | `undefined` | 显示状态改变的回调函数 | 2.43.0 |\n| on-update:show | `(value: boolean) => void` | `undefined` | 显示状态改变的回调函数 | 2.43.0 |\n\n### ImagePreview Props\n\n| 名称 | 类型 | 默认值 | 说明 | 版本 |\n| --- | --- | --- | --- | --- |\n| default-show | `boolean` | `false` | 默认展示大图预览 | 2.43.0 |\n| render-toolbar | `(props: { nodes: { prev: VNode, next: VNode, rotateCounterclockwise: VNode, rotateClockwise: VNode, resizeToOriginalSize: VNode, zoomOut: VNode, zoomIn: VNode, download: VNode, close: VNode } }) => VNodeChild` | `undefined` | 工具栏的渲染函数 | 2.43.0 |\n| show | `boolean` | `undefined` | 是否展示大图预览 | 2.43.0 |\n| show-toolbar | `boolean` | `true` | 图片放大后是否展示底部工具栏 | 2.43.0 |\n| show-toolbar-tooltip | `boolean` | `false` | 是否展示工具栏的提示 | 2.43.0 |\n| src | `string` | `undefined` | 图片地址 | 2.43.0 |\n| on-close | `() => void` | `undefined` | 关闭预览时的回调 | 2.43.0 |\n| on-update:show | `(value: boolean) => void` | `undefined` | 显示状态改变的回调函数 | 2.43.0 |\n\n### Image Slots\n\n| 名称        | 参数 | 说明                       | 版本   |\n| ----------- | ---- | -------------------------- | ------ |\n| error       | `()` | 图像加载失败时候的占位     | 2.40.2 |\n| placeholder | `()` | 图像没有加载成功时候的占位 | 2.30.5 |\n\n### ImageGroup Slots\n\n| 名称    | 参数 | 说明         |\n| ------- | ---- | ------------ |\n| default | `()` | 图像组的内容 |\n\n### Image Methods\n\n| 名称        | 类型         | 说明             | 版本   |\n| ----------- | ------------ | ---------------- | ------ |\n| showPreview | `() => void` | 手动打开大图预览 | 2.43.0 |\n"
  },
  {
    "path": "src/image/demos/zhCN/lazy.demo.vue",
    "content": "<markdown>\n# 懒加载\n\n让图片进入视口再加载，两种使用方式：一种是单独使用 `lazy` 属性，则将设置为原生 [HTMLImageElement.loading](https://developer.mozilla.org/zh-CN/docs/Web/API/HTMLImageElement/loading) 的属性值；\n另一种方式是配合 `intersection-observer-options` 配置，将采用 [IntersectionObserver](https://developer.mozilla.org/zh-CN/docs/Web/API/IntersectionObserver) API 实现懒加载。\n</markdown>\n\n<script lang=\"ts\" setup>\nconst srcList = [\n  'https://picsum.photos/id/1/100/100',\n  'https://picsum.photos/id/2/100/100',\n  'https://picsum.photos/id/3/100/100',\n  'https://picsum.photos/id/4/100/100',\n  'https://picsum.photos/id/5/100/100',\n  'https://picsum.photos/id/6/100/100',\n  'https://picsum.photos/id/7/100/100',\n  'https://picsum.photos/id/8/100/100',\n  'https://picsum.photos/id/9/100/100',\n  'https://picsum.photos/id/10/100/100'\n]\n</script>\n\n<template>\n  <n-p>\n    单独设置 <n-text code>\n      lazy\n    </n-text> 属性\n  </n-p>\n  <n-image\n    lazy\n    width=\"100\"\n    src=\"https://07akioni.oss-cn-beijing.aliyuncs.com/07akioni.jpeg\"\n  />\n  <n-p>\n    <n-text code>\n      lazy\n    </n-text> 属性配合\n    <n-text code>\n      intersection-observer-options\n    </n-text>\n  </n-p>\n  <div\n    id=\"image-scroll-container\"\n    style=\"\n      overflow: auto;\n      height: 100px;\n      display: flex;\n      flex-direction: column;\n      gap: 8px;\n    \"\n  >\n    <n-image\n      v-for=\"(src, index) in srcList\"\n      :key=\"index\"\n      width=\"100\"\n      height=\"100\"\n      lazy\n      :src=\"src\"\n      :intersection-observer-options=\"{\n        root: '#image-scroll-container',\n      }\"\n    >\n      <template #placeholder>\n        <div\n          style=\"\n            width: 100px;\n            height: 100px;\n            display: flex;\n            align-items: center;\n            justify-content: center;\n            background-color: #0001;\n          \"\n        >\n          Loading\n        </div>\n      </template>\n    </n-image>\n  </div>\n</template>\n"
  },
  {
    "path": "src/image/demos/zhCN/manually-open-preview.demo.vue",
    "content": "<markdown>\n# 手动打开预览\n\n通过调用 `showPreview` 来触发大图预览。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { ImageInst } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst imageRef = ref<ImageInst>()\nfunction handleClick() {\n  imageRef.value?.showPreview()\n}\n</script>\n\n<template>\n  <n-space vertical>\n    <n-button type=\"primary\" @click=\"handleClick\">\n      展示图片预览\n    </n-button>\n    <n-image\n      ref=\"imageRef\"\n      width=\"100\"\n      src=\"https://07akioni.oss-cn-beijing.aliyuncs.com/07akioni.jpeg\"\n    />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/image/demos/zhCN/preview-disabled.demo.vue",
    "content": "<markdown>\n# 禁止预览\n\n你可以使用 `preview-disabled` 来禁止预览。\n</markdown>\n\n<template>\n  <n-image\n    width=\"100\"\n    src=\"https://07akioni.oss-cn-beijing.aliyuncs.com/07akioni.jpeg\"\n    preview-disabled\n  />\n</template>\n"
  },
  {
    "path": "src/image/demos/zhCN/previewed-img-props.demo.vue",
    "content": "<markdown>\n# 预览时的属性\n\n可以通过 `previewed-img-props` 设定预览时图像的属性。\n</markdown>\n\n<template>\n  <n-image\n    width=\"100\"\n    src=\"https://07akioni.oss-cn-beijing.aliyuncs.com/07akioni.jpeg\"\n    :previewed-img-props=\"{ style: { border: '8px solid white' } }\"\n  />\n</template>\n"
  },
  {
    "path": "src/image/demos/zhCN/tooltip.demo.vue",
    "content": "<markdown>\n# 工具栏的弹出提示\n\n设定 `show-toolbar-tooltip` 来使用弹出提示。因为有的用户不知道如何进行键盘操作。\n</markdown>\n\n<template>\n  <n-image-group show-toolbar-tooltip>\n    <n-space>\n      <n-image\n        width=\"100\"\n        src=\"https://07akioni.oss-cn-beijing.aliyuncs.com/07akioni.jpeg\"\n      />\n      <n-image\n        width=\"100\"\n        src=\"https://gw.alipayobjects.com/zos/antfincdn/aPkFc8Sj7n/method-draw-image.svg\"\n      />\n    </n-space>\n  </n-image-group>\n</template>\n"
  },
  {
    "path": "src/image/index.ts",
    "content": "export { imageProps, default as NImage } from './src/Image'\nexport type { ImageProps } from './src/Image'\nexport { imageGroupProps, default as NImageGroup } from './src/ImageGroup'\nexport type { ImageGroupProps } from './src/ImageGroup'\nexport { imagePreviewProps, default as NImagePreview } from './src/ImagePreview'\nexport type { ImagePreviewProps } from './src/ImagePreview'\nexport type * from './src/public-types'\n"
  },
  {
    "path": "src/image/src/Image.tsx",
    "content": "import type { ImgHTMLAttributes, PropType, SlotsType } from 'vue'\nimport type { ExtractPublicPropTypes } from '../../_utils'\nimport type { ImageInst, ImagePreviewInst, ImageSlots } from './public-types'\nimport type { IntersectionObserverOptions } from './utils'\nimport {\n  computed,\n  defineComponent,\n  h,\n  inject,\n  onBeforeUnmount,\n  onMounted,\n  provide,\n  ref,\n  toRef,\n  watchEffect\n} from 'vue'\nimport { useConfig } from '../../_mixins'\nimport { resolveSlot } from '../../_utils'\nimport { isImageSupportNativeLazy } from '../../_utils/env/is-native-lazy-load'\nimport { imageGroupInjectionKey } from './ImageGroup'\nimport NImagePreview from './ImagePreview'\nimport { imageContextKey, imagePreviewSharedProps } from './interface'\nimport { observeIntersection } from './utils'\n\nexport const imageProps = {\n  alt: String,\n  height: [String, Number] as PropType<string | number>,\n  imgProps: Object as PropType<ImgHTMLAttributes>,\n  previewedImgProps: Object as PropType<ImgHTMLAttributes>,\n  lazy: Boolean,\n  intersectionObserverOptions: Object as PropType<IntersectionObserverOptions>,\n  objectFit: {\n    type: String as PropType<\n      'fill' | 'contain' | 'cover' | 'none' | 'scale-down'\n    >,\n    default: 'fill'\n  },\n  previewSrc: String,\n  fallbackSrc: String,\n  width: [String, Number] as PropType<string | number>,\n  src: String,\n  previewDisabled: Boolean,\n  loadDescription: String,\n  onError: Function as PropType<(e: Event) => void>,\n  onLoad: Function as PropType<(e: Event) => void>,\n  ...imagePreviewSharedProps\n}\n\nexport type ImageProps = ExtractPublicPropTypes<typeof imageProps>\n\nlet uuid = 0\n\nexport default defineComponent({\n  name: 'Image',\n  props: imageProps,\n  slots: Object as SlotsType<ImageSlots>,\n  inheritAttrs: false,\n  setup(props) {\n    const imageRef = ref<HTMLImageElement | null>(null)\n    const showErrorRef = ref(false)\n    const previewInstRef = ref<ImagePreviewInst | null>(null)\n    const imageGroupHandle = inject(imageGroupInjectionKey, null)\n    const { mergedClsPrefixRef } = imageGroupHandle || useConfig(props)\n\n    const mergedPreviewSrcRef = computed(() => {\n      return props.previewSrc || props.src\n    })\n\n    const previewShowRef = ref(false)\n\n    const imageId = uuid++\n\n    const showPreview = () => {\n      if (props.previewDisabled || showErrorRef.value)\n        return\n      if (imageGroupHandle) {\n        imageGroupHandle.setThumbnailEl(imageRef.value)\n        imageGroupHandle.toggleShow(`r${imageId}`)\n        return\n      }\n      const { value: previewInst } = previewInstRef\n      if (!previewInst)\n        return\n      previewInst.setThumbnailEl(imageRef.value)\n      previewShowRef.value = true\n    }\n\n    const exposedMethods: ImageInst = {\n      click: () => {\n        showPreview()\n      },\n      showPreview\n    }\n\n    const shouldStartLoadingRef = ref(!props.lazy)\n\n    onMounted(() => {\n      imageRef.value?.setAttribute(\n        'data-group-id',\n        imageGroupHandle?.groupId || ''\n      )\n    })\n\n    onMounted(() => {\n      // Use IntersectionObserver if lazy and intersectionObserverOptions is set\n      if (props.lazy && props.intersectionObserverOptions) {\n        let unobserve: (() => void) | undefined\n        const stopWatchHandle = watchEffect(() => {\n          unobserve?.()\n          unobserve = undefined\n          unobserve = observeIntersection(\n            imageRef.value,\n            props.intersectionObserverOptions,\n            shouldStartLoadingRef\n          )\n        })\n        onBeforeUnmount(() => {\n          stopWatchHandle()\n          unobserve?.()\n        })\n      }\n    })\n\n    watchEffect(() => {\n      void (props.src || props.imgProps?.src)\n      showErrorRef.value = false\n    })\n\n    watchEffect((onInvalidate) => {\n      const unregister = imageGroupHandle?.registerImageUrl?.(\n        imageId,\n        mergedPreviewSrcRef.value || ''\n      )\n      onInvalidate(() => {\n        unregister?.()\n      })\n    })\n\n    function onImgClick(e: PointerEvent) {\n      exposedMethods.showPreview()\n      props.imgProps?.onClick?.(e)\n    }\n\n    function onPreviewClose() {\n      previewShowRef.value = false\n    }\n\n    const loadedRef = ref(false)\n\n    provide(imageContextKey, {\n      previewedImgPropsRef: toRef(props, 'previewedImgProps')\n    })\n    return {\n      mergedClsPrefix: mergedClsPrefixRef,\n      groupId: imageGroupHandle?.groupId,\n      previewInstRef,\n      imageRef,\n      mergedPreviewSrc: mergedPreviewSrcRef,\n      showError: showErrorRef,\n      shouldStartLoading: shouldStartLoadingRef,\n      loaded: loadedRef,\n      mergedOnClick: (e: PointerEvent) => {\n        onImgClick(e)\n      },\n      onPreviewClose,\n      mergedOnError: (e: Event) => {\n        if (!shouldStartLoadingRef.value)\n          return\n        showErrorRef.value = true\n        const { onError, imgProps: { onError: imgPropsOnError } = {} } = props\n        onError?.(e)\n        imgPropsOnError?.(e)\n      },\n      mergedOnLoad: (e: Event) => {\n        const { onLoad, imgProps: { onLoad: imgPropsOnLoad } = {} } = props\n        onLoad?.(e)\n        imgPropsOnLoad?.(e)\n        loadedRef.value = true\n      },\n      previewShow: previewShowRef,\n      ...exposedMethods\n    }\n  },\n  render() {\n    const { mergedClsPrefix, imgProps = {}, loaded, $attrs, lazy } = this\n    const errorNode = resolveSlot(this.$slots.error, () => [])\n    const placeholderNode = this.$slots.placeholder?.()\n    const loadSrc = this.src || imgProps.src\n\n    const imgNode\n      = this.showError && errorNode.length\n        ? errorNode\n        : h('img', {\n            ...imgProps,\n            ref: 'imageRef',\n            width: this.width || imgProps.width,\n            height: this.height || imgProps.height,\n            src: this.showError\n              ? this.fallbackSrc\n              : lazy && this.intersectionObserverOptions\n                ? this.shouldStartLoading\n                  ? loadSrc\n                  : undefined\n                : loadSrc,\n            alt: this.alt || imgProps.alt,\n            'aria-label': this.alt || imgProps.alt,\n            onClick: this.mergedOnClick,\n            onError: this.mergedOnError,\n            onLoad: this.mergedOnLoad,\n            // If interseciton observer options is set, do not use native lazy\n            loading:\n              isImageSupportNativeLazy\n              && lazy\n              && !this.intersectionObserverOptions\n                ? 'lazy'\n                : 'eager',\n            style: [\n              imgProps.style || '',\n              placeholderNode && !loaded\n                ? { height: '0', width: '0', visibility: 'hidden' }\n                : '',\n              { objectFit: this.objectFit }\n            ],\n            'data-error': this.showError,\n            'data-preview-src': this.previewSrc || this.src\n          })\n    return (\n      <div\n        {...$attrs}\n        role=\"none\"\n        class={[\n          $attrs.class,\n          `${mergedClsPrefix}-image`,\n          (this.previewDisabled || this.showError)\n          && `${mergedClsPrefix}-image--preview-disabled`\n        ]}\n      >\n        {this.groupId ? (\n          imgNode\n        ) : (\n          <NImagePreview\n            theme={this.theme}\n            themeOverrides={this.themeOverrides}\n            ref=\"previewInstRef\"\n            showToolbar={this.showToolbar}\n            showToolbarTooltip={this.showToolbarTooltip}\n            renderToolbar={this.renderToolbar}\n            src={this.mergedPreviewSrc}\n            show={!this.previewDisabled && this.previewShow}\n            onClose={this.onPreviewClose}\n          >\n            {{\n              default: () => imgNode\n            }}\n          </NImagePreview>\n        )}\n        {!loaded && placeholderNode}\n      </div>\n    )\n  }\n})\n"
  },
  {
    "path": "src/image/src/ImageGroup.tsx",
    "content": "import type { PropType, Ref } from 'vue'\nimport type { ExtractPublicPropTypes, MaybeArray } from '../../_utils'\nimport type { ImagePreviewInst, ImageRenderToolbar } from './public-types'\nimport { createId } from 'seemly'\nimport { useMergedState } from 'vooks'\nimport { computed, defineComponent, h, provide, ref, toRef } from 'vue'\nimport { useConfig } from '../../_mixins'\nimport { call, createInjectionKey, throwError } from '../../_utils'\n\nimport NImagePreview from './ImagePreview'\nimport { imagePreviewSharedProps } from './interface'\n\nexport const imageGroupInjectionKey = createInjectionKey<\n  ImagePreviewInst & {\n    groupId: string\n    mergedClsPrefixRef: Ref<string>\n    renderToolbarRef: Ref<ImageRenderToolbar | undefined>\n    registerImageUrl: (id: number, url: string) => () => void\n    toggleShow: (imageId: string) => void\n  }\n>('n-image-group')\n\nexport const imageGroupProps = {\n  ...imagePreviewSharedProps,\n  srcList: Array as PropType<string[]>,\n  current: Number,\n  defaultCurrent: {\n    type: Number,\n    default: 0\n  },\n  show: {\n    type: Boolean,\n    default: undefined\n  },\n  defaultShow: Boolean,\n  onUpdateShow: [Function, Array] as PropType<\n    MaybeArray<(show: boolean) => void>\n  >,\n  'onUpdate:show': [Function, Array] as PropType<\n    MaybeArray<(show: boolean) => void>\n  >,\n  onUpdateCurrent: [Function, Array] as PropType<\n    MaybeArray<(current: number) => void>\n  >,\n  'onUpdate:current': [Function, Array] as PropType<\n    MaybeArray<(current: number) => void>\n  >\n}\n\nexport type ImageGroupProps = ExtractPublicPropTypes<typeof imageGroupProps>\n\nexport default defineComponent({\n  name: 'ImageGroup',\n  props: imageGroupProps,\n  setup(props) {\n    const { mergedClsPrefixRef } = useConfig(props)\n    const groupId = `c${createId()}`\n    const previewInstRef = ref<ImagePreviewInst | null>(null)\n\n    const uncontrolledShowRef = ref(props.defaultShow)\n    const controlledShowRef = toRef(props, 'show')\n    const mergedShowRef = useMergedState(controlledShowRef, uncontrolledShowRef)\n\n    const registeredImageUrlMap = ref(new Map<string, string>())\n\n    const mergedImageUrlMap = computed(() => {\n      if (props.srcList) {\n        const map: Map<string, string> = new Map()\n        props.srcList.forEach((url, index) => {\n          map.set(`p${index}`, url)\n        })\n        return map\n      }\n      return registeredImageUrlMap.value\n    })\n\n    const imageIdListRef = computed(() =>\n      Array.from(mergedImageUrlMap.value.keys())\n    )\n\n    const imageCountGetter = () => imageIdListRef.value.length\n\n    function registerImageUrl(id: number, url: string) {\n      if (props.srcList) {\n        throwError(\n          'image-group',\n          '`n-image` can\\'t be placed inside `n-image-group` when image group\\'s `src-list` prop is set.'\n        )\n      }\n\n      const sid = `r${id}`\n      if (!registeredImageUrlMap.value.has(`r${sid}`)) {\n        registeredImageUrlMap.value.set(sid, url)\n      }\n\n      return function unregisterPreviewUrl() {\n        if (!registeredImageUrlMap.value.has(sid)) {\n          registeredImageUrlMap.value.delete(sid)\n        }\n      }\n    }\n\n    const uncontrolledCurrentRef = ref(props.defaultCurrent)\n    const controlledCurrentRef = toRef(props, 'current')\n    const mergedCurrentRef = useMergedState(\n      controlledCurrentRef,\n      uncontrolledCurrentRef\n    )\n\n    const setCurrentIndex = (index: number) => {\n      if (index !== mergedCurrentRef.value) {\n        const { onUpdateCurrent, 'onUpdate:current': _onUpdateCurrent } = props\n        if (onUpdateCurrent) {\n          call(onUpdateCurrent, index)\n        }\n        if (_onUpdateCurrent) {\n          call(_onUpdateCurrent, index)\n        }\n        uncontrolledCurrentRef.value = index\n      }\n    }\n\n    const currentId = computed(\n      () => imageIdListRef.value[mergedCurrentRef.value]\n    )\n    const setCurrentId = (nextId: string) => {\n      const nextIndex = imageIdListRef.value.indexOf(nextId)\n      if (nextIndex !== mergedCurrentRef.value) {\n        setCurrentIndex(nextIndex)\n      }\n    }\n\n    const currentUrl = computed(() =>\n      mergedImageUrlMap.value.get(currentId.value)\n    )\n\n    function doUpdateShow(value: boolean): void {\n      const { onUpdateShow, 'onUpdate:show': _onUpdateShow } = props\n      if (onUpdateShow) {\n        call(onUpdateShow, value)\n      }\n      if (_onUpdateShow) {\n        call(_onUpdateShow, value)\n      }\n      uncontrolledShowRef.value = value\n    }\n\n    function onClose() {\n      doUpdateShow(false)\n    }\n\n    const nextIndex = computed(() => {\n      const findNext = (start: number, end: number) => {\n        for (let i = start; i <= end; i++) {\n          const id = imageIdListRef.value[i]\n          if (mergedImageUrlMap.value.get(id)) {\n            return i\n          }\n        }\n        return undefined\n      }\n\n      const next = findNext(mergedCurrentRef.value + 1, imageCountGetter() - 1)\n      return next === undefined ? findNext(0, mergedCurrentRef.value - 1) : next\n    })\n\n    const prevIndex = computed(() => {\n      const findPrev = (start: number, end: number) => {\n        for (let i = start; i >= end; i--) {\n          const id = imageIdListRef.value[i]\n          if (mergedImageUrlMap.value.get(id)) {\n            return i\n          }\n        }\n        return undefined\n      }\n\n      const prev = findPrev(mergedCurrentRef.value - 1, 0)\n      return prev === undefined\n        ? findPrev(imageCountGetter() - 1, mergedCurrentRef.value + 1)\n        : prev\n    })\n\n    function go(step: 1 | -1): void {\n      if (step === 1) {\n        prevIndex.value !== undefined && setCurrentIndex(nextIndex.value!)\n        props.onPreviewNext?.()\n      }\n      else {\n        nextIndex.value !== undefined && setCurrentIndex(prevIndex.value!)\n        props.onPreviewPrev?.()\n      }\n    }\n    provide(imageGroupInjectionKey, {\n      mergedClsPrefixRef,\n      registerImageUrl,\n      setThumbnailEl: (el) => {\n        previewInstRef.value?.setThumbnailEl(el)\n      },\n      toggleShow: (imageId: string) => {\n        doUpdateShow(true)\n        setCurrentId(imageId)\n      },\n      groupId,\n      renderToolbarRef: toRef(props, 'renderToolbar')\n    })\n\n    return {\n      mergedClsPrefix: mergedClsPrefixRef,\n      previewInstRef,\n      mergedShow: mergedShowRef,\n      src: currentUrl,\n      onClose,\n      next: () => {\n        go(1)\n      },\n      prev: () => {\n        go(-1)\n      }\n    }\n  },\n  render() {\n    return (\n      <NImagePreview\n        theme={this.theme}\n        themeOverrides={this.themeOverrides}\n        ref=\"previewInstRef\"\n        onPrev={this.prev}\n        onNext={this.next}\n        src={this.src}\n        show={this.mergedShow}\n        showToolbar={this.showToolbar}\n        showToolbarTooltip={this.showToolbarTooltip}\n        renderToolbar={this.renderToolbar}\n        onClose={this.onClose}\n      >\n        {this.$slots}\n      </NImagePreview>\n    )\n  }\n})\n"
  },
  {
    "path": "src/image/src/ImagePreview.tsx",
    "content": "import type { CSSProperties, PropType, VNode } from 'vue'\nimport type { ExtractPublicPropTypes, MaybeArray } from '../../_utils'\nimport type { MoveStrategy } from './interface'\nimport type { ImagePreviewInst } from './public-types'\nimport { off, on } from 'evtd'\nimport { kebabCase } from 'lodash-es'\nimport { beforeNextFrameOnce } from 'seemly'\nimport { zindexable } from 'vdirs'\nimport { useIsMounted, useMergedState } from 'vooks'\nimport {\n  computed,\n  defineComponent,\n  Fragment,\n  h,\n  inject,\n  normalizeStyle,\n  onBeforeUnmount,\n  ref,\n  toRef,\n  toRefs,\n  Transition,\n  vShow,\n  watch,\n  withDirectives\n} from 'vue'\nimport { LazyTeleport } from 'vueuc'\nimport { NBaseIcon } from '../../_internal'\nimport {\n  DownloadIcon,\n  ResizeSmallIcon,\n  RotateClockwiseIcon,\n  RotateCounterclockwiseIcon,\n  ZoomInIcon,\n  ZoomOutIcon\n} from '../../_internal/icons'\nimport { useConfig, useLocale, useTheme, useThemeClass } from '../../_mixins'\nimport { call, download } from '../../_utils'\nimport { NTooltip } from '../../tooltip'\nimport { imageLight } from '../styles'\nimport { renderCloseIcon, renderNextIcon, renderPrevIcon } from './icons'\nimport { imageContextKey, imagePreviewSharedProps } from './interface'\nimport style from './styles/index.cssr'\n\nconst BLEEDING = 32\n\nexport const imagePreviewProps = {\n  ...imagePreviewSharedProps,\n  src: String,\n  show: {\n    type: Boolean,\n    default: undefined\n  },\n  defaultShow: Boolean,\n  'onUpdate:show': [Function, Array] as PropType<\n    MaybeArray<(show: boolean) => void>\n  >,\n  onUpdateShow: [Function, Array] as PropType<\n    MaybeArray<(show: boolean) => void>\n  >,\n  onNext: Function as PropType<() => void>,\n  onPrev: Function as PropType<() => void>,\n  onClose: [Function, Array] as PropType<MaybeArray<() => void>>\n}\n\nexport type ImagePreviewProps = ExtractPublicPropTypes<typeof imagePreviewProps>\n\nexport default defineComponent({\n  name: 'ImagePreview',\n  props: imagePreviewProps,\n  setup(props) {\n    const { src } = toRefs(props)\n\n    const { mergedClsPrefixRef } = useConfig(props)\n    const themeRef = useTheme(\n      'Image',\n      '-image',\n      style,\n      imageLight,\n      props,\n      mergedClsPrefixRef\n    )\n    let thumbnailEl: HTMLImageElement | null = null\n    const previewRef = ref<HTMLImageElement | null>(null)\n    const previewWrapperRef = ref<HTMLDivElement | null>(null)\n\n    const displayedRef = ref(false)\n    const { localeRef } = useLocale('Image')\n\n    const uncontrolledShowRef = ref(props.defaultShow)\n    const controlledShowRef = toRef(props, 'show')\n    const mergedShowRef = useMergedState(controlledShowRef, uncontrolledShowRef)\n\n    function syncTransformOrigin(): void {\n      const { value: previewWrapper } = previewWrapperRef\n      if (!thumbnailEl || !previewWrapper)\n        return\n      const { style } = previewWrapper\n      const tbox = thumbnailEl.getBoundingClientRect()\n      const tx = tbox.left + tbox.width / 2\n      const ty = tbox.top + tbox.height / 2\n\n      style.transformOrigin = `${tx}px ${ty}px`\n    }\n\n    function handleKeydown(e: KeyboardEvent): void {\n      switch (e.key) {\n        case ' ':\n          e.preventDefault()\n          break\n        case 'ArrowLeft':\n          props.onPrev?.()\n          break\n        case 'ArrowRight':\n          props.onNext?.()\n          break\n        case 'ArrowUp':\n          e.preventDefault()\n          zoomIn()\n          break\n        case 'ArrowDown':\n          e.preventDefault()\n          zoomOut()\n          break\n        case 'Escape':\n          close()\n          break\n      }\n    }\n\n    function doUpdateShow(value: boolean): void {\n      const { onUpdateShow, 'onUpdate:show': _onUpdateShow } = props\n      if (onUpdateShow) {\n        call(onUpdateShow, value)\n      }\n      if (_onUpdateShow) {\n        call(_onUpdateShow, value)\n      }\n      uncontrolledShowRef.value = value\n      displayedRef.value = true\n    }\n\n    watch(mergedShowRef, (value) => {\n      if (value) {\n        on('keydown', document, handleKeydown)\n      }\n      else {\n        off('keydown', document, handleKeydown)\n      }\n    })\n\n    onBeforeUnmount(() => {\n      off('keydown', document, handleKeydown)\n    })\n\n    let startX = 0\n    let startY = 0\n    let offsetX = 0\n    let offsetY = 0\n    let startOffsetX = 0\n    let startOffsetY = 0\n    let mouseDownClientX = 0\n    let mouseDownClientY = 0\n\n    let dragging = false\n\n    function handleMouseMove(e: MouseEvent): void {\n      const { clientX, clientY } = e\n      offsetX = clientX - startX\n      offsetY = clientY - startY\n      beforeNextFrameOnce(derivePreviewStyle)\n    }\n\n    function getMoveStrategy(opts: {\n      mouseUpClientX: number\n      mouseUpClientY: number\n      mouseDownClientX: number\n      mouseDownClientY: number\n    }): MoveStrategy {\n      const {\n        mouseUpClientX,\n        mouseUpClientY,\n        mouseDownClientX,\n        mouseDownClientY\n      } = opts\n      const deltaHorizontal = mouseDownClientX - mouseUpClientX\n      const deltaVertical = mouseDownClientY - mouseUpClientY\n      const moveVerticalDirection: 'verticalTop' | 'verticalBottom'\n        = `vertical${deltaVertical > 0 ? 'Top' : 'Bottom'}`\n      const moveHorizontalDirection: 'horizontalLeft' | 'horizontalRight'\n        = `horizontal${deltaHorizontal > 0 ? 'Left' : 'Right'}`\n\n      return {\n        moveVerticalDirection,\n        moveHorizontalDirection,\n        deltaHorizontal,\n        deltaVertical\n      }\n    }\n\n    // avoid image move outside viewport\n    function getDerivedOffset(moveStrategy?: MoveStrategy): {\n      offsetX: number\n      offsetY: number\n    } {\n      const { value: preview } = previewRef\n      if (!preview)\n        return { offsetX: 0, offsetY: 0 }\n      const pbox = preview.getBoundingClientRect()\n      const {\n        moveVerticalDirection,\n        moveHorizontalDirection,\n        deltaHorizontal,\n        deltaVertical\n      } = moveStrategy || {}\n\n      let nextOffsetX = 0\n      let nextOffsetY = 0\n      if (pbox.width <= window.innerWidth) {\n        nextOffsetX = 0\n      }\n      else if (pbox.left > 0) {\n        nextOffsetX = (pbox.width - window.innerWidth) / 2\n      }\n      else if (pbox.right < window.innerWidth) {\n        nextOffsetX = -(pbox.width - window.innerWidth) / 2\n      }\n      else if (moveHorizontalDirection === 'horizontalRight') {\n        nextOffsetX = Math.min(\n          (pbox.width - window.innerWidth) / 2,\n          startOffsetX - (deltaHorizontal ?? 0)\n        )\n      }\n      else {\n        nextOffsetX = Math.max(\n          -((pbox.width - window.innerWidth) / 2),\n          startOffsetX - (deltaHorizontal ?? 0)\n        )\n      }\n\n      if (pbox.height <= window.innerHeight) {\n        nextOffsetY = 0\n      }\n      else if (pbox.top > 0) {\n        nextOffsetY = (pbox.height - window.innerHeight) / 2\n      }\n      else if (pbox.bottom < window.innerHeight) {\n        nextOffsetY = -(pbox.height - window.innerHeight) / 2\n      }\n      else if (moveVerticalDirection === 'verticalBottom') {\n        nextOffsetY = Math.min(\n          (pbox.height - window.innerHeight) / 2,\n          startOffsetY - (deltaVertical ?? 0)\n        )\n      }\n      else {\n        nextOffsetY = Math.max(\n          -((pbox.height - window.innerHeight) / 2),\n          startOffsetY - (deltaVertical ?? 0)\n        )\n      }\n\n      return {\n        offsetX: nextOffsetX,\n        offsetY: nextOffsetY\n      }\n    }\n    function handleMouseUp(e: MouseEvent): void {\n      off('mousemove', document, handleMouseMove)\n      off('mouseup', document, handleMouseUp)\n      const { clientX: mouseUpClientX, clientY: mouseUpClientY } = e\n      dragging = false\n      const moveStrategy = getMoveStrategy({\n        mouseUpClientX,\n        mouseUpClientY,\n        mouseDownClientX,\n        mouseDownClientY\n      })\n      const offset = getDerivedOffset(moveStrategy)\n      offsetX = offset.offsetX\n      offsetY = offset.offsetY\n      derivePreviewStyle()\n    }\n    const imageContext = inject(imageContextKey, null)\n\n    function handlePreviewMousedown(e: MouseEvent): void {\n      imageContext?.previewedImgPropsRef.value?.onMousedown?.(e)\n      if (e.button !== 0)\n        return\n\n      const { clientX, clientY } = e\n      dragging = true\n      startX = clientX - offsetX\n      startY = clientY - offsetY\n      startOffsetX = offsetX\n      startOffsetY = offsetY\n\n      mouseDownClientX = clientX\n      mouseDownClientY = clientY\n\n      derivePreviewStyle()\n      on('mousemove', document, handleMouseMove)\n      on('mouseup', document, handleMouseUp)\n    }\n\n    const scaleRadix = 1.5\n    let scaleExp = 0\n    let scale = 1\n    let rotate = 0\n    function handlePreviewDblclick(e: MouseEvent): void {\n      imageContext?.previewedImgPropsRef.value?.onDblclick?.(e)\n      const originalImageSizeScale = getOrignalImageSizeScale()\n      scale = scale === originalImageSizeScale ? 1 : originalImageSizeScale\n      derivePreviewStyle()\n    }\n    function resetScale(): void {\n      scale = 1\n      scaleExp = 0\n    }\n    function handleSwitchPrev(): void {\n      resetScale()\n      rotate = 0\n      props.onPrev?.()\n    }\n    function handleSwitchNext(): void {\n      resetScale()\n      rotate = 0\n      props.onNext?.()\n    }\n    function rotateCounterclockwise(): void {\n      rotate -= 90\n      derivePreviewStyle()\n    }\n    function rotateClockwise(): void {\n      rotate += 90\n      derivePreviewStyle()\n    }\n    function getMaxScale(): number {\n      const { value: preview } = previewRef\n      if (!preview)\n        return 1\n      const { innerWidth, innerHeight } = window\n      const heightMaxScale = Math.max(\n        1,\n        preview.naturalHeight / (innerHeight - BLEEDING)\n      )\n      const widthMaxScale = Math.max(\n        1,\n        preview.naturalWidth / (innerWidth - BLEEDING)\n      )\n      return Math.max(3, heightMaxScale * 2, widthMaxScale * 2)\n    }\n    function getOrignalImageSizeScale(): number {\n      const { value: preview } = previewRef\n      if (!preview)\n        return 1\n      const { innerWidth, innerHeight } = window\n      const heightScale = preview.naturalHeight / (innerHeight - BLEEDING)\n      const widthScale = preview.naturalWidth / (innerWidth - BLEEDING)\n      if (heightScale < 1 && widthScale < 1) {\n        return 1\n      }\n      return Math.max(heightScale, widthScale)\n    }\n\n    function zoomIn(): void {\n      const maxScale = getMaxScale()\n      if (scale < maxScale) {\n        scaleExp += 1\n        scale = Math.min(maxScale, scaleRadix ** scaleExp)\n        derivePreviewStyle()\n      }\n    }\n    function zoomOut(): void {\n      if (scale > 0.5) {\n        const originalScale = scale\n        scaleExp -= 1\n        scale = Math.max(0.5, scaleRadix ** scaleExp)\n        const diff = originalScale - scale\n        derivePreviewStyle(false)\n        const offset = getDerivedOffset()\n        scale += diff\n        derivePreviewStyle(false)\n        scale -= diff\n        offsetX = offset.offsetX\n        offsetY = offset.offsetY\n        derivePreviewStyle()\n      }\n    }\n\n    function handleDownloadClick(): void {\n      const imgSrc = src.value\n      if (imgSrc) {\n        download(imgSrc, undefined)\n      }\n    }\n\n    function derivePreviewStyle(transition: boolean = true): void {\n      const { value: preview } = previewRef\n      if (!preview)\n        return\n      const { style } = preview\n      const controlledStyle = normalizeStyle(\n        imageContext?.previewedImgPropsRef.value?.style\n      )\n      let controlledStyleString = ''\n      if (typeof controlledStyle === 'string') {\n        controlledStyleString = `${controlledStyle};`\n      }\n      else {\n        for (const key in controlledStyle) {\n          controlledStyleString += `${kebabCase(key)}: ${controlledStyle[key]};`\n        }\n      }\n      const transformStyle = `transform-origin: center; transform: translateX(${offsetX}px) translateY(${offsetY}px) rotate(${rotate}deg) scale(${scale});`\n      if (dragging) {\n        style.cssText = `${\n          controlledStyleString\n        }cursor: grabbing; transition: none;${transformStyle}`\n      }\n      else {\n        style.cssText = `${controlledStyleString}cursor: grab;${\n          transformStyle\n        }${transition ? '' : 'transition: none;'}`\n      }\n      if (!transition) {\n        void preview.offsetHeight\n      }\n    }\n\n    function close() {\n      if (mergedShowRef.value) {\n        const { onClose } = props\n        if (onClose)\n          call(onClose)\n        doUpdateShow(false)\n        uncontrolledShowRef.value = false\n      }\n    }\n\n    function resizeToOrignalImageSize(): void {\n      scale = getOrignalImageSizeScale()\n      scaleExp = Math.ceil(Math.log(scale) / Math.log(scaleRadix))\n      offsetX = 0\n      offsetY = 0\n      derivePreviewStyle()\n    }\n    const exposedMethods: ImagePreviewInst = {\n      setThumbnailEl: (el) => {\n        thumbnailEl = el\n      }\n    }\n\n    function withTooltip(\n      node: VNode,\n      tooltipKey: keyof typeof localeRef.value\n    ): VNode {\n      if (props.showToolbarTooltip) {\n        const { value: theme } = themeRef\n        return (\n          <NTooltip\n            to={false}\n            theme={theme.peers.Tooltip}\n            themeOverrides={theme.peerOverrides.Tooltip}\n            keepAliveOnHover={false}\n          >\n            {{\n              default: () => {\n                return localeRef.value[tooltipKey]\n              },\n              trigger: () => node\n            }}\n          </NTooltip>\n        )\n      }\n      else {\n        return node\n      }\n    }\n\n    const cssVarsRef = computed(() => {\n      const {\n        common: { cubicBezierEaseInOut },\n        self: {\n          toolbarIconColor,\n          toolbarBorderRadius,\n          toolbarBoxShadow,\n          toolbarColor\n        }\n      } = themeRef.value\n      return {\n        '--n-bezier': cubicBezierEaseInOut,\n        '--n-toolbar-icon-color': toolbarIconColor,\n        '--n-toolbar-color': toolbarColor,\n        '--n-toolbar-border-radius': toolbarBorderRadius,\n        '--n-toolbar-box-shadow': toolbarBoxShadow\n      }\n    })\n\n    const { inlineThemeDisabled } = useConfig()\n\n    const themeClassHandle = inlineThemeDisabled\n      ? useThemeClass('image-preview', undefined, cssVarsRef, props)\n      : undefined\n\n    function handleWheel(event: WheelEvent) {\n      event.preventDefault()\n    }\n\n    return {\n      clsPrefix: mergedClsPrefixRef,\n      previewRef,\n      previewWrapperRef,\n      previewSrc: src,\n      mergedShow: mergedShowRef,\n      appear: useIsMounted(),\n      displayed: displayedRef,\n      previewedImgProps: imageContext?.previewedImgPropsRef,\n      handleWheel,\n      handlePreviewMousedown,\n      handlePreviewDblclick,\n      syncTransformOrigin,\n      handleAfterLeave: () => {\n        resetScale()\n        rotate = 0\n        displayedRef.value = false\n      },\n      handleDragStart: (e: DragEvent) => {\n        imageContext?.previewedImgPropsRef.value?.onDragstart?.(e)\n        e.preventDefault()\n      },\n      zoomIn,\n      zoomOut,\n      handleDownloadClick,\n      rotateCounterclockwise,\n      rotateClockwise,\n      handleSwitchPrev,\n      handleSwitchNext,\n      withTooltip,\n      resizeToOrignalImageSize,\n      cssVars: inlineThemeDisabled ? undefined : cssVarsRef,\n      themeClass: themeClassHandle?.themeClass,\n      onRender: themeClassHandle?.onRender,\n      doUpdateShow,\n      close,\n      ...exposedMethods\n    }\n  },\n  render() {\n    const { clsPrefix, renderToolbar, withTooltip } = this\n\n    const prevNode = withTooltip(\n      <NBaseIcon clsPrefix={clsPrefix} onClick={this.handleSwitchPrev}>\n        {{ default: renderPrevIcon }}\n      </NBaseIcon>,\n      'tipPrevious'\n    )\n    const nextNode = withTooltip(\n      <NBaseIcon clsPrefix={clsPrefix} onClick={this.handleSwitchNext}>\n        {{ default: renderNextIcon }}\n      </NBaseIcon>,\n      'tipNext'\n    )\n\n    const rotateCounterclockwiseNode = withTooltip(\n      <NBaseIcon clsPrefix={clsPrefix} onClick={this.rotateCounterclockwise}>\n        {{\n          default: () => <RotateCounterclockwiseIcon />\n        }}\n      </NBaseIcon>,\n      'tipCounterclockwise'\n    )\n    const rotateClockwiseNode = withTooltip(\n      <NBaseIcon clsPrefix={clsPrefix} onClick={this.rotateClockwise}>\n        {{\n          default: () => <RotateClockwiseIcon />\n        }}\n      </NBaseIcon>,\n      'tipClockwise'\n    )\n    const originalSizeNode = withTooltip(\n      <NBaseIcon clsPrefix={clsPrefix} onClick={this.resizeToOrignalImageSize}>\n        {{\n          default: () => {\n            return <ResizeSmallIcon />\n          }\n        }}\n      </NBaseIcon>,\n      'tipOriginalSize'\n    )\n    const zoomOutNode = withTooltip(\n      <NBaseIcon clsPrefix={clsPrefix} onClick={this.zoomOut}>\n        {{ default: () => <ZoomOutIcon /> }}\n      </NBaseIcon>,\n      'tipZoomOut'\n    )\n\n    const downloadNode = withTooltip(\n      <NBaseIcon clsPrefix={clsPrefix} onClick={this.handleDownloadClick}>\n        {{ default: () => <DownloadIcon /> }}\n      </NBaseIcon>,\n      'tipDownload'\n    )\n\n    const closeNode = withTooltip(\n      <NBaseIcon clsPrefix={clsPrefix} onClick={() => this.close()}>\n        {{ default: renderCloseIcon }}\n      </NBaseIcon>,\n      'tipClose'\n    )\n\n    const zoomInNode = withTooltip(\n      <NBaseIcon clsPrefix={clsPrefix} onClick={this.zoomIn}>\n        {{ default: () => <ZoomInIcon /> }}\n      </NBaseIcon>,\n      'tipZoomIn'\n    )\n\n    return (\n      <>\n        {this.$slots.default?.()}\n        <LazyTeleport show={this.mergedShow}>\n          {{\n            default: () => {\n              if (!(this.mergedShow || this.displayed)) {\n                return null\n              }\n              this.onRender?.()\n              return withDirectives(\n                <div\n                  ref=\"containerRef\"\n                  class={[\n                    `${clsPrefix}-image-preview-container`,\n                    this.themeClass\n                  ]}\n                  style={this.cssVars as CSSProperties}\n                  onWheel={this.handleWheel}\n                >\n                  <Transition name=\"fade-in-transition\" appear={this.appear}>\n                    {{\n                      default: () =>\n                        this.mergedShow ? (\n                          <div\n                            class={`${clsPrefix}-image-preview-overlay`}\n                            onClick={() => this.close()}\n                          />\n                        ) : null\n                    }}\n                  </Transition>\n                  {this.showToolbar ? (\n                    <Transition name=\"fade-in-transition\" appear={this.appear}>\n                      {{\n                        default: () => {\n                          if (!this.mergedShow)\n                            return null\n                          return (\n                            <div class={`${clsPrefix}-image-preview-toolbar`}>\n                              {renderToolbar ? (\n                                renderToolbar({\n                                  nodes: {\n                                    prev: prevNode,\n                                    next: nextNode,\n                                    rotateCounterclockwise:\n                                      rotateCounterclockwiseNode,\n                                    rotateClockwise: rotateClockwiseNode,\n                                    resizeToOriginalSize: originalSizeNode,\n                                    zoomOut: zoomOutNode,\n                                    zoomIn: zoomInNode,\n                                    download: downloadNode,\n                                    close: closeNode\n                                  }\n                                })\n                              ) : (\n                                <>\n                                  {this.onPrev ? (\n                                    <>\n                                      {prevNode}\n                                      {nextNode}\n                                    </>\n                                  ) : null}\n                                  {rotateCounterclockwiseNode}\n                                  {rotateClockwiseNode}\n                                  {originalSizeNode}\n                                  {zoomOutNode}\n                                  {zoomInNode}\n                                  {downloadNode}\n                                  {closeNode}\n                                </>\n                              )}\n                            </div>\n                          )\n                        }\n                      }}\n                    </Transition>\n                  ) : null}\n                  <Transition\n                    name=\"fade-in-scale-up-transition\"\n                    onAfterLeave={this.handleAfterLeave}\n                    appear={this.appear}\n                    // BUG:\n                    // onEnter will be called twice, I don't know why\n                    // Maybe it is a bug of vue\n                    onEnter={this.syncTransformOrigin}\n                    onBeforeLeave={this.syncTransformOrigin}\n                  >\n                    {{\n                      default: () => {\n                        const { previewedImgProps = {} } = this\n                        return withDirectives(\n                          <div\n                            class={`${clsPrefix}-image-preview-wrapper`}\n                            ref=\"previewWrapperRef\"\n                          >\n                            <img\n                              {...previewedImgProps}\n                              draggable={false}\n                              onMousedown={this.handlePreviewMousedown}\n                              onDblclick={this.handlePreviewDblclick}\n                              class={[\n                                `${clsPrefix}-image-preview`,\n                                previewedImgProps.class\n                              ]}\n                              key={this.previewSrc}\n                              src={this.previewSrc}\n                              ref=\"previewRef\"\n                              onDragstart={this.handleDragStart}\n                            />\n                          </div>,\n                          [[vShow, this.mergedShow]]\n                        )\n                      }\n                    }}\n                  </Transition>\n                </div>,\n                [[zindexable, { enabled: this.mergedShow }]]\n              )\n            }\n          }}\n        </LazyTeleport>\n      </>\n    )\n  }\n})\n"
  },
  {
    "path": "src/image/src/icons.tsx",
    "content": "import { h } from 'vue'\n\nexport function renderPrevIcon() {\n  return (\n    <svg viewBox=\"0 0 20 20\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n      <path\n        d=\"M6 5C5.75454 5 5.55039 5.17688 5.50806 5.41012L5.5 5.5V14.5C5.5 14.7761 5.72386 15 6 15C6.24546 15 6.44961 14.8231 6.49194 14.5899L6.5 14.5V5.5C6.5 5.22386 6.27614 5 6 5ZM13.8536 5.14645C13.68 4.97288 13.4106 4.9536 13.2157 5.08859L13.1464 5.14645L8.64645 9.64645C8.47288 9.82001 8.4536 10.0894 8.58859 10.2843L8.64645 10.3536L13.1464 14.8536C13.3417 15.0488 13.6583 15.0488 13.8536 14.8536C14.0271 14.68 14.0464 14.4106 13.9114 14.2157L13.8536 14.1464L9.70711 10L13.8536 5.85355C14.0488 5.65829 14.0488 5.34171 13.8536 5.14645Z\"\n        fill=\"currentColor\"\n      />\n    </svg>\n  )\n}\n\nexport function renderNextIcon() {\n  return (\n    <svg viewBox=\"0 0 20 20\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n      <path\n        d=\"M13.5 5C13.7455 5 13.9496 5.17688 13.9919 5.41012L14 5.5V14.5C14 14.7761 13.7761 15 13.5 15C13.2545 15 13.0504 14.8231 13.0081 14.5899L13 14.5V5.5C13 5.22386 13.2239 5 13.5 5ZM5.64645 5.14645C5.82001 4.97288 6.08944 4.9536 6.28431 5.08859L6.35355 5.14645L10.8536 9.64645C11.0271 9.82001 11.0464 10.0894 10.9114 10.2843L10.8536 10.3536L6.35355 14.8536C6.15829 15.0488 5.84171 15.0488 5.64645 14.8536C5.47288 14.68 5.4536 14.4106 5.58859 14.2157L5.64645 14.1464L9.79289 10L5.64645 5.85355C5.45118 5.65829 5.45118 5.34171 5.64645 5.14645Z\"\n        fill=\"currentColor\"\n      />\n    </svg>\n  )\n}\n\nexport function renderCloseIcon() {\n  return (\n    <svg viewBox=\"0 0 20 20\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n      <path\n        d=\"M4.089 4.216l.057-.07a.5.5 0 0 1 .638-.057l.07.057L10 9.293l5.146-5.147a.5.5 0 0 1 .638-.057l.07.057a.5.5 0 0 1 .057.638l-.057.07L10.707 10l5.147 5.146a.5.5 0 0 1 .057.638l-.057.07a.5.5 0 0 1-.638.057l-.07-.057L10 10.707l-5.146 5.147a.5.5 0 0 1-.638.057l-.07-.057a.5.5 0 0 1-.057-.638l.057-.07L9.293 10L4.146 4.854a.5.5 0 0 1-.057-.638l.057-.07l-.057.07z\"\n        fill=\"currentColor\"\n      />\n    </svg>\n  )\n}\n"
  },
  {
    "path": "src/image/src/interface.ts",
    "content": "import type { ImgHTMLAttributes, PropType, Ref } from 'vue'\nimport type { ThemeProps } from '../../_mixins'\nimport type { ImageTheme } from '../styles'\nimport type { ImageRenderToolbar } from './public-types'\nimport { useTheme } from '../../_mixins'\nimport { createInjectionKey } from '../../_utils'\n\nexport interface MoveStrategy {\n  moveVerticalDirection: 'verticalTop' | 'verticalBottom'\n  moveHorizontalDirection: 'horizontalLeft' | 'horizontalRight'\n  deltaHorizontal: number\n  deltaVertical: number\n}\n\nexport const imagePreviewSharedProps = {\n  ...(useTheme.props as ThemeProps<ImageTheme>),\n  onPreviewPrev: Function as PropType<() => void>,\n  onPreviewNext: Function as PropType<() => void>,\n  showToolbar: { type: Boolean, default: true },\n  showToolbarTooltip: Boolean,\n  renderToolbar: Function as PropType<ImageRenderToolbar>\n}\n\nexport interface ImageContext {\n  previewedImgPropsRef: Ref<ImgHTMLAttributes | undefined>\n}\n\nexport const imageContextKey = createInjectionKey<ImageContext>('n-image')\n"
  },
  {
    "path": "src/image/src/public-types.ts",
    "content": "import type { VNode, VNodeChild } from 'vue'\n\nexport interface ImageRenderToolbarProps {\n  nodes: {\n    prev: VNode\n    next: VNode\n    rotateCounterclockwise: VNode\n    rotateClockwise: VNode\n    resizeToOriginalSize: VNode\n    zoomOut: VNode\n    zoomIn: VNode\n    download: VNode\n    close: VNode\n  }\n}\n\nexport type ImageRenderToolbar = (props: ImageRenderToolbarProps) => VNodeChild\nexport type ImageGroupRenderToolbarProps = ImageRenderToolbarProps\nexport type ImageGroupRenderToolbar = ImageRenderToolbar\n\nexport interface ImageInst {\n  /** @deprecated Use `showPreview` instead */\n  click: () => void\n  showPreview: () => void\n}\n\nexport interface ImageSlots {\n  placeholder?: ImagePlaceholderSlot\n  error?: ImageErrorSlot\n}\n\nexport type ImagePlaceholderSlot = () => VNode[]\nexport type ImageErrorSlot = () => VNode[]\n\nexport interface ImagePreviewInst {\n  setThumbnailEl: (e: HTMLImageElement | null) => void\n}\n"
  },
  {
    "path": "src/image/src/styles/index.cssr.ts",
    "content": "import { fadeInScaleUpTransition } from '../../../_styles/transitions/fade-in-scale-up.cssr'\nimport { fadeInTransition } from '../../../_styles/transitions/fade-in.cssr'\nimport { c, cB, cNotM } from '../../../_utils/cssr'\n\n// vars:\n// --n-toolbar-icon-color\n// --n-toolbar-color\n// --n-toolbar-border-radius\n// --n-toolbar-box-shadow\n// --n-bezier\nexport default c([\n  c('body >', [\n    cB('image-container', 'position: fixed;')\n  ]),\n  cB('image-preview-container', `\n    position: fixed;\n    left: 0;\n    right: 0;\n    top: 0;\n    bottom: 0;\n    display: flex;\n  `),\n  cB('image-preview-overlay', `\n    z-index: -1;\n    position: absolute;\n    left: 0;\n    right: 0;\n    top: 0;\n    bottom: 0;\n    background: rgba(0, 0, 0, .3);\n  `, [\n    fadeInTransition()\n  ]),\n  cB('image-preview-toolbar', `\n    z-index: 1;\n    position: absolute;\n    left: 50%;\n    transform: translateX(-50%);\n    border-radius: var(--n-toolbar-border-radius);\n    height: 48px;\n    bottom: 40px;\n    padding: 0 12px;\n    background: var(--n-toolbar-color);\n    box-shadow: var(--n-toolbar-box-shadow);\n    color: var(--n-toolbar-icon-color);\n    transition: color .3s var(--n-bezier);\n    display: flex;\n    align-items: center;\n  `, [\n    cB('base-icon', `\n      padding: 0 8px;\n      font-size: 28px;\n      cursor: pointer;\n    `),\n    fadeInTransition()\n  ]),\n  cB('image-preview-wrapper', `\n    position: absolute;\n    left: 0;\n    right: 0;\n    top: 0;\n    bottom: 0;\n    display: flex;\n    pointer-events: none;\n  `, [\n    fadeInScaleUpTransition()\n  ]),\n  cB('image-preview', `\n    user-select: none;\n    -webkit-user-select: none;\n    pointer-events: all;\n    margin: auto;\n    max-height: calc(100vh - 32px);\n    max-width: calc(100vw - 32px);\n    transition: transform .3s var(--n-bezier);\n  `),\n  cB('image', `\n    display: inline-flex;\n    max-height: 100%;\n    max-width: 100%;\n  `, [\n    cNotM('preview-disabled', `\n      cursor: pointer;\n    `),\n    c('img', `\n      border-radius: inherit;\n    `)\n  ])\n])\n"
  },
  {
    "path": "src/image/src/utils.ts",
    "content": "import type { Ref } from 'vue'\n\nexport type IntersectionObserverOptions = Omit<\n  IntersectionObserverInit,\n  'root'\n> & {\n  root?: Element | Document | null | string\n}\n\nexport function resolveOptionsAndHash(\n  options: IntersectionObserverOptions | undefined = {}\n): {\n  hash: string\n  options: Omit<IntersectionObserverInit, 'root'> & { root: Element | Document }\n} {\n  const { root = null } = options\n  return {\n    hash: `${options.rootMargin || '0px 0px 0px 0px'}-${\n      Array.isArray(options.threshold)\n        ? options.threshold.join(',')\n        : (options.threshold ?? '0')\n    }`,\n    options: {\n      ...options,\n      root:\n        (typeof root === 'string' ? document.querySelector(root) : root)\n        || document.documentElement\n    }\n  }\n}\n\n// root -> options -> [observer, elements]\nconst observers = new WeakMap<\n  Document | Element,\n  Map<string, [IntersectionObserver, Set<Element | Document>]>\n>()\n\nconst unobserveHandleMap = new WeakMap<HTMLElement, () => void>()\nconst shouldStartLoadingRefMap = new WeakMap<HTMLElement, Ref<boolean>>()\n\nexport const observeIntersection: (\n  el: HTMLElement | null,\n  options: IntersectionObserverOptions | undefined,\n  shouldStartLoadingRef: Ref<boolean>\n) => () => void = (el, options, shouldStartLoadingRef) => {\n  if (!el)\n    return () => {}\n  const resolvedOptionsAndHash = resolveOptionsAndHash(options)\n  const { root } = resolvedOptionsAndHash.options\n  let rootObservers: Map<\n    string,\n    [IntersectionObserver, Set<Element | Document>]\n  >\n  const _rootObservers = observers.get(root)\n  if (_rootObservers) {\n    rootObservers = _rootObservers\n  }\n  else {\n    rootObservers = new Map()\n    observers.set(root, rootObservers)\n  }\n  let observer: IntersectionObserver\n  let observerAndObservedElements: [\n    IntersectionObserver,\n    Set<Element | Document>\n  ]\n  if (rootObservers.has(resolvedOptionsAndHash.hash)) {\n    observerAndObservedElements = rootObservers.get(\n      resolvedOptionsAndHash.hash\n    )!\n    if (!observerAndObservedElements[1].has(el)) {\n      observer = observerAndObservedElements[0]\n      observerAndObservedElements[1].add(el)\n      observer.observe(el)\n    }\n  }\n  else {\n    observer = new IntersectionObserver((entries) => {\n      entries.forEach((entry) => {\n        if (entry.isIntersecting) {\n          const _unobserve = unobserveHandleMap.get(\n            entry.target as HTMLImageElement\n          )\n          const _shouldStartLoadingRef = shouldStartLoadingRefMap.get(\n            entry.target as HTMLImageElement\n          )\n          if (_unobserve)\n            _unobserve()\n          if (_shouldStartLoadingRef) {\n            _shouldStartLoadingRef.value = true\n          }\n        }\n      })\n    }, resolvedOptionsAndHash.options)\n    observer.observe(el)\n    observerAndObservedElements = [observer, new Set([el])]\n    rootObservers.set(resolvedOptionsAndHash.hash, observerAndObservedElements)\n  }\n  let unobservered = false\n  const unobserve = (): void => {\n    if (unobservered)\n      return\n    unobserveHandleMap.delete(el)\n    shouldStartLoadingRefMap.delete(el)\n    unobservered = true\n    if (observerAndObservedElements[1].has(el)) {\n      observerAndObservedElements[0].unobserve(el)\n      observerAndObservedElements[1].delete(el)\n    }\n    if (observerAndObservedElements[1].size <= 0) {\n      rootObservers.delete(resolvedOptionsAndHash.hash)\n    }\n    if (!rootObservers.size) {\n      observers.delete(root)\n    }\n  }\n  unobserveHandleMap.set(el, unobserve)\n  shouldStartLoadingRefMap.set(el, shouldStartLoadingRef)\n  return unobserve\n}\n"
  },
  {
    "path": "src/image/styles/dark.ts",
    "content": "import type { ImageTheme } from './light'\nimport { commonDark } from '../../_styles/common'\nimport { tooltipDark } from '../../styles'\n\nexport const imageDark: ImageTheme = {\n  name: 'Image',\n  common: commonDark,\n  peers: {\n    Tooltip: tooltipDark\n  },\n  self: (vars) => {\n    const { textColor2 } = vars\n    return {\n      toolbarIconColor: textColor2,\n      toolbarColor: 'rgba(0, 0, 0, .35)',\n      toolbarBoxShadow: 'none',\n      toolbarBorderRadius: '24px'\n    }\n  }\n}\n"
  },
  {
    "path": "src/image/styles/index.ts",
    "content": "export { imageDark } from './dark'\nexport { imageLight } from './light'\nexport type { ImageTheme, ImageThemeVars } from './light'\n"
  },
  {
    "path": "src/image/styles/light.ts",
    "content": "import { createTheme } from '../../_mixins'\nimport { commonLight } from '../../_styles/common'\nimport { tooltipLight } from '../../tooltip/styles'\n\nfunction self() {\n  return {\n    toolbarIconColor: 'rgba(255, 255, 255, .9)',\n    toolbarColor: 'rgba(0, 0, 0, .35)',\n    toolbarBoxShadow: 'none',\n    toolbarBorderRadius: '24px'\n  }\n}\nexport const imageLight = createTheme({\n  name: 'Image',\n  common: commonLight,\n  peers: {\n    Tooltip: tooltipLight\n  },\n  self\n})\n\nexport type ImageTheme = typeof imageLight\nexport type ImageThemeVars = ReturnType<typeof self>\n"
  },
  {
    "path": "src/image/tests/Image.spec.tsx",
    "content": "import { mount } from '@vue/test-utils'\nimport { h, nextTick } from 'vue'\nimport { NImage, NImageGroup } from '../index'\nimport NImagePreview from '../src/ImagePreview'\n\ndescribe('n-image', () => {\n  it('should work with import on demand', () => {\n    mount(NImage)\n  })\n\n  it('should work with `alt` prop', async () => {\n    const wrapper = mount(NImage)\n\n    await wrapper.setProps({ alt: 'This is just a picture' })\n\n    expect(wrapper.find('img').attributes('alt')).toBe('This is just a picture')\n    expect(wrapper.find('img').attributes('aria-label')).toBe(\n      'This is just a picture'\n    )\n    wrapper.unmount()\n  })\n\n  it('should work with `width` prop', async () => {\n    const wrapper = mount(NImage)\n\n    await wrapper.setProps({ width: '200' })\n\n    expect(wrapper.find('img').attributes('width')).toBe('200')\n\n    await wrapper.setProps({ width: 200 })\n\n    expect(wrapper.find('img').attributes('width')).toBe('200')\n    wrapper.unmount()\n  })\n\n  it('should work with `height` prop', async () => {\n    const wrapper = mount(NImage)\n\n    await wrapper.setProps({ height: '300' })\n\n    expect(wrapper.find('img').attributes('height')).toBe('300')\n\n    await wrapper.setProps({ height: 300 })\n\n    expect(wrapper.find('img').attributes('height')).toBe('300')\n    wrapper.unmount()\n  })\n\n  it('should work with `src` prop', async () => {\n    const wrapper = mount(NImage)\n\n    await wrapper.setProps({\n      src: 'https://www.naiveui.com/assets/naivelogo.93278402.svg'\n    })\n\n    expect(wrapper.find('img').attributes('src')).toBe(\n      'https://www.naiveui.com/assets/naivelogo.93278402.svg'\n    )\n    wrapper.unmount()\n  })\n\n  it('should work with `previewSrc` prop', async () => {\n    const wrapper = mount(NImage)\n\n    await wrapper.setProps({\n      previewSrc: 'https://www.naiveui.com/assets/naivelogo.93278402.svg'\n    })\n\n    expect(wrapper.find('img').attributes('data-preview-src')).toBe(\n      'https://www.naiveui.com/assets/naivelogo.93278402.svg'\n    )\n    wrapper.unmount()\n  })\n\n  it('should work with `showToolbar` prop', async () => {\n    const wrapper = mount(NImage)\n\n    await wrapper.setProps({\n      showToolbar: true\n    })\n\n    await wrapper.find('img').trigger('click')\n\n    expect(document.querySelector('.n-image-preview-toolbar')).not.toEqual(null)\n    wrapper.unmount()\n  })\n\n  it('should work with `image group` prop', async () => {\n    const wrapper = mount(NImageGroup, {\n      slots: {\n        default: () => [\n          h(NImage, null, {\n            default: () =>\n              'https://07akioni.oss-cn-beijing.aliyuncs.com/07akioni.jpeg'\n          }),\n          h(NImage, null, {\n            default: () =>\n              'https://gw.alipayobjects.com/zos/antfincdn/aPkFc8Sj7n/method-draw-image.svg'\n          })\n        ]\n      }\n    })\n\n    expect(wrapper.findAll('img').length).toBe(2)\n\n    await wrapper.findAll('img')[0].trigger('click')\n    expect(wrapper.findComponent(NImagePreview).exists()).toBe(true)\n    wrapper.unmount()\n  })\n  it('should inherit attrs', () => {\n    const wrapper = mount(NImage, {\n      attrs: {\n        'data-cool': true\n      }\n    })\n    expect(wrapper.find('[data-cool]').exists()).toEqual(true)\n    wrapper.unmount()\n  })\n\n  it('should work with `onError` prop', async () => {\n    const onError = vi.fn()\n    const wrapper = mount(NImage, {\n      props: {\n        src: 'https:// 07akioni.oss-cn-beijing.aliyuncs.com/07akioni.jpeg',\n        onError\n      }\n    })\n    await wrapper.find('img').trigger('error')\n    expect(onError).toHaveBeenCalled()\n    wrapper.unmount()\n  })\n\n  it('should work with `objectFit` prop', () => {\n    const wrapper = mount(NImage, {\n      props: {\n        src: 'https://07akioni.oss-cn-beijing.aliyuncs.com/07akioni.jpeg',\n        objectFit: 'contain'\n      }\n    })\n    expect(wrapper.find('img').attributes('style')).toContain(\n      'object-fit: contain;'\n    )\n    wrapper.unmount()\n  })\n  it('should work with `showToolbar close` prop', async () => {\n    const wrapper = mount(NImage, {\n      props: {\n        src: 'https://07akioni.oss-cn-beijing.aliyuncs.com/07akioni.jpeg'\n      }\n    })\n    await wrapper.find('img').trigger('click')\n    expect(document.querySelector('.n-image-preview-toolbar')).not.toEqual(null)\n    expect(wrapper.findComponent(NImagePreview).exists()).toBe(true)\n    const toolbars = document.querySelector('.n-image-preview-toolbar')\n    toolbars?.children[toolbars?.children.length - 1].dispatchEvent(\n      new MouseEvent('click')\n    )\n    await nextTick()\n    expect(document.querySelector('.n-image-preview-toolbar')).toEqual(null)\n    wrapper.unmount()\n  })\n\n  it('should work with `onLoad` prop', async () => {\n    const onLoad = vi.fn()\n    const wrapper = mount(NImage, {\n      props: {\n        src: 'https://07akioni.oss-cn-beijing.aliyuncs.com/07akioni.jpeg',\n        onLoad\n      }\n    })\n    await wrapper.find('img').trigger('load')\n    expect(onLoad).toHaveBeenCalled()\n    wrapper.unmount()\n  })\n\n  it('should work with `canPreview` prop', async () => {\n    const wrapper = mount(NImage, {\n      props: {\n        previewDisabled: true\n      }\n    })\n\n    await wrapper.find('img').trigger('click')\n    expect(document.querySelector('.n-image-preview-overlay')).toEqual(null)\n    wrapper.unmount()\n  })\n})\n"
  },
  {
    "path": "src/image/tests/server.spec.tsx",
    "content": "import { setup } from '@css-render/vue3-ssr'\nimport { renderToString } from '@vue/server-renderer'\n/**\n * @vitest-environment node\n */\nimport { createSSRApp, h } from 'vue'\nimport { NImage } from '../..'\n\ndescribe('server side rendering', () => {\n  it('works', async () => {\n    const app = createSSRApp(() => <NImage />)\n    setup(app)\n    try {\n      await renderToString(app)\n    }\n    catch (e) {\n      expect(e).not.toBeTruthy()\n    }\n  })\n})\n"
  },
  {
    "path": "src/index.ts",
    "content": "export { c, cB, cE, cM, cNotM } from './_utils/cssr'\n\nexport * from './components'\n\nexport * from './composables'\n\nexport { default as create } from './create'\n\nexport * from './locales'\nexport { default, install } from './preset'\n// component themes\nexport * from './styles'\n\nexport { NThemeEditor } from './theme-editor'\n// composed global theme, createTheme from component themes util\nexport { createTheme, darkTheme, lightTheme } from './themes'\n\nexport { default as version } from './version'\n\nexport { zindexable } from 'vdirs'\n\nexport { useOsTheme } from 'vooks'\n"
  },
  {
    "path": "src/infinite-scroll/demos/enUS/basic.demo.vue",
    "content": "<markdown>\n# Basic\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst count = ref(6)\nfunction handleLoad() {\n  count.value += 1\n}\n</script>\n\n<template>\n  <n-infinite-scroll style=\"height: 240px\" :distance=\"10\" @load=\"handleLoad\">\n    <div v-for=\"i in count\" :key=\"i\" class=\"item\">\n      {{ i }}\n    </div>\n  </n-infinite-scroll>\n</template>\n\n<style>\n.item {\n  display: flex;\n  align-items: center;\n  height: 46px;\n  justify-content: center;\n  margin-bottom: 10px;\n  background-color: rgba(0, 128, 0, 0.16);\n}\n\n.item:last-child {\n  margin-bottom: 0;\n}\n</style>\n"
  },
  {
    "path": "src/infinite-scroll/demos/enUS/chat.demo.vue",
    "content": "<markdown>\n# A bit complex example\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { computed, ref } from 'vue'\n\nconst loading = ref(false)\n\nconst avatars = [\n  'https://07akioni.oss-cn-beijing.aliyuncs.com/07akioni.jpeg',\n  'https://avatars.githubusercontent.com/u/20943608?s=60&v=4',\n  'https://avatars.githubusercontent.com/u/46394163?s=60&v=4',\n  'https://avatars.githubusercontent.com/u/39197136?s=60&v=4',\n  'https://avatars.githubusercontent.com/u/19239641?s=60&v=4'\n]\n\nconst messages = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday']\n\nfunction mock(i: number) {\n  return {\n    key: `${i}`,\n    value: i,\n    avatar: avatars[i % avatars.length],\n    message: messages[Math.floor(Math.random() * messages.length)]\n  }\n}\n\nconst items = ref(Array.from({ length: 10 }, (_, i) => mock(i)))\nconst noMore = computed(() => items.value.length > 16)\n\nasync function handleLoad() {\n  if (loading.value || noMore.value)\n    return\n  loading.value = true\n  await new Promise(resolve => setTimeout(resolve, 1000))\n  items.value.push(...[mock(items.value.length), mock(items.value.length + 1)])\n  loading.value = false\n}\n</script>\n\n<template>\n  <n-infinite-scroll style=\"height: 240px\" :distance=\"10\" @load=\"handleLoad\">\n    <div\n      v-for=\"(item, index) in items\"\n      :key=\"item.key\"\n      class=\"message\"\n      :class=\"{ reverse: index % 5 === 0 }\"\n    >\n      <img class=\"avatar\" :src=\"item.avatar\" alt=\"\">\n      <span> {{ item.message }} {{ index % 5 === 0 ? '?' : '' }}</span>\n    </div>\n    <div v-if=\"loading\" class=\"text\">\n      Loading...\n    </div>\n    <div v-if=\"noMore\" class=\"text\">\n      No More 🤪\n    </div>\n  </n-infinite-scroll>\n</template>\n\n<style>\n.message {\n  display: flex;\n  align-items: center;\n  margin-bottom: 10px;\n  padding: 10px;\n}\n\n.message:last-child {\n  margin-bottom: 0;\n}\n\n.reverse {\n  flex-direction: row-reverse;\n}\n\n.text {\n  text-align: center;\n}\n\n.reverse .avatar {\n  margin-left: 10px;\n}\n\n.avatar {\n  width: 28px;\n  height: 28px;\n  border-radius: 50%;\n  margin-right: 10px;\n}\n</style>\n"
  },
  {
    "path": "src/infinite-scroll/demos/enUS/index.demo-entry.md",
    "content": "# Infinite Scroll\n\nScroll, scroll, scroll, scroll...\n\nAvailable since `2.38.2`.\n\n## Demos\n\n```demo\nbasic.vue\nchat.vue\n```\n\n## API\n\n### Infinite Scroll Props\n\n| Name | Type | Default | Description | Version |\n| --- | --- | --- | --- | --- |\n| distance | `number` | `0` | Distance threshold that triggers loading. | 2.38.2 |\n| scrollbar-props | `Object` | `undefined` | Attribute reference [Scrollbar props](scrollbar#Scrollbar-Props). | 2.38.2 |\n| on-load | `() => Promise<void> \\| void` | `undefined` | The callback function when scrolling to the bottom. | 2.38.2 |\n"
  },
  {
    "path": "src/infinite-scroll/demos/zhCN/basic.demo.vue",
    "content": "<markdown>\n# 基础\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst count = ref(6)\nfunction handleLoad() {\n  count.value += 1\n}\n</script>\n\n<template>\n  <n-infinite-scroll style=\"height: 240px\" :distance=\"10\" @load=\"handleLoad\">\n    <div v-for=\"i in count\" :key=\"i\" class=\"item\">\n      {{ i }}\n    </div>\n  </n-infinite-scroll>\n</template>\n\n<style>\n.item {\n  display: flex;\n  align-items: center;\n  height: 46px;\n  justify-content: center;\n  margin-bottom: 10px;\n  background-color: rgba(0, 128, 0, 0.16);\n}\n\n.item:last-child {\n  margin-bottom: 0;\n}\n</style>\n"
  },
  {
    "path": "src/infinite-scroll/demos/zhCN/chat.demo.vue",
    "content": "<markdown>\n# 稍微复杂的例子\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { computed, ref } from 'vue'\n\nconst loading = ref(false)\n\nconst avatars = [\n  'https://07akioni.oss-cn-beijing.aliyuncs.com/07akioni.jpeg',\n  'https://avatars.githubusercontent.com/u/20943608?s=60&v=4',\n  'https://avatars.githubusercontent.com/u/46394163?s=60&v=4',\n  'https://avatars.githubusercontent.com/u/39197136?s=60&v=4',\n  'https://avatars.githubusercontent.com/u/19239641?s=60&v=4'\n]\n\nconst messages = ['星期一', '星期二', '星期三', '星期四', '星期五']\n\nfunction mock(i: number) {\n  return {\n    key: `${i}`,\n    value: i,\n    avatar: avatars[i % avatars.length],\n    message: messages[Math.floor(Math.random() * messages.length)]\n  }\n}\n\nconst items = ref(Array.from({ length: 10 }, (_, i) => mock(i)))\nconst noMore = computed(() => items.value.length > 16)\n\nasync function handleLoad() {\n  if (loading.value || noMore.value)\n    return\n  loading.value = true\n  await new Promise(resolve => setTimeout(resolve, 1000))\n  items.value.push(...[mock(items.value.length), mock(items.value.length + 1)])\n  loading.value = false\n}\n</script>\n\n<template>\n  <n-infinite-scroll style=\"height: 240px\" :distance=\"10\" @load=\"handleLoad\">\n    <div\n      v-for=\"(item, index) in items\"\n      :key=\"item.key\"\n      class=\"message\"\n      :class=\"{ reverse: index % 5 === 0 }\"\n    >\n      <img class=\"avatar\" :src=\"item.avatar\" alt=\"\">\n      <span> {{ item.message }} {{ index % 5 === 0 ? '?' : '' }}</span>\n    </div>\n    <div v-if=\"loading\" class=\"text\">\n      加载中...\n    </div>\n    <div v-if=\"noMore\" class=\"text\">\n      没有更多了 🤪\n    </div>\n  </n-infinite-scroll>\n</template>\n\n<style>\n.message {\n  display: flex;\n  align-items: center;\n  margin-bottom: 10px;\n  padding: 10px;\n}\n\n.message:last-child {\n  margin-bottom: 0;\n}\n\n.reverse {\n  flex-direction: row-reverse;\n}\n\n.text {\n  text-align: center;\n}\n\n.reverse .avatar {\n  margin-left: 10px;\n}\n\n.avatar {\n  width: 28px;\n  height: 28px;\n  border-radius: 50%;\n  margin-right: 10px;\n}\n</style>\n"
  },
  {
    "path": "src/infinite-scroll/demos/zhCN/index.demo-entry.md",
    "content": "# 无限滚动 Infinite Scroll\n\n滚雪球，滚啊滚，内容越来越多，停不下来。\n\n自 `2.38.2` 开始提供。\n\n## 演示\n\n```demo\nbasic.vue\nchat.vue\n```\n\n## API\n\n### Infinite Scroll Props\n\n| 名称 | 类型 | 默认值 | 说明 | 版本 |\n| --- | --- | --- | --- | --- |\n| distance | `number` | `0` | 触发加载的距离阈值 | 2.38.2 |\n| scrollbar-props | `Object` | `undefined` | 属性参考 [Scrollbar props](scrollbar#Scrollbar-Props) | 2.38.2 |\n| on-load | `() => Promise<void> \\| void` | `undefined` | 滚动到底部时的回调函数 | 2.38.2 |\n"
  },
  {
    "path": "src/infinite-scroll/index.ts",
    "content": "export {\n  infiniteScrollProps,\n  default as NInfiniteScroll\n} from './src/InfiniteScroll'\nexport type { InfiniteScrollProps } from './src/InfiniteScroll'\n"
  },
  {
    "path": "src/infinite-scroll/src/InfiniteScroll.tsx",
    "content": "import type { PropType } from 'vue'\nimport type { ScrollbarInst } from '../../_internal'\nimport type { ExtractPublicPropTypes } from '../../_utils'\nimport type { ScrollbarProps } from '../../scrollbar/src/Scrollbar'\nimport { defineComponent, h, ref } from 'vue'\nimport { NxScrollbar } from '../../_internal'\nimport { resolveSlot } from '../../_utils'\n\nexport const infiniteScrollProps = {\n  distance: {\n    type: Number,\n    default: 0\n  },\n  onLoad: Function as PropType<() => Promise<void> | void>,\n  scrollbarProps: Object as PropType<ScrollbarProps>\n} as const\n\nexport type InfiniteScrollProps = ExtractPublicPropTypes<\n  typeof infiniteScrollProps\n>\n\nexport default defineComponent({\n  name: 'InfiniteScroll',\n  props: infiniteScrollProps,\n  setup(props) {\n    const scrollbarInstRef = ref<ScrollbarInst | null>(null)\n\n    let loading = false\n\n    const handleCheckBottom = async (): Promise<void> => {\n      const { value: scrollbarInst } = scrollbarInstRef\n      if (scrollbarInst) {\n        const { containerRef } = scrollbarInst\n        const scrollHeight = containerRef?.scrollHeight\n        const clientHeight = containerRef?.clientHeight\n        const scrollTop = containerRef?.scrollTop\n\n        if (\n          containerRef\n          && scrollHeight !== undefined\n          && clientHeight !== undefined\n          && scrollTop !== undefined\n        ) {\n          if (scrollTop + clientHeight >= scrollHeight - props.distance) {\n            loading = true\n            try {\n              await props.onLoad?.()\n            }\n            catch {}\n            loading = false\n          }\n        }\n      }\n    }\n\n    const handleScroll = (): void => {\n      if (loading)\n        return\n      void handleCheckBottom()\n    }\n\n    const handleWheel = (e: WheelEvent): void => {\n      if (e.deltaY <= 0)\n        return\n      if (loading)\n        return\n      void handleCheckBottom()\n    }\n\n    return {\n      scrollbarInstRef,\n      handleScroll,\n      handleWheel\n    }\n  },\n  render() {\n    return (\n      <NxScrollbar\n        {...this.scrollbarProps}\n        ref=\"scrollbarInstRef\"\n        onWheel={this.handleWheel}\n        onScroll={this.handleScroll}\n      >\n        {{\n          default: () => {\n            return resolveSlot(this.$slots.default, () => [])\n          }\n        }}\n      </NxScrollbar>\n    )\n  }\n})\n"
  },
  {
    "path": "src/input/demos/enUS/autosize.demo.vue",
    "content": "<markdown>\n# Autosize\n\nAutosize the input.\n</markdown>\n\n<template>\n  <n-space vertical>\n    <n-input placeholder=\"Autosizable\" autosize style=\"min-width: 50%\" />\n    <n-input\n      placeholder=\"Autosizable\"\n      type=\"textarea\"\n      size=\"small\"\n      :autosize=\"{\n        minRows: 3,\n        maxRows: 5,\n      }\"\n    />\n    <n-input\n      type=\"textarea\"\n      placeholder=\"Autosizable\"\n      :autosize=\"{\n        minRows: 3,\n      }\"\n    />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/input/demos/enUS/basic.demo.vue",
    "content": "<markdown>\n# Basic\n\nBasic use of `n-input`.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst value = ref(null)\n</script>\n\n<template>\n  <n-space vertical>\n    <n-input v-model:value=\"value\" type=\"text\" placeholder=\"Basic Input\" />\n    <n-input\n      v-model:value=\"value\"\n      type=\"textarea\"\n      placeholder=\"Basic Textarea\"\n    />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/input/demos/enUS/clearable.demo.vue",
    "content": "<markdown>\n# Clearable\n\nMake the input clearable after a value is set.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { TrashBinOutline } from '@vicons/ionicons5'\n</script>\n\n<template>\n  <n-space vertical>\n    <n-input type=\"text\" placeholder=\"Content is clearable\" clearable />\n    <n-input type=\"password\" placeholder=\"Content is clearable\" clearable />\n    <n-input\n      type=\"textarea\"\n      placeholder=\"Content is clearable\"\n      round\n      clearable\n    />\n    <n-input type=\"text\" placeholder=\"Custom clear icon\" round clearable>\n      <template #clear-icon>\n        <n-icon :component=\"TrashBinOutline\" />\n      </template>\n    </n-input>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/input/demos/enUS/count.demo.vue",
    "content": "<markdown>\n# Word limit\n\nDon't waste words.\n</markdown>\n\n<template>\n  <n-space vertical>\n    <n-input maxlength=\"30\" show-count clearable />\n    <n-input default-value=\"Yes\" show-count clearable>\n      <template #count=\"{ value }\">\n        {{ value.includes('Yes') ? '99+' : value.length }}\n      </template>\n    </n-input>\n    <n-input type=\"textarea\" maxlength=\"30\" show-count />\n    <n-input type=\"textarea\" default-value=\"What?\" show-count>\n      <template #count=\"{ value }\">\n        {{ value.includes('What?') ? '99+' : value.length }}\n      </template>\n    </n-input>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/input/demos/enUS/disabled.demo.vue",
    "content": "<markdown>\n# Disabled\n\nInputs can also be disabled.\n</markdown>\n\n<script lang=\"ts\">\nimport { FlashOutline } from '@vicons/ionicons5'\nimport { defineComponent, ref } from 'vue'\n\nexport default defineComponent({\n  setup() {\n    return {\n      FlashOutline,\n      active: ref(false)\n    }\n  }\n})\n</script>\n\n<template>\n  <n-space vertical>\n    <n-input\n      type=\"text\"\n      size=\"small\"\n      placeholder=\"Oops! It is disabled.\"\n      :disabled=\"!active\"\n      round\n    />\n    <n-input\n      type=\"textarea\"\n      size=\"small\"\n      placeholder=\"Oops! It is disabled.\"\n      :disabled=\"!active\"\n      round\n    />\n    <n-input pair separator=\"to\" clearable :disabled=\"!active\">\n      <template #suffix>\n        <n-icon :component=\"FlashOutline\" />\n      </template>\n    </n-input>\n    <n-switch v-model:value=\"active\" />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/input/demos/enUS/event.demo.vue",
    "content": "<markdown>\n# Events\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { useMessage } from 'naive-ui'\n\nconst message = useMessage()\n\nfunction handleFocus() {\n  message.info('[Event focus]')\n}\n\nfunction handleBlur() {\n  message.info('[Event blur]')\n}\n\nfunction handleChange(v: string) {\n  message.info(`[Event change]: ${v}`)\n}\n\nfunction handleKeyUp() {\n  message.info('[Event keyup]')\n}\n\nfunction handleInput(v: string) {\n  message.info(`[Event input]: ${v}`)\n}\n</script>\n\n<template>\n  <n-space vertical>\n    <n-input\n      placeholder=\"Interact to trigger events\"\n      @blur=\"handleBlur\"\n      @focus=\"handleFocus\"\n      @change=\"handleChange\"\n      @keyup=\"handleKeyUp\"\n      @input=\"handleInput\"\n    />\n    <n-input\n      type=\"textarea\"\n      placeholder=\"Interact to trigger events\"\n      @blur=\"handleBlur\"\n      @focus=\"handleFocus\"\n      @change=\"handleChange\"\n      @keyup=\"handleKeyUp\"\n      @input=\"handleInput\"\n    />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/input/demos/enUS/focus.demo.vue",
    "content": "<markdown>\n# Imperative handle\n\n Clear. Focus. Blur. Selection. Scroll.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { InputInst } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst inputInstRef = ref<InputInst | null>(null)\nconst inputValue = ref('I heard you\\'re going to select all? '.repeat(4).trim())\n\nfunction handleClear() {\n  inputInstRef.value?.clear()\n}\n\nfunction handleFocus() {\n  inputInstRef.value?.focus()\n}\n\nfunction handleBlur() {\n  inputInstRef.value?.blur()\n}\n\nfunction handleSelect() {\n  inputInstRef.value?.select()\n}\n\nfunction handleScrollEnd() {\n  inputInstRef.value?.scrollTo({\n    behavior: 'smooth',\n    left: 10000\n  })\n}\n</script>\n\n<template>\n  <n-space vertical>\n    <n-space>\n      <n-button @click=\"handleClear\">\n        Clear\n      </n-button>\n      <n-button @click=\"handleFocus\">\n        Focus\n      </n-button>\n      <n-button :focusable=\"false\" @click=\"handleBlur\">\n        Blur\n      </n-button>\n      <n-button :focusable=\"false\" @click=\"handleSelect\">\n        Select\n      </n-button>\n      <n-button :focusable=\"false\" @click=\"handleScrollEnd\">\n        ScrollToEnd\n      </n-button>\n    </n-space>\n    <n-input ref=\"inputInstRef\" v-model:value=\"inputValue\" />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/input/demos/enUS/graphemes.demo.vue",
    "content": "<markdown>\n# Count graphemes\n\nBrowser's default `maxlength` and `minlength` and naive-ui's builtin character count method can't split all string correctly. You can use `count-graphemes` count to count graphemes correctly.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport GraphemeSplitter from 'grapheme-splitter'\n\nconst splitter = new GraphemeSplitter()\nconst countGraphemes = (value: string) => splitter.countGraphemes(value)\n</script>\n\n<template>\n  <n-form>\n    <n-form-item label=\"Default behavior\">\n      <n-input default-value=\"🌷🏳️‍🌈\" show-count :maxlength=\"12\" />\n    </n-form-item>\n    <n-form-item label=\"Correct behavior\">\n      <n-input\n        default-value=\"🌷🏳️‍🌈\"\n        show-count\n        :maxlength=\"12\"\n        :count-graphemes=\"countGraphemes\"\n      />\n    </n-form-item>\n  </n-form>\n</template>\n"
  },
  {
    "path": "src/input/demos/enUS/icon.demo.vue",
    "content": "<markdown>\n# Prefix & suffix\n\nSet a prefix and/or suffix for the input.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { FlashOutline } from '@vicons/ionicons5'\n</script>\n\n<template>\n  <n-space vertical>\n    <n-input placeholder=\"Flash\">\n      <template #prefix>\n        <n-icon :component=\"FlashOutline\" />\n      </template>\n    </n-input>\n    <n-input round placeholder=\"1,400,000\">\n      <template #suffix>\n        $\n      </template>\n    </n-input>\n    <n-input round placeholder=\"Flash\">\n      <template #suffix>\n        <n-icon :component=\"FlashOutline\" />\n      </template>\n    </n-input>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/input/demos/enUS/index.demo-entry.md",
    "content": "# Input\n\nMany years ago, inputs were just punched cards.\n\n## Demos\n\n```demo\nbasic.vue\nsize.vue\nround.vue\nicon.vue\nloading.vue\npassword.vue\ndisabled.vue\nclearable.vue\nautosize.vue\npair.vue\ninput-group.vue\npassively-activated.vue\ncount.vue\nfocus.vue\nevent.vue\ninput-props.vue\nstatus.vue\npattern.vue\ngraphemes.vue\n```\n\n## API\n\n### Input Props\n\n| Name | Type | Default | Description | Version |\n| --- | --- | --- | --- | --- |\n| allow-input | `(value: string) => boolean` | `undefined` | Check the incoming value, if it returns `false`, input will not be accepted. | 2.30.4 |\n| autofocus | `boolean` | `false` | Whether to autofocus. |  |\n| autosize | `boolean \\| { minRows?: number, maxRows?: number }` | `false` | Sizing property for when the input is of type `textarea`. e.g. `{ minRows: 1, maxRows: 3 }`. |  |\n| clearable | `boolean` | `false` | Whether the input is clearable. |  |\n| count-graphemes | `(value: string) => number` | `undefined` | Count graphemes of input value. If it's set, native `maxlength` and `minlength` won't be used. | 2.34.0 |\n| default-value | `string \\| [string, string] \\| null` | `null` | Default value when not manually set. |  |\n| disabled | `boolean` | `false` | Whether to disable the input. |  |\n| input-props | `InputHTMLAttributes \\| TextareaHTMLAttributes` | `undefined` | The dom props of the input element inside the component. This is disabled if the `pair` property is true. For avaiable attributes, [see here](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input). Warning：It won't override internal props with the same name (except `type`). |  |\n| loading | `boolean` | `undefined` | Set loading state. If set (true/false), the element will always take up enough space for the loading indicator. |  |\n| maxlength | `number` | `undefined` | Maximum input length. |  |\n| minlength | `number` | `undefined` | Minimum input length. |  |\n| pair | `boolean` | `false` | Whether to use the pairwise type input. |  |\n| passively-activated | `boolean` | `false` | Whether to passively activate the input. |  |\n| placeholder | `string \\| [string, string]` | `undefined` | Placeholder of input. When `pair` is `true`, this is an array. |  |\n| readonly | `boolean` | `false` | Set the readonly state. |  |\n| render-count | `(props: { value: string }) => void` | `undefined` | Render function of word count. | 2.32.2 |\n| round | `boolean` | `false` | Use a rounded input style. |  |\n| rows | `number` | `3` | Rows property for when the input is of type `textarea`. |  |\n| separator | `string` | `undefined` | The separator between pairwise inputs. |  |\n| show-count | `boolean` | `false` | Whether to show the word count. |  |\n| show-password-on | `'click' \\| 'mousedown'` | `undefined` | The event to show the password. |  |\n| size | `'tiny' \\| 'small' \\| 'medium' \\| 'large'` | `'medium'` | Input size. |  |\n| status | `'success' \\| 'warning' \\| 'error'` | `undefined` | Validation status. | 2.25.0 |\n| type | `'text' \\| 'password' \\| 'textarea'` | `'text'` | Input type. |  |\n| value | `string \\| [string, string] \\| null` | `undefined` | Manually set the input value. When `pair` is `true`, this is an array. |  |\n| on-blur | `() => void` | `undefined` | Callback triggered when the input is blurred. |  |\n| on-change | `(value: string \\| [string, string]) => void` | `undefined` | Callback triggered when native change event is fired. |  |\n| on-clear | `() => void` | `undefined` | Callback triggered when the input is cleared. |  |\n| on-focus | `() => void` | `undefined` | Callback triggered when the input is focussed on. |  |\n| on-input | `(value: string \\| [string, string]) => void` | `undefined` | Callback triggered when the input gets user input. |  |\n| on-update:value | `(value: string \\| [string, string]) => void` | `undefined` | Callback triggered when the input value changes. |  |\n\n### Input Slots\n\n| Name | Parameters | Description | Version |\n| --- | --- | --- | --- |\n| clear-icon | `()` | Custom clear icon. | 2.29.0 |\n| count | `(props: { value: string })` | Word count. |  |\n| password-invisible-icon | `()` | Password toggle icon when password is invisible. | 2.27.0 |\n| password-visible-icon | `()` | Password toggle icon when password is visible. | 2.27.0 |\n| prefix | `()` | Prefix content slot. |  |\n| separator | `()` | The separator content of the input, only works when `pair` is true. This will take priority over the separator property. |  |\n| suffix | `()` | Suffix content slot. |  |\n\n### InputGroup Slots\n\n| Name    | Parameters | Description                     |\n| ------- | ---------- | ------------------------------- |\n| default | `()`       | The content of the input group. |\n\n### InputGroupLabel Slots\n\n| Name    | Parameters | Description                           |\n| ------- | ---------- | ------------------------------------- |\n| default | `()`       | The content of the input group label. |\n\n### Input Methods\n\n| Name | Type | Description | Version |\n| --- | --- | --- | --- |\n| blur | `() => void` | Blur the input element. |  |\n| clear | `() => void` | Clear input value. | 2.37.0 |\n| focus | `() => void` | Focus the input element. |  |\n| scrollTo | `(options: { left?: number, top?: number, behavior?: 'auto' \\| 'smooth' }) => void` | Scroll To. | 2.32.0 |\n| select | `() => void` | Select the input element. |  |\n"
  },
  {
    "path": "src/input/demos/enUS/input-group.demo.vue",
    "content": "<markdown>\n# Input group\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst selectOptions = ref([\n  {\n    label: 'option',\n    value: 'option'\n  }\n])\n\nconst cascaderOptions = ref([\n  {\n    label: 'option-1',\n    value: 'option-1',\n    children: [\n      {\n        label: 'option-1-1',\n        value: 'option-1-1'\n      }\n    ]\n  }\n])\n</script>\n\n<template>\n  <n-space vertical>\n    <n-input-group>\n      <n-input :style=\"{ width: '33%' }\" />\n      <n-input-number :style=\"{ width: '33%' }\" />\n      <n-input :style=\"{ width: '33%' }\" />\n    </n-input-group>\n    <n-input-group>\n      <n-input-group-label>https://www.</n-input-group-label>\n      <n-input :style=\"{ width: '33%' }\" />\n      <n-input-group-label>.com</n-input-group-label>\n    </n-input-group>\n    <n-input-group>\n      <n-select :style=\"{ width: '33%' }\" :options=\"selectOptions\" />\n      <n-cascader :style=\"{ width: '33%' }\" :options=\"cascaderOptions\" />\n      <n-select :style=\"{ width: '33%' }\" multiple :options=\"selectOptions\" />\n    </n-input-group>\n    <n-input-group>\n      <n-button type=\"primary\">\n        Search\n      </n-button>\n      <n-input :style=\"{ width: '50%' }\" />\n      <n-button type=\"primary\" ghost>\n        Search\n      </n-button>\n    </n-input-group>\n    <n-input-group>\n      <n-date-picker />\n      <n-time-picker />\n    </n-input-group>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/input/demos/enUS/input-props.demo.vue",
    "content": "<markdown>\n# Input props\n\nInput element has some special attributes, such as `auto-complete` or `type`. You can use `input-props` to set it.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst value = ref(null)\n</script>\n\n<template>\n  <n-space vertical>\n    <n-input\n      v-model:value=\"value\"\n      :input-props=\"{ type: 'url' }\"\n      placeholder=\"URL\"\n    />\n    <n-input\n      v-model:value=\"value\"\n      :input-props=\"{ type: 'tel' }\"\n      placeholder=\"Tel\"\n    />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/input/demos/enUS/loading.demo.vue",
    "content": "<markdown>\n# Loading\n\n`input` has a loading state.\n\nNote: When using `clearable`, `suffix` and `loading` at the same time, and `loading` is `false`, there will be a space between the clear button and the suffix, if you want to remove the whitespace, `loading` should be set to `undefined` when stopping loading.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst value = ref(null)\n</script>\n\n<template>\n  <n-input\n    v-model:value=\"value\"\n    type=\"text\"\n    placeholder=\"Basic Input\"\n    loading\n  />\n</template>\n"
  },
  {
    "path": "src/input/demos/enUS/pair.demo.vue",
    "content": "<markdown>\n# Pairwise value\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { useMessage } from 'naive-ui'\n\nconst message = useMessage()\nconst placeholder: string | [string, string] | undefined = ['From', 'To']\n\nfunction handleInputBlur() {\n  message.info('Pairwise Value：Blur')\n}\n\nfunction handleInputFocus() {\n  message.info('Pairwise Value：Focus')\n}\n\nfunction handleInputInput() {\n  message.info('Pairwise Value：Input')\n}\n\nfunction handleInputChange() {\n  message.info('Pairwise Value：Change')\n}\n</script>\n\n<template>\n  <n-input\n    pair\n    separator=\"-\"\n    :placeholder=\"placeholder\"\n    clearable\n    @blur=\"handleInputBlur\"\n    @focus=\"handleInputFocus\"\n    @change=\"handleInputChange\"\n    @update:value=\"handleInputInput\"\n  />\n</template>\n"
  },
  {
    "path": "src/input/demos/enUS/passively-activated.demo.vue",
    "content": "<markdown>\n# Passively activated\n\nIf you want to activate the input by pressing enter after it's focused, use `passively-activated`. Use Tab to focus on the next input(s).\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { useMessage } from 'naive-ui'\n\nconst message = useMessage()\n\nfunction handleFocus() {\n  message.info('[Event focus]')\n}\n\nfunction handleBlur() {\n  message.info('[Event blur]')\n}\n\nfunction handleChange(v: string) {\n  message.info(`[Event change]: ${v}`)\n}\n\nfunction handleKeyUp() {\n  message.info('[Event keyup]')\n}\n\nfunction handleInput(v: string) {\n  message.info(`[Event input]: ${v}`)\n}\n</script>\n\n<template>\n  <n-space vertical>\n    <n-input\n      placeholder=\"Interact to trigger events\"\n      :passively-activated=\"true\"\n      @blur=\"handleBlur\"\n      @focus=\"handleFocus\"\n      @change=\"handleChange\"\n      @keyup=\"handleKeyUp\"\n      @input=\"handleInput\"\n    />\n    <n-input\n      type=\"textarea\"\n      placeholder=\"Interact to trigger events\"\n      :passively-activated=\"true\"\n      @blur=\"handleBlur\"\n      @focus=\"handleFocus\"\n      @change=\"handleChange\"\n      @keyup=\"handleKeyUp\"\n      @input=\"handleInput\"\n    />\n    <n-input\n      pair\n      separator=\"to\"\n      :passively-activated=\"true\"\n      @blur=\"handleBlur\"\n      @focus=\"handleFocus\"\n    />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/input/demos/enUS/password.demo.vue",
    "content": "<markdown>\n# Password\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { Glasses, GlassesOutline } from '@vicons/ionicons5'\n</script>\n\n<template>\n  <n-space vertical>\n    <n-input\n      type=\"password\"\n      show-password-on=\"mousedown\"\n      placeholder=\"Password\"\n      :maxlength=\"8\"\n    />\n    <n-input\n      type=\"password\"\n      show-password-on=\"click\"\n      placeholder=\"Custom Password Toggle Icon\"\n      :maxlength=\"8\"\n    >\n      <template #password-visible-icon>\n        <n-icon :size=\"16\" :component=\"GlassesOutline\" />\n      </template>\n      <template #password-invisible-icon>\n        <n-icon :size=\"16\" :component=\"Glasses\" />\n      </template>\n    </n-input>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/input/demos/enUS/pattern.demo.vue",
    "content": "<markdown>\n# Limit input format\n\nUse `allow-input` to limit input value to desired format. You can use it to achieve trim effect.\n</markdown>\n\n<script lang=\"ts\" setup>\nconst onlyAllowNumber = (value: string) => !value || /^\\d+$/.test(value)\nconst noSideSpace = (value: string) => !/ /g.test(value)\n</script>\n\n<template>\n  <n-space vertical>\n    <n-input\n      type=\"text\"\n      :allow-input=\"onlyAllowNumber\"\n      placeholder=\"Only allow number\"\n    />\n    <n-input\n      type=\"textarea\"\n      :allow-input=\"noSideSpace\"\n      placeholder=\"No leading or trailing space\"\n    />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/input/demos/enUS/round.demo.vue",
    "content": "<markdown>\n# Round corner\n\nInputs can have rounded corners.\n</markdown>\n\n<template>\n  <n-space vertical>\n    <n-input size=\"small\" round placeholder=\"Small\" />\n    <n-input round placeholder=\"Medium\" />\n    <n-input size=\"large\" round placeholder=\"Large\" />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/input/demos/enUS/size.demo.vue",
    "content": "<markdown>\n# Size\n</markdown>\n\n<template>\n  <n-space vertical>\n    <n-input type=\"text\" size=\"tiny\" placeholder=\"Tiny Input\" />\n    <n-input type=\"text\" size=\"small\" placeholder=\"Small Input\" />\n    <n-input type=\"text\" placeholder=\"Medium Input\" />\n    <n-input type=\"text\" size=\"large\" placeholder=\"Large Input\" />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/input/demos/enUS/status.demo.vue",
    "content": "<markdown>\n# Validation status\n\nValidation status can be applied outside form.\n</markdown>\n\n<template>\n  <n-space vertical>\n    <n-input status=\"warning\" placeholder=\"\" />\n    <n-input status=\"error\" placeholder=\"\" />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/input/demos/enUS/trim.demo.vue",
    "content": "<markdown>\n# Trim\n\nTrim the space at both ends.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst value = ref(null)\n</script>\n\n<template>\n  <n-space vertical>\n    <n-input v-model:value=\"value\" type=\"text\" trim />\n    <n-input v-model:value=\"value\" type=\"textarea\" trim />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/input/demos/zhCN/autosize.demo.vue",
    "content": "<markdown>\n# 自动调整尺寸\n\n自动调整尺寸。\n</markdown>\n\n<template>\n  <n-space vertical>\n    <n-input placeholder=\"自动调整尺寸\" autosize style=\"min-width: 50%\" />\n    <n-input\n      placeholder=\"自动调整尺寸\"\n      type=\"textarea\"\n      size=\"small\"\n      :autosize=\"{\n        minRows: 3,\n        maxRows: 5,\n      }\"\n    />\n    <n-input\n      type=\"textarea\"\n      placeholder=\"自动调整尺寸\"\n      :autosize=\"{\n        minRows: 3,\n      }\"\n    />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/input/demos/zhCN/basic.demo.vue",
    "content": "<markdown>\n# 基础用法\n\n文本输入的基础用法。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst value = ref(null)\n</script>\n\n<template>\n  <n-space vertical>\n    <n-input v-model:value=\"value\" type=\"text\" placeholder=\"基本的 Input\" />\n    <n-input\n      v-model:value=\"value\"\n      type=\"textarea\"\n      placeholder=\"基本的 Textarea\"\n    />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/input/demos/zhCN/clearable.demo.vue",
    "content": "<markdown>\n# 可清除\n\n让输入值可以清除（当有值的时候）。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { TrashBinOutline } from '@vicons/ionicons5'\n</script>\n\n<template>\n  <n-space vertical>\n    <n-input type=\"text\" placeholder=\"可以清除\" clearable />\n    <n-input type=\"password\" placeholder=\"可以清除\" clearable />\n    <n-input type=\"textarea\" placeholder=\"可以清除\" round clearable />\n    <n-input type=\"text\" placeholder=\"自定义图标\" round clearable>\n      <template #clear-icon>\n        <n-icon :component=\"TrashBinOutline\" />\n      </template>\n    </n-input>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/input/demos/zhCN/count.demo.vue",
    "content": "<markdown>\n# 字数限制\n\n惜字如金。\n</markdown>\n\n<template>\n  <n-space vertical>\n    <n-input maxlength=\"30\" show-count clearable />\n    <n-input default-value=\"哦\" show-count clearable>\n      <template #count=\"{ value }\">\n        {{ value.includes('哦') ? '99+' : value.length }}\n      </template>\n    </n-input>\n    <n-input type=\"textarea\" maxlength=\"30\" show-count />\n    <n-input type=\"textarea\" default-value=\"啥\" show-count>\n      <template #count=\"{ value }\">\n        {{ value.includes('啥') ? '99+' : value.length }}\n      </template>\n    </n-input>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/input/demos/zhCN/disabled.demo.vue",
    "content": "<markdown>\n# 禁用\n\n文本输入可以被禁用。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { FlashOutline } from '@vicons/ionicons5'\nimport { ref } from 'vue'\n\nconst active = ref(false)\n</script>\n\n<template>\n  <n-space vertical>\n    <n-input\n      type=\"text\"\n      size=\"small\"\n      placeholder=\"噢！它被禁用了。\"\n      :disabled=\"!active\"\n      round\n    />\n    <n-input\n      type=\"textarea\"\n      size=\"small\"\n      placeholder=\"噢！它被禁用了。\"\n      :disabled=\"!active\"\n      round\n    />\n    <n-input pair separator=\"to\" clearable :disabled=\"!active\">\n      <template #suffix>\n        <n-icon :component=\"FlashOutline\" />\n      </template>\n    </n-input>\n    <n-switch v-model:value=\"active\" />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/input/demos/zhCN/event.demo.vue",
    "content": "<markdown>\n# 事件\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { useMessage } from 'naive-ui'\n\nconst message = useMessage()\n\nfunction handleFocus() {\n  message.info('[Event focus]')\n}\n\nfunction handleBlur() {\n  message.info('[Event blur]')\n}\n\nfunction handleChange(v: string) {\n  message.info(`[Event change]: ${v}`)\n}\n\nfunction handleKeyUp() {\n  message.info('[Event keyup]')\n}\n\nfunction handleInput(v: string) {\n  message.info(`[Event input]: ${v}`)\n}\n</script>\n\n<template>\n  <n-space vertical>\n    <n-input\n      placeholder=\"触发事件\"\n      @blur=\"handleBlur\"\n      @focus=\"handleFocus\"\n      @change=\"handleChange\"\n      @keyup=\"handleKeyUp\"\n      @input=\"handleInput\"\n    />\n    <n-input\n      type=\"textarea\"\n      placeholder=\"触发事件\"\n      @blur=\"handleBlur\"\n      @focus=\"handleFocus\"\n      @change=\"handleChange\"\n      @keyup=\"handleKeyUp\"\n      @input=\"handleInput\"\n    />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/input/demos/zhCN/focus.demo.vue",
    "content": "<markdown>\n# 手动操作\n\n清除、聚焦、失焦、选中、滚动。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { InputInst } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst inputInstRef = ref<InputInst | null>(null)\nconst inputValue = ref('马儿乖，马儿好，马儿光跑不吃草。'.repeat(4))\n\nfunction handleClear() {\n  inputInstRef.value?.clear()\n}\n\nfunction handleFocus() {\n  inputInstRef.value?.focus()\n}\n\nfunction handleBlur() {\n  inputInstRef.value?.blur()\n}\n\nfunction handleSelect() {\n  inputInstRef.value?.select()\n}\n\nfunction handleScrollEnd() {\n  inputInstRef.value?.scrollTo({\n    behavior: 'smooth',\n    left: 10000\n  })\n}\n</script>\n\n<template>\n  <n-space vertical>\n    <n-space>\n      <n-button @click=\"handleClear\">\n        Clear\n      </n-button>\n      <n-button @click=\"handleFocus\">\n        Focus\n      </n-button>\n      <n-button :focusable=\"false\" @click=\"handleBlur\">\n        Blur\n      </n-button>\n      <n-button :focusable=\"false\" @click=\"handleSelect\">\n        Select\n      </n-button>\n      <n-button :focusable=\"false\" @click=\"handleScrollEnd\">\n        ScrollToEnd\n      </n-button>\n    </n-space>\n    <n-input ref=\"inputInstRef\" v-model:value=\"inputValue\" />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/input/demos/zhCN/graphemes.demo.vue",
    "content": "<markdown>\n# 字素计数\n\n浏览器默认的 `maxlength` 和 `minlength` 以及 naive-ui 自带的字数统计功能并不能准确地拆分所有的字符串，你可以使用 `count-graphemes` 属性来精确的测量文字长度。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport GraphemeSplitter from 'grapheme-splitter'\n\nconst splitter = new GraphemeSplitter()\nconst countGraphemes = (value: string) => splitter.countGraphemes(value)\n</script>\n\n<template>\n  <n-form>\n    <n-form-item label=\"默认表现\">\n      <n-input default-value=\"🌷🏳️‍🌈\" show-count :maxlength=\"12\" />\n    </n-form-item>\n    <n-form-item label=\"正确表现\">\n      <n-input\n        default-value=\"🌷🏳️‍🌈\"\n        show-count\n        :maxlength=\"12\"\n        :count-graphemes=\"countGraphemes\"\n      />\n    </n-form-item>\n  </n-form>\n</template>\n"
  },
  {
    "path": "src/input/demos/zhCN/icon-debug.demo.vue",
    "content": "<markdown>\n# 图标\n\n添加图标\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { MdSearch } from '@vicons/ionicons4'\n</script>\n\n<template>\n  <n-input placeholder=\"搜索\" clearable>\n    <template #prefix>\n      <n-icon>\n        <MdSearch />\n      </n-icon>\n    </template>\n  </n-input>\n  <n-input placeholder=\"搜索\" clearable>\n    <template #suffix>\n      DOLLAR\n    </template>\n  </n-input>\n  <n-input round placeholder=\"搜索\" size=\"small\" clearable>\n    <template #suffix>\n      <n-icon>\n        <MdSearch />\n      </n-icon>\n    </template>\n    <template #prefix>\n      <n-icon>\n        <MdSearch />\n      </n-icon>\n    </template>\n  </n-input>\n  <n-input placeholder=\"搜索\" size=\"large\" clearable>\n    <template #suffix>\n      <n-icon>\n        <MdSearch />\n      </n-icon>\n    </template>\n    <template #prefix>\n      <n-icon>\n        <MdSearch />\n      </n-icon>\n    </template>\n  </n-input>\n  <n-input placeholder=\"搜索\" size=\"small\" clearable>\n    <template #suffix>\n      <n-icon>\n        <MdSearch />\n      </n-icon>\n    </template>\n    <template #prefix>\n      <n-icon>\n        <MdSearch />\n      </n-icon>\n    </template>\n  </n-input>\n  <n-input placeholder=\"搜索\" pair size=\"large\" separator=\"-\" clearable>\n    <template #suffix>\n      <n-icon>\n        <MdSearch />\n      </n-icon>\n    </template>\n    <template #prefix>\n      <n-icon>\n        <MdSearch />\n      </n-icon>\n    </template>\n  </n-input>\n  <n-input placeholder=\"搜索\" pair size=\"small\" separator=\"-\" clearable>\n    <template #suffix>\n      <n-icon>\n        <MdSearch />\n      </n-icon>\n    </template>\n    <template #prefix>\n      <n-icon>\n        <MdSearch />\n      </n-icon>\n    </template>\n  </n-input>\n  <n-input round placeholder=\"搜索\" size=\"large\" clearable>\n    <template #suffix>\n      <n-icon>\n        <MdSearch />\n      </n-icon>\n    </template>\n    <template #prefix>\n      <n-icon>\n        <MdSearch />\n      </n-icon>\n    </template>\n  </n-input>\n  <n-input round placeholder=\"搜索\" clearable>\n    <template #suffix>\n      <n-icon>\n        <MdSearch />\n      </n-icon>\n    </template>\n  </n-input>\n</template>\n\n<style>\n.n-input {\n  margin-bottom: 8px;\n}\n</style>\n"
  },
  {
    "path": "src/input/demos/zhCN/icon.demo.vue",
    "content": "<markdown>\n# 前缀 & 后缀\n\n在前缀后缀添加内容。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { FlashOutline } from '@vicons/ionicons5'\n</script>\n\n<template>\n  <n-space vertical>\n    <n-input placeholder=\"搜索\">\n      <template #prefix>\n        <n-icon :component=\"FlashOutline\" />\n      </template>\n    </n-input>\n    <n-input round placeholder=\"100,000,000\">\n      <template #suffix>\n        元\n      </template>\n    </n-input>\n    <n-input round placeholder=\"搜索\">\n      <template #suffix>\n        <n-icon :component=\"FlashOutline\" />\n      </template>\n    </n-input>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/input/demos/zhCN/index.demo-entry.md",
    "content": "# 文本输入 Input\n\n很多年前，人们还在用打孔纸卡输入。\n\n## 演示\n\n```demo\nbasic.vue\nsize.vue\nround.vue\nicon.vue\nloading.vue\npassword.vue\ndisabled.vue\nclearable.vue\nautosize.vue\npair.vue\ninput-group.vue\npassively-activated.vue\ncount.vue\nfocus.vue\nevent.vue\ninput-props.vue\nstatus.vue\npattern.vue\ngraphemes.vue\nrtl-debug.vue\nprefix-debug.vue\nmodal-debug.vue\ntextarea-resize-debug.vue\n```\n\n## API\n\n### Input Props\n\n| 名称 | 类型 | 默认值 | 说明 | 版本 |\n| --- | --- | --- | --- | --- |\n| allow-input | `(value: string) => false` | `undefined` | 校验当前的输入是否合法，如果返回 `false` 输入框便不会响应此次的输入 | 2.30.4 |\n| autofocus | `boolean` | `false` | 是否自动获取焦点 |  |\n| autosize | `boolean \\| { minRows?: number, maxRows?: number }` | `false` | 自适应内容高度，只对 `type=\"textarea\"` 有效，可传入对象，如 `{ minRows: 1, maxRows: 3 }` |  |\n| clearable | `boolean` | `false` | 是否可清空 |  |\n| default-value | `string \\| [string, string] \\| null` | `null` | 输入框默认值 |  |\n| count-graphemes | `(value: string) => number` | `undefined` | 计算输入的字数。如果设定了，那么原生的 `maxlength` 和 `minlength` 属性将不再被使用 | 2.34.0 |\n| disabled | `boolean` | `false` | 是否禁用 |  |\n| input-props | `InputHTMLAttributes \\| TextareaHTMLAttributes` | `undefined` | Input 组件内部 input 元素的属性，对 `pair` 类型不生效，[在这里查看原生属性](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input)。注意：input-props 不会覆盖内部 input 元素的已经存在的属性（除了 `type`） |  |\n| loading | `boolean` | `undefined` | 是否展示加载图标，设为非 `undefined` 会占据空间 |  |\n| maxlength | `number` | `undefined` | 最大输入长度 |  |\n| minlength | `number` | `undefined` | 最小输入长度 |  |\n| pair | `boolean` | `false` | 是否输入成对的值 |  |\n| passively-activated | `boolean` | `false` | 是否被动激活输入框 |  |\n| placeholder | `string \\| [string, string]` | `undefined` | 文本输入的占位符。如果 `pair` 是 `true`，`placeholder`是一个数组 |  |\n| readonly | `boolean` | `false` | 是否只读 |  |\n| render-count | `(props: { value: string }) => void` | `undefined` | 字数统计的渲染函数 | 2.32.2 |\n| round | `boolean` | `false` | 输入框是否圆角 |  |\n| rows | `number` | `3` | 输入框行数，对 type=\"textarea\" 有效 |  |\n| separator | `string` | `undefined` | 成对输入框中间的分隔符 |  |\n| show-count | `boolean` | `false` | 是否显示字数统计 |  |\n| show-password-on | `'click' \\| 'mousedown'` | `undefined` | 显示密码的时机 |  |\n| size | `'tiny' \\| 'small' \\| 'medium' \\| 'large'` | `'medium'` | 输入框尺寸 |  |\n| status | `'success' \\| 'warning' \\| 'error'` | `undefined` | 验证状态 | 2.25.0 |\n| type | `'text' \\| 'password' \\| 'textarea'` | `'text'` | 输入框类型 |  |\n| value | `string \\| [string, string] \\| null` | `undefined` | 文本输入的值。如果 `pair` 是 `true`，`value` 是一个数组 |  |\n| on-blur | `() => void` | `undefined` | 输入框失去焦点时触发 |  |\n| on-change | `(value: string \\| [string, string]) => void` | `undefined` | 原生 change 事件触发时触发 |  |\n| on-clear | `() => void` | `undefined` | 输入框点击清空按钮时触发 |  |\n| on-focus | `() => void` | `undefined` | 输入框获得焦点时触发 |  |\n| on-input | `(value: string \\| [string, string]) => void` | `undefined` | 输入框在用户输入时触发 |  |\n| on-update:value | `(value: string \\| [string, string]) => void` | `undefined` | 输入框值 change 时触发 |  |\n\n### Input Slots\n\n| 属性 | 参数 | 说明 | 版本 |\n| --- | --- | --- | --- |\n| clear-icon | `()` | 自定义清除图标 | 2.29.0 |\n| count | `(props: { value: string })` | 字数统计 |  |\n| password-invisible-icon | `()` | 密码关闭时的密码开关图标 | 2.27.0 |\n| password-visible-icon | `()` | 密码显示时的密码开关图标 | 2.27.0 |\n| prefix | `()` | 输入框头部内容 |  |\n| separator | `()` | 成对输入框之间分隔符，仅 `pair` = true 生效且优先级高于 separator 属性 |  |\n| suffix | `()` | 输入框尾部内容 |  |\n\n### InputGroup Slots\n\n| 属性    | 参数 | 说明         |\n| ------- | ---- | ------------ |\n| default | `()` | 输入组的内容 |\n\n### InputGroupLabel Slots\n\n| 属性    | 参数 | 说明             |\n| ------- | ---- | ---------------- |\n| default | `()` | 输入组标签的内容 |\n\n### Input Methods\n\n| 名称 | 类型 | 说明 | 版本 |\n| --- | --- | --- | --- |\n| blur | `() => void` | Blur 输入框 |  |\n| clear | `() => void` | 清空输入框 | 2.37.0 |\n| focus | `() => void` | Focus 输入框 |  |\n| scrollTo | `(options: { left?: number, top?: number, behavior?: 'auto' \\| 'smooth' }) => void` | 滚动到 | 2.32.0 |\n| select | `() => void` | 选中输入框内容 |  |\n"
  },
  {
    "path": "src/input/demos/zhCN/input-group.demo.vue",
    "content": "<markdown>\n# 输入组\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst selectOptions = ref([\n  {\n    label: 'option',\n    value: 'option'\n  }\n])\n\nconst cascaderOptions = ref([\n  {\n    label: 'option-1',\n    value: 'option-1',\n    children: [\n      {\n        label: 'option-1-1',\n        value: 'option-1-1'\n      }\n    ]\n  }\n])\n</script>\n\n<template>\n  <n-space vertical>\n    <n-input-group>\n      <n-input :style=\"{ width: '33%' }\" />\n      <n-input-number :style=\"{ width: '33%' }\" />\n      <n-input :style=\"{ width: '33%' }\" />\n    </n-input-group>\n    <n-input-group>\n      <n-input-group-label>https://www.</n-input-group-label>\n      <n-input :style=\"{ width: '33%' }\" />\n      <n-input-group-label>.com</n-input-group-label>\n    </n-input-group>\n    <n-input-group>\n      <n-select :style=\"{ width: '33%' }\" :options=\"selectOptions\" />\n      <n-cascader :style=\"{ width: '33%' }\" :options=\"cascaderOptions\" />\n      <n-select :style=\"{ width: '33%' }\" multiple :options=\"selectOptions\" />\n    </n-input-group>\n    <n-input-group>\n      <n-button type=\"primary\">\n        搜索\n      </n-button>\n      <n-input :style=\"{ width: '50%' }\" />\n      <n-button type=\"primary\" ghost>\n        搜索\n      </n-button>\n    </n-input-group>\n    <n-input-group>\n      <n-date-picker />\n      <n-time-picker />\n    </n-input-group>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/input/demos/zhCN/input-props.demo.vue",
    "content": "<markdown>\n# 原生属性\n\n`input` 有一些比较特殊的 DOM 属性，有时候你可能会想使用，比如 `auto-complete` 或者特殊的 type。你可以使用 `input-props` 设定。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst value = ref(null)\n</script>\n\n<template>\n  <n-space vertical>\n    <n-input\n      v-model:value=\"value\"\n      :input-props=\"{ type: 'url' }\"\n      placeholder=\"URL\"\n    />\n    <n-input\n      v-model:value=\"value\"\n      :input-props=\"{ type: 'tel' }\"\n      placeholder=\"Tel\"\n    />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/input/demos/zhCN/loading.demo.vue",
    "content": "<markdown>\n# 加载状态\n\n`input` 支持加载状态。\n\n注意：同时使用 `clearable`、`suffix` 和 `loading`，且 `loading` 为 `false` 时，清除按钮和后缀之间会有空白，如果想去除空白，停止加载时 `loading` 应当设置为 `undefined`。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst value = ref(null)\n</script>\n\n<template>\n  <n-input\n    v-model:value=\"value\"\n    type=\"text\"\n    placeholder=\"基本的 Input\"\n    loading\n  />\n</template>\n"
  },
  {
    "path": "src/input/demos/zhCN/modal-debug.demo.vue",
    "content": "<markdown>\n # Modal debug\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { onMounted, ref } from 'vue'\n\nconst name = ref('')\nconst value = ref('')\nconst showModal = ref(false)\n\nonMounted(() => {\n  setInterval(() => {\n    name.value = Math.random().toString()\n  }, 100)\n})\n\nfunction renderCount() {\n  return `${value.value.length} / Max`\n}\n</script>\n\n<template>\n  <div>\n    <n-button @click=\"showModal = true\">\n      Display\n    </n-button>\n  </div>\n\n  <n-modal v-model:show=\"showModal\">\n    <div>\n      <div>{{ name }}</div>\n      <n-input v-model:value=\"value\" show-count :render-count=\"renderCount\" />\n    </div>\n  </n-modal>\n</template>\n"
  },
  {
    "path": "src/input/demos/zhCN/pair.demo.vue",
    "content": "<markdown>\n# 输入成对值\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { useMessage } from 'naive-ui'\n\nconst message = useMessage()\nconst placeholder: string | [string, string] | undefined = ['从', '到']\n\nfunction handleInputBlur() {\n  message.info('输入成对值：Blur')\n}\n\nfunction handleInputFocus() {\n  message.info('输入成对值：Focus')\n}\n\nfunction handleInputInput() {\n  message.info('输入成对值：Input')\n}\n\nfunction handleInputChange() {\n  message.info('输入成对值：Change')\n}\n</script>\n\n<template>\n  <n-input\n    pair\n    separator=\"-\"\n    :placeholder=\"placeholder\"\n    clearable\n    @blur=\"handleInputBlur\"\n    @focus=\"handleInputFocus\"\n    @change=\"handleInputChange\"\n    @update:value=\"handleInputInput\"\n  />\n</template>\n"
  },
  {
    "path": "src/input/demos/zhCN/passively-activated.demo.vue",
    "content": "<markdown>\n# 被动激活\n\n如果需要在 focus 之后使用回车键来激活输入，可以设定 `passively-activated`。 (使用 tab 键来聚焦这些输入)\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { useMessage } from 'naive-ui'\n\nconst message = useMessage()\n\nfunction handleFocus() {\n  message.info('[Event focus]')\n}\n\nfunction handleBlur() {\n  message.info('[Event blur]')\n}\n\nfunction handleChange(v: string) {\n  message.info(`[Event change]: ${v}`)\n}\n\nfunction handleKeyUp() {\n  message.info('[Event keyup]')\n}\n\nfunction handleInput(v: string) {\n  message.info(`[Event input]: ${v}`)\n}\n</script>\n\n<template>\n  <n-space vertical>\n    <n-input\n      placeholder=\"操作来触发事件\"\n      passively-activated\n      @blur=\"handleBlur\"\n      @focus=\"handleFocus\"\n      @change=\"handleChange\"\n      @keyup=\"handleKeyUp\"\n      @input=\"handleInput\"\n    />\n    <n-input\n      type=\"textarea\"\n      placeholder=\"操作来触发事件\"\n      passively-activated\n      @blur=\"handleBlur\"\n      @focus=\"handleFocus\"\n      @change=\"handleChange\"\n      @keyup=\"handleKeyUp\"\n      @input=\"handleInput\"\n    />\n    <n-input\n      pair\n      separator=\"to\"\n      passively-activated\n      @blur=\"handleBlur\"\n      @focus=\"handleFocus\"\n    />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/input/demos/zhCN/password.demo.vue",
    "content": "<markdown>\n# 密码\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { Glasses, GlassesOutline } from '@vicons/ionicons5'\n</script>\n\n<template>\n  <n-space>\n    <n-input\n      type=\"password\"\n      show-password-on=\"mousedown\"\n      placeholder=\"密码\"\n      :maxlength=\"8\"\n    />\n    <n-input\n      type=\"password\"\n      show-password-on=\"click\"\n      placeholder=\"自定义密码图标\"\n      :maxlength=\"8\"\n    >\n      <template #password-visible-icon>\n        <n-icon :size=\"16\" :component=\"GlassesOutline\" />\n      </template>\n      <template #password-invisible-icon>\n        <n-icon :size=\"16\" :component=\"Glasses\" />\n      </template>\n    </n-input>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/input/demos/zhCN/pattern.demo.vue",
    "content": "<markdown>\n# 只允许输入特定值\n\n使用 `allow-input` 限制输入框的输入格式，你可以使用它来达到 `trim` 的效果。\n</markdown>\n\n<script lang=\"ts\" setup>\nconst onlyAllowNumber = (value: string) => !value || /^\\d+$/.test(value)\nfunction noSideSpace(value: string) {\n  return !value.startsWith(' ') && !value.endsWith(' ')\n}\n</script>\n\n<template>\n  <n-space vertical>\n    <n-input\n      type=\"text\"\n      :allow-input=\"onlyAllowNumber\"\n      placeholder=\"只能输入数字\"\n    />\n    <n-input\n      type=\"textarea\"\n      :allow-input=\"noSideSpace\"\n      placeholder=\"没有前后空格\"\n    />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/input/demos/zhCN/prefix-debug.demo.vue",
    "content": "<markdown>\n# Prefix debug\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { FlashOutline } from '@vicons/ionicons5'\nimport { ref } from 'vue'\n\nconst value1 = ref(null)\nconst value2 = ref(null)\nconst value3 = ref(null)\nconst value4 = ref(null)\nconst value5 = ref('Test value')\nconst value6 = ref('Test value')\n</script>\n\n<template>\n  <n-space vertical>\n    <n-input v-model:value=\"value1\" type=\"text\" placeholder=\"Basic Input\">\n      <template #prefix>\n        <n-icon :component=\"FlashOutline\" />\n      </template>\n    </n-input>\n    <n-input\n      v-model:value=\"value2\"\n      type=\"textarea\"\n      placeholder=\"Default Textarea\"\n    >\n      <template #prefix>\n        <n-icon :component=\"FlashOutline\" />\n      </template>\n    </n-input>\n\n    <n-divider dashed>\n      Below is a bug with prefix indentation\n    </n-divider>\n\n    <n-input\n      v-model:value=\"value3\"\n      type=\"textarea\"\n      autosize\n      placeholder=\"AutoSize Textarea 1\"\n    >\n      <template #prefix>\n        <n-icon :component=\"FlashOutline\" />\n      </template>\n    </n-input>\n    <n-input\n      v-model:value=\"value4\"\n      type=\"textarea\"\n      :autosize=\"{ minRows: 2 }\"\n      placeholder=\"AutoSize Textarea 2\"\n    >\n      <template #prefix>\n        <n-icon :component=\"FlashOutline\" />\n      </template>\n    </n-input>\n\n    <n-divider />\n\n    <n-input\n      v-model:value=\"value5\"\n      type=\"textarea\"\n      autosize\n      placeholder=\"AutoSize Textarea 1\"\n    >\n      <template #prefix>\n        <n-icon :component=\"FlashOutline\" />\n      </template>\n    </n-input>\n    <n-input\n      v-model:value=\"value6\"\n      type=\"textarea\"\n      :autosize=\"{ minRows: 2 }\"\n      placeholder=\"AutoSize Textarea 2\"\n    >\n      <template #prefix>\n        <n-icon :component=\"FlashOutline\" />\n      </template>\n    </n-input>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/input/demos/zhCN/round.demo.vue",
    "content": "<markdown>\n# 圆角\n\n文本输入可以是圆角的。\n</markdown>\n\n<template>\n  <n-space vertical>\n    <n-input size=\"small\" round placeholder=\"小\" />\n    <n-input round placeholder=\"中\" />\n    <n-input size=\"large\" round placeholder=\"大\" />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/input/demos/zhCN/rtl-debug.demo.vue",
    "content": "<markdown>\n# Rtl Debug\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { unstableInputRtl } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst value = ref(null)\nconst rtlEnabled = ref(false)\nconst rtlStyles = [unstableInputRtl]\n</script>\n\n<template>\n  <n-space vertical>\n    <n-space><n-switch v-model:value=\"rtlEnabled\" />Rtl</n-space>\n    <n-config-provider :rtl=\"rtlEnabled ? rtlStyles : undefined\">\n      <n-space vertical>\n        <n-input v-model:value=\"value\" type=\"text\" placeholder=\"基本的 Input\" />\n        <n-input\n          v-model:value=\"value\"\n          type=\"textarea\"\n          placeholder=\"基本的 Textarea\"\n        />\n      </n-space>\n    </n-config-provider>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/input/demos/zhCN/size.demo.vue",
    "content": "<markdown>\n# 尺寸\n</markdown>\n\n<template>\n  <n-space vertical>\n    <n-input type=\"text\" size=\"tiny\" placeholder=\"很小\" />\n    <n-input type=\"text\" size=\"small\" placeholder=\"小\" />\n    <n-input type=\"text\" placeholder=\"中\" />\n    <n-input type=\"text\" size=\"large\" placeholder=\"大\" />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/input/demos/zhCN/status.demo.vue",
    "content": "<markdown>\n# 验证状态\n\n输入的验证状态可以脱离表单使用。\n</markdown>\n\n<template>\n  <n-space vertical>\n    <n-input status=\"warning\" placeholder=\"\" />\n    <n-input status=\"error\" placeholder=\"\" />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/input/demos/zhCN/textarea-resize-debug.demo.vue",
    "content": "<markdown>\n# textarea-resize-debug\n</markdown>\n\n<template>\n  <n-space>\n    <n-input type=\"textarea\" size=\"small\" show-count />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/input/index.ts",
    "content": "export { inputProps, default as NInput } from './src/Input'\nexport type { InputProps, InputSlots } from './src/Input'\nexport { inputGroupProps, default as NInputGroup } from './src/InputGroup'\nexport type { InputGroupProps } from './src/InputGroup'\nexport {\n  inputGroupLabelProps,\n  default as NInputGroupLabel\n} from './src/InputGroupLabel'\nexport type { InputGroupLabelProps } from './src/InputGroupLabel'\nexport type * from './src/public-types'\n"
  },
  {
    "path": "src/input/src/Input.tsx",
    "content": "import type {\n  CSSProperties,\n  InputHTMLAttributes,\n  PropType,\n  SlotsType,\n  TextareaHTMLAttributes,\n  VNode,\n  VNodeChild,\n  WatchStopHandle\n} from 'vue'\nimport type { ScrollbarInst } from '../../_internal'\nimport type { ThemeProps } from '../../_mixins'\nimport type { ExtractPublicPropTypes, MaybeArray } from '../../_utils'\nimport type { FormValidationStatus } from '../../form/src/public-types'\nimport type { InputTheme } from '../styles'\nimport type {\n  InputWrappedRef,\n  OnUpdateValue,\n  OnUpdateValueImpl\n} from './interface'\nimport type { InputSize } from './public-types'\nimport { off, on } from 'evtd'\nimport { getPadding } from 'seemly'\nimport { useMemo, useMergedState } from 'vooks'\nimport {\n  computed,\n  defineComponent,\n  Fragment,\n  getCurrentInstance,\n  h,\n  nextTick,\n  onMounted,\n  provide,\n  ref,\n  toRef,\n  watch,\n  watchEffect\n} from 'vue'\nimport { VResizeObserver } from 'vueuc'\nimport { NBaseClear, NBaseIcon, NBaseSuffix, NScrollbar } from '../../_internal'\nimport { EyeIcon, EyeOffIcon } from '../../_internal/icons'\nimport {\n  useConfig,\n  useFormItem,\n  useLocale,\n  useStyle,\n  useTheme,\n  useThemeClass\n} from '../../_mixins'\nimport { useRtl } from '../../_mixins/use-rtl'\nimport { call, createKey, resolveSlot, resolveWrappedSlot } from '../../_utils'\nimport { isSafari } from '../../_utils/env/browser'\nimport { inputLight } from '../styles'\nimport { inputInjectionKey } from './interface'\nimport style, { safariStyle } from './styles/input.cssr'\nimport { isEmptyInputValue, useCursor } from './utils'\nimport WordCount from './WordCount'\n\nexport const inputProps = {\n  ...(useTheme.props as ThemeProps<InputTheme>),\n  bordered: {\n    type: Boolean as PropType<boolean | undefined>,\n    default: undefined\n  },\n  type: {\n    type: String as PropType<'text' | 'textarea' | 'password'>,\n    default: 'text'\n  },\n  placeholder: [Array, String] as PropType<string | [string, string]>,\n  defaultValue: {\n    type: [String, Array] as PropType<null | string | [string, string]>,\n    default: null\n  },\n  value: [String, Array] as PropType<null | string | [string, string]>,\n  disabled: {\n    type: Boolean as PropType<boolean | undefined>,\n    default: undefined\n  },\n  size: String as PropType<InputSize>,\n  rows: {\n    type: [Number, String] as PropType<number | string>,\n    default: 3\n  },\n  round: Boolean,\n  minlength: [String, Number] as PropType<number | string>,\n  maxlength: [String, Number] as PropType<number | string>,\n  clearable: Boolean,\n  autosize: {\n    type: [Boolean, Object] as PropType<\n      boolean | { minRows?: number, maxRows?: number }\n    >,\n    default: false\n  },\n  pair: Boolean,\n  separator: String,\n  readonly: {\n    type: [String, Boolean],\n    default: false\n  },\n  passivelyActivated: Boolean,\n  showPasswordOn: String as PropType<'mousedown' | 'click'>,\n  stateful: {\n    type: Boolean,\n    default: true\n  },\n  autofocus: Boolean,\n  inputProps: Object as PropType<TextareaHTMLAttributes | InputHTMLAttributes>,\n  resizable: {\n    type: Boolean,\n    default: true\n  },\n  showCount: Boolean,\n  loading: {\n    type: Boolean,\n    default: undefined\n  },\n  allowInput: Function as PropType<(value: string) => boolean>,\n  renderCount: Function as PropType<(props: { value: string }) => VNodeChild>,\n  onMousedown: Function as PropType<(e: MouseEvent) => void>,\n  onKeydown: Function as PropType<(e: KeyboardEvent) => void>,\n  onKeyup: [Function, Array] as PropType<(e: KeyboardEvent) => void>,\n  onInput: [Function, Array] as PropType<OnUpdateValue>,\n  onFocus: [Function, Array] as PropType<MaybeArray<(e: FocusEvent) => void>>,\n  onBlur: [Function, Array] as PropType<MaybeArray<(e: FocusEvent) => void>>,\n  onClick: [Function, Array] as PropType<MaybeArray<(e: MouseEvent) => void>>,\n  onChange: [Function, Array] as PropType<OnUpdateValue>,\n  onClear: [Function, Array] as PropType<MaybeArray<(e: MouseEvent) => void>>,\n  countGraphemes: Function as PropType<(value: string) => number>,\n  status: String as PropType<FormValidationStatus>,\n  'onUpdate:value': [Function, Array] as PropType<MaybeArray<OnUpdateValue>>,\n  onUpdateValue: [Function, Array] as PropType<MaybeArray<OnUpdateValue>>,\n  /** private */\n  textDecoration: [String, Array] as PropType<string | [string, string]>,\n  attrSize: {\n    type: Number,\n    default: 20\n  },\n  onInputBlur: [Function, Array] as PropType<\n    MaybeArray<(e: FocusEvent) => void>\n  >,\n  onInputFocus: [Function, Array] as PropType<\n    MaybeArray<(e: FocusEvent) => void>\n  >,\n  onDeactivate: [Function, Array] as PropType<MaybeArray<() => void>>,\n  onActivate: [Function, Array] as PropType<MaybeArray<() => void>>,\n  onWrapperFocus: [Function, Array] as PropType<\n    MaybeArray<(e: FocusEvent) => void>\n  >,\n  onWrapperBlur: [Function, Array] as PropType<\n    MaybeArray<(e: FocusEvent) => void>\n  >,\n  internalDeactivateOnEnter: Boolean,\n  internalForceFocus: Boolean,\n  internalLoadingBeforeSuffix: {\n    type: Boolean,\n    default: true\n  },\n  /** deprecated */\n  showPasswordToggle: Boolean\n}\n\nexport type InputProps = ExtractPublicPropTypes<typeof inputProps>\n\nexport interface InputSlots {\n  'clear-icon'?: () => VNode[]\n  count?: (props: { value: string }) => VNode[]\n  'password-invisible-icon'?: () => VNode[]\n  'password-visible-icon'?: () => VNode[]\n  prefix?: () => VNode[]\n  separator?: () => VNode[]\n  suffix?: () => VNode[]\n}\n\nexport default defineComponent({\n  name: 'Input',\n  props: inputProps,\n  slots: Object as SlotsType<InputSlots>,\n  setup(props) {\n    const {\n      mergedClsPrefixRef,\n      mergedBorderedRef,\n      inlineThemeDisabled,\n      mergedRtlRef,\n      mergedComponentPropsRef\n    } = useConfig(props)\n    const themeRef = useTheme(\n      'Input',\n      '-input',\n      style,\n      inputLight,\n      props,\n      mergedClsPrefixRef\n    )\n    if (isSafari) {\n      useStyle('-input-safari', safariStyle, mergedClsPrefixRef)\n    }\n    // dom refs\n    const wrapperElRef = ref<HTMLElement | null>(null)\n    const textareaElRef = ref<HTMLTextAreaElement | null>(null)\n    const textareaMirrorElRef = ref<HTMLElement | null>(null)\n    const inputMirrorElRef = ref<HTMLElement | null>(null)\n    const inputElRef = ref<HTMLInputElement | null>(null)\n    const inputEl2Ref = ref<HTMLInputElement | null>(null)\n    const currentFocusedInputRef = ref<\n      HTMLInputElement | HTMLTextAreaElement | null\n    >(null)\n    const focusedInputCursorControl = useCursor(currentFocusedInputRef)\n    const textareaScrollbarInstRef = ref<ScrollbarInst | null>(null)\n    // local\n    const { localeRef } = useLocale('Input')\n    // value\n    const uncontrolledValueRef = ref(props.defaultValue)\n    const controlledValueRef = toRef(props, 'value')\n    const mergedValueRef = useMergedState(\n      controlledValueRef,\n      uncontrolledValueRef\n    )\n    // form-item\n    const formItem = useFormItem(props, {\n      mergedSize: (NFormItem) => {\n        const { size } = props\n        if (size)\n          return size\n        const { mergedSize: formItemSize } = NFormItem || {}\n        if (formItemSize?.value)\n          return formItemSize.value as InputSize\n        const configSize = mergedComponentPropsRef?.value?.Input?.size\n        if (configSize)\n          return configSize\n        return 'medium'\n      }\n    })\n    const { mergedSizeRef, mergedDisabledRef, mergedStatusRef } = formItem\n    // states\n    const focusedRef = ref(false)\n    const hoverRef = ref(false)\n    const isComposingRef = ref(false)\n    const activatedRef = ref(false)\n    let syncSource: string | null = null\n    // placeholder\n    const mergedPlaceholderRef = computed<[string, string] | [string]>(() => {\n      const { placeholder, pair } = props\n      if (pair) {\n        if (Array.isArray(placeholder)) {\n          return placeholder\n        }\n        else if (placeholder === undefined) {\n          return ['', '']\n        }\n        return [placeholder, placeholder]\n      }\n      else if (placeholder === undefined) {\n        return [localeRef.value.placeholder]\n      }\n      else {\n        return [placeholder] as [string]\n      }\n    })\n    const showPlaceholder1Ref = computed(() => {\n      const { value: isComposing } = isComposingRef\n      const { value: mergedValue } = mergedValueRef\n      const { value: mergedPlaceholder } = mergedPlaceholderRef\n      return (\n        !isComposing\n        && (isEmptyInputValue(mergedValue)\n          || (Array.isArray(mergedValue) && isEmptyInputValue(mergedValue[0])))\n        && mergedPlaceholder[0]\n      )\n    })\n    const showPlaceholder2Ref = computed(() => {\n      const { value: isComposing } = isComposingRef\n      const { value: mergedValue } = mergedValueRef\n      const { value: mergedPlaceholder } = mergedPlaceholderRef\n      return (\n        !isComposing\n        && mergedPlaceholder[1]\n        && (isEmptyInputValue(mergedValue)\n          || (Array.isArray(mergedValue) && isEmptyInputValue(mergedValue[1])))\n      )\n    })\n    // focus\n    const mergedFocusRef = useMemo(() => {\n      return props.internalForceFocus || focusedRef.value\n    })\n    // clear\n    const showClearButton = useMemo(() => {\n      if (\n        mergedDisabledRef.value\n        || props.readonly\n        || !props.clearable\n        || (!mergedFocusRef.value && !hoverRef.value)\n      ) {\n        return false\n      }\n      const { value: mergedValue } = mergedValueRef\n      const { value: mergedFocus } = mergedFocusRef\n      if (props.pair) {\n        return (\n          !!(\n            Array.isArray(mergedValue)\n            && (mergedValue[0] || mergedValue[1])\n          )\n          && (hoverRef.value || mergedFocus)\n        )\n      }\n      else {\n        return !!mergedValue && (hoverRef.value || mergedFocus)\n      }\n    })\n    // passwordVisible\n    const mergedShowPasswordOnRef = computed(() => {\n      const { showPasswordOn } = props\n      if (showPasswordOn) {\n        return showPasswordOn\n      }\n      if (props.showPasswordToggle)\n        return 'click'\n      return undefined\n    })\n    const passwordVisibleRef = ref<boolean>(false)\n    // text-decoration\n    const textDecorationStyleRef = computed(() => {\n      const { textDecoration } = props\n      if (!textDecoration)\n        return ['', '']\n      if (Array.isArray(textDecoration)) {\n        return textDecoration.map(v => ({\n          textDecoration: v\n        }))\n      }\n      return [\n        {\n          textDecoration\n        }\n      ]\n    })\n    const textAreaScrollContainerWidthRef = ref<number | undefined>(undefined)\n    // textarea autosize\n    const updateTextAreaStyle = (): void => {\n      if (props.type === 'textarea') {\n        const { autosize } = props\n        if (autosize) {\n          textAreaScrollContainerWidthRef.value\n            = textareaScrollbarInstRef.value?.$el?.offsetWidth\n        }\n        if (!textareaElRef.value)\n          return\n        if (typeof autosize === 'boolean')\n          return\n        const {\n          paddingTop: stylePaddingTop,\n          paddingBottom: stylePaddingBottom,\n          lineHeight: styleLineHeight\n        } = window.getComputedStyle(textareaElRef.value)\n        const paddingTop = Number(stylePaddingTop.slice(0, -2))\n        const paddingBottom = Number(stylePaddingBottom.slice(0, -2))\n        const lineHeight = Number(styleLineHeight.slice(0, -2))\n        const { value: textareaMirrorEl } = textareaMirrorElRef\n        if (!textareaMirrorEl)\n          return\n        if (autosize.minRows) {\n          const minRows = Math.max(autosize.minRows, 1)\n          const styleMinHeight = `${\n            paddingTop + paddingBottom + lineHeight * minRows\n          }px`\n          textareaMirrorEl.style.minHeight = styleMinHeight\n        }\n        if (autosize.maxRows) {\n          const styleMaxHeight = `${\n            paddingTop + paddingBottom + lineHeight * autosize.maxRows\n          }px`\n          textareaMirrorEl.style.maxHeight = styleMaxHeight\n        }\n      }\n    }\n    // word count\n    const maxlengthRef = computed(() => {\n      const { maxlength } = props\n      return maxlength === undefined ? undefined : Number(maxlength)\n    })\n    onMounted(() => {\n      // sync mirror if is not pair\n      const { value } = mergedValueRef\n      if (!Array.isArray(value)) {\n        syncMirror(value)\n      }\n    })\n    // other methods\n    const vm = getCurrentInstance()!.proxy!\n    function doUpdateValue(\n      value: [string, string],\n      meta: { source: 0 | 1 | 'clear' }\n    ): void\n    function doUpdateValue(\n      value: string,\n      meta: { source: 0 | 1 | 'clear' }\n    ): void\n    function doUpdateValue(\n      value: string | [string, string],\n      meta: { source: 0 | 1 | 'clear' }\n    ): void {\n      const { onUpdateValue, 'onUpdate:value': _onUpdateValue, onInput } = props\n      const { nTriggerFormInput } = formItem\n      if (onUpdateValue)\n        call(onUpdateValue as OnUpdateValueImpl, value, meta)\n      if (_onUpdateValue)\n        call(_onUpdateValue as OnUpdateValueImpl, value, meta)\n      if (onInput)\n        call(onInput as OnUpdateValueImpl, value, meta)\n      uncontrolledValueRef.value = value\n      nTriggerFormInput()\n    }\n    function doChange(\n      value: [string, string],\n      meta: { source: 0 | 1 | 'clear' }\n    ): void\n    function doChange(value: string, meta: { source: 0 | 1 | 'clear' }): void\n    function doChange(\n      value: string | [string, string],\n      meta: { source: 0 | 1 | 'clear' }\n    ): void {\n      const { onChange } = props\n      const { nTriggerFormChange } = formItem\n      if (onChange)\n        call(onChange as OnUpdateValueImpl, value, meta)\n      uncontrolledValueRef.value = value\n      nTriggerFormChange()\n    }\n    function doBlur(e: FocusEvent): void {\n      const { onBlur } = props\n      const { nTriggerFormBlur } = formItem\n      if (onBlur)\n        call(onBlur, e)\n      nTriggerFormBlur()\n    }\n    function doFocus(e: FocusEvent): void {\n      const { onFocus } = props\n      const { nTriggerFormFocus } = formItem\n      if (onFocus)\n        call(onFocus, e)\n      nTriggerFormFocus()\n    }\n    function doClear(e: MouseEvent): void {\n      const { onClear } = props\n      if (onClear)\n        call(onClear, e)\n    }\n    function doUpdateValueBlur(e: FocusEvent): void {\n      const { onInputBlur } = props\n      if (onInputBlur)\n        call(onInputBlur, e)\n    }\n    function doUpdateValueFocus(e: FocusEvent): void {\n      const { onInputFocus } = props\n      if (onInputFocus)\n        call(onInputFocus, e)\n    }\n    function doDeactivate(): void {\n      const { onDeactivate } = props\n      if (onDeactivate)\n        call(onDeactivate)\n    }\n    function doActivate(): void {\n      const { onActivate } = props\n      if (onActivate)\n        call(onActivate)\n    }\n    function doClick(e: MouseEvent): void {\n      const { onClick } = props\n      if (onClick)\n        call(onClick, e)\n    }\n    function doWrapperFocus(e: FocusEvent): void {\n      const { onWrapperFocus } = props\n      if (onWrapperFocus)\n        call(onWrapperFocus, e)\n    }\n    function doWrapperBlur(e: FocusEvent): void {\n      const { onWrapperBlur } = props\n      if (onWrapperBlur)\n        call(onWrapperBlur, e)\n    }\n    // methods\n    function handleCompositionStart(): void {\n      isComposingRef.value = true\n    }\n    function handleCompositionEnd(e: CompositionEvent): void {\n      isComposingRef.value = false\n      if (e.target === inputEl2Ref.value) {\n        handleInput(e, 1)\n      }\n      else {\n        handleInput(e, 0)\n      }\n    }\n    function handleInput(\n      e: InputEvent | CompositionEvent | Event,\n      index: 0 | 1 = 0,\n      event = 'input'\n    ): void {\n      const targetValue = (e.target as HTMLInputElement).value\n      syncMirror(targetValue)\n      if (e instanceof InputEvent && !e.isComposing) {\n        isComposingRef.value = false\n      }\n      if (props.type === 'textarea') {\n        const { value: textareaScrollbarInst } = textareaScrollbarInstRef\n        if (textareaScrollbarInst) {\n          textareaScrollbarInst.syncUnifiedContainer()\n        }\n      }\n      syncSource = targetValue\n      if (isComposingRef.value)\n        return\n      focusedInputCursorControl.recordCursor()\n      const isIncomingValueValid = allowInput(targetValue)\n      if (isIncomingValueValid) {\n        if (!props.pair) {\n          if (event === 'input') {\n            doUpdateValue(targetValue, { source: index })\n          }\n          else {\n            doChange(targetValue, { source: index })\n          }\n        }\n        else {\n          let { value } = mergedValueRef\n          if (!Array.isArray(value)) {\n            value = ['', '']\n          }\n          else {\n            value = [value[0], value[1]]\n          }\n          value[index] = targetValue\n          if (event === 'input') {\n            doUpdateValue(value, { source: index })\n          }\n          else {\n            doChange(value, { source: index })\n          }\n        }\n      }\n      // force update to sync input's view with value\n      // if not set, after input, input value won't sync with dom input value\n      vm.$forceUpdate()\n      if (!isIncomingValueValid) {\n        void nextTick(focusedInputCursorControl.restoreCursor)\n      }\n    }\n    function allowInput(value: string): boolean {\n      const { countGraphemes, maxlength, minlength } = props\n      if (countGraphemes) {\n        let graphemesCount: number | undefined\n        if (maxlength !== undefined) {\n          if (graphemesCount === undefined) {\n            graphemesCount = countGraphemes(value)\n          }\n          if (graphemesCount > Number(maxlength))\n            return false\n        }\n        if (minlength !== undefined) {\n          if (graphemesCount === undefined) {\n            graphemesCount = countGraphemes(value)\n          }\n          if (graphemesCount < Number(maxlength))\n            return false\n        }\n      }\n      const { allowInput } = props\n      if (typeof allowInput === 'function') {\n        return allowInput(value)\n      }\n      return true\n    }\n    function handleInputBlur(e: FocusEvent): void {\n      doUpdateValueBlur(e)\n      if (e.relatedTarget === wrapperElRef.value) {\n        doDeactivate()\n      }\n      if (\n        !(\n          e.relatedTarget !== null\n          && (e.relatedTarget === inputElRef.value\n            || e.relatedTarget === inputEl2Ref.value\n            || e.relatedTarget === textareaElRef.value)\n        )\n      ) {\n        activatedRef.value = false\n      }\n      dealWithEvent(e, 'blur')\n      currentFocusedInputRef.value = null\n    }\n    function handleInputFocus(e: FocusEvent, index: number): void {\n      doUpdateValueFocus(e)\n      focusedRef.value = true\n      activatedRef.value = true\n      doActivate()\n      dealWithEvent(e, 'focus')\n      if (index === 0) {\n        currentFocusedInputRef.value = inputElRef.value\n      }\n      else if (index === 1) {\n        currentFocusedInputRef.value = inputEl2Ref.value\n      }\n      else if (index === 2) {\n        currentFocusedInputRef.value = textareaElRef.value\n      }\n    }\n    function handleWrapperBlur(e: FocusEvent): void {\n      if (props.passivelyActivated) {\n        doWrapperBlur(e)\n        dealWithEvent(e, 'blur')\n      }\n    }\n    function handleWrapperFocus(e: FocusEvent): void {\n      if (props.passivelyActivated) {\n        focusedRef.value = true\n        doWrapperFocus(e)\n        dealWithEvent(e, 'focus')\n      }\n    }\n    function dealWithEvent(e: FocusEvent, type: 'focus' | 'blur'): void {\n      if (\n        e.relatedTarget !== null\n        && (e.relatedTarget === inputElRef.value\n          || e.relatedTarget === inputEl2Ref.value\n          || e.relatedTarget === textareaElRef.value\n          || e.relatedTarget === wrapperElRef.value)\n      ) {\n        /**\n         * activeElement transfer inside the input, do nothing\n         */\n      }\n      else {\n        if (type === 'focus') {\n          doFocus(e)\n          focusedRef.value = true\n        }\n        else if (type === 'blur') {\n          doBlur(e)\n          focusedRef.value = false\n        }\n      }\n    }\n    function handleChange(e: Event, index?: 0 | 1): void {\n      handleInput(e, index, 'change')\n    }\n    function handleClick(e: MouseEvent): void {\n      doClick(e)\n    }\n    function handleClear(e: MouseEvent): void {\n      doClear(e)\n      clearValue()\n    }\n    function clearValue(): void {\n      if (props.pair) {\n        doUpdateValue(['', ''], { source: 'clear' })\n        doChange(['', ''], { source: 'clear' })\n      }\n      else {\n        doUpdateValue('', { source: 'clear' })\n        doChange('', { source: 'clear' })\n      }\n    }\n    function handleMouseDown(e: MouseEvent): void {\n      const { onMousedown } = props\n      if (onMousedown)\n        onMousedown(e)\n      const { tagName } = e.target as HTMLElement\n      if (tagName !== 'INPUT' && tagName !== 'TEXTAREA') {\n        if (props.resizable) {\n          const { value: wrapperEl } = wrapperElRef\n          if (wrapperEl) {\n            const { left, top, width, height }\n              = wrapperEl.getBoundingClientRect()\n            const resizeHandleSize = 14\n            if (\n              left + width - resizeHandleSize < e.clientX\n              && e.clientX < left + width\n              && top + height - resizeHandleSize < e.clientY\n              && e.clientY < top + height\n            ) {\n              // touching resize handle, just let it go.\n              // resize won't take focus, maybe there is a better way to do this.\n              // hope someone can figure out a better solution\n              return\n            }\n          }\n        }\n        e.preventDefault()\n        if (!focusedRef.value) {\n          focus()\n        }\n      }\n    }\n    function handleMouseEnter(): void {\n      hoverRef.value = true\n      if (props.type === 'textarea') {\n        textareaScrollbarInstRef.value?.handleMouseEnterWrapper()\n      }\n    }\n    function handleMouseLeave(): void {\n      hoverRef.value = false\n      if (props.type === 'textarea') {\n        textareaScrollbarInstRef.value?.handleMouseLeaveWrapper()\n      }\n    }\n    function handlePasswordToggleClick(): void {\n      if (mergedDisabledRef.value)\n        return\n      if (mergedShowPasswordOnRef.value !== 'click')\n        return\n      passwordVisibleRef.value = !passwordVisibleRef.value\n    }\n    function handlePasswordToggleMousedown(e: MouseEvent): void {\n      if (mergedDisabledRef.value)\n        return\n      e.preventDefault()\n      const preventDefaultOnce = (e: MouseEvent): void => {\n        e.preventDefault()\n        off('mouseup', document, preventDefaultOnce)\n      }\n      on('mouseup', document, preventDefaultOnce)\n      if (mergedShowPasswordOnRef.value !== 'mousedown')\n        return\n      passwordVisibleRef.value = true\n      const hidePassword = (): void => {\n        passwordVisibleRef.value = false\n        off('mouseup', document, hidePassword)\n      }\n      on('mouseup', document, hidePassword)\n    }\n    function handleWrapperKeyup(e: KeyboardEvent): void {\n      if (props.onKeyup)\n        call(props.onKeyup, e)\n    }\n    function handleWrapperKeydown(e: KeyboardEvent): void {\n      if (props.onKeydown)\n        call(props.onKeydown, e)\n      switch (e.key) {\n        case 'Escape':\n          handleWrapperKeydownEsc()\n          break\n        case 'Enter':\n          handleWrapperKeydownEnter(e)\n          break\n      }\n    }\n    function handleWrapperKeydownEnter(e: KeyboardEvent): void {\n      if (props.passivelyActivated) {\n        const { value: focused } = activatedRef\n        if (focused) {\n          if (props.internalDeactivateOnEnter) {\n            handleWrapperKeydownEsc()\n          }\n          return\n        }\n        e.preventDefault()\n        if (props.type === 'textarea') {\n          textareaElRef.value?.focus()\n        }\n        else {\n          inputElRef.value?.focus()\n        }\n      }\n    }\n    function handleWrapperKeydownEsc(): void {\n      if (props.passivelyActivated) {\n        activatedRef.value = false\n        void nextTick(() => {\n          wrapperElRef.value?.focus()\n        })\n      }\n    }\n    function focus(): void {\n      if (mergedDisabledRef.value)\n        return\n      if (props.passivelyActivated) {\n        wrapperElRef.value?.focus()\n      }\n      else {\n        textareaElRef.value?.focus()\n        inputElRef.value?.focus()\n      }\n    }\n    function blur(): void {\n      if (wrapperElRef.value?.contains(document.activeElement)) {\n        ;(document.activeElement as HTMLElement).blur()\n      }\n    }\n    function select(): void {\n      textareaElRef.value?.select()\n      inputElRef.value?.select()\n    }\n    function activate(): void {\n      if (mergedDisabledRef.value)\n        return\n      if (textareaElRef.value)\n        textareaElRef.value.focus()\n      else if (inputElRef.value)\n        inputElRef.value.focus()\n    }\n    function deactivate(): void {\n      const { value: wrapperEl } = wrapperElRef\n      if (\n        wrapperEl?.contains(document.activeElement)\n        && wrapperEl !== document.activeElement\n      ) {\n        handleWrapperKeydownEsc()\n      }\n    }\n\n    function scrollTo(options: ScrollToOptions): void {\n      if (props.type === 'textarea') {\n        const { value: textareaEl } = textareaElRef\n        textareaEl?.scrollTo(options)\n      }\n      else {\n        const { value: inputEl } = inputElRef\n        inputEl?.scrollTo(options)\n      }\n    }\n\n    function syncMirror(value: string | null): void {\n      const { type, pair, autosize } = props\n      if (!pair && autosize) {\n        if (type === 'textarea') {\n          const { value: textareaMirrorEl } = textareaMirrorElRef\n          if (textareaMirrorEl) {\n            textareaMirrorEl.textContent = `${value ?? ''}\\r\\n`\n          }\n        }\n        else {\n          const { value: inputMirrorEl } = inputMirrorElRef\n          if (inputMirrorEl) {\n            if (value) {\n              inputMirrorEl.textContent = value\n            }\n            else {\n              inputMirrorEl.innerHTML = '&nbsp;'\n            }\n          }\n        }\n      }\n    }\n    function handleTextAreaMirrorResize(): void {\n      updateTextAreaStyle()\n    }\n\n    const placeholderStyleRef = ref({\n      top: '0'\n    })\n    function handleTextAreaScroll(e: Event): void {\n      const { scrollTop } = e.target as HTMLElement\n      placeholderStyleRef.value.top = `${-scrollTop}px`\n      textareaScrollbarInstRef.value?.syncUnifiedContainer()\n    }\n\n    let stopWatchMergedValue1: WatchStopHandle | null = null\n    watchEffect(() => {\n      const { autosize, type } = props\n      if (autosize && type === 'textarea') {\n        stopWatchMergedValue1 = watch(mergedValueRef, (value) => {\n          if (!Array.isArray(value) && value !== syncSource) {\n            syncMirror(value)\n          }\n        })\n      }\n      else {\n        stopWatchMergedValue1?.()\n      }\n    })\n\n    let stopWatchMergedValue2: WatchStopHandle | null = null\n    watchEffect(() => {\n      if (props.type === 'textarea') {\n        stopWatchMergedValue2 = watch(mergedValueRef, (value) => {\n          if (!Array.isArray(value) && value !== syncSource) {\n            textareaScrollbarInstRef.value?.syncUnifiedContainer()\n          }\n        })\n      }\n      else {\n        stopWatchMergedValue2?.()\n      }\n    })\n\n    provide(inputInjectionKey, {\n      mergedValueRef,\n      maxlengthRef,\n      mergedClsPrefixRef,\n      countGraphemesRef: toRef(props, 'countGraphemes')\n    })\n\n    const exposedProps: InputWrappedRef = {\n      wrapperElRef,\n      inputElRef,\n      textareaElRef,\n      isCompositing: isComposingRef,\n      clear: clearValue,\n      focus,\n      blur,\n      select,\n      deactivate,\n      activate,\n      scrollTo\n    }\n\n    const rtlEnabledRef = useRtl('Input', mergedRtlRef, mergedClsPrefixRef)\n    const cssVarsRef = computed(() => {\n      const { value: size } = mergedSizeRef\n      const {\n        common: { cubicBezierEaseInOut },\n        self: {\n          color,\n          borderRadius,\n          textColor,\n          caretColor,\n          caretColorError,\n          caretColorWarning,\n          textDecorationColor,\n          border,\n          borderDisabled,\n          borderHover,\n          borderFocus,\n          placeholderColor,\n          placeholderColorDisabled,\n          lineHeightTextarea,\n          colorDisabled,\n          colorFocus,\n          textColorDisabled,\n          boxShadowFocus,\n          iconSize,\n          colorFocusWarning,\n          boxShadowFocusWarning,\n          borderWarning,\n          borderFocusWarning,\n          borderHoverWarning,\n          colorFocusError,\n          boxShadowFocusError,\n          borderError,\n          borderFocusError,\n          borderHoverError,\n          clearSize,\n          clearColor,\n          clearColorHover,\n          clearColorPressed,\n          iconColor,\n          iconColorDisabled,\n          suffixTextColor,\n          countTextColor,\n          countTextColorDisabled,\n          iconColorHover,\n          iconColorPressed,\n          loadingColor,\n          loadingColorError,\n          loadingColorWarning,\n          fontWeight,\n          [createKey('padding', size)]: padding,\n          [createKey('fontSize', size)]: fontSize,\n          [createKey('height', size)]: height\n        }\n      } = themeRef.value\n      const { left: paddingLeft, right: paddingRight } = getPadding(padding)\n      return {\n        '--n-bezier': cubicBezierEaseInOut,\n        '--n-count-text-color': countTextColor,\n        '--n-count-text-color-disabled': countTextColorDisabled,\n        '--n-color': color,\n        '--n-font-size': fontSize,\n        '--n-font-weight': fontWeight,\n        '--n-border-radius': borderRadius,\n        '--n-height': height,\n        '--n-padding-left': paddingLeft,\n        '--n-padding-right': paddingRight,\n        '--n-text-color': textColor,\n        '--n-caret-color': caretColor,\n        '--n-text-decoration-color': textDecorationColor,\n        '--n-border': border,\n        '--n-border-disabled': borderDisabled,\n        '--n-border-hover': borderHover,\n        '--n-border-focus': borderFocus,\n        '--n-placeholder-color': placeholderColor,\n        '--n-placeholder-color-disabled': placeholderColorDisabled,\n        '--n-icon-size': iconSize,\n        '--n-line-height-textarea': lineHeightTextarea,\n        '--n-color-disabled': colorDisabled,\n        '--n-color-focus': colorFocus,\n        '--n-text-color-disabled': textColorDisabled,\n        '--n-box-shadow-focus': boxShadowFocus,\n        '--n-loading-color': loadingColor,\n        // form warning\n        '--n-caret-color-warning': caretColorWarning,\n        '--n-color-focus-warning': colorFocusWarning,\n        '--n-box-shadow-focus-warning': boxShadowFocusWarning,\n        '--n-border-warning': borderWarning,\n        '--n-border-focus-warning': borderFocusWarning,\n        '--n-border-hover-warning': borderHoverWarning,\n        '--n-loading-color-warning': loadingColorWarning,\n        // form error\n        '--n-caret-color-error': caretColorError,\n        '--n-color-focus-error': colorFocusError,\n        '--n-box-shadow-focus-error': boxShadowFocusError,\n        '--n-border-error': borderError,\n        '--n-border-focus-error': borderFocusError,\n        '--n-border-hover-error': borderHoverError,\n        '--n-loading-color-error': loadingColorError,\n        // clear-button\n        '--n-clear-color': clearColor,\n        '--n-clear-size': clearSize,\n        '--n-clear-color-hover': clearColorHover,\n        '--n-clear-color-pressed': clearColorPressed,\n        '--n-icon-color': iconColor,\n        '--n-icon-color-hover': iconColorHover,\n        '--n-icon-color-pressed': iconColorPressed,\n        '--n-icon-color-disabled': iconColorDisabled,\n        '--n-suffix-text-color': suffixTextColor\n      }\n    })\n\n    const themeClassHandle = inlineThemeDisabled\n      ? useThemeClass(\n          'input',\n          computed(() => {\n            const { value: size } = mergedSizeRef\n            return size[0]\n          }),\n          cssVarsRef,\n          props\n        )\n      : undefined\n\n    return {\n      ...exposedProps,\n      // DOM ref\n      wrapperElRef,\n      inputElRef,\n      inputMirrorElRef,\n      inputEl2Ref,\n      textareaElRef,\n      textareaMirrorElRef,\n      textareaScrollbarInstRef,\n      // value\n      rtlEnabled: rtlEnabledRef,\n      uncontrolledValue: uncontrolledValueRef,\n      mergedValue: mergedValueRef,\n      passwordVisible: passwordVisibleRef,\n      mergedPlaceholder: mergedPlaceholderRef,\n      showPlaceholder1: showPlaceholder1Ref,\n      showPlaceholder2: showPlaceholder2Ref,\n      mergedFocus: mergedFocusRef,\n      isComposing: isComposingRef,\n      activated: activatedRef,\n      showClearButton,\n      mergedSize: mergedSizeRef,\n      mergedDisabled: mergedDisabledRef,\n      textDecorationStyle: textDecorationStyleRef,\n      mergedClsPrefix: mergedClsPrefixRef,\n      mergedBordered: mergedBorderedRef,\n      mergedShowPasswordOn: mergedShowPasswordOnRef,\n      placeholderStyle: placeholderStyleRef,\n      mergedStatus: mergedStatusRef,\n      textAreaScrollContainerWidth: textAreaScrollContainerWidthRef,\n      // methods\n      handleTextAreaScroll,\n      handleCompositionStart,\n      handleCompositionEnd,\n      handleInput,\n      handleInputBlur,\n      handleInputFocus,\n      handleWrapperBlur,\n      handleWrapperFocus,\n      handleMouseEnter,\n      handleMouseLeave,\n      handleMouseDown,\n      handleChange,\n      handleClick,\n      handleClear,\n      handlePasswordToggleClick,\n      handlePasswordToggleMousedown,\n      handleWrapperKeydown,\n      handleWrapperKeyup,\n      handleTextAreaMirrorResize,\n      getTextareaScrollContainer: () => {\n        return textareaElRef.value\n      },\n      mergedTheme: themeRef,\n      cssVars: inlineThemeDisabled ? undefined : cssVarsRef,\n      themeClass: themeClassHandle?.themeClass,\n      onRender: themeClassHandle?.onRender\n    }\n  },\n  render() {\n    const {\n      mergedClsPrefix,\n      mergedStatus,\n      themeClass,\n      type,\n      countGraphemes,\n      onRender\n    } = this\n    const $slots = this.$slots as {\n      prefix?: () => VNode[]\n      suffix?: () => VNode[]\n      separator?: () => VNode[]\n      count?: (props: unknown) => VNode[]\n      ['clear-icon']?: () => VNode[]\n      ['clear-icon-placeholder']?: () => VNode[]\n      ['password-visible-icon']?: () => VNode[]\n      ['password-invisible-icon']?: () => VNode[]\n    }\n    onRender?.()\n    return (\n      <div\n        ref=\"wrapperElRef\"\n        class={[\n          `${mergedClsPrefix}-input`,\n          `${mergedClsPrefix}-input--${this.mergedSize}-size`,\n          themeClass,\n          mergedStatus && `${mergedClsPrefix}-input--${mergedStatus}-status`,\n          {\n            [`${mergedClsPrefix}-input--rtl`]: this.rtlEnabled,\n            [`${mergedClsPrefix}-input--disabled`]: this.mergedDisabled,\n            [`${mergedClsPrefix}-input--textarea`]: type === 'textarea',\n            [`${mergedClsPrefix}-input--resizable`]:\n              this.resizable && !this.autosize,\n            [`${mergedClsPrefix}-input--autosize`]: this.autosize,\n            [`${mergedClsPrefix}-input--round`]:\n              this.round && !(type === 'textarea'),\n            [`${mergedClsPrefix}-input--pair`]: this.pair,\n            [`${mergedClsPrefix}-input--focus`]: this.mergedFocus,\n            [`${mergedClsPrefix}-input--stateful`]: this.stateful\n          }\n        ]}\n        style={this.cssVars as CSSProperties}\n        tabindex={\n          !this.mergedDisabled && this.passivelyActivated && !this.activated\n            ? 0\n            : undefined\n        }\n        onFocus={this.handleWrapperFocus}\n        onBlur={this.handleWrapperBlur}\n        onClick={this.handleClick}\n        onMousedown={this.handleMouseDown}\n        onMouseenter={this.handleMouseEnter}\n        onMouseleave={this.handleMouseLeave}\n        onCompositionstart={this.handleCompositionStart}\n        onCompositionend={this.handleCompositionEnd}\n        onKeyup={this.handleWrapperKeyup}\n        onKeydown={this.handleWrapperKeydown}\n      >\n        {/* textarea & basic input */}\n        <div class={`${mergedClsPrefix}-input-wrapper`}>\n          {resolveWrappedSlot(\n            $slots.prefix,\n            children =>\n              children && (\n                <div class={`${mergedClsPrefix}-input__prefix`}>{children}</div>\n              )\n          )}\n          {type === 'textarea' ? (\n            <NScrollbar\n              ref=\"textareaScrollbarInstRef\"\n              class={`${mergedClsPrefix}-input__textarea`}\n              container={this.getTextareaScrollContainer}\n              theme={this.theme?.peers?.Scrollbar}\n              themeOverrides={this.themeOverrides?.peers?.Scrollbar}\n              triggerDisplayManually\n              useUnifiedContainer\n              internalHoistYRail\n            >\n              {{\n                default: () => {\n                  const { textAreaScrollContainerWidth } = this\n                  const scrollContainerWidthStyle = {\n                    width:\n                      this.autosize\n                      && textAreaScrollContainerWidth\n                      && `${textAreaScrollContainerWidth}px`\n                  }\n                  return (\n                    <>\n                      <textarea\n                        {...this.inputProps}\n                        ref=\"textareaElRef\"\n                        class={[\n                          `${mergedClsPrefix}-input__textarea-el`,\n                          this.inputProps?.class\n                        ]}\n                        autofocus={this.autofocus}\n                        rows={Number(this.rows)}\n                        placeholder={this.placeholder as string | undefined}\n                        value={this.mergedValue as string | undefined}\n                        disabled={this.mergedDisabled}\n                        maxlength={countGraphemes ? undefined : this.maxlength}\n                        minlength={countGraphemes ? undefined : this.minlength}\n                        readonly={this.readonly as any}\n                        tabindex={\n                          this.passivelyActivated && !this.activated\n                            ? -1\n                            : undefined\n                        }\n                        style={[\n                          this.textDecorationStyle[0] as any,\n                          this.inputProps?.style,\n                          scrollContainerWidthStyle\n                        ]}\n                        onBlur={this.handleInputBlur}\n                        onFocus={(e) => {\n                          this.handleInputFocus(e, 2)\n                        }}\n                        onInput={this.handleInput}\n                        onChange={this.handleChange}\n                        onScroll={this.handleTextAreaScroll}\n                      />\n                      {this.showPlaceholder1 ? (\n                        <div\n                          class={`${mergedClsPrefix}-input__placeholder`}\n                          style={[\n                            this.placeholderStyle as any,\n                            scrollContainerWidthStyle\n                          ]}\n                          key=\"placeholder\"\n                        >\n                          {this.mergedPlaceholder[0]}\n                        </div>\n                      ) : null}\n                      {this.autosize ? (\n                        <VResizeObserver\n                          onResize={this.handleTextAreaMirrorResize}\n                        >\n                          {{\n                            default: () => (\n                              <div\n                                ref=\"textareaMirrorElRef\"\n                                class={`${mergedClsPrefix}-input__textarea-mirror`}\n                                key=\"mirror\"\n                              />\n                            )\n                          }}\n                        </VResizeObserver>\n                      ) : null}\n                    </>\n                  )\n                }\n              }}\n            </NScrollbar>\n          ) : (\n            <div class={`${mergedClsPrefix}-input__input`}>\n              <input\n                type={\n                  type === 'password'\n                  && this.mergedShowPasswordOn\n                  && this.passwordVisible\n                    ? 'text'\n                    : type\n                }\n                {...this.inputProps}\n                ref=\"inputElRef\"\n                class={[\n                  `${mergedClsPrefix}-input__input-el`,\n                  this.inputProps?.class\n                ]}\n                style={[\n                  this.textDecorationStyle[0] as any,\n                  this.inputProps?.style\n                ]}\n                tabindex={\n                  this.passivelyActivated && !this.activated\n                    ? -1\n                    : this.inputProps?.tabindex\n                }\n                placeholder={this.mergedPlaceholder[0]}\n                disabled={this.mergedDisabled}\n                maxlength={countGraphemes ? undefined : this.maxlength}\n                minlength={countGraphemes ? undefined : this.minlength}\n                value={\n                  Array.isArray(this.mergedValue)\n                    ? this.mergedValue[0]\n                    : (this.mergedValue as any)\n                }\n                readonly={this.readonly as any}\n                autofocus={this.autofocus}\n                size={this.attrSize}\n                onBlur={this.handleInputBlur}\n                onFocus={(e) => {\n                  this.handleInputFocus(e, 0)\n                }}\n                onInput={(e) => {\n                  this.handleInput(e, 0)\n                }}\n                onChange={(e) => {\n                  this.handleChange(e, 0)\n                }}\n              />\n              {this.showPlaceholder1 ? (\n                <div class={`${mergedClsPrefix}-input__placeholder`}>\n                  <span>{this.mergedPlaceholder[0]}</span>\n                </div>\n              ) : null}\n              {this.autosize ? (\n                <div\n                  class={`${mergedClsPrefix}-input__input-mirror`}\n                  key=\"mirror\"\n                  ref=\"inputMirrorElRef\"\n                >\n                  &nbsp;\n                </div>\n              ) : null}\n            </div>\n          )}\n          {!this.pair\n            && resolveWrappedSlot($slots.suffix, (children) => {\n              return children\n                || this.clearable\n                || this.showCount\n                || this.mergedShowPasswordOn\n                || this.loading !== undefined ? (\n                    <div class={`${mergedClsPrefix}-input__suffix`}>\n                      {[\n                        resolveWrappedSlot(\n                          $slots['clear-icon-placeholder'],\n                          (children) => {\n                            return (\n                              (this.clearable || children) && (\n                                <NBaseClear\n                                  clsPrefix={mergedClsPrefix}\n                                  show={this.showClearButton}\n                                  onClear={this.handleClear}\n                                >\n                                  {{\n                                    placeholder: () => children,\n                                    icon: () => this.$slots['clear-icon']?.()\n                                  }}\n                                </NBaseClear>\n                              )\n                            )\n                          }\n                        ),\n                        !this.internalLoadingBeforeSuffix ? children : null,\n                        this.loading !== undefined ? (\n                          <NBaseSuffix\n                            clsPrefix={mergedClsPrefix}\n                            loading={this.loading}\n                            showArrow={false}\n                            showClear={false}\n                            style={this.cssVars as CSSProperties}\n                          />\n                        ) : null,\n                        this.internalLoadingBeforeSuffix ? children : null,\n                        this.showCount && this.type !== 'textarea' ? (\n                          <WordCount>\n                            {{\n                              default: (props: unknown) => {\n                                const { renderCount } = this\n                                if (renderCount) {\n                                  return renderCount(props as { value: string })\n                                }\n                                return $slots.count?.(props)\n                              }\n                            }}\n                          </WordCount>\n                        ) : null,\n                        this.mergedShowPasswordOn && this.type === 'password' ? (\n                          <div\n                            class={`${mergedClsPrefix}-input__eye`}\n                            onMousedown={this.handlePasswordToggleMousedown}\n                            onClick={this.handlePasswordToggleClick}\n                          >\n                            {this.passwordVisible\n                              ? resolveSlot($slots['password-visible-icon'], () => [\n                                  <NBaseIcon clsPrefix={mergedClsPrefix}>\n                                    {{ default: () => <EyeIcon /> }}\n                                  </NBaseIcon>\n                                ])\n                              : resolveSlot(\n                                  $slots['password-invisible-icon'],\n                                  () => [\n                                    <NBaseIcon clsPrefix={mergedClsPrefix}>\n                                      {{ default: () => <EyeOffIcon /> }}\n                                    </NBaseIcon>\n                                  ]\n                                )}\n                          </div>\n                        ) : null\n                      ]}\n                    </div>\n                  ) : null\n            })}\n        </div>\n        {/* pair input */}\n        {this.pair ? (\n          <span class={`${mergedClsPrefix}-input__separator`}>\n            {resolveSlot($slots.separator, () => [this.separator])}\n          </span>\n        ) : null}\n        {this.pair ? (\n          <div class={`${mergedClsPrefix}-input-wrapper`}>\n            <div class={`${mergedClsPrefix}-input__input`}>\n              <input\n                ref=\"inputEl2Ref\"\n                type={this.type}\n                class={`${mergedClsPrefix}-input__input-el`}\n                tabindex={\n                  this.passivelyActivated && !this.activated ? -1 : undefined\n                }\n                placeholder={this.mergedPlaceholder[1]}\n                disabled={this.mergedDisabled}\n                maxlength={countGraphemes ? undefined : this.maxlength}\n                minlength={countGraphemes ? undefined : this.minlength}\n                value={\n                  Array.isArray(this.mergedValue)\n                    ? this.mergedValue[1]\n                    : undefined\n                }\n                readonly={this.readonly as any}\n                style={this.textDecorationStyle[1] as any}\n                onBlur={this.handleInputBlur}\n                onFocus={(e) => {\n                  this.handleInputFocus(e, 1)\n                }}\n                onInput={(e) => {\n                  this.handleInput(e, 1)\n                }}\n                onChange={(e) => {\n                  this.handleChange(e, 1)\n                }}\n              />\n              {this.showPlaceholder2 ? (\n                <div class={`${mergedClsPrefix}-input__placeholder`}>\n                  <span>{this.mergedPlaceholder[1]}</span>\n                </div>\n              ) : null}\n            </div>\n            {resolveWrappedSlot($slots.suffix, (children) => {\n              return (\n                (this.clearable || children) && (\n                  <div class={`${mergedClsPrefix}-input__suffix`}>\n                    {[\n                      this.clearable && (\n                        <NBaseClear\n                          clsPrefix={mergedClsPrefix}\n                          show={this.showClearButton}\n                          onClear={this.handleClear}\n                        >\n                          {{\n                            icon: () => $slots['clear-icon']?.(),\n                            placeholder: () =>\n                              $slots['clear-icon-placeholder']?.()\n                          }}\n                        </NBaseClear>\n                      ),\n                      children\n                    ]}\n                  </div>\n                )\n              )\n            })}\n          </div>\n        ) : null}\n        {/* border */}\n        {this.mergedBordered ? (\n          <div class={`${mergedClsPrefix}-input__border`} />\n        ) : null}\n        {this.mergedBordered ? (\n          <div class={`${mergedClsPrefix}-input__state-border`} />\n        ) : null}\n        {this.showCount && type === 'textarea' ? (\n          <WordCount>\n            {{\n              default: (props: unknown) => {\n                const { renderCount } = this\n                if (renderCount) {\n                  return renderCount(props as { value: string })\n                }\n                return $slots.count?.(props)\n              }\n            }}\n          </WordCount>\n        ) : null}\n      </div>\n    )\n  }\n})\n"
  },
  {
    "path": "src/input/src/InputGroup.tsx",
    "content": "import type { ExtractPublicPropTypes } from '../../_utils'\nimport { defineComponent, h } from 'vue'\nimport { useConfig, useStyle } from '../../_mixins'\nimport style from './styles/input-group.cssr'\n\nexport const inputGroupProps: { [key in any]: never } = {}\n\nexport type InputGroupProps = ExtractPublicPropTypes<typeof inputGroupProps>\n\nexport default defineComponent({\n  name: 'InputGroup',\n  props: inputGroupProps,\n  setup(props) {\n    const { mergedClsPrefixRef } = useConfig(props)\n    useStyle('-input-group', style, mergedClsPrefixRef)\n    return {\n      mergedClsPrefix: mergedClsPrefixRef\n    }\n  },\n  render() {\n    const { mergedClsPrefix } = this\n    return <div class={`${mergedClsPrefix}-input-group`}>{this.$slots}</div>\n  }\n})\n"
  },
  {
    "path": "src/input/src/InputGroupLabel.tsx",
    "content": "import type { PropType } from 'vue'\nimport type { ThemeProps } from '../../_mixins'\nimport type { ExtractPublicPropTypes } from '../../_utils'\nimport type { InputTheme } from '../styles'\nimport type { InputSize } from './public-types'\nimport { computed, defineComponent, h } from 'vue'\nimport { useConfig, useFormItem, useTheme, useThemeClass } from '../../_mixins'\nimport { createKey } from '../../_utils'\nimport { inputLight } from '../styles'\nimport style from './styles/input-group-label.cssr'\n\nexport const inputGroupLabelProps = {\n  ...(useTheme.props as ThemeProps<InputTheme>),\n  size: String as PropType<InputSize>,\n  bordered: {\n    type: Boolean as PropType<boolean | undefined>,\n    default: undefined\n  }\n} as const\n\nexport type InputGroupLabelProps = ExtractPublicPropTypes<\n  typeof inputGroupLabelProps\n>\n\nexport default defineComponent({\n  name: 'InputGroupLabel',\n  props: inputGroupLabelProps,\n  setup(props) {\n    const {\n      mergedBorderedRef,\n      mergedClsPrefixRef,\n      inlineThemeDisabled,\n      mergedComponentPropsRef\n    } = useConfig(props)\n    const themeRef = useTheme(\n      'Input',\n      '-input-group-label',\n      style,\n      inputLight,\n      props,\n      mergedClsPrefixRef\n    )\n    const { mergedSizeRef } = useFormItem(props, {\n      mergedSize(NFormItem) {\n        if (props.size !== undefined)\n          return props.size\n        if (NFormItem) {\n          return NFormItem.mergedSize.value as InputSize\n        }\n        const configSize = mergedComponentPropsRef?.value?.Input?.size\n        if (configSize)\n          return configSize\n        return 'medium'\n      }\n    })\n    const cssVarsRef = computed(() => {\n      const { value: size } = mergedSizeRef\n      const {\n        common: { cubicBezierEaseInOut },\n        self: {\n          groupLabelColor,\n          borderRadius,\n          groupLabelTextColor,\n          lineHeight,\n          groupLabelBorder,\n          [createKey('fontSize', size)]: fontSize,\n          [createKey('height', size)]: height\n        }\n      } = themeRef.value\n      return {\n        '--n-bezier': cubicBezierEaseInOut,\n        '--n-group-label-color': groupLabelColor,\n        '--n-group-label-border': groupLabelBorder,\n        '--n-border-radius': borderRadius,\n        '--n-group-label-text-color': groupLabelTextColor,\n        '--n-font-size': fontSize,\n        '--n-line-height': lineHeight,\n        '--n-height': height\n      }\n    })\n    const themeClassHandle = inlineThemeDisabled\n      ? useThemeClass(\n          'input-group-label',\n          computed(() => mergedSizeRef.value[0]),\n          cssVarsRef,\n          props\n        )\n      : undefined\n    return {\n      mergedClsPrefix: mergedClsPrefixRef,\n      mergedBordered: mergedBorderedRef,\n      cssVars: inlineThemeDisabled ? undefined : cssVarsRef,\n      themeClass: themeClassHandle?.themeClass,\n      onRender: themeClassHandle?.onRender\n    }\n  },\n  render() {\n    const { mergedClsPrefix } = this\n    this.onRender?.()\n    return (\n      <div\n        class={[`${mergedClsPrefix}-input-group-label`, this.themeClass]}\n        style={this.cssVars as any}\n      >\n        {this.$slots.default?.()}\n        {this.mergedBordered ? (\n          <div class={`${mergedClsPrefix}-input-group-label__border`} />\n        ) : null}\n      </div>\n    )\n  }\n})\n"
  },
  {
    "path": "src/input/src/WordCount.tsx",
    "content": "import { computed, defineComponent, h, inject } from 'vue'\nimport { resolveSlotWithTypedProps } from '../../_utils'\nimport { inputInjectionKey } from './interface'\nimport { len } from './utils'\n\nexport default defineComponent({\n  name: 'InputWordCount',\n  setup(_, { slots }) {\n    const {\n      mergedValueRef,\n      maxlengthRef,\n      mergedClsPrefixRef,\n      countGraphemesRef\n    } = inject(inputInjectionKey)!\n    const wordCountRef = computed(() => {\n      const { value: mergedValue } = mergedValueRef\n      if (mergedValue === null || Array.isArray(mergedValue))\n        return 0\n      return (countGraphemesRef.value || len)(mergedValue)\n    })\n    return () => {\n      const { value: maxlength } = maxlengthRef\n      const { value: mergedValue } = mergedValueRef\n      return (\n        <span class={`${mergedClsPrefixRef.value}-input-word-count`}>\n          {resolveSlotWithTypedProps(\n            slots.default,\n            {\n              value:\n                mergedValue === null || Array.isArray(mergedValue)\n                  ? ''\n                  : mergedValue\n            },\n            () => [\n              maxlength === undefined\n                ? wordCountRef.value\n                : `${wordCountRef.value} / ${maxlength}`\n            ]\n          )}\n        </span>\n      )\n    }\n  }\n})\n"
  },
  {
    "path": "src/input/src/interface.ts",
    "content": "import type { Ref } from 'vue'\nimport { createInjectionKey } from '../../_utils'\n\nexport type OnUpdateValue = (\n  value: string & [string, string],\n  meta: { source: 0 | 1 | 'clear' }\n) => void\nexport type OnUpdateValueImpl = (\n  value: string | [string, string],\n  meta: { source: 0 | 1 | 'clear' }\n) => void\n\nexport interface InputWrappedRef {\n  wrapperElRef: Ref<HTMLElement | null>\n  textareaElRef: Ref<HTMLTextAreaElement | null>\n  inputElRef: Ref<HTMLInputElement | null>\n  isCompositing: Ref<boolean>\n  blur: () => void\n  clear: () => void\n  focus: () => void\n  select: () => void\n  activate: () => void\n  deactivate: () => void\n  scrollTo: (options: ScrollToOptions) => void\n}\n\nexport const inputInjectionKey = createInjectionKey<{\n  countGraphemesRef: Ref<((input: string) => number) | undefined>\n  mergedValueRef: Ref<string | [string, string] | null>\n  maxlengthRef: Ref<number | undefined>\n  mergedClsPrefixRef: Ref<string>\n}>('n-input')\n"
  },
  {
    "path": "src/input/src/public-types.ts",
    "content": "import type { UnwrapRef } from 'vue'\nimport type { InputWrappedRef } from './interface'\n\nexport type InputSize = 'tiny' | 'small' | 'medium' | 'large'\n\nexport type InputInst = UnwrapRef<InputWrappedRef>\n"
  },
  {
    "path": "src/input/src/styles/input-group-label.cssr.ts",
    "content": "import { cB, cE } from '../../../_utils/cssr'\n\n// vars:\n// --n-bezier\n// --n-group-label-color\n// --n-border-radius\n// --n-group-label-text-color\n// --n-font-size\n// --n-height\n// --n-group-label-border\nexport default cB('input-group-label', `\n  position: relative;\n  user-select: none;\n  -webkit-user-select: none;\n  box-sizing: border-box;\n  padding: 0 12px;\n  display: inline-block;\n  border-radius: var(--n-border-radius);\n  background-color: var(--n-group-label-color);\n  color: var(--n-group-label-text-color);\n  font-size: var(--n-font-size);\n  line-height: var(--n-height);\n  height: var(--n-height);\n  flex-shrink: 0;\n  white-space: nowrap;\n  transition: \n    color .3s var(--n-bezier),\n    background-color .3s var(--n-bezier),\n    box-shadow .3s var(--n-bezier);\n`, [\n  cE('border', `\n    position: absolute;\n    left: 0;\n    right: 0;\n    top: 0;\n    bottom: 0;\n    border-radius: inherit;\n    border: var(--n-group-label-border);\n    transition: border-color .3s var(--n-bezier);\n  `)\n])\n"
  },
  {
    "path": "src/input/src/styles/input-group.cssr.ts",
    "content": "import { c, cB, cE } from '../../../_utils/cssr'\n\nexport default cB('input-group', `\n  display: inline-flex;\n  width: 100%;\n  flex-wrap: nowrap;\n  vertical-align: bottom;\n`, [\n  c('>', [\n    cB('input', [\n      c('&:not(:last-child)', `\n        border-top-right-radius: 0!important;\n        border-bottom-right-radius: 0!important;\n      `),\n      c('&:not(:first-child)', `\n        border-top-left-radius: 0!important;\n        border-bottom-left-radius: 0!important;\n        margin-left: -1px!important;\n      `)\n    ]),\n    cB('button', [\n      c('&:not(:last-child)', `\n        border-top-right-radius: 0!important;\n        border-bottom-right-radius: 0!important;\n      `, [\n        cE('state-border, border', `\n          border-top-right-radius: 0!important;\n          border-bottom-right-radius: 0!important;\n        `)\n      ]),\n      c('&:not(:first-child)', `\n        border-top-left-radius: 0!important;\n        border-bottom-left-radius: 0!important;\n      `, [\n        cE('state-border, border', `\n          border-top-left-radius: 0!important;\n          border-bottom-left-radius: 0!important;\n        `)\n      ])\n    ]),\n    c('*', [\n      c('&:not(:last-child)', `\n        border-top-right-radius: 0!important;\n        border-bottom-right-radius: 0!important;\n      `, [\n        c('>', [\n          cB('input', `\n            border-top-right-radius: 0!important;\n            border-bottom-right-radius: 0!important;\n          `),\n          cB('base-selection', [\n            cB('base-selection-label', `\n              border-top-right-radius: 0!important;\n              border-bottom-right-radius: 0!important;\n            `),\n            cB('base-selection-tags', `\n              border-top-right-radius: 0!important;\n              border-bottom-right-radius: 0!important;\n            `),\n            cE('box-shadow, border, state-border', `\n              border-top-right-radius: 0!important;\n              border-bottom-right-radius: 0!important;\n            `)\n          ])\n        ])\n      ]),\n      c('&:not(:first-child)', `\n        margin-left: -1px!important;\n        border-top-left-radius: 0!important;\n        border-bottom-left-radius: 0!important;\n      `, [\n        c('>', [\n          cB('input', `\n            border-top-left-radius: 0!important;\n            border-bottom-left-radius: 0!important;\n          `),\n          cB('base-selection', [\n            cB('base-selection-label', `\n              border-top-left-radius: 0!important;\n              border-bottom-left-radius: 0!important;\n            `),\n            cB('base-selection-tags', `\n              border-top-left-radius: 0!important;\n              border-bottom-left-radius: 0!important;\n            `),\n            cE('box-shadow, border, state-border', `\n              border-top-left-radius: 0!important;\n              border-bottom-left-radius: 0!important;\n            `)\n          ])\n        ])\n      ])\n    ])\n  ])\n])\n"
  },
  {
    "path": "src/input/src/styles/input.cssr.ts",
    "content": "import { c, cB, cE, cM, cNotM } from '../../../_utils/cssr'\n\n// vars:\n// --n-bezier\n// --n-color\n// --n-font-size\n// --n-border-radius\n// --n-height\n// --n-padding-left\n// --n-padding-right\n// --n-text-color\n// --n-text-color-disabled\n// --n-caret-color\n// --n-text-decoration-color\n// --n-border\n// --n-border-disabled\n// --n-border-hover\n// --n-border-focus\n// --n-placeholder-color\n// --n-placeholder-color-disabled\n// --n-line-height-textarea\n// --n-color-disabled\n// --n-color-focus\n// --n-box-shadow-focus\n// --n-clear-color\n// --n-clear-size\n// --n-clear-color-hover\n// --n-clear-color-pressed\n// --n-suffix-text-color\n// --n-icon-color\n// --n-icon-color-hover\n// --n-icon-color-pressed\n// --n-icon-color-disabled\n// --n-count-text-color\n// --n-count-text-color-disabled\n// --n-loading-color\n// ...form item vars\nexport default cB('input', `\n  max-width: 100%;\n  cursor: text;\n  line-height: 1.5;\n  z-index: auto;\n  outline: none;\n  box-sizing: border-box;\n  position: relative;\n  display: inline-flex;\n  border-radius: var(--n-border-radius);\n  background-color: var(--n-color);\n  transition: background-color .3s var(--n-bezier);\n  font-size: var(--n-font-size);\n  font-weight: var(--n-font-weight);\n  --n-padding-vertical: calc((var(--n-height) - 1.5 * var(--n-font-size)) / 2);\n`, [\n  // common\n  cE('input, textarea', `\n    overflow: hidden;\n    flex-grow: 1;\n    position: relative;\n  `),\n  cE('input-el, textarea-el, input-mirror, textarea-mirror, separator, placeholder', `\n    box-sizing: border-box;\n    font-size: inherit;\n    line-height: 1.5;\n    font-family: inherit;\n    border: none;\n    outline: none;\n    background-color: #0000;\n    text-align: inherit;\n    transition:\n      -webkit-text-fill-color .3s var(--n-bezier),\n      caret-color .3s var(--n-bezier),\n      color .3s var(--n-bezier),\n      text-decoration-color .3s var(--n-bezier);\n  `),\n  cE('input-el, textarea-el', `\n    -webkit-appearance: none;\n    scrollbar-width: none;\n    width: 100%;\n    min-width: 0;\n    text-decoration-color: var(--n-text-decoration-color);\n    color: var(--n-text-color);\n    caret-color: var(--n-caret-color);\n    background-color: transparent;\n  `, [\n    c('&::-webkit-scrollbar, &::-webkit-scrollbar-track-piece, &::-webkit-scrollbar-thumb', `\n      width: 0;\n      height: 0;\n      display: none;\n    `),\n    c('&::placeholder', `\n      color: #0000;\n      -webkit-text-fill-color: transparent !important;\n    `),\n    c('&:-webkit-autofill ~', [\n      cE('placeholder', 'display: none;')\n    ])\n  ]),\n  cM('round', [\n    cNotM('textarea', 'border-radius: calc(var(--n-height) / 2);')\n  ]),\n  cE('placeholder', `\n    pointer-events: none;\n    position: absolute;\n    left: 0;\n    right: 0;\n    top: 0;\n    bottom: 0;\n    overflow: hidden;\n    color: var(--n-placeholder-color);\n  `, [\n    c('span', `\n      width: 100%;\n      display: inline-block;\n    `)\n  ]),\n  cM('textarea', [\n    cE('placeholder', 'overflow: visible;')\n  ]),\n  cNotM('autosize', 'width: 100%;'),\n  cM('autosize', [\n    cE('textarea-el, input-el', `\n      position: absolute;\n      top: 0;\n      left: 0;\n      height: 100%;\n    `)\n  ]),\n  // input\n  cB('input-wrapper', `\n    overflow: hidden;\n    display: inline-flex;\n    flex-grow: 1;\n    position: relative;\n    padding-left: var(--n-padding-left);\n    padding-right: var(--n-padding-right);\n  `),\n  cE('input-mirror', `\n    padding: 0;\n    height: var(--n-height);\n    line-height: var(--n-height);\n    overflow: hidden;\n    visibility: hidden;\n    position: static;\n    white-space: pre;\n    pointer-events: none;\n  `),\n  cE('input-el', `\n    padding: 0;\n    height: var(--n-height);\n    line-height: var(--n-height);\n  `, [\n    c('&[type=password]::-ms-reveal', 'display: none;'),\n    c('+', [\n      cE('placeholder', `\n        display: flex;\n        align-items: center;  \n      `)\n    ])\n  ]),\n  cNotM('textarea', [\n    cE('placeholder', 'white-space: nowrap;')\n  ]),\n  cE('eye', `\n    display: flex;\n    align-items: center;\n    justify-content: center;\n    transition: color .3s var(--n-bezier);\n  `),\n  // textarea\n  cM('textarea', 'width: 100%;', [\n    cB('input-word-count', `\n      position: absolute;\n      right: var(--n-padding-right);\n      bottom: var(--n-padding-vertical);\n    `),\n    cM('resizable', [\n      cB('input-wrapper', `\n        resize: vertical;\n        min-height: var(--n-height);\n      `)\n    ]),\n    cE('textarea-el, textarea-mirror, placeholder', `\n      height: 100%;\n      padding-left: 0;\n      padding-right: 0;\n      padding-top: var(--n-padding-vertical);\n      padding-bottom: var(--n-padding-vertical);\n      word-break: break-word;\n      display: inline-block;\n      vertical-align: bottom;\n      box-sizing: border-box;\n      line-height: var(--n-line-height-textarea);\n      margin: 0;\n      resize: none;\n      white-space: pre-wrap;\n      scroll-padding-block-end: var(--n-padding-vertical);\n    `),\n    cE('textarea-mirror', `\n      width: 100%;\n      pointer-events: none;\n      overflow: hidden;\n      visibility: hidden;\n      position: static;\n      white-space: pre-wrap;\n      overflow-wrap: break-word;\n    `)\n  ]),\n  // pair\n  cM('pair', [\n    cE('input-el, placeholder', 'text-align: center;'),\n    cE('separator', `\n      display: flex;\n      align-items: center;\n      transition: color .3s var(--n-bezier);\n      color: var(--n-text-color);\n      white-space: nowrap;\n    `, [\n      cB('icon', `\n        color: var(--n-icon-color);\n      `),\n      cB('base-icon', `\n        color: var(--n-icon-color);\n      `)\n    ])\n  ]),\n  cM('disabled', `\n    cursor: not-allowed;\n    background-color: var(--n-color-disabled);\n  `, [\n    cE('border', 'border: var(--n-border-disabled);'),\n    cE('input-el, textarea-el', `\n      cursor: not-allowed;\n      color: var(--n-text-color-disabled);\n      text-decoration-color: var(--n-text-color-disabled);\n    `),\n    cE('placeholder', 'color: var(--n-placeholder-color-disabled);'),\n    cE('separator', 'color: var(--n-text-color-disabled);', [\n      cB('icon', `\n        color: var(--n-icon-color-disabled);\n      `),\n      cB('base-icon', `\n        color: var(--n-icon-color-disabled);\n      `)\n    ]),\n    cB('input-word-count', `\n      color: var(--n-count-text-color-disabled);\n    `),\n    cE('suffix, prefix', 'color: var(--n-text-color-disabled);', [\n      cB('icon', `\n        color: var(--n-icon-color-disabled);\n      `),\n      cB('internal-icon', `\n        color: var(--n-icon-color-disabled);\n      `)\n    ])\n  ]),\n  cNotM('disabled', [\n    cE('eye', `\n      color: var(--n-icon-color);\n      cursor: pointer;\n    `, [\n      c('&:hover', `\n        color: var(--n-icon-color-hover);\n      `),\n      c('&:active', `\n        color: var(--n-icon-color-pressed);\n      `)\n    ]),\n    c('&:hover', [\n      cE('state-border', 'border: var(--n-border-hover);')\n    ]),\n    cM('focus', 'background-color: var(--n-color-focus);', [\n      cE('state-border', `\n        border: var(--n-border-focus);\n        box-shadow: var(--n-box-shadow-focus);\n      `)\n    ])\n  ]),\n  cE('border, state-border', `\n    box-sizing: border-box;\n    position: absolute;\n    left: 0;\n    right: 0;\n    top: 0;\n    bottom: 0;\n    pointer-events: none;\n    border-radius: inherit;\n    border: var(--n-border);\n    transition:\n      box-shadow .3s var(--n-bezier),\n      border-color .3s var(--n-bezier);\n  `),\n  cE('state-border', `\n    border-color: #0000;\n    z-index: 1;\n  `),\n  cE('prefix', 'margin-right: 4px;'),\n  cE('suffix', `\n    margin-left: 4px;\n  `),\n  cE('suffix, prefix', `\n    transition: color .3s var(--n-bezier);\n    flex-wrap: nowrap;\n    flex-shrink: 0;\n    line-height: var(--n-height);\n    white-space: nowrap;\n    display: inline-flex;\n    align-items: center;\n    justify-content: center;\n    color: var(--n-suffix-text-color);\n  `, [\n    cB('base-loading', `\n      font-size: var(--n-icon-size);\n      margin: 0 2px;\n      color: var(--n-loading-color);\n    `),\n    cB('base-clear', `\n      font-size: var(--n-icon-size);\n    `, [\n      cE('placeholder', [\n        cB('base-icon', `\n          transition: color .3s var(--n-bezier);\n          color: var(--n-icon-color);\n          font-size: var(--n-icon-size);\n        `)\n      ])\n    ]),\n    c('>', [\n      cB('icon', `\n        transition: color .3s var(--n-bezier);\n        color: var(--n-icon-color);\n        font-size: var(--n-icon-size);\n      `)\n    ]),\n    cB('base-icon', `\n      font-size: var(--n-icon-size);\n    `)\n  ]),\n  cB('input-word-count', `\n    pointer-events: none;\n    line-height: 1.5;\n    font-size: .85em;\n    color: var(--n-count-text-color);\n    transition: color .3s var(--n-bezier);\n    margin-left: 4px;\n    font-variant: tabular-nums;\n  `),\n  ['warning', 'error'].map(status => cM(`${status}-status`, [\n    cNotM('disabled', [\n      cB('base-loading', `\n        color: var(--n-loading-color-${status})\n      `),\n      cE('input-el, textarea-el', `\n        caret-color: var(--n-caret-color-${status});\n      `),\n      cE('state-border', `\n        border: var(--n-border-${status});\n      `),\n      c('&:hover', [\n        cE('state-border', `\n          border: var(--n-border-hover-${status});\n        `)\n      ]),\n      c('&:focus', `\n        background-color: var(--n-color-focus-${status});\n      `, [\n        cE('state-border', `\n          box-shadow: var(--n-box-shadow-focus-${status});\n          border: var(--n-border-focus-${status});\n        `)\n      ]),\n      cM('focus', `\n        background-color: var(--n-color-focus-${status});\n      `, [\n        cE('state-border', `\n          box-shadow: var(--n-box-shadow-focus-${status});\n          border: var(--n-border-focus-${status});\n        `)\n      ])\n    ])\n  ]))\n])\n\nexport const safariStyle = cB('input', [\n  cM('disabled', [\n    cE('input-el, textarea-el', `\n      -webkit-text-fill-color: var(--n-text-color-disabled);\n    `)\n  ])\n])\n"
  },
  {
    "path": "src/input/src/styles/rtl.cssr.ts",
    "content": "import { cB, cE, cM } from '../../../_utils/cssr'\n\nexport default cB('input', [\n  cM('rtl', `\n    direction: rtl;\n  `, [\n    cE('prefix', {\n      marginRight: 0,\n      marginLeft: '4px'\n    }),\n    cE('suffix', {\n      marginRight: '4px',\n      marginLeft: 0\n    }),\n    cM('textarea', 'width: 100%;', [\n      cB('input-word-count', `\n      left: var(--n-padding-right);\n      right: unset;\n    `)\n    ]),\n    cB('input-word-count', `\n      margin-left: 0;\n      margin-right: 4px;\n    `)\n  ])\n])\n"
  },
  {
    "path": "src/input/src/utils.ts",
    "content": "import type { Ref } from 'vue'\nimport { ref, watch } from 'vue'\n\nexport function len(s: string): number {\n  let count = 0\n  for (const _ of s) {\n    count++\n  }\n  return count\n}\n\nexport function isEmptyInputValue(value: unknown): boolean {\n  return value === '' || value == null\n}\n\nexport interface UseCursorControl {\n  recordCursor: () => void\n  restoreCursor: () => void\n}\n\nexport function useCursor(\n  inputElRef: Ref<HTMLInputElement | HTMLTextAreaElement | null>\n): UseCursorControl {\n  const selectionRef = ref<{\n    start: number\n    end: number\n    beforeText: string\n    afterText: string\n  } | null>(null)\n\n  function recordCursor(): void {\n    const { value: input } = inputElRef\n    if (!input?.focus) {\n      reset()\n      return\n    }\n    const { selectionStart, selectionEnd, value } = input\n    if (selectionStart == null || selectionEnd == null) {\n      reset()\n      return\n    }\n    selectionRef.value = {\n      start: selectionStart,\n      end: selectionEnd,\n      beforeText: value.slice(0, selectionStart),\n      afterText: value.slice(selectionEnd)\n    }\n  }\n\n  function restoreCursor(): void {\n    const { value: selection } = selectionRef\n    const { value: inputEl } = inputElRef\n    if (!selection || !inputEl) {\n      return\n    }\n    const { value } = inputEl\n    const { start, beforeText, afterText } = selection\n    let startPos = value.length\n    if (value.endsWith(afterText)) {\n      startPos = value.length - afterText.length\n    }\n    else if (value.startsWith(beforeText)) {\n      startPos = beforeText.length\n    }\n    else {\n      const beforeLastChar = beforeText[start - 1]\n      const newIndex = value.indexOf(beforeLastChar, start - 1)\n      if (newIndex !== -1) {\n        startPos = newIndex + 1\n      }\n    }\n    inputEl.setSelectionRange?.(startPos, startPos)\n  }\n\n  function reset(): void {\n    selectionRef.value = null\n  }\n  watch(inputElRef, reset)\n\n  return {\n    recordCursor,\n    restoreCursor\n  }\n}\n"
  },
  {
    "path": "src/input/styles/_common.ts",
    "content": "export default {\n  paddingTiny: '0 8px',\n  paddingSmall: '0 10px',\n  paddingMedium: '0 12px',\n  paddingLarge: '0 14px',\n  clearSize: '16px'\n}\n"
  },
  {
    "path": "src/input/styles/dark.ts",
    "content": "import type { ThemeCommonVars } from '../../_styles/common'\nimport { changeColor } from 'seemly'\nimport { scrollbarDark } from '../../_internal/scrollbar/styles'\nimport { createTheme } from '../../_mixins'\nimport { commonDark } from '../../_styles/common'\nimport commonVariables from './_common'\n\nfunction self(vars: ThemeCommonVars) {\n  const {\n    textColor2,\n    textColor3,\n    textColorDisabled,\n    primaryColor,\n    primaryColorHover,\n    inputColor,\n    inputColorDisabled,\n    warningColor,\n    warningColorHover,\n    errorColor,\n    errorColorHover,\n    borderRadius,\n    lineHeight,\n    fontSizeTiny,\n    fontSizeSmall,\n    fontSizeMedium,\n    fontSizeLarge,\n    heightTiny,\n    heightSmall,\n    heightMedium,\n    heightLarge,\n    clearColor,\n    clearColorHover,\n    clearColorPressed,\n    placeholderColor,\n    placeholderColorDisabled,\n    iconColor,\n    iconColorDisabled,\n    iconColorHover,\n    iconColorPressed,\n    fontWeight\n  } = vars\n  return {\n    ...commonVariables,\n    fontWeight,\n    countTextColorDisabled: textColorDisabled,\n    countTextColor: textColor3,\n    heightTiny,\n    heightSmall,\n    heightMedium,\n    heightLarge,\n    fontSizeTiny,\n    fontSizeSmall,\n    fontSizeMedium,\n    fontSizeLarge,\n    lineHeight,\n    lineHeightTextarea: lineHeight,\n    borderRadius,\n    iconSize: '16px',\n    groupLabelColor: inputColor,\n    textColor: textColor2,\n    textColorDisabled,\n    textDecorationColor: textColor2,\n    groupLabelTextColor: textColor2,\n    caretColor: primaryColor,\n    placeholderColor,\n    placeholderColorDisabled,\n    color: inputColor,\n    colorDisabled: inputColorDisabled,\n    colorFocus: changeColor(primaryColor, { alpha: 0.1 }),\n    groupLabelBorder: '1px solid #0000',\n    border: '1px solid #0000',\n    borderHover: `1px solid ${primaryColorHover}`,\n    borderDisabled: '1px solid #0000',\n    borderFocus: `1px solid ${primaryColorHover}`,\n    boxShadowFocus: `0 0 8px 0 ${changeColor(primaryColor, { alpha: 0.3 })}`,\n    loadingColor: primaryColor,\n    // warning\n    loadingColorWarning: warningColor,\n    borderWarning: `1px solid ${warningColor}`,\n    borderHoverWarning: `1px solid ${warningColorHover}`,\n    colorFocusWarning: changeColor(warningColor, { alpha: 0.1 }),\n    borderFocusWarning: `1px solid ${warningColorHover}`,\n    boxShadowFocusWarning: `0 0 8px 0 ${changeColor(warningColor, {\n      alpha: 0.3\n    })}`,\n    caretColorWarning: warningColor,\n    // error\n    loadingColorError: errorColor,\n    borderError: `1px solid ${errorColor}`,\n    borderHoverError: `1px solid ${errorColorHover}`,\n    colorFocusError: changeColor(errorColor, { alpha: 0.1 }),\n    borderFocusError: `1px solid ${errorColorHover}`,\n    boxShadowFocusError: `0 0 8px 0 ${changeColor(errorColor, {\n      alpha: 0.3\n    })}`,\n    caretColorError: errorColor,\n    clearColor,\n    clearColorHover,\n    clearColorPressed,\n    iconColor,\n    iconColorDisabled,\n    iconColorHover,\n    iconColorPressed,\n    suffixTextColor: textColor2\n  }\n}\n\nconst inputDark = createTheme({\n  name: 'Input',\n  common: commonDark,\n  peers: {\n    Scrollbar: scrollbarDark\n  },\n  self\n})\n\nexport type InputThemeVars = ReturnType<typeof self>\nexport default inputDark\n"
  },
  {
    "path": "src/input/styles/index.ts",
    "content": "export { default as inputDark } from './dark'\nexport { default as inputLight } from './light'\nexport type { InputTheme, InputThemeVars } from './light'\nexport { inputRtl } from './rtl'\n"
  },
  {
    "path": "src/input/styles/light.ts",
    "content": "import type { ThemeCommonVars } from '../../_styles/common'\nimport { changeColor } from 'seemly'\nimport { scrollbarLight } from '../../_internal/scrollbar/styles'\nimport { createTheme } from '../../_mixins'\nimport { commonLight } from '../../_styles/common'\nimport commonVariables from './_common'\n\nfunction self(vars: ThemeCommonVars) {\n  const {\n    textColor2,\n    textColor3,\n    textColorDisabled,\n    primaryColor,\n    primaryColorHover,\n    inputColor,\n    inputColorDisabled,\n    borderColor,\n    warningColor,\n    warningColorHover,\n    errorColor,\n    errorColorHover,\n    borderRadius,\n    lineHeight,\n    fontSizeTiny,\n    fontSizeSmall,\n    fontSizeMedium,\n    fontSizeLarge,\n    heightTiny,\n    heightSmall,\n    heightMedium,\n    heightLarge,\n    actionColor,\n    clearColor,\n    clearColorHover,\n    clearColorPressed,\n    placeholderColor,\n    placeholderColorDisabled,\n    iconColor,\n    iconColorDisabled,\n    iconColorHover,\n    iconColorPressed,\n    fontWeight\n  } = vars\n  return {\n    ...commonVariables,\n    fontWeight,\n    countTextColorDisabled: textColorDisabled,\n    countTextColor: textColor3,\n    heightTiny,\n    heightSmall,\n    heightMedium,\n    heightLarge,\n    fontSizeTiny,\n    fontSizeSmall,\n    fontSizeMedium,\n    fontSizeLarge,\n    lineHeight,\n    lineHeightTextarea: lineHeight,\n    borderRadius,\n    iconSize: '16px',\n    groupLabelColor: actionColor,\n    groupLabelTextColor: textColor2,\n    textColor: textColor2,\n    textColorDisabled,\n    textDecorationColor: textColor2,\n    caretColor: primaryColor,\n    placeholderColor,\n    placeholderColorDisabled,\n    color: inputColor,\n    colorDisabled: inputColorDisabled,\n    colorFocus: inputColor,\n    groupLabelBorder: `1px solid ${borderColor}`,\n    border: `1px solid ${borderColor}`,\n    borderHover: `1px solid ${primaryColorHover}`,\n    borderDisabled: `1px solid ${borderColor}`,\n    borderFocus: `1px solid ${primaryColorHover}`,\n    boxShadowFocus: `0 0 0 2px ${changeColor(primaryColor, { alpha: 0.2 })}`,\n    loadingColor: primaryColor,\n    // warning\n    loadingColorWarning: warningColor,\n    borderWarning: `1px solid ${warningColor}`,\n    borderHoverWarning: `1px solid ${warningColorHover}`,\n    colorFocusWarning: inputColor,\n    borderFocusWarning: `1px solid ${warningColorHover}`,\n    boxShadowFocusWarning: `0 0 0 2px ${changeColor(warningColor, {\n      alpha: 0.2\n    })}`,\n    caretColorWarning: warningColor,\n    // error\n    loadingColorError: errorColor,\n    borderError: `1px solid ${errorColor}`,\n    borderHoverError: `1px solid ${errorColorHover}`,\n    colorFocusError: inputColor,\n    borderFocusError: `1px solid ${errorColorHover}`,\n    boxShadowFocusError: `0 0 0 2px ${changeColor(errorColor, {\n      alpha: 0.2\n    })}`,\n    caretColorError: errorColor,\n    clearColor,\n    clearColorHover,\n    clearColorPressed,\n    iconColor,\n    iconColorDisabled,\n    iconColorHover,\n    iconColorPressed,\n    suffixTextColor: textColor2\n  }\n}\n\nconst inputLight = createTheme({\n  name: 'Input',\n  common: commonLight,\n  peers: {\n    Scrollbar: scrollbarLight\n  },\n  self\n})\n\nexport type InputThemeVars = ReturnType<typeof self>\nexport type InputTheme = typeof inputLight\nexport default inputLight\n"
  },
  {
    "path": "src/input/styles/rtl.ts",
    "content": "import type { RtlItem } from '../../config-provider/src/internal-interface'\nimport rtlStyle from '../src/styles/rtl.cssr'\n\nexport const inputRtl: RtlItem = {\n  name: 'Input',\n  style: rtlStyle\n}\n"
  },
  {
    "path": "src/input/tests/Input.spec.tsx",
    "content": "import type { InputInst } from '../index'\nimport { mount } from '@vue/test-utils'\nimport { defineComponent, h, onMounted, ref } from 'vue'\nimport { NInput } from '../index'\nimport InputGroup from '../src/InputGroup'\nimport InputGroupLabel from '../src/InputGroupLabel'\nimport WordCount from '../src/WordCount'\n\ndescribe('n-input', () => {\n  it('should work with import on demand', () => {\n    mount(NInput)\n  })\n\n  it('should call input callbacks', async () => {\n    const onUpdateValue = vi.fn()\n    const wrapper = mount(NInput, {\n      props: {\n        onUpdateValue\n      }\n    })\n    wrapper.find('input').element.value = 'cool'\n    await wrapper.find('input').trigger('input')\n    expect(onUpdateValue).toHaveBeenCalledWith('cool', { source: 0 })\n    wrapper.unmount()\n  })\n\n  it('`loading` prop', async () => {\n    const wrapper = mount(NInput)\n    expect(wrapper.find('.n-input__suffix').exists()).toBe(false)\n    expect(wrapper.find('.n-base-loading__container').exists()).toBe(false)\n    await wrapper.setProps({ loading: false })\n    expect(wrapper.find('.n-input__suffix').exists()).toBe(true)\n    expect(wrapper.find('.n-base-loading__container').exists()).toBe(false)\n    await wrapper.setProps({ loading: true })\n    expect(wrapper.find('.n-base-loading__container').exists()).toBe(true)\n    wrapper.unmount()\n  })\n\n  it('should work with `clearable` prop', async () => {\n    const wrapper = mount(NInput)\n    expect(wrapper.find('.n-base-clear').exists()).not.toBe(true)\n    await wrapper.setProps({\n      clearable: true\n    })\n    expect(wrapper.find('.n-base-clear').exists()).toBe(true)\n    wrapper.unmount()\n  })\n\n  it('should work with `disabled` prop', async () => {\n    const wrapper = mount(NInput)\n    expect(wrapper.find('.n-input').classes()).not.toContain(\n      'n-input--disabled'\n    )\n    await wrapper.setProps({\n      disabled: true\n    })\n    expect(wrapper.find('.n-input').classes()).toContain('n-input--disabled')\n    wrapper.unmount()\n  })\n\n  it('should work with `placeholder` prop', async () => {\n    const wrapper = mount(NInput)\n    expect(wrapper.find('input').attributes('placeholder')).toBe('Please Input')\n    await wrapper.setProps({\n      placeholder: 'test-placeholder'\n    })\n    expect(wrapper.find('input').attributes('placeholder')).toBe(\n      'test-placeholder'\n    )\n    wrapper.unmount()\n  })\n\n  it('should work with `readonly` prop', async () => {\n    const wrapper = mount(NInput)\n    expect(wrapper.find('input').attributes('readonly')).not.toBe('')\n\n    await wrapper.setProps({ readonly: true })\n    expect(wrapper.find('input').attributes('readonly')).toBe('')\n    wrapper.unmount()\n  })\n\n  it('should work with `round` prop', async () => {\n    const wrapper = mount(NInput)\n    expect(wrapper.find('.n-input').classes()).not.toContain('n-input--round')\n\n    await wrapper.setProps({ round: true })\n    expect(wrapper.find('.n-input').classes()).toContain('n-input--round')\n    wrapper.unmount()\n  })\n\n  it('should work with `rows` prop', async () => {\n    const wrapper = mount(NInput, { props: { type: 'textarea' } })\n    expect(wrapper.find('textarea').attributes('rows')).toBe('3')\n\n    await wrapper.setProps({ type: 'textarea', rows: 5 })\n    expect(wrapper.find('textarea').attributes('rows')).toBe('5')\n    wrapper.unmount()\n  })\n\n  it('should work with `size` prop', async () => {\n    ;(['small', 'medium', 'large'] as const).forEach((size) => {\n      const wrapper = mount(NInput, { props: { size } })\n      expect(wrapper.find('.n-input').attributes('style')).toMatchSnapshot()\n      wrapper.unmount()\n    })\n  })\n\n  it('should work with `status` prop', async () => {\n    ;(['success', 'warning', 'error'] as const).forEach((status) => {\n      const wrapper = mount(NInput, { props: { status } })\n      expect(wrapper.find('.n-input').classes()).toContain(\n        `n-input--${status}-status`\n      )\n      wrapper.unmount()\n    })\n  })\n\n  it('should work with `type` prop', async () => {\n    const wrapper = mount(NInput)\n    await wrapper.setProps({ type: 'text' })\n    expect(wrapper.find('input').exists()).toBe(true)\n\n    await wrapper.setProps({ type: 'textarea' })\n    expect(wrapper.find('.n-input').classes()).toContain('n-input--textarea')\n    expect(wrapper.find('textarea').exists()).toBe(true)\n    wrapper.unmount()\n  })\n\n  it('should work with `show-password-on` prop', async () => {\n    let wrapper = mount(NInput, {\n      props: { type: 'password', showPasswordOn: 'click' }\n    })\n    expect(wrapper.find('input').attributes('type')).toBe('password')\n    await wrapper.find('.n-base-icon').trigger('click')\n    expect(wrapper.find('input').attributes('type')).toBe('text')\n\n    wrapper = mount(NInput, {\n      props: { type: 'password', showPasswordOn: 'mousedown' }\n    })\n    expect(wrapper.find('input').attributes('type')).toBe('password')\n    await wrapper.find('.n-base-icon').trigger('mousedown')\n    expect(wrapper.find('input').attributes('type')).toBe('text')\n\n    wrapper.unmount()\n  })\n\n  it('should work with `show-count` prop', async () => {\n    const maxlength = 30\n    const wrapper = mount(NInput)\n    expect(wrapper.findComponent(WordCount).exists()).not.toBe(true)\n\n    await wrapper.setProps({ showCount: true, maxlength })\n    expect(\n      wrapper.find('.n-input__suffix').findComponent(WordCount).exists()\n    ).toBe(true)\n    expect(wrapper.find('.n-input-word-count').text()).toBe(`0 / ${maxlength}`)\n\n    await wrapper.setProps({ showCount: true, maxlength, type: 'textarea' })\n    expect(\n      wrapper.find('.n-input--textarea').findComponent(WordCount).exists()\n    ).toBe(true)\n    expect(wrapper.find('.n-input-word-count').text()).toBe(`0 / ${maxlength}`)\n    wrapper.unmount()\n  })\n\n  it('should work with `pair` `separator` `placeholder` prop', async () => {\n    const wrapper = mount(NInput, {\n      props: { pair: true, separator: '-', placeholder: ['从', '到'] }\n    })\n\n    expect(wrapper.find('.n-input').classes()).toContain('n-input--pair')\n    expect(wrapper.find('.n-input__separator').text()).toBe('-')\n    expect(wrapper.findAll('input')[0].attributes('placeholder')).toBe('从')\n    expect(wrapper.findAll('input')[1].attributes('placeholder')).toBe('到')\n\n    wrapper.unmount()\n  })\n\n  it('should work with `on-blur` prop', async () => {\n    const onBlur = vi.fn()\n    const wrapper = mount(NInput, {\n      props: { onBlur }\n    })\n    await wrapper.find('input').trigger('focus')\n    await wrapper.find('input').trigger('blur')\n    expect(onBlur).toHaveBeenCalled()\n    wrapper.unmount()\n  })\n\n  it('should work with `on-change` prop', async () => {\n    const onChange = vi.fn()\n    const wrapper = mount(NInput, {\n      props: { onChange }\n    })\n    wrapper.find('input').element.focus()\n    await wrapper.find('input').setValue('test')\n    await wrapper.find('input').trigger('blur')\n    expect(onChange).toHaveBeenCalled()\n    wrapper.unmount()\n  })\n\n  it('should work with `on-focus` prop', async () => {\n    const onFocus = vi.fn()\n    const wrapper = mount(NInput, {\n      props: { onFocus }\n    })\n    await wrapper.find('input').trigger('focus')\n    expect(onFocus).toHaveBeenCalled()\n    wrapper.unmount()\n  })\n\n  it('should work with `on-input` prop', async () => {\n    const onInput = vi.fn()\n    const wrapper = mount(NInput, {\n      props: { onInput }\n    })\n    wrapper.find('input').element.focus()\n    await wrapper.find('input').setValue('test')\n    expect(onInput).toHaveBeenCalled()\n    wrapper.unmount()\n  })\n\n  it('should work with `on-update:value` prop', async () => {\n    const onUpdateValue = vi.fn()\n    const wrapper = mount(NInput, {\n      props: { onUpdateValue }\n    })\n    wrapper.find('input').element.focus()\n    await wrapper.find('input').setValue('test')\n    expect(onUpdateValue).toHaveBeenCalled()\n    wrapper.unmount()\n  })\n\n  it('should work with `prefix` slots', async () => {\n    const wrapper = mount(NInput, {\n      slots: { prefix: '￥' }\n    })\n    expect(wrapper.find('.n-input__prefix').exists()).toBe(true)\n    expect(wrapper.find('.n-input__prefix').text()).toBe('￥')\n    wrapper.unmount()\n  })\n\n  it('should work with `suffix` slots', async () => {\n    const wrapper = mount(NInput, {\n      slots: { suffix: '元' }\n    })\n    expect(wrapper.find('.n-input__suffix').exists()).toBe(true)\n    expect(wrapper.find('.n-input__suffix').text()).toBe('元')\n    wrapper.unmount()\n  })\n\n  it('should work with `separator` slot', async () => {\n    const wrapper = mount(NInput, {\n      props: { pair: true },\n      slots: { separator: '-' }\n    })\n\n    expect(wrapper.find('.n-input').classes()).toContain('n-input--pair')\n    expect(wrapper.find('.n-input__separator').text()).toBe('-')\n    wrapper.unmount()\n  })\n\n  it('should work with `InputGroup` `InputGroupLabel` slot', async () => {\n    const wrapper = mount(InputGroup, {\n      slots: {\n        default: () => [\n          h(InputGroupLabel, null, { default: () => 'test1' }),\n          h(NInput),\n          h(InputGroupLabel, null, { default: () => 'test2' })\n        ]\n      }\n    })\n\n    expect(wrapper.find('.n-input-group').exists()).toBe(true)\n    expect(wrapper.find('.n-input-group').element.children.length).toBe(3)\n    expect(\n      wrapper.find('.n-input-group').element.children[0].getAttribute('class')\n    ).toContain('n-input-group-label')\n    expect(wrapper.find('.n-input-group').element.children[0].textContent).toBe(\n      'test1'\n    )\n    expect(\n      wrapper.find('.n-input-group').element.children[1].getAttribute('class')\n    ).toContain('n-input')\n    expect(\n      wrapper.find('.n-input-group').element.children[2].getAttribute('class')\n    ).toContain('n-input-group-label')\n    expect(wrapper.find('.n-input-group').element.children[2].textContent).toBe(\n      'test2'\n    )\n    wrapper.unmount()\n  })\n\n  it('should work with `blur` `focus` `select` methods', async () => {\n    const onBlur = vi.fn()\n    const onFocus = vi.fn()\n    const onSelect = vi.fn()\n    const Mock = defineComponent({\n      setup() {\n        const inputInstRef = ref<InputInst | null>(null)\n        onMounted(() => {\n          inputInstRef.value?.focus()\n          inputInstRef.value?.blur()\n          inputInstRef.value?.select()\n        })\n        return () => {\n          return (\n            <NInput\n              ref={inputInstRef}\n              onBlur={onBlur}\n              onFocus={onFocus}\n              // @ts-expect-error onSelect is not an exposed jsx prop\n              onSelect={onSelect}\n            />\n          )\n        }\n      }\n    })\n\n    const wrapper = mount(() => <Mock />, {\n      attachTo: document.body\n    })\n    expect(onBlur).toHaveBeenCalled()\n    expect(onFocus).toHaveBeenCalled()\n    // won't call onSelect because it not a NInput prop\n    expect(onSelect).not.toHaveBeenCalled()\n    wrapper.unmount()\n  })\n})\n"
  },
  {
    "path": "src/input/tests/__snapshots__/Input.spec.tsx.snap",
    "content": "// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html\n\nexports[`n-input > should work with \\`size\\` prop 1`] = `\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-count-text-color: rgb(118, 124, 130); --n-count-text-color-disabled: rgba(194, 194, 194, 1); --n-color: rgba(255, 255, 255, 1); --n-font-size: 14px; --n-font-weight: 400; --n-border-radius: 3px; --n-height: 28px; --n-padding-left: 10px; --n-padding-right: 10px; --n-text-color: rgb(51, 54, 57); --n-caret-color: #18a058; --n-text-decoration-color: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-focus: 1px solid #36ad6a; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-icon-size: 16px; --n-line-height-textarea: 1.6; --n-color-disabled: rgb(250, 250, 252); --n-color-focus: rgba(255, 255, 255, 1); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-loading-color: #18a058; --n-caret-color-warning: #f0a020; --n-color-focus-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-loading-color-warning: #f0a020; --n-caret-color-error: #d03050; --n-color-focus-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-loading-color-error: #d03050; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-size: 16px; --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-icon-color-hover: rgba(146, 146, 146, 1); --n-icon-color-pressed: rgba(175, 175, 175, 1); --n-icon-color-disabled: rgba(209, 209, 209, 1); --n-suffix-text-color: rgb(51, 54, 57);\"`;\n\nexports[`n-input > should work with \\`size\\` prop 2`] = `\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-count-text-color: rgb(118, 124, 130); --n-count-text-color-disabled: rgba(194, 194, 194, 1); --n-color: rgba(255, 255, 255, 1); --n-font-size: 14px; --n-font-weight: 400; --n-border-radius: 3px; --n-height: 34px; --n-padding-left: 12px; --n-padding-right: 12px; --n-text-color: rgb(51, 54, 57); --n-caret-color: #18a058; --n-text-decoration-color: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-focus: 1px solid #36ad6a; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-icon-size: 16px; --n-line-height-textarea: 1.6; --n-color-disabled: rgb(250, 250, 252); --n-color-focus: rgba(255, 255, 255, 1); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-loading-color: #18a058; --n-caret-color-warning: #f0a020; --n-color-focus-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-loading-color-warning: #f0a020; --n-caret-color-error: #d03050; --n-color-focus-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-loading-color-error: #d03050; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-size: 16px; --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-icon-color-hover: rgba(146, 146, 146, 1); --n-icon-color-pressed: rgba(175, 175, 175, 1); --n-icon-color-disabled: rgba(209, 209, 209, 1); --n-suffix-text-color: rgb(51, 54, 57);\"`;\n\nexports[`n-input > should work with \\`size\\` prop 3`] = `\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-count-text-color: rgb(118, 124, 130); --n-count-text-color-disabled: rgba(194, 194, 194, 1); --n-color: rgba(255, 255, 255, 1); --n-font-size: 15px; --n-font-weight: 400; --n-border-radius: 3px; --n-height: 40px; --n-padding-left: 14px; --n-padding-right: 14px; --n-text-color: rgb(51, 54, 57); --n-caret-color: #18a058; --n-text-decoration-color: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-focus: 1px solid #36ad6a; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-icon-size: 16px; --n-line-height-textarea: 1.6; --n-color-disabled: rgb(250, 250, 252); --n-color-focus: rgba(255, 255, 255, 1); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-loading-color: #18a058; --n-caret-color-warning: #f0a020; --n-color-focus-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-loading-color-warning: #f0a020; --n-caret-color-error: #d03050; --n-color-focus-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-loading-color-error: #d03050; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-size: 16px; --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-icon-color-hover: rgba(146, 146, 146, 1); --n-icon-color-pressed: rgba(175, 175, 175, 1); --n-icon-color-disabled: rgba(209, 209, 209, 1); --n-suffix-text-color: rgb(51, 54, 57);\"`;\n"
  },
  {
    "path": "src/input/tests/server.spec.tsx",
    "content": "import { setup } from '@css-render/vue3-ssr'\nimport { renderToString } from '@vue/server-renderer'\n/**\n * @vitest-environment node\n */\nimport { createSSRApp, h } from 'vue'\nimport { NInput } from '../..'\n\ndescribe('server side rendering', () => {\n  it('works', async () => {\n    const app = createSSRApp(() => <NInput />)\n    setup(app)\n    try {\n      await renderToString(app)\n    }\n    catch (e) {\n      expect(e).not.toBeTruthy()\n    }\n  })\n})\n"
  },
  {
    "path": "src/input-number/demos/enUS/basic.demo.vue",
    "content": "<markdown>\n# Basic\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst value = ref(0)\n</script>\n\n<template>\n  <n-input-number v-model:value=\"value\" clearable />\n</template>\n"
  },
  {
    "path": "src/input-number/demos/enUS/button-placement.demo.vue",
    "content": "<markdown>\n# Button placement\n\nButton can be placed at both ends.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst value = ref(0)\n</script>\n\n<template>\n  <n-space vertical>\n    <n-input-number v-model:value=\"value\" button-placement=\"both\" />\n    <n-input-number v-model:value=\"value\" button-placement=\"both\">\n      <template #prefix>\n        $\n      </template>\n    </n-input-number>\n    <n-input-number v-model:value=\"value\" button-placement=\"both\">\n      <template #suffix>\n        ฿\n      </template>\n    </n-input-number>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/input-number/demos/enUS/change-timing.demo.vue",
    "content": "<markdown>\n# Timing to change\n\nSet `update-value-on-input` to `false`, the value won't be changed on input.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst value = ref(35)\n</script>\n\n<template>\n  <n-space vertical>\n    <n-input-number\n      v-model:value=\"value\"\n      :update-value-on-input=\"false\"\n      placeholder=\"\"\n      :min=\"20\"\n      :max=\"50\"\n    />\n    <n-input-number v-model:value=\"value\" placeholder=\"\" :min=\"20\" :max=\"50\" />\n    {{ value }}\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/input-number/demos/enUS/custom-icon.demo.vue",
    "content": "<markdown>\n# Custom Icon\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ArrowDownCircleOutline, ArrowUpCircleOutline } from '@vicons/ionicons5'\nimport { ref } from 'vue'\n\nconst value = ref(0)\n</script>\n\n<template>\n  <n-space vertical>\n    <n-input-number v-model:value=\"value\">\n      <template #minus-icon>\n        <n-icon :component=\"ArrowDownCircleOutline\" />\n      </template>\n      <template #add-icon>\n        <n-icon :component=\"ArrowUpCircleOutline\" />\n      </template>\n    </n-input-number>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/input-number/demos/enUS/disable-keyboard.demo.vue",
    "content": "<markdown>\n# Disable keyboard arrow up & down\n\nSet `:keyboard=\"{ ArrowUp: false, ArrowDown: false }\"` to disabled keyboard arrow up & down.\n</markdown>\n\n<template>\n  <n-input-number :keyboard=\"{ ArrowUp: false, ArrowDown: false }\" />\n</template>\n"
  },
  {
    "path": "src/input-number/demos/enUS/disabled.demo.vue",
    "content": "<markdown>\n# Disabled\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst value = ref(0)\nconst disabled = ref(true)\n</script>\n\n<template>\n  <n-space align=\"center\">\n    <n-switch v-model:value=\"disabled\" />\n    <n-input-number v-model:value=\"value\" :disabled=\"disabled\" />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/input-number/demos/enUS/event.demo.vue",
    "content": "<markdown>\n# Event\n\nBlur & change events are exposed.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { useMessage } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst message = useMessage()\nconst value = ref(0)\n\nfunction handleChange(v: number | null) {\n  message.info(`update:value(${v})`)\n}\n\nfunction handleBlur() {\n  message.info('blur')\n}\n\nfunction handleFocus() {\n  message.info('focus')\n}\n</script>\n\n<template>\n  <n-input-number\n    v-model:value=\"value\"\n    @update:value=\"handleChange\"\n    @focus=\"handleFocus\"\n    @blur=\"handleBlur\"\n  />\n</template>\n"
  },
  {
    "path": "src/input-number/demos/enUS/icon.demo.vue",
    "content": "<markdown>\n# Prefix & suffix\n\nAdd prefix and suffix contents.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst value = ref(0)\n</script>\n\n<template>\n  <n-space vertical>\n    <n-input-number v-model:value=\"value\">\n      <template #prefix>\n        $\n      </template>\n    </n-input-number>\n    <n-input-number v-model:value=\"value\">\n      <template #suffix>\n        %\n      </template>\n    </n-input-number>\n    <n-input-number v-model:value=\"value\" :show-button=\"false\">\n      <template #suffix>\n        %\n      </template>\n    </n-input-number>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/input-number/demos/enUS/index.demo-entry.md",
    "content": "# Input Number\n\nIf you just want a number, this is for you.\n\n## Demos\n\n```demo\nbasic.vue\ndisabled.vue\nparse.vue\nprecision.vue\nevent.vue\nicon.vue\nbutton-placement.vue\nloading.vue\nmin-max.vue\nsize.vue\nstep.vue\nvalidator.vue\nshow-button.vue\ndisable-keyboard.vue\nchange-timing.vue\nstatus.vue\ncustom-icon.vue\n```\n\n## API\n\n### InputNumber Props\n\n| Name | Type | Default | Description | Version |\n| --- | --- | --- | --- | --- |\n| autofocus | `boolean` | `false` | Whether to autofocus. | 2.26.1 |\n| bordered | `boolean` | `true` | Whether to show a border. |  |\n| button-placement | `'both' \\| 'right'` | `'right'` | Placement of add & minus button. | 2.29.1 |\n| clearable | `boolean` | `false` | Whether the input is clearable. |  |\n| default-value | `number \\| null` | `null` | Default value when not manually set. |  |\n| disabled | `boolean` | `false` | Whether to disable the input. |  |\n| format | `(value: number \\| null) => string` | `undefined` | Method to format value. If it's set, `update-value-on-input` will be disabled. | 2.30.0 |\n| input-props | `InputHTMLAttributes` | `undefined` | The dom props of the input element inside the component. For avaiable attributes, [see here](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input). Warning：It won't override internal props with the same name (except `type`). | 2.37.0 |\n| keyboard | `{ ArrowUp?: boolean, ArrowDown?: boolean }` | `{}` | Control the keyboard behavior. If you set corresponding to false, the keyboard behavior will be disabled. |  |\n| loading | `boolean` | `undefined` | Set loading state. If set (true/false), the element will always take up enough space for the loading indicator. |  |\n| max | `number` | `undefined` | The max value. |  |\n| min | `number` | `undefined` | The min value. |  |\n| parse | `(input: string) => number \\| null` | `undefined` | Method to parse input string. If it's set, `update-value-on-input` will be disabled. | 2.30.0 |\n| placeholder | `string` | `'Please Input'` | Placeholder. |  |\n| precision | `number` | `undefined` | Precision of input value. If it's set, `update-value-on-input` will be disabled. | 2.30.0 |\n| round | `boolean` | `undefined` | Use a rounded input style. | 2.39.0 |\n| readonly | `boolean` | `false` | Whether it's readonly. |  |\n| show-button | `boolean` | `true` | Whether to show increase/decrease buttons. |  |\n| size | `'tiny' \\| 'small' \\| 'medium' \\| 'large'` | `'medium'` | The size of input box. |  |\n| status | `'success' \\| 'warning' \\| 'error'` | `undefined` | Validation status. | 2.27.0 |\n| step | `number` | `1` | The number which the current value is increased or decreased on key or button press. It can be an integer or a decimal. |  |\n| update-value-on-input | `boolean` | `true` | Whether to change the value on input if the input value is valid. |  |\n| validator | `(value) => boolean` | `undefined` | Setup custom validation. |  |\n| value | `number \\| null` | `undefined` | Manually set the input value. |  |\n| on-blur | `(event: FocusEvent) => void` | `undefined` | Callback triggered when the input is blurred. |  |\n| on-clear | `() => void` | `undefined` | Callback triggered when the input is cleared. |  |\n| on-focus | `(event: FocusEvent) => void` | `undefined` | Callback triggered when the input is focussed on. |  |\n| on-update:value | `(value: number \\| null) => void` | `undefined` | Callback triggered when the input value changes. |  |\n\n### InputNumber Slots\n\n| Name       | Parameters | Description               | Version |\n| ---------- | ---------- | ------------------------- | ------- |\n| add-icon   | `()`       | icon of the add button.   | 2.28.1  |\n| minus-icon | `()`       | icon of the minus button. | 2.28.1  |\n| prefix     | `()`       | Prefix content slot.      |         |\n| suffix     | `()`       | Suffix content slot.      |         |\n\n### InputNumber Methods\n\n| Name  | Type         | Description             |\n| ----- | ------------ | ----------------------- |\n| blur  | `() => void` | Blur the input number.  |\n| focus | `() => void` | Focus the input number. |\n"
  },
  {
    "path": "src/input-number/demos/enUS/loading.demo.vue",
    "content": "<markdown>\n# Loading\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst loading = ref(false)\n</script>\n\n<template>\n  <n-space align=\"center\">\n    <n-input-number clearable :loading=\"loading\" />\n    <n-switch v-model:value=\"loading\" />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/input-number/demos/enUS/min-max.demo.vue",
    "content": "<markdown>\n# Min and max\n\nYou can set minimum and maximum values too.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst value = ref(null)\n</script>\n\n<template>\n  <n-space vertical>\n    <n-input-number\n      v-model:value=\"value\"\n      placeholder=\"Min\"\n      :min=\"-3\"\n      :max=\"5\"\n    />\n    <n-input-number\n      v-model:value=\"value\"\n      placeholder=\"Max\"\n      :min=\"-5\"\n      :max=\"3\"\n    />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/input-number/demos/enUS/parse.demo.vue",
    "content": "<markdown>\n# Custom parsing\n\nYou can use `parse` and `format` to custom parsing & display. For example add thousand separator. Usually they should be set together, especially you have a custom `validator` set.\n\nUse `parse` and `format` will disable `update-value-on-input`.\n</markdown>\n\n<script lang=\"ts\" setup>\nfunction parse(input: string) {\n  const nums = input.replace(/,/g, '').trim()\n  if (/^\\d+(\\.(\\d+)?)?$/.test(nums))\n    return Number(nums)\n  return nums === '' ? null : Number.NaN\n}\n\nfunction format(value: number | null) {\n  if (value === null)\n    return ''\n  return value.toLocaleString('en-US')\n}\n\nfunction parseCurrency(input: string) {\n  const nums = input.replace(/(,|\\$|\\s)/g, '').trim()\n  if (/^\\d+(\\.(\\d+)?)?$/.test(nums))\n    return Number(nums)\n  return nums === '' ? null : Number.NaN\n}\n\nfunction formatCurrency(value: number | null) {\n  if (value === null)\n    return ''\n  return `${value.toLocaleString('en-US')} \\u{24}`\n}\n</script>\n\n<template>\n  <n-space vertical>\n    <n-input-number :default-value=\"1075\" :parse=\"parse\" :format=\"format\" />\n    <n-input-number\n      :default-value=\"1075\"\n      :parse=\"parseCurrency\"\n      :format=\"formatCurrency\"\n    />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/input-number/demos/enUS/precision.demo.vue",
    "content": "<markdown>\n# Precision\n\nSet the `precision` property to control the numerical precision.\n\nUse `precision` will disable `update-value-on-input`.\n</markdown>\n\n<template>\n  <n-space vertical>\n    <n-input-number clearable :precision=\"2\" />\n    <n-input-number clearable :precision=\"0\" />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/input-number/demos/enUS/show-button.demo.vue",
    "content": "<markdown>\n# Hide button\n\nUse `show-button` prop to control whether to show control buttons.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst value = ref(0)\nconst disabled = ref(true)\n</script>\n\n<template>\n  <n-space align=\"center\">\n    <n-switch v-model:value=\"disabled\" />\n    <n-input-number v-model:value=\"value\" :show-button=\"disabled\" />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/input-number/demos/enUS/size.demo.vue",
    "content": "<markdown>\n# Size\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst value = ref(0)\n</script>\n\n<template>\n  <n-space vertical>\n    <n-input-number v-model:value=\"value\" size=\"tiny\" />\n    <n-input-number v-model:value=\"value\" size=\"small\" />\n    <n-input-number v-model:value=\"value\" size=\"medium\" />\n    <n-input-number v-model:value=\"value\" size=\"large\" />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/input-number/demos/enUS/status.demo.vue",
    "content": "<markdown>\n# Validation status\n\nValidation status can be applied outside form.\n</markdown>\n\n<template>\n  <n-space vertical>\n    <n-input-number status=\"warning\" placeholder=\"\" />\n    <n-input-number status=\"error\" placeholder=\"\" />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/input-number/demos/enUS/step.demo.vue",
    "content": "<markdown>\n# Step\n\nSet how much the buttons change the value.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst value = ref(0)\n</script>\n\n<template>\n  <n-input-number v-model:value=\"value\" :step=\"2\" />\n</template>\n"
  },
  {
    "path": "src/input-number/demos/enUS/validator.demo.vue",
    "content": "<markdown>\n# Validator\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst value = ref(0)\nconst validator = (x: number) => x > 0\n</script>\n\n<template>\n  <n-input-number v-model:value=\"value\" :validator=\"validator\" />\n</template>\n"
  },
  {
    "path": "src/input-number/demos/zhCN/basic.demo.vue",
    "content": "<markdown>\n# 基础用法\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst value = ref(0)\n</script>\n\n<template>\n  <n-input-number v-model:value=\"value\" clearable />\n</template>\n"
  },
  {
    "path": "src/input-number/demos/zhCN/button-placement.demo.vue",
    "content": "<markdown>\n# 按钮位置\n\n按钮可以被放在两侧。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst value = ref(0)\n</script>\n\n<template>\n  <n-space vertical>\n    <n-input-number v-model:value=\"value\" button-placement=\"both\" />\n    <n-input-number v-model:value=\"value\" button-placement=\"both\">\n      <template #prefix>\n        $\n      </template>\n    </n-input-number>\n    <n-input-number v-model:value=\"value\" button-placement=\"both\">\n      <template #suffix>\n        ฿\n      </template>\n    </n-input-number>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/input-number/demos/zhCN/change-timing.demo.vue",
    "content": "<markdown>\n# 改变值的时机\n\n将 `update-value-on-input` 设为 `false`，则在输入的过程中不会改变值。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst value = ref(35)\n</script>\n\n<template>\n  <n-space vertical>\n    <n-input-number\n      v-model:value=\"value\"\n      :update-value-on-input=\"false\"\n      placeholder=\"\"\n      :min=\"20\"\n      :max=\"50\"\n    />\n    <n-input-number v-model:value=\"value\" placeholder=\"\" :min=\"20\" :max=\"50\" />\n    {{ value }}\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/input-number/demos/zhCN/custom-icon.demo.vue",
    "content": "<markdown>\n# 自定义图标\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ArrowDownCircleOutline, ArrowUpCircleOutline } from '@vicons/ionicons5'\nimport { ref } from 'vue'\n\nconst value = ref(0)\n</script>\n\n<template>\n  <n-space vertical>\n    <n-input-number v-model:value=\"value\">\n      <template #minus-icon>\n        <n-icon :component=\"ArrowDownCircleOutline\" />\n      </template>\n      <template #add-icon>\n        <n-icon :component=\"ArrowUpCircleOutline\" />\n      </template>\n    </n-input-number>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/input-number/demos/zhCN/debug.demo.vue",
    "content": "<markdown>\n# Debug\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nfunction handleUpdateValue1(v: number | null) {\n  console.log(v)\n}\n\nfunction handleUpdateValue2(v: number | null) {\n  console.log(v)\n}\n\nconst value1 = ref(null)\nconst value2 = ref(null)\n</script>\n\n<template>\n  <n-input-number\n    v-model:value=\"value1\"\n    placeholder=\"最小值\"\n    :min=\"-3\"\n    :max=\"5\"\n    loading\n    @update:value=\"handleUpdateValue1\"\n  />\n  {{ JSON.stringify(value1) }}\n  <n-input-number v-model:value=\"value2\" @update:value=\"handleUpdateValue2\" />\n  {{ JSON.stringify(value2) }}\n</template>\n"
  },
  {
    "path": "src/input-number/demos/zhCN/disable-keyboard.demo.vue",
    "content": "<markdown>\n# 禁用键盘上下\n\n设定 `:keyboard=\"{ ArrowUp: false, ArrowDown: false }\"` 来禁用键盘上下键。\n</markdown>\n\n<template>\n  <n-input-number :keyboard=\"{ ArrowUp: false, ArrowDown: false }\" />\n</template>\n"
  },
  {
    "path": "src/input-number/demos/zhCN/disabled.demo.vue",
    "content": "<markdown>\n# 禁用\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst value = ref(0)\nconst disabled = ref(true)\n</script>\n\n<template>\n  <n-space align=\"center\">\n    <n-switch v-model:value=\"disabled\" />\n    <n-input-number v-model:value=\"value\" :disabled=\"disabled\" />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/input-number/demos/zhCN/event.demo.vue",
    "content": "<markdown>\n# 事件\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { useMessage } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst message = useMessage()\nconst value = ref(0)\n\nfunction handleChange(v: number | null) {\n  message.info(`update:value(${v})`)\n}\n\nfunction handleBlur() {\n  message.info('blur')\n}\n\nfunction handleFocus() {\n  message.info('focus')\n}\n</script>\n\n<template>\n  <n-input-number\n    v-model:value=\"value\"\n    @update:value=\"handleChange\"\n    @focus=\"handleFocus\"\n    @blur=\"handleBlur\"\n  />\n</template>\n"
  },
  {
    "path": "src/input-number/demos/zhCN/icon.demo.vue",
    "content": "<markdown>\n# 前缀 & 后缀\n\n在前缀后缀添加内容\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst value = ref(0)\n</script>\n\n<template>\n  <n-space vertical>\n    <n-input-number v-model:value=\"value\">\n      <template #prefix>\n        ￥\n      </template>\n    </n-input-number>\n    <n-input-number v-model:value=\"value\">\n      <template #suffix>\n        %\n      </template>\n    </n-input-number>\n    <n-input-number v-model:value=\"value\" :show-button=\"false\">\n      <template #suffix>\n        %\n      </template>\n    </n-input-number>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/input-number/demos/zhCN/index.demo-entry.md",
    "content": "# 数字输入 Input Number\n\n输入数字就用它。\n\n## 演示\n\n```demo\nbasic.vue\ndisabled.vue\nparse.vue\nprecision.vue\nevent.vue\nicon.vue\nbutton-placement.vue\nloading.vue\nmin-max.vue\nsize.vue\nstep.vue\nvalidator.vue\nshow-button.vue\ndisable-keyboard.vue\nchange-timing.vue\nstatus.vue\ncustom-icon.vue\ndebug.vue\nrtl-debug.vue\ntheme-debug.vue\nprecision-debug.vue\n```\n\n## API\n\n### InputNumber Props\n\n| 名称 | 类型 | 默认值 | 说明 | 版本 |\n| --- | --- | --- | --- | --- |\n| autofocus | `boolean` | `false` | 是否自动获取焦点 | 2.26.1 |\n| bordered | `boolean` | `true` | 是否有边框 |  |\n| button-placement | `'both' \\| 'right'` | `'right'` | 加减按钮的位置 | 2.29.1 |\n| clearable | `boolean` | `false` | 是否可清空 |  |\n| default-value | `number \\| null` | `null` | 非受控模式下的默认值 |  |\n| disabled | `boolean` | `false` | 是否禁用 |  |\n| format | `(value: number \\| null) => string` | `undefined` | 格式化值的方法，设定后会禁用 `update-value-on-input` | 2.30.0 |\n| input-props | `InputHTMLAttributes` | `undefined` | 组件内部 input 元素的属性，[在这里查看原生属性](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input)。注意：`input-props` 不会覆盖内部 input 元素的已经存在的属性（除了 `type`） | 2.37.0 |\n| keyboard | `{ ArrowUp?: boolean, ArrowDown?: boolean }` | `{}` | 控制允许的键盘操作，属性值设为 `false` 的时候会禁用对应的键盘操作 |\n| loading | `boolean` | `undefined` | 是否展示加载图标，设为非 `undefined` 会占据空间 |  |\n| max | `number` | `undefined` | 最大值 |  |\n| min | `number` | `undefined` | 最小值 |  |\n| parse | `(input: string) => number \\| null` | `undefined` | 解析输入的字符串，设定后会禁用 `update-value-on-input` | 2.30.0 |\n| placeholder | `string` | `'请输入'` | 提示信息 |  |\n| precision | `number` | `undefined` | 数值保留的精度值，设定后会禁用 `update-value-on-input` | 2.30.0 |\n| readonly | `boolean` | `false` | 是否只读 |  |\n| round | `boolean` | `undefined` | 输入框是否圆角 | 2.39.0 |\n| show-button | `boolean` | `true` | 是否有按钮 |  |\n| size | `'tiny' \\| 'small' \\| 'medium' \\| 'large'` | `'medium'` | 输入框大小 |  |\n| status | `'success' \\| 'warning' \\| 'error'` | `undefined` | 验证状态 | 2.27.0 |\n| step | `number` | `1` | 每次改变步数，可以为小数 |  |\n| update-value-on-input | `boolean` | `true` | 在输入的过程中，在输入值合法的情况下，是否改变值 |  |\n| validator | `(value) => boolean` | `undefined` | 设置自定义验证 |  |\n| value | `number \\| null` | `undefined` | 受控模式下的值 |  |\n| on-blur | `(event: FocusEvent) => void` | `undefined` | 移除焦点的回调 |  |\n| on-clear | `() => void` | `undefined` | 点击清空按钮时的回调 |  |\n| on-focus | `(event: FocusEvent) => void` | `undefined` | 获取焦点的回调 |  |\n| on-update:value | `(value: number \\| null) => void` | `undefined` | 组件值发生变化的回调 |  |\n\n### InputNumber Slots\n\n| 名称       | 参数 | 说明               | 版本   |\n| ---------- | ---- | ------------------ | ------ |\n| add-icon   | `()` | 增加按钮的图标     | 2.28.1 |\n| minus-icon | `()` | 减少按钮的图标     | 2.28.1 |\n| prefix     | `()` | 输入框头部内容插槽 |        |\n| suffix     | `()` | 输入框尾部内容插槽 |        |\n\n### InputNumber Methods\n\n| 名称  | 类型         | 说明     |\n| ----- | ------------ | -------- |\n| blur  | `() => void` | 失焦输入 |\n| focus | `() => void` | 聚焦输入 |\n"
  },
  {
    "path": "src/input-number/demos/zhCN/loading.demo.vue",
    "content": "<markdown>\n# 加载状态\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst loading = ref(false)\n</script>\n\n<template>\n  <n-space align=\"center\">\n    <n-input-number clearable :loading=\"loading\" />\n    <n-switch v-model:value=\"loading\" />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/input-number/demos/zhCN/min-max.demo.vue",
    "content": "<markdown>\n# 最小值 & 最大值\n\n你可以设定最小值和最大值。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst value = ref(null)\n</script>\n\n<template>\n  <n-space vertical>\n    <n-input-number\n      v-model:value=\"value\"\n      placeholder=\"最小值\"\n      :min=\"-3\"\n      :max=\"5\"\n    />\n    <n-input-number\n      v-model:value=\"value\"\n      placeholder=\"最大值\"\n      :min=\"-5\"\n      :max=\"3\"\n    />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/input-number/demos/zhCN/parse.demo.vue",
    "content": "<markdown>\n# 自定义解析\n\n你可以使用 `parse` 和 `format` 来自定义解析和展示内容，例如增加千位分隔符。通常这两个要一起设定，尤其是当你使用了自定义的 `validator` 时。\n\n使用 `parse` 和 `format` 会使 `update-value-on-input` 失效。\n</markdown>\n\n<script lang=\"ts\" setup>\nfunction parse(input: string) {\n  const nums = input.replace(/,/g, '').trim()\n  if (/^\\d+(\\.(\\d+)?)?$/.test(nums))\n    return Number(nums)\n  return nums === '' ? null : Number.NaN\n}\n\nfunction format(value: number | null) {\n  if (value === null)\n    return ''\n  return value.toLocaleString('en-US')\n}\n\nfunction parseCurrency(input: string) {\n  const nums = input.replace(/(,|¥|\\s)/g, '').trim()\n  if (/^\\d+(\\.(\\d+)?)?$/.test(nums))\n    return Number(nums)\n  return nums === '' ? null : Number.NaN\n}\n\nfunction formatCurrency(value: number | null) {\n  if (value === null)\n    return ''\n  return `${value.toLocaleString('en-US')} ¥`\n}\n</script>\n\n<template>\n  <n-space vertical>\n    <n-input-number :default-value=\"1075\" :parse=\"parse\" :format=\"format\" />\n    <n-input-number\n      :default-value=\"1075\"\n      :parse=\"parseCurrency\"\n      :format=\"formatCurrency\"\n    />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/input-number/demos/zhCN/precision-debug.demo.vue",
    "content": "<markdown>\n# precision debug\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst v = ref(1)\n\nfunction check() {\n  if (v.value === null) {\n    v.value = 1\n  }\n}\n</script>\n\n<template>\n  <n-input-number v-model:value=\"v\" :precision=\"0\" @blur=\"check\" />\n</template>\n"
  },
  {
    "path": "src/input-number/demos/zhCN/precision.demo.vue",
    "content": "<markdown>\n# 精度\n\n设置 `precision` 属性可以控制数值精度。\n\n使用 `precision` 会使 `update-value-on-input` 失效。\n</markdown>\n\n<template>\n  <n-space vertical>\n    <n-input-number clearable :precision=\"2\" />\n    <n-input-number clearable :precision=\"0\" />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/input-number/demos/zhCN/rtl-debug.demo.vue",
    "content": "<markdown>\n# Rtl Debug\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { unstableInputNumberRtl } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst value = ref(0)\nconst rtlEnabled = ref(false)\nconst rtlStyles = [unstableInputNumberRtl]\n</script>\n\n<template>\n  <n-space vertical>\n    <n-space><n-switch v-model:value=\"rtlEnabled\" />Rtl</n-space>\n    <n-config-provider :rtl=\"rtlEnabled ? rtlStyles : undefined\">\n      <n-input-number v-model:value=\"value\" clearable />\n    </n-config-provider>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/input-number/demos/zhCN/show-button.demo.vue",
    "content": "<markdown>\n# 隐藏按钮\n\n使用 `show-button` 属性来控制是否展示按钮。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst value = ref(0)\nconst disabled = ref(true)\n</script>\n\n<template>\n  <n-space align=\"center\">\n    <n-switch v-model:value=\"disabled\" />\n    <n-input-number v-model:value=\"value\" :show-button=\"disabled\" />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/input-number/demos/zhCN/size.demo.vue",
    "content": "<markdown>\n# 尺寸\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst value = ref(0)\n</script>\n\n<template>\n  <n-space vertical>\n    <n-input-number v-model:value=\"value\" size=\"tiny\" />\n    <n-input-number v-model:value=\"value\" size=\"small\" />\n    <n-input-number v-model:value=\"value\" size=\"medium\" />\n    <n-input-number v-model:value=\"value\" size=\"large\" />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/input-number/demos/zhCN/status.demo.vue",
    "content": "<markdown>\n# 验证状态\n\n输入的验证状态可以脱离表单使用。\n</markdown>\n\n<template>\n  <n-space vertical>\n    <n-input-number status=\"warning\" placeholder=\"\" />\n    <n-input-number status=\"error\" placeholder=\"\" />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/input-number/demos/zhCN/step.demo.vue",
    "content": "<markdown>\n# 间隔\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst value = ref(0)\n</script>\n\n<template>\n  <n-input-number v-model:value=\"value\" :step=\"2\" />\n</template>\n"
  },
  {
    "path": "src/input-number/demos/zhCN/theme-debug.demo.vue",
    "content": "<markdown>\n# Theme debug\n</markdown>\n\n<template>\n  <n-input-number\n    :theme-overrides=\"{\n      peers: {\n        Button: {\n          textColorText: 'green',\n        },\n      },\n    }\"\n  />\n</template>\n"
  },
  {
    "path": "src/input-number/demos/zhCN/validator.demo.vue",
    "content": "<markdown>\n# 自定义验证\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst value = ref(0)\nconst validator = (x: number) => x > 0\n</script>\n\n<template>\n  <n-input-number v-model:value=\"value\" :validator=\"validator\" />\n</template>\n"
  },
  {
    "path": "src/input-number/index.ts",
    "content": "export { inputNumberProps, default as NInputNumber } from './src/InputNumber'\nexport type { InputNumberProps, InputNumberSlots } from './src/InputNumber'\nexport type { InputNumberInst } from './src/interface'\n"
  },
  {
    "path": "src/input-number/src/InputNumber.tsx",
    "content": "import type { InputHTMLAttributes, PropType, SlotsType, VNode } from 'vue'\nimport type { ThemeProps } from '../../_mixins'\nimport type { ExtractPublicPropTypes, MaybeArray } from '../../_utils'\nimport type { FormValidationStatus } from '../../form/src/public-types'\nimport type { InputInst } from '../../input'\nimport type { InputNumberTheme } from '../styles'\nimport type { InputNumberInst, OnUpdateValue, Size } from './interface'\nimport { on } from 'evtd'\nimport { rgba } from 'seemly'\nimport { useMemo, useMergedState } from 'vooks'\nimport {\n  computed,\n  defineComponent,\n  h,\n  nextTick,\n  ref,\n  toRef,\n  watch,\n  watchEffect\n} from 'vue'\nimport { NBaseIcon } from '../../_internal'\nimport { AddIcon, RemoveIcon } from '../../_internal/icons'\nimport { useConfig, useFormItem, useLocale, useTheme } from '../../_mixins'\nimport { useRtl } from '../../_mixins/use-rtl'\nimport { call, resolveSlot, resolveWrappedSlot, warnOnce } from '../../_utils'\nimport { NxButton } from '../../button'\nimport { NInput } from '../../input'\nimport { inputNumberLight } from '../styles'\nimport style from './styles/input-number.cssr'\nimport { format, isWipValue, parse, parseNumber, validator } from './utils'\n\nconst HOLDING_CHANGE_THRESHOLD = 800\nconst HOLDING_CHANGE_INTERVAL = 100\n\nexport const inputNumberProps = {\n  ...(useTheme.props as ThemeProps<InputNumberTheme>),\n  autofocus: Boolean,\n  loading: {\n    type: Boolean,\n    default: undefined\n  },\n  placeholder: String,\n  defaultValue: {\n    type: Number as PropType<number | null>,\n    default: null\n  },\n  value: Number as PropType<number | null>,\n  step: {\n    type: [Number, String],\n    default: 1\n  },\n  min: [Number, String],\n  max: [Number, String],\n  size: String as PropType<Size>,\n  disabled: {\n    type: Boolean as PropType<boolean | undefined>,\n    default: undefined\n  },\n  validator: Function as PropType<(value: number) => boolean>,\n  bordered: {\n    type: Boolean as PropType<boolean | undefined>,\n    default: undefined\n  },\n  showButton: {\n    type: Boolean,\n    default: true\n  },\n  buttonPlacement: {\n    type: String as PropType<'right' | 'both'>,\n    default: 'right'\n  },\n  inputProps: Object as PropType<InputHTMLAttributes>,\n  readonly: Boolean,\n  clearable: Boolean,\n  keyboard: {\n    type: Object as PropType<{\n      ArrowUp?: boolean\n      ArrowDown?: boolean\n    }>,\n    default: {}\n  },\n  updateValueOnInput: {\n    type: Boolean,\n    default: true\n  },\n  round: {\n    type: Boolean as PropType<boolean | undefined>,\n    default: undefined\n  },\n  parse: Function as PropType<(input: string) => number | null>,\n  format: Function as PropType<(value: number | null) => string>,\n  precision: Number,\n  status: String as PropType<FormValidationStatus>,\n  'onUpdate:value': [Function, Array] as PropType<MaybeArray<OnUpdateValue>>,\n  onUpdateValue: [Function, Array] as PropType<MaybeArray<OnUpdateValue>>,\n  onFocus: [Function, Array] as PropType<MaybeArray<(e: FocusEvent) => void>>,\n  onBlur: [Function, Array] as PropType<MaybeArray<(e: FocusEvent) => void>>,\n  onClear: [Function, Array] as PropType<MaybeArray<(e: MouseEvent) => void>>,\n  // deprecated\n  onChange: [Function, Array] as PropType<MaybeArray<OnUpdateValue>>\n}\n\nexport type InputNumberProps = ExtractPublicPropTypes<typeof inputNumberProps>\n\nexport interface InputNumberSlots {\n  'add-icon'?: () => VNode[]\n  'minus-icon'?: () => VNode[]\n  prefix?: () => VNode[]\n  suffix?: () => VNode[]\n}\n\nexport default defineComponent({\n  name: 'InputNumber',\n  props: inputNumberProps,\n  slots: Object as SlotsType<InputNumberSlots>,\n  setup(props) {\n    if (__DEV__) {\n      watchEffect(() => {\n        if (props.onChange !== undefined) {\n          warnOnce(\n            'input-number',\n            '`on-change` is deprecated, please use `on-update:value` instead'\n          )\n        }\n      })\n    }\n    const {\n      mergedBorderedRef,\n      mergedClsPrefixRef,\n      mergedRtlRef,\n      mergedComponentPropsRef\n    } = useConfig(props)\n    const themeRef = useTheme(\n      'InputNumber',\n      '-input-number',\n      style,\n      inputNumberLight,\n      props,\n      mergedClsPrefixRef\n    )\n    const { localeRef } = useLocale('InputNumber')\n    const formItem = useFormItem(props, {\n      mergedSize: (NFormItem) => {\n        const { size } = props\n        if (size)\n          return size\n        const { mergedSize: formItemSize } = NFormItem || {}\n        if (formItemSize?.value)\n          return formItemSize.value as Size\n        const configSize = mergedComponentPropsRef?.value?.InputNumber?.size\n        if (configSize)\n          return configSize\n        return 'medium'\n      }\n    })\n    const { mergedSizeRef, mergedDisabledRef, mergedStatusRef } = formItem\n    // dom ref\n    const inputInstRef = ref<InputInst | null>(null)\n    const minusButtonInstRef = ref<{ $el: HTMLElement } | null>(null)\n    const addButtonInstRef = ref<{ $el: HTMLElement } | null>(null)\n    // value\n    const uncontrolledValueRef = ref(props.defaultValue)\n    const controlledValueRef = toRef(props, 'value')\n    const mergedValueRef = useMergedState(\n      controlledValueRef,\n      uncontrolledValueRef\n    )\n    const displayedValueRef = ref('')\n    const getPrecision = (value: string | number): number => {\n      const fraction = String(value).split('.')[1]\n      return fraction ? fraction.length : 0\n    }\n    const getMaxPrecision = (currentValue: number): number => {\n      const precisions = [props.min, props.max, props.step, currentValue].map(\n        (value): number => {\n          if (value === undefined)\n            return 0\n          return getPrecision(value)\n        }\n      )\n      return Math.max(...precisions)\n    }\n    const mergedPlaceholderRef = useMemo(() => {\n      const { placeholder } = props\n      if (placeholder !== undefined)\n        return placeholder\n      return localeRef.value.placeholder\n    })\n    const mergedStepRef = useMemo(() => {\n      const parsedNumber = parseNumber(props.step)\n      if (parsedNumber !== null) {\n        return parsedNumber === 0 ? 1 : Math.abs(parsedNumber)\n      }\n      return 1\n    })\n    const mergedMinRef = useMemo(() => {\n      const parsedNumber = parseNumber(props.min)\n      if (parsedNumber !== null)\n        return parsedNumber\n      else return null\n    })\n    const mergedMaxRef = useMemo(() => {\n      const parsedNumber = parseNumber(props.max)\n      if (parsedNumber !== null)\n        return parsedNumber\n      else return null\n    })\n    const deriveDisplayedValueFromValue = (): void => {\n      const { value: mergedValue } = mergedValueRef\n      if (validator(mergedValue)) {\n        const { format: formatProp, precision } = props\n        if (formatProp) {\n          displayedValueRef.value = formatProp(mergedValue)\n        }\n        else {\n          if (\n            mergedValue === null\n            || precision === undefined\n            // precision overflow\n            || getPrecision(mergedValue) > precision\n          ) {\n            displayedValueRef.value = format(mergedValue, undefined)\n          }\n          else {\n            displayedValueRef.value = format(mergedValue, precision)\n          }\n        }\n      }\n      else {\n        // null can pass the validator check\n        // so mergedValue is a number\n        displayedValueRef.value = String(mergedValue)\n      }\n    }\n    deriveDisplayedValueFromValue()\n    const doUpdateValue = (value: number | null): void => {\n      const { value: mergedValue } = mergedValueRef\n      if (value === mergedValue) {\n        deriveDisplayedValueFromValue()\n        return\n      }\n      const {\n        'onUpdate:value': _onUpdateValue,\n        onUpdateValue,\n        onChange\n      } = props\n      const { nTriggerFormInput, nTriggerFormChange } = formItem\n      if (onChange)\n        call(onChange, value)\n      if (onUpdateValue)\n        call(onUpdateValue, value)\n      if (_onUpdateValue)\n        call(_onUpdateValue, value)\n      uncontrolledValueRef.value = value\n      nTriggerFormInput()\n      nTriggerFormChange()\n    }\n    const deriveValueFromDisplayedValue = ({\n      offset,\n      doUpdateIfValid,\n      fixPrecision,\n      isInputing\n    }: {\n      offset: number\n      doUpdateIfValid: boolean\n      fixPrecision: boolean\n      isInputing: boolean\n    }): null | number | false => {\n      const { value: displayedValue } = displayedValueRef\n      if (isInputing && isWipValue(displayedValue)) {\n        return false\n      }\n      const parsedValue = (props.parse || parse)(displayedValue)\n      if (parsedValue === null) {\n        if (doUpdateIfValid)\n          doUpdateValue(null)\n        return null\n      }\n      if (validator(parsedValue)) {\n        const currentPrecision = getPrecision(parsedValue)\n        const { precision } = props\n        if (\n          precision !== undefined\n          && precision < currentPrecision\n          && !fixPrecision\n        ) {\n          return false\n        }\n        let nextValue = Number.parseFloat(\n          (parsedValue + offset).toFixed(\n            precision ?? getMaxPrecision(parsedValue)\n          )\n        )\n        if (validator(nextValue)) {\n          const { value: mergedMax } = mergedMaxRef\n          const { value: mergedMin } = mergedMinRef\n          if (mergedMax !== null && nextValue > mergedMax) {\n            if (!doUpdateIfValid || isInputing)\n              return false\n            // if doUpdateIfValid=true, we try to make it a valid value\n            nextValue = mergedMax\n          }\n          if (mergedMin !== null && nextValue < mergedMin) {\n            if (!doUpdateIfValid || isInputing)\n              return false\n            // if doUpdateIfValid=true, we try to make it a valid value\n            nextValue = mergedMin\n          }\n          if (props.validator && !props.validator(nextValue))\n            return false\n          if (doUpdateIfValid)\n            doUpdateValue(nextValue)\n          return nextValue\n        }\n      }\n      return false\n    }\n    const displayedValueInvalidRef = useMemo(() => {\n      const derivedValue = deriveValueFromDisplayedValue({\n        offset: 0,\n        doUpdateIfValid: false,\n        isInputing: false,\n        fixPrecision: false\n      })\n      return derivedValue === false\n    })\n    const minusableRef = useMemo(() => {\n      const { value: mergedValue } = mergedValueRef\n      if (props.validator && mergedValue === null) {\n        return false\n      }\n      const { value: mergedStep } = mergedStepRef\n      const derivedNextValue = deriveValueFromDisplayedValue({\n        offset: -mergedStep,\n        doUpdateIfValid: false,\n        isInputing: false,\n        fixPrecision: false\n      })\n      return derivedNextValue !== false\n    })\n    const addableRef = useMemo(() => {\n      const { value: mergedValue } = mergedValueRef\n      if (props.validator && mergedValue === null) {\n        return false\n      }\n      const { value: mergedStep } = mergedStepRef\n      const derivedNextValue = deriveValueFromDisplayedValue({\n        offset: +mergedStep,\n        doUpdateIfValid: false,\n        isInputing: false,\n        fixPrecision: false\n      })\n      return derivedNextValue !== false\n    })\n    function doFocus(e: FocusEvent): void {\n      const { onFocus } = props\n      const { nTriggerFormFocus } = formItem\n      if (onFocus)\n        call(onFocus, e)\n      nTriggerFormFocus()\n    }\n    function doBlur(e: FocusEvent): void {\n      if (e.target === inputInstRef.value?.wrapperElRef) {\n        // hit input wrapper\n        // which means not activated\n        return\n      }\n      const value = deriveValueFromDisplayedValue({\n        offset: 0,\n        doUpdateIfValid: true,\n        isInputing: false,\n        fixPrecision: true\n      })\n      // If valid, update event has been emitted\n      // make sure e.target.value is correct in blur callback\n      if (value !== false) {\n        const inputElRef = inputInstRef.value?.inputElRef\n        if (inputElRef) {\n          inputElRef.value = String(value || '')\n        }\n        // If value is not changed, the displayed value may be greater than or\n        // less than the current value. The derived value is reformatted so the\n        // value is not changed. We can simply derive a new displayed value\n        if (mergedValueRef.value === value) {\n          deriveDisplayedValueFromValue()\n        }\n      }\n      else {\n        // If not valid, nothing will be emitted, so derive displayed value from\n        // origin value\n        deriveDisplayedValueFromValue()\n      }\n      const { onBlur } = props\n      const { nTriggerFormBlur } = formItem\n      if (onBlur)\n        call(onBlur, e)\n      nTriggerFormBlur()\n      // User may change value in blur callback, we make sure it will be\n      // displayed. Sometimes mergedValue won't be viewed as changed\n      void nextTick(() => {\n        deriveDisplayedValueFromValue()\n      })\n    }\n    function doClear(e: MouseEvent): void {\n      const { onClear } = props\n      if (onClear)\n        call(onClear, e)\n    }\n    function doAdd(): void {\n      const { value: addable } = addableRef\n      if (!addable) {\n        clearAddHoldTimeout()\n        return\n      }\n      const { value: mergedValue } = mergedValueRef\n      if (mergedValue === null) {\n        if (!props.validator) {\n          doUpdateValue(createValidValue())\n        }\n      }\n      else {\n        const { value: mergedStep } = mergedStepRef\n        deriveValueFromDisplayedValue({\n          offset: mergedStep,\n          doUpdateIfValid: true,\n          isInputing: false,\n          fixPrecision: true\n        })\n      }\n    }\n    function doMinus(): void {\n      const { value: minusable } = minusableRef\n      if (!minusable) {\n        clearMinusHoldTimeout()\n        return\n      }\n      const { value: mergedValue } = mergedValueRef\n      if (mergedValue === null) {\n        if (!props.validator) {\n          doUpdateValue(createValidValue())\n        }\n      }\n      else {\n        const { value: mergedStep } = mergedStepRef\n        deriveValueFromDisplayedValue({\n          offset: -mergedStep,\n          doUpdateIfValid: true,\n          isInputing: false,\n          fixPrecision: true\n        })\n      }\n    }\n    const handleFocus = doFocus\n    const handleBlur = doBlur\n    function createValidValue(): number | null {\n      if (props.validator)\n        return null\n      const { value: mergedMin } = mergedMinRef\n      const { value: mergedMax } = mergedMaxRef\n      if (mergedMin !== null) {\n        return Math.max(0, mergedMin)\n      }\n      else if (mergedMax !== null) {\n        return Math.min(0, mergedMax)\n      }\n      else {\n        return 0\n      }\n    }\n    function handleClear(e: MouseEvent): void {\n      doClear(e)\n      doUpdateValue(null)\n    }\n    function handleMouseDown(e: MouseEvent): void {\n      if (addButtonInstRef.value?.$el.contains(e.target as Node)) {\n        e.preventDefault()\n      }\n      if (minusButtonInstRef.value?.$el.contains(e.target as Node)) {\n        e.preventDefault()\n      }\n      inputInstRef.value?.activate()\n    }\n    let minusHoldStateIntervalId: number | null = null\n    let addHoldStateIntervalId: number | null = null\n    let firstMinusMousedownId: number | null = null\n    function clearMinusHoldTimeout(): void {\n      if (firstMinusMousedownId) {\n        window.clearTimeout(firstMinusMousedownId)\n        firstMinusMousedownId = null\n      }\n      if (minusHoldStateIntervalId) {\n        window.clearInterval(minusHoldStateIntervalId)\n        minusHoldStateIntervalId = null\n      }\n    }\n    let firstAddMousedownId: number | null = null\n    function clearAddHoldTimeout(): void {\n      if (firstAddMousedownId) {\n        window.clearTimeout(firstAddMousedownId)\n        firstAddMousedownId = null\n      }\n      if (addHoldStateIntervalId) {\n        window.clearInterval(addHoldStateIntervalId)\n        addHoldStateIntervalId = null\n      }\n    }\n    function handleMinusMousedown(): void {\n      clearMinusHoldTimeout()\n      firstMinusMousedownId = window.setTimeout(() => {\n        minusHoldStateIntervalId = window.setInterval(() => {\n          doMinus()\n        }, HOLDING_CHANGE_INTERVAL)\n      }, HOLDING_CHANGE_THRESHOLD)\n      on('mouseup', document, clearMinusHoldTimeout, {\n        once: true\n      })\n    }\n    function handleAddMousedown(): void {\n      clearAddHoldTimeout()\n      firstAddMousedownId = window.setTimeout(() => {\n        addHoldStateIntervalId = window.setInterval(() => {\n          doAdd()\n        }, HOLDING_CHANGE_INTERVAL)\n      }, HOLDING_CHANGE_THRESHOLD)\n      on('mouseup', document, clearAddHoldTimeout, {\n        once: true\n      })\n    }\n    const handleAddClick = (): void => {\n      if (addHoldStateIntervalId)\n        return\n      doAdd()\n    }\n    const handleMinusClick = (): void => {\n      if (minusHoldStateIntervalId)\n        return\n      doMinus()\n    }\n    function handleKeyDown(e: KeyboardEvent): void {\n      if (e.key === 'Enter') {\n        if (e.target === inputInstRef.value?.wrapperElRef) {\n          // hit input wrapper\n          // which means not activated\n          return\n        }\n        const value = deriveValueFromDisplayedValue({\n          offset: 0,\n          doUpdateIfValid: true,\n          isInputing: false,\n          fixPrecision: true\n        })\n        if (value !== false) {\n          inputInstRef.value?.deactivate()\n        }\n      }\n      else if (e.key === 'ArrowUp') {\n        if (!addableRef.value)\n          return\n        if (props.keyboard.ArrowUp === false)\n          return\n        e.preventDefault()\n        const value = deriveValueFromDisplayedValue({\n          offset: 0,\n          doUpdateIfValid: true,\n          isInputing: false,\n          fixPrecision: true\n        })\n        if (value !== false) {\n          doAdd()\n        }\n      }\n      else if (e.key === 'ArrowDown') {\n        if (!minusableRef.value)\n          return\n        if (props.keyboard.ArrowDown === false)\n          return\n        e.preventDefault()\n        const value = deriveValueFromDisplayedValue({\n          offset: 0,\n          doUpdateIfValid: true,\n          isInputing: false,\n          fixPrecision: true\n        })\n        if (value !== false) {\n          doMinus()\n        }\n      }\n    }\n    function handleUpdateDisplayedValue(value: string): void {\n      displayedValueRef.value = value\n      if (\n        props.updateValueOnInput\n        && !props.format\n        && !props.parse\n        && props.precision === undefined\n      ) {\n        deriveValueFromDisplayedValue({\n          offset: 0,\n          doUpdateIfValid: true,\n          isInputing: true,\n          fixPrecision: false\n        })\n      }\n    }\n    watch(mergedValueRef, () => {\n      deriveDisplayedValueFromValue()\n    })\n    const exposedMethods: InputNumberInst = {\n      focus: () => inputInstRef.value?.focus(),\n      blur: () => inputInstRef.value?.blur(),\n      select: () => inputInstRef.value?.select()\n    }\n    const rtlEnabledRef = useRtl(\n      'InputNumber',\n      mergedRtlRef,\n      mergedClsPrefixRef\n    )\n    return {\n      ...exposedMethods,\n      rtlEnabled: rtlEnabledRef,\n      inputInstRef,\n      minusButtonInstRef,\n      addButtonInstRef,\n      mergedClsPrefix: mergedClsPrefixRef,\n      mergedBordered: mergedBorderedRef,\n      uncontrolledValue: uncontrolledValueRef,\n      mergedValue: mergedValueRef,\n      mergedPlaceholder: mergedPlaceholderRef,\n      displayedValueInvalid: displayedValueInvalidRef,\n      mergedSize: mergedSizeRef,\n      mergedDisabled: mergedDisabledRef,\n      displayedValue: displayedValueRef,\n      addable: addableRef,\n      minusable: minusableRef,\n      mergedStatus: mergedStatusRef,\n      handleFocus,\n      handleBlur,\n      handleClear,\n      handleMouseDown,\n      handleAddClick,\n      handleMinusClick,\n      handleAddMousedown,\n      handleMinusMousedown,\n      handleKeyDown,\n      handleUpdateDisplayedValue,\n      // theme\n      mergedTheme: themeRef,\n      inputThemeOverrides: {\n        paddingSmall: '0 8px 0 10px',\n        paddingMedium: '0 8px 0 12px',\n        paddingLarge: '0 8px 0 14px'\n      },\n      buttonThemeOverrides: computed(() => {\n        const {\n          self: { iconColorDisabled }\n        } = themeRef.value\n        const [r, g, b, a] = rgba(iconColorDisabled)\n        return {\n          textColorTextDisabled: `rgb(${r}, ${g}, ${b})`,\n          opacityDisabled: `${a}`\n        }\n      })\n    }\n  },\n  render() {\n    const { mergedClsPrefix, $slots } = this\n    const renderMinusButton = (): VNode => {\n      return (\n        <NxButton\n          text\n          disabled={!this.minusable || this.mergedDisabled || this.readonly}\n          focusable={false}\n          theme={this.mergedTheme.peers.Button}\n          themeOverrides={this.mergedTheme.peerOverrides.Button}\n          builtinThemeOverrides={this.buttonThemeOverrides}\n          onClick={this.handleMinusClick}\n          onMousedown={this.handleMinusMousedown}\n          ref=\"minusButtonInstRef\"\n        >\n          {{\n            icon: () =>\n              resolveSlot($slots['minus-icon'], () => [\n                <NBaseIcon clsPrefix={mergedClsPrefix}>\n                  {{\n                    default: () => <RemoveIcon />\n                  }}\n                </NBaseIcon>\n              ])\n          }}\n        </NxButton>\n      )\n    }\n    const renderAddButton = (): VNode => {\n      return (\n        <NxButton\n          text\n          disabled={!this.addable || this.mergedDisabled || this.readonly}\n          focusable={false}\n          theme={this.mergedTheme.peers.Button}\n          themeOverrides={this.mergedTheme.peerOverrides.Button}\n          builtinThemeOverrides={this.buttonThemeOverrides}\n          onClick={this.handleAddClick}\n          onMousedown={this.handleAddMousedown}\n          ref=\"addButtonInstRef\"\n        >\n          {{\n            icon: () =>\n              resolveSlot($slots['add-icon'], () => [\n                <NBaseIcon clsPrefix={mergedClsPrefix}>\n                  {{\n                    default: () => <AddIcon />\n                  }}\n                </NBaseIcon>\n              ])\n          }}\n        </NxButton>\n      )\n    }\n    return (\n      <div\n        class={[\n          `${mergedClsPrefix}-input-number`,\n          this.rtlEnabled && `${mergedClsPrefix}-input-number--rtl`\n        ]}\n      >\n        <NInput\n          ref=\"inputInstRef\"\n          autofocus={this.autofocus}\n          status={this.mergedStatus}\n          bordered={this.mergedBordered}\n          loading={this.loading}\n          value={this.displayedValue}\n          onUpdateValue={this.handleUpdateDisplayedValue}\n          theme={this.mergedTheme.peers.Input}\n          themeOverrides={this.mergedTheme.peerOverrides.Input}\n          builtinThemeOverrides={this.inputThemeOverrides}\n          size={this.mergedSize}\n          placeholder={this.mergedPlaceholder}\n          disabled={this.mergedDisabled}\n          readonly={this.readonly as any}\n          round={this.round}\n          textDecoration={\n            this.displayedValueInvalid ? 'line-through' : undefined\n          }\n          onFocus={this.handleFocus}\n          onBlur={this.handleBlur}\n          onKeydown={this.handleKeyDown}\n          onMousedown={this.handleMouseDown}\n          onClear={this.handleClear}\n          clearable={this.clearable}\n          inputProps={this.inputProps}\n          internalLoadingBeforeSuffix\n        >\n          {{\n            prefix: () =>\n              this.showButton && this.buttonPlacement === 'both'\n                ? [\n                    renderMinusButton(),\n                    resolveWrappedSlot($slots.prefix, (children) => {\n                      if (children) {\n                        return (\n                          <span\n                            class={`${mergedClsPrefix}-input-number-prefix`}\n                          >\n                            {children}\n                          </span>\n                        )\n                      }\n                      return null\n                    })\n                  ]\n                : $slots.prefix?.(),\n            suffix: () =>\n              this.showButton\n                ? [\n                    resolveWrappedSlot($slots.suffix, (children) => {\n                      if (children) {\n                        return (\n                          <span\n                            class={`${mergedClsPrefix}-input-number-suffix`}\n                          >\n                            {children}\n                          </span>\n                        )\n                      }\n                      return null\n                    }),\n                    this.buttonPlacement === 'right'\n                      ? renderMinusButton()\n                      : null,\n                    renderAddButton()\n                  ]\n                : $slots.suffix?.()\n          }}\n        </NInput>\n      </div>\n    )\n  }\n})\n"
  },
  {
    "path": "src/input-number/src/interface.ts",
    "content": "import type { InputNumberSize } from './public-types'\n\nexport type OnUpdateValue = (value: number | null) => void\nexport type Size = InputNumberSize\n\nexport interface InputNumberInst {\n  focus: () => void\n  blur: () => void\n  select: () => void\n}\n"
  },
  {
    "path": "src/input-number/src/public-types.ts",
    "content": "export type InputNumberSize = 'tiny' | 'small' | 'medium' | 'large'\n"
  },
  {
    "path": "src/input-number/src/styles/input-number.cssr.ts",
    "content": "import { c, cB } from '../../../_utils/cssr'\n\nexport default c([\n  cB('input-number-suffix', `\n    display: inline-block;\n    margin-right: 10px;\n  `),\n  cB('input-number-prefix', `\n    display: inline-block;\n    margin-left: 10px;\n  `)\n])\n"
  },
  {
    "path": "src/input-number/src/styles/rtl.cssr.ts",
    "content": "import { cB, cM } from '../../../_utils/cssr'\n\nexport default cB('input-number', [\n  cM('rtl', `\n    direction: rtl;\n  `)\n])\n"
  },
  {
    "path": "src/input-number/src/utils.ts",
    "content": "// string => string (expected, not implemented)\n// string => number (legacy)\nexport function parse(value: string): number | null {\n  if (\n    value === undefined\n    || value === null\n    || (typeof value === 'string' && value.trim() === '')\n  ) {\n    return null\n  }\n  return Number(value)\n}\n\n// This function is created for `update-value-on-input` prop. When the prop is\n// true, the input value will update the value and <input />'s value at the same\n// time. So we need to make user's content won't be replaced by its parsed value\n// in some certain cases. For example '0.' should be parsed and replaced by '0',\n// '-0' should be parsed and replaced by '0', since user may input '-0.1' after.\nexport function isWipValue(value: string): boolean {\n  return (\n    (value.includes('.')\n      && (/^(-)?\\d+.*(\\.|0)$/.test(value) || /^-?\\d*$/.test(value)))\n    || value === '-'\n    || value === '-0'\n  )\n}\n\n// string => boolean (expected, not implemented)\n// number => boolean (legacy)\nexport function validator(value: number | null): boolean {\n  if (value === undefined || value === null)\n    return true\n  if (Number.isNaN(value))\n    return false\n  return true\n}\n\n// string => string (expected, not implemented)\n// number => string (legacy)\nexport function format(\n  value: number | undefined | null,\n  precision: number | undefined\n): string {\n  if (typeof value !== 'number')\n    return ''\n  return precision === undefined ? String(value) : value.toFixed(precision)\n}\n\nexport function parseNumber(\n  number: number | null | undefined | string\n): number | null {\n  if (number === null)\n    return null\n  if (typeof number === 'number') {\n    return number\n  }\n  else {\n    const parsedNumber = Number(number)\n    if (Number.isNaN(parsedNumber)) {\n      return null\n    }\n    else {\n      return parsedNumber\n    }\n  }\n}\n"
  },
  {
    "path": "src/input-number/styles/dark.ts",
    "content": "import type { InputNumberTheme } from './light'\nimport { commonDark } from '../../_styles/common'\nimport { buttonDark } from '../../button/styles'\nimport { inputDark } from '../../input/styles'\n\nconst inputNumberDark: InputNumberTheme = {\n  name: 'InputNumber',\n  common: commonDark,\n  peers: {\n    Button: buttonDark,\n    Input: inputDark\n  },\n  self(vars) {\n    const { textColorDisabled } = vars\n    return {\n      iconColorDisabled: textColorDisabled\n    }\n  }\n}\n\nexport default inputNumberDark\n"
  },
  {
    "path": "src/input-number/styles/index.ts",
    "content": "export { default as inputNumberDark } from './dark'\nexport { default as inputNumberLight } from './light'\nexport type { InputNumberTheme, InputNumberThemeVars } from './light'\nexport { inputNumberRtl } from './rtl'\n"
  },
  {
    "path": "src/input-number/styles/light.ts",
    "content": "import type { ThemeCommonVars } from '../../_styles/common'\nimport { createTheme } from '../../_mixins'\nimport { commonLight } from '../../_styles/common'\nimport { buttonLight } from '../../button/styles'\nimport { inputLight } from '../../input/styles'\n\nfunction self(vars: ThemeCommonVars) {\n  const { textColorDisabled } = vars\n  return {\n    iconColorDisabled: textColorDisabled\n  }\n}\n\nexport type InputNumberThemeVars = ReturnType<typeof self>\n\nconst inputNumberLight = createTheme({\n  name: 'InputNumber',\n  common: commonLight,\n  peers: {\n    Button: buttonLight,\n    Input: inputLight\n  },\n  self\n})\n\nexport default inputNumberLight\nexport type InputNumberTheme = typeof inputNumberLight\n"
  },
  {
    "path": "src/input-number/styles/rtl.ts",
    "content": "import type { RtlItem } from '../../config-provider/src/internal-interface'\nimport { buttonRtl } from '../../button/styles/rtl'\nimport { inputRtl } from '../../input/styles/rtl'\nimport rtlStyle from '../src/styles/rtl.cssr'\n\nexport const inputNumberRtl: RtlItem = {\n  name: 'InputNumber',\n  style: rtlStyle,\n  peers: [inputRtl, buttonRtl]\n}\n"
  },
  {
    "path": "src/input-number/tests/InputNumber.spec.tsx",
    "content": "import { mount } from '@vue/test-utils'\nimport { h } from 'vue'\nimport { NButton } from '../../button'\nimport { NInputNumber } from '../index'\n\ndescribe('n-input-number', () => {\n  it('should work with import on demand', () => {\n    mount(NInputNumber)\n  })\n\n  it('props.value can be null', () => {\n    ;<NInputNumber value={null} />\n  })\n\n  it('should work with `loading` prop', async () => {\n    const wrapper = mount(NInputNumber)\n    expect(wrapper.find('.n-base-loading__container').exists()).toBe(false)\n    await wrapper.setProps({ loading: false })\n    expect(wrapper.find('.n-base-loading__container').exists()).toBe(false)\n    await wrapper.setProps({ loading: true })\n    expect(wrapper.find('.n-base-loading__container').exists()).toBe(true)\n    wrapper.unmount()\n  })\n\n  it('should work with `show-button` prop', async () => {\n    // Here is a strange case, we must make input number's slots flag to 2\n    // (dynamic) to make it work.\n    const wrapper = mount(NInputNumber)\n    expect(wrapper.findComponent(NButton).exists()).toBe(true)\n    await wrapper.setProps({ showButton: false })\n    expect(wrapper.findComponent(NButton).exists()).toBe(false)\n  })\n\n  it('should work with default value', async () => {\n    const wrapper = mount(NInputNumber, {\n      props: {\n        defaultValue: 1\n      }\n    })\n    expect(wrapper.find('input').element.value).toEqual('1')\n  })\n\n  it('should not trigger update if value is same', async () => {\n    const onUpdateValue = vi.fn()\n    const wrapper = mount(NInputNumber, {\n      attachTo: document.body,\n      props: {\n        defaultValue: 1,\n        onUpdateValue\n      }\n    })\n    wrapper.find('input').element.value = ''\n    await wrapper.find('input').trigger('input')\n    expect(onUpdateValue).toHaveBeenCalledWith(null)\n    wrapper.unmount()\n  })\n\n  it('trigger focus & blur event', () => {\n    const onFocus = vi.fn()\n    const onBlur = vi.fn()\n    const wrapper = mount(NInputNumber, {\n      attachTo: document.body,\n      props: {\n        onFocus,\n        onBlur\n      }\n    })\n    wrapper.find('input').element.focus()\n    expect(onFocus).toHaveBeenCalledTimes(1)\n    wrapper.find('input').element.blur()\n    expect(onBlur).toHaveBeenCalledTimes(1)\n    wrapper.unmount()\n  })\n\n  it('should work with `prefix` & `suffix` slots', async () => {\n    const wrapper = mount(NInputNumber, {\n      slots: { prefix: () => '$', suffix: () => '%' }\n    })\n    expect(wrapper.find('.n-input__prefix').exists()).toBe(true)\n    expect(wrapper.find('.n-input__prefix').text()).toBe('$')\n    expect(wrapper.find('.n-input__suffix').exists()).toBe(true)\n    expect(wrapper.find('.n-input-number-suffix').exists()).toBe(true)\n    expect(wrapper.find('.n-input-number-suffix').text()).toBe('%')\n    wrapper.unmount()\n  })\n  it('should work with decimal `step`', async () => {\n    const wrapper = mount(NInputNumber, {\n      attachTo: document.body,\n      props: {\n        defaultValue: 0.2,\n        min: 0,\n        step: 0.1\n      }\n    })\n    const input = wrapper.find('.n-input__input-el')\n    expect((input.element as HTMLInputElement).value).toEqual('0.2')\n    const buttons = wrapper.findAll('.n-input__suffix > button')\n    const minusBtn = buttons[0]\n    const addBtn = buttons[1]\n\n    let arr = [0.1, 0]\n    for (let i = 0; i < arr.length; i++) {\n      await minusBtn.trigger('click')\n      expect((input.element as HTMLInputElement).value).toEqual(\n        arr[i].toString()\n      )\n    }\n    expect(minusBtn.classes()).toContain('n-button--disabled')\n    await wrapper.setProps({ step: 0.2 })\n    await wrapper.setProps({ max: 0.6 })\n    arr = [0.2, 0.4, 0.6]\n    for (let i = 0; i < arr.length; i++) {\n      await addBtn.trigger('click')\n      expect((input.element as HTMLInputElement).value).toEqual(\n        arr[i].toString()\n      )\n    }\n    expect(addBtn.classes()).toContain('n-button--disabled')\n    wrapper.unmount()\n  })\n\n  it('should work with decimal value', async () => {\n    const wrapper = mount(NInputNumber, {\n      attachTo: document.body,\n      props: {\n        defaultValue: 0\n      }\n    })\n    wrapper.find('input').element.value = '0.22'\n    await wrapper.find('input').trigger('input')\n    await wrapper.find('input').trigger('blur')\n    expect(wrapper.find('input').element.value).toEqual('0.22')\n    await wrapper.setProps({ step: 2 })\n    wrapper.find('input').element.value = '0.3333'\n    await wrapper.find('input').trigger('input')\n    await wrapper.find('input').trigger('blur')\n    expect(wrapper.find('input').element.value).toEqual('0.3333')\n    const addBtn = wrapper.findAll('.n-input__suffix > button')[1]\n    await addBtn.trigger('mousedown')\n    await addBtn.trigger('mouseup')\n    expect(wrapper.find('input').element.value).toEqual('0.3333')\n    await addBtn.trigger('click')\n    expect(wrapper.find('input').element.value).toEqual('2.3333')\n    await wrapper.setProps({ step: 2.333333 })\n    await addBtn.trigger('mousedown')\n    await addBtn.trigger('mouseup')\n    expect(wrapper.find('input').element.value).toEqual('2.3333')\n    await addBtn.trigger('click')\n    expect(wrapper.find('input').element.value).toEqual('4.666633')\n    await wrapper.setProps({ step: 2.33 })\n    await addBtn.trigger('mousedown')\n    await addBtn.trigger('mouseup')\n    expect(wrapper.find('input').element.value).toEqual('4.666633')\n    await addBtn.trigger('click')\n    expect(wrapper.find('input').element.value).toEqual('6.996633')\n    wrapper.unmount()\n  })\n\n  it('should work with `updateValueOnInput` prop', async () => {\n    const onUpdateValue = vi.fn()\n    const wrapper = mount(NInputNumber, {\n      attachTo: document.body,\n      props: {\n        defaultValue: 2,\n        onUpdateValue\n      }\n    })\n    wrapper.find('input').element.value = '2.'\n    await wrapper.find('input').trigger('input')\n    expect(onUpdateValue).toHaveBeenCalledTimes(0)\n    wrapper.find('input').element.value = '2.2'\n    await wrapper.find('input').trigger('input')\n    expect(onUpdateValue).toHaveBeenCalledWith(2.2)\n    wrapper.find('input').element.value = ''\n    await wrapper.find('input').trigger('input')\n    expect(onUpdateValue).toHaveBeenCalledTimes(2)\n    await wrapper.setProps({ min: 20, max: 50 })\n    wrapper.find('input').element.value = '18.'\n    await wrapper.find('input').trigger('input')\n    wrapper.find('input').element.value = '.18'\n    expect(onUpdateValue).toHaveBeenCalledTimes(2)\n    wrapper.find('input').element.value = '22.2'\n    await wrapper.find('input').trigger('input')\n    expect(onUpdateValue).toHaveBeenCalledWith(22.2)\n    await wrapper.setProps({ updateValueOnInput: false })\n    wrapper.find('input').element.value = '24'\n    await wrapper.find('input').trigger('input')\n    expect(onUpdateValue).toHaveBeenCalledTimes(3)\n    await wrapper.find('input').trigger('blur')\n    expect(onUpdateValue).toHaveBeenCalledWith(24)\n    wrapper.unmount()\n  })\n\n  it('should work with negative decimal value', async () => {\n    const onUpdateValue = vi.fn()\n    const wrapper = mount(NInputNumber, {\n      attachTo: document.body,\n      props: {\n        defaultValue: 2,\n        onUpdateValue\n      }\n    })\n    wrapper.find('input').element.value = '-2.'\n    await wrapper.find('input').trigger('input')\n    expect(onUpdateValue).toHaveBeenCalledTimes(0)\n    wrapper.find('input').element.value = '-2.2'\n    await wrapper.find('input').trigger('input')\n    expect(onUpdateValue).toHaveBeenCalledWith(-2.2)\n    wrapper.find('input').element.value = '-.'\n    await wrapper.find('input').trigger('input')\n    expect(onUpdateValue).toHaveBeenCalledTimes(1)\n    wrapper.find('input').element.value = '-.2'\n    await wrapper.find('input').trigger('input')\n    expect(onUpdateValue).toHaveBeenCalledWith(-0.2)\n    wrapper.unmount()\n  })\n\n  it('should work with decimal value ends at 0', async () => {\n    const onUpdateValue = vi.fn()\n    const wrapper = mount(NInputNumber, {\n      attachTo: document.body,\n      props: {\n        defaultValue: 0,\n        onUpdateValue\n      }\n    })\n    wrapper.find('input').element.value = '2.'\n    await wrapper.find('input').trigger('input')\n    expect(onUpdateValue).toHaveBeenCalledTimes(0)\n    wrapper.find('input').element.value = '2.0'\n    await wrapper.find('input').trigger('input')\n    expect(onUpdateValue).toHaveBeenCalledTimes(0)\n    wrapper.find('input').element.value = '2.012'\n    await wrapper.find('input').trigger('input')\n    expect(onUpdateValue).toHaveBeenCalledWith(2.012)\n    wrapper.find('input').element.value = '-2.0'\n    await wrapper.find('input').trigger('input')\n    expect(onUpdateValue).toHaveBeenCalledTimes(1)\n    wrapper.find('input').element.value = '-2.02'\n    await wrapper.find('input').trigger('input')\n    expect(onUpdateValue).toHaveBeenCalledWith(-2.02)\n    wrapper.find('input').element.value = '-2.0200'\n    await wrapper.find('input').trigger('input')\n    expect(onUpdateValue).toHaveBeenCalledTimes(2)\n    wrapper.find('input').element.value = '-2.02003'\n    await wrapper.find('input').trigger('input')\n    expect(onUpdateValue).toHaveBeenCalledWith(-2.02003)\n    wrapper.unmount()\n  })\n\n  it('should work with integer value ends with 0', async () => {\n    const onUpdateValue = vi.fn()\n    const wrapper = mount(NInputNumber, {\n      attachTo: document.body,\n      props: {\n        defaultValue: 0,\n        onUpdateValue\n      }\n    })\n    wrapper.find('input').element.value = '1'\n    await wrapper.find('input').trigger('input')\n    expect(onUpdateValue).toHaveBeenCalledWith(1)\n    wrapper.find('input').element.value = '10'\n    await wrapper.find('input').trigger('input')\n    expect(onUpdateValue).toHaveBeenCalledWith(10)\n    wrapper.unmount()\n  })\n\n  it('should work with `status` prop', async () => {\n    ;(['success', 'warning', 'error'] as const).forEach((status) => {\n      const wrapper = mount(NInputNumber, { props: { status } })\n      expect(wrapper.find('.n-input').classes()).toContain(\n        `n-input--${status}-status`\n      )\n      wrapper.unmount()\n    })\n  })\n\n  it('should work with `input-props` prop', async () => {\n    const wrapper = mount(NInputNumber, {\n      props: { inputProps: { id: 'i am an id' } }\n    })\n    expect(wrapper.find('input').element.id).toEqual('i am an id')\n    wrapper.unmount()\n  })\n})\n"
  },
  {
    "path": "src/input-number/tests/server.spec.tsx",
    "content": "import { setup } from '@css-render/vue3-ssr'\nimport { renderToString } from '@vue/server-renderer'\n/**\n * @vitest-environment node\n */\nimport { createSSRApp, h } from 'vue'\nimport { NInputNumber } from '../..'\n\ndescribe('server side rendering', () => {\n  it('works', async () => {\n    const app = createSSRApp(() => <NInputNumber />)\n    setup(app)\n    try {\n      await renderToString(app)\n    }\n    catch (e) {\n      expect(e).not.toBeTruthy()\n    }\n  })\n})\n"
  },
  {
    "path": "src/input-otp/demos/enUS/basic.demo.vue",
    "content": "<markdown>\n# Basic\n\nThe number of characters is defined by the `length` prop, which by default is `6`.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { InputOtpOnUpdateValue } from 'naive-ui'\nimport { useMessage } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst message = useMessage()\n\nconst value = ref('654321'.split(''))\nconst onFocus = () => message.info('focus')\nconst onBlur = () => message.info('blur')\nconst onFinish = () => message.info('finish')\nconst onUpdateValue: InputOtpOnUpdateValue = value =>\n  message.info(JSON.stringify(value))\n</script>\n\n<template>\n  <n-input-otp\n    v-model:value=\"value\"\n    @focus=\"onFocus\"\n    @blur=\"onBlur\"\n    @finish=\"onFinish\"\n    @update:value=\"onUpdateValue\"\n  />\n</template>\n"
  },
  {
    "path": "src/input-otp/demos/enUS/block.demo.vue",
    "content": "<markdown>\n# Block\n\n`block` property will make the `n-input-otp` fit to its parent width.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { InputOtpOnUpdateValue } from 'naive-ui'\nimport { useMessage } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst message = useMessage()\n\nconst value = ref('654321'.split(''))\nconst onFocus = () => message.info('focus')\nconst onBlur = () => message.info('blur')\nconst onFinish = () => message.info('finish')\nconst onUpdateValue: InputOtpOnUpdateValue = value =>\n  message.info(JSON.stringify(value))\n</script>\n\n<template>\n  <n-input-otp\n    v-model:value=\"value\"\n    block\n    @focus=\"onFocus\"\n    @blur=\"onBlur\"\n    @finish=\"onFinish\"\n    @update:value=\"onUpdateValue\"\n  />\n</template>\n"
  },
  {
    "path": "src/input-otp/demos/enUS/form.demo.vue",
    "content": "<markdown>\n# Use with form\n\nAn example for using together with `n-form`.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { FormInst, FormRules } from 'naive-ui'\nimport { useMessage } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst formRef = ref<FormInst | null>(null)\nconst message = useMessage()\n\nconst formValue = ref({\n  passcode: null\n})\n\nconst rules: FormRules = {\n  passcode: [\n    {\n      message: 'Missing passcode',\n      validator: (_, value: string[] | null) => {\n        if (value === null)\n          return false\n        return value.filter(Boolean).length >= 6\n      },\n      trigger: ['blur']\n    },\n    {\n      message: 'Missing passcode',\n      validator: (_, value: string[] | null) => {\n        if (value === null)\n          return false\n        return value.filter(Boolean).length >= 1\n      },\n      trigger: ['input']\n    }\n  ]\n}\n\nfunction handleValidateClick(e: MouseEvent) {\n  e.preventDefault()\n  formRef.value?.validate(\n    (errors) => {\n      if (!errors) {\n        message.success('Valid')\n      }\n      else {\n        console.log(errors)\n        message.error('Invalid')\n      }\n    },\n    rule => !!rule.trigger?.includes('blur')\n  )\n}\n</script>\n\n<template>\n  <n-form ref=\"formRef\" inline :model=\"formValue\" :rules=\"rules\">\n    <n-form-item path=\"passcode\" label=\"Pass Code\">\n      <n-input-otp v-model:value=\"formValue.passcode\" />\n    </n-form-item>\n    <n-form-item>\n      <n-button attr-type=\"button\" @click=\"handleValidateClick\">\n        Validate\n      </n-button>\n    </n-form-item>\n  </n-form>\n</template>\n"
  },
  {
    "path": "src/input-otp/demos/enUS/index.demo-entry.md",
    "content": "# Input OTP\n\nInputOTP is used to enter one time password.\n\nAvailable since `2.41.1`.\n\n## Demos\n\n```demo\nbasic.vue\nstatus.vue\nmask.vue\ntemplate.vue\nblock.vue\nsize.vue\nform.vue\npattern.vue\n```\n\n## API\n\n### InputOTP Props\n\n| Name | Type | Type Alais | Default | Description | Version |\n| --- | --- | --- | --- | --- | --- |\n| allow-input | `(char: string, index: number, currentValue: string[]) => boolean` | `InputOtpAllowInput` | `undefined` | Check the incoming value, if it returns `false`, input will not be accepted. | 2.41.1 |\n| block | `boolean` |  | `false` | Whether to fit its width to its parent's width. | 2.42.0 |\n| default-value | `string[]` |  | `[]` | Default value. | 2.41.1 |\n| disabled | `boolean` |  | `false` | Whether the component is disabled. | 2.41.1 |\n| gap | `string \\| number` |  | `undefined` | Gap between different input. If not specified, the default styling would be applied. | 2.41.1 |\n| length | `number` |  | `6` | Number of characters to initiate. | 2.41.1 |\n| mask | `boolean` |  | `false` | Whether to enable password mode. | 2.41.1 |\n| placeholder | `string` |  | `''` | Input placeholder. | 2.41.1 |\n| readonly | `boolean` |  | `false` | Whether the component is readonly. | 2.41.1 |\n| size | `'small' \\| 'medium' \\| 'large'` | `InputOtpSize` | `'medium'` | Size of the component. | 2.41.1 |\n| status | `'success' \\| 'warning' \\| 'error'` | `FormValidationStatus` | `undefined` | The validation status of the component. | 2.41.1 |\n| value | `string \\| null` |  | `undefined` | Value of the component (in controlled mode). | 2.41.1 |\n| on-blur | `(event: FocusEvent, index: number) => void` | `InputOtpOnBlur` | `undefined` | Callback fired when the focus is out of the component. | 2.41.1 |\n| on-finish | `(value: string[]) => void` | `InputOtpOnFinish` | `undefined` | Callback fired when all child inputs are settled. | 2.41.1 |\n| on-focus | `(event: FocusEvent, index: number) => void` | `InputOtpOnFocus` | `undefined` | Callback fired when the focus is moved from outside to the component. | 2.41.1 |\n| on-update:value | `(value: string[], meta: { diff: string, index: number, source: 'input' \\| 'delete' \\| 'paste' }) => void` | `InputOtpOnUpdateValue`, `InputOtpOnUpdateValueMeta`, `InputOtpOnUpdateValueMetaSource` | `undefined` | Callback fired when user inputs value. `meta.index` is the start index of the value change.`meta.diff` is the content that changes. `meta.source` is the reason of the value change. If reason is `'delete'`, `meta.diff` is `''`. If reason is `'paste'`, `meta.diff` is the final accepted part of the paste content. | 2.41.1 |\n\n### InputOTP Slots\n\n| Name | Parameters | Type Alias | Description | Version |\n| --- | --- | --- | --- | --- |\n| default | `(props: InputProps & { index: number, ref: (inst: InputInst) => void })` | `InputOtpDefaultSlot` | Input area. | 2.41.1 |\n\n### InputOTP Methods\n\n| 名称 | 类型 | 说明 | 版本 |\n| --- | --- | --- | --- |\n| focusOnChar | `(charIndex: number) => void` | Focus on a certain input box. | 2.43.0 |\n"
  },
  {
    "path": "src/input-otp/demos/enUS/mask.demo.vue",
    "content": "<markdown>\n# Mask\n\nSet `mask=true` to turn on input mask.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst value = ref('654321'.split(''))\n</script>\n\n<template>\n  <n-input-otp v-model:value=\"value\" mask />\n</template>\n"
  },
  {
    "path": "src/input-otp/demos/enUS/pattern.demo.vue",
    "content": "<markdown>\n# Limit input format\n\nUse `allow-input` to limit input value to desired format.\n</markdown>\n\n<script lang=\"ts\" setup>\nconst onlyAllowNumber = (value: string) => !value || /^\\d+$/.test(value)\nconst onlyAllowEnglish = (value: string) => !value || /^[a-zA-Z]+$/.test(value)\n</script>\n\n<template>\n  <n-space vertical>\n    Only allow number input\n    <n-input-otp :allow-input=\"onlyAllowNumber\" />\n    Only allow character input\n    <n-input-otp :allow-input=\"onlyAllowEnglish\" />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/input-otp/demos/enUS/size.demo.vue",
    "content": "<markdown>\n# Size\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst value = ref('654321'.split(''))\n</script>\n\n<template>\n  <n-space vertical>\n    <n-input-otp v-model:value=\"value\" size=\"small\" />\n    <n-input-otp v-model:value=\"value\" />\n    <n-input-otp v-model:value=\"value\" size=\"large\" />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/input-otp/demos/enUS/status.demo.vue",
    "content": "<markdown>\n# Status\n\nReadonly, disabled, warning, error status.\n</markdown>\n\n<template>\n  <n-space vertical>\n    <n-input-otp :default-value=\"'123456'.split('')\" readonly />\n    <n-input-otp :default-value=\"'123456'.split('')\" disabled />\n    <n-input-otp :default-value=\"'123456'.split('')\" status=\"warning\" />\n    <n-input-otp :default-value=\"'123456'.split('')\" status=\"error\" />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/input-otp/demos/enUS/template.demo.vue",
    "content": "<markdown>\n# Custom rendering\n\nBy using `default` slot, you can custom UI to replace default design.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst value = ref('654321'.split(''))\n</script>\n\n<template>\n  <n-input-otp v-model:value=\"value\" gap=\"0\">\n    <template #default=\"{ index, ...inputProps }\">\n      <n-input\n        v-bind=\"inputProps\"\n        :style=\"index === 0 ? '' : 'margin-left: 6px;'\"\n      />\n      <span v-if=\"index === 1\" style=\"padding-left: 6px\">-</span>\n      <span v-if=\"index === 3\" style=\"padding-left: 6px\">-</span>\n    </template>\n  </n-input-otp>\n</template>\n"
  },
  {
    "path": "src/input-otp/demos/zhCN/basic.demo.vue",
    "content": "<markdown>\n# 基础用法\n\n字符数由 `length` 选项定义，默认情况下设置为 `6`。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { InputOtpOnUpdateValue } from 'naive-ui'\nimport { useMessage } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst message = useMessage()\n\nconst value = ref('654321'.split(''))\nconst onFocus = () => message.info('focus')\nconst onBlur = () => message.info('blur')\nconst onFinish = () => message.info('finish')\nconst onUpdateValue: InputOtpOnUpdateValue = value =>\n  message.info(JSON.stringify(value))\n</script>\n\n<template>\n  <n-input-otp\n    v-model:value=\"value\"\n    @focus=\"onFocus\"\n    @blur=\"onBlur\"\n    @finish=\"onFinish\"\n    @update:value=\"onUpdateValue\"\n  />\n</template>\n"
  },
  {
    "path": "src/input-otp/demos/zhCN/block.demo.vue",
    "content": "<markdown>\n# 沾满宽度\n\n设定 `block` 属性使其适合父元素宽度。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { InputOtpOnUpdateValue } from 'naive-ui'\nimport { useMessage } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst message = useMessage()\n\nconst value = ref('654321'.split(''))\nconst onFocus = () => message.info('focus')\nconst onBlur = () => message.info('blur')\nconst onFinish = () => message.info('finish')\nconst onUpdateValue: InputOtpOnUpdateValue = value =>\n  message.info(JSON.stringify(value))\n</script>\n\n<template>\n  <n-input-otp\n    v-model:value=\"value\"\n    block\n    @focus=\"onFocus\"\n    @blur=\"onBlur\"\n    @finish=\"onFinish\"\n    @update:value=\"onUpdateValue\"\n  />\n</template>\n"
  },
  {
    "path": "src/input-otp/demos/zhCN/form.demo.vue",
    "content": "<markdown>\n# 配合表单使用\n\n配合表单使用实现校验。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { FormInst, FormRules } from 'naive-ui'\nimport { useMessage } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst formRef = ref<FormInst | null>(null)\nconst message = useMessage()\n\nconst formValue = ref({\n  passcode: null\n})\n\nconst rules: FormRules = {\n  passcode: [\n    {\n      message: '请输入验证码',\n      validator: (_, value: string[] | null) => {\n        if (value === null)\n          return false\n        return value.filter(Boolean).length >= 6\n      },\n      trigger: ['blur']\n    },\n    {\n      message: '请输入验证码',\n      validator: (_, value: string[] | null) => {\n        if (value === null)\n          return false\n        return value.filter(Boolean).length >= 1\n      },\n      trigger: ['input']\n    }\n  ]\n}\n\nfunction handleValidateClick(e: MouseEvent) {\n  e.preventDefault()\n  formRef.value?.validate(\n    (errors) => {\n      if (!errors) {\n        message.success('验证成功')\n      }\n      else {\n        console.log(errors)\n        message.error('验证失败')\n      }\n    },\n    rule => !!rule.trigger?.includes('blur')\n  )\n}\n</script>\n\n<template>\n  <n-form ref=\"formRef\" inline :model=\"formValue\" :rules=\"rules\">\n    <n-form-item path=\"passcode\" label=\"验证码\">\n      <n-input-otp v-model:value=\"formValue.passcode\" />\n    </n-form-item>\n    <n-form-item>\n      <n-button attr-type=\"button\" @click=\"handleValidateClick\">\n        验证\n      </n-button>\n    </n-form-item>\n  </n-form>\n</template>\n"
  },
  {
    "path": "src/input-otp/demos/zhCN/index.demo-entry.md",
    "content": "# 验证码 Input OTP\n\n输入一次性密码。\n\n自 `2.41.1` 开始提供。\n\n## 演示\n\n```demo\nbasic.vue\nstatus.vue\nmask.vue\ntemplate.vue\nblock.vue\nsize.vue\nform.vue\npattern.vue\nrtl-debug.vue\n```\n\n## API\n\n### InputOTP Props\n\n| 名称 | 类型 | 类型别名 | 默认值 | 说明 | 版本 |\n| --- | --- | --- | --- | --- | --- |\n| allow-input | `(char: string, index: number, currentValue: string[]) => boolean` | `InputOtpAllowInput` | `undefined` | 校验当前的输入是否合法，如果返回 `false` 输入框便不会响应此次的输入 | 2.41.1 |\n| block | `boolean` |  | `false` | 是否将宽度调整为父元素宽度 | 2.42.0 |\n| default-value | `string[]` |  | `[]` | 默认值 | 2.41.1 |\n| disabled | `boolean` |  | `false` | 是否禁用 | 2.41.1 |\n| gap | `string \\| number` |  | `undefined` | 不同输入框之间的距离，如果不设定将使用默认值 | 2.41.1 |\n| length | `number` |  | `6` | 验证码的长度，根据长度渲染对应个数的输入框 | 2.41.1 |\n| mask | `boolean` |  | `false` | 是否是密码模式 | 2.41.1 |\n| placeholder | `string` |  | `''` | 输入的占位内容 | 2.41.1 |\n| readonly | `boolean` |  | `false` | 是否只读 | 2.41.1 |\n| size | `'small' \\| 'medium' \\| 'large'` | `InputOtpSize` | `'medium'` | 输入框尺寸 | 2.41.1 |\n| status | `'success' \\| 'warning' \\| 'error'` | `FormValidationStatus` | `undefined` | 验证状态 | 2.41.1 |\n| value | `string \\| null` |  | `undefined` | 验证码输入框的值，受控模式 | 2.41.1 |\n| on-blur | `(event: FocusEvent, index: number) => void` | `InputOtpOnBlur` | `undefined` | 从一个输入框被聚焦触发，到没有任何一个输入框被聚焦的回调 | 2.41.1 |\n| on-finish | `(value: string[]) => void` | `InputOtpOnFinish` | `undefined` | 完成输入的回调 | 2.41.1 |\n| on-focus | `(event: FocusEvent, index: number) => void` | `InputOtpOnFocus` | `undefined` | 从没有任何一个输入框被聚焦，到有一个输入框被聚焦触发的回调 | 2.41.1 |\n| on-update:value | `(value: string[], meta: { diff: string, index: number, source: 'input' \\| 'delete' \\| 'paste' }) => void` | `InputOtpOnUpdateValue`, `InputOtpOnUpdateValueMeta`, `InputOtpOnUpdateValueMetaSource` | `undefined` | 输入值时触发的回调，`meta.index` 为变更开始的 index，`meta.diff` 是变更的内容，`meta.source` 为变更的原因，当原因为 `'delete'` 时，`meta.diff` 为 `''`，当原因为 `'paste'` 时，`meta.diff` 最终粘贴进入的内容 | 2.41.1 |\n\n### InputOTP Slots\n\n| 名称 | 参数 | 类型别名 | 说明 | 版本 |\n| --- | --- | --- | --- | --- |\n| default | `(props: InputProps & { index: number, ref: (inst: InputInst) => void })` | `InputOtpDefaultSlot` | 输入区域 | 2.41.1 |\n\n### InputOTP Methods\n\n| 名称        | 类型                          | 说明             | 版本   |\n| ----------- | ----------------------------- | ---------------- | ------ |\n| focusOnChar | `(charIndex: number) => void` | 聚焦到某个输入框 | 2.43.0 |\n"
  },
  {
    "path": "src/input-otp/demos/zhCN/mask.demo.vue",
    "content": "<markdown>\n# 密码模式\n\n指定 `mask = true`，可开启密码模式。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst value = ref('654321'.split(''))\n</script>\n\n<template>\n  <n-input-otp v-model:value=\"value\" mask />\n</template>\n"
  },
  {
    "path": "src/input-otp/demos/zhCN/pattern.demo.vue",
    "content": "<markdown>\n# 只允许输入特定值\n\n使用 `allow-input` 限制输入框输入的内容。\n</markdown>\n\n<script lang=\"ts\" setup>\nconst onlyAllowNumber = (value: string) => !value || /^\\d+$/.test(value)\nconst onlyAllowEnglish = (value: string) => !value || /^[a-zA-Z]+$/.test(value)\n</script>\n\n<template>\n  <n-space vertical>\n    只允许数字输入\n    <n-input-otp :allow-input=\"onlyAllowNumber\" />\n    只允许英文字母输入\n    <n-input-otp :allow-input=\"onlyAllowEnglish\" />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/input-otp/demos/zhCN/rtl-debug.demo.vue",
    "content": "<markdown>\n# Rtl Debug\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { unstableInputOtpRtl } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst rtlEnabled = ref(false)\nconst rtlStyles = [unstableInputOtpRtl]\nconst value = ref('654321')\n</script>\n\n<template>\n  <n-space vertical>\n    <n-space><n-switch v-model:value=\"rtlEnabled\" />Rtl</n-space>\n    <n-config-provider :rtl=\"rtlEnabled ? rtlStyles : undefined\">\n      <n-input-otp v-model=\"value\" />\n    </n-config-provider>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/input-otp/demos/zhCN/size.demo.vue",
    "content": "<markdown>\n# 尺寸\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst value = ref('654321'.split(''))\n</script>\n\n<template>\n  <n-space vertical>\n    <n-input-otp v-model:value=\"value\" size=\"small\" />\n    <n-input-otp v-model:value=\"value\" />\n    <n-input-otp v-model:value=\"value\" size=\"large\" />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/input-otp/demos/zhCN/status.demo.vue",
    "content": "<markdown>\n# 状态\n\n只读状态、禁用状态、警告状态、错误状态。\n</markdown>\n\n<template>\n  <n-space vertical>\n    <n-input-otp :default-value=\"'123456'.split('')\" readonly />\n    <n-input-otp :default-value=\"'123456'.split('')\" disabled />\n    <n-input-otp :default-value=\"'123456'.split('')\" status=\"warning\" />\n    <n-input-otp :default-value=\"'123456'.split('')\" status=\"error\" />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/input-otp/demos/zhCN/template.demo.vue",
    "content": "<markdown>\n# 自定义渲染\n\n通过使用 `default` slot，你可以任意的对界面进行调整，以替换默认设计。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst value = ref('654321'.split(''))\n</script>\n\n<template>\n  <n-input-otp v-model:value=\"value\" gap=\"0\">\n    <template #default=\"{ index, ...inputProps }\">\n      <n-input\n        v-bind=\"inputProps\"\n        :style=\"index === 0 ? '' : 'margin-left: 6px;'\"\n      />\n      <span v-if=\"index === 1\" style=\"padding-left: 6px\">-</span>\n      <span v-if=\"index === 3\" style=\"padding-left: 6px\">-</span>\n    </template>\n  </n-input-otp>\n</template>\n"
  },
  {
    "path": "src/input-otp/index.ts",
    "content": "export { inputOtpProps, default as NInputOtp } from './src/InputOtp'\nexport type { InputOtpProps } from './src/InputOtp'\nexport type * from './src/public-types'\n"
  },
  {
    "path": "src/input-otp/src/InputOtp.tsx",
    "content": "import type { InputInst } from 'naive-ui'\nimport type { CSSProperties, PropType, SlotsType } from 'vue'\nimport type { ThemeProps } from '../../_mixins'\nimport type { ExtractPublicPropTypes, MaybeArray } from '../../_utils'\nimport type { FormValidationStatus } from '../../form/src/public-types'\nimport type { InputOtpTheme } from '../styles/light'\nimport type {\n  InputOtpAllowInput,\n  InputOtpInst,\n  InputOtpOnBlur,\n  InputOtpOnFinish,\n  InputOtpOnFocus,\n  InputOtpOnUpdateValue,\n  InputOtpOnUpdateValueMeta,\n  InputOtpSize,\n  InputOtpSlots\n} from './public-types'\nimport { pxfy, repeat } from 'seemly'\nimport { useMergedState } from 'vooks'\nimport { computed, defineComponent, h, ref, toRef } from 'vue'\nimport {\n  useConfig,\n  useFormItem,\n  useRtl,\n  useTheme,\n  useThemeClass\n} from '../../_mixins'\nimport {\n  call,\n  createKey,\n  isArrayShallowEqual,\n  resolveSlotWithTypedProps\n} from '../../_utils'\nimport { NInput } from '../../input'\nimport inputOtpLight from '../styles/light'\nimport style from './styles/index.cssr'\n\nexport const inputOtpProps = {\n  ...(useTheme.props as ThemeProps<InputOtpTheme>),\n  defaultValue: { type: Array as PropType<string[]>, default: [] },\n  value: Array as PropType<null | string[]>,\n  length: {\n    type: Number,\n    default: 6\n  },\n  block: Boolean,\n  size: String as PropType<InputOtpSize>,\n  disabled: Boolean,\n  mask: Boolean,\n  readonly: Boolean,\n  status: String as PropType<FormValidationStatus>,\n  gap: [String, Number] as PropType<string | number>,\n  placeholder: { type: String, default: '' },\n  allowInput: Function as PropType<InputOtpAllowInput>,\n  onBlur: [Function, Array] as PropType<MaybeArray<InputOtpOnBlur>>,\n  onFocus: [Function, Array] as PropType<MaybeArray<InputOtpOnFocus>>,\n  'onUpdate:value': [Function, Array] as PropType<\n    MaybeArray<InputOtpOnUpdateValue>\n  >,\n  onUpdateValue: [Function, Array] as PropType<\n    MaybeArray<InputOtpOnUpdateValue>\n  >,\n  onFinish: [Function, Array] as PropType<MaybeArray<InputOtpOnFinish>>\n}\n\nexport type InputOtpProps = ExtractPublicPropTypes<typeof inputOtpProps>\n\nexport default defineComponent({\n  name: 'InputOtp',\n  props: inputOtpProps,\n  slots: Object as SlotsType<InputOtpSlots>,\n  setup(props) {\n    const {\n      mergedClsPrefixRef,\n      mergedRtlRef,\n      inlineThemeDisabled,\n      mergedComponentPropsRef\n    } = useConfig(props)\n    const themeRef = useTheme(\n      'InputOtp',\n      '-input-otp',\n      style,\n      inputOtpLight,\n      props,\n      mergedClsPrefixRef\n    )\n    const rtlEnabledRef = useRtl('InputOtp', mergedRtlRef, mergedClsPrefixRef)\n\n    // form-item\n    const formItem = useFormItem(props, {\n      mergedSize: (NFormItem) => {\n        const { size } = props\n        if (size)\n          return size\n        const { mergedSize: formItemSize } = NFormItem || {}\n        if (formItemSize?.value)\n          return formItemSize.value as InputOtpSize\n        const configSize = mergedComponentPropsRef?.value?.InputOtp?.size\n        if (configSize)\n          return configSize\n        return 'medium'\n      }\n    })\n    const { mergedSizeRef, mergedDisabledRef, mergedStatusRef } = formItem\n\n    const cssVarsRef = computed(() => {\n      const { value: size } = mergedSizeRef\n      const { gap: propGap } = props\n      const {\n        self: {\n          [createKey('inputWidth', size)]: inputWidth,\n          [createKey('gap', size)]: gap\n        }\n      } = themeRef.value\n      return {\n        '--n-gap':\n          propGap === undefined\n            ? gap\n            : typeof propGap === 'number'\n              ? pxfy(propGap)\n              : propGap,\n        '--n-input-width': inputWidth\n      }\n    })\n\n    const themeClassHandle = inlineThemeDisabled\n      ? useThemeClass(\n          'input-otp',\n          computed(() => {\n            const { value: size } = mergedSizeRef\n            return size[0]\n          }),\n          cssVarsRef,\n          props\n        )\n      : undefined\n\n    const uncontrolledValueRef = ref(props.defaultValue)\n    const controlledValueRef = toRef(props, 'value')\n    const mergedValueRef = useMergedState(\n      controlledValueRef,\n      uncontrolledValueRef\n    )\n\n    const inputRefList = ref<InputInst[]>([])\n    const inputTypeRef = computed(() =>\n      props.mask ? ('password' as const) : ('text' as const)\n    )\n\n    const handleFocus = (e: FocusEvent, index: number) => {\n      // If it's focused from other input element inside the component, returns\n      if (\n        inputRefList?.value.some(\n          inputInst => inputInst.inputElRef === e.relatedTarget\n        )\n      ) {\n        return\n      }\n      const { onFocus } = props\n      if (onFocus) {\n        call(onFocus, e, index)\n      }\n      const { nTriggerFormFocus } = formItem\n      nTriggerFormFocus()\n    }\n\n    const handleBlur = (e: FocusEvent, index: number) => {\n      // If it's blured to other input element inside the component, returns\n      if (\n        inputRefList?.value.some(\n          inputInst => inputInst.inputElRef === e.relatedTarget\n        )\n      ) {\n        return\n      }\n      const { onBlur } = props\n      const { nTriggerFormBlur } = formItem\n      if (onBlur)\n        call(onBlur, e, index)\n      nTriggerFormBlur()\n    }\n\n    const focusOnChar = (charIndex: number) => {\n      if (charIndex >= props.length)\n        return\n      if (charIndex < 0)\n        return\n      inputRefList?.value[charIndex].focus()\n      inputRefList?.value[charIndex].select()\n    }\n\n    const focusOnNextChar = (currentIndex: number) => {\n      if (currentIndex >= props.length - 1) {\n        return\n      }\n      focusOnChar(currentIndex + 1)\n    }\n\n    const focusOnPrevChar = (currentIndex: number) => {\n      if (currentIndex <= 0) {\n        return\n      }\n      focusOnChar(currentIndex - 1)\n    }\n\n    const justifyValue = (value: string[] | null): string[] => {\n      const justifiedValue = value ? Array.from(value) : []\n      const length = props.length\n      while (justifiedValue.length > length) {\n        justifiedValue.pop()\n      }\n      while (justifiedValue.length < length) {\n        justifiedValue.push('')\n      }\n      return justifiedValue\n    }\n\n    function doUpdateValue(\n      value: string[],\n      meta: InputOtpOnUpdateValueMeta\n    ): void {\n      const { nTriggerFormInput, nTriggerFormChange } = formItem\n      if (isArrayShallowEqual(value, mergedValueRef.value)) {\n        nTriggerFormInput()\n        return\n      }\n      const {\n        'onUpdate:value': _onUpdateValue,\n        onUpdateValue,\n        length,\n        onFinish\n      } = props\n      if (_onUpdateValue)\n        call(_onUpdateValue, value, meta)\n      if (onUpdateValue)\n        call(onUpdateValue, value, meta)\n      if (value.filter(v => v).length === length && onFinish) {\n        call(onFinish, value)\n      }\n      uncontrolledValueRef.value = value\n      nTriggerFormInput()\n      nTriggerFormChange()\n    }\n\n    const handlePaste = (e: ClipboardEvent, index: number) => {\n      if (props.readonly || mergedDisabledRef.value) {\n        return\n      }\n\n      e.preventDefault()\n      const { clipboardData } = e\n      const text = clipboardData?.getData('text')\n      if (!text)\n        return\n\n      const currentValue = justifyValue(mergedValueRef.value)\n      let startIndex = index\n      const allowInput = props.allowInput\n      let pasteApplied = false\n      let appendedText = ''\n      for (let i = 0; i < text.length; ++i) {\n        if (allowInput && !allowInput(text[i], startIndex, currentValue)) {\n          continue\n        }\n        pasteApplied = true\n        currentValue[startIndex] = text[i]\n        appendedText += text[i]\n        startIndex++\n        if (startIndex >= currentValue.length) {\n          break\n        }\n      }\n\n      if (pasteApplied) {\n        focusOnChar(startIndex)\n        doUpdateValue(currentValue, {\n          diff: appendedText,\n          index: startIndex,\n          source: 'paste'\n        })\n      }\n    }\n\n    const handleKeydown = (e: KeyboardEvent, index: number) => {\n      if (mergedDisabledRef.value)\n        return\n      const keyCode = e.code || e.key\n      const currentValue = justifyValue(mergedValueRef.value)\n      if (keyCode === 'Backspace' && !props.readonly) {\n        e.preventDefault()\n        currentValue[Math.max(index, 0)] = ''\n        doUpdateValue(currentValue, { diff: '', index, source: 'delete' })\n        focusOnPrevChar(index)\n      }\n      else if (keyCode === 'ArrowLeft') {\n        e.preventDefault()\n        focusOnPrevChar(index)\n      }\n      else if (keyCode === 'ArrowRight') {\n        e.preventDefault()\n        focusOnNextChar(index)\n      }\n    }\n\n    const handleInput = (value: string, index: number) => {\n      const currentValue = justifyValue(mergedValueRef.value)\n      const currentValueAtIndex = currentValue[index]\n      const diff = value.replace(currentValueAtIndex, '')\n      const char = diff[diff.length - 1] || value[value.length - 1] || ''\n      const allowInput = props.allowInput\n      if (allowInput && !allowInput(char, index, currentValue)) {\n        return\n      }\n      currentValue[index] = char\n      doUpdateValue(currentValue, { diff: char, index, source: 'input' })\n      focusOnNextChar(index)\n    }\n\n    const getTemplateEvents = (index: number) => {\n      return {\n        onInput: (value: string) => handleInput(value, index),\n        onPaste: (event: ClipboardEvent) => handlePaste(event, index),\n        onKeydown: (event: KeyboardEvent) => handleKeydown(event, index),\n        onFocus: (event: FocusEvent) => handleFocus(event, index),\n        onBlur: (event: FocusEvent) => handleBlur(event, index)\n      }\n    }\n\n    const exposedMethods: InputOtpInst = {\n      focusOnChar\n    }\n\n    return {\n      mergedTheme: themeRef,\n      perItemValueArray: computed(() => justifyValue(mergedValueRef.value)),\n      mergedClsPrefix: mergedClsPrefixRef,\n      inputRefList,\n      inputType: inputTypeRef,\n      rtlEnabled: rtlEnabledRef,\n      mergedStatus: mergedStatusRef,\n      mergedDisabled: mergedDisabledRef,\n      cssVars: inlineThemeDisabled ? undefined : cssVarsRef,\n      themeClass: themeClassHandle?.themeClass,\n      getTemplateEvents,\n      onRender: themeClassHandle?.onRender,\n      ...exposedMethods\n    }\n  },\n  render() {\n    const {\n      mergedTheme,\n      mergedClsPrefix,\n      perItemValueArray,\n      size,\n      placeholder,\n      mergedDisabled,\n      mergedStatus,\n      readonly,\n      inputType,\n      $slots,\n      getTemplateEvents,\n      themeClass,\n      onRender\n    } = this\n    onRender?.()\n    return (\n      <div\n        style={this.cssVars as CSSProperties}\n        class={[\n          `${mergedClsPrefix}-input-otp`,\n          themeClass,\n          this.rtlEnabled && `${mergedClsPrefix}-input-otp--rtl`,\n          this.block && `${mergedClsPrefix}-input-otp--block`\n        ]}\n      >\n        {repeat(this.length, undefined).map((_, index) =>\n          resolveSlotWithTypedProps(\n            $slots.default,\n            {\n              index,\n              value: perItemValueArray[index],\n              type: inputType,\n              size,\n              placeholder,\n              disabled: mergedDisabled,\n              readonly,\n              status: mergedStatus,\n              builtinThemeOverrides: {\n                paddingTiny: '0',\n                paddingSmall: '0',\n                paddingMedium: '0',\n                paddingLarge: '0'\n              },\n              theme: mergedTheme.peers.Input,\n              themeOverrides: mergedTheme.peerOverrides.Input,\n              ref: (el: any) => (this.inputRefList[index] = el),\n              ...getTemplateEvents(index)\n            },\n            ({ index, ...restProps }) => [<NInput {...restProps} key={index} />]\n          )\n        )}\n      </div>\n    )\n  }\n})\n"
  },
  {
    "path": "src/input-otp/src/public-types.ts",
    "content": "import type { VNode } from 'vue'\nimport type { InputInst } from '../../components'\nimport type { InputProps } from '../../input/src/Input'\n\nexport type InputOtpAllowInput = (\n  char: string,\n  index: number,\n  currentValue: string[]\n) => boolean\nexport type InputOtpSize = 'small' | 'medium' | 'large'\nexport type InputOtpOnUpdateValue = (\n  value: string[],\n  meta: InputOtpOnUpdateValueMeta\n) => void\nexport type InputOtpOnFocus = (e: FocusEvent, index: number) => void\nexport type InputOtpOnBlur = (e: FocusEvent, index: number) => void\nexport interface InputOtpSlots {\n  default?: InputOtpDefaultSlot\n}\nexport type InputOtpDefaultSlot = (\n  props: InputProps & { index: number, ref: (inst: InputInst) => void }\n) => VNode[]\nexport type InputOtpOnFinish = (value: string[]) => void\nexport interface InputOtpOnUpdateValueMeta {\n  diff: string\n  index: number\n  source: InputOtpOnUpdateValueMetaSource\n}\nexport type InputOtpOnUpdateValueMetaSource = 'paste' | 'input' | 'delete'\nexport interface InputOtpInst {\n  focusOnChar: (charIndex: number) => void\n}\n"
  },
  {
    "path": "src/input-otp/src/styles/index.cssr.ts",
    "content": "import { c, cB, cM, cNotM } from '../../../_utils/cssr'\n\n// --n-input-width\n// --n-gap\nexport default c([\n  cB('input-otp', `\n    display: flex;\n    align-items: center;\n    gap: var(--n-gap);\n  `, [\n    cM('block', ``, [\n      cB('input', ``, [\n        cNotM('autosize', `\n          text-align: center;\n          min-width: 0;\n        `),\n        cM('autosize', `\n          text-align: center;\n          min-width: 0;\n        `)\n      ]),\n    ]),\n    cNotM('block', ``, [\n      cB('input', ``, [\n        cNotM('autosize', `\n          width: var(--n-input-width);\n          text-align: center;\n        `),\n        cM('autosize', `\n          width: var(--n-input-width);\n          text-align: center;\n        `)\n      ])\n    ])\n  ])\n])\n"
  },
  {
    "path": "src/input-otp/src/styles/input-otp-rtl.cssr.ts",
    "content": "import { cB, cM } from '../../../_utils/cssr'\n\n// --n-gap\nexport default cB('input-otp', [\n  cM('rtl', `\n    direction: rtl;\n  `)\n])\n"
  },
  {
    "path": "src/input-otp/styles/dark.ts",
    "content": "import type { InputOtpTheme } from './light'\nimport { commonDark } from '../../_styles/common'\nimport { inputDark } from '../../input/styles'\nimport { self } from './light'\n\nconst inputOtpDark: InputOtpTheme = {\n  name: 'InputOtp',\n  common: commonDark,\n  peers: {\n    Input: inputDark\n  },\n  self\n}\n\nexport default inputOtpDark\n"
  },
  {
    "path": "src/input-otp/styles/index.ts",
    "content": "export { default as inputOtpDark } from './dark'\nexport { default as inputOtpLight } from './light'\nexport type { InputOtpTheme } from './light'\nexport { inputOtpRtl } from './rtl'\n"
  },
  {
    "path": "src/input-otp/styles/light.ts",
    "content": "import { createTheme } from '../../_mixins'\nimport { commonLight } from '../../_styles/common'\nimport { inputLight } from '../../input/styles'\n\nexport function self() {\n  return {\n    inputWidthSmall: '24px',\n    inputWidthMedium: '30px',\n    inputWidthLarge: '36px',\n    gapSmall: '8px',\n    gapMedium: '8px',\n    gapLarge: '8px'\n  }\n}\n\nconst inputOtpLight = createTheme({\n  name: 'InputOtp',\n  common: commonLight,\n  peers: {\n    Input: inputLight\n  },\n  self\n})\n\nexport default inputOtpLight\nexport type InputOtpTheme = typeof inputOtpLight\n"
  },
  {
    "path": "src/input-otp/styles/rtl.ts",
    "content": "import type { RtlItem } from '../../config-provider/src/internal-interface'\nimport rtlStyle from '../src/styles/input-otp-rtl.cssr'\n\nexport const inputOtpRtl: RtlItem = {\n  name: 'InputOtp',\n  style: rtlStyle\n}\n"
  },
  {
    "path": "src/input-otp/tests/InputOtp.spec.tsx",
    "content": "import { mount } from '@vue/test-utils'\nimport { NInputOtp } from '../index'\n\ndescribe('n-input-number', () => {\n  it('should work with import on demand', () => {\n    mount(NInputOtp)\n  })\n})\n"
  },
  {
    "path": "src/input-otp/tests/server.spec.tsx",
    "content": "import { setup } from '@css-render/vue3-ssr'\nimport { renderToString } from '@vue/server-renderer'\n/**\n * @vitest-environment node\n */\nimport { createSSRApp, h } from 'vue'\nimport { NInputOtp } from '../..'\n\ndescribe('server side rendering', () => {\n  it('works', async () => {\n    const app = createSSRApp(() => <NInputOtp />)\n    setup(app)\n    try {\n      await renderToString(app)\n    }\n    catch (e) {\n      expect(e).not.toBeTruthy()\n    }\n  })\n})\n"
  },
  {
    "path": "src/layout/demos/enUS/absolute.demo.vue",
    "content": "<markdown>\n# Absolute position\n\nAll layout components can use absolute positioning. It can be used when you want content scrolling inside fixed area.\n</markdown>\n\n<template>\n  <div style=\"height: 360px; position: relative\">\n    <n-layout position=\"absolute\">\n      <n-layout-header style=\"height: 64px; padding: 24px\" bordered>\n        Yiheyuan Road\n      </n-layout-header>\n      <n-layout has-sider position=\"absolute\" style=\"top: 64px; bottom: 64px\">\n        <n-layout-sider bordered content-style=\"padding: 24px;\">\n          Handian Bridge\n        </n-layout-sider>\n        <n-layout content-style=\"padding: 24px;\">\n          <n-h2>Pingshan Road</n-h2>\n          <n-h2>Pingshan Road</n-h2>\n          <n-h2>Pingshan Road</n-h2>\n          <n-h2>Pingshan Road</n-h2>\n          <n-h2>Pingshan Road</n-h2>\n          <n-h2>Pingshan Road</n-h2>\n          <n-h2>Pingshan Road</n-h2>\n          <n-h2>Pingshan Road</n-h2>\n          <n-h2>Pingshan Road</n-h2>\n          <n-h2>Pingshan Road</n-h2>\n          <n-h2>Pingshan Road</n-h2>\n          <n-h2>Pingshan Road</n-h2>\n        </n-layout>\n      </n-layout>\n      <n-layout-footer\n        bordered\n        position=\"absolute\"\n        style=\"height: 64px; padding: 24px\"\n      >\n        城府路\n      </n-layout-footer>\n    </n-layout>\n  </div>\n</template>\n"
  },
  {
    "path": "src/layout/demos/enUS/basic.demo.vue",
    "content": "<markdown>\n# Basic\n\nI hope the demo can meet you demand, so that you can have more time to do other things.\n</markdown>\n\n<template>\n  <n-space vertical size=\"large\">\n    <n-layout>\n      <n-layout-header>Yiheyuan Road</n-layout-header>\n      <n-layout-content content-style=\"padding: 24px;\">\n        Pingshan Road\n      </n-layout-content>\n      <n-layout-footer>Chengfu Road</n-layout-footer>\n    </n-layout>\n    <n-layout>\n      <n-layout-header>Yiheyuan Road</n-layout-header>\n      <n-layout has-sider>\n        <n-layout-sider content-style=\"padding: 24px;\">\n          Handian Bridge\n        </n-layout-sider>\n        <n-layout-content content-style=\"padding: 24px;\">\n          Pingshan Road\n        </n-layout-content>\n      </n-layout>\n      <n-layout-footer>Chengfu Road</n-layout-footer>\n    </n-layout>\n    <n-layout has-sider>\n      <n-layout-sider content-style=\"padding: 24px;\">\n        Handian Bridge\n      </n-layout-sider>\n      <n-layout>\n        <n-layout-header>Yiheyuan Road</n-layout-header>\n        <n-layout-content content-style=\"padding: 24px;\">\n          Pingshan Road\n        </n-layout-content>\n        <n-layout-footer>Chengfu Road</n-layout-footer>\n      </n-layout>\n    </n-layout>\n  </n-space>\n</template>\n\n<style>\n.n-layout-header,\n.n-layout-footer {\n  background: rgba(128, 128, 128, 0.2);\n  padding: 24px;\n}\n\n.n-layout-sider {\n  background: rgba(128, 128, 128, 0.3);\n}\n\n.n-layout-content {\n  background: rgba(128, 128, 128, 0.4);\n}\n</style>\n"
  },
  {
    "path": "src/layout/demos/enUS/border.demo.vue",
    "content": "<markdown>\n# Border\n\nYou can set `bordered` on sider、footer、header.\n</markdown>\n\n<template>\n  <n-layout has-sider>\n    <n-layout-sider bordered content-style=\"padding: 24px;\">\n      Handian Bridge\n    </n-layout-sider>\n    <n-layout>\n      <n-layout-header bordered>\n        Yiheyuan Road\n      </n-layout-header>\n      <n-layout-content content-style=\"padding: 24px;\">\n        Pingshan Road\n      </n-layout-content>\n      <n-layout-footer bordered>\n        Chengfu Road\n      </n-layout-footer>\n    </n-layout>\n  </n-layout>\n</template>\n\n<style>\n.n-layout-header {\n  padding: 24px;\n}\n\n.n-layout-footer {\n  padding: 24px;\n}\n</style>\n"
  },
  {
    "path": "src/layout/demos/enUS/collapse-right.demo.vue",
    "content": "<markdown>\n# Sider placement\n\nSometimes you might want to put the collapsed sidebar on the right.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { Component } from 'vue'\nimport {\n  BookOutline as BookIcon,\n  PersonOutline as PersonIcon,\n  WineOutline as WineIcon\n} from '@vicons/ionicons5'\nimport { NIcon } from 'naive-ui'\nimport { h } from 'vue'\n\nfunction renderIcon(icon: Component) {\n  return () => h(NIcon, null, { default: () => h(icon) })\n}\n\nconst menuOptions = [\n  {\n    label: 'Hear the Wind Sing',\n    key: 'hear-the-wind-sing',\n    icon: renderIcon(BookIcon)\n  },\n  {\n    label: 'Pinball 1973',\n    key: 'pinball-1973',\n    icon: renderIcon(BookIcon),\n    disabled: true,\n    children: [\n      {\n        label: 'Rat',\n        key: 'rat'\n      }\n    ]\n  },\n  {\n    label: 'A Wild Sheep Chase',\n    key: 'a-wild-sheep-chase',\n    disabled: true,\n    icon: renderIcon(BookIcon)\n  },\n  {\n    label: 'Dance Dance Dance',\n    key: 'Dance Dance Dance',\n    icon: renderIcon(BookIcon),\n    children: [\n      {\n        type: 'group',\n        label: 'People',\n        key: 'people',\n        children: [\n          {\n            label: 'Narrator',\n            key: 'narrator',\n            icon: renderIcon(PersonIcon)\n          },\n          {\n            label: 'Sheep Man',\n            key: 'sheep-man',\n            icon: renderIcon(PersonIcon)\n          }\n        ]\n      },\n      {\n        label: 'Beverage',\n        key: 'beverage',\n        icon: renderIcon(WineIcon),\n        children: [\n          {\n            label: 'Whisky',\n            key: 'whisky'\n          }\n        ]\n      },\n      {\n        label: 'Food',\n        key: 'food',\n        children: [\n          {\n            label: 'Sandwich',\n            key: 'sandwich'\n          }\n        ]\n      },\n      {\n        label: 'The past increases. The future recedes.',\n        key: 'the-past-increases-the-future-recedes'\n      }\n    ]\n  }\n]\n</script>\n\n<template>\n  <n-space vertical size=\"large\">\n    <n-layout has-sider sider-placement=\"right\">\n      <n-layout-content content-style=\"padding: 24px;\">\n        Pingshan Road\n      </n-layout-content>\n      <n-layout-sider\n        collapse-mode=\"width\"\n        :collapsed-width=\"120\"\n        :native-scrollbar=\"true\"\n        :width=\"240\"\n        show-trigger=\"arrow-circle\"\n        content-style=\"padding: 24px;\"\n        bordered\n      >\n        <p>\n          Handian Bridge Handian Bridge Handian Bridge Handian Bridge Handian\n          Bridge\n        </p>\n      </n-layout-sider>\n    </n-layout>\n    <n-layout has-sider sider-placement=\"right\">\n      <n-layout-content content-style=\"padding: 24px;\">\n        Pingshan Road\n      </n-layout-content>\n      <n-layout-sider\n        collapse-mode=\"transform\"\n        :native-scrollbar=\"false\"\n        :collapsed-width=\"120\"\n        :width=\"240\"\n        show-trigger=\"bar\"\n        content-style=\"padding: 24px;\"\n        bordered\n      >\n        <n-h2>Handian Bridge</n-h2>\n      </n-layout-sider>\n    </n-layout>\n    <n-layout has-sider sider-placement=\"right\">\n      <n-layout style=\"max-height: 320px\" />\n      <n-layout-sider\n        bordered\n        show-trigger\n        collapse-mode=\"width\"\n        :collapsed-width=\"64\"\n        :width=\"240\"\n        :native-scrollbar=\"false\"\n        style=\"max-height: 320px\"\n      >\n        <n-menu\n          :collapsed-width=\"64\"\n          :collapsed-icon-size=\"22\"\n          :options=\"menuOptions\"\n        />\n      </n-layout-sider>\n    </n-layout>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/layout/demos/enUS/collapse.demo.vue",
    "content": "<markdown>\n# Collapse sider\n\nUse `show-trigger` to use builtin button.\n</markdown>\n\n<template>\n  <n-space vertical size=\"large\">\n    <n-layout has-sider>\n      <n-layout-sider\n        collapse-mode=\"width\"\n        :collapsed-width=\"120\"\n        :width=\"240\"\n        show-trigger=\"bar\"\n        content-style=\"padding: 24px;\"\n        bordered\n      >\n        <p>\n          Handian Bridge Handian Bridge Handian Bridge Handian Bridge Handian\n          Bridge\n        </p>\n      </n-layout-sider>\n      <n-layout-content content-style=\"padding: 24px;\">\n        Pingshan Road\n      </n-layout-content>\n    </n-layout>\n    <n-layout has-sider>\n      <n-layout-sider\n        collapse-mode=\"transform\"\n        :collapsed-width=\"120\"\n        :width=\"240\"\n        show-trigger=\"arrow-circle\"\n        content-style=\"padding: 24px;\"\n        bordered\n      >\n        <n-h2>Handian Bridge</n-h2>\n      </n-layout-sider>\n      <n-layout-content content-style=\"padding: 24px;\">\n        Pingshan Road\n      </n-layout-content>\n    </n-layout>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/layout/demos/enUS/embedded.demo.vue",
    "content": "<markdown>\n# Embedded effect\n\nSometimes you may want the background to be darker to highlight the content (especially card like things).\n</markdown>\n\n<template>\n  <n-layout embedded content-style=\"padding: 24px;\">\n    <n-card>\n      All you need to do to look to those clouds,<br>\n      and every day be in a good mood.\n    </n-card>\n  </n-layout>\n</template>\n"
  },
  {
    "path": "src/layout/demos/enUS/index.demo-entry.md",
    "content": "# Layout\n\n<!--single-column-->\n\nLayout is for layout.\n\nThe component is a bit complicated to use. But like a manual gear car, it worths a shot.\n\nIf you are use version before v2.3.0, you may want to know about <n-a href=\"#Changes-After-v2.3.0\">Changes After v2.3.0</n-a>.\n\n## Demos\n\n```demo\nbasic.vue\nset-padding.vue\nborder.vue\nembedded.vue\nabsolute.vue\nscrollbar.vue\ncollapse.vue\ncollapse-right.vue\ninverted.vue\nshow-sider-content.vue\nscroll-to.vue\n```\n\n## API\n\n### Layout, Layout Content Props\n\n| Name | Type | Default | Description | Version |\n| --- | --- | --- | --- | --- |\n| content-class | `string` | `undefined` | Class of scrollable content node. | 2.36.0 |\n| content-style | `string \\| Object` | `undefined` | Style of scrollable content node. |  |\n| embedded | `boolean` | `false` | Use darker background to show a embedded effect. Only work for light theme. |  |\n| has-sider | `boolean` | `false` | Whether the component has sider inside. If so it must be `true`. |  |\n| native-scrollbar | `boolean` | `true` | Whether to use native scrollbar on itself. If set to `false`, layout will use a naive-ui style scrollbar for content. |  |\n| position | `'static' \\| 'absolute'` | `'static'` | `static` position will make it css position set to `static`. `absolute` position will make it css position set to `absolute` and `left`, `right`, `top`, `bottom` to `0`. `absolute` position is very useful when you want to make content scroll in a fixed container or make the whole page's layout in a fixed position. You may need to change the style of the component to make it display as you expect. |  |\n| scrollbar-props | `ScrollbarProps` | `undefined` | See [Scrollbar props](scrollbar#Scrollbar-Props). |  |\n| sider-placement | `'left' \\| 'right'` | `left` | The sidebar is displayed on the left or the right side. |  |\n| on-scroll | `(e: Event) => void` | `undefined` | Callback function when the content scroll. |  |\n\n### Layout Footer Props\n\n| Name | Type | Default | Description |\n| --- | --- | --- | --- |\n| bordered | `boolean` | `false` | Whether to show the border. |\n| inverted | `boolean` | `false` | Whether to use inverted background. |\n| position | `'static' \\| 'absolute'` | `'static'` | `static` position will make it css position set to `static`. `absolute` position will make it css position set to `absolute` and `left`, `right`, `top` to `0`. `absolute` position is very useful when you want to make content scroll in a fixed container or make the whole page's layout in a fixed position. You may need to change the style of the component to make it display as you expect. |\n\n### Layout Header Props\n\n| Name | Type | Default | Description |\n| --- | --- | --- | --- |\n| bordered | `boolean` | `false` | Whether to show the border. |\n| inverted | `boolean` | `false` | Whether to use inverted background. |\n| position | `'static' \\| 'absolute'` | `'static'` | `static` position will make it css position set to `static`. `absolute` position will make it css position set to `absolute` and `left`, `right`, `bottom` to `0`. `absolute` position is very useful when you want to make content scroll in a fixed container or make the whole page's layout in a fixed position. You may need to change the style of the component to ma ke as you expect. |\n\n### Layout Sider Props\n\n| Name | Type | Default | Description | Version |\n| --- | --- | --- | --- | --- |\n| bordered | `boolean` | `false` | Whether to show the border. |  |\n| collapse-mode | `'transform' \\| 'width'` | `'transform'` | If set to `'width'`, the sider's content width will be actually collapsed. If set to `'transform'`, the sider will only move it's position and won't change its content width. |  |\n| collapsed | `boolean` | `undefined` | Whether the sider is collapsed. It only works for when `position` is `'static'`. |  |\n| collapsed-trigger-class | `string` | `undefined` | Trigger class when collapsed. | 2.36.0 |\n| collapsed-trigger-style | `string \\| Object` | `undefined` | Trigger style when collapsed. |  |\n| collapsed-width | `number` | `48` | Folded width. |  |\n| content-class | `string` | `undefined` | Class of scrollable content node. |  |\n| content-style | `string \\| Object` | `undefined` | Style of scrollable content node. |  |\n| default-collapsed | `boolean` | `false` | Default collapsed state in uncontrolled mode. |  |\n| inverted | `boolean` | `false` | Whether to use inverted background. |  |\n| native-scrollbar | `boolean` | `true` | Whether to use native scrollbar on itself. If set to `false`, sider will use a naive-ui style scrollbar for content. |  |\n| position | `'static' \\| 'absolute'` | `'static'` | `static` position will make it css position set to `static`. `absolute` position will make it css position set to `absolute` and `left`, `top`, `bottom` to `0`. `absolute` position is very useful when you want to make content scroll in a fixed container or make the whole page's layout in a fixed position. You may need to change the style of the component to make it as you expect. |  |\n| scrollbar-props | `ScrollbarProps` | `undefined` | See [Scrollbar props](scrollbar#Scrollbar-Props). |  |\n| show-collapsed-content | `boolean` | `true` | Whether to show content in sider after it is collapsed. |  |\n| show-trigger | `boolean \\| 'bar' \\| 'arrow-circle'` | `false` | Whether to show the built-in trigger button on sider. |  |\n| trigger-class | `string` | `undefined` | Trigger class. | 2.36.0 |\n| trigger-style | `string \\| Object` | `undefined` | Trigger style. |  |\n| width | `number \\| string` | `272` | Width CSS value. When it is number, px will be added. |  |\n| on-after-enter | `() => void` | `undefined` | Callback after it's expanded. |  |\n| on-after-leave | `() => void` | `undefined` | Callback after it's collapsed. |  |\n| on-scroll | `(e: Event) => void` | `undefined` | Callback function when the content scroll. |  |\n| on-update:collapsed | `(collapsed: boolean) => void` | `undefined` | Callback function when the folding state changes. |  |\n\n### Layout, Layout Content, Layout Sider, Layout Header, Layout Footer Slots\n\n| Name    | Parameters | Description     |\n| ------- | ---------- | --------------- |\n| default | `()`       | Layout content. |\n\n### Layout, Layout Content, Layout Sider Methods\n\n| Name | Type | Description |\n| --- | --- | --- |\n| scrollTo | `((xCoord: number, yCoord: number) => void) \\| (options: { left?: number, top?: number, behavior: 'smooth' \\| 'auto' }) => void` | Scroll to somewhere. |\n\n## Changes After v2.3.0\n\nDue to concerns about performance and SSR, after v2.3.0 you need to specify `has-sider` on the `n-layout` which contains `n-layout-sider`. Collapsing won't work for `n-layout-sider` with `position=\"absolute\"`.\n\n```html\nBefore v2.3.0:\n<n-layout>\n  <n-layout-sider />\n  <n-layout />\n</n-layout>\n\nAfter v2.3.0:\n<n-layout has-sider>\n  <n-layout-sider />\n  <n-layout />\n</n-layout>\n```\n"
  },
  {
    "path": "src/layout/demos/enUS/inverted.demo.vue",
    "content": "<markdown>\n# Inverted\n\nUse `inverted` to add contrast. You can set the prop on header, footer and sider. Usually used with menu.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { Component } from 'vue'\nimport {\n  BookOutline as BookIcon,\n  PersonOutline as PersonIcon,\n  WineOutline as WineIcon\n} from '@vicons/ionicons5'\nimport { NIcon } from 'naive-ui'\nimport { h, ref } from 'vue'\n\nfunction renderIcon(icon: Component) {\n  return () => h(NIcon, null, { default: () => h(icon) })\n}\n\nconst menuOptions = [\n  {\n    label: 'Hear the Wind Sing',\n    key: 'hear-the-wind-sing',\n    icon: renderIcon(BookIcon)\n  },\n  {\n    label: 'Pinball 1973',\n    key: 'pinball-1973',\n    icon: renderIcon(BookIcon),\n    disabled: true,\n    children: [\n      {\n        label: 'Rat',\n        key: 'rat'\n      }\n    ]\n  },\n  {\n    label: 'A Wild Sheep Chase',\n    key: 'a-wild-sheep-chase',\n    disabled: true,\n    icon: renderIcon(BookIcon)\n  },\n  {\n    label: 'Dance Dance Dance',\n    key: 'Dance Dance Dance',\n    icon: renderIcon(BookIcon),\n    children: [\n      {\n        type: 'group',\n        label: 'People',\n        key: 'people',\n        children: [\n          {\n            label: 'Narrator',\n            key: 'narrator',\n            icon: renderIcon(PersonIcon)\n          },\n          {\n            label: 'Sheep Man',\n            key: 'sheep-man',\n            icon: renderIcon(PersonIcon)\n          }\n        ]\n      },\n      {\n        label: 'Beverage',\n        key: 'beverage',\n        icon: renderIcon(WineIcon),\n        children: [\n          {\n            label: 'Whisky',\n            key: 'whisky'\n          }\n        ]\n      },\n      {\n        label: 'Food',\n        key: 'food',\n        children: [\n          {\n            label: 'Sandwich',\n            key: 'sandwich'\n          }\n        ]\n      },\n      {\n        label: 'The past increases. The future recedes.',\n        key: 'the-past-increases-the-future-recedes'\n      }\n    ]\n  }\n]\n\nconst inverted = ref(false)\n</script>\n\n<template>\n  <n-space vertical>\n    <n-space> <n-switch v-model:value=\"inverted\" /> inverted </n-space>\n    <n-layout>\n      <n-layout-header :inverted=\"inverted\" bordered>\n        Header Header Header\n        <n-menu mode=\"horizontal\" :inverted=\"inverted\" :options=\"menuOptions\" />\n      </n-layout-header>\n      <n-layout has-sider>\n        <n-layout-sider\n          bordered\n          show-trigger\n          collapse-mode=\"width\"\n          :collapsed-width=\"64\"\n          :width=\"240\"\n          :native-scrollbar=\"false\"\n          :inverted=\"inverted\"\n          style=\"max-height: 320px\"\n        >\n          <n-menu\n            :inverted=\"inverted\"\n            :collapsed-width=\"64\"\n            :collapsed-icon-size=\"22\"\n            :options=\"menuOptions\"\n          />\n        </n-layout-sider>\n        <n-layout style=\"max-height: 320px\" />\n      </n-layout>\n      <n-layout-footer :inverted=\"inverted\" bordered>\n        Footer Footer Footer\n      </n-layout-footer>\n    </n-layout>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/layout/demos/enUS/scroll-to.demo.vue",
    "content": "<markdown>\n# Scroll to\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { LayoutInst, LayoutSiderInst } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst siderRef = ref<LayoutSiderInst | null>(null)\nconst contentRef = ref<LayoutInst | null>(null)\n</script>\n\n<template>\n  <n-space vertical size=\"large\">\n    <n-space>\n      <n-button @click=\"siderRef?.scrollTo({ top: 120, behavior: 'smooth' })\">\n        Sider scroll to 120px\n      </n-button>\n      <n-button @click=\"contentRef?.scrollTo({ top: 120, behavior: 'smooth' })\">\n        Content scroll to 120px\n      </n-button>\n    </n-space>\n    <n-layout style=\"height: 360px\">\n      <n-layout-header style=\"height: 64px; padding: 24px\" bordered>\n        Yiheyuan Road\n      </n-layout-header>\n      <n-layout has-sider position=\"absolute\" style=\"top: 64px; bottom: 64px\">\n        <n-layout-sider ref=\"siderRef\" bordered content-style=\"padding: 24px;\">\n          <n-h2>Handian Bridge</n-h2>\n          <n-h2>Handian Bridge</n-h2>\n          <n-h2>Handian Bridge</n-h2>\n          <n-h2>Handian Bridge</n-h2>\n          <n-h2>Handian Bridge</n-h2>\n          <n-h2>Handian Bridge</n-h2>\n          <n-h2>Handian Bridge</n-h2>\n          <n-h2>Handian Bridge</n-h2>\n          <n-h2>Handian Bridge</n-h2>\n          <n-h2>Handian Bridge</n-h2>\n          <n-h2>Handian Bridge</n-h2>\n          <n-h2>Handian Bridge</n-h2>\n        </n-layout-sider>\n        <n-layout-content\n          ref=\"contentRef\"\n          content-style=\"padding: 24px;\"\n          :native-scrollbar=\"false\"\n        >\n          <n-h2>Pingshan Road</n-h2>\n          <n-h2>Pingshan Road</n-h2>\n          <n-h2>Pingshan Road</n-h2>\n          <n-h2>Pingshan Road</n-h2>\n          <n-h2>Pingshan Road</n-h2>\n          <n-h2>Pingshan Road</n-h2>\n          <n-h2>Pingshan Road</n-h2>\n          <n-h2>Pingshan Road</n-h2>\n          <n-h2>Pingshan Road</n-h2>\n          <n-h2>Pingshan Road</n-h2>\n          <n-h2>Pingshan Road</n-h2>\n          <n-h2>Pingshan Road</n-h2>\n        </n-layout-content>\n      </n-layout>\n      <n-layout-footer\n        bordered\n        position=\"absolute\"\n        style=\"height: 64px; padding: 24px\"\n      >\n        Chengfu Road\n      </n-layout-footer>\n    </n-layout>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/layout/demos/enUS/scrollbar.demo.vue",
    "content": "<markdown>\n# Use built-in scrollbar\n\nSometimes you will find native scrollbar doesn't meet the style of naive-ui. You can use built-in scrollbar of naive-ui (on `n-layout-sider`, `n-layout` or `n-content`).\n</markdown>\n\n<template>\n  <n-layout style=\"height: 360px\">\n    <n-layout-header style=\"height: 64px; padding: 24px\" bordered>\n      Yiheyuan Road\n    </n-layout-header>\n    <n-layout position=\"absolute\" style=\"top: 64px; bottom: 64px\" has-sider>\n      <n-layout-sider\n        content-style=\"padding: 24px;\"\n        :native-scrollbar=\"false\"\n        bordered\n      >\n        <n-h2>Handian Bridge</n-h2>\n        <n-h2>Handian Bridge</n-h2>\n        <n-h2>Handian Bridge</n-h2>\n        <n-h2>Handian Bridge</n-h2>\n        <n-h2>Handian Bridge</n-h2>\n        <n-h2>Handian Bridge</n-h2>\n        <n-h2>Handian Bridge</n-h2>\n        <n-h2>Handian Bridge</n-h2>\n        <n-h2>Handian Bridge</n-h2>\n        <n-h2>Handian Bridge</n-h2>\n        <n-h2>Handian Bridge</n-h2>\n        <n-h2>Handian Bridge</n-h2>\n      </n-layout-sider>\n      <n-layout content-style=\"padding: 24px;\" :native-scrollbar=\"false\">\n        <n-h2>Pingshan Road</n-h2>\n        <n-h2>Pingshan Road</n-h2>\n        <n-h2>Pingshan Road</n-h2>\n        <n-h2>Pingshan Road</n-h2>\n        <n-h2>Pingshan Road</n-h2>\n        <n-h2>Pingshan Road</n-h2>\n        <n-h2>Pingshan Road</n-h2>\n        <n-h2>Pingshan Road</n-h2>\n        <n-h2>Pingshan Road</n-h2>\n        <n-h2>Pingshan Road</n-h2>\n        <n-h2>Pingshan Road</n-h2>\n        <n-h2>Pingshan Road</n-h2>\n      </n-layout>\n    </n-layout>\n    <n-layout-footer\n      position=\"absolute\"\n      style=\"height: 64px; padding: 24px\"\n      bordered\n    >\n      城府路\n    </n-layout-footer>\n  </n-layout>\n</template>\n"
  },
  {
    "path": "src/layout/demos/enUS/set-padding.demo.vue",
    "content": "<markdown>\n# About setting padding\n\nIf you still want to do so, please make sure you know about their DOM structure.\n</markdown>\n\n<template>\n  <n-space vertical size=\"large\">\n    <n-layout has-sider style=\"height: 240px\">\n      <n-layout-sider style=\"padding: 24px\">\n        <n-h2>... Not Recommended</n-h2>\n        <n-h2>... Not Recommended</n-h2>\n        <n-h2>... Not Recommended</n-h2>\n        <n-h2>... Not Recommended</n-h2>\n        <n-h2>... Not Recommended</n-h2>\n        <n-h2>... Not Recommended</n-h2>\n        <n-h2>... Not Recommended</n-h2>\n        <n-h2>... Not Recommended</n-h2>\n      </n-layout-sider>\n    </n-layout>\n    <n-layout has-sider style=\"height: 240px\">\n      <n-layout-sider content-style=\"padding: 24px;\">\n        <n-h2>Recommended</n-h2>\n        <n-h2>Recommended</n-h2>\n        <n-h2>Recommended</n-h2>\n        <n-h2>Recommended</n-h2>\n        <n-h2>Recommended</n-h2>\n        <n-h2>Recommended</n-h2>\n        <n-h2>Recommended</n-h2>\n        <n-h2>Recommended</n-h2>\n      </n-layout-sider>\n    </n-layout>\n  </n-space>\n</template>\n\n<style>\n.n-layout-sider {\n  background: rgba(128, 128, 128, 0.3);\n}\n</style>\n"
  },
  {
    "path": "src/layout/demos/enUS/show-sider-content.demo.vue",
    "content": "<markdown>\n# Hide sider content\n\nSometimes you don't want to see content inside sider after it's collapsed. Set `show-collapsed-content` to `false` on sider.\n</markdown>\n\n<template>\n  <n-space vertical size=\"large\">\n    <n-layout has-sider>\n      <n-layout-sider\n        collapse-mode=\"width\"\n        :collapsed-width=\"120\"\n        :width=\"240\"\n        :show-collapsed-content=\"false\"\n        show-trigger=\"arrow-circle\"\n        content-style=\"padding: 24px;\"\n        bordered\n      >\n        Handian Bridge Handian Bridge Handian Bridge Handian Bridge Handian\n        Bridge\n      </n-layout-sider>\n      <n-layout-content content-style=\"padding: 24px;\">\n        Pingshan Road\n      </n-layout-content>\n    </n-layout>\n    <n-layout has-sider>\n      <n-layout-sider\n        collapse-mode=\"transform\"\n        :collapsed-width=\"120\"\n        :width=\"240\"\n        show-trigger=\"arrow-circle\"\n        content-style=\"padding: 24px;\"\n        bordered\n      >\n        <n-h2>Handian Bridge</n-h2>\n      </n-layout-sider>\n      <n-layout-content content-style=\"padding: 24px;\">\n        Pingshan Road\n      </n-layout-content>\n    </n-layout>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/layout/demos/zhCN/absolute.demo.vue",
    "content": "<markdown>\n# 绝对定位模式\n\n所有布局组件可以使用绝对定位。如果你期望内容在固定的区域内滚动，可以使用 `absolute` 模式。\n</markdown>\n\n<template>\n  <div style=\"height: 360px; position: relative\">\n    <n-layout position=\"absolute\">\n      <n-layout-header style=\"height: 64px; padding: 24px\" bordered>\n        颐和园路\n      </n-layout-header>\n      <n-layout has-sider position=\"absolute\" style=\"top: 64px; bottom: 64px\">\n        <n-layout-sider bordered content-style=\"padding: 24px;\">\n          海淀桥\n        </n-layout-sider>\n        <n-layout content-style=\"padding: 24px;\">\n          <n-h2>平山道</n-h2>\n          <n-h2>平山道</n-h2>\n          <n-h2>平山道</n-h2>\n          <n-h2>平山道</n-h2>\n          <n-h2>平山道</n-h2>\n          <n-h2>平山道</n-h2>\n          <n-h2>平山道</n-h2>\n          <n-h2>平山道</n-h2>\n          <n-h2>平山道</n-h2>\n          <n-h2>平山道</n-h2>\n          <n-h2>平山道</n-h2>\n          <n-h2>平山道</n-h2>\n        </n-layout>\n      </n-layout>\n      <n-layout-footer\n        bordered\n        position=\"absolute\"\n        style=\"height: 64px; padding: 24px\"\n      >\n        城府路\n      </n-layout-footer>\n    </n-layout>\n  </div>\n</template>\n"
  },
  {
    "path": "src/layout/demos/zhCN/basic.demo.vue",
    "content": "<markdown>\n# 基础用法\n\n我希望这个 demo 就能满足你的需求，这样你的时间还能干点别的。\n</markdown>\n\n<template>\n  <n-space vertical size=\"large\">\n    <n-layout>\n      <n-layout-header>颐和园路</n-layout-header>\n      <n-layout-content content-style=\"padding: 24px;\">\n        平山道\n      </n-layout-content>\n      <n-layout-footer>成府路</n-layout-footer>\n    </n-layout>\n    <n-layout>\n      <n-layout-header>颐和园路</n-layout-header>\n      <n-layout has-sider>\n        <n-layout-sider content-style=\"padding: 24px;\">\n          海淀桥\n        </n-layout-sider>\n        <n-layout-content content-style=\"padding: 24px;\">\n          平山道\n        </n-layout-content>\n      </n-layout>\n      <n-layout-footer>成府路</n-layout-footer>\n    </n-layout>\n    <n-layout has-sider>\n      <n-layout-sider content-style=\"padding: 24px;\">\n        海淀桥\n      </n-layout-sider>\n      <n-layout>\n        <n-layout-header>颐和园路</n-layout-header>\n        <n-layout-content content-style=\"padding: 24px;\">\n          平山道\n        </n-layout-content>\n        <n-layout-footer>成府路</n-layout-footer>\n      </n-layout>\n    </n-layout>\n  </n-space>\n</template>\n\n<style>\n.n-layout-header,\n.n-layout-footer {\n  background: rgba(128, 128, 128, 0.2);\n  padding: 24px;\n}\n\n.n-layout-sider {\n  background: rgba(128, 128, 128, 0.3);\n}\n\n.n-layout-content {\n  background: rgba(128, 128, 128, 0.4);\n}\n</style>\n"
  },
  {
    "path": "src/layout/demos/zhCN/border.demo.vue",
    "content": "<markdown>\n# 使用边框\n\nsider、footer、header 可以设定 `bordered`。\n</markdown>\n\n<template>\n  <n-layout has-sider>\n    <n-layout-sider bordered content-style=\"padding: 24px;\">\n      海淀桥\n    </n-layout-sider>\n    <n-layout>\n      <n-layout-header bordered>\n        颐和园路\n      </n-layout-header>\n      <n-layout-content content-style=\"padding: 24px;\">\n        平山道\n      </n-layout-content>\n      <n-layout-footer bordered>\n        成府路\n      </n-layout-footer>\n    </n-layout>\n  </n-layout>\n</template>\n\n<style>\n.n-layout-header {\n  padding: 24px;\n}\n\n.n-layout-footer {\n  padding: 24px;\n}\n</style>\n"
  },
  {
    "path": "src/layout/demos/zhCN/collapse-right.demo.vue",
    "content": "<markdown>\n# 折叠侧边栏的位置\n\n有时候你可能想将折叠侧边栏放在右侧。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { Component } from 'vue'\nimport {\n  BookOutline as BookIcon,\n  PersonOutline as PersonIcon,\n  WineOutline as WineIcon\n} from '@vicons/ionicons5'\nimport { NIcon } from 'naive-ui'\nimport { h } from 'vue'\n\nfunction renderIcon(icon: Component) {\n  return () => h(NIcon, null, { default: () => h(icon) })\n}\n\nconst menuOptions = [\n  {\n    label: '且听风吟',\n    key: 'hear-the-wind-sing',\n    icon: renderIcon(BookIcon)\n  },\n  {\n    label: '1973年的弹珠玩具',\n    key: 'pinball-1973',\n    icon: renderIcon(BookIcon),\n    disabled: true,\n    children: [\n      {\n        label: '鼠',\n        key: 'rat'\n      }\n    ]\n  },\n  {\n    label: '寻羊冒险记',\n    key: 'a-wild-sheep-chase',\n    disabled: true,\n    icon: renderIcon(BookIcon)\n  },\n  {\n    label: '舞，舞，舞',\n    key: 'dance-dance-dance',\n    icon: renderIcon(BookIcon),\n    children: [\n      {\n        type: 'group',\n        label: '人物',\n        key: 'people',\n        children: [\n          {\n            label: '叙事者',\n            key: 'narrator',\n            icon: renderIcon(PersonIcon)\n          },\n          {\n            label: '羊男',\n            key: 'sheep-man',\n            icon: renderIcon(PersonIcon)\n          }\n        ]\n      },\n      {\n        label: '饮品',\n        key: 'beverage',\n        icon: renderIcon(WineIcon),\n        children: [\n          {\n            label: '威士忌',\n            key: 'whisky'\n          }\n        ]\n      },\n      {\n        label: '食物',\n        key: 'food',\n        children: [\n          {\n            label: '三明治',\n            key: 'sandwich'\n          }\n        ]\n      },\n      {\n        label: '过去增多，未来减少',\n        key: 'the-past-increases-the-future-recedes'\n      }\n    ]\n  }\n]\n</script>\n\n<template>\n  <n-space vertical size=\"large\">\n    <n-layout has-sider sider-placement=\"right\">\n      <n-layout-content content-style=\"padding: 24px;\">\n        平山道\n      </n-layout-content>\n      <n-layout-sider\n        collapse-mode=\"width\"\n        :collapsed-width=\"120\"\n        :width=\"240\"\n        :native-scrollbar=\"true\"\n        show-trigger=\"arrow-circle\"\n        content-style=\"padding: 24px;\"\n        bordered\n      >\n        <p>海淀桥 海淀桥 海淀桥 海淀桥 海淀桥</p>\n      </n-layout-sider>\n    </n-layout>\n    <n-layout has-sider sider-placement=\"right\">\n      <n-layout-content content-style=\"padding: 24px;\">\n        平山道\n      </n-layout-content>\n      <n-layout-sider\n        collapse-mode=\"transform\"\n        :collapsed-width=\"120\"\n        :width=\"240\"\n        :native-scrollbar=\"false\"\n        show-trigger=\"bar\"\n        content-style=\"padding: 24px;\"\n        bordered\n      >\n        <n-h2>海淀桥</n-h2>\n      </n-layout-sider>\n    </n-layout>\n    <n-layout has-sider sider-placement=\"right\">\n      <n-layout style=\"max-height: 320px\" />\n      <n-layout-sider\n        bordered\n        show-trigger\n        collapse-mode=\"width\"\n        :collapsed-width=\"64\"\n        :width=\"240\"\n        :native-scrollbar=\"false\"\n        style=\"max-height: 320px\"\n      >\n        <n-menu\n          :collapsed-width=\"64\"\n          :collapsed-icon-size=\"22\"\n          :options=\"menuOptions\"\n        />\n      </n-layout-sider>\n    </n-layout>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/layout/demos/zhCN/collapse.demo.vue",
    "content": "<markdown>\n# 折叠侧边栏\n\n使用 `collapsed-width` 和 `width` 设置侧边栏的宽度。\n</markdown>\n\n<template>\n  <n-space vertical size=\"large\">\n    <n-layout has-sider>\n      <n-layout-sider\n        collapse-mode=\"width\"\n        :collapsed-width=\"120\"\n        :width=\"240\"\n        show-trigger=\"arrow-circle\"\n        content-style=\"padding: 24px;\"\n        bordered\n      >\n        <p>海淀桥 海淀桥 海淀桥 海淀桥 海淀桥</p>\n      </n-layout-sider>\n      <n-layout-content content-style=\"padding: 24px;\">\n        平山道\n      </n-layout-content>\n    </n-layout>\n    <n-layout has-sider>\n      <n-layout-sider\n        collapse-mode=\"transform\"\n        :collapsed-width=\"120\"\n        :width=\"240\"\n        show-trigger=\"bar\"\n        content-style=\"padding: 24px;\"\n        bordered\n      >\n        <n-h2>海淀桥</n-h2>\n      </n-layout-sider>\n      <n-layout-content content-style=\"padding: 24px;\">\n        平山道\n      </n-layout-content>\n    </n-layout>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/layout/demos/zhCN/embedded.demo.vue",
    "content": "<markdown>\n# 嵌入效果\n\n有的时候你希望背景色暗一点，来突出上面显示的内容（尤其是卡片）。\n</markdown>\n\n<template>\n  <n-layout embedded content-style=\"padding: 24px;\">\n    <n-card>\n      只要是 看到天边云一朵<br>\n      逐天拢有好心情\n    </n-card>\n  </n-layout>\n</template>\n"
  },
  {
    "path": "src/layout/demos/zhCN/index.demo-entry.md",
    "content": "# 布局 Layout\n\n布局是用来布局的。\n\n这个组件用起来有点麻烦，但是就像手动挡的车，还是值得一试的。\n\n如果你正在使用 v2.3.0 以前的版本，你可能需要了解一下 <n-a href=\"#v2.3.0-的变化\">v2.3.0 的变化</n-a>。\n\n<!--single-column-->\n\n## 演示\n\n```demo\nbasic.vue\nset-padding.vue\nembedded.vue\nborder.vue\nabsolute.vue\nscrollbar.vue\ncollapse.vue\ncollapse-right.vue\ninverted.vue\nshow-sider-content.vue\nscroll-to.vue\nkeep-alive-debug.vue\n```\n\n## API\n\n### Layout, Layout Content Props\n\n| 名称 | 类型 | 默认值 | 说明 | 版本 |\n| --- | --- | --- | --- | --- |\n| content-class | `string` | `undefined` | 可滚动内容节点的类名 | 2.36.0 |\n| content-style | `string \\| Object` | `undefined` | 可滚动内容节点的样式 |  |\n| embedded | `boolean` | `false` | 使用更深的背景色展现嵌入效果，只对亮色主题生效 |  |\n| has-sider | `boolean` | `false` | 组件内部是否有边栏，如果有的话必须设为 `true` |  |\n| native-scrollbar | `boolean` | `true` | 是否在自身使用原生滚动条。如果设定为 `false`，`Layout` 将会对内容使用 `naive-ui` 风格的滚动条 |  |\n| position | `'static' \\| 'absolute'` | `'static'` | `static` 模式将会把 CSS `position` 设为 `static`，`absolute` 模式将会把 CSS `position` 设为 `absolute`，还将 `left`、`right`、`top`、`bottom` 设为 `0`。`absolute` 模式在你想将内容在一个固定容器或者将这个页面的布局设为固定位置的时候很有用。你可能需要修改一些 style 来确保它按照你预想的方式展示 |  |\n| scrollbar-props | `ScrollbarProps` | `undefined` | 属性参考 [Scrollbar props](scrollbar#Scrollbar-Props) |  |\n| sider-placement | `'left' \\| 'right'` | `left` | 组件折叠侧边栏在哪一侧 |  |\n| on-scroll | `(e: Event) => void` | `undefined` | 内容的滚动事件回调函数 |  |\n\n### Layout Footer Props\n\n| 名称 | 类型 | 默认值 | 说明 |\n| --- | --- | --- | --- |\n| bordered | `boolean` | `false` | 是否显示边框 |\n| inverted | `boolean` | `false` | 使用反转背景色 |\n| position | `'static' \\| 'absolute'` | `'static'` | `static` 模式将会把 CSS `position` 设为 `static`，`absolute` 模式将会把 CSS `position` 设为 `absolute`，还将 `left`、`right`、`bottom` 设为 `0`。`absolute` 模式在你想将内容在一个固定容器或者将这个页面的布局设为固定位置的时候很有用。你可能需要修改一些 style 来确保它按照你预想的方式展示 |\n\n### Layout Header Props\n\n| 名称 | 类型 | 默认值 | 说明 |\n| --- | --- | --- | --- |\n| bordered | `boolean` | `false` | 是否显示边框 |\n| inverted | `boolean` | `false` | 使用反转背景色 |\n| position | `'static' \\| 'absolute'` | `'static'` | `static` 模式将会把 CSS `position` 设为 `static`， `absolute` 模式将会把 CSS `position` 设为 `absolute`，还将 `left`、`right`、`top` 设为 `0`。`absolute` 模式在你想将内容在一个固定容器或者将这个页面的布局设为固定位置的时候很有用。你可能需要修改一些 style 来确保它按照你预想的方式展示 |\n\n### Layout Sider Props\n\n| 名称 | 类型 | 默认值 | 说明 | 版本 |\n| --- | --- | --- | --- | --- |\n| bordered | `boolean` | `false` | 是否显示边框 |  |\n| collapse-mode | `'transform' \\| 'width'` | `'transform'` | 如果设定为 `'width'`，Sider 的内容宽度将会被实际改变；如果设定为 `'transform'`，边栏将只会移动它的位置而不会改变宽度 |  |\n| collapsed | `boolean` | `undefined` | 边栏是否折叠。只在 `position` 为 `'static'` 时生效 |  |\n| collapsed-trigger-class | `string` | `undefined` | 折叠时触发器类名 | 2.36.0 |\n| collapsed-trigger-style | `string \\| Object` | `undefined` | 折叠时触发器样式 |  |\n| collapsed-width | `number` | `48` | 折叠宽度 |  |\n| content-class | `string` | `undefined` | 可滚动内容节点的类名 |  |\n| content-style | `string \\| Object` | `undefined` | 可滚动内容节点的样式 |  |\n| default-collapsed | `boolean` | `false` | 非受控模式下的默认折叠状态 |  |\n| inverted | `boolean` | `false` | 使用反转背景色 |  |\n| native-scrollbar | `boolean` | `true` | 是否在自身使用原生滚动条。如果设定为 `false`，`Sider` 将会对内容使用 naive-ui 风格的滚动条 |  |\n| position | `'static' \\| 'absolute'` | `'static'` | `static` 模式将会把 CSS `position` 设为 `static`， `absolute` 模式将会把 CSS `position` 设为 `absolute`，还将 `left`、`top`、`bottom` 设为 `0`。`absolute` 模式在你想将内容在一个固定容器或者将这个页面的布局设为固定位置的时候很有用。你可能需要修改一些 style 来确保它按照你预想的方式展示 |  |\n| scrollbar-props | `ScrollbarProps` | `undefined` | 属性参考 [Scrollbar props](scrollbar#Scrollbar-Props) |  |\n| show-collapsed-content | `boolean` | `true` | 是否在 `sider` 折叠后展示内部内容 |  |\n| show-trigger | `boolean \\| 'bar' \\| 'arrow-circle'` | `false` | 内置的触发按钮是否展示 |  |\n| trigger-class | `string` | `undefined` | 触发器类名 | 2.36.0 |\n| trigger-style | `string \\| Object` | `undefined` | 触发器样式 |  |\n| width | `number \\| string` | `272` | 宽度的 CSS 值，为数字时会添加 px |  |\n| on-after-enter | `() => void` | `undefined` | 完成展开后的回调 |  |\n| on-after-leave | `() => void` | `undefined` | 完成折叠后的回调 |  |\n| on-scroll | `(e: Event) => void` | `undefined` | 内容的滚动事件回调函数 |  |\n| on-update:collapsed | `(collapsed: boolean) => void` | `undefined` | 折叠状态发生改变时的回调函数 |  |\n\n### Layout, Layout Content, Layout Sider, Layout Header, Layout Footer Slots\n\n| 名称    | 参数 | 说明       |\n| ------- | ---- | ---------- |\n| default | `()` | 布局的内容 |\n\n### Layout, Layout Content, Layout Sider Methods\n\n| 名称 | 类型 | 说明 |\n| --- | --- | --- |\n| scrollTo | `((xCoord: number, yCoord: number) => void) \\| (options: { left?: number, top?: number, behavior: 'smooth' \\| 'auto' }) => void` | 滚动到某处 |\n\n## v2.3.0 的变化\n\n出于性能和未来 SSR 相关的考虑，在 v2.3.0 后，对于包含 `n-layout-sider` 的 `n-layout` 组件，需要显示的设定 `has-sider`. 同时折叠对于 `position=\"absolute\"` 的 `n-layout-sider` 不再生效。\n\n```html\nv2.3.0 前:\n<n-layout>\n  <n-layout-sider />\n  <n-layout />\n</n-layout>\n\nv2.3.0 后:\n<n-layout has-sider>\n  <n-layout-sider />\n  <n-layout />\n</n-layout>\n```\n"
  },
  {
    "path": "src/layout/demos/zhCN/inverted.demo.vue",
    "content": "<markdown>\n# 反转\n\n使用 `inverted` 增加对比度，可以使用在 header、footer 和 sider 上，可以和 menu 搭配使用。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { Component } from 'vue'\nimport {\n  BookOutline as BookIcon,\n  PersonOutline as PersonIcon,\n  WineOutline as WineIcon\n} from '@vicons/ionicons5'\nimport { NIcon } from 'naive-ui'\nimport { h, ref } from 'vue'\n\nfunction renderIcon(icon: Component) {\n  return () => h(NIcon, null, { default: () => h(icon) })\n}\n\nconst menuOptions = [\n  {\n    label: '且听风吟',\n    key: 'hear-the-wind-sing',\n    icon: renderIcon(BookIcon)\n  },\n  {\n    label: '1973年的弹珠玩具',\n    key: 'pinball-1973',\n    icon: renderIcon(BookIcon),\n    disabled: true,\n    children: [\n      {\n        label: '鼠',\n        key: 'rat'\n      }\n    ]\n  },\n  {\n    label: '寻羊冒险记',\n    key: 'a-wild-sheep-chase',\n    disabled: true,\n    icon: renderIcon(BookIcon)\n  },\n  {\n    label: '舞，舞，舞',\n    key: 'dance-dance-dance',\n    icon: renderIcon(BookIcon),\n    children: [\n      {\n        type: 'group',\n        label: '人物',\n        key: 'people',\n        children: [\n          {\n            label: '叙事者',\n            key: 'narrator',\n            icon: renderIcon(PersonIcon)\n          },\n          {\n            label: '羊男',\n            key: 'sheep-man',\n            icon: renderIcon(PersonIcon)\n          }\n        ]\n      },\n      {\n        label: '饮品',\n        key: 'beverage',\n        icon: renderIcon(WineIcon),\n        children: [\n          {\n            label: '威士忌',\n            key: 'whisky'\n          }\n        ]\n      },\n      {\n        label: '食物',\n        key: 'food',\n        children: [\n          {\n            label: '三明治',\n            key: 'sandwich'\n          }\n        ]\n      },\n      {\n        label: '过去增多，未来减少',\n        key: 'the-past-increases-the-future-recedes'\n      }\n    ]\n  }\n]\n\nconst inverted = ref(false)\n</script>\n\n<template>\n  <n-space vertical>\n    <n-space> <n-switch v-model:value=\"inverted\" /> inverted </n-space>\n    <n-layout>\n      <n-layout-header :inverted=\"inverted\" bordered>\n        Header Header Header\n        <n-menu mode=\"horizontal\" :inverted=\"inverted\" :options=\"menuOptions\" />\n      </n-layout-header>\n      <n-layout has-sider>\n        <n-layout-sider\n          bordered\n          show-trigger\n          collapse-mode=\"width\"\n          :collapsed-width=\"64\"\n          :width=\"240\"\n          :native-scrollbar=\"false\"\n          :inverted=\"inverted\"\n          style=\"max-height: 320px\"\n        >\n          <n-menu\n            :inverted=\"inverted\"\n            :collapsed-width=\"64\"\n            :collapsed-icon-size=\"22\"\n            :options=\"menuOptions\"\n          />\n        </n-layout-sider>\n        <n-layout style=\"max-height: 320px\" />\n      </n-layout>\n      <n-layout-footer :inverted=\"inverted\" bordered>\n        Footer Footer Footer\n      </n-layout-footer>\n    </n-layout>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/layout/demos/zhCN/keep-alive-debug.demo.vue",
    "content": "<markdown>\n# Keep alive debug\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst showLayout = ref(true)\n</script>\n\n<template>\n  <n-button @click=\"showLayout = !showLayout\">\n    xxx\n  </n-button>\n  <keep-alive>\n    <n-layout v-if=\"showLayout\" style=\"height: 100px\">\n      <h1>123</h1>\n      <h1>123</h1>\n      <h1>123</h1>\n      <h1>123</h1>\n      <h1>123</h1>\n      <h1>123</h1>\n      <h1>123</h1>\n      <h1>123</h1>\n      <h1>123</h1>\n      <h1>123</h1>\n      <h1>123</h1>\n      <h1>123</h1>\n    </n-layout>\n    <n-empty v-else />\n  </keep-alive>\n  <keep-alive>\n    <n-layout v-if=\"showLayout\" style=\"height: 100px\" :native-scrollbar=\"false\">\n      <h1>123</h1>\n      <h1>123</h1>\n      <h1>123</h1>\n      <h1>123</h1>\n      <h1>123</h1>\n      <h1>123</h1>\n      <h1>123</h1>\n      <h1>123</h1>\n      <h1>123</h1>\n      <h1>123</h1>\n      <h1>123</h1>\n      <h1>123</h1>\n    </n-layout>\n    <n-empty v-else />\n  </keep-alive>\n</template>\n"
  },
  {
    "path": "src/layout/demos/zhCN/scroll-to.demo.vue",
    "content": "<markdown>\n# 滚动到\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { LayoutInst, LayoutSiderInst } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst siderRef = ref<LayoutSiderInst | null>(null)\nconst contentRef = ref<LayoutInst | null>(null)\n</script>\n\n<template>\n  <n-space vertical size=\"large\">\n    <n-space>\n      <n-button @click=\"siderRef?.scrollTo({ top: 120, behavior: 'smooth' })\">\n        边栏滚到 120px\n      </n-button>\n      <n-button @click=\"contentRef?.scrollTo({ top: 120, behavior: 'smooth' })\">\n        内容滚到 120px\n      </n-button>\n    </n-space>\n    <n-layout style=\"height: 360px\">\n      <n-layout-header style=\"height: 64px; padding: 24px\" bordered>\n        颐和园路\n      </n-layout-header>\n      <n-layout has-sider position=\"absolute\" style=\"top: 64px; bottom: 64px\">\n        <n-layout-sider ref=\"siderRef\" bordered content-style=\"padding: 24px;\">\n          <n-h2>海淀桥</n-h2>\n          <n-h2>海淀桥</n-h2>\n          <n-h2>海淀桥</n-h2>\n          <n-h2>海淀桥</n-h2>\n          <n-h2>海淀桥</n-h2>\n          <n-h2>海淀桥</n-h2>\n          <n-h2>海淀桥</n-h2>\n          <n-h2>海淀桥</n-h2>\n          <n-h2>海淀桥</n-h2>\n          <n-h2>海淀桥</n-h2>\n          <n-h2>海淀桥</n-h2>\n          <n-h2>海淀桥</n-h2>\n        </n-layout-sider>\n        <n-layout-content\n          ref=\"contentRef\"\n          content-style=\"padding: 24px;\"\n          :native-scrollbar=\"false\"\n        >\n          <n-h2>平山道</n-h2>\n          <n-h2>平山道</n-h2>\n          <n-h2>平山道</n-h2>\n          <n-h2>平山道</n-h2>\n          <n-h2>平山道</n-h2>\n          <n-h2>平山道</n-h2>\n          <n-h2>平山道</n-h2>\n          <n-h2>平山道</n-h2>\n          <n-h2>平山道</n-h2>\n          <n-h2>平山道</n-h2>\n          <n-h2>平山道</n-h2>\n          <n-h2>平山道</n-h2>\n        </n-layout-content>\n      </n-layout>\n      <n-layout-footer\n        bordered\n        position=\"absolute\"\n        style=\"height: 64px; padding: 24px\"\n      >\n        成府路\n      </n-layout-footer>\n    </n-layout>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/layout/demos/zhCN/scrollbar.demo.vue",
    "content": "<markdown>\n# 使用内置滚动条\n\n有时原生滚动条与 naive-ui 的样式不协调。可以（在 `n-layout-sider`、`n-layout` 或 `n-layout-content`）使用 naive-ui 内置的滚动条。\n</markdown>\n\n<template>\n  <n-layout style=\"height: 360px\">\n    <n-layout-header style=\"height: 64px; padding: 24px\" bordered>\n      颐和园路\n    </n-layout-header>\n    <n-layout position=\"absolute\" style=\"top: 64px; bottom: 64px\" has-sider>\n      <n-layout-sider\n        content-style=\"padding: 24px;\"\n        :native-scrollbar=\"false\"\n        bordered\n      >\n        <n-h2>海淀桥</n-h2>\n        <n-h2>海淀桥</n-h2>\n        <n-h2>海淀桥</n-h2>\n        <n-h2>海淀桥</n-h2>\n        <n-h2>海淀桥</n-h2>\n        <n-h2>海淀桥</n-h2>\n        <n-h2>海淀桥</n-h2>\n        <n-h2>海淀桥</n-h2>\n        <n-h2>海淀桥</n-h2>\n        <n-h2>海淀桥</n-h2>\n        <n-h2>海淀桥</n-h2>\n        <n-h2>海淀桥</n-h2>\n      </n-layout-sider>\n      <n-layout content-style=\"padding: 24px;\" :native-scrollbar=\"false\">\n        <n-h2>平山道</n-h2>\n        <n-h2>平山道</n-h2>\n        <n-h2>平山道</n-h2>\n        <n-h2>平山道</n-h2>\n        <n-h2>平山道</n-h2>\n        <n-h2>平山道</n-h2>\n        <n-h2>平山道</n-h2>\n        <n-h2>平山道</n-h2>\n        <n-h2>平山道</n-h2>\n        <n-h2>平山道</n-h2>\n        <n-h2>平山道</n-h2>\n        <n-h2>平山道</n-h2>\n      </n-layout>\n    </n-layout>\n    <n-layout-footer\n      position=\"absolute\"\n      style=\"height: 64px; padding: 24px\"\n      bordered\n    >\n      城府路\n    </n-layout-footer>\n  </n-layout>\n</template>\n"
  },
  {
    "path": "src/layout/demos/zhCN/set-padding.demo.vue",
    "content": "<markdown>\n# 关于设定 Padding\n\nnaive-ui 不推荐直接在 `n-layout-sider` 和 `n-layout` 上设定 padding。因为他们存在嵌套的 DOM 结构，你可以使用 `content-style` 来设定可滚动内容的样式。\n</markdown>\n\n<template>\n  <n-space vertical size=\"large\">\n    <n-layout has-sider style=\"height: 240px\">\n      <n-layout-sider style=\"padding: 24px\">\n        <n-h2>... 不推荐</n-h2>\n        <n-h2>... 不推荐</n-h2>\n        <n-h2>... 不推荐</n-h2>\n        <n-h2>... 不推荐</n-h2>\n        <n-h2>... 不推荐</n-h2>\n        <n-h2>... 不推荐</n-h2>\n        <n-h2>... 不推荐</n-h2>\n        <n-h2>... 不推荐</n-h2>\n      </n-layout-sider>\n    </n-layout>\n    <n-layout has-sider style=\"height: 240px\">\n      <n-layout-sider content-style=\"padding: 24px;\">\n        <n-h2>推荐</n-h2>\n        <n-h2>推荐</n-h2>\n        <n-h2>推荐</n-h2>\n        <n-h2>推荐</n-h2>\n        <n-h2>推荐</n-h2>\n        <n-h2>推荐</n-h2>\n        <n-h2>推荐</n-h2>\n        <n-h2>推荐</n-h2>\n      </n-layout-sider>\n    </n-layout>\n  </n-space>\n</template>\n\n<style>\n.n-layout-sider {\n  background: rgba(128, 128, 128, 0.3);\n}\n</style>\n"
  },
  {
    "path": "src/layout/demos/zhCN/show-sider-content.demo.vue",
    "content": "<markdown>\n# 隐藏侧边栏内容\n\n有时候收起边栏后，你不想看到里面有什么，你可以设定 `show-collapsed-content` 为 `false`。\n</markdown>\n\n<template>\n  <n-space vertical size=\"large\">\n    <n-layout has-sider>\n      <n-layout-sider\n        collapse-mode=\"width\"\n        :collapsed-width=\"120\"\n        :width=\"240\"\n        :show-collapsed-content=\"false\"\n        show-trigger=\"arrow-circle\"\n        content-style=\"padding: 24px;\"\n        bordered\n      >\n        海淀桥 海淀桥 海淀桥 海淀桥 海淀桥\n      </n-layout-sider>\n      <n-layout-content content-style=\"padding: 24px;\">\n        平山道\n      </n-layout-content>\n    </n-layout>\n    <n-layout has-sider>\n      <n-layout-sider\n        collapse-mode=\"transform\"\n        :collapsed-width=\"120\"\n        :width=\"240\"\n        show-trigger=\"arrow-circle\"\n        content-style=\"padding: 24px;\"\n        bordered\n      >\n        <n-h2>海淀桥</n-h2>\n      </n-layout-sider>\n      <n-layout-content content-style=\"padding: 24px;\">\n        平山道\n      </n-layout-content>\n    </n-layout>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/layout/index.ts",
    "content": "export type {\n  LayoutInst as LayoutContentInst,\n  LayoutInst,\n  LayoutSiderInst\n} from './src/interface'\nexport {\n  layoutProps as layoutContentProps,\n  layoutProps,\n  default as NLayout\n} from './src/Layout'\nexport type {\n  LayoutProps as LayoutContentProps,\n  LayoutProps\n} from './src/Layout'\nexport { default as NLayoutContent } from './src/LayoutContent'\nexport { layoutFooterProps, default as NLayoutFooter } from './src/LayoutFooter'\nexport type { LayoutFooterProps } from './src/LayoutFooter'\nexport {\n  headerProps as layoutHeaderProps,\n  default as NLayoutHeader\n} from './src/LayoutHeader'\nexport type { LayoutHeaderProps } from './src/LayoutHeader'\nexport { layoutSiderProps, default as NLayoutSider } from './src/LayoutSider'\nexport type { LayoutSiderProps } from './src/LayoutSider'\n"
  },
  {
    "path": "src/layout/src/Layout.tsx",
    "content": "import type { CSSProperties, ExtractPropTypes, PropType } from 'vue'\nimport type { ScrollbarInst, ScrollbarProps } from '../../_internal'\nimport type { ThemeProps } from '../../_mixins'\nimport type { ExtractPublicPropTypes } from '../../_utils'\nimport type { LayoutTheme } from '../styles'\nimport type { LayoutInst } from './interface'\nimport { computed, defineComponent, h, provide, ref } from 'vue'\nimport { NScrollbar } from '../../_internal'\nimport { useConfig, useTheme, useThemeClass } from '../../_mixins'\nimport { createInjectionKey, useReactivated } from '../../_utils'\nimport { layoutLight } from '../styles'\nimport { positionProp } from './interface'\nimport style from './styles/layout.cssr'\n\nexport const layoutProps = {\n  embedded: Boolean,\n  position: positionProp,\n  nativeScrollbar: {\n    type: Boolean,\n    default: true\n  },\n  scrollbarProps: Object as PropType<Partial<ScrollbarProps>>,\n  onScroll: Function as PropType<(e: Event) => void>,\n  contentClass: String,\n  contentStyle: {\n    type: [String, Object] as PropType<string | CSSProperties>,\n    default: ''\n  },\n  hasSider: Boolean,\n  siderPlacement: {\n    type: String as PropType<'left' | 'right'>,\n    default: 'left'\n  }\n} as const\n\nexport type LayoutProps = ExtractPublicPropTypes<typeof layoutProps>\n\nexport const layoutInjectionKey\n  = createInjectionKey<ExtractPropTypes<typeof layoutProps>>('n-layout')\n\nexport function createLayoutComponent(isContent: boolean) {\n  return defineComponent({\n    name: isContent ? 'LayoutContent' : 'Layout',\n    props: {\n      ...(useTheme.props as ThemeProps<LayoutTheme>),\n      ...layoutProps\n    },\n    setup(props) {\n      const scrollableElRef = ref<HTMLElement | null>(null)\n      const scrollbarInstRef = ref<ScrollbarInst | null>(null)\n      const { mergedClsPrefixRef, inlineThemeDisabled } = useConfig(props)\n      const themeRef = useTheme(\n        'Layout',\n        '-layout',\n        style,\n        layoutLight,\n        props,\n        mergedClsPrefixRef\n      )\n      function scrollTo(options: ScrollToOptions): void\n      function scrollTo(x: number, y: number): void\n      function scrollTo(options: ScrollToOptions | number, y?: number): void {\n        if (props.nativeScrollbar) {\n          const { value: scrollableEl } = scrollableElRef\n          if (scrollableEl) {\n            if (y === undefined) {\n              scrollableEl.scrollTo(options as any)\n            }\n            else {\n              scrollableEl.scrollTo(options as any, y as any)\n            }\n          }\n        }\n        else {\n          const { value: scrollbarInst } = scrollbarInstRef\n          if (scrollbarInst) {\n            scrollbarInst.scrollTo(options as any, y as any)\n          }\n        }\n      }\n      provide(layoutInjectionKey, props)\n      let scrollX = 0\n      let scrollY = 0\n      const handleNativeElScroll = (e: Event): void => {\n        const target = e.target as HTMLElement\n        scrollX = target.scrollLeft\n        scrollY = target.scrollTop\n        props.onScroll?.(e)\n      }\n      useReactivated(() => {\n        if (props.nativeScrollbar) {\n          const el = scrollableElRef.value\n          if (el) {\n            el.scrollTop = scrollY\n            el.scrollLeft = scrollX\n          }\n        }\n      })\n      const hasSiderStyle: CSSProperties = {\n        display: 'flex',\n        flexWrap: 'nowrap',\n        width: '100%',\n        flexDirection: 'row'\n      }\n      const exposedMethods: LayoutInst = {\n        scrollTo\n      }\n      const cssVarsRef = computed(() => {\n        const {\n          common: { cubicBezierEaseInOut },\n          self\n        } = themeRef.value\n        return {\n          '--n-bezier': cubicBezierEaseInOut,\n          '--n-color': props.embedded ? self.colorEmbedded : self.color,\n          '--n-text-color': self.textColor\n        }\n      })\n      const themeClassHandle = inlineThemeDisabled\n        ? useThemeClass(\n            'layout',\n            computed(() => {\n              return props.embedded ? 'e' : ''\n            }),\n            cssVarsRef,\n            props\n          )\n        : undefined\n      return {\n        mergedClsPrefix: mergedClsPrefixRef,\n        scrollableElRef,\n        scrollbarInstRef,\n        hasSiderStyle,\n        mergedTheme: themeRef,\n        handleNativeElScroll,\n        cssVars: inlineThemeDisabled ? undefined : cssVarsRef,\n        themeClass: themeClassHandle?.themeClass,\n        onRender: themeClassHandle?.onRender,\n        ...exposedMethods\n      }\n    },\n    render() {\n      const { mergedClsPrefix, hasSider } = this\n      this.onRender?.()\n      const hasSiderStyle = hasSider ? this.hasSiderStyle : undefined\n      const layoutClass = [\n        this.themeClass,\n        isContent && `${mergedClsPrefix}-layout-content`,\n        `${mergedClsPrefix}-layout`,\n        `${mergedClsPrefix}-layout--${this.position}-positioned`\n      ]\n      return (\n        <div class={layoutClass} style={this.cssVars as CSSProperties}>\n          {this.nativeScrollbar ? (\n            <div\n              ref=\"scrollableElRef\"\n              class={[\n                `${mergedClsPrefix}-layout-scroll-container`,\n                this.contentClass\n              ]}\n              style={[this.contentStyle, hasSiderStyle] as any}\n              onScroll={this.handleNativeElScroll}\n            >\n              {this.$slots}\n            </div>\n          ) : (\n            <NScrollbar\n              {...this.scrollbarProps}\n              onScroll={this.onScroll}\n              ref=\"scrollbarInstRef\"\n              theme={this.mergedTheme.peers.Scrollbar}\n              themeOverrides={this.mergedTheme.peerOverrides.Scrollbar}\n              contentClass={this.contentClass}\n              contentStyle={[this.contentStyle, hasSiderStyle] as any}\n            >\n              {this.$slots}\n            </NScrollbar>\n          )}\n        </div>\n      )\n    }\n  })\n}\n\nexport default createLayoutComponent(false)\n"
  },
  {
    "path": "src/layout/src/LayoutContent.tsx",
    "content": "import { createLayoutComponent } from './Layout'\n\nexport default createLayoutComponent(true)\n"
  },
  {
    "path": "src/layout/src/LayoutFooter.tsx",
    "content": "import type { ThemeProps } from '../../_mixins'\nimport type { ExtractPublicPropTypes } from '../../_utils'\nimport type { LayoutTheme } from '../styles'\nimport { computed, defineComponent, h } from 'vue'\nimport { useConfig, useTheme, useThemeClass } from '../../_mixins'\nimport { layoutLight } from '../styles'\nimport { positionProp } from './interface'\nimport style from './styles/layout-footer.cssr'\n\nexport const layoutFooterProps = {\n  ...(useTheme.props as ThemeProps<LayoutTheme>),\n  inverted: Boolean,\n  position: positionProp,\n  bordered: Boolean\n}\n\nexport type LayoutFooterProps = ExtractPublicPropTypes<typeof layoutFooterProps>\n\nexport default defineComponent({\n  name: 'LayoutFooter',\n  props: layoutFooterProps,\n  setup(props) {\n    const { mergedClsPrefixRef, inlineThemeDisabled } = useConfig(props)\n    const themeRef = useTheme(\n      'Layout',\n      '-layout-footer',\n      style,\n      layoutLight,\n      props,\n      mergedClsPrefixRef\n    )\n    const cssVarsRef = computed(() => {\n      const {\n        common: { cubicBezierEaseInOut },\n        self\n      } = themeRef.value\n      const vars: any = {\n        '--n-bezier': cubicBezierEaseInOut\n      }\n      if (props.inverted) {\n        vars['--n-color'] = self.footerColorInverted\n        vars['--n-text-color'] = self.textColorInverted\n        vars['--n-border-color'] = self.footerBorderColorInverted\n      }\n      else {\n        vars['--n-color'] = self.footerColor\n        vars['--n-text-color'] = self.textColor\n        vars['--n-border-color'] = self.footerBorderColor\n      }\n      return vars\n    })\n    const themeClassHandle = inlineThemeDisabled\n      ? useThemeClass(\n          'layout-footer',\n          computed(() => (props.inverted ? 'a' : 'b')),\n          cssVarsRef,\n          props\n        )\n      : undefined\n    return {\n      mergedClsPrefix: mergedClsPrefixRef,\n      cssVars: inlineThemeDisabled ? undefined : cssVarsRef,\n      themeClass: themeClassHandle?.themeClass,\n      onRender: themeClassHandle?.onRender\n    }\n  },\n  render() {\n    const { mergedClsPrefix } = this\n    this.onRender?.()\n    return (\n      <div\n        class={[\n          `${mergedClsPrefix}-layout-footer`,\n          this.themeClass,\n          this.position\n          && `${mergedClsPrefix}-layout-footer--${this.position}-positioned`,\n          this.bordered && `${mergedClsPrefix}-layout-footer--bordered`\n        ]}\n        style={this.cssVars}\n      >\n        {this.$slots}\n      </div>\n    )\n  }\n})\n"
  },
  {
    "path": "src/layout/src/LayoutHeader.tsx",
    "content": "import type { ThemeProps } from '../../_mixins'\nimport type { ExtractPublicPropTypes } from '../../_utils'\nimport type { LayoutTheme } from '../styles'\nimport { computed, defineComponent, h } from 'vue'\nimport { useConfig, useTheme, useThemeClass } from '../../_mixins'\nimport { layoutLight } from '../styles'\nimport { positionProp } from './interface'\nimport style from './styles/layout-header.cssr'\n\nexport const headerProps = {\n  position: positionProp,\n  inverted: Boolean,\n  bordered: {\n    type: Boolean,\n    default: false\n  }\n} as const\n\nexport type LayoutHeaderProps = ExtractPublicPropTypes<typeof headerProps>\n\nexport default defineComponent({\n  name: 'LayoutHeader',\n  props: {\n    ...(useTheme.props as ThemeProps<LayoutTheme>),\n    ...headerProps\n  },\n  setup(props) {\n    const { mergedClsPrefixRef, inlineThemeDisabled } = useConfig(props)\n    const themeRef = useTheme(\n      'Layout',\n      '-layout-header',\n      style,\n      layoutLight,\n      props,\n      mergedClsPrefixRef\n    )\n    const cssVarsRef = computed(() => {\n      const {\n        common: { cubicBezierEaseInOut },\n        self\n      } = themeRef.value\n      const vars: any = {\n        '--n-bezier': cubicBezierEaseInOut\n      }\n      if (props.inverted) {\n        vars['--n-color'] = self.headerColorInverted\n        vars['--n-text-color'] = self.textColorInverted\n        vars['--n-border-color'] = self.headerBorderColorInverted\n      }\n      else {\n        vars['--n-color'] = self.headerColor\n        vars['--n-text-color'] = self.textColor\n        vars['--n-border-color'] = self.headerBorderColor\n      }\n      return vars\n    })\n    const themeClassHandle = inlineThemeDisabled\n      ? useThemeClass(\n          'layout-header',\n          computed(() => (props.inverted ? 'a' : 'b')),\n          cssVarsRef,\n          props\n        )\n      : undefined\n    return {\n      mergedClsPrefix: mergedClsPrefixRef,\n      cssVars: inlineThemeDisabled ? undefined : cssVarsRef,\n      themeClass: themeClassHandle?.themeClass,\n      onRender: themeClassHandle?.onRender\n    }\n  },\n  render() {\n    const { mergedClsPrefix } = this\n    this.onRender?.()\n    return (\n      <div\n        class={[\n          `${mergedClsPrefix}-layout-header`,\n          this.themeClass,\n          this.position\n          && `${mergedClsPrefix}-layout-header--${this.position}-positioned`,\n          this.bordered && `${mergedClsPrefix}-layout-header--bordered`\n        ]}\n        style={this.cssVars}\n      >\n        {this.$slots}\n      </div>\n    )\n  }\n})\n"
  },
  {
    "path": "src/layout/src/LayoutSider.tsx",
    "content": "import type { CSSProperties, PropType } from 'vue'\nimport type { ScrollbarInst, ScrollbarProps } from '../../_internal'\nimport type { ThemeProps } from '../../_mixins'\nimport type { ExtractPublicPropTypes, MaybeArray } from '../../_utils'\nimport type { LayoutTheme } from '../styles'\nimport type { LayoutSiderInst } from './interface'\nimport { useMergedState } from 'vooks'\nimport { computed, defineComponent, h, inject, provide, ref, toRef } from 'vue'\nimport { NScrollbar } from '../../_internal'\nimport { useConfig, useTheme, useThemeClass } from '../../_mixins'\nimport { call, formatLength, useReactivated, warn } from '../../_utils'\nimport { layoutLight } from '../styles'\nimport { layoutSiderInjectionKey, positionProp } from './interface'\nimport { layoutInjectionKey } from './Layout'\nimport style from './styles/layout-sider.cssr'\nimport ToggleBar from './ToggleBar'\nimport ToggleButton from './ToggleButton'\n\nexport const layoutSiderProps = {\n  position: positionProp,\n  bordered: Boolean,\n  collapsedWidth: {\n    type: Number,\n    default: 48\n  },\n  width: {\n    type: [Number, String] as PropType<string | number>,\n    default: 272\n  },\n  contentClass: String,\n  contentStyle: {\n    type: [String, Object] as PropType<string | CSSProperties>,\n    default: ''\n  },\n  collapseMode: {\n    type: String as PropType<'width' | 'transform'>,\n    default: 'transform'\n  },\n  collapsed: {\n    type: Boolean as PropType<boolean | undefined>,\n    default: undefined\n  },\n  defaultCollapsed: Boolean,\n  showCollapsedContent: {\n    type: Boolean,\n    default: true\n  },\n  showTrigger: {\n    type: [Boolean, String] as PropType<boolean | 'arrow-circle' | 'bar'>,\n    default: false\n  },\n  nativeScrollbar: {\n    type: Boolean,\n    default: true\n  },\n  inverted: Boolean,\n  scrollbarProps: Object as PropType<\n    Partial<ScrollbarProps> & { style: CSSProperties }\n  >,\n  triggerClass: String,\n  triggerStyle: [String, Object] as PropType<string | CSSProperties>,\n  collapsedTriggerClass: String,\n  collapsedTriggerStyle: [String, Object] as PropType<string | CSSProperties>,\n  'onUpdate:collapsed': [Function, Array] as PropType<\n    MaybeArray<(value: boolean) => void>\n  >,\n  onUpdateCollapsed: [Function, Array] as PropType<\n    MaybeArray<(value: boolean) => void>\n  >,\n  onAfterEnter: Function as PropType<() => void>,\n  onAfterLeave: Function as PropType<() => void>,\n  // deprecated\n  onExpand: [Function, Array] as PropType<MaybeArray<() => void>>,\n  onCollapse: [Function, Array] as PropType<MaybeArray<() => void>>,\n  onScroll: Function as PropType<(e: Event) => void>\n} as const\n\nexport type LayoutSiderProps = ExtractPublicPropTypes<typeof layoutSiderProps>\n\nexport default defineComponent({\n  name: 'LayoutSider',\n  props: {\n    ...(useTheme.props as ThemeProps<LayoutTheme>),\n    ...layoutSiderProps\n  },\n  setup(props) {\n    const layoutProps = inject(layoutInjectionKey)\n    if (__DEV__) {\n      if (!layoutProps) {\n        warn(\n          'layout-sider',\n          'Layout sider is not allowed to be put outside layout.'\n        )\n      }\n      else {\n        if (!layoutProps.hasSider) {\n          warn(\n            'layout-sider',\n            'You are putting `n-layout-sider` in a `n-layout` but haven\\'t set `has-sider` on the `n-layout`.'\n          )\n        }\n      }\n    }\n    const scrollableElRef = ref<HTMLElement | null>(null)\n    const scrollbarInstRef = ref<ScrollbarInst | null>(null)\n    const uncontrolledCollapsedRef = ref(props.defaultCollapsed)\n    const mergedCollapsedRef = useMergedState(\n      toRef(props, 'collapsed'),\n      uncontrolledCollapsedRef\n    )\n    const styleMaxWidthRef = computed(() => {\n      return formatLength(\n        mergedCollapsedRef.value ? props.collapsedWidth : props.width\n      )\n    })\n    const scrollContainerStyleRef = computed<CSSProperties>(() => {\n      if (props.collapseMode !== 'transform')\n        return {}\n      return {\n        minWidth: formatLength(props.width)\n      }\n    })\n    const siderPlacementRef = computed(() => {\n      return layoutProps ? layoutProps.siderPlacement : 'left'\n    })\n    function scrollTo(options: ScrollToOptions): void\n    function scrollTo(x: number, y: number): void\n    function scrollTo(options: ScrollToOptions | number, y?: number): void {\n      if (props.nativeScrollbar) {\n        const { value: scrollableEl } = scrollableElRef\n        if (scrollableEl) {\n          if (y === undefined) {\n            scrollableEl.scrollTo(options as any)\n          }\n          else {\n            scrollableEl.scrollTo(options as any, y as any)\n          }\n        }\n      }\n      else {\n        const { value: scrollbarInst } = scrollbarInstRef\n        if (scrollbarInst) {\n          scrollbarInst.scrollTo(options as any, y as any)\n        }\n      }\n    }\n    function handleTriggerClick(): void {\n      const {\n        'onUpdate:collapsed': _onUpdateCollapsed,\n        onUpdateCollapsed,\n        // deprecated\n        onExpand,\n        onCollapse\n      } = props\n      const { value: collapsed } = mergedCollapsedRef\n      if (onUpdateCollapsed) {\n        call(onUpdateCollapsed, !collapsed)\n      }\n      if (_onUpdateCollapsed) {\n        call(_onUpdateCollapsed, !collapsed)\n      }\n      uncontrolledCollapsedRef.value = !collapsed\n      if (collapsed) {\n        if (onExpand)\n          call(onExpand)\n      }\n      else {\n        if (onCollapse)\n          call(onCollapse)\n      }\n    }\n    let scrollX = 0\n    let scrollY = 0\n    const handleNativeElScroll = (e: Event): void => {\n      const target = e.target as HTMLElement\n      scrollX = target.scrollLeft\n      scrollY = target.scrollTop\n      props.onScroll?.(e)\n    }\n    useReactivated(() => {\n      if (props.nativeScrollbar) {\n        const el = scrollableElRef.value\n        if (el) {\n          el.scrollTop = scrollY\n          el.scrollLeft = scrollX\n        }\n      }\n    })\n    provide(layoutSiderInjectionKey, {\n      collapsedRef: mergedCollapsedRef,\n      collapseModeRef: toRef(props, 'collapseMode')\n    })\n    const { mergedClsPrefixRef, inlineThemeDisabled } = useConfig(props)\n    const themeRef = useTheme(\n      'Layout',\n      '-layout-sider',\n      style,\n      layoutLight,\n      props,\n      mergedClsPrefixRef\n    )\n\n    function handleTransitionend(e: TransitionEvent): void {\n      if (e.propertyName === 'max-width') {\n        if (mergedCollapsedRef.value) {\n          props.onAfterLeave?.()\n        }\n        else {\n          props.onAfterEnter?.()\n        }\n      }\n    }\n\n    const exposedMethods: LayoutSiderInst = {\n      scrollTo\n    }\n\n    const cssVarsRef = computed(() => {\n      const {\n        common: { cubicBezierEaseInOut },\n        self\n      } = themeRef.value\n      const {\n        siderToggleButtonColor,\n        siderToggleButtonBorder,\n        siderToggleBarColor,\n        siderToggleBarColorHover\n      } = self\n      const vars: any = {\n        '--n-bezier': cubicBezierEaseInOut,\n        '--n-toggle-button-color': siderToggleButtonColor,\n        '--n-toggle-button-border': siderToggleButtonBorder,\n        '--n-toggle-bar-color': siderToggleBarColor,\n        '--n-toggle-bar-color-hover': siderToggleBarColorHover\n      }\n      if (props.inverted) {\n        vars['--n-color'] = self.siderColorInverted\n        vars['--n-text-color'] = self.textColorInverted\n        vars['--n-border-color'] = self.siderBorderColorInverted\n        vars['--n-toggle-button-icon-color']\n          = self.siderToggleButtonIconColorInverted\n        vars.__invertScrollbar = self.__invertScrollbar\n      }\n      else {\n        vars['--n-color'] = self.siderColor\n        vars['--n-text-color'] = self.textColor\n        vars['--n-border-color'] = self.siderBorderColor\n        vars['--n-toggle-button-icon-color'] = self.siderToggleButtonIconColor\n      }\n      return vars\n    })\n    const themeClassHandle = inlineThemeDisabled\n      ? useThemeClass(\n          'layout-sider',\n          computed(() => (props.inverted ? 'a' : 'b')),\n          cssVarsRef,\n          props\n        )\n      : undefined\n    return {\n      scrollableElRef,\n      scrollbarInstRef,\n      mergedClsPrefix: mergedClsPrefixRef,\n      mergedTheme: themeRef,\n      styleMaxWidth: styleMaxWidthRef,\n      mergedCollapsed: mergedCollapsedRef,\n      scrollContainerStyle: scrollContainerStyleRef,\n      siderPlacement: siderPlacementRef,\n      handleNativeElScroll,\n      handleTransitionend,\n      handleTriggerClick,\n      inlineThemeDisabled,\n      cssVars: cssVarsRef,\n      themeClass: themeClassHandle?.themeClass,\n      onRender: themeClassHandle?.onRender,\n      ...exposedMethods\n    }\n  },\n  render() {\n    const { mergedClsPrefix, mergedCollapsed, showTrigger } = this\n    this.onRender?.()\n    return (\n      <aside\n        class={[\n          `${mergedClsPrefix}-layout-sider`,\n          this.themeClass,\n          `${mergedClsPrefix}-layout-sider--${this.position}-positioned`,\n          `${mergedClsPrefix}-layout-sider--${this.siderPlacement}-placement`,\n          this.bordered && `${mergedClsPrefix}-layout-sider--bordered`,\n          mergedCollapsed && `${mergedClsPrefix}-layout-sider--collapsed`,\n          (!mergedCollapsed || this.showCollapsedContent)\n          && `${mergedClsPrefix}-layout-sider--show-content`\n        ]}\n        onTransitionend={this.handleTransitionend}\n        style={[\n          this.inlineThemeDisabled ? undefined : this.cssVars,\n          {\n            maxWidth: this.styleMaxWidth,\n            width: formatLength(this.width)\n          }\n        ]}\n      >\n        {!this.nativeScrollbar ? (\n          <NScrollbar\n            {...this.scrollbarProps}\n            onScroll={this.onScroll}\n            ref=\"scrollbarInstRef\"\n            style={this.scrollContainerStyle}\n            contentStyle={this.contentStyle}\n            contentClass={this.contentClass}\n            theme={this.mergedTheme.peers.Scrollbar}\n            themeOverrides={this.mergedTheme.peerOverrides.Scrollbar}\n            // here is a hack, since in light theme the scrollbar color is dark,\n            // we need to invert it in light color...\n            builtinThemeOverrides={\n              this.inverted && this.cssVars.__invertScrollbar === 'true'\n                ? {\n                    colorHover: 'rgba(255, 255, 255, .4)',\n                    color: 'rgba(255, 255, 255, .3)'\n                  }\n                : undefined\n            }\n          >\n            {this.$slots}\n          </NScrollbar>\n        ) : (\n          <div\n            class={[\n              `${mergedClsPrefix}-layout-sider-scroll-container`,\n              this.contentClass\n            ]}\n            onScroll={this.handleNativeElScroll}\n            style={[\n              this.scrollContainerStyle,\n              {\n                overflow: 'auto'\n              },\n              this.contentStyle\n            ]}\n            ref=\"scrollableElRef\"\n          >\n            {this.$slots}\n          </div>\n        )}\n        {showTrigger ? (\n          showTrigger === 'bar' ? (\n            <ToggleBar\n              clsPrefix={mergedClsPrefix}\n              class={\n                mergedCollapsed ? this.collapsedTriggerClass : this.triggerClass\n              }\n              style={\n                mergedCollapsed ? this.collapsedTriggerStyle : this.triggerStyle\n              }\n              onClick={this.handleTriggerClick}\n            />\n          ) : (\n            <ToggleButton\n              clsPrefix={mergedClsPrefix}\n              class={\n                mergedCollapsed ? this.collapsedTriggerClass : this.triggerClass\n              }\n              style={\n                mergedCollapsed ? this.collapsedTriggerStyle : this.triggerStyle\n              }\n              onClick={this.handleTriggerClick}\n            />\n          )\n        ) : null}\n        {this.bordered ? (\n          <div class={`${mergedClsPrefix}-layout-sider__border`} />\n        ) : null}\n      </aside>\n    )\n  }\n})\n"
  },
  {
    "path": "src/layout/src/ToggleBar.tsx",
    "content": "import type { PropType } from 'vue'\nimport { defineComponent, h } from 'vue'\n\nexport default defineComponent({\n  props: {\n    clsPrefix: {\n      type: String,\n      required: true\n    },\n    onClick: Function as PropType<(e: MouseEvent) => void>\n  },\n  render() {\n    const { clsPrefix } = this\n    return (\n      <div onClick={this.onClick} class={`${clsPrefix}-layout-toggle-bar`}>\n        <div class={`${clsPrefix}-layout-toggle-bar__top`} />\n        <div class={`${clsPrefix}-layout-toggle-bar__bottom`} />\n      </div>\n    )\n  }\n})\n"
  },
  {
    "path": "src/layout/src/ToggleButton.tsx",
    "content": "import type { PropType } from 'vue'\nimport { defineComponent, h } from 'vue'\nimport { NBaseIcon } from '../../_internal'\nimport { ChevronRightIcon } from '../../_internal/icons'\n\nexport default defineComponent({\n  name: 'LayoutToggleButton',\n  props: {\n    clsPrefix: {\n      type: String,\n      required: true\n    },\n    onClick: Function as PropType<(e: MouseEvent) => void>\n  },\n  render() {\n    const { clsPrefix } = this\n    return (\n      <div class={`${clsPrefix}-layout-toggle-button`} onClick={this.onClick}>\n        <NBaseIcon clsPrefix={clsPrefix}>\n          {{\n            default: () => <ChevronRightIcon />\n          }}\n        </NBaseIcon>\n      </div>\n    )\n  }\n})\n"
  },
  {
    "path": "src/layout/src/interface.ts",
    "content": "import type { PropType, Ref } from 'vue'\nimport { createInjectionKey } from '../../_utils'\n\nexport const layoutSiderInjectionKey = createInjectionKey<{\n  collapsedRef: Ref<boolean>\n  collapseModeRef: Ref<'transform' | 'width'>\n}>('n-layout-sider')\n\nexport const positionProp = {\n  type: String as PropType<'static' | 'absolute'>,\n  default: 'static'\n} as const\n\nexport interface LayoutInst {\n  scrollTo: ((options: ScrollToOptions) => void)\n    & ((x: number, y: number) => void)\n}\n\nexport type LayoutSiderInst = LayoutInst\n"
  },
  {
    "path": "src/layout/src/styles/layout-footer.cssr.ts",
    "content": "import { cB, cM } from '../../../_utils/cssr'\n\n// vars:\n// --n-bezier\n// --n-color\n// --n-border-color\n// --n-text-color\nexport default cB('layout-footer', `\n  transition:\n    box-shadow .3s var(--n-bezier),\n    color .3s var(--n-bezier),\n    background-color .3s var(--n-bezier),\n    border-color .3s var(--n-bezier);\n  color: var(--n-text-color);\n  background-color: var(--n-color);\n  box-sizing: border-box;\n`, [\n  cM('absolute-positioned', `\n    position: absolute;\n    left: 0;\n    right: 0;\n    bottom: 0;\n  `),\n  cM('bordered', `\n    border-top: solid 1px var(--n-border-color);\n  `)\n])\n"
  },
  {
    "path": "src/layout/src/styles/layout-header.cssr.ts",
    "content": "import { cB, cM } from '../../../_utils/cssr'\n\n// vars:\n// --n-bezier\n// --n-text-color\n// --n-color\n// --n-border-color\nexport default cB('layout-header', `\n  transition:\n    color .3s var(--n-bezier),\n    background-color .3s var(--n-bezier),\n    box-shadow .3s var(--n-bezier),\n    border-color .3s var(--n-bezier);\n  box-sizing: border-box;\n  width: 100%;\n  background-color: var(--n-color);\n  color: var(--n-text-color);\n`, [\n  cM('absolute-positioned', `\n    position: absolute;\n    left: 0;\n    right: 0;\n    top: 0;\n  `),\n  cM('bordered', `\n    border-bottom: solid 1px var(--n-border-color);\n  `)\n])\n"
  },
  {
    "path": "src/layout/src/styles/layout-sider.cssr.ts",
    "content": "import { c, cB, cE, cM } from '../../../_utils/cssr'\n\n// vars:\n// --n-bezier\n// --n-color\n// --n-text-color\n// --n-border-color\n// --n-toggle-button-color\n// --n-toggle-bar-color\n// --n-toggle-bar-color-hover\nexport default cB('layout-sider', `\n  flex-shrink: 0;\n  box-sizing: border-box;\n  position: relative;\n  z-index: 1;\n  color: var(--n-text-color);\n  transition:\n    color .3s var(--n-bezier),\n    border-color .3s var(--n-bezier),\n    min-width .3s var(--n-bezier),\n    max-width .3s var(--n-bezier),\n    transform .3s var(--n-bezier),\n    background-color .3s var(--n-bezier);\n  background-color: var(--n-color);\n  display: flex;\n  justify-content: flex-end;\n`, [\n  cM('bordered', [\n    cE('border', `\n      content: \"\";\n      position: absolute;\n      top: 0;\n      bottom: 0;\n      width: 1px;\n      background-color: var(--n-border-color);\n      transition: background-color .3s var(--n-bezier);\n    `)\n  ]),\n  cE('left-placement', [\n    cM('bordered', [\n      cE('border', `\n        right: 0;\n      `)\n    ])\n  ]),\n  cM('right-placement', `\n    justify-content: flex-start;\n  `, [\n    cM('bordered', [\n      cE('border', `\n        left: 0;\n      `)\n    ]),\n    cM('collapsed', [\n      cB('layout-toggle-button', [\n        cB('base-icon', `\n          transform: rotate(180deg);\n        `)\n      ]),\n      cB('layout-toggle-bar', [\n        c('&:hover', [\n          cE('top', {\n            transform: 'rotate(-12deg) scale(1.15) translateY(-2px)'\n          }),\n          cE('bottom', {\n            transform: 'rotate(12deg) scale(1.15) translateY(2px)'\n          })\n        ])\n      ])\n    ]),\n    cB('layout-toggle-button', `\n      left: 0;\n      transform: translateX(-50%) translateY(-50%);\n    `, [\n      cB('base-icon', `\n        transform: rotate(0);\n      `)\n    ]),\n    cB('layout-toggle-bar', `\n      left: -28px;\n      transform: rotate(180deg);\n    `, [\n      c('&:hover', [\n        cE('top', {\n          transform: 'rotate(12deg) scale(1.15) translateY(-2px)'\n        }),\n        cE('bottom', {\n          transform: 'rotate(-12deg) scale(1.15) translateY(2px)'\n        })\n      ])\n    ])\n  ]),\n  cM('collapsed', [\n    cB('layout-toggle-bar', [\n      c('&:hover', [\n        cE('top', {\n          transform: 'rotate(-12deg) scale(1.15) translateY(-2px)'\n        }),\n        cE('bottom', {\n          transform: 'rotate(12deg) scale(1.15) translateY(2px)'\n        })\n      ])\n    ]),\n    cB('layout-toggle-button', [\n      cB('base-icon', `\n        transform: rotate(0);\n      `)\n    ])\n  ]),\n  cB('layout-toggle-button', `\n    transition:\n      color .3s var(--n-bezier),\n      right .3s var(--n-bezier),\n      left .3s var(--n-bezier),\n      border-color .3s var(--n-bezier),\n      background-color .3s var(--n-bezier);\n    cursor: pointer;\n    width: 24px;\n    height: 24px;\n    position: absolute;\n    top: 50%;\n    right: 0;\n    border-radius: 50%;\n    display: flex;\n    align-items: center;\n    justify-content: center;\n    font-size: 18px;\n    color: var(--n-toggle-button-icon-color);\n    border: var(--n-toggle-button-border);\n    background-color: var(--n-toggle-button-color);\n    box-shadow: 0 2px 4px 0px rgba(0, 0, 0, .06);\n    transform: translateX(50%) translateY(-50%);\n    z-index: 1;\n  `, [\n    cB('base-icon', `\n      transition: transform .3s var(--n-bezier);\n      transform: rotate(180deg);\n    `)\n  ]),\n  cB('layout-toggle-bar', `\n    cursor: pointer;\n    height: 72px;\n    width: 32px;\n    position: absolute;\n    top: calc(50% - 36px);\n    right: -28px;\n  `, [\n    cE('top, bottom', `\n      position: absolute;\n      width: 4px;\n      border-radius: 2px;\n      height: 38px;\n      left: 14px;\n      transition: \n        background-color .3s var(--n-bezier),\n        transform .3s var(--n-bezier);\n    `),\n    cE('bottom', `\n      position: absolute;\n      top: 34px;\n    `),\n    c('&:hover', [\n      cE('top', {\n        transform: 'rotate(12deg) scale(1.15) translateY(-2px)'\n      }),\n      cE('bottom', {\n        transform: 'rotate(-12deg) scale(1.15) translateY(2px)'\n      })\n    ]),\n    cE('top, bottom', {\n      backgroundColor: 'var(--n-toggle-bar-color)'\n    }),\n    c('&:hover', [\n      cE('top, bottom', {\n        backgroundColor: 'var(--n-toggle-bar-color-hover)'\n      })\n    ])\n  ]),\n  cE('border', `\n    position: absolute;\n    top: 0;\n    right: 0;\n    bottom: 0;\n    width: 1px;\n    transition: background-color .3s var(--n-bezier);\n  `),\n  cB('layout-sider-scroll-container', `\n    flex-grow: 1;\n    flex-shrink: 0;\n    box-sizing: border-box;\n    height: 100%;\n    opacity: 0;\n    transition: opacity .3s var(--n-bezier);\n    max-width: 100%;\n  `),\n  cM('show-content', [\n    cB('layout-sider-scroll-container', {\n      opacity: 1\n    })\n  ]),\n  cM('absolute-positioned', `\n    position: absolute;\n    left: 0;\n    top: 0;\n    bottom: 0;\n  `)\n])\n"
  },
  {
    "path": "src/layout/src/styles/layout.cssr.ts",
    "content": "import { cB, cM } from '../../../_utils/cssr'\n\n// vars:\n// --n-bezier\n// --n-color\n// --n-text-color\nexport default cB('layout', `\n  color: var(--n-text-color);\n  background-color: var(--n-color);\n  box-sizing: border-box;\n  position: relative;\n  z-index: auto;\n  flex: auto;\n  overflow: hidden;\n  transition:\n    box-shadow .3s var(--n-bezier),\n    background-color .3s var(--n-bezier),\n    color .3s var(--n-bezier);\n`, [\n  cB('layout-scroll-container', `\n    overflow-x: hidden;\n    box-sizing: border-box;\n    height: 100%;\n  `),\n  cM('absolute-positioned', `\n    position: absolute;\n    left: 0;\n    right: 0;\n    top: 0;\n    bottom: 0;\n  `)\n])\n"
  },
  {
    "path": "src/layout/styles/dark.ts",
    "content": "import type { LayoutTheme } from './light'\nimport { composite } from 'seemly'\nimport { scrollbarDark } from '../../_internal/scrollbar/styles'\nimport { commonDark } from '../../_styles/common'\n\nconst layoutDark: LayoutTheme = {\n  name: 'Layout',\n  common: commonDark,\n  peers: {\n    Scrollbar: scrollbarDark\n  },\n  self(vars) {\n    const {\n      textColor2,\n      bodyColor,\n      popoverColor,\n      cardColor,\n      dividerColor,\n      scrollbarColor,\n      scrollbarColorHover\n    } = vars\n    return {\n      textColor: textColor2,\n      textColorInverted: textColor2,\n      color: bodyColor,\n      colorEmbedded: bodyColor,\n      headerColor: cardColor,\n      headerColorInverted: cardColor,\n      footerColor: cardColor,\n      footerColorInverted: cardColor,\n      headerBorderColor: dividerColor,\n      headerBorderColorInverted: dividerColor,\n      footerBorderColor: dividerColor,\n      footerBorderColorInverted: dividerColor,\n      siderBorderColor: dividerColor,\n      siderBorderColorInverted: dividerColor,\n      siderColor: cardColor,\n      siderColorInverted: cardColor,\n      siderToggleButtonBorder: '1px solid transparent',\n      siderToggleButtonColor: popoverColor,\n      siderToggleButtonIconColor: textColor2,\n      siderToggleButtonIconColorInverted: textColor2,\n      siderToggleBarColor: composite(bodyColor, scrollbarColor),\n      siderToggleBarColorHover: composite(bodyColor, scrollbarColorHover),\n      __invertScrollbar: 'false'\n    }\n  }\n}\n\nexport default layoutDark\n"
  },
  {
    "path": "src/layout/styles/index.ts",
    "content": "export { default as layoutDark } from './dark'\nexport { default as layoutLight } from './light'\nexport type { LayoutTheme, LayoutThemeVars } from './light'\n"
  },
  {
    "path": "src/layout/styles/light.ts",
    "content": "import type { ThemeCommonVars } from '../../_styles/common'\nimport { composite } from 'seemly'\nimport { scrollbarLight } from '../../_internal/scrollbar/styles'\nimport { createTheme } from '../../_mixins'\nimport { commonLight } from '../../_styles/common'\n\nexport function self(vars: ThemeCommonVars) {\n  const {\n    baseColor,\n    textColor2,\n    bodyColor,\n    cardColor,\n    dividerColor,\n    actionColor,\n    scrollbarColor,\n    scrollbarColorHover,\n    invertedColor\n  } = vars\n  return {\n    textColor: textColor2,\n    textColorInverted: '#FFF',\n    color: bodyColor,\n    colorEmbedded: actionColor,\n    headerColor: cardColor,\n    headerColorInverted: invertedColor,\n    footerColor: actionColor,\n    footerColorInverted: invertedColor,\n    headerBorderColor: dividerColor,\n    headerBorderColorInverted: invertedColor,\n    footerBorderColor: dividerColor,\n    footerBorderColorInverted: invertedColor,\n    siderBorderColor: dividerColor,\n    siderBorderColorInverted: invertedColor,\n    siderColor: cardColor,\n    siderColorInverted: invertedColor,\n    siderToggleButtonBorder: `1px solid ${dividerColor}`,\n    siderToggleButtonColor: baseColor,\n    siderToggleButtonIconColor: textColor2,\n    siderToggleButtonIconColorInverted: textColor2,\n    siderToggleBarColor: composite(bodyColor, scrollbarColor),\n    siderToggleBarColorHover: composite(bodyColor, scrollbarColorHover),\n    // hack for inverted background\n    __invertScrollbar: 'true'\n  }\n}\n\nexport type LayoutThemeVars = ReturnType<typeof self>\n\nconst layoutLight = createTheme({\n  name: 'Layout',\n  common: commonLight,\n  peers: {\n    Scrollbar: scrollbarLight\n  },\n  self\n})\n\nexport default layoutLight\nexport type LayoutTheme = typeof layoutLight\n"
  },
  {
    "path": "src/layout/tests/Layout.spec.ts",
    "content": "import { mount } from '@vue/test-utils'\nimport { h } from 'vue'\nimport { NCard } from '../../card'\nimport { NH2 } from '../../typography'\nimport {\n  NLayout,\n  NLayoutContent,\n  NLayoutFooter,\n  NLayoutHeader,\n  NLayoutSider\n} from '../index'\n\ndescribe('n-layout', () => {\n  it('should work with import on demand', () => {\n    mount(NLayout)\n  })\n\n  it('should work with Basic', async () => {\n    const wrapper = mount(NLayout, {\n      props: {\n        'has-sider': true\n      },\n      slots: {\n        default: () => [\n          h(NLayoutHeader, null, { default: () => 'test-header' }),\n          h(NLayoutContent, null, { default: () => 'test-content' }),\n          h(NLayoutSider, null, { default: () => 'test-sider' }),\n          h(NLayoutFooter, null, { default: () => 'test-footer' })\n        ]\n      }\n    })\n\n    expect(\n      wrapper.find('.n-layout-scroll-container').element.children.length\n    ).toBe(4)\n    expect(\n      wrapper\n        .find('.n-layout-scroll-container')\n        .element.children[0].getAttribute('class')\n    ).toContain('n-layout-header')\n    expect(wrapper.find('.n-layout-header').text()).toBe('test-header')\n    expect(\n      wrapper\n        .find('.n-layout-scroll-container')\n        .element.children[1].getAttribute('class')\n    ).toContain('n-layout-content')\n    expect(wrapper.findAll('.n-layout-scroll-container')[1].text()).toBe(\n      'test-content'\n    )\n    expect(\n      wrapper\n        .find('.n-layout-scroll-container')\n        .element.children[2].getAttribute('class')\n    ).toContain('n-layout-sider')\n    expect(wrapper.find('.n-layout-sider-scroll-container').text()).toBe(\n      'test-sider'\n    )\n    expect(\n      wrapper\n        .find('.n-layout-scroll-container')\n        .element.children[3].getAttribute('class')\n    ).toContain('n-layout-footer')\n    expect(wrapper.find('.n-layout-footer').text()).toBe('test-footer')\n    wrapper.unmount()\n  })\n\n  it('should work with `content-style` prop', async () => {\n    const wrapper = mount(NLayout, {\n      props: {\n        'has-sider': true\n      },\n      slots: {\n        default: () =>\n          h(\n            NLayoutSider,\n            { 'content-style': 'padding: 24px' },\n            {\n              default: () => [\n                h(NH2, null, { default: () => 'test1' }),\n                h(NH2, null, { default: () => 'test2' })\n              ]\n            }\n          )\n      }\n    })\n    expect(\n      wrapper.find('.n-layout-sider-scroll-container').attributes('style')\n    ).toContain('padding: 24px')\n    wrapper.unmount()\n  })\n\n  it('should work with `embedded` prop', async () => {\n    const wrapper = mount(NLayout, {\n      props: {\n        embedded: true\n      },\n      slots: {\n        default: () =>\n          h(NCard, null, {\n            default: () => 'test'\n          })\n      }\n    })\n    expect(wrapper.find('.n-layout').attributes('style')).toMatchSnapshot()\n    wrapper.unmount()\n  })\n\n  it('should work with `bordered` prop', async () => {\n    const wrapper = mount(NLayout, {\n      props: {\n        'has-sider': true\n      },\n      slots: {\n        default: () => [\n          h(\n            NLayoutHeader,\n            { bordered: true },\n            { default: () => 'test-header' }\n          ),\n          h(NLayoutSider, { bordered: true }, { default: () => 'test-sider' }),\n          h(NLayoutFooter, { bordered: true }, { default: () => 'test-footer' })\n        ]\n      }\n    })\n    expect(wrapper.find('.n-layout-header').classes()).toContain(\n      'n-layout-header--bordered'\n    )\n    expect(wrapper.find('.n-layout-sider').classes()).toContain(\n      'n-layout-sider--bordered'\n    )\n    expect(wrapper.find('.n-layout-footer').classes()).toContain(\n      'n-layout-footer--bordered'\n    )\n    wrapper.unmount()\n  })\n\n  it('should work with `inverted` prop', async () => {\n    const wrapper = mount(NLayout, {\n      props: {\n        'has-sider': true\n      },\n      slots: {\n        default: () => [\n          h(\n            NLayoutHeader,\n            { inverted: true },\n            { default: () => 'test-header' }\n          ),\n          h(NLayoutSider, { inverted: true }, { default: () => 'test-sider' }),\n          h(NLayoutFooter, { inverted: true }, { default: () => 'test-footer' })\n        ]\n      }\n    })\n    expect(\n      wrapper.find('.n-layout-header').attributes('style')\n    ).toMatchSnapshot()\n    expect(\n      wrapper.find('.n-layout-sider').attributes('style')\n    ).toMatchSnapshot()\n    expect(\n      wrapper.find('.n-layout-footer').attributes('style')\n    ).toMatchSnapshot()\n    wrapper.unmount()\n  })\n\n  it('should work with `position` prop', async () => {\n    let wrapper = mount(NLayout, {\n      slots: {\n        default: () => [\n          h(NLayoutHeader, null, { default: () => 'test-header' })\n        ]\n      }\n    })\n    expect(wrapper.find('.n-layout').classes()).toContain(\n      'n-layout--static-positioned'\n    )\n    wrapper = mount(NLayout, {\n      props: {\n        position: 'absolute'\n      },\n      slots: {\n        default: () => [\n          h(NLayoutHeader, null, { default: () => 'test-header' })\n        ]\n      }\n    })\n    expect(wrapper.find('.n-layout').classes()).toContain(\n      'n-layout--absolute-positioned'\n    )\n    wrapper.unmount()\n  })\n\n  it('should work with `sider-placement` prop', async () => {\n    const wrapper = mount(NLayout, {\n      props: {\n        hasSider: true\n      },\n      slots: {\n        default: () => [\n          h(NLayoutSider, null, { default: () => 'test-sider' }),\n          h(NLayoutContent, null, { default: () => 'test-footer' })\n        ]\n      }\n    })\n    expect(wrapper.find('.n-layout-sider').classes()).toContain(\n      'n-layout-sider--left-placement'\n    )\n\n    await wrapper.setProps({ siderPlacement: 'right' })\n    expect(wrapper.find('.n-layout-sider').classes()).toContain(\n      'n-layout-sider--right-placement'\n    )\n    wrapper.unmount()\n  })\n})\n"
  },
  {
    "path": "src/layout/tests/__snapshots__/Layout.spec.ts.snap",
    "content": "// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html\n\nexports[`n-layout > should work with \\`embedded\\` prop 1`] = `\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-color: rgb(250, 250, 252); --n-text-color: rgb(51, 54, 57);\"`;\n\nexports[`n-layout > should work with \\`inverted\\` prop 1`] = `\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-color: rgb(0, 20, 40); --n-text-color: #FFF; --n-border-color: rgb(0, 20, 40);\"`;\n\nexports[`n-layout > should work with \\`inverted\\` prop 2`] = `\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-toggle-button-color: #FFF; --n-toggle-button-border: 1px solid rgb(239, 239, 245); --n-toggle-bar-color: rgba(191, 191, 191, 1); --n-toggle-bar-color-hover: rgba(153, 153, 153, 1); --n-color: rgb(0, 20, 40); --n-text-color: #FFF; --n-border-color: rgb(0, 20, 40); --n-toggle-button-icon-color: rgb(51, 54, 57); max-width: 272px; width: 272px;\"`;\n\nexports[`n-layout > should work with \\`inverted\\` prop 3`] = `\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-color: rgb(0, 20, 40); --n-text-color: #FFF; --n-border-color: rgb(0, 20, 40);\"`;\n"
  },
  {
    "path": "src/layout/tests/server.spec.tsx",
    "content": "import { setup } from '@css-render/vue3-ssr'\nimport { renderToString } from '@vue/server-renderer'\n/**\n * @vitest-environment node\n */\nimport { createSSRApp, h } from 'vue'\nimport { NLayout } from '../..'\n\ndescribe('server side rendering', () => {\n  it('works', async () => {\n    const app = createSSRApp(() => <NLayout />)\n    setup(app)\n    try {\n      await renderToString(app)\n    }\n    catch (e) {\n      expect(e).not.toBeTruthy()\n    }\n  })\n})\n"
  },
  {
    "path": "src/legacy-grid/demos/enUS/basic.demo.vue",
    "content": "<markdown>\n# Basic\n</markdown>\n\n<template>\n  <n-row gutter=\"12\">\n    <n-col :span=\"6\">\n      <div class=\"light-green\" />\n    </n-col>\n    <n-col :span=\"6\">\n      <div class=\"green\" />\n    </n-col>\n    <n-col :span=\"6\">\n      <div class=\"light-green\" />\n    </n-col>\n    <n-col :span=\"6\">\n      <div class=\"green\" />\n    </n-col>\n  </n-row>\n</template>\n\n<style>\n.light-green {\n  height: 108px;\n  background-color: rgba(0, 128, 0, 0.12);\n}\n.green {\n  height: 108px;\n  background-color: rgba(0, 128, 0, 0.24);\n}\n</style>\n"
  },
  {
    "path": "src/legacy-grid/demos/enUS/gutter.demo.vue",
    "content": "<markdown>\n# Gutter\n\nSet horizontal gutter & vertical gutter.\n</markdown>\n\n<template>\n  <n-row :gutter=\"[12, 8]\">\n    <n-col :span=\"6\">\n      <div class=\"light-green\" />\n    </n-col>\n    <n-col :span=\"6\">\n      <div class=\"green\" />\n    </n-col>\n    <n-col :span=\"6\">\n      <div class=\"light-green\" />\n    </n-col>\n    <n-col :span=\"6\">\n      <div class=\"green\" />\n    </n-col>\n    <n-col :span=\"6\">\n      <div class=\"light-green\" />\n    </n-col>\n    <n-col :span=\"6\">\n      <div class=\"green\" />\n    </n-col>\n    <n-col :span=\"6\">\n      <div class=\"light-green\" />\n    </n-col>\n    <n-col :span=\"6\">\n      <div class=\"green\" />\n    </n-col>\n  </n-row>\n</template>\n\n<style>\n.light-green {\n  height: 108px;\n  background-color: rgba(0, 128, 0, 0.12);\n}\n.green {\n  height: 108px;\n  background-color: rgba(0, 128, 0, 0.24);\n}\n</style>\n"
  },
  {
    "path": "src/legacy-grid/demos/enUS/index.demo-entry.md",
    "content": "# Legacy Grid\n\n<!--single-column-->\n\n<n-alert title=\"Caveat\" type=\"warning\" style=\"margin-bottom: 16px\" :bordered=\"false\">\n  At most of time you should use <router-link to=\"grid\" #=\"{ navigate, href }\" custom><n-a :href=\"href\" @click=\"navigate\">Grid</n-a></router-link>.\n</n-alert>\n\nA basic grid system.\n\n## Demos\n\n```demo\nbasic.vue\ngutter.vue\noffset.vue\npush-pull.vue\n```\n\n## API\n\n### Row Props\n\n| Name | Type | Default | Description |\n| --- | --- | --- | --- |\n| gutter | `number \\| string \\| [number, number] \\| [string, string]` | `0` | `horizontal gutter` or `[horizontal gutter, vertical gutter]` |\n\n### Col Props\n\n| Name   | Type     | Default | Description |\n| ------ | -------- | ------- | ----------- |\n| span   | `number` | `1`     |             |\n| offset | `number` | `0`     |             |\n| push   | `number` | `0`     |             |\n| pull   | `number` | `0`     |             |\n"
  },
  {
    "path": "src/legacy-grid/demos/enUS/offset.demo.vue",
    "content": "<markdown>\n# Offset\n</markdown>\n\n<template>\n  <n-row :gutter=\"12\">\n    <n-col :span=\"6\" :offset=\"6\">\n      <div class=\"light-green\" />\n    </n-col>\n    <n-col :span=\"6\" :offset=\"6\">\n      <div class=\"green\" />\n    </n-col>\n  </n-row>\n</template>\n\n<style>\n.light-green {\n  height: 108px;\n  background-color: rgba(0, 128, 0, 0.12);\n}\n.green {\n  height: 108px;\n  background-color: rgba(0, 128, 0, 0.24);\n}\n</style>\n"
  },
  {
    "path": "src/legacy-grid/demos/enUS/push-pull.demo.vue",
    "content": "<markdown>\n# Push & pull\n\nSee codes to know what happens. Basically it is relative position change.\n</markdown>\n\n<template>\n  <n-row :gutter=\"12\">\n    <n-col :span=\"6\" :push=\"6\">\n      <div class=\"light-green\" />\n    </n-col>\n    <n-col :span=\"6\" :pull=\"6\">\n      <div class=\"green\" />\n    </n-col>\n    <n-col :span=\"6\">\n      <div class=\"light-green\" />\n    </n-col>\n    <n-col :span=\"6\">\n      <div class=\"green\" />\n    </n-col>\n  </n-row>\n</template>\n\n<style>\n.light-green {\n  height: 108px;\n  background-color: rgba(0, 128, 0, 0.12);\n}\n.green {\n  height: 108px;\n  background-color: rgba(0, 128, 0, 0.24);\n}\n</style>\n"
  },
  {
    "path": "src/legacy-grid/demos/zhCN/basic.demo.vue",
    "content": "<markdown>\n# 基础用法\n</markdown>\n\n<template>\n  <n-row gutter=\"12\">\n    <n-col :span=\"6\">\n      <div class=\"light-green\" />\n    </n-col>\n    <n-col :span=\"6\">\n      <div class=\"green\" />\n    </n-col>\n    <n-col :span=\"6\">\n      <div class=\"light-green\" />\n    </n-col>\n    <n-col :span=\"6\">\n      <div class=\"green\" />\n    </n-col>\n  </n-row>\n</template>\n\n<style>\n.light-green {\n  height: 108px;\n  background-color: rgba(0, 128, 0, 0.12);\n}\n.green {\n  height: 108px;\n  background-color: rgba(0, 128, 0, 0.24);\n}\n</style>\n"
  },
  {
    "path": "src/legacy-grid/demos/zhCN/gutter.demo.vue",
    "content": "<markdown>\n# 间隔\n\n设定水平、垂直间隔。\n</markdown>\n\n<template>\n  <n-row :gutter=\"[12, 8]\">\n    <n-col :span=\"6\">\n      <div class=\"light-green\" />\n    </n-col>\n    <n-col :span=\"6\">\n      <div class=\"green\" />\n    </n-col>\n    <n-col :span=\"6\">\n      <div class=\"light-green\" />\n    </n-col>\n    <n-col :span=\"6\">\n      <div class=\"green\" />\n    </n-col>\n    <n-col :span=\"6\">\n      <div class=\"light-green\" />\n    </n-col>\n    <n-col :span=\"6\">\n      <div class=\"green\" />\n    </n-col>\n    <n-col :span=\"6\">\n      <div class=\"light-green\" />\n    </n-col>\n    <n-col :span=\"6\">\n      <div class=\"green\" />\n    </n-col>\n  </n-row>\n</template>\n\n<style>\n.light-green {\n  height: 108px;\n  background-color: rgba(0, 128, 0, 0.12);\n}\n.green {\n  height: 108px;\n  background-color: rgba(0, 128, 0, 0.24);\n}\n</style>\n"
  },
  {
    "path": "src/legacy-grid/demos/zhCN/index.demo-entry.md",
    "content": "# 旧版栅格 Legacy Grid\n\n<!--single-column-->\n\n<n-alert title=\"警告\" type=\"warning\" style=\"margin-bottom: 16px\" :bordered=\"false\">\n绝大多数情况下你应该使用<router-link to=\"grid\" #=\"{ navigate, href }\" custom><n-a :href=\"href\" @click=\"navigate\">栅格</n-a></router-link>。\n</n-alert>\n\n一个基本的栅格系统。\n\n## 演示\n\n```demo\nbasic.vue\ngutter.vue\noffset.vue\npush-pull.vue\nwrap-debug.vue\nrtl-debug.vue\n```\n\n## API\n\n### Row Props\n\n| 名称 | 类型 | 默认值 | 说明 |\n| --- | --- | --- | --- |\n| gutter | `number \\| string \\| [number, number] \\| [string, string]` | `0` | `水平间隔` 或者 `[水平间隔, 垂直间隔]` |\n\n### Col Props\n\n| 名称   | 类型     | 默认值 | 说明 |\n| ------ | -------- | ------ | ---- |\n| span   | `number` | `1`    |      |\n| offset | `number` | `0`    |      |\n| push   | `number` | `0`    |      |\n| pull   | `number` | `0`    |      |\n"
  },
  {
    "path": "src/legacy-grid/demos/zhCN/offset.demo.vue",
    "content": "<markdown>\n# 偏移\n</markdown>\n\n<template>\n  <n-row :gutter=\"12\">\n    <n-col :span=\"6\" :offset=\"6\">\n      <div class=\"light-green\" />\n    </n-col>\n    <n-col :span=\"6\" :offset=\"6\">\n      <div class=\"green\" />\n    </n-col>\n  </n-row>\n</template>\n\n<style>\n.light-green {\n  height: 108px;\n  background-color: rgba(0, 128, 0, 0.12);\n}\n.green {\n  height: 108px;\n  background-color: rgba(0, 128, 0, 0.24);\n}\n</style>\n"
  },
  {
    "path": "src/legacy-grid/demos/zhCN/push-pull.demo.vue",
    "content": "<markdown>\n# 推 & 拉\n\n看看代码就明白这个怎么用了，基本来说就是相对位置的改变。\n</markdown>\n\n<template>\n  <n-row :gutter=\"12\">\n    <n-col :span=\"6\" :push=\"6\">\n      <div class=\"light-green\" />\n    </n-col>\n    <n-col :span=\"6\" :pull=\"6\">\n      <div class=\"green\" />\n    </n-col>\n    <n-col :span=\"6\">\n      <div class=\"light-green\" />\n    </n-col>\n    <n-col :span=\"6\">\n      <div class=\"green\" />\n    </n-col>\n  </n-row>\n</template>\n\n<style>\n.light-green {\n  height: 108px;\n  background-color: rgba(0, 128, 0, 0.12);\n}\n.green {\n  height: 108px;\n  background-color: rgba(0, 128, 0, 0.24);\n}\n</style>\n"
  },
  {
    "path": "src/legacy-grid/demos/zhCN/rtl-debug.demo.vue",
    "content": "<markdown>\n# Rtl Debug\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { unstableRowRtl } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst rtlEnabled = ref(false)\nconst rtlStyles = [unstableRowRtl]\n</script>\n\n<template>\n  <n-space vertical>\n    <n-space><n-switch v-model:value=\"rtlEnabled\" />Rtl</n-space>\n    <n-config-provider :rtl=\"rtlEnabled ? rtlStyles : undefined\">\n      <n-row gutter=\"12\">\n        <n-col :span=\"6\">\n          <div class=\"light-green\" />\n        </n-col>\n        <n-col :span=\"6\">\n          <div class=\"green\" />\n        </n-col>\n        <n-col :span=\"6\">\n          <div class=\"light-green\" />\n        </n-col>\n        <n-col :span=\"6\">\n          <div class=\"green\" />\n        </n-col>\n      </n-row>\n    </n-config-provider>\n  </n-space>\n</template>\n\n<style>\n.light-green {\n  height: 108px;\n  background-color: rgba(0, 128, 0, 0.12);\n}\n.green {\n  height: 108px;\n  background-color: rgba(0, 128, 0, 0.24);\n}\n</style>\n"
  },
  {
    "path": "src/legacy-grid/demos/zhCN/wrap-debug.demo.vue",
    "content": "<markdown>\n# Wrap debug\n</markdown>\n\n<template>\n  <n-row :gutter=\"[12, 8]\">\n    <n-col :span=\"4\">\n      <div class=\"light-green\" />\n    </n-col>\n    <n-col :span=\"4\">\n      <div class=\"green\" />\n    </n-col>\n    <n-col :span=\"4\">\n      <div class=\"light-green\" />\n    </n-col>\n    <n-col :span=\"4\">\n      <div class=\"green\" />\n    </n-col>\n    <n-col :span=\"4\">\n      <div class=\"light-green\" />\n    </n-col>\n    <n-col :span=\"4\">\n      <div class=\"green\" />\n    </n-col>\n    <n-col :span=\"4\">\n      <div class=\"light-green\" />\n    </n-col>\n    <n-col :span=\"4\">\n      <div class=\"green\" />\n    </n-col>\n  </n-row>\n</template>\n\n<style>\n.light-green {\n  height: 108px;\n  background-color: rgba(0, 128, 0, 0.12);\n}\n.green {\n  height: 108px;\n  background-color: rgba(0, 128, 0, 0.24);\n}\n</style>\n"
  },
  {
    "path": "src/legacy-grid/index.ts",
    "content": "export { colProps, default as NCol } from './src/Col'\nexport type { ColProps } from './src/Col'\nexport { default as NRow, rowProps } from './src/Row'\nexport type { RowProps } from './src/Row'\n"
  },
  {
    "path": "src/legacy-grid/src/Col.tsx",
    "content": "import type { PropType } from 'vue'\nimport type { ExtractPublicPropTypes } from '../../_utils'\nimport type { Span } from './interface'\nimport { computed, defineComponent, h, inject } from 'vue'\nimport { formatLength, keysOf, throwError } from '../../_utils'\nimport { rowInjectionKey } from './Row'\n\nexport const colProps = {\n  span: {\n    type: [String, Number] as PropType<Span>,\n    default: 1\n  },\n  push: {\n    type: [String, Number] as PropType<Span>,\n    default: 0\n  },\n  pull: {\n    type: [String, Number] as PropType<Span>,\n    default: 0\n  },\n  offset: {\n    type: [String, Number] as PropType<Span>,\n    default: 0\n  }\n} as const\n\nexport const colPropKeys = keysOf(colProps)\n\nexport type ColProps = ExtractPublicPropTypes<typeof colProps>\n\nexport default defineComponent({\n  name: 'Col',\n  props: colProps,\n  setup(props) {\n    const NRow = inject(rowInjectionKey, null)\n    if (!NRow)\n      throwError('col', '`n-col` must be placed inside `n-row`.')\n    return {\n      mergedClsPrefix: NRow.mergedClsPrefixRef,\n      gutter: NRow.gutterRef,\n      stylePadding: computed(\n        () =>\n          `${formatLength(NRow.verticalGutterRef.value, {\n            c: 0.5\n          })} ${formatLength(NRow.horizontalGutterRef.value, { c: 0.5 })}`\n      ),\n      mergedPush: computed(() => Number(props.push) - Number(props.pull))\n    }\n  },\n  render() {\n    const {\n      $slots,\n      span,\n      mergedPush,\n      offset,\n      stylePadding,\n      gutter,\n      mergedClsPrefix\n    } = this\n    return (\n      <div\n        class={[\n          `${mergedClsPrefix}-col`,\n          {\n            [`${mergedClsPrefix}-col--${span}-span`]: true,\n            [`${mergedClsPrefix}-col--${mergedPush}-push`]: mergedPush > 0,\n            [`${mergedClsPrefix}-col--${-mergedPush}-pull`]: mergedPush < 0,\n            [`${mergedClsPrefix}-col--${offset}-offset`]: offset\n          }\n        ]}\n        style={{\n          padding: stylePadding\n        }}\n      >\n        {gutter ? <div>{$slots}</div> : $slots}\n      </div>\n    )\n  }\n})\n"
  },
  {
    "path": "src/legacy-grid/src/Row.tsx",
    "content": "import type { PropType, Ref } from 'vue'\nimport type { ExtractPublicPropTypes } from '../../_utils'\nimport { useMemo } from 'vooks'\nimport { defineComponent, h, provide, toRef } from 'vue'\nimport { useConfig, useRtl, useStyle } from '../../_mixins'\nimport { createInjectionKey, formatLength, keysOf } from '../../_utils'\nimport style from './styles/index.cssr'\n\nexport interface RowInjection {\n  gutterRef: Ref<string | number | [number, number]>\n  verticalGutterRef: Ref<number>\n  horizontalGutterRef: Ref<number>\n  mergedClsPrefixRef: Ref<string>\n}\n\nexport const rowInjectionKey = createInjectionKey<RowInjection>('n-row')\n\nexport const rowProps = {\n  gutter: {\n    type: [Array, Number, String] as PropType<\n      string | number | [number, number]\n    >,\n    default: 0\n  },\n  alignItems: String,\n  justifyContent: String\n} as const\n\nexport const rowPropKeys = keysOf(rowProps)\n\nexport type RowProps = ExtractPublicPropTypes<typeof rowProps>\n\nexport default defineComponent({\n  name: 'Row',\n  props: rowProps,\n  setup(props) {\n    const { mergedClsPrefixRef, mergedRtlRef } = useConfig(props)\n    useStyle('-legacy-grid', style, mergedClsPrefixRef)\n    const rtlEnabledRef = useRtl('Row', mergedRtlRef, mergedClsPrefixRef)\n    const verticalGutterRef = useMemo(() => {\n      const { gutter } = props\n      if (Array.isArray(gutter)) {\n        return gutter[1] || 0\n      }\n      return 0\n    })\n    const horizontalGutterRef = useMemo(() => {\n      const { gutter } = props\n      if (Array.isArray(gutter)) {\n        return gutter[0]\n      }\n      return Number(gutter)\n    })\n    provide(rowInjectionKey, {\n      mergedClsPrefixRef,\n      gutterRef: toRef(props, 'gutter'),\n      verticalGutterRef,\n      horizontalGutterRef\n    })\n    return {\n      mergedClsPrefix: mergedClsPrefixRef,\n      rtlEnabled: rtlEnabledRef,\n      styleMargin: useMemo(\n        () =>\n          `-${formatLength(verticalGutterRef.value, {\n            c: 0.5\n          })} -${formatLength(horizontalGutterRef.value, { c: 0.5 })}`\n      ),\n      styleWidth: useMemo(\n        () => `calc(100% + ${formatLength(horizontalGutterRef.value)})`\n      )\n    }\n  },\n  render() {\n    return (\n      <div\n        class={[\n          `${this.mergedClsPrefix}-row`,\n          this.rtlEnabled && `${this.mergedClsPrefix}-row--rtl`\n        ]}\n        style={{\n          margin: this.styleMargin,\n          width: this.styleWidth,\n          alignItems: this.alignItems,\n          justifyContent: this.justifyContent\n        }}\n      >\n        {this.$slots}\n      </div>\n    )\n  }\n})\n"
  },
  {
    "path": "src/legacy-grid/src/interface.ts",
    "content": "export type Span\n  = | 1\n    | 2\n    | 3\n    | 4\n    | 5\n    | 6\n    | 7\n    | 8\n    | 9\n    | 10\n    | 11\n    | 12\n    | 13\n    | 14\n    | 15\n    | 16\n    | 17\n    | 18\n    | 19\n    | 20\n    | 21\n    | 22\n    | 23\n    | 24\n    | '1'\n    | '2'\n    | '3'\n    | '4'\n    | '5'\n    | '6'\n    | '7'\n    | '8'\n    | '9'\n    | '10'\n    | '11'\n    | '12'\n    | '13'\n    | '14'\n    | '15'\n    | '16'\n    | '17'\n    | '18'\n    | '19'\n    | '20'\n    | '21'\n    | '22'\n    | '23'\n    | '24'\n"
  },
  {
    "path": "src/legacy-grid/src/styles/index.cssr.ts",
    "content": "import { repeat } from 'seemly'\nimport { c, cB, cE, cM } from '../../../_utils/cssr'\n\nconst positionStyles = repeat(24, null)\n  .map((_, index) => {\n    const prefixIndex = index + 1\n    const percent = `calc(100% / 24 * ${prefixIndex})`\n    return [\n      cM(`${prefixIndex}-span`, {\n        width: percent\n      }),\n      cM(`${prefixIndex}-offset`, {\n        marginLeft: percent\n      }),\n      cM(`${prefixIndex}-push`, {\n        left: percent\n      }),\n      cM(`${prefixIndex}-pull`, {\n        right: percent\n      })\n    ]\n  })\n\nexport default c([\n  cB('row', {\n    width: '100%',\n    display: 'flex',\n    flexWrap: 'wrap'\n  }),\n  cB('col', {\n    verticalAlign: 'top',\n    boxSizing: 'border-box',\n    display: 'inline-block',\n    position: 'relative',\n    zIndex: 'auto'\n  }, [\n    cE('box', {\n      position: 'relative',\n      zIndex: 'auto',\n      width: '100%',\n      height: '100%'\n    }),\n    positionStyles\n  ])\n])\n"
  },
  {
    "path": "src/legacy-grid/src/styles/rtl.cssr.ts",
    "content": "import { repeat } from 'seemly'\nimport { cB, cM } from '../../../_utils/cssr'\n\nconst positionStyles = repeat(24, null)\n  .map((_, index) => {\n    const prefixIndex = index + 1\n    const percent = `calc(100% / 24 * ${prefixIndex})`\n    return [\n      cM(`${prefixIndex}-span`, {\n        width: percent\n      }),\n      cM(`${prefixIndex}-offset`, {\n        marginLeft: percent\n      }),\n      cM(`${prefixIndex}-push`, {\n        right: percent,\n        left: 'unset'\n      }),\n      cM(`${prefixIndex}-pull`, {\n        left: percent,\n        right: 'unset'\n      })\n    ]\n  })\n\nexport default cB('row', [\n  cM('rtl', `\n    direction: rtl;\n  `, [\n    cB('col', positionStyles)\n  ])\n])\n"
  },
  {
    "path": "src/legacy-grid/styles/dark.ts",
    "content": "import type { Theme } from '../../_mixins'\nimport { commonDark } from '../../_styles/common'\n\nconst rowDark: Theme<'Row'> = {\n  name: 'Row',\n  common: commonDark\n}\n\nexport default rowDark\nexport type RowTheme = typeof rowDark\n"
  },
  {
    "path": "src/legacy-grid/styles/index.ts",
    "content": "export { default as rowDark } from './dark'\nexport { default as rowLight } from './light'\nexport type { RowTheme } from './light'\nexport { rowRtl } from './rtl'\n"
  },
  {
    "path": "src/legacy-grid/styles/light.ts",
    "content": "import type { Theme } from '../../_mixins'\nimport { commonLight } from '../../_styles/common'\n\nconst rowLight: Theme<'Row'> = {\n  name: 'Row',\n  common: commonLight\n}\n\nexport default rowLight\nexport type RowTheme = typeof rowLight\n"
  },
  {
    "path": "src/legacy-grid/styles/rtl.ts",
    "content": "import type { RtlItem } from '../../config-provider/src/internal-interface'\nimport rtlStyle from '../src/styles/rtl.cssr'\n\nexport const rowRtl: RtlItem = {\n  name: 'Row',\n  style: rtlStyle\n}\n"
  },
  {
    "path": "src/legacy-grid/tests/Grid.spec.tsx",
    "content": "import { mount } from '@vue/test-utils'\nimport { defineComponent, h } from 'vue'\nimport { NCol, NRow } from '../index'\n\ndescribe('n-grid', () => {\n  it('should work with import on demand', () => {\n    mount(\n      defineComponent({\n        render() {\n          return (\n            <NRow>\n              {{\n                default: () => [<NCol />]\n              }}\n            </NRow>\n          )\n        }\n      })\n    )\n  })\n})\n"
  },
  {
    "path": "src/legacy-grid/tests/server.spec.tsx",
    "content": "import { setup } from '@css-render/vue3-ssr'\nimport { renderToString } from '@vue/server-renderer'\n/**\n * @vitest-environment node\n */\nimport { createSSRApp, h } from 'vue'\nimport { NCol, NRow } from '../..'\n\ndescribe('server side rendering', () => {\n  it('works', async () => {\n    const app = createSSRApp(() => (\n      <NRow>\n        {{\n          default: () => <NCol />\n        }}\n      </NRow>\n    ))\n    setup(app)\n    try {\n      await renderToString(app)\n    }\n    catch (e) {\n      expect(e).not.toBeTruthy()\n    }\n  })\n})\n"
  },
  {
    "path": "src/legacy-transfer/demos/enUS/basic.demo.vue",
    "content": "<markdown>\n# Basic\n\nBasic example of the Transfer component. If you have tons of data, see below for virtualized list.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nfunction createOptions() {\n  return Array.from({ length: 100 }).map((v, i) => ({\n    label: `Option ${i}`,\n    value: i,\n    disabled: i % 5 === 0\n  }))\n}\n\nfunction createValues() {\n  return Array.from({ length: 50 }).map((v, i) => i)\n}\n\nconst options = createOptions()\nconst value = ref(createValues())\n</script>\n\n<template>\n  <n-legacy-transfer v-model:value=\"value\" :options=\"options\" />\n</template>\n"
  },
  {
    "path": "src/legacy-transfer/demos/enUS/filterable.demo.vue",
    "content": "<markdown>\n# Filterable\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nfunction createOptions() {\n  return Array.from({ length: 100 }).map((v, i) => ({\n    label: `Option ${i}`,\n    value: i,\n    disabled: i % 5 === 0\n  }))\n}\n\nfunction createValues() {\n  return Array.from({ length: 50 }).map((v, i) => i)\n}\n\nconst options = createOptions()\nconst value = ref(createValues())\n</script>\n\n<template>\n  <n-legacy-transfer\n    v-model:value=\"value\"\n    virtual-scroll\n    :options=\"options\"\n    filterable\n  />\n</template>\n"
  },
  {
    "path": "src/legacy-transfer/demos/enUS/index.demo-entry.md",
    "content": "# Legacy Transfer\n\n<!--single-column-->\n\n<n-alert title=\"Warning\" type=\"warning\" :bordered=\"false\">\n  The transfer component is deprecated. It won't have any new feature and will be removed in the next major version. It's recommended to use new  <router-link to=\"transfer\" custom v-slot=\"{ href, navigate }\">\n    <n-a :href=\"href\" @click=\"navigate\">Transfer</n-a>\n  </router-link>.\n</n-alert>\n\nLeft, right, right, left... I'm a simple man, and I can play this all day.\n\n## Demos\n\n```demo\nbasic.vue\nlarge-data.vue\nsize.vue\nfilterable.vue\n```\n\n## API\n\n### Transfer Props\n\n| Name | Type | Default | Description |\n| --- | --- | --- | --- |\n| default-value | `Array<string \\| number> \\| null` | `null` | Default value. |\n| disabled | `boolean` | `true` | Disabled state. |\n| filterable | `boolean` | `false` | Filterable state. |\n| filter | `function` | `(pattern: string, option: TransferOption, from: 'source' \\| 'target') => boolean` | A basic label string match function. |\n| options | `TransferOption[]` | `[]` | For configuration options, see the TransferOption Type below. |\n| size | `'small' \\| 'medium' \\| 'large'` | `'medium'` | Size. |\n| source-filter-placeholder | `string` | `undefined` | Placeholder for the source items search box. |\n| source-title | `string` | `'Source'` | Source items title. |\n| target-filter-placeholder | `string` | `undefined` | Placeholder for the target items search box. |\n| target-title | `string` | `'Target'` | Target items title. |\n| value | `Array<string \\| number> \\| null` | `undefined` | Value when being set manually. |\n| on-update:value | `(value: Array<string \\| number>) => void` | `undefined` | Callback when the value changes. |\n| virtual-scroll | `boolean` | `false` | Enable virtual scrolling. |\n\n#### TransferOption Type\n\n| Property | Type               | Description                    |\n| -------- | ------------------ | ------------------------------ |\n| label    | `string`           | The option's label to display. |\n| value    | `string \\| number` | The option's unique value.     |\n| disabled | `boolean`          | The option's disabled state.   |\n"
  },
  {
    "path": "src/legacy-transfer/demos/enUS/large-data.demo.vue",
    "content": "<markdown>\n# Large Data\n\nIf you have tons of data, you may need to speed the transfer up! Set `virtual-scroll` on transfer to use a blazing fast transfer (which turns the ridiculous animation off).\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nfunction createOptions() {\n  return Array.from({ length: 42000 }).map((v, i) => ({\n    label: `Option${i}`,\n    value: i,\n    disabled: i % 5 === 0\n  }))\n}\n\nfunction createValues() {\n  return Array.from({ length: 50 }).map((v, i) => i)\n}\n\nconst options = createOptions()\nconst value = ref(createValues())\n</script>\n\n<template>\n  <n-legacy-transfer v-model:value=\"value\" :options=\"options\" virtual-scroll />\n</template>\n"
  },
  {
    "path": "src/legacy-transfer/demos/enUS/size.demo.vue",
    "content": "<markdown>\n# Size\n\nMixing sizes does not look harmonious.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nfunction createOptions() {\n  return Array.from({ length: 100 }).map((v, i) => ({\n    label: `Option ${i}`,\n    value: i,\n    disabled: i % 5 === 0\n  }))\n}\n\nfunction createValues() {\n  return Array.from({ length: 50 }).map((v, i) => i)\n}\n\nconst options = createOptions()\nconst value = ref(createValues())\n</script>\n\n<template>\n  <n-space vertical>\n    <n-legacy-transfer v-model:value=\"value\" :options=\"options\" size=\"small\" />\n    <n-legacy-transfer v-model:value=\"value\" :options=\"options\" size=\"large\" />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/legacy-transfer/demos/zhCN/basic.demo.vue",
    "content": "<markdown>\n# 基础用法\n\n穿梭框的基础用法。如果你有一大堆数据，看下一个例子。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nfunction createOptions() {\n  return Array.from({ length: 100 }).map((v, i) => ({\n    label: `选项 ${i}`,\n    value: i,\n    disabled: i % 5 === 0\n  }))\n}\n\nfunction createValues() {\n  return Array.from({ length: 50 }).map((v, i) => i)\n}\n\nconst options = createOptions()\nconst value = ref(createValues())\n</script>\n\n<template>\n  <n-legacy-transfer v-model:value=\"value\" :options=\"options\" />\n</template>\n"
  },
  {
    "path": "src/legacy-transfer/demos/zhCN/filterable.demo.vue",
    "content": "<markdown>\n# 可过滤\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nfunction createOptions() {\n  return Array.from({ length: 100 }).map((v, i) => ({\n    label: `选项 ${i}`,\n    value: i,\n    disabled: i % 5 === 0\n  }))\n}\n\nfunction createValues() {\n  return Array.from({ length: 50 }).map((v, i) => i)\n}\n\nconst options = createOptions()\nconst value = ref(createValues())\n</script>\n\n<template>\n  <n-legacy-transfer\n    v-model:value=\"value\"\n    virtual-scroll\n    :options=\"options\"\n    filterable\n  />\n</template>\n"
  },
  {
    "path": "src/legacy-transfer/demos/zhCN/index.demo-entry.md",
    "content": "# 旧版穿梭框 Legacy Transfer\n\n<!--single-column-->\n\n<n-alert title=\"警告\" type=\"warning\" :bordered=\"false\">\n  这个穿梭框组件已经被废弃，不会迭代任何新的功能，并将在下一个大版本中彻底移除。推荐使用新的 <router-link to=\"transfer\" custom v-slot=\"{ href, navigate }\">\n    <n-a :href=\"href\" @click=\"navigate\">穿梭框</n-a>\n  </router-link>。\n</n-alert>\n\n左、右、左、右...像我这么无聊的人能玩一整天。\n\n## 演示\n\n```demo\nbasic.vue\nlarge-data.vue\nsize.vue\nfilterable.vue\n```\n\n## API\n\n### Transfer Props\n\n| 名称 | 类型 | 默认值 | 说明 |\n| --- | --- | --- | --- |\n| default-value | `Array<string \\| number> \\| null` | `null` | 非受控模式下的默认值 |\n| disabled | `boolean` | `true` | 是否禁用 |\n| filterable | `boolean` | `false` | 是否可过滤 |\n| filter | `(pattern: string, option: TransferOption, from: 'source' \\| 'target') => boolean` | 一个简单的标签字符串匹配函数 | 搜索时使用的过滤函数 |\n| options | `TransferOption[]` | `[]` | 配置选项内容，详情见 TransferOption Type |\n| size | `'small' \\| 'medium' \\| 'large'` | `'medium'` | 尺寸 |\n| source-filter-placeholder | `string` | `undefined` | 源项搜索框中的占位符 |\n| source-title | `string` | `'源项'` | 源项标题 |\n| target-filter-placeholder | `string` | `undefined` | 目标项搜索框中的占位符 |\n| target-title | `string` | `'目标项'` | 目标项标题 |\n| value | `Array<string \\| number> \\| null` | `undefined` | 受控模式下的值 |\n| on-update:value | `(value: Array<string \\| number>) => void` | `undefined` | 值发生改变时的回调 |\n| virtual-scroll | `boolean` | `false` | 是否启用虚拟滚动 |\n\n#### TransferOption Type\n\n| 属性     | 类型               | 说明                     |\n| -------- | ------------------ | ------------------------ |\n| label    | `string`           | 选项中用以页面显示的名称 |\n| value    | `string \\| number` | 所有选项中唯一的 `value` |\n| disabled | `boolean`          | 是否禁用这个选项         |\n"
  },
  {
    "path": "src/legacy-transfer/demos/zhCN/large-data.demo.vue",
    "content": "<markdown>\n# 一大堆数据\n\n如果你有一大堆数据，你可能想让它快一点。设定 `virtual-scroll` 来使用一个飞快的穿梭框（会关掉那个傻乎乎的动画）。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nfunction createOptions() {\n  return Array.from({ length: 42000 }).map((v, i) => ({\n    label: `选项${i}`,\n    value: i,\n    disabled: i % 5 === 0\n  }))\n}\n\nfunction createValues() {\n  return Array.from({ length: 50 }).map((v, i) => i)\n}\n\nconst options = createOptions()\nconst value = ref(createValues())\n</script>\n\n<template>\n  <n-legacy-transfer v-model:value=\"value\" :options=\"options\" virtual-scroll />\n</template>\n"
  },
  {
    "path": "src/legacy-transfer/demos/zhCN/size.demo.vue",
    "content": "<markdown>\n# 尺寸\n\n太小太大好像都不怎么好看。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nfunction createOptions() {\n  return Array.from({ length: 100 }).map((v, i) => ({\n    label: `选项 ${i}`,\n    value: i,\n    disabled: i % 5 === 0\n  }))\n}\n\nfunction createValues() {\n  return Array.from({ length: 50 }).map((v, i) => i)\n}\n\nconst options = createOptions()\nconst value = ref(createValues())\n</script>\n\n<template>\n  <n-space vertical>\n    <n-legacy-transfer v-model:value=\"value\" :options=\"options\" size=\"small\" />\n    <n-legacy-transfer v-model:value=\"value\" :options=\"options\" size=\"large\" />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/legacy-transfer/index.ts",
    "content": "export type { Option as LegacyTransferOption } from './src/interface'\nexport {\n  transferProps as legacyTransferProps,\n  default as NLegacyTransfer\n} from './src/Transfer'\nexport type { transferProps as LegacyTransferProps } from './src/Transfer'\n"
  },
  {
    "path": "src/legacy-transfer/src/Transfer.tsx",
    "content": "import type { CSSProperties, PropType } from 'vue'\nimport type { ThemeProps } from '../../_mixins'\nimport type { ExtractPublicPropTypes, MaybeArray } from '../../_utils'\nimport type { LegacyTransferTheme } from '../styles'\nimport type { Filter, OnUpdateValue, Option, OptionValue } from './interface'\nimport { depx } from 'seemly'\nimport { useIsMounted } from 'vooks'\nimport { computed, defineComponent, h, provide, watchEffect } from 'vue'\nimport { NBaseIcon } from '../../_internal'\nimport { ChevronLeftIcon, ChevronRightIcon } from '../../_internal/icons'\nimport { useConfig, useFormItem, useLocale, useTheme } from '../../_mixins'\nimport { call, warnOnce } from '../../_utils'\nimport { createKey } from '../../_utils/cssr'\nimport { NButton } from '../../button'\nimport { legacyTransferLight } from '../styles'\nimport { transferInjectionKey } from './interface'\nimport style from './styles/index.cssr'\nimport NTransferFilter from './TransferFilter'\nimport NTransferHeader from './TransferHeader'\nimport NTransferList from './TransferList'\nimport { useTransferData } from './use-transfer-data'\n\nexport const transferProps = {\n  ...(useTheme.props as ThemeProps<LegacyTransferTheme>),\n  value: Array as PropType<OptionValue[] | null>,\n  defaultValue: {\n    type: Array as PropType<OptionValue[] | null>,\n    default: null\n  },\n  options: {\n    type: Array as PropType<Option[]>,\n    default: () => []\n  },\n  disabled: {\n    type: Boolean as PropType<boolean | undefined>,\n    default: undefined\n  },\n  virtualScroll: Boolean,\n  sourceTitle: String,\n  targetTitle: String,\n  filterable: Boolean,\n  sourceFilterPlaceholder: String,\n  targetFilterPlaceholder: String,\n  filter: {\n    type: Function as PropType<Filter>,\n    default: (pattern: string, option: Option) => {\n      if (!pattern)\n        return true\n      return ~`${option.label}`\n        .toLowerCase()\n        .indexOf(`${pattern}`.toLowerCase())\n    }\n  },\n  size: String as PropType<'small' | 'medium' | 'large'>,\n  'onUpdate:value': [Function, Array] as PropType<MaybeArray<OnUpdateValue>>,\n  onUpdateValue: [Function, Array] as PropType<MaybeArray<OnUpdateValue>>,\n  onChange: [Function, Array] as PropType<MaybeArray<OnUpdateValue>>\n} as const\n\nexport type TransferProps = ExtractPublicPropTypes<typeof transferProps>\n\nexport default defineComponent({\n  name: 'LegacyTransfer',\n  props: transferProps,\n  setup(props) {\n    if (__DEV__) {\n      watchEffect(() => {\n        if (props.onChange !== undefined) {\n          warnOnce(\n            'legacy-transfer',\n            '`on-change` is deprecated, please use `on-update:value` instead.'\n          )\n        }\n      })\n    }\n    const { mergedClsPrefixRef } = useConfig(props)\n    const themeRef = useTheme(\n      'LegacyTransfer',\n      '-legacy-transfer',\n      style,\n      legacyTransferLight,\n      props,\n      mergedClsPrefixRef\n    )\n    const formItem = useFormItem(props)\n    const { mergedSizeRef, mergedDisabledRef } = formItem\n    const itemSizeRef = computed(() => {\n      const { value: size } = mergedSizeRef\n      const {\n        self: { [createKey('itemHeight', size)]: itemSize }\n      } = themeRef.value\n      return depx(itemSize)\n    })\n    const {\n      uncontrolledValue: uncontrolledValueRef,\n      mergedValue: mergedValueRef,\n      avlSrcValueSet: avlSrcValueSetRef,\n      avlTgtValueSet: avlTgtValueSetRef,\n      tgtOpts: tgtOptsRef,\n      srcOpts: srcOptsRef,\n      filteredSrcOpts: filteredSrcOptsRef,\n      filteredTgtOpts: filteredTgtOptsRef,\n      srcCheckedValues: srcCheckedValuesRef,\n      tgtCheckedValues: tgtCheckedValuesRef,\n      srcCheckedStatus: srcCheckedStatusRef,\n      tgtCheckedStatus: tgtCheckedStatusRef,\n      srcPattern: srcPatternRef,\n      tgtPattern: tgtPatternRef,\n      isInputing: isInputingRef,\n      fromButtonDisabled: fromButtonDisabledRef,\n      toButtonDisabled: toButtonDisabledRef,\n      handleInputFocus,\n      handleInputBlur,\n      handleTgtFilterUpdateValue,\n      handleSrcFilterUpdateValue\n    } = useTransferData(props, mergedDisabledRef)\n    function doUpdateValue(value: OptionValue[]): void {\n      const {\n        onUpdateValue,\n        'onUpdate:value': _onUpdateValue,\n        onChange\n      } = props\n      const { nTriggerFormInput, nTriggerFormChange } = formItem\n      if (onUpdateValue)\n        call(onUpdateValue, value)\n      if (_onUpdateValue)\n        call(_onUpdateValue, value)\n      if (onChange)\n        call(onChange, value)\n      uncontrolledValueRef.value = value\n      nTriggerFormInput()\n      nTriggerFormChange()\n    }\n    function handleSrcHeaderCheck(): void {\n      const {\n        value: { checked, indeterminate }\n      } = srcCheckedStatusRef\n      if (indeterminate || checked) {\n        srcCheckedValuesRef.value = []\n      }\n      else {\n        srcCheckedValuesRef.value = Array.from(avlSrcValueSetRef.value)\n      }\n    }\n    function handleTgtHeaderCheck(): void {\n      const {\n        value: { checked, indeterminate }\n      } = tgtCheckedStatusRef\n      if (indeterminate || checked) {\n        tgtCheckedValuesRef.value = []\n      }\n      else {\n        tgtCheckedValuesRef.value = Array.from(avlTgtValueSetRef.value)\n      }\n    }\n    function handleTgtCheckboxClick(\n      checked: boolean,\n      optionValue: OptionValue\n    ): void {\n      if (checked) {\n        tgtCheckedValuesRef.value.push(optionValue)\n      }\n      else {\n        const index = tgtCheckedValuesRef.value.findIndex(\n          v => v === optionValue\n        )\n        if (~index) {\n          tgtCheckedValuesRef.value.splice(index, 1)\n        }\n      }\n    }\n    function handleSrcCheckboxClick(\n      checked: boolean,\n      optionValue: OptionValue\n    ): void {\n      if (checked) {\n        srcCheckedValuesRef.value.push(optionValue)\n      }\n      else {\n        const index = srcCheckedValuesRef.value.findIndex(\n          v => v === optionValue\n        )\n        if (~index) {\n          srcCheckedValuesRef.value.splice(index, 1)\n        }\n      }\n    }\n    function handleToTgtClick(): void {\n      doUpdateValue(\n        srcCheckedValuesRef.value.concat(mergedValueRef.value || [])\n      )\n      srcCheckedValuesRef.value = []\n    }\n    function handleToSrcClick(): void {\n      const tgtCheckedValueSet = new Set(tgtCheckedValuesRef.value)\n      doUpdateValue(\n        (mergedValueRef.value || []).filter(v => !tgtCheckedValueSet.has(v))\n      )\n      tgtCheckedValuesRef.value = []\n    }\n    provide(transferInjectionKey, {\n      mergedClsPrefixRef,\n      mergedSizeRef,\n      disabledRef: mergedDisabledRef,\n      mergedThemeRef: themeRef,\n      srcCheckedValuesRef,\n      tgtCheckedValuesRef,\n      srcOptsRef,\n      tgtOptsRef,\n      srcCheckedStatusRef,\n      tgtCheckedStatusRef,\n      handleSrcCheckboxClick,\n      handleTgtCheckboxClick\n    })\n    const { localeRef } = useLocale('LegacyTransfer')\n    return {\n      locale: localeRef,\n      mergedClsPrefix: mergedClsPrefixRef,\n      mergedDisabled: mergedDisabledRef,\n      itemSize: itemSizeRef,\n      isMounted: useIsMounted(),\n      isInputing: isInputingRef,\n      mergedTheme: themeRef,\n      filteredSrcOpts: filteredSrcOptsRef,\n      filteredTgtOpts: filteredTgtOptsRef,\n      srcPattern: srcPatternRef,\n      tgtPattern: tgtPatternRef,\n      toButtonDisabled: toButtonDisabledRef,\n      fromButtonDisabled: fromButtonDisabledRef,\n      handleSrcHeaderCheck,\n      handleTgtHeaderCheck,\n      handleToSrcClick,\n      handleToTgtClick,\n      handleInputFocus,\n      handleInputBlur,\n      handleTgtFilterUpdateValue,\n      handleSrcFilterUpdateValue,\n      cssVars: computed(() => {\n        const { value: size } = mergedSizeRef\n        const {\n          common: {\n            cubicBezierEaseInOut,\n            cubicBezierEaseIn,\n            cubicBezierEaseOut\n          },\n          self: {\n            width,\n            borderRadius,\n            borderColor,\n            listColor,\n            headerColor,\n            titleTextColor,\n            titleTextColorDisabled,\n            extraTextColor,\n            filterDividerColor,\n            itemTextColor,\n            itemColorPending,\n            itemTextColorDisabled,\n            extraFontSize,\n            titleFontWeight,\n            iconColor,\n            iconColorDisabled,\n            [createKey('fontSize', size)]: fontSize,\n            [createKey('itemHeight', size)]: itemHeight\n          }\n        } = themeRef.value\n        return {\n          '--n-bezier': cubicBezierEaseInOut,\n          '--n-bezier-ease-in': cubicBezierEaseIn,\n          '--n-bezier-ease-out': cubicBezierEaseOut,\n          '--n-border-color': borderColor,\n          '--n-border-radius': borderRadius,\n          '--n-extra-font-size': extraFontSize,\n          '--n-filter-divider-color': filterDividerColor,\n          '--n-font-size': fontSize,\n          '--n-header-color': headerColor,\n          '--n-header-extra-text-color': extraTextColor,\n          '--n-header-font-weight': titleFontWeight,\n          '--n-header-text-color': titleTextColor,\n          '--n-header-text-color-disabled': titleTextColorDisabled,\n          '--n-item-color-pending': itemColorPending,\n          '--n-item-height': itemHeight,\n          '--n-item-text-color': itemTextColor,\n          '--n-item-text-color-disabled': itemTextColorDisabled,\n          '--n-list-color': listColor,\n          '--n-width': width,\n          '--n-icon-color': iconColor,\n          '--n-icon-color-disabled': iconColorDisabled\n        }\n      })\n    }\n  },\n  render() {\n    const { mergedClsPrefix } = this\n    return (\n      <div\n        class={[\n          `${mergedClsPrefix}-legacy-transfer`,\n          this.mergedDisabled && `${mergedClsPrefix}-legacy-transfer--disabled`,\n          this.filterable && `${mergedClsPrefix}-legacy-transfer--filterable`\n        ]}\n        style={this.cssVars as CSSProperties}\n      >\n        <div class={`${mergedClsPrefix}-legacy-transfer-list`}>\n          <NTransferHeader\n            source\n            onChange={this.handleSrcHeaderCheck}\n            title={this.sourceTitle || this.locale.sourceTitle}\n          />\n          <div class={`${mergedClsPrefix}-legacy-transfer-list-body`}>\n            {this.filterable ? (\n              <NTransferFilter\n                onUpdateValue={this.handleSrcFilterUpdateValue}\n                value={this.srcPattern}\n                disabled={this.mergedDisabled}\n                placeholder={this.sourceFilterPlaceholder}\n                onFocus={this.handleInputFocus}\n                onBlur={this.handleInputBlur}\n              />\n            ) : null}\n            <div\n              class={`${mergedClsPrefix}-legacy-transfer-list-flex-container`}\n            >\n              <NTransferList\n                source\n                options={this.filteredSrcOpts}\n                disabled={this.mergedDisabled}\n                virtualScroll={this.virtualScroll}\n                isMounted={this.isMounted}\n                isInputing={this.isInputing}\n                itemSize={this.itemSize}\n              />\n            </div>\n          </div>\n          <div class={`${mergedClsPrefix}-legacy-transfer-list__border`} />\n        </div>\n        <div class={`${mergedClsPrefix}-legacy-transfer-gap`}>\n          <NButton\n            disabled={this.toButtonDisabled || this.mergedDisabled}\n            theme={this.mergedTheme.peers.Button}\n            themeOverrides={this.mergedTheme.peerOverrides.Button}\n            onClick={this.handleToTgtClick}\n          >\n            {{\n              icon: () => (\n                <NBaseIcon clsPrefix={mergedClsPrefix}>\n                  {{ default: () => <ChevronRightIcon /> }}\n                </NBaseIcon>\n              )\n            }}\n          </NButton>\n          <NButton\n            disabled={this.fromButtonDisabled || this.mergedDisabled}\n            theme={this.mergedTheme.peers.Button}\n            themeOverrides={this.mergedTheme.peerOverrides.Button}\n            onClick={this.handleToSrcClick}\n          >\n            {{\n              icon: () => (\n                <NBaseIcon clsPrefix={mergedClsPrefix}>\n                  {{ default: () => <ChevronLeftIcon /> }}\n                </NBaseIcon>\n              )\n            }}\n          </NButton>\n        </div>\n        <div class={`${mergedClsPrefix}-legacy-transfer-list`}>\n          <NTransferHeader\n            onChange={this.handleTgtHeaderCheck}\n            title={this.targetTitle || this.locale.targetTitle}\n          />\n          <div class={`${mergedClsPrefix}-legacy-transfer-list-body`}>\n            {this.filterable ? (\n              <NTransferFilter\n                onUpdateValue={this.handleTgtFilterUpdateValue}\n                value={this.tgtPattern}\n                disabled={this.mergedDisabled}\n                placeholder={this.targetFilterPlaceholder}\n                onFocus={this.handleInputFocus}\n                onBlur={this.handleInputBlur}\n              />\n            ) : null}\n            <div\n              class={`${mergedClsPrefix}-legacy-transfer-list-flex-container`}\n            >\n              <NTransferList\n                options={this.filteredTgtOpts}\n                disabled={this.mergedDisabled}\n                virtualScroll={this.virtualScroll}\n                isMounted={this.isMounted}\n                isInputing={this.isInputing}\n                itemSize={this.itemSize}\n              />\n            </div>\n          </div>\n          <div class={`${mergedClsPrefix}-legacy-transfer-list__border`} />\n        </div>\n      </div>\n    )\n  }\n})\n"
  },
  {
    "path": "src/legacy-transfer/src/TransferFilter.tsx",
    "content": "import type { PropType } from 'vue'\nimport { defineComponent, h, inject } from 'vue'\nimport { NBaseIcon } from '../../_internal'\nimport { SearchIcon } from '../../_internal/icons'\nimport { NInput } from '../../input'\nimport { transferInjectionKey } from './interface'\n\nexport default defineComponent({\n  name: 'TransferFilter',\n  props: {\n    value: String,\n    placeholder: String,\n    disabled: Boolean,\n    onFocus: {\n      type: Function as PropType<() => void>,\n      required: true\n    },\n    onBlur: {\n      type: Function as PropType<() => void>,\n      required: true\n    },\n    onUpdateValue: {\n      type: Function as PropType<(value: string | null) => void>,\n      required: true\n    }\n  },\n  setup() {\n    const { mergedThemeRef, mergedClsPrefixRef } = inject(transferInjectionKey)!\n    return {\n      mergedClsPrefix: mergedClsPrefixRef,\n      mergedTheme: mergedThemeRef\n    }\n  },\n  render() {\n    const { mergedTheme, mergedClsPrefix } = this\n    return (\n      <div class={`${mergedClsPrefix}-legacy-transfer-filter`}>\n        <NInput\n          value={this.value}\n          onUpdateValue={this.onUpdateValue}\n          disabled={this.disabled}\n          theme={mergedTheme.peers.Input}\n          themeOverrides={mergedTheme.peerOverrides.Input}\n          clearable\n          size=\"small\"\n          placeholder={this.placeholder}\n          onFocus={this.onFocus}\n          onBlur={this.onBlur}\n        >\n          {{\n            'clear-icon-placeholder': () => (\n              <NBaseIcon\n                clsPrefix={mergedClsPrefix}\n                class={`${mergedClsPrefix}-legacy-transfer-icon`}\n              >\n                {{ default: () => <SearchIcon /> }}\n              </NBaseIcon>\n            )\n          }}\n        </NInput>\n      </div>\n    )\n  }\n})\n"
  },
  {
    "path": "src/legacy-transfer/src/TransferHeader.tsx",
    "content": "import type { PropType } from 'vue'\nimport { computed, defineComponent, h, inject } from 'vue'\nimport { NCheckbox } from '../../checkbox'\nimport { transferInjectionKey } from './interface'\n\nexport default defineComponent({\n  name: 'TransferHeader',\n  props: {\n    source: {\n      type: Boolean,\n      default: false\n    },\n    onChange: {\n      type: Function as PropType<(value: boolean) => void>,\n      required: true\n    },\n    title: String\n  },\n  setup(props) {\n    const {\n      srcOptsRef,\n      tgtOptsRef,\n      srcCheckedStatusRef,\n      tgtCheckedStatusRef,\n      srcCheckedValuesRef,\n      tgtCheckedValuesRef,\n      mergedThemeRef,\n      disabledRef,\n      mergedClsPrefixRef\n    } = inject(transferInjectionKey)!\n    const checkboxPropsRef = computed(() => {\n      const { source } = props\n      if (source) {\n        return srcCheckedStatusRef.value\n      }\n      else {\n        return tgtCheckedStatusRef.value\n      }\n    })\n    return () => {\n      const { source } = props\n      const { value: checkboxProps } = checkboxPropsRef\n      const { value: mergedTheme } = mergedThemeRef\n      const { value: mergedClsPrefix } = mergedClsPrefixRef\n      return (\n        <div class={`${mergedClsPrefix}-legacy-transfer-list-header`}>\n          <div\n            class={`${mergedClsPrefix}-legacy-transfer-list-header__checkbox`}\n          >\n            <NCheckbox\n              theme={mergedTheme.peers.Checkbox}\n              themeOverrides={mergedTheme.peerOverrides.Checkbox}\n              checked={checkboxProps.checked}\n              indeterminate={checkboxProps.indeterminate}\n              disabled={checkboxProps.disabled || disabledRef.value}\n              onUpdateChecked={props.onChange}\n            />\n          </div>\n          <div class={`${mergedClsPrefix}-legacy-transfer-list-header__header`}>\n            {props.title}\n          </div>\n          <div class={`${mergedClsPrefix}-legacy-transfer-list-header__extra`}>\n            {source\n              ? srcCheckedValuesRef.value.length\n              : tgtCheckedValuesRef.value.length}\n            /\n            {source ? srcOptsRef.value.length : tgtOptsRef.value.length}\n          </div>\n        </div>\n      )\n    }\n  }\n})\n"
  },
  {
    "path": "src/legacy-transfer/src/TransferList.tsx",
    "content": "import type { PropType } from 'vue'\nimport type { VirtualListInst } from 'vueuc'\nimport type { ScrollbarInst } from '../../_internal'\nimport type { Option } from './interface'\nimport {\n  computed,\n  defineComponent,\n  Fragment,\n  h,\n  inject,\n  ref,\n  Transition,\n  TransitionGroup\n} from 'vue'\nimport { VirtualList } from 'vueuc'\nimport { NScrollbar } from '../../_internal'\nimport { useConfig } from '../../_mixins'\nimport { NEmpty } from '../../empty'\nimport { transferInjectionKey } from './interface'\nimport NTransferListItem from './TransferListItem'\n\nexport default defineComponent({\n  name: 'TransferList',\n  props: {\n    virtualScroll: {\n      type: Boolean,\n      required: true\n    },\n    itemSize: {\n      type: Number,\n      required: true\n    },\n    options: {\n      type: Array as PropType<Option[]>,\n      required: true\n    },\n    disabled: {\n      type: Boolean,\n      required: true\n    },\n    isMounted: {\n      type: Boolean,\n      required: true\n    },\n    isInputing: {\n      type: Boolean,\n      required: true\n    },\n    source: {\n      type: Boolean,\n      default: false\n    }\n  },\n  setup() {\n    const { mergedThemeRef, mergedClsPrefixRef } = inject(transferInjectionKey)!\n    const { mergedComponentPropsRef } = useConfig()\n    const scrollerInstRef = ref<ScrollbarInst | null>(null)\n    const vlInstRef = ref<VirtualListInst | null>(null)\n    const mergedRenderEmptyRef = computed(() => {\n      return mergedComponentPropsRef?.value?.Transfer?.renderEmpty\n    })\n    function syncVLScroller(): void {\n      scrollerInstRef.value?.sync()\n    }\n    function scrollContainer(): HTMLElement | null {\n      const { value } = vlInstRef\n      if (!value)\n        return null\n      const { listElRef } = value\n      return listElRef\n    }\n    function scrollContent(): HTMLElement | null {\n      const { value } = vlInstRef\n      if (!value)\n        return null\n      const { itemsElRef } = value\n      return itemsElRef\n    }\n    return {\n      mergedTheme: mergedThemeRef,\n      mergedClsPrefix: mergedClsPrefixRef,\n      mergedRenderEmpty: mergedRenderEmptyRef,\n      scrollerInstRef,\n      vlInstRef,\n      syncVLScroller,\n      scrollContainer,\n      scrollContent\n    }\n  },\n  render() {\n    const { mergedTheme, mergedClsPrefix, virtualScroll, syncVLScroller } = this\n    return (\n      <>\n        <NScrollbar\n          ref=\"scrollerInstRef\"\n          theme={mergedTheme.peers.Scrollbar}\n          themeOverrides={mergedTheme.peerOverrides.Scrollbar}\n          container={virtualScroll ? this.scrollContainer : undefined}\n          content={virtualScroll ? this.scrollContent : undefined}\n        >\n          {{\n            default: () =>\n              virtualScroll ? (\n                <VirtualList\n                  ref=\"vlInstRef\"\n                  style={{ height: '100%' }}\n                  class={`${mergedClsPrefix}-legacy-transfer-list-content`}\n                  items={this.options}\n                  itemSize={this.itemSize}\n                  showScrollbar={false}\n                  onResize={syncVLScroller}\n                  onScroll={syncVLScroller}\n                  keyField=\"value\"\n                >\n                  {{\n                    default: ({ item }: { item: Option }) => {\n                      const { source, disabled } = this\n                      return (\n                        <NTransferListItem\n                          source={source}\n                          key={item.value}\n                          value={item.value}\n                          disabled={item.disabled || disabled}\n                          label={item.label}\n                        />\n                      )\n                    }\n                  }}\n                </VirtualList>\n              ) : (\n                <div class={`${mergedClsPrefix}-legacy-transfer-list-content`}>\n                  <TransitionGroup\n                    name=\"item\"\n                    appear={this.isMounted}\n                    css={!this.isInputing}\n                  >\n                    {{\n                      default: () => {\n                        const { source, disabled } = this\n                        return this.options.map(option => (\n                          <NTransferListItem\n                            source={source}\n                            key={option.value}\n                            value={option.value}\n                            disabled={option.disabled || disabled}\n                            label={option.label}\n                          />\n                        ))\n                      }\n                    }}\n                  </TransitionGroup>\n                </div>\n              )\n          }}\n        </NScrollbar>\n        <Transition\n          name=\"fade-in-transition\"\n          appear={this.isMounted}\n          css={!this.isInputing}\n        >\n          {{\n            default: () =>\n              this.options.length\n                ? null\n                : this.mergedRenderEmpty?.() || (\n                  <NEmpty\n                    theme={mergedTheme.peers.Empty}\n                    themeOverrides={mergedTheme.peerOverrides.Empty}\n                  />\n                )\n          }}\n        </Transition>\n      </>\n    )\n  }\n})\n"
  },
  {
    "path": "src/legacy-transfer/src/TransferListItem.tsx",
    "content": "import { useMemo } from 'vooks'\nimport { defineComponent, h, inject } from 'vue'\nimport { getTitleAttribute } from '../../_utils'\nimport { NCheckbox } from '../../checkbox'\nimport { transferInjectionKey } from './interface'\n\nexport default defineComponent({\n  name: 'NTransferListItem',\n  props: {\n    source: {\n      type: Boolean,\n      default: false\n    },\n    label: {\n      type: String,\n      required: true\n    },\n    value: {\n      type: [String, Number],\n      required: true\n    },\n    disabled: {\n      type: Boolean,\n      default: false\n    }\n  },\n  setup(props) {\n    const { source } = props\n    const {\n      mergedClsPrefixRef,\n      mergedThemeRef,\n      srcCheckedValuesRef,\n      tgtCheckedValuesRef,\n      handleSrcCheckboxClick,\n      handleTgtCheckboxClick\n    } = inject(transferInjectionKey)!\n    const checkedRef = source\n      ? useMemo(() => srcCheckedValuesRef.value.includes(props.value))\n      : useMemo(() => tgtCheckedValuesRef.value.includes(props.value))\n    const handleClick = source\n      ? () => {\n          if (!props.disabled) {\n            handleSrcCheckboxClick(!checkedRef.value, props.value)\n          }\n        }\n      : () => {\n          if (!props.disabled) {\n            handleTgtCheckboxClick(!checkedRef.value, props.value)\n          }\n        }\n    return {\n      mergedClsPrefix: mergedClsPrefixRef,\n      mergedTheme: mergedThemeRef,\n      checked: checkedRef,\n      handleClick\n    }\n  },\n  render() {\n    const { disabled, mergedTheme, mergedClsPrefix, label, checked, source }\n      = this\n    return (\n      <div\n        class={[\n          `${mergedClsPrefix}-legacy-transfer-list-item`,\n          disabled && `${mergedClsPrefix}-legacy-transfer-list-item--disabled`,\n          source\n            ? `${mergedClsPrefix}-legacy-transfer-list-item--source`\n            : `${mergedClsPrefix}-legacy-transfer-list-item--target`\n        ]}\n        onClick={this.handleClick}\n      >\n        <div class={`${mergedClsPrefix}-legacy-transfer-list-item__checkbox`}>\n          <NCheckbox\n            theme={mergedTheme.peers.Checkbox}\n            themeOverrides={mergedTheme.peerOverrides.Checkbox}\n            disabled={disabled}\n            checked={checked}\n          />\n        </div>\n        <div\n          class={`${mergedClsPrefix}-legacy-transfer-list-item__label`}\n          title={getTitleAttribute(label)}\n        >\n          {label}\n        </div>\n      </div>\n    )\n  }\n})\n"
  },
  {
    "path": "src/legacy-transfer/src/interface.ts",
    "content": "import type { Ref } from 'vue'\nimport type { MergedTheme } from '../../_mixins'\nimport type { LegacyTransferTheme } from '../styles'\nimport { createInjectionKey } from '../../_utils'\n\nexport type OptionValue = string | number\nexport interface Option {\n  label: string\n  value: OptionValue\n  disabled?: boolean\n}\n\nexport interface CheckedStatus {\n  checked: boolean\n  indeterminate: boolean\n  disabled?: boolean\n}\n\nexport type Filter = (\n  pattern: string,\n  option: Option,\n  from: 'source' | 'target'\n) => boolean\n\nexport interface TransferInjection {\n  mergedClsPrefixRef: Ref<string>\n  mergedSizeRef: Ref<'small' | 'medium' | 'large'>\n  disabledRef: Ref<boolean>\n  mergedThemeRef: Ref<MergedTheme<LegacyTransferTheme>>\n  srcCheckedValuesRef: Ref<OptionValue[]>\n  tgtCheckedValuesRef: Ref<OptionValue[]>\n  srcOptsRef: Ref<Option[]>\n  tgtOptsRef: Ref<Option[]>\n  srcCheckedStatusRef: Ref<CheckedStatus>\n  tgtCheckedStatusRef: Ref<CheckedStatus>\n  handleSrcCheckboxClick: (checked: boolean, value: OptionValue) => void\n  handleTgtCheckboxClick: (checked: boolean, value: OptionValue) => void\n}\n\nexport const transferInjectionKey\n  = createInjectionKey<TransferInjection>('n-transfer')\n\nexport type OnUpdateValue = (value: OptionValue[]) => void\n"
  },
  {
    "path": "src/legacy-transfer/src/styles/index.cssr.ts",
    "content": "import { fadeInTransition } from '../../../_styles/transitions/fade-in.cssr'\nimport { c, cB, cE, cM, cNotM } from '../../../_utils/cssr'\n\nconst animation = c([\n  c('@keyframes legacy-transfer-slide-in-from-left', `\n    0% {\n      transform: translateX(-150%);\n    }\n    100% {\n      transform: translateX(0);\n    }\n  `),\n  c('@keyframes legacy-transfer-slide-out-to-right', `\n    0% {\n      transform: translateX(0);\n    }\n    100% {\n      transform: translateX(150%);\n    }\n  `),\n  c('@keyframes legacy-transfer-slide-in-from-right', `\n    0% {\n      transform: translateX(150%);\n    }\n    100% {\n      transform: translateX(0);\n    }\n  `),\n  c('@keyframes legacy-transfer-slide-out-to-left', `\n    0% {\n      transform: translateX(0);\n    }\n    100% {\n      transform: translateX(-150%);\n    }\n  `),\n  c('@keyframes legacy-transfer-height-collapse', `\n    0% {\n      max-height: var(--n-item-height);\n    }\n    100% {\n      max-height: 0;\n    }\n  `),\n  c('@keyframes legacy-transfer-height-expand', `\n    0% {\n      max-height: 0;\n    }\n    100% {\n      max-height: var(--n-item-height);\n    }\n  `)\n])\n\nexport default c([\n  cB('legacy-transfer', `\n    display: flex;\n    width: var(--n-width);\n    font-size: var(--n-font-size);\n    height: 240px;\n    display: flex;\n    flex-wrap: nowrap;\n  `, [\n    cB('legacy-transfer-icon', `\n      color: var(--n-icon-color);\n      transition: color .3s var(--n-bezier);\n    `),\n    cM('disabled', [\n      cB('legacy-transfer-icon', {\n        color: 'var(--n-icon-color-disabled)'\n      })\n    ]),\n    cB('legacy-transfer-list', `\n      height: inherit;\n      display: flex;\n      flex-direction: column;\n      background-clip: padding-box;\n      width: calc(50% - 36px);\n      position: relative;\n      transition: background-color .3s var(--n-bezier);\n      border-radius: var(--n-border-radius);\n      background-color: var(--n-list-color);\n    `, [\n      cE('border', `\n        border: 1px solid var(--n-border-color);\n        transition: border-color .3s var(--n-bezier);\n        pointer-events: none;\n        border-radius: inherit;\n        position: absolute;\n        left: 0;\n        right: 0;\n        top: 0;\n        bottom: 0;\n      `),\n      cB('legacy-transfer-list-header', `\n        height: calc(var(--n-item-height) + 4px);\n        box-sizing: border-box;\n        display: flex;\n        align-items: center;\n        background-clip: padding-box;\n        border-radius: inherit;\n        border-bottom-left-radius: 0;\n        border-bottom-right-radius: 0;\n        background-color: var(--n-header-color);\n        transition:\n          border-color .3s var(--n-bezier),\n          background-color .3s var(--n-bezier);\n      `, [\n        cE('checkbox', `\n          display: flex;\n          align-items: center;\n          position: relative;\n          padding: 0 9px 0 14px;\n        `),\n        cE('header', `\n          flex: 1;\n          line-height: 1;\n          font-weight: var(--n-header-font-weight);\n          transition: color .3s var(--n-bezier);\n          color: var(--n-header-text-color);\n        `, [\n          cM('disabled', {\n            color: 'var(--n-header-text-color-disabled)'\n          })\n        ]),\n        cE('extra', `\n          transition: color .3s var(--n-bezier);\n          font-size: var(--n-extra-font-size);\n          justify-self: flex-end;\n          margin-right: 14px;\n          white-space: nowrap;\n          color: var(--n-header-extra-text-color);\n        `)\n      ]),\n      cB('legacy-transfer-list-body', `\n        flex-basis: 0;\n        flex-grow: 1;\n        box-sizing: border-box;\n        position: relative;\n        display: flex;\n        flex-direction: column;\n        border-radius: inherit;\n        border-top-left-radius: 0;\n        border-top-right-radius: 0;\n      `, [\n        cB('legacy-transfer-filter', `\n          padding: 0 8px 8px 8px;\n          box-sizing: border-box;\n          background-color: var(--n-header-color);\n          transition:\n            border-color .3s var(--n-bezier),\n            background-color .3s var(--n-bezier);\n          border-bottom: 1px solid var(--n-filter-divider-color);\n        `),\n        cB('legacy-transfer-list-flex-container', `\n          flex: 1;\n          position: relative;\n        `, [\n          cB('scrollbar', `\n            position: absolute;\n            left: 0;\n            right: 0;\n            top: 0;\n            bottom: 0;\n            height: unset;\n          `, [\n            cB('scrollbar-content', {\n              width: '100%'\n            })\n          ]),\n          cB('empty', `\n            position: absolute;\n            left: 50%;\n            top: 50%;\n            transform: translateY(-50%) translateX(-50%);\n          `, [\n            fadeInTransition()\n          ]),\n          cB('legacy-transfer-list-content', `\n            padding: 0;\n            margin: 0;\n            position: relative;\n          `, [\n            cM('transition-disabled', [\n              cB('legacy-transfer-list-item', {\n                animation: 'none !important'\n              })\n            ]),\n            cB('legacy-transfer-list-item', `\n              height: var(--n-item-height);\n              max-height: var(--n-item-height);\n                transition:\n                  background-color .3s var(--n-bezier),\n                  color .3s var(--n-bezier);\n              position: relative;\n              cursor: pointer;\n              display: flex;\n              align-items: center;\n              color: var(--n-item-text-color);\n            `, [\n              cNotM('disabled', [\n                c('&:hover', {\n                  backgroundColor: 'var(--n-item-color-pending)'\n                })\n              ]),\n              cE('extra', `\n                text-overflow: ellipsis;\n                overflow: hidden;\n                white-space: nowrap;\n                padding-right: 4px;\n              `),\n              cE('checkbox', `\n                display: flex;\n                align-items: center;\n                position: relative;\n                padding: 0 9px 0 14px;\n              `),\n              cM('disabled', `\n                cursor: not-allowed\n                background-color: #0000;\n                color: var(--n-item-text-color-disabled);\n              `),\n              cM('source', {\n                animationFillMode: 'forwards'\n              }, [\n                c('&.item-enter-active', `\n                  transform: translateX(150%);\n                  animation-duration: .25s, .25s;\n                  animation-timing-function: var(--n-bezier), var(--n-bezier-ease-out);\n                  animation-delay: 0s, .25s;\n                  animation-name: legacy-transfer-height-expand, legacy-transfer-slide-in-from-right;\n                `),\n                c('&.item-leave-active', `\n                  transform: translateX(-150%);\n                  animation-duration: .25s, .25s;\n                  animation-timing-function: var(--n-bezier), var(--n-bezier-ease-in);\n                  animation-delay: .25s, 0s;\n                  animation-name: legacy-transfer-height-collapse, legacy-transfer-slide-out-to-right;\n                `)\n              ]),\n              cM('target', {\n                animationFillMode: 'forwards'\n              }, [\n                c('&.item-enter-active', `\n                  transform: translateX(-150%);\n                  animation-duration: .25s, .25s;\n                  animation-timing-function: var(--n-bezier), var(--n-bezier-ease-out);\n                  animation-delay: 0s, .25s;\n                  animation-name: legacy-transfer-height-expand, legacy-transfer-slide-in-from-left;\n                `),\n                c('&.item-leave-active', `\n                  transform: translateX(150%);\n                  animation-duration: .25s, .25s;\n                  animation-timing-function: var(--n-bezier), var(--n-bezier-ease-in);\n                  animation-delay: .25s, 0s;\n                  animation-name: legacy-transfer-height-collapse, legacy-transfer-slide-out-to-left;\n                `)\n              ])\n            ])\n          ])\n        ])\n      ])\n    ]),\n    cB('legacy-transfer-gap', {\n      width: '72px',\n      display: 'flex',\n      alignItems: 'center',\n      justifyContent: 'center',\n      flexDirection: 'column'\n    }),\n    cB('button', [\n      c('&:first-child', {\n        marginBottom: '12px'\n      })\n    ])\n  ]),\n  animation\n])\n"
  },
  {
    "path": "src/legacy-transfer/src/use-transfer-data.ts",
    "content": "import type { Ref } from 'vue'\nimport type { CheckedStatus, Filter, Option, OptionValue } from './interface'\nimport { useMemo, useMergedState } from 'vooks'\nimport { computed, ref, toRef } from 'vue'\n\ninterface UseTransferDataProps {\n  defaultValue: OptionValue[] | null\n  value?: OptionValue[] | null\n  options: Option[]\n  filterable: boolean\n  filter: Filter\n}\n\nexport function useTransferData(\n  props: UseTransferDataProps,\n  mergedDisabledRef: Ref<boolean>\n) {\n  const uncontrolledValueRef = ref(props.defaultValue)\n  const controlledValueRef = toRef(props, 'value')\n  const mergedValueRef = useMergedState(\n    controlledValueRef,\n    uncontrolledValueRef\n  )\n  const optMapRef = computed(() => {\n    const map = new Map()\n    ;(props.options || []).forEach(opt => map.set(opt.value, opt))\n    return map\n  })\n  const tgtValueSetRef = computed(() => new Set(mergedValueRef.value || []))\n  const srcOptsRef = computed(() =>\n    props.options.filter(option => !tgtValueSetRef.value.has(option.value))\n  )\n  const tgtOptsRef = computed(() => {\n    const optMap = optMapRef.value\n    return (mergedValueRef.value || []).map(v => optMap.get(v))\n  })\n  const srcPatternRef = ref('')\n  const tgtPatternRef = ref('')\n  const filteredSrcOptsRef = computed(() => {\n    if (!props.filterable)\n      return srcOptsRef.value\n    const { filter } = props\n    return srcOptsRef.value.filter(opt =>\n      filter(srcPatternRef.value, opt, 'source')\n    )\n  })\n  const filteredTgtOptsRef = computed(() => {\n    if (!props.filterable)\n      return tgtOptsRef.value\n    const { filter } = props\n    return tgtOptsRef.value.filter(opt =>\n      filter(tgtPatternRef.value, opt as Option, 'target')\n    )\n  })\n  const avlSrcValueSetRef = computed(\n    () =>\n      new Set(\n        filteredSrcOptsRef.value\n          .filter(opt => !opt.disabled)\n          .map(opt => opt.value)\n      )\n  )\n  const avlTgtValueSetRef = computed(\n    () =>\n      new Set(\n        filteredTgtOptsRef.value\n          .filter(opt => !opt.disabled)\n          .map(opt => opt.value)\n      )\n  )\n  const srcCheckedValuesRef = ref<OptionValue[]>([])\n  const tgtCheckedValuesRef = ref<OptionValue[]>([])\n  const srcCheckedStatusRef = computed<CheckedStatus>(() => {\n    const srcCheckedLength = srcCheckedValuesRef.value.filter(v =>\n      avlSrcValueSetRef.value.has(v)\n    ).length\n    const avlValueCount = avlSrcValueSetRef.value.size\n    if (avlValueCount === 0) {\n      return {\n        checked: false,\n        indeterminate: false,\n        disabled: true\n      }\n    }\n    else if (srcCheckedLength === 0) {\n      return {\n        checked: false,\n        indeterminate: false\n      }\n    }\n    else if (srcCheckedLength === avlValueCount) {\n      return {\n        checked: true,\n        indeterminate: false\n      }\n    }\n    else {\n      return {\n        checked: false,\n        indeterminate: true\n      }\n    }\n  })\n  const tgtCheckedStatusRef = computed(() => {\n    const tgtCheckedLength = tgtCheckedValuesRef.value.filter(v =>\n      avlTgtValueSetRef.value.has(v)\n    ).length\n    const avlValueCount = avlTgtValueSetRef.value.size\n    if (avlValueCount === 0) {\n      return {\n        checked: false,\n        indeterminate: false,\n        disabled: true\n      }\n    }\n    else if (tgtCheckedLength === 0) {\n      return {\n        checked: false,\n        indeterminate: false\n      }\n    }\n    else if (tgtCheckedLength === avlValueCount) {\n      return {\n        checked: true,\n        indeterminate: false\n      }\n    }\n    else {\n      return {\n        checked: false,\n        indeterminate: true\n      }\n    }\n  })\n  const fromButtonDisabledRef = useMemo(() => {\n    if (mergedDisabledRef.value)\n      return true\n    return tgtCheckedValuesRef.value.length === 0\n  })\n  const toButtonDisabledRef = useMemo(() => {\n    if (mergedDisabledRef.value)\n      return true\n    return srcCheckedValuesRef.value.length === 0\n  })\n  const isInputingRef = ref(false)\n  function handleInputFocus(): void {\n    isInputingRef.value = true\n  }\n  function handleInputBlur(): void {\n    isInputingRef.value = false\n  }\n  function handleSrcFilterUpdateValue(value: string | null): void {\n    srcPatternRef.value = value ?? ''\n  }\n  function handleTgtFilterUpdateValue(value: string | null): void {\n    tgtPatternRef.value = value ?? ''\n  }\n  return {\n    uncontrolledValue: uncontrolledValueRef,\n    mergedValue: mergedValueRef,\n    avlSrcValueSet: avlSrcValueSetRef,\n    avlTgtValueSet: avlTgtValueSetRef,\n    tgtOpts: tgtOptsRef,\n    srcOpts: srcOptsRef,\n    filteredSrcOpts: filteredSrcOptsRef,\n    filteredTgtOpts: filteredTgtOptsRef,\n    srcCheckedValues: srcCheckedValuesRef,\n    tgtCheckedValues: tgtCheckedValuesRef,\n    srcCheckedStatus: srcCheckedStatusRef,\n    tgtCheckedStatus: tgtCheckedStatusRef,\n    srcPattern: srcPatternRef,\n    tgtPattern: tgtPatternRef,\n    isInputing: isInputingRef,\n    fromButtonDisabled: fromButtonDisabledRef,\n    toButtonDisabled: toButtonDisabledRef,\n    handleInputFocus,\n    handleInputBlur,\n    handleTgtFilterUpdateValue,\n    handleSrcFilterUpdateValue\n  }\n}\n"
  },
  {
    "path": "src/legacy-transfer/styles/_common.ts",
    "content": "export default {\n  extraFontSize: '12px',\n  width: '440px'\n}\n"
  },
  {
    "path": "src/legacy-transfer/styles/dark.ts",
    "content": "import type { TransferTheme } from './light'\nimport { scrollbarDark } from '../../_internal/scrollbar/styles'\nimport { commonDark } from '../../_styles/common'\nimport { buttonDark } from '../../button/styles'\nimport { checkboxDark } from '../../checkbox/styles'\nimport { emptyDark } from '../../empty/styles'\nimport { inputDark } from '../../input/styles'\nimport commonVariables from './_common'\n\nconst transferDark: TransferTheme = {\n  name: 'Transfer',\n  common: commonDark,\n  peers: {\n    Checkbox: checkboxDark,\n    Scrollbar: scrollbarDark,\n    Input: inputDark,\n    Empty: emptyDark,\n    Button: buttonDark\n  },\n  self(vars) {\n    const {\n      iconColorDisabled,\n      iconColor,\n      fontWeight,\n      fontSizeLarge,\n      fontSizeMedium,\n      fontSizeSmall,\n      heightLarge,\n      heightMedium,\n      heightSmall,\n      borderRadius,\n      inputColor,\n      tableHeaderColor,\n      textColor1,\n      textColorDisabled,\n      textColor2,\n      hoverColor\n    } = vars\n    return {\n      ...commonVariables,\n      itemHeightSmall: heightSmall,\n      itemHeightMedium: heightMedium,\n      itemHeightLarge: heightLarge,\n      fontSizeSmall,\n      fontSizeMedium,\n      fontSizeLarge,\n      borderRadius,\n      borderColor: '#0000',\n      listColor: inputColor,\n      headerColor: tableHeaderColor,\n      titleTextColor: textColor1,\n      titleTextColorDisabled: textColorDisabled,\n      extraTextColor: textColor2,\n      filterDividerColor: '#0000',\n      itemTextColor: textColor2,\n      itemTextColorDisabled: textColorDisabled,\n      itemColorPending: hoverColor,\n      titleFontWeight: fontWeight,\n      iconColor,\n      iconColorDisabled\n    }\n  }\n}\n\nexport default transferDark\n"
  },
  {
    "path": "src/legacy-transfer/styles/index.ts",
    "content": "export { default as legacyTransferDark } from './dark'\nexport { default as legacyTransferLight } from './light'\nexport type {\n  TransferTheme as LegacyTransferTheme,\n  TransferThemeVars as LegacyTransferThemeVars\n} from './light'\n"
  },
  {
    "path": "src/legacy-transfer/styles/light.ts",
    "content": "import type { ThemeCommonVars } from '../../_styles/common'\nimport { composite } from 'seemly'\nimport { scrollbarLight } from '../../_internal/scrollbar/styles'\nimport { createTheme } from '../../_mixins'\nimport { commonLight } from '../../_styles/common'\nimport { buttonLight } from '../../button/styles'\nimport { checkboxLight } from '../../checkbox/styles'\nimport { emptyLight } from '../../empty/styles'\nimport { inputLight } from '../../input/styles'\nimport commonVariables from './_common'\n\nfunction self(vars: ThemeCommonVars) {\n  const {\n    fontWeight,\n    iconColorDisabled,\n    iconColor,\n    fontSizeLarge,\n    fontSizeMedium,\n    fontSizeSmall,\n    heightLarge,\n    heightMedium,\n    heightSmall,\n    borderRadius,\n    cardColor,\n    tableHeaderColor,\n    textColor1,\n    textColorDisabled,\n    textColor2,\n    borderColor,\n    hoverColor\n  } = vars\n  return {\n    ...commonVariables,\n    itemHeightSmall: heightSmall,\n    itemHeightMedium: heightMedium,\n    itemHeightLarge: heightLarge,\n    fontSizeSmall,\n    fontSizeMedium,\n    fontSizeLarge,\n    borderRadius,\n    borderColor,\n    listColor: cardColor,\n    headerColor: composite(cardColor, tableHeaderColor),\n    titleTextColor: textColor1,\n    titleTextColorDisabled: textColorDisabled,\n    extraTextColor: textColor2,\n    filterDividerColor: borderColor,\n    itemTextColor: textColor2,\n    itemTextColorDisabled: textColorDisabled,\n    itemColorPending: hoverColor,\n    titleFontWeight: fontWeight,\n    iconColor,\n    iconColorDisabled\n  }\n}\n\nexport type TransferThemeVars = ReturnType<typeof self>\n\nconst transferLight = createTheme({\n  name: 'Transfer',\n  common: commonLight,\n  peers: {\n    Checkbox: checkboxLight,\n    Scrollbar: scrollbarLight,\n    Input: inputLight,\n    Empty: emptyLight,\n    Button: buttonLight\n  },\n  self\n})\n\nexport default transferLight\nexport type TransferTheme = typeof transferLight\n"
  },
  {
    "path": "src/legacy-transfer/tests/Transfer.spec.ts",
    "content": "import { mount } from '@vue/test-utils'\nimport { sleep } from 'seemly'\nimport { NLegacyTransfer } from '../index'\n\ndescribe('n-legacy-transfer', () => {\n  it('should work with import on demand', () => {\n    mount(NLegacyTransfer)\n  })\n\n  it('should work with `disabled` prop', () => {\n    const wrapper = mount(NLegacyTransfer, { props: { disabled: true } })\n    expect(wrapper.find('.n-legacy-transfer').attributes('class')).toContain(\n      'n-legacy-transfer--disabled'\n    )\n    wrapper.unmount()\n  })\n\n  it('should work with `filterable` prop', () => {\n    const wrapper = mount(NLegacyTransfer, { props: { filterable: true } })\n    expect(wrapper.find('.n-legacy-transfer').attributes('class')).toContain(\n      'n-legacy-transfer--filterable'\n    )\n    wrapper.unmount()\n  })\n\n  it('should work with `filter` prop', async () => {\n    const options = [\n      {\n        label: 'test1',\n        value: 'test1'\n      }\n    ]\n    const onFilter = vi.fn()\n    const wrapper = mount(NLegacyTransfer, {\n      props: { filterable: true, filter: onFilter, options }\n    })\n    await wrapper.find('input').setValue('1')\n    await sleep(300)\n    expect(onFilter).toHaveBeenCalled()\n    wrapper.unmount()\n  })\n\n  it('should work with `size` prop', async () => {\n    ;(['small', 'medium', 'large'] as const).forEach((i) => {\n      const wrapper = mount(NLegacyTransfer, {\n        props: { size: i }\n      })\n      expect(\n        wrapper.find('.n-legacy-transfer').attributes('style')\n      ).toMatchSnapshot()\n      wrapper.unmount()\n    })\n  })\n\n  it('should work with `source-filter-placeholder`、`target-filter-placeholder` props', async () => {\n    const wrapper = mount(NLegacyTransfer, {\n      props: {\n        filterable: true,\n        'source-filter-placeholder': 'test-source',\n        'target-filter-placeholder': 'test-target'\n      }\n    })\n    expect(wrapper.findAll('input')[0].attributes('placeholder')).toBe(\n      'test-source'\n    )\n    expect(wrapper.findAll('input')[1].attributes('placeholder')).toBe(\n      'test-target'\n    )\n    wrapper.unmount()\n  })\n\n  it('should work with `source-title`、`target-title` props', async () => {\n    const wrapper = mount(NLegacyTransfer, {\n      props: {\n        'source-title': 'test-source',\n        'target-title': 'test-target'\n      }\n    })\n    expect(\n      wrapper.findAll('.n-legacy-transfer-list-header__header')[0].text()\n    ).toBe('test-source')\n    expect(\n      wrapper.findAll('.n-legacy-transfer-list-header__header')[1].text()\n    ).toBe('test-target')\n    wrapper.unmount()\n  })\n})\n"
  },
  {
    "path": "src/legacy-transfer/tests/__snapshots__/Transfer.spec.ts.snap",
    "content": "// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html\n\nexports[`n-legacy-transfer > should work with \\`size\\` prop 1`] = `\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-bezier-ease-in: cubic-bezier(.4, 0, 1, 1); --n-bezier-ease-out: cubic-bezier(0, 0, .2, 1); --n-border-color: rgb(224, 224, 230); --n-border-radius: 3px; --n-extra-font-size: 12px; --n-filter-divider-color: rgb(224, 224, 230); --n-font-size: 14px; --n-header-color: rgba(250, 250, 252, 1); --n-header-extra-text-color: rgb(51, 54, 57); --n-header-font-weight: 400; --n-header-text-color: rgb(31, 34, 37); --n-header-text-color-disabled: rgba(194, 194, 194, 1); --n-item-color-pending: rgb(243, 243, 245); --n-item-height: 28px; --n-item-text-color: rgb(51, 54, 57); --n-item-text-color-disabled: rgba(194, 194, 194, 1); --n-list-color: #fff; --n-width: 440px; --n-icon-color: rgba(194, 194, 194, 1); --n-icon-color-disabled: rgba(209, 209, 209, 1);\"`;\n\nexports[`n-legacy-transfer > should work with \\`size\\` prop 2`] = `\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-bezier-ease-in: cubic-bezier(.4, 0, 1, 1); --n-bezier-ease-out: cubic-bezier(0, 0, .2, 1); --n-border-color: rgb(224, 224, 230); --n-border-radius: 3px; --n-extra-font-size: 12px; --n-filter-divider-color: rgb(224, 224, 230); --n-font-size: 14px; --n-header-color: rgba(250, 250, 252, 1); --n-header-extra-text-color: rgb(51, 54, 57); --n-header-font-weight: 400; --n-header-text-color: rgb(31, 34, 37); --n-header-text-color-disabled: rgba(194, 194, 194, 1); --n-item-color-pending: rgb(243, 243, 245); --n-item-height: 34px; --n-item-text-color: rgb(51, 54, 57); --n-item-text-color-disabled: rgba(194, 194, 194, 1); --n-list-color: #fff; --n-width: 440px; --n-icon-color: rgba(194, 194, 194, 1); --n-icon-color-disabled: rgba(209, 209, 209, 1);\"`;\n\nexports[`n-legacy-transfer > should work with \\`size\\` prop 3`] = `\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-bezier-ease-in: cubic-bezier(.4, 0, 1, 1); --n-bezier-ease-out: cubic-bezier(0, 0, .2, 1); --n-border-color: rgb(224, 224, 230); --n-border-radius: 3px; --n-extra-font-size: 12px; --n-filter-divider-color: rgb(224, 224, 230); --n-font-size: 15px; --n-header-color: rgba(250, 250, 252, 1); --n-header-extra-text-color: rgb(51, 54, 57); --n-header-font-weight: 400; --n-header-text-color: rgb(31, 34, 37); --n-header-text-color-disabled: rgba(194, 194, 194, 1); --n-item-color-pending: rgb(243, 243, 245); --n-item-height: 40px; --n-item-text-color: rgb(51, 54, 57); --n-item-text-color-disabled: rgba(194, 194, 194, 1); --n-list-color: #fff; --n-width: 440px; --n-icon-color: rgba(194, 194, 194, 1); --n-icon-color-disabled: rgba(209, 209, 209, 1);\"`;\n"
  },
  {
    "path": "src/legacy-transfer/tests/server.spec.tsx",
    "content": "import { setup } from '@css-render/vue3-ssr'\nimport { renderToString } from '@vue/server-renderer'\n/**\n * @vitest-environment node\n */\nimport { createSSRApp, h } from 'vue'\nimport { NTransfer } from '../..'\n\ndescribe('server side rendering', () => {\n  it('works', async () => {\n    const app = createSSRApp(() => <NTransfer />)\n    setup(app)\n    try {\n      await renderToString(app)\n    }\n    catch (e) {\n      expect(e).not.toBeTruthy()\n    }\n  })\n})\n"
  },
  {
    "path": "src/list/demos/enUS/basic.demo.vue",
    "content": "<markdown>\n# Basic\n</markdown>\n\n<template>\n  <n-list>\n    <template #header>\n      hhh\n    </template>\n    <template #footer>\n      fff\n    </template>\n    <n-list-item>\n      <template #prefix>\n        <n-button>Prefix</n-button>\n      </template>\n      <template #suffix>\n        <n-button>Suffix</n-button>\n      </template>\n      <n-thing title=\"Thing\" title-extra=\"extra\" description=\"description\">\n        Biu<br>\n        Biu<br>\n        Biu<br>\n      </n-thing>\n    </n-list-item>\n    <n-list-item>\n      <n-thing title=\"Thing\" title-extra=\"extra\" description=\"description\" />\n    </n-list-item>\n  </n-list>\n</template>\n"
  },
  {
    "path": "src/list/demos/enUS/border.demo.vue",
    "content": "<markdown>\n# Border\n\nList can be bordered or unbordered.\n</markdown>\n\n<template>\n  <n-list bordered>\n    <template #header>\n      hhh\n    </template>\n    <template #footer>\n      fff\n    </template>\n    <n-list-item>\n      <template #prefix>\n        <n-button>Prefix</n-button>\n      </template>\n      <template #suffix>\n        <n-button>Suffix</n-button>\n      </template>\n      <n-thing title=\"Thing\" title-extra=\"extra\" description=\"description\">\n        Biu<br>\n        Biu<br>\n        Biu<br>\n      </n-thing>\n    </n-list-item>\n    <n-list-item>\n      <n-thing title=\"Thing\" title-extra=\"extra\" description=\"description\">\n        Biu<br>\n        Biu<br>\n        Biu<br>\n      </n-thing>\n      <template #suffix>\n        <n-button>Suffix</n-button>\n      </template>\n    </n-list-item>\n  </n-list>\n</template>\n"
  },
  {
    "path": "src/list/demos/enUS/hoverable.demo.vue",
    "content": "<markdown>\n# Hoverable\n</markdown>\n\n<template>\n  <n-list hoverable clickable>\n    <n-list-item>\n      <n-thing title=\"Better Late Than Never\" content-style=\"margin-top: 10px;\">\n        <template #description>\n          <n-space size=\"small\" style=\"margin-top: 4px\">\n            <n-tag :bordered=\"false\" type=\"info\" size=\"small\">\n              Tag A\n            </n-tag>\n            <n-tag :bordered=\"false\" type=\"info\" size=\"small\">\n              Tag B\n            </n-tag>\n          </n-space>\n        </template>\n        Lorem ipsum dolor sit amet,<br>\n        consectetur adipiscing elit,<br>\n        sed do eiusmod tempor incididunt<br>\n        ut labore et dolore magna aliqua.<br>\n        Ut enim ad minim veniam,<br>\n        quis nostrud exercitation ullamco\n      </n-thing>\n    </n-list-item>\n    <n-list-item>\n      <n-thing title=\"Lorem Ipsum\" content-style=\"margin-top: 10px;\">\n        <template #description>\n          <n-space size=\"small\" style=\"margin-top: 4px\">\n            <n-tag :bordered=\"false\" type=\"info\" size=\"small\">\n              Tag C\n            </n-tag>\n            <n-tag :bordered=\"false\" type=\"info\" size=\"small\">\n              Tag D\n            </n-tag>\n          </n-space>\n        </template>\n        Lorem ipsum dolor sit amet,<br>\n        consectetur adipiscing elit,<br>\n        sed do eiusmod tempor incididunt<br>\n        ut labore et dolore magna aliqua.<br>\n        Ut enim ad minim veniam,<br>\n        quis nostrud exercitation ullamco\n      </n-thing>\n    </n-list-item>\n  </n-list>\n</template>\n"
  },
  {
    "path": "src/list/demos/enUS/index.demo-entry.md",
    "content": "# List\n\nIt is hard to make it looks elegant. However things should be done.\n\n<!--single-column-->\n\n## Demos\n\n```demo\nbasic.vue\nhoverable.vue\nborder.vue\n```\n\n## API\n\n### List Props\n\n| Name | Type | Default | Description | Version |\n| --- | --- | --- | --- | --- |\n| bordered | `boolean` | `false` | Whether to show the border. |  |\n| clickable | `boolean` | `false` | Whether item has clickable style. | 2.32.2 |\n| hoverable | `boolean` | `false` | Whether item has hoverable style. | 2.32.2 |\n| show-divider | `boolean` | `true` | Whether to show item divider. | 2.32.2 |\n\n### List Slots\n\n| Name    | Parameters | Description                           |\n| ------- | ---------- | ------------------------------------- |\n| default | `()`       | The contents of the list.             |\n| footer  | `()`       | Content at the bottom of the list.    |\n| header  | `()`       | The contents of the head of the list. |\n\n### ListItem Slots\n\n| Name    | Parameters | Description                         |\n| ------- | ---------- | ----------------------------------- |\n| default | `()`       | The contents of the list item.      |\n| prefix  | `()`       | The first content of the list item. |\n| suffix  | `()`       | The end of the list item.           |\n"
  },
  {
    "path": "src/list/demos/zhCN/basic.demo.vue",
    "content": "<markdown>\n# 基础用法\n</markdown>\n\n<template>\n  <n-list>\n    <template #header>\n      hhh\n    </template>\n    <template #footer>\n      fff\n    </template>\n    <n-list-item>\n      <template #prefix>\n        <n-button>Prefix</n-button>\n      </template>\n      <template #suffix>\n        <n-button>Suffix</n-button>\n      </template>\n      <n-thing title=\"Thing\" title-extra=\"extra\" description=\"description\">\n        Biu<br>\n        Biu<br>\n        Biu<br>\n      </n-thing>\n    </n-list-item>\n    <n-list-item>\n      <n-thing title=\"Thing\" title-extra=\"extra\" description=\"description\" />\n    </n-list-item>\n  </n-list>\n</template>\n"
  },
  {
    "path": "src/list/demos/zhCN/border.demo.vue",
    "content": "<markdown>\n# 边框\n\nList 可以控制边框。\n</markdown>\n\n<template>\n  <n-list bordered>\n    <template #header>\n      hhh\n    </template>\n    <template #footer>\n      fff\n    </template>\n    <n-list-item>\n      <template #prefix>\n        <n-button>Prefix</n-button>\n      </template>\n      <template #suffix>\n        <n-button>Suffix</n-button>\n      </template>\n      <n-thing title=\"Thing\" title-extra=\"extra\" description=\"description\">\n        Biu<br>\n        Biu<br>\n        Biu<br>\n      </n-thing>\n    </n-list-item>\n    <n-list-item>\n      <n-thing title=\"Thing\" title-extra=\"extra\" description=\"description\">\n        Biu<br>\n        Biu<br>\n        Biu<br>\n      </n-thing>\n      <template #suffix>\n        <n-button>Suffix</n-button>\n      </template>\n    </n-list-item>\n  </n-list>\n</template>\n"
  },
  {
    "path": "src/list/demos/zhCN/hoverable.demo.vue",
    "content": "<markdown>\n# 可悬浮\n</markdown>\n\n<template>\n  <n-list hoverable clickable>\n    <n-list-item>\n      <n-thing title=\"相见恨晚\" content-style=\"margin-top: 10px;\">\n        <template #description>\n          <n-space size=\"small\" style=\"margin-top: 4px\">\n            <n-tag :bordered=\"false\" type=\"info\" size=\"small\">\n              暑夜\n            </n-tag>\n            <n-tag :bordered=\"false\" type=\"info\" size=\"small\">\n              晚春\n            </n-tag>\n          </n-space>\n        </template>\n        奋勇呀然后休息呀<br>\n        完成你伟大的人生\n      </n-thing>\n    </n-list-item>\n    <n-list-item>\n      <n-thing title=\"他在时间门外\" content-style=\"margin-top: 10px;\">\n        <template #description>\n          <n-space size=\"small\" style=\"margin-top: 4px\">\n            <n-tag :bordered=\"false\" type=\"info\" size=\"small\">\n              环形公路\n            </n-tag>\n            <n-tag :bordered=\"false\" type=\"info\" size=\"small\">\n              潜水艇司机\n            </n-tag>\n          </n-space>\n        </template>\n        最新的打印机<br>\n        复制着彩色傀儡<br>\n        早上好我的罐头先生<br>\n        让他带你去被工厂敲击\n      </n-thing>\n    </n-list-item>\n  </n-list>\n</template>\n"
  },
  {
    "path": "src/list/demos/zhCN/index.demo-entry.md",
    "content": "# 列表 List\n\n想让列表看起来优雅真的挺难的。但是也不能不做这个组件啊。\n\n<!--single-column-->\n\n## 演示\n\n```demo\nbasic.vue\nhoverable.vue\nborder.vue\nrtl-debug.vue\n```\n\n## API\n\n### List Props\n\n| 名称         | 类型      | 默认值  | 说明                     | 版本   |\n| ------------ | --------- | ------- | ------------------------ | ------ |\n| bordered     | `boolean` | `false` | 是否显示边框             |        |\n| clickable    | `boolean` | `false` | 列表项是否有可点击样式   | 2.32.2 |\n| hoverable    | `boolean` | `false` | 列表项是否有悬浮样式     | 2.32.2 |\n| show-divider | `boolean` | `true`  | 是否显示标项之间的分割线 | 2.32.2 |\n\n### List Slots\n\n| 名称    | 参数 | 说明           |\n| ------- | ---- | -------------- |\n| default | `()` | 列表的内容     |\n| footer  | `()` | 列表底部的内容 |\n| header  | `()` | 列表头部的内容 |\n\n### ListItem Slots\n\n| 名称    | 参数 | 说明             |\n| ------- | ---- | ---------------- |\n| default | `()` | 列表项的内容     |\n| prefix  | `()` | 列表项的首部内容 |\n| suffix  | `()` | 列表项的尾部内容 |\n"
  },
  {
    "path": "src/list/demos/zhCN/rtl-debug.demo.vue",
    "content": "<markdown>\n# Rtl Debug\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { unstableListRtl } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst rtlEnabled = ref(false)\nconst rtlStyles = [unstableListRtl]\n</script>\n\n<template>\n  <n-space vertical>\n    <n-space><n-switch v-model:value=\"rtlEnabled\" />Rtl</n-space>\n    <n-config-provider :rtl=\"rtlEnabled ? rtlStyles : undefined\">\n      <n-list bordered>\n        <template #header>\n          hhh\n        </template>\n        <template #footer>\n          fff\n        </template>\n        <n-list-item>\n          <template #prefix>\n            <n-button>Prefix</n-button>\n          </template>\n          <template #suffix>\n            <n-button>Suffix</n-button>\n          </template>\n          <n-thing title=\"Thing\" title-extra=\"extra\" description=\"description\">\n            Biu<br>\n            Biu<br>\n            Biu<br>\n          </n-thing>\n        </n-list-item>\n        <n-list-item>\n          <n-thing\n            title=\"Thing\"\n            title-extra=\"extra\"\n            description=\"description\"\n          />\n        </n-list-item>\n      </n-list>\n    </n-config-provider>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/list/index.ts",
    "content": "export { listProps, default as NList } from './src/List'\nexport type { ListProps, ListSlots } from './src/List'\nexport { default as NListItem } from './src/ListItem'\nexport type { ListItemSlots } from './src/ListItem'\n"
  },
  {
    "path": "src/list/src/List.tsx",
    "content": "import type { CSSProperties, PropType, Ref, SlotsType, VNode } from 'vue'\nimport type { ThemeProps } from '../../_mixins'\nimport type { ExtractPublicPropTypes } from '../../_utils'\nimport type { ListTheme } from '../styles'\nimport { computed, defineComponent, h, provide, toRef } from 'vue'\nimport { useConfig, useRtl, useTheme, useThemeClass } from '../../_mixins'\nimport { createInjectionKey } from '../../_utils'\nimport { listLight } from '../styles'\nimport style from './styles/index.cssr'\n\nexport const listProps = {\n  ...(useTheme.props as ThemeProps<ListTheme>),\n  size: {\n    type: String as PropType<'small' | 'medium' | 'large'>,\n    default: 'medium'\n  },\n  bordered: Boolean,\n  clickable: Boolean,\n  hoverable: Boolean,\n  showDivider: {\n    type: Boolean,\n    default: true\n  }\n}\n\nexport type ListProps = ExtractPublicPropTypes<typeof listProps>\n\nexport interface ListSlots {\n  default?: () => VNode[]\n  footer?: () => VNode[]\n  header?: () => VNode[]\n}\n\ninterface ListInjection {\n  showDividerRef: Ref<boolean>\n  mergedClsPrefixRef: Ref<string>\n}\n\nexport const listInjectionKey = createInjectionKey<ListInjection>('n-list')\n\nexport default defineComponent({\n  name: 'List',\n  props: listProps,\n  slots: Object as SlotsType<ListSlots>,\n  setup(props) {\n    const { mergedClsPrefixRef, inlineThemeDisabled, mergedRtlRef }\n      = useConfig(props)\n    const rtlEnabledRef = useRtl('List', mergedRtlRef, mergedClsPrefixRef)\n    const themeRef = useTheme(\n      'List',\n      '-list',\n      style,\n      listLight,\n      props,\n      mergedClsPrefixRef\n    )\n    provide(listInjectionKey, {\n      showDividerRef: toRef(props, 'showDivider'),\n      mergedClsPrefixRef\n    })\n    const cssVarsRef = computed(() => {\n      const {\n        common: { cubicBezierEaseInOut },\n        self: {\n          fontSize,\n          textColor,\n          color,\n          colorModal,\n          colorPopover,\n          borderColor,\n          borderColorModal,\n          borderColorPopover,\n          borderRadius,\n          colorHover,\n          colorHoverModal,\n          colorHoverPopover\n        }\n      } = themeRef.value\n      return {\n        '--n-font-size': fontSize,\n        '--n-bezier': cubicBezierEaseInOut,\n        '--n-text-color': textColor,\n        '--n-color': color,\n        '--n-border-radius': borderRadius,\n        '--n-border-color': borderColor,\n        '--n-border-color-modal': borderColorModal,\n        '--n-border-color-popover': borderColorPopover,\n        '--n-color-modal': colorModal,\n        '--n-color-popover': colorPopover,\n        '--n-color-hover': colorHover,\n        '--n-color-hover-modal': colorHoverModal,\n        '--n-color-hover-popover': colorHoverPopover\n      }\n    })\n    const themeClassHandle = inlineThemeDisabled\n      ? useThemeClass('list', undefined, cssVarsRef, props)\n      : undefined\n\n    return {\n      mergedClsPrefix: mergedClsPrefixRef,\n      rtlEnabled: rtlEnabledRef,\n      cssVars: inlineThemeDisabled ? undefined : cssVarsRef,\n      themeClass: themeClassHandle?.themeClass,\n      onRender: themeClassHandle?.onRender\n    }\n  },\n  render() {\n    const { $slots, mergedClsPrefix, onRender } = this\n    onRender?.()\n    return (\n      <ul\n        class={[\n          `${mergedClsPrefix}-list`,\n          this.rtlEnabled && `${mergedClsPrefix}-list--rtl`,\n          this.bordered && `${mergedClsPrefix}-list--bordered`,\n          this.showDivider && `${mergedClsPrefix}-list--show-divider`,\n          this.hoverable && `${mergedClsPrefix}-list--hoverable`,\n          this.clickable && `${mergedClsPrefix}-list--clickable`,\n          this.themeClass\n        ]}\n        style={this.cssVars as CSSProperties}\n      >\n        {$slots.header ? (\n          <div class={`${mergedClsPrefix}-list__header`}>{$slots.header()}</div>\n        ) : null}\n        {$slots.default?.()}\n        {$slots.footer ? (\n          <div class={`${mergedClsPrefix}-list__footer`}>{$slots.footer()}</div>\n        ) : null}\n      </ul>\n    )\n  }\n})\n"
  },
  {
    "path": "src/list/src/ListItem.tsx",
    "content": "import type { SlotsType, VNode } from 'vue'\nimport { defineComponent, h, inject } from 'vue'\nimport { throwError } from '../../_utils'\nimport { listInjectionKey } from './List'\n\nexport interface ListItemSlots {\n  default?: () => VNode[]\n  prefix?: () => VNode[]\n  suffix?: () => VNode[]\n}\n\nexport default defineComponent({\n  name: 'ListItem',\n  slots: Object as SlotsType<ListItemSlots>,\n  setup() {\n    const listInjection = inject(listInjectionKey, null)\n    if (!listInjection) {\n      throwError('list-item', '`n-list-item` must be placed in `n-list`.')\n    }\n    return {\n      showDivider: listInjection.showDividerRef,\n      mergedClsPrefix: listInjection.mergedClsPrefixRef\n    }\n  },\n  render() {\n    const { $slots, mergedClsPrefix } = this\n    return (\n      <li class={`${mergedClsPrefix}-list-item`}>\n        {$slots.prefix ? (\n          <div class={`${mergedClsPrefix}-list-item__prefix`}>\n            {$slots.prefix()}\n          </div>\n        ) : null}\n        {$slots.default ? (\n          <div class={`${mergedClsPrefix}-list-item__main`}>{$slots}</div>\n        ) : null}\n        {$slots.suffix ? (\n          <div class={`${mergedClsPrefix}-list-item__suffix`}>\n            {$slots.suffix()}\n          </div>\n        ) : null}\n        {this.showDivider && (\n          <div class={`${mergedClsPrefix}-list-item__divider`} />\n        )}\n      </li>\n    )\n  }\n})\n"
  },
  {
    "path": "src/list/src/styles/index.cssr.ts",
    "content": "import { c, cB, cE, cM, insideModal, insidePopover } from '../../../_utils/cssr'\n\n// vars:\n// --n-font-size\n// --n-bezier\n// --n-text-color\n// --n-color\n// --n-color-hover\n// --n-border-radius\n// --n-border-color\n// --n-border-color-modal\n// --n-border-color-popover\n// --n-color-modal\n// --n-color-popover\n// --n-color-hover-modal\n// --n-color-hover-popover\nexport default c([\n  cB('list', `\n    --n-merged-border-color: var(--n-border-color);\n    --n-merged-color: var(--n-color);\n    --n-merged-color-hover: var(--n-color-hover);\n    margin: 0;\n    font-size: var(--n-font-size);\n    transition:\n      background-color .3s var(--n-bezier),\n      color .3s var(--n-bezier),\n      border-color .3s var(--n-bezier);\n    padding: 0;\n    list-style-type: none;\n    color: var(--n-text-color);\n    background-color: var(--n-merged-color);\n  `, [\n    cM('show-divider', [\n      cB('list-item', [\n        c('&:not(:last-child)', [\n          cE('divider', `\n            background-color: var(--n-merged-border-color);\n          `)\n        ])\n      ])\n    ]),\n    cM('clickable', [\n      cB('list-item', `\n        cursor: pointer;\n      `)\n    ]),\n    cM('bordered', `\n      border: 1px solid var(--n-merged-border-color);\n      border-radius: var(--n-border-radius);\n    `),\n    cM('hoverable', [\n      cB('list-item', `\n        border-radius: var(--n-border-radius);\n      `, [\n        c('&:hover', `\n          background-color: var(--n-merged-color-hover);\n        `, [\n          cE('divider', `\n            background-color: transparent;\n          `)\n        ])\n      ])\n    ]),\n    cM('bordered, hoverable', [\n      cB('list-item', `\n        padding: 12px 20px;\n      `),\n      cE('header, footer', `\n        padding: 12px 20px;\n      `)\n    ]),\n    cE('header, footer', `\n      padding: 12px 0;\n      box-sizing: border-box;\n      transition: border-color .3s var(--n-bezier);\n    `, [\n      c('&:not(:last-child)', `\n        border-bottom: 1px solid var(--n-merged-border-color);\n      `)\n    ]),\n    cB('list-item', `\n      position: relative;\n      padding: 12px 0;    \n      box-sizing: border-box;\n      display: flex;\n      flex-wrap: nowrap;\n      align-items: center;\n      transition:\n        background-color .3s var(--n-bezier),\n        border-color .3s var(--n-bezier);\n    `, [\n      cE('prefix', `\n        margin-right: 20px;\n        flex: 0;\n      `),\n      cE('suffix', `\n        margin-left: 20px;\n        flex: 0;\n      `),\n      cE('main', `\n        flex: 1;\n      `),\n      cE('divider', `\n        height: 1px;\n        position: absolute;\n        bottom: 0;\n        left: 0;\n        right: 0;\n        background-color: transparent;\n        transition: background-color .3s var(--n-bezier);\n        pointer-events: none;\n      `)\n    ])\n  ]),\n  insideModal(\n    cB('list', `\n      --n-merged-color-hover: var(--n-color-hover-modal);\n      --n-merged-color: var(--n-color-modal);\n      --n-merged-border-color: var(--n-border-color-modal);\n    `)\n  ),\n  insidePopover(\n    cB('list', `\n      --n-merged-color-hover: var(--n-color-hover-popover);\n      --n-merged-color: var(--n-color-popover);\n      --n-merged-border-color: var(--n-border-color-popover);\n    `)\n  )\n])\n"
  },
  {
    "path": "src/list/src/styles/rtl.cssr.ts",
    "content": "import { cB, cE, cM } from '../../../_utils/cssr'\n\nexport default cB('list', [\n  cM('rtl', `\n    direction: rtl;\n    text-align: right;\n  `, [\n    cB('list-item', [\n      cE('prefix', `\n        margin-right: 0;\n        margin-left: 20px;\n      `),\n      cE('suffix', `\n        margin-right: 20px;\n        margin-left: 0;\n      `)\n    ])\n  ])\n])\n"
  },
  {
    "path": "src/list/styles/dark.ts",
    "content": "import type { ListTheme } from './light'\nimport { commonDark } from '../../_styles/common'\nimport { self } from './light'\n\nconst listDark: ListTheme = {\n  name: 'List',\n  common: commonDark,\n  self\n}\n\nexport default listDark\n"
  },
  {
    "path": "src/list/styles/index.ts",
    "content": "export { default as listDark } from './dark'\nexport { default as listLight } from './light'\nexport type { ListTheme, ListThemeVars } from './light'\nexport { listRtl } from './rtl'\n"
  },
  {
    "path": "src/list/styles/light.ts",
    "content": "import type { Theme } from '../../_mixins'\nimport type { ThemeCommonVars } from '../../_styles/common'\nimport { composite } from 'seemly'\nimport { commonLight } from '../../_styles/common'\n\nexport function self(vars: ThemeCommonVars) {\n  const {\n    textColor2,\n    cardColor,\n    modalColor,\n    popoverColor,\n    dividerColor,\n    borderRadius,\n    fontSize,\n    hoverColor\n  } = vars\n  return {\n    textColor: textColor2,\n    color: cardColor,\n    colorHover: hoverColor,\n    colorModal: modalColor,\n    colorHoverModal: composite(modalColor, hoverColor),\n    colorPopover: popoverColor,\n    colorHoverPopover: composite(popoverColor, hoverColor),\n    borderColor: dividerColor,\n    borderColorModal: composite(modalColor, dividerColor),\n    borderColorPopover: composite(popoverColor, dividerColor),\n    borderRadius,\n    fontSize\n  }\n}\n\nexport type ListThemeVars = ReturnType<typeof self>\n\nconst listLight: Theme<'List', ListThemeVars> = {\n  name: 'List',\n  common: commonLight,\n  self\n}\n\nexport default listLight\nexport type ListTheme = typeof listLight\n"
  },
  {
    "path": "src/list/styles/rtl.ts",
    "content": "import type { RtlItem } from '../../config-provider/src/internal-interface'\nimport rtlStyle from '../src/styles/rtl.cssr'\n\nexport const listRtl: RtlItem = {\n  name: 'List',\n  style: rtlStyle\n}\n"
  },
  {
    "path": "src/list/tests/List.spec.ts",
    "content": "import { mount } from '@vue/test-utils'\nimport { h } from 'vue'\nimport { NList, NListItem } from '../index'\n\ndescribe('n-list', () => {\n  it('should work with import on demand', () => {\n    mount(NList)\n  })\n\n  it('should work with n-list slots', async () => {\n    const wrapper = mount(NList, {\n      slots: {\n        default: () => 'test default',\n        header: () => 'test header',\n        footer: () => 'test footer'\n      }\n    })\n    expect(wrapper.text()).toContain('test default')\n    expect(wrapper.find('.n-list__header').exists()).toBe(true)\n    expect(wrapper.find('.n-list__header').text()).toBe('test header')\n    expect(wrapper.find('.n-list__footer').exists()).toBe(true)\n    expect(wrapper.find('.n-list__footer').text()).toBe('test footer')\n    wrapper.unmount()\n  })\n\n  it('should work with n-list-item slots', async () => {\n    const wrapper = mount(NList, {\n      slots: {\n        default: () =>\n          h(NListItem, null, {\n            default: () => 'test default',\n            prefix: () => 'test prefix',\n            suffix: () => 'test suffix'\n          })\n      }\n    })\n    expect(wrapper.find('.n-list-item__main').exists()).toBe(true)\n    expect(wrapper.find('.n-list-item__main').text()).toBe('test default')\n    expect(wrapper.find('.n-list-item__prefix').exists()).toBe(true)\n    expect(wrapper.find('.n-list-item__prefix').text()).toBe('test prefix')\n    expect(wrapper.find('.n-list-item__suffix').exists()).toBe(true)\n    expect(wrapper.find('.n-list-item__suffix').text()).toBe('test suffix')\n    wrapper.unmount()\n  })\n\n  it('should work with `bordered` prop', async () => {\n    const wrapper = mount(NList, {\n      slots: {\n        default: () =>\n          h(NListItem, null, {\n            default: () => 'test'\n          })\n      }\n    })\n    expect(wrapper.find('.n-list').classes()).not.toContain('n-list--bordered')\n\n    await wrapper.setProps({ bordered: true })\n    expect(wrapper.find('.n-list').classes()).toContain('n-list--bordered')\n    wrapper.unmount()\n  })\n})\n"
  },
  {
    "path": "src/list/tests/server.spec.tsx",
    "content": "import { setup } from '@css-render/vue3-ssr'\nimport { renderToString } from '@vue/server-renderer'\n/**\n * @vitest-environment node\n */\nimport { createSSRApp, h } from 'vue'\nimport { NList } from '../..'\n\ndescribe('server side rendering', () => {\n  it('works', async () => {\n    const app = createSSRApp(() => <NList />)\n    setup(app)\n    try {\n      await renderToString(app)\n    }\n    catch (e) {\n      expect(e).not.toBeTruthy()\n    }\n  })\n})\n"
  },
  {
    "path": "src/loading-bar/demos/enUS/basic.demo.vue",
    "content": "<markdown>\n# Basic\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { useLoadingBar } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst loadingBar = useLoadingBar()\nconst disabled = ref(true)\n\nfunction handleStart() {\n  loadingBar.start()\n  disabled.value = false\n}\n\nfunction handleFinish() {\n  loadingBar.finish()\n  disabled.value = true\n}\n\nfunction handleError() {\n  disabled.value = true\n  loadingBar.error()\n}\n</script>\n\n<template>\n  <n-space>\n    <n-button @click=\"handleStart\">\n      start\n    </n-button>\n    <n-button :disabled=\"disabled\" @click=\"handleFinish\">\n      finish\n    </n-button>\n    <n-button @click=\"handleError\">\n      error\n    </n-button>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/loading-bar/demos/enUS/container.demo.vue",
    "content": "<markdown>\n# Use loading bar locally\n\nYou can set mount target of loading by `to` prop.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { NButton, NSpace, useLoadingBar } from 'naive-ui'\nimport { defineComponent, h, ref } from 'vue'\n\n// Define the LoadingBarTrigger component\nconst LoadingBarTrigger = defineComponent(() => {\n  const loadingBar = useLoadingBar()\n  return () => {\n    return h(NSpace, null, {\n      default: () => [\n        h(\n          NButton,\n          { onClick: () => loadingBar.start() },\n          { default: () => 'Start' }\n        ),\n        h(\n          NButton,\n          { onClick: () => loadingBar.finish() },\n          { default: () => 'Finish' }\n        )\n      ]\n    })\n  }\n})\n\nconst loadingBarTargetRef = ref<undefined | HTMLElement>(undefined)\n</script>\n\n<template>\n  <n-loading-bar-provider\n    :to=\"loadingBarTargetRef\"\n    container-style=\"position: absolute;\"\n  >\n    <div\n      ref=\"loadingBarTargetRef\"\n      style=\"\n        position: absolute;\n        top: 0;\n        right: 0;\n        bottom: 0;\n        left: 0;\n        border-radius: var(--n-border-radius);\n        overflow: hidden;\n        pointer-events: none;\n      \"\n    />\n    <LoadingBarTrigger />\n  </n-loading-bar-provider>\n</template>\n"
  },
  {
    "path": "src/loading-bar/demos/enUS/index.demo-entry.md",
    "content": "# Loading Bar\n\nA kind of good placebo for anxiety.\n\n<n-space vertical size=\"large\">\n<n-alert title=\"Prerequisite\" type=\"warning\" :bordered=\"false\">\n  If you want to use loading bar, you need to wrap the component where you call related methods inside <n-text code>n-loading-bar-provider</n-text> and inject <n-text code>loadingBar</n-text>.\n</n-alert>\nFor example:\n\n```html\n<!-- App.vue -->\n<n-loading-bar-provider>\n  <content />\n</n-loading-bar-provider>\n```\n\n```js\nimport { useLoadingBar } from 'naive-ui'\nimport { defineComponent } from 'vue'\n\n// content\nexport default defineComponent({\n  setup() {\n    const loadingBar = useLoadingBar()\n    return {\n      loading() {\n        loadingBar.start()\n      }\n    }\n  }\n})\n```\n\n</n-space>\n\n## Demos\n\n```demo\nbasic.vue\ncontainer.vue\n```\n\n## API\n\n### LoadingBarProvider Props\n\n| Name | Type | Default | Description | Version |\n| --- | --- | --- | --- | --- |\n| container-class | `string` | `undefined` | Class of the loading bar container. | 2.33.4 |\n| container-style | `string \\| object` | `undefined` | Style of the loading bar container. | 2.33.4 |\n| loading-bar-style | `{ loading?: string \\| object, error?: string \\| object }` | `undefined` | Style of the loading bar. |  |\n| to | `string \\| HTMLElement \\| false` | `undefined` | Mount target of loading bar. | 2.33.4 |\n\n### loadingBar Injection Methods\n\n| Name | Type | Description |\n| --- | --- | --- |\n| error | `() => void` | Callback function for loading bar error. |\n| finish | `() => void` | The callback function when the loading bar finishes loading. |\n| start | `() => void` | Callback function for loading bar to start loading. |\n"
  },
  {
    "path": "src/loading-bar/demos/zhCN/basic.demo.vue",
    "content": "<markdown>\n# 基础用法\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { useLoadingBar } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst loadingBar = useLoadingBar()\nconst disabled = ref(true)\n\nfunction handleStart() {\n  loadingBar.start()\n  disabled.value = false\n}\n\nfunction handleFinish() {\n  loadingBar.finish()\n  disabled.value = true\n}\n\nfunction handleError() {\n  disabled.value = true\n  loadingBar.error()\n}\n</script>\n\n<template>\n  <n-space>\n    <n-button @click=\"handleStart\">\n      开始\n    </n-button>\n    <n-button :disabled=\"disabled\" @click=\"handleFinish\">\n      结束\n    </n-button>\n    <n-button @click=\"handleError\">\n      报个错\n    </n-button>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/loading-bar/demos/zhCN/container.demo.vue",
    "content": "<markdown>\n# 在局部使用进度条\n\n你可以设定 `to` 来控制进度条的挂载位置\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { NButton, NSpace, useLoadingBar } from 'naive-ui'\nimport { defineComponent, h, ref } from 'vue'\n\n// 定义 LoadingBarTrigger 组件\nconst LoadingBarTrigger = defineComponent(() => {\n  const loadingBar = useLoadingBar()\n  return () => {\n    return h(NSpace, null, {\n      default: () => [\n        h(NButton, { onClick: () => loadingBar.start() }, () => 'Start'),\n        h(NButton, { onClick: () => loadingBar.finish() }, () => 'Finish')\n      ]\n    })\n  }\n})\n\nconst loadingBarTargetRef = ref<undefined | HTMLElement>(undefined)\n</script>\n\n<template>\n  <n-loading-bar-provider\n    :to=\"loadingBarTargetRef\"\n    container-style=\"position: absolute;\"\n  >\n    <div\n      ref=\"loadingBarTargetRef\"\n      style=\"\n        position: absolute;\n        top: 0;\n        right: 0;\n        bottom: 0;\n        left: 0;\n        border-radius: var(--n-border-radius);\n        overflow: hidden;\n        pointer-events: none;\n      \"\n    />\n    <LoadingBarTrigger />\n  </n-loading-bar-provider>\n</template>\n"
  },
  {
    "path": "src/loading-bar/demos/zhCN/index.demo-entry.md",
    "content": "# 加载条 Loading Bar\n\n焦虑的安慰剂，疗效尚可。\n\n<n-space vertical size=\"large\">\n<n-alert title=\"使用前提\" type=\"warning\" :bordered=\"false\">\n  如果你想使用加载条，你需要把调用其方法的组件放在 <n-text code>n-loading-bar-provider</n-text> 内部并且注入 <n-text code>loadingBar</n-text>。\n</n-alert>\n例如：\n\n```html\n<!-- App.vue -->\n<n-loading-bar-provider>\n  <content />\n</n-loading-bar-provider>\n```\n\n```js\nimport { useLoadingBar } from 'naive-ui'\nimport { defineComponent } from 'vue'\n\n// content\nexport default defineComponent({\n  setup() {\n    const loadingBar = useLoadingBar()\n    return {\n      loading() {\n        loadingBar.start()\n      }\n    }\n  }\n})\n```\n\n</n-space>\n\n## 演示\n\n```demo\nbasic.vue\ncontainer.vue\n```\n\n## API\n\n### LoadingBarProvider Props\n\n| 名称 | 类型 | 默认值 | 说明 | 版本 |\n| --- | --- | --- | --- | --- |\n| container-class | `string` | `undefined` | 加载条容器的类名 | 2.33.4 |\n| container-style | `string \\| object` | `undefined` | 加载条容器的样式 | 2.33.4 |\n| loading-bar-style | `{ loading?: string \\| object, error?: string \\| object }` | `undefined` | 加载条样式 |  |\n| to | `string \\| HTMLElement \\| false` | `undefined` | 加载条的挂载位置 | 2.33.4 |\n\n### loadingBar Injection Methods\n\n| 名称   | 类型         | 说明                     |\n| ------ | ------------ | ------------------------ |\n| error  | `() => void` | 加载条出现错误的回调函数 |\n| finish | `() => void` | 加载条结束加载的回调函数 |\n| start  | `() => void` | 加载条开始加载的回调函数 |\n"
  },
  {
    "path": "src/loading-bar/index.ts",
    "content": "export {\n  loadingBarProviderProps,\n  default as NLoadingBarProvider\n} from './src/LoadingBarProvider'\nexport type {\n  LoadingBarApiInjection as LoadingBarApi,\n  LoadingBarProviderInst,\n  LoadingBarProviderProps\n} from './src/LoadingBarProvider'\nexport { useLoadingBar } from './src/use-loading-bar'\n"
  },
  {
    "path": "src/loading-bar/src/LoadingBar.tsx",
    "content": "import type { CSSProperties, PropType } from 'vue'\nimport {\n  computed,\n  defineComponent,\n  h,\n  inject,\n  nextTick,\n  ref,\n  Transition,\n  vShow,\n  withDirectives\n} from 'vue'\nimport { useConfig, useTheme, useThemeClass } from '../../_mixins'\nimport { loadingBarLight } from '../styles'\nimport { loadingBarProviderInjectionKey } from './context'\nimport style from './styles/index.cssr'\n\nfunction createClassName(\n  status: 'error' | 'finishing' | 'starting',\n  clsPrefix: string\n): string {\n  return `${clsPrefix}-loading-bar ${clsPrefix}-loading-bar--${status}`\n}\n\nexport default defineComponent({\n  name: 'LoadingBar',\n  props: {\n    containerClass: String,\n    containerStyle: [String, Object] as PropType<string | CSSProperties>\n  },\n  setup() {\n    const { inlineThemeDisabled } = useConfig()\n    const { props: providerProps, mergedClsPrefixRef } = inject(\n      loadingBarProviderInjectionKey\n    )!\n    const loadingBarRef = ref<HTMLElement | null>(null)\n    const enteringRef = ref(false)\n    const startedRef = ref(false)\n    const loadingRef = ref(false)\n    const transitionDisabledRef = ref(false)\n    let finishing = false\n    const erroringRef = ref(false)\n    const mergedLoadingBarStyle = computed(() => {\n      const { loadingBarStyle } = providerProps\n      if (!loadingBarStyle)\n        return ''\n      return loadingBarStyle[erroringRef.value ? 'error' : 'loading']\n    })\n    async function init(): Promise<void> {\n      enteringRef.value = false\n      loadingRef.value = false\n      finishing = false\n      erroringRef.value = false\n      transitionDisabledRef.value = true\n      await nextTick()\n      transitionDisabledRef.value = false\n    }\n    async function start(\n      fromProgress = 0,\n      toProgress = 80,\n      status: 'starting' | 'error' = 'starting'\n    ): Promise<void> {\n      startedRef.value = true\n      await init()\n      if (finishing)\n        return\n      loadingRef.value = true\n      await nextTick()\n      const el = loadingBarRef.value\n      if (!el)\n        return\n      el.style.maxWidth = `${fromProgress}%`\n      el.style.transition = 'none'\n      void el.offsetWidth\n      el.className = createClassName(status, mergedClsPrefixRef.value)\n      el.style.transition = ''\n      el.style.maxWidth = `${toProgress}%`\n    }\n    async function finish(): Promise<void> {\n      if (finishing || erroringRef.value)\n        return\n      if (startedRef.value) {\n        await nextTick()\n      }\n      finishing = true\n      const el = loadingBarRef.value\n      if (!el)\n        return\n      el.className = createClassName('finishing', mergedClsPrefixRef.value)\n      el.style.maxWidth = '100%'\n      void el.offsetWidth\n      loadingRef.value = false\n    }\n    function error(): void {\n      if (finishing || erroringRef.value)\n        return\n      if (!loadingRef.value) {\n        void start(100, 100, 'error').then(() => {\n          erroringRef.value = true\n          const el = loadingBarRef.value\n          if (!el)\n            return\n          el.className = createClassName('error', mergedClsPrefixRef.value)\n          void el.offsetWidth\n          loadingRef.value = false\n        })\n      }\n      else {\n        erroringRef.value = true\n        const el = loadingBarRef.value\n        if (!el)\n          return\n        el.className = createClassName('error', mergedClsPrefixRef.value)\n        el.style.maxWidth = '100%'\n        void el.offsetWidth\n        loadingRef.value = false\n      }\n    }\n    function handleEnter(): void {\n      enteringRef.value = true\n    }\n    function handleAfterEnter(): void {\n      enteringRef.value = false\n    }\n    async function handleAfterLeave(): Promise<void> {\n      await init()\n    }\n    const themeRef = useTheme(\n      'LoadingBar',\n      '-loading-bar',\n      style,\n      loadingBarLight,\n      providerProps,\n      mergedClsPrefixRef\n    )\n    const cssVarsRef = computed(() => {\n      const {\n        self: { height, colorError, colorLoading }\n      } = themeRef.value\n      return {\n        '--n-height': height,\n        '--n-color-loading': colorLoading,\n        '--n-color-error': colorError\n      }\n    })\n    const themeClassHandle = inlineThemeDisabled\n      ? useThemeClass('loading-bar', undefined, cssVarsRef, providerProps)\n      : undefined\n    return {\n      mergedClsPrefix: mergedClsPrefixRef,\n      loadingBarRef,\n      started: startedRef,\n      loading: loadingRef,\n      entering: enteringRef,\n      transitionDisabled: transitionDisabledRef,\n      start,\n      error,\n      finish,\n      handleEnter,\n      handleAfterEnter,\n      handleAfterLeave,\n      mergedLoadingBarStyle,\n      cssVars: inlineThemeDisabled ? undefined : cssVarsRef,\n      themeClass: themeClassHandle?.themeClass,\n      onRender: themeClassHandle?.onRender\n    }\n  },\n  render() {\n    if (!this.started)\n      return null\n    const { mergedClsPrefix } = this\n    return (\n      <Transition\n        name=\"fade-in-transition\"\n        appear\n        onEnter={this.handleEnter}\n        onAfterEnter={this.handleAfterEnter}\n        onAfterLeave={this.handleAfterLeave}\n        css={!this.transitionDisabled}\n      >\n        {/*\n          BUG: need to use v-show nor it will glitch when triggers start, end,\n          start. This could be a bug of vue but currently I have no time to verify\n          it.\n        */}\n        {{\n          default: () => {\n            this.onRender?.()\n            return withDirectives(\n              <div\n                class={[\n                  `${mergedClsPrefix}-loading-bar-container`,\n                  this.themeClass,\n                  this.containerClass\n                ]}\n                style={this.containerStyle}\n              >\n                <div\n                  ref=\"loadingBarRef\"\n                  class={[`${mergedClsPrefix}-loading-bar`]}\n                  style={[\n                    this.cssVars as any,\n                    this.mergedLoadingBarStyle as any\n                  ]}\n                />\n              </div>,\n              [[vShow, this.loading || (!this.loading && this.entering)]]\n            )\n          }\n        }}\n      </Transition>\n    )\n  }\n})\n"
  },
  {
    "path": "src/loading-bar/src/LoadingBarProvider.tsx",
    "content": "import type { CSSProperties, ExtractPropTypes, PropType } from 'vue'\nimport type { ThemeProps } from '../../_mixins'\nimport type { ExtractPublicPropTypes } from '../../_utils'\nimport type { LoadingBarTheme } from '../styles'\nimport { useIsMounted } from 'vooks'\nimport {\n  defineComponent,\n  Fragment,\n  h,\n  nextTick,\n  provide,\n  ref,\n  Teleport\n} from 'vue'\nimport { useConfig, useTheme } from '../../_mixins'\nimport {\n  loadingBarApiInjectionKey,\n  loadingBarProviderInjectionKey\n} from './context'\nimport NLoadingBar from './LoadingBar'\n\nexport interface LoadingBarInst {\n  start: () => void\n  error: () => void\n  finish: () => void\n}\n\nexport type LoadingBarProviderInst = LoadingBarInst\nexport type LoadingBarApiInjection = LoadingBarInst\n\nexport const loadingBarProviderProps = {\n  ...(useTheme.props as ThemeProps<LoadingBarTheme>),\n  to: {\n    type: [String, Object, Boolean] as PropType<string | HTMLElement | false>,\n    default: undefined\n  },\n  containerClass: String,\n  containerStyle: [String, Object] as PropType<string | CSSProperties>,\n  loadingBarStyle: {\n    type: Object as PropType<{\n      loading?: string | CSSProperties\n      error?: string | CSSProperties\n    }>\n  }\n}\n\nexport type LoadingBarProviderProps = ExtractPublicPropTypes<\n  typeof loadingBarProviderProps\n>\n\nexport type LoadingBarProviderSetupProps = ExtractPropTypes<\n  typeof loadingBarProviderProps\n>\n\nexport default defineComponent({\n  name: 'LoadingBarProvider',\n  props: loadingBarProviderProps,\n  setup(props) {\n    const isMountedRef = useIsMounted()\n    const loadingBarRef = ref<LoadingBarInst | null>(null)\n    const methods: LoadingBarProviderInst = {\n      start() {\n        if (isMountedRef.value) {\n          loadingBarRef.value?.start()\n        }\n        else {\n          void nextTick(() => {\n            loadingBarRef.value?.start()\n          })\n        }\n      },\n      error() {\n        if (isMountedRef.value) {\n          loadingBarRef.value?.error()\n        }\n        else {\n          void nextTick(() => {\n            loadingBarRef.value?.error()\n          })\n        }\n      },\n      finish() {\n        if (isMountedRef.value) {\n          loadingBarRef.value?.finish()\n        }\n        else {\n          void nextTick(() => {\n            loadingBarRef.value?.finish()\n          })\n        }\n      }\n    }\n    const { mergedClsPrefixRef } = useConfig(props)\n    provide(loadingBarApiInjectionKey, methods)\n    provide(loadingBarProviderInjectionKey, {\n      props,\n      mergedClsPrefixRef\n    })\n    return Object.assign(methods, {\n      loadingBarRef\n    })\n  },\n  render() {\n    return (\n      <>\n        <Teleport disabled={this.to === false} to={this.to || 'body'}>\n          <NLoadingBar\n            ref=\"loadingBarRef\"\n            containerStyle={this.containerStyle}\n            containerClass={this.containerClass}\n          />\n        </Teleport>\n        {this.$slots.default?.()}\n      </>\n    )\n  }\n})\n"
  },
  {
    "path": "src/loading-bar/src/context.ts",
    "content": "import type { Ref } from 'vue'\nimport type {\n  LoadingBarApiInjection,\n  LoadingBarProviderSetupProps\n} from './LoadingBarProvider'\nimport { createInjectionKey } from '../../_utils'\n\nexport const loadingBarProviderInjectionKey = createInjectionKey<{\n  props: LoadingBarProviderSetupProps\n  mergedClsPrefixRef: Ref<string>\n}>('n-loading-bar')\n\nexport const loadingBarApiInjectionKey\n  = createInjectionKey<LoadingBarApiInjection>('n-loading-bar-api')\n"
  },
  {
    "path": "src/loading-bar/src/styles/index.cssr.ts",
    "content": "import { fadeInTransition } from '../../../_styles/transitions/fade-in.cssr'\nimport { cB, cM } from '../../../_utils/cssr'\n\n// vars:\n// --n-height\n// --n-color-loading\n// --n-color-error\nexport default cB('loading-bar-container', `\n  z-index: 5999;\n  position: fixed;\n  top: 0;\n  left: 0;\n  right: 0;\n  height: 2px;\n`, [\n  fadeInTransition({\n    enterDuration: '0.3s',\n    leaveDuration: '0.8s'\n  }),\n  cB('loading-bar', `\n    width: 100%;\n    transition:\n      max-width 4s linear,\n      background .2s linear;\n    height: var(--n-height);\n  `, [\n    cM('starting', `\n      background: var(--n-color-loading);\n    `),\n    cM('finishing', `\n      background: var(--n-color-loading);\n      transition:\n        max-width .2s linear,\n        background .2s linear;\n    `),\n    cM('error', `\n      background: var(--n-color-error);\n      transition:\n        max-width .2s linear,\n        background .2s linear;\n    `)\n  ])\n])\n"
  },
  {
    "path": "src/loading-bar/src/use-loading-bar.ts",
    "content": "import type { LoadingBarApiInjection } from './LoadingBarProvider'\nimport { inject } from 'vue'\nimport { throwError } from '../../_utils'\nimport { loadingBarApiInjectionKey } from './context'\n\nexport function useLoadingBar(): LoadingBarApiInjection {\n  const loadingBar = inject(loadingBarApiInjectionKey, null)\n  if (loadingBar === null) {\n    throwError(\n      'use-loading-bar',\n      'No outer <n-loading-bar-provider /> founded.'\n    )\n  }\n  return loadingBar\n}\n"
  },
  {
    "path": "src/loading-bar/styles/dark.ts",
    "content": "import type { LoadingBarTheme } from './light'\nimport { commonDark } from '../../_styles/common'\n\nconst loadingBarDark: LoadingBarTheme = {\n  name: 'LoadingBar',\n  common: commonDark,\n  self(vars) {\n    const { primaryColor } = vars\n    return {\n      colorError: 'red',\n      colorLoading: primaryColor,\n      height: '2px'\n    }\n  }\n}\n\nexport default loadingBarDark\n"
  },
  {
    "path": "src/loading-bar/styles/index.ts",
    "content": "export { default as loadingBarDark } from './dark'\nexport { default as loadingBarLight } from './light'\nexport type { LoadingBarTheme, LoadingBarThemeVars } from './light'\n"
  },
  {
    "path": "src/loading-bar/styles/light.ts",
    "content": "import type { Theme } from '../../_mixins'\nimport type { ThemeCommonVars } from '../../_styles/common'\nimport { commonLight } from '../../_styles/common'\n\nfunction self(vars: ThemeCommonVars) {\n  const { primaryColor, errorColor } = vars\n  return {\n    colorError: errorColor,\n    colorLoading: primaryColor,\n    height: '2px'\n  }\n}\n\nexport type LoadingBarThemeVars = ReturnType<typeof self>\n\nconst loadingBarLight: Theme<'LoadingBar', LoadingBarThemeVars> = {\n  name: 'LoadingBar',\n  common: commonLight,\n  self\n}\n\nexport default loadingBarLight\nexport type LoadingBarTheme = typeof loadingBarLight\n"
  },
  {
    "path": "src/loading-bar/tests/LoadingBar.spec.tsx",
    "content": "import { mount } from '@vue/test-utils'\nimport { sleep } from 'seemly'\nimport { defineComponent, h } from 'vue'\nimport { NLoadingBarProvider, useLoadingBar } from '../index'\n\nconst Provider = defineComponent({\n  render() {\n    return <NLoadingBarProvider>{this.$slots}</NLoadingBarProvider>\n  }\n})\n\ndescribe('n-loading-bar', () => {\n  it('should work with import on demand', () => {\n    mount(NLoadingBarProvider)\n  })\n\n  it('should have start type', async () => {\n    const Test = defineComponent({\n      setup() {\n        const loadingBar = useLoadingBar()\n        loadingBar.start()\n      },\n      render() {\n        return null\n      }\n    })\n    const wrapper = mount(() => (\n      <Provider>{{ default: () => <Test /> }}</Provider>\n    ))\n    await sleep(0)\n    expect(document.querySelector('.n-loading-bar')).not.toEqual(null)\n    wrapper.unmount()\n  })\n\n  it('should have finish type', async () => {\n    const Test = defineComponent({\n      async setup() {\n        const loadingBar = useLoadingBar()\n        loadingBar.start()\n        await vi.waitFor(() => {\n          loadingBar.finish()\n        })\n      },\n      render() {\n        return null\n      }\n    })\n    const wrapper = mount(() => (\n      <Provider>{{ default: () => <Test /> }}</Provider>\n    ))\n    await sleep(0)\n    expect(document.querySelector('.n-loading-bar--finishing')).not.toEqual(\n      null\n    )\n    wrapper.unmount()\n  })\n\n  it('should have error type', async () => {\n    const Test = defineComponent({\n      setup() {\n        const loadingBar = useLoadingBar()\n        loadingBar.error()\n      },\n      render() {\n        return null\n      }\n    })\n    const wrapper = mount(() => (\n      <Provider>{{ default: () => <Test /> }}</Provider>\n    ))\n    await vi.waitFor(() => {\n      expect(document.querySelector('.n-loading-bar--error')).not.toEqual(null)\n      wrapper.unmount()\n    })\n  })\n\n  it('should have loadingBarStyle prop', async () => {\n    const Test = defineComponent({\n      setup() {\n        const loadingBar = useLoadingBar()\n        loadingBar.error()\n      },\n      render() {\n        return null\n      }\n    })\n    const wrapper = mount(NLoadingBarProvider, {\n      props: {\n        loadingBarStyle: {\n          error: {\n            height: '5px',\n            color: '#ccc'\n          }\n        }\n      },\n      slots: {\n        default: () => <Test />\n      }\n    })\n    await vi.waitFor(() => {\n      expect(\n        document.querySelector('.n-loading-bar--error')?.getAttribute('style')\n      ).toContain('height: 5px;')\n    })\n    wrapper.unmount()\n  })\n})\n"
  },
  {
    "path": "src/locales/__snapshots__/index.spec.tsx.snap",
    "content": "// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html\n\nexports[`locale > works 1`] = `\n\"<div class=\"n-config-provider\">\n  <div>\n    <div class=\"n-input n-input--medium-size n-input--resizable n-input--stateful\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-count-text-color: rgb(118, 124, 130); --n-count-text-color-disabled: rgba(194, 194, 194, 1); --n-color: rgba(255, 255, 255, 1); --n-font-size: 14px; --n-font-weight: 400; --n-border-radius: 3px; --n-height: 34px; --n-padding-left: 12px; --n-padding-right: 12px; --n-text-color: rgb(51, 54, 57); --n-caret-color: #18a058; --n-text-decoration-color: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-focus: 1px solid #36ad6a; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-icon-size: 16px; --n-line-height-textarea: 1.6; --n-color-disabled: rgb(250, 250, 252); --n-color-focus: rgba(255, 255, 255, 1); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-loading-color: #18a058; --n-caret-color-warning: #f0a020; --n-color-focus-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-loading-color-warning: #f0a020; --n-caret-color-error: #d03050; --n-color-focus-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-loading-color-error: #d03050; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-size: 16px; --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-icon-color-hover: rgba(146, 146, 146, 1); --n-icon-color-pressed: rgba(175, 175, 175, 1); --n-icon-color-disabled: rgba(209, 209, 209, 1); --n-suffix-text-color: rgb(51, 54, 57);\">\n      <div class=\"n-input-wrapper\">\n        <!---->\n        <div class=\"n-input__input\"><input type=\"text\" class=\"n-input__input-el\" placeholder=\"请输入\" size=\"20\">\n          <div class=\"n-input__placeholder\"><span>请输入</span></div>\n          <!---->\n        </div>\n        <!---->\n      </div>\n      <!---->\n      <!---->\n      <div class=\"n-input__border\"></div>\n      <div class=\"n-input__state-border\"></div>\n      <!---->\n    </div>\n    <div>\n      <div class=\"n-date-picker\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-icon-color-override: rgba(194, 194, 194, 1); --n-icon-color-disabled-override: rgba(209, 209, 209, 1);\">\n        <div class=\"n-input n-input--medium-size n-input--resizable n-input--stateful\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-count-text-color: rgb(118, 124, 130); --n-count-text-color-disabled: rgba(194, 194, 194, 1); --n-color: rgba(255, 255, 255, 1); --n-font-size: 14px; --n-font-weight: 400; --n-border-radius: 3px; --n-height: 34px; --n-padding-left: 12px; --n-padding-right: 12px; --n-text-color: rgb(51, 54, 57); --n-caret-color: #18a058; --n-text-decoration-color: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-focus: 1px solid #36ad6a; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-icon-size: 16px; --n-line-height-textarea: 1.6; --n-color-disabled: rgb(250, 250, 252); --n-color-focus: rgba(255, 255, 255, 1); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-loading-color: #18a058; --n-caret-color-warning: #f0a020; --n-color-focus-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-loading-color-warning: #f0a020; --n-caret-color-error: #d03050; --n-color-focus-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-loading-color-error: #d03050; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-size: 16px; --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-icon-color-hover: rgba(146, 146, 146, 1); --n-icon-color-pressed: rgba(175, 175, 175, 1); --n-icon-color-disabled: rgba(209, 209, 209, 1); --n-suffix-text-color: rgb(51, 54, 57);\" tabindex=\"0\">\n          <div class=\"n-input-wrapper\">\n            <!---->\n            <div class=\"n-input__input\"><input type=\"text\" class=\"n-input__input-el\" tabindex=\"-1\" placeholder=\"选择日期\" size=\"20\" value=\"1970-01-01\">\n              <!---->\n              <!---->\n            </div>\n            <div class=\"n-input__suffix\">\n              <!---->\n              <!---->\n              <!----><i class=\"n-base-icon n-date-picker-icon\"><svg width=\"28px\" height=\"28px\" viewBox=\"0 0 28 28\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n                  <g stroke=\"none\" stroke-width=\"1\" fill-rule=\"evenodd\">\n                    <g fill-rule=\"nonzero\">\n                      <path d=\"M21.75,3 C23.5449254,3 25,4.45507456 25,6.25 L25,21.75 C25,23.5449254 23.5449254,25 21.75,25 L6.25,25 C4.45507456,25 3,23.5449254 3,21.75 L3,6.25 C3,4.45507456 4.45507456,3 6.25,3 L21.75,3 Z M23.5,9.503 L4.5,9.503 L4.5,21.75 C4.5,22.7164983 5.28350169,23.5 6.25,23.5 L21.75,23.5 C22.7164983,23.5 23.5,22.7164983 23.5,21.75 L23.5,9.503 Z M21.75,4.5 L6.25,4.5 C5.28350169,4.5 4.5,5.28350169 4.5,6.25 L4.5,8.003 L23.5,8.003 L23.5,6.25 C23.5,5.28350169 22.7164983,4.5 21.75,4.5 Z\"></path>\n                    </g>\n                  </g>\n                </svg></i>\n              <!---->\n              <!---->\n            </div>\n          </div>\n          <!---->\n          <!---->\n          <div class=\"n-input__border\"></div>\n          <div class=\"n-input__state-border\"></div>\n          <!---->\n        </div>\n        <!---->\n      </div>\n      <div class=\"n-date-picker\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-icon-color-override: rgba(194, 194, 194, 1); --n-icon-color-disabled-override: rgba(209, 209, 209, 1);\">\n        <div class=\"n-input n-input--medium-size n-input--resizable n-input--stateful\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-count-text-color: rgb(118, 124, 130); --n-count-text-color-disabled: rgba(194, 194, 194, 1); --n-color: rgba(255, 255, 255, 1); --n-font-size: 14px; --n-font-weight: 400; --n-border-radius: 3px; --n-height: 34px; --n-padding-left: 12px; --n-padding-right: 12px; --n-text-color: rgb(51, 54, 57); --n-caret-color: #18a058; --n-text-decoration-color: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-focus: 1px solid #36ad6a; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-icon-size: 16px; --n-line-height-textarea: 1.6; --n-color-disabled: rgb(250, 250, 252); --n-color-focus: rgba(255, 255, 255, 1); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-loading-color: #18a058; --n-caret-color-warning: #f0a020; --n-color-focus-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-loading-color-warning: #f0a020; --n-caret-color-error: #d03050; --n-color-focus-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-loading-color-error: #d03050; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-size: 16px; --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-icon-color-hover: rgba(146, 146, 146, 1); --n-icon-color-pressed: rgba(175, 175, 175, 1); --n-icon-color-disabled: rgba(209, 209, 209, 1); --n-suffix-text-color: rgb(51, 54, 57);\" tabindex=\"0\">\n          <div class=\"n-input-wrapper\">\n            <!---->\n            <div class=\"n-input__input\"><input type=\"text\" class=\"n-input__input-el\" tabindex=\"-1\" placeholder=\"选择日期时间\" size=\"20\" value=\"1970-01-01 08:00:00\">\n              <!---->\n              <!---->\n            </div>\n            <div class=\"n-input__suffix\">\n              <!---->\n              <!---->\n              <!----><i class=\"n-base-icon n-date-picker-icon\"><svg width=\"28px\" height=\"28px\" viewBox=\"0 0 28 28\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n                  <g stroke=\"none\" stroke-width=\"1\" fill-rule=\"evenodd\">\n                    <g fill-rule=\"nonzero\">\n                      <path d=\"M21.75,3 C23.5449254,3 25,4.45507456 25,6.25 L25,21.75 C25,23.5449254 23.5449254,25 21.75,25 L6.25,25 C4.45507456,25 3,23.5449254 3,21.75 L3,6.25 C3,4.45507456 4.45507456,3 6.25,3 L21.75,3 Z M23.5,9.503 L4.5,9.503 L4.5,21.75 C4.5,22.7164983 5.28350169,23.5 6.25,23.5 L21.75,23.5 C22.7164983,23.5 23.5,22.7164983 23.5,21.75 L23.5,9.503 Z M21.75,4.5 L6.25,4.5 C5.28350169,4.5 4.5,5.28350169 4.5,6.25 L4.5,8.003 L23.5,8.003 L23.5,6.25 C23.5,5.28350169 22.7164983,4.5 21.75,4.5 Z\"></path>\n                    </g>\n                  </g>\n                </svg></i>\n              <!---->\n              <!---->\n            </div>\n          </div>\n          <!---->\n          <!---->\n          <div class=\"n-input__border\"></div>\n          <div class=\"n-input__state-border\"></div>\n          <!---->\n        </div>\n        <!---->\n      </div>\n      <div class=\"n-date-picker\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-icon-color-override: rgba(194, 194, 194, 1); --n-icon-color-disabled-override: rgba(209, 209, 209, 1);\">\n        <div class=\"n-input n-input--medium-size n-input--resizable n-input--stateful\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-count-text-color: rgb(118, 124, 130); --n-count-text-color-disabled: rgba(194, 194, 194, 1); --n-color: rgba(255, 255, 255, 1); --n-font-size: 14px; --n-font-weight: 400; --n-border-radius: 3px; --n-height: 34px; --n-padding-left: 12px; --n-padding-right: 12px; --n-text-color: rgb(51, 54, 57); --n-caret-color: #18a058; --n-text-decoration-color: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-focus: 1px solid #36ad6a; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-icon-size: 16px; --n-line-height-textarea: 1.6; --n-color-disabled: rgb(250, 250, 252); --n-color-focus: rgba(255, 255, 255, 1); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-loading-color: #18a058; --n-caret-color-warning: #f0a020; --n-color-focus-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-loading-color-warning: #f0a020; --n-caret-color-error: #d03050; --n-color-focus-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-loading-color-error: #d03050; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-size: 16px; --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-icon-color-hover: rgba(146, 146, 146, 1); --n-icon-color-pressed: rgba(175, 175, 175, 1); --n-icon-color-disabled: rgba(209, 209, 209, 1); --n-suffix-text-color: rgb(51, 54, 57);\" tabindex=\"0\">\n          <div class=\"n-input-wrapper\">\n            <!---->\n            <div class=\"n-input__input\"><input type=\"text\" class=\"n-input__input-el\" tabindex=\"-1\" placeholder=\"选择年份\" size=\"20\" value=\"1970\">\n              <!---->\n              <!---->\n            </div>\n            <div class=\"n-input__suffix\">\n              <!---->\n              <!---->\n              <!----><i class=\"n-base-icon n-date-picker-icon\"><svg width=\"28px\" height=\"28px\" viewBox=\"0 0 28 28\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n                  <g stroke=\"none\" stroke-width=\"1\" fill-rule=\"evenodd\">\n                    <g fill-rule=\"nonzero\">\n                      <path d=\"M21.75,3 C23.5449254,3 25,4.45507456 25,6.25 L25,21.75 C25,23.5449254 23.5449254,25 21.75,25 L6.25,25 C4.45507456,25 3,23.5449254 3,21.75 L3,6.25 C3,4.45507456 4.45507456,3 6.25,3 L21.75,3 Z M23.5,9.503 L4.5,9.503 L4.5,21.75 C4.5,22.7164983 5.28350169,23.5 6.25,23.5 L21.75,23.5 C22.7164983,23.5 23.5,22.7164983 23.5,21.75 L23.5,9.503 Z M21.75,4.5 L6.25,4.5 C5.28350169,4.5 4.5,5.28350169 4.5,6.25 L4.5,8.003 L23.5,8.003 L23.5,6.25 C23.5,5.28350169 22.7164983,4.5 21.75,4.5 Z\"></path>\n                    </g>\n                  </g>\n                </svg></i>\n              <!---->\n              <!---->\n            </div>\n          </div>\n          <!---->\n          <!---->\n          <div class=\"n-input__border\"></div>\n          <div class=\"n-input__state-border\"></div>\n          <!---->\n        </div>\n        <!---->\n      </div>\n      <div class=\"n-date-picker\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-icon-color-override: rgba(194, 194, 194, 1); --n-icon-color-disabled-override: rgba(209, 209, 209, 1);\">\n        <div class=\"n-input n-input--medium-size n-input--resizable n-input--stateful\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-count-text-color: rgb(118, 124, 130); --n-count-text-color-disabled: rgba(194, 194, 194, 1); --n-color: rgba(255, 255, 255, 1); --n-font-size: 14px; --n-font-weight: 400; --n-border-radius: 3px; --n-height: 34px; --n-padding-left: 12px; --n-padding-right: 12px; --n-text-color: rgb(51, 54, 57); --n-caret-color: #18a058; --n-text-decoration-color: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-focus: 1px solid #36ad6a; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-icon-size: 16px; --n-line-height-textarea: 1.6; --n-color-disabled: rgb(250, 250, 252); --n-color-focus: rgba(255, 255, 255, 1); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-loading-color: #18a058; --n-caret-color-warning: #f0a020; --n-color-focus-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-loading-color-warning: #f0a020; --n-caret-color-error: #d03050; --n-color-focus-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-loading-color-error: #d03050; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-size: 16px; --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-icon-color-hover: rgba(146, 146, 146, 1); --n-icon-color-pressed: rgba(175, 175, 175, 1); --n-icon-color-disabled: rgba(209, 209, 209, 1); --n-suffix-text-color: rgb(51, 54, 57);\" tabindex=\"0\">\n          <div class=\"n-input-wrapper\">\n            <!---->\n            <div class=\"n-input__input\"><input type=\"text\" class=\"n-input__input-el\" tabindex=\"-1\" placeholder=\"选择月份\" size=\"20\" value=\"1970-01\">\n              <!---->\n              <!---->\n            </div>\n            <div class=\"n-input__suffix\">\n              <!---->\n              <!---->\n              <!----><i class=\"n-base-icon n-date-picker-icon\"><svg width=\"28px\" height=\"28px\" viewBox=\"0 0 28 28\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n                  <g stroke=\"none\" stroke-width=\"1\" fill-rule=\"evenodd\">\n                    <g fill-rule=\"nonzero\">\n                      <path d=\"M21.75,3 C23.5449254,3 25,4.45507456 25,6.25 L25,21.75 C25,23.5449254 23.5449254,25 21.75,25 L6.25,25 C4.45507456,25 3,23.5449254 3,21.75 L3,6.25 C3,4.45507456 4.45507456,3 6.25,3 L21.75,3 Z M23.5,9.503 L4.5,9.503 L4.5,21.75 C4.5,22.7164983 5.28350169,23.5 6.25,23.5 L21.75,23.5 C22.7164983,23.5 23.5,22.7164983 23.5,21.75 L23.5,9.503 Z M21.75,4.5 L6.25,4.5 C5.28350169,4.5 4.5,5.28350169 4.5,6.25 L4.5,8.003 L23.5,8.003 L23.5,6.25 C23.5,5.28350169 22.7164983,4.5 21.75,4.5 Z\"></path>\n                    </g>\n                  </g>\n                </svg></i>\n              <!---->\n              <!---->\n            </div>\n          </div>\n          <!---->\n          <!---->\n          <div class=\"n-input__border\"></div>\n          <div class=\"n-input__state-border\"></div>\n          <!---->\n        </div>\n        <!---->\n      </div>\n    </div>\n  </div>\n</div>\"\n`;\n\nexports[`locale > works 2`] = `\n\"<div class=\"n-config-provider\">\n  <div>\n    <div class=\"n-input n-input--medium-size n-input--resizable n-input--stateful\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-count-text-color: rgb(118, 124, 130); --n-count-text-color-disabled: rgba(194, 194, 194, 1); --n-color: rgba(255, 255, 255, 1); --n-font-size: 14px; --n-font-weight: 400; --n-border-radius: 3px; --n-height: 34px; --n-padding-left: 12px; --n-padding-right: 12px; --n-text-color: rgb(51, 54, 57); --n-caret-color: #18a058; --n-text-decoration-color: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-focus: 1px solid #36ad6a; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-icon-size: 16px; --n-line-height-textarea: 1.6; --n-color-disabled: rgb(250, 250, 252); --n-color-focus: rgba(255, 255, 255, 1); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-loading-color: #18a058; --n-caret-color-warning: #f0a020; --n-color-focus-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-loading-color-warning: #f0a020; --n-caret-color-error: #d03050; --n-color-focus-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-loading-color-error: #d03050; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-size: 16px; --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-icon-color-hover: rgba(146, 146, 146, 1); --n-icon-color-pressed: rgba(175, 175, 175, 1); --n-icon-color-disabled: rgba(209, 209, 209, 1); --n-suffix-text-color: rgb(51, 54, 57);\">\n      <div class=\"n-input-wrapper\">\n        <!---->\n        <div class=\"n-input__input\"><input type=\"text\" class=\"n-input__input-el\" placeholder=\"請輸入\" size=\"20\">\n          <div class=\"n-input__placeholder\"><span>請輸入</span></div>\n          <!---->\n        </div>\n        <!---->\n      </div>\n      <!---->\n      <!---->\n      <div class=\"n-input__border\"></div>\n      <div class=\"n-input__state-border\"></div>\n      <!---->\n    </div>\n    <div>\n      <div class=\"n-date-picker\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-icon-color-override: rgba(194, 194, 194, 1); --n-icon-color-disabled-override: rgba(209, 209, 209, 1);\">\n        <div class=\"n-input n-input--medium-size n-input--resizable n-input--stateful\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-count-text-color: rgb(118, 124, 130); --n-count-text-color-disabled: rgba(194, 194, 194, 1); --n-color: rgba(255, 255, 255, 1); --n-font-size: 14px; --n-font-weight: 400; --n-border-radius: 3px; --n-height: 34px; --n-padding-left: 12px; --n-padding-right: 12px; --n-text-color: rgb(51, 54, 57); --n-caret-color: #18a058; --n-text-decoration-color: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-focus: 1px solid #36ad6a; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-icon-size: 16px; --n-line-height-textarea: 1.6; --n-color-disabled: rgb(250, 250, 252); --n-color-focus: rgba(255, 255, 255, 1); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-loading-color: #18a058; --n-caret-color-warning: #f0a020; --n-color-focus-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-loading-color-warning: #f0a020; --n-caret-color-error: #d03050; --n-color-focus-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-loading-color-error: #d03050; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-size: 16px; --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-icon-color-hover: rgba(146, 146, 146, 1); --n-icon-color-pressed: rgba(175, 175, 175, 1); --n-icon-color-disabled: rgba(209, 209, 209, 1); --n-suffix-text-color: rgb(51, 54, 57);\" tabindex=\"0\">\n          <div class=\"n-input-wrapper\">\n            <!---->\n            <div class=\"n-input__input\"><input type=\"text\" class=\"n-input__input-el\" tabindex=\"-1\" placeholder=\"選擇日期\" size=\"20\" value=\"1970-01-01\">\n              <!---->\n              <!---->\n            </div>\n            <div class=\"n-input__suffix\">\n              <!---->\n              <!---->\n              <!----><i class=\"n-base-icon n-date-picker-icon\"><svg width=\"28px\" height=\"28px\" viewBox=\"0 0 28 28\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n                  <g stroke=\"none\" stroke-width=\"1\" fill-rule=\"evenodd\">\n                    <g fill-rule=\"nonzero\">\n                      <path d=\"M21.75,3 C23.5449254,3 25,4.45507456 25,6.25 L25,21.75 C25,23.5449254 23.5449254,25 21.75,25 L6.25,25 C4.45507456,25 3,23.5449254 3,21.75 L3,6.25 C3,4.45507456 4.45507456,3 6.25,3 L21.75,3 Z M23.5,9.503 L4.5,9.503 L4.5,21.75 C4.5,22.7164983 5.28350169,23.5 6.25,23.5 L21.75,23.5 C22.7164983,23.5 23.5,22.7164983 23.5,21.75 L23.5,9.503 Z M21.75,4.5 L6.25,4.5 C5.28350169,4.5 4.5,5.28350169 4.5,6.25 L4.5,8.003 L23.5,8.003 L23.5,6.25 C23.5,5.28350169 22.7164983,4.5 21.75,4.5 Z\"></path>\n                    </g>\n                  </g>\n                </svg></i>\n              <!---->\n              <!---->\n            </div>\n          </div>\n          <!---->\n          <!---->\n          <div class=\"n-input__border\"></div>\n          <div class=\"n-input__state-border\"></div>\n          <!---->\n        </div>\n        <!---->\n      </div>\n      <div class=\"n-date-picker\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-icon-color-override: rgba(194, 194, 194, 1); --n-icon-color-disabled-override: rgba(209, 209, 209, 1);\">\n        <div class=\"n-input n-input--medium-size n-input--resizable n-input--stateful\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-count-text-color: rgb(118, 124, 130); --n-count-text-color-disabled: rgba(194, 194, 194, 1); --n-color: rgba(255, 255, 255, 1); --n-font-size: 14px; --n-font-weight: 400; --n-border-radius: 3px; --n-height: 34px; --n-padding-left: 12px; --n-padding-right: 12px; --n-text-color: rgb(51, 54, 57); --n-caret-color: #18a058; --n-text-decoration-color: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-focus: 1px solid #36ad6a; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-icon-size: 16px; --n-line-height-textarea: 1.6; --n-color-disabled: rgb(250, 250, 252); --n-color-focus: rgba(255, 255, 255, 1); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-loading-color: #18a058; --n-caret-color-warning: #f0a020; --n-color-focus-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-loading-color-warning: #f0a020; --n-caret-color-error: #d03050; --n-color-focus-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-loading-color-error: #d03050; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-size: 16px; --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-icon-color-hover: rgba(146, 146, 146, 1); --n-icon-color-pressed: rgba(175, 175, 175, 1); --n-icon-color-disabled: rgba(209, 209, 209, 1); --n-suffix-text-color: rgb(51, 54, 57);\" tabindex=\"0\">\n          <div class=\"n-input-wrapper\">\n            <!---->\n            <div class=\"n-input__input\"><input type=\"text\" class=\"n-input__input-el\" tabindex=\"-1\" placeholder=\"選擇日期時間\" size=\"20\" value=\"1970-01-01 08:00:00\">\n              <!---->\n              <!---->\n            </div>\n            <div class=\"n-input__suffix\">\n              <!---->\n              <!---->\n              <!----><i class=\"n-base-icon n-date-picker-icon\"><svg width=\"28px\" height=\"28px\" viewBox=\"0 0 28 28\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n                  <g stroke=\"none\" stroke-width=\"1\" fill-rule=\"evenodd\">\n                    <g fill-rule=\"nonzero\">\n                      <path d=\"M21.75,3 C23.5449254,3 25,4.45507456 25,6.25 L25,21.75 C25,23.5449254 23.5449254,25 21.75,25 L6.25,25 C4.45507456,25 3,23.5449254 3,21.75 L3,6.25 C3,4.45507456 4.45507456,3 6.25,3 L21.75,3 Z M23.5,9.503 L4.5,9.503 L4.5,21.75 C4.5,22.7164983 5.28350169,23.5 6.25,23.5 L21.75,23.5 C22.7164983,23.5 23.5,22.7164983 23.5,21.75 L23.5,9.503 Z M21.75,4.5 L6.25,4.5 C5.28350169,4.5 4.5,5.28350169 4.5,6.25 L4.5,8.003 L23.5,8.003 L23.5,6.25 C23.5,5.28350169 22.7164983,4.5 21.75,4.5 Z\"></path>\n                    </g>\n                  </g>\n                </svg></i>\n              <!---->\n              <!---->\n            </div>\n          </div>\n          <!---->\n          <!---->\n          <div class=\"n-input__border\"></div>\n          <div class=\"n-input__state-border\"></div>\n          <!---->\n        </div>\n        <!---->\n      </div>\n      <div class=\"n-date-picker\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-icon-color-override: rgba(194, 194, 194, 1); --n-icon-color-disabled-override: rgba(209, 209, 209, 1);\">\n        <div class=\"n-input n-input--medium-size n-input--resizable n-input--stateful\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-count-text-color: rgb(118, 124, 130); --n-count-text-color-disabled: rgba(194, 194, 194, 1); --n-color: rgba(255, 255, 255, 1); --n-font-size: 14px; --n-font-weight: 400; --n-border-radius: 3px; --n-height: 34px; --n-padding-left: 12px; --n-padding-right: 12px; --n-text-color: rgb(51, 54, 57); --n-caret-color: #18a058; --n-text-decoration-color: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-focus: 1px solid #36ad6a; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-icon-size: 16px; --n-line-height-textarea: 1.6; --n-color-disabled: rgb(250, 250, 252); --n-color-focus: rgba(255, 255, 255, 1); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-loading-color: #18a058; --n-caret-color-warning: #f0a020; --n-color-focus-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-loading-color-warning: #f0a020; --n-caret-color-error: #d03050; --n-color-focus-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-loading-color-error: #d03050; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-size: 16px; --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-icon-color-hover: rgba(146, 146, 146, 1); --n-icon-color-pressed: rgba(175, 175, 175, 1); --n-icon-color-disabled: rgba(209, 209, 209, 1); --n-suffix-text-color: rgb(51, 54, 57);\" tabindex=\"0\">\n          <div class=\"n-input-wrapper\">\n            <!---->\n            <div class=\"n-input__input\"><input type=\"text\" class=\"n-input__input-el\" tabindex=\"-1\" placeholder=\"選擇年份\" size=\"20\" value=\"1970\">\n              <!---->\n              <!---->\n            </div>\n            <div class=\"n-input__suffix\">\n              <!---->\n              <!---->\n              <!----><i class=\"n-base-icon n-date-picker-icon\"><svg width=\"28px\" height=\"28px\" viewBox=\"0 0 28 28\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n                  <g stroke=\"none\" stroke-width=\"1\" fill-rule=\"evenodd\">\n                    <g fill-rule=\"nonzero\">\n                      <path d=\"M21.75,3 C23.5449254,3 25,4.45507456 25,6.25 L25,21.75 C25,23.5449254 23.5449254,25 21.75,25 L6.25,25 C4.45507456,25 3,23.5449254 3,21.75 L3,6.25 C3,4.45507456 4.45507456,3 6.25,3 L21.75,3 Z M23.5,9.503 L4.5,9.503 L4.5,21.75 C4.5,22.7164983 5.28350169,23.5 6.25,23.5 L21.75,23.5 C22.7164983,23.5 23.5,22.7164983 23.5,21.75 L23.5,9.503 Z M21.75,4.5 L6.25,4.5 C5.28350169,4.5 4.5,5.28350169 4.5,6.25 L4.5,8.003 L23.5,8.003 L23.5,6.25 C23.5,5.28350169 22.7164983,4.5 21.75,4.5 Z\"></path>\n                    </g>\n                  </g>\n                </svg></i>\n              <!---->\n              <!---->\n            </div>\n          </div>\n          <!---->\n          <!---->\n          <div class=\"n-input__border\"></div>\n          <div class=\"n-input__state-border\"></div>\n          <!---->\n        </div>\n        <!---->\n      </div>\n      <div class=\"n-date-picker\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-icon-color-override: rgba(194, 194, 194, 1); --n-icon-color-disabled-override: rgba(209, 209, 209, 1);\">\n        <div class=\"n-input n-input--medium-size n-input--resizable n-input--stateful\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-count-text-color: rgb(118, 124, 130); --n-count-text-color-disabled: rgba(194, 194, 194, 1); --n-color: rgba(255, 255, 255, 1); --n-font-size: 14px; --n-font-weight: 400; --n-border-radius: 3px; --n-height: 34px; --n-padding-left: 12px; --n-padding-right: 12px; --n-text-color: rgb(51, 54, 57); --n-caret-color: #18a058; --n-text-decoration-color: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-focus: 1px solid #36ad6a; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-icon-size: 16px; --n-line-height-textarea: 1.6; --n-color-disabled: rgb(250, 250, 252); --n-color-focus: rgba(255, 255, 255, 1); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-loading-color: #18a058; --n-caret-color-warning: #f0a020; --n-color-focus-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-loading-color-warning: #f0a020; --n-caret-color-error: #d03050; --n-color-focus-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-loading-color-error: #d03050; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-size: 16px; --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-icon-color-hover: rgba(146, 146, 146, 1); --n-icon-color-pressed: rgba(175, 175, 175, 1); --n-icon-color-disabled: rgba(209, 209, 209, 1); --n-suffix-text-color: rgb(51, 54, 57);\" tabindex=\"0\">\n          <div class=\"n-input-wrapper\">\n            <!---->\n            <div class=\"n-input__input\"><input type=\"text\" class=\"n-input__input-el\" tabindex=\"-1\" placeholder=\"選擇月份\" size=\"20\" value=\"1970-01\">\n              <!---->\n              <!---->\n            </div>\n            <div class=\"n-input__suffix\">\n              <!---->\n              <!---->\n              <!----><i class=\"n-base-icon n-date-picker-icon\"><svg width=\"28px\" height=\"28px\" viewBox=\"0 0 28 28\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n                  <g stroke=\"none\" stroke-width=\"1\" fill-rule=\"evenodd\">\n                    <g fill-rule=\"nonzero\">\n                      <path d=\"M21.75,3 C23.5449254,3 25,4.45507456 25,6.25 L25,21.75 C25,23.5449254 23.5449254,25 21.75,25 L6.25,25 C4.45507456,25 3,23.5449254 3,21.75 L3,6.25 C3,4.45507456 4.45507456,3 6.25,3 L21.75,3 Z M23.5,9.503 L4.5,9.503 L4.5,21.75 C4.5,22.7164983 5.28350169,23.5 6.25,23.5 L21.75,23.5 C22.7164983,23.5 23.5,22.7164983 23.5,21.75 L23.5,9.503 Z M21.75,4.5 L6.25,4.5 C5.28350169,4.5 4.5,5.28350169 4.5,6.25 L4.5,8.003 L23.5,8.003 L23.5,6.25 C23.5,5.28350169 22.7164983,4.5 21.75,4.5 Z\"></path>\n                    </g>\n                  </g>\n                </svg></i>\n              <!---->\n              <!---->\n            </div>\n          </div>\n          <!---->\n          <!---->\n          <div class=\"n-input__border\"></div>\n          <div class=\"n-input__state-border\"></div>\n          <!---->\n        </div>\n        <!---->\n      </div>\n    </div>\n  </div>\n</div>\"\n`;\n\nexports[`locale > works 3`] = `\n\"<div class=\"n-config-provider\">\n  <div>\n    <div class=\"n-input n-input--medium-size n-input--resizable n-input--stateful\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-count-text-color: rgb(118, 124, 130); --n-count-text-color-disabled: rgba(194, 194, 194, 1); --n-color: rgba(255, 255, 255, 1); --n-font-size: 14px; --n-font-weight: 400; --n-border-radius: 3px; --n-height: 34px; --n-padding-left: 12px; --n-padding-right: 12px; --n-text-color: rgb(51, 54, 57); --n-caret-color: #18a058; --n-text-decoration-color: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-focus: 1px solid #36ad6a; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-icon-size: 16px; --n-line-height-textarea: 1.6; --n-color-disabled: rgb(250, 250, 252); --n-color-focus: rgba(255, 255, 255, 1); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-loading-color: #18a058; --n-caret-color-warning: #f0a020; --n-color-focus-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-loading-color-warning: #f0a020; --n-caret-color-error: #d03050; --n-color-focus-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-loading-color-error: #d03050; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-size: 16px; --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-icon-color-hover: rgba(146, 146, 146, 1); --n-icon-color-pressed: rgba(175, 175, 175, 1); --n-icon-color-disabled: rgba(209, 209, 209, 1); --n-suffix-text-color: rgb(51, 54, 57);\">\n      <div class=\"n-input-wrapper\">\n        <!---->\n        <div class=\"n-input__input\"><input type=\"text\" class=\"n-input__input-el\" placeholder=\"Please Input\" size=\"20\">\n          <div class=\"n-input__placeholder\"><span>Please Input</span></div>\n          <!---->\n        </div>\n        <!---->\n      </div>\n      <!---->\n      <!---->\n      <div class=\"n-input__border\"></div>\n      <div class=\"n-input__state-border\"></div>\n      <!---->\n    </div>\n    <div>\n      <div class=\"n-date-picker\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-icon-color-override: rgba(194, 194, 194, 1); --n-icon-color-disabled-override: rgba(209, 209, 209, 1);\">\n        <div class=\"n-input n-input--medium-size n-input--resizable n-input--stateful\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-count-text-color: rgb(118, 124, 130); --n-count-text-color-disabled: rgba(194, 194, 194, 1); --n-color: rgba(255, 255, 255, 1); --n-font-size: 14px; --n-font-weight: 400; --n-border-radius: 3px; --n-height: 34px; --n-padding-left: 12px; --n-padding-right: 12px; --n-text-color: rgb(51, 54, 57); --n-caret-color: #18a058; --n-text-decoration-color: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-focus: 1px solid #36ad6a; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-icon-size: 16px; --n-line-height-textarea: 1.6; --n-color-disabled: rgb(250, 250, 252); --n-color-focus: rgba(255, 255, 255, 1); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-loading-color: #18a058; --n-caret-color-warning: #f0a020; --n-color-focus-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-loading-color-warning: #f0a020; --n-caret-color-error: #d03050; --n-color-focus-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-loading-color-error: #d03050; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-size: 16px; --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-icon-color-hover: rgba(146, 146, 146, 1); --n-icon-color-pressed: rgba(175, 175, 175, 1); --n-icon-color-disabled: rgba(209, 209, 209, 1); --n-suffix-text-color: rgb(51, 54, 57);\" tabindex=\"0\">\n          <div class=\"n-input-wrapper\">\n            <!---->\n            <div class=\"n-input__input\"><input type=\"text\" class=\"n-input__input-el\" tabindex=\"-1\" placeholder=\"Select Date\" size=\"20\" value=\"1970-01-01\">\n              <!---->\n              <!---->\n            </div>\n            <div class=\"n-input__suffix\">\n              <!---->\n              <!---->\n              <!----><i class=\"n-base-icon n-date-picker-icon\"><svg width=\"28px\" height=\"28px\" viewBox=\"0 0 28 28\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n                  <g stroke=\"none\" stroke-width=\"1\" fill-rule=\"evenodd\">\n                    <g fill-rule=\"nonzero\">\n                      <path d=\"M21.75,3 C23.5449254,3 25,4.45507456 25,6.25 L25,21.75 C25,23.5449254 23.5449254,25 21.75,25 L6.25,25 C4.45507456,25 3,23.5449254 3,21.75 L3,6.25 C3,4.45507456 4.45507456,3 6.25,3 L21.75,3 Z M23.5,9.503 L4.5,9.503 L4.5,21.75 C4.5,22.7164983 5.28350169,23.5 6.25,23.5 L21.75,23.5 C22.7164983,23.5 23.5,22.7164983 23.5,21.75 L23.5,9.503 Z M21.75,4.5 L6.25,4.5 C5.28350169,4.5 4.5,5.28350169 4.5,6.25 L4.5,8.003 L23.5,8.003 L23.5,6.25 C23.5,5.28350169 22.7164983,4.5 21.75,4.5 Z\"></path>\n                    </g>\n                  </g>\n                </svg></i>\n              <!---->\n              <!---->\n            </div>\n          </div>\n          <!---->\n          <!---->\n          <div class=\"n-input__border\"></div>\n          <div class=\"n-input__state-border\"></div>\n          <!---->\n        </div>\n        <!---->\n      </div>\n      <div class=\"n-date-picker\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-icon-color-override: rgba(194, 194, 194, 1); --n-icon-color-disabled-override: rgba(209, 209, 209, 1);\">\n        <div class=\"n-input n-input--medium-size n-input--resizable n-input--stateful\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-count-text-color: rgb(118, 124, 130); --n-count-text-color-disabled: rgba(194, 194, 194, 1); --n-color: rgba(255, 255, 255, 1); --n-font-size: 14px; --n-font-weight: 400; --n-border-radius: 3px; --n-height: 34px; --n-padding-left: 12px; --n-padding-right: 12px; --n-text-color: rgb(51, 54, 57); --n-caret-color: #18a058; --n-text-decoration-color: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-focus: 1px solid #36ad6a; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-icon-size: 16px; --n-line-height-textarea: 1.6; --n-color-disabled: rgb(250, 250, 252); --n-color-focus: rgba(255, 255, 255, 1); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-loading-color: #18a058; --n-caret-color-warning: #f0a020; --n-color-focus-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-loading-color-warning: #f0a020; --n-caret-color-error: #d03050; --n-color-focus-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-loading-color-error: #d03050; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-size: 16px; --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-icon-color-hover: rgba(146, 146, 146, 1); --n-icon-color-pressed: rgba(175, 175, 175, 1); --n-icon-color-disabled: rgba(209, 209, 209, 1); --n-suffix-text-color: rgb(51, 54, 57);\" tabindex=\"0\">\n          <div class=\"n-input-wrapper\">\n            <!---->\n            <div class=\"n-input__input\"><input type=\"text\" class=\"n-input__input-el\" tabindex=\"-1\" placeholder=\"Select Date and Time\" size=\"20\" value=\"1970-01-01 08:00:00\">\n              <!---->\n              <!---->\n            </div>\n            <div class=\"n-input__suffix\">\n              <!---->\n              <!---->\n              <!----><i class=\"n-base-icon n-date-picker-icon\"><svg width=\"28px\" height=\"28px\" viewBox=\"0 0 28 28\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n                  <g stroke=\"none\" stroke-width=\"1\" fill-rule=\"evenodd\">\n                    <g fill-rule=\"nonzero\">\n                      <path d=\"M21.75,3 C23.5449254,3 25,4.45507456 25,6.25 L25,21.75 C25,23.5449254 23.5449254,25 21.75,25 L6.25,25 C4.45507456,25 3,23.5449254 3,21.75 L3,6.25 C3,4.45507456 4.45507456,3 6.25,3 L21.75,3 Z M23.5,9.503 L4.5,9.503 L4.5,21.75 C4.5,22.7164983 5.28350169,23.5 6.25,23.5 L21.75,23.5 C22.7164983,23.5 23.5,22.7164983 23.5,21.75 L23.5,9.503 Z M21.75,4.5 L6.25,4.5 C5.28350169,4.5 4.5,5.28350169 4.5,6.25 L4.5,8.003 L23.5,8.003 L23.5,6.25 C23.5,5.28350169 22.7164983,4.5 21.75,4.5 Z\"></path>\n                    </g>\n                  </g>\n                </svg></i>\n              <!---->\n              <!---->\n            </div>\n          </div>\n          <!---->\n          <!---->\n          <div class=\"n-input__border\"></div>\n          <div class=\"n-input__state-border\"></div>\n          <!---->\n        </div>\n        <!---->\n      </div>\n      <div class=\"n-date-picker\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-icon-color-override: rgba(194, 194, 194, 1); --n-icon-color-disabled-override: rgba(209, 209, 209, 1);\">\n        <div class=\"n-input n-input--medium-size n-input--resizable n-input--stateful\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-count-text-color: rgb(118, 124, 130); --n-count-text-color-disabled: rgba(194, 194, 194, 1); --n-color: rgba(255, 255, 255, 1); --n-font-size: 14px; --n-font-weight: 400; --n-border-radius: 3px; --n-height: 34px; --n-padding-left: 12px; --n-padding-right: 12px; --n-text-color: rgb(51, 54, 57); --n-caret-color: #18a058; --n-text-decoration-color: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-focus: 1px solid #36ad6a; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-icon-size: 16px; --n-line-height-textarea: 1.6; --n-color-disabled: rgb(250, 250, 252); --n-color-focus: rgba(255, 255, 255, 1); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-loading-color: #18a058; --n-caret-color-warning: #f0a020; --n-color-focus-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-loading-color-warning: #f0a020; --n-caret-color-error: #d03050; --n-color-focus-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-loading-color-error: #d03050; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-size: 16px; --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-icon-color-hover: rgba(146, 146, 146, 1); --n-icon-color-pressed: rgba(175, 175, 175, 1); --n-icon-color-disabled: rgba(209, 209, 209, 1); --n-suffix-text-color: rgb(51, 54, 57);\" tabindex=\"0\">\n          <div class=\"n-input-wrapper\">\n            <!---->\n            <div class=\"n-input__input\"><input type=\"text\" class=\"n-input__input-el\" tabindex=\"-1\" placeholder=\"Select Year\" size=\"20\" value=\"1970\">\n              <!---->\n              <!---->\n            </div>\n            <div class=\"n-input__suffix\">\n              <!---->\n              <!---->\n              <!----><i class=\"n-base-icon n-date-picker-icon\"><svg width=\"28px\" height=\"28px\" viewBox=\"0 0 28 28\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n                  <g stroke=\"none\" stroke-width=\"1\" fill-rule=\"evenodd\">\n                    <g fill-rule=\"nonzero\">\n                      <path d=\"M21.75,3 C23.5449254,3 25,4.45507456 25,6.25 L25,21.75 C25,23.5449254 23.5449254,25 21.75,25 L6.25,25 C4.45507456,25 3,23.5449254 3,21.75 L3,6.25 C3,4.45507456 4.45507456,3 6.25,3 L21.75,3 Z M23.5,9.503 L4.5,9.503 L4.5,21.75 C4.5,22.7164983 5.28350169,23.5 6.25,23.5 L21.75,23.5 C22.7164983,23.5 23.5,22.7164983 23.5,21.75 L23.5,9.503 Z M21.75,4.5 L6.25,4.5 C5.28350169,4.5 4.5,5.28350169 4.5,6.25 L4.5,8.003 L23.5,8.003 L23.5,6.25 C23.5,5.28350169 22.7164983,4.5 21.75,4.5 Z\"></path>\n                    </g>\n                  </g>\n                </svg></i>\n              <!---->\n              <!---->\n            </div>\n          </div>\n          <!---->\n          <!---->\n          <div class=\"n-input__border\"></div>\n          <div class=\"n-input__state-border\"></div>\n          <!---->\n        </div>\n        <!---->\n      </div>\n      <div class=\"n-date-picker\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-icon-color-override: rgba(194, 194, 194, 1); --n-icon-color-disabled-override: rgba(209, 209, 209, 1);\">\n        <div class=\"n-input n-input--medium-size n-input--resizable n-input--stateful\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-count-text-color: rgb(118, 124, 130); --n-count-text-color-disabled: rgba(194, 194, 194, 1); --n-color: rgba(255, 255, 255, 1); --n-font-size: 14px; --n-font-weight: 400; --n-border-radius: 3px; --n-height: 34px; --n-padding-left: 12px; --n-padding-right: 12px; --n-text-color: rgb(51, 54, 57); --n-caret-color: #18a058; --n-text-decoration-color: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-focus: 1px solid #36ad6a; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-icon-size: 16px; --n-line-height-textarea: 1.6; --n-color-disabled: rgb(250, 250, 252); --n-color-focus: rgba(255, 255, 255, 1); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-loading-color: #18a058; --n-caret-color-warning: #f0a020; --n-color-focus-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-loading-color-warning: #f0a020; --n-caret-color-error: #d03050; --n-color-focus-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-loading-color-error: #d03050; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-size: 16px; --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-icon-color-hover: rgba(146, 146, 146, 1); --n-icon-color-pressed: rgba(175, 175, 175, 1); --n-icon-color-disabled: rgba(209, 209, 209, 1); --n-suffix-text-color: rgb(51, 54, 57);\" tabindex=\"0\">\n          <div class=\"n-input-wrapper\">\n            <!---->\n            <div class=\"n-input__input\"><input type=\"text\" class=\"n-input__input-el\" tabindex=\"-1\" placeholder=\"Select Month\" size=\"20\" value=\"1970-01\">\n              <!---->\n              <!---->\n            </div>\n            <div class=\"n-input__suffix\">\n              <!---->\n              <!---->\n              <!----><i class=\"n-base-icon n-date-picker-icon\"><svg width=\"28px\" height=\"28px\" viewBox=\"0 0 28 28\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n                  <g stroke=\"none\" stroke-width=\"1\" fill-rule=\"evenodd\">\n                    <g fill-rule=\"nonzero\">\n                      <path d=\"M21.75,3 C23.5449254,3 25,4.45507456 25,6.25 L25,21.75 C25,23.5449254 23.5449254,25 21.75,25 L6.25,25 C4.45507456,25 3,23.5449254 3,21.75 L3,6.25 C3,4.45507456 4.45507456,3 6.25,3 L21.75,3 Z M23.5,9.503 L4.5,9.503 L4.5,21.75 C4.5,22.7164983 5.28350169,23.5 6.25,23.5 L21.75,23.5 C22.7164983,23.5 23.5,22.7164983 23.5,21.75 L23.5,9.503 Z M21.75,4.5 L6.25,4.5 C5.28350169,4.5 4.5,5.28350169 4.5,6.25 L4.5,8.003 L23.5,8.003 L23.5,6.25 C23.5,5.28350169 22.7164983,4.5 21.75,4.5 Z\"></path>\n                    </g>\n                  </g>\n                </svg></i>\n              <!---->\n              <!---->\n            </div>\n          </div>\n          <!---->\n          <!---->\n          <div class=\"n-input__border\"></div>\n          <div class=\"n-input__state-border\"></div>\n          <!---->\n        </div>\n        <!---->\n      </div>\n    </div>\n  </div>\n</div>\"\n`;\n\nexports[`locale > works 4`] = `\n\"<div class=\"n-config-provider\">\n  <div>\n    <div class=\"n-input n-input--medium-size n-input--resizable n-input--stateful\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-count-text-color: rgb(118, 124, 130); --n-count-text-color-disabled: rgba(194, 194, 194, 1); --n-color: rgba(255, 255, 255, 1); --n-font-size: 14px; --n-font-weight: 400; --n-border-radius: 3px; --n-height: 34px; --n-padding-left: 12px; --n-padding-right: 12px; --n-text-color: rgb(51, 54, 57); --n-caret-color: #18a058; --n-text-decoration-color: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-focus: 1px solid #36ad6a; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-icon-size: 16px; --n-line-height-textarea: 1.6; --n-color-disabled: rgb(250, 250, 252); --n-color-focus: rgba(255, 255, 255, 1); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-loading-color: #18a058; --n-caret-color-warning: #f0a020; --n-color-focus-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-loading-color-warning: #f0a020; --n-caret-color-error: #d03050; --n-color-focus-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-loading-color-error: #d03050; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-size: 16px; --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-icon-color-hover: rgba(146, 146, 146, 1); --n-icon-color-pressed: rgba(175, 175, 175, 1); --n-icon-color-disabled: rgba(209, 209, 209, 1); --n-suffix-text-color: rgb(51, 54, 57);\">\n      <div class=\"n-input-wrapper\">\n        <!---->\n        <div class=\"n-input__input\"><input type=\"text\" class=\"n-input__input-el\" placeholder=\"Ввести\" size=\"20\">\n          <div class=\"n-input__placeholder\"><span>Ввести</span></div>\n          <!---->\n        </div>\n        <!---->\n      </div>\n      <!---->\n      <!---->\n      <div class=\"n-input__border\"></div>\n      <div class=\"n-input__state-border\"></div>\n      <!---->\n    </div>\n    <div>\n      <div class=\"n-date-picker\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-icon-color-override: rgba(194, 194, 194, 1); --n-icon-color-disabled-override: rgba(209, 209, 209, 1);\">\n        <div class=\"n-input n-input--medium-size n-input--resizable n-input--stateful\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-count-text-color: rgb(118, 124, 130); --n-count-text-color-disabled: rgba(194, 194, 194, 1); --n-color: rgba(255, 255, 255, 1); --n-font-size: 14px; --n-font-weight: 400; --n-border-radius: 3px; --n-height: 34px; --n-padding-left: 12px; --n-padding-right: 12px; --n-text-color: rgb(51, 54, 57); --n-caret-color: #18a058; --n-text-decoration-color: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-focus: 1px solid #36ad6a; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-icon-size: 16px; --n-line-height-textarea: 1.6; --n-color-disabled: rgb(250, 250, 252); --n-color-focus: rgba(255, 255, 255, 1); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-loading-color: #18a058; --n-caret-color-warning: #f0a020; --n-color-focus-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-loading-color-warning: #f0a020; --n-caret-color-error: #d03050; --n-color-focus-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-loading-color-error: #d03050; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-size: 16px; --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-icon-color-hover: rgba(146, 146, 146, 1); --n-icon-color-pressed: rgba(175, 175, 175, 1); --n-icon-color-disabled: rgba(209, 209, 209, 1); --n-suffix-text-color: rgb(51, 54, 57);\" tabindex=\"0\">\n          <div class=\"n-input-wrapper\">\n            <!---->\n            <div class=\"n-input__input\"><input type=\"text\" class=\"n-input__input-el\" tabindex=\"-1\" placeholder=\"Выбрать дату\" size=\"20\" value=\"1970-01-01\">\n              <!---->\n              <!---->\n            </div>\n            <div class=\"n-input__suffix\">\n              <!---->\n              <!---->\n              <!----><i class=\"n-base-icon n-date-picker-icon\"><svg width=\"28px\" height=\"28px\" viewBox=\"0 0 28 28\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n                  <g stroke=\"none\" stroke-width=\"1\" fill-rule=\"evenodd\">\n                    <g fill-rule=\"nonzero\">\n                      <path d=\"M21.75,3 C23.5449254,3 25,4.45507456 25,6.25 L25,21.75 C25,23.5449254 23.5449254,25 21.75,25 L6.25,25 C4.45507456,25 3,23.5449254 3,21.75 L3,6.25 C3,4.45507456 4.45507456,3 6.25,3 L21.75,3 Z M23.5,9.503 L4.5,9.503 L4.5,21.75 C4.5,22.7164983 5.28350169,23.5 6.25,23.5 L21.75,23.5 C22.7164983,23.5 23.5,22.7164983 23.5,21.75 L23.5,9.503 Z M21.75,4.5 L6.25,4.5 C5.28350169,4.5 4.5,5.28350169 4.5,6.25 L4.5,8.003 L23.5,8.003 L23.5,6.25 C23.5,5.28350169 22.7164983,4.5 21.75,4.5 Z\"></path>\n                    </g>\n                  </g>\n                </svg></i>\n              <!---->\n              <!---->\n            </div>\n          </div>\n          <!---->\n          <!---->\n          <div class=\"n-input__border\"></div>\n          <div class=\"n-input__state-border\"></div>\n          <!---->\n        </div>\n        <!---->\n      </div>\n      <div class=\"n-date-picker\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-icon-color-override: rgba(194, 194, 194, 1); --n-icon-color-disabled-override: rgba(209, 209, 209, 1);\">\n        <div class=\"n-input n-input--medium-size n-input--resizable n-input--stateful\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-count-text-color: rgb(118, 124, 130); --n-count-text-color-disabled: rgba(194, 194, 194, 1); --n-color: rgba(255, 255, 255, 1); --n-font-size: 14px; --n-font-weight: 400; --n-border-radius: 3px; --n-height: 34px; --n-padding-left: 12px; --n-padding-right: 12px; --n-text-color: rgb(51, 54, 57); --n-caret-color: #18a058; --n-text-decoration-color: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-focus: 1px solid #36ad6a; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-icon-size: 16px; --n-line-height-textarea: 1.6; --n-color-disabled: rgb(250, 250, 252); --n-color-focus: rgba(255, 255, 255, 1); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-loading-color: #18a058; --n-caret-color-warning: #f0a020; --n-color-focus-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-loading-color-warning: #f0a020; --n-caret-color-error: #d03050; --n-color-focus-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-loading-color-error: #d03050; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-size: 16px; --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-icon-color-hover: rgba(146, 146, 146, 1); --n-icon-color-pressed: rgba(175, 175, 175, 1); --n-icon-color-disabled: rgba(209, 209, 209, 1); --n-suffix-text-color: rgb(51, 54, 57);\" tabindex=\"0\">\n          <div class=\"n-input-wrapper\">\n            <!---->\n            <div class=\"n-input__input\"><input type=\"text\" class=\"n-input__input-el\" tabindex=\"-1\" placeholder=\"Выбрать дату и время\" size=\"20\" value=\"1970-01-01 08:00:00\">\n              <!---->\n              <!---->\n            </div>\n            <div class=\"n-input__suffix\">\n              <!---->\n              <!---->\n              <!----><i class=\"n-base-icon n-date-picker-icon\"><svg width=\"28px\" height=\"28px\" viewBox=\"0 0 28 28\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n                  <g stroke=\"none\" stroke-width=\"1\" fill-rule=\"evenodd\">\n                    <g fill-rule=\"nonzero\">\n                      <path d=\"M21.75,3 C23.5449254,3 25,4.45507456 25,6.25 L25,21.75 C25,23.5449254 23.5449254,25 21.75,25 L6.25,25 C4.45507456,25 3,23.5449254 3,21.75 L3,6.25 C3,4.45507456 4.45507456,3 6.25,3 L21.75,3 Z M23.5,9.503 L4.5,9.503 L4.5,21.75 C4.5,22.7164983 5.28350169,23.5 6.25,23.5 L21.75,23.5 C22.7164983,23.5 23.5,22.7164983 23.5,21.75 L23.5,9.503 Z M21.75,4.5 L6.25,4.5 C5.28350169,4.5 4.5,5.28350169 4.5,6.25 L4.5,8.003 L23.5,8.003 L23.5,6.25 C23.5,5.28350169 22.7164983,4.5 21.75,4.5 Z\"></path>\n                    </g>\n                  </g>\n                </svg></i>\n              <!---->\n              <!---->\n            </div>\n          </div>\n          <!---->\n          <!---->\n          <div class=\"n-input__border\"></div>\n          <div class=\"n-input__state-border\"></div>\n          <!---->\n        </div>\n        <!---->\n      </div>\n      <div class=\"n-date-picker\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-icon-color-override: rgba(194, 194, 194, 1); --n-icon-color-disabled-override: rgba(209, 209, 209, 1);\">\n        <div class=\"n-input n-input--medium-size n-input--resizable n-input--stateful\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-count-text-color: rgb(118, 124, 130); --n-count-text-color-disabled: rgba(194, 194, 194, 1); --n-color: rgba(255, 255, 255, 1); --n-font-size: 14px; --n-font-weight: 400; --n-border-radius: 3px; --n-height: 34px; --n-padding-left: 12px; --n-padding-right: 12px; --n-text-color: rgb(51, 54, 57); --n-caret-color: #18a058; --n-text-decoration-color: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-focus: 1px solid #36ad6a; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-icon-size: 16px; --n-line-height-textarea: 1.6; --n-color-disabled: rgb(250, 250, 252); --n-color-focus: rgba(255, 255, 255, 1); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-loading-color: #18a058; --n-caret-color-warning: #f0a020; --n-color-focus-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-loading-color-warning: #f0a020; --n-caret-color-error: #d03050; --n-color-focus-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-loading-color-error: #d03050; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-size: 16px; --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-icon-color-hover: rgba(146, 146, 146, 1); --n-icon-color-pressed: rgba(175, 175, 175, 1); --n-icon-color-disabled: rgba(209, 209, 209, 1); --n-suffix-text-color: rgb(51, 54, 57);\" tabindex=\"0\">\n          <div class=\"n-input-wrapper\">\n            <!---->\n            <div class=\"n-input__input\"><input type=\"text\" class=\"n-input__input-el\" tabindex=\"-1\" placeholder=\"Выберите год\" size=\"20\" value=\"1970\">\n              <!---->\n              <!---->\n            </div>\n            <div class=\"n-input__suffix\">\n              <!---->\n              <!---->\n              <!----><i class=\"n-base-icon n-date-picker-icon\"><svg width=\"28px\" height=\"28px\" viewBox=\"0 0 28 28\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n                  <g stroke=\"none\" stroke-width=\"1\" fill-rule=\"evenodd\">\n                    <g fill-rule=\"nonzero\">\n                      <path d=\"M21.75,3 C23.5449254,3 25,4.45507456 25,6.25 L25,21.75 C25,23.5449254 23.5449254,25 21.75,25 L6.25,25 C4.45507456,25 3,23.5449254 3,21.75 L3,6.25 C3,4.45507456 4.45507456,3 6.25,3 L21.75,3 Z M23.5,9.503 L4.5,9.503 L4.5,21.75 C4.5,22.7164983 5.28350169,23.5 6.25,23.5 L21.75,23.5 C22.7164983,23.5 23.5,22.7164983 23.5,21.75 L23.5,9.503 Z M21.75,4.5 L6.25,4.5 C5.28350169,4.5 4.5,5.28350169 4.5,6.25 L4.5,8.003 L23.5,8.003 L23.5,6.25 C23.5,5.28350169 22.7164983,4.5 21.75,4.5 Z\"></path>\n                    </g>\n                  </g>\n                </svg></i>\n              <!---->\n              <!---->\n            </div>\n          </div>\n          <!---->\n          <!---->\n          <div class=\"n-input__border\"></div>\n          <div class=\"n-input__state-border\"></div>\n          <!---->\n        </div>\n        <!---->\n      </div>\n      <div class=\"n-date-picker\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-icon-color-override: rgba(194, 194, 194, 1); --n-icon-color-disabled-override: rgba(209, 209, 209, 1);\">\n        <div class=\"n-input n-input--medium-size n-input--resizable n-input--stateful\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-count-text-color: rgb(118, 124, 130); --n-count-text-color-disabled: rgba(194, 194, 194, 1); --n-color: rgba(255, 255, 255, 1); --n-font-size: 14px; --n-font-weight: 400; --n-border-radius: 3px; --n-height: 34px; --n-padding-left: 12px; --n-padding-right: 12px; --n-text-color: rgb(51, 54, 57); --n-caret-color: #18a058; --n-text-decoration-color: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-focus: 1px solid #36ad6a; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-icon-size: 16px; --n-line-height-textarea: 1.6; --n-color-disabled: rgb(250, 250, 252); --n-color-focus: rgba(255, 255, 255, 1); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-loading-color: #18a058; --n-caret-color-warning: #f0a020; --n-color-focus-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-loading-color-warning: #f0a020; --n-caret-color-error: #d03050; --n-color-focus-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-loading-color-error: #d03050; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-size: 16px; --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-icon-color-hover: rgba(146, 146, 146, 1); --n-icon-color-pressed: rgba(175, 175, 175, 1); --n-icon-color-disabled: rgba(209, 209, 209, 1); --n-suffix-text-color: rgb(51, 54, 57);\" tabindex=\"0\">\n          <div class=\"n-input-wrapper\">\n            <!---->\n            <div class=\"n-input__input\"><input type=\"text\" class=\"n-input__input-el\" tabindex=\"-1\" placeholder=\"Выберите месяц\" size=\"20\" value=\"1970-01\">\n              <!---->\n              <!---->\n            </div>\n            <div class=\"n-input__suffix\">\n              <!---->\n              <!---->\n              <!----><i class=\"n-base-icon n-date-picker-icon\"><svg width=\"28px\" height=\"28px\" viewBox=\"0 0 28 28\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n                  <g stroke=\"none\" stroke-width=\"1\" fill-rule=\"evenodd\">\n                    <g fill-rule=\"nonzero\">\n                      <path d=\"M21.75,3 C23.5449254,3 25,4.45507456 25,6.25 L25,21.75 C25,23.5449254 23.5449254,25 21.75,25 L6.25,25 C4.45507456,25 3,23.5449254 3,21.75 L3,6.25 C3,4.45507456 4.45507456,3 6.25,3 L21.75,3 Z M23.5,9.503 L4.5,9.503 L4.5,21.75 C4.5,22.7164983 5.28350169,23.5 6.25,23.5 L21.75,23.5 C22.7164983,23.5 23.5,22.7164983 23.5,21.75 L23.5,9.503 Z M21.75,4.5 L6.25,4.5 C5.28350169,4.5 4.5,5.28350169 4.5,6.25 L4.5,8.003 L23.5,8.003 L23.5,6.25 C23.5,5.28350169 22.7164983,4.5 21.75,4.5 Z\"></path>\n                    </g>\n                  </g>\n                </svg></i>\n              <!---->\n              <!---->\n            </div>\n          </div>\n          <!---->\n          <!---->\n          <div class=\"n-input__border\"></div>\n          <div class=\"n-input__state-border\"></div>\n          <!---->\n        </div>\n        <!---->\n      </div>\n    </div>\n  </div>\n</div>\"\n`;\n\nexports[`locale > works 5`] = `\n\"<div class=\"n-config-provider\">\n  <div>\n    <div class=\"n-input n-input--medium-size n-input--resizable n-input--stateful\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-count-text-color: rgb(118, 124, 130); --n-count-text-color-disabled: rgba(194, 194, 194, 1); --n-color: rgba(255, 255, 255, 1); --n-font-size: 14px; --n-font-weight: 400; --n-border-radius: 3px; --n-height: 34px; --n-padding-left: 12px; --n-padding-right: 12px; --n-text-color: rgb(51, 54, 57); --n-caret-color: #18a058; --n-text-decoration-color: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-focus: 1px solid #36ad6a; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-icon-size: 16px; --n-line-height-textarea: 1.6; --n-color-disabled: rgb(250, 250, 252); --n-color-focus: rgba(255, 255, 255, 1); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-loading-color: #18a058; --n-caret-color-warning: #f0a020; --n-color-focus-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-loading-color-warning: #f0a020; --n-caret-color-error: #d03050; --n-color-focus-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-loading-color-error: #d03050; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-size: 16px; --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-icon-color-hover: rgba(146, 146, 146, 1); --n-icon-color-pressed: rgba(175, 175, 175, 1); --n-icon-color-disabled: rgba(209, 209, 209, 1); --n-suffix-text-color: rgb(51, 54, 57);\">\n      <div class=\"n-input-wrapper\">\n        <!---->\n        <div class=\"n-input__input\"><input type=\"text\" class=\"n-input__input-el\" placeholder=\"Ввести\" size=\"20\">\n          <div class=\"n-input__placeholder\"><span>Ввести</span></div>\n          <!---->\n        </div>\n        <!---->\n      </div>\n      <!---->\n      <!---->\n      <div class=\"n-input__border\"></div>\n      <div class=\"n-input__state-border\"></div>\n      <!---->\n    </div>\n    <div>\n      <div class=\"n-date-picker\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-icon-color-override: rgba(194, 194, 194, 1); --n-icon-color-disabled-override: rgba(209, 209, 209, 1);\">\n        <div class=\"n-input n-input--medium-size n-input--resizable n-input--stateful\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-count-text-color: rgb(118, 124, 130); --n-count-text-color-disabled: rgba(194, 194, 194, 1); --n-color: rgba(255, 255, 255, 1); --n-font-size: 14px; --n-font-weight: 400; --n-border-radius: 3px; --n-height: 34px; --n-padding-left: 12px; --n-padding-right: 12px; --n-text-color: rgb(51, 54, 57); --n-caret-color: #18a058; --n-text-decoration-color: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-focus: 1px solid #36ad6a; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-icon-size: 16px; --n-line-height-textarea: 1.6; --n-color-disabled: rgb(250, 250, 252); --n-color-focus: rgba(255, 255, 255, 1); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-loading-color: #18a058; --n-caret-color-warning: #f0a020; --n-color-focus-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-loading-color-warning: #f0a020; --n-caret-color-error: #d03050; --n-color-focus-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-loading-color-error: #d03050; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-size: 16px; --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-icon-color-hover: rgba(146, 146, 146, 1); --n-icon-color-pressed: rgba(175, 175, 175, 1); --n-icon-color-disabled: rgba(209, 209, 209, 1); --n-suffix-text-color: rgb(51, 54, 57);\" tabindex=\"0\">\n          <div class=\"n-input-wrapper\">\n            <!---->\n            <div class=\"n-input__input\"><input type=\"text\" class=\"n-input__input-el\" tabindex=\"-1\" placeholder=\"Обрати дату\" size=\"20\" value=\"1970-01-01\">\n              <!---->\n              <!---->\n            </div>\n            <div class=\"n-input__suffix\">\n              <!---->\n              <!---->\n              <!----><i class=\"n-base-icon n-date-picker-icon\"><svg width=\"28px\" height=\"28px\" viewBox=\"0 0 28 28\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n                  <g stroke=\"none\" stroke-width=\"1\" fill-rule=\"evenodd\">\n                    <g fill-rule=\"nonzero\">\n                      <path d=\"M21.75,3 C23.5449254,3 25,4.45507456 25,6.25 L25,21.75 C25,23.5449254 23.5449254,25 21.75,25 L6.25,25 C4.45507456,25 3,23.5449254 3,21.75 L3,6.25 C3,4.45507456 4.45507456,3 6.25,3 L21.75,3 Z M23.5,9.503 L4.5,9.503 L4.5,21.75 C4.5,22.7164983 5.28350169,23.5 6.25,23.5 L21.75,23.5 C22.7164983,23.5 23.5,22.7164983 23.5,21.75 L23.5,9.503 Z M21.75,4.5 L6.25,4.5 C5.28350169,4.5 4.5,5.28350169 4.5,6.25 L4.5,8.003 L23.5,8.003 L23.5,6.25 C23.5,5.28350169 22.7164983,4.5 21.75,4.5 Z\"></path>\n                    </g>\n                  </g>\n                </svg></i>\n              <!---->\n              <!---->\n            </div>\n          </div>\n          <!---->\n          <!---->\n          <div class=\"n-input__border\"></div>\n          <div class=\"n-input__state-border\"></div>\n          <!---->\n        </div>\n        <!---->\n      </div>\n      <div class=\"n-date-picker\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-icon-color-override: rgba(194, 194, 194, 1); --n-icon-color-disabled-override: rgba(209, 209, 209, 1);\">\n        <div class=\"n-input n-input--medium-size n-input--resizable n-input--stateful\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-count-text-color: rgb(118, 124, 130); --n-count-text-color-disabled: rgba(194, 194, 194, 1); --n-color: rgba(255, 255, 255, 1); --n-font-size: 14px; --n-font-weight: 400; --n-border-radius: 3px; --n-height: 34px; --n-padding-left: 12px; --n-padding-right: 12px; --n-text-color: rgb(51, 54, 57); --n-caret-color: #18a058; --n-text-decoration-color: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-focus: 1px solid #36ad6a; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-icon-size: 16px; --n-line-height-textarea: 1.6; --n-color-disabled: rgb(250, 250, 252); --n-color-focus: rgba(255, 255, 255, 1); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-loading-color: #18a058; --n-caret-color-warning: #f0a020; --n-color-focus-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-loading-color-warning: #f0a020; --n-caret-color-error: #d03050; --n-color-focus-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-loading-color-error: #d03050; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-size: 16px; --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-icon-color-hover: rgba(146, 146, 146, 1); --n-icon-color-pressed: rgba(175, 175, 175, 1); --n-icon-color-disabled: rgba(209, 209, 209, 1); --n-suffix-text-color: rgb(51, 54, 57);\" tabindex=\"0\">\n          <div class=\"n-input-wrapper\">\n            <!---->\n            <div class=\"n-input__input\"><input type=\"text\" class=\"n-input__input-el\" tabindex=\"-1\" placeholder=\"Обрати дату і час\" size=\"20\" value=\"1970-01-01 08:00:00\">\n              <!---->\n              <!---->\n            </div>\n            <div class=\"n-input__suffix\">\n              <!---->\n              <!---->\n              <!----><i class=\"n-base-icon n-date-picker-icon\"><svg width=\"28px\" height=\"28px\" viewBox=\"0 0 28 28\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n                  <g stroke=\"none\" stroke-width=\"1\" fill-rule=\"evenodd\">\n                    <g fill-rule=\"nonzero\">\n                      <path d=\"M21.75,3 C23.5449254,3 25,4.45507456 25,6.25 L25,21.75 C25,23.5449254 23.5449254,25 21.75,25 L6.25,25 C4.45507456,25 3,23.5449254 3,21.75 L3,6.25 C3,4.45507456 4.45507456,3 6.25,3 L21.75,3 Z M23.5,9.503 L4.5,9.503 L4.5,21.75 C4.5,22.7164983 5.28350169,23.5 6.25,23.5 L21.75,23.5 C22.7164983,23.5 23.5,22.7164983 23.5,21.75 L23.5,9.503 Z M21.75,4.5 L6.25,4.5 C5.28350169,4.5 4.5,5.28350169 4.5,6.25 L4.5,8.003 L23.5,8.003 L23.5,6.25 C23.5,5.28350169 22.7164983,4.5 21.75,4.5 Z\"></path>\n                    </g>\n                  </g>\n                </svg></i>\n              <!---->\n              <!---->\n            </div>\n          </div>\n          <!---->\n          <!---->\n          <div class=\"n-input__border\"></div>\n          <div class=\"n-input__state-border\"></div>\n          <!---->\n        </div>\n        <!---->\n      </div>\n      <div class=\"n-date-picker\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-icon-color-override: rgba(194, 194, 194, 1); --n-icon-color-disabled-override: rgba(209, 209, 209, 1);\">\n        <div class=\"n-input n-input--medium-size n-input--resizable n-input--stateful\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-count-text-color: rgb(118, 124, 130); --n-count-text-color-disabled: rgba(194, 194, 194, 1); --n-color: rgba(255, 255, 255, 1); --n-font-size: 14px; --n-font-weight: 400; --n-border-radius: 3px; --n-height: 34px; --n-padding-left: 12px; --n-padding-right: 12px; --n-text-color: rgb(51, 54, 57); --n-caret-color: #18a058; --n-text-decoration-color: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-focus: 1px solid #36ad6a; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-icon-size: 16px; --n-line-height-textarea: 1.6; --n-color-disabled: rgb(250, 250, 252); --n-color-focus: rgba(255, 255, 255, 1); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-loading-color: #18a058; --n-caret-color-warning: #f0a020; --n-color-focus-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-loading-color-warning: #f0a020; --n-caret-color-error: #d03050; --n-color-focus-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-loading-color-error: #d03050; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-size: 16px; --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-icon-color-hover: rgba(146, 146, 146, 1); --n-icon-color-pressed: rgba(175, 175, 175, 1); --n-icon-color-disabled: rgba(209, 209, 209, 1); --n-suffix-text-color: rgb(51, 54, 57);\" tabindex=\"0\">\n          <div class=\"n-input-wrapper\">\n            <!---->\n            <div class=\"n-input__input\"><input type=\"text\" class=\"n-input__input-el\" tabindex=\"-1\" placeholder=\"Оберіть рік\" size=\"20\" value=\"1970\">\n              <!---->\n              <!---->\n            </div>\n            <div class=\"n-input__suffix\">\n              <!---->\n              <!---->\n              <!----><i class=\"n-base-icon n-date-picker-icon\"><svg width=\"28px\" height=\"28px\" viewBox=\"0 0 28 28\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n                  <g stroke=\"none\" stroke-width=\"1\" fill-rule=\"evenodd\">\n                    <g fill-rule=\"nonzero\">\n                      <path d=\"M21.75,3 C23.5449254,3 25,4.45507456 25,6.25 L25,21.75 C25,23.5449254 23.5449254,25 21.75,25 L6.25,25 C4.45507456,25 3,23.5449254 3,21.75 L3,6.25 C3,4.45507456 4.45507456,3 6.25,3 L21.75,3 Z M23.5,9.503 L4.5,9.503 L4.5,21.75 C4.5,22.7164983 5.28350169,23.5 6.25,23.5 L21.75,23.5 C22.7164983,23.5 23.5,22.7164983 23.5,21.75 L23.5,9.503 Z M21.75,4.5 L6.25,4.5 C5.28350169,4.5 4.5,5.28350169 4.5,6.25 L4.5,8.003 L23.5,8.003 L23.5,6.25 C23.5,5.28350169 22.7164983,4.5 21.75,4.5 Z\"></path>\n                    </g>\n                  </g>\n                </svg></i>\n              <!---->\n              <!---->\n            </div>\n          </div>\n          <!---->\n          <!---->\n          <div class=\"n-input__border\"></div>\n          <div class=\"n-input__state-border\"></div>\n          <!---->\n        </div>\n        <!---->\n      </div>\n      <div class=\"n-date-picker\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-icon-color-override: rgba(194, 194, 194, 1); --n-icon-color-disabled-override: rgba(209, 209, 209, 1);\">\n        <div class=\"n-input n-input--medium-size n-input--resizable n-input--stateful\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-count-text-color: rgb(118, 124, 130); --n-count-text-color-disabled: rgba(194, 194, 194, 1); --n-color: rgba(255, 255, 255, 1); --n-font-size: 14px; --n-font-weight: 400; --n-border-radius: 3px; --n-height: 34px; --n-padding-left: 12px; --n-padding-right: 12px; --n-text-color: rgb(51, 54, 57); --n-caret-color: #18a058; --n-text-decoration-color: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-focus: 1px solid #36ad6a; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-icon-size: 16px; --n-line-height-textarea: 1.6; --n-color-disabled: rgb(250, 250, 252); --n-color-focus: rgba(255, 255, 255, 1); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-loading-color: #18a058; --n-caret-color-warning: #f0a020; --n-color-focus-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-loading-color-warning: #f0a020; --n-caret-color-error: #d03050; --n-color-focus-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-loading-color-error: #d03050; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-size: 16px; --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-icon-color-hover: rgba(146, 146, 146, 1); --n-icon-color-pressed: rgba(175, 175, 175, 1); --n-icon-color-disabled: rgba(209, 209, 209, 1); --n-suffix-text-color: rgb(51, 54, 57);\" tabindex=\"0\">\n          <div class=\"n-input-wrapper\">\n            <!---->\n            <div class=\"n-input__input\"><input type=\"text\" class=\"n-input__input-el\" tabindex=\"-1\" placeholder=\"Оберіть місяць\" size=\"20\" value=\"1970-01\">\n              <!---->\n              <!---->\n            </div>\n            <div class=\"n-input__suffix\">\n              <!---->\n              <!---->\n              <!----><i class=\"n-base-icon n-date-picker-icon\"><svg width=\"28px\" height=\"28px\" viewBox=\"0 0 28 28\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n                  <g stroke=\"none\" stroke-width=\"1\" fill-rule=\"evenodd\">\n                    <g fill-rule=\"nonzero\">\n                      <path d=\"M21.75,3 C23.5449254,3 25,4.45507456 25,6.25 L25,21.75 C25,23.5449254 23.5449254,25 21.75,25 L6.25,25 C4.45507456,25 3,23.5449254 3,21.75 L3,6.25 C3,4.45507456 4.45507456,3 6.25,3 L21.75,3 Z M23.5,9.503 L4.5,9.503 L4.5,21.75 C4.5,22.7164983 5.28350169,23.5 6.25,23.5 L21.75,23.5 C22.7164983,23.5 23.5,22.7164983 23.5,21.75 L23.5,9.503 Z M21.75,4.5 L6.25,4.5 C5.28350169,4.5 4.5,5.28350169 4.5,6.25 L4.5,8.003 L23.5,8.003 L23.5,6.25 C23.5,5.28350169 22.7164983,4.5 21.75,4.5 Z\"></path>\n                    </g>\n                  </g>\n                </svg></i>\n              <!---->\n              <!---->\n            </div>\n          </div>\n          <!---->\n          <!---->\n          <div class=\"n-input__border\"></div>\n          <div class=\"n-input__state-border\"></div>\n          <!---->\n        </div>\n        <!---->\n      </div>\n    </div>\n  </div>\n</div>\"\n`;\n\nexports[`locale > works 6`] = `\n\"<div class=\"n-config-provider\">\n  <div>\n    <div class=\"n-input n-input--medium-size n-input--resizable n-input--stateful\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-count-text-color: rgb(118, 124, 130); --n-count-text-color-disabled: rgba(194, 194, 194, 1); --n-color: rgba(255, 255, 255, 1); --n-font-size: 14px; --n-font-weight: 400; --n-border-radius: 3px; --n-height: 34px; --n-padding-left: 12px; --n-padding-right: 12px; --n-text-color: rgb(51, 54, 57); --n-caret-color: #18a058; --n-text-decoration-color: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-focus: 1px solid #36ad6a; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-icon-size: 16px; --n-line-height-textarea: 1.6; --n-color-disabled: rgb(250, 250, 252); --n-color-focus: rgba(255, 255, 255, 1); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-loading-color: #18a058; --n-caret-color-warning: #f0a020; --n-color-focus-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-loading-color-warning: #f0a020; --n-caret-color-error: #d03050; --n-color-focus-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-loading-color-error: #d03050; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-size: 16px; --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-icon-color-hover: rgba(146, 146, 146, 1); --n-icon-color-pressed: rgba(175, 175, 175, 1); --n-icon-color-disabled: rgba(209, 209, 209, 1); --n-suffix-text-color: rgb(51, 54, 57);\">\n      <div class=\"n-input-wrapper\">\n        <!---->\n        <div class=\"n-input__input\"><input type=\"text\" class=\"n-input__input-el\" placeholder=\"Kiriting\" size=\"20\">\n          <div class=\"n-input__placeholder\"><span>Kiriting</span></div>\n          <!---->\n        </div>\n        <!---->\n      </div>\n      <!---->\n      <!---->\n      <div class=\"n-input__border\"></div>\n      <div class=\"n-input__state-border\"></div>\n      <!---->\n    </div>\n    <div>\n      <div class=\"n-date-picker\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-icon-color-override: rgba(194, 194, 194, 1); --n-icon-color-disabled-override: rgba(209, 209, 209, 1);\">\n        <div class=\"n-input n-input--medium-size n-input--resizable n-input--stateful\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-count-text-color: rgb(118, 124, 130); --n-count-text-color-disabled: rgba(194, 194, 194, 1); --n-color: rgba(255, 255, 255, 1); --n-font-size: 14px; --n-font-weight: 400; --n-border-radius: 3px; --n-height: 34px; --n-padding-left: 12px; --n-padding-right: 12px; --n-text-color: rgb(51, 54, 57); --n-caret-color: #18a058; --n-text-decoration-color: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-focus: 1px solid #36ad6a; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-icon-size: 16px; --n-line-height-textarea: 1.6; --n-color-disabled: rgb(250, 250, 252); --n-color-focus: rgba(255, 255, 255, 1); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-loading-color: #18a058; --n-caret-color-warning: #f0a020; --n-color-focus-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-loading-color-warning: #f0a020; --n-caret-color-error: #d03050; --n-color-focus-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-loading-color-error: #d03050; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-size: 16px; --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-icon-color-hover: rgba(146, 146, 146, 1); --n-icon-color-pressed: rgba(175, 175, 175, 1); --n-icon-color-disabled: rgba(209, 209, 209, 1); --n-suffix-text-color: rgb(51, 54, 57);\" tabindex=\"0\">\n          <div class=\"n-input-wrapper\">\n            <!---->\n            <div class=\"n-input__input\"><input type=\"text\" class=\"n-input__input-el\" tabindex=\"-1\" placeholder=\"Sana tanlash\" size=\"20\" value=\"1970-01-01\">\n              <!---->\n              <!---->\n            </div>\n            <div class=\"n-input__suffix\">\n              <!---->\n              <!---->\n              <!----><i class=\"n-base-icon n-date-picker-icon\"><svg width=\"28px\" height=\"28px\" viewBox=\"0 0 28 28\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n                  <g stroke=\"none\" stroke-width=\"1\" fill-rule=\"evenodd\">\n                    <g fill-rule=\"nonzero\">\n                      <path d=\"M21.75,3 C23.5449254,3 25,4.45507456 25,6.25 L25,21.75 C25,23.5449254 23.5449254,25 21.75,25 L6.25,25 C4.45507456,25 3,23.5449254 3,21.75 L3,6.25 C3,4.45507456 4.45507456,3 6.25,3 L21.75,3 Z M23.5,9.503 L4.5,9.503 L4.5,21.75 C4.5,22.7164983 5.28350169,23.5 6.25,23.5 L21.75,23.5 C22.7164983,23.5 23.5,22.7164983 23.5,21.75 L23.5,9.503 Z M21.75,4.5 L6.25,4.5 C5.28350169,4.5 4.5,5.28350169 4.5,6.25 L4.5,8.003 L23.5,8.003 L23.5,6.25 C23.5,5.28350169 22.7164983,4.5 21.75,4.5 Z\"></path>\n                    </g>\n                  </g>\n                </svg></i>\n              <!---->\n              <!---->\n            </div>\n          </div>\n          <!---->\n          <!---->\n          <div class=\"n-input__border\"></div>\n          <div class=\"n-input__state-border\"></div>\n          <!---->\n        </div>\n        <!---->\n      </div>\n      <div class=\"n-date-picker\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-icon-color-override: rgba(194, 194, 194, 1); --n-icon-color-disabled-override: rgba(209, 209, 209, 1);\">\n        <div class=\"n-input n-input--medium-size n-input--resizable n-input--stateful\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-count-text-color: rgb(118, 124, 130); --n-count-text-color-disabled: rgba(194, 194, 194, 1); --n-color: rgba(255, 255, 255, 1); --n-font-size: 14px; --n-font-weight: 400; --n-border-radius: 3px; --n-height: 34px; --n-padding-left: 12px; --n-padding-right: 12px; --n-text-color: rgb(51, 54, 57); --n-caret-color: #18a058; --n-text-decoration-color: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-focus: 1px solid #36ad6a; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-icon-size: 16px; --n-line-height-textarea: 1.6; --n-color-disabled: rgb(250, 250, 252); --n-color-focus: rgba(255, 255, 255, 1); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-loading-color: #18a058; --n-caret-color-warning: #f0a020; --n-color-focus-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-loading-color-warning: #f0a020; --n-caret-color-error: #d03050; --n-color-focus-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-loading-color-error: #d03050; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-size: 16px; --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-icon-color-hover: rgba(146, 146, 146, 1); --n-icon-color-pressed: rgba(175, 175, 175, 1); --n-icon-color-disabled: rgba(209, 209, 209, 1); --n-suffix-text-color: rgb(51, 54, 57);\" tabindex=\"0\">\n          <div class=\"n-input-wrapper\">\n            <!---->\n            <div class=\"n-input__input\"><input type=\"text\" class=\"n-input__input-el\" tabindex=\"-1\" placeholder=\"Sana va vaqtni tanlash\" size=\"20\" value=\"1970-01-01 08:00:00\">\n              <!---->\n              <!---->\n            </div>\n            <div class=\"n-input__suffix\">\n              <!---->\n              <!---->\n              <!----><i class=\"n-base-icon n-date-picker-icon\"><svg width=\"28px\" height=\"28px\" viewBox=\"0 0 28 28\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n                  <g stroke=\"none\" stroke-width=\"1\" fill-rule=\"evenodd\">\n                    <g fill-rule=\"nonzero\">\n                      <path d=\"M21.75,3 C23.5449254,3 25,4.45507456 25,6.25 L25,21.75 C25,23.5449254 23.5449254,25 21.75,25 L6.25,25 C4.45507456,25 3,23.5449254 3,21.75 L3,6.25 C3,4.45507456 4.45507456,3 6.25,3 L21.75,3 Z M23.5,9.503 L4.5,9.503 L4.5,21.75 C4.5,22.7164983 5.28350169,23.5 6.25,23.5 L21.75,23.5 C22.7164983,23.5 23.5,22.7164983 23.5,21.75 L23.5,9.503 Z M21.75,4.5 L6.25,4.5 C5.28350169,4.5 4.5,5.28350169 4.5,6.25 L4.5,8.003 L23.5,8.003 L23.5,6.25 C23.5,5.28350169 22.7164983,4.5 21.75,4.5 Z\"></path>\n                    </g>\n                  </g>\n                </svg></i>\n              <!---->\n              <!---->\n            </div>\n          </div>\n          <!---->\n          <!---->\n          <div class=\"n-input__border\"></div>\n          <div class=\"n-input__state-border\"></div>\n          <!---->\n        </div>\n        <!---->\n      </div>\n      <div class=\"n-date-picker\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-icon-color-override: rgba(194, 194, 194, 1); --n-icon-color-disabled-override: rgba(209, 209, 209, 1);\">\n        <div class=\"n-input n-input--medium-size n-input--resizable n-input--stateful\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-count-text-color: rgb(118, 124, 130); --n-count-text-color-disabled: rgba(194, 194, 194, 1); --n-color: rgba(255, 255, 255, 1); --n-font-size: 14px; --n-font-weight: 400; --n-border-radius: 3px; --n-height: 34px; --n-padding-left: 12px; --n-padding-right: 12px; --n-text-color: rgb(51, 54, 57); --n-caret-color: #18a058; --n-text-decoration-color: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-focus: 1px solid #36ad6a; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-icon-size: 16px; --n-line-height-textarea: 1.6; --n-color-disabled: rgb(250, 250, 252); --n-color-focus: rgba(255, 255, 255, 1); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-loading-color: #18a058; --n-caret-color-warning: #f0a020; --n-color-focus-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-loading-color-warning: #f0a020; --n-caret-color-error: #d03050; --n-color-focus-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-loading-color-error: #d03050; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-size: 16px; --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-icon-color-hover: rgba(146, 146, 146, 1); --n-icon-color-pressed: rgba(175, 175, 175, 1); --n-icon-color-disabled: rgba(209, 209, 209, 1); --n-suffix-text-color: rgb(51, 54, 57);\" tabindex=\"0\">\n          <div class=\"n-input-wrapper\">\n            <!---->\n            <div class=\"n-input__input\"><input type=\"text\" class=\"n-input__input-el\" tabindex=\"-1\" placeholder=\"Yil tanlash\" size=\"20\" value=\"1970\">\n              <!---->\n              <!---->\n            </div>\n            <div class=\"n-input__suffix\">\n              <!---->\n              <!---->\n              <!----><i class=\"n-base-icon n-date-picker-icon\"><svg width=\"28px\" height=\"28px\" viewBox=\"0 0 28 28\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n                  <g stroke=\"none\" stroke-width=\"1\" fill-rule=\"evenodd\">\n                    <g fill-rule=\"nonzero\">\n                      <path d=\"M21.75,3 C23.5449254,3 25,4.45507456 25,6.25 L25,21.75 C25,23.5449254 23.5449254,25 21.75,25 L6.25,25 C4.45507456,25 3,23.5449254 3,21.75 L3,6.25 C3,4.45507456 4.45507456,3 6.25,3 L21.75,3 Z M23.5,9.503 L4.5,9.503 L4.5,21.75 C4.5,22.7164983 5.28350169,23.5 6.25,23.5 L21.75,23.5 C22.7164983,23.5 23.5,22.7164983 23.5,21.75 L23.5,9.503 Z M21.75,4.5 L6.25,4.5 C5.28350169,4.5 4.5,5.28350169 4.5,6.25 L4.5,8.003 L23.5,8.003 L23.5,6.25 C23.5,5.28350169 22.7164983,4.5 21.75,4.5 Z\"></path>\n                    </g>\n                  </g>\n                </svg></i>\n              <!---->\n              <!---->\n            </div>\n          </div>\n          <!---->\n          <!---->\n          <div class=\"n-input__border\"></div>\n          <div class=\"n-input__state-border\"></div>\n          <!---->\n        </div>\n        <!---->\n      </div>\n      <div class=\"n-date-picker\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-icon-color-override: rgba(194, 194, 194, 1); --n-icon-color-disabled-override: rgba(209, 209, 209, 1);\">\n        <div class=\"n-input n-input--medium-size n-input--resizable n-input--stateful\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-count-text-color: rgb(118, 124, 130); --n-count-text-color-disabled: rgba(194, 194, 194, 1); --n-color: rgba(255, 255, 255, 1); --n-font-size: 14px; --n-font-weight: 400; --n-border-radius: 3px; --n-height: 34px; --n-padding-left: 12px; --n-padding-right: 12px; --n-text-color: rgb(51, 54, 57); --n-caret-color: #18a058; --n-text-decoration-color: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-focus: 1px solid #36ad6a; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-icon-size: 16px; --n-line-height-textarea: 1.6; --n-color-disabled: rgb(250, 250, 252); --n-color-focus: rgba(255, 255, 255, 1); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-loading-color: #18a058; --n-caret-color-warning: #f0a020; --n-color-focus-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-loading-color-warning: #f0a020; --n-caret-color-error: #d03050; --n-color-focus-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-loading-color-error: #d03050; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-size: 16px; --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-icon-color-hover: rgba(146, 146, 146, 1); --n-icon-color-pressed: rgba(175, 175, 175, 1); --n-icon-color-disabled: rgba(209, 209, 209, 1); --n-suffix-text-color: rgb(51, 54, 57);\" tabindex=\"0\">\n          <div class=\"n-input-wrapper\">\n            <!---->\n            <div class=\"n-input__input\"><input type=\"text\" class=\"n-input__input-el\" tabindex=\"-1\" placeholder=\"Oy tanlash\" size=\"20\" value=\"1970-01\">\n              <!---->\n              <!---->\n            </div>\n            <div class=\"n-input__suffix\">\n              <!---->\n              <!---->\n              <!----><i class=\"n-base-icon n-date-picker-icon\"><svg width=\"28px\" height=\"28px\" viewBox=\"0 0 28 28\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n                  <g stroke=\"none\" stroke-width=\"1\" fill-rule=\"evenodd\">\n                    <g fill-rule=\"nonzero\">\n                      <path d=\"M21.75,3 C23.5449254,3 25,4.45507456 25,6.25 L25,21.75 C25,23.5449254 23.5449254,25 21.75,25 L6.25,25 C4.45507456,25 3,23.5449254 3,21.75 L3,6.25 C3,4.45507456 4.45507456,3 6.25,3 L21.75,3 Z M23.5,9.503 L4.5,9.503 L4.5,21.75 C4.5,22.7164983 5.28350169,23.5 6.25,23.5 L21.75,23.5 C22.7164983,23.5 23.5,22.7164983 23.5,21.75 L23.5,9.503 Z M21.75,4.5 L6.25,4.5 C5.28350169,4.5 4.5,5.28350169 4.5,6.25 L4.5,8.003 L23.5,8.003 L23.5,6.25 C23.5,5.28350169 22.7164983,4.5 21.75,4.5 Z\"></path>\n                    </g>\n                  </g>\n                </svg></i>\n              <!---->\n              <!---->\n            </div>\n          </div>\n          <!---->\n          <!---->\n          <div class=\"n-input__border\"></div>\n          <div class=\"n-input__state-border\"></div>\n          <!---->\n        </div>\n        <!---->\n      </div>\n    </div>\n  </div>\n</div>\"\n`;\n\nexports[`locale > works 7`] = `\n\"<div class=\"n-config-provider\">\n  <div>\n    <div class=\"n-input n-input--medium-size n-input--resizable n-input--stateful\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-count-text-color: rgb(118, 124, 130); --n-count-text-color-disabled: rgba(194, 194, 194, 1); --n-color: rgba(255, 255, 255, 1); --n-font-size: 14px; --n-font-weight: 400; --n-border-radius: 3px; --n-height: 34px; --n-padding-left: 12px; --n-padding-right: 12px; --n-text-color: rgb(51, 54, 57); --n-caret-color: #18a058; --n-text-decoration-color: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-focus: 1px solid #36ad6a; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-icon-size: 16px; --n-line-height-textarea: 1.6; --n-color-disabled: rgb(250, 250, 252); --n-color-focus: rgba(255, 255, 255, 1); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-loading-color: #18a058; --n-caret-color-warning: #f0a020; --n-color-focus-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-loading-color-warning: #f0a020; --n-caret-color-error: #d03050; --n-color-focus-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-loading-color-error: #d03050; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-size: 16px; --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-icon-color-hover: rgba(146, 146, 146, 1); --n-icon-color-pressed: rgba(175, 175, 175, 1); --n-icon-color-disabled: rgba(209, 209, 209, 1); --n-suffix-text-color: rgb(51, 54, 57);\">\n      <div class=\"n-input-wrapper\">\n        <!---->\n        <div class=\"n-input__input\"><input type=\"text\" class=\"n-input__input-el\" placeholder=\"入力してください\" size=\"20\">\n          <div class=\"n-input__placeholder\"><span>入力してください</span></div>\n          <!---->\n        </div>\n        <!---->\n      </div>\n      <!---->\n      <!---->\n      <div class=\"n-input__border\"></div>\n      <div class=\"n-input__state-border\"></div>\n      <!---->\n    </div>\n    <div>\n      <div class=\"n-date-picker\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-icon-color-override: rgba(194, 194, 194, 1); --n-icon-color-disabled-override: rgba(209, 209, 209, 1);\">\n        <div class=\"n-input n-input--medium-size n-input--resizable n-input--stateful\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-count-text-color: rgb(118, 124, 130); --n-count-text-color-disabled: rgba(194, 194, 194, 1); --n-color: rgba(255, 255, 255, 1); --n-font-size: 14px; --n-font-weight: 400; --n-border-radius: 3px; --n-height: 34px; --n-padding-left: 12px; --n-padding-right: 12px; --n-text-color: rgb(51, 54, 57); --n-caret-color: #18a058; --n-text-decoration-color: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-focus: 1px solid #36ad6a; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-icon-size: 16px; --n-line-height-textarea: 1.6; --n-color-disabled: rgb(250, 250, 252); --n-color-focus: rgba(255, 255, 255, 1); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-loading-color: #18a058; --n-caret-color-warning: #f0a020; --n-color-focus-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-loading-color-warning: #f0a020; --n-caret-color-error: #d03050; --n-color-focus-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-loading-color-error: #d03050; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-size: 16px; --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-icon-color-hover: rgba(146, 146, 146, 1); --n-icon-color-pressed: rgba(175, 175, 175, 1); --n-icon-color-disabled: rgba(209, 209, 209, 1); --n-suffix-text-color: rgb(51, 54, 57);\" tabindex=\"0\">\n          <div class=\"n-input-wrapper\">\n            <!---->\n            <div class=\"n-input__input\"><input type=\"text\" class=\"n-input__input-el\" tabindex=\"-1\" placeholder=\"日付を選択\" size=\"20\" value=\"1970-01-01\">\n              <!---->\n              <!---->\n            </div>\n            <div class=\"n-input__suffix\">\n              <!---->\n              <!---->\n              <!----><i class=\"n-base-icon n-date-picker-icon\"><svg width=\"28px\" height=\"28px\" viewBox=\"0 0 28 28\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n                  <g stroke=\"none\" stroke-width=\"1\" fill-rule=\"evenodd\">\n                    <g fill-rule=\"nonzero\">\n                      <path d=\"M21.75,3 C23.5449254,3 25,4.45507456 25,6.25 L25,21.75 C25,23.5449254 23.5449254,25 21.75,25 L6.25,25 C4.45507456,25 3,23.5449254 3,21.75 L3,6.25 C3,4.45507456 4.45507456,3 6.25,3 L21.75,3 Z M23.5,9.503 L4.5,9.503 L4.5,21.75 C4.5,22.7164983 5.28350169,23.5 6.25,23.5 L21.75,23.5 C22.7164983,23.5 23.5,22.7164983 23.5,21.75 L23.5,9.503 Z M21.75,4.5 L6.25,4.5 C5.28350169,4.5 4.5,5.28350169 4.5,6.25 L4.5,8.003 L23.5,8.003 L23.5,6.25 C23.5,5.28350169 22.7164983,4.5 21.75,4.5 Z\"></path>\n                    </g>\n                  </g>\n                </svg></i>\n              <!---->\n              <!---->\n            </div>\n          </div>\n          <!---->\n          <!---->\n          <div class=\"n-input__border\"></div>\n          <div class=\"n-input__state-border\"></div>\n          <!---->\n        </div>\n        <!---->\n      </div>\n      <div class=\"n-date-picker\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-icon-color-override: rgba(194, 194, 194, 1); --n-icon-color-disabled-override: rgba(209, 209, 209, 1);\">\n        <div class=\"n-input n-input--medium-size n-input--resizable n-input--stateful\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-count-text-color: rgb(118, 124, 130); --n-count-text-color-disabled: rgba(194, 194, 194, 1); --n-color: rgba(255, 255, 255, 1); --n-font-size: 14px; --n-font-weight: 400; --n-border-radius: 3px; --n-height: 34px; --n-padding-left: 12px; --n-padding-right: 12px; --n-text-color: rgb(51, 54, 57); --n-caret-color: #18a058; --n-text-decoration-color: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-focus: 1px solid #36ad6a; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-icon-size: 16px; --n-line-height-textarea: 1.6; --n-color-disabled: rgb(250, 250, 252); --n-color-focus: rgba(255, 255, 255, 1); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-loading-color: #18a058; --n-caret-color-warning: #f0a020; --n-color-focus-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-loading-color-warning: #f0a020; --n-caret-color-error: #d03050; --n-color-focus-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-loading-color-error: #d03050; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-size: 16px; --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-icon-color-hover: rgba(146, 146, 146, 1); --n-icon-color-pressed: rgba(175, 175, 175, 1); --n-icon-color-disabled: rgba(209, 209, 209, 1); --n-suffix-text-color: rgb(51, 54, 57);\" tabindex=\"0\">\n          <div class=\"n-input-wrapper\">\n            <!---->\n            <div class=\"n-input__input\"><input type=\"text\" class=\"n-input__input-el\" tabindex=\"-1\" placeholder=\"選択\" size=\"20\" value=\"1970-01-01 08:00:00\">\n              <!---->\n              <!---->\n            </div>\n            <div class=\"n-input__suffix\">\n              <!---->\n              <!---->\n              <!----><i class=\"n-base-icon n-date-picker-icon\"><svg width=\"28px\" height=\"28px\" viewBox=\"0 0 28 28\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n                  <g stroke=\"none\" stroke-width=\"1\" fill-rule=\"evenodd\">\n                    <g fill-rule=\"nonzero\">\n                      <path d=\"M21.75,3 C23.5449254,3 25,4.45507456 25,6.25 L25,21.75 C25,23.5449254 23.5449254,25 21.75,25 L6.25,25 C4.45507456,25 3,23.5449254 3,21.75 L3,6.25 C3,4.45507456 4.45507456,3 6.25,3 L21.75,3 Z M23.5,9.503 L4.5,9.503 L4.5,21.75 C4.5,22.7164983 5.28350169,23.5 6.25,23.5 L21.75,23.5 C22.7164983,23.5 23.5,22.7164983 23.5,21.75 L23.5,9.503 Z M21.75,4.5 L6.25,4.5 C5.28350169,4.5 4.5,5.28350169 4.5,6.25 L4.5,8.003 L23.5,8.003 L23.5,6.25 C23.5,5.28350169 22.7164983,4.5 21.75,4.5 Z\"></path>\n                    </g>\n                  </g>\n                </svg></i>\n              <!---->\n              <!---->\n            </div>\n          </div>\n          <!---->\n          <!---->\n          <div class=\"n-input__border\"></div>\n          <div class=\"n-input__state-border\"></div>\n          <!---->\n        </div>\n        <!---->\n      </div>\n      <div class=\"n-date-picker\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-icon-color-override: rgba(194, 194, 194, 1); --n-icon-color-disabled-override: rgba(209, 209, 209, 1);\">\n        <div class=\"n-input n-input--medium-size n-input--resizable n-input--stateful\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-count-text-color: rgb(118, 124, 130); --n-count-text-color-disabled: rgba(194, 194, 194, 1); --n-color: rgba(255, 255, 255, 1); --n-font-size: 14px; --n-font-weight: 400; --n-border-radius: 3px; --n-height: 34px; --n-padding-left: 12px; --n-padding-right: 12px; --n-text-color: rgb(51, 54, 57); --n-caret-color: #18a058; --n-text-decoration-color: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-focus: 1px solid #36ad6a; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-icon-size: 16px; --n-line-height-textarea: 1.6; --n-color-disabled: rgb(250, 250, 252); --n-color-focus: rgba(255, 255, 255, 1); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-loading-color: #18a058; --n-caret-color-warning: #f0a020; --n-color-focus-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-loading-color-warning: #f0a020; --n-caret-color-error: #d03050; --n-color-focus-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-loading-color-error: #d03050; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-size: 16px; --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-icon-color-hover: rgba(146, 146, 146, 1); --n-icon-color-pressed: rgba(175, 175, 175, 1); --n-icon-color-disabled: rgba(209, 209, 209, 1); --n-suffix-text-color: rgb(51, 54, 57);\" tabindex=\"0\">\n          <div class=\"n-input-wrapper\">\n            <!---->\n            <div class=\"n-input__input\"><input type=\"text\" class=\"n-input__input-el\" tabindex=\"-1\" placeholder=\"年を選択\" size=\"20\" value=\"1970\">\n              <!---->\n              <!---->\n            </div>\n            <div class=\"n-input__suffix\">\n              <!---->\n              <!---->\n              <!----><i class=\"n-base-icon n-date-picker-icon\"><svg width=\"28px\" height=\"28px\" viewBox=\"0 0 28 28\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n                  <g stroke=\"none\" stroke-width=\"1\" fill-rule=\"evenodd\">\n                    <g fill-rule=\"nonzero\">\n                      <path d=\"M21.75,3 C23.5449254,3 25,4.45507456 25,6.25 L25,21.75 C25,23.5449254 23.5449254,25 21.75,25 L6.25,25 C4.45507456,25 3,23.5449254 3,21.75 L3,6.25 C3,4.45507456 4.45507456,3 6.25,3 L21.75,3 Z M23.5,9.503 L4.5,9.503 L4.5,21.75 C4.5,22.7164983 5.28350169,23.5 6.25,23.5 L21.75,23.5 C22.7164983,23.5 23.5,22.7164983 23.5,21.75 L23.5,9.503 Z M21.75,4.5 L6.25,4.5 C5.28350169,4.5 4.5,5.28350169 4.5,6.25 L4.5,8.003 L23.5,8.003 L23.5,6.25 C23.5,5.28350169 22.7164983,4.5 21.75,4.5 Z\"></path>\n                    </g>\n                  </g>\n                </svg></i>\n              <!---->\n              <!---->\n            </div>\n          </div>\n          <!---->\n          <!---->\n          <div class=\"n-input__border\"></div>\n          <div class=\"n-input__state-border\"></div>\n          <!---->\n        </div>\n        <!---->\n      </div>\n      <div class=\"n-date-picker\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-icon-color-override: rgba(194, 194, 194, 1); --n-icon-color-disabled-override: rgba(209, 209, 209, 1);\">\n        <div class=\"n-input n-input--medium-size n-input--resizable n-input--stateful\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-count-text-color: rgb(118, 124, 130); --n-count-text-color-disabled: rgba(194, 194, 194, 1); --n-color: rgba(255, 255, 255, 1); --n-font-size: 14px; --n-font-weight: 400; --n-border-radius: 3px; --n-height: 34px; --n-padding-left: 12px; --n-padding-right: 12px; --n-text-color: rgb(51, 54, 57); --n-caret-color: #18a058; --n-text-decoration-color: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-focus: 1px solid #36ad6a; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-icon-size: 16px; --n-line-height-textarea: 1.6; --n-color-disabled: rgb(250, 250, 252); --n-color-focus: rgba(255, 255, 255, 1); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-loading-color: #18a058; --n-caret-color-warning: #f0a020; --n-color-focus-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-loading-color-warning: #f0a020; --n-caret-color-error: #d03050; --n-color-focus-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-loading-color-error: #d03050; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-size: 16px; --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-icon-color-hover: rgba(146, 146, 146, 1); --n-icon-color-pressed: rgba(175, 175, 175, 1); --n-icon-color-disabled: rgba(209, 209, 209, 1); --n-suffix-text-color: rgb(51, 54, 57);\" tabindex=\"0\">\n          <div class=\"n-input-wrapper\">\n            <!---->\n            <div class=\"n-input__input\"><input type=\"text\" class=\"n-input__input-el\" tabindex=\"-1\" placeholder=\"月を選択\" size=\"20\" value=\"1970-01\">\n              <!---->\n              <!---->\n            </div>\n            <div class=\"n-input__suffix\">\n              <!---->\n              <!---->\n              <!----><i class=\"n-base-icon n-date-picker-icon\"><svg width=\"28px\" height=\"28px\" viewBox=\"0 0 28 28\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n                  <g stroke=\"none\" stroke-width=\"1\" fill-rule=\"evenodd\">\n                    <g fill-rule=\"nonzero\">\n                      <path d=\"M21.75,3 C23.5449254,3 25,4.45507456 25,6.25 L25,21.75 C25,23.5449254 23.5449254,25 21.75,25 L6.25,25 C4.45507456,25 3,23.5449254 3,21.75 L3,6.25 C3,4.45507456 4.45507456,3 6.25,3 L21.75,3 Z M23.5,9.503 L4.5,9.503 L4.5,21.75 C4.5,22.7164983 5.28350169,23.5 6.25,23.5 L21.75,23.5 C22.7164983,23.5 23.5,22.7164983 23.5,21.75 L23.5,9.503 Z M21.75,4.5 L6.25,4.5 C5.28350169,4.5 4.5,5.28350169 4.5,6.25 L4.5,8.003 L23.5,8.003 L23.5,6.25 C23.5,5.28350169 22.7164983,4.5 21.75,4.5 Z\"></path>\n                    </g>\n                  </g>\n                </svg></i>\n              <!---->\n              <!---->\n            </div>\n          </div>\n          <!---->\n          <!---->\n          <div class=\"n-input__border\"></div>\n          <div class=\"n-input__state-border\"></div>\n          <!---->\n        </div>\n        <!---->\n      </div>\n    </div>\n  </div>\n</div>\"\n`;\n\nexports[`locale > works 8`] = `\n\"<div class=\"n-config-provider\">\n  <div>\n    <div class=\"n-input n-input--medium-size n-input--resizable n-input--stateful\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-count-text-color: rgb(118, 124, 130); --n-count-text-color-disabled: rgba(194, 194, 194, 1); --n-color: rgba(255, 255, 255, 1); --n-font-size: 14px; --n-font-weight: 400; --n-border-radius: 3px; --n-height: 34px; --n-padding-left: 12px; --n-padding-right: 12px; --n-text-color: rgb(51, 54, 57); --n-caret-color: #18a058; --n-text-decoration-color: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-focus: 1px solid #36ad6a; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-icon-size: 16px; --n-line-height-textarea: 1.6; --n-color-disabled: rgb(250, 250, 252); --n-color-focus: rgba(255, 255, 255, 1); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-loading-color: #18a058; --n-caret-color-warning: #f0a020; --n-color-focus-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-loading-color-warning: #f0a020; --n-caret-color-error: #d03050; --n-color-focus-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-loading-color-error: #d03050; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-size: 16px; --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-icon-color-hover: rgba(146, 146, 146, 1); --n-icon-color-pressed: rgba(175, 175, 175, 1); --n-icon-color-disabled: rgba(209, 209, 209, 1); --n-suffix-text-color: rgb(51, 54, 57);\">\n      <div class=\"n-input-wrapper\">\n        <!---->\n        <div class=\"n-input__input\"><input type=\"text\" class=\"n-input__input-el\" placeholder=\"សូមបញ្ចូល\" size=\"20\">\n          <div class=\"n-input__placeholder\"><span>សូមបញ្ចូល</span></div>\n          <!---->\n        </div>\n        <!---->\n      </div>\n      <!---->\n      <!---->\n      <div class=\"n-input__border\"></div>\n      <div class=\"n-input__state-border\"></div>\n      <!---->\n    </div>\n    <div>\n      <div class=\"n-date-picker\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-icon-color-override: rgba(194, 194, 194, 1); --n-icon-color-disabled-override: rgba(209, 209, 209, 1);\">\n        <div class=\"n-input n-input--medium-size n-input--resizable n-input--stateful\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-count-text-color: rgb(118, 124, 130); --n-count-text-color-disabled: rgba(194, 194, 194, 1); --n-color: rgba(255, 255, 255, 1); --n-font-size: 14px; --n-font-weight: 400; --n-border-radius: 3px; --n-height: 34px; --n-padding-left: 12px; --n-padding-right: 12px; --n-text-color: rgb(51, 54, 57); --n-caret-color: #18a058; --n-text-decoration-color: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-focus: 1px solid #36ad6a; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-icon-size: 16px; --n-line-height-textarea: 1.6; --n-color-disabled: rgb(250, 250, 252); --n-color-focus: rgba(255, 255, 255, 1); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-loading-color: #18a058; --n-caret-color-warning: #f0a020; --n-color-focus-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-loading-color-warning: #f0a020; --n-caret-color-error: #d03050; --n-color-focus-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-loading-color-error: #d03050; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-size: 16px; --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-icon-color-hover: rgba(146, 146, 146, 1); --n-icon-color-pressed: rgba(175, 175, 175, 1); --n-icon-color-disabled: rgba(209, 209, 209, 1); --n-suffix-text-color: rgb(51, 54, 57);\" tabindex=\"0\">\n          <div class=\"n-input-wrapper\">\n            <!---->\n            <div class=\"n-input__input\"><input type=\"text\" class=\"n-input__input-el\" tabindex=\"-1\" placeholder=\"ជ្រើសរើសកាលបរិច្ឆេទ\" size=\"20\" value=\"1970-01-01\">\n              <!---->\n              <!---->\n            </div>\n            <div class=\"n-input__suffix\">\n              <!---->\n              <!---->\n              <!----><i class=\"n-base-icon n-date-picker-icon\"><svg width=\"28px\" height=\"28px\" viewBox=\"0 0 28 28\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n                  <g stroke=\"none\" stroke-width=\"1\" fill-rule=\"evenodd\">\n                    <g fill-rule=\"nonzero\">\n                      <path d=\"M21.75,3 C23.5449254,3 25,4.45507456 25,6.25 L25,21.75 C25,23.5449254 23.5449254,25 21.75,25 L6.25,25 C4.45507456,25 3,23.5449254 3,21.75 L3,6.25 C3,4.45507456 4.45507456,3 6.25,3 L21.75,3 Z M23.5,9.503 L4.5,9.503 L4.5,21.75 C4.5,22.7164983 5.28350169,23.5 6.25,23.5 L21.75,23.5 C22.7164983,23.5 23.5,22.7164983 23.5,21.75 L23.5,9.503 Z M21.75,4.5 L6.25,4.5 C5.28350169,4.5 4.5,5.28350169 4.5,6.25 L4.5,8.003 L23.5,8.003 L23.5,6.25 C23.5,5.28350169 22.7164983,4.5 21.75,4.5 Z\"></path>\n                    </g>\n                  </g>\n                </svg></i>\n              <!---->\n              <!---->\n            </div>\n          </div>\n          <!---->\n          <!---->\n          <div class=\"n-input__border\"></div>\n          <div class=\"n-input__state-border\"></div>\n          <!---->\n        </div>\n        <!---->\n      </div>\n      <div class=\"n-date-picker\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-icon-color-override: rgba(194, 194, 194, 1); --n-icon-color-disabled-override: rgba(209, 209, 209, 1);\">\n        <div class=\"n-input n-input--medium-size n-input--resizable n-input--stateful\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-count-text-color: rgb(118, 124, 130); --n-count-text-color-disabled: rgba(194, 194, 194, 1); --n-color: rgba(255, 255, 255, 1); --n-font-size: 14px; --n-font-weight: 400; --n-border-radius: 3px; --n-height: 34px; --n-padding-left: 12px; --n-padding-right: 12px; --n-text-color: rgb(51, 54, 57); --n-caret-color: #18a058; --n-text-decoration-color: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-focus: 1px solid #36ad6a; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-icon-size: 16px; --n-line-height-textarea: 1.6; --n-color-disabled: rgb(250, 250, 252); --n-color-focus: rgba(255, 255, 255, 1); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-loading-color: #18a058; --n-caret-color-warning: #f0a020; --n-color-focus-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-loading-color-warning: #f0a020; --n-caret-color-error: #d03050; --n-color-focus-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-loading-color-error: #d03050; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-size: 16px; --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-icon-color-hover: rgba(146, 146, 146, 1); --n-icon-color-pressed: rgba(175, 175, 175, 1); --n-icon-color-disabled: rgba(209, 209, 209, 1); --n-suffix-text-color: rgb(51, 54, 57);\" tabindex=\"0\">\n          <div class=\"n-input-wrapper\">\n            <!---->\n            <div class=\"n-input__input\"><input type=\"text\" class=\"n-input__input-el\" tabindex=\"-1\" placeholder=\"ជ្រើសរើសពេលវេលាកាលបរិច្ឆេទ\" size=\"20\" value=\"1970-01-01 08:00:00\">\n              <!---->\n              <!---->\n            </div>\n            <div class=\"n-input__suffix\">\n              <!---->\n              <!---->\n              <!----><i class=\"n-base-icon n-date-picker-icon\"><svg width=\"28px\" height=\"28px\" viewBox=\"0 0 28 28\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n                  <g stroke=\"none\" stroke-width=\"1\" fill-rule=\"evenodd\">\n                    <g fill-rule=\"nonzero\">\n                      <path d=\"M21.75,3 C23.5449254,3 25,4.45507456 25,6.25 L25,21.75 C25,23.5449254 23.5449254,25 21.75,25 L6.25,25 C4.45507456,25 3,23.5449254 3,21.75 L3,6.25 C3,4.45507456 4.45507456,3 6.25,3 L21.75,3 Z M23.5,9.503 L4.5,9.503 L4.5,21.75 C4.5,22.7164983 5.28350169,23.5 6.25,23.5 L21.75,23.5 C22.7164983,23.5 23.5,22.7164983 23.5,21.75 L23.5,9.503 Z M21.75,4.5 L6.25,4.5 C5.28350169,4.5 4.5,5.28350169 4.5,6.25 L4.5,8.003 L23.5,8.003 L23.5,6.25 C23.5,5.28350169 22.7164983,4.5 21.75,4.5 Z\"></path>\n                    </g>\n                  </g>\n                </svg></i>\n              <!---->\n              <!---->\n            </div>\n          </div>\n          <!---->\n          <!---->\n          <div class=\"n-input__border\"></div>\n          <div class=\"n-input__state-border\"></div>\n          <!---->\n        </div>\n        <!---->\n      </div>\n      <div class=\"n-date-picker\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-icon-color-override: rgba(194, 194, 194, 1); --n-icon-color-disabled-override: rgba(209, 209, 209, 1);\">\n        <div class=\"n-input n-input--medium-size n-input--resizable n-input--stateful\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-count-text-color: rgb(118, 124, 130); --n-count-text-color-disabled: rgba(194, 194, 194, 1); --n-color: rgba(255, 255, 255, 1); --n-font-size: 14px; --n-font-weight: 400; --n-border-radius: 3px; --n-height: 34px; --n-padding-left: 12px; --n-padding-right: 12px; --n-text-color: rgb(51, 54, 57); --n-caret-color: #18a058; --n-text-decoration-color: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-focus: 1px solid #36ad6a; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-icon-size: 16px; --n-line-height-textarea: 1.6; --n-color-disabled: rgb(250, 250, 252); --n-color-focus: rgba(255, 255, 255, 1); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-loading-color: #18a058; --n-caret-color-warning: #f0a020; --n-color-focus-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-loading-color-warning: #f0a020; --n-caret-color-error: #d03050; --n-color-focus-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-loading-color-error: #d03050; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-size: 16px; --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-icon-color-hover: rgba(146, 146, 146, 1); --n-icon-color-pressed: rgba(175, 175, 175, 1); --n-icon-color-disabled: rgba(209, 209, 209, 1); --n-suffix-text-color: rgb(51, 54, 57);\" tabindex=\"0\">\n          <div class=\"n-input-wrapper\">\n            <!---->\n            <div class=\"n-input__input\"><input type=\"text\" class=\"n-input__input-el\" tabindex=\"-1\" placeholder=\"ជ្រើសរើសឆ្នាំ\" size=\"20\" value=\"1970\">\n              <!---->\n              <!---->\n            </div>\n            <div class=\"n-input__suffix\">\n              <!---->\n              <!---->\n              <!----><i class=\"n-base-icon n-date-picker-icon\"><svg width=\"28px\" height=\"28px\" viewBox=\"0 0 28 28\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n                  <g stroke=\"none\" stroke-width=\"1\" fill-rule=\"evenodd\">\n                    <g fill-rule=\"nonzero\">\n                      <path d=\"M21.75,3 C23.5449254,3 25,4.45507456 25,6.25 L25,21.75 C25,23.5449254 23.5449254,25 21.75,25 L6.25,25 C4.45507456,25 3,23.5449254 3,21.75 L3,6.25 C3,4.45507456 4.45507456,3 6.25,3 L21.75,3 Z M23.5,9.503 L4.5,9.503 L4.5,21.75 C4.5,22.7164983 5.28350169,23.5 6.25,23.5 L21.75,23.5 C22.7164983,23.5 23.5,22.7164983 23.5,21.75 L23.5,9.503 Z M21.75,4.5 L6.25,4.5 C5.28350169,4.5 4.5,5.28350169 4.5,6.25 L4.5,8.003 L23.5,8.003 L23.5,6.25 C23.5,5.28350169 22.7164983,4.5 21.75,4.5 Z\"></path>\n                    </g>\n                  </g>\n                </svg></i>\n              <!---->\n              <!---->\n            </div>\n          </div>\n          <!---->\n          <!---->\n          <div class=\"n-input__border\"></div>\n          <div class=\"n-input__state-border\"></div>\n          <!---->\n        </div>\n        <!---->\n      </div>\n      <div class=\"n-date-picker\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-icon-color-override: rgba(194, 194, 194, 1); --n-icon-color-disabled-override: rgba(209, 209, 209, 1);\">\n        <div class=\"n-input n-input--medium-size n-input--resizable n-input--stateful\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-count-text-color: rgb(118, 124, 130); --n-count-text-color-disabled: rgba(194, 194, 194, 1); --n-color: rgba(255, 255, 255, 1); --n-font-size: 14px; --n-font-weight: 400; --n-border-radius: 3px; --n-height: 34px; --n-padding-left: 12px; --n-padding-right: 12px; --n-text-color: rgb(51, 54, 57); --n-caret-color: #18a058; --n-text-decoration-color: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-focus: 1px solid #36ad6a; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-icon-size: 16px; --n-line-height-textarea: 1.6; --n-color-disabled: rgb(250, 250, 252); --n-color-focus: rgba(255, 255, 255, 1); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-loading-color: #18a058; --n-caret-color-warning: #f0a020; --n-color-focus-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-loading-color-warning: #f0a020; --n-caret-color-error: #d03050; --n-color-focus-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-loading-color-error: #d03050; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-size: 16px; --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-icon-color-hover: rgba(146, 146, 146, 1); --n-icon-color-pressed: rgba(175, 175, 175, 1); --n-icon-color-disabled: rgba(209, 209, 209, 1); --n-suffix-text-color: rgb(51, 54, 57);\" tabindex=\"0\">\n          <div class=\"n-input-wrapper\">\n            <!---->\n            <div class=\"n-input__input\"><input type=\"text\" class=\"n-input__input-el\" tabindex=\"-1\" placeholder=\"ជ្រើសរើសខែ\" size=\"20\" value=\"1970-01\">\n              <!---->\n              <!---->\n            </div>\n            <div class=\"n-input__suffix\">\n              <!---->\n              <!---->\n              <!----><i class=\"n-base-icon n-date-picker-icon\"><svg width=\"28px\" height=\"28px\" viewBox=\"0 0 28 28\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n                  <g stroke=\"none\" stroke-width=\"1\" fill-rule=\"evenodd\">\n                    <g fill-rule=\"nonzero\">\n                      <path d=\"M21.75,3 C23.5449254,3 25,4.45507456 25,6.25 L25,21.75 C25,23.5449254 23.5449254,25 21.75,25 L6.25,25 C4.45507456,25 3,23.5449254 3,21.75 L3,6.25 C3,4.45507456 4.45507456,3 6.25,3 L21.75,3 Z M23.5,9.503 L4.5,9.503 L4.5,21.75 C4.5,22.7164983 5.28350169,23.5 6.25,23.5 L21.75,23.5 C22.7164983,23.5 23.5,22.7164983 23.5,21.75 L23.5,9.503 Z M21.75,4.5 L6.25,4.5 C5.28350169,4.5 4.5,5.28350169 4.5,6.25 L4.5,8.003 L23.5,8.003 L23.5,6.25 C23.5,5.28350169 22.7164983,4.5 21.75,4.5 Z\"></path>\n                    </g>\n                  </g>\n                </svg></i>\n              <!---->\n              <!---->\n            </div>\n          </div>\n          <!---->\n          <!---->\n          <div class=\"n-input__border\"></div>\n          <div class=\"n-input__state-border\"></div>\n          <!---->\n        </div>\n        <!---->\n      </div>\n    </div>\n  </div>\n</div>\"\n`;\n\nexports[`locale > works 9`] = `\n\"<div class=\"n-config-provider\">\n  <div>\n    <div class=\"n-input n-input--medium-size n-input--resizable n-input--stateful\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-count-text-color: rgb(118, 124, 130); --n-count-text-color-disabled: rgba(194, 194, 194, 1); --n-color: rgba(255, 255, 255, 1); --n-font-size: 14px; --n-font-weight: 400; --n-border-radius: 3px; --n-height: 34px; --n-padding-left: 12px; --n-padding-right: 12px; --n-text-color: rgb(51, 54, 57); --n-caret-color: #18a058; --n-text-decoration-color: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-focus: 1px solid #36ad6a; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-icon-size: 16px; --n-line-height-textarea: 1.6; --n-color-disabled: rgb(250, 250, 252); --n-color-focus: rgba(255, 255, 255, 1); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-loading-color: #18a058; --n-caret-color-warning: #f0a020; --n-color-focus-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-loading-color-warning: #f0a020; --n-caret-color-error: #d03050; --n-color-focus-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-loading-color-error: #d03050; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-size: 16px; --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-icon-color-hover: rgba(146, 146, 146, 1); --n-icon-color-pressed: rgba(175, 175, 175, 1); --n-icon-color-disabled: rgba(209, 209, 209, 1); --n-suffix-text-color: rgb(51, 54, 57);\">\n      <div class=\"n-input-wrapper\">\n        <!---->\n        <div class=\"n-input__input\"><input type=\"text\" class=\"n-input__input-el\" placeholder=\"입력해 주세요\" size=\"20\">\n          <div class=\"n-input__placeholder\"><span>입력해 주세요</span></div>\n          <!---->\n        </div>\n        <!---->\n      </div>\n      <!---->\n      <!---->\n      <div class=\"n-input__border\"></div>\n      <div class=\"n-input__state-border\"></div>\n      <!---->\n    </div>\n    <div>\n      <div class=\"n-date-picker\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-icon-color-override: rgba(194, 194, 194, 1); --n-icon-color-disabled-override: rgba(209, 209, 209, 1);\">\n        <div class=\"n-input n-input--medium-size n-input--resizable n-input--stateful\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-count-text-color: rgb(118, 124, 130); --n-count-text-color-disabled: rgba(194, 194, 194, 1); --n-color: rgba(255, 255, 255, 1); --n-font-size: 14px; --n-font-weight: 400; --n-border-radius: 3px; --n-height: 34px; --n-padding-left: 12px; --n-padding-right: 12px; --n-text-color: rgb(51, 54, 57); --n-caret-color: #18a058; --n-text-decoration-color: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-focus: 1px solid #36ad6a; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-icon-size: 16px; --n-line-height-textarea: 1.6; --n-color-disabled: rgb(250, 250, 252); --n-color-focus: rgba(255, 255, 255, 1); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-loading-color: #18a058; --n-caret-color-warning: #f0a020; --n-color-focus-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-loading-color-warning: #f0a020; --n-caret-color-error: #d03050; --n-color-focus-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-loading-color-error: #d03050; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-size: 16px; --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-icon-color-hover: rgba(146, 146, 146, 1); --n-icon-color-pressed: rgba(175, 175, 175, 1); --n-icon-color-disabled: rgba(209, 209, 209, 1); --n-suffix-text-color: rgb(51, 54, 57);\" tabindex=\"0\">\n          <div class=\"n-input-wrapper\">\n            <!---->\n            <div class=\"n-input__input\"><input type=\"text\" class=\"n-input__input-el\" tabindex=\"-1\" placeholder=\"날짜 선택\" size=\"20\" value=\"1970-01-01\">\n              <!---->\n              <!---->\n            </div>\n            <div class=\"n-input__suffix\">\n              <!---->\n              <!---->\n              <!----><i class=\"n-base-icon n-date-picker-icon\"><svg width=\"28px\" height=\"28px\" viewBox=\"0 0 28 28\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n                  <g stroke=\"none\" stroke-width=\"1\" fill-rule=\"evenodd\">\n                    <g fill-rule=\"nonzero\">\n                      <path d=\"M21.75,3 C23.5449254,3 25,4.45507456 25,6.25 L25,21.75 C25,23.5449254 23.5449254,25 21.75,25 L6.25,25 C4.45507456,25 3,23.5449254 3,21.75 L3,6.25 C3,4.45507456 4.45507456,3 6.25,3 L21.75,3 Z M23.5,9.503 L4.5,9.503 L4.5,21.75 C4.5,22.7164983 5.28350169,23.5 6.25,23.5 L21.75,23.5 C22.7164983,23.5 23.5,22.7164983 23.5,21.75 L23.5,9.503 Z M21.75,4.5 L6.25,4.5 C5.28350169,4.5 4.5,5.28350169 4.5,6.25 L4.5,8.003 L23.5,8.003 L23.5,6.25 C23.5,5.28350169 22.7164983,4.5 21.75,4.5 Z\"></path>\n                    </g>\n                  </g>\n                </svg></i>\n              <!---->\n              <!---->\n            </div>\n          </div>\n          <!---->\n          <!---->\n          <div class=\"n-input__border\"></div>\n          <div class=\"n-input__state-border\"></div>\n          <!---->\n        </div>\n        <!---->\n      </div>\n      <div class=\"n-date-picker\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-icon-color-override: rgba(194, 194, 194, 1); --n-icon-color-disabled-override: rgba(209, 209, 209, 1);\">\n        <div class=\"n-input n-input--medium-size n-input--resizable n-input--stateful\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-count-text-color: rgb(118, 124, 130); --n-count-text-color-disabled: rgba(194, 194, 194, 1); --n-color: rgba(255, 255, 255, 1); --n-font-size: 14px; --n-font-weight: 400; --n-border-radius: 3px; --n-height: 34px; --n-padding-left: 12px; --n-padding-right: 12px; --n-text-color: rgb(51, 54, 57); --n-caret-color: #18a058; --n-text-decoration-color: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-focus: 1px solid #36ad6a; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-icon-size: 16px; --n-line-height-textarea: 1.6; --n-color-disabled: rgb(250, 250, 252); --n-color-focus: rgba(255, 255, 255, 1); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-loading-color: #18a058; --n-caret-color-warning: #f0a020; --n-color-focus-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-loading-color-warning: #f0a020; --n-caret-color-error: #d03050; --n-color-focus-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-loading-color-error: #d03050; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-size: 16px; --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-icon-color-hover: rgba(146, 146, 146, 1); --n-icon-color-pressed: rgba(175, 175, 175, 1); --n-icon-color-disabled: rgba(209, 209, 209, 1); --n-suffix-text-color: rgb(51, 54, 57);\" tabindex=\"0\">\n          <div class=\"n-input-wrapper\">\n            <!---->\n            <div class=\"n-input__input\"><input type=\"text\" class=\"n-input__input-el\" tabindex=\"-1\" placeholder=\"날짜 및 시간 선택\" size=\"20\" value=\"1970-01-01 08:00:00\">\n              <!---->\n              <!---->\n            </div>\n            <div class=\"n-input__suffix\">\n              <!---->\n              <!---->\n              <!----><i class=\"n-base-icon n-date-picker-icon\"><svg width=\"28px\" height=\"28px\" viewBox=\"0 0 28 28\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n                  <g stroke=\"none\" stroke-width=\"1\" fill-rule=\"evenodd\">\n                    <g fill-rule=\"nonzero\">\n                      <path d=\"M21.75,3 C23.5449254,3 25,4.45507456 25,6.25 L25,21.75 C25,23.5449254 23.5449254,25 21.75,25 L6.25,25 C4.45507456,25 3,23.5449254 3,21.75 L3,6.25 C3,4.45507456 4.45507456,3 6.25,3 L21.75,3 Z M23.5,9.503 L4.5,9.503 L4.5,21.75 C4.5,22.7164983 5.28350169,23.5 6.25,23.5 L21.75,23.5 C22.7164983,23.5 23.5,22.7164983 23.5,21.75 L23.5,9.503 Z M21.75,4.5 L6.25,4.5 C5.28350169,4.5 4.5,5.28350169 4.5,6.25 L4.5,8.003 L23.5,8.003 L23.5,6.25 C23.5,5.28350169 22.7164983,4.5 21.75,4.5 Z\"></path>\n                    </g>\n                  </g>\n                </svg></i>\n              <!---->\n              <!---->\n            </div>\n          </div>\n          <!---->\n          <!---->\n          <div class=\"n-input__border\"></div>\n          <div class=\"n-input__state-border\"></div>\n          <!---->\n        </div>\n        <!---->\n      </div>\n      <div class=\"n-date-picker\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-icon-color-override: rgba(194, 194, 194, 1); --n-icon-color-disabled-override: rgba(209, 209, 209, 1);\">\n        <div class=\"n-input n-input--medium-size n-input--resizable n-input--stateful\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-count-text-color: rgb(118, 124, 130); --n-count-text-color-disabled: rgba(194, 194, 194, 1); --n-color: rgba(255, 255, 255, 1); --n-font-size: 14px; --n-font-weight: 400; --n-border-radius: 3px; --n-height: 34px; --n-padding-left: 12px; --n-padding-right: 12px; --n-text-color: rgb(51, 54, 57); --n-caret-color: #18a058; --n-text-decoration-color: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-focus: 1px solid #36ad6a; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-icon-size: 16px; --n-line-height-textarea: 1.6; --n-color-disabled: rgb(250, 250, 252); --n-color-focus: rgba(255, 255, 255, 1); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-loading-color: #18a058; --n-caret-color-warning: #f0a020; --n-color-focus-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-loading-color-warning: #f0a020; --n-caret-color-error: #d03050; --n-color-focus-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-loading-color-error: #d03050; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-size: 16px; --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-icon-color-hover: rgba(146, 146, 146, 1); --n-icon-color-pressed: rgba(175, 175, 175, 1); --n-icon-color-disabled: rgba(209, 209, 209, 1); --n-suffix-text-color: rgb(51, 54, 57);\" tabindex=\"0\">\n          <div class=\"n-input-wrapper\">\n            <!---->\n            <div class=\"n-input__input\"><input type=\"text\" class=\"n-input__input-el\" tabindex=\"-1\" placeholder=\"년 선택\" size=\"20\" value=\"1970\">\n              <!---->\n              <!---->\n            </div>\n            <div class=\"n-input__suffix\">\n              <!---->\n              <!---->\n              <!----><i class=\"n-base-icon n-date-picker-icon\"><svg width=\"28px\" height=\"28px\" viewBox=\"0 0 28 28\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n                  <g stroke=\"none\" stroke-width=\"1\" fill-rule=\"evenodd\">\n                    <g fill-rule=\"nonzero\">\n                      <path d=\"M21.75,3 C23.5449254,3 25,4.45507456 25,6.25 L25,21.75 C25,23.5449254 23.5449254,25 21.75,25 L6.25,25 C4.45507456,25 3,23.5449254 3,21.75 L3,6.25 C3,4.45507456 4.45507456,3 6.25,3 L21.75,3 Z M23.5,9.503 L4.5,9.503 L4.5,21.75 C4.5,22.7164983 5.28350169,23.5 6.25,23.5 L21.75,23.5 C22.7164983,23.5 23.5,22.7164983 23.5,21.75 L23.5,9.503 Z M21.75,4.5 L6.25,4.5 C5.28350169,4.5 4.5,5.28350169 4.5,6.25 L4.5,8.003 L23.5,8.003 L23.5,6.25 C23.5,5.28350169 22.7164983,4.5 21.75,4.5 Z\"></path>\n                    </g>\n                  </g>\n                </svg></i>\n              <!---->\n              <!---->\n            </div>\n          </div>\n          <!---->\n          <!---->\n          <div class=\"n-input__border\"></div>\n          <div class=\"n-input__state-border\"></div>\n          <!---->\n        </div>\n        <!---->\n      </div>\n      <div class=\"n-date-picker\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-icon-color-override: rgba(194, 194, 194, 1); --n-icon-color-disabled-override: rgba(209, 209, 209, 1);\">\n        <div class=\"n-input n-input--medium-size n-input--resizable n-input--stateful\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-count-text-color: rgb(118, 124, 130); --n-count-text-color-disabled: rgba(194, 194, 194, 1); --n-color: rgba(255, 255, 255, 1); --n-font-size: 14px; --n-font-weight: 400; --n-border-radius: 3px; --n-height: 34px; --n-padding-left: 12px; --n-padding-right: 12px; --n-text-color: rgb(51, 54, 57); --n-caret-color: #18a058; --n-text-decoration-color: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-focus: 1px solid #36ad6a; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-icon-size: 16px; --n-line-height-textarea: 1.6; --n-color-disabled: rgb(250, 250, 252); --n-color-focus: rgba(255, 255, 255, 1); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-loading-color: #18a058; --n-caret-color-warning: #f0a020; --n-color-focus-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-loading-color-warning: #f0a020; --n-caret-color-error: #d03050; --n-color-focus-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-loading-color-error: #d03050; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-size: 16px; --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-icon-color-hover: rgba(146, 146, 146, 1); --n-icon-color-pressed: rgba(175, 175, 175, 1); --n-icon-color-disabled: rgba(209, 209, 209, 1); --n-suffix-text-color: rgb(51, 54, 57);\" tabindex=\"0\">\n          <div class=\"n-input-wrapper\">\n            <!---->\n            <div class=\"n-input__input\"><input type=\"text\" class=\"n-input__input-el\" tabindex=\"-1\" placeholder=\"월 선택\" size=\"20\" value=\"1970-01\">\n              <!---->\n              <!---->\n            </div>\n            <div class=\"n-input__suffix\">\n              <!---->\n              <!---->\n              <!----><i class=\"n-base-icon n-date-picker-icon\"><svg width=\"28px\" height=\"28px\" viewBox=\"0 0 28 28\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n                  <g stroke=\"none\" stroke-width=\"1\" fill-rule=\"evenodd\">\n                    <g fill-rule=\"nonzero\">\n                      <path d=\"M21.75,3 C23.5449254,3 25,4.45507456 25,6.25 L25,21.75 C25,23.5449254 23.5449254,25 21.75,25 L6.25,25 C4.45507456,25 3,23.5449254 3,21.75 L3,6.25 C3,4.45507456 4.45507456,3 6.25,3 L21.75,3 Z M23.5,9.503 L4.5,9.503 L4.5,21.75 C4.5,22.7164983 5.28350169,23.5 6.25,23.5 L21.75,23.5 C22.7164983,23.5 23.5,22.7164983 23.5,21.75 L23.5,9.503 Z M21.75,4.5 L6.25,4.5 C5.28350169,4.5 4.5,5.28350169 4.5,6.25 L4.5,8.003 L23.5,8.003 L23.5,6.25 C23.5,5.28350169 22.7164983,4.5 21.75,4.5 Z\"></path>\n                    </g>\n                  </g>\n                </svg></i>\n              <!---->\n              <!---->\n            </div>\n          </div>\n          <!---->\n          <!---->\n          <div class=\"n-input__border\"></div>\n          <div class=\"n-input__state-border\"></div>\n          <!---->\n        </div>\n        <!---->\n      </div>\n    </div>\n  </div>\n</div>\"\n`;\n\nexports[`locale > works 10`] = `\n\"<div class=\"n-config-provider\">\n  <div>\n    <div class=\"n-input n-input--medium-size n-input--resizable n-input--stateful\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-count-text-color: rgb(118, 124, 130); --n-count-text-color-disabled: rgba(194, 194, 194, 1); --n-color: rgba(255, 255, 255, 1); --n-font-size: 14px; --n-font-weight: 400; --n-border-radius: 3px; --n-height: 34px; --n-padding-left: 12px; --n-padding-right: 12px; --n-text-color: rgb(51, 54, 57); --n-caret-color: #18a058; --n-text-decoration-color: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-focus: 1px solid #36ad6a; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-icon-size: 16px; --n-line-height-textarea: 1.6; --n-color-disabled: rgb(250, 250, 252); --n-color-focus: rgba(255, 255, 255, 1); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-loading-color: #18a058; --n-caret-color-warning: #f0a020; --n-color-focus-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-loading-color-warning: #f0a020; --n-caret-color-error: #d03050; --n-color-focus-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-loading-color-error: #d03050; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-size: 16px; --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-icon-color-hover: rgba(146, 146, 146, 1); --n-icon-color-pressed: rgba(175, 175, 175, 1); --n-icon-color-disabled: rgba(209, 209, 209, 1); --n-suffix-text-color: rgb(51, 54, 57);\">\n      <div class=\"n-input-wrapper\">\n        <!---->\n        <div class=\"n-input__input\"><input type=\"text\" class=\"n-input__input-el\" placeholder=\"Mohon isi\" size=\"20\">\n          <div class=\"n-input__placeholder\"><span>Mohon isi</span></div>\n          <!---->\n        </div>\n        <!---->\n      </div>\n      <!---->\n      <!---->\n      <div class=\"n-input__border\"></div>\n      <div class=\"n-input__state-border\"></div>\n      <!---->\n    </div>\n    <div>\n      <div class=\"n-date-picker\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-icon-color-override: rgba(194, 194, 194, 1); --n-icon-color-disabled-override: rgba(209, 209, 209, 1);\">\n        <div class=\"n-input n-input--medium-size n-input--resizable n-input--stateful\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-count-text-color: rgb(118, 124, 130); --n-count-text-color-disabled: rgba(194, 194, 194, 1); --n-color: rgba(255, 255, 255, 1); --n-font-size: 14px; --n-font-weight: 400; --n-border-radius: 3px; --n-height: 34px; --n-padding-left: 12px; --n-padding-right: 12px; --n-text-color: rgb(51, 54, 57); --n-caret-color: #18a058; --n-text-decoration-color: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-focus: 1px solid #36ad6a; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-icon-size: 16px; --n-line-height-textarea: 1.6; --n-color-disabled: rgb(250, 250, 252); --n-color-focus: rgba(255, 255, 255, 1); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-loading-color: #18a058; --n-caret-color-warning: #f0a020; --n-color-focus-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-loading-color-warning: #f0a020; --n-caret-color-error: #d03050; --n-color-focus-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-loading-color-error: #d03050; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-size: 16px; --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-icon-color-hover: rgba(146, 146, 146, 1); --n-icon-color-pressed: rgba(175, 175, 175, 1); --n-icon-color-disabled: rgba(209, 209, 209, 1); --n-suffix-text-color: rgb(51, 54, 57);\" tabindex=\"0\">\n          <div class=\"n-input-wrapper\">\n            <!---->\n            <div class=\"n-input__input\"><input type=\"text\" class=\"n-input__input-el\" tabindex=\"-1\" placeholder=\"Pilih Tanggal\" size=\"20\" value=\"01-01-1970\">\n              <!---->\n              <!---->\n            </div>\n            <div class=\"n-input__suffix\">\n              <!---->\n              <!---->\n              <!----><i class=\"n-base-icon n-date-picker-icon\"><svg width=\"28px\" height=\"28px\" viewBox=\"0 0 28 28\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n                  <g stroke=\"none\" stroke-width=\"1\" fill-rule=\"evenodd\">\n                    <g fill-rule=\"nonzero\">\n                      <path d=\"M21.75,3 C23.5449254,3 25,4.45507456 25,6.25 L25,21.75 C25,23.5449254 23.5449254,25 21.75,25 L6.25,25 C4.45507456,25 3,23.5449254 3,21.75 L3,6.25 C3,4.45507456 4.45507456,3 6.25,3 L21.75,3 Z M23.5,9.503 L4.5,9.503 L4.5,21.75 C4.5,22.7164983 5.28350169,23.5 6.25,23.5 L21.75,23.5 C22.7164983,23.5 23.5,22.7164983 23.5,21.75 L23.5,9.503 Z M21.75,4.5 L6.25,4.5 C5.28350169,4.5 4.5,5.28350169 4.5,6.25 L4.5,8.003 L23.5,8.003 L23.5,6.25 C23.5,5.28350169 22.7164983,4.5 21.75,4.5 Z\"></path>\n                    </g>\n                  </g>\n                </svg></i>\n              <!---->\n              <!---->\n            </div>\n          </div>\n          <!---->\n          <!---->\n          <div class=\"n-input__border\"></div>\n          <div class=\"n-input__state-border\"></div>\n          <!---->\n        </div>\n        <!---->\n      </div>\n      <div class=\"n-date-picker\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-icon-color-override: rgba(194, 194, 194, 1); --n-icon-color-disabled-override: rgba(209, 209, 209, 1);\">\n        <div class=\"n-input n-input--medium-size n-input--resizable n-input--stateful\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-count-text-color: rgb(118, 124, 130); --n-count-text-color-disabled: rgba(194, 194, 194, 1); --n-color: rgba(255, 255, 255, 1); --n-font-size: 14px; --n-font-weight: 400; --n-border-radius: 3px; --n-height: 34px; --n-padding-left: 12px; --n-padding-right: 12px; --n-text-color: rgb(51, 54, 57); --n-caret-color: #18a058; --n-text-decoration-color: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-focus: 1px solid #36ad6a; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-icon-size: 16px; --n-line-height-textarea: 1.6; --n-color-disabled: rgb(250, 250, 252); --n-color-focus: rgba(255, 255, 255, 1); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-loading-color: #18a058; --n-caret-color-warning: #f0a020; --n-color-focus-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-loading-color-warning: #f0a020; --n-caret-color-error: #d03050; --n-color-focus-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-loading-color-error: #d03050; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-size: 16px; --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-icon-color-hover: rgba(146, 146, 146, 1); --n-icon-color-pressed: rgba(175, 175, 175, 1); --n-icon-color-disabled: rgba(209, 209, 209, 1); --n-suffix-text-color: rgb(51, 54, 57);\" tabindex=\"0\">\n          <div class=\"n-input-wrapper\">\n            <!---->\n            <div class=\"n-input__input\"><input type=\"text\" class=\"n-input__input-el\" tabindex=\"-1\" placeholder=\"Pilih Tanggal dan Waktu\" size=\"20\" value=\"01-01-1970 08:00:00\">\n              <!---->\n              <!---->\n            </div>\n            <div class=\"n-input__suffix\">\n              <!---->\n              <!---->\n              <!----><i class=\"n-base-icon n-date-picker-icon\"><svg width=\"28px\" height=\"28px\" viewBox=\"0 0 28 28\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n                  <g stroke=\"none\" stroke-width=\"1\" fill-rule=\"evenodd\">\n                    <g fill-rule=\"nonzero\">\n                      <path d=\"M21.75,3 C23.5449254,3 25,4.45507456 25,6.25 L25,21.75 C25,23.5449254 23.5449254,25 21.75,25 L6.25,25 C4.45507456,25 3,23.5449254 3,21.75 L3,6.25 C3,4.45507456 4.45507456,3 6.25,3 L21.75,3 Z M23.5,9.503 L4.5,9.503 L4.5,21.75 C4.5,22.7164983 5.28350169,23.5 6.25,23.5 L21.75,23.5 C22.7164983,23.5 23.5,22.7164983 23.5,21.75 L23.5,9.503 Z M21.75,4.5 L6.25,4.5 C5.28350169,4.5 4.5,5.28350169 4.5,6.25 L4.5,8.003 L23.5,8.003 L23.5,6.25 C23.5,5.28350169 22.7164983,4.5 21.75,4.5 Z\"></path>\n                    </g>\n                  </g>\n                </svg></i>\n              <!---->\n              <!---->\n            </div>\n          </div>\n          <!---->\n          <!---->\n          <div class=\"n-input__border\"></div>\n          <div class=\"n-input__state-border\"></div>\n          <!---->\n        </div>\n        <!---->\n      </div>\n      <div class=\"n-date-picker\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-icon-color-override: rgba(194, 194, 194, 1); --n-icon-color-disabled-override: rgba(209, 209, 209, 1);\">\n        <div class=\"n-input n-input--medium-size n-input--resizable n-input--stateful\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-count-text-color: rgb(118, 124, 130); --n-count-text-color-disabled: rgba(194, 194, 194, 1); --n-color: rgba(255, 255, 255, 1); --n-font-size: 14px; --n-font-weight: 400; --n-border-radius: 3px; --n-height: 34px; --n-padding-left: 12px; --n-padding-right: 12px; --n-text-color: rgb(51, 54, 57); --n-caret-color: #18a058; --n-text-decoration-color: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-focus: 1px solid #36ad6a; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-icon-size: 16px; --n-line-height-textarea: 1.6; --n-color-disabled: rgb(250, 250, 252); --n-color-focus: rgba(255, 255, 255, 1); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-loading-color: #18a058; --n-caret-color-warning: #f0a020; --n-color-focus-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-loading-color-warning: #f0a020; --n-caret-color-error: #d03050; --n-color-focus-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-loading-color-error: #d03050; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-size: 16px; --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-icon-color-hover: rgba(146, 146, 146, 1); --n-icon-color-pressed: rgba(175, 175, 175, 1); --n-icon-color-disabled: rgba(209, 209, 209, 1); --n-suffix-text-color: rgb(51, 54, 57);\" tabindex=\"0\">\n          <div class=\"n-input-wrapper\">\n            <!---->\n            <div class=\"n-input__input\"><input type=\"text\" class=\"n-input__input-el\" tabindex=\"-1\" placeholder=\"Pilih tahun\" size=\"20\" value=\"1970\">\n              <!---->\n              <!---->\n            </div>\n            <div class=\"n-input__suffix\">\n              <!---->\n              <!---->\n              <!----><i class=\"n-base-icon n-date-picker-icon\"><svg width=\"28px\" height=\"28px\" viewBox=\"0 0 28 28\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n                  <g stroke=\"none\" stroke-width=\"1\" fill-rule=\"evenodd\">\n                    <g fill-rule=\"nonzero\">\n                      <path d=\"M21.75,3 C23.5449254,3 25,4.45507456 25,6.25 L25,21.75 C25,23.5449254 23.5449254,25 21.75,25 L6.25,25 C4.45507456,25 3,23.5449254 3,21.75 L3,6.25 C3,4.45507456 4.45507456,3 6.25,3 L21.75,3 Z M23.5,9.503 L4.5,9.503 L4.5,21.75 C4.5,22.7164983 5.28350169,23.5 6.25,23.5 L21.75,23.5 C22.7164983,23.5 23.5,22.7164983 23.5,21.75 L23.5,9.503 Z M21.75,4.5 L6.25,4.5 C5.28350169,4.5 4.5,5.28350169 4.5,6.25 L4.5,8.003 L23.5,8.003 L23.5,6.25 C23.5,5.28350169 22.7164983,4.5 21.75,4.5 Z\"></path>\n                    </g>\n                  </g>\n                </svg></i>\n              <!---->\n              <!---->\n            </div>\n          </div>\n          <!---->\n          <!---->\n          <div class=\"n-input__border\"></div>\n          <div class=\"n-input__state-border\"></div>\n          <!---->\n        </div>\n        <!---->\n      </div>\n      <div class=\"n-date-picker\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-icon-color-override: rgba(194, 194, 194, 1); --n-icon-color-disabled-override: rgba(209, 209, 209, 1);\">\n        <div class=\"n-input n-input--medium-size n-input--resizable n-input--stateful\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-count-text-color: rgb(118, 124, 130); --n-count-text-color-disabled: rgba(194, 194, 194, 1); --n-color: rgba(255, 255, 255, 1); --n-font-size: 14px; --n-font-weight: 400; --n-border-radius: 3px; --n-height: 34px; --n-padding-left: 12px; --n-padding-right: 12px; --n-text-color: rgb(51, 54, 57); --n-caret-color: #18a058; --n-text-decoration-color: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-focus: 1px solid #36ad6a; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-icon-size: 16px; --n-line-height-textarea: 1.6; --n-color-disabled: rgb(250, 250, 252); --n-color-focus: rgba(255, 255, 255, 1); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-loading-color: #18a058; --n-caret-color-warning: #f0a020; --n-color-focus-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-loading-color-warning: #f0a020; --n-caret-color-error: #d03050; --n-color-focus-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-loading-color-error: #d03050; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-size: 16px; --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-icon-color-hover: rgba(146, 146, 146, 1); --n-icon-color-pressed: rgba(175, 175, 175, 1); --n-icon-color-disabled: rgba(209, 209, 209, 1); --n-suffix-text-color: rgb(51, 54, 57);\" tabindex=\"0\">\n          <div class=\"n-input-wrapper\">\n            <!---->\n            <div class=\"n-input__input\"><input type=\"text\" class=\"n-input__input-el\" tabindex=\"-1\" placeholder=\"Pilih Bulan\" size=\"20\" value=\"01-1970\">\n              <!---->\n              <!---->\n            </div>\n            <div class=\"n-input__suffix\">\n              <!---->\n              <!---->\n              <!----><i class=\"n-base-icon n-date-picker-icon\"><svg width=\"28px\" height=\"28px\" viewBox=\"0 0 28 28\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n                  <g stroke=\"none\" stroke-width=\"1\" fill-rule=\"evenodd\">\n                    <g fill-rule=\"nonzero\">\n                      <path d=\"M21.75,3 C23.5449254,3 25,4.45507456 25,6.25 L25,21.75 C25,23.5449254 23.5449254,25 21.75,25 L6.25,25 C4.45507456,25 3,23.5449254 3,21.75 L3,6.25 C3,4.45507456 4.45507456,3 6.25,3 L21.75,3 Z M23.5,9.503 L4.5,9.503 L4.5,21.75 C4.5,22.7164983 5.28350169,23.5 6.25,23.5 L21.75,23.5 C22.7164983,23.5 23.5,22.7164983 23.5,21.75 L23.5,9.503 Z M21.75,4.5 L6.25,4.5 C5.28350169,4.5 4.5,5.28350169 4.5,6.25 L4.5,8.003 L23.5,8.003 L23.5,6.25 C23.5,5.28350169 22.7164983,4.5 21.75,4.5 Z\"></path>\n                    </g>\n                  </g>\n                </svg></i>\n              <!---->\n              <!---->\n            </div>\n          </div>\n          <!---->\n          <!---->\n          <div class=\"n-input__border\"></div>\n          <div class=\"n-input__state-border\"></div>\n          <!---->\n        </div>\n        <!---->\n      </div>\n    </div>\n  </div>\n</div>\"\n`;\n\nexports[`locale > works 11`] = `\n\"<div class=\"n-config-provider\">\n  <div>\n    <div class=\"n-input n-input--medium-size n-input--resizable n-input--stateful\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-count-text-color: rgb(118, 124, 130); --n-count-text-color-disabled: rgba(194, 194, 194, 1); --n-color: rgba(255, 255, 255, 1); --n-font-size: 14px; --n-font-weight: 400; --n-border-radius: 3px; --n-height: 34px; --n-padding-left: 12px; --n-padding-right: 12px; --n-text-color: rgb(51, 54, 57); --n-caret-color: #18a058; --n-text-decoration-color: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-focus: 1px solid #36ad6a; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-icon-size: 16px; --n-line-height-textarea: 1.6; --n-color-disabled: rgb(250, 250, 252); --n-color-focus: rgba(255, 255, 255, 1); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-loading-color: #18a058; --n-caret-color-warning: #f0a020; --n-color-focus-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-loading-color-warning: #f0a020; --n-caret-color-error: #d03050; --n-color-focus-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-loading-color-error: #d03050; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-size: 16px; --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-icon-color-hover: rgba(146, 146, 146, 1); --n-icon-color-pressed: rgba(175, 175, 175, 1); --n-icon-color-disabled: rgba(209, 209, 209, 1); --n-suffix-text-color: rgb(51, 54, 57);\">\n      <div class=\"n-input-wrapper\">\n        <!---->\n        <div class=\"n-input__input\"><input type=\"text\" class=\"n-input__input-el\" placeholder=\"Bitte ausfüllen\" size=\"20\">\n          <div class=\"n-input__placeholder\"><span>Bitte ausfüllen</span></div>\n          <!---->\n        </div>\n        <!---->\n      </div>\n      <!---->\n      <!---->\n      <div class=\"n-input__border\"></div>\n      <div class=\"n-input__state-border\"></div>\n      <!---->\n    </div>\n    <div>\n      <div class=\"n-date-picker\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-icon-color-override: rgba(194, 194, 194, 1); --n-icon-color-disabled-override: rgba(209, 209, 209, 1);\">\n        <div class=\"n-input n-input--medium-size n-input--resizable n-input--stateful\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-count-text-color: rgb(118, 124, 130); --n-count-text-color-disabled: rgba(194, 194, 194, 1); --n-color: rgba(255, 255, 255, 1); --n-font-size: 14px; --n-font-weight: 400; --n-border-radius: 3px; --n-height: 34px; --n-padding-left: 12px; --n-padding-right: 12px; --n-text-color: rgb(51, 54, 57); --n-caret-color: #18a058; --n-text-decoration-color: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-focus: 1px solid #36ad6a; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-icon-size: 16px; --n-line-height-textarea: 1.6; --n-color-disabled: rgb(250, 250, 252); --n-color-focus: rgba(255, 255, 255, 1); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-loading-color: #18a058; --n-caret-color-warning: #f0a020; --n-color-focus-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-loading-color-warning: #f0a020; --n-caret-color-error: #d03050; --n-color-focus-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-loading-color-error: #d03050; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-size: 16px; --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-icon-color-hover: rgba(146, 146, 146, 1); --n-icon-color-pressed: rgba(175, 175, 175, 1); --n-icon-color-disabled: rgba(209, 209, 209, 1); --n-suffix-text-color: rgb(51, 54, 57);\" tabindex=\"0\">\n          <div class=\"n-input-wrapper\">\n            <!---->\n            <div class=\"n-input__input\"><input type=\"text\" class=\"n-input__input-el\" tabindex=\"-1\" placeholder=\"Datum auswählen\" size=\"20\" value=\"01.01.1970\">\n              <!---->\n              <!---->\n            </div>\n            <div class=\"n-input__suffix\">\n              <!---->\n              <!---->\n              <!----><i class=\"n-base-icon n-date-picker-icon\"><svg width=\"28px\" height=\"28px\" viewBox=\"0 0 28 28\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n                  <g stroke=\"none\" stroke-width=\"1\" fill-rule=\"evenodd\">\n                    <g fill-rule=\"nonzero\">\n                      <path d=\"M21.75,3 C23.5449254,3 25,4.45507456 25,6.25 L25,21.75 C25,23.5449254 23.5449254,25 21.75,25 L6.25,25 C4.45507456,25 3,23.5449254 3,21.75 L3,6.25 C3,4.45507456 4.45507456,3 6.25,3 L21.75,3 Z M23.5,9.503 L4.5,9.503 L4.5,21.75 C4.5,22.7164983 5.28350169,23.5 6.25,23.5 L21.75,23.5 C22.7164983,23.5 23.5,22.7164983 23.5,21.75 L23.5,9.503 Z M21.75,4.5 L6.25,4.5 C5.28350169,4.5 4.5,5.28350169 4.5,6.25 L4.5,8.003 L23.5,8.003 L23.5,6.25 C23.5,5.28350169 22.7164983,4.5 21.75,4.5 Z\"></path>\n                    </g>\n                  </g>\n                </svg></i>\n              <!---->\n              <!---->\n            </div>\n          </div>\n          <!---->\n          <!---->\n          <div class=\"n-input__border\"></div>\n          <div class=\"n-input__state-border\"></div>\n          <!---->\n        </div>\n        <!---->\n      </div>\n      <div class=\"n-date-picker\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-icon-color-override: rgba(194, 194, 194, 1); --n-icon-color-disabled-override: rgba(209, 209, 209, 1);\">\n        <div class=\"n-input n-input--medium-size n-input--resizable n-input--stateful\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-count-text-color: rgb(118, 124, 130); --n-count-text-color-disabled: rgba(194, 194, 194, 1); --n-color: rgba(255, 255, 255, 1); --n-font-size: 14px; --n-font-weight: 400; --n-border-radius: 3px; --n-height: 34px; --n-padding-left: 12px; --n-padding-right: 12px; --n-text-color: rgb(51, 54, 57); --n-caret-color: #18a058; --n-text-decoration-color: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-focus: 1px solid #36ad6a; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-icon-size: 16px; --n-line-height-textarea: 1.6; --n-color-disabled: rgb(250, 250, 252); --n-color-focus: rgba(255, 255, 255, 1); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-loading-color: #18a058; --n-caret-color-warning: #f0a020; --n-color-focus-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-loading-color-warning: #f0a020; --n-caret-color-error: #d03050; --n-color-focus-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-loading-color-error: #d03050; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-size: 16px; --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-icon-color-hover: rgba(146, 146, 146, 1); --n-icon-color-pressed: rgba(175, 175, 175, 1); --n-icon-color-disabled: rgba(209, 209, 209, 1); --n-suffix-text-color: rgb(51, 54, 57);\" tabindex=\"0\">\n          <div class=\"n-input-wrapper\">\n            <!---->\n            <div class=\"n-input__input\"><input type=\"text\" class=\"n-input__input-el\" tabindex=\"-1\" placeholder=\"Datum und Uhrzeit auswählen\" size=\"20\" value=\"01.01.1970 08:00:00\">\n              <!---->\n              <!---->\n            </div>\n            <div class=\"n-input__suffix\">\n              <!---->\n              <!---->\n              <!----><i class=\"n-base-icon n-date-picker-icon\"><svg width=\"28px\" height=\"28px\" viewBox=\"0 0 28 28\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n                  <g stroke=\"none\" stroke-width=\"1\" fill-rule=\"evenodd\">\n                    <g fill-rule=\"nonzero\">\n                      <path d=\"M21.75,3 C23.5449254,3 25,4.45507456 25,6.25 L25,21.75 C25,23.5449254 23.5449254,25 21.75,25 L6.25,25 C4.45507456,25 3,23.5449254 3,21.75 L3,6.25 C3,4.45507456 4.45507456,3 6.25,3 L21.75,3 Z M23.5,9.503 L4.5,9.503 L4.5,21.75 C4.5,22.7164983 5.28350169,23.5 6.25,23.5 L21.75,23.5 C22.7164983,23.5 23.5,22.7164983 23.5,21.75 L23.5,9.503 Z M21.75,4.5 L6.25,4.5 C5.28350169,4.5 4.5,5.28350169 4.5,6.25 L4.5,8.003 L23.5,8.003 L23.5,6.25 C23.5,5.28350169 22.7164983,4.5 21.75,4.5 Z\"></path>\n                    </g>\n                  </g>\n                </svg></i>\n              <!---->\n              <!---->\n            </div>\n          </div>\n          <!---->\n          <!---->\n          <div class=\"n-input__border\"></div>\n          <div class=\"n-input__state-border\"></div>\n          <!---->\n        </div>\n        <!---->\n      </div>\n      <div class=\"n-date-picker\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-icon-color-override: rgba(194, 194, 194, 1); --n-icon-color-disabled-override: rgba(209, 209, 209, 1);\">\n        <div class=\"n-input n-input--medium-size n-input--resizable n-input--stateful\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-count-text-color: rgb(118, 124, 130); --n-count-text-color-disabled: rgba(194, 194, 194, 1); --n-color: rgba(255, 255, 255, 1); --n-font-size: 14px; --n-font-weight: 400; --n-border-radius: 3px; --n-height: 34px; --n-padding-left: 12px; --n-padding-right: 12px; --n-text-color: rgb(51, 54, 57); --n-caret-color: #18a058; --n-text-decoration-color: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-focus: 1px solid #36ad6a; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-icon-size: 16px; --n-line-height-textarea: 1.6; --n-color-disabled: rgb(250, 250, 252); --n-color-focus: rgba(255, 255, 255, 1); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-loading-color: #18a058; --n-caret-color-warning: #f0a020; --n-color-focus-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-loading-color-warning: #f0a020; --n-caret-color-error: #d03050; --n-color-focus-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-loading-color-error: #d03050; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-size: 16px; --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-icon-color-hover: rgba(146, 146, 146, 1); --n-icon-color-pressed: rgba(175, 175, 175, 1); --n-icon-color-disabled: rgba(209, 209, 209, 1); --n-suffix-text-color: rgb(51, 54, 57);\" tabindex=\"0\">\n          <div class=\"n-input-wrapper\">\n            <!---->\n            <div class=\"n-input__input\"><input type=\"text\" class=\"n-input__input-el\" tabindex=\"-1\" placeholder=\"Jahr auswählen\" size=\"20\" value=\"1970\">\n              <!---->\n              <!---->\n            </div>\n            <div class=\"n-input__suffix\">\n              <!---->\n              <!---->\n              <!----><i class=\"n-base-icon n-date-picker-icon\"><svg width=\"28px\" height=\"28px\" viewBox=\"0 0 28 28\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n                  <g stroke=\"none\" stroke-width=\"1\" fill-rule=\"evenodd\">\n                    <g fill-rule=\"nonzero\">\n                      <path d=\"M21.75,3 C23.5449254,3 25,4.45507456 25,6.25 L25,21.75 C25,23.5449254 23.5449254,25 21.75,25 L6.25,25 C4.45507456,25 3,23.5449254 3,21.75 L3,6.25 C3,4.45507456 4.45507456,3 6.25,3 L21.75,3 Z M23.5,9.503 L4.5,9.503 L4.5,21.75 C4.5,22.7164983 5.28350169,23.5 6.25,23.5 L21.75,23.5 C22.7164983,23.5 23.5,22.7164983 23.5,21.75 L23.5,9.503 Z M21.75,4.5 L6.25,4.5 C5.28350169,4.5 4.5,5.28350169 4.5,6.25 L4.5,8.003 L23.5,8.003 L23.5,6.25 C23.5,5.28350169 22.7164983,4.5 21.75,4.5 Z\"></path>\n                    </g>\n                  </g>\n                </svg></i>\n              <!---->\n              <!---->\n            </div>\n          </div>\n          <!---->\n          <!---->\n          <div class=\"n-input__border\"></div>\n          <div class=\"n-input__state-border\"></div>\n          <!---->\n        </div>\n        <!---->\n      </div>\n      <div class=\"n-date-picker\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-icon-color-override: rgba(194, 194, 194, 1); --n-icon-color-disabled-override: rgba(209, 209, 209, 1);\">\n        <div class=\"n-input n-input--medium-size n-input--resizable n-input--stateful\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-count-text-color: rgb(118, 124, 130); --n-count-text-color-disabled: rgba(194, 194, 194, 1); --n-color: rgba(255, 255, 255, 1); --n-font-size: 14px; --n-font-weight: 400; --n-border-radius: 3px; --n-height: 34px; --n-padding-left: 12px; --n-padding-right: 12px; --n-text-color: rgb(51, 54, 57); --n-caret-color: #18a058; --n-text-decoration-color: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-focus: 1px solid #36ad6a; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-icon-size: 16px; --n-line-height-textarea: 1.6; --n-color-disabled: rgb(250, 250, 252); --n-color-focus: rgba(255, 255, 255, 1); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-loading-color: #18a058; --n-caret-color-warning: #f0a020; --n-color-focus-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-loading-color-warning: #f0a020; --n-caret-color-error: #d03050; --n-color-focus-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-loading-color-error: #d03050; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-size: 16px; --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-icon-color-hover: rgba(146, 146, 146, 1); --n-icon-color-pressed: rgba(175, 175, 175, 1); --n-icon-color-disabled: rgba(209, 209, 209, 1); --n-suffix-text-color: rgb(51, 54, 57);\" tabindex=\"0\">\n          <div class=\"n-input-wrapper\">\n            <!---->\n            <div class=\"n-input__input\"><input type=\"text\" class=\"n-input__input-el\" tabindex=\"-1\" placeholder=\"Monat auswählen\" size=\"20\" value=\"01-1970\">\n              <!---->\n              <!---->\n            </div>\n            <div class=\"n-input__suffix\">\n              <!---->\n              <!---->\n              <!----><i class=\"n-base-icon n-date-picker-icon\"><svg width=\"28px\" height=\"28px\" viewBox=\"0 0 28 28\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n                  <g stroke=\"none\" stroke-width=\"1\" fill-rule=\"evenodd\">\n                    <g fill-rule=\"nonzero\">\n                      <path d=\"M21.75,3 C23.5449254,3 25,4.45507456 25,6.25 L25,21.75 C25,23.5449254 23.5449254,25 21.75,25 L6.25,25 C4.45507456,25 3,23.5449254 3,21.75 L3,6.25 C3,4.45507456 4.45507456,3 6.25,3 L21.75,3 Z M23.5,9.503 L4.5,9.503 L4.5,21.75 C4.5,22.7164983 5.28350169,23.5 6.25,23.5 L21.75,23.5 C22.7164983,23.5 23.5,22.7164983 23.5,21.75 L23.5,9.503 Z M21.75,4.5 L6.25,4.5 C5.28350169,4.5 4.5,5.28350169 4.5,6.25 L4.5,8.003 L23.5,8.003 L23.5,6.25 C23.5,5.28350169 22.7164983,4.5 21.75,4.5 Z\"></path>\n                    </g>\n                  </g>\n                </svg></i>\n              <!---->\n              <!---->\n            </div>\n          </div>\n          <!---->\n          <!---->\n          <div class=\"n-input__border\"></div>\n          <div class=\"n-input__state-border\"></div>\n          <!---->\n        </div>\n        <!---->\n      </div>\n    </div>\n  </div>\n</div>\"\n`;\n\nexports[`locale > works 12`] = `\n\"<div class=\"n-config-provider\">\n  <div>\n    <div class=\"n-input n-input--medium-size n-input--resizable n-input--stateful\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-count-text-color: rgb(118, 124, 130); --n-count-text-color-disabled: rgba(194, 194, 194, 1); --n-color: rgba(255, 255, 255, 1); --n-font-size: 14px; --n-font-weight: 400; --n-border-radius: 3px; --n-height: 34px; --n-padding-left: 12px; --n-padding-right: 12px; --n-text-color: rgb(51, 54, 57); --n-caret-color: #18a058; --n-text-decoration-color: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-focus: 1px solid #36ad6a; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-icon-size: 16px; --n-line-height-textarea: 1.6; --n-color-disabled: rgb(250, 250, 252); --n-color-focus: rgba(255, 255, 255, 1); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-loading-color: #18a058; --n-caret-color-warning: #f0a020; --n-color-focus-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-loading-color-warning: #f0a020; --n-caret-color-error: #d03050; --n-color-focus-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-loading-color-error: #d03050; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-size: 16px; --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-icon-color-hover: rgba(146, 146, 146, 1); --n-icon-color-pressed: rgba(175, 175, 175, 1); --n-icon-color-disabled: rgba(209, 209, 209, 1); --n-suffix-text-color: rgb(51, 54, 57);\">\n      <div class=\"n-input-wrapper\">\n        <!---->\n        <div class=\"n-input__input\"><input type=\"text\" class=\"n-input__input-el\" placeholder=\"Vennligst fyll ut\" size=\"20\">\n          <div class=\"n-input__placeholder\"><span>Vennligst fyll ut</span></div>\n          <!---->\n        </div>\n        <!---->\n      </div>\n      <!---->\n      <!---->\n      <div class=\"n-input__border\"></div>\n      <div class=\"n-input__state-border\"></div>\n      <!---->\n    </div>\n    <div>\n      <div class=\"n-date-picker\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-icon-color-override: rgba(194, 194, 194, 1); --n-icon-color-disabled-override: rgba(209, 209, 209, 1);\">\n        <div class=\"n-input n-input--medium-size n-input--resizable n-input--stateful\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-count-text-color: rgb(118, 124, 130); --n-count-text-color-disabled: rgba(194, 194, 194, 1); --n-color: rgba(255, 255, 255, 1); --n-font-size: 14px; --n-font-weight: 400; --n-border-radius: 3px; --n-height: 34px; --n-padding-left: 12px; --n-padding-right: 12px; --n-text-color: rgb(51, 54, 57); --n-caret-color: #18a058; --n-text-decoration-color: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-focus: 1px solid #36ad6a; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-icon-size: 16px; --n-line-height-textarea: 1.6; --n-color-disabled: rgb(250, 250, 252); --n-color-focus: rgba(255, 255, 255, 1); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-loading-color: #18a058; --n-caret-color-warning: #f0a020; --n-color-focus-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-loading-color-warning: #f0a020; --n-caret-color-error: #d03050; --n-color-focus-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-loading-color-error: #d03050; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-size: 16px; --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-icon-color-hover: rgba(146, 146, 146, 1); --n-icon-color-pressed: rgba(175, 175, 175, 1); --n-icon-color-disabled: rgba(209, 209, 209, 1); --n-suffix-text-color: rgb(51, 54, 57);\" tabindex=\"0\">\n          <div class=\"n-input-wrapper\">\n            <!---->\n            <div class=\"n-input__input\"><input type=\"text\" class=\"n-input__input-el\" tabindex=\"-1\" placeholder=\"Velg dato\" size=\"20\" value=\"01.01.1970\">\n              <!---->\n              <!---->\n            </div>\n            <div class=\"n-input__suffix\">\n              <!---->\n              <!---->\n              <!----><i class=\"n-base-icon n-date-picker-icon\"><svg width=\"28px\" height=\"28px\" viewBox=\"0 0 28 28\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n                  <g stroke=\"none\" stroke-width=\"1\" fill-rule=\"evenodd\">\n                    <g fill-rule=\"nonzero\">\n                      <path d=\"M21.75,3 C23.5449254,3 25,4.45507456 25,6.25 L25,21.75 C25,23.5449254 23.5449254,25 21.75,25 L6.25,25 C4.45507456,25 3,23.5449254 3,21.75 L3,6.25 C3,4.45507456 4.45507456,3 6.25,3 L21.75,3 Z M23.5,9.503 L4.5,9.503 L4.5,21.75 C4.5,22.7164983 5.28350169,23.5 6.25,23.5 L21.75,23.5 C22.7164983,23.5 23.5,22.7164983 23.5,21.75 L23.5,9.503 Z M21.75,4.5 L6.25,4.5 C5.28350169,4.5 4.5,5.28350169 4.5,6.25 L4.5,8.003 L23.5,8.003 L23.5,6.25 C23.5,5.28350169 22.7164983,4.5 21.75,4.5 Z\"></path>\n                    </g>\n                  </g>\n                </svg></i>\n              <!---->\n              <!---->\n            </div>\n          </div>\n          <!---->\n          <!---->\n          <div class=\"n-input__border\"></div>\n          <div class=\"n-input__state-border\"></div>\n          <!---->\n        </div>\n        <!---->\n      </div>\n      <div class=\"n-date-picker\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-icon-color-override: rgba(194, 194, 194, 1); --n-icon-color-disabled-override: rgba(209, 209, 209, 1);\">\n        <div class=\"n-input n-input--medium-size n-input--resizable n-input--stateful\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-count-text-color: rgb(118, 124, 130); --n-count-text-color-disabled: rgba(194, 194, 194, 1); --n-color: rgba(255, 255, 255, 1); --n-font-size: 14px; --n-font-weight: 400; --n-border-radius: 3px; --n-height: 34px; --n-padding-left: 12px; --n-padding-right: 12px; --n-text-color: rgb(51, 54, 57); --n-caret-color: #18a058; --n-text-decoration-color: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-focus: 1px solid #36ad6a; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-icon-size: 16px; --n-line-height-textarea: 1.6; --n-color-disabled: rgb(250, 250, 252); --n-color-focus: rgba(255, 255, 255, 1); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-loading-color: #18a058; --n-caret-color-warning: #f0a020; --n-color-focus-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-loading-color-warning: #f0a020; --n-caret-color-error: #d03050; --n-color-focus-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-loading-color-error: #d03050; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-size: 16px; --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-icon-color-hover: rgba(146, 146, 146, 1); --n-icon-color-pressed: rgba(175, 175, 175, 1); --n-icon-color-disabled: rgba(209, 209, 209, 1); --n-suffix-text-color: rgb(51, 54, 57);\" tabindex=\"0\">\n          <div class=\"n-input-wrapper\">\n            <!---->\n            <div class=\"n-input__input\"><input type=\"text\" class=\"n-input__input-el\" tabindex=\"-1\" placeholder=\"Velg dato og tid\" size=\"20\" value=\"01.01.1970 08:00:00\">\n              <!---->\n              <!---->\n            </div>\n            <div class=\"n-input__suffix\">\n              <!---->\n              <!---->\n              <!----><i class=\"n-base-icon n-date-picker-icon\"><svg width=\"28px\" height=\"28px\" viewBox=\"0 0 28 28\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n                  <g stroke=\"none\" stroke-width=\"1\" fill-rule=\"evenodd\">\n                    <g fill-rule=\"nonzero\">\n                      <path d=\"M21.75,3 C23.5449254,3 25,4.45507456 25,6.25 L25,21.75 C25,23.5449254 23.5449254,25 21.75,25 L6.25,25 C4.45507456,25 3,23.5449254 3,21.75 L3,6.25 C3,4.45507456 4.45507456,3 6.25,3 L21.75,3 Z M23.5,9.503 L4.5,9.503 L4.5,21.75 C4.5,22.7164983 5.28350169,23.5 6.25,23.5 L21.75,23.5 C22.7164983,23.5 23.5,22.7164983 23.5,21.75 L23.5,9.503 Z M21.75,4.5 L6.25,4.5 C5.28350169,4.5 4.5,5.28350169 4.5,6.25 L4.5,8.003 L23.5,8.003 L23.5,6.25 C23.5,5.28350169 22.7164983,4.5 21.75,4.5 Z\"></path>\n                    </g>\n                  </g>\n                </svg></i>\n              <!---->\n              <!---->\n            </div>\n          </div>\n          <!---->\n          <!---->\n          <div class=\"n-input__border\"></div>\n          <div class=\"n-input__state-border\"></div>\n          <!---->\n        </div>\n        <!---->\n      </div>\n      <div class=\"n-date-picker\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-icon-color-override: rgba(194, 194, 194, 1); --n-icon-color-disabled-override: rgba(209, 209, 209, 1);\">\n        <div class=\"n-input n-input--medium-size n-input--resizable n-input--stateful\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-count-text-color: rgb(118, 124, 130); --n-count-text-color-disabled: rgba(194, 194, 194, 1); --n-color: rgba(255, 255, 255, 1); --n-font-size: 14px; --n-font-weight: 400; --n-border-radius: 3px; --n-height: 34px; --n-padding-left: 12px; --n-padding-right: 12px; --n-text-color: rgb(51, 54, 57); --n-caret-color: #18a058; --n-text-decoration-color: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-focus: 1px solid #36ad6a; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-icon-size: 16px; --n-line-height-textarea: 1.6; --n-color-disabled: rgb(250, 250, 252); --n-color-focus: rgba(255, 255, 255, 1); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-loading-color: #18a058; --n-caret-color-warning: #f0a020; --n-color-focus-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-loading-color-warning: #f0a020; --n-caret-color-error: #d03050; --n-color-focus-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-loading-color-error: #d03050; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-size: 16px; --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-icon-color-hover: rgba(146, 146, 146, 1); --n-icon-color-pressed: rgba(175, 175, 175, 1); --n-icon-color-disabled: rgba(209, 209, 209, 1); --n-suffix-text-color: rgb(51, 54, 57);\" tabindex=\"0\">\n          <div class=\"n-input-wrapper\">\n            <!---->\n            <div class=\"n-input__input\"><input type=\"text\" class=\"n-input__input-el\" tabindex=\"-1\" placeholder=\"Select Year\" size=\"20\" value=\"1970\">\n              <!---->\n              <!---->\n            </div>\n            <div class=\"n-input__suffix\">\n              <!---->\n              <!---->\n              <!----><i class=\"n-base-icon n-date-picker-icon\"><svg width=\"28px\" height=\"28px\" viewBox=\"0 0 28 28\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n                  <g stroke=\"none\" stroke-width=\"1\" fill-rule=\"evenodd\">\n                    <g fill-rule=\"nonzero\">\n                      <path d=\"M21.75,3 C23.5449254,3 25,4.45507456 25,6.25 L25,21.75 C25,23.5449254 23.5449254,25 21.75,25 L6.25,25 C4.45507456,25 3,23.5449254 3,21.75 L3,6.25 C3,4.45507456 4.45507456,3 6.25,3 L21.75,3 Z M23.5,9.503 L4.5,9.503 L4.5,21.75 C4.5,22.7164983 5.28350169,23.5 6.25,23.5 L21.75,23.5 C22.7164983,23.5 23.5,22.7164983 23.5,21.75 L23.5,9.503 Z M21.75,4.5 L6.25,4.5 C5.28350169,4.5 4.5,5.28350169 4.5,6.25 L4.5,8.003 L23.5,8.003 L23.5,6.25 C23.5,5.28350169 22.7164983,4.5 21.75,4.5 Z\"></path>\n                    </g>\n                  </g>\n                </svg></i>\n              <!---->\n              <!---->\n            </div>\n          </div>\n          <!---->\n          <!---->\n          <div class=\"n-input__border\"></div>\n          <div class=\"n-input__state-border\"></div>\n          <!---->\n        </div>\n        <!---->\n      </div>\n      <div class=\"n-date-picker\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-icon-color-override: rgba(194, 194, 194, 1); --n-icon-color-disabled-override: rgba(209, 209, 209, 1);\">\n        <div class=\"n-input n-input--medium-size n-input--resizable n-input--stateful\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-count-text-color: rgb(118, 124, 130); --n-count-text-color-disabled: rgba(194, 194, 194, 1); --n-color: rgba(255, 255, 255, 1); --n-font-size: 14px; --n-font-weight: 400; --n-border-radius: 3px; --n-height: 34px; --n-padding-left: 12px; --n-padding-right: 12px; --n-text-color: rgb(51, 54, 57); --n-caret-color: #18a058; --n-text-decoration-color: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-focus: 1px solid #36ad6a; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-icon-size: 16px; --n-line-height-textarea: 1.6; --n-color-disabled: rgb(250, 250, 252); --n-color-focus: rgba(255, 255, 255, 1); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-loading-color: #18a058; --n-caret-color-warning: #f0a020; --n-color-focus-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-loading-color-warning: #f0a020; --n-caret-color-error: #d03050; --n-color-focus-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-loading-color-error: #d03050; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-size: 16px; --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-icon-color-hover: rgba(146, 146, 146, 1); --n-icon-color-pressed: rgba(175, 175, 175, 1); --n-icon-color-disabled: rgba(209, 209, 209, 1); --n-suffix-text-color: rgb(51, 54, 57);\" tabindex=\"0\">\n          <div class=\"n-input-wrapper\">\n            <!---->\n            <div class=\"n-input__input\"><input type=\"text\" class=\"n-input__input-el\" tabindex=\"-1\" placeholder=\"Velg måned\" size=\"20\" value=\"01.1970\">\n              <!---->\n              <!---->\n            </div>\n            <div class=\"n-input__suffix\">\n              <!---->\n              <!---->\n              <!----><i class=\"n-base-icon n-date-picker-icon\"><svg width=\"28px\" height=\"28px\" viewBox=\"0 0 28 28\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n                  <g stroke=\"none\" stroke-width=\"1\" fill-rule=\"evenodd\">\n                    <g fill-rule=\"nonzero\">\n                      <path d=\"M21.75,3 C23.5449254,3 25,4.45507456 25,6.25 L25,21.75 C25,23.5449254 23.5449254,25 21.75,25 L6.25,25 C4.45507456,25 3,23.5449254 3,21.75 L3,6.25 C3,4.45507456 4.45507456,3 6.25,3 L21.75,3 Z M23.5,9.503 L4.5,9.503 L4.5,21.75 C4.5,22.7164983 5.28350169,23.5 6.25,23.5 L21.75,23.5 C22.7164983,23.5 23.5,22.7164983 23.5,21.75 L23.5,9.503 Z M21.75,4.5 L6.25,4.5 C5.28350169,4.5 4.5,5.28350169 4.5,6.25 L4.5,8.003 L23.5,8.003 L23.5,6.25 C23.5,5.28350169 22.7164983,4.5 21.75,4.5 Z\"></path>\n                    </g>\n                  </g>\n                </svg></i>\n              <!---->\n              <!---->\n            </div>\n          </div>\n          <!---->\n          <!---->\n          <div class=\"n-input__border\"></div>\n          <div class=\"n-input__state-border\"></div>\n          <!---->\n        </div>\n        <!---->\n      </div>\n    </div>\n  </div>\n</div>\"\n`;\n\nexports[`locale > works 13`] = `\n\"<div class=\"n-config-provider\">\n  <div>\n    <div class=\"n-input n-input--medium-size n-input--resizable n-input--stateful\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-count-text-color: rgb(118, 124, 130); --n-count-text-color-disabled: rgba(194, 194, 194, 1); --n-color: rgba(255, 255, 255, 1); --n-font-size: 14px; --n-font-weight: 400; --n-border-radius: 3px; --n-height: 34px; --n-padding-left: 12px; --n-padding-right: 12px; --n-text-color: rgb(51, 54, 57); --n-caret-color: #18a058; --n-text-decoration-color: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-focus: 1px solid #36ad6a; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-icon-size: 16px; --n-line-height-textarea: 1.6; --n-color-disabled: rgb(250, 250, 252); --n-color-focus: rgba(255, 255, 255, 1); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-loading-color: #18a058; --n-caret-color-warning: #f0a020; --n-color-focus-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-loading-color-warning: #f0a020; --n-caret-color-error: #d03050; --n-color-focus-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-loading-color-error: #d03050; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-size: 16px; --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-icon-color-hover: rgba(146, 146, 146, 1); --n-icon-color-pressed: rgba(175, 175, 175, 1); --n-icon-color-disabled: rgba(209, 209, 209, 1); --n-suffix-text-color: rgb(51, 54, 57);\">\n      <div class=\"n-input-wrapper\">\n        <!---->\n        <div class=\"n-input__input\"><input type=\"text\" class=\"n-input__input-el\" placeholder=\"Saisir\" size=\"20\">\n          <div class=\"n-input__placeholder\"><span>Saisir</span></div>\n          <!---->\n        </div>\n        <!---->\n      </div>\n      <!---->\n      <!---->\n      <div class=\"n-input__border\"></div>\n      <div class=\"n-input__state-border\"></div>\n      <!---->\n    </div>\n    <div>\n      <div class=\"n-date-picker\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-icon-color-override: rgba(194, 194, 194, 1); --n-icon-color-disabled-override: rgba(209, 209, 209, 1);\">\n        <div class=\"n-input n-input--medium-size n-input--resizable n-input--stateful\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-count-text-color: rgb(118, 124, 130); --n-count-text-color-disabled: rgba(194, 194, 194, 1); --n-color: rgba(255, 255, 255, 1); --n-font-size: 14px; --n-font-weight: 400; --n-border-radius: 3px; --n-height: 34px; --n-padding-left: 12px; --n-padding-right: 12px; --n-text-color: rgb(51, 54, 57); --n-caret-color: #18a058; --n-text-decoration-color: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-focus: 1px solid #36ad6a; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-icon-size: 16px; --n-line-height-textarea: 1.6; --n-color-disabled: rgb(250, 250, 252); --n-color-focus: rgba(255, 255, 255, 1); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-loading-color: #18a058; --n-caret-color-warning: #f0a020; --n-color-focus-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-loading-color-warning: #f0a020; --n-caret-color-error: #d03050; --n-color-focus-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-loading-color-error: #d03050; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-size: 16px; --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-icon-color-hover: rgba(146, 146, 146, 1); --n-icon-color-pressed: rgba(175, 175, 175, 1); --n-icon-color-disabled: rgba(209, 209, 209, 1); --n-suffix-text-color: rgb(51, 54, 57);\" tabindex=\"0\">\n          <div class=\"n-input-wrapper\">\n            <!---->\n            <div class=\"n-input__input\"><input type=\"text\" class=\"n-input__input-el\" tabindex=\"-1\" placeholder=\"Sélectionner la date\" size=\"20\" value=\"01/01/1970\">\n              <!---->\n              <!---->\n            </div>\n            <div class=\"n-input__suffix\">\n              <!---->\n              <!---->\n              <!----><i class=\"n-base-icon n-date-picker-icon\"><svg width=\"28px\" height=\"28px\" viewBox=\"0 0 28 28\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n                  <g stroke=\"none\" stroke-width=\"1\" fill-rule=\"evenodd\">\n                    <g fill-rule=\"nonzero\">\n                      <path d=\"M21.75,3 C23.5449254,3 25,4.45507456 25,6.25 L25,21.75 C25,23.5449254 23.5449254,25 21.75,25 L6.25,25 C4.45507456,25 3,23.5449254 3,21.75 L3,6.25 C3,4.45507456 4.45507456,3 6.25,3 L21.75,3 Z M23.5,9.503 L4.5,9.503 L4.5,21.75 C4.5,22.7164983 5.28350169,23.5 6.25,23.5 L21.75,23.5 C22.7164983,23.5 23.5,22.7164983 23.5,21.75 L23.5,9.503 Z M21.75,4.5 L6.25,4.5 C5.28350169,4.5 4.5,5.28350169 4.5,6.25 L4.5,8.003 L23.5,8.003 L23.5,6.25 C23.5,5.28350169 22.7164983,4.5 21.75,4.5 Z\"></path>\n                    </g>\n                  </g>\n                </svg></i>\n              <!---->\n              <!---->\n            </div>\n          </div>\n          <!---->\n          <!---->\n          <div class=\"n-input__border\"></div>\n          <div class=\"n-input__state-border\"></div>\n          <!---->\n        </div>\n        <!---->\n      </div>\n      <div class=\"n-date-picker\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-icon-color-override: rgba(194, 194, 194, 1); --n-icon-color-disabled-override: rgba(209, 209, 209, 1);\">\n        <div class=\"n-input n-input--medium-size n-input--resizable n-input--stateful\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-count-text-color: rgb(118, 124, 130); --n-count-text-color-disabled: rgba(194, 194, 194, 1); --n-color: rgba(255, 255, 255, 1); --n-font-size: 14px; --n-font-weight: 400; --n-border-radius: 3px; --n-height: 34px; --n-padding-left: 12px; --n-padding-right: 12px; --n-text-color: rgb(51, 54, 57); --n-caret-color: #18a058; --n-text-decoration-color: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-focus: 1px solid #36ad6a; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-icon-size: 16px; --n-line-height-textarea: 1.6; --n-color-disabled: rgb(250, 250, 252); --n-color-focus: rgba(255, 255, 255, 1); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-loading-color: #18a058; --n-caret-color-warning: #f0a020; --n-color-focus-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-loading-color-warning: #f0a020; --n-caret-color-error: #d03050; --n-color-focus-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-loading-color-error: #d03050; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-size: 16px; --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-icon-color-hover: rgba(146, 146, 146, 1); --n-icon-color-pressed: rgba(175, 175, 175, 1); --n-icon-color-disabled: rgba(209, 209, 209, 1); --n-suffix-text-color: rgb(51, 54, 57);\" tabindex=\"0\">\n          <div class=\"n-input-wrapper\">\n            <!---->\n            <div class=\"n-input__input\"><input type=\"text\" class=\"n-input__input-el\" tabindex=\"-1\" placeholder=\"Sélectionner la date et l'heure\" size=\"20\" value=\"01/01/1970 08:00:00\">\n              <!---->\n              <!---->\n            </div>\n            <div class=\"n-input__suffix\">\n              <!---->\n              <!---->\n              <!----><i class=\"n-base-icon n-date-picker-icon\"><svg width=\"28px\" height=\"28px\" viewBox=\"0 0 28 28\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n                  <g stroke=\"none\" stroke-width=\"1\" fill-rule=\"evenodd\">\n                    <g fill-rule=\"nonzero\">\n                      <path d=\"M21.75,3 C23.5449254,3 25,4.45507456 25,6.25 L25,21.75 C25,23.5449254 23.5449254,25 21.75,25 L6.25,25 C4.45507456,25 3,23.5449254 3,21.75 L3,6.25 C3,4.45507456 4.45507456,3 6.25,3 L21.75,3 Z M23.5,9.503 L4.5,9.503 L4.5,21.75 C4.5,22.7164983 5.28350169,23.5 6.25,23.5 L21.75,23.5 C22.7164983,23.5 23.5,22.7164983 23.5,21.75 L23.5,9.503 Z M21.75,4.5 L6.25,4.5 C5.28350169,4.5 4.5,5.28350169 4.5,6.25 L4.5,8.003 L23.5,8.003 L23.5,6.25 C23.5,5.28350169 22.7164983,4.5 21.75,4.5 Z\"></path>\n                    </g>\n                  </g>\n                </svg></i>\n              <!---->\n              <!---->\n            </div>\n          </div>\n          <!---->\n          <!---->\n          <div class=\"n-input__border\"></div>\n          <div class=\"n-input__state-border\"></div>\n          <!---->\n        </div>\n        <!---->\n      </div>\n      <div class=\"n-date-picker\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-icon-color-override: rgba(194, 194, 194, 1); --n-icon-color-disabled-override: rgba(209, 209, 209, 1);\">\n        <div class=\"n-input n-input--medium-size n-input--resizable n-input--stateful\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-count-text-color: rgb(118, 124, 130); --n-count-text-color-disabled: rgba(194, 194, 194, 1); --n-color: rgba(255, 255, 255, 1); --n-font-size: 14px; --n-font-weight: 400; --n-border-radius: 3px; --n-height: 34px; --n-padding-left: 12px; --n-padding-right: 12px; --n-text-color: rgb(51, 54, 57); --n-caret-color: #18a058; --n-text-decoration-color: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-focus: 1px solid #36ad6a; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-icon-size: 16px; --n-line-height-textarea: 1.6; --n-color-disabled: rgb(250, 250, 252); --n-color-focus: rgba(255, 255, 255, 1); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-loading-color: #18a058; --n-caret-color-warning: #f0a020; --n-color-focus-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-loading-color-warning: #f0a020; --n-caret-color-error: #d03050; --n-color-focus-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-loading-color-error: #d03050; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-size: 16px; --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-icon-color-hover: rgba(146, 146, 146, 1); --n-icon-color-pressed: rgba(175, 175, 175, 1); --n-icon-color-disabled: rgba(209, 209, 209, 1); --n-suffix-text-color: rgb(51, 54, 57);\" tabindex=\"0\">\n          <div class=\"n-input-wrapper\">\n            <!---->\n            <div class=\"n-input__input\"><input type=\"text\" class=\"n-input__input-el\" tabindex=\"-1\" placeholder=\"Sélectionner l'année\" size=\"20\" value=\"1970\">\n              <!---->\n              <!---->\n            </div>\n            <div class=\"n-input__suffix\">\n              <!---->\n              <!---->\n              <!----><i class=\"n-base-icon n-date-picker-icon\"><svg width=\"28px\" height=\"28px\" viewBox=\"0 0 28 28\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n                  <g stroke=\"none\" stroke-width=\"1\" fill-rule=\"evenodd\">\n                    <g fill-rule=\"nonzero\">\n                      <path d=\"M21.75,3 C23.5449254,3 25,4.45507456 25,6.25 L25,21.75 C25,23.5449254 23.5449254,25 21.75,25 L6.25,25 C4.45507456,25 3,23.5449254 3,21.75 L3,6.25 C3,4.45507456 4.45507456,3 6.25,3 L21.75,3 Z M23.5,9.503 L4.5,9.503 L4.5,21.75 C4.5,22.7164983 5.28350169,23.5 6.25,23.5 L21.75,23.5 C22.7164983,23.5 23.5,22.7164983 23.5,21.75 L23.5,9.503 Z M21.75,4.5 L6.25,4.5 C5.28350169,4.5 4.5,5.28350169 4.5,6.25 L4.5,8.003 L23.5,8.003 L23.5,6.25 C23.5,5.28350169 22.7164983,4.5 21.75,4.5 Z\"></path>\n                    </g>\n                  </g>\n                </svg></i>\n              <!---->\n              <!---->\n            </div>\n          </div>\n          <!---->\n          <!---->\n          <div class=\"n-input__border\"></div>\n          <div class=\"n-input__state-border\"></div>\n          <!---->\n        </div>\n        <!---->\n      </div>\n      <div class=\"n-date-picker\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-icon-color-override: rgba(194, 194, 194, 1); --n-icon-color-disabled-override: rgba(209, 209, 209, 1);\">\n        <div class=\"n-input n-input--medium-size n-input--resizable n-input--stateful\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-count-text-color: rgb(118, 124, 130); --n-count-text-color-disabled: rgba(194, 194, 194, 1); --n-color: rgba(255, 255, 255, 1); --n-font-size: 14px; --n-font-weight: 400; --n-border-radius: 3px; --n-height: 34px; --n-padding-left: 12px; --n-padding-right: 12px; --n-text-color: rgb(51, 54, 57); --n-caret-color: #18a058; --n-text-decoration-color: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-focus: 1px solid #36ad6a; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-icon-size: 16px; --n-line-height-textarea: 1.6; --n-color-disabled: rgb(250, 250, 252); --n-color-focus: rgba(255, 255, 255, 1); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-loading-color: #18a058; --n-caret-color-warning: #f0a020; --n-color-focus-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-loading-color-warning: #f0a020; --n-caret-color-error: #d03050; --n-color-focus-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-loading-color-error: #d03050; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-size: 16px; --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-icon-color-hover: rgba(146, 146, 146, 1); --n-icon-color-pressed: rgba(175, 175, 175, 1); --n-icon-color-disabled: rgba(209, 209, 209, 1); --n-suffix-text-color: rgb(51, 54, 57);\" tabindex=\"0\">\n          <div class=\"n-input-wrapper\">\n            <!---->\n            <div class=\"n-input__input\"><input type=\"text\" class=\"n-input__input-el\" tabindex=\"-1\" placeholder=\"Sélectionner le mois\" size=\"20\" value=\"01/1970\">\n              <!---->\n              <!---->\n            </div>\n            <div class=\"n-input__suffix\">\n              <!---->\n              <!---->\n              <!----><i class=\"n-base-icon n-date-picker-icon\"><svg width=\"28px\" height=\"28px\" viewBox=\"0 0 28 28\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n                  <g stroke=\"none\" stroke-width=\"1\" fill-rule=\"evenodd\">\n                    <g fill-rule=\"nonzero\">\n                      <path d=\"M21.75,3 C23.5449254,3 25,4.45507456 25,6.25 L25,21.75 C25,23.5449254 23.5449254,25 21.75,25 L6.25,25 C4.45507456,25 3,23.5449254 3,21.75 L3,6.25 C3,4.45507456 4.45507456,3 6.25,3 L21.75,3 Z M23.5,9.503 L4.5,9.503 L4.5,21.75 C4.5,22.7164983 5.28350169,23.5 6.25,23.5 L21.75,23.5 C22.7164983,23.5 23.5,22.7164983 23.5,21.75 L23.5,9.503 Z M21.75,4.5 L6.25,4.5 C5.28350169,4.5 4.5,5.28350169 4.5,6.25 L4.5,8.003 L23.5,8.003 L23.5,6.25 C23.5,5.28350169 22.7164983,4.5 21.75,4.5 Z\"></path>\n                    </g>\n                  </g>\n                </svg></i>\n              <!---->\n              <!---->\n            </div>\n          </div>\n          <!---->\n          <!---->\n          <div class=\"n-input__border\"></div>\n          <div class=\"n-input__state-border\"></div>\n          <!---->\n        </div>\n        <!---->\n      </div>\n    </div>\n  </div>\n</div>\"\n`;\n\nexports[`locale > works 14`] = `\n\"<div class=\"n-config-provider\">\n  <div>\n    <div class=\"n-input n-input--medium-size n-input--resizable n-input--stateful\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-count-text-color: rgb(118, 124, 130); --n-count-text-color-disabled: rgba(194, 194, 194, 1); --n-color: rgba(255, 255, 255, 1); --n-font-size: 14px; --n-font-weight: 400; --n-border-radius: 3px; --n-height: 34px; --n-padding-left: 12px; --n-padding-right: 12px; --n-text-color: rgb(51, 54, 57); --n-caret-color: #18a058; --n-text-decoration-color: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-focus: 1px solid #36ad6a; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-icon-size: 16px; --n-line-height-textarea: 1.6; --n-color-disabled: rgb(250, 250, 252); --n-color-focus: rgba(255, 255, 255, 1); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-loading-color: #18a058; --n-caret-color-warning: #f0a020; --n-color-focus-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-loading-color-warning: #f0a020; --n-caret-color-error: #d03050; --n-color-focus-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-loading-color-error: #d03050; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-size: 16px; --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-icon-color-hover: rgba(146, 146, 146, 1); --n-icon-color-pressed: rgba(175, 175, 175, 1); --n-icon-color-disabled: rgba(209, 209, 209, 1); --n-suffix-text-color: rgb(51, 54, 57);\">\n      <div class=\"n-input-wrapper\">\n        <!---->\n        <div class=\"n-input__input\"><input type=\"text\" class=\"n-input__input-el\" placeholder=\"Ingrese datos por favor\" size=\"20\">\n          <div class=\"n-input__placeholder\"><span>Ingrese datos por favor</span></div>\n          <!---->\n        </div>\n        <!---->\n      </div>\n      <!---->\n      <!---->\n      <div class=\"n-input__border\"></div>\n      <div class=\"n-input__state-border\"></div>\n      <!---->\n    </div>\n    <div>\n      <div class=\"n-date-picker\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-icon-color-override: rgba(194, 194, 194, 1); --n-icon-color-disabled-override: rgba(209, 209, 209, 1);\">\n        <div class=\"n-input n-input--medium-size n-input--resizable n-input--stateful\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-count-text-color: rgb(118, 124, 130); --n-count-text-color-disabled: rgba(194, 194, 194, 1); --n-color: rgba(255, 255, 255, 1); --n-font-size: 14px; --n-font-weight: 400; --n-border-radius: 3px; --n-height: 34px; --n-padding-left: 12px; --n-padding-right: 12px; --n-text-color: rgb(51, 54, 57); --n-caret-color: #18a058; --n-text-decoration-color: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-focus: 1px solid #36ad6a; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-icon-size: 16px; --n-line-height-textarea: 1.6; --n-color-disabled: rgb(250, 250, 252); --n-color-focus: rgba(255, 255, 255, 1); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-loading-color: #18a058; --n-caret-color-warning: #f0a020; --n-color-focus-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-loading-color-warning: #f0a020; --n-caret-color-error: #d03050; --n-color-focus-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-loading-color-error: #d03050; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-size: 16px; --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-icon-color-hover: rgba(146, 146, 146, 1); --n-icon-color-pressed: rgba(175, 175, 175, 1); --n-icon-color-disabled: rgba(209, 209, 209, 1); --n-suffix-text-color: rgb(51, 54, 57);\" tabindex=\"0\">\n          <div class=\"n-input-wrapper\">\n            <!---->\n            <div class=\"n-input__input\"><input type=\"text\" class=\"n-input__input-el\" tabindex=\"-1\" placeholder=\"Seleccionar fecha\" size=\"20\" value=\"1970-01-01\">\n              <!---->\n              <!---->\n            </div>\n            <div class=\"n-input__suffix\">\n              <!---->\n              <!---->\n              <!----><i class=\"n-base-icon n-date-picker-icon\"><svg width=\"28px\" height=\"28px\" viewBox=\"0 0 28 28\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n                  <g stroke=\"none\" stroke-width=\"1\" fill-rule=\"evenodd\">\n                    <g fill-rule=\"nonzero\">\n                      <path d=\"M21.75,3 C23.5449254,3 25,4.45507456 25,6.25 L25,21.75 C25,23.5449254 23.5449254,25 21.75,25 L6.25,25 C4.45507456,25 3,23.5449254 3,21.75 L3,6.25 C3,4.45507456 4.45507456,3 6.25,3 L21.75,3 Z M23.5,9.503 L4.5,9.503 L4.5,21.75 C4.5,22.7164983 5.28350169,23.5 6.25,23.5 L21.75,23.5 C22.7164983,23.5 23.5,22.7164983 23.5,21.75 L23.5,9.503 Z M21.75,4.5 L6.25,4.5 C5.28350169,4.5 4.5,5.28350169 4.5,6.25 L4.5,8.003 L23.5,8.003 L23.5,6.25 C23.5,5.28350169 22.7164983,4.5 21.75,4.5 Z\"></path>\n                    </g>\n                  </g>\n                </svg></i>\n              <!---->\n              <!---->\n            </div>\n          </div>\n          <!---->\n          <!---->\n          <div class=\"n-input__border\"></div>\n          <div class=\"n-input__state-border\"></div>\n          <!---->\n        </div>\n        <!---->\n      </div>\n      <div class=\"n-date-picker\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-icon-color-override: rgba(194, 194, 194, 1); --n-icon-color-disabled-override: rgba(209, 209, 209, 1);\">\n        <div class=\"n-input n-input--medium-size n-input--resizable n-input--stateful\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-count-text-color: rgb(118, 124, 130); --n-count-text-color-disabled: rgba(194, 194, 194, 1); --n-color: rgba(255, 255, 255, 1); --n-font-size: 14px; --n-font-weight: 400; --n-border-radius: 3px; --n-height: 34px; --n-padding-left: 12px; --n-padding-right: 12px; --n-text-color: rgb(51, 54, 57); --n-caret-color: #18a058; --n-text-decoration-color: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-focus: 1px solid #36ad6a; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-icon-size: 16px; --n-line-height-textarea: 1.6; --n-color-disabled: rgb(250, 250, 252); --n-color-focus: rgba(255, 255, 255, 1); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-loading-color: #18a058; --n-caret-color-warning: #f0a020; --n-color-focus-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-loading-color-warning: #f0a020; --n-caret-color-error: #d03050; --n-color-focus-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-loading-color-error: #d03050; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-size: 16px; --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-icon-color-hover: rgba(146, 146, 146, 1); --n-icon-color-pressed: rgba(175, 175, 175, 1); --n-icon-color-disabled: rgba(209, 209, 209, 1); --n-suffix-text-color: rgb(51, 54, 57);\" tabindex=\"0\">\n          <div class=\"n-input-wrapper\">\n            <!---->\n            <div class=\"n-input__input\"><input type=\"text\" class=\"n-input__input-el\" tabindex=\"-1\" placeholder=\"Seleccionar fecha y hora\" size=\"20\" value=\"1970-01-01 08:00:00\">\n              <!---->\n              <!---->\n            </div>\n            <div class=\"n-input__suffix\">\n              <!---->\n              <!---->\n              <!----><i class=\"n-base-icon n-date-picker-icon\"><svg width=\"28px\" height=\"28px\" viewBox=\"0 0 28 28\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n                  <g stroke=\"none\" stroke-width=\"1\" fill-rule=\"evenodd\">\n                    <g fill-rule=\"nonzero\">\n                      <path d=\"M21.75,3 C23.5449254,3 25,4.45507456 25,6.25 L25,21.75 C25,23.5449254 23.5449254,25 21.75,25 L6.25,25 C4.45507456,25 3,23.5449254 3,21.75 L3,6.25 C3,4.45507456 4.45507456,3 6.25,3 L21.75,3 Z M23.5,9.503 L4.5,9.503 L4.5,21.75 C4.5,22.7164983 5.28350169,23.5 6.25,23.5 L21.75,23.5 C22.7164983,23.5 23.5,22.7164983 23.5,21.75 L23.5,9.503 Z M21.75,4.5 L6.25,4.5 C5.28350169,4.5 4.5,5.28350169 4.5,6.25 L4.5,8.003 L23.5,8.003 L23.5,6.25 C23.5,5.28350169 22.7164983,4.5 21.75,4.5 Z\"></path>\n                    </g>\n                  </g>\n                </svg></i>\n              <!---->\n              <!---->\n            </div>\n          </div>\n          <!---->\n          <!---->\n          <div class=\"n-input__border\"></div>\n          <div class=\"n-input__state-border\"></div>\n          <!---->\n        </div>\n        <!---->\n      </div>\n      <div class=\"n-date-picker\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-icon-color-override: rgba(194, 194, 194, 1); --n-icon-color-disabled-override: rgba(209, 209, 209, 1);\">\n        <div class=\"n-input n-input--medium-size n-input--resizable n-input--stateful\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-count-text-color: rgb(118, 124, 130); --n-count-text-color-disabled: rgba(194, 194, 194, 1); --n-color: rgba(255, 255, 255, 1); --n-font-size: 14px; --n-font-weight: 400; --n-border-radius: 3px; --n-height: 34px; --n-padding-left: 12px; --n-padding-right: 12px; --n-text-color: rgb(51, 54, 57); --n-caret-color: #18a058; --n-text-decoration-color: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-focus: 1px solid #36ad6a; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-icon-size: 16px; --n-line-height-textarea: 1.6; --n-color-disabled: rgb(250, 250, 252); --n-color-focus: rgba(255, 255, 255, 1); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-loading-color: #18a058; --n-caret-color-warning: #f0a020; --n-color-focus-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-loading-color-warning: #f0a020; --n-caret-color-error: #d03050; --n-color-focus-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-loading-color-error: #d03050; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-size: 16px; --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-icon-color-hover: rgba(146, 146, 146, 1); --n-icon-color-pressed: rgba(175, 175, 175, 1); --n-icon-color-disabled: rgba(209, 209, 209, 1); --n-suffix-text-color: rgb(51, 54, 57);\" tabindex=\"0\">\n          <div class=\"n-input-wrapper\">\n            <!---->\n            <div class=\"n-input__input\"><input type=\"text\" class=\"n-input__input-el\" tabindex=\"-1\" placeholder=\"Seleccionar año\" size=\"20\" value=\"1970\">\n              <!---->\n              <!---->\n            </div>\n            <div class=\"n-input__suffix\">\n              <!---->\n              <!---->\n              <!----><i class=\"n-base-icon n-date-picker-icon\"><svg width=\"28px\" height=\"28px\" viewBox=\"0 0 28 28\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n                  <g stroke=\"none\" stroke-width=\"1\" fill-rule=\"evenodd\">\n                    <g fill-rule=\"nonzero\">\n                      <path d=\"M21.75,3 C23.5449254,3 25,4.45507456 25,6.25 L25,21.75 C25,23.5449254 23.5449254,25 21.75,25 L6.25,25 C4.45507456,25 3,23.5449254 3,21.75 L3,6.25 C3,4.45507456 4.45507456,3 6.25,3 L21.75,3 Z M23.5,9.503 L4.5,9.503 L4.5,21.75 C4.5,22.7164983 5.28350169,23.5 6.25,23.5 L21.75,23.5 C22.7164983,23.5 23.5,22.7164983 23.5,21.75 L23.5,9.503 Z M21.75,4.5 L6.25,4.5 C5.28350169,4.5 4.5,5.28350169 4.5,6.25 L4.5,8.003 L23.5,8.003 L23.5,6.25 C23.5,5.28350169 22.7164983,4.5 21.75,4.5 Z\"></path>\n                    </g>\n                  </g>\n                </svg></i>\n              <!---->\n              <!---->\n            </div>\n          </div>\n          <!---->\n          <!---->\n          <div class=\"n-input__border\"></div>\n          <div class=\"n-input__state-border\"></div>\n          <!---->\n        </div>\n        <!---->\n      </div>\n      <div class=\"n-date-picker\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-icon-color-override: rgba(194, 194, 194, 1); --n-icon-color-disabled-override: rgba(209, 209, 209, 1);\">\n        <div class=\"n-input n-input--medium-size n-input--resizable n-input--stateful\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-count-text-color: rgb(118, 124, 130); --n-count-text-color-disabled: rgba(194, 194, 194, 1); --n-color: rgba(255, 255, 255, 1); --n-font-size: 14px; --n-font-weight: 400; --n-border-radius: 3px; --n-height: 34px; --n-padding-left: 12px; --n-padding-right: 12px; --n-text-color: rgb(51, 54, 57); --n-caret-color: #18a058; --n-text-decoration-color: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-focus: 1px solid #36ad6a; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-icon-size: 16px; --n-line-height-textarea: 1.6; --n-color-disabled: rgb(250, 250, 252); --n-color-focus: rgba(255, 255, 255, 1); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-loading-color: #18a058; --n-caret-color-warning: #f0a020; --n-color-focus-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-loading-color-warning: #f0a020; --n-caret-color-error: #d03050; --n-color-focus-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-loading-color-error: #d03050; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-size: 16px; --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-icon-color-hover: rgba(146, 146, 146, 1); --n-icon-color-pressed: rgba(175, 175, 175, 1); --n-icon-color-disabled: rgba(209, 209, 209, 1); --n-suffix-text-color: rgb(51, 54, 57);\" tabindex=\"0\">\n          <div class=\"n-input-wrapper\">\n            <!---->\n            <div class=\"n-input__input\"><input type=\"text\" class=\"n-input__input-el\" tabindex=\"-1\" placeholder=\"Seleccionar mes\" size=\"20\" value=\"1970-01\">\n              <!---->\n              <!---->\n            </div>\n            <div class=\"n-input__suffix\">\n              <!---->\n              <!---->\n              <!----><i class=\"n-base-icon n-date-picker-icon\"><svg width=\"28px\" height=\"28px\" viewBox=\"0 0 28 28\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n                  <g stroke=\"none\" stroke-width=\"1\" fill-rule=\"evenodd\">\n                    <g fill-rule=\"nonzero\">\n                      <path d=\"M21.75,3 C23.5449254,3 25,4.45507456 25,6.25 L25,21.75 C25,23.5449254 23.5449254,25 21.75,25 L6.25,25 C4.45507456,25 3,23.5449254 3,21.75 L3,6.25 C3,4.45507456 4.45507456,3 6.25,3 L21.75,3 Z M23.5,9.503 L4.5,9.503 L4.5,21.75 C4.5,22.7164983 5.28350169,23.5 6.25,23.5 L21.75,23.5 C22.7164983,23.5 23.5,22.7164983 23.5,21.75 L23.5,9.503 Z M21.75,4.5 L6.25,4.5 C5.28350169,4.5 4.5,5.28350169 4.5,6.25 L4.5,8.003 L23.5,8.003 L23.5,6.25 C23.5,5.28350169 22.7164983,4.5 21.75,4.5 Z\"></path>\n                    </g>\n                  </g>\n                </svg></i>\n              <!---->\n              <!---->\n            </div>\n          </div>\n          <!---->\n          <!---->\n          <div class=\"n-input__border\"></div>\n          <div class=\"n-input__state-border\"></div>\n          <!---->\n        </div>\n        <!---->\n      </div>\n    </div>\n  </div>\n</div>\"\n`;\n\nexports[`locale > works 15`] = `\n\"<div class=\"n-config-provider\">\n  <div>\n    <div class=\"n-input n-input--medium-size n-input--resizable n-input--stateful\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-count-text-color: rgb(118, 124, 130); --n-count-text-color-disabled: rgba(194, 194, 194, 1); --n-color: rgba(255, 255, 255, 1); --n-font-size: 14px; --n-font-weight: 400; --n-border-radius: 3px; --n-height: 34px; --n-padding-left: 12px; --n-padding-right: 12px; --n-text-color: rgb(51, 54, 57); --n-caret-color: #18a058; --n-text-decoration-color: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-focus: 1px solid #36ad6a; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-icon-size: 16px; --n-line-height-textarea: 1.6; --n-color-disabled: rgb(250, 250, 252); --n-color-focus: rgba(255, 255, 255, 1); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-loading-color: #18a058; --n-caret-color-warning: #f0a020; --n-color-focus-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-loading-color-warning: #f0a020; --n-caret-color-error: #d03050; --n-color-focus-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-loading-color-error: #d03050; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-size: 16px; --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-icon-color-hover: rgba(146, 146, 146, 1); --n-icon-color-pressed: rgba(175, 175, 175, 1); --n-icon-color-disabled: rgba(209, 209, 209, 1); --n-suffix-text-color: rgb(51, 54, 57);\">\n      <div class=\"n-input-wrapper\">\n        <!---->\n        <div class=\"n-input__input\"><input type=\"text\" class=\"n-input__input-el\" placeholder=\"Si prega di inserire\" size=\"20\">\n          <div class=\"n-input__placeholder\"><span>Si prega di inserire</span></div>\n          <!---->\n        </div>\n        <!---->\n      </div>\n      <!---->\n      <!---->\n      <div class=\"n-input__border\"></div>\n      <div class=\"n-input__state-border\"></div>\n      <!---->\n    </div>\n    <div>\n      <div class=\"n-date-picker\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-icon-color-override: rgba(194, 194, 194, 1); --n-icon-color-disabled-override: rgba(209, 209, 209, 1);\">\n        <div class=\"n-input n-input--medium-size n-input--resizable n-input--stateful\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-count-text-color: rgb(118, 124, 130); --n-count-text-color-disabled: rgba(194, 194, 194, 1); --n-color: rgba(255, 255, 255, 1); --n-font-size: 14px; --n-font-weight: 400; --n-border-radius: 3px; --n-height: 34px; --n-padding-left: 12px; --n-padding-right: 12px; --n-text-color: rgb(51, 54, 57); --n-caret-color: #18a058; --n-text-decoration-color: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-focus: 1px solid #36ad6a; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-icon-size: 16px; --n-line-height-textarea: 1.6; --n-color-disabled: rgb(250, 250, 252); --n-color-focus: rgba(255, 255, 255, 1); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-loading-color: #18a058; --n-caret-color-warning: #f0a020; --n-color-focus-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-loading-color-warning: #f0a020; --n-caret-color-error: #d03050; --n-color-focus-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-loading-color-error: #d03050; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-size: 16px; --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-icon-color-hover: rgba(146, 146, 146, 1); --n-icon-color-pressed: rgba(175, 175, 175, 1); --n-icon-color-disabled: rgba(209, 209, 209, 1); --n-suffix-text-color: rgb(51, 54, 57);\" tabindex=\"0\">\n          <div class=\"n-input-wrapper\">\n            <!---->\n            <div class=\"n-input__input\"><input type=\"text\" class=\"n-input__input-el\" tabindex=\"-1\" placeholder=\"Seleziona data\" size=\"20\" value=\"1970-01-01\">\n              <!---->\n              <!---->\n            </div>\n            <div class=\"n-input__suffix\">\n              <!---->\n              <!---->\n              <!----><i class=\"n-base-icon n-date-picker-icon\"><svg width=\"28px\" height=\"28px\" viewBox=\"0 0 28 28\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n                  <g stroke=\"none\" stroke-width=\"1\" fill-rule=\"evenodd\">\n                    <g fill-rule=\"nonzero\">\n                      <path d=\"M21.75,3 C23.5449254,3 25,4.45507456 25,6.25 L25,21.75 C25,23.5449254 23.5449254,25 21.75,25 L6.25,25 C4.45507456,25 3,23.5449254 3,21.75 L3,6.25 C3,4.45507456 4.45507456,3 6.25,3 L21.75,3 Z M23.5,9.503 L4.5,9.503 L4.5,21.75 C4.5,22.7164983 5.28350169,23.5 6.25,23.5 L21.75,23.5 C22.7164983,23.5 23.5,22.7164983 23.5,21.75 L23.5,9.503 Z M21.75,4.5 L6.25,4.5 C5.28350169,4.5 4.5,5.28350169 4.5,6.25 L4.5,8.003 L23.5,8.003 L23.5,6.25 C23.5,5.28350169 22.7164983,4.5 21.75,4.5 Z\"></path>\n                    </g>\n                  </g>\n                </svg></i>\n              <!---->\n              <!---->\n            </div>\n          </div>\n          <!---->\n          <!---->\n          <div class=\"n-input__border\"></div>\n          <div class=\"n-input__state-border\"></div>\n          <!---->\n        </div>\n        <!---->\n      </div>\n      <div class=\"n-date-picker\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-icon-color-override: rgba(194, 194, 194, 1); --n-icon-color-disabled-override: rgba(209, 209, 209, 1);\">\n        <div class=\"n-input n-input--medium-size n-input--resizable n-input--stateful\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-count-text-color: rgb(118, 124, 130); --n-count-text-color-disabled: rgba(194, 194, 194, 1); --n-color: rgba(255, 255, 255, 1); --n-font-size: 14px; --n-font-weight: 400; --n-border-radius: 3px; --n-height: 34px; --n-padding-left: 12px; --n-padding-right: 12px; --n-text-color: rgb(51, 54, 57); --n-caret-color: #18a058; --n-text-decoration-color: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-focus: 1px solid #36ad6a; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-icon-size: 16px; --n-line-height-textarea: 1.6; --n-color-disabled: rgb(250, 250, 252); --n-color-focus: rgba(255, 255, 255, 1); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-loading-color: #18a058; --n-caret-color-warning: #f0a020; --n-color-focus-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-loading-color-warning: #f0a020; --n-caret-color-error: #d03050; --n-color-focus-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-loading-color-error: #d03050; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-size: 16px; --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-icon-color-hover: rgba(146, 146, 146, 1); --n-icon-color-pressed: rgba(175, 175, 175, 1); --n-icon-color-disabled: rgba(209, 209, 209, 1); --n-suffix-text-color: rgb(51, 54, 57);\" tabindex=\"0\">\n          <div class=\"n-input-wrapper\">\n            <!---->\n            <div class=\"n-input__input\"><input type=\"text\" class=\"n-input__input-el\" tabindex=\"-1\" placeholder=\"Seleziona data e ora\" size=\"20\" value=\"1970-01-01 08:00:00\">\n              <!---->\n              <!---->\n            </div>\n            <div class=\"n-input__suffix\">\n              <!---->\n              <!---->\n              <!----><i class=\"n-base-icon n-date-picker-icon\"><svg width=\"28px\" height=\"28px\" viewBox=\"0 0 28 28\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n                  <g stroke=\"none\" stroke-width=\"1\" fill-rule=\"evenodd\">\n                    <g fill-rule=\"nonzero\">\n                      <path d=\"M21.75,3 C23.5449254,3 25,4.45507456 25,6.25 L25,21.75 C25,23.5449254 23.5449254,25 21.75,25 L6.25,25 C4.45507456,25 3,23.5449254 3,21.75 L3,6.25 C3,4.45507456 4.45507456,3 6.25,3 L21.75,3 Z M23.5,9.503 L4.5,9.503 L4.5,21.75 C4.5,22.7164983 5.28350169,23.5 6.25,23.5 L21.75,23.5 C22.7164983,23.5 23.5,22.7164983 23.5,21.75 L23.5,9.503 Z M21.75,4.5 L6.25,4.5 C5.28350169,4.5 4.5,5.28350169 4.5,6.25 L4.5,8.003 L23.5,8.003 L23.5,6.25 C23.5,5.28350169 22.7164983,4.5 21.75,4.5 Z\"></path>\n                    </g>\n                  </g>\n                </svg></i>\n              <!---->\n              <!---->\n            </div>\n          </div>\n          <!---->\n          <!---->\n          <div class=\"n-input__border\"></div>\n          <div class=\"n-input__state-border\"></div>\n          <!---->\n        </div>\n        <!---->\n      </div>\n      <div class=\"n-date-picker\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-icon-color-override: rgba(194, 194, 194, 1); --n-icon-color-disabled-override: rgba(209, 209, 209, 1);\">\n        <div class=\"n-input n-input--medium-size n-input--resizable n-input--stateful\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-count-text-color: rgb(118, 124, 130); --n-count-text-color-disabled: rgba(194, 194, 194, 1); --n-color: rgba(255, 255, 255, 1); --n-font-size: 14px; --n-font-weight: 400; --n-border-radius: 3px; --n-height: 34px; --n-padding-left: 12px; --n-padding-right: 12px; --n-text-color: rgb(51, 54, 57); --n-caret-color: #18a058; --n-text-decoration-color: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-focus: 1px solid #36ad6a; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-icon-size: 16px; --n-line-height-textarea: 1.6; --n-color-disabled: rgb(250, 250, 252); --n-color-focus: rgba(255, 255, 255, 1); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-loading-color: #18a058; --n-caret-color-warning: #f0a020; --n-color-focus-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-loading-color-warning: #f0a020; --n-caret-color-error: #d03050; --n-color-focus-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-loading-color-error: #d03050; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-size: 16px; --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-icon-color-hover: rgba(146, 146, 146, 1); --n-icon-color-pressed: rgba(175, 175, 175, 1); --n-icon-color-disabled: rgba(209, 209, 209, 1); --n-suffix-text-color: rgb(51, 54, 57);\" tabindex=\"0\">\n          <div class=\"n-input-wrapper\">\n            <!---->\n            <div class=\"n-input__input\"><input type=\"text\" class=\"n-input__input-el\" tabindex=\"-1\" placeholder=\"Seleziona anno\" size=\"20\" value=\"1970\">\n              <!---->\n              <!---->\n            </div>\n            <div class=\"n-input__suffix\">\n              <!---->\n              <!---->\n              <!----><i class=\"n-base-icon n-date-picker-icon\"><svg width=\"28px\" height=\"28px\" viewBox=\"0 0 28 28\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n                  <g stroke=\"none\" stroke-width=\"1\" fill-rule=\"evenodd\">\n                    <g fill-rule=\"nonzero\">\n                      <path d=\"M21.75,3 C23.5449254,3 25,4.45507456 25,6.25 L25,21.75 C25,23.5449254 23.5449254,25 21.75,25 L6.25,25 C4.45507456,25 3,23.5449254 3,21.75 L3,6.25 C3,4.45507456 4.45507456,3 6.25,3 L21.75,3 Z M23.5,9.503 L4.5,9.503 L4.5,21.75 C4.5,22.7164983 5.28350169,23.5 6.25,23.5 L21.75,23.5 C22.7164983,23.5 23.5,22.7164983 23.5,21.75 L23.5,9.503 Z M21.75,4.5 L6.25,4.5 C5.28350169,4.5 4.5,5.28350169 4.5,6.25 L4.5,8.003 L23.5,8.003 L23.5,6.25 C23.5,5.28350169 22.7164983,4.5 21.75,4.5 Z\"></path>\n                    </g>\n                  </g>\n                </svg></i>\n              <!---->\n              <!---->\n            </div>\n          </div>\n          <!---->\n          <!---->\n          <div class=\"n-input__border\"></div>\n          <div class=\"n-input__state-border\"></div>\n          <!---->\n        </div>\n        <!---->\n      </div>\n      <div class=\"n-date-picker\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-icon-color-override: rgba(194, 194, 194, 1); --n-icon-color-disabled-override: rgba(209, 209, 209, 1);\">\n        <div class=\"n-input n-input--medium-size n-input--resizable n-input--stateful\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-count-text-color: rgb(118, 124, 130); --n-count-text-color-disabled: rgba(194, 194, 194, 1); --n-color: rgba(255, 255, 255, 1); --n-font-size: 14px; --n-font-weight: 400; --n-border-radius: 3px; --n-height: 34px; --n-padding-left: 12px; --n-padding-right: 12px; --n-text-color: rgb(51, 54, 57); --n-caret-color: #18a058; --n-text-decoration-color: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-focus: 1px solid #36ad6a; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-icon-size: 16px; --n-line-height-textarea: 1.6; --n-color-disabled: rgb(250, 250, 252); --n-color-focus: rgba(255, 255, 255, 1); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-loading-color: #18a058; --n-caret-color-warning: #f0a020; --n-color-focus-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-loading-color-warning: #f0a020; --n-caret-color-error: #d03050; --n-color-focus-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-loading-color-error: #d03050; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-size: 16px; --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-icon-color-hover: rgba(146, 146, 146, 1); --n-icon-color-pressed: rgba(175, 175, 175, 1); --n-icon-color-disabled: rgba(209, 209, 209, 1); --n-suffix-text-color: rgb(51, 54, 57);\" tabindex=\"0\">\n          <div class=\"n-input-wrapper\">\n            <!---->\n            <div class=\"n-input__input\"><input type=\"text\" class=\"n-input__input-el\" tabindex=\"-1\" placeholder=\"Seleziona mese\" size=\"20\" value=\"1970-01\">\n              <!---->\n              <!---->\n            </div>\n            <div class=\"n-input__suffix\">\n              <!---->\n              <!---->\n              <!----><i class=\"n-base-icon n-date-picker-icon\"><svg width=\"28px\" height=\"28px\" viewBox=\"0 0 28 28\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n                  <g stroke=\"none\" stroke-width=\"1\" fill-rule=\"evenodd\">\n                    <g fill-rule=\"nonzero\">\n                      <path d=\"M21.75,3 C23.5449254,3 25,4.45507456 25,6.25 L25,21.75 C25,23.5449254 23.5449254,25 21.75,25 L6.25,25 C4.45507456,25 3,23.5449254 3,21.75 L3,6.25 C3,4.45507456 4.45507456,3 6.25,3 L21.75,3 Z M23.5,9.503 L4.5,9.503 L4.5,21.75 C4.5,22.7164983 5.28350169,23.5 6.25,23.5 L21.75,23.5 C22.7164983,23.5 23.5,22.7164983 23.5,21.75 L23.5,9.503 Z M21.75,4.5 L6.25,4.5 C5.28350169,4.5 4.5,5.28350169 4.5,6.25 L4.5,8.003 L23.5,8.003 L23.5,6.25 C23.5,5.28350169 22.7164983,4.5 21.75,4.5 Z\"></path>\n                    </g>\n                  </g>\n                </svg></i>\n              <!---->\n              <!---->\n            </div>\n          </div>\n          <!---->\n          <!---->\n          <div class=\"n-input__border\"></div>\n          <div class=\"n-input__state-border\"></div>\n          <!---->\n        </div>\n        <!---->\n      </div>\n    </div>\n  </div>\n</div>\"\n`;\n\nexports[`locale > works 16`] = `\n\"<div class=\"n-config-provider\">\n  <div>\n    <div class=\"n-input n-input--medium-size n-input--resizable n-input--stateful\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-count-text-color: rgb(118, 124, 130); --n-count-text-color-disabled: rgba(194, 194, 194, 1); --n-color: rgba(255, 255, 255, 1); --n-font-size: 14px; --n-font-weight: 400; --n-border-radius: 3px; --n-height: 34px; --n-padding-left: 12px; --n-padding-right: 12px; --n-text-color: rgb(51, 54, 57); --n-caret-color: #18a058; --n-text-decoration-color: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-focus: 1px solid #36ad6a; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-icon-size: 16px; --n-line-height-textarea: 1.6; --n-color-disabled: rgb(250, 250, 252); --n-color-focus: rgba(255, 255, 255, 1); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-loading-color: #18a058; --n-caret-color-warning: #f0a020; --n-color-focus-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-loading-color-warning: #f0a020; --n-caret-color-error: #d03050; --n-color-focus-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-loading-color-error: #d03050; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-size: 16px; --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-icon-color-hover: rgba(146, 146, 146, 1); --n-icon-color-pressed: rgba(175, 175, 175, 1); --n-icon-color-disabled: rgba(209, 209, 209, 1); --n-suffix-text-color: rgb(51, 54, 57);\">\n      <div class=\"n-input-wrapper\">\n        <!---->\n        <div class=\"n-input__input\"><input type=\"text\" class=\"n-input__input-el\" placeholder=\"Please Input\" size=\"20\">\n          <div class=\"n-input__placeholder\"><span>Please Input</span></div>\n          <!---->\n        </div>\n        <!---->\n      </div>\n      <!---->\n      <!---->\n      <div class=\"n-input__border\"></div>\n      <div class=\"n-input__state-border\"></div>\n      <!---->\n    </div>\n    <div>\n      <div class=\"n-date-picker\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-icon-color-override: rgba(194, 194, 194, 1); --n-icon-color-disabled-override: rgba(209, 209, 209, 1);\">\n        <div class=\"n-input n-input--medium-size n-input--resizable n-input--stateful\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-count-text-color: rgb(118, 124, 130); --n-count-text-color-disabled: rgba(194, 194, 194, 1); --n-color: rgba(255, 255, 255, 1); --n-font-size: 14px; --n-font-weight: 400; --n-border-radius: 3px; --n-height: 34px; --n-padding-left: 12px; --n-padding-right: 12px; --n-text-color: rgb(51, 54, 57); --n-caret-color: #18a058; --n-text-decoration-color: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-focus: 1px solid #36ad6a; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-icon-size: 16px; --n-line-height-textarea: 1.6; --n-color-disabled: rgb(250, 250, 252); --n-color-focus: rgba(255, 255, 255, 1); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-loading-color: #18a058; --n-caret-color-warning: #f0a020; --n-color-focus-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-loading-color-warning: #f0a020; --n-caret-color-error: #d03050; --n-color-focus-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-loading-color-error: #d03050; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-size: 16px; --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-icon-color-hover: rgba(146, 146, 146, 1); --n-icon-color-pressed: rgba(175, 175, 175, 1); --n-icon-color-disabled: rgba(209, 209, 209, 1); --n-suffix-text-color: rgb(51, 54, 57);\" tabindex=\"0\">\n          <div class=\"n-input-wrapper\">\n            <!---->\n            <div class=\"n-input__input\"><input type=\"text\" class=\"n-input__input-el\" tabindex=\"-1\" placeholder=\"Select Date\" size=\"20\" value=\"1970/01/01\">\n              <!---->\n              <!---->\n            </div>\n            <div class=\"n-input__suffix\">\n              <!---->\n              <!---->\n              <!----><i class=\"n-base-icon n-date-picker-icon\"><svg width=\"28px\" height=\"28px\" viewBox=\"0 0 28 28\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n                  <g stroke=\"none\" stroke-width=\"1\" fill-rule=\"evenodd\">\n                    <g fill-rule=\"nonzero\">\n                      <path d=\"M21.75,3 C23.5449254,3 25,4.45507456 25,6.25 L25,21.75 C25,23.5449254 23.5449254,25 21.75,25 L6.25,25 C4.45507456,25 3,23.5449254 3,21.75 L3,6.25 C3,4.45507456 4.45507456,3 6.25,3 L21.75,3 Z M23.5,9.503 L4.5,9.503 L4.5,21.75 C4.5,22.7164983 5.28350169,23.5 6.25,23.5 L21.75,23.5 C22.7164983,23.5 23.5,22.7164983 23.5,21.75 L23.5,9.503 Z M21.75,4.5 L6.25,4.5 C5.28350169,4.5 4.5,5.28350169 4.5,6.25 L4.5,8.003 L23.5,8.003 L23.5,6.25 C23.5,5.28350169 22.7164983,4.5 21.75,4.5 Z\"></path>\n                    </g>\n                  </g>\n                </svg></i>\n              <!---->\n              <!---->\n            </div>\n          </div>\n          <!---->\n          <!---->\n          <div class=\"n-input__border\"></div>\n          <div class=\"n-input__state-border\"></div>\n          <!---->\n        </div>\n        <!---->\n      </div>\n      <div class=\"n-date-picker\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-icon-color-override: rgba(194, 194, 194, 1); --n-icon-color-disabled-override: rgba(209, 209, 209, 1);\">\n        <div class=\"n-input n-input--medium-size n-input--resizable n-input--stateful\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-count-text-color: rgb(118, 124, 130); --n-count-text-color-disabled: rgba(194, 194, 194, 1); --n-color: rgba(255, 255, 255, 1); --n-font-size: 14px; --n-font-weight: 400; --n-border-radius: 3px; --n-height: 34px; --n-padding-left: 12px; --n-padding-right: 12px; --n-text-color: rgb(51, 54, 57); --n-caret-color: #18a058; --n-text-decoration-color: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-focus: 1px solid #36ad6a; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-icon-size: 16px; --n-line-height-textarea: 1.6; --n-color-disabled: rgb(250, 250, 252); --n-color-focus: rgba(255, 255, 255, 1); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-loading-color: #18a058; --n-caret-color-warning: #f0a020; --n-color-focus-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-loading-color-warning: #f0a020; --n-caret-color-error: #d03050; --n-color-focus-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-loading-color-error: #d03050; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-size: 16px; --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-icon-color-hover: rgba(146, 146, 146, 1); --n-icon-color-pressed: rgba(175, 175, 175, 1); --n-icon-color-disabled: rgba(209, 209, 209, 1); --n-suffix-text-color: rgb(51, 54, 57);\" tabindex=\"0\">\n          <div class=\"n-input-wrapper\">\n            <!---->\n            <div class=\"n-input__input\"><input type=\"text\" class=\"n-input__input-el\" tabindex=\"-1\" placeholder=\"Select Date and Time\" size=\"20\" value=\"1970/01/01 08:00:00\">\n              <!---->\n              <!---->\n            </div>\n            <div class=\"n-input__suffix\">\n              <!---->\n              <!---->\n              <!----><i class=\"n-base-icon n-date-picker-icon\"><svg width=\"28px\" height=\"28px\" viewBox=\"0 0 28 28\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n                  <g stroke=\"none\" stroke-width=\"1\" fill-rule=\"evenodd\">\n                    <g fill-rule=\"nonzero\">\n                      <path d=\"M21.75,3 C23.5449254,3 25,4.45507456 25,6.25 L25,21.75 C25,23.5449254 23.5449254,25 21.75,25 L6.25,25 C4.45507456,25 3,23.5449254 3,21.75 L3,6.25 C3,4.45507456 4.45507456,3 6.25,3 L21.75,3 Z M23.5,9.503 L4.5,9.503 L4.5,21.75 C4.5,22.7164983 5.28350169,23.5 6.25,23.5 L21.75,23.5 C22.7164983,23.5 23.5,22.7164983 23.5,21.75 L23.5,9.503 Z M21.75,4.5 L6.25,4.5 C5.28350169,4.5 4.5,5.28350169 4.5,6.25 L4.5,8.003 L23.5,8.003 L23.5,6.25 C23.5,5.28350169 22.7164983,4.5 21.75,4.5 Z\"></path>\n                    </g>\n                  </g>\n                </svg></i>\n              <!---->\n              <!---->\n            </div>\n          </div>\n          <!---->\n          <!---->\n          <div class=\"n-input__border\"></div>\n          <div class=\"n-input__state-border\"></div>\n          <!---->\n        </div>\n        <!---->\n      </div>\n      <div class=\"n-date-picker\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-icon-color-override: rgba(194, 194, 194, 1); --n-icon-color-disabled-override: rgba(209, 209, 209, 1);\">\n        <div class=\"n-input n-input--medium-size n-input--resizable n-input--stateful\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-count-text-color: rgb(118, 124, 130); --n-count-text-color-disabled: rgba(194, 194, 194, 1); --n-color: rgba(255, 255, 255, 1); --n-font-size: 14px; --n-font-weight: 400; --n-border-radius: 3px; --n-height: 34px; --n-padding-left: 12px; --n-padding-right: 12px; --n-text-color: rgb(51, 54, 57); --n-caret-color: #18a058; --n-text-decoration-color: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-focus: 1px solid #36ad6a; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-icon-size: 16px; --n-line-height-textarea: 1.6; --n-color-disabled: rgb(250, 250, 252); --n-color-focus: rgba(255, 255, 255, 1); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-loading-color: #18a058; --n-caret-color-warning: #f0a020; --n-color-focus-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-loading-color-warning: #f0a020; --n-caret-color-error: #d03050; --n-color-focus-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-loading-color-error: #d03050; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-size: 16px; --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-icon-color-hover: rgba(146, 146, 146, 1); --n-icon-color-pressed: rgba(175, 175, 175, 1); --n-icon-color-disabled: rgba(209, 209, 209, 1); --n-suffix-text-color: rgb(51, 54, 57);\" tabindex=\"0\">\n          <div class=\"n-input-wrapper\">\n            <!---->\n            <div class=\"n-input__input\"><input type=\"text\" class=\"n-input__input-el\" tabindex=\"-1\" placeholder=\"Select Year\" size=\"20\" value=\"1970\">\n              <!---->\n              <!---->\n            </div>\n            <div class=\"n-input__suffix\">\n              <!---->\n              <!---->\n              <!----><i class=\"n-base-icon n-date-picker-icon\"><svg width=\"28px\" height=\"28px\" viewBox=\"0 0 28 28\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n                  <g stroke=\"none\" stroke-width=\"1\" fill-rule=\"evenodd\">\n                    <g fill-rule=\"nonzero\">\n                      <path d=\"M21.75,3 C23.5449254,3 25,4.45507456 25,6.25 L25,21.75 C25,23.5449254 23.5449254,25 21.75,25 L6.25,25 C4.45507456,25 3,23.5449254 3,21.75 L3,6.25 C3,4.45507456 4.45507456,3 6.25,3 L21.75,3 Z M23.5,9.503 L4.5,9.503 L4.5,21.75 C4.5,22.7164983 5.28350169,23.5 6.25,23.5 L21.75,23.5 C22.7164983,23.5 23.5,22.7164983 23.5,21.75 L23.5,9.503 Z M21.75,4.5 L6.25,4.5 C5.28350169,4.5 4.5,5.28350169 4.5,6.25 L4.5,8.003 L23.5,8.003 L23.5,6.25 C23.5,5.28350169 22.7164983,4.5 21.75,4.5 Z\"></path>\n                    </g>\n                  </g>\n                </svg></i>\n              <!---->\n              <!---->\n            </div>\n          </div>\n          <!---->\n          <!---->\n          <div class=\"n-input__border\"></div>\n          <div class=\"n-input__state-border\"></div>\n          <!---->\n        </div>\n        <!---->\n      </div>\n      <div class=\"n-date-picker\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-icon-color-override: rgba(194, 194, 194, 1); --n-icon-color-disabled-override: rgba(209, 209, 209, 1);\">\n        <div class=\"n-input n-input--medium-size n-input--resizable n-input--stateful\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-count-text-color: rgb(118, 124, 130); --n-count-text-color-disabled: rgba(194, 194, 194, 1); --n-color: rgba(255, 255, 255, 1); --n-font-size: 14px; --n-font-weight: 400; --n-border-radius: 3px; --n-height: 34px; --n-padding-left: 12px; --n-padding-right: 12px; --n-text-color: rgb(51, 54, 57); --n-caret-color: #18a058; --n-text-decoration-color: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-focus: 1px solid #36ad6a; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-icon-size: 16px; --n-line-height-textarea: 1.6; --n-color-disabled: rgb(250, 250, 252); --n-color-focus: rgba(255, 255, 255, 1); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-loading-color: #18a058; --n-caret-color-warning: #f0a020; --n-color-focus-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-loading-color-warning: #f0a020; --n-caret-color-error: #d03050; --n-color-focus-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-loading-color-error: #d03050; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-size: 16px; --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-icon-color-hover: rgba(146, 146, 146, 1); --n-icon-color-pressed: rgba(175, 175, 175, 1); --n-icon-color-disabled: rgba(209, 209, 209, 1); --n-suffix-text-color: rgb(51, 54, 57);\" tabindex=\"0\">\n          <div class=\"n-input-wrapper\">\n            <!---->\n            <div class=\"n-input__input\"><input type=\"text\" class=\"n-input__input-el\" tabindex=\"-1\" placeholder=\"Select Month\" size=\"20\" value=\"1970/01\">\n              <!---->\n              <!---->\n            </div>\n            <div class=\"n-input__suffix\">\n              <!---->\n              <!---->\n              <!----><i class=\"n-base-icon n-date-picker-icon\"><svg width=\"28px\" height=\"28px\" viewBox=\"0 0 28 28\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n                  <g stroke=\"none\" stroke-width=\"1\" fill-rule=\"evenodd\">\n                    <g fill-rule=\"nonzero\">\n                      <path d=\"M21.75,3 C23.5449254,3 25,4.45507456 25,6.25 L25,21.75 C25,23.5449254 23.5449254,25 21.75,25 L6.25,25 C4.45507456,25 3,23.5449254 3,21.75 L3,6.25 C3,4.45507456 4.45507456,3 6.25,3 L21.75,3 Z M23.5,9.503 L4.5,9.503 L4.5,21.75 C4.5,22.7164983 5.28350169,23.5 6.25,23.5 L21.75,23.5 C22.7164983,23.5 23.5,22.7164983 23.5,21.75 L23.5,9.503 Z M21.75,4.5 L6.25,4.5 C5.28350169,4.5 4.5,5.28350169 4.5,6.25 L4.5,8.003 L23.5,8.003 L23.5,6.25 C23.5,5.28350169 22.7164983,4.5 21.75,4.5 Z\"></path>\n                    </g>\n                  </g>\n                </svg></i>\n              <!---->\n              <!---->\n            </div>\n          </div>\n          <!---->\n          <!---->\n          <div class=\"n-input__border\"></div>\n          <div class=\"n-input__state-border\"></div>\n          <!---->\n        </div>\n        <!---->\n      </div>\n    </div>\n  </div>\n</div>\"\n`;\n\nexports[`locale > works 17`] = `\n\"<div class=\"n-config-provider\">\n  <div>\n    <div class=\"n-input n-input--medium-size n-input--resizable n-input--stateful\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-count-text-color: rgb(118, 124, 130); --n-count-text-color-disabled: rgba(194, 194, 194, 1); --n-color: rgba(255, 255, 255, 1); --n-font-size: 14px; --n-font-weight: 400; --n-border-radius: 3px; --n-height: 34px; --n-padding-left: 12px; --n-padding-right: 12px; --n-text-color: rgb(51, 54, 57); --n-caret-color: #18a058; --n-text-decoration-color: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-focus: 1px solid #36ad6a; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-icon-size: 16px; --n-line-height-textarea: 1.6; --n-color-disabled: rgb(250, 250, 252); --n-color-focus: rgba(255, 255, 255, 1); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-loading-color: #18a058; --n-caret-color-warning: #f0a020; --n-color-focus-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-loading-color-warning: #f0a020; --n-caret-color-error: #d03050; --n-color-focus-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-loading-color-error: #d03050; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-size: 16px; --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-icon-color-hover: rgba(146, 146, 146, 1); --n-icon-color-pressed: rgba(175, 175, 175, 1); --n-icon-color-disabled: rgba(209, 209, 209, 1); --n-suffix-text-color: rgb(51, 54, 57);\">\n      <div class=\"n-input-wrapper\">\n        <!---->\n        <div class=\"n-input__input\"><input type=\"text\" class=\"n-input__input-el\" placeholder=\"Zadajte\" size=\"20\">\n          <div class=\"n-input__placeholder\"><span>Zadajte</span></div>\n          <!---->\n        </div>\n        <!---->\n      </div>\n      <!---->\n      <!---->\n      <div class=\"n-input__border\"></div>\n      <div class=\"n-input__state-border\"></div>\n      <!---->\n    </div>\n    <div>\n      <div class=\"n-date-picker\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-icon-color-override: rgba(194, 194, 194, 1); --n-icon-color-disabled-override: rgba(209, 209, 209, 1);\">\n        <div class=\"n-input n-input--medium-size n-input--resizable n-input--stateful\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-count-text-color: rgb(118, 124, 130); --n-count-text-color-disabled: rgba(194, 194, 194, 1); --n-color: rgba(255, 255, 255, 1); --n-font-size: 14px; --n-font-weight: 400; --n-border-radius: 3px; --n-height: 34px; --n-padding-left: 12px; --n-padding-right: 12px; --n-text-color: rgb(51, 54, 57); --n-caret-color: #18a058; --n-text-decoration-color: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-focus: 1px solid #36ad6a; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-icon-size: 16px; --n-line-height-textarea: 1.6; --n-color-disabled: rgb(250, 250, 252); --n-color-focus: rgba(255, 255, 255, 1); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-loading-color: #18a058; --n-caret-color-warning: #f0a020; --n-color-focus-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-loading-color-warning: #f0a020; --n-caret-color-error: #d03050; --n-color-focus-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-loading-color-error: #d03050; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-size: 16px; --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-icon-color-hover: rgba(146, 146, 146, 1); --n-icon-color-pressed: rgba(175, 175, 175, 1); --n-icon-color-disabled: rgba(209, 209, 209, 1); --n-suffix-text-color: rgb(51, 54, 57);\" tabindex=\"0\">\n          <div class=\"n-input-wrapper\">\n            <!---->\n            <div class=\"n-input__input\"><input type=\"text\" class=\"n-input__input-el\" tabindex=\"-1\" placeholder=\"Vyberte čas\" size=\"20\" value=\"1-1-1970\">\n              <!---->\n              <!---->\n            </div>\n            <div class=\"n-input__suffix\">\n              <!---->\n              <!---->\n              <!----><i class=\"n-base-icon n-date-picker-icon\"><svg width=\"28px\" height=\"28px\" viewBox=\"0 0 28 28\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n                  <g stroke=\"none\" stroke-width=\"1\" fill-rule=\"evenodd\">\n                    <g fill-rule=\"nonzero\">\n                      <path d=\"M21.75,3 C23.5449254,3 25,4.45507456 25,6.25 L25,21.75 C25,23.5449254 23.5449254,25 21.75,25 L6.25,25 C4.45507456,25 3,23.5449254 3,21.75 L3,6.25 C3,4.45507456 4.45507456,3 6.25,3 L21.75,3 Z M23.5,9.503 L4.5,9.503 L4.5,21.75 C4.5,22.7164983 5.28350169,23.5 6.25,23.5 L21.75,23.5 C22.7164983,23.5 23.5,22.7164983 23.5,21.75 L23.5,9.503 Z M21.75,4.5 L6.25,4.5 C5.28350169,4.5 4.5,5.28350169 4.5,6.25 L4.5,8.003 L23.5,8.003 L23.5,6.25 C23.5,5.28350169 22.7164983,4.5 21.75,4.5 Z\"></path>\n                    </g>\n                  </g>\n                </svg></i>\n              <!---->\n              <!---->\n            </div>\n          </div>\n          <!---->\n          <!---->\n          <div class=\"n-input__border\"></div>\n          <div class=\"n-input__state-border\"></div>\n          <!---->\n        </div>\n        <!---->\n      </div>\n      <div class=\"n-date-picker\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-icon-color-override: rgba(194, 194, 194, 1); --n-icon-color-disabled-override: rgba(209, 209, 209, 1);\">\n        <div class=\"n-input n-input--medium-size n-input--resizable n-input--stateful\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-count-text-color: rgb(118, 124, 130); --n-count-text-color-disabled: rgba(194, 194, 194, 1); --n-color: rgba(255, 255, 255, 1); --n-font-size: 14px; --n-font-weight: 400; --n-border-radius: 3px; --n-height: 34px; --n-padding-left: 12px; --n-padding-right: 12px; --n-text-color: rgb(51, 54, 57); --n-caret-color: #18a058; --n-text-decoration-color: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-focus: 1px solid #36ad6a; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-icon-size: 16px; --n-line-height-textarea: 1.6; --n-color-disabled: rgb(250, 250, 252); --n-color-focus: rgba(255, 255, 255, 1); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-loading-color: #18a058; --n-caret-color-warning: #f0a020; --n-color-focus-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-loading-color-warning: #f0a020; --n-caret-color-error: #d03050; --n-color-focus-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-loading-color-error: #d03050; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-size: 16px; --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-icon-color-hover: rgba(146, 146, 146, 1); --n-icon-color-pressed: rgba(175, 175, 175, 1); --n-icon-color-disabled: rgba(209, 209, 209, 1); --n-suffix-text-color: rgb(51, 54, 57);\" tabindex=\"0\">\n          <div class=\"n-input-wrapper\">\n            <!---->\n            <div class=\"n-input__input\"><input type=\"text\" class=\"n-input__input-el\" tabindex=\"-1\" placeholder=\"Vyberte dátum a čas\" size=\"20\" value=\"1-1-1970 08:00:00\">\n              <!---->\n              <!---->\n            </div>\n            <div class=\"n-input__suffix\">\n              <!---->\n              <!---->\n              <!----><i class=\"n-base-icon n-date-picker-icon\"><svg width=\"28px\" height=\"28px\" viewBox=\"0 0 28 28\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n                  <g stroke=\"none\" stroke-width=\"1\" fill-rule=\"evenodd\">\n                    <g fill-rule=\"nonzero\">\n                      <path d=\"M21.75,3 C23.5449254,3 25,4.45507456 25,6.25 L25,21.75 C25,23.5449254 23.5449254,25 21.75,25 L6.25,25 C4.45507456,25 3,23.5449254 3,21.75 L3,6.25 C3,4.45507456 4.45507456,3 6.25,3 L21.75,3 Z M23.5,9.503 L4.5,9.503 L4.5,21.75 C4.5,22.7164983 5.28350169,23.5 6.25,23.5 L21.75,23.5 C22.7164983,23.5 23.5,22.7164983 23.5,21.75 L23.5,9.503 Z M21.75,4.5 L6.25,4.5 C5.28350169,4.5 4.5,5.28350169 4.5,6.25 L4.5,8.003 L23.5,8.003 L23.5,6.25 C23.5,5.28350169 22.7164983,4.5 21.75,4.5 Z\"></path>\n                    </g>\n                  </g>\n                </svg></i>\n              <!---->\n              <!---->\n            </div>\n          </div>\n          <!---->\n          <!---->\n          <div class=\"n-input__border\"></div>\n          <div class=\"n-input__state-border\"></div>\n          <!---->\n        </div>\n        <!---->\n      </div>\n      <div class=\"n-date-picker\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-icon-color-override: rgba(194, 194, 194, 1); --n-icon-color-disabled-override: rgba(209, 209, 209, 1);\">\n        <div class=\"n-input n-input--medium-size n-input--resizable n-input--stateful\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-count-text-color: rgb(118, 124, 130); --n-count-text-color-disabled: rgba(194, 194, 194, 1); --n-color: rgba(255, 255, 255, 1); --n-font-size: 14px; --n-font-weight: 400; --n-border-radius: 3px; --n-height: 34px; --n-padding-left: 12px; --n-padding-right: 12px; --n-text-color: rgb(51, 54, 57); --n-caret-color: #18a058; --n-text-decoration-color: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-focus: 1px solid #36ad6a; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-icon-size: 16px; --n-line-height-textarea: 1.6; --n-color-disabled: rgb(250, 250, 252); --n-color-focus: rgba(255, 255, 255, 1); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-loading-color: #18a058; --n-caret-color-warning: #f0a020; --n-color-focus-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-loading-color-warning: #f0a020; --n-caret-color-error: #d03050; --n-color-focus-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-loading-color-error: #d03050; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-size: 16px; --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-icon-color-hover: rgba(146, 146, 146, 1); --n-icon-color-pressed: rgba(175, 175, 175, 1); --n-icon-color-disabled: rgba(209, 209, 209, 1); --n-suffix-text-color: rgb(51, 54, 57);\" tabindex=\"0\">\n          <div class=\"n-input-wrapper\">\n            <!---->\n            <div class=\"n-input__input\"><input type=\"text\" class=\"n-input__input-el\" tabindex=\"-1\" placeholder=\"Vyberte rok\" size=\"20\" value=\"1970\">\n              <!---->\n              <!---->\n            </div>\n            <div class=\"n-input__suffix\">\n              <!---->\n              <!---->\n              <!----><i class=\"n-base-icon n-date-picker-icon\"><svg width=\"28px\" height=\"28px\" viewBox=\"0 0 28 28\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n                  <g stroke=\"none\" stroke-width=\"1\" fill-rule=\"evenodd\">\n                    <g fill-rule=\"nonzero\">\n                      <path d=\"M21.75,3 C23.5449254,3 25,4.45507456 25,6.25 L25,21.75 C25,23.5449254 23.5449254,25 21.75,25 L6.25,25 C4.45507456,25 3,23.5449254 3,21.75 L3,6.25 C3,4.45507456 4.45507456,3 6.25,3 L21.75,3 Z M23.5,9.503 L4.5,9.503 L4.5,21.75 C4.5,22.7164983 5.28350169,23.5 6.25,23.5 L21.75,23.5 C22.7164983,23.5 23.5,22.7164983 23.5,21.75 L23.5,9.503 Z M21.75,4.5 L6.25,4.5 C5.28350169,4.5 4.5,5.28350169 4.5,6.25 L4.5,8.003 L23.5,8.003 L23.5,6.25 C23.5,5.28350169 22.7164983,4.5 21.75,4.5 Z\"></path>\n                    </g>\n                  </g>\n                </svg></i>\n              <!---->\n              <!---->\n            </div>\n          </div>\n          <!---->\n          <!---->\n          <div class=\"n-input__border\"></div>\n          <div class=\"n-input__state-border\"></div>\n          <!---->\n        </div>\n        <!---->\n      </div>\n      <div class=\"n-date-picker\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-icon-color-override: rgba(194, 194, 194, 1); --n-icon-color-disabled-override: rgba(209, 209, 209, 1);\">\n        <div class=\"n-input n-input--medium-size n-input--resizable n-input--stateful\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-count-text-color: rgb(118, 124, 130); --n-count-text-color-disabled: rgba(194, 194, 194, 1); --n-color: rgba(255, 255, 255, 1); --n-font-size: 14px; --n-font-weight: 400; --n-border-radius: 3px; --n-height: 34px; --n-padding-left: 12px; --n-padding-right: 12px; --n-text-color: rgb(51, 54, 57); --n-caret-color: #18a058; --n-text-decoration-color: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-focus: 1px solid #36ad6a; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-icon-size: 16px; --n-line-height-textarea: 1.6; --n-color-disabled: rgb(250, 250, 252); --n-color-focus: rgba(255, 255, 255, 1); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-loading-color: #18a058; --n-caret-color-warning: #f0a020; --n-color-focus-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-loading-color-warning: #f0a020; --n-caret-color-error: #d03050; --n-color-focus-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-loading-color-error: #d03050; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-size: 16px; --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-icon-color-hover: rgba(146, 146, 146, 1); --n-icon-color-pressed: rgba(175, 175, 175, 1); --n-icon-color-disabled: rgba(209, 209, 209, 1); --n-suffix-text-color: rgb(51, 54, 57);\" tabindex=\"0\">\n          <div class=\"n-input-wrapper\">\n            <!---->\n            <div class=\"n-input__input\"><input type=\"text\" class=\"n-input__input-el\" tabindex=\"-1\" placeholder=\"Vyberte mesiac\" size=\"20\" value=\"jan-1970\">\n              <!---->\n              <!---->\n            </div>\n            <div class=\"n-input__suffix\">\n              <!---->\n              <!---->\n              <!----><i class=\"n-base-icon n-date-picker-icon\"><svg width=\"28px\" height=\"28px\" viewBox=\"0 0 28 28\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n                  <g stroke=\"none\" stroke-width=\"1\" fill-rule=\"evenodd\">\n                    <g fill-rule=\"nonzero\">\n                      <path d=\"M21.75,3 C23.5449254,3 25,4.45507456 25,6.25 L25,21.75 C25,23.5449254 23.5449254,25 21.75,25 L6.25,25 C4.45507456,25 3,23.5449254 3,21.75 L3,6.25 C3,4.45507456 4.45507456,3 6.25,3 L21.75,3 Z M23.5,9.503 L4.5,9.503 L4.5,21.75 C4.5,22.7164983 5.28350169,23.5 6.25,23.5 L21.75,23.5 C22.7164983,23.5 23.5,22.7164983 23.5,21.75 L23.5,9.503 Z M21.75,4.5 L6.25,4.5 C5.28350169,4.5 4.5,5.28350169 4.5,6.25 L4.5,8.003 L23.5,8.003 L23.5,6.25 C23.5,5.28350169 22.7164983,4.5 21.75,4.5 Z\"></path>\n                    </g>\n                  </g>\n                </svg></i>\n              <!---->\n              <!---->\n            </div>\n          </div>\n          <!---->\n          <!---->\n          <div class=\"n-input__border\"></div>\n          <div class=\"n-input__state-border\"></div>\n          <!---->\n        </div>\n        <!---->\n      </div>\n    </div>\n  </div>\n</div>\"\n`;\n\nexports[`locale > works 18`] = `\n\"<div class=\"n-config-provider\">\n  <div>\n    <div class=\"n-input n-input--medium-size n-input--resizable n-input--stateful\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-count-text-color: rgb(118, 124, 130); --n-count-text-color-disabled: rgba(194, 194, 194, 1); --n-color: rgba(255, 255, 255, 1); --n-font-size: 14px; --n-font-weight: 400; --n-border-radius: 3px; --n-height: 34px; --n-padding-left: 12px; --n-padding-right: 12px; --n-text-color: rgb(51, 54, 57); --n-caret-color: #18a058; --n-text-decoration-color: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-focus: 1px solid #36ad6a; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-icon-size: 16px; --n-line-height-textarea: 1.6; --n-color-disabled: rgb(250, 250, 252); --n-color-focus: rgba(255, 255, 255, 1); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-loading-color: #18a058; --n-caret-color-warning: #f0a020; --n-color-focus-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-loading-color-warning: #f0a020; --n-caret-color-error: #d03050; --n-color-focus-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-loading-color-error: #d03050; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-size: 16px; --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-icon-color-hover: rgba(146, 146, 146, 1); --n-icon-color-pressed: rgba(175, 175, 175, 1); --n-icon-color-disabled: rgba(209, 209, 209, 1); --n-suffix-text-color: rgb(51, 54, 57);\">\n      <div class=\"n-input-wrapper\">\n        <!---->\n        <div class=\"n-input__input\"><input type=\"text\" class=\"n-input__input-el\" placeholder=\"Zadejte\" size=\"20\">\n          <div class=\"n-input__placeholder\"><span>Zadejte</span></div>\n          <!---->\n        </div>\n        <!---->\n      </div>\n      <!---->\n      <!---->\n      <div class=\"n-input__border\"></div>\n      <div class=\"n-input__state-border\"></div>\n      <!---->\n    </div>\n    <div>\n      <div class=\"n-date-picker\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-icon-color-override: rgba(194, 194, 194, 1); --n-icon-color-disabled-override: rgba(209, 209, 209, 1);\">\n        <div class=\"n-input n-input--medium-size n-input--resizable n-input--stateful\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-count-text-color: rgb(118, 124, 130); --n-count-text-color-disabled: rgba(194, 194, 194, 1); --n-color: rgba(255, 255, 255, 1); --n-font-size: 14px; --n-font-weight: 400; --n-border-radius: 3px; --n-height: 34px; --n-padding-left: 12px; --n-padding-right: 12px; --n-text-color: rgb(51, 54, 57); --n-caret-color: #18a058; --n-text-decoration-color: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-focus: 1px solid #36ad6a; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-icon-size: 16px; --n-line-height-textarea: 1.6; --n-color-disabled: rgb(250, 250, 252); --n-color-focus: rgba(255, 255, 255, 1); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-loading-color: #18a058; --n-caret-color-warning: #f0a020; --n-color-focus-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-loading-color-warning: #f0a020; --n-caret-color-error: #d03050; --n-color-focus-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-loading-color-error: #d03050; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-size: 16px; --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-icon-color-hover: rgba(146, 146, 146, 1); --n-icon-color-pressed: rgba(175, 175, 175, 1); --n-icon-color-disabled: rgba(209, 209, 209, 1); --n-suffix-text-color: rgb(51, 54, 57);\" tabindex=\"0\">\n          <div class=\"n-input-wrapper\">\n            <!---->\n            <div class=\"n-input__input\"><input type=\"text\" class=\"n-input__input-el\" tabindex=\"-1\" placeholder=\"Vyberte čas\" size=\"20\" value=\"1-1-1970\">\n              <!---->\n              <!---->\n            </div>\n            <div class=\"n-input__suffix\">\n              <!---->\n              <!---->\n              <!----><i class=\"n-base-icon n-date-picker-icon\"><svg width=\"28px\" height=\"28px\" viewBox=\"0 0 28 28\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n                  <g stroke=\"none\" stroke-width=\"1\" fill-rule=\"evenodd\">\n                    <g fill-rule=\"nonzero\">\n                      <path d=\"M21.75,3 C23.5449254,3 25,4.45507456 25,6.25 L25,21.75 C25,23.5449254 23.5449254,25 21.75,25 L6.25,25 C4.45507456,25 3,23.5449254 3,21.75 L3,6.25 C3,4.45507456 4.45507456,3 6.25,3 L21.75,3 Z M23.5,9.503 L4.5,9.503 L4.5,21.75 C4.5,22.7164983 5.28350169,23.5 6.25,23.5 L21.75,23.5 C22.7164983,23.5 23.5,22.7164983 23.5,21.75 L23.5,9.503 Z M21.75,4.5 L6.25,4.5 C5.28350169,4.5 4.5,5.28350169 4.5,6.25 L4.5,8.003 L23.5,8.003 L23.5,6.25 C23.5,5.28350169 22.7164983,4.5 21.75,4.5 Z\"></path>\n                    </g>\n                  </g>\n                </svg></i>\n              <!---->\n              <!---->\n            </div>\n          </div>\n          <!---->\n          <!---->\n          <div class=\"n-input__border\"></div>\n          <div class=\"n-input__state-border\"></div>\n          <!---->\n        </div>\n        <!---->\n      </div>\n      <div class=\"n-date-picker\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-icon-color-override: rgba(194, 194, 194, 1); --n-icon-color-disabled-override: rgba(209, 209, 209, 1);\">\n        <div class=\"n-input n-input--medium-size n-input--resizable n-input--stateful\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-count-text-color: rgb(118, 124, 130); --n-count-text-color-disabled: rgba(194, 194, 194, 1); --n-color: rgba(255, 255, 255, 1); --n-font-size: 14px; --n-font-weight: 400; --n-border-radius: 3px; --n-height: 34px; --n-padding-left: 12px; --n-padding-right: 12px; --n-text-color: rgb(51, 54, 57); --n-caret-color: #18a058; --n-text-decoration-color: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-focus: 1px solid #36ad6a; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-icon-size: 16px; --n-line-height-textarea: 1.6; --n-color-disabled: rgb(250, 250, 252); --n-color-focus: rgba(255, 255, 255, 1); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-loading-color: #18a058; --n-caret-color-warning: #f0a020; --n-color-focus-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-loading-color-warning: #f0a020; --n-caret-color-error: #d03050; --n-color-focus-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-loading-color-error: #d03050; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-size: 16px; --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-icon-color-hover: rgba(146, 146, 146, 1); --n-icon-color-pressed: rgba(175, 175, 175, 1); --n-icon-color-disabled: rgba(209, 209, 209, 1); --n-suffix-text-color: rgb(51, 54, 57);\" tabindex=\"0\">\n          <div class=\"n-input-wrapper\">\n            <!---->\n            <div class=\"n-input__input\"><input type=\"text\" class=\"n-input__input-el\" tabindex=\"-1\" placeholder=\"Vyberte datum a čas\" size=\"20\" value=\"1-1-1970 08:00:00\">\n              <!---->\n              <!---->\n            </div>\n            <div class=\"n-input__suffix\">\n              <!---->\n              <!---->\n              <!----><i class=\"n-base-icon n-date-picker-icon\"><svg width=\"28px\" height=\"28px\" viewBox=\"0 0 28 28\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n                  <g stroke=\"none\" stroke-width=\"1\" fill-rule=\"evenodd\">\n                    <g fill-rule=\"nonzero\">\n                      <path d=\"M21.75,3 C23.5449254,3 25,4.45507456 25,6.25 L25,21.75 C25,23.5449254 23.5449254,25 21.75,25 L6.25,25 C4.45507456,25 3,23.5449254 3,21.75 L3,6.25 C3,4.45507456 4.45507456,3 6.25,3 L21.75,3 Z M23.5,9.503 L4.5,9.503 L4.5,21.75 C4.5,22.7164983 5.28350169,23.5 6.25,23.5 L21.75,23.5 C22.7164983,23.5 23.5,22.7164983 23.5,21.75 L23.5,9.503 Z M21.75,4.5 L6.25,4.5 C5.28350169,4.5 4.5,5.28350169 4.5,6.25 L4.5,8.003 L23.5,8.003 L23.5,6.25 C23.5,5.28350169 22.7164983,4.5 21.75,4.5 Z\"></path>\n                    </g>\n                  </g>\n                </svg></i>\n              <!---->\n              <!---->\n            </div>\n          </div>\n          <!---->\n          <!---->\n          <div class=\"n-input__border\"></div>\n          <div class=\"n-input__state-border\"></div>\n          <!---->\n        </div>\n        <!---->\n      </div>\n      <div class=\"n-date-picker\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-icon-color-override: rgba(194, 194, 194, 1); --n-icon-color-disabled-override: rgba(209, 209, 209, 1);\">\n        <div class=\"n-input n-input--medium-size n-input--resizable n-input--stateful\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-count-text-color: rgb(118, 124, 130); --n-count-text-color-disabled: rgba(194, 194, 194, 1); --n-color: rgba(255, 255, 255, 1); --n-font-size: 14px; --n-font-weight: 400; --n-border-radius: 3px; --n-height: 34px; --n-padding-left: 12px; --n-padding-right: 12px; --n-text-color: rgb(51, 54, 57); --n-caret-color: #18a058; --n-text-decoration-color: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-focus: 1px solid #36ad6a; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-icon-size: 16px; --n-line-height-textarea: 1.6; --n-color-disabled: rgb(250, 250, 252); --n-color-focus: rgba(255, 255, 255, 1); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-loading-color: #18a058; --n-caret-color-warning: #f0a020; --n-color-focus-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-loading-color-warning: #f0a020; --n-caret-color-error: #d03050; --n-color-focus-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-loading-color-error: #d03050; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-size: 16px; --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-icon-color-hover: rgba(146, 146, 146, 1); --n-icon-color-pressed: rgba(175, 175, 175, 1); --n-icon-color-disabled: rgba(209, 209, 209, 1); --n-suffix-text-color: rgb(51, 54, 57);\" tabindex=\"0\">\n          <div class=\"n-input-wrapper\">\n            <!---->\n            <div class=\"n-input__input\"><input type=\"text\" class=\"n-input__input-el\" tabindex=\"-1\" placeholder=\"Vyberte rok\" size=\"20\" value=\"1970\">\n              <!---->\n              <!---->\n            </div>\n            <div class=\"n-input__suffix\">\n              <!---->\n              <!---->\n              <!----><i class=\"n-base-icon n-date-picker-icon\"><svg width=\"28px\" height=\"28px\" viewBox=\"0 0 28 28\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n                  <g stroke=\"none\" stroke-width=\"1\" fill-rule=\"evenodd\">\n                    <g fill-rule=\"nonzero\">\n                      <path d=\"M21.75,3 C23.5449254,3 25,4.45507456 25,6.25 L25,21.75 C25,23.5449254 23.5449254,25 21.75,25 L6.25,25 C4.45507456,25 3,23.5449254 3,21.75 L3,6.25 C3,4.45507456 4.45507456,3 6.25,3 L21.75,3 Z M23.5,9.503 L4.5,9.503 L4.5,21.75 C4.5,22.7164983 5.28350169,23.5 6.25,23.5 L21.75,23.5 C22.7164983,23.5 23.5,22.7164983 23.5,21.75 L23.5,9.503 Z M21.75,4.5 L6.25,4.5 C5.28350169,4.5 4.5,5.28350169 4.5,6.25 L4.5,8.003 L23.5,8.003 L23.5,6.25 C23.5,5.28350169 22.7164983,4.5 21.75,4.5 Z\"></path>\n                    </g>\n                  </g>\n                </svg></i>\n              <!---->\n              <!---->\n            </div>\n          </div>\n          <!---->\n          <!---->\n          <div class=\"n-input__border\"></div>\n          <div class=\"n-input__state-border\"></div>\n          <!---->\n        </div>\n        <!---->\n      </div>\n      <div class=\"n-date-picker\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-icon-color-override: rgba(194, 194, 194, 1); --n-icon-color-disabled-override: rgba(209, 209, 209, 1);\">\n        <div class=\"n-input n-input--medium-size n-input--resizable n-input--stateful\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-count-text-color: rgb(118, 124, 130); --n-count-text-color-disabled: rgba(194, 194, 194, 1); --n-color: rgba(255, 255, 255, 1); --n-font-size: 14px; --n-font-weight: 400; --n-border-radius: 3px; --n-height: 34px; --n-padding-left: 12px; --n-padding-right: 12px; --n-text-color: rgb(51, 54, 57); --n-caret-color: #18a058; --n-text-decoration-color: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-focus: 1px solid #36ad6a; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-icon-size: 16px; --n-line-height-textarea: 1.6; --n-color-disabled: rgb(250, 250, 252); --n-color-focus: rgba(255, 255, 255, 1); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-loading-color: #18a058; --n-caret-color-warning: #f0a020; --n-color-focus-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-loading-color-warning: #f0a020; --n-caret-color-error: #d03050; --n-color-focus-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-loading-color-error: #d03050; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-size: 16px; --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-icon-color-hover: rgba(146, 146, 146, 1); --n-icon-color-pressed: rgba(175, 175, 175, 1); --n-icon-color-disabled: rgba(209, 209, 209, 1); --n-suffix-text-color: rgb(51, 54, 57);\" tabindex=\"0\">\n          <div class=\"n-input-wrapper\">\n            <!---->\n            <div class=\"n-input__input\"><input type=\"text\" class=\"n-input__input-el\" tabindex=\"-1\" placeholder=\"Vyberte měsíc\" size=\"20\" value=\"led-1970\">\n              <!---->\n              <!---->\n            </div>\n            <div class=\"n-input__suffix\">\n              <!---->\n              <!---->\n              <!----><i class=\"n-base-icon n-date-picker-icon\"><svg width=\"28px\" height=\"28px\" viewBox=\"0 0 28 28\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n                  <g stroke=\"none\" stroke-width=\"1\" fill-rule=\"evenodd\">\n                    <g fill-rule=\"nonzero\">\n                      <path d=\"M21.75,3 C23.5449254,3 25,4.45507456 25,6.25 L25,21.75 C25,23.5449254 23.5449254,25 21.75,25 L6.25,25 C4.45507456,25 3,23.5449254 3,21.75 L3,6.25 C3,4.45507456 4.45507456,3 6.25,3 L21.75,3 Z M23.5,9.503 L4.5,9.503 L4.5,21.75 C4.5,22.7164983 5.28350169,23.5 6.25,23.5 L21.75,23.5 C22.7164983,23.5 23.5,22.7164983 23.5,21.75 L23.5,9.503 Z M21.75,4.5 L6.25,4.5 C5.28350169,4.5 4.5,5.28350169 4.5,6.25 L4.5,8.003 L23.5,8.003 L23.5,6.25 C23.5,5.28350169 22.7164983,4.5 21.75,4.5 Z\"></path>\n                    </g>\n                  </g>\n                </svg></i>\n              <!---->\n              <!---->\n            </div>\n          </div>\n          <!---->\n          <!---->\n          <div class=\"n-input__border\"></div>\n          <div class=\"n-input__state-border\"></div>\n          <!---->\n        </div>\n        <!---->\n      </div>\n    </div>\n  </div>\n</div>\"\n`;\n\nexports[`locale > works 19`] = `\n\"<div class=\"n-config-provider\">\n  <div>\n    <div class=\"n-input n-input--medium-size n-input--resizable n-input--stateful\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-count-text-color: rgb(118, 124, 130); --n-count-text-color-disabled: rgba(194, 194, 194, 1); --n-color: rgba(255, 255, 255, 1); --n-font-size: 14px; --n-font-weight: 400; --n-border-radius: 3px; --n-height: 34px; --n-padding-left: 12px; --n-padding-right: 12px; --n-text-color: rgb(51, 54, 57); --n-caret-color: #18a058; --n-text-decoration-color: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-focus: 1px solid #36ad6a; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-icon-size: 16px; --n-line-height-textarea: 1.6; --n-color-disabled: rgb(250, 250, 252); --n-color-focus: rgba(255, 255, 255, 1); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-loading-color: #18a058; --n-caret-color-warning: #f0a020; --n-color-focus-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-loading-color-warning: #f0a020; --n-caret-color-error: #d03050; --n-color-focus-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-loading-color-error: #d03050; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-size: 16px; --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-icon-color-hover: rgba(146, 146, 146, 1); --n-icon-color-pressed: rgba(175, 175, 175, 1); --n-icon-color-disabled: rgba(209, 209, 209, 1); --n-suffix-text-color: rgb(51, 54, 57);\">\n      <div class=\"n-input-wrapper\">\n        <!---->\n        <div class=\"n-input__input\"><input type=\"text\" class=\"n-input__input-el\" placeholder=\"Wprowadź dane\" size=\"20\">\n          <div class=\"n-input__placeholder\"><span>Wprowadź dane</span></div>\n          <!---->\n        </div>\n        <!---->\n      </div>\n      <!---->\n      <!---->\n      <div class=\"n-input__border\"></div>\n      <div class=\"n-input__state-border\"></div>\n      <!---->\n    </div>\n    <div>\n      <div class=\"n-date-picker\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-icon-color-override: rgba(194, 194, 194, 1); --n-icon-color-disabled-override: rgba(209, 209, 209, 1);\">\n        <div class=\"n-input n-input--medium-size n-input--resizable n-input--stateful\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-count-text-color: rgb(118, 124, 130); --n-count-text-color-disabled: rgba(194, 194, 194, 1); --n-color: rgba(255, 255, 255, 1); --n-font-size: 14px; --n-font-weight: 400; --n-border-radius: 3px; --n-height: 34px; --n-padding-left: 12px; --n-padding-right: 12px; --n-text-color: rgb(51, 54, 57); --n-caret-color: #18a058; --n-text-decoration-color: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-focus: 1px solid #36ad6a; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-icon-size: 16px; --n-line-height-textarea: 1.6; --n-color-disabled: rgb(250, 250, 252); --n-color-focus: rgba(255, 255, 255, 1); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-loading-color: #18a058; --n-caret-color-warning: #f0a020; --n-color-focus-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-loading-color-warning: #f0a020; --n-caret-color-error: #d03050; --n-color-focus-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-loading-color-error: #d03050; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-size: 16px; --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-icon-color-hover: rgba(146, 146, 146, 1); --n-icon-color-pressed: rgba(175, 175, 175, 1); --n-icon-color-disabled: rgba(209, 209, 209, 1); --n-suffix-text-color: rgb(51, 54, 57);\" tabindex=\"0\">\n          <div class=\"n-input-wrapper\">\n            <!---->\n            <div class=\"n-input__input\"><input type=\"text\" class=\"n-input__input-el\" tabindex=\"-1\" placeholder=\"Wybierz datę\" size=\"20\" value=\"1970-01-01\">\n              <!---->\n              <!---->\n            </div>\n            <div class=\"n-input__suffix\">\n              <!---->\n              <!---->\n              <!----><i class=\"n-base-icon n-date-picker-icon\"><svg width=\"28px\" height=\"28px\" viewBox=\"0 0 28 28\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n                  <g stroke=\"none\" stroke-width=\"1\" fill-rule=\"evenodd\">\n                    <g fill-rule=\"nonzero\">\n                      <path d=\"M21.75,3 C23.5449254,3 25,4.45507456 25,6.25 L25,21.75 C25,23.5449254 23.5449254,25 21.75,25 L6.25,25 C4.45507456,25 3,23.5449254 3,21.75 L3,6.25 C3,4.45507456 4.45507456,3 6.25,3 L21.75,3 Z M23.5,9.503 L4.5,9.503 L4.5,21.75 C4.5,22.7164983 5.28350169,23.5 6.25,23.5 L21.75,23.5 C22.7164983,23.5 23.5,22.7164983 23.5,21.75 L23.5,9.503 Z M21.75,4.5 L6.25,4.5 C5.28350169,4.5 4.5,5.28350169 4.5,6.25 L4.5,8.003 L23.5,8.003 L23.5,6.25 C23.5,5.28350169 22.7164983,4.5 21.75,4.5 Z\"></path>\n                    </g>\n                  </g>\n                </svg></i>\n              <!---->\n              <!---->\n            </div>\n          </div>\n          <!---->\n          <!---->\n          <div class=\"n-input__border\"></div>\n          <div class=\"n-input__state-border\"></div>\n          <!---->\n        </div>\n        <!---->\n      </div>\n      <div class=\"n-date-picker\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-icon-color-override: rgba(194, 194, 194, 1); --n-icon-color-disabled-override: rgba(209, 209, 209, 1);\">\n        <div class=\"n-input n-input--medium-size n-input--resizable n-input--stateful\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-count-text-color: rgb(118, 124, 130); --n-count-text-color-disabled: rgba(194, 194, 194, 1); --n-color: rgba(255, 255, 255, 1); --n-font-size: 14px; --n-font-weight: 400; --n-border-radius: 3px; --n-height: 34px; --n-padding-left: 12px; --n-padding-right: 12px; --n-text-color: rgb(51, 54, 57); --n-caret-color: #18a058; --n-text-decoration-color: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-focus: 1px solid #36ad6a; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-icon-size: 16px; --n-line-height-textarea: 1.6; --n-color-disabled: rgb(250, 250, 252); --n-color-focus: rgba(255, 255, 255, 1); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-loading-color: #18a058; --n-caret-color-warning: #f0a020; --n-color-focus-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-loading-color-warning: #f0a020; --n-caret-color-error: #d03050; --n-color-focus-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-loading-color-error: #d03050; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-size: 16px; --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-icon-color-hover: rgba(146, 146, 146, 1); --n-icon-color-pressed: rgba(175, 175, 175, 1); --n-icon-color-disabled: rgba(209, 209, 209, 1); --n-suffix-text-color: rgb(51, 54, 57);\" tabindex=\"0\">\n          <div class=\"n-input-wrapper\">\n            <!---->\n            <div class=\"n-input__input\"><input type=\"text\" class=\"n-input__input-el\" tabindex=\"-1\" placeholder=\"Wybierz datę i czas\" size=\"20\" value=\"1970-01-01 08:00:00\">\n              <!---->\n              <!---->\n            </div>\n            <div class=\"n-input__suffix\">\n              <!---->\n              <!---->\n              <!----><i class=\"n-base-icon n-date-picker-icon\"><svg width=\"28px\" height=\"28px\" viewBox=\"0 0 28 28\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n                  <g stroke=\"none\" stroke-width=\"1\" fill-rule=\"evenodd\">\n                    <g fill-rule=\"nonzero\">\n                      <path d=\"M21.75,3 C23.5449254,3 25,4.45507456 25,6.25 L25,21.75 C25,23.5449254 23.5449254,25 21.75,25 L6.25,25 C4.45507456,25 3,23.5449254 3,21.75 L3,6.25 C3,4.45507456 4.45507456,3 6.25,3 L21.75,3 Z M23.5,9.503 L4.5,9.503 L4.5,21.75 C4.5,22.7164983 5.28350169,23.5 6.25,23.5 L21.75,23.5 C22.7164983,23.5 23.5,22.7164983 23.5,21.75 L23.5,9.503 Z M21.75,4.5 L6.25,4.5 C5.28350169,4.5 4.5,5.28350169 4.5,6.25 L4.5,8.003 L23.5,8.003 L23.5,6.25 C23.5,5.28350169 22.7164983,4.5 21.75,4.5 Z\"></path>\n                    </g>\n                  </g>\n                </svg></i>\n              <!---->\n              <!---->\n            </div>\n          </div>\n          <!---->\n          <!---->\n          <div class=\"n-input__border\"></div>\n          <div class=\"n-input__state-border\"></div>\n          <!---->\n        </div>\n        <!---->\n      </div>\n      <div class=\"n-date-picker\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-icon-color-override: rgba(194, 194, 194, 1); --n-icon-color-disabled-override: rgba(209, 209, 209, 1);\">\n        <div class=\"n-input n-input--medium-size n-input--resizable n-input--stateful\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-count-text-color: rgb(118, 124, 130); --n-count-text-color-disabled: rgba(194, 194, 194, 1); --n-color: rgba(255, 255, 255, 1); --n-font-size: 14px; --n-font-weight: 400; --n-border-radius: 3px; --n-height: 34px; --n-padding-left: 12px; --n-padding-right: 12px; --n-text-color: rgb(51, 54, 57); --n-caret-color: #18a058; --n-text-decoration-color: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-focus: 1px solid #36ad6a; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-icon-size: 16px; --n-line-height-textarea: 1.6; --n-color-disabled: rgb(250, 250, 252); --n-color-focus: rgba(255, 255, 255, 1); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-loading-color: #18a058; --n-caret-color-warning: #f0a020; --n-color-focus-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-loading-color-warning: #f0a020; --n-caret-color-error: #d03050; --n-color-focus-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-loading-color-error: #d03050; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-size: 16px; --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-icon-color-hover: rgba(146, 146, 146, 1); --n-icon-color-pressed: rgba(175, 175, 175, 1); --n-icon-color-disabled: rgba(209, 209, 209, 1); --n-suffix-text-color: rgb(51, 54, 57);\" tabindex=\"0\">\n          <div class=\"n-input-wrapper\">\n            <!---->\n            <div class=\"n-input__input\"><input type=\"text\" class=\"n-input__input-el\" tabindex=\"-1\" placeholder=\"Wybierz rok\" size=\"20\" value=\"1970\">\n              <!---->\n              <!---->\n            </div>\n            <div class=\"n-input__suffix\">\n              <!---->\n              <!---->\n              <!----><i class=\"n-base-icon n-date-picker-icon\"><svg width=\"28px\" height=\"28px\" viewBox=\"0 0 28 28\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n                  <g stroke=\"none\" stroke-width=\"1\" fill-rule=\"evenodd\">\n                    <g fill-rule=\"nonzero\">\n                      <path d=\"M21.75,3 C23.5449254,3 25,4.45507456 25,6.25 L25,21.75 C25,23.5449254 23.5449254,25 21.75,25 L6.25,25 C4.45507456,25 3,23.5449254 3,21.75 L3,6.25 C3,4.45507456 4.45507456,3 6.25,3 L21.75,3 Z M23.5,9.503 L4.5,9.503 L4.5,21.75 C4.5,22.7164983 5.28350169,23.5 6.25,23.5 L21.75,23.5 C22.7164983,23.5 23.5,22.7164983 23.5,21.75 L23.5,9.503 Z M21.75,4.5 L6.25,4.5 C5.28350169,4.5 4.5,5.28350169 4.5,6.25 L4.5,8.003 L23.5,8.003 L23.5,6.25 C23.5,5.28350169 22.7164983,4.5 21.75,4.5 Z\"></path>\n                    </g>\n                  </g>\n                </svg></i>\n              <!---->\n              <!---->\n            </div>\n          </div>\n          <!---->\n          <!---->\n          <div class=\"n-input__border\"></div>\n          <div class=\"n-input__state-border\"></div>\n          <!---->\n        </div>\n        <!---->\n      </div>\n      <div class=\"n-date-picker\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-icon-color-override: rgba(194, 194, 194, 1); --n-icon-color-disabled-override: rgba(209, 209, 209, 1);\">\n        <div class=\"n-input n-input--medium-size n-input--resizable n-input--stateful\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-count-text-color: rgb(118, 124, 130); --n-count-text-color-disabled: rgba(194, 194, 194, 1); --n-color: rgba(255, 255, 255, 1); --n-font-size: 14px; --n-font-weight: 400; --n-border-radius: 3px; --n-height: 34px; --n-padding-left: 12px; --n-padding-right: 12px; --n-text-color: rgb(51, 54, 57); --n-caret-color: #18a058; --n-text-decoration-color: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-focus: 1px solid #36ad6a; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-icon-size: 16px; --n-line-height-textarea: 1.6; --n-color-disabled: rgb(250, 250, 252); --n-color-focus: rgba(255, 255, 255, 1); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-loading-color: #18a058; --n-caret-color-warning: #f0a020; --n-color-focus-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-loading-color-warning: #f0a020; --n-caret-color-error: #d03050; --n-color-focus-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-loading-color-error: #d03050; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-size: 16px; --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-icon-color-hover: rgba(146, 146, 146, 1); --n-icon-color-pressed: rgba(175, 175, 175, 1); --n-icon-color-disabled: rgba(209, 209, 209, 1); --n-suffix-text-color: rgb(51, 54, 57);\" tabindex=\"0\">\n          <div class=\"n-input-wrapper\">\n            <!---->\n            <div class=\"n-input__input\"><input type=\"text\" class=\"n-input__input-el\" tabindex=\"-1\" placeholder=\"Wybierz miesiąc\" size=\"20\" value=\"1970-01\">\n              <!---->\n              <!---->\n            </div>\n            <div class=\"n-input__suffix\">\n              <!---->\n              <!---->\n              <!----><i class=\"n-base-icon n-date-picker-icon\"><svg width=\"28px\" height=\"28px\" viewBox=\"0 0 28 28\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n                  <g stroke=\"none\" stroke-width=\"1\" fill-rule=\"evenodd\">\n                    <g fill-rule=\"nonzero\">\n                      <path d=\"M21.75,3 C23.5449254,3 25,4.45507456 25,6.25 L25,21.75 C25,23.5449254 23.5449254,25 21.75,25 L6.25,25 C4.45507456,25 3,23.5449254 3,21.75 L3,6.25 C3,4.45507456 4.45507456,3 6.25,3 L21.75,3 Z M23.5,9.503 L4.5,9.503 L4.5,21.75 C4.5,22.7164983 5.28350169,23.5 6.25,23.5 L21.75,23.5 C22.7164983,23.5 23.5,22.7164983 23.5,21.75 L23.5,9.503 Z M21.75,4.5 L6.25,4.5 C5.28350169,4.5 4.5,5.28350169 4.5,6.25 L4.5,8.003 L23.5,8.003 L23.5,6.25 C23.5,5.28350169 22.7164983,4.5 21.75,4.5 Z\"></path>\n                    </g>\n                  </g>\n                </svg></i>\n              <!---->\n              <!---->\n            </div>\n          </div>\n          <!---->\n          <!---->\n          <div class=\"n-input__border\"></div>\n          <div class=\"n-input__state-border\"></div>\n          <!---->\n        </div>\n        <!---->\n      </div>\n    </div>\n  </div>\n</div>\"\n`;\n\nexports[`locale > works 20`] = `\n\"<div class=\"n-config-provider\">\n  <div>\n    <div class=\"n-input n-input--medium-size n-input--resizable n-input--stateful\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-count-text-color: rgb(118, 124, 130); --n-count-text-color-disabled: rgba(194, 194, 194, 1); --n-color: rgba(255, 255, 255, 1); --n-font-size: 14px; --n-font-weight: 400; --n-border-radius: 3px; --n-height: 34px; --n-padding-left: 12px; --n-padding-right: 12px; --n-text-color: rgb(51, 54, 57); --n-caret-color: #18a058; --n-text-decoration-color: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-focus: 1px solid #36ad6a; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-icon-size: 16px; --n-line-height-textarea: 1.6; --n-color-disabled: rgb(250, 250, 252); --n-color-focus: rgba(255, 255, 255, 1); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-loading-color: #18a058; --n-caret-color-warning: #f0a020; --n-color-focus-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-loading-color-warning: #f0a020; --n-caret-color-error: #d03050; --n-color-focus-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-loading-color-error: #d03050; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-size: 16px; --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-icon-color-hover: rgba(146, 146, 146, 1); --n-icon-color-pressed: rgba(175, 175, 175, 1); --n-icon-color-disabled: rgba(209, 209, 209, 1); --n-suffix-text-color: rgb(51, 54, 57);\">\n      <div class=\"n-input-wrapper\">\n        <!---->\n        <div class=\"n-input__input\"><input type=\"text\" class=\"n-input__input-el\" placeholder=\"Por favor digite\" size=\"20\">\n          <div class=\"n-input__placeholder\"><span>Por favor digite</span></div>\n          <!---->\n        </div>\n        <!---->\n      </div>\n      <!---->\n      <!---->\n      <div class=\"n-input__border\"></div>\n      <div class=\"n-input__state-border\"></div>\n      <!---->\n    </div>\n    <div>\n      <div class=\"n-date-picker\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-icon-color-override: rgba(194, 194, 194, 1); --n-icon-color-disabled-override: rgba(209, 209, 209, 1);\">\n        <div class=\"n-input n-input--medium-size n-input--resizable n-input--stateful\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-count-text-color: rgb(118, 124, 130); --n-count-text-color-disabled: rgba(194, 194, 194, 1); --n-color: rgba(255, 255, 255, 1); --n-font-size: 14px; --n-font-weight: 400; --n-border-radius: 3px; --n-height: 34px; --n-padding-left: 12px; --n-padding-right: 12px; --n-text-color: rgb(51, 54, 57); --n-caret-color: #18a058; --n-text-decoration-color: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-focus: 1px solid #36ad6a; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-icon-size: 16px; --n-line-height-textarea: 1.6; --n-color-disabled: rgb(250, 250, 252); --n-color-focus: rgba(255, 255, 255, 1); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-loading-color: #18a058; --n-caret-color-warning: #f0a020; --n-color-focus-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-loading-color-warning: #f0a020; --n-caret-color-error: #d03050; --n-color-focus-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-loading-color-error: #d03050; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-size: 16px; --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-icon-color-hover: rgba(146, 146, 146, 1); --n-icon-color-pressed: rgba(175, 175, 175, 1); --n-icon-color-disabled: rgba(209, 209, 209, 1); --n-suffix-text-color: rgb(51, 54, 57);\" tabindex=\"0\">\n          <div class=\"n-input-wrapper\">\n            <!---->\n            <div class=\"n-input__input\"><input type=\"text\" class=\"n-input__input-el\" tabindex=\"-1\" placeholder=\"Selecione a data\" size=\"20\" value=\"01/01/1970\">\n              <!---->\n              <!---->\n            </div>\n            <div class=\"n-input__suffix\">\n              <!---->\n              <!---->\n              <!----><i class=\"n-base-icon n-date-picker-icon\"><svg width=\"28px\" height=\"28px\" viewBox=\"0 0 28 28\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n                  <g stroke=\"none\" stroke-width=\"1\" fill-rule=\"evenodd\">\n                    <g fill-rule=\"nonzero\">\n                      <path d=\"M21.75,3 C23.5449254,3 25,4.45507456 25,6.25 L25,21.75 C25,23.5449254 23.5449254,25 21.75,25 L6.25,25 C4.45507456,25 3,23.5449254 3,21.75 L3,6.25 C3,4.45507456 4.45507456,3 6.25,3 L21.75,3 Z M23.5,9.503 L4.5,9.503 L4.5,21.75 C4.5,22.7164983 5.28350169,23.5 6.25,23.5 L21.75,23.5 C22.7164983,23.5 23.5,22.7164983 23.5,21.75 L23.5,9.503 Z M21.75,4.5 L6.25,4.5 C5.28350169,4.5 4.5,5.28350169 4.5,6.25 L4.5,8.003 L23.5,8.003 L23.5,6.25 C23.5,5.28350169 22.7164983,4.5 21.75,4.5 Z\"></path>\n                    </g>\n                  </g>\n                </svg></i>\n              <!---->\n              <!---->\n            </div>\n          </div>\n          <!---->\n          <!---->\n          <div class=\"n-input__border\"></div>\n          <div class=\"n-input__state-border\"></div>\n          <!---->\n        </div>\n        <!---->\n      </div>\n      <div class=\"n-date-picker\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-icon-color-override: rgba(194, 194, 194, 1); --n-icon-color-disabled-override: rgba(209, 209, 209, 1);\">\n        <div class=\"n-input n-input--medium-size n-input--resizable n-input--stateful\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-count-text-color: rgb(118, 124, 130); --n-count-text-color-disabled: rgba(194, 194, 194, 1); --n-color: rgba(255, 255, 255, 1); --n-font-size: 14px; --n-font-weight: 400; --n-border-radius: 3px; --n-height: 34px; --n-padding-left: 12px; --n-padding-right: 12px; --n-text-color: rgb(51, 54, 57); --n-caret-color: #18a058; --n-text-decoration-color: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-focus: 1px solid #36ad6a; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-icon-size: 16px; --n-line-height-textarea: 1.6; --n-color-disabled: rgb(250, 250, 252); --n-color-focus: rgba(255, 255, 255, 1); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-loading-color: #18a058; --n-caret-color-warning: #f0a020; --n-color-focus-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-loading-color-warning: #f0a020; --n-caret-color-error: #d03050; --n-color-focus-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-loading-color-error: #d03050; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-size: 16px; --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-icon-color-hover: rgba(146, 146, 146, 1); --n-icon-color-pressed: rgba(175, 175, 175, 1); --n-icon-color-disabled: rgba(209, 209, 209, 1); --n-suffix-text-color: rgb(51, 54, 57);\" tabindex=\"0\">\n          <div class=\"n-input-wrapper\">\n            <!---->\n            <div class=\"n-input__input\"><input type=\"text\" class=\"n-input__input-el\" tabindex=\"-1\" placeholder=\"Selecione a data e hora\" size=\"20\" value=\"01/01/1970 08:00:00\">\n              <!---->\n              <!---->\n            </div>\n            <div class=\"n-input__suffix\">\n              <!---->\n              <!---->\n              <!----><i class=\"n-base-icon n-date-picker-icon\"><svg width=\"28px\" height=\"28px\" viewBox=\"0 0 28 28\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n                  <g stroke=\"none\" stroke-width=\"1\" fill-rule=\"evenodd\">\n                    <g fill-rule=\"nonzero\">\n                      <path d=\"M21.75,3 C23.5449254,3 25,4.45507456 25,6.25 L25,21.75 C25,23.5449254 23.5449254,25 21.75,25 L6.25,25 C4.45507456,25 3,23.5449254 3,21.75 L3,6.25 C3,4.45507456 4.45507456,3 6.25,3 L21.75,3 Z M23.5,9.503 L4.5,9.503 L4.5,21.75 C4.5,22.7164983 5.28350169,23.5 6.25,23.5 L21.75,23.5 C22.7164983,23.5 23.5,22.7164983 23.5,21.75 L23.5,9.503 Z M21.75,4.5 L6.25,4.5 C5.28350169,4.5 4.5,5.28350169 4.5,6.25 L4.5,8.003 L23.5,8.003 L23.5,6.25 C23.5,5.28350169 22.7164983,4.5 21.75,4.5 Z\"></path>\n                    </g>\n                  </g>\n                </svg></i>\n              <!---->\n              <!---->\n            </div>\n          </div>\n          <!---->\n          <!---->\n          <div class=\"n-input__border\"></div>\n          <div class=\"n-input__state-border\"></div>\n          <!---->\n        </div>\n        <!---->\n      </div>\n      <div class=\"n-date-picker\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-icon-color-override: rgba(194, 194, 194, 1); --n-icon-color-disabled-override: rgba(209, 209, 209, 1);\">\n        <div class=\"n-input n-input--medium-size n-input--resizable n-input--stateful\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-count-text-color: rgb(118, 124, 130); --n-count-text-color-disabled: rgba(194, 194, 194, 1); --n-color: rgba(255, 255, 255, 1); --n-font-size: 14px; --n-font-weight: 400; --n-border-radius: 3px; --n-height: 34px; --n-padding-left: 12px; --n-padding-right: 12px; --n-text-color: rgb(51, 54, 57); --n-caret-color: #18a058; --n-text-decoration-color: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-focus: 1px solid #36ad6a; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-icon-size: 16px; --n-line-height-textarea: 1.6; --n-color-disabled: rgb(250, 250, 252); --n-color-focus: rgba(255, 255, 255, 1); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-loading-color: #18a058; --n-caret-color-warning: #f0a020; --n-color-focus-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-loading-color-warning: #f0a020; --n-caret-color-error: #d03050; --n-color-focus-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-loading-color-error: #d03050; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-size: 16px; --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-icon-color-hover: rgba(146, 146, 146, 1); --n-icon-color-pressed: rgba(175, 175, 175, 1); --n-icon-color-disabled: rgba(209, 209, 209, 1); --n-suffix-text-color: rgb(51, 54, 57);\" tabindex=\"0\">\n          <div class=\"n-input-wrapper\">\n            <!---->\n            <div class=\"n-input__input\"><input type=\"text\" class=\"n-input__input-el\" tabindex=\"-1\" placeholder=\"Selecione o ano\" size=\"20\" value=\"1970\">\n              <!---->\n              <!---->\n            </div>\n            <div class=\"n-input__suffix\">\n              <!---->\n              <!---->\n              <!----><i class=\"n-base-icon n-date-picker-icon\"><svg width=\"28px\" height=\"28px\" viewBox=\"0 0 28 28\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n                  <g stroke=\"none\" stroke-width=\"1\" fill-rule=\"evenodd\">\n                    <g fill-rule=\"nonzero\">\n                      <path d=\"M21.75,3 C23.5449254,3 25,4.45507456 25,6.25 L25,21.75 C25,23.5449254 23.5449254,25 21.75,25 L6.25,25 C4.45507456,25 3,23.5449254 3,21.75 L3,6.25 C3,4.45507456 4.45507456,3 6.25,3 L21.75,3 Z M23.5,9.503 L4.5,9.503 L4.5,21.75 C4.5,22.7164983 5.28350169,23.5 6.25,23.5 L21.75,23.5 C22.7164983,23.5 23.5,22.7164983 23.5,21.75 L23.5,9.503 Z M21.75,4.5 L6.25,4.5 C5.28350169,4.5 4.5,5.28350169 4.5,6.25 L4.5,8.003 L23.5,8.003 L23.5,6.25 C23.5,5.28350169 22.7164983,4.5 21.75,4.5 Z\"></path>\n                    </g>\n                  </g>\n                </svg></i>\n              <!---->\n              <!---->\n            </div>\n          </div>\n          <!---->\n          <!---->\n          <div class=\"n-input__border\"></div>\n          <div class=\"n-input__state-border\"></div>\n          <!---->\n        </div>\n        <!---->\n      </div>\n      <div class=\"n-date-picker\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-icon-color-override: rgba(194, 194, 194, 1); --n-icon-color-disabled-override: rgba(209, 209, 209, 1);\">\n        <div class=\"n-input n-input--medium-size n-input--resizable n-input--stateful\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-count-text-color: rgb(118, 124, 130); --n-count-text-color-disabled: rgba(194, 194, 194, 1); --n-color: rgba(255, 255, 255, 1); --n-font-size: 14px; --n-font-weight: 400; --n-border-radius: 3px; --n-height: 34px; --n-padding-left: 12px; --n-padding-right: 12px; --n-text-color: rgb(51, 54, 57); --n-caret-color: #18a058; --n-text-decoration-color: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-focus: 1px solid #36ad6a; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-icon-size: 16px; --n-line-height-textarea: 1.6; --n-color-disabled: rgb(250, 250, 252); --n-color-focus: rgba(255, 255, 255, 1); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-loading-color: #18a058; --n-caret-color-warning: #f0a020; --n-color-focus-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-loading-color-warning: #f0a020; --n-caret-color-error: #d03050; --n-color-focus-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-loading-color-error: #d03050; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-size: 16px; --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-icon-color-hover: rgba(146, 146, 146, 1); --n-icon-color-pressed: rgba(175, 175, 175, 1); --n-icon-color-disabled: rgba(209, 209, 209, 1); --n-suffix-text-color: rgb(51, 54, 57);\" tabindex=\"0\">\n          <div class=\"n-input-wrapper\">\n            <!---->\n            <div class=\"n-input__input\"><input type=\"text\" class=\"n-input__input-el\" tabindex=\"-1\" placeholder=\"Selecione o mês\" size=\"20\" value=\"1970/01\">\n              <!---->\n              <!---->\n            </div>\n            <div class=\"n-input__suffix\">\n              <!---->\n              <!---->\n              <!----><i class=\"n-base-icon n-date-picker-icon\"><svg width=\"28px\" height=\"28px\" viewBox=\"0 0 28 28\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n                  <g stroke=\"none\" stroke-width=\"1\" fill-rule=\"evenodd\">\n                    <g fill-rule=\"nonzero\">\n                      <path d=\"M21.75,3 C23.5449254,3 25,4.45507456 25,6.25 L25,21.75 C25,23.5449254 23.5449254,25 21.75,25 L6.25,25 C4.45507456,25 3,23.5449254 3,21.75 L3,6.25 C3,4.45507456 4.45507456,3 6.25,3 L21.75,3 Z M23.5,9.503 L4.5,9.503 L4.5,21.75 C4.5,22.7164983 5.28350169,23.5 6.25,23.5 L21.75,23.5 C22.7164983,23.5 23.5,22.7164983 23.5,21.75 L23.5,9.503 Z M21.75,4.5 L6.25,4.5 C5.28350169,4.5 4.5,5.28350169 4.5,6.25 L4.5,8.003 L23.5,8.003 L23.5,6.25 C23.5,5.28350169 22.7164983,4.5 21.75,4.5 Z\"></path>\n                    </g>\n                  </g>\n                </svg></i>\n              <!---->\n              <!---->\n            </div>\n          </div>\n          <!---->\n          <!---->\n          <div class=\"n-input__border\"></div>\n          <div class=\"n-input__state-border\"></div>\n          <!---->\n        </div>\n        <!---->\n      </div>\n    </div>\n  </div>\n</div>\"\n`;\n\nexports[`locale > works 21`] = `\n\"<div class=\"n-config-provider\">\n  <div>\n    <div class=\"n-input n-input--medium-size n-input--resizable n-input--stateful\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-count-text-color: rgb(118, 124, 130); --n-count-text-color-disabled: rgba(194, 194, 194, 1); --n-color: rgba(255, 255, 255, 1); --n-font-size: 14px; --n-font-weight: 400; --n-border-radius: 3px; --n-height: 34px; --n-padding-left: 12px; --n-padding-right: 12px; --n-text-color: rgb(51, 54, 57); --n-caret-color: #18a058; --n-text-decoration-color: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-focus: 1px solid #36ad6a; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-icon-size: 16px; --n-line-height-textarea: 1.6; --n-color-disabled: rgb(250, 250, 252); --n-color-focus: rgba(255, 255, 255, 1); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-loading-color: #18a058; --n-caret-color-warning: #f0a020; --n-color-focus-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-loading-color-warning: #f0a020; --n-caret-color-error: #d03050; --n-color-focus-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-loading-color-error: #d03050; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-size: 16px; --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-icon-color-hover: rgba(146, 146, 146, 1); --n-icon-color-pressed: rgba(175, 175, 175, 1); --n-icon-color-disabled: rgba(209, 209, 209, 1); --n-suffix-text-color: rgb(51, 54, 57);\">\n      <div class=\"n-input-wrapper\">\n        <!---->\n        <div class=\"n-input__input\"><input type=\"text\" class=\"n-input__input-el\" placeholder=\"กรุณากรอก\" size=\"20\">\n          <div class=\"n-input__placeholder\"><span>กรุณากรอก</span></div>\n          <!---->\n        </div>\n        <!---->\n      </div>\n      <!---->\n      <!---->\n      <div class=\"n-input__border\"></div>\n      <div class=\"n-input__state-border\"></div>\n      <!---->\n    </div>\n    <div>\n      <div class=\"n-date-picker\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-icon-color-override: rgba(194, 194, 194, 1); --n-icon-color-disabled-override: rgba(209, 209, 209, 1);\">\n        <div class=\"n-input n-input--medium-size n-input--resizable n-input--stateful\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-count-text-color: rgb(118, 124, 130); --n-count-text-color-disabled: rgba(194, 194, 194, 1); --n-color: rgba(255, 255, 255, 1); --n-font-size: 14px; --n-font-weight: 400; --n-border-radius: 3px; --n-height: 34px; --n-padding-left: 12px; --n-padding-right: 12px; --n-text-color: rgb(51, 54, 57); --n-caret-color: #18a058; --n-text-decoration-color: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-focus: 1px solid #36ad6a; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-icon-size: 16px; --n-line-height-textarea: 1.6; --n-color-disabled: rgb(250, 250, 252); --n-color-focus: rgba(255, 255, 255, 1); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-loading-color: #18a058; --n-caret-color-warning: #f0a020; --n-color-focus-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-loading-color-warning: #f0a020; --n-caret-color-error: #d03050; --n-color-focus-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-loading-color-error: #d03050; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-size: 16px; --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-icon-color-hover: rgba(146, 146, 146, 1); --n-icon-color-pressed: rgba(175, 175, 175, 1); --n-icon-color-disabled: rgba(209, 209, 209, 1); --n-suffix-text-color: rgb(51, 54, 57);\" tabindex=\"0\">\n          <div class=\"n-input-wrapper\">\n            <!---->\n            <div class=\"n-input__input\"><input type=\"text\" class=\"n-input__input-el\" tabindex=\"-1\" placeholder=\"วันที่\" size=\"20\" value=\"01/มกราคม/1970\">\n              <!---->\n              <!---->\n            </div>\n            <div class=\"n-input__suffix\">\n              <!---->\n              <!---->\n              <!----><i class=\"n-base-icon n-date-picker-icon\"><svg width=\"28px\" height=\"28px\" viewBox=\"0 0 28 28\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n                  <g stroke=\"none\" stroke-width=\"1\" fill-rule=\"evenodd\">\n                    <g fill-rule=\"nonzero\">\n                      <path d=\"M21.75,3 C23.5449254,3 25,4.45507456 25,6.25 L25,21.75 C25,23.5449254 23.5449254,25 21.75,25 L6.25,25 C4.45507456,25 3,23.5449254 3,21.75 L3,6.25 C3,4.45507456 4.45507456,3 6.25,3 L21.75,3 Z M23.5,9.503 L4.5,9.503 L4.5,21.75 C4.5,22.7164983 5.28350169,23.5 6.25,23.5 L21.75,23.5 C22.7164983,23.5 23.5,22.7164983 23.5,21.75 L23.5,9.503 Z M21.75,4.5 L6.25,4.5 C5.28350169,4.5 4.5,5.28350169 4.5,6.25 L4.5,8.003 L23.5,8.003 L23.5,6.25 C23.5,5.28350169 22.7164983,4.5 21.75,4.5 Z\"></path>\n                    </g>\n                  </g>\n                </svg></i>\n              <!---->\n              <!---->\n            </div>\n          </div>\n          <!---->\n          <!---->\n          <div class=\"n-input__border\"></div>\n          <div class=\"n-input__state-border\"></div>\n          <!---->\n        </div>\n        <!---->\n      </div>\n      <div class=\"n-date-picker\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-icon-color-override: rgba(194, 194, 194, 1); --n-icon-color-disabled-override: rgba(209, 209, 209, 1);\">\n        <div class=\"n-input n-input--medium-size n-input--resizable n-input--stateful\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-count-text-color: rgb(118, 124, 130); --n-count-text-color-disabled: rgba(194, 194, 194, 1); --n-color: rgba(255, 255, 255, 1); --n-font-size: 14px; --n-font-weight: 400; --n-border-radius: 3px; --n-height: 34px; --n-padding-left: 12px; --n-padding-right: 12px; --n-text-color: rgb(51, 54, 57); --n-caret-color: #18a058; --n-text-decoration-color: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-focus: 1px solid #36ad6a; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-icon-size: 16px; --n-line-height-textarea: 1.6; --n-color-disabled: rgb(250, 250, 252); --n-color-focus: rgba(255, 255, 255, 1); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-loading-color: #18a058; --n-caret-color-warning: #f0a020; --n-color-focus-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-loading-color-warning: #f0a020; --n-caret-color-error: #d03050; --n-color-focus-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-loading-color-error: #d03050; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-size: 16px; --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-icon-color-hover: rgba(146, 146, 146, 1); --n-icon-color-pressed: rgba(175, 175, 175, 1); --n-icon-color-disabled: rgba(209, 209, 209, 1); --n-suffix-text-color: rgb(51, 54, 57);\" tabindex=\"0\">\n          <div class=\"n-input-wrapper\">\n            <!---->\n            <div class=\"n-input__input\"><input type=\"text\" class=\"n-input__input-el\" tabindex=\"-1\" placeholder=\"เวลา-วันที่\" size=\"20\" value=\"01/มกราคม/1970 08:00:00\">\n              <!---->\n              <!---->\n            </div>\n            <div class=\"n-input__suffix\">\n              <!---->\n              <!---->\n              <!----><i class=\"n-base-icon n-date-picker-icon\"><svg width=\"28px\" height=\"28px\" viewBox=\"0 0 28 28\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n                  <g stroke=\"none\" stroke-width=\"1\" fill-rule=\"evenodd\">\n                    <g fill-rule=\"nonzero\">\n                      <path d=\"M21.75,3 C23.5449254,3 25,4.45507456 25,6.25 L25,21.75 C25,23.5449254 23.5449254,25 21.75,25 L6.25,25 C4.45507456,25 3,23.5449254 3,21.75 L3,6.25 C3,4.45507456 4.45507456,3 6.25,3 L21.75,3 Z M23.5,9.503 L4.5,9.503 L4.5,21.75 C4.5,22.7164983 5.28350169,23.5 6.25,23.5 L21.75,23.5 C22.7164983,23.5 23.5,22.7164983 23.5,21.75 L23.5,9.503 Z M21.75,4.5 L6.25,4.5 C5.28350169,4.5 4.5,5.28350169 4.5,6.25 L4.5,8.003 L23.5,8.003 L23.5,6.25 C23.5,5.28350169 22.7164983,4.5 21.75,4.5 Z\"></path>\n                    </g>\n                  </g>\n                </svg></i>\n              <!---->\n              <!---->\n            </div>\n          </div>\n          <!---->\n          <!---->\n          <div class=\"n-input__border\"></div>\n          <div class=\"n-input__state-border\"></div>\n          <!---->\n        </div>\n        <!---->\n      </div>\n      <div class=\"n-date-picker\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-icon-color-override: rgba(194, 194, 194, 1); --n-icon-color-disabled-override: rgba(209, 209, 209, 1);\">\n        <div class=\"n-input n-input--medium-size n-input--resizable n-input--stateful\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-count-text-color: rgb(118, 124, 130); --n-count-text-color-disabled: rgba(194, 194, 194, 1); --n-color: rgba(255, 255, 255, 1); --n-font-size: 14px; --n-font-weight: 400; --n-border-radius: 3px; --n-height: 34px; --n-padding-left: 12px; --n-padding-right: 12px; --n-text-color: rgb(51, 54, 57); --n-caret-color: #18a058; --n-text-decoration-color: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-focus: 1px solid #36ad6a; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-icon-size: 16px; --n-line-height-textarea: 1.6; --n-color-disabled: rgb(250, 250, 252); --n-color-focus: rgba(255, 255, 255, 1); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-loading-color: #18a058; --n-caret-color-warning: #f0a020; --n-color-focus-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-loading-color-warning: #f0a020; --n-caret-color-error: #d03050; --n-color-focus-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-loading-color-error: #d03050; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-size: 16px; --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-icon-color-hover: rgba(146, 146, 146, 1); --n-icon-color-pressed: rgba(175, 175, 175, 1); --n-icon-color-disabled: rgba(209, 209, 209, 1); --n-suffix-text-color: rgb(51, 54, 57);\" tabindex=\"0\">\n          <div class=\"n-input-wrapper\">\n            <!---->\n            <div class=\"n-input__input\"><input type=\"text\" class=\"n-input__input-el\" tabindex=\"-1\" placeholder=\"ปี\" size=\"20\" value=\"1970\">\n              <!---->\n              <!---->\n            </div>\n            <div class=\"n-input__suffix\">\n              <!---->\n              <!---->\n              <!----><i class=\"n-base-icon n-date-picker-icon\"><svg width=\"28px\" height=\"28px\" viewBox=\"0 0 28 28\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n                  <g stroke=\"none\" stroke-width=\"1\" fill-rule=\"evenodd\">\n                    <g fill-rule=\"nonzero\">\n                      <path d=\"M21.75,3 C23.5449254,3 25,4.45507456 25,6.25 L25,21.75 C25,23.5449254 23.5449254,25 21.75,25 L6.25,25 C4.45507456,25 3,23.5449254 3,21.75 L3,6.25 C3,4.45507456 4.45507456,3 6.25,3 L21.75,3 Z M23.5,9.503 L4.5,9.503 L4.5,21.75 C4.5,22.7164983 5.28350169,23.5 6.25,23.5 L21.75,23.5 C22.7164983,23.5 23.5,22.7164983 23.5,21.75 L23.5,9.503 Z M21.75,4.5 L6.25,4.5 C5.28350169,4.5 4.5,5.28350169 4.5,6.25 L4.5,8.003 L23.5,8.003 L23.5,6.25 C23.5,5.28350169 22.7164983,4.5 21.75,4.5 Z\"></path>\n                    </g>\n                  </g>\n                </svg></i>\n              <!---->\n              <!---->\n            </div>\n          </div>\n          <!---->\n          <!---->\n          <div class=\"n-input__border\"></div>\n          <div class=\"n-input__state-border\"></div>\n          <!---->\n        </div>\n        <!---->\n      </div>\n      <div class=\"n-date-picker\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-icon-color-override: rgba(194, 194, 194, 1); --n-icon-color-disabled-override: rgba(209, 209, 209, 1);\">\n        <div class=\"n-input n-input--medium-size n-input--resizable n-input--stateful\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-count-text-color: rgb(118, 124, 130); --n-count-text-color-disabled: rgba(194, 194, 194, 1); --n-color: rgba(255, 255, 255, 1); --n-font-size: 14px; --n-font-weight: 400; --n-border-radius: 3px; --n-height: 34px; --n-padding-left: 12px; --n-padding-right: 12px; --n-text-color: rgb(51, 54, 57); --n-caret-color: #18a058; --n-text-decoration-color: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-focus: 1px solid #36ad6a; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-icon-size: 16px; --n-line-height-textarea: 1.6; --n-color-disabled: rgb(250, 250, 252); --n-color-focus: rgba(255, 255, 255, 1); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-loading-color: #18a058; --n-caret-color-warning: #f0a020; --n-color-focus-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-loading-color-warning: #f0a020; --n-caret-color-error: #d03050; --n-color-focus-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-loading-color-error: #d03050; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-size: 16px; --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-icon-color-hover: rgba(146, 146, 146, 1); --n-icon-color-pressed: rgba(175, 175, 175, 1); --n-icon-color-disabled: rgba(209, 209, 209, 1); --n-suffix-text-color: rgb(51, 54, 57);\" tabindex=\"0\">\n          <div class=\"n-input-wrapper\">\n            <!---->\n            <div class=\"n-input__input\"><input type=\"text\" class=\"n-input__input-el\" tabindex=\"-1\" placeholder=\"เดือน\" size=\"20\" value=\"1970-01\">\n              <!---->\n              <!---->\n            </div>\n            <div class=\"n-input__suffix\">\n              <!---->\n              <!---->\n              <!----><i class=\"n-base-icon n-date-picker-icon\"><svg width=\"28px\" height=\"28px\" viewBox=\"0 0 28 28\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n                  <g stroke=\"none\" stroke-width=\"1\" fill-rule=\"evenodd\">\n                    <g fill-rule=\"nonzero\">\n                      <path d=\"M21.75,3 C23.5449254,3 25,4.45507456 25,6.25 L25,21.75 C25,23.5449254 23.5449254,25 21.75,25 L6.25,25 C4.45507456,25 3,23.5449254 3,21.75 L3,6.25 C3,4.45507456 4.45507456,3 6.25,3 L21.75,3 Z M23.5,9.503 L4.5,9.503 L4.5,21.75 C4.5,22.7164983 5.28350169,23.5 6.25,23.5 L21.75,23.5 C22.7164983,23.5 23.5,22.7164983 23.5,21.75 L23.5,9.503 Z M21.75,4.5 L6.25,4.5 C5.28350169,4.5 4.5,5.28350169 4.5,6.25 L4.5,8.003 L23.5,8.003 L23.5,6.25 C23.5,5.28350169 22.7164983,4.5 21.75,4.5 Z\"></path>\n                    </g>\n                  </g>\n                </svg></i>\n              <!---->\n              <!---->\n            </div>\n          </div>\n          <!---->\n          <!---->\n          <div class=\"n-input__border\"></div>\n          <div class=\"n-input__state-border\"></div>\n          <!---->\n        </div>\n        <!---->\n      </div>\n    </div>\n  </div>\n</div>\"\n`;\n\nexports[`locale > works 22`] = `\n\"<div class=\"n-config-provider\">\n  <div>\n    <div class=\"n-input n-input--medium-size n-input--resizable n-input--stateful\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-count-text-color: rgb(118, 124, 130); --n-count-text-color-disabled: rgba(194, 194, 194, 1); --n-color: rgba(255, 255, 255, 1); --n-font-size: 14px; --n-font-weight: 400; --n-border-radius: 3px; --n-height: 34px; --n-padding-left: 12px; --n-padding-right: 12px; --n-text-color: rgb(51, 54, 57); --n-caret-color: #18a058; --n-text-decoration-color: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-focus: 1px solid #36ad6a; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-icon-size: 16px; --n-line-height-textarea: 1.6; --n-color-disabled: rgb(250, 250, 252); --n-color-focus: rgba(255, 255, 255, 1); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-loading-color: #18a058; --n-caret-color-warning: #f0a020; --n-color-focus-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-loading-color-warning: #f0a020; --n-caret-color-error: #d03050; --n-color-focus-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-loading-color-error: #d03050; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-size: 16px; --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-icon-color-hover: rgba(146, 146, 146, 1); --n-icon-color-pressed: rgba(175, 175, 175, 1); --n-icon-color-disabled: rgba(209, 209, 209, 1); --n-suffix-text-color: rgb(51, 54, 57);\">\n      <div class=\"n-input-wrapper\">\n        <!---->\n        <div class=\"n-input__input\"><input type=\"text\" class=\"n-input__input-el\" placeholder=\"Bonvolu entajpi\" size=\"20\">\n          <div class=\"n-input__placeholder\"><span>Bonvolu entajpi</span></div>\n          <!---->\n        </div>\n        <!---->\n      </div>\n      <!---->\n      <!---->\n      <div class=\"n-input__border\"></div>\n      <div class=\"n-input__state-border\"></div>\n      <!---->\n    </div>\n    <div>\n      <div class=\"n-date-picker\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-icon-color-override: rgba(194, 194, 194, 1); --n-icon-color-disabled-override: rgba(209, 209, 209, 1);\">\n        <div class=\"n-input n-input--medium-size n-input--resizable n-input--stateful\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-count-text-color: rgb(118, 124, 130); --n-count-text-color-disabled: rgba(194, 194, 194, 1); --n-color: rgba(255, 255, 255, 1); --n-font-size: 14px; --n-font-weight: 400; --n-border-radius: 3px; --n-height: 34px; --n-padding-left: 12px; --n-padding-right: 12px; --n-text-color: rgb(51, 54, 57); --n-caret-color: #18a058; --n-text-decoration-color: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-focus: 1px solid #36ad6a; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-icon-size: 16px; --n-line-height-textarea: 1.6; --n-color-disabled: rgb(250, 250, 252); --n-color-focus: rgba(255, 255, 255, 1); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-loading-color: #18a058; --n-caret-color-warning: #f0a020; --n-color-focus-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-loading-color-warning: #f0a020; --n-caret-color-error: #d03050; --n-color-focus-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-loading-color-error: #d03050; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-size: 16px; --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-icon-color-hover: rgba(146, 146, 146, 1); --n-icon-color-pressed: rgba(175, 175, 175, 1); --n-icon-color-disabled: rgba(209, 209, 209, 1); --n-suffix-text-color: rgb(51, 54, 57);\" tabindex=\"0\">\n          <div class=\"n-input-wrapper\">\n            <!---->\n            <div class=\"n-input__input\"><input type=\"text\" class=\"n-input__input-el\" tabindex=\"-1\" placeholder=\"Elekti daton\" size=\"20\" value=\"1970-01-01\">\n              <!---->\n              <!---->\n            </div>\n            <div class=\"n-input__suffix\">\n              <!---->\n              <!---->\n              <!----><i class=\"n-base-icon n-date-picker-icon\"><svg width=\"28px\" height=\"28px\" viewBox=\"0 0 28 28\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n                  <g stroke=\"none\" stroke-width=\"1\" fill-rule=\"evenodd\">\n                    <g fill-rule=\"nonzero\">\n                      <path d=\"M21.75,3 C23.5449254,3 25,4.45507456 25,6.25 L25,21.75 C25,23.5449254 23.5449254,25 21.75,25 L6.25,25 C4.45507456,25 3,23.5449254 3,21.75 L3,6.25 C3,4.45507456 4.45507456,3 6.25,3 L21.75,3 Z M23.5,9.503 L4.5,9.503 L4.5,21.75 C4.5,22.7164983 5.28350169,23.5 6.25,23.5 L21.75,23.5 C22.7164983,23.5 23.5,22.7164983 23.5,21.75 L23.5,9.503 Z M21.75,4.5 L6.25,4.5 C5.28350169,4.5 4.5,5.28350169 4.5,6.25 L4.5,8.003 L23.5,8.003 L23.5,6.25 C23.5,5.28350169 22.7164983,4.5 21.75,4.5 Z\"></path>\n                    </g>\n                  </g>\n                </svg></i>\n              <!---->\n              <!---->\n            </div>\n          </div>\n          <!---->\n          <!---->\n          <div class=\"n-input__border\"></div>\n          <div class=\"n-input__state-border\"></div>\n          <!---->\n        </div>\n        <!---->\n      </div>\n      <div class=\"n-date-picker\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-icon-color-override: rgba(194, 194, 194, 1); --n-icon-color-disabled-override: rgba(209, 209, 209, 1);\">\n        <div class=\"n-input n-input--medium-size n-input--resizable n-input--stateful\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-count-text-color: rgb(118, 124, 130); --n-count-text-color-disabled: rgba(194, 194, 194, 1); --n-color: rgba(255, 255, 255, 1); --n-font-size: 14px; --n-font-weight: 400; --n-border-radius: 3px; --n-height: 34px; --n-padding-left: 12px; --n-padding-right: 12px; --n-text-color: rgb(51, 54, 57); --n-caret-color: #18a058; --n-text-decoration-color: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-focus: 1px solid #36ad6a; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-icon-size: 16px; --n-line-height-textarea: 1.6; --n-color-disabled: rgb(250, 250, 252); --n-color-focus: rgba(255, 255, 255, 1); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-loading-color: #18a058; --n-caret-color-warning: #f0a020; --n-color-focus-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-loading-color-warning: #f0a020; --n-caret-color-error: #d03050; --n-color-focus-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-loading-color-error: #d03050; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-size: 16px; --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-icon-color-hover: rgba(146, 146, 146, 1); --n-icon-color-pressed: rgba(175, 175, 175, 1); --n-icon-color-disabled: rgba(209, 209, 209, 1); --n-suffix-text-color: rgb(51, 54, 57);\" tabindex=\"0\">\n          <div class=\"n-input-wrapper\">\n            <!---->\n            <div class=\"n-input__input\"><input type=\"text\" class=\"n-input__input-el\" tabindex=\"-1\" placeholder=\"Elekti daton kaj tempon\" size=\"20\" value=\"1970-01-01 08:00:00\">\n              <!---->\n              <!---->\n            </div>\n            <div class=\"n-input__suffix\">\n              <!---->\n              <!---->\n              <!----><i class=\"n-base-icon n-date-picker-icon\"><svg width=\"28px\" height=\"28px\" viewBox=\"0 0 28 28\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n                  <g stroke=\"none\" stroke-width=\"1\" fill-rule=\"evenodd\">\n                    <g fill-rule=\"nonzero\">\n                      <path d=\"M21.75,3 C23.5449254,3 25,4.45507456 25,6.25 L25,21.75 C25,23.5449254 23.5449254,25 21.75,25 L6.25,25 C4.45507456,25 3,23.5449254 3,21.75 L3,6.25 C3,4.45507456 4.45507456,3 6.25,3 L21.75,3 Z M23.5,9.503 L4.5,9.503 L4.5,21.75 C4.5,22.7164983 5.28350169,23.5 6.25,23.5 L21.75,23.5 C22.7164983,23.5 23.5,22.7164983 23.5,21.75 L23.5,9.503 Z M21.75,4.5 L6.25,4.5 C5.28350169,4.5 4.5,5.28350169 4.5,6.25 L4.5,8.003 L23.5,8.003 L23.5,6.25 C23.5,5.28350169 22.7164983,4.5 21.75,4.5 Z\"></path>\n                    </g>\n                  </g>\n                </svg></i>\n              <!---->\n              <!---->\n            </div>\n          </div>\n          <!---->\n          <!---->\n          <div class=\"n-input__border\"></div>\n          <div class=\"n-input__state-border\"></div>\n          <!---->\n        </div>\n        <!---->\n      </div>\n      <div class=\"n-date-picker\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-icon-color-override: rgba(194, 194, 194, 1); --n-icon-color-disabled-override: rgba(209, 209, 209, 1);\">\n        <div class=\"n-input n-input--medium-size n-input--resizable n-input--stateful\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-count-text-color: rgb(118, 124, 130); --n-count-text-color-disabled: rgba(194, 194, 194, 1); --n-color: rgba(255, 255, 255, 1); --n-font-size: 14px; --n-font-weight: 400; --n-border-radius: 3px; --n-height: 34px; --n-padding-left: 12px; --n-padding-right: 12px; --n-text-color: rgb(51, 54, 57); --n-caret-color: #18a058; --n-text-decoration-color: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-focus: 1px solid #36ad6a; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-icon-size: 16px; --n-line-height-textarea: 1.6; --n-color-disabled: rgb(250, 250, 252); --n-color-focus: rgba(255, 255, 255, 1); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-loading-color: #18a058; --n-caret-color-warning: #f0a020; --n-color-focus-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-loading-color-warning: #f0a020; --n-caret-color-error: #d03050; --n-color-focus-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-loading-color-error: #d03050; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-size: 16px; --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-icon-color-hover: rgba(146, 146, 146, 1); --n-icon-color-pressed: rgba(175, 175, 175, 1); --n-icon-color-disabled: rgba(209, 209, 209, 1); --n-suffix-text-color: rgb(51, 54, 57);\" tabindex=\"0\">\n          <div class=\"n-input-wrapper\">\n            <!---->\n            <div class=\"n-input__input\"><input type=\"text\" class=\"n-input__input-el\" tabindex=\"-1\" placeholder=\"Elekti jaron\" size=\"20\" value=\"1970\">\n              <!---->\n              <!---->\n            </div>\n            <div class=\"n-input__suffix\">\n              <!---->\n              <!---->\n              <!----><i class=\"n-base-icon n-date-picker-icon\"><svg width=\"28px\" height=\"28px\" viewBox=\"0 0 28 28\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n                  <g stroke=\"none\" stroke-width=\"1\" fill-rule=\"evenodd\">\n                    <g fill-rule=\"nonzero\">\n                      <path d=\"M21.75,3 C23.5449254,3 25,4.45507456 25,6.25 L25,21.75 C25,23.5449254 23.5449254,25 21.75,25 L6.25,25 C4.45507456,25 3,23.5449254 3,21.75 L3,6.25 C3,4.45507456 4.45507456,3 6.25,3 L21.75,3 Z M23.5,9.503 L4.5,9.503 L4.5,21.75 C4.5,22.7164983 5.28350169,23.5 6.25,23.5 L21.75,23.5 C22.7164983,23.5 23.5,22.7164983 23.5,21.75 L23.5,9.503 Z M21.75,4.5 L6.25,4.5 C5.28350169,4.5 4.5,5.28350169 4.5,6.25 L4.5,8.003 L23.5,8.003 L23.5,6.25 C23.5,5.28350169 22.7164983,4.5 21.75,4.5 Z\"></path>\n                    </g>\n                  </g>\n                </svg></i>\n              <!---->\n              <!---->\n            </div>\n          </div>\n          <!---->\n          <!---->\n          <div class=\"n-input__border\"></div>\n          <div class=\"n-input__state-border\"></div>\n          <!---->\n        </div>\n        <!---->\n      </div>\n      <div class=\"n-date-picker\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-icon-color-override: rgba(194, 194, 194, 1); --n-icon-color-disabled-override: rgba(209, 209, 209, 1);\">\n        <div class=\"n-input n-input--medium-size n-input--resizable n-input--stateful\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-count-text-color: rgb(118, 124, 130); --n-count-text-color-disabled: rgba(194, 194, 194, 1); --n-color: rgba(255, 255, 255, 1); --n-font-size: 14px; --n-font-weight: 400; --n-border-radius: 3px; --n-height: 34px; --n-padding-left: 12px; --n-padding-right: 12px; --n-text-color: rgb(51, 54, 57); --n-caret-color: #18a058; --n-text-decoration-color: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-focus: 1px solid #36ad6a; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-icon-size: 16px; --n-line-height-textarea: 1.6; --n-color-disabled: rgb(250, 250, 252); --n-color-focus: rgba(255, 255, 255, 1); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-loading-color: #18a058; --n-caret-color-warning: #f0a020; --n-color-focus-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-loading-color-warning: #f0a020; --n-caret-color-error: #d03050; --n-color-focus-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-loading-color-error: #d03050; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-size: 16px; --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-icon-color-hover: rgba(146, 146, 146, 1); --n-icon-color-pressed: rgba(175, 175, 175, 1); --n-icon-color-disabled: rgba(209, 209, 209, 1); --n-suffix-text-color: rgb(51, 54, 57);\" tabindex=\"0\">\n          <div class=\"n-input-wrapper\">\n            <!---->\n            <div class=\"n-input__input\"><input type=\"text\" class=\"n-input__input-el\" tabindex=\"-1\" placeholder=\"Elekti monaton\" size=\"20\" value=\"1970-01\">\n              <!---->\n              <!---->\n            </div>\n            <div class=\"n-input__suffix\">\n              <!---->\n              <!---->\n              <!----><i class=\"n-base-icon n-date-picker-icon\"><svg width=\"28px\" height=\"28px\" viewBox=\"0 0 28 28\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n                  <g stroke=\"none\" stroke-width=\"1\" fill-rule=\"evenodd\">\n                    <g fill-rule=\"nonzero\">\n                      <path d=\"M21.75,3 C23.5449254,3 25,4.45507456 25,6.25 L25,21.75 C25,23.5449254 23.5449254,25 21.75,25 L6.25,25 C4.45507456,25 3,23.5449254 3,21.75 L3,6.25 C3,4.45507456 4.45507456,3 6.25,3 L21.75,3 Z M23.5,9.503 L4.5,9.503 L4.5,21.75 C4.5,22.7164983 5.28350169,23.5 6.25,23.5 L21.75,23.5 C22.7164983,23.5 23.5,22.7164983 23.5,21.75 L23.5,9.503 Z M21.75,4.5 L6.25,4.5 C5.28350169,4.5 4.5,5.28350169 4.5,6.25 L4.5,8.003 L23.5,8.003 L23.5,6.25 C23.5,5.28350169 22.7164983,4.5 21.75,4.5 Z\"></path>\n                    </g>\n                  </g>\n                </svg></i>\n              <!---->\n              <!---->\n            </div>\n          </div>\n          <!---->\n          <!---->\n          <div class=\"n-input__border\"></div>\n          <div class=\"n-input__state-border\"></div>\n          <!---->\n        </div>\n        <!---->\n      </div>\n    </div>\n  </div>\n</div>\"\n`;\n\nexports[`locale > works 23`] = `\n\"<div class=\"n-config-provider\">\n  <div>\n    <div class=\"n-input n-input--medium-size n-input--resizable n-input--stateful\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-count-text-color: rgb(118, 124, 130); --n-count-text-color-disabled: rgba(194, 194, 194, 1); --n-color: rgba(255, 255, 255, 1); --n-font-size: 14px; --n-font-weight: 400; --n-border-radius: 3px; --n-height: 34px; --n-padding-left: 12px; --n-padding-right: 12px; --n-text-color: rgb(51, 54, 57); --n-caret-color: #18a058; --n-text-decoration-color: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-focus: 1px solid #36ad6a; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-icon-size: 16px; --n-line-height-textarea: 1.6; --n-color-disabled: rgb(250, 250, 252); --n-color-focus: rgba(255, 255, 255, 1); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-loading-color: #18a058; --n-caret-color-warning: #f0a020; --n-color-focus-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-loading-color-warning: #f0a020; --n-caret-color-error: #d03050; --n-color-focus-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-loading-color-error: #d03050; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-size: 16px; --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-icon-color-hover: rgba(146, 146, 146, 1); --n-icon-color-pressed: rgba(175, 175, 175, 1); --n-icon-color-disabled: rgba(209, 209, 209, 1); --n-suffix-text-color: rgb(51, 54, 57);\">\n      <div class=\"n-input-wrapper\">\n        <!---->\n        <div class=\"n-input__input\"><input type=\"text\" class=\"n-input__input-el\" placeholder=\"Invoeren a.u.b.\" size=\"20\">\n          <div class=\"n-input__placeholder\"><span>Invoeren a.u.b.</span></div>\n          <!---->\n        </div>\n        <!---->\n      </div>\n      <!---->\n      <!---->\n      <div class=\"n-input__border\"></div>\n      <div class=\"n-input__state-border\"></div>\n      <!---->\n    </div>\n    <div>\n      <div class=\"n-date-picker\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-icon-color-override: rgba(194, 194, 194, 1); --n-icon-color-disabled-override: rgba(209, 209, 209, 1);\">\n        <div class=\"n-input n-input--medium-size n-input--resizable n-input--stateful\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-count-text-color: rgb(118, 124, 130); --n-count-text-color-disabled: rgba(194, 194, 194, 1); --n-color: rgba(255, 255, 255, 1); --n-font-size: 14px; --n-font-weight: 400; --n-border-radius: 3px; --n-height: 34px; --n-padding-left: 12px; --n-padding-right: 12px; --n-text-color: rgb(51, 54, 57); --n-caret-color: #18a058; --n-text-decoration-color: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-focus: 1px solid #36ad6a; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-icon-size: 16px; --n-line-height-textarea: 1.6; --n-color-disabled: rgb(250, 250, 252); --n-color-focus: rgba(255, 255, 255, 1); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-loading-color: #18a058; --n-caret-color-warning: #f0a020; --n-color-focus-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-loading-color-warning: #f0a020; --n-caret-color-error: #d03050; --n-color-focus-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-loading-color-error: #d03050; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-size: 16px; --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-icon-color-hover: rgba(146, 146, 146, 1); --n-icon-color-pressed: rgba(175, 175, 175, 1); --n-icon-color-disabled: rgba(209, 209, 209, 1); --n-suffix-text-color: rgb(51, 54, 57);\" tabindex=\"0\">\n          <div class=\"n-input-wrapper\">\n            <!---->\n            <div class=\"n-input__input\"><input type=\"text\" class=\"n-input__input-el\" tabindex=\"-1\" placeholder=\"Selecteer Datum\" size=\"20\" value=\"01/01/1970\">\n              <!---->\n              <!---->\n            </div>\n            <div class=\"n-input__suffix\">\n              <!---->\n              <!---->\n              <!----><i class=\"n-base-icon n-date-picker-icon\"><svg width=\"28px\" height=\"28px\" viewBox=\"0 0 28 28\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n                  <g stroke=\"none\" stroke-width=\"1\" fill-rule=\"evenodd\">\n                    <g fill-rule=\"nonzero\">\n                      <path d=\"M21.75,3 C23.5449254,3 25,4.45507456 25,6.25 L25,21.75 C25,23.5449254 23.5449254,25 21.75,25 L6.25,25 C4.45507456,25 3,23.5449254 3,21.75 L3,6.25 C3,4.45507456 4.45507456,3 6.25,3 L21.75,3 Z M23.5,9.503 L4.5,9.503 L4.5,21.75 C4.5,22.7164983 5.28350169,23.5 6.25,23.5 L21.75,23.5 C22.7164983,23.5 23.5,22.7164983 23.5,21.75 L23.5,9.503 Z M21.75,4.5 L6.25,4.5 C5.28350169,4.5 4.5,5.28350169 4.5,6.25 L4.5,8.003 L23.5,8.003 L23.5,6.25 C23.5,5.28350169 22.7164983,4.5 21.75,4.5 Z\"></path>\n                    </g>\n                  </g>\n                </svg></i>\n              <!---->\n              <!---->\n            </div>\n          </div>\n          <!---->\n          <!---->\n          <div class=\"n-input__border\"></div>\n          <div class=\"n-input__state-border\"></div>\n          <!---->\n        </div>\n        <!---->\n      </div>\n      <div class=\"n-date-picker\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-icon-color-override: rgba(194, 194, 194, 1); --n-icon-color-disabled-override: rgba(209, 209, 209, 1);\">\n        <div class=\"n-input n-input--medium-size n-input--resizable n-input--stateful\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-count-text-color: rgb(118, 124, 130); --n-count-text-color-disabled: rgba(194, 194, 194, 1); --n-color: rgba(255, 255, 255, 1); --n-font-size: 14px; --n-font-weight: 400; --n-border-radius: 3px; --n-height: 34px; --n-padding-left: 12px; --n-padding-right: 12px; --n-text-color: rgb(51, 54, 57); --n-caret-color: #18a058; --n-text-decoration-color: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-focus: 1px solid #36ad6a; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-icon-size: 16px; --n-line-height-textarea: 1.6; --n-color-disabled: rgb(250, 250, 252); --n-color-focus: rgba(255, 255, 255, 1); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-loading-color: #18a058; --n-caret-color-warning: #f0a020; --n-color-focus-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-loading-color-warning: #f0a020; --n-caret-color-error: #d03050; --n-color-focus-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-loading-color-error: #d03050; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-size: 16px; --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-icon-color-hover: rgba(146, 146, 146, 1); --n-icon-color-pressed: rgba(175, 175, 175, 1); --n-icon-color-disabled: rgba(209, 209, 209, 1); --n-suffix-text-color: rgb(51, 54, 57);\" tabindex=\"0\">\n          <div class=\"n-input-wrapper\">\n            <!---->\n            <div class=\"n-input__input\"><input type=\"text\" class=\"n-input__input-el\" tabindex=\"-1\" placeholder=\"Selecteer Dag en Uur\" size=\"20\" value=\"01/01/1970 08:00:00\">\n              <!---->\n              <!---->\n            </div>\n            <div class=\"n-input__suffix\">\n              <!---->\n              <!---->\n              <!----><i class=\"n-base-icon n-date-picker-icon\"><svg width=\"28px\" height=\"28px\" viewBox=\"0 0 28 28\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n                  <g stroke=\"none\" stroke-width=\"1\" fill-rule=\"evenodd\">\n                    <g fill-rule=\"nonzero\">\n                      <path d=\"M21.75,3 C23.5449254,3 25,4.45507456 25,6.25 L25,21.75 C25,23.5449254 23.5449254,25 21.75,25 L6.25,25 C4.45507456,25 3,23.5449254 3,21.75 L3,6.25 C3,4.45507456 4.45507456,3 6.25,3 L21.75,3 Z M23.5,9.503 L4.5,9.503 L4.5,21.75 C4.5,22.7164983 5.28350169,23.5 6.25,23.5 L21.75,23.5 C22.7164983,23.5 23.5,22.7164983 23.5,21.75 L23.5,9.503 Z M21.75,4.5 L6.25,4.5 C5.28350169,4.5 4.5,5.28350169 4.5,6.25 L4.5,8.003 L23.5,8.003 L23.5,6.25 C23.5,5.28350169 22.7164983,4.5 21.75,4.5 Z\"></path>\n                    </g>\n                  </g>\n                </svg></i>\n              <!---->\n              <!---->\n            </div>\n          </div>\n          <!---->\n          <!---->\n          <div class=\"n-input__border\"></div>\n          <div class=\"n-input__state-border\"></div>\n          <!---->\n        </div>\n        <!---->\n      </div>\n      <div class=\"n-date-picker\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-icon-color-override: rgba(194, 194, 194, 1); --n-icon-color-disabled-override: rgba(209, 209, 209, 1);\">\n        <div class=\"n-input n-input--medium-size n-input--resizable n-input--stateful\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-count-text-color: rgb(118, 124, 130); --n-count-text-color-disabled: rgba(194, 194, 194, 1); --n-color: rgba(255, 255, 255, 1); --n-font-size: 14px; --n-font-weight: 400; --n-border-radius: 3px; --n-height: 34px; --n-padding-left: 12px; --n-padding-right: 12px; --n-text-color: rgb(51, 54, 57); --n-caret-color: #18a058; --n-text-decoration-color: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-focus: 1px solid #36ad6a; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-icon-size: 16px; --n-line-height-textarea: 1.6; --n-color-disabled: rgb(250, 250, 252); --n-color-focus: rgba(255, 255, 255, 1); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-loading-color: #18a058; --n-caret-color-warning: #f0a020; --n-color-focus-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-loading-color-warning: #f0a020; --n-caret-color-error: #d03050; --n-color-focus-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-loading-color-error: #d03050; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-size: 16px; --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-icon-color-hover: rgba(146, 146, 146, 1); --n-icon-color-pressed: rgba(175, 175, 175, 1); --n-icon-color-disabled: rgba(209, 209, 209, 1); --n-suffix-text-color: rgb(51, 54, 57);\" tabindex=\"0\">\n          <div class=\"n-input-wrapper\">\n            <!---->\n            <div class=\"n-input__input\"><input type=\"text\" class=\"n-input__input-el\" tabindex=\"-1\" placeholder=\"Selecteer Jaar\" size=\"20\" value=\"1970\">\n              <!---->\n              <!---->\n            </div>\n            <div class=\"n-input__suffix\">\n              <!---->\n              <!---->\n              <!----><i class=\"n-base-icon n-date-picker-icon\"><svg width=\"28px\" height=\"28px\" viewBox=\"0 0 28 28\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n                  <g stroke=\"none\" stroke-width=\"1\" fill-rule=\"evenodd\">\n                    <g fill-rule=\"nonzero\">\n                      <path d=\"M21.75,3 C23.5449254,3 25,4.45507456 25,6.25 L25,21.75 C25,23.5449254 23.5449254,25 21.75,25 L6.25,25 C4.45507456,25 3,23.5449254 3,21.75 L3,6.25 C3,4.45507456 4.45507456,3 6.25,3 L21.75,3 Z M23.5,9.503 L4.5,9.503 L4.5,21.75 C4.5,22.7164983 5.28350169,23.5 6.25,23.5 L21.75,23.5 C22.7164983,23.5 23.5,22.7164983 23.5,21.75 L23.5,9.503 Z M21.75,4.5 L6.25,4.5 C5.28350169,4.5 4.5,5.28350169 4.5,6.25 L4.5,8.003 L23.5,8.003 L23.5,6.25 C23.5,5.28350169 22.7164983,4.5 21.75,4.5 Z\"></path>\n                    </g>\n                  </g>\n                </svg></i>\n              <!---->\n              <!---->\n            </div>\n          </div>\n          <!---->\n          <!---->\n          <div class=\"n-input__border\"></div>\n          <div class=\"n-input__state-border\"></div>\n          <!---->\n        </div>\n        <!---->\n      </div>\n      <div class=\"n-date-picker\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-icon-color-override: rgba(194, 194, 194, 1); --n-icon-color-disabled-override: rgba(209, 209, 209, 1);\">\n        <div class=\"n-input n-input--medium-size n-input--resizable n-input--stateful\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-count-text-color: rgb(118, 124, 130); --n-count-text-color-disabled: rgba(194, 194, 194, 1); --n-color: rgba(255, 255, 255, 1); --n-font-size: 14px; --n-font-weight: 400; --n-border-radius: 3px; --n-height: 34px; --n-padding-left: 12px; --n-padding-right: 12px; --n-text-color: rgb(51, 54, 57); --n-caret-color: #18a058; --n-text-decoration-color: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-focus: 1px solid #36ad6a; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-icon-size: 16px; --n-line-height-textarea: 1.6; --n-color-disabled: rgb(250, 250, 252); --n-color-focus: rgba(255, 255, 255, 1); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-loading-color: #18a058; --n-caret-color-warning: #f0a020; --n-color-focus-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-loading-color-warning: #f0a020; --n-caret-color-error: #d03050; --n-color-focus-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-loading-color-error: #d03050; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-size: 16px; --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-icon-color-hover: rgba(146, 146, 146, 1); --n-icon-color-pressed: rgba(175, 175, 175, 1); --n-icon-color-disabled: rgba(209, 209, 209, 1); --n-suffix-text-color: rgb(51, 54, 57);\" tabindex=\"0\">\n          <div class=\"n-input-wrapper\">\n            <!---->\n            <div class=\"n-input__input\"><input type=\"text\" class=\"n-input__input-el\" tabindex=\"-1\" placeholder=\"Selecteer Maand\" size=\"20\" value=\"01/1970\">\n              <!---->\n              <!---->\n            </div>\n            <div class=\"n-input__suffix\">\n              <!---->\n              <!---->\n              <!----><i class=\"n-base-icon n-date-picker-icon\"><svg width=\"28px\" height=\"28px\" viewBox=\"0 0 28 28\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n                  <g stroke=\"none\" stroke-width=\"1\" fill-rule=\"evenodd\">\n                    <g fill-rule=\"nonzero\">\n                      <path d=\"M21.75,3 C23.5449254,3 25,4.45507456 25,6.25 L25,21.75 C25,23.5449254 23.5449254,25 21.75,25 L6.25,25 C4.45507456,25 3,23.5449254 3,21.75 L3,6.25 C3,4.45507456 4.45507456,3 6.25,3 L21.75,3 Z M23.5,9.503 L4.5,9.503 L4.5,21.75 C4.5,22.7164983 5.28350169,23.5 6.25,23.5 L21.75,23.5 C22.7164983,23.5 23.5,22.7164983 23.5,21.75 L23.5,9.503 Z M21.75,4.5 L6.25,4.5 C5.28350169,4.5 4.5,5.28350169 4.5,6.25 L4.5,8.003 L23.5,8.003 L23.5,6.25 C23.5,5.28350169 22.7164983,4.5 21.75,4.5 Z\"></path>\n                    </g>\n                  </g>\n                </svg></i>\n              <!---->\n              <!---->\n            </div>\n          </div>\n          <!---->\n          <!---->\n          <div class=\"n-input__border\"></div>\n          <div class=\"n-input__state-border\"></div>\n          <!---->\n        </div>\n        <!---->\n      </div>\n    </div>\n  </div>\n</div>\"\n`;\n\nexports[`locale > works 24`] = `\n\"<div class=\"n-config-provider\">\n  <div>\n    <div class=\"n-input n-input--medium-size n-input--resizable n-input--stateful\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-count-text-color: rgb(118, 124, 130); --n-count-text-color-disabled: rgba(194, 194, 194, 1); --n-color: rgba(255, 255, 255, 1); --n-font-size: 14px; --n-font-weight: 400; --n-border-radius: 3px; --n-height: 34px; --n-padding-left: 12px; --n-padding-right: 12px; --n-text-color: rgb(51, 54, 57); --n-caret-color: #18a058; --n-text-decoration-color: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-focus: 1px solid #36ad6a; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-icon-size: 16px; --n-line-height-textarea: 1.6; --n-color-disabled: rgb(250, 250, 252); --n-color-focus: rgba(255, 255, 255, 1); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-loading-color: #18a058; --n-caret-color-warning: #f0a020; --n-color-focus-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-loading-color-warning: #f0a020; --n-caret-color-error: #d03050; --n-color-focus-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-loading-color-error: #d03050; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-size: 16px; --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-icon-color-hover: rgba(146, 146, 146, 1); --n-icon-color-pressed: rgba(175, 175, 175, 1); --n-icon-color-disabled: rgba(209, 209, 209, 1); --n-suffix-text-color: rgb(51, 54, 57);\">\n      <div class=\"n-input-wrapper\">\n        <!---->\n        <div class=\"n-input__input\"><input type=\"text\" class=\"n-input__input-el\" placeholder=\"يرجى الإدخال\" size=\"20\">\n          <div class=\"n-input__placeholder\"><span>يرجى الإدخال</span></div>\n          <!---->\n        </div>\n        <!---->\n      </div>\n      <!---->\n      <!---->\n      <div class=\"n-input__border\"></div>\n      <div class=\"n-input__state-border\"></div>\n      <!---->\n    </div>\n    <div>\n      <div class=\"n-date-picker\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-icon-color-override: rgba(194, 194, 194, 1); --n-icon-color-disabled-override: rgba(209, 209, 209, 1);\">\n        <div class=\"n-input n-input--medium-size n-input--resizable n-input--stateful\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-count-text-color: rgb(118, 124, 130); --n-count-text-color-disabled: rgba(194, 194, 194, 1); --n-color: rgba(255, 255, 255, 1); --n-font-size: 14px; --n-font-weight: 400; --n-border-radius: 3px; --n-height: 34px; --n-padding-left: 12px; --n-padding-right: 12px; --n-text-color: rgb(51, 54, 57); --n-caret-color: #18a058; --n-text-decoration-color: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-focus: 1px solid #36ad6a; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-icon-size: 16px; --n-line-height-textarea: 1.6; --n-color-disabled: rgb(250, 250, 252); --n-color-focus: rgba(255, 255, 255, 1); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-loading-color: #18a058; --n-caret-color-warning: #f0a020; --n-color-focus-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-loading-color-warning: #f0a020; --n-caret-color-error: #d03050; --n-color-focus-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-loading-color-error: #d03050; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-size: 16px; --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-icon-color-hover: rgba(146, 146, 146, 1); --n-icon-color-pressed: rgba(175, 175, 175, 1); --n-icon-color-disabled: rgba(209, 209, 209, 1); --n-suffix-text-color: rgb(51, 54, 57);\" tabindex=\"0\">\n          <div class=\"n-input-wrapper\">\n            <!---->\n            <div class=\"n-input__input\"><input type=\"text\" class=\"n-input__input-el\" tabindex=\"-1\" placeholder=\"إختيار التاريخ\" size=\"20\" value=\"1970-01-01\">\n              <!---->\n              <!---->\n            </div>\n            <div class=\"n-input__suffix\">\n              <!---->\n              <!---->\n              <!----><i class=\"n-base-icon n-date-picker-icon\"><svg width=\"28px\" height=\"28px\" viewBox=\"0 0 28 28\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n                  <g stroke=\"none\" stroke-width=\"1\" fill-rule=\"evenodd\">\n                    <g fill-rule=\"nonzero\">\n                      <path d=\"M21.75,3 C23.5449254,3 25,4.45507456 25,6.25 L25,21.75 C25,23.5449254 23.5449254,25 21.75,25 L6.25,25 C4.45507456,25 3,23.5449254 3,21.75 L3,6.25 C3,4.45507456 4.45507456,3 6.25,3 L21.75,3 Z M23.5,9.503 L4.5,9.503 L4.5,21.75 C4.5,22.7164983 5.28350169,23.5 6.25,23.5 L21.75,23.5 C22.7164983,23.5 23.5,22.7164983 23.5,21.75 L23.5,9.503 Z M21.75,4.5 L6.25,4.5 C5.28350169,4.5 4.5,5.28350169 4.5,6.25 L4.5,8.003 L23.5,8.003 L23.5,6.25 C23.5,5.28350169 22.7164983,4.5 21.75,4.5 Z\"></path>\n                    </g>\n                  </g>\n                </svg></i>\n              <!---->\n              <!---->\n            </div>\n          </div>\n          <!---->\n          <!---->\n          <div class=\"n-input__border\"></div>\n          <div class=\"n-input__state-border\"></div>\n          <!---->\n        </div>\n        <!---->\n      </div>\n      <div class=\"n-date-picker\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-icon-color-override: rgba(194, 194, 194, 1); --n-icon-color-disabled-override: rgba(209, 209, 209, 1);\">\n        <div class=\"n-input n-input--medium-size n-input--resizable n-input--stateful\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-count-text-color: rgb(118, 124, 130); --n-count-text-color-disabled: rgba(194, 194, 194, 1); --n-color: rgba(255, 255, 255, 1); --n-font-size: 14px; --n-font-weight: 400; --n-border-radius: 3px; --n-height: 34px; --n-padding-left: 12px; --n-padding-right: 12px; --n-text-color: rgb(51, 54, 57); --n-caret-color: #18a058; --n-text-decoration-color: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-focus: 1px solid #36ad6a; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-icon-size: 16px; --n-line-height-textarea: 1.6; --n-color-disabled: rgb(250, 250, 252); --n-color-focus: rgba(255, 255, 255, 1); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-loading-color: #18a058; --n-caret-color-warning: #f0a020; --n-color-focus-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-loading-color-warning: #f0a020; --n-caret-color-error: #d03050; --n-color-focus-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-loading-color-error: #d03050; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-size: 16px; --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-icon-color-hover: rgba(146, 146, 146, 1); --n-icon-color-pressed: rgba(175, 175, 175, 1); --n-icon-color-disabled: rgba(209, 209, 209, 1); --n-suffix-text-color: rgb(51, 54, 57);\" tabindex=\"0\">\n          <div class=\"n-input-wrapper\">\n            <!---->\n            <div class=\"n-input__input\"><input type=\"text\" class=\"n-input__input-el\" tabindex=\"-1\" placeholder=\"إختيار التاريخ والوقت\" size=\"20\" value=\"1970-01-01 08:00:00\">\n              <!---->\n              <!---->\n            </div>\n            <div class=\"n-input__suffix\">\n              <!---->\n              <!---->\n              <!----><i class=\"n-base-icon n-date-picker-icon\"><svg width=\"28px\" height=\"28px\" viewBox=\"0 0 28 28\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n                  <g stroke=\"none\" stroke-width=\"1\" fill-rule=\"evenodd\">\n                    <g fill-rule=\"nonzero\">\n                      <path d=\"M21.75,3 C23.5449254,3 25,4.45507456 25,6.25 L25,21.75 C25,23.5449254 23.5449254,25 21.75,25 L6.25,25 C4.45507456,25 3,23.5449254 3,21.75 L3,6.25 C3,4.45507456 4.45507456,3 6.25,3 L21.75,3 Z M23.5,9.503 L4.5,9.503 L4.5,21.75 C4.5,22.7164983 5.28350169,23.5 6.25,23.5 L21.75,23.5 C22.7164983,23.5 23.5,22.7164983 23.5,21.75 L23.5,9.503 Z M21.75,4.5 L6.25,4.5 C5.28350169,4.5 4.5,5.28350169 4.5,6.25 L4.5,8.003 L23.5,8.003 L23.5,6.25 C23.5,5.28350169 22.7164983,4.5 21.75,4.5 Z\"></path>\n                    </g>\n                  </g>\n                </svg></i>\n              <!---->\n              <!---->\n            </div>\n          </div>\n          <!---->\n          <!---->\n          <div class=\"n-input__border\"></div>\n          <div class=\"n-input__state-border\"></div>\n          <!---->\n        </div>\n        <!---->\n      </div>\n      <div class=\"n-date-picker\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-icon-color-override: rgba(194, 194, 194, 1); --n-icon-color-disabled-override: rgba(209, 209, 209, 1);\">\n        <div class=\"n-input n-input--medium-size n-input--resizable n-input--stateful\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-count-text-color: rgb(118, 124, 130); --n-count-text-color-disabled: rgba(194, 194, 194, 1); --n-color: rgba(255, 255, 255, 1); --n-font-size: 14px; --n-font-weight: 400; --n-border-radius: 3px; --n-height: 34px; --n-padding-left: 12px; --n-padding-right: 12px; --n-text-color: rgb(51, 54, 57); --n-caret-color: #18a058; --n-text-decoration-color: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-focus: 1px solid #36ad6a; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-icon-size: 16px; --n-line-height-textarea: 1.6; --n-color-disabled: rgb(250, 250, 252); --n-color-focus: rgba(255, 255, 255, 1); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-loading-color: #18a058; --n-caret-color-warning: #f0a020; --n-color-focus-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-loading-color-warning: #f0a020; --n-caret-color-error: #d03050; --n-color-focus-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-loading-color-error: #d03050; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-size: 16px; --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-icon-color-hover: rgba(146, 146, 146, 1); --n-icon-color-pressed: rgba(175, 175, 175, 1); --n-icon-color-disabled: rgba(209, 209, 209, 1); --n-suffix-text-color: rgb(51, 54, 57);\" tabindex=\"0\">\n          <div class=\"n-input-wrapper\">\n            <!---->\n            <div class=\"n-input__input\"><input type=\"text\" class=\"n-input__input-el\" tabindex=\"-1\" placeholder=\"إختيار السنة\" size=\"20\" value=\"1970\">\n              <!---->\n              <!---->\n            </div>\n            <div class=\"n-input__suffix\">\n              <!---->\n              <!---->\n              <!----><i class=\"n-base-icon n-date-picker-icon\"><svg width=\"28px\" height=\"28px\" viewBox=\"0 0 28 28\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n                  <g stroke=\"none\" stroke-width=\"1\" fill-rule=\"evenodd\">\n                    <g fill-rule=\"nonzero\">\n                      <path d=\"M21.75,3 C23.5449254,3 25,4.45507456 25,6.25 L25,21.75 C25,23.5449254 23.5449254,25 21.75,25 L6.25,25 C4.45507456,25 3,23.5449254 3,21.75 L3,6.25 C3,4.45507456 4.45507456,3 6.25,3 L21.75,3 Z M23.5,9.503 L4.5,9.503 L4.5,21.75 C4.5,22.7164983 5.28350169,23.5 6.25,23.5 L21.75,23.5 C22.7164983,23.5 23.5,22.7164983 23.5,21.75 L23.5,9.503 Z M21.75,4.5 L6.25,4.5 C5.28350169,4.5 4.5,5.28350169 4.5,6.25 L4.5,8.003 L23.5,8.003 L23.5,6.25 C23.5,5.28350169 22.7164983,4.5 21.75,4.5 Z\"></path>\n                    </g>\n                  </g>\n                </svg></i>\n              <!---->\n              <!---->\n            </div>\n          </div>\n          <!---->\n          <!---->\n          <div class=\"n-input__border\"></div>\n          <div class=\"n-input__state-border\"></div>\n          <!---->\n        </div>\n        <!---->\n      </div>\n      <div class=\"n-date-picker\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-icon-color-override: rgba(194, 194, 194, 1); --n-icon-color-disabled-override: rgba(209, 209, 209, 1);\">\n        <div class=\"n-input n-input--medium-size n-input--resizable n-input--stateful\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-count-text-color: rgb(118, 124, 130); --n-count-text-color-disabled: rgba(194, 194, 194, 1); --n-color: rgba(255, 255, 255, 1); --n-font-size: 14px; --n-font-weight: 400; --n-border-radius: 3px; --n-height: 34px; --n-padding-left: 12px; --n-padding-right: 12px; --n-text-color: rgb(51, 54, 57); --n-caret-color: #18a058; --n-text-decoration-color: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-focus: 1px solid #36ad6a; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-icon-size: 16px; --n-line-height-textarea: 1.6; --n-color-disabled: rgb(250, 250, 252); --n-color-focus: rgba(255, 255, 255, 1); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-loading-color: #18a058; --n-caret-color-warning: #f0a020; --n-color-focus-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-loading-color-warning: #f0a020; --n-caret-color-error: #d03050; --n-color-focus-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-loading-color-error: #d03050; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-size: 16px; --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-icon-color-hover: rgba(146, 146, 146, 1); --n-icon-color-pressed: rgba(175, 175, 175, 1); --n-icon-color-disabled: rgba(209, 209, 209, 1); --n-suffix-text-color: rgb(51, 54, 57);\" tabindex=\"0\">\n          <div class=\"n-input-wrapper\">\n            <!---->\n            <div class=\"n-input__input\"><input type=\"text\" class=\"n-input__input-el\" tabindex=\"-1\" placeholder=\"إختيار الشهر\" size=\"20\" value=\"1970-01\">\n              <!---->\n              <!---->\n            </div>\n            <div class=\"n-input__suffix\">\n              <!---->\n              <!---->\n              <!----><i class=\"n-base-icon n-date-picker-icon\"><svg width=\"28px\" height=\"28px\" viewBox=\"0 0 28 28\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n                  <g stroke=\"none\" stroke-width=\"1\" fill-rule=\"evenodd\">\n                    <g fill-rule=\"nonzero\">\n                      <path d=\"M21.75,3 C23.5449254,3 25,4.45507456 25,6.25 L25,21.75 C25,23.5449254 23.5449254,25 21.75,25 L6.25,25 C4.45507456,25 3,23.5449254 3,21.75 L3,6.25 C3,4.45507456 4.45507456,3 6.25,3 L21.75,3 Z M23.5,9.503 L4.5,9.503 L4.5,21.75 C4.5,22.7164983 5.28350169,23.5 6.25,23.5 L21.75,23.5 C22.7164983,23.5 23.5,22.7164983 23.5,21.75 L23.5,9.503 Z M21.75,4.5 L6.25,4.5 C5.28350169,4.5 4.5,5.28350169 4.5,6.25 L4.5,8.003 L23.5,8.003 L23.5,6.25 C23.5,5.28350169 22.7164983,4.5 21.75,4.5 Z\"></path>\n                    </g>\n                  </g>\n                </svg></i>\n              <!---->\n              <!---->\n            </div>\n          </div>\n          <!---->\n          <!---->\n          <div class=\"n-input__border\"></div>\n          <div class=\"n-input__state-border\"></div>\n          <!---->\n        </div>\n        <!---->\n      </div>\n    </div>\n  </div>\n</div>\"\n`;\n\nexports[`locale > works 25`] = `\n\"<div class=\"n-config-provider\">\n  <div>\n    <div class=\"n-input n-input--medium-size n-input--resizable n-input--stateful\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-count-text-color: rgb(118, 124, 130); --n-count-text-color-disabled: rgba(194, 194, 194, 1); --n-color: rgba(255, 255, 255, 1); --n-font-size: 14px; --n-font-weight: 400; --n-border-radius: 3px; --n-height: 34px; --n-padding-left: 12px; --n-padding-right: 12px; --n-text-color: rgb(51, 54, 57); --n-caret-color: #18a058; --n-text-decoration-color: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-focus: 1px solid #36ad6a; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-icon-size: 16px; --n-line-height-textarea: 1.6; --n-color-disabled: rgb(250, 250, 252); --n-color-focus: rgba(255, 255, 255, 1); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-loading-color: #18a058; --n-caret-color-warning: #f0a020; --n-color-focus-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-loading-color-warning: #f0a020; --n-caret-color-error: #d03050; --n-color-focus-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-loading-color-error: #d03050; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-size: 16px; --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-icon-color-hover: rgba(146, 146, 146, 1); --n-icon-color-pressed: rgba(175, 175, 175, 1); --n-icon-color-disabled: rgba(209, 209, 209, 1); --n-suffix-text-color: rgb(51, 54, 57);\">\n      <div class=\"n-input-wrapper\">\n        <!---->\n        <div class=\"n-input__input\"><input type=\"text\" class=\"n-input__input-el\" placeholder=\"Lütfen Girin\" size=\"20\">\n          <div class=\"n-input__placeholder\"><span>Lütfen Girin</span></div>\n          <!---->\n        </div>\n        <!---->\n      </div>\n      <!---->\n      <!---->\n      <div class=\"n-input__border\"></div>\n      <div class=\"n-input__state-border\"></div>\n      <!---->\n    </div>\n    <div>\n      <div class=\"n-date-picker\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-icon-color-override: rgba(194, 194, 194, 1); --n-icon-color-disabled-override: rgba(209, 209, 209, 1);\">\n        <div class=\"n-input n-input--medium-size n-input--resizable n-input--stateful\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-count-text-color: rgb(118, 124, 130); --n-count-text-color-disabled: rgba(194, 194, 194, 1); --n-color: rgba(255, 255, 255, 1); --n-font-size: 14px; --n-font-weight: 400; --n-border-radius: 3px; --n-height: 34px; --n-padding-left: 12px; --n-padding-right: 12px; --n-text-color: rgb(51, 54, 57); --n-caret-color: #18a058; --n-text-decoration-color: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-focus: 1px solid #36ad6a; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-icon-size: 16px; --n-line-height-textarea: 1.6; --n-color-disabled: rgb(250, 250, 252); --n-color-focus: rgba(255, 255, 255, 1); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-loading-color: #18a058; --n-caret-color-warning: #f0a020; --n-color-focus-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-loading-color-warning: #f0a020; --n-caret-color-error: #d03050; --n-color-focus-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-loading-color-error: #d03050; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-size: 16px; --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-icon-color-hover: rgba(146, 146, 146, 1); --n-icon-color-pressed: rgba(175, 175, 175, 1); --n-icon-color-disabled: rgba(209, 209, 209, 1); --n-suffix-text-color: rgb(51, 54, 57);\" tabindex=\"0\">\n          <div class=\"n-input-wrapper\">\n            <!---->\n            <div class=\"n-input__input\"><input type=\"text\" class=\"n-input__input-el\" tabindex=\"-1\" placeholder=\"Tarih Seç\" size=\"20\" value=\"1970-01-01\">\n              <!---->\n              <!---->\n            </div>\n            <div class=\"n-input__suffix\">\n              <!---->\n              <!---->\n              <!----><i class=\"n-base-icon n-date-picker-icon\"><svg width=\"28px\" height=\"28px\" viewBox=\"0 0 28 28\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n                  <g stroke=\"none\" stroke-width=\"1\" fill-rule=\"evenodd\">\n                    <g fill-rule=\"nonzero\">\n                      <path d=\"M21.75,3 C23.5449254,3 25,4.45507456 25,6.25 L25,21.75 C25,23.5449254 23.5449254,25 21.75,25 L6.25,25 C4.45507456,25 3,23.5449254 3,21.75 L3,6.25 C3,4.45507456 4.45507456,3 6.25,3 L21.75,3 Z M23.5,9.503 L4.5,9.503 L4.5,21.75 C4.5,22.7164983 5.28350169,23.5 6.25,23.5 L21.75,23.5 C22.7164983,23.5 23.5,22.7164983 23.5,21.75 L23.5,9.503 Z M21.75,4.5 L6.25,4.5 C5.28350169,4.5 4.5,5.28350169 4.5,6.25 L4.5,8.003 L23.5,8.003 L23.5,6.25 C23.5,5.28350169 22.7164983,4.5 21.75,4.5 Z\"></path>\n                    </g>\n                  </g>\n                </svg></i>\n              <!---->\n              <!---->\n            </div>\n          </div>\n          <!---->\n          <!---->\n          <div class=\"n-input__border\"></div>\n          <div class=\"n-input__state-border\"></div>\n          <!---->\n        </div>\n        <!---->\n      </div>\n      <div class=\"n-date-picker\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-icon-color-override: rgba(194, 194, 194, 1); --n-icon-color-disabled-override: rgba(209, 209, 209, 1);\">\n        <div class=\"n-input n-input--medium-size n-input--resizable n-input--stateful\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-count-text-color: rgb(118, 124, 130); --n-count-text-color-disabled: rgba(194, 194, 194, 1); --n-color: rgba(255, 255, 255, 1); --n-font-size: 14px; --n-font-weight: 400; --n-border-radius: 3px; --n-height: 34px; --n-padding-left: 12px; --n-padding-right: 12px; --n-text-color: rgb(51, 54, 57); --n-caret-color: #18a058; --n-text-decoration-color: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-focus: 1px solid #36ad6a; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-icon-size: 16px; --n-line-height-textarea: 1.6; --n-color-disabled: rgb(250, 250, 252); --n-color-focus: rgba(255, 255, 255, 1); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-loading-color: #18a058; --n-caret-color-warning: #f0a020; --n-color-focus-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-loading-color-warning: #f0a020; --n-caret-color-error: #d03050; --n-color-focus-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-loading-color-error: #d03050; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-size: 16px; --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-icon-color-hover: rgba(146, 146, 146, 1); --n-icon-color-pressed: rgba(175, 175, 175, 1); --n-icon-color-disabled: rgba(209, 209, 209, 1); --n-suffix-text-color: rgb(51, 54, 57);\" tabindex=\"0\">\n          <div class=\"n-input-wrapper\">\n            <!---->\n            <div class=\"n-input__input\"><input type=\"text\" class=\"n-input__input-el\" tabindex=\"-1\" placeholder=\"Tarih ve Saat Seçin\" size=\"20\" value=\"1970-01-01 08:00:00\">\n              <!---->\n              <!---->\n            </div>\n            <div class=\"n-input__suffix\">\n              <!---->\n              <!---->\n              <!----><i class=\"n-base-icon n-date-picker-icon\"><svg width=\"28px\" height=\"28px\" viewBox=\"0 0 28 28\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n                  <g stroke=\"none\" stroke-width=\"1\" fill-rule=\"evenodd\">\n                    <g fill-rule=\"nonzero\">\n                      <path d=\"M21.75,3 C23.5449254,3 25,4.45507456 25,6.25 L25,21.75 C25,23.5449254 23.5449254,25 21.75,25 L6.25,25 C4.45507456,25 3,23.5449254 3,21.75 L3,6.25 C3,4.45507456 4.45507456,3 6.25,3 L21.75,3 Z M23.5,9.503 L4.5,9.503 L4.5,21.75 C4.5,22.7164983 5.28350169,23.5 6.25,23.5 L21.75,23.5 C22.7164983,23.5 23.5,22.7164983 23.5,21.75 L23.5,9.503 Z M21.75,4.5 L6.25,4.5 C5.28350169,4.5 4.5,5.28350169 4.5,6.25 L4.5,8.003 L23.5,8.003 L23.5,6.25 C23.5,5.28350169 22.7164983,4.5 21.75,4.5 Z\"></path>\n                    </g>\n                  </g>\n                </svg></i>\n              <!---->\n              <!---->\n            </div>\n          </div>\n          <!---->\n          <!---->\n          <div class=\"n-input__border\"></div>\n          <div class=\"n-input__state-border\"></div>\n          <!---->\n        </div>\n        <!---->\n      </div>\n      <div class=\"n-date-picker\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-icon-color-override: rgba(194, 194, 194, 1); --n-icon-color-disabled-override: rgba(209, 209, 209, 1);\">\n        <div class=\"n-input n-input--medium-size n-input--resizable n-input--stateful\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-count-text-color: rgb(118, 124, 130); --n-count-text-color-disabled: rgba(194, 194, 194, 1); --n-color: rgba(255, 255, 255, 1); --n-font-size: 14px; --n-font-weight: 400; --n-border-radius: 3px; --n-height: 34px; --n-padding-left: 12px; --n-padding-right: 12px; --n-text-color: rgb(51, 54, 57); --n-caret-color: #18a058; --n-text-decoration-color: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-focus: 1px solid #36ad6a; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-icon-size: 16px; --n-line-height-textarea: 1.6; --n-color-disabled: rgb(250, 250, 252); --n-color-focus: rgba(255, 255, 255, 1); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-loading-color: #18a058; --n-caret-color-warning: #f0a020; --n-color-focus-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-loading-color-warning: #f0a020; --n-caret-color-error: #d03050; --n-color-focus-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-loading-color-error: #d03050; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-size: 16px; --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-icon-color-hover: rgba(146, 146, 146, 1); --n-icon-color-pressed: rgba(175, 175, 175, 1); --n-icon-color-disabled: rgba(209, 209, 209, 1); --n-suffix-text-color: rgb(51, 54, 57);\" tabindex=\"0\">\n          <div class=\"n-input-wrapper\">\n            <!---->\n            <div class=\"n-input__input\"><input type=\"text\" class=\"n-input__input-el\" tabindex=\"-1\" placeholder=\"Yıl Seçin\" size=\"20\" value=\"1970\">\n              <!---->\n              <!---->\n            </div>\n            <div class=\"n-input__suffix\">\n              <!---->\n              <!---->\n              <!----><i class=\"n-base-icon n-date-picker-icon\"><svg width=\"28px\" height=\"28px\" viewBox=\"0 0 28 28\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n                  <g stroke=\"none\" stroke-width=\"1\" fill-rule=\"evenodd\">\n                    <g fill-rule=\"nonzero\">\n                      <path d=\"M21.75,3 C23.5449254,3 25,4.45507456 25,6.25 L25,21.75 C25,23.5449254 23.5449254,25 21.75,25 L6.25,25 C4.45507456,25 3,23.5449254 3,21.75 L3,6.25 C3,4.45507456 4.45507456,3 6.25,3 L21.75,3 Z M23.5,9.503 L4.5,9.503 L4.5,21.75 C4.5,22.7164983 5.28350169,23.5 6.25,23.5 L21.75,23.5 C22.7164983,23.5 23.5,22.7164983 23.5,21.75 L23.5,9.503 Z M21.75,4.5 L6.25,4.5 C5.28350169,4.5 4.5,5.28350169 4.5,6.25 L4.5,8.003 L23.5,8.003 L23.5,6.25 C23.5,5.28350169 22.7164983,4.5 21.75,4.5 Z\"></path>\n                    </g>\n                  </g>\n                </svg></i>\n              <!---->\n              <!---->\n            </div>\n          </div>\n          <!---->\n          <!---->\n          <div class=\"n-input__border\"></div>\n          <div class=\"n-input__state-border\"></div>\n          <!---->\n        </div>\n        <!---->\n      </div>\n      <div class=\"n-date-picker\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-icon-color-override: rgba(194, 194, 194, 1); --n-icon-color-disabled-override: rgba(209, 209, 209, 1);\">\n        <div class=\"n-input n-input--medium-size n-input--resizable n-input--stateful\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-count-text-color: rgb(118, 124, 130); --n-count-text-color-disabled: rgba(194, 194, 194, 1); --n-color: rgba(255, 255, 255, 1); --n-font-size: 14px; --n-font-weight: 400; --n-border-radius: 3px; --n-height: 34px; --n-padding-left: 12px; --n-padding-right: 12px; --n-text-color: rgb(51, 54, 57); --n-caret-color: #18a058; --n-text-decoration-color: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-focus: 1px solid #36ad6a; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-icon-size: 16px; --n-line-height-textarea: 1.6; --n-color-disabled: rgb(250, 250, 252); --n-color-focus: rgba(255, 255, 255, 1); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-loading-color: #18a058; --n-caret-color-warning: #f0a020; --n-color-focus-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-loading-color-warning: #f0a020; --n-caret-color-error: #d03050; --n-color-focus-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-loading-color-error: #d03050; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-size: 16px; --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-icon-color-hover: rgba(146, 146, 146, 1); --n-icon-color-pressed: rgba(175, 175, 175, 1); --n-icon-color-disabled: rgba(209, 209, 209, 1); --n-suffix-text-color: rgb(51, 54, 57);\" tabindex=\"0\">\n          <div class=\"n-input-wrapper\">\n            <!---->\n            <div class=\"n-input__input\"><input type=\"text\" class=\"n-input__input-el\" tabindex=\"-1\" placeholder=\"Ay Seçin\" size=\"20\" value=\"1970-01\">\n              <!---->\n              <!---->\n            </div>\n            <div class=\"n-input__suffix\">\n              <!---->\n              <!---->\n              <!----><i class=\"n-base-icon n-date-picker-icon\"><svg width=\"28px\" height=\"28px\" viewBox=\"0 0 28 28\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n                  <g stroke=\"none\" stroke-width=\"1\" fill-rule=\"evenodd\">\n                    <g fill-rule=\"nonzero\">\n                      <path d=\"M21.75,3 C23.5449254,3 25,4.45507456 25,6.25 L25,21.75 C25,23.5449254 23.5449254,25 21.75,25 L6.25,25 C4.45507456,25 3,23.5449254 3,21.75 L3,6.25 C3,4.45507456 4.45507456,3 6.25,3 L21.75,3 Z M23.5,9.503 L4.5,9.503 L4.5,21.75 C4.5,22.7164983 5.28350169,23.5 6.25,23.5 L21.75,23.5 C22.7164983,23.5 23.5,22.7164983 23.5,21.75 L23.5,9.503 Z M21.75,4.5 L6.25,4.5 C5.28350169,4.5 4.5,5.28350169 4.5,6.25 L4.5,8.003 L23.5,8.003 L23.5,6.25 C23.5,5.28350169 22.7164983,4.5 21.75,4.5 Z\"></path>\n                    </g>\n                  </g>\n                </svg></i>\n              <!---->\n              <!---->\n            </div>\n          </div>\n          <!---->\n          <!---->\n          <div class=\"n-input__border\"></div>\n          <div class=\"n-input__state-border\"></div>\n          <!---->\n        </div>\n        <!---->\n      </div>\n    </div>\n  </div>\n</div>\"\n`;\n\nexports[`locale > works 26`] = `\n\"<div class=\"n-config-provider\">\n  <div>\n    <div class=\"n-input n-input--medium-size n-input--resizable n-input--stateful\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-count-text-color: rgb(118, 124, 130); --n-count-text-color-disabled: rgba(194, 194, 194, 1); --n-color: rgba(255, 255, 255, 1); --n-font-size: 14px; --n-font-weight: 400; --n-border-radius: 3px; --n-height: 34px; --n-padding-left: 12px; --n-padding-right: 12px; --n-text-color: rgb(51, 54, 57); --n-caret-color: #18a058; --n-text-decoration-color: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-focus: 1px solid #36ad6a; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-icon-size: 16px; --n-line-height-textarea: 1.6; --n-color-disabled: rgb(250, 250, 252); --n-color-focus: rgba(255, 255, 255, 1); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-loading-color: #18a058; --n-caret-color-warning: #f0a020; --n-color-focus-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-loading-color-warning: #f0a020; --n-caret-color-error: #d03050; --n-color-focus-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-loading-color-error: #d03050; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-size: 16px; --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-icon-color-hover: rgba(146, 146, 146, 1); --n-icon-color-pressed: rgba(175, 175, 175, 1); --n-icon-color-disabled: rgba(209, 209, 209, 1); --n-suffix-text-color: rgb(51, 54, 57);\">\n      <div class=\"n-input-wrapper\">\n        <!---->\n        <div class=\"n-input__input\"><input type=\"text\" class=\"n-input__input-el\" placeholder=\"لطفاً وارد کنید\" size=\"20\">\n          <div class=\"n-input__placeholder\"><span>لطفاً وارد کنید</span></div>\n          <!---->\n        </div>\n        <!---->\n      </div>\n      <!---->\n      <!---->\n      <div class=\"n-input__border\"></div>\n      <div class=\"n-input__state-border\"></div>\n      <!---->\n    </div>\n    <div>\n      <div class=\"n-date-picker\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-icon-color-override: rgba(194, 194, 194, 1); --n-icon-color-disabled-override: rgba(209, 209, 209, 1);\">\n        <div class=\"n-input n-input--medium-size n-input--resizable n-input--stateful\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-count-text-color: rgb(118, 124, 130); --n-count-text-color-disabled: rgba(194, 194, 194, 1); --n-color: rgba(255, 255, 255, 1); --n-font-size: 14px; --n-font-weight: 400; --n-border-radius: 3px; --n-height: 34px; --n-padding-left: 12px; --n-padding-right: 12px; --n-text-color: rgb(51, 54, 57); --n-caret-color: #18a058; --n-text-decoration-color: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-focus: 1px solid #36ad6a; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-icon-size: 16px; --n-line-height-textarea: 1.6; --n-color-disabled: rgb(250, 250, 252); --n-color-focus: rgba(255, 255, 255, 1); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-loading-color: #18a058; --n-caret-color-warning: #f0a020; --n-color-focus-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-loading-color-warning: #f0a020; --n-caret-color-error: #d03050; --n-color-focus-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-loading-color-error: #d03050; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-size: 16px; --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-icon-color-hover: rgba(146, 146, 146, 1); --n-icon-color-pressed: rgba(175, 175, 175, 1); --n-icon-color-disabled: rgba(209, 209, 209, 1); --n-suffix-text-color: rgb(51, 54, 57);\" tabindex=\"0\">\n          <div class=\"n-input-wrapper\">\n            <!---->\n            <div class=\"n-input__input\"><input type=\"text\" class=\"n-input__input-el\" tabindex=\"-1\" placeholder=\"انتخاب تاریخ\" size=\"20\" value=\"1970/01/01\">\n              <!---->\n              <!---->\n            </div>\n            <div class=\"n-input__suffix\">\n              <!---->\n              <!---->\n              <!----><i class=\"n-base-icon n-date-picker-icon\"><svg width=\"28px\" height=\"28px\" viewBox=\"0 0 28 28\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n                  <g stroke=\"none\" stroke-width=\"1\" fill-rule=\"evenodd\">\n                    <g fill-rule=\"nonzero\">\n                      <path d=\"M21.75,3 C23.5449254,3 25,4.45507456 25,6.25 L25,21.75 C25,23.5449254 23.5449254,25 21.75,25 L6.25,25 C4.45507456,25 3,23.5449254 3,21.75 L3,6.25 C3,4.45507456 4.45507456,3 6.25,3 L21.75,3 Z M23.5,9.503 L4.5,9.503 L4.5,21.75 C4.5,22.7164983 5.28350169,23.5 6.25,23.5 L21.75,23.5 C22.7164983,23.5 23.5,22.7164983 23.5,21.75 L23.5,9.503 Z M21.75,4.5 L6.25,4.5 C5.28350169,4.5 4.5,5.28350169 4.5,6.25 L4.5,8.003 L23.5,8.003 L23.5,6.25 C23.5,5.28350169 22.7164983,4.5 21.75,4.5 Z\"></path>\n                    </g>\n                  </g>\n                </svg></i>\n              <!---->\n              <!---->\n            </div>\n          </div>\n          <!---->\n          <!---->\n          <div class=\"n-input__border\"></div>\n          <div class=\"n-input__state-border\"></div>\n          <!---->\n        </div>\n        <!---->\n      </div>\n      <div class=\"n-date-picker\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-icon-color-override: rgba(194, 194, 194, 1); --n-icon-color-disabled-override: rgba(209, 209, 209, 1);\">\n        <div class=\"n-input n-input--medium-size n-input--resizable n-input--stateful\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-count-text-color: rgb(118, 124, 130); --n-count-text-color-disabled: rgba(194, 194, 194, 1); --n-color: rgba(255, 255, 255, 1); --n-font-size: 14px; --n-font-weight: 400; --n-border-radius: 3px; --n-height: 34px; --n-padding-left: 12px; --n-padding-right: 12px; --n-text-color: rgb(51, 54, 57); --n-caret-color: #18a058; --n-text-decoration-color: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-focus: 1px solid #36ad6a; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-icon-size: 16px; --n-line-height-textarea: 1.6; --n-color-disabled: rgb(250, 250, 252); --n-color-focus: rgba(255, 255, 255, 1); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-loading-color: #18a058; --n-caret-color-warning: #f0a020; --n-color-focus-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-loading-color-warning: #f0a020; --n-caret-color-error: #d03050; --n-color-focus-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-loading-color-error: #d03050; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-size: 16px; --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-icon-color-hover: rgba(146, 146, 146, 1); --n-icon-color-pressed: rgba(175, 175, 175, 1); --n-icon-color-disabled: rgba(209, 209, 209, 1); --n-suffix-text-color: rgb(51, 54, 57);\" tabindex=\"0\">\n          <div class=\"n-input-wrapper\">\n            <!---->\n            <div class=\"n-input__input\"><input type=\"text\" class=\"n-input__input-el\" tabindex=\"-1\" placeholder=\"انتخاب تاریخ و زمان\" size=\"20\" value=\"1970/01/01 08:00:00\">\n              <!---->\n              <!---->\n            </div>\n            <div class=\"n-input__suffix\">\n              <!---->\n              <!---->\n              <!----><i class=\"n-base-icon n-date-picker-icon\"><svg width=\"28px\" height=\"28px\" viewBox=\"0 0 28 28\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n                  <g stroke=\"none\" stroke-width=\"1\" fill-rule=\"evenodd\">\n                    <g fill-rule=\"nonzero\">\n                      <path d=\"M21.75,3 C23.5449254,3 25,4.45507456 25,6.25 L25,21.75 C25,23.5449254 23.5449254,25 21.75,25 L6.25,25 C4.45507456,25 3,23.5449254 3,21.75 L3,6.25 C3,4.45507456 4.45507456,3 6.25,3 L21.75,3 Z M23.5,9.503 L4.5,9.503 L4.5,21.75 C4.5,22.7164983 5.28350169,23.5 6.25,23.5 L21.75,23.5 C22.7164983,23.5 23.5,22.7164983 23.5,21.75 L23.5,9.503 Z M21.75,4.5 L6.25,4.5 C5.28350169,4.5 4.5,5.28350169 4.5,6.25 L4.5,8.003 L23.5,8.003 L23.5,6.25 C23.5,5.28350169 22.7164983,4.5 21.75,4.5 Z\"></path>\n                    </g>\n                  </g>\n                </svg></i>\n              <!---->\n              <!---->\n            </div>\n          </div>\n          <!---->\n          <!---->\n          <div class=\"n-input__border\"></div>\n          <div class=\"n-input__state-border\"></div>\n          <!---->\n        </div>\n        <!---->\n      </div>\n      <div class=\"n-date-picker\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-icon-color-override: rgba(194, 194, 194, 1); --n-icon-color-disabled-override: rgba(209, 209, 209, 1);\">\n        <div class=\"n-input n-input--medium-size n-input--resizable n-input--stateful\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-count-text-color: rgb(118, 124, 130); --n-count-text-color-disabled: rgba(194, 194, 194, 1); --n-color: rgba(255, 255, 255, 1); --n-font-size: 14px; --n-font-weight: 400; --n-border-radius: 3px; --n-height: 34px; --n-padding-left: 12px; --n-padding-right: 12px; --n-text-color: rgb(51, 54, 57); --n-caret-color: #18a058; --n-text-decoration-color: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-focus: 1px solid #36ad6a; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-icon-size: 16px; --n-line-height-textarea: 1.6; --n-color-disabled: rgb(250, 250, 252); --n-color-focus: rgba(255, 255, 255, 1); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-loading-color: #18a058; --n-caret-color-warning: #f0a020; --n-color-focus-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-loading-color-warning: #f0a020; --n-caret-color-error: #d03050; --n-color-focus-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-loading-color-error: #d03050; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-size: 16px; --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-icon-color-hover: rgba(146, 146, 146, 1); --n-icon-color-pressed: rgba(175, 175, 175, 1); --n-icon-color-disabled: rgba(209, 209, 209, 1); --n-suffix-text-color: rgb(51, 54, 57);\" tabindex=\"0\">\n          <div class=\"n-input-wrapper\">\n            <!---->\n            <div class=\"n-input__input\"><input type=\"text\" class=\"n-input__input-el\" tabindex=\"-1\" placeholder=\"انتخاب سال\" size=\"20\" value=\"1970\">\n              <!---->\n              <!---->\n            </div>\n            <div class=\"n-input__suffix\">\n              <!---->\n              <!---->\n              <!----><i class=\"n-base-icon n-date-picker-icon\"><svg width=\"28px\" height=\"28px\" viewBox=\"0 0 28 28\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n                  <g stroke=\"none\" stroke-width=\"1\" fill-rule=\"evenodd\">\n                    <g fill-rule=\"nonzero\">\n                      <path d=\"M21.75,3 C23.5449254,3 25,4.45507456 25,6.25 L25,21.75 C25,23.5449254 23.5449254,25 21.75,25 L6.25,25 C4.45507456,25 3,23.5449254 3,21.75 L3,6.25 C3,4.45507456 4.45507456,3 6.25,3 L21.75,3 Z M23.5,9.503 L4.5,9.503 L4.5,21.75 C4.5,22.7164983 5.28350169,23.5 6.25,23.5 L21.75,23.5 C22.7164983,23.5 23.5,22.7164983 23.5,21.75 L23.5,9.503 Z M21.75,4.5 L6.25,4.5 C5.28350169,4.5 4.5,5.28350169 4.5,6.25 L4.5,8.003 L23.5,8.003 L23.5,6.25 C23.5,5.28350169 22.7164983,4.5 21.75,4.5 Z\"></path>\n                    </g>\n                  </g>\n                </svg></i>\n              <!---->\n              <!---->\n            </div>\n          </div>\n          <!---->\n          <!---->\n          <div class=\"n-input__border\"></div>\n          <div class=\"n-input__state-border\"></div>\n          <!---->\n        </div>\n        <!---->\n      </div>\n      <div class=\"n-date-picker\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-icon-color-override: rgba(194, 194, 194, 1); --n-icon-color-disabled-override: rgba(209, 209, 209, 1);\">\n        <div class=\"n-input n-input--medium-size n-input--resizable n-input--stateful\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-count-text-color: rgb(118, 124, 130); --n-count-text-color-disabled: rgba(194, 194, 194, 1); --n-color: rgba(255, 255, 255, 1); --n-font-size: 14px; --n-font-weight: 400; --n-border-radius: 3px; --n-height: 34px; --n-padding-left: 12px; --n-padding-right: 12px; --n-text-color: rgb(51, 54, 57); --n-caret-color: #18a058; --n-text-decoration-color: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-focus: 1px solid #36ad6a; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-icon-size: 16px; --n-line-height-textarea: 1.6; --n-color-disabled: rgb(250, 250, 252); --n-color-focus: rgba(255, 255, 255, 1); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-loading-color: #18a058; --n-caret-color-warning: #f0a020; --n-color-focus-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-loading-color-warning: #f0a020; --n-caret-color-error: #d03050; --n-color-focus-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-loading-color-error: #d03050; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-size: 16px; --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-icon-color-hover: rgba(146, 146, 146, 1); --n-icon-color-pressed: rgba(175, 175, 175, 1); --n-icon-color-disabled: rgba(209, 209, 209, 1); --n-suffix-text-color: rgb(51, 54, 57);\" tabindex=\"0\">\n          <div class=\"n-input-wrapper\">\n            <!---->\n            <div class=\"n-input__input\"><input type=\"text\" class=\"n-input__input-el\" tabindex=\"-1\" placeholder=\"انتخاب ماه\" size=\"20\" value=\"01/1970\">\n              <!---->\n              <!---->\n            </div>\n            <div class=\"n-input__suffix\">\n              <!---->\n              <!---->\n              <!----><i class=\"n-base-icon n-date-picker-icon\"><svg width=\"28px\" height=\"28px\" viewBox=\"0 0 28 28\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n                  <g stroke=\"none\" stroke-width=\"1\" fill-rule=\"evenodd\">\n                    <g fill-rule=\"nonzero\">\n                      <path d=\"M21.75,3 C23.5449254,3 25,4.45507456 25,6.25 L25,21.75 C25,23.5449254 23.5449254,25 21.75,25 L6.25,25 C4.45507456,25 3,23.5449254 3,21.75 L3,6.25 C3,4.45507456 4.45507456,3 6.25,3 L21.75,3 Z M23.5,9.503 L4.5,9.503 L4.5,21.75 C4.5,22.7164983 5.28350169,23.5 6.25,23.5 L21.75,23.5 C22.7164983,23.5 23.5,22.7164983 23.5,21.75 L23.5,9.503 Z M21.75,4.5 L6.25,4.5 C5.28350169,4.5 4.5,5.28350169 4.5,6.25 L4.5,8.003 L23.5,8.003 L23.5,6.25 C23.5,5.28350169 22.7164983,4.5 21.75,4.5 Z\"></path>\n                    </g>\n                  </g>\n                </svg></i>\n              <!---->\n              <!---->\n            </div>\n          </div>\n          <!---->\n          <!---->\n          <div class=\"n-input__border\"></div>\n          <div class=\"n-input__state-border\"></div>\n          <!---->\n        </div>\n        <!---->\n      </div>\n    </div>\n  </div>\n</div>\"\n`;\n\nexports[`locale > works 27`] = `\n\"<div class=\"n-config-provider\">\n  <div>\n    <div class=\"n-input n-input--medium-size n-input--resizable n-input--stateful\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-count-text-color: rgb(118, 124, 130); --n-count-text-color-disabled: rgba(194, 194, 194, 1); --n-color: rgba(255, 255, 255, 1); --n-font-size: 14px; --n-font-weight: 400; --n-border-radius: 3px; --n-height: 34px; --n-padding-left: 12px; --n-padding-right: 12px; --n-text-color: rgb(51, 54, 57); --n-caret-color: #18a058; --n-text-decoration-color: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-focus: 1px solid #36ad6a; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-icon-size: 16px; --n-line-height-textarea: 1.6; --n-color-disabled: rgb(250, 250, 252); --n-color-focus: rgba(255, 255, 255, 1); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-loading-color: #18a058; --n-caret-color-warning: #f0a020; --n-color-focus-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-loading-color-warning: #f0a020; --n-caret-color-error: #d03050; --n-color-focus-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-loading-color-error: #d03050; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-size: 16px; --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-icon-color-hover: rgba(146, 146, 146, 1); --n-icon-color-pressed: rgba(175, 175, 175, 1); --n-icon-color-disabled: rgba(209, 209, 209, 1); --n-suffix-text-color: rgb(51, 54, 57);\">\n      <div class=\"n-input-wrapper\">\n        <!---->\n        <div class=\"n-input__input\"><input type=\"text\" class=\"n-input__input-el\" placeholder=\"Vänligen fyll i\" size=\"20\">\n          <div class=\"n-input__placeholder\"><span>Vänligen fyll i</span></div>\n          <!---->\n        </div>\n        <!---->\n      </div>\n      <!---->\n      <!---->\n      <div class=\"n-input__border\"></div>\n      <div class=\"n-input__state-border\"></div>\n      <!---->\n    </div>\n    <div>\n      <div class=\"n-date-picker\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-icon-color-override: rgba(194, 194, 194, 1); --n-icon-color-disabled-override: rgba(209, 209, 209, 1);\">\n        <div class=\"n-input n-input--medium-size n-input--resizable n-input--stateful\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-count-text-color: rgb(118, 124, 130); --n-count-text-color-disabled: rgba(194, 194, 194, 1); --n-color: rgba(255, 255, 255, 1); --n-font-size: 14px; --n-font-weight: 400; --n-border-radius: 3px; --n-height: 34px; --n-padding-left: 12px; --n-padding-right: 12px; --n-text-color: rgb(51, 54, 57); --n-caret-color: #18a058; --n-text-decoration-color: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-focus: 1px solid #36ad6a; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-icon-size: 16px; --n-line-height-textarea: 1.6; --n-color-disabled: rgb(250, 250, 252); --n-color-focus: rgba(255, 255, 255, 1); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-loading-color: #18a058; --n-caret-color-warning: #f0a020; --n-color-focus-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-loading-color-warning: #f0a020; --n-caret-color-error: #d03050; --n-color-focus-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-loading-color-error: #d03050; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-size: 16px; --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-icon-color-hover: rgba(146, 146, 146, 1); --n-icon-color-pressed: rgba(175, 175, 175, 1); --n-icon-color-disabled: rgba(209, 209, 209, 1); --n-suffix-text-color: rgb(51, 54, 57);\" tabindex=\"0\">\n          <div class=\"n-input-wrapper\">\n            <!---->\n            <div class=\"n-input__input\"><input type=\"text\" class=\"n-input__input-el\" tabindex=\"-1\" placeholder=\"Välj datum\" size=\"20\" value=\"1970-01-01\">\n              <!---->\n              <!---->\n            </div>\n            <div class=\"n-input__suffix\">\n              <!---->\n              <!---->\n              <!----><i class=\"n-base-icon n-date-picker-icon\"><svg width=\"28px\" height=\"28px\" viewBox=\"0 0 28 28\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n                  <g stroke=\"none\" stroke-width=\"1\" fill-rule=\"evenodd\">\n                    <g fill-rule=\"nonzero\">\n                      <path d=\"M21.75,3 C23.5449254,3 25,4.45507456 25,6.25 L25,21.75 C25,23.5449254 23.5449254,25 21.75,25 L6.25,25 C4.45507456,25 3,23.5449254 3,21.75 L3,6.25 C3,4.45507456 4.45507456,3 6.25,3 L21.75,3 Z M23.5,9.503 L4.5,9.503 L4.5,21.75 C4.5,22.7164983 5.28350169,23.5 6.25,23.5 L21.75,23.5 C22.7164983,23.5 23.5,22.7164983 23.5,21.75 L23.5,9.503 Z M21.75,4.5 L6.25,4.5 C5.28350169,4.5 4.5,5.28350169 4.5,6.25 L4.5,8.003 L23.5,8.003 L23.5,6.25 C23.5,5.28350169 22.7164983,4.5 21.75,4.5 Z\"></path>\n                    </g>\n                  </g>\n                </svg></i>\n              <!---->\n              <!---->\n            </div>\n          </div>\n          <!---->\n          <!---->\n          <div class=\"n-input__border\"></div>\n          <div class=\"n-input__state-border\"></div>\n          <!---->\n        </div>\n        <!---->\n      </div>\n      <div class=\"n-date-picker\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-icon-color-override: rgba(194, 194, 194, 1); --n-icon-color-disabled-override: rgba(209, 209, 209, 1);\">\n        <div class=\"n-input n-input--medium-size n-input--resizable n-input--stateful\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-count-text-color: rgb(118, 124, 130); --n-count-text-color-disabled: rgba(194, 194, 194, 1); --n-color: rgba(255, 255, 255, 1); --n-font-size: 14px; --n-font-weight: 400; --n-border-radius: 3px; --n-height: 34px; --n-padding-left: 12px; --n-padding-right: 12px; --n-text-color: rgb(51, 54, 57); --n-caret-color: #18a058; --n-text-decoration-color: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-focus: 1px solid #36ad6a; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-icon-size: 16px; --n-line-height-textarea: 1.6; --n-color-disabled: rgb(250, 250, 252); --n-color-focus: rgba(255, 255, 255, 1); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-loading-color: #18a058; --n-caret-color-warning: #f0a020; --n-color-focus-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-loading-color-warning: #f0a020; --n-caret-color-error: #d03050; --n-color-focus-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-loading-color-error: #d03050; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-size: 16px; --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-icon-color-hover: rgba(146, 146, 146, 1); --n-icon-color-pressed: rgba(175, 175, 175, 1); --n-icon-color-disabled: rgba(209, 209, 209, 1); --n-suffix-text-color: rgb(51, 54, 57);\" tabindex=\"0\">\n          <div class=\"n-input-wrapper\">\n            <!---->\n            <div class=\"n-input__input\"><input type=\"text\" class=\"n-input__input-el\" tabindex=\"-1\" placeholder=\"Välj datum och tid\" size=\"20\" value=\"1970-01-01 08:00:00\">\n              <!---->\n              <!---->\n            </div>\n            <div class=\"n-input__suffix\">\n              <!---->\n              <!---->\n              <!----><i class=\"n-base-icon n-date-picker-icon\"><svg width=\"28px\" height=\"28px\" viewBox=\"0 0 28 28\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n                  <g stroke=\"none\" stroke-width=\"1\" fill-rule=\"evenodd\">\n                    <g fill-rule=\"nonzero\">\n                      <path d=\"M21.75,3 C23.5449254,3 25,4.45507456 25,6.25 L25,21.75 C25,23.5449254 23.5449254,25 21.75,25 L6.25,25 C4.45507456,25 3,23.5449254 3,21.75 L3,6.25 C3,4.45507456 4.45507456,3 6.25,3 L21.75,3 Z M23.5,9.503 L4.5,9.503 L4.5,21.75 C4.5,22.7164983 5.28350169,23.5 6.25,23.5 L21.75,23.5 C22.7164983,23.5 23.5,22.7164983 23.5,21.75 L23.5,9.503 Z M21.75,4.5 L6.25,4.5 C5.28350169,4.5 4.5,5.28350169 4.5,6.25 L4.5,8.003 L23.5,8.003 L23.5,6.25 C23.5,5.28350169 22.7164983,4.5 21.75,4.5 Z\"></path>\n                    </g>\n                  </g>\n                </svg></i>\n              <!---->\n              <!---->\n            </div>\n          </div>\n          <!---->\n          <!---->\n          <div class=\"n-input__border\"></div>\n          <div class=\"n-input__state-border\"></div>\n          <!---->\n        </div>\n        <!---->\n      </div>\n      <div class=\"n-date-picker\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-icon-color-override: rgba(194, 194, 194, 1); --n-icon-color-disabled-override: rgba(209, 209, 209, 1);\">\n        <div class=\"n-input n-input--medium-size n-input--resizable n-input--stateful\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-count-text-color: rgb(118, 124, 130); --n-count-text-color-disabled: rgba(194, 194, 194, 1); --n-color: rgba(255, 255, 255, 1); --n-font-size: 14px; --n-font-weight: 400; --n-border-radius: 3px; --n-height: 34px; --n-padding-left: 12px; --n-padding-right: 12px; --n-text-color: rgb(51, 54, 57); --n-caret-color: #18a058; --n-text-decoration-color: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-focus: 1px solid #36ad6a; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-icon-size: 16px; --n-line-height-textarea: 1.6; --n-color-disabled: rgb(250, 250, 252); --n-color-focus: rgba(255, 255, 255, 1); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-loading-color: #18a058; --n-caret-color-warning: #f0a020; --n-color-focus-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-loading-color-warning: #f0a020; --n-caret-color-error: #d03050; --n-color-focus-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-loading-color-error: #d03050; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-size: 16px; --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-icon-color-hover: rgba(146, 146, 146, 1); --n-icon-color-pressed: rgba(175, 175, 175, 1); --n-icon-color-disabled: rgba(209, 209, 209, 1); --n-suffix-text-color: rgb(51, 54, 57);\" tabindex=\"0\">\n          <div class=\"n-input-wrapper\">\n            <!---->\n            <div class=\"n-input__input\"><input type=\"text\" class=\"n-input__input-el\" tabindex=\"-1\" placeholder=\"Välj år\" size=\"20\" value=\"1970\">\n              <!---->\n              <!---->\n            </div>\n            <div class=\"n-input__suffix\">\n              <!---->\n              <!---->\n              <!----><i class=\"n-base-icon n-date-picker-icon\"><svg width=\"28px\" height=\"28px\" viewBox=\"0 0 28 28\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n                  <g stroke=\"none\" stroke-width=\"1\" fill-rule=\"evenodd\">\n                    <g fill-rule=\"nonzero\">\n                      <path d=\"M21.75,3 C23.5449254,3 25,4.45507456 25,6.25 L25,21.75 C25,23.5449254 23.5449254,25 21.75,25 L6.25,25 C4.45507456,25 3,23.5449254 3,21.75 L3,6.25 C3,4.45507456 4.45507456,3 6.25,3 L21.75,3 Z M23.5,9.503 L4.5,9.503 L4.5,21.75 C4.5,22.7164983 5.28350169,23.5 6.25,23.5 L21.75,23.5 C22.7164983,23.5 23.5,22.7164983 23.5,21.75 L23.5,9.503 Z M21.75,4.5 L6.25,4.5 C5.28350169,4.5 4.5,5.28350169 4.5,6.25 L4.5,8.003 L23.5,8.003 L23.5,6.25 C23.5,5.28350169 22.7164983,4.5 21.75,4.5 Z\"></path>\n                    </g>\n                  </g>\n                </svg></i>\n              <!---->\n              <!---->\n            </div>\n          </div>\n          <!---->\n          <!---->\n          <div class=\"n-input__border\"></div>\n          <div class=\"n-input__state-border\"></div>\n          <!---->\n        </div>\n        <!---->\n      </div>\n      <div class=\"n-date-picker\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-icon-color-override: rgba(194, 194, 194, 1); --n-icon-color-disabled-override: rgba(209, 209, 209, 1);\">\n        <div class=\"n-input n-input--medium-size n-input--resizable n-input--stateful\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-count-text-color: rgb(118, 124, 130); --n-count-text-color-disabled: rgba(194, 194, 194, 1); --n-color: rgba(255, 255, 255, 1); --n-font-size: 14px; --n-font-weight: 400; --n-border-radius: 3px; --n-height: 34px; --n-padding-left: 12px; --n-padding-right: 12px; --n-text-color: rgb(51, 54, 57); --n-caret-color: #18a058; --n-text-decoration-color: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-focus: 1px solid #36ad6a; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-icon-size: 16px; --n-line-height-textarea: 1.6; --n-color-disabled: rgb(250, 250, 252); --n-color-focus: rgba(255, 255, 255, 1); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-loading-color: #18a058; --n-caret-color-warning: #f0a020; --n-color-focus-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-loading-color-warning: #f0a020; --n-caret-color-error: #d03050; --n-color-focus-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-loading-color-error: #d03050; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-size: 16px; --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-icon-color-hover: rgba(146, 146, 146, 1); --n-icon-color-pressed: rgba(175, 175, 175, 1); --n-icon-color-disabled: rgba(209, 209, 209, 1); --n-suffix-text-color: rgb(51, 54, 57);\" tabindex=\"0\">\n          <div class=\"n-input-wrapper\">\n            <!---->\n            <div class=\"n-input__input\"><input type=\"text\" class=\"n-input__input-el\" tabindex=\"-1\" placeholder=\"Välj månad\" size=\"20\" value=\"1970-01\">\n              <!---->\n              <!---->\n            </div>\n            <div class=\"n-input__suffix\">\n              <!---->\n              <!---->\n              <!----><i class=\"n-base-icon n-date-picker-icon\"><svg width=\"28px\" height=\"28px\" viewBox=\"0 0 28 28\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n                  <g stroke=\"none\" stroke-width=\"1\" fill-rule=\"evenodd\">\n                    <g fill-rule=\"nonzero\">\n                      <path d=\"M21.75,3 C23.5449254,3 25,4.45507456 25,6.25 L25,21.75 C25,23.5449254 23.5449254,25 21.75,25 L6.25,25 C4.45507456,25 3,23.5449254 3,21.75 L3,6.25 C3,4.45507456 4.45507456,3 6.25,3 L21.75,3 Z M23.5,9.503 L4.5,9.503 L4.5,21.75 C4.5,22.7164983 5.28350169,23.5 6.25,23.5 L21.75,23.5 C22.7164983,23.5 23.5,22.7164983 23.5,21.75 L23.5,9.503 Z M21.75,4.5 L6.25,4.5 C5.28350169,4.5 4.5,5.28350169 4.5,6.25 L4.5,8.003 L23.5,8.003 L23.5,6.25 C23.5,5.28350169 22.7164983,4.5 21.75,4.5 Z\"></path>\n                    </g>\n                  </g>\n                </svg></i>\n              <!---->\n              <!---->\n            </div>\n          </div>\n          <!---->\n          <!---->\n          <div class=\"n-input__border\"></div>\n          <div class=\"n-input__state-border\"></div>\n          <!---->\n        </div>\n        <!---->\n      </div>\n    </div>\n  </div>\n</div>\"\n`;\n\nexports[`locale > works 28`] = `\n\"<div class=\"n-config-provider\">\n  <div>\n    <div class=\"n-input n-input--medium-size n-input--resizable n-input--stateful\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-count-text-color: rgb(118, 124, 130); --n-count-text-color-disabled: rgba(194, 194, 194, 1); --n-color: rgba(255, 255, 255, 1); --n-font-size: 14px; --n-font-weight: 400; --n-border-radius: 3px; --n-height: 34px; --n-padding-left: 12px; --n-padding-right: 12px; --n-text-color: rgb(51, 54, 57); --n-caret-color: #18a058; --n-text-decoration-color: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-focus: 1px solid #36ad6a; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-icon-size: 16px; --n-line-height-textarea: 1.6; --n-color-disabled: rgb(250, 250, 252); --n-color-focus: rgba(255, 255, 255, 1); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-loading-color: #18a058; --n-caret-color-warning: #f0a020; --n-color-focus-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-loading-color-warning: #f0a020; --n-caret-color-error: #d03050; --n-color-focus-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-loading-color-error: #d03050; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-size: 16px; --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-icon-color-hover: rgba(146, 146, 146, 1); --n-icon-color-pressed: rgba(175, 175, 175, 1); --n-icon-color-disabled: rgba(209, 209, 209, 1); --n-suffix-text-color: rgb(51, 54, 57);\">\n      <div class=\"n-input-wrapper\">\n        <!---->\n        <div class=\"n-input__input\"><input type=\"text\" class=\"n-input__input-el\" placeholder=\"Sisesta\" size=\"20\">\n          <div class=\"n-input__placeholder\"><span>Sisesta</span></div>\n          <!---->\n        </div>\n        <!---->\n      </div>\n      <!---->\n      <!---->\n      <div class=\"n-input__border\"></div>\n      <div class=\"n-input__state-border\"></div>\n      <!---->\n    </div>\n    <div>\n      <div class=\"n-date-picker\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-icon-color-override: rgba(194, 194, 194, 1); --n-icon-color-disabled-override: rgba(209, 209, 209, 1);\">\n        <div class=\"n-input n-input--medium-size n-input--resizable n-input--stateful\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-count-text-color: rgb(118, 124, 130); --n-count-text-color-disabled: rgba(194, 194, 194, 1); --n-color: rgba(255, 255, 255, 1); --n-font-size: 14px; --n-font-weight: 400; --n-border-radius: 3px; --n-height: 34px; --n-padding-left: 12px; --n-padding-right: 12px; --n-text-color: rgb(51, 54, 57); --n-caret-color: #18a058; --n-text-decoration-color: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-focus: 1px solid #36ad6a; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-icon-size: 16px; --n-line-height-textarea: 1.6; --n-color-disabled: rgb(250, 250, 252); --n-color-focus: rgba(255, 255, 255, 1); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-loading-color: #18a058; --n-caret-color-warning: #f0a020; --n-color-focus-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-loading-color-warning: #f0a020; --n-caret-color-error: #d03050; --n-color-focus-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-loading-color-error: #d03050; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-size: 16px; --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-icon-color-hover: rgba(146, 146, 146, 1); --n-icon-color-pressed: rgba(175, 175, 175, 1); --n-icon-color-disabled: rgba(209, 209, 209, 1); --n-suffix-text-color: rgb(51, 54, 57);\" tabindex=\"0\">\n          <div class=\"n-input-wrapper\">\n            <!---->\n            <div class=\"n-input__input\"><input type=\"text\" class=\"n-input__input-el\" tabindex=\"-1\" placeholder=\"Vali kuupäev\" size=\"20\" value=\"01.01.1970\">\n              <!---->\n              <!---->\n            </div>\n            <div class=\"n-input__suffix\">\n              <!---->\n              <!---->\n              <!----><i class=\"n-base-icon n-date-picker-icon\"><svg width=\"28px\" height=\"28px\" viewBox=\"0 0 28 28\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n                  <g stroke=\"none\" stroke-width=\"1\" fill-rule=\"evenodd\">\n                    <g fill-rule=\"nonzero\">\n                      <path d=\"M21.75,3 C23.5449254,3 25,4.45507456 25,6.25 L25,21.75 C25,23.5449254 23.5449254,25 21.75,25 L6.25,25 C4.45507456,25 3,23.5449254 3,21.75 L3,6.25 C3,4.45507456 4.45507456,3 6.25,3 L21.75,3 Z M23.5,9.503 L4.5,9.503 L4.5,21.75 C4.5,22.7164983 5.28350169,23.5 6.25,23.5 L21.75,23.5 C22.7164983,23.5 23.5,22.7164983 23.5,21.75 L23.5,9.503 Z M21.75,4.5 L6.25,4.5 C5.28350169,4.5 4.5,5.28350169 4.5,6.25 L4.5,8.003 L23.5,8.003 L23.5,6.25 C23.5,5.28350169 22.7164983,4.5 21.75,4.5 Z\"></path>\n                    </g>\n                  </g>\n                </svg></i>\n              <!---->\n              <!---->\n            </div>\n          </div>\n          <!---->\n          <!---->\n          <div class=\"n-input__border\"></div>\n          <div class=\"n-input__state-border\"></div>\n          <!---->\n        </div>\n        <!---->\n      </div>\n      <div class=\"n-date-picker\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-icon-color-override: rgba(194, 194, 194, 1); --n-icon-color-disabled-override: rgba(209, 209, 209, 1);\">\n        <div class=\"n-input n-input--medium-size n-input--resizable n-input--stateful\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-count-text-color: rgb(118, 124, 130); --n-count-text-color-disabled: rgba(194, 194, 194, 1); --n-color: rgba(255, 255, 255, 1); --n-font-size: 14px; --n-font-weight: 400; --n-border-radius: 3px; --n-height: 34px; --n-padding-left: 12px; --n-padding-right: 12px; --n-text-color: rgb(51, 54, 57); --n-caret-color: #18a058; --n-text-decoration-color: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-focus: 1px solid #36ad6a; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-icon-size: 16px; --n-line-height-textarea: 1.6; --n-color-disabled: rgb(250, 250, 252); --n-color-focus: rgba(255, 255, 255, 1); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-loading-color: #18a058; --n-caret-color-warning: #f0a020; --n-color-focus-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-loading-color-warning: #f0a020; --n-caret-color-error: #d03050; --n-color-focus-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-loading-color-error: #d03050; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-size: 16px; --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-icon-color-hover: rgba(146, 146, 146, 1); --n-icon-color-pressed: rgba(175, 175, 175, 1); --n-icon-color-disabled: rgba(209, 209, 209, 1); --n-suffix-text-color: rgb(51, 54, 57);\" tabindex=\"0\">\n          <div class=\"n-input-wrapper\">\n            <!---->\n            <div class=\"n-input__input\"><input type=\"text\" class=\"n-input__input-el\" tabindex=\"-1\" placeholder=\"Vali aeg ja kuupäev\" size=\"20\" value=\"01.01.1970 08:00:00\">\n              <!---->\n              <!---->\n            </div>\n            <div class=\"n-input__suffix\">\n              <!---->\n              <!---->\n              <!----><i class=\"n-base-icon n-date-picker-icon\"><svg width=\"28px\" height=\"28px\" viewBox=\"0 0 28 28\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n                  <g stroke=\"none\" stroke-width=\"1\" fill-rule=\"evenodd\">\n                    <g fill-rule=\"nonzero\">\n                      <path d=\"M21.75,3 C23.5449254,3 25,4.45507456 25,6.25 L25,21.75 C25,23.5449254 23.5449254,25 21.75,25 L6.25,25 C4.45507456,25 3,23.5449254 3,21.75 L3,6.25 C3,4.45507456 4.45507456,3 6.25,3 L21.75,3 Z M23.5,9.503 L4.5,9.503 L4.5,21.75 C4.5,22.7164983 5.28350169,23.5 6.25,23.5 L21.75,23.5 C22.7164983,23.5 23.5,22.7164983 23.5,21.75 L23.5,9.503 Z M21.75,4.5 L6.25,4.5 C5.28350169,4.5 4.5,5.28350169 4.5,6.25 L4.5,8.003 L23.5,8.003 L23.5,6.25 C23.5,5.28350169 22.7164983,4.5 21.75,4.5 Z\"></path>\n                    </g>\n                  </g>\n                </svg></i>\n              <!---->\n              <!---->\n            </div>\n          </div>\n          <!---->\n          <!---->\n          <div class=\"n-input__border\"></div>\n          <div class=\"n-input__state-border\"></div>\n          <!---->\n        </div>\n        <!---->\n      </div>\n      <div class=\"n-date-picker\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-icon-color-override: rgba(194, 194, 194, 1); --n-icon-color-disabled-override: rgba(209, 209, 209, 1);\">\n        <div class=\"n-input n-input--medium-size n-input--resizable n-input--stateful\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-count-text-color: rgb(118, 124, 130); --n-count-text-color-disabled: rgba(194, 194, 194, 1); --n-color: rgba(255, 255, 255, 1); --n-font-size: 14px; --n-font-weight: 400; --n-border-radius: 3px; --n-height: 34px; --n-padding-left: 12px; --n-padding-right: 12px; --n-text-color: rgb(51, 54, 57); --n-caret-color: #18a058; --n-text-decoration-color: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-focus: 1px solid #36ad6a; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-icon-size: 16px; --n-line-height-textarea: 1.6; --n-color-disabled: rgb(250, 250, 252); --n-color-focus: rgba(255, 255, 255, 1); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-loading-color: #18a058; --n-caret-color-warning: #f0a020; --n-color-focus-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-loading-color-warning: #f0a020; --n-caret-color-error: #d03050; --n-color-focus-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-loading-color-error: #d03050; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-size: 16px; --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-icon-color-hover: rgba(146, 146, 146, 1); --n-icon-color-pressed: rgba(175, 175, 175, 1); --n-icon-color-disabled: rgba(209, 209, 209, 1); --n-suffix-text-color: rgb(51, 54, 57);\" tabindex=\"0\">\n          <div class=\"n-input-wrapper\">\n            <!---->\n            <div class=\"n-input__input\"><input type=\"text\" class=\"n-input__input-el\" tabindex=\"-1\" placeholder=\"Vali aasta\" size=\"20\" value=\"1970\">\n              <!---->\n              <!---->\n            </div>\n            <div class=\"n-input__suffix\">\n              <!---->\n              <!---->\n              <!----><i class=\"n-base-icon n-date-picker-icon\"><svg width=\"28px\" height=\"28px\" viewBox=\"0 0 28 28\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n                  <g stroke=\"none\" stroke-width=\"1\" fill-rule=\"evenodd\">\n                    <g fill-rule=\"nonzero\">\n                      <path d=\"M21.75,3 C23.5449254,3 25,4.45507456 25,6.25 L25,21.75 C25,23.5449254 23.5449254,25 21.75,25 L6.25,25 C4.45507456,25 3,23.5449254 3,21.75 L3,6.25 C3,4.45507456 4.45507456,3 6.25,3 L21.75,3 Z M23.5,9.503 L4.5,9.503 L4.5,21.75 C4.5,22.7164983 5.28350169,23.5 6.25,23.5 L21.75,23.5 C22.7164983,23.5 23.5,22.7164983 23.5,21.75 L23.5,9.503 Z M21.75,4.5 L6.25,4.5 C5.28350169,4.5 4.5,5.28350169 4.5,6.25 L4.5,8.003 L23.5,8.003 L23.5,6.25 C23.5,5.28350169 22.7164983,4.5 21.75,4.5 Z\"></path>\n                    </g>\n                  </g>\n                </svg></i>\n              <!---->\n              <!---->\n            </div>\n          </div>\n          <!---->\n          <!---->\n          <div class=\"n-input__border\"></div>\n          <div class=\"n-input__state-border\"></div>\n          <!---->\n        </div>\n        <!---->\n      </div>\n      <div class=\"n-date-picker\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-icon-color-override: rgba(194, 194, 194, 1); --n-icon-color-disabled-override: rgba(209, 209, 209, 1);\">\n        <div class=\"n-input n-input--medium-size n-input--resizable n-input--stateful\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-count-text-color: rgb(118, 124, 130); --n-count-text-color-disabled: rgba(194, 194, 194, 1); --n-color: rgba(255, 255, 255, 1); --n-font-size: 14px; --n-font-weight: 400; --n-border-radius: 3px; --n-height: 34px; --n-padding-left: 12px; --n-padding-right: 12px; --n-text-color: rgb(51, 54, 57); --n-caret-color: #18a058; --n-text-decoration-color: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-focus: 1px solid #36ad6a; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-icon-size: 16px; --n-line-height-textarea: 1.6; --n-color-disabled: rgb(250, 250, 252); --n-color-focus: rgba(255, 255, 255, 1); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-loading-color: #18a058; --n-caret-color-warning: #f0a020; --n-color-focus-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-loading-color-warning: #f0a020; --n-caret-color-error: #d03050; --n-color-focus-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-loading-color-error: #d03050; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-size: 16px; --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-icon-color-hover: rgba(146, 146, 146, 1); --n-icon-color-pressed: rgba(175, 175, 175, 1); --n-icon-color-disabled: rgba(209, 209, 209, 1); --n-suffix-text-color: rgb(51, 54, 57);\" tabindex=\"0\">\n          <div class=\"n-input-wrapper\">\n            <!---->\n            <div class=\"n-input__input\"><input type=\"text\" class=\"n-input__input-el\" tabindex=\"-1\" placeholder=\"Vali kuu\" size=\"20\" value=\"01-1970\">\n              <!---->\n              <!---->\n            </div>\n            <div class=\"n-input__suffix\">\n              <!---->\n              <!---->\n              <!----><i class=\"n-base-icon n-date-picker-icon\"><svg width=\"28px\" height=\"28px\" viewBox=\"0 0 28 28\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n                  <g stroke=\"none\" stroke-width=\"1\" fill-rule=\"evenodd\">\n                    <g fill-rule=\"nonzero\">\n                      <path d=\"M21.75,3 C23.5449254,3 25,4.45507456 25,6.25 L25,21.75 C25,23.5449254 23.5449254,25 21.75,25 L6.25,25 C4.45507456,25 3,23.5449254 3,21.75 L3,6.25 C3,4.45507456 4.45507456,3 6.25,3 L21.75,3 Z M23.5,9.503 L4.5,9.503 L4.5,21.75 C4.5,22.7164983 5.28350169,23.5 6.25,23.5 L21.75,23.5 C22.7164983,23.5 23.5,22.7164983 23.5,21.75 L23.5,9.503 Z M21.75,4.5 L6.25,4.5 C5.28350169,4.5 4.5,5.28350169 4.5,6.25 L4.5,8.003 L23.5,8.003 L23.5,6.25 C23.5,5.28350169 22.7164983,4.5 21.75,4.5 Z\"></path>\n                    </g>\n                  </g>\n                </svg></i>\n              <!---->\n              <!---->\n            </div>\n          </div>\n          <!---->\n          <!---->\n          <div class=\"n-input__border\"></div>\n          <div class=\"n-input__state-border\"></div>\n          <!---->\n        </div>\n        <!---->\n      </div>\n    </div>\n  </div>\n</div>\"\n`;\n\nexports[`locale > works 29`] = `\n\"<div class=\"n-config-provider\">\n  <div>\n    <div class=\"n-input n-input--medium-size n-input--resizable n-input--stateful\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-count-text-color: rgb(118, 124, 130); --n-count-text-color-disabled: rgba(194, 194, 194, 1); --n-color: rgba(255, 255, 255, 1); --n-font-size: 14px; --n-font-weight: 400; --n-border-radius: 3px; --n-height: 34px; --n-padding-left: 12px; --n-padding-right: 12px; --n-text-color: rgb(51, 54, 57); --n-caret-color: #18a058; --n-text-decoration-color: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-focus: 1px solid #36ad6a; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-icon-size: 16px; --n-line-height-textarea: 1.6; --n-color-disabled: rgb(250, 250, 252); --n-color-focus: rgba(255, 255, 255, 1); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-loading-color: #18a058; --n-caret-color-warning: #f0a020; --n-color-focus-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-loading-color-warning: #f0a020; --n-caret-color-error: #d03050; --n-color-focus-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-loading-color-error: #d03050; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-size: 16px; --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-icon-color-hover: rgba(146, 146, 146, 1); --n-icon-color-pressed: rgba(175, 175, 175, 1); --n-icon-color-disabled: rgba(209, 209, 209, 1); --n-suffix-text-color: rgb(51, 54, 57);\">\n      <div class=\"n-input-wrapper\">\n        <!---->\n        <div class=\"n-input__input\"><input type=\"text\" class=\"n-input__input-el\" placeholder=\"Zəhmət olmasa, daxil edin\" size=\"20\">\n          <div class=\"n-input__placeholder\"><span>Zəhmət olmasa, daxil edin</span></div>\n          <!---->\n        </div>\n        <!---->\n      </div>\n      <!---->\n      <!---->\n      <div class=\"n-input__border\"></div>\n      <div class=\"n-input__state-border\"></div>\n      <!---->\n    </div>\n    <div>\n      <div class=\"n-date-picker\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-icon-color-override: rgba(194, 194, 194, 1); --n-icon-color-disabled-override: rgba(209, 209, 209, 1);\">\n        <div class=\"n-input n-input--medium-size n-input--resizable n-input--stateful\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-count-text-color: rgb(118, 124, 130); --n-count-text-color-disabled: rgba(194, 194, 194, 1); --n-color: rgba(255, 255, 255, 1); --n-font-size: 14px; --n-font-weight: 400; --n-border-radius: 3px; --n-height: 34px; --n-padding-left: 12px; --n-padding-right: 12px; --n-text-color: rgb(51, 54, 57); --n-caret-color: #18a058; --n-text-decoration-color: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-focus: 1px solid #36ad6a; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-icon-size: 16px; --n-line-height-textarea: 1.6; --n-color-disabled: rgb(250, 250, 252); --n-color-focus: rgba(255, 255, 255, 1); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-loading-color: #18a058; --n-caret-color-warning: #f0a020; --n-color-focus-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-loading-color-warning: #f0a020; --n-caret-color-error: #d03050; --n-color-focus-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-loading-color-error: #d03050; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-size: 16px; --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-icon-color-hover: rgba(146, 146, 146, 1); --n-icon-color-pressed: rgba(175, 175, 175, 1); --n-icon-color-disabled: rgba(209, 209, 209, 1); --n-suffix-text-color: rgb(51, 54, 57);\" tabindex=\"0\">\n          <div class=\"n-input-wrapper\">\n            <!---->\n            <div class=\"n-input__input\"><input type=\"text\" class=\"n-input__input-el\" tabindex=\"-1\" placeholder=\"Tarixi seç\" size=\"20\" value=\"01 Yanvar 1970\">\n              <!---->\n              <!---->\n            </div>\n            <div class=\"n-input__suffix\">\n              <!---->\n              <!---->\n              <!----><i class=\"n-base-icon n-date-picker-icon\"><svg width=\"28px\" height=\"28px\" viewBox=\"0 0 28 28\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n                  <g stroke=\"none\" stroke-width=\"1\" fill-rule=\"evenodd\">\n                    <g fill-rule=\"nonzero\">\n                      <path d=\"M21.75,3 C23.5449254,3 25,4.45507456 25,6.25 L25,21.75 C25,23.5449254 23.5449254,25 21.75,25 L6.25,25 C4.45507456,25 3,23.5449254 3,21.75 L3,6.25 C3,4.45507456 4.45507456,3 6.25,3 L21.75,3 Z M23.5,9.503 L4.5,9.503 L4.5,21.75 C4.5,22.7164983 5.28350169,23.5 6.25,23.5 L21.75,23.5 C22.7164983,23.5 23.5,22.7164983 23.5,21.75 L23.5,9.503 Z M21.75,4.5 L6.25,4.5 C5.28350169,4.5 4.5,5.28350169 4.5,6.25 L4.5,8.003 L23.5,8.003 L23.5,6.25 C23.5,5.28350169 22.7164983,4.5 21.75,4.5 Z\"></path>\n                    </g>\n                  </g>\n                </svg></i>\n              <!---->\n              <!---->\n            </div>\n          </div>\n          <!---->\n          <!---->\n          <div class=\"n-input__border\"></div>\n          <div class=\"n-input__state-border\"></div>\n          <!---->\n        </div>\n        <!---->\n      </div>\n      <div class=\"n-date-picker\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-icon-color-override: rgba(194, 194, 194, 1); --n-icon-color-disabled-override: rgba(209, 209, 209, 1);\">\n        <div class=\"n-input n-input--medium-size n-input--resizable n-input--stateful\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-count-text-color: rgb(118, 124, 130); --n-count-text-color-disabled: rgba(194, 194, 194, 1); --n-color: rgba(255, 255, 255, 1); --n-font-size: 14px; --n-font-weight: 400; --n-border-radius: 3px; --n-height: 34px; --n-padding-left: 12px; --n-padding-right: 12px; --n-text-color: rgb(51, 54, 57); --n-caret-color: #18a058; --n-text-decoration-color: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-focus: 1px solid #36ad6a; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-icon-size: 16px; --n-line-height-textarea: 1.6; --n-color-disabled: rgb(250, 250, 252); --n-color-focus: rgba(255, 255, 255, 1); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-loading-color: #18a058; --n-caret-color-warning: #f0a020; --n-color-focus-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-loading-color-warning: #f0a020; --n-caret-color-error: #d03050; --n-color-focus-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-loading-color-error: #d03050; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-size: 16px; --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-icon-color-hover: rgba(146, 146, 146, 1); --n-icon-color-pressed: rgba(175, 175, 175, 1); --n-icon-color-disabled: rgba(209, 209, 209, 1); --n-suffix-text-color: rgb(51, 54, 57);\" tabindex=\"0\">\n          <div class=\"n-input-wrapper\">\n            <!---->\n            <div class=\"n-input__input\"><input type=\"text\" class=\"n-input__input-el\" tabindex=\"-1\" placeholder=\"Tarix və vaxtı seçin\" size=\"20\" value=\"1970-01-01 08:00:00\">\n              <!---->\n              <!---->\n            </div>\n            <div class=\"n-input__suffix\">\n              <!---->\n              <!---->\n              <!----><i class=\"n-base-icon n-date-picker-icon\"><svg width=\"28px\" height=\"28px\" viewBox=\"0 0 28 28\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n                  <g stroke=\"none\" stroke-width=\"1\" fill-rule=\"evenodd\">\n                    <g fill-rule=\"nonzero\">\n                      <path d=\"M21.75,3 C23.5449254,3 25,4.45507456 25,6.25 L25,21.75 C25,23.5449254 23.5449254,25 21.75,25 L6.25,25 C4.45507456,25 3,23.5449254 3,21.75 L3,6.25 C3,4.45507456 4.45507456,3 6.25,3 L21.75,3 Z M23.5,9.503 L4.5,9.503 L4.5,21.75 C4.5,22.7164983 5.28350169,23.5 6.25,23.5 L21.75,23.5 C22.7164983,23.5 23.5,22.7164983 23.5,21.75 L23.5,9.503 Z M21.75,4.5 L6.25,4.5 C5.28350169,4.5 4.5,5.28350169 4.5,6.25 L4.5,8.003 L23.5,8.003 L23.5,6.25 C23.5,5.28350169 22.7164983,4.5 21.75,4.5 Z\"></path>\n                    </g>\n                  </g>\n                </svg></i>\n              <!---->\n              <!---->\n            </div>\n          </div>\n          <!---->\n          <!---->\n          <div class=\"n-input__border\"></div>\n          <div class=\"n-input__state-border\"></div>\n          <!---->\n        </div>\n        <!---->\n      </div>\n      <div class=\"n-date-picker\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-icon-color-override: rgba(194, 194, 194, 1); --n-icon-color-disabled-override: rgba(209, 209, 209, 1);\">\n        <div class=\"n-input n-input--medium-size n-input--resizable n-input--stateful\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-count-text-color: rgb(118, 124, 130); --n-count-text-color-disabled: rgba(194, 194, 194, 1); --n-color: rgba(255, 255, 255, 1); --n-font-size: 14px; --n-font-weight: 400; --n-border-radius: 3px; --n-height: 34px; --n-padding-left: 12px; --n-padding-right: 12px; --n-text-color: rgb(51, 54, 57); --n-caret-color: #18a058; --n-text-decoration-color: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-focus: 1px solid #36ad6a; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-icon-size: 16px; --n-line-height-textarea: 1.6; --n-color-disabled: rgb(250, 250, 252); --n-color-focus: rgba(255, 255, 255, 1); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-loading-color: #18a058; --n-caret-color-warning: #f0a020; --n-color-focus-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-loading-color-warning: #f0a020; --n-caret-color-error: #d03050; --n-color-focus-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-loading-color-error: #d03050; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-size: 16px; --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-icon-color-hover: rgba(146, 146, 146, 1); --n-icon-color-pressed: rgba(175, 175, 175, 1); --n-icon-color-disabled: rgba(209, 209, 209, 1); --n-suffix-text-color: rgb(51, 54, 57);\" tabindex=\"0\">\n          <div class=\"n-input-wrapper\">\n            <!---->\n            <div class=\"n-input__input\"><input type=\"text\" class=\"n-input__input-el\" tabindex=\"-1\" placeholder=\"İli seçin\" size=\"20\" value=\"1970\">\n              <!---->\n              <!---->\n            </div>\n            <div class=\"n-input__suffix\">\n              <!---->\n              <!---->\n              <!----><i class=\"n-base-icon n-date-picker-icon\"><svg width=\"28px\" height=\"28px\" viewBox=\"0 0 28 28\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n                  <g stroke=\"none\" stroke-width=\"1\" fill-rule=\"evenodd\">\n                    <g fill-rule=\"nonzero\">\n                      <path d=\"M21.75,3 C23.5449254,3 25,4.45507456 25,6.25 L25,21.75 C25,23.5449254 23.5449254,25 21.75,25 L6.25,25 C4.45507456,25 3,23.5449254 3,21.75 L3,6.25 C3,4.45507456 4.45507456,3 6.25,3 L21.75,3 Z M23.5,9.503 L4.5,9.503 L4.5,21.75 C4.5,22.7164983 5.28350169,23.5 6.25,23.5 L21.75,23.5 C22.7164983,23.5 23.5,22.7164983 23.5,21.75 L23.5,9.503 Z M21.75,4.5 L6.25,4.5 C5.28350169,4.5 4.5,5.28350169 4.5,6.25 L4.5,8.003 L23.5,8.003 L23.5,6.25 C23.5,5.28350169 22.7164983,4.5 21.75,4.5 Z\"></path>\n                    </g>\n                  </g>\n                </svg></i>\n              <!---->\n              <!---->\n            </div>\n          </div>\n          <!---->\n          <!---->\n          <div class=\"n-input__border\"></div>\n          <div class=\"n-input__state-border\"></div>\n          <!---->\n        </div>\n        <!---->\n      </div>\n      <div class=\"n-date-picker\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-icon-color-override: rgba(194, 194, 194, 1); --n-icon-color-disabled-override: rgba(209, 209, 209, 1);\">\n        <div class=\"n-input n-input--medium-size n-input--resizable n-input--stateful\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-count-text-color: rgb(118, 124, 130); --n-count-text-color-disabled: rgba(194, 194, 194, 1); --n-color: rgba(255, 255, 255, 1); --n-font-size: 14px; --n-font-weight: 400; --n-border-radius: 3px; --n-height: 34px; --n-padding-left: 12px; --n-padding-right: 12px; --n-text-color: rgb(51, 54, 57); --n-caret-color: #18a058; --n-text-decoration-color: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-focus: 1px solid #36ad6a; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-icon-size: 16px; --n-line-height-textarea: 1.6; --n-color-disabled: rgb(250, 250, 252); --n-color-focus: rgba(255, 255, 255, 1); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-loading-color: #18a058; --n-caret-color-warning: #f0a020; --n-color-focus-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-loading-color-warning: #f0a020; --n-caret-color-error: #d03050; --n-color-focus-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-loading-color-error: #d03050; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-size: 16px; --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-icon-color-hover: rgba(146, 146, 146, 1); --n-icon-color-pressed: rgba(175, 175, 175, 1); --n-icon-color-disabled: rgba(209, 209, 209, 1); --n-suffix-text-color: rgb(51, 54, 57);\" tabindex=\"0\">\n          <div class=\"n-input-wrapper\">\n            <!---->\n            <div class=\"n-input__input\"><input type=\"text\" class=\"n-input__input-el\" tabindex=\"-1\" placeholder=\"Ayi seçin\" size=\"20\" value=\"1970-01\">\n              <!---->\n              <!---->\n            </div>\n            <div class=\"n-input__suffix\">\n              <!---->\n              <!---->\n              <!----><i class=\"n-base-icon n-date-picker-icon\"><svg width=\"28px\" height=\"28px\" viewBox=\"0 0 28 28\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n                  <g stroke=\"none\" stroke-width=\"1\" fill-rule=\"evenodd\">\n                    <g fill-rule=\"nonzero\">\n                      <path d=\"M21.75,3 C23.5449254,3 25,4.45507456 25,6.25 L25,21.75 C25,23.5449254 23.5449254,25 21.75,25 L6.25,25 C4.45507456,25 3,23.5449254 3,21.75 L3,6.25 C3,4.45507456 4.45507456,3 6.25,3 L21.75,3 Z M23.5,9.503 L4.5,9.503 L4.5,21.75 C4.5,22.7164983 5.28350169,23.5 6.25,23.5 L21.75,23.5 C22.7164983,23.5 23.5,22.7164983 23.5,21.75 L23.5,9.503 Z M21.75,4.5 L6.25,4.5 C5.28350169,4.5 4.5,5.28350169 4.5,6.25 L4.5,8.003 L23.5,8.003 L23.5,6.25 C23.5,5.28350169 22.7164983,4.5 21.75,4.5 Z\"></path>\n                    </g>\n                  </g>\n                </svg></i>\n              <!---->\n              <!---->\n            </div>\n          </div>\n          <!---->\n          <!---->\n          <div class=\"n-input__border\"></div>\n          <div class=\"n-input__state-border\"></div>\n          <!---->\n        </div>\n        <!---->\n      </div>\n    </div>\n  </div>\n</div>\"\n`;\n\nexports[`locale > works 30`] = `\n\"<div class=\"n-config-provider\">\n  <div>\n    <div class=\"n-input n-input--medium-size n-input--resizable n-input--stateful\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-count-text-color: rgb(118, 124, 130); --n-count-text-color-disabled: rgba(194, 194, 194, 1); --n-color: rgba(255, 255, 255, 1); --n-font-size: 14px; --n-font-weight: 400; --n-border-radius: 3px; --n-height: 34px; --n-padding-left: 12px; --n-padding-right: 12px; --n-text-color: rgb(51, 54, 57); --n-caret-color: #18a058; --n-text-decoration-color: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-focus: 1px solid #36ad6a; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-icon-size: 16px; --n-line-height-textarea: 1.6; --n-color-disabled: rgb(250, 250, 252); --n-color-focus: rgba(255, 255, 255, 1); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-loading-color: #18a058; --n-caret-color-warning: #f0a020; --n-color-focus-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-loading-color-warning: #f0a020; --n-caret-color-error: #d03050; --n-color-focus-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-loading-color-error: #d03050; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-size: 16px; --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-icon-color-hover: rgba(146, 146, 146, 1); --n-icon-color-pressed: rgba(175, 175, 175, 1); --n-icon-color-disabled: rgba(209, 209, 209, 1); --n-suffix-text-color: rgb(51, 54, 57);\">\n      <div class=\"n-input-wrapper\">\n        <!---->\n        <div class=\"n-input__input\"><input type=\"text\" class=\"n-input__input-el\" placeholder=\"كىرگۈزۈڭ\" size=\"20\">\n          <div class=\"n-input__placeholder\"><span>كىرگۈزۈڭ</span></div>\n          <!---->\n        </div>\n        <!---->\n      </div>\n      <!---->\n      <!---->\n      <div class=\"n-input__border\"></div>\n      <div class=\"n-input__state-border\"></div>\n      <!---->\n    </div>\n    <div>\n      <div class=\"n-date-picker\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-icon-color-override: rgba(194, 194, 194, 1); --n-icon-color-disabled-override: rgba(209, 209, 209, 1);\">\n        <div class=\"n-input n-input--medium-size n-input--resizable n-input--stateful\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-count-text-color: rgb(118, 124, 130); --n-count-text-color-disabled: rgba(194, 194, 194, 1); --n-color: rgba(255, 255, 255, 1); --n-font-size: 14px; --n-font-weight: 400; --n-border-radius: 3px; --n-height: 34px; --n-padding-left: 12px; --n-padding-right: 12px; --n-text-color: rgb(51, 54, 57); --n-caret-color: #18a058; --n-text-decoration-color: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-focus: 1px solid #36ad6a; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-icon-size: 16px; --n-line-height-textarea: 1.6; --n-color-disabled: rgb(250, 250, 252); --n-color-focus: rgba(255, 255, 255, 1); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-loading-color: #18a058; --n-caret-color-warning: #f0a020; --n-color-focus-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-loading-color-warning: #f0a020; --n-caret-color-error: #d03050; --n-color-focus-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-loading-color-error: #d03050; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-size: 16px; --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-icon-color-hover: rgba(146, 146, 146, 1); --n-icon-color-pressed: rgba(175, 175, 175, 1); --n-icon-color-disabled: rgba(209, 209, 209, 1); --n-suffix-text-color: rgb(51, 54, 57);\" tabindex=\"0\">\n          <div class=\"n-input-wrapper\">\n            <!---->\n            <div class=\"n-input__input\"><input type=\"text\" class=\"n-input__input-el\" tabindex=\"-1\" placeholder=\"چىسلا تاللاڭ\" size=\"20\" value=\"1970-01-01\">\n              <!---->\n              <!---->\n            </div>\n            <div class=\"n-input__suffix\">\n              <!---->\n              <!---->\n              <!----><i class=\"n-base-icon n-date-picker-icon\"><svg width=\"28px\" height=\"28px\" viewBox=\"0 0 28 28\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n                  <g stroke=\"none\" stroke-width=\"1\" fill-rule=\"evenodd\">\n                    <g fill-rule=\"nonzero\">\n                      <path d=\"M21.75,3 C23.5449254,3 25,4.45507456 25,6.25 L25,21.75 C25,23.5449254 23.5449254,25 21.75,25 L6.25,25 C4.45507456,25 3,23.5449254 3,21.75 L3,6.25 C3,4.45507456 4.45507456,3 6.25,3 L21.75,3 Z M23.5,9.503 L4.5,9.503 L4.5,21.75 C4.5,22.7164983 5.28350169,23.5 6.25,23.5 L21.75,23.5 C22.7164983,23.5 23.5,22.7164983 23.5,21.75 L23.5,9.503 Z M21.75,4.5 L6.25,4.5 C5.28350169,4.5 4.5,5.28350169 4.5,6.25 L4.5,8.003 L23.5,8.003 L23.5,6.25 C23.5,5.28350169 22.7164983,4.5 21.75,4.5 Z\"></path>\n                    </g>\n                  </g>\n                </svg></i>\n              <!---->\n              <!---->\n            </div>\n          </div>\n          <!---->\n          <!---->\n          <div class=\"n-input__border\"></div>\n          <div class=\"n-input__state-border\"></div>\n          <!---->\n        </div>\n        <!---->\n      </div>\n      <div class=\"n-date-picker\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-icon-color-override: rgba(194, 194, 194, 1); --n-icon-color-disabled-override: rgba(209, 209, 209, 1);\">\n        <div class=\"n-input n-input--medium-size n-input--resizable n-input--stateful\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-count-text-color: rgb(118, 124, 130); --n-count-text-color-disabled: rgba(194, 194, 194, 1); --n-color: rgba(255, 255, 255, 1); --n-font-size: 14px; --n-font-weight: 400; --n-border-radius: 3px; --n-height: 34px; --n-padding-left: 12px; --n-padding-right: 12px; --n-text-color: rgb(51, 54, 57); --n-caret-color: #18a058; --n-text-decoration-color: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-focus: 1px solid #36ad6a; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-icon-size: 16px; --n-line-height-textarea: 1.6; --n-color-disabled: rgb(250, 250, 252); --n-color-focus: rgba(255, 255, 255, 1); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-loading-color: #18a058; --n-caret-color-warning: #f0a020; --n-color-focus-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-loading-color-warning: #f0a020; --n-caret-color-error: #d03050; --n-color-focus-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-loading-color-error: #d03050; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-size: 16px; --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-icon-color-hover: rgba(146, 146, 146, 1); --n-icon-color-pressed: rgba(175, 175, 175, 1); --n-icon-color-disabled: rgba(209, 209, 209, 1); --n-suffix-text-color: rgb(51, 54, 57);\" tabindex=\"0\">\n          <div class=\"n-input-wrapper\">\n            <!---->\n            <div class=\"n-input__input\"><input type=\"text\" class=\"n-input__input-el\" tabindex=\"-1\" placeholder=\"چىسلا ۋاقىت تاللاڭ\" size=\"20\" value=\"1970-01-01 08:00:00\">\n              <!---->\n              <!---->\n            </div>\n            <div class=\"n-input__suffix\">\n              <!---->\n              <!---->\n              <!----><i class=\"n-base-icon n-date-picker-icon\"><svg width=\"28px\" height=\"28px\" viewBox=\"0 0 28 28\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n                  <g stroke=\"none\" stroke-width=\"1\" fill-rule=\"evenodd\">\n                    <g fill-rule=\"nonzero\">\n                      <path d=\"M21.75,3 C23.5449254,3 25,4.45507456 25,6.25 L25,21.75 C25,23.5449254 23.5449254,25 21.75,25 L6.25,25 C4.45507456,25 3,23.5449254 3,21.75 L3,6.25 C3,4.45507456 4.45507456,3 6.25,3 L21.75,3 Z M23.5,9.503 L4.5,9.503 L4.5,21.75 C4.5,22.7164983 5.28350169,23.5 6.25,23.5 L21.75,23.5 C22.7164983,23.5 23.5,22.7164983 23.5,21.75 L23.5,9.503 Z M21.75,4.5 L6.25,4.5 C5.28350169,4.5 4.5,5.28350169 4.5,6.25 L4.5,8.003 L23.5,8.003 L23.5,6.25 C23.5,5.28350169 22.7164983,4.5 21.75,4.5 Z\"></path>\n                    </g>\n                  </g>\n                </svg></i>\n              <!---->\n              <!---->\n            </div>\n          </div>\n          <!---->\n          <!---->\n          <div class=\"n-input__border\"></div>\n          <div class=\"n-input__state-border\"></div>\n          <!---->\n        </div>\n        <!---->\n      </div>\n      <div class=\"n-date-picker\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-icon-color-override: rgba(194, 194, 194, 1); --n-icon-color-disabled-override: rgba(209, 209, 209, 1);\">\n        <div class=\"n-input n-input--medium-size n-input--resizable n-input--stateful\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-count-text-color: rgb(118, 124, 130); --n-count-text-color-disabled: rgba(194, 194, 194, 1); --n-color: rgba(255, 255, 255, 1); --n-font-size: 14px; --n-font-weight: 400; --n-border-radius: 3px; --n-height: 34px; --n-padding-left: 12px; --n-padding-right: 12px; --n-text-color: rgb(51, 54, 57); --n-caret-color: #18a058; --n-text-decoration-color: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-focus: 1px solid #36ad6a; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-icon-size: 16px; --n-line-height-textarea: 1.6; --n-color-disabled: rgb(250, 250, 252); --n-color-focus: rgba(255, 255, 255, 1); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-loading-color: #18a058; --n-caret-color-warning: #f0a020; --n-color-focus-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-loading-color-warning: #f0a020; --n-caret-color-error: #d03050; --n-color-focus-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-loading-color-error: #d03050; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-size: 16px; --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-icon-color-hover: rgba(146, 146, 146, 1); --n-icon-color-pressed: rgba(175, 175, 175, 1); --n-icon-color-disabled: rgba(209, 209, 209, 1); --n-suffix-text-color: rgb(51, 54, 57);\" tabindex=\"0\">\n          <div class=\"n-input-wrapper\">\n            <!---->\n            <div class=\"n-input__input\"><input type=\"text\" class=\"n-input__input-el\" tabindex=\"-1\" placeholder=\"يىل تاللاڭ\" size=\"20\" value=\"1970\">\n              <!---->\n              <!---->\n            </div>\n            <div class=\"n-input__suffix\">\n              <!---->\n              <!---->\n              <!----><i class=\"n-base-icon n-date-picker-icon\"><svg width=\"28px\" height=\"28px\" viewBox=\"0 0 28 28\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n                  <g stroke=\"none\" stroke-width=\"1\" fill-rule=\"evenodd\">\n                    <g fill-rule=\"nonzero\">\n                      <path d=\"M21.75,3 C23.5449254,3 25,4.45507456 25,6.25 L25,21.75 C25,23.5449254 23.5449254,25 21.75,25 L6.25,25 C4.45507456,25 3,23.5449254 3,21.75 L3,6.25 C3,4.45507456 4.45507456,3 6.25,3 L21.75,3 Z M23.5,9.503 L4.5,9.503 L4.5,21.75 C4.5,22.7164983 5.28350169,23.5 6.25,23.5 L21.75,23.5 C22.7164983,23.5 23.5,22.7164983 23.5,21.75 L23.5,9.503 Z M21.75,4.5 L6.25,4.5 C5.28350169,4.5 4.5,5.28350169 4.5,6.25 L4.5,8.003 L23.5,8.003 L23.5,6.25 C23.5,5.28350169 22.7164983,4.5 21.75,4.5 Z\"></path>\n                    </g>\n                  </g>\n                </svg></i>\n              <!---->\n              <!---->\n            </div>\n          </div>\n          <!---->\n          <!---->\n          <div class=\"n-input__border\"></div>\n          <div class=\"n-input__state-border\"></div>\n          <!---->\n        </div>\n        <!---->\n      </div>\n      <div class=\"n-date-picker\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-icon-color-override: rgba(194, 194, 194, 1); --n-icon-color-disabled-override: rgba(209, 209, 209, 1);\">\n        <div class=\"n-input n-input--medium-size n-input--resizable n-input--stateful\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-count-text-color: rgb(118, 124, 130); --n-count-text-color-disabled: rgba(194, 194, 194, 1); --n-color: rgba(255, 255, 255, 1); --n-font-size: 14px; --n-font-weight: 400; --n-border-radius: 3px; --n-height: 34px; --n-padding-left: 12px; --n-padding-right: 12px; --n-text-color: rgb(51, 54, 57); --n-caret-color: #18a058; --n-text-decoration-color: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-focus: 1px solid #36ad6a; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-icon-size: 16px; --n-line-height-textarea: 1.6; --n-color-disabled: rgb(250, 250, 252); --n-color-focus: rgba(255, 255, 255, 1); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-loading-color: #18a058; --n-caret-color-warning: #f0a020; --n-color-focus-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-loading-color-warning: #f0a020; --n-caret-color-error: #d03050; --n-color-focus-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-loading-color-error: #d03050; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-size: 16px; --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-icon-color-hover: rgba(146, 146, 146, 1); --n-icon-color-pressed: rgba(175, 175, 175, 1); --n-icon-color-disabled: rgba(209, 209, 209, 1); --n-suffix-text-color: rgb(51, 54, 57);\" tabindex=\"0\">\n          <div class=\"n-input-wrapper\">\n            <!---->\n            <div class=\"n-input__input\"><input type=\"text\" class=\"n-input__input-el\" tabindex=\"-1\" placeholder=\"ئاي تاللاڭ\" size=\"20\" value=\"1970-01\">\n              <!---->\n              <!---->\n            </div>\n            <div class=\"n-input__suffix\">\n              <!---->\n              <!---->\n              <!----><i class=\"n-base-icon n-date-picker-icon\"><svg width=\"28px\" height=\"28px\" viewBox=\"0 0 28 28\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n                  <g stroke=\"none\" stroke-width=\"1\" fill-rule=\"evenodd\">\n                    <g fill-rule=\"nonzero\">\n                      <path d=\"M21.75,3 C23.5449254,3 25,4.45507456 25,6.25 L25,21.75 C25,23.5449254 23.5449254,25 21.75,25 L6.25,25 C4.45507456,25 3,23.5449254 3,21.75 L3,6.25 C3,4.45507456 4.45507456,3 6.25,3 L21.75,3 Z M23.5,9.503 L4.5,9.503 L4.5,21.75 C4.5,22.7164983 5.28350169,23.5 6.25,23.5 L21.75,23.5 C22.7164983,23.5 23.5,22.7164983 23.5,21.75 L23.5,9.503 Z M21.75,4.5 L6.25,4.5 C5.28350169,4.5 4.5,5.28350169 4.5,6.25 L4.5,8.003 L23.5,8.003 L23.5,6.25 C23.5,5.28350169 22.7164983,4.5 21.75,4.5 Z\"></path>\n                    </g>\n                  </g>\n                </svg></i>\n              <!---->\n              <!---->\n            </div>\n          </div>\n          <!---->\n          <!---->\n          <div class=\"n-input__border\"></div>\n          <div class=\"n-input__state-border\"></div>\n          <!---->\n        </div>\n        <!---->\n      </div>\n    </div>\n  </div>\n</div>\"\n`;\n\nexports[`locale > works 31`] = `\n\"<div class=\"n-config-provider\">\n  <div>\n    <div class=\"n-input n-input--medium-size n-input--resizable n-input--stateful\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-count-text-color: rgb(118, 124, 130); --n-count-text-color-disabled: rgba(194, 194, 194, 1); --n-color: rgba(255, 255, 255, 1); --n-font-size: 14px; --n-font-weight: 400; --n-border-radius: 3px; --n-height: 34px; --n-padding-left: 12px; --n-padding-right: 12px; --n-text-color: rgb(51, 54, 57); --n-caret-color: #18a058; --n-text-decoration-color: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-focus: 1px solid #36ad6a; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-icon-size: 16px; --n-line-height-textarea: 1.6; --n-color-disabled: rgb(250, 250, 252); --n-color-focus: rgba(255, 255, 255, 1); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-loading-color: #18a058; --n-caret-color-warning: #f0a020; --n-color-focus-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-loading-color-warning: #f0a020; --n-caret-color-error: #d03050; --n-color-focus-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-loading-color-error: #d03050; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-size: 16px; --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-icon-color-hover: rgba(146, 146, 146, 1); --n-icon-color-pressed: rgba(175, 175, 175, 1); --n-icon-color-disabled: rgba(209, 209, 209, 1); --n-suffix-text-color: rgb(51, 54, 57);\">\n      <div class=\"n-input-wrapper\">\n        <!---->\n        <div class=\"n-input__input\"><input type=\"text\" class=\"n-input__input-el\" placeholder=\"Udfyld venligst\" size=\"20\">\n          <div class=\"n-input__placeholder\"><span>Udfyld venligst</span></div>\n          <!---->\n        </div>\n        <!---->\n      </div>\n      <!---->\n      <!---->\n      <div class=\"n-input__border\"></div>\n      <div class=\"n-input__state-border\"></div>\n      <!---->\n    </div>\n    <div>\n      <div class=\"n-date-picker\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-icon-color-override: rgba(194, 194, 194, 1); --n-icon-color-disabled-override: rgba(209, 209, 209, 1);\">\n        <div class=\"n-input n-input--medium-size n-input--resizable n-input--stateful\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-count-text-color: rgb(118, 124, 130); --n-count-text-color-disabled: rgba(194, 194, 194, 1); --n-color: rgba(255, 255, 255, 1); --n-font-size: 14px; --n-font-weight: 400; --n-border-radius: 3px; --n-height: 34px; --n-padding-left: 12px; --n-padding-right: 12px; --n-text-color: rgb(51, 54, 57); --n-caret-color: #18a058; --n-text-decoration-color: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-focus: 1px solid #36ad6a; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-icon-size: 16px; --n-line-height-textarea: 1.6; --n-color-disabled: rgb(250, 250, 252); --n-color-focus: rgba(255, 255, 255, 1); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-loading-color: #18a058; --n-caret-color-warning: #f0a020; --n-color-focus-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-loading-color-warning: #f0a020; --n-caret-color-error: #d03050; --n-color-focus-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-loading-color-error: #d03050; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-size: 16px; --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-icon-color-hover: rgba(146, 146, 146, 1); --n-icon-color-pressed: rgba(175, 175, 175, 1); --n-icon-color-disabled: rgba(209, 209, 209, 1); --n-suffix-text-color: rgb(51, 54, 57);\" tabindex=\"0\">\n          <div class=\"n-input-wrapper\">\n            <!---->\n            <div class=\"n-input__input\"><input type=\"text\" class=\"n-input__input-el\" tabindex=\"-1\" placeholder=\"Vælg dato\" size=\"20\" value=\"1970-01-01\">\n              <!---->\n              <!---->\n            </div>\n            <div class=\"n-input__suffix\">\n              <!---->\n              <!---->\n              <!----><i class=\"n-base-icon n-date-picker-icon\"><svg width=\"28px\" height=\"28px\" viewBox=\"0 0 28 28\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n                  <g stroke=\"none\" stroke-width=\"1\" fill-rule=\"evenodd\">\n                    <g fill-rule=\"nonzero\">\n                      <path d=\"M21.75,3 C23.5449254,3 25,4.45507456 25,6.25 L25,21.75 C25,23.5449254 23.5449254,25 21.75,25 L6.25,25 C4.45507456,25 3,23.5449254 3,21.75 L3,6.25 C3,4.45507456 4.45507456,3 6.25,3 L21.75,3 Z M23.5,9.503 L4.5,9.503 L4.5,21.75 C4.5,22.7164983 5.28350169,23.5 6.25,23.5 L21.75,23.5 C22.7164983,23.5 23.5,22.7164983 23.5,21.75 L23.5,9.503 Z M21.75,4.5 L6.25,4.5 C5.28350169,4.5 4.5,5.28350169 4.5,6.25 L4.5,8.003 L23.5,8.003 L23.5,6.25 C23.5,5.28350169 22.7164983,4.5 21.75,4.5 Z\"></path>\n                    </g>\n                  </g>\n                </svg></i>\n              <!---->\n              <!---->\n            </div>\n          </div>\n          <!---->\n          <!---->\n          <div class=\"n-input__border\"></div>\n          <div class=\"n-input__state-border\"></div>\n          <!---->\n        </div>\n        <!---->\n      </div>\n      <div class=\"n-date-picker\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-icon-color-override: rgba(194, 194, 194, 1); --n-icon-color-disabled-override: rgba(209, 209, 209, 1);\">\n        <div class=\"n-input n-input--medium-size n-input--resizable n-input--stateful\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-count-text-color: rgb(118, 124, 130); --n-count-text-color-disabled: rgba(194, 194, 194, 1); --n-color: rgba(255, 255, 255, 1); --n-font-size: 14px; --n-font-weight: 400; --n-border-radius: 3px; --n-height: 34px; --n-padding-left: 12px; --n-padding-right: 12px; --n-text-color: rgb(51, 54, 57); --n-caret-color: #18a058; --n-text-decoration-color: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-focus: 1px solid #36ad6a; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-icon-size: 16px; --n-line-height-textarea: 1.6; --n-color-disabled: rgb(250, 250, 252); --n-color-focus: rgba(255, 255, 255, 1); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-loading-color: #18a058; --n-caret-color-warning: #f0a020; --n-color-focus-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-loading-color-warning: #f0a020; --n-caret-color-error: #d03050; --n-color-focus-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-loading-color-error: #d03050; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-size: 16px; --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-icon-color-hover: rgba(146, 146, 146, 1); --n-icon-color-pressed: rgba(175, 175, 175, 1); --n-icon-color-disabled: rgba(209, 209, 209, 1); --n-suffix-text-color: rgb(51, 54, 57);\" tabindex=\"0\">\n          <div class=\"n-input-wrapper\">\n            <!---->\n            <div class=\"n-input__input\"><input type=\"text\" class=\"n-input__input-el\" tabindex=\"-1\" placeholder=\"Vælg dato og tid\" size=\"20\" value=\"1970-01-01 08:00:00\">\n              <!---->\n              <!---->\n            </div>\n            <div class=\"n-input__suffix\">\n              <!---->\n              <!---->\n              <!----><i class=\"n-base-icon n-date-picker-icon\"><svg width=\"28px\" height=\"28px\" viewBox=\"0 0 28 28\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n                  <g stroke=\"none\" stroke-width=\"1\" fill-rule=\"evenodd\">\n                    <g fill-rule=\"nonzero\">\n                      <path d=\"M21.75,3 C23.5449254,3 25,4.45507456 25,6.25 L25,21.75 C25,23.5449254 23.5449254,25 21.75,25 L6.25,25 C4.45507456,25 3,23.5449254 3,21.75 L3,6.25 C3,4.45507456 4.45507456,3 6.25,3 L21.75,3 Z M23.5,9.503 L4.5,9.503 L4.5,21.75 C4.5,22.7164983 5.28350169,23.5 6.25,23.5 L21.75,23.5 C22.7164983,23.5 23.5,22.7164983 23.5,21.75 L23.5,9.503 Z M21.75,4.5 L6.25,4.5 C5.28350169,4.5 4.5,5.28350169 4.5,6.25 L4.5,8.003 L23.5,8.003 L23.5,6.25 C23.5,5.28350169 22.7164983,4.5 21.75,4.5 Z\"></path>\n                    </g>\n                  </g>\n                </svg></i>\n              <!---->\n              <!---->\n            </div>\n          </div>\n          <!---->\n          <!---->\n          <div class=\"n-input__border\"></div>\n          <div class=\"n-input__state-border\"></div>\n          <!---->\n        </div>\n        <!---->\n      </div>\n      <div class=\"n-date-picker\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-icon-color-override: rgba(194, 194, 194, 1); --n-icon-color-disabled-override: rgba(209, 209, 209, 1);\">\n        <div class=\"n-input n-input--medium-size n-input--resizable n-input--stateful\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-count-text-color: rgb(118, 124, 130); --n-count-text-color-disabled: rgba(194, 194, 194, 1); --n-color: rgba(255, 255, 255, 1); --n-font-size: 14px; --n-font-weight: 400; --n-border-radius: 3px; --n-height: 34px; --n-padding-left: 12px; --n-padding-right: 12px; --n-text-color: rgb(51, 54, 57); --n-caret-color: #18a058; --n-text-decoration-color: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-focus: 1px solid #36ad6a; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-icon-size: 16px; --n-line-height-textarea: 1.6; --n-color-disabled: rgb(250, 250, 252); --n-color-focus: rgba(255, 255, 255, 1); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-loading-color: #18a058; --n-caret-color-warning: #f0a020; --n-color-focus-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-loading-color-warning: #f0a020; --n-caret-color-error: #d03050; --n-color-focus-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-loading-color-error: #d03050; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-size: 16px; --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-icon-color-hover: rgba(146, 146, 146, 1); --n-icon-color-pressed: rgba(175, 175, 175, 1); --n-icon-color-disabled: rgba(209, 209, 209, 1); --n-suffix-text-color: rgb(51, 54, 57);\" tabindex=\"0\">\n          <div class=\"n-input-wrapper\">\n            <!---->\n            <div class=\"n-input__input\"><input type=\"text\" class=\"n-input__input-el\" tabindex=\"-1\" placeholder=\"Vælg år\" size=\"20\" value=\"1970\">\n              <!---->\n              <!---->\n            </div>\n            <div class=\"n-input__suffix\">\n              <!---->\n              <!---->\n              <!----><i class=\"n-base-icon n-date-picker-icon\"><svg width=\"28px\" height=\"28px\" viewBox=\"0 0 28 28\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n                  <g stroke=\"none\" stroke-width=\"1\" fill-rule=\"evenodd\">\n                    <g fill-rule=\"nonzero\">\n                      <path d=\"M21.75,3 C23.5449254,3 25,4.45507456 25,6.25 L25,21.75 C25,23.5449254 23.5449254,25 21.75,25 L6.25,25 C4.45507456,25 3,23.5449254 3,21.75 L3,6.25 C3,4.45507456 4.45507456,3 6.25,3 L21.75,3 Z M23.5,9.503 L4.5,9.503 L4.5,21.75 C4.5,22.7164983 5.28350169,23.5 6.25,23.5 L21.75,23.5 C22.7164983,23.5 23.5,22.7164983 23.5,21.75 L23.5,9.503 Z M21.75,4.5 L6.25,4.5 C5.28350169,4.5 4.5,5.28350169 4.5,6.25 L4.5,8.003 L23.5,8.003 L23.5,6.25 C23.5,5.28350169 22.7164983,4.5 21.75,4.5 Z\"></path>\n                    </g>\n                  </g>\n                </svg></i>\n              <!---->\n              <!---->\n            </div>\n          </div>\n          <!---->\n          <!---->\n          <div class=\"n-input__border\"></div>\n          <div class=\"n-input__state-border\"></div>\n          <!---->\n        </div>\n        <!---->\n      </div>\n      <div class=\"n-date-picker\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-icon-color-override: rgba(194, 194, 194, 1); --n-icon-color-disabled-override: rgba(209, 209, 209, 1);\">\n        <div class=\"n-input n-input--medium-size n-input--resizable n-input--stateful\" style=\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-count-text-color: rgb(118, 124, 130); --n-count-text-color-disabled: rgba(194, 194, 194, 1); --n-color: rgba(255, 255, 255, 1); --n-font-size: 14px; --n-font-weight: 400; --n-border-radius: 3px; --n-height: 34px; --n-padding-left: 12px; --n-padding-right: 12px; --n-text-color: rgb(51, 54, 57); --n-caret-color: #18a058; --n-text-decoration-color: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-focus: 1px solid #36ad6a; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-icon-size: 16px; --n-line-height-textarea: 1.6; --n-color-disabled: rgb(250, 250, 252); --n-color-focus: rgba(255, 255, 255, 1); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-loading-color: #18a058; --n-caret-color-warning: #f0a020; --n-color-focus-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-loading-color-warning: #f0a020; --n-caret-color-error: #d03050; --n-color-focus-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-loading-color-error: #d03050; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-size: 16px; --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-icon-color-hover: rgba(146, 146, 146, 1); --n-icon-color-pressed: rgba(175, 175, 175, 1); --n-icon-color-disabled: rgba(209, 209, 209, 1); --n-suffix-text-color: rgb(51, 54, 57);\" tabindex=\"0\">\n          <div class=\"n-input-wrapper\">\n            <!---->\n            <div class=\"n-input__input\"><input type=\"text\" class=\"n-input__input-el\" tabindex=\"-1\" placeholder=\"Vælg måned\" size=\"20\" value=\"1970-01\">\n              <!---->\n              <!---->\n            </div>\n            <div class=\"n-input__suffix\">\n              <!---->\n              <!---->\n              <!----><i class=\"n-base-icon n-date-picker-icon\"><svg width=\"28px\" height=\"28px\" viewBox=\"0 0 28 28\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n                  <g stroke=\"none\" stroke-width=\"1\" fill-rule=\"evenodd\">\n                    <g fill-rule=\"nonzero\">\n                      <path d=\"M21.75,3 C23.5449254,3 25,4.45507456 25,6.25 L25,21.75 C25,23.5449254 23.5449254,25 21.75,25 L6.25,25 C4.45507456,25 3,23.5449254 3,21.75 L3,6.25 C3,4.45507456 4.45507456,3 6.25,3 L21.75,3 Z M23.5,9.503 L4.5,9.503 L4.5,21.75 C4.5,22.7164983 5.28350169,23.5 6.25,23.5 L21.75,23.5 C22.7164983,23.5 23.5,22.7164983 23.5,21.75 L23.5,9.503 Z M21.75,4.5 L6.25,4.5 C5.28350169,4.5 4.5,5.28350169 4.5,6.25 L4.5,8.003 L23.5,8.003 L23.5,6.25 C23.5,5.28350169 22.7164983,4.5 21.75,4.5 Z\"></path>\n                    </g>\n                  </g>\n                </svg></i>\n              <!---->\n              <!---->\n            </div>\n          </div>\n          <!---->\n          <!---->\n          <div class=\"n-input__border\"></div>\n          <div class=\"n-input__state-border\"></div>\n          <!---->\n        </div>\n        <!---->\n      </div>\n    </div>\n  </div>\n</div>\"\n`;\n"
  },
  {
    "path": "src/locales/common/arDZ.ts",
    "content": "import type { NLocale } from './enUS'\n\nconst arDZ: NLocale = {\n  name: 'ar-DZ',\n  global: {\n    undo: 'تراجع',\n    redo: 'إعادة',\n    confirm: 'تأكيد',\n    clear: 'مسح'\n  },\n  Popconfirm: {\n    positiveText: 'تأكيد',\n    negativeText: 'إلغاء'\n  },\n  Cascader: {\n    placeholder: 'يرجى التحديد',\n    loading: 'جاري التحميل',\n    loadingRequiredMessage: (label: string): string =>\n      `يرجى تحميل جميع الـ ${label} الفرعية قبل التحقق منها.`\n  },\n  Time: {\n    dateFormat: 'yyyy-MM-dd',\n    dateTimeFormat: 'yyyy-MM-dd HH:mm:ss'\n  },\n  DatePicker: {\n    yearFormat: 'yyyy',\n    monthFormat: 'MMM',\n    dayFormat: 'eeeeee',\n    yearTypeFormat: 'yyyy',\n    monthTypeFormat: 'yyyy-MM',\n    dateFormat: 'yyyy-MM-dd',\n    dateTimeFormat: 'yyyy-MM-dd HH:mm:ss',\n    quarterFormat: 'yyyy-qqq',\n    weekFormat: 'YYYY-w',\n    clear: 'مسح',\n    now: 'الآن',\n    confirm: 'تأكيد',\n    selectTime: 'إختيار الوقت',\n    selectDate: 'إختيار التاريخ',\n    datePlaceholder: 'إختيار التاريخ',\n    datetimePlaceholder: 'إختيار التاريخ والوقت',\n    monthPlaceholder: 'إختيار الشهر',\n    yearPlaceholder: 'إختيار السنة',\n    quarterPlaceholder: 'إختيار الربع',\n    weekPlaceholder: 'Select Week',\n    startDatePlaceholder: 'تاريخ البدء',\n    endDatePlaceholder: 'تاريخ الإنتهاء',\n    startDatetimePlaceholder: 'تاريخ ووقت البدء',\n    endDatetimePlaceholder: 'تاريخ ووقت الإنتهاء',\n    startMonthPlaceholder: 'شهر البدء',\n    endMonthPlaceholder: 'شهر الإنتهاء',\n    monthBeforeYear: true,\n    firstDayOfWeek: 6 as 0 | 1 | 2 | 3 | 4 | 5 | 6,\n    today: 'اليوم'\n  },\n  DataTable: {\n    checkTableAll: 'تحديد كل العناصر في الجدول',\n    uncheckTableAll: 'إلغاء تحديد كل العناصر في الجدول',\n    confirm: 'تأكيد',\n    clear: 'مسح'\n  },\n  LegacyTransfer: {\n    sourceTitle: 'المصدر',\n    targetTitle: 'الهدف'\n  },\n  Transfer: {\n    selectAll: 'تحديد الكل',\n    unselectAll: 'إلغاء تحديد الكل',\n    clearAll: 'مسح',\n    total: (num: number): string => `إجمالي ${num} عنصر`,\n    selected: (num: number): string => `${num} عنصر محدد`\n  },\n  Empty: {\n    description: 'لا توجد بيانات'\n  },\n  Select: {\n    placeholder: 'يرجى الإختيار'\n  },\n  TimePicker: {\n    placeholder: 'إختيار الوقت',\n    positiveText: 'تأكيد',\n    negativeText: 'إلغاء',\n    now: 'الآن',\n    clear: 'مسح'\n  },\n  Pagination: {\n    goto: 'إذهب إلى',\n    selectionSuffix: 'صفحة'\n  },\n  DynamicTags: {\n    add: 'إضافة'\n  },\n  Log: {\n    loading: 'جاري التحميل'\n  },\n  Input: {\n    placeholder: 'يرجى الإدخال'\n  },\n  InputNumber: {\n    placeholder: 'يرجى الإدخال'\n  },\n  DynamicInput: {\n    create: 'إنشاء'\n  },\n  ThemeEditor: {\n    title: 'محرر النمط',\n    clearAllVars: 'مسح جميع المتغيرات',\n    clearSearch: 'مسح البحث',\n    filterCompName: 'تصفية إسم المكون',\n    filterVarName: 'تصفية إسم المتغير',\n    import: 'إستيراد',\n    export: 'تصدير',\n    restore: 'إعادة تعيين إلى الإفتراضي'\n  },\n  Image: {\n    tipPrevious: '(→) الصورة السابقة',\n    tipNext: '(←) الصورة التالية',\n    tipCounterclockwise: 'عكس عقارب الساعة',\n    tipClockwise: 'إتجاه عقارب الساعة',\n    tipZoomOut: 'تكبير',\n    tipZoomIn: 'تصغير',\n    tipDownload: 'للتحميل',\n    tipClose: 'إغلاق (Esc زر)',\n    tipOriginalSize: 'تكبير إلى الحجم الأصلي'\n  },\n  Heatmap: {\n    less: 'less',\n    more: 'more',\n    monthFormat: 'MMM',\n    weekdayFormat: 'eeeeee'\n  }\n}\n\nexport default arDZ\n"
  },
  {
    "path": "src/locales/common/azAZ.ts",
    "content": "import type { NLocale } from './enUS'\n\nconst azAZ: NLocale = {\n  name: 'az-AZ',\n  global: {\n    undo: 'Geri al',\n    redo: 'Təkrar et',\n    confirm: 'Təsdiqlə',\n    clear: 'Təmizlə'\n  },\n  Popconfirm: {\n    positiveText: 'Təsdiqlə',\n    negativeText: 'İmtina et'\n  },\n  Cascader: {\n    placeholder: 'Zəhmət olmasa, seçin',\n    loading: 'Yüklənir',\n    loadingRequiredMessage: label =>\n      `Zəhmət olmasa, yoxlamadan əvvəl bütün ${label}ləri yükləyin.`\n  },\n  Time: {\n    dateFormat: 'yyyy-MM-dd',\n    dateTimeFormat: 'yyyy-MM-dd HH:mm:ss'\n  },\n  DatePicker: {\n    yearFormat: 'yyyy',\n    monthFormat: 'MMM',\n    dayFormat: 'eeeeee',\n    yearTypeFormat: 'yyyy',\n    monthTypeFormat: 'yyyy-MM',\n    dateFormat: 'dd MMMM yyyy',\n    dateTimeFormat: 'yyyy-MM-dd HH:mm:ss',\n    quarterFormat: 'yyyy-qqq',\n    weekFormat: 'YYYY-w',\n    clear: 'Təmizlə',\n    now: 'İndi',\n    confirm: 'Təsdiqlə',\n    selectTime: 'Vaxtı seçin',\n    selectDate: 'Tarixi seçin',\n    datePlaceholder: 'Tarixi seç',\n    datetimePlaceholder: 'Tarix və vaxtı seçin',\n    monthPlaceholder: 'Ayi seçin',\n    yearPlaceholder: 'İli seçin',\n    quarterPlaceholder: 'Rübu seçin',\n    weekPlaceholder: 'Həftəni seçin',\n    startDatePlaceholder: 'Başlanğıc tarixi',\n    endDatePlaceholder: 'Son tarix',\n    startDatetimePlaceholder: 'Başlanğıc tarixi və vaxtı',\n    endDatetimePlaceholder: 'Bitiş tarixi və vaxtı',\n    startMonthPlaceholder: 'Başlanğıc ayı',\n    endMonthPlaceholder: 'Son ay',\n    monthBeforeYear: true,\n    firstDayOfWeek: 0 as 0 | 1 | 2 | 3 | 4 | 5 | 6,\n    today: 'Bu gün'\n  },\n  DataTable: {\n    checkTableAll: 'Bütün cədvəli seç',\n    uncheckTableAll: 'Cədvəldəki bütün seçimləri ləğv et',\n    confirm: 'Təsdiqlə',\n    clear: 'Təmizlə'\n  },\n  LegacyTransfer: {\n    sourceTitle: 'Mənbə',\n    targetTitle: 'Hədəf'\n  },\n  Transfer: {\n    selectAll: 'Hamısını seç',\n    unselectAll: 'Hamısını ləğv et',\n    clearAll: 'Təmizlə',\n    total: num => `Cəmi ${num} maddə`,\n    selected: num => `${num} maddə seçildi`\n  },\n  Empty: {\n    description: 'Məlumat yoxdur'\n  },\n  Select: {\n    placeholder: 'Zəhmət olmasa, seçin'\n  },\n  TimePicker: {\n    placeholder: 'Vaxtı seçin',\n    positiveText: 'Təsdiqlə',\n    negativeText: 'İmtina et',\n    now: 'İndi',\n    clear: 'Təmizlə'\n  },\n  Pagination: {\n    goto: 'Get',\n    selectionSuffix: 'səhifə'\n  },\n  DynamicTags: {\n    add: 'Əlavə et'\n  },\n  Log: {\n    loading: 'Yüklənir'\n  },\n  Input: {\n    placeholder: 'Zəhmət olmasa, daxil edin'\n  },\n  InputNumber: {\n    placeholder: 'Zəhmət olmasa, daxil edin'\n  },\n  DynamicInput: {\n    create: 'Yarat'\n  },\n  ThemeEditor: {\n    title: 'Tema redaktoru',\n    clearAllVars: 'Bütün dəyişənləri təmizlə',\n    clearSearch: 'Axtarışı təmizlə',\n    filterCompName: 'Komponent adını filtrlə',\n    filterVarName: 'Dəyişən adını filtrlə',\n    import: 'İdxal et',\n    export: 'İxrac et',\n    restore: 'Varsayılanı bərpa et'\n  },\n  Image: {\n    tipPrevious: 'Əvvəlki şəkil (←)',\n    tipNext: 'Növbəti şəkil (→)',\n    tipCounterclockwise: 'Saat əqrəbinin əksinə',\n    tipClockwise: 'Saat əqrəbinin istiqamətində',\n    tipZoomOut: 'Uzaqlaşdır',\n    tipZoomIn: 'Yaxınlaşdır',\n    tipDownload: 'Yüklə',\n    tipClose: 'Bağla (Esc)',\n    tipOriginalSize: 'Orijinal ölçüyə yaxınlaşdır'\n  },\n  Heatmap: {\n    less: 'less',\n    more: 'more',\n    monthFormat: 'MMM',\n    weekdayFormat: 'eeeeee'\n  }\n}\n\nexport default azAZ\n"
  },
  {
    "path": "src/locales/common/csCZ.ts",
    "content": "import type { NLocale } from './enUS'\n\nconst csCZ: NLocale = {\n  name: 'cs-CZ',\n  global: {\n    undo: 'Zpět',\n    redo: 'Obnovit',\n    confirm: 'Potvrdit',\n    clear: 'Vyčistit'\n  },\n  Popconfirm: {\n    positiveText: 'Potvrdit',\n    negativeText: 'Zrušit'\n  },\n  Cascader: {\n    placeholder: 'Prosím vyberte',\n    loading: 'Načítání',\n    loadingRequiredMessage: (label: string): string =>\n      `Prosím načtěte před kontrolou všechny potomky pro ${label}.`\n  },\n  Time: {\n    dateFormat: 'd-M-yyyy',\n    dateTimeFormat: 'd-M-yyyy HH:mm:ss'\n  },\n  DatePicker: {\n    yearFormat: 'yyyy',\n    monthFormat: 'MMM',\n    dayFormat: 'EEEE',\n    yearTypeFormat: 'yyyy',\n    monthTypeFormat: 'MMM-yyyy',\n    dateFormat: 'd-M-yyyy',\n    dateTimeFormat: 'd-M-yyyy HH:mm:ss',\n    quarterFormat: 'qqq-yyyy',\n    weekFormat: 'YYYY-w',\n    clear: 'Vyčistit',\n    now: 'Teď',\n    confirm: 'Potvrdit',\n    selectTime: 'Vybrat čas',\n    selectDate: 'Vybrat datum',\n    datePlaceholder: 'Vyberte čas',\n    datetimePlaceholder: 'Vyberte datum a čas',\n    monthPlaceholder: 'Vyberte měsíc',\n    yearPlaceholder: 'Vyberte rok',\n    quarterPlaceholder: 'Vyberte čtvrtletí',\n    weekPlaceholder: 'Vyberte týden',\n    startDatePlaceholder: 'Datum začátku',\n    endDatePlaceholder: 'Datum ukončení',\n    startDatetimePlaceholder: 'Datum a čas začátku',\n    endDatetimePlaceholder: 'Datum a čas ukončení ',\n    startMonthPlaceholder: 'Začátek měsíce',\n    endMonthPlaceholder: 'Konec měsíce',\n    monthBeforeYear: true,\n    firstDayOfWeek: 6 as 0 | 1 | 2 | 3 | 4 | 5 | 6,\n    today: 'Dnes'\n  },\n  DataTable: {\n    checkTableAll: 'Vybrat vše v tabulce',\n    uncheckTableAll: 'Zrušit výběr všeho v tabulce ',\n    confirm: 'Potvrdit',\n    clear: 'Vyčistit'\n  },\n  LegacyTransfer: {\n    sourceTitle: 'Zdroj',\n    targetTitle: 'Cíl'\n  },\n  Transfer: {\n    selectAll: 'Vybrat vše',\n    unselectAll: 'Odznačit vše',\n    clearAll: 'Vyčistit',\n    total: (num: number): string => `Celkem ${num} položek`,\n    selected: (num: number): string => `${num} položek vybráno`\n  },\n  Empty: {\n    description: 'Žádná data'\n  },\n  Select: {\n    placeholder: 'Prosím vyberte'\n  },\n  TimePicker: {\n    placeholder: 'Vybrat čas',\n    positiveText: 'OK',\n    negativeText: 'Zrušit',\n    now: 'Teď',\n    clear: 'Vyčistit'\n  },\n  Pagination: {\n    goto: 'Jít na',\n    selectionSuffix: 'Strana'\n  },\n  DynamicTags: {\n    add: 'Přidat'\n  },\n  Log: {\n    loading: 'Načítání'\n  },\n  Input: {\n    placeholder: 'Zadejte'\n  },\n  InputNumber: {\n    placeholder: 'Zadejte'\n  },\n  DynamicInput: {\n    create: 'Vytvořit'\n  },\n  ThemeEditor: {\n    title: 'Editor témat',\n    clearAllVars: 'Vymazat všechny proměnné',\n    clearSearch: 'Vymazat vyhledávání',\n    filterCompName: 'Filtrovat název komponenty',\n    filterVarName: 'Filztrovat název proměnné',\n    import: 'Importovat',\n    export: 'Exportovat',\n    restore: 'Obnovit původní nastavení'\n  },\n  Image: {\n    tipPrevious: 'Předchozí obrázek (←)',\n    tipNext: 'Další obrázek (→)',\n    tipCounterclockwise: 'Proti směru hodinových ručiček',\n    tipClockwise: 'Ve směru hodinových ručiček',\n    tipZoomOut: 'Oddálit',\n    tipZoomIn: 'Přiblížit',\n    tipDownload: 'Stáhnout',\n    tipClose: 'Zavřít (Esc)',\n    tipOriginalSize: 'Přiblížit na původní velikost'\n  },\n  Heatmap: {\n    less: 'méně',\n    more: 'více',\n    monthFormat: 'MMM',\n    weekdayFormat: 'eeeeee'\n  }\n}\n\nexport default csCZ\n"
  },
  {
    "path": "src/locales/common/daDK.ts",
    "content": "import type { NLocale } from 'naive-ui'\n\nconst daDK: NLocale = {\n  name: 'da-DK',\n  global: {\n    undo: 'Fortryd',\n    redo: 'Gentag',\n    confirm: 'Bekræft',\n    clear: 'Ryd'\n  },\n  Popconfirm: {\n    positiveText: 'Bekræft',\n    negativeText: 'Annuller'\n  },\n  Cascader: {\n    placeholder: 'Vælg venligst',\n    loading: 'Indlæser',\n    loadingRequiredMessage: (label: string): string =>\n      `Indlæs venligst alle underpunkter til ${label} før du vælger punktet.`\n  },\n  Time: {\n    dateFormat: 'yyyy-MM-dd',\n    dateTimeFormat: 'yyyy-MM-dd HH:mm:ss'\n  },\n  DatePicker: {\n    yearFormat: 'yyyy',\n    monthFormat: 'MMM',\n    dayFormat: 'eeeeee',\n    yearTypeFormat: 'yyyy',\n    monthTypeFormat: 'yyyy-MM',\n    dateFormat: 'yyyy-MM-dd',\n    dateTimeFormat: 'yyyy-MM-dd HH:mm:ss',\n    quarterFormat: 'yyyy-qqq',\n    weekFormat: 'YYYY-w',\n    clear: 'Ryd',\n    now: 'Nu',\n    confirm: 'Bekræft',\n    selectTime: 'Vælg tid',\n    selectDate: 'Vælg dato',\n    datePlaceholder: 'Vælg dato',\n    datetimePlaceholder: 'Vælg dato og tid',\n    monthPlaceholder: 'Vælg måned',\n    yearPlaceholder: 'Vælg år',\n    quarterPlaceholder: 'Vælg kvartal',\n    weekPlaceholder: 'Vælg uge',\n    startDatePlaceholder: 'Startdato',\n    endDatePlaceholder: 'Slutdato',\n    startDatetimePlaceholder: 'Startdato og -tid',\n    endDatetimePlaceholder: 'Slutdato og -tid',\n    startMonthPlaceholder: 'Startmåned',\n    endMonthPlaceholder: 'Slutmåned',\n    monthBeforeYear: true,\n    firstDayOfWeek: 0 as 0 | 1 | 2 | 3 | 4 | 5 | 6,\n    today: 'I dag'\n  },\n  DataTable: {\n    checkTableAll: 'Vælg alle',\n    uncheckTableAll: 'Vælg ingen',\n    confirm: 'Bekræft',\n    clear: 'Ryd'\n  },\n  LegacyTransfer: {\n    sourceTitle: 'Kilde',\n    targetTitle: 'Mål'\n  },\n  Transfer: {\n    selectAll: 'Vælg alle',\n    unselectAll: 'Vælg ingen',\n    clearAll: 'Ryd',\n    total: (num: number): string => `I alt ${num} rækker`,\n    selected: (num: number): string => `${num} rækker valgt`\n  },\n  Empty: {\n    description: 'Ingen data'\n  },\n  Select: {\n    placeholder: 'Vælg venligst'\n  },\n  TimePicker: {\n    placeholder: 'Vælg tid',\n    positiveText: 'OK',\n    negativeText: 'Annuller',\n    now: 'Nu',\n    clear: 'Ryd'\n  },\n  Pagination: {\n    goto: 'Gå til',\n    selectionSuffix: 'side'\n  },\n  DynamicTags: {\n    add: 'Tilføj'\n  },\n  Log: {\n    loading: 'Indlæser'\n  },\n  Input: {\n    placeholder: 'Udfyld venligst'\n  },\n  InputNumber: {\n    placeholder: 'Udfyld venligst'\n  },\n  DynamicInput: {\n    create: 'Opret'\n  },\n  ThemeEditor: {\n    title: 'Temaværktøj',\n    clearAllVars: 'Nulstil alle variabler',\n    clearSearch: 'Ryd søgning',\n    filterCompName: 'Filtrer efter komponentnavn',\n    filterVarName: 'Filtrer efter variabelnavn',\n    import: 'Importér',\n    export: 'Eksportér',\n    restore: 'Nulstil til oprindelige valg'\n  },\n  Image: {\n    tipPrevious: 'Forrige billede (←)',\n    tipNext: 'Næste billede (→)',\n    tipCounterclockwise: 'Mod uret',\n    tipClockwise: 'Med uret',\n    tipZoomOut: 'Zoom ud',\n    tipZoomIn: 'Zoom ind',\n    tipDownload: 'Download',\n    tipClose: 'Luk (Esc)',\n    tipOriginalSize: 'Zoom til oprindelig størrelse'\n  },\n  Heatmap: {\n    less: 'mindre',\n    more: 'mere',\n    monthFormat: 'MMM',\n    weekdayFormat: 'eee'\n  }\n}\n\nexport default daDK\n"
  },
  {
    "path": "src/locales/common/deDE.ts",
    "content": "import type { NLocale } from './enUS'\n\nconst deDE: NLocale = {\n  name: 'de-DE',\n  global: {\n    undo: 'Rückgängig',\n    redo: 'Wiederholen',\n    confirm: 'Bestätigen',\n    clear: 'Löschen'\n  },\n  Popconfirm: {\n    positiveText: 'Bestätigen',\n    negativeText: 'Abbrechen'\n  },\n  Cascader: {\n    placeholder: 'Bitte auswählen',\n    loading: 'Wird geladen',\n    loadingRequiredMessage: (label: string): string =>\n      `Bitte laden Sie alle Unterpunkte von ${label}, bevor Sie es auswählen.`\n  },\n  Time: {\n    dateFormat: 'dd.MM.yyyy',\n    dateTimeFormat: 'dd.MM.yyyy HH:mm:ss'\n  },\n  DatePicker: {\n    yearFormat: 'yyyy',\n    monthFormat: 'MMM',\n    dayFormat: 'eeeeee',\n    yearTypeFormat: 'yyyy',\n    monthTypeFormat: 'MM-yyyy',\n    dateFormat: 'dd.MM.yyyy',\n    dateTimeFormat: 'dd.MM.yyyy HH:mm:ss',\n    quarterFormat: 'yyyy-qqq',\n    weekFormat: 'YYYY-w',\n    clear: 'Löschen',\n    now: 'Jetzt',\n    confirm: 'Bestätigen',\n    selectTime: 'Uhrzeit auswählen',\n    selectDate: 'Datum auswählen',\n    datePlaceholder: 'Datum auswählen',\n    datetimePlaceholder: 'Datum und Uhrzeit auswählen',\n    monthPlaceholder: 'Monat auswählen',\n    yearPlaceholder: 'Jahr auswählen',\n    quarterPlaceholder: 'Quartal auswählen',\n    weekPlaceholder: 'Select Week',\n    startDatePlaceholder: 'Anfangsdatum',\n    endDatePlaceholder: 'Enddatum',\n    startDatetimePlaceholder: 'Anfangsdatum und Uhrzeit',\n    endDatetimePlaceholder: 'Enddatum und Uhrzeit',\n    startMonthPlaceholder: 'Anfangsmonat',\n    endMonthPlaceholder: 'Endmonat',\n    monthBeforeYear: true,\n    firstDayOfWeek: 0 as 0 | 1 | 2 | 3 | 4 | 5 | 6,\n    today: 'Heute'\n  },\n  DataTable: {\n    checkTableAll: 'Alles auswählen',\n    uncheckTableAll: 'Auswahl aufheben',\n    confirm: 'Bestätigen',\n    clear: 'Löschen'\n  },\n  LegacyTransfer: {\n    sourceTitle: 'Quelle',\n    targetTitle: 'Ziel'\n  },\n  Transfer: {\n    selectAll: 'Alle auswählen',\n    unselectAll: 'Alle abwählen',\n    clearAll: 'Leeren',\n    total: (num: number): string => `Insgesamt ${num} Einträge`,\n    selected: (num: number): string => `${num} Einträge ausgewählt`\n  },\n  Empty: {\n    description: 'Keine Daten'\n  },\n  Select: {\n    placeholder: 'Bitte auswählen'\n  },\n  TimePicker: {\n    placeholder: 'Uhrzeit auswählen',\n    positiveText: 'OK',\n    negativeText: 'Abbrechen',\n    now: 'Jetzt',\n    clear: 'Löschen'\n  },\n  Pagination: {\n    goto: 'Gehe zu',\n    selectionSuffix: 'Seite'\n  },\n  DynamicTags: {\n    add: 'Hinzufügen'\n  },\n  Log: {\n    loading: 'Wird geladen'\n  },\n  Input: {\n    placeholder: 'Bitte ausfüllen'\n  },\n  InputNumber: {\n    placeholder: 'Bitte ausfüllen'\n  },\n  DynamicInput: {\n    create: 'Erstellen'\n  },\n  ThemeEditor: {\n    title: 'Theme Editor',\n    clearAllVars: 'Alle Variablen löschen',\n    clearSearch: 'Suche löschen',\n    filterCompName: 'Filter Komponentenname',\n    filterVarName: 'Filter Variablenname',\n    import: 'Importieren',\n    export: 'Exportieren',\n    restore: 'Auf Standard zurücksetzen'\n  },\n  Image: {\n    tipPrevious: 'Vorheriges Bild (←)',\n    tipNext: 'Nächstes Bild (→)',\n    tipCounterclockwise: 'Gegen Uhrzeigersinn',\n    tipClockwise: 'Uhrzeigersinn',\n    tipZoomOut: 'Rauszoomen',\n    tipZoomIn: 'Reinzoomen',\n    tipDownload: 'Download',\n    tipClose: 'Schließen (Esc)',\n    tipOriginalSize: 'Zoom zurücksetzen'\n  },\n  Heatmap: {\n    less: 'weniger',\n    more: 'mehr',\n    monthFormat: 'MMM',\n    weekdayFormat: 'eeeeee'\n  }\n}\n\nexport default deDE\n"
  },
  {
    "path": "src/locales/common/enGB.ts",
    "content": "import type { NLocale } from './enUS'\n\nconst enGB: NLocale = {\n  name: 'en-GB',\n  global: {\n    undo: 'Undo',\n    redo: 'Redo',\n    confirm: 'Confirm',\n    clear: 'Clear'\n  },\n  Popconfirm: {\n    positiveText: 'Confirm',\n    negativeText: 'Cancel'\n  },\n  Cascader: {\n    placeholder: 'Please Select',\n    loading: 'Loading',\n    loadingRequiredMessage: (label: string): string =>\n      `Please load all ${label}'s descendants before checking it.`\n  },\n  Time: {\n    dateFormat: 'yyyy/MM/dd',\n    dateTimeFormat: 'yyyy/MM/dd HH:mm:ss'\n  },\n  DatePicker: {\n    yearFormat: 'yyyy',\n    monthFormat: 'MMM',\n    dayFormat: 'eeeeee',\n    yearTypeFormat: 'yyyy',\n    monthTypeFormat: 'yyyy/MM',\n    dateFormat: 'yyyy/MM/dd',\n    dateTimeFormat: 'yyyy/MM/dd HH:mm:ss',\n    quarterFormat: 'yyyy-qqq',\n    weekFormat: 'YYYY-w',\n    clear: 'Clear',\n    now: 'Now',\n    confirm: 'Confirm',\n    selectTime: 'Select Time',\n    selectDate: 'Select Date',\n    datePlaceholder: 'Select Date',\n    datetimePlaceholder: 'Select Date and Time',\n    monthPlaceholder: 'Select Month',\n    yearPlaceholder: 'Select Year',\n    quarterPlaceholder: 'Select Quarter',\n    weekPlaceholder: 'Select Week',\n    startDatePlaceholder: 'Start Date',\n    endDatePlaceholder: 'End Date',\n    startDatetimePlaceholder: 'Start Date and Time',\n    endDatetimePlaceholder: 'End Date and Time',\n    startMonthPlaceholder: 'Start Month',\n    endMonthPlaceholder: 'End Month',\n    monthBeforeYear: true,\n    firstDayOfWeek: 0 as 0 | 1 | 2 | 3 | 4 | 5 | 6,\n    today: 'Today'\n  },\n  DataTable: {\n    checkTableAll: 'Select all in the table',\n    uncheckTableAll: 'Unselect all in the table',\n    confirm: 'Confirm',\n    clear: 'Clear'\n  },\n  LegacyTransfer: {\n    sourceTitle: 'Source',\n    targetTitle: 'Target'\n  },\n  Transfer: {\n    selectAll: 'Select all',\n    unselectAll: 'Unselect all',\n    clearAll: 'Clear',\n    total: (num: number): string => `Total ${num} items`,\n    selected: (num: number): string => `${num} items selected`\n  },\n  Empty: {\n    description: 'No Data'\n  },\n  Select: {\n    placeholder: 'Please Select'\n  },\n  TimePicker: {\n    placeholder: 'Select Time',\n    positiveText: 'OK',\n    negativeText: 'Cancel',\n    now: 'Now',\n    clear: 'Clear'\n  },\n  Pagination: {\n    goto: 'Goto',\n    selectionSuffix: 'page'\n  },\n  DynamicTags: {\n    add: 'Add'\n  },\n  Log: {\n    loading: 'Loading'\n  },\n  Input: {\n    placeholder: 'Please Input'\n  },\n  InputNumber: {\n    placeholder: 'Please Input'\n  },\n  DynamicInput: {\n    create: 'Create'\n  },\n  ThemeEditor: {\n    title: 'Theme Editor',\n    clearAllVars: 'Clear All Variables',\n    clearSearch: 'Clear Search',\n    filterCompName: 'Filter Component Name',\n    filterVarName: 'Filter Variable Name',\n    import: 'Import',\n    export: 'Export',\n    restore: 'Reset to Default'\n  },\n  Image: {\n    tipPrevious: 'Previous picture (←)',\n    tipNext: 'Next picture (→)',\n    tipCounterclockwise: 'Counterclockwise',\n    tipClockwise: 'Clockwise',\n    tipZoomOut: 'Zoom out',\n    tipZoomIn: 'Zoom in',\n    tipDownload: 'Download',\n    tipClose: 'Close (Esc)',\n    // TODO: translation\n    tipOriginalSize: 'Zoom to original size'\n  },\n  Heatmap: {\n    less: 'less',\n    more: 'more',\n    monthFormat: 'MMM',\n    weekdayFormat: 'eee'\n  }\n}\n\nexport default enGB\n"
  },
  {
    "path": "src/locales/common/enUS.ts",
    "content": "const enUS = {\n  name: 'en-US',\n  global: {\n    undo: 'Undo',\n    redo: 'Redo',\n    confirm: 'Confirm',\n    clear: 'Clear'\n  },\n  Popconfirm: {\n    positiveText: 'Confirm',\n    negativeText: 'Cancel'\n  },\n  Cascader: {\n    placeholder: 'Please Select',\n    loading: 'Loading',\n    loadingRequiredMessage: (label: string): string =>\n      `Please load all ${label}'s descendants before checking it.`\n  },\n  Time: {\n    dateFormat: 'yyyy-MM-dd',\n    dateTimeFormat: 'yyyy-MM-dd HH:mm:ss'\n  },\n  DatePicker: {\n    yearFormat: 'yyyy',\n    monthFormat: 'MMM',\n    dayFormat: 'eeeeee',\n    yearTypeFormat: 'yyyy',\n    monthTypeFormat: 'yyyy-MM',\n    dateFormat: 'yyyy-MM-dd',\n    dateTimeFormat: 'yyyy-MM-dd HH:mm:ss',\n    quarterFormat: 'yyyy-qqq',\n    weekFormat: 'YYYY-w',\n    clear: 'Clear',\n    now: 'Now',\n    confirm: 'Confirm',\n    selectTime: 'Select Time',\n    selectDate: 'Select Date',\n    datePlaceholder: 'Select Date',\n    datetimePlaceholder: 'Select Date and Time',\n    monthPlaceholder: 'Select Month',\n    yearPlaceholder: 'Select Year',\n    quarterPlaceholder: 'Select Quarter',\n    weekPlaceholder: 'Select Week',\n    startDatePlaceholder: 'Start Date',\n    endDatePlaceholder: 'End Date',\n    startDatetimePlaceholder: 'Start Date and Time',\n    endDatetimePlaceholder: 'End Date and Time',\n    startMonthPlaceholder: 'Start Month',\n    endMonthPlaceholder: 'End Month',\n    monthBeforeYear: true,\n    firstDayOfWeek: 6 as 0 | 1 | 2 | 3 | 4 | 5 | 6,\n    today: 'Today'\n  },\n  DataTable: {\n    checkTableAll: 'Select all in the table',\n    uncheckTableAll: 'Unselect all in the table',\n    confirm: 'Confirm',\n    clear: 'Clear'\n  },\n  LegacyTransfer: {\n    sourceTitle: 'Source',\n    targetTitle: 'Target'\n  },\n  Transfer: {\n    selectAll: 'Select all',\n    unselectAll: 'Unselect all',\n    clearAll: 'Clear',\n    total: (num: number): string => `Total ${num} items`,\n    selected: (num: number): string => `${num} items selected`\n  },\n  Empty: {\n    description: 'No Data'\n  },\n  Select: {\n    placeholder: 'Please Select'\n  },\n  TimePicker: {\n    placeholder: 'Select Time',\n    positiveText: 'OK',\n    negativeText: 'Cancel',\n    now: 'Now',\n    clear: 'Clear'\n  },\n  Pagination: {\n    goto: 'Goto',\n    selectionSuffix: 'page'\n  },\n  DynamicTags: {\n    add: 'Add'\n  },\n  Log: {\n    loading: 'Loading'\n  },\n  Input: {\n    placeholder: 'Please Input'\n  },\n  InputNumber: {\n    placeholder: 'Please Input'\n  },\n  DynamicInput: {\n    create: 'Create'\n  },\n  ThemeEditor: {\n    title: 'Theme Editor',\n    clearAllVars: 'Clear All Variables',\n    clearSearch: 'Clear Search',\n    filterCompName: 'Filter Component Name',\n    filterVarName: 'Filter Variable Name',\n    import: 'Import',\n    export: 'Export',\n    restore: 'Reset to Default'\n  },\n  Image: {\n    tipPrevious: 'Previous picture (←)',\n    tipNext: 'Next picture (→)',\n    tipCounterclockwise: 'Counterclockwise',\n    tipClockwise: 'Clockwise',\n    tipZoomOut: 'Zoom out',\n    tipZoomIn: 'Zoom in',\n    tipDownload: 'Download',\n    tipClose: 'Close (Esc)',\n    // TODO: translation\n    tipOriginalSize: 'Zoom to original size'\n  },\n  Heatmap: {\n    less: 'less',\n    more: 'more',\n    monthFormat: 'MMM',\n    weekdayFormat: 'eee'\n  }\n}\n\nexport type NLocale = typeof enUS\nexport default enUS\n"
  },
  {
    "path": "src/locales/common/eo.ts",
    "content": "import type { NLocale } from './enUS'\n\nconst eo: NLocale = {\n  name: 'eo',\n  global: {\n    undo: 'Malfari',\n    redo: 'Refari',\n    confirm: 'Konfirmi',\n    clear: 'Malplenigi'\n  },\n  Popconfirm: {\n    positiveText: 'Konfirmi',\n    negativeText: 'Nuligi'\n  },\n  Cascader: {\n    placeholder: 'Bonvolu elekti',\n    loading: 'Ŝargiĝo',\n    loadingRequiredMessage: (label: string): string =>\n      `Bonvolu ŝargi ĉiujn idojn de ${label} antaŭ ol elekti ĝin.`\n  },\n  Time: {\n    dateFormat: 'yyyy-MM-dd',\n    dateTimeFormat: 'yyyy-MM-dd HH:mm:ss'\n  },\n  DatePicker: {\n    yearFormat: 'yyyy',\n    monthFormat: 'MMM',\n    dayFormat: 'eeeeee',\n    yearTypeFormat: 'yyyy',\n    monthTypeFormat: 'yyyy-MM',\n    dateFormat: 'yyyy-MM-dd',\n    dateTimeFormat: 'yyyy-MM-dd HH:mm:ss',\n    quarterFormat: 'yyyy-qqq',\n    weekFormat: 'YYYY-w',\n    clear: 'Malplenigi',\n    now: 'Nun',\n    confirm: 'Konfirmi',\n    selectTime: 'Elekti tempon',\n    selectDate: 'Elekti daton',\n    datePlaceholder: 'Elekti daton',\n    datetimePlaceholder: 'Elekti daton kaj tempon',\n    monthPlaceholder: 'Elekti monaton',\n    yearPlaceholder: 'Elekti jaron',\n    quarterPlaceholder: 'Elekti jarkvaronon',\n    weekPlaceholder: 'Select Week',\n    startDatePlaceholder: 'Komenca dato',\n    endDatePlaceholder: 'Fina dato',\n    startDatetimePlaceholder: 'Komencaj dato kaj tempo',\n    endDatetimePlaceholder: 'Finaj dato kaj tempo',\n    // FIXME: translation needed\n    startMonthPlaceholder: 'Start Month',\n    endMonthPlaceholder: 'End Month',\n    monthBeforeYear: true,\n    firstDayOfWeek: 0 as 0 | 1 | 2 | 3 | 4 | 5 | 6,\n    today: 'Hodiaŭ'\n  },\n  DataTable: {\n    checkTableAll: 'Elekti ĉiujn en la tabelo',\n    uncheckTableAll: 'Malelekti ĉiujn en la tabelo',\n    confirm: 'Konfirmi',\n    clear: 'Malplenigi'\n  },\n  LegacyTransfer: {\n    sourceTitle: 'Source',\n    targetTitle: 'Target'\n  },\n  // TODO: translation\n  Transfer: {\n    selectAll: 'Select all',\n    unselectAll: 'Unselect all',\n    clearAll: 'Clear',\n    total: (num: number): string => `Total ${num} items`,\n    selected: (num: number): string => `${num} items selected`\n  },\n  Empty: {\n    description: 'Neniu datumo'\n  },\n  Select: {\n    placeholder: 'Bonvolu elekti'\n  },\n  TimePicker: {\n    placeholder: 'Elekti tempon',\n    positiveText: 'Bone',\n    negativeText: 'Nuligi',\n    now: 'Nun',\n    clear: 'Malplenigi'\n  },\n  Pagination: {\n    goto: 'Iri al',\n    selectionSuffix: 'paĝo'\n  },\n  DynamicTags: {\n    add: 'Aldoni'\n  },\n  Log: {\n    loading: 'Ŝargado'\n  },\n  Input: {\n    placeholder: 'Bonvolu entajpi'\n  },\n  InputNumber: {\n    placeholder: 'Bonvolu entajpi'\n  },\n  DynamicInput: {\n    create: 'Krei'\n  },\n  ThemeEditor: {\n    title: 'Etosredaktilo',\n    clearAllVars: 'Malplenigi ĉiujn variablojn',\n    clearSearch: 'Malplenigi serĉon',\n    filterCompName: 'Filtri nomojn de komponaĵoj',\n    filterVarName: 'Filtri nomojn de variabloj',\n    import: 'Importi',\n    export: 'Eksporti',\n    restore: 'Restarigi defaŭltajn valorojn'\n  },\n  Image: {\n    tipPrevious: 'Antaŭa bildo (←)',\n    tipNext: 'Sekva bildo (→)',\n    tipCounterclockwise: 'Maldekstrume',\n    tipClockwise: 'Dekstrume',\n    tipZoomOut: 'Malzomi',\n    tipZoomIn: 'Zomi',\n    tipDownload: 'Elŝuti',\n    tipClose: 'Fermi (Esc)',\n    tipOriginalSize: 'Zoom to original size'\n  },\n  Heatmap: {\n    less: 'less',\n    more: 'more',\n    monthFormat: 'MMM',\n    weekdayFormat: 'eeeeee'\n  }\n}\n\nexport default eo\n"
  },
  {
    "path": "src/locales/common/esAR.ts",
    "content": "import type { NLocale } from './enUS'\n\nconst esAR: NLocale = {\n  name: 'es-AR',\n  global: {\n    undo: 'Deshacer',\n    redo: 'Rehacer',\n    confirm: 'Confirmar',\n    clear: 'Borrar'\n  },\n  Popconfirm: {\n    positiveText: 'Confirmar',\n    negativeText: 'Cancelar'\n  },\n  Cascader: {\n    placeholder: 'Seleccionar por favor',\n    loading: 'Cargando',\n    loadingRequiredMessage: (label: string): string =>\n      `Por favor, cargue los descendientes de ${label} antes de marcarlo.`\n  },\n  Time: {\n    dateFormat: 'yyyy-MM-dd',\n    dateTimeFormat: 'yyyy-MM-dd HH:mm:ss'\n  },\n  DatePicker: {\n    yearFormat: 'yyyy',\n    monthFormat: 'MMM',\n    dayFormat: 'eeeeee',\n    yearTypeFormat: 'yyyy',\n    monthTypeFormat: 'yyyy-MM',\n    dateFormat: 'yyyy-MM-dd',\n    dateTimeFormat: 'yyyy-MM-dd HH:mm:ss',\n    quarterFormat: 'yyyy-qqq',\n    weekFormat: 'YYYY-w',\n    clear: 'Borrar',\n    now: 'Ahora',\n    confirm: 'Confirmar',\n    selectTime: 'Seleccionar hora',\n    selectDate: 'Seleccionar fecha',\n    datePlaceholder: 'Seleccionar fecha',\n    datetimePlaceholder: 'Seleccionar fecha y hora',\n    monthPlaceholder: 'Seleccionar mes',\n    yearPlaceholder: 'Seleccionar año',\n    quarterPlaceholder: 'Seleccionar Trimestre',\n    weekPlaceholder: 'Select Week',\n    startDatePlaceholder: 'Fecha de inicio',\n    endDatePlaceholder: 'Fecha final',\n    startDatetimePlaceholder: 'Fecha y hora de inicio',\n    endDatetimePlaceholder: 'Fecha y hora final',\n    monthBeforeYear: true,\n    // FIXME: translation needed\n    startMonthPlaceholder: 'Start Month',\n    endMonthPlaceholder: 'End Month',\n    // 0 is Monday / 0 es Lunes\n    firstDayOfWeek: 6 as 0 | 1 | 2 | 3 | 4 | 5 | 6,\n    today: 'Hoy'\n  },\n  DataTable: {\n    checkTableAll: 'Seleccionar todo de la tabla',\n    uncheckTableAll: 'Deseleccionar todo de la tabla',\n    confirm: 'Confirmar',\n    clear: 'Limpiar'\n  },\n  LegacyTransfer: {\n    sourceTitle: 'Fuente',\n    targetTitle: 'Objetivo'\n  },\n  // TODO: translation\n  Transfer: {\n    selectAll: 'Select all',\n    unselectAll: 'Unselect all',\n    clearAll: 'Clear',\n    total: (num: number): string => `Total ${num} items`,\n    selected: (num: number): string => `${num} items selected`\n  },\n  Empty: {\n    description: 'Sin datos'\n  },\n  Select: {\n    placeholder: 'Seleccionar por favor'\n  },\n  TimePicker: {\n    placeholder: 'Seleccionar hora',\n    positiveText: 'OK',\n    negativeText: 'Cancelar',\n    now: 'Ahora',\n    clear: 'Borrar'\n  },\n  Pagination: {\n    goto: 'Ir a',\n    selectionSuffix: 'página'\n  },\n  DynamicTags: {\n    add: 'Agregar'\n  },\n  Log: {\n    loading: 'Cargando'\n  },\n  Input: {\n    placeholder: 'Ingrese datos por favor'\n  },\n  InputNumber: {\n    placeholder: 'Ingrese datos por favor'\n  },\n  DynamicInput: {\n    create: 'Crear'\n  },\n  ThemeEditor: {\n    title: 'Editor de Tema',\n    clearAllVars: 'Limpiar todas las variables',\n    clearSearch: 'Limpiar búsqueda',\n    filterCompName: 'Filtro para nombre del componente',\n    filterVarName: 'Filtro para nombre de la variable',\n    import: 'Importar',\n    export: 'Exportar',\n    restore: 'Restablecer los valores por defecto'\n  },\n  Image: {\n    tipPrevious: 'Imagen anterior (←)',\n    tipNext: 'Siguiente imagen (→)',\n    tipCounterclockwise: 'Sentido antihorario',\n    tipClockwise: 'Sentido horario',\n    tipZoomOut: 'Alejar',\n    tipZoomIn: 'Acercar',\n    tipDownload: 'Descargar',\n    tipClose: 'Cerrar (Esc)',\n    // TODO: translation\n    tipOriginalSize: 'Zoom to original size'\n  },\n  Heatmap: {\n    less: 'menos',\n    more: 'más',\n    monthFormat: 'MMM',\n    weekdayFormat: 'eeeeee'\n  }\n}\n\nexport default esAR\n"
  },
  {
    "path": "src/locales/common/etEE.ts",
    "content": "import type { NLocale } from './enUS'\n\nconst etEE: NLocale = {\n  name: 'et-EE',\n  global: {\n    undo: 'Võta tagasi',\n    redo: 'Rakenda uuesti',\n    confirm: 'Kinnita',\n    clear: 'Tühjenda'\n  },\n  Popconfirm: {\n    positiveText: 'Kinnita',\n    negativeText: 'Katkesta'\n  },\n  Cascader: {\n    placeholder: 'Vali',\n    loading: 'Laeb',\n    loadingRequiredMessage: (label: string): string =>\n      `Enne kontrollimist pead elemendi ${label} kõik alamad laadima.`\n  },\n  Time: {\n    dateFormat: 'dd.MM.yyyy',\n    dateTimeFormat: 'dd.MM.yyyy HH:mm:ss'\n  },\n  DatePicker: {\n    yearFormat: 'yyyy',\n    monthFormat: 'MMM',\n    dayFormat: 'eeeeee',\n    yearTypeFormat: 'yyyy',\n    monthTypeFormat: 'MM-yyyy',\n    dateFormat: 'dd.MM.yyyy',\n    dateTimeFormat: 'dd.MM.yyyy HH:mm:ss',\n    quarterFormat: 'yyyy-qqq',\n    weekFormat: 'YYYY-w',\n    clear: 'Tühjenda',\n    now: 'Nüüd',\n    confirm: 'Kinnita',\n    selectTime: 'Vali aeg',\n    selectDate: 'Vali kuupäev',\n    datePlaceholder: 'Vali kuupäev',\n    datetimePlaceholder: 'Vali aeg ja kuupäev',\n    monthPlaceholder: 'Vali kuu',\n    yearPlaceholder: 'Vali aasta',\n    quarterPlaceholder: 'Vali kvartal',\n    weekPlaceholder: 'Vali nädal',\n    startDatePlaceholder: 'Alguskpv',\n    endDatePlaceholder: 'Lõppkpv',\n    startDatetimePlaceholder: 'Alguskpv ja -aeg',\n    endDatetimePlaceholder: 'Lõppkpv ja -aeg',\n    startMonthPlaceholder: 'Alguskuu',\n    endMonthPlaceholder: 'Lõppkuu',\n    monthBeforeYear: true,\n    firstDayOfWeek: 0 as 0 | 1 | 2 | 3 | 4 | 5 | 6,\n    today: 'Täna'\n  },\n  DataTable: {\n    checkTableAll: 'Vali tabelis kõik',\n    uncheckTableAll: 'Tühista tabeli valik',\n    confirm: 'Kinnita',\n    clear: 'Tühjenda'\n  },\n  LegacyTransfer: {\n    sourceTitle: 'Kust',\n    targetTitle: 'Kuhu'\n  },\n  Transfer: {\n    selectAll: 'Vali kõik',\n    unselectAll: 'Tühista valik',\n    clearAll: 'Tühjenda',\n    total: (num: number): string => `Kokku ${num} rida`,\n    selected: (num: number): string => `${num} rida valitud`\n  },\n  Empty: {\n    description: 'Andmeid pole'\n  },\n  Select: {\n    placeholder: 'Vali'\n  },\n  TimePicker: {\n    placeholder: 'Vali aeg',\n    positiveText: 'OK',\n    negativeText: 'Katkesta',\n    now: 'Nüüd',\n    clear: 'Tühjenda'\n  },\n  Pagination: {\n    goto: 'Mine',\n    selectionSuffix: 'lk'\n  },\n  DynamicTags: {\n    add: 'Lisa'\n  },\n  Log: {\n    loading: 'Laeb'\n  },\n  Input: {\n    placeholder: 'Sisesta'\n  },\n  InputNumber: {\n    placeholder: 'Sisesta'\n  },\n  DynamicInput: {\n    create: 'Loo'\n  },\n  ThemeEditor: {\n    title: 'Teemaredaktor',\n    clearAllVars: 'Tühjenda kõik muutujad',\n    clearSearch: 'Tühjenda otsing',\n    filterCompName: 'Filter komponendi nimega',\n    filterVarName: 'Filter muutuja nimega',\n    import: 'Import',\n    export: 'Eksport',\n    restore: 'Taasta originaal'\n  },\n  Image: {\n    tipPrevious: 'Eelmine pilt (←)',\n    tipNext: 'Järgmine pilt (→)',\n    tipCounterclockwise: 'Vastupäeva',\n    tipClockwise: 'Päripäeva',\n    tipZoomOut: 'Suumi välja',\n    tipZoomIn: 'Suumi sisse',\n    tipDownload: 'Lae alla',\n    tipClose: 'Sulge (Esc)',\n    tipOriginalSize: 'Algsuurus'\n  },\n  Heatmap: {\n    less: 'less',\n    more: 'more',\n    monthFormat: 'MMM',\n    weekdayFormat: 'eeeeee'\n  }\n}\n\nexport default etEE\n"
  },
  {
    "path": "src/locales/common/faIR.ts",
    "content": "import type { NLocale } from './enUS'\n\nconst faIR: NLocale = {\n  name: 'fa-IR',\n  global: {\n    undo: 'لغو انجام شده',\n    redo: 'انجام دوباره',\n    confirm: 'تأیید',\n    clear: 'پاک کردن'\n  },\n  Popconfirm: {\n    positiveText: 'تأیید',\n    negativeText: 'لغو'\n  },\n  Cascader: {\n    placeholder: 'لطفا انتخاب کنید',\n    loading: 'بارگذاری',\n    loadingRequiredMessage: (label: string): string =>\n      `پس از بارگیری کامل زیرمجموعه های ${label} می توانید انتخاب کنید `\n  },\n  Time: {\n    dateFormat: 'yyyy/MM/dd',\n    dateTimeFormat: 'yyyy/MM/dd، H:mm:ss'\n  },\n  DatePicker: {\n    yearFormat: 'yyyy سال',\n    monthFormat: 'MMM',\n    dayFormat: 'eeeeee',\n    yearTypeFormat: 'yyyy',\n    monthTypeFormat: 'MM/yyyy',\n    dateFormat: 'yyyy/MM/dd',\n    dateTimeFormat: 'yyyy/MM/dd HH:mm:ss',\n    quarterFormat: 'سه ماهه yyyy',\n    weekFormat: 'YYYY-w',\n    clear: 'پاک کردن',\n    now: 'اکنون',\n    confirm: 'تأیید',\n    selectTime: 'انتخاب زمان',\n    selectDate: 'انتخاب تاریخ',\n    datePlaceholder: 'انتخاب تاریخ',\n    datetimePlaceholder: 'انتخاب تاریخ و زمان',\n    monthPlaceholder: 'انتخاب ماه',\n    yearPlaceholder: 'انتخاب سال',\n    quarterPlaceholder: 'انتخاب سه‌ماهه',\n    weekPlaceholder: 'Select Week',\n    startDatePlaceholder: 'تاریخ شروع',\n    endDatePlaceholder: 'تاریخ پایان',\n    startDatetimePlaceholder: 'زمان شروع',\n    endDatetimePlaceholder: 'زمان پایان',\n    startMonthPlaceholder: 'ماه شروع',\n    endMonthPlaceholder: 'ماه پایان',\n    monthBeforeYear: false,\n    firstDayOfWeek: 6,\n    today: 'امروز'\n  },\n  DataTable: {\n    checkTableAll: 'انتخاب همه داده‌های جدول',\n    uncheckTableAll: 'عدم انتخاب همه داده‌های جدول',\n    confirm: 'تأیید',\n    clear: 'تنظیم مجدد'\n  },\n  LegacyTransfer: {\n    sourceTitle: 'آیتم منبع',\n    targetTitle: 'آیتم مقصد'\n  },\n  Transfer: {\n    selectAll: 'انتخاب همه',\n    clearAll: 'حذف همه',\n    unselectAll: 'عدم انتخاب همه',\n    total: (num: number): string => `کل ${num} مورد`,\n    selected: (num: number): string => `انتخاب شده ${num} مورد`\n  },\n  Empty: {\n    description: 'اطلاعاتی وجود ندارد'\n  },\n  Select: {\n    placeholder: 'لطفاً انتخاب کنید'\n  },\n  TimePicker: {\n    placeholder: 'لطفاً زمان مورد نظر را انتخاب کنید',\n    positiveText: 'تأیید',\n    negativeText: 'لغو',\n    now: 'همین الان',\n    clear: 'پاک کردن'\n  },\n  Pagination: {\n    goto: 'رفتن به صفحه',\n    selectionSuffix: 'صفحه'\n  },\n  DynamicTags: {\n    add: 'افزودن'\n  },\n  Log: {\n    loading: 'در حال بارگذاری'\n  },\n  Input: {\n    placeholder: 'لطفاً وارد کنید'\n  },\n  InputNumber: {\n    placeholder: 'لطفاً وارد کنید'\n  },\n  DynamicInput: {\n    create: 'افزودن'\n  },\n  ThemeEditor: {\n    title: 'ویرایشگر پوسته',\n    clearAllVars: 'پاک کردن همه متغیرها',\n    clearSearch: 'پاک کردن جستجو',\n    filterCompName: 'فیلتر نام کامپوننت',\n    filterVarName: 'فیلتر نام متغیر',\n    import: 'ورود',\n    export: 'خروج',\n    restore: 'بازگردانی به حالت پیش‌فرض'\n  },\n  Image: {\n    tipPrevious: 'تصویر قبلی (←)',\n    tipNext: 'تصویر بعدی (→)',\n    tipCounterclockwise: 'چرخش به سمت چپ',\n    tipClockwise: 'چرخش به سمت راست',\n    tipZoomOut: 'کوچک نمایی تصویر',\n    tipZoomIn: 'بزرگ نمایی تصویر',\n    tipDownload: 'بارگیری',\n    tipClose: 'بستن (Esc)',\n    tipOriginalSize: 'اندازه اصلی تصویر'\n  },\n  Heatmap: {\n    less: 'less',\n    more: 'more',\n    monthFormat: 'MMM',\n    weekdayFormat: 'eeeeee'\n  }\n}\n\nexport default faIR\n"
  },
  {
    "path": "src/locales/common/frFR.ts",
    "content": "import type { NLocale } from './enUS'\n\nconst frFR: NLocale = {\n  name: 'fr-FR',\n  global: {\n    undo: 'Défaire',\n    redo: 'Refaire',\n    confirm: 'Confirmer',\n    clear: 'Effacer'\n  },\n  Popconfirm: {\n    positiveText: 'Confirmer',\n    negativeText: 'Annuler'\n  },\n  Cascader: {\n    placeholder: 'Sélectionner',\n    loading: 'Chargement',\n    loadingRequiredMessage: (label: string): string =>\n      `Charger tous les enfants de ${label} avant de le sélectionner`\n  },\n  Time: {\n    dateFormat: 'dd/MM/yyyy',\n    dateTimeFormat: 'dd/MM/yyyy HH:mm:ss'\n  },\n  DatePicker: {\n    yearFormat: 'yyyy',\n    monthFormat: 'MMM',\n    dayFormat: 'eeeeee',\n    yearTypeFormat: 'yyyy',\n    monthTypeFormat: 'MM/yyyy',\n    dateFormat: 'dd/MM/yyyy',\n    dateTimeFormat: 'dd/MM/yyyy HH:mm:ss',\n    quarterFormat: 'qqq yyyy',\n    weekFormat: 'YYYY-w',\n    clear: 'Effacer',\n    now: 'Maintenant',\n    confirm: 'Confirmer',\n    selectTime: 'Sélectionner l\\'heure',\n    selectDate: 'Sélectionner la date',\n    datePlaceholder: 'Sélectionner la date',\n    datetimePlaceholder: 'Sélectionner la date et l\\'heure',\n    monthPlaceholder: 'Sélectionner le mois',\n    yearPlaceholder: 'Sélectionner l\\'année',\n    quarterPlaceholder: 'Sélectionner le trimestre',\n    weekPlaceholder: 'Select Week',\n    startDatePlaceholder: 'Date de début',\n    endDatePlaceholder: 'Date de fin',\n    startDatetimePlaceholder: 'Date et heure de début',\n    endDatetimePlaceholder: 'Date et heure de fin',\n    startMonthPlaceholder: 'Mois de début',\n    endMonthPlaceholder: 'Mois de fin',\n    monthBeforeYear: true,\n    firstDayOfWeek: 0,\n    today: 'Aujourd\\'hui'\n  },\n  DataTable: {\n    checkTableAll: 'Sélectionner tout',\n    uncheckTableAll: 'Désélectionner tout',\n    confirm: 'Confirmer',\n    clear: 'Effacer'\n  },\n  LegacyTransfer: {\n    sourceTitle: 'Source',\n    targetTitle: 'Cible'\n  },\n  Transfer: {\n    selectAll: 'Sélectionner tout',\n    unselectAll: 'Désélectionner tout',\n    clearAll: 'Effacer',\n    total: (num: number): string => `Total ${num} éléments`,\n    selected: (num: number): string => `${num} éléments sélectionnés`\n  },\n  Empty: {\n    description: 'Aucune donnée'\n  },\n  Select: {\n    placeholder: 'Sélectionner'\n  },\n  TimePicker: {\n    placeholder: 'Sélectionner l\\'heure',\n    positiveText: 'OK',\n    negativeText: 'Annuler',\n    now: 'Maintenant',\n    clear: 'Effacer'\n  },\n  Pagination: {\n    goto: 'Aller à',\n    selectionSuffix: 'page'\n  },\n  DynamicTags: {\n    add: 'Ajouter'\n  },\n  Log: {\n    loading: 'Chargement'\n  },\n  Input: {\n    placeholder: 'Saisir'\n  },\n  InputNumber: {\n    placeholder: 'Saisir'\n  },\n  DynamicInput: {\n    create: 'Créer'\n  },\n  ThemeEditor: {\n    title: 'Éditeur de thème',\n    clearAllVars: 'Effacer toutes les variables',\n    clearSearch: 'Effacer la recherche',\n    filterCompName: 'Filtrer par nom de composant',\n    filterVarName: 'Filtrer par nom de variable',\n    import: 'Importer',\n    export: 'Exporter',\n    restore: 'Réinitialiser'\n  },\n  Image: {\n    tipPrevious: 'Image précédente (←)',\n    tipNext: 'Image suivante (→)',\n    tipCounterclockwise: 'Sens antihoraire',\n    tipClockwise: 'Sens horaire',\n    tipZoomOut: 'Dézoomer',\n    tipZoomIn: 'Zoomer',\n    tipDownload: 'Descargar',\n    tipClose: 'Fermer (Échap.)',\n    tipOriginalSize: 'Zoom à la taille originale'\n  },\n  Heatmap: {\n    less: 'moins',\n    more: 'plus',\n    monthFormat: 'MMM',\n    weekdayFormat: 'eeeeee'\n  }\n}\n\nexport default frFR\n"
  },
  {
    "path": "src/locales/common/idID.ts",
    "content": "import type { NLocale } from './enUS'\n\nconst idID: NLocale = {\n  name: 'id-ID',\n  global: {\n    undo: 'Membatalkan',\n    redo: 'Mem-perbarui',\n    confirm: 'Setuju',\n    clear: 'Bersihkan'\n  },\n  Popconfirm: {\n    positiveText: 'Setuju',\n    negativeText: 'Batalkan'\n  },\n  Cascader: {\n    placeholder: 'Mohon Pilih',\n    loading: 'Memuat',\n    loadingRequiredMessage: (label: string): string =>\n      `Mohon muat semua ${label} sebelum memeriksa.`\n  },\n  Time: {\n    dateFormat: 'dd-MM-yyyy',\n    dateTimeFormat: 'dd-MM-yyyy HH:mm:ss'\n  },\n  DatePicker: {\n    yearFormat: 'yyyy',\n    monthFormat: 'MMM',\n    dayFormat: 'eeeeee',\n    yearTypeFormat: 'yyyy',\n    monthTypeFormat: 'MM-yyyy',\n    dateFormat: 'dd-MM-yyyy',\n    dateTimeFormat: 'dd-MM-yyyy HH:mm:ss',\n    quarterFormat: 'yyyy-qqq',\n    weekFormat: 'YYYY-w',\n    clear: 'Bersihkan',\n    now: 'Sekarang',\n    confirm: 'Setuju',\n    selectTime: 'Pilih Waktu',\n    selectDate: 'Pilih Tanggal',\n    datePlaceholder: 'Pilih Tanggal',\n    datetimePlaceholder: 'Pilih Tanggal dan Waktu',\n    monthPlaceholder: 'Pilih Bulan',\n    // FIXME: translation needed\n    yearPlaceholder: 'Pilih tahun',\n    quarterPlaceholder: 'Pilih perempat tahun',\n    weekPlaceholder: 'Select Week',\n    startDatePlaceholder: 'Tanggal Mulai',\n    endDatePlaceholder: 'Tanggal Selesai',\n    startDatetimePlaceholder: 'Tanggal dan Waktu Mulai',\n    endDatetimePlaceholder: 'Tanggal dan Waktu Selesai',\n    // FIXME: translation needed\n    startMonthPlaceholder: 'Awal bulan',\n    endMonthPlaceholder: 'Akhir bulan',\n    monthBeforeYear: true,\n    firstDayOfWeek: 6 as 0 | 1 | 2 | 3 | 4 | 5 | 6,\n    today: 'Hari ini'\n  },\n  DataTable: {\n    checkTableAll: 'Pilih semua pada tabel',\n    uncheckTableAll: 'Batalkan pilihan semua',\n    confirm: 'Setuju',\n    clear: 'Bersihkan'\n  },\n  LegacyTransfer: {\n    sourceTitle: 'Sumber',\n    targetTitle: 'Tujuan'\n  },\n  // TODO: translation\n  Transfer: {\n    selectAll: 'Pilih semua',\n    unselectAll: 'Batalkan pilihan',\n    clearAll: 'Bersihkan',\n    total: (num: number): string => `Total ${num} item`,\n    selected: (num: number): string => `${num} item dipilih`\n  },\n  Empty: {\n    description: 'Tidak ada data'\n  },\n  Select: {\n    placeholder: 'Mohon Pilih'\n  },\n  TimePicker: {\n    placeholder: 'Pilih Waktu',\n    positiveText: 'OK',\n    negativeText: 'Batalkan',\n    now: 'Sekarang',\n    clear: 'Bersihkan'\n  },\n  Pagination: {\n    goto: 'Ke',\n    selectionSuffix: 'halaman'\n  },\n  DynamicTags: {\n    add: 'Tambah'\n  },\n  Log: {\n    loading: 'Memuat'\n  },\n  Input: {\n    placeholder: 'Mohon isi'\n  },\n  InputNumber: {\n    placeholder: 'Mohon isi'\n  },\n  DynamicInput: {\n    create: 'Buat baru'\n  },\n  ThemeEditor: {\n    title: 'Pengaturan Tema',\n    clearAllVars: 'Bersihkan semua variabel',\n    clearSearch: 'Bersihkan pencarian',\n    filterCompName: 'Saring nama komponen',\n    filterVarName: 'Saring nama variabel',\n    import: 'Impor',\n    export: 'Ekspor',\n    restore: 'Setel ulang ke awal'\n  },\n  Image: {\n    tipPrevious: 'Gambar sebelumnya (←)',\n    tipNext: 'Gambar berikutnya (→)',\n    tipCounterclockwise: 'Berlawanan arah jarum jam',\n    tipClockwise: 'Searah jarum jam',\n    tipZoomOut: 'Zoom out',\n    tipZoomIn: 'Zoom in',\n    tipDownload: 'Download',\n    tipClose: 'Tutup (Esc)',\n    // TODO: translation\n    tipOriginalSize: 'Zoom ke ukuran asli'\n  },\n  Heatmap: {\n    less: 'less',\n    more: 'more',\n    monthFormat: 'MMM',\n    weekdayFormat: 'eeeeee'\n  }\n}\n\nexport default idID\n"
  },
  {
    "path": "src/locales/common/itIT.ts",
    "content": "import type { NLocale } from './enUS'\n\nconst itIT: NLocale = {\n  name: 'it-IT',\n  global: {\n    undo: 'Annulla',\n    redo: 'Ripeti',\n    confirm: 'Conferma',\n    clear: 'Cancella'\n  },\n  Popconfirm: {\n    positiveText: 'Conferma',\n    negativeText: 'Annulla'\n  },\n  Cascader: {\n    placeholder: 'Si prega di selezionare',\n    loading: 'Caricamento',\n    loadingRequiredMessage: (label: string): string =>\n      `Carica tutti i discendenti di ${label} prima di controllarlo.`\n  },\n  Time: {\n    dateFormat: 'dd/MM/yyyy',\n    dateTimeFormat: 'dd/MM/yyyy HH:mm:ss'\n  },\n  DatePicker: {\n    yearFormat: 'yyyy',\n    monthFormat: 'MMM',\n    dayFormat: 'eeeeee',\n    yearTypeFormat: 'yyyy',\n    monthTypeFormat: 'yyyy-MM',\n    dateFormat: 'yyyy-MM-dd',\n    dateTimeFormat: 'yyyy-MM-dd HH:mm:ss',\n    quarterFormat: 'yyyy-qqq',\n    weekFormat: 'YYYY-w',\n    clear: 'Cancella',\n    now: 'Adesso',\n    confirm: 'Conferma',\n    selectTime: 'Seleziona ora',\n    selectDate: 'Seleziona data',\n    datePlaceholder: 'Seleziona data',\n    datetimePlaceholder: 'Seleziona data e ora',\n    monthPlaceholder: 'Seleziona mese',\n    yearPlaceholder: 'Seleziona anno',\n    quarterPlaceholder: 'Seleziona trimestre',\n    weekPlaceholder: 'Select Week',\n    startDatePlaceholder: 'Data inizio',\n    endDatePlaceholder: 'Data fine',\n    startDatetimePlaceholder: 'Data e ora di inizio',\n    endDatetimePlaceholder: 'Data e ora di fine',\n    startMonthPlaceholder: 'Mese di inizio',\n    endMonthPlaceholder: 'Mese di fine',\n    monthBeforeYear: true,\n    firstDayOfWeek: 0 as 0 | 1 | 2 | 3 | 4 | 5 | 6,\n    today: 'Oggi'\n  },\n  DataTable: {\n    checkTableAll: 'Seleziona tutto nella tabella',\n    uncheckTableAll: 'Deseleziona tutto nella tabella',\n    confirm: 'Conferma',\n    clear: 'Cancella'\n  },\n  LegacyTransfer: {\n    sourceTitle: 'Fonte',\n    targetTitle: 'Destinazione'\n  },\n  Transfer: {\n    selectAll: 'Seleziona tutto',\n    unselectAll: 'Deseleziona tutto',\n    clearAll: 'Pulisci',\n    total: (num: number): string => {\n      if (num !== 1)\n        return `${num} elementi in totale`\n      return '1 elemento in totale'\n    },\n    selected: (num: number): string => {\n      if (num !== 1)\n        return `${num} elementi selezionati`\n      return '1 elemento selezionato'\n    }\n  },\n  Empty: {\n    description: 'Nessun Dato'\n  },\n  Select: {\n    placeholder: 'Si prega di selezionare'\n  },\n  TimePicker: {\n    placeholder: 'Seleziona ora',\n    positiveText: 'OK',\n    negativeText: 'Annulla',\n    now: 'Ora',\n    clear: 'Cancella'\n  },\n  Pagination: {\n    goto: 'Vai a',\n    selectionSuffix: 'per pagina'\n  },\n  DynamicTags: {\n    add: 'Aggiungi'\n  },\n  Log: {\n    loading: 'Caricamento'\n  },\n  Input: {\n    placeholder: 'Si prega di inserire'\n  },\n  InputNumber: {\n    placeholder: 'Si prega di inserire'\n  },\n  DynamicInput: {\n    create: 'Crea'\n  },\n  ThemeEditor: {\n    title: 'Editor Tema',\n    clearAllVars: 'Cancella tutte le variabili',\n    clearSearch: 'Cancella ricerca',\n    filterCompName: 'Filtra componenti',\n    filterVarName: 'Filtra variabili',\n    import: 'Importa',\n    export: 'Esporta',\n    restore: 'Ripristina'\n  },\n  Image: {\n    tipPrevious: 'Immagine precedente (←)',\n    tipNext: 'Immagine successiva (→)',\n    tipCounterclockwise: 'Ruota a sinistra',\n    tipClockwise: 'Ruota a destra',\n    tipZoomOut: 'Ingrandisci',\n    tipZoomIn: 'Riduci',\n    tipDownload: 'Download',\n    tipClose: 'Chiudi (Esc)',\n    tipOriginalSize: 'Torna alla dimensione originale'\n  },\n  Heatmap: {\n    less: 'meno',\n    more: 'più',\n    monthFormat: 'MMM',\n    weekdayFormat: 'eeeeee'\n  }\n}\n\nexport default itIT\n"
  },
  {
    "path": "src/locales/common/jaJP.ts",
    "content": "import type { NLocale } from './enUS'\n\nconst jaJP: NLocale = {\n  name: 'ja-JP',\n  global: {\n    undo: '元に戻す',\n    redo: 'やり直す',\n    confirm: 'OK',\n    clear: 'クリア'\n  },\n  Popconfirm: {\n    positiveText: 'OK',\n    negativeText: 'キャンセル'\n  },\n  Cascader: {\n    placeholder: '選択してください',\n    loading: 'ロード中',\n    loadingRequiredMessage: (label: string): string =>\n      `すべての ${label} サブノードをロードしてから選択できます。`\n  },\n  Time: {\n    dateFormat: 'yyyy-MM-dd',\n    dateTimeFormat: 'yyyy-MM-dd HH:mm:ss'\n  },\n  DatePicker: {\n    yearFormat: 'yyyy年',\n    monthFormat: 'MMM',\n    dayFormat: 'eeeeee',\n    yearTypeFormat: 'yyyy',\n    monthTypeFormat: 'yyyy-MM',\n    dateFormat: 'yyyy-MM-dd',\n    dateTimeFormat: 'yyyy-MM-dd HH:mm:ss',\n    quarterFormat: 'yyyy-qqq',\n    weekFormat: 'YYYY-w',\n    clear: 'クリア',\n    now: '現在',\n    confirm: 'OK',\n    selectTime: '時間を選択',\n    selectDate: '日付を選択',\n    datePlaceholder: '日付を選択',\n    datetimePlaceholder: '選択',\n    monthPlaceholder: '月を選択',\n    yearPlaceholder: '年を選択',\n    quarterPlaceholder: '四半期を選択',\n    weekPlaceholder: 'Select Week',\n    startDatePlaceholder: '開始日',\n    endDatePlaceholder: '終了日',\n    startDatetimePlaceholder: '開始時間',\n    endDatetimePlaceholder: '終了時間',\n    startMonthPlaceholder: '開始月',\n    endMonthPlaceholder: '終了月',\n    monthBeforeYear: false,\n    firstDayOfWeek: 0,\n    today: '今日'\n  },\n  DataTable: {\n    checkTableAll: '全選択',\n    uncheckTableAll: '全選択取消',\n    confirm: 'OK',\n    clear: 'リセット'\n  },\n  LegacyTransfer: {\n    sourceTitle: '元',\n    targetTitle: '先'\n  },\n  Transfer: {\n    selectAll: '全選択',\n    unselectAll: '全選択取消',\n    clearAll: 'リセット',\n    total: (num: number): string => `合計 ${num} 項目`,\n    selected: (num: number): string => `${num} 個の項目を選択`\n  },\n  Empty: {\n    description: 'データなし'\n  },\n  Select: {\n    placeholder: '選択してください'\n  },\n  TimePicker: {\n    placeholder: '選択してください',\n    positiveText: 'OK',\n    negativeText: 'キャンセル',\n    now: '現在',\n    clear: 'クリア'\n  },\n  Pagination: {\n    goto: 'ページジャンプ',\n    selectionSuffix: 'ページ'\n  },\n  DynamicTags: {\n    add: '追加'\n  },\n  Log: {\n    loading: 'ロード中'\n  },\n  Input: {\n    placeholder: '入力してください'\n  },\n  InputNumber: {\n    placeholder: '入力してください'\n  },\n  DynamicInput: {\n    create: '追加'\n  },\n  ThemeEditor: {\n    title: 'テーマエディタ',\n    clearAllVars: '全件変数クリア',\n    clearSearch: '検索クリア',\n    filterCompName: 'コンポネント名をフィルタ',\n    filterVarName: '変数をフィルタ',\n    import: 'インポート',\n    export: 'エクスポート',\n    restore: 'デフォルト'\n  },\n  Image: {\n    tipPrevious: '前の画像 (←)',\n    tipNext: '次の画像 (→)',\n    tipCounterclockwise: '左に回転',\n    tipClockwise: '右に回転',\n    tipZoomOut: '縮小',\n    tipZoomIn: '拡大',\n    tipDownload: 'ダウンロード',\n    tipClose: '閉じる (Esc)',\n    tipOriginalSize: '元のサイズに戻す'\n  },\n  Heatmap: {\n    less: '少',\n    more: '多',\n    monthFormat: 'MMM',\n    weekdayFormat: 'eeeeee'\n  }\n}\n\nexport default jaJP\n"
  },
  {
    "path": "src/locales/common/kmKH.ts",
    "content": "import type { NLocale } from './enUS'\n\nconst kmKH: NLocale = {\n  name: 'km-KH',\n  global: {\n    undo: 'បោះបង់',\n    redo: 'ធ្វើឡើងវិញ',\n    confirm: 'បញ្ជាក់',\n    clear: 'ច្បាស់'\n  },\n  Popconfirm: {\n    positiveText: 'បញ្ជាក់',\n    negativeText: 'បោះបង់'\n  },\n  Cascader: {\n    placeholder: 'សូមជ្រើសរើស',\n    loading: 'ការផ្ទុក',\n    loadingRequiredMessage: (label: string): string =>\n      `អាចជ្រើសរើសបានតែបន្ទាប់ពីផ្ទុកថ្នាំងកូន  ${label} ទាំងអស់។`\n  },\n  Time: {\n    dateFormat: 'yyyy-MM-dd',\n    dateTimeFormat: 'yyyy-MM-dd HH:mm:ss'\n  },\n  DatePicker: {\n    yearFormat: 'yyyyឆ្នាំ',\n    monthFormat: 'MMM',\n    dayFormat: 'eeeeee',\n    yearTypeFormat: 'yyyy',\n    monthTypeFormat: 'yyyy-MM',\n    dateFormat: 'yyyy-MM-dd',\n    dateTimeFormat: 'yyyy-MM-dd HH:mm:ss',\n    quarterFormat: 'yyyy-qqq',\n    weekFormat: 'YYYY-wសប្តាហ៍',\n    clear: 'ច្បាស់',\n    now: 'ឥឡូវនេះ',\n    confirm: 'បញ្ជាក់',\n    selectTime: 'ជ្រើសរើសកាលបរិច្ឆេទ',\n    selectDate: 'ជ្រើសរើសកាលបរិច្ឆេទ',\n    datePlaceholder: 'ជ្រើសរើសកាលបរិច្ឆេទ',\n    datetimePlaceholder: 'ជ្រើសរើសពេលវេលាកាលបរិច្ឆេទ',\n    monthPlaceholder: 'ជ្រើសរើសខែ',\n    yearPlaceholder: 'ជ្រើសរើសឆ្នាំ',\n    quarterPlaceholder: 'ជ្រើសរើសត្រីមាស',\n    weekPlaceholder: 'ជ្រើសរើសសប្តាហ៍',\n    startDatePlaceholder: 'កាលបរិច្ឆេទចាប់ផ្តើម',\n    endDatePlaceholder: 'កាលបរិច្ឆេទបញ្ចប់',\n    startDatetimePlaceholder: 'កាលបរិច្ឆេទចាប់ផ្តើម',\n    endDatetimePlaceholder: 'កាលបរិច្ឆេទបញ្ចប់',\n    startMonthPlaceholder: 'ខែចាប់ផ្តើម',\n    endMonthPlaceholder: 'ចុងខែ',\n    monthBeforeYear: false,\n    firstDayOfWeek: 0,\n    today: 'ថ្ងៃនេះ'\n  },\n  DataTable: {\n    checkTableAll: 'ជ្រើសរើសទិន្នន័យតារាងទាំងអស់។',\n    uncheckTableAll: 'ដកការជ្រើសរើសទិន្នន័យតារាងទាំងអស់។',\n    confirm: 'បញ្ជាក់',\n    clear: 'កំណត់ឡើងវិញ'\n  },\n  LegacyTransfer: {\n    sourceTitle: 'ធាតុប្រភព',\n    targetTitle: 'ធាតុគោលដៅ'\n  },\n  Transfer: {\n    selectAll: 'ជ្រើសរើសទាំងអស់។',\n    clearAll: 'ច្បាស់',\n    unselectAll: 'ដកការជ្រើសរើសទាំងអស់។',\n    total: (num: number): string => `ទូទៅ ${num} ធាតុ`,\n    selected: (num: number): string => `បានជ្រើសរើស ${num} ធាតុ`\n  },\n  Empty: {\n    description: 'គ្មានទិន្នន័យ'\n  },\n  Select: {\n    placeholder: 'សូមជ្រើសរើស'\n  },\n  TimePicker: {\n    placeholder: 'សូមជ្រើសរើសពេលវេលាមួយ។',\n    positiveText: 'បញ្ជាក់',\n    negativeText: 'បោះបង់',\n    now: 'ឥឡូវនេះ',\n    clear: 'ច្បាស់'\n  },\n  Pagination: {\n    goto: 'លោតទៅ',\n    selectionSuffix: 'ទំព័រ'\n  },\n  DynamicTags: {\n    add: 'បន្ថែមទៅ'\n  },\n  Log: {\n    loading: 'ការផ្ទុក'\n  },\n  Input: {\n    placeholder: 'សូមបញ្ចូល'\n  },\n  InputNumber: {\n    placeholder: 'សូមបញ្ចូល'\n  },\n  DynamicInput: {\n    create: 'បន្ថែមទៅ'\n  },\n  ThemeEditor: {\n    title: 'កម្មវិធីនិពន្ធប្រធានបទ',\n    clearAllVars: 'សម្អាតអថេរទាំងអស់។',\n    clearSearch: 'ជម្រះការស្វែងរក',\n    filterCompName: 'តម្រងឈ្មោះសមាសភាគ',\n    filterVarName: 'ត្រងឈ្មោះអថេរ',\n    import: 'នាំចូល',\n    export: 'នាំចេញ',\n    restore: 'ស្តារលំនាំដើម'\n  },\n  Image: {\n    tipPrevious: 'រូបភាពមុន។（←）',\n    tipNext: 'បន្ទាប់（→）',\n    tipCounterclockwise: 'បង្វិលឆ្វេង',\n    tipClockwise: 'បង្វិលស្តាំ',\n    tipZoomOut: 'បង្រួម ',\n    tipZoomIn: 'ពង្រីក',\n    tipDownload: 'ទាញយក',\n    tipClose: 'ការបិទ（Esc）',\n    tipOriginalSize: 'ធ្វើមាត្រដ្ឋានទៅទំហំដើម'\n  },\n  Heatmap: {\n    less: 'less',\n    more: 'more',\n    monthFormat: 'MMM',\n    weekdayFormat: 'eeeeee'\n  }\n}\n\nexport default kmKH\n"
  },
  {
    "path": "src/locales/common/koKR.ts",
    "content": "import type { NLocale } from './enUS'\n\nconst koKR: NLocale = {\n  name: 'ko-KR',\n  global: {\n    undo: '실행 취소',\n    redo: '다시 실행',\n    confirm: '확인',\n    clear: '지우기'\n  },\n  Popconfirm: {\n    positiveText: '확인',\n    negativeText: '취소'\n  },\n  Cascader: {\n    placeholder: '선택해 주세요',\n    loading: '불러오는 중',\n    loadingRequiredMessage: (label: string): string =>\n      `${label}의 모든 하위 항목을 불러온 뒤에 선택할 수 있습니다.`\n  },\n  Time: {\n    dateFormat: 'yyyy-MM-dd',\n    dateTimeFormat: 'yyyy-MM-dd HH:mm:ss'\n  },\n  DatePicker: {\n    yearFormat: 'yyyy년',\n    monthFormat: 'MMM',\n    dayFormat: 'eeeeee',\n    yearTypeFormat: 'yyyy',\n    monthTypeFormat: 'yyyy-MM',\n    dateFormat: 'yyyy-MM-dd',\n    dateTimeFormat: 'yyyy-MM-dd HH:mm:ss',\n    quarterFormat: 'yyyy-qqq',\n    weekFormat: 'YYYY-w',\n    clear: '지우기',\n    now: '현재',\n    confirm: '확인',\n    selectTime: '시간 선택',\n    selectDate: '날짜 선택',\n    datePlaceholder: '날짜 선택',\n    datetimePlaceholder: '날짜 및 시간 선택',\n    monthPlaceholder: '월 선택',\n    yearPlaceholder: '년 선택',\n    quarterPlaceholder: '분기 선택',\n    weekPlaceholder: 'Select Week',\n    startDatePlaceholder: '시작 날짜',\n    endDatePlaceholder: '종료 날짜',\n    startDatetimePlaceholder: '시작 날짜 및 시간',\n    endDatetimePlaceholder: '종료 날짜 및 시간',\n    // FIXME: translation needed\n    startMonthPlaceholder: '시작 월',\n    endMonthPlaceholder: '종료 월',\n    monthBeforeYear: false,\n    firstDayOfWeek: 6 as 0 | 1 | 2 | 3 | 4 | 5 | 6,\n    today: '오늘'\n  },\n  DataTable: {\n    checkTableAll: '모두 선택',\n    uncheckTableAll: '모두 선택 해제',\n    confirm: '확인',\n    clear: '지우기'\n  },\n  LegacyTransfer: {\n    sourceTitle: '원본',\n    targetTitle: '타깃'\n  },\n  // TODO: translation\n  Transfer: {\n    selectAll: '전체 선택',\n    unselectAll: '전체 해제',\n    clearAll: '전체 삭제',\n    total: (num: number): string => `총 ${num} 개`,\n    selected: (num: number): string => `${num} 개 선택`\n  },\n  Empty: {\n    description: '데이터 없음'\n  },\n  Select: {\n    placeholder: '선택해 주세요'\n  },\n  TimePicker: {\n    placeholder: '시간 선택',\n    positiveText: '확인',\n    negativeText: '취소',\n    now: '현재 시간',\n    clear: '지우기'\n  },\n  Pagination: {\n    goto: '이동',\n    selectionSuffix: '페이지'\n  },\n  DynamicTags: {\n    add: '추가'\n  },\n  Log: {\n    loading: '불러오는 중'\n  },\n  Input: {\n    placeholder: '입력해 주세요'\n  },\n  InputNumber: {\n    placeholder: '입력해 주세요'\n  },\n  DynamicInput: {\n    create: '추가'\n  },\n  ThemeEditor: {\n    title: '테마 편집기',\n    clearAllVars: '모든 변수 지우기',\n    clearSearch: '검색 지우기',\n    filterCompName: '구성 요소 이름 필터',\n    filterVarName: '변수 이름 필터',\n    import: '가져오기',\n    export: '내보내기',\n    restore: '기본으로 재설정'\n  },\n  Image: {\n    tipPrevious: '이전 (←)',\n    tipNext: '다음 (→)',\n    tipCounterclockwise: '시계 반대 방향으로 회전',\n    tipClockwise: '시계 방향으로 회전',\n    tipZoomOut: '축소',\n    tipZoomIn: '확대',\n    tipDownload: '다운로드',\n    tipClose: '닫기 (Esc)',\n    // TODO: translation\n    tipOriginalSize: '원본 크기로 확대'\n  },\n  Heatmap: {\n    less: '적음',\n    more: '많음',\n    monthFormat: 'MMM',\n    weekdayFormat: 'eeeeee'\n  }\n}\n\nexport default koKR\n"
  },
  {
    "path": "src/locales/common/nbNO.ts",
    "content": "import type { NLocale } from './enUS'\n\nconst nbNO: NLocale = {\n  name: 'nb-NO',\n  global: {\n    undo: 'Angre',\n    redo: 'Utfør likevel',\n    confirm: 'Bekreft',\n    clear: 'Tøm'\n  },\n  Popconfirm: {\n    positiveText: 'Bekreft',\n    negativeText: 'Avbryt'\n  },\n  Cascader: {\n    placeholder: 'Vennligst velg',\n    loading: 'Laster',\n    loadingRequiredMessage: (label: string): string =>\n      `Vennligst last alle underpunkter av ${label} før du velger oppføringen.`\n  },\n  Time: {\n    dateFormat: 'dd.MM.yyyy',\n    dateTimeFormat: 'dd.MM.yyyy HH:mm:ss'\n  },\n  DatePicker: {\n    yearFormat: 'yyyy',\n    monthFormat: 'MMM',\n    dayFormat: 'eeeeee',\n    yearTypeFormat: 'yyyy',\n    monthTypeFormat: 'MM.yyyy',\n    dateFormat: 'dd.MM.yyyy',\n    dateTimeFormat: 'dd.MM.yyyy HH:mm:ss',\n    quarterFormat: 'yyyy-qqq',\n    weekFormat: 'YYYY-w',\n    clear: 'Tøm',\n    now: 'Nå',\n    confirm: 'Bekreft',\n    selectTime: 'Velg tid',\n    selectDate: 'Velg dato',\n    datePlaceholder: 'Velg dato',\n    datetimePlaceholder: 'Velg dato og tid',\n    monthPlaceholder: 'Velg måned',\n    // FIXME: translation needed\n    yearPlaceholder: 'Select Year',\n    quarterPlaceholder: 'Select Quarter',\n    weekPlaceholder: 'Select Week',\n    startDatePlaceholder: 'Startdato',\n    endDatePlaceholder: 'Sluttdato',\n    startDatetimePlaceholder: 'Startdato og -tid',\n    endDatetimePlaceholder: 'Sluttdato og -tid',\n    // FIXME: translation needed\n    startMonthPlaceholder: 'Start Month',\n    endMonthPlaceholder: 'End Month',\n    monthBeforeYear: true,\n    firstDayOfWeek: 0 as 0 | 1 | 2 | 3 | 4 | 5 | 6,\n    today: 'I dag'\n  },\n  DataTable: {\n    checkTableAll: 'Velg alt',\n    uncheckTableAll: 'Velg ingenting',\n    confirm: 'Bekreft',\n    clear: 'Tøm'\n  },\n  LegacyTransfer: {\n    sourceTitle: 'Kilde',\n    targetTitle: 'Mål'\n  },\n  // TODO: translation\n  Transfer: {\n    selectAll: 'Select all',\n    unselectAll: 'Unselect all',\n    clearAll: 'Clear',\n    total: (num: number): string => `Total ${num} items`,\n    selected: (num: number): string => `${num} items selected`\n  },\n  Empty: {\n    description: 'Ingen data'\n  },\n  Select: {\n    placeholder: 'Vennligst velg'\n  },\n  TimePicker: {\n    placeholder: 'Velg tid',\n    positiveText: 'OK',\n    negativeText: 'Avbryt',\n    now: 'Nå',\n    clear: 'Tøm'\n  },\n  Pagination: {\n    goto: 'Gå til',\n    selectionSuffix: 'side'\n  },\n  DynamicTags: {\n    add: 'Legg til'\n  },\n  Log: {\n    loading: 'Laster'\n  },\n  Input: {\n    placeholder: 'Vennligst fyll ut'\n  },\n  InputNumber: {\n    placeholder: 'Vennligst fyll ut'\n  },\n  DynamicInput: {\n    create: 'Opprett'\n  },\n  ThemeEditor: {\n    title: 'Temaredigerer',\n    clearAllVars: 'Nullstill alle variabler',\n    clearSearch: 'Tøm søk',\n    filterCompName: 'Filtrer etter komponentnavn',\n    filterVarName: 'Filtrer etter variabelnavn',\n    import: 'Importer',\n    export: 'Eksporter',\n    restore: 'Nullstill til standardvalg'\n  },\n  Image: {\n    tipPrevious: 'Previous picture (←)',\n    tipNext: 'Next picture (→)',\n    tipCounterclockwise: 'Counterclockwise',\n    tipClockwise: 'Clockwise',\n    tipZoomOut: 'Zoom out',\n    tipZoomIn: 'Zoom in',\n    tipDownload: 'Download',\n    tipClose: 'Close (Esc)',\n    // TODO: translation\n    tipOriginalSize: 'Zoom to original size'\n  },\n  Heatmap: {\n    less: 'mindre',\n    more: 'mer',\n    monthFormat: 'MMM',\n    weekdayFormat: 'eeeeee'\n  }\n}\n\nexport default nbNO\n"
  },
  {
    "path": "src/locales/common/nlNL.ts",
    "content": "import type { NLocale } from './enUS'\n\nconst nlNL: NLocale = {\n  name: 'nl-NL',\n  global: {\n    undo: 'Ongedaan Maken',\n    redo: 'Opnieuw Doen',\n    confirm: 'Bevestig',\n    clear: 'Wis'\n  },\n  Popconfirm: {\n    positiveText: 'Bevestig',\n    negativeText: 'Annuleer'\n  },\n  Cascader: {\n    placeholder: 'Selecteer a.u.b.',\n    loading: 'Laden',\n    loadingRequiredMessage: (label: string): string =>\n      `Laad alle afstammelingen van ${label} alvorens het te selecteren.`\n  },\n  Time: {\n    dateFormat: 'dd/MM/yyyy',\n    dateTimeFormat: 'dd/MM/yyyy HH:mm:ss'\n  },\n  DatePicker: {\n    yearFormat: 'yyyy',\n    monthFormat: 'MMM',\n    dayFormat: 'eeeeee',\n    yearTypeFormat: 'yyyy',\n    monthTypeFormat: 'MM/yyyy',\n    dateFormat: 'dd/MM/yyyy',\n    dateTimeFormat: 'dd/MM/yyyy HH:mm:ss',\n    quarterFormat: 'qqq yyyy',\n    weekFormat: 'YYYY-w',\n    clear: 'Wis',\n    now: 'Nu',\n    confirm: 'Bevestig',\n    selectTime: 'Selecteer Uur',\n    selectDate: 'Selecteer Datum',\n    datePlaceholder: 'Selecteer Datum',\n    datetimePlaceholder: 'Selecteer Dag en Uur',\n    monthPlaceholder: 'Selecteer Maand',\n    yearPlaceholder: 'Selecteer Jaar',\n    quarterPlaceholder: 'Selecteer Kwartaal',\n    weekPlaceholder: 'Select Week',\n    startDatePlaceholder: 'Begindatum',\n    endDatePlaceholder: 'Einddatum',\n    startDatetimePlaceholder: 'Begindatum en Uur',\n    endDatetimePlaceholder: 'Einddatum en Uur',\n    startMonthPlaceholder: 'Begin Maand',\n    endMonthPlaceholder: 'Eind Maand',\n    monthBeforeYear: true,\n    firstDayOfWeek: 0 as 0 | 1 | 2 | 3 | 4 | 5 | 6,\n    today: 'Vandaag'\n  },\n  DataTable: {\n    checkTableAll: 'Selecteer alles in de tabel',\n    uncheckTableAll: 'Alles in de tabel deselecteren',\n    confirm: 'Bevestig',\n    clear: 'Wis'\n  },\n  LegacyTransfer: {\n    sourceTitle: 'Bron',\n    targetTitle: 'Doel'\n  },\n  // TODO: translation\n  Transfer: {\n    selectAll: 'Select all',\n    unselectAll: 'Unselect all',\n    clearAll: 'Clear',\n    total: (num: number): string => `Total ${num} items`,\n    selected: (num: number): string => `${num} items selected`\n  },\n  Empty: {\n    description: 'Geen Data'\n  },\n  Select: {\n    placeholder: 'Selecteer a.u.b.'\n  },\n  TimePicker: {\n    placeholder: 'Selecteer Uur',\n    positiveText: 'OK',\n    negativeText: 'Annuleer',\n    now: 'Nu',\n    clear: 'Wis'\n  },\n  Pagination: {\n    goto: 'Ga naar',\n    selectionSuffix: 'pagina'\n  },\n  DynamicTags: {\n    add: 'Toevoegen'\n  },\n  Log: {\n    loading: 'Laden'\n  },\n  Input: {\n    placeholder: 'Invoeren a.u.b.'\n  },\n  InputNumber: {\n    placeholder: 'Invoeren a.u.b.'\n  },\n  DynamicInput: {\n    create: 'Creëer'\n  },\n  ThemeEditor: {\n    title: 'Thema Bewerker',\n    clearAllVars: 'Wis Alle Variabelen',\n    clearSearch: 'Wis Zoekopdracht',\n    filterCompName: 'Filter Componentsnaam',\n    filterVarName: 'Filter Variablenaam',\n    import: 'Importen',\n    export: 'Exporteren',\n    restore: 'Reset naar Standaard'\n  },\n  Image: {\n    tipPrevious: 'Vorige afbeelding (←)',\n    tipNext: 'Volgende afbeelding (→)',\n    tipCounterclockwise: 'Tegen de klok in',\n    tipClockwise: 'Met de klok mee',\n    tipZoomOut: 'Uitzoomen',\n    tipZoomIn: 'Inzoomen',\n    tipDownload: 'Download',\n    tipClose: 'Sluiten (Esc)',\n    // TODO: translation\n    tipOriginalSize: 'Zoom to original size'\n  },\n  Heatmap: {\n    less: 'minder',\n    more: 'meer',\n    monthFormat: 'MMM',\n    weekdayFormat: 'eeeeee'\n  }\n}\n\nexport default nlNL\n"
  },
  {
    "path": "src/locales/common/plPL.ts",
    "content": "import type { NLocale } from './enUS'\n\nconst plPL: NLocale = {\n  name: 'pl-PL',\n  global: {\n    undo: 'Cofnij',\n    redo: 'Ponów',\n    confirm: 'Potwierdź',\n    clear: 'Wyczyść'\n  },\n  Popconfirm: {\n    positiveText: 'Potwierdź',\n    negativeText: 'Anuluj'\n  },\n  Cascader: {\n    placeholder: 'Wybierz',\n    loading: 'Ładowanie',\n    loadingRequiredMessage: (label: string): string =>\n      `Proszę załadować wszystkie ${label}'s elementy przed sprawdzeniem.`\n  },\n  Time: {\n    dateFormat: 'yyyy-MM-dd',\n    dateTimeFormat: 'yyyy-MM-dd HH:mm:ss'\n  },\n  DatePicker: {\n    yearFormat: 'yyyy',\n    monthFormat: 'MMM',\n    dayFormat: 'eeeeee',\n    yearTypeFormat: 'yyyy',\n    monthTypeFormat: 'yyyy-MM',\n    dateFormat: 'yyyy-MM-dd',\n    dateTimeFormat: 'yyyy-MM-dd HH:mm:ss',\n    quarterFormat: 'yyyy-qqq',\n    weekFormat: 'YYYY-w',\n    clear: 'Wyczyść',\n    now: 'Teraz',\n    confirm: 'Potwierdź',\n    selectTime: 'Wybierz czas',\n    selectDate: 'Wybierz datę',\n    datePlaceholder: 'Wybierz datę',\n    datetimePlaceholder: 'Wybierz datę i czas',\n    monthPlaceholder: 'Wybierz miesiąc',\n    yearPlaceholder: 'Wybierz rok',\n    quarterPlaceholder: 'Wybierz kwartał',\n    weekPlaceholder: 'Select Week',\n    startDatePlaceholder: 'Data rozpoczęcia',\n    endDatePlaceholder: 'Data zakończenia',\n    startDatetimePlaceholder: 'Data i godzina rozpoczęcia',\n    endDatetimePlaceholder: 'Data i godzina zakończenia',\n    // FIXME: translation needed\n    startMonthPlaceholder: 'Start Month',\n    endMonthPlaceholder: 'End Month',\n    monthBeforeYear: true,\n    firstDayOfWeek: 6,\n    today: 'Dziś'\n  },\n  DataTable: {\n    checkTableAll: 'Zaznacz wszystkie w tabeli',\n    uncheckTableAll: 'Odznacz wszystkie w tabeli',\n    confirm: 'Potwierdź',\n    clear: 'Wyczyść'\n  },\n  LegacyTransfer: {\n    sourceTitle: 'Źródło',\n    targetTitle: 'Cel'\n  },\n  // TODO: translation\n  Transfer: {\n    selectAll: 'Select all',\n    unselectAll: 'Unselect all',\n    clearAll: 'Clear',\n    total: (num: number): string => `Total ${num} items`,\n    selected: (num: number): string => `${num} items selected`\n  },\n  Empty: {\n    description: 'Brak danych'\n  },\n  Select: {\n    placeholder: 'Wybierz'\n  },\n  TimePicker: {\n    placeholder: 'Wybierz czas',\n    positiveText: 'Potwierdź',\n    negativeText: 'Anuluj',\n    now: 'Teraz',\n    clear: 'Wyczyść'\n  },\n  Pagination: {\n    goto: 'Idź do',\n    selectionSuffix: 'strona'\n  },\n  DynamicTags: {\n    add: 'Dodaj'\n  },\n  Log: {\n    loading: 'Ładowanie'\n  },\n  Input: {\n    placeholder: 'Wprowadź dane'\n  },\n  InputNumber: {\n    placeholder: 'Wprowadź dane'\n  },\n  DynamicInput: {\n    create: 'Utwórz'\n  },\n  ThemeEditor: {\n    title: 'Edytor motywów',\n    clearAllVars: 'Wyczyść wszystkie zmienne',\n    clearSearch: 'Wyczyść wyszukiwanie',\n    filterCompName: 'Nazwa komponentu filtra',\n    filterVarName: 'Nazwa zmiennej filtra',\n    import: 'Importuj',\n    export: 'Eksportuj',\n    restore: 'Przywróć ustawienia domyślne'\n  },\n  Image: {\n    tipPrevious: 'Poprzednie zdjęcie (←)',\n    tipNext: 'Następne zdjęcie (→)',\n    tipCounterclockwise: 'Przeciwnie do ruchu wskazówek zegara',\n    tipClockwise: 'Zgodnie z ruchem wskazówek zegara',\n    tipZoomOut: 'Powiększ',\n    tipZoomIn: 'Pomniejsz',\n    tipDownload: 'Pobierz',\n    tipClose: 'Zamknij (Esc)',\n    // TODO: translation\n    tipOriginalSize: 'Zoom to original size'\n  },\n  Heatmap: {\n    less: 'mniej',\n    more: 'więcej',\n    monthFormat: 'MMM',\n    weekdayFormat: 'eeeeee'\n  }\n}\n\nexport default plPL\n"
  },
  {
    "path": "src/locales/common/ptBR.ts",
    "content": "import type { NLocale } from './enUS'\n\nconst ptBR: NLocale = {\n  name: 'pt-BR',\n  global: {\n    undo: 'Desfazer',\n    redo: 'Refazer',\n    confirm: 'Confirmar',\n    clear: 'Limpar'\n  },\n  Popconfirm: {\n    positiveText: 'Confirmar',\n    negativeText: 'Cancelar'\n  },\n  Cascader: {\n    placeholder: 'Por favor selecione',\n    loading: 'Carregando',\n    loadingRequiredMessage: (label: string): string =>\n      `Carregue todos os descendentes de ${label} antes de verificar.`\n  },\n  Time: {\n    dateFormat: 'dd/MM/yyyy',\n    dateTimeFormat: 'dd/MM/yyyy HH:mm:ss'\n  },\n  DatePicker: {\n    yearFormat: 'yyyy',\n    monthFormat: 'MMM',\n    dayFormat: 'eeeeee',\n    yearTypeFormat: 'yyyy',\n    monthTypeFormat: 'yyyy/MM',\n    dateFormat: 'dd/MM/yyyy',\n    dateTimeFormat: 'dd/MM/yyyy HH:mm:ss',\n    quarterFormat: 'yyyy/qqq',\n    weekFormat: 'YYYY-w',\n    clear: 'Limpar',\n    now: 'Agora',\n    confirm: 'Confirmar',\n    selectTime: 'Selecione a hora',\n    selectDate: 'Selecione a data',\n    datePlaceholder: 'Selecione a data',\n    datetimePlaceholder: 'Selecione a data e hora',\n    monthPlaceholder: 'Selecione o mês',\n    yearPlaceholder: 'Selecione o ano',\n    quarterPlaceholder: 'Selecione o trimestre',\n    weekPlaceholder: 'Select Week',\n    startDatePlaceholder: 'Selecione a data de início',\n    endDatePlaceholder: 'Selecione a data de término',\n    startDatetimePlaceholder: 'Selecione a data e hora de início',\n    endDatetimePlaceholder: 'Selecione a data e hora de término',\n    startMonthPlaceholder: 'Selecione o mês de início',\n    endMonthPlaceholder: 'Selecione o mês de término',\n    monthBeforeYear: true,\n    firstDayOfWeek: 6 as 0 | 1 | 2 | 3 | 4 | 5 | 6,\n    today: 'Hoje'\n  },\n  DataTable: {\n    checkTableAll: 'Selecionar todos na tabela',\n    uncheckTableAll: 'Desmarcar todos na tabela',\n    confirm: 'Confirmar',\n    clear: 'Limpar'\n  },\n  LegacyTransfer: {\n    sourceTitle: 'Origem',\n    targetTitle: 'Destino'\n  },\n  Transfer: {\n    selectAll: 'Selecionar todos',\n    unselectAll: 'Desmarcar todos',\n    clearAll: 'Limpar',\n    total: (num: number): string => `Total ${num} itens`,\n    selected: (num: number): string => `${num} itens selecionados`\n  },\n  Empty: {\n    description: 'Não há dados'\n  },\n  Select: {\n    placeholder: 'Por favor selecione'\n  },\n  TimePicker: {\n    placeholder: 'Selecione a hora',\n    positiveText: 'OK',\n    negativeText: 'Cancelar',\n    now: 'Agora',\n    clear: 'Limpar'\n  },\n  Pagination: {\n    goto: 'Ir para',\n    selectionSuffix: 'página'\n  },\n  DynamicTags: {\n    add: 'Adicionar'\n  },\n  Log: {\n    loading: 'Carregando'\n  },\n  Input: {\n    placeholder: 'Por favor digite'\n  },\n  InputNumber: {\n    placeholder: 'Por favor digite'\n  },\n  DynamicInput: {\n    create: 'Criar'\n  },\n  ThemeEditor: {\n    title: 'Editor de temas',\n    clearAllVars: 'Limpar todas as variáveis',\n    clearSearch: 'Limpar pesquisa',\n    filterCompName: 'Filtrar nome do componente',\n    filterVarName: 'Filtrar nome da variável',\n    import: 'Importar',\n    export: 'Exportar',\n    restore: 'Restaurar'\n  },\n  Image: {\n    tipPrevious: 'Foto anterior (←)',\n    tipNext: 'Próxima foto (→)',\n    tipCounterclockwise: 'Sentido anti-horário',\n    tipClockwise: 'Sentido horário',\n    tipZoomOut: 'Reduzir o zoom',\n    tipZoomIn: 'Aumentar o zoom',\n    tipDownload: 'Download',\n    tipClose: 'Fechar (Esc)',\n    tipOriginalSize: 'Exibir no tamanho original'\n  },\n  Heatmap: {\n    less: 'menos',\n    more: 'mais',\n    monthFormat: 'MMM',\n    weekdayFormat: 'eeeeee'\n  }\n}\n\nexport default ptBR\n"
  },
  {
    "path": "src/locales/common/ruRU.ts",
    "content": "import type { NLocale } from './enUS'\n\nconst ruRu: NLocale = {\n  name: 'ru-RU',\n  global: {\n    undo: 'Отменить',\n    redo: 'Вернуть',\n    confirm: 'Подтвердить',\n    clear: 'Очистить'\n  },\n  Popconfirm: {\n    positiveText: 'Подтвердить',\n    negativeText: 'Отмена'\n  },\n  Cascader: {\n    placeholder: 'Выбрать',\n    loading: 'Загрузка',\n    loadingRequiredMessage: (label: string): string =>\n      `Загрузите все дочерние узлы ${label} прежде чем они станут необязательными`\n  },\n  Time: {\n    dateFormat: 'yyyy-MM-dd',\n    dateTimeFormat: 'yyyy-MM-dd HH:mm:ss'\n  },\n  DatePicker: {\n    yearFormat: 'yyyy',\n    monthFormat: 'MMM',\n    dayFormat: 'eeeeee',\n    yearTypeFormat: 'yyyy',\n    monthTypeFormat: 'yyyy-MM',\n    dateFormat: 'yyyy-MM-dd',\n    dateTimeFormat: 'yyyy-MM-dd HH:mm:ss',\n    quarterFormat: 'yyyy-qqq',\n    weekFormat: 'YYYY-w',\n    clear: 'Очистить',\n    now: 'Сейчас',\n    confirm: 'Подтвердить',\n    selectTime: 'Выбрать время',\n    selectDate: 'Выбрать дату',\n    datePlaceholder: 'Выбрать дату',\n    datetimePlaceholder: 'Выбрать дату и время',\n    monthPlaceholder: 'Выберите месяц',\n    yearPlaceholder: 'Выберите год',\n    quarterPlaceholder: 'Выберите квартал',\n    weekPlaceholder: 'Select Week',\n    startDatePlaceholder: 'Дата начала',\n    endDatePlaceholder: 'Дата окончания',\n    startDatetimePlaceholder: 'Дата и время начала',\n    endDatetimePlaceholder: 'Дата и время окончания',\n    startMonthPlaceholder: 'Начало месяца',\n    endMonthPlaceholder: 'Конец месяца',\n    monthBeforeYear: true,\n    firstDayOfWeek: 0 as 0 | 1 | 2 | 3 | 4 | 5 | 6,\n    today: 'Сегодня'\n  },\n  DataTable: {\n    checkTableAll: 'Выбрать все в таблице',\n    uncheckTableAll: 'Отменить все в таблице',\n    confirm: 'Подтвердить',\n    clear: 'Очистить'\n  },\n  LegacyTransfer: {\n    sourceTitle: 'Источник',\n    targetTitle: 'Назначение'\n  },\n  Transfer: {\n    selectAll: 'Выбрать все',\n    unselectAll: 'Снять все',\n    clearAll: 'Очистить',\n    total: (num: number): string => `Всего ${num} элементов`,\n    selected: (num: number): string => `${num} выбрано элементов`\n  },\n  Empty: {\n    description: 'Нет данных'\n  },\n  Select: {\n    placeholder: 'Выбрать'\n  },\n  TimePicker: {\n    placeholder: 'Выбрать время',\n    positiveText: 'OK',\n    negativeText: 'Отменить',\n    now: 'Сейчас',\n    clear: 'Очистить'\n  },\n  Pagination: {\n    goto: 'Перейти',\n    selectionSuffix: 'страница'\n  },\n  DynamicTags: {\n    add: 'Добавить'\n  },\n  Log: {\n    loading: 'Загрузка'\n  },\n  Input: {\n    placeholder: 'Ввести'\n  },\n  InputNumber: {\n    placeholder: 'Ввести'\n  },\n  DynamicInput: {\n    create: 'Создать'\n  },\n  ThemeEditor: {\n    title: 'Редактор темы',\n    clearAllVars: 'Очистить все',\n    clearSearch: 'Очистить поиск',\n    filterCompName: 'Фильтровать по имени компонента',\n    filterVarName: 'Фильтровать имена переменных',\n    import: 'Импорт',\n    export: 'Экспорт',\n    restore: 'Сбросить'\n  },\n  Image: {\n    tipPrevious: 'Предыдущее изображение (←)',\n    tipNext: 'Следующее изображение (→)',\n    tipCounterclockwise: 'Против часовой стрелки',\n    tipClockwise: 'По часовой стрелке',\n    tipZoomOut: 'Отдалить',\n    tipZoomIn: 'Приблизить',\n    tipDownload: 'Скачать',\n    tipClose: 'Закрыть (Esc)',\n    tipOriginalSize: 'Вернуть исходный размер'\n  },\n  Heatmap: {\n    less: 'меньше',\n    more: 'больше',\n    monthFormat: 'MMM',\n    weekdayFormat: 'eeeeee'\n  }\n}\n\nexport default ruRu\n"
  },
  {
    "path": "src/locales/common/skSK.ts",
    "content": "import type { NLocale } from './enUS'\n\nconst skSK: NLocale = {\n  name: 'sk-SK',\n  global: {\n    undo: 'Späť',\n    redo: 'Obnoviť',\n    confirm: 'Potvrdiť',\n    clear: 'Vyčistiť'\n  },\n  Popconfirm: {\n    positiveText: 'Potvrdiť',\n    negativeText: 'Zrušiť'\n  },\n  Cascader: {\n    placeholder: 'Prosím vyberte',\n    loading: 'Načítavanie',\n    loadingRequiredMessage: (label: string): string =>\n      `Prosím načítajte všetkých ${label} potomkov pred kontrolou.`\n  },\n  Time: {\n    dateFormat: 'd-M-yyyy',\n    dateTimeFormat: 'd-M-yyyy HH:mm:ss'\n  },\n  DatePicker: {\n    yearFormat: 'yyyy',\n    monthFormat: 'MMM',\n    dayFormat: 'EEEE',\n    yearTypeFormat: 'yyyy',\n    monthTypeFormat: 'MMM-yyyy',\n    dateFormat: 'd-M-yyyy',\n    dateTimeFormat: 'd-M-yyyy HH:mm:ss',\n    quarterFormat: 'qqq-yyyy',\n    weekFormat: 'YYYY-w',\n    clear: 'Vyčistiť',\n    now: 'Teraz',\n    confirm: 'Potvrdiť',\n    selectTime: 'Vybrať čas',\n    selectDate: 'Vybrať dátum',\n    datePlaceholder: 'Vyberte čas',\n    datetimePlaceholder: 'Vyberte dátum a čas',\n    monthPlaceholder: 'Vyberte mesiac',\n    yearPlaceholder: 'Vyberte rok',\n    quarterPlaceholder: 'Vyberte štvrťrok',\n    weekPlaceholder: 'Vyberte týždeň',\n    startDatePlaceholder: 'Dátum začiatku',\n    endDatePlaceholder: 'Dátum ukončenia',\n    startDatetimePlaceholder: 'Dátum a čas začiatku',\n    endDatetimePlaceholder: 'Dátum a čas ukončenia ',\n    startMonthPlaceholder: 'Začiatok mesiaca',\n    endMonthPlaceholder: 'Koniec mesiaca',\n    monthBeforeYear: true,\n    firstDayOfWeek: 6 as 0 | 1 | 2 | 3 | 4 | 5 | 6,\n    today: 'Dnes'\n  },\n  DataTable: {\n    checkTableAll: 'Vybrať všetko v tabuľke',\n    uncheckTableAll: 'Zrušiť výber všetkého v tabuľke ',\n    confirm: 'Potvrdiť',\n    clear: 'Vyčistiť'\n  },\n  LegacyTransfer: {\n    sourceTitle: 'Zdroj',\n    targetTitle: 'Cieľ'\n  },\n  Transfer: {\n    selectAll: 'Vybrať všetko',\n    unselectAll: 'odznačiť všetko',\n    clearAll: 'Vyčistiť',\n    total: (num: number): string => `Celkom ${num} položiek`,\n    selected: (num: number): string => `Vybratých ${num} položiek`\n  },\n  Empty: {\n    description: 'Žiadne dáta'\n  },\n  Select: {\n    placeholder: 'Prosím vyberte'\n  },\n  TimePicker: {\n    placeholder: 'Vybrať čas',\n    positiveText: 'OK',\n    negativeText: 'Zrušiť',\n    now: 'Teraz',\n    clear: 'Vyčistiť'\n  },\n  Pagination: {\n    goto: 'Ísť na',\n    selectionSuffix: 'Strana'\n  },\n  DynamicTags: {\n    add: 'Pridať'\n  },\n  Log: {\n    loading: 'Načítavanie'\n  },\n  Input: {\n    placeholder: 'Zadajte'\n  },\n  InputNumber: {\n    placeholder: 'Zadajte'\n  },\n  DynamicInput: {\n    create: 'Vytvoriť'\n  },\n  ThemeEditor: {\n    title: 'Editor tém',\n    clearAllVars: 'Vymazať všetky premenné',\n    clearSearch: 'Vymazať vyhľadávanie',\n    filterCompName: 'Filtrovať názov komponentu',\n    filterVarName: 'Filtrovať názov premennej',\n    import: 'Importovať',\n    export: 'Exportovať',\n    restore: 'Obnoviť pôvodné nastavenia'\n  },\n  Image: {\n    tipPrevious: 'Predchádzajúci obrázok (←)',\n    tipNext: 'Ďalší obrázok (→)',\n    tipCounterclockwise: 'Proti smeru hodinových ručičiek',\n    tipClockwise: 'V smere hodinových ručičiek',\n    tipZoomOut: 'Oddialiť',\n    tipZoomIn: 'Priblížiť',\n    tipDownload: 'Sťahovať',\n    tipClose: 'Zavrieť (Esc)',\n    tipOriginalSize: 'Priblížiť na pôvodnú veľkosť'\n  },\n  Heatmap: {\n    less: 'menej',\n    more: 'viac',\n    monthFormat: 'MMM',\n    weekdayFormat: 'eeeeee'\n  }\n}\n\nexport default skSK\n"
  },
  {
    "path": "src/locales/common/svSE.ts",
    "content": "import type { NLocale } from './enUS'\n\nconst svSE: NLocale = {\n  name: 'sv-SE',\n  global: {\n    undo: 'Ångra',\n    redo: 'Gör om',\n    confirm: 'Bekräfta',\n    clear: 'Rensa'\n  },\n  Popconfirm: {\n    positiveText: 'Bekräfta',\n    negativeText: 'Avbryt'\n  },\n  Cascader: {\n    placeholder: 'Vänligen välj',\n    loading: 'Laddar',\n    loadingRequiredMessage: (label: string): string =>\n      `Vänligen ladda alla underpunkter till ${label} innan du väljer punkten.`\n  },\n  Time: {\n    dateFormat: 'yyyy-MM-dd',\n    dateTimeFormat: 'yyyy-MM-dd HH:mm:ss'\n  },\n  DatePicker: {\n    yearFormat: 'yyyy',\n    monthFormat: 'MMM',\n    dayFormat: 'eeeeee',\n    yearTypeFormat: 'yyyy',\n    monthTypeFormat: 'yyyy-MM',\n    dateFormat: 'yyyy-MM-dd',\n    dateTimeFormat: 'yyyy-MM-dd HH:mm:ss',\n    quarterFormat: 'yyyy-qqq',\n    weekFormat: 'YYYY-w',\n    clear: 'Rensa',\n    now: 'Nu',\n    confirm: 'Bekräfta',\n    selectTime: 'Välj tid',\n    selectDate: 'Välj datum',\n    datePlaceholder: 'Välj datum',\n    datetimePlaceholder: 'Välj datum och tid',\n    monthPlaceholder: 'Välj månad',\n    yearPlaceholder: 'Välj år',\n    quarterPlaceholder: 'Välj kvartal',\n    weekPlaceholder: 'Select Week',\n    startDatePlaceholder: 'Startdatum',\n    endDatePlaceholder: 'Slutdatum',\n    startDatetimePlaceholder: 'Startdatum och -tid',\n    endDatetimePlaceholder: 'Slutdatum och -tid',\n    startMonthPlaceholder: 'Startmånad',\n    endMonthPlaceholder: 'Slutmånad',\n    monthBeforeYear: true,\n    firstDayOfWeek: 0 as 0 | 1 | 2 | 3 | 4 | 5 | 6,\n    today: 'I dag'\n  },\n  DataTable: {\n    checkTableAll: 'Välj allt',\n    uncheckTableAll: 'Välj inget',\n    confirm: 'Bekräfta',\n    clear: 'Rensa'\n  },\n  LegacyTransfer: {\n    sourceTitle: 'Källa',\n    targetTitle: 'Mål'\n  },\n  Transfer: {\n    selectAll: 'Välj allt',\n    unselectAll: 'Välj inget',\n    clearAll: 'Rensa',\n    total: (num: number): string => `Totalt ${num} rader`,\n    selected: (num: number): string => `${num} rader valda`\n  },\n  Empty: {\n    description: 'Ingen data'\n  },\n  Select: {\n    placeholder: 'Vänligen välj'\n  },\n  TimePicker: {\n    placeholder: 'Välj tid',\n    positiveText: 'OK',\n    negativeText: 'Avbryt',\n    now: 'Nu',\n    clear: 'Rensa'\n  },\n  Pagination: {\n    goto: 'Gå till',\n    selectionSuffix: 'sida'\n  },\n  DynamicTags: {\n    add: 'Lägg till'\n  },\n  Log: {\n    loading: 'Laddar'\n  },\n  Input: {\n    placeholder: 'Vänligen fyll i'\n  },\n  InputNumber: {\n    placeholder: 'Vänligen fyll i'\n  },\n  DynamicInput: {\n    create: 'Skapa'\n  },\n  ThemeEditor: {\n    title: 'Temaverktyg',\n    clearAllVars: 'Nollställ alla variabler',\n    clearSearch: 'Rensa sökning',\n    filterCompName: 'Filtrera efter komponentnamn',\n    filterVarName: 'Filtrera efter variabelnamn',\n    import: 'Importera',\n    export: 'Exportera',\n    restore: 'Nollställ till ursprungsval'\n  },\n  Image: {\n    tipPrevious: 'Förgående bild (←)',\n    tipNext: 'Nästa bild (→)',\n    tipCounterclockwise: 'Moturs',\n    tipClockwise: 'Medurs',\n    tipZoomOut: 'Zooma ut',\n    tipZoomIn: 'Zooma in',\n    tipDownload: 'Ladda ned',\n    tipClose: 'Stäng (Esc)',\n    tipOriginalSize: 'Zooma till ursprunglig storlek'\n  },\n  Heatmap: {\n    less: 'mindre',\n    more: 'mer',\n    monthFormat: 'MMM',\n    weekdayFormat: 'eeeeee'\n  }\n}\n\nexport default svSE\n"
  },
  {
    "path": "src/locales/common/thTH.ts",
    "content": "import type { NLocale } from './enUS'\n\nconst thTH: NLocale = {\n  name: 'thTH',\n  global: {\n    undo: 'เลิกทำ',\n    redo: 'ทำซ้ำ',\n    confirm: 'ยืนยัน',\n    clear: 'ล้าง'\n  },\n  Popconfirm: {\n    positiveText: 'ยืนยัน',\n    negativeText: 'ยกเลิก'\n  },\n  Cascader: {\n    placeholder: 'กรุณาเลือก',\n    loading: 'กำลังโหลด',\n    loadingRequiredMessage: (label: string): string =>\n      `Please load all ${label}'s descendants before checking it.`\n  },\n  Time: {\n    dateFormat: 'dd-MMMM-yyyy',\n    dateTimeFormat: 'dd-MMMM-yyyy HH:mm:ss'\n  },\n  DatePicker: {\n    yearFormat: 'yyyy',\n    monthFormat: 'MMM',\n    dayFormat: 'eeeeee',\n    yearTypeFormat: 'yyyy',\n    monthTypeFormat: 'yyyy-MM',\n    dateFormat: 'dd/MMMM/yyyy',\n    dateTimeFormat: 'dd/MMMM/yyyy HH:mm:ss',\n    quarterFormat: 'yyyy-qqq',\n    weekFormat: 'YYYY-w',\n    clear: 'ล้าง',\n    now: 'วันนี้',\n    confirm: 'ยืนยัน',\n    selectTime: 'เวลา',\n    selectDate: 'วันที่',\n    datePlaceholder: 'วันที่',\n    datetimePlaceholder: 'เวลา-วันที่',\n    monthPlaceholder: 'เดือน',\n    yearPlaceholder: 'ปี',\n    quarterPlaceholder: 'ไตรมาส',\n    weekPlaceholder: 'Select Week',\n    startDatePlaceholder: 'วันที่เริ่มต้น',\n    endDatePlaceholder: 'วันที่สิ้นสุด',\n    startDatetimePlaceholder: 'วันที่เริ่มต้นและสิ้นสุด',\n    endDatetimePlaceholder: 'วันที่สิ้นสุดและเวลา',\n    // FIXME: translation needed\n    startMonthPlaceholder: 'Start Month',\n    endMonthPlaceholder: 'End Month',\n    monthBeforeYear: true,\n    firstDayOfWeek: 6 as 0 | 1 | 2 | 3 | 4 | 5 | 6,\n    today: 'วันนี้'\n  },\n  DataTable: {\n    checkTableAll: 'เลือกทั้งหมด',\n    uncheckTableAll: 'ไม่เลือกทั้งหมด',\n    confirm: 'ยืนยัน',\n    clear: 'ล้างข้อมูล'\n  },\n  LegacyTransfer: {\n    sourceTitle: 'Source',\n    targetTitle: 'Target'\n  },\n  // TODO: translation\n  Transfer: {\n    selectAll: 'Select all',\n    unselectAll: 'Unselect all',\n    clearAll: 'Clear',\n    total: (num: number): string => `Total ${num} items`,\n    selected: (num: number): string => `${num} items selected`\n  },\n  Empty: {\n    description: 'ไม่มีข้อมูล'\n  },\n  Select: {\n    placeholder: 'กรุณาเลือก'\n  },\n  TimePicker: {\n    placeholder: 'เวลา',\n    positiveText: 'ตกลง',\n    negativeText: 'ยกเลิก',\n    now: 'วันนี้',\n    clear: 'ล้าง'\n  },\n  Pagination: {\n    goto: 'ไปยัง',\n    selectionSuffix: 'หน้า'\n  },\n  DynamicTags: {\n    add: 'เพิ่ม'\n  },\n  Log: {\n    loading: 'กำลังโหลด'\n  },\n  Input: {\n    placeholder: 'กรุณากรอก'\n  },\n  InputNumber: {\n    placeholder: 'กรุณากรอก'\n  },\n  DynamicInput: {\n    create: 'สร้าง'\n  },\n  ThemeEditor: {\n    title: 'แก้ไขธีม',\n    clearAllVars: 'ล้างข้อมูลตัวแปร',\n    clearSearch: 'ล้างข้อมูลค้นหา',\n    filterCompName: 'กรองโดยชื่อ Component',\n    filterVarName: 'กรองโดยชื่อตัวแปร',\n    import: 'นำเข้า',\n    export: 'ส่งออก',\n    restore: 'รีเซ็ต'\n  },\n  // TODO: translation\n  Image: {\n    tipPrevious: 'ก่อนหน้า (←)',\n    tipNext: 'ถัดไป (→)',\n    tipCounterclockwise: 'หมุน (↺)',\n    tipClockwise: 'หมุน (↻)',\n    tipZoomOut: 'ซูมออก',\n    tipZoomIn: 'ซูมเข้า',\n    tipDownload: 'ดาวน์โหลด',\n    tipClose: 'ปิด (Esc)',\n    // TODO: translation\n    tipOriginalSize: 'Zoom to original size'\n  },\n  Heatmap: {\n    less: 'น้อย',\n    more: 'มาก',\n    monthFormat: 'MMM',\n    weekdayFormat: 'eeeeee'\n  }\n}\n\nexport default thTH\n"
  },
  {
    "path": "src/locales/common/trTR.ts",
    "content": "import type { NLocale } from './enUS'\n\nconst trTR: NLocale = {\n  name: 'tr-TR',\n  global: {\n    undo: 'Vazgeç',\n    redo: 'Tekrar Dene',\n    confirm: 'Kabul Et',\n    clear: 'Temizle'\n  },\n  Popconfirm: {\n    positiveText: 'Kabul Et',\n    negativeText: 'İptal'\n  },\n  Cascader: {\n    placeholder: 'Lütfen Seçin',\n    loading: 'Yükleniyor',\n    loadingRequiredMessage: (label: string): string =>\n      `Lütfen kontrol etmeden önce tüm ${label}ları yükleyin.`\n  },\n  Time: {\n    dateFormat: 'yyyy-MM-dd',\n    dateTimeFormat: 'yyyy-MM-dd HH:mm:ss'\n  },\n  DatePicker: {\n    yearFormat: 'yyyy',\n    monthFormat: 'MMM',\n    dayFormat: 'eeeeee',\n    yearTypeFormat: 'yyyy',\n    monthTypeFormat: 'yyyy-MM',\n    dateFormat: 'yyyy-MM-dd',\n    dateTimeFormat: 'yyyy-MM-dd HH:mm:ss',\n    quarterFormat: 'yyyy-qqq',\n    weekFormat: 'YYYY-w',\n    clear: 'Temizle',\n    now: 'Şimdi',\n    confirm: 'Onayla',\n    selectTime: 'Saat Seçin',\n    selectDate: 'Tarih Seçin',\n    datePlaceholder: 'Tarih Seç',\n    datetimePlaceholder: 'Tarih ve Saat Seçin',\n    monthPlaceholder: 'Ay Seçin',\n    yearPlaceholder: 'Yıl Seçin',\n    quarterPlaceholder: 'Mevsim Seçin',\n    weekPlaceholder: 'Select Week',\n    startDatePlaceholder: 'Başlangıç Tarihi',\n    endDatePlaceholder: 'Bitiş Tarihi',\n    startDatetimePlaceholder: 'Başlangıç Tarih ve Saati',\n    endDatetimePlaceholder: 'Bitiş Tarihi ve Saati',\n    startMonthPlaceholder: 'Başlangıç Ayı',\n    endMonthPlaceholder: 'Bitiş Ayı',\n    monthBeforeYear: true,\n    firstDayOfWeek: 6 as 0 | 1 | 2 | 3 | 4 | 5 | 6,\n    today: 'Bugün'\n  },\n  DataTable: {\n    checkTableAll: 'Tüm Tabloyu Seç',\n    uncheckTableAll: 'Tablodaki tüm seçimleri kaldır',\n    confirm: 'Onayla',\n    clear: 'Temizle'\n  },\n  LegacyTransfer: {\n    sourceTitle: 'Kaynak',\n    targetTitle: 'Hedef'\n  },\n  Transfer: {\n    selectAll: 'Tümünü Seç',\n    unselectAll: 'Tüm Seçimi Kaldır',\n    clearAll: 'Temizle',\n    total: (num: number): string => `Toplam ${num} öğe`,\n    selected: (num: number): string => `${num} öğe Seçili`\n  },\n  Empty: {\n    description: 'Veri Yok'\n  },\n  Select: {\n    placeholder: 'Lütfen seçin'\n  },\n  TimePicker: {\n    placeholder: 'Saat Seç',\n    positiveText: 'Tamam',\n    negativeText: 'İptal',\n    now: 'Şimdi',\n    clear: 'Temizle'\n  },\n  Pagination: {\n    goto: 'git',\n    selectionSuffix: 'sayfa'\n  },\n  DynamicTags: {\n    add: 'Ekle'\n  },\n  Log: {\n    loading: 'Yükleniyor'\n  },\n  Input: {\n    placeholder: 'Lütfen Girin'\n  },\n  InputNumber: {\n    placeholder: 'Lütfen Girin'\n  },\n  DynamicInput: {\n    create: 'Oluştur'\n  },\n  ThemeEditor: {\n    title: 'Tema Editörü',\n    clearAllVars: 'Tüm Değişkenleri Temizle',\n    clearSearch: 'Aramayı Temizle',\n    filterCompName: 'Bileşen Adını Filtrele',\n    filterVarName: 'Değişken Adını Filtrele',\n    import: 'Ekle',\n    export: 'Çıkar',\n    restore: 'Varsayılana sıfırla'\n  },\n  Image: {\n    tipPrevious: 'Önceki resim (←)',\n    tipNext: 'Sonraki resim (→)',\n    tipCounterclockwise: 'saat yönünün tersine',\n    tipClockwise: 'saat yönününe',\n    tipZoomOut: 'Uzaklaştır',\n    tipZoomIn: 'Yakınlaştır',\n    tipDownload: 'indir',\n    tipClose: 'Kapat (Esc)',\n    // TODO: translation\n    tipOriginalSize: 'Orijinal boyuta yakınlaştır'\n  },\n  Heatmap: {\n    less: 'az',\n    more: 'çok',\n    monthFormat: 'MMM',\n    weekdayFormat: 'eeeeee'\n  }\n}\n\nexport default trTR\n"
  },
  {
    "path": "src/locales/common/ugCN.ts",
    "content": "import type { NLocale } from './enUS'\n\nconst ugCN: NLocale = {\n  name: 'ug-CN',\n  global: {\n    undo: 'قالدۇرۇش',\n    redo: 'قايتا',\n    confirm: 'جەزملەش',\n    clear: 'تازلاش'\n  },\n  Popconfirm: {\n    positiveText: 'جەزملەش',\n    negativeText: 'بىكار قىلىش'\n  },\n  Cascader: {\n    placeholder: 'تاللاڭ',\n    loading: 'يۈكلەۋاتىدۇ',\n    loadingRequiredMessage: (label: string): string =>\n      `جەمئى ${label} تۈگۈننى يۈكلەپ بولغاندىن كېيىن تاللىغىلى بولىدۇ`\n  },\n  Time: {\n    dateFormat: 'yyyy-MM-dd',\n    dateTimeFormat: 'yyyy-MM-dd HH:mm:ss'\n  },\n  DatePicker: {\n    yearFormat: 'yyyy-يىل',\n    monthFormat: 'MMM',\n    dayFormat: 'eeeeee',\n    yearTypeFormat: 'yyyy',\n    monthTypeFormat: 'yyyy-MM',\n    dateFormat: 'yyyy-MM-dd',\n    dateTimeFormat: 'yyyy-MM-dd HH:mm:ss',\n    quarterFormat: 'yyyy-qqq',\n    weekFormat: 'YYYY-wھەپتە',\n    clear: 'تازلاش',\n    now: 'مۇشۇ ۋاقىت',\n    confirm: 'جەزملەش',\n    selectTime: 'ۋاقىت تاللاڭ',\n    selectDate: 'چىسلا تاللاڭ',\n    datePlaceholder: 'چىسلا تاللاڭ',\n    datetimePlaceholder: 'چىسلا ۋاقىت تاللاڭ',\n    monthPlaceholder: 'ئاي تاللاڭ',\n    yearPlaceholder: 'يىل تاللاڭ',\n    quarterPlaceholder: 'پەسىل تاللاڭ',\n    weekPlaceholder: 'ھەپتە تاللاڭ',\n    startDatePlaceholder: 'باشلىنىش ۋاقتى',\n    endDatePlaceholder: 'ئاخىرلىشىش ۋاقتى',\n    startDatetimePlaceholder: 'باشلىندىغان چىسلا ۋاقىت',\n    endDatetimePlaceholder: 'ئاخىرلىشىدىغان چىسلا ۋاقىت',\n    startMonthPlaceholder: 'باشلىندىغان ئاي',\n    endMonthPlaceholder: 'ئاخىرلىشىدىغان ئاي',\n    monthBeforeYear: false,\n    firstDayOfWeek: 0,\n    today: 'بۈگۈن'\n  },\n  DataTable: {\n    checkTableAll: 'ھەممە ئۇچۇرنى تاللاش',\n    uncheckTableAll: 'تاللاشنى بىكار قىلىش',\n    confirm: 'جەزملەش',\n    clear: 'تازلاش'\n  },\n  LegacyTransfer: {\n    sourceTitle: 'ئەسلى تۈر',\n    targetTitle: 'نىشان تۈر'\n  },\n  Transfer: {\n    selectAll: 'ھەممىنى تاللاش',\n    clearAll: 'تازلاش',\n    unselectAll: 'ھەممىنى بىكار قىلىش',\n    total: (num: number): string => `جەمئى ${num} تۈر`,\n    selected: (num: number): string => `${num} تۈر تاللاندى`\n  },\n  Empty: {\n    description: 'ئۇچۇر يوق'\n  },\n  Select: {\n    placeholder: 'تاللاڭ'\n  },\n  TimePicker: {\n    placeholder: 'ۋاقىت تاللاڭ',\n    positiveText: 'جەزملەش',\n    negativeText: 'بىكار قىلىش',\n    now: 'مۇشۇ ۋاقىت',\n    clear: 'تازلاش'\n  },\n  Pagination: {\n    goto: 'ئاتلاش',\n    selectionSuffix: 'بەت'\n  },\n  DynamicTags: {\n    add: 'قوشۇش'\n  },\n  Log: {\n    loading: 'يۈكلەۋاتىدۇ'\n  },\n  Input: {\n    placeholder: 'كىرگۈزۈڭ'\n  },\n  InputNumber: {\n    placeholder: 'كىرگۈزۈڭ'\n  },\n  DynamicInput: {\n    create: 'قوشۇش'\n  },\n  ThemeEditor: {\n    title: 'ئۇسلوب تەھرىرلىگۈچ',\n    clearAllVars: 'ھەممە پارامىتىرنى تازلاش',\n    clearSearch: 'ئىزدەشنى تازلاش',\n    filterCompName: 'ۋىجىت ئىسمىنى فىلتىرلاش',\n    filterVarName: 'پارامىتېرنى فىلتىرلاش',\n    import: 'ئەكىرىش',\n    export: 'چىقىرىش',\n    restore: 'ئەسلىگە قايتۇرۇش'\n  },\n  Image: {\n    tipPrevious: '（←）ئالدىنقىسى',\n    tipNext: 'كېيىنكىسى（→）',\n    tipCounterclockwise: 'سولغا چۆرۈش',\n    tipClockwise: 'ئوڭغا چۆرۈش',\n    tipZoomOut: 'كىچىكلىتىش',\n    tipZoomIn: 'چوڭايتىش',\n    tipDownload: 'چۈشۈرۈش',\n    tipClose: 'تاقاش（Esc）',\n    tipOriginalSize: 'ئەسلىگە قايتۇرۇش'\n  },\n  Heatmap: {\n    less: 'less',\n    more: 'more',\n    monthFormat: 'MMM',\n    weekdayFormat: 'eeeeee'\n  }\n}\n\nexport default ugCN\n"
  },
  {
    "path": "src/locales/common/ukUA.ts",
    "content": "import type { NLocale } from './enUS'\n\nconst ukUA: NLocale = {\n  name: 'uk-UA',\n  global: {\n    undo: 'Відмінити',\n    redo: 'Повторити',\n    confirm: 'Підтвердити',\n    clear: 'Стерти'\n  },\n  Popconfirm: {\n    positiveText: 'Підтвердити',\n    negativeText: 'Скасувати'\n  },\n  Cascader: {\n    placeholder: 'Обрати',\n    loading: 'Завантаження',\n    loadingRequiredMessage: (label: string): string =>\n      `Завантажте всі дочірні вузли ${label} перед перевіркою`\n  },\n  Time: {\n    dateFormat: 'yyyy-MM-dd',\n    dateTimeFormat: 'yyyy-MM-dd HH:mm:ss'\n  },\n  DatePicker: {\n    yearFormat: 'yyyy',\n    monthFormat: 'MMM',\n    dayFormat: 'eeeeee',\n    yearTypeFormat: 'yyyy',\n    monthTypeFormat: 'yyyy-MM',\n    dateFormat: 'yyyy-MM-dd',\n    dateTimeFormat: 'yyyy-MM-dd HH:mm:ss',\n    quarterFormat: 'yyyy-qqq',\n    weekFormat: 'YYYY-w',\n    clear: 'Стерти',\n    now: 'Зараз',\n    confirm: 'Підтвердити',\n    selectTime: 'Обрати час',\n    selectDate: 'Обрати дату',\n    datePlaceholder: 'Обрати дату',\n    datetimePlaceholder: 'Обрати дату і час',\n    monthPlaceholder: 'Оберіть місяць',\n    yearPlaceholder: 'Оберіть рік',\n    quarterPlaceholder: 'Оберіть квартал',\n    weekPlaceholder: 'Select Week',\n    startDatePlaceholder: 'Дата початку',\n    endDatePlaceholder: 'Дата завершення',\n    startDatetimePlaceholder: 'Дата і час початку',\n    endDatetimePlaceholder: 'Дата і час завершення',\n    startMonthPlaceholder: 'Перший місяць',\n    endMonthPlaceholder: 'Останній місяць',\n    monthBeforeYear: true,\n    firstDayOfWeek: 0 as 0 | 1 | 2 | 3 | 4 | 5 | 6,\n    today: 'Сьогодні'\n  },\n  DataTable: {\n    checkTableAll: 'Обрати все в таблиці',\n    uncheckTableAll: 'Скасувати вибір усього в таблиці',\n    confirm: 'Підтвердити',\n    clear: 'Стерти'\n  },\n  LegacyTransfer: {\n    sourceTitle: 'Джерело',\n    targetTitle: 'Ціль'\n  },\n  // TODO: translation\n  Transfer: {\n    selectAll: 'Select all',\n    unselectAll: 'Unselect all',\n    clearAll: 'Clear',\n    total: (num: number): string => `Total ${num} items`,\n    selected: (num: number): string => `${num} items selected`\n  },\n  Empty: {\n    description: 'Немає даних'\n  },\n  Select: {\n    placeholder: 'Обрати'\n  },\n  TimePicker: {\n    placeholder: 'Обрати час',\n    positiveText: 'OK',\n    negativeText: 'Скасувати',\n    now: 'Зараз',\n    clear: 'Стерти'\n  },\n  Pagination: {\n    goto: 'Перейти',\n    selectionSuffix: 'сторінка'\n  },\n  DynamicTags: {\n    add: 'Додати'\n  },\n  Log: {\n    loading: 'Завантаження'\n  },\n  Input: {\n    placeholder: 'Ввести'\n  },\n  InputNumber: {\n    placeholder: 'Ввести'\n  },\n  DynamicInput: {\n    create: 'Створити'\n  },\n  ThemeEditor: {\n    title: 'Редактор теми',\n    clearAllVars: 'Стерти все',\n    clearSearch: 'Очистити пошук',\n    filterCompName: 'Фільтрувати за іменем компонента',\n    filterVarName: 'Фільтрувати імена змінних',\n    import: 'Імпорт',\n    export: 'Експорт',\n    restore: 'Скинути'\n  },\n  Image: {\n    tipPrevious: 'Попереднє зображення (←)',\n    tipNext: 'Наступне зображення (→)',\n    tipCounterclockwise: 'Проти годинникової стрілки',\n    tipClockwise: 'За годинниковою стрілкою',\n    tipZoomOut: 'Віддалити',\n    tipZoomIn: 'Наблизити',\n    tipDownload: 'звантажити',\n    tipClose: 'Закрити (Esc)',\n    tipOriginalSize: 'Масштабувати до оригінального розміру'\n  },\n  Heatmap: {\n    less: 'менше',\n    more: 'більше',\n    monthFormat: 'MMM',\n    weekdayFormat: 'eeeeee'\n  }\n}\n\nexport default ukUA\n"
  },
  {
    "path": "src/locales/common/uzUZ.ts",
    "content": "import type { NLocale } from './enUS'\n\nconst uzUZ: NLocale = {\n  name: 'uz-UZ',\n  global: {\n    undo: 'Bekor qilish',\n    redo: 'Qaytadan amalga oshirish',\n    confirm: 'Tasdiqlash',\n    clear: 'Tozalash'\n  },\n  Popconfirm: {\n    positiveText: 'Tasdiqlash',\n    negativeText: 'Bekor qilish'\n  },\n  Cascader: {\n    placeholder: 'Tanlash',\n    loading: 'Yuklanmoqda',\n    loadingRequiredMessage: (label: string): string =>\n      `${label} ning barcha farzand elementlarini yuklang, keyin ularga to'liq ruxsat bering`\n  },\n  Time: {\n    dateFormat: 'yyyy-MM-dd',\n    dateTimeFormat: 'yyyy-MM-dd HH:mm:ss'\n  },\n  DatePicker: {\n    yearFormat: 'yyyy',\n    monthFormat: 'MMM',\n    dayFormat: 'eeeeee',\n    yearTypeFormat: 'yyyy',\n    monthTypeFormat: 'yyyy-MM',\n    dateFormat: 'yyyy-MM-dd',\n    dateTimeFormat: 'yyyy-MM-dd HH:mm:ss',\n    quarterFormat: 'yyyy-qqq',\n    weekFormat: 'YYYY-w',\n    clear: 'Tozalash',\n    now: 'Hozir',\n    confirm: 'Tasdiqlash',\n    selectTime: 'Vaqtni tanlash',\n    selectDate: 'Sana tanlash',\n    datePlaceholder: 'Sana tanlash',\n    datetimePlaceholder: 'Sana va vaqtni tanlash',\n    monthPlaceholder: 'Oy tanlash',\n    yearPlaceholder: 'Yil tanlash',\n    quarterPlaceholder: 'Chet tanlash',\n    weekPlaceholder: 'Hafta tanlash',\n    startDatePlaceholder: 'Boshlang`ich sana',\n    endDatePlaceholder: 'Tugash sanasi',\n    startDatetimePlaceholder: 'Boshlang`ich sana va vaqti',\n    endDatetimePlaceholder: 'Tugash sanasi va vaqti',\n    startMonthPlaceholder: 'Boshlang`ich oy',\n    endMonthPlaceholder: 'Oxirgi oy',\n    monthBeforeYear: true,\n    firstDayOfWeek: 1 as 0 | 1 | 2 | 3 | 4 | 5 | 6, // in Uzbekistan monday\n    today: 'Bugun'\n  },\n  DataTable: {\n    checkTableAll: 'Jadvaldagi barchasini tanlash',\n    uncheckTableAll: 'Jadvaldagi barchasini bekor qilish',\n    confirm: 'Tasdiqlash',\n    clear: 'Tozalash'\n  },\n  LegacyTransfer: {\n    sourceTitle: 'Manba',\n    targetTitle: 'Mansub'\n  },\n  Transfer: {\n    selectAll: 'Barchasini tanlash',\n    unselectAll: 'Barchasini bekor qilish',\n    clearAll: 'Tozalash',\n    total: (num: number): string => `Jami ${num} ta`,\n    selected: (num: number): string => `Tanlandi ${num} ta`\n  },\n  Empty: {\n    description: 'Ma`lumotlar yo`q'\n  },\n  Select: {\n    placeholder: 'Tanlash'\n  },\n  TimePicker: {\n    placeholder: 'Vaqtni tanlash',\n    positiveText: 'OK',\n    negativeText: 'Bekor qilish',\n    now: 'Hozir',\n    clear: 'Tozalash'\n  },\n  Pagination: {\n    goto: 'O`tish',\n    selectionSuffix: 'sahifa'\n  },\n  DynamicTags: {\n    add: 'Qo`shish'\n  },\n  Log: {\n    loading: 'Yuklanmoqda'\n  },\n  Input: {\n    placeholder: 'Kiriting'\n  },\n  InputNumber: {\n    placeholder: 'Kiriting'\n  },\n  DynamicInput: {\n    create: 'Yaratish'\n  },\n  ThemeEditor: {\n    title: 'Mavzu muharriri',\n    clearAllVars: 'Barchasini tozalash',\n    clearSearch: 'Qidiruvni tozalash',\n    filterCompName: 'Komponent nomi bo`yicha filtr',\n    filterVarName: 'O`zgaruvchi nomlarini filtrlash',\n    import: 'Import qilish',\n    export: 'Eksport qilish',\n    restore: 'Qayta tiklash'\n  },\n  Image: {\n    tipPrevious: 'Oldingi rasm (←)',\n    tipNext: 'Keyingi rasm (→)',\n    tipCounterclockwise: 'Soat yonida',\n    tipClockwise: 'Soat bo`yicha',\n    tipZoomOut: 'Yaqinlash',\n    tipZoomIn: 'Uzoq qilish',\n    tipDownload: 'Yuklab olish',\n    tipClose: 'Yopish (Esc)',\n    tipOriginalSize: 'Asl o`lchamga qaytish'\n  },\n  Heatmap: {\n    less: 'less',\n    more: 'more',\n    monthFormat: 'MMM',\n    weekdayFormat: 'eeeeee'\n  }\n}\n\nexport default uzUZ\n"
  },
  {
    "path": "src/locales/common/viVN.ts",
    "content": "import type { NLocale } from './enUS'\n\nconst viVN: NLocale = {\n  name: 'vi-VN',\n  global: {\n    undo: 'Hoàn tác',\n    redo: 'Làm lại',\n    confirm: 'Xác nhận',\n    clear: 'xóa'\n  },\n  Popconfirm: {\n    positiveText: 'Xác nhận',\n    negativeText: 'Hủy'\n  },\n  Cascader: {\n    placeholder: 'Vui lòng chọn',\n    loading: 'Đang tải',\n    loadingRequiredMessage: (label: string): string =>\n      `Vui lòng tải tất cả thông tin con của ${label} trước.`\n  },\n  Time: {\n    dateFormat: '',\n    dateTimeFormat: 'HH:mm:ss dd-MM-yyyy'\n  },\n  DatePicker: {\n    yearFormat: 'yyyy',\n    monthFormat: 'MMM',\n    dayFormat: 'eeeeee',\n    yearTypeFormat: 'yyyy',\n    monthTypeFormat: 'MM-yyyy',\n    dateFormat: 'dd-MM-yyyy',\n    dateTimeFormat: 'HH:mm:ss dd-MM-yyyy',\n    quarterFormat: 'qqq-yyyy',\n    weekFormat: 'YYYY-w',\n    clear: 'Xóa',\n    now: 'Hôm nay',\n    confirm: 'Xác nhận',\n    selectTime: 'Chọn giờ',\n    selectDate: 'Chọn ngày',\n    datePlaceholder: 'Chọn ngày',\n    datetimePlaceholder: 'Chọn ngày giờ',\n    monthPlaceholder: 'Chọn tháng',\n    yearPlaceholder: 'Chọn năm',\n    quarterPlaceholder: 'Chọn quý',\n    weekPlaceholder: 'Select Week',\n    startDatePlaceholder: 'Ngày bắt đầu',\n    endDatePlaceholder: 'Ngày kết thúc',\n    startDatetimePlaceholder: 'Thời gian bắt đầu',\n    endDatetimePlaceholder: 'Thời gian kết thúc',\n    startMonthPlaceholder: 'Tháng bắt đầu',\n    endMonthPlaceholder: 'Tháng kết thúc',\n    monthBeforeYear: true,\n    firstDayOfWeek: 0 as 0 | 1 | 2 | 3 | 4 | 5 | 6,\n    today: 'Hôm nay'\n  },\n  DataTable: {\n    checkTableAll: 'Chọn tất cả có trong bảng',\n    uncheckTableAll: 'Bỏ chọn tất cả có trong bảng',\n    confirm: 'Xác nhận',\n    clear: 'Xóa'\n  },\n  LegacyTransfer: {\n    sourceTitle: 'Nguồn',\n    targetTitle: 'Đích'\n  },\n  Transfer: {\n    selectAll: 'Chọn tất cả',\n    unselectAll: 'Bỏ chọn tất cả',\n    clearAll: 'Xoá tất cả',\n    total: (num: number): string => `Tổng cộng ${num} mục`,\n    selected: (num: number): string => `${num} mục được chọn`\n  },\n  Empty: {\n    description: 'Không có dữ liệu'\n  },\n  Select: {\n    placeholder: 'Vui lòng chọn'\n  },\n  TimePicker: {\n    placeholder: 'Chọn thời gian',\n    positiveText: 'OK',\n    negativeText: 'Hủy',\n    now: 'Hiện tại',\n    clear: 'Xóa'\n  },\n  Pagination: {\n    goto: 'Đi đến trang',\n    selectionSuffix: 'trang'\n  },\n  DynamicTags: {\n    add: 'Thêm'\n  },\n  Log: {\n    loading: 'Đang tải'\n  },\n  Input: {\n    placeholder: 'Vui lòng nhập'\n  },\n  InputNumber: {\n    placeholder: 'Vui lòng nhập'\n  },\n  DynamicInput: {\n    create: 'Tạo'\n  },\n  ThemeEditor: {\n    title: 'Tùy chỉnh giao diện',\n    clearAllVars: 'Xóa tất cả các biến',\n    clearSearch: 'Xóa tìm kiếm',\n    filterCompName: 'Lọc tên component',\n    filterVarName: 'Lọc tên biến',\n    import: 'Nhập',\n    export: 'Xuất',\n    restore: 'Đặt lại mặc định'\n  },\n  Image: {\n    tipPrevious: 'Hình trước (←)',\n    tipNext: 'Hình tiếp (→)',\n    tipCounterclockwise: 'Counterclockwise',\n    tipClockwise: 'Chiều kim đồng hồ',\n    tipZoomOut: 'Thu nhỏ',\n    tipZoomIn: 'Phóng to',\n    tipDownload: 'Tải về',\n    tipClose: 'Đóng (Esc)',\n    tipOriginalSize: 'Xem kích thước gốc'\n  },\n  Heatmap: {\n    less: 'ít',\n    more: 'nhiều',\n    monthFormat: 'MMM',\n    weekdayFormat: 'eeeeee'\n  }\n}\n\nexport default viVN\n"
  },
  {
    "path": "src/locales/common/zhCN.ts",
    "content": "import type { NLocale } from './enUS'\n\nconst zhCN: NLocale = {\n  name: 'zh-CN',\n  global: {\n    undo: '撤销',\n    redo: '重做',\n    confirm: '确认',\n    clear: '清除'\n  },\n  Popconfirm: {\n    positiveText: '确认',\n    negativeText: '取消'\n  },\n  Cascader: {\n    placeholder: '请选择',\n    loading: '加载中',\n    loadingRequiredMessage: (label: string): string =>\n      `加载全部 ${label} 的子节点后才可选中`\n  },\n  Time: {\n    dateFormat: 'yyyy-MM-dd',\n    dateTimeFormat: 'yyyy-MM-dd HH:mm:ss'\n  },\n  DatePicker: {\n    yearFormat: 'yyyy年',\n    monthFormat: 'MMM',\n    dayFormat: 'eeeeee',\n    yearTypeFormat: 'yyyy',\n    monthTypeFormat: 'yyyy-MM',\n    dateFormat: 'yyyy-MM-dd',\n    dateTimeFormat: 'yyyy-MM-dd HH:mm:ss',\n    quarterFormat: 'yyyy-qqq',\n    weekFormat: 'YYYY-w周',\n    clear: '清除',\n    now: '此刻',\n    confirm: '确认',\n    selectTime: '选择时间',\n    selectDate: '选择日期',\n    datePlaceholder: '选择日期',\n    datetimePlaceholder: '选择日期时间',\n    monthPlaceholder: '选择月份',\n    yearPlaceholder: '选择年份',\n    quarterPlaceholder: '选择季度',\n    weekPlaceholder: '选择周',\n    startDatePlaceholder: '开始日期',\n    endDatePlaceholder: '结束日期',\n    startDatetimePlaceholder: '开始日期时间',\n    endDatetimePlaceholder: '结束日期时间',\n    startMonthPlaceholder: '开始月份',\n    endMonthPlaceholder: '结束月份',\n    monthBeforeYear: false,\n    firstDayOfWeek: 0,\n    today: '今天'\n  },\n  DataTable: {\n    checkTableAll: '选择全部表格数据',\n    uncheckTableAll: '取消选择全部表格数据',\n    confirm: '确认',\n    clear: '重置'\n  },\n  LegacyTransfer: {\n    sourceTitle: '源项',\n    targetTitle: '目标项'\n  },\n  Transfer: {\n    selectAll: '全选',\n    clearAll: '清除',\n    unselectAll: '取消全选',\n    total: (num: number): string => `共 ${num} 项`,\n    selected: (num: number): string => `已选 ${num} 项`\n  },\n  Empty: {\n    description: '无数据'\n  },\n  Select: {\n    placeholder: '请选择'\n  },\n  TimePicker: {\n    placeholder: '请选择时间',\n    positiveText: '确认',\n    negativeText: '取消',\n    now: '此刻',\n    clear: '清除'\n  },\n  Pagination: {\n    goto: '跳至',\n    selectionSuffix: '页'\n  },\n  DynamicTags: {\n    add: '添加'\n  },\n  Log: {\n    loading: '加载中'\n  },\n  Input: {\n    placeholder: '请输入'\n  },\n  InputNumber: {\n    placeholder: '请输入'\n  },\n  DynamicInput: {\n    create: '添加'\n  },\n  ThemeEditor: {\n    title: '主题编辑器',\n    clearAllVars: '清除全部变量',\n    clearSearch: '清除搜索',\n    filterCompName: '过滤组件名',\n    filterVarName: '过滤变量名',\n    import: '导入',\n    export: '导出',\n    restore: '恢复默认'\n  },\n  Image: {\n    tipPrevious: '上一张（←）',\n    tipNext: '下一张（→）',\n    tipCounterclockwise: '向左旋转',\n    tipClockwise: '向右旋转',\n    tipZoomOut: '缩小',\n    tipZoomIn: '放大',\n    tipDownload: '下载',\n    tipClose: '关闭（Esc）',\n    tipOriginalSize: '缩放到原始尺寸'\n  },\n  Heatmap: {\n    less: '少',\n    more: '多',\n    monthFormat: 'MMM',\n    weekdayFormat: 'eeeeee'\n  }\n}\n\nexport default zhCN\n"
  },
  {
    "path": "src/locales/common/zhTW.ts",
    "content": "import type { NLocale } from './enUS'\n\nconst zhTW: NLocale = {\n  name: 'zh-TW',\n  global: {\n    undo: '復原',\n    redo: '重做',\n    confirm: '確定',\n    clear: '清除'\n  },\n  Popconfirm: {\n    positiveText: '確定',\n    negativeText: '取消'\n  },\n  Cascader: {\n    placeholder: '請選擇',\n    loading: '載入中',\n    loadingRequiredMessage: (label: string): string =>\n      `載入全部 ${label} 的子節點後才可選擇`\n  },\n  Time: {\n    dateFormat: 'yyyy-MM-dd',\n    dateTimeFormat: 'yyyy-MM-dd HH:mm:ss'\n  },\n  DatePicker: {\n    yearFormat: 'yyyy 年',\n    monthFormat: 'MMM',\n    dayFormat: 'eeeeee',\n    yearTypeFormat: 'yyyy',\n    monthTypeFormat: 'yyyy-MM',\n    dateFormat: 'yyyy-MM-dd',\n    dateTimeFormat: 'yyyy-MM-dd HH:mm:ss',\n    quarterFormat: 'yyyy-qqq',\n    weekFormat: 'YYYY-w',\n    clear: '清除',\n    now: '現在',\n    confirm: '確定',\n    selectTime: '選擇時間',\n    selectDate: '選擇日期',\n    datePlaceholder: '選擇日期',\n    datetimePlaceholder: '選擇日期時間',\n    monthPlaceholder: '選擇月份',\n    yearPlaceholder: '選擇年份',\n    quarterPlaceholder: '選擇季度',\n    weekPlaceholder: 'Select Week',\n    startDatePlaceholder: '開始日期',\n    endDatePlaceholder: '結束日期',\n    startDatetimePlaceholder: '開始日期時間',\n    endDatetimePlaceholder: '結束日期時間',\n    startMonthPlaceholder: '開始月份',\n    endMonthPlaceholder: '結束月份',\n    monthBeforeYear: false,\n    firstDayOfWeek: 0,\n    today: '今天'\n  },\n  DataTable: {\n    checkTableAll: '選擇全部表格資料',\n    uncheckTableAll: '取消選擇全部表格資料',\n    confirm: '確定',\n    clear: '重設'\n  },\n  LegacyTransfer: {\n    sourceTitle: '來源',\n    targetTitle: '目標'\n  },\n  Transfer: {\n    selectAll: '全選',\n    unselectAll: '取消全選',\n    clearAll: '清除全部',\n    total: (num: number): string => `共 ${num} 項`,\n    selected: (num: number): string => `已選 ${num} 項`\n  },\n  Empty: {\n    description: '無資料'\n  },\n  Select: {\n    placeholder: '請選擇'\n  },\n  TimePicker: {\n    placeholder: '請選擇時間',\n    positiveText: '確定',\n    negativeText: '取消',\n    now: '現在',\n    clear: '清除'\n  },\n  Pagination: {\n    goto: '跳至',\n    selectionSuffix: '頁'\n  },\n  DynamicTags: {\n    add: '新增'\n  },\n  Log: {\n    loading: '載入中'\n  },\n  Input: {\n    placeholder: '請輸入'\n  },\n  InputNumber: {\n    placeholder: '請輸入'\n  },\n  DynamicInput: {\n    create: '新增'\n  },\n  ThemeEditor: {\n    title: '主題編輯器',\n    clearAllVars: '清除全部變數',\n    clearSearch: '清除搜尋',\n    filterCompName: '過濾組件名稱',\n    filterVarName: '過濾變數名稱',\n    import: '匯入',\n    export: '匯出',\n    restore: '恢復預設'\n  },\n  Image: {\n    tipPrevious: '上一張（←）',\n    tipNext: '下一張（→）',\n    tipCounterclockwise: '向左旋轉',\n    tipClockwise: '向右旋轉',\n    tipZoomOut: '縮小',\n    tipZoomIn: '放大',\n    tipDownload: '下載',\n    tipClose: '關閉（Esc）',\n    tipOriginalSize: '縮放到原始尺寸'\n  },\n  Heatmap: {\n    less: '少',\n    more: '多',\n    monthFormat: 'MMM',\n    weekdayFormat: 'eeeeee'\n  }\n}\n\nexport default zhTW\n"
  },
  {
    "path": "src/locales/date/arDZ.ts",
    "content": "import type { NDateLocale } from './enUS'\nimport { arDZ } from 'date-fns/locale'\n\nconst dateArDZ: NDateLocale = {\n  name: 'ar-DZ',\n  locale: arDZ\n}\n\nexport default dateArDZ\n"
  },
  {
    "path": "src/locales/date/azAZ.ts",
    "content": "import type { NDateLocale } from './enUS'\nimport { az } from 'date-fns/locale'\n\nconst dateAzAZ: NDateLocale = {\n  name: 'az-AZ',\n  locale: az\n}\n\nexport default dateAzAZ\n"
  },
  {
    "path": "src/locales/date/csCZ.ts",
    "content": "import type { NDateLocale } from './enUS'\nimport { cs } from 'date-fns/locale'\n\nconst dateCsCZ: NDateLocale = {\n  name: 'cs-CZ',\n  locale: cs\n}\n\nexport default dateCsCZ\n"
  },
  {
    "path": "src/locales/date/daDK.ts",
    "content": "import type { NDateLocale } from './enUS'\nimport { da } from 'date-fns/locale'\n\nconst dateDaDK: NDateLocale = {\n  name: 'da-DK',\n  locale: da\n}\n\nexport default dateDaDK\n"
  },
  {
    "path": "src/locales/date/deDE.ts",
    "content": "import type { NDateLocale } from './enUS'\nimport { de } from 'date-fns/locale'\n\nconst dateDeDE: NDateLocale = {\n  name: 'de-DE',\n  locale: de\n}\n\nexport default dateDeDE\n"
  },
  {
    "path": "src/locales/date/enGB.ts",
    "content": "import type { NDateLocale } from './enUS'\nimport { enGB } from 'date-fns/locale'\n\nconst dateEnGB: NDateLocale = {\n  name: 'en-GB',\n  locale: enGB\n}\n\nexport default dateEnGB\n"
  },
  {
    "path": "src/locales/date/enUS.ts",
    "content": "import type { Locale } from 'date-fns'\nimport { enUS } from 'date-fns/locale'\n\ninterface NDateLocale {\n  name: string\n  locale: Locale\n}\n\nconst dateEnUs: NDateLocale = {\n  name: 'en-US',\n  locale: enUS\n}\n\nexport type { NDateLocale }\nexport default dateEnUs\n"
  },
  {
    "path": "src/locales/date/eo.ts",
    "content": "import type { NDateLocale } from './enUS'\nimport { eo } from 'date-fns/locale'\n\nconst dateEo: NDateLocale = {\n  name: 'eo',\n  locale: eo\n}\n\nexport default dateEo\n"
  },
  {
    "path": "src/locales/date/esAR.ts",
    "content": "import type { NDateLocale } from './enUS'\nimport { es } from 'date-fns/locale'\n\nconst dateEsAR: NDateLocale = {\n  name: 'es-AR',\n  locale: es\n}\n\nexport default dateEsAR\n"
  },
  {
    "path": "src/locales/date/etEE.ts",
    "content": "import type { NDateLocale } from './enUS'\nimport { et } from 'date-fns/locale'\n\nconst dateEtEE: NDateLocale = {\n  name: 'et-EE',\n  locale: et\n}\n\nexport default dateEtEE\n"
  },
  {
    "path": "src/locales/date/faIR.ts",
    "content": "import type { NDateLocale } from './enUS'\nimport { faIR } from 'date-fns/locale'\n\nconst dateFaIR: NDateLocale = {\n  name: 'fa-IR',\n  locale: faIR\n}\n\nexport default dateFaIR\n"
  },
  {
    "path": "src/locales/date/frFR.ts",
    "content": "import type { NDateLocale } from './enUS'\nimport { fr } from 'date-fns/locale'\n\nconst dateFrFR: NDateLocale = {\n  name: 'fr-FR',\n  locale: fr\n}\n\nexport default dateFrFR\n"
  },
  {
    "path": "src/locales/date/idID.ts",
    "content": "import type { NDateLocale } from './enUS'\nimport { id } from 'date-fns/locale'\n\nconst dateIdID: NDateLocale = {\n  name: 'id-ID',\n  locale: id\n}\n\nexport default dateIdID\n"
  },
  {
    "path": "src/locales/date/itIT.ts",
    "content": "import type { NDateLocale } from './enUS'\nimport { it } from 'date-fns/locale'\n\nconst dateItIT: NDateLocale = {\n  name: 'it-IT',\n  locale: it\n}\n\nexport default dateItIT\n"
  },
  {
    "path": "src/locales/date/jaJP.ts",
    "content": "import type { NDateLocale } from './enUS'\nimport { ja } from 'date-fns/locale'\n\nconst dateJaJP: NDateLocale = {\n  name: 'ja-JP',\n  locale: ja\n}\n\nexport default dateJaJP\n"
  },
  {
    "path": "src/locales/date/kmKH.ts",
    "content": "import type { NDateLocale } from './enUS'\nimport { km } from 'date-fns/locale'\n\nconst dateKmKH: NDateLocale = {\n  name: 'km-KH',\n  locale: km\n}\n\nexport default dateKmKH\n"
  },
  {
    "path": "src/locales/date/koKR.ts",
    "content": "import type { NDateLocale } from './enUS'\nimport { ko } from 'date-fns/locale'\n\nconst dateKoKR: NDateLocale = {\n  name: 'ko-KR',\n  locale: ko\n}\n\nexport default dateKoKR\n"
  },
  {
    "path": "src/locales/date/nbNO.ts",
    "content": "import type { NDateLocale } from './enUS'\nimport { nb } from 'date-fns/locale'\n\nconst dateNbNO: NDateLocale = {\n  name: 'nb-NO',\n  locale: nb\n}\n\nexport default dateNbNO\n"
  },
  {
    "path": "src/locales/date/nlNL.ts",
    "content": "import type { NDateLocale } from './enUS'\nimport { nl } from 'date-fns/locale'\n\nconst dateNlNL: NDateLocale = {\n  name: 'nl-NL',\n  locale: nl\n}\n\nexport default dateNlNL\n"
  },
  {
    "path": "src/locales/date/plPL.ts",
    "content": "import type { NDateLocale } from './enUS'\nimport { pl } from 'date-fns/locale'\n\nconst datePlPL: NDateLocale = {\n  name: 'pl-PL',\n  locale: pl\n}\n\nexport default datePlPL\n"
  },
  {
    "path": "src/locales/date/ptBR.ts",
    "content": "import type { NDateLocale } from './enUS'\nimport { ptBR } from 'date-fns/locale'\n\nconst datePtBr: NDateLocale = {\n  name: 'pt-BR',\n  locale: ptBR\n}\n\nexport default datePtBr\n"
  },
  {
    "path": "src/locales/date/ruRU.ts",
    "content": "import type { NDateLocale } from './enUS'\nimport { ru } from 'date-fns/locale'\n\nconst dateRuRU: NDateLocale = {\n  name: 'ru-RU',\n  locale: ru\n}\n\nexport default dateRuRU\n"
  },
  {
    "path": "src/locales/date/skSK.ts",
    "content": "import type { NDateLocale } from './enUS'\nimport { sk } from 'date-fns/locale'\n\nconst dateSkSK: NDateLocale = {\n  name: 'sk-SK',\n  locale: sk\n}\n\nexport default dateSkSK\n"
  },
  {
    "path": "src/locales/date/svSE.ts",
    "content": "import type { NDateLocale } from './enUS'\nimport { sv } from 'date-fns/locale'\n\nconst dateSvSE: NDateLocale = {\n  name: 'sv-SE',\n  locale: sv\n}\n\nexport default dateSvSE\n"
  },
  {
    "path": "src/locales/date/thTH.ts",
    "content": "import type { NDateLocale } from './enUS'\nimport { th } from 'date-fns/locale'\n\nconst dateThTH: NDateLocale = {\n  name: 'th-TH',\n  locale: th\n}\n\nexport default dateThTH\n"
  },
  {
    "path": "src/locales/date/trTR.ts",
    "content": "import type { NDateLocale } from './enUS'\nimport { tr } from 'date-fns/locale'\n\nconst dateTrTR: NDateLocale = {\n  name: 'tr-TR',\n  locale: tr\n}\n\nexport default dateTrTR\n"
  },
  {
    "path": "src/locales/date/ugCN.ts",
    "content": "import type { NDateLocale } from './enUS'\nimport { ug } from 'date-fns/locale'\n\nconst dateUgCN: NDateLocale = {\n  name: 'ug-CN',\n  locale: ug\n}\n\nexport default dateUgCN\n"
  },
  {
    "path": "src/locales/date/ukUA.ts",
    "content": "import type { NDateLocale } from './enUS'\nimport { uk } from 'date-fns/locale'\n\nconst dateUkUA: NDateLocale = {\n  name: 'uk-UA',\n  locale: uk\n}\n\nexport default dateUkUA\n"
  },
  {
    "path": "src/locales/date/uzUZ.ts",
    "content": "import type { NDateLocale } from './enUS'\nimport { uz } from 'date-fns/locale'\n\nconst dateUzUZ: NDateLocale = {\n  name: 'uz-UZ',\n  locale: uz\n}\n\nexport default dateUzUZ\n"
  },
  {
    "path": "src/locales/date/viVN.ts",
    "content": "import type { NDateLocale } from './enUS'\nimport { vi } from 'date-fns/locale'\n\nconst dateVi: NDateLocale = {\n  name: 'vi-VN',\n  locale: vi\n}\n\nexport default dateVi\n"
  },
  {
    "path": "src/locales/date/zhCN.ts",
    "content": "import type { NDateLocale } from './enUS'\nimport { zhCN } from 'date-fns/locale'\n\nconst dateZhCN: NDateLocale = {\n  name: 'zh-CN',\n  locale: zhCN\n}\n\nexport default dateZhCN\n"
  },
  {
    "path": "src/locales/date/zhTW.ts",
    "content": "import type { NDateLocale } from './enUS'\nimport { zhTW } from 'date-fns/locale'\n\nconst datezhTW: NDateLocale = {\n  name: 'zh-TW',\n  locale: zhTW\n}\n\nexport default datezhTW\n"
  },
  {
    "path": "src/locales/index.spec.tsx",
    "content": "import type { PropType } from 'vue'\nimport type { NLocale } from './common/enUS'\nimport type { NDateLocale } from './date/enUS'\nimport { mount } from '@vue/test-utils'\nimport { defineComponent, h, onMounted, ref } from 'vue'\nimport { NConfigProvider } from '../config-provider/index'\nimport { NDatePicker } from '../date-picker/index'\nimport {\n  arDZ,\n  azAZ,\n  csCZ,\n  daDK,\n  dateArDZ,\n  dateAzAZ,\n  dateCsCZ,\n  dateDaDK,\n  dateDeDE,\n  dateEnGB,\n  dateEnUS,\n  dateEo,\n  dateEsAR,\n  dateEtEE,\n  dateFaIR,\n  dateFrFR,\n  dateIdID,\n  dateItIT,\n  dateJaJP,\n  dateKmKH,\n  dateKoKR,\n  dateNbNO,\n  dateNlNL,\n  datePlPL,\n  datePtBR,\n  dateRuRU,\n  dateSkSK,\n  dateSvSE,\n  dateThTH,\n  dateTrTR,\n  dateUgCN,\n  dateUkUA,\n  dateUzUZ,\n  dateZhCN,\n  dateZhTW,\n  deDE,\n  enGB,\n  enUS,\n  eo,\n  esAR,\n  etEE,\n  faIR,\n  frFR,\n  idID,\n  itIT,\n  jaJP,\n  kmKH,\n  koKR,\n  nbNO,\n  nlNL,\n  plPL,\n  ptBR,\n  ruRU,\n  skSK,\n  svSE,\n  thTH,\n  trTR,\n  ukUA,\n  uzUZ,\n  zhCN,\n  zhTW\n} from '../index'\nimport { NInput } from '../input/index'\nimport ugCN from './common/ugCN'\nimport { createLocale } from './utils/index'\n\nconst Wrapper = defineComponent({\n  props: {\n    dateLocale: Object as PropType<NDateLocale>,\n    locale: Object as PropType<NLocale>,\n    onMounted: Function as PropType<(date: string) => void>\n  },\n  setup() {\n    const datePickerWrapperElRef = ref<HTMLElement | null>(null)\n    onMounted(() => {\n      // const { value: datePickerWrapperEl } = datePickerWrapperElRef\n      // if (!datePickerWrapperEl) return\n      // TODO: Fix timezone caused CI Error\n      // const dateInputEls = datePickerWrapperEl?.querySelectorAll('input')\n      // props.onMounted?.(\n      //   JSON.stringify([\n      //     'check date format',\n      //     dateInputEls[0].value,\n      //     dateInputEls[1].value,\n      //     dateInputEls[2].value,\n      //     dateInputEls[3].value\n      //   ])\n      // )\n    })\n    return {\n      datePickerWrapperElRef\n    }\n  },\n  render() {\n    return (\n      <NConfigProvider {...this.$props}>\n        {{\n          default: () => (\n            <div>\n              <NInput />\n              <div ref=\"datePickerWrapperElRef\">\n                <NDatePicker type=\"date\" value={666} />\n                <NDatePicker type=\"datetime\" value={666} />\n                <NDatePicker type=\"year\" value={666} />\n                <NDatePicker type=\"month\" value={666} />\n              </div>\n            </div>\n          )\n        }}\n      </NConfigProvider>\n    )\n  }\n})\n\ndescribe('locale', () => {\n  it('works with createLocale', () => {\n    const locale1: NLocale = createLocale(\n      {\n        Select: {\n          placeholder: '???'\n        }\n      },\n      enUS\n    )\n    expect(locale1.Select.placeholder).toEqual('???')\n    locale1.Select.placeholder = enUS.Select.placeholder\n    expect(locale1).toEqual(enUS)\n    const locale2: NLocale = createLocale(enUS)\n    expect(locale2).toEqual(enUS)\n  })\n  it('works', () => {\n    expect(\n      mount(Wrapper, {\n        props: {\n          dateLocale: dateZhCN,\n          locale: zhCN,\n          onMounted: (date: string) => {\n            expect(date).toMatchSnapshot()\n          }\n        }\n      }).html()\n    ).toMatchSnapshot()\n    expect(\n      mount(Wrapper, {\n        props: {\n          dateLocale: dateZhTW,\n          locale: zhTW,\n          onMounted: (date: string) => {\n            expect(date).toMatchSnapshot()\n          }\n        }\n      }).html()\n    ).toMatchSnapshot()\n    expect(\n      mount(Wrapper, {\n        props: {\n          dateLocale: dateEnUS,\n          locale: enUS,\n          onMounted: (date: string) => {\n            expect(date).toMatchSnapshot()\n          }\n        }\n      }).html()\n    ).toMatchSnapshot()\n    expect(\n      mount(Wrapper, {\n        props: {\n          dateLocale: dateRuRU,\n          locale: ruRU,\n          onMounted: (date: string) => {\n            expect(date).toMatchSnapshot()\n          }\n        }\n      }).html()\n    ).toMatchSnapshot()\n    expect(\n      mount(Wrapper, {\n        props: {\n          dateLocale: dateUkUA,\n          locale: ukUA,\n          onMounted: (date: string) => {\n            expect(date).toMatchSnapshot()\n          }\n        }\n      }).html()\n    ).toMatchSnapshot()\n    expect(\n      mount(Wrapper, {\n        props: {\n          dateLocale: dateUzUZ,\n          locale: uzUZ,\n          onMounted: (date: string) => {\n            expect(date).toMatchSnapshot()\n          }\n        }\n      }).html()\n    ).toMatchSnapshot()\n    expect(\n      mount(Wrapper, {\n        props: {\n          dateLocale: dateJaJP,\n          locale: jaJP,\n          onMounted: (date: string) => {\n            expect(date).toMatchSnapshot()\n          }\n        }\n      }).html()\n    ).toMatchSnapshot()\n\n    expect(\n      mount(Wrapper, {\n        props: {\n          dateLocale: dateKmKH,\n          locale: kmKH,\n          onMounted: (date: string) => {\n            expect(date).toMatchSnapshot()\n          }\n        }\n      }).html()\n    ).toMatchSnapshot()\n    expect(\n      mount(Wrapper, {\n        props: {\n          dateLocale: dateKoKR,\n          locale: koKR,\n          onMounted: (date: string) => {\n            expect(date).toMatchSnapshot()\n          }\n        }\n      }).html()\n    ).toMatchSnapshot()\n    expect(\n      mount(Wrapper, {\n        props: {\n          dateLocale: dateIdID,\n          locale: idID,\n          onMounted: (date: string) => {\n            expect(date).toMatchSnapshot()\n          }\n        }\n      }).html()\n    ).toMatchSnapshot()\n    expect(\n      mount(Wrapper, {\n        props: {\n          dateLocale: dateDeDE,\n          locale: deDE,\n          onMounted: (date: string) => {\n            expect(date).toMatchSnapshot()\n          }\n        }\n      }).html()\n    ).toMatchSnapshot()\n    expect(\n      mount(Wrapper, {\n        props: {\n          dateLocale: dateNbNO,\n          locale: nbNO,\n          onMounted: (date: string) => {\n            expect(date).toMatchSnapshot()\n          }\n        }\n      }).html()\n    ).toMatchSnapshot()\n    expect(\n      mount(Wrapper, {\n        props: {\n          dateLocale: dateFrFR,\n          locale: frFR\n        }\n      }).html()\n    ).toMatchSnapshot()\n    expect(\n      mount(Wrapper, {\n        props: {\n          dateLocale: dateEsAR,\n          locale: esAR\n        }\n      }).html()\n    ).toMatchSnapshot()\n    expect(\n      mount(Wrapper, {\n        props: {\n          dateLocale: dateItIT,\n          locale: itIT\n        }\n      }).html()\n    ).toMatchSnapshot()\n    expect(\n      mount(Wrapper, {\n        props: {\n          dateLocale: dateEnGB,\n          locale: enGB\n        }\n      }).html()\n    ).toMatchSnapshot()\n    expect(\n      mount(Wrapper, {\n        props: {\n          dateLocale: dateSkSK,\n          locale: skSK\n        }\n      }).html()\n    ).toMatchSnapshot()\n    expect(\n      mount(Wrapper, {\n        props: {\n          dateLocale: dateCsCZ,\n          locale: csCZ\n        }\n      }).html()\n    ).toMatchSnapshot()\n    expect(\n      mount(Wrapper, {\n        props: {\n          dateLocale: datePlPL,\n          locale: plPL\n        }\n      }).html()\n    ).toMatchSnapshot()\n    expect(\n      mount(Wrapper, {\n        props: {\n          dateLocale: datePtBR,\n          locale: ptBR\n        }\n      }).html()\n    ).toMatchSnapshot()\n    expect(\n      mount(Wrapper, {\n        props: {\n          dateLocale: dateThTH,\n          locale: thTH\n        }\n      }).html()\n    ).toMatchSnapshot()\n    expect(\n      mount(Wrapper, {\n        props: {\n          dateLocale: dateEo,\n          locale: eo\n        }\n      }).html()\n    ).toMatchSnapshot()\n    expect(\n      mount(Wrapper, {\n        props: {\n          dateLocale: dateNlNL,\n          locale: nlNL\n        }\n      }).html()\n    ).toMatchSnapshot()\n    expect(\n      mount(Wrapper, {\n        props: {\n          dateLocale: dateArDZ,\n          locale: arDZ\n        }\n      }).html()\n    ).toMatchSnapshot()\n    expect(\n      mount(Wrapper, {\n        props: {\n          dateLocale: dateTrTR,\n          locale: trTR\n        }\n      }).html()\n    ).toMatchSnapshot()\n    expect(\n      mount(Wrapper, {\n        props: {\n          dateLocale: dateFaIR,\n          locale: faIR\n        }\n      }).html()\n    ).toMatchSnapshot()\n    expect(\n      mount(Wrapper, {\n        props: {\n          dateLocale: dateSvSE,\n          locale: svSE,\n          onMounted: (date: string) => {\n            expect(date).toMatchSnapshot()\n          }\n        }\n      }).html()\n    ).toMatchSnapshot()\n    expect(\n      mount(Wrapper, {\n        props: {\n          dateLocale: dateEtEE,\n          locale: etEE,\n          onMounted: (date: string) => {\n            expect(date).toMatchSnapshot()\n          }\n        }\n      }).html()\n    ).toMatchSnapshot()\n    expect(\n      mount(Wrapper, {\n        props: {\n          dateLocale: dateAzAZ,\n          locale: azAZ\n        }\n      }).html()\n    ).toMatchSnapshot()\n    expect(\n      mount(Wrapper, {\n        props: {\n          dateLocale: dateUgCN,\n          locale: ugCN\n        }\n      }).html()\n    ).toMatchSnapshot()\n    expect(\n      mount(Wrapper, {\n        props: {\n          dateLocale: dateDaDK,\n          locale: daDK\n        }\n      }).html()\n    ).toMatchSnapshot()\n  })\n})\n"
  },
  {
    "path": "src/locales/index.ts",
    "content": "export { default as arDZ } from './common/arDZ'\nexport { default as azAZ } from './common/azAZ'\nexport { default as csCZ } from './common/csCZ'\nexport { default as daDK } from './common/daDK'\nexport { default as deDE } from './common/deDE'\nexport { default as enGB } from './common/enGB'\nexport { default as enUS } from './common/enUS'\nexport type { NLocale } from './common/enUS'\nexport { default as eo } from './common/eo'\nexport { default as esAR } from './common/esAR'\nexport { default as etEE } from './common/etEE'\nexport { default as faIR } from './common/faIR'\nexport { default as frFR } from './common/frFR'\nexport { default as idID } from './common/idID'\nexport { default as itIT } from './common/itIT'\nexport { default as jaJP } from './common/jaJP'\nexport { default as kmKH } from './common/kmKH'\nexport { default as koKR } from './common/koKR'\nexport { default as nbNO } from './common/nbNO'\nexport { default as nlNL } from './common/nlNL'\nexport { default as plPL } from './common/plPL'\nexport { default as ptBR } from './common/ptBR'\nexport { default as ruRU } from './common/ruRU'\nexport { default as skSK } from './common/skSK'\nexport { default as svSE } from './common/svSE'\nexport { default as thTH } from './common/thTH'\nexport { default as trTR } from './common/trTR'\nexport { default as ukUA } from './common/ukUA'\nexport { default as uzUZ } from './common/uzUZ'\nexport { default as viVN } from './common/viVN'\nexport { default as zhCN } from './common/zhCN'\nexport { default as zhTW } from './common/zhTW'\nexport { default as dateArDZ } from './date/arDZ'\nexport { default as dateAzAZ } from './date/azAZ'\nexport { default as dateCsCZ } from './date/csCZ'\nexport { default as dateDaDK } from './date/daDK'\nexport { default as dateDeDE } from './date/deDE'\nexport { default as dateEnGB } from './date/enGB'\nexport { default as dateEnUS } from './date/enUS'\nexport type { NDateLocale } from './date/enUS'\nexport { default as dateEo } from './date/eo'\nexport { default as dateEsAR } from './date/esAR'\nexport { default as dateEtEE } from './date/etEE'\nexport { default as dateFaIR } from './date/faIR'\nexport { default as dateFrFR } from './date/frFR'\nexport { default as dateIdID } from './date/idID'\nexport { default as dateItIT } from './date/itIT'\nexport { default as dateJaJP } from './date/jaJP'\nexport { default as dateKmKH } from './date/kmKH'\nexport { default as dateKoKR } from './date/koKR'\nexport { default as dateNbNO } from './date/nbNO'\nexport { default as dateNlNL } from './date/nlNL'\nexport { default as datePlPL } from './date/plPL'\nexport { default as datePtBR } from './date/ptBR'\nexport { default as dateRuRU } from './date/ruRU'\nexport { default as dateSkSK } from './date/skSK'\nexport { default as dateSvSE } from './date/svSE'\nexport { default as dateThTH } from './date/thTH'\nexport { default as dateTrTR } from './date/trTR'\nexport { default as dateUgCN } from './date/ugCN'\nexport { default as dateUkUA } from './date/ukUA'\nexport { default as dateUzUZ } from './date/uzUZ'\nexport { default as dateViVN } from './date/viVN'\nexport { default as dateZhCN } from './date/zhCN'\nexport { default as dateZhTW } from './date/zhTW'\nexport type { NPartialLocale } from './utils/index'\nexport { createLocale } from './utils/index'\n"
  },
  {
    "path": "src/locales/utils/index.ts",
    "content": "import type { NLocale } from '../common/enUS'\nimport { merge } from 'lodash-es'\n\nexport type NPartialLocale = {\n  [key in keyof NLocale]+?: {\n    [childKey in keyof NLocale[key]]+?: NLocale[key][childKey]\n  }\n}\n\nexport function createLocale(locale: NLocale): NLocale\nexport function createLocale(\n  locale: NPartialLocale,\n  fallbackLocale: NLocale\n): NLocale\nexport function createLocale(\n  locale: NPartialLocale,\n  fallbackLocale?: NLocale\n): NLocale {\n  return merge({}, fallbackLocale, locale)\n}\n"
  },
  {
    "path": "src/log/demos/enUS/auto-bottom.demo.vue",
    "content": "<markdown>\n# Scroll to latest\n\nScroll to the latest when log is gradually increasing.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { LogInst } from 'naive-ui'\nimport { nextTick, onMounted, ref, watchEffect } from 'vue'\n\nfunction log() {\n  const l: string[] = []\n  for (let i = 0; i < 40; ++i) {\n    l.push(Math.random().toString(16))\n  }\n  return `${l.join('\\n')}\\n`\n}\n\nconst logRef = ref(log())\nconst logInstRef = ref<LogInst | null>(null)\nconst startRef = ref(false)\nconst timerRef = ref<number | null>(null)\nfunction handleClick() {\n  startRef.value = !startRef.value\n  if (startRef.value) {\n    timerRef.value = window.setInterval(() => {\n      logRef.value = logRef.value + log()\n    }, 1000)\n  }\n  else if (timerRef.value) {\n    clearInterval(timerRef.value)\n    timerRef.value = null\n  }\n}\nonMounted(() => {\n  watchEffect(() => {\n    if (logRef.value) {\n      nextTick(() => {\n        logInstRef.value?.scrollTo({ position: 'bottom', silent: true })\n      })\n    }\n  })\n})\n</script>\n\n<template>\n  <n-space vertical>\n    <n-button @click=\"handleClick\">\n      Add Data\n    </n-button>\n    <n-log ref=\"logInstRef\" :log=\"logRef\" language=\"naive-log\" trim />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/log/demos/enUS/event.demo.vue",
    "content": "<markdown>\n# Event\n\nLog has `require-more`, `reach-top` and `reach-bottom` event. Note that even if logs are scrolled to top or bottom, when you wheel to the same direction, `require-more` will still be triggered while `reach-xxx` will not. If you don't want to trigger handler when logs are at top or bottom. Use `reach-top` or `reach-bottom` instead.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { useMessage } from 'naive-ui'\nimport { ref } from 'vue'\n\nfunction log() {\n  const l: string[] = []\n  for (let i = 0; i < 10; ++i) {\n    l.push(Math.random().toString(16))\n  }\n  return `${l.join('\\n')}\\n`\n}\n\nconst message = useMessage()\nconst loadingRef = ref(false)\nconst logRef = ref(log())\n\nfunction handleRequireMore(from: 'top' | 'bottom') {\n  message.info(`Require More from ${from}`)\n  if (loadingRef.value)\n    return\n  loadingRef.value = true\n  setTimeout(() => {\n    if (from === 'top') {\n      logRef.value = log() + logRef.value\n    }\n    else if (from === 'bottom') {\n      logRef.value = logRef.value + log()\n    }\n    loadingRef.value = false\n  }, 1000)\n}\n\nfunction handleReachTop() {\n  message.info('Reach Top')\n}\n\nfunction handleReachBottom() {\n  message.info('Reach Bottom')\n}\n</script>\n\n<template>\n  <n-log\n    :log=\"logRef\"\n    :loading=\"loadingRef\"\n    trim\n    @require-more=\"handleRequireMore\"\n    @reach-top=\"handleReachTop\"\n    @reach-bottom=\"handleReachBottom\"\n  />\n</template>\n"
  },
  {
    "path": "src/log/demos/enUS/highlight.demo.vue",
    "content": "<markdown>\n# Highlight\n\nBefore you use highlight, see Note section of the page to make sure you won't miss messages that are important to make it work.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nfunction log() {\n  const l: string[] = []\n  for (let i = 0; i < 40; ++i) {\n    l.push(Math.random().toString(16))\n  }\n  return `${l.join('\\n')}\\n`\n}\n\nconst loadingRef = ref(false)\nconst logRef = ref(log())\n\nfunction handlerequireTop() {\n  if (loadingRef.value)\n    return\n  loadingRef.value = true\n  setTimeout(() => {\n    logRef.value = log() + logRef.value\n    loadingRef.value = false\n  }, 1000)\n}\n\nfunction handlerequireBottom() {\n  if (loadingRef.value)\n    return\n  loadingRef.value = true\n  setTimeout(() => {\n    logRef.value = logRef.value + log()\n    loadingRef.value = false\n  }, 1000)\n}\n</script>\n\n<template>\n  <n-log\n    :log=\"logRef\"\n    :loading=\"loadingRef\"\n    language=\"naive-log\"\n    trim\n    @require-top=\"handlerequireTop\"\n    @require-bottom=\"handlerequireBottom\"\n  />\n</template>\n"
  },
  {
    "path": "src/log/demos/enUS/index.demo-entry.md",
    "content": "# Log\n\n<!--single-column-->\n\nIf you have some logs to show, use log.\n\n<n-alert title=\"Note\" type=\"warning\" style=\"margin-bottom: 16px;\" :bordered=\"false\">\n  Due to package size, Naive UI doesn't include highlight.js. If you want highlight logs, make sure you have set highlightjs before using it.\n</n-alert>\n\nIn highlight demo, we defined a language called `naive-log` which will highlight all the numbers of line. The following code shows how we defined it. If you want to know more about highlight.js, see <n-a href=\"https://highlightjs.org/\" target=\"_blank\">highlight.js</n-a> and <n-a href=\"https://highlightjs.readthedocs.io/en/latest/index.html\" target=\"_blank\">highlight.js developer documentation</n-a>\n\n```html\n<template>\n  <n-config-provider :hljs=\"hljs\">\n    <my-app />\n  </n-config-provider>\n</template>\n\n<script>\n  import { defineComponent } from 'vue'\n  import hljs from 'highlight.js/lib/core'\n\n  hljs.registerLanguage('naive-log', () => ({\n    contains: [\n      {\n        className: 'number',\n        begin: /\\d+/\n      }\n    ]\n  }))\n\n  export default defineComponent({\n    setup() {\n      return {\n        hljs\n      }\n    }\n  })\n</script>\n```\n\n## Demos\n\n```demo\nsize.vue\nevent.vue\nscroll.vue\nhighlight.vue\nloading.vue\nauto-bottom.vue\n```\n\n## API\n\n### Log Props\n\n| Name | Type | Default | Description |\n| --- | --- | --- | --- | --- |\n| font-size | `number` | `14` | Font size. |\n| hljs | `Object` | `undefined` | If you want to set `hljs` locally, pass it using this prop. |\n| language | `string` | `undefined` | The language of the log in `highlightjs`. |\n| line-height | `number` | `1.25` | Line height. |\n| lines | `Array<string>` | `undefined` | Display the log content by line. When the `log` parameter exists at the same time, the parameter is invalid. |\n| loading | `boolean` | `false` | Whether to show loading. |\n| log | `string` | `undefined` | The content of the log. |\n| rows | `number` | `15` | Log size. |\n| spin-props | `{ strokeWidth?: number, stroke?: string, scale?: number, radius?: number }` | `undefined` | Loading icon properties. | 2.44.0 |\n| trim | `boolean` | `false` | Whether to display the log after `trim`. |\n| on-require-more | `(from: 'top' \\| 'bottom') => void` | `undefined` | Callback function for scroll loading log. |\n| on-reach-top | `() => void` | `undefined` | Scroll to the top callback function. |\n| on-reach-bottom | `() => void` | `undefined` | Scroll to the bottom callback function. |\n\n### Log Methods\n\n| Name | Parameters | Description |\n| --- | --- | --- |\n| scrollTo | `(options: { top?: number, position?: 'top' \\| 'bottom', silent?: boolean })` | Callback function for scroll event. |\n"
  },
  {
    "path": "src/log/demos/enUS/loading.demo.vue",
    "content": "<markdown>\n# Loading\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nfunction log() {\n  const l: string[] = []\n  for (let i = 0; i < 40; ++i) {\n    l.push(Math.random().toString(16))\n  }\n  return `${l.join('\\n')}\\n`\n}\n\nconst loading = ref(false)\nconst logRef = ref(log())\n</script>\n\n<template>\n  <n-switch v-model:value=\"loading\" />\n  <n-log :loading=\"loading\" :log=\"logRef\" />\n</template>\n"
  },
  {
    "path": "src/log/demos/enUS/scroll.demo.vue",
    "content": "<markdown>\n# Scroll\n\nYou can easily make log scroll to top or bottom. Also you can make the scroll action silent (don't trigger events of Log in this scroll action).\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { LogInst } from 'naive-ui'\nimport { useMessage } from 'naive-ui'\nimport { ref } from 'vue'\n\nfunction log() {\n  const l: string[] = []\n  for (let i = 0; i < 10; ++i) {\n    l.push(Math.random().toString(16))\n  }\n  return `${l.join('\\n')}\\n`\n}\n\nconst message = useMessage()\nconst loadingRef = ref(false)\nconst logRef = ref(log())\nconst logInstRef = ref<LogInst | null>(null)\n\nfunction handleRequireMore(from: 'top' | 'bottom') {\n  message.info(`Require More from ${from}`)\n  if (loadingRef.value)\n    return\n  loadingRef.value = true\n  setTimeout(() => {\n    if (from === 'top') {\n      logRef.value = log() + logRef.value\n    }\n    else if (from === 'bottom') {\n      logRef.value = logRef.value + log()\n    }\n    loadingRef.value = false\n  }, 1000)\n}\n\nfunction handleReachTop() {\n  message.info('Reach Top')\n}\n\nfunction handleReachBottom() {\n  message.info('Reach Bottom')\n}\n\nfunction scrollTo(options: { position: 'bottom' | 'top', silent: boolean }) {\n  logInstRef.value?.scrollTo(options)\n}\n</script>\n\n<template>\n  <n-space vertical>\n    <n-button-group>\n      <n-button @click=\"scrollTo({ position: 'bottom', silent: false })\">\n        Scroll To Bottom\n      </n-button>\n      <n-button @click=\"scrollTo({ position: 'bottom', silent: true })\">\n        Scroll To Bottom (silent)\n      </n-button>\n      <n-button @click=\"scrollTo({ position: 'top', silent: false })\">\n        Scroll To Top\n      </n-button>\n      <n-button @click=\"scrollTo({ position: 'top', silent: true })\">\n        Scroll To Top (silent)\n      </n-button>\n    </n-button-group>\n    <n-log\n      ref=\"logInstRef\"\n      :log=\"logRef\"\n      :loading=\"loadingRef\"\n      trim\n      @require-more=\"handleRequireMore\"\n      @reach-top=\"handleReachTop\"\n      @reach-bottom=\"handleReachBottom\"\n    />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/log/demos/enUS/size.demo.vue",
    "content": "<markdown>\n# Rows\n\nUse `rows` to change the size of log.\n</markdown>\n\n<template>\n  <n-log\n    :rows=\"5\"\n    log=\"1\n2\n3\n4\n5\n6\"\n  />\n</template>\n"
  },
  {
    "path": "src/log/demos/zhCN/auto-bottom.demo.vue",
    "content": "<markdown>\n# 滚动到最新\n\n当日志不断增加时总是滚动到最新。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { LogInst } from 'naive-ui'\nimport { nextTick, onMounted, ref, watchEffect } from 'vue'\n\nfunction log() {\n  const l: string[] = []\n  for (let i = 0; i < 40; ++i) {\n    l.push(Math.random().toString(16))\n  }\n  return `${l.join('\\n')}\\n`\n}\n\nconst logRef = ref(log())\nconst logInstRef = ref<LogInst | null>(null)\nconst startRef = ref(false)\nconst timerRef = ref<number | null>(null)\nfunction handleClick() {\n  startRef.value = !startRef.value\n  if (startRef.value) {\n    timerRef.value = window.setInterval(() => {\n      logRef.value = logRef.value + log()\n    }, 1000)\n  }\n  else if (timerRef.value) {\n    clearInterval(timerRef.value)\n    timerRef.value = null\n  }\n}\nonMounted(() => {\n  watchEffect(() => {\n    if (logRef.value) {\n      nextTick(() => {\n        logInstRef.value?.scrollTo({ position: 'bottom', silent: true })\n      })\n    }\n  })\n})\n</script>\n\n<template>\n  <n-space vertical>\n    <n-button @click=\"handleClick\">\n      添加数据\n    </n-button>\n    <n-log ref=\"logInstRef\" :log=\"logRef\" language=\"naive-log\" trim />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/log/demos/zhCN/debug.demo.vue",
    "content": "<markdown>\n# Debug\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nfunction log() {\n  const l: string[] = []\n  for (let i = 0; i < 40; ++i) {\n    l.push(Math.random().toString(16))\n  }\n  return `${l.join('\\n')}\\n`\n}\n\nconst loadingRef = ref(false)\nconst logRef = ref(log())\n\nfunction clear() {\n  logRef.value = ''\n}\n\nfunction handleRequireMore(from: 'top' | 'bottom') {\n  if (loadingRef.value)\n    return\n  loadingRef.value = true\n  setTimeout(() => {\n    if (from === 'top') {\n      logRef.value = log() + logRef.value\n    }\n    else if (from === 'bottom') {\n      logRef.value = logRef.value + log()\n    }\n    loadingRef.value = false\n  }, 1000)\n}\n</script>\n\n<template>\n  <n-card\n    title=\"Random String Logs\"\n    :segmented=\"{\n      content: true,\n    }\"\n  >\n    <n-log\n      style=\"margin-top: -12px; margin-bottom: -12px\"\n      :log=\"logRef\"\n      :loading=\"loadingRef\"\n      trim\n      @require-more=\"handleRequireMore\"\n    />\n    <template #action>\n      <n-button @click=\"clear\">\n        Clear\n      </n-button>\n    </template>\n  </n-card>\n</template>\n"
  },
  {
    "path": "src/log/demos/zhCN/event.demo.vue",
    "content": "<markdown>\n# 事件\n\nLog 有 `require-more`、`reach-top` 和 `reach-bottom` 事件。需要注意的是即使 Log 已经滚到了头或者尾，你继续滚动鼠标的时候，`require-more` 还是会被触发，而 `reach-xxx` 并不会。如果你不需要这种特性，可以使用 `reach-top` 或者 `reach-bottom`。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { useMessage } from 'naive-ui'\nimport { ref } from 'vue'\n\nfunction log() {\n  const l: string[] = []\n  for (let i = 0; i < 10; ++i) {\n    l.push(Math.random().toString(16))\n  }\n  return `${l.join('\\n')}\\n`\n}\n\nconst message = useMessage()\nconst loadingRef = ref(false)\nconst logRef = ref(log())\n\nfunction handleRequireMore(from: 'top' | 'bottom') {\n  message.info(`Require More from ${from}`)\n  if (loadingRef.value)\n    return\n  loadingRef.value = true\n  setTimeout(() => {\n    if (from === 'top') {\n      logRef.value = log() + logRef.value\n    }\n    else if (from === 'bottom') {\n      logRef.value = logRef.value + log()\n    }\n    loadingRef.value = false\n  }, 1000)\n}\n\nfunction handleReachTop() {\n  message.info('Reach Top')\n}\n\nfunction handleReachBottom() {\n  message.info('Reach Bottom')\n}\n</script>\n\n<template>\n  <n-log\n    :log=\"logRef\"\n    :loading=\"loadingRef\"\n    trim\n    @require-more=\"handleRequireMore\"\n    @reach-top=\"handleReachTop\"\n    @reach-bottom=\"handleReachBottom\"\n  />\n</template>\n"
  },
  {
    "path": "src/log/demos/zhCN/highlight.demo.vue",
    "content": "<markdown>\n# 高亮\n\n在你使用高亮之前，请看本页开始的注意事项，那些对于确保这个例子按预期展示是很重要的。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nfunction log() {\n  const l: string[] = []\n  for (let i = 0; i < 40; ++i) {\n    l.push(Math.random().toString(16))\n  }\n  return `${l.join('\\n')}\\n`\n}\n\nconst loadingRef = ref(false)\nconst logRef = ref(log())\n\nfunction handlerequireTop() {\n  if (loadingRef.value)\n    return\n  loadingRef.value = true\n  setTimeout(() => {\n    logRef.value = log() + logRef.value\n    loadingRef.value = false\n  }, 1000)\n}\n\nfunction handlerequireBottom() {\n  if (loadingRef.value)\n    return\n  loadingRef.value = true\n  setTimeout(() => {\n    logRef.value = logRef.value + log()\n    loadingRef.value = false\n  }, 1000)\n}\n</script>\n\n<template>\n  <n-log\n    :log=\"logRef\"\n    :loading=\"loadingRef\"\n    language=\"naive-log\"\n    trim\n    @require-top=\"handlerequireTop\"\n    @require-bottom=\"handlerequireBottom\"\n  />\n</template>\n"
  },
  {
    "path": "src/log/demos/zhCN/index.demo-entry.md",
    "content": "# 日志 Log\n\n<!--single-column-->\n\n如果你有一些日志要展示，可以使用 Log。\n\n<n-alert title=\"注意\" type=\"warning\" style=\"margin-bottom: 16px;\" :bordered=\"false\">\n  由于尺寸原因，Naive UI 不内置 highlight.js。如果你需要高亮日志，请确保你在使用之前已经设定了 highlight.js。\n</n-alert>\n\n在本页如何高亮的演示中，我们定义了一个叫做 `naive-log` 的语言来高亮全部的数字。下面的代码是我们怎么定义的。如果你想了解 highlight.js，可以参考 <n-a href=\"https://highlightjs.org/\" target=\"_blank\">highlight.js</n-a> 和 <n-a href=\"https://highlightjs.readthedocs.io/en/latest/index.html\" target=\"_blank\">highlight.js developer documentation</n-a>\n\n```html\n<template>\n  <n-config-provider :hljs=\"hljs\">\n    <my-app />\n  </n-config-provider>\n</template>\n\n<script>\n  import { defineComponent } from 'vue'\n  import hljs from 'highlight.js/lib/core'\n\n  hljs.registerLanguage('naive-log', () => ({\n    contains: [\n      {\n        className: 'number',\n        begin: /\\d+/\n      }\n    ]\n  }))\n\n  export default defineComponent({\n    setup() {\n      return {\n        hljs\n      }\n    }\n  })\n</script>\n```\n\n## 演示\n\n```demo\nsize.vue\nevent.vue\nscroll.vue\nhighlight.vue\nloading.vue\nauto-bottom.vue\n```\n\n## API\n\n### Log Props\n\n| 名称 | 类型 | 默认值 | 说明 |\n| --- | --- | --- | --- | --- |\n| font-size | `number` | `14` | 文字大小 |\n| hljs | `Object` | `undefined` | 如果你想局部设定 `hljs` ，可以通过这个属性传给组件 |\n| language | `string` | `undefined` | 日志在 `highlightjs` 中的语言 |\n| line-height | `number` | `1.25` | 行高 |\n| lines | `Array<string>` | `undefined` | 按行显示日志内容，在同时存在 `log` 参数时，该参数无效 |\n| loading | `boolean` | `false` | 是否显示加载中 |\n| log | `string` | `undefined` | 日志的内容 |\n| rows | `number` | `15` | 日志的尺寸 |\n| spin-props | `{ strokeWidth?: number, stroke?: string, scale?: number, radius?: number }` | `undefined` | 加载图标的属性 | 2.44.0 |\n| trim | `boolean` | `false` | 是否显示 `trim` 后的日志 |\n| on-require-more | `(from: 'top' \\| 'bottom') => void` | `undefined` | 滚动加载日志的回调函数 |\n| on-reach-top | `() => void` | `undefined` | 滚动到顶部的回调函数 |\n| on-reach-bottom | `() => void` | `undefined` | 滚动到底部的回调函数 |\n\n### Log Methods\n\n| 名称 | 参数 | 说明 |\n| --- | --- | --- |\n| scrollTo | `(options: { top?: number, position?: 'top' \\| 'bottom', silent?: boolean })` | 滚动事件的回调函数 |\n"
  },
  {
    "path": "src/log/demos/zhCN/loading.demo.vue",
    "content": "<markdown>\n# 加载\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nfunction log() {\n  const l: string[] = []\n  for (let i = 0; i < 40; ++i) {\n    l.push(Math.random().toString(16))\n  }\n  return `${l.join('\\n')}\\n`\n}\n\nconst loading = ref(false)\nconst logRef = ref(log())\n</script>\n\n<template>\n  <n-switch v-model:value=\"loading\" />\n  <n-log :loading=\"loading\" :log=\"logRef\" />\n</template>\n"
  },
  {
    "path": "src/log/demos/zhCN/scroll.demo.vue",
    "content": "<markdown>\n# 滚动\n\n你可以很简单的让 Log 滚到顶部或者底部。同时你可以控制这个滚动操作是否发出事件。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { LogInst } from 'naive-ui'\nimport { useMessage } from 'naive-ui'\nimport { ref } from 'vue'\n\nfunction log() {\n  const l: string[] = []\n  for (let i = 0; i < 10; ++i) {\n    l.push(Math.random().toString(16))\n  }\n  return `${l.join('\\n')}\\n`\n}\n\nconst message = useMessage()\nconst loadingRef = ref(false)\nconst logRef = ref(log())\nconst logInstRef = ref<LogInst | null>(null)\n\nfunction handleRequireMore(from: 'top' | 'bottom') {\n  message.info(`Require More from ${from}`)\n  if (loadingRef.value)\n    return\n  loadingRef.value = true\n  setTimeout(() => {\n    if (from === 'top') {\n      logRef.value = log() + logRef.value\n    }\n    else if (from === 'bottom') {\n      logRef.value = logRef.value + log()\n    }\n    loadingRef.value = false\n  }, 1000)\n}\n\nfunction handleReachTop() {\n  message.info('Reach Top')\n}\n\nfunction handleReachBottom() {\n  message.info('Reach Bottom')\n}\n\nfunction scrollTo(options: { position: 'bottom' | 'top', silent: boolean }) {\n  logInstRef.value?.scrollTo(options)\n}\n</script>\n\n<template>\n  <n-space vertical>\n    <n-button-group>\n      <n-button @click=\"scrollTo({ position: 'bottom', silent: false })\">\n        滚动到底部\n      </n-button>\n      <n-button @click=\"scrollTo({ position: 'bottom', silent: true })\">\n        滚动到底部（无事件）\n      </n-button>\n      <n-button @click=\"scrollTo({ position: 'top', silent: false })\">\n        滚动到顶部\n      </n-button>\n      <n-button @click=\"scrollTo({ position: 'top', silent: true })\">\n        滚动到顶部（无事件）\n      </n-button>\n    </n-button-group>\n    <n-log\n      ref=\"logInstRef\"\n      :log=\"logRef\"\n      :loading=\"loadingRef\"\n      trim\n      @require-more=\"handleRequireMore\"\n      @reach-top=\"handleReachTop\"\n      @reach-bottom=\"handleReachBottom\"\n    />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/log/demos/zhCN/size.demo.vue",
    "content": "<markdown>\n# 行数\n\n使用 `rows` 来设定 Log 的尺寸。\n</markdown>\n\n<template>\n  <n-log\n    :rows=\"5\"\n    log=\"1\n2\n3\n4\n5\n6\"\n  />\n</template>\n"
  },
  {
    "path": "src/log/index.ts",
    "content": "export { logProps, default as NLog } from './src/Log'\nexport type { LogInst, LogProps } from './src/Log'\nexport type * from './src/public-types'\n"
  },
  {
    "path": "src/log/src/Log.tsx",
    "content": "import type { PropType, Ref } from 'vue'\nimport type { ScrollbarInst } from '../../_internal'\nimport type { Hljs, ThemeProps } from '../../_mixins'\nimport type { ExtractPublicPropTypes } from '../../_utils'\nimport type { LogTheme } from '../styles'\nimport type { LogSpinProps } from './public-types'\nimport { throttle as _throttle } from 'lodash-es'\nimport {\n  computed,\n  defineComponent,\n  h,\n  nextTick,\n  provide,\n  ref,\n  toRef,\n  Transition\n} from 'vue'\nimport { NScrollbar } from '../../_internal'\nimport { useConfig, useHljs, useTheme, useThemeClass } from '../../_mixins'\nimport { warn } from '../../_utils'\nimport { NCode } from '../../code'\nimport { logLight } from '../styles'\nimport { logInjectionKey } from './context'\nimport NLogLine from './LogLine'\nimport NLogLoader from './LogLoader'\nimport style from './styles/index.cssr'\n\n// Fix vue-tsc error\nconst throttle: <T>(f: T, t: number) => T = _throttle\n\nexport interface LogInjection {\n  trimRef: Ref<boolean>\n  languageRef: Ref<string | undefined>\n  highlightRef: Ref<boolean>\n  mergedHljsRef: Ref<Hljs | undefined>\n}\n\nexport interface LogInst {\n  scrollTo: ((options: {\n    silent?: boolean\n    position: 'top' | 'bottom'\n  }) => void)\n  & ((options: { silent?: boolean, top: number }) => void)\n}\n\nexport const logProps = {\n  ...(useTheme.props as ThemeProps<LogTheme>),\n  loading: Boolean,\n  trim: Boolean,\n  log: String,\n  fontSize: {\n    type: Number,\n    default: 14\n  },\n  lines: {\n    type: Array as PropType<string[]>,\n    default: () => []\n  },\n  lineHeight: {\n    type: Number,\n    default: 1.25\n  },\n  language: String,\n  rows: {\n    type: Number,\n    default: 15\n  },\n  offsetTop: {\n    type: Number,\n    default: 0\n  },\n  offsetBottom: {\n    type: Number,\n    default: 0\n  },\n  hljs: Object,\n  spinProps: Object as PropType<LogSpinProps>,\n  onReachTop: Function as PropType<() => void>,\n  onReachBottom: Function as PropType<() => void>,\n  onRequireMore: Function as PropType<(from: 'top' | 'bottom') => void>\n} as const\n\nexport type LogProps = ExtractPublicPropTypes<typeof logProps>\n\nexport default defineComponent({\n  name: 'Log',\n  props: logProps,\n  setup(props) {\n    const { mergedClsPrefixRef, inlineThemeDisabled } = useConfig(props)\n    const silentRef = ref(false)\n    const highlightRef = computed(() => {\n      return props.language !== undefined\n    })\n    const styleHeightRef = computed(() => {\n      return `calc(${Math.round(\n        props.rows * props.lineHeight * props.fontSize\n      )}px)`\n    })\n    const mergedLinesRef = computed(() => {\n      const { log } = props\n      if (log) {\n        return log.split('\\n')\n      }\n      return props.lines\n    })\n    const scrollbarRef = ref<ScrollbarInst | null>(null)\n    const themeRef = useTheme(\n      'Log',\n      '-log',\n      style,\n      logLight,\n      props,\n      mergedClsPrefixRef\n    )\n    function handleScroll(e: Event): void {\n      const container = e.target as HTMLElement\n      const content = container.firstElementChild as HTMLElement\n      if (silentRef.value) {\n        void nextTick(() => {\n          silentRef.value = false\n        })\n        return\n      }\n      const containerHeight = container.offsetHeight\n      const containerScrollTop = container.scrollTop\n      const contentHeight = content.offsetHeight\n      const scrollTop = containerScrollTop\n      const scrollBottom = contentHeight - containerScrollTop - containerHeight\n      if (scrollTop <= props.offsetTop) {\n        const { onReachTop, onRequireMore } = props\n        if (onRequireMore)\n          onRequireMore('top')\n        if (onReachTop)\n          onReachTop()\n      }\n      if (scrollBottom <= props.offsetBottom) {\n        const { onReachBottom, onRequireMore } = props\n        if (onRequireMore)\n          onRequireMore('bottom')\n        if (onReachBottom)\n          onReachBottom()\n      }\n    }\n    const handleWheel: (e: WheelEvent) => void = throttle(_handleWheel, 300)\n    function _handleWheel(e: WheelEvent): void {\n      if (silentRef.value) {\n        void nextTick(() => {\n          silentRef.value = false\n        })\n        return\n      }\n      if (scrollbarRef.value) {\n        const { containerRef, contentRef } = scrollbarRef.value\n        if (containerRef && contentRef) {\n          const containerHeight = containerRef.offsetHeight\n          const containerScrollTop = containerRef.scrollTop\n          const contentHeight = contentRef.offsetHeight\n          const scrollTop = containerScrollTop\n          const scrollBottom\n            = contentHeight - containerScrollTop - containerHeight\n          const deltaY = e.deltaY\n          if (scrollTop === 0 && deltaY < 0) {\n            const { onRequireMore } = props\n            if (onRequireMore)\n              onRequireMore('top')\n          }\n          if (scrollBottom <= 0 && deltaY > 0) {\n            const { onRequireMore } = props\n            if (onRequireMore)\n              onRequireMore('bottom')\n          }\n        }\n      }\n    }\n    function scrollTo(options: {\n      silent?: boolean\n      position: 'top' | 'bottom'\n    }): void\n    function scrollTo(options: { silent?: boolean, top: number }): void\n    function scrollTo(options: {\n      silent?: boolean\n      top?: number\n      position?: 'top' | 'bottom'\n    }): void {\n      const { value: scrollbarInst } = scrollbarRef\n      if (!scrollbarInst)\n        return\n      const { silent, top, position } = options\n      if (silent) {\n        silentRef.value = true\n      }\n      if (top !== undefined) {\n        scrollbarInst.scrollTo({ left: 0, top })\n      }\n      else if (position === 'bottom' || position === 'top') {\n        scrollbarInst.scrollTo({ position })\n      }\n    }\n    // deprecated\n    function scrollToTop(silent = false): void {\n      warn(\n        'log',\n        '`scrollToTop` is deprecated, please use `scrollTo({ position: \\'top\\'})` instead.'\n      )\n      scrollTo({\n        position: 'top',\n        silent\n      })\n    }\n    function scrollToBottom(silent = false): void {\n      warn(\n        'log',\n        '`scrollToTop` is deprecated, please use `scrollTo({ position: \\'bottom\\'})` instead.'\n      )\n      scrollTo({\n        position: 'bottom',\n        silent\n      })\n    }\n    provide(logInjectionKey, {\n      languageRef: toRef(props, 'language'),\n      mergedHljsRef: useHljs(props, highlightRef),\n      trimRef: toRef(props, 'trim'),\n      highlightRef\n    })\n\n    const exportedMethods: LogInst = {\n      scrollTo\n    }\n\n    const cssVarsRef = computed(() => {\n      const {\n        self: {\n          loaderFontSize,\n          loaderTextColor,\n          loaderColor,\n          loaderBorder,\n          loadingColor\n        },\n        common: { cubicBezierEaseInOut }\n      } = themeRef.value\n      return {\n        '--n-bezier': cubicBezierEaseInOut,\n        '--n-loader-font-size': loaderFontSize,\n        '--n-loader-border': loaderBorder,\n        '--n-loader-color': loaderColor,\n        '--n-loader-text-color': loaderTextColor,\n        '--n-loading-color': loadingColor\n      }\n    })\n    const themeClassHandle = inlineThemeDisabled\n      ? useThemeClass('log', undefined, cssVarsRef, props)\n      : undefined\n\n    return {\n      ...exportedMethods,\n      mergedClsPrefix: mergedClsPrefixRef,\n      scrollbarRef,\n      mergedTheme: themeRef,\n      styleHeight: styleHeightRef,\n      mergedLines: mergedLinesRef,\n      scrollToTop,\n      scrollToBottom,\n      handleWheel,\n      handleScroll,\n      cssVars: inlineThemeDisabled ? undefined : cssVarsRef,\n      themeClass: themeClassHandle?.themeClass,\n      onRender: themeClassHandle?.onRender\n    }\n  },\n  render() {\n    const { mergedClsPrefix, mergedTheme, onRender } = this\n    onRender?.()\n    return h(\n      'div',\n      {\n        class: [`${mergedClsPrefix}-log`, this.themeClass],\n        style: [\n          {\n            lineHeight: this.lineHeight,\n            height: this.styleHeight\n          },\n          this.cssVars\n        ],\n        onWheelPassive: this.handleWheel\n      },\n      [\n        <NScrollbar\n          ref=\"scrollbarRef\"\n          theme={mergedTheme.peers.Scrollbar}\n          themeOverrides={mergedTheme.peerOverrides.Scrollbar}\n          onScroll={this.handleScroll}\n        >\n          {{\n            default: () => (\n              <NCode\n                internalNoHighlight\n                internalFontSize={this.fontSize}\n                theme={mergedTheme.peers.Code}\n                themeOverrides={mergedTheme.peerOverrides.Code}\n              >\n                {{\n                  default: () =>\n                    this.mergedLines.map((line, index) => {\n                      return <NLogLine key={index} line={line} />\n                    })\n                }}\n              </NCode>\n            )\n          }}\n        </NScrollbar>,\n        <Transition name=\"fade-in-scale-up-transition\">\n          {{\n            default: () =>\n              this.loading ? (\n                <NLogLoader\n                  clsPrefix={mergedClsPrefix}\n                  spinProps={this.spinProps}\n                />\n              ) : null\n          }}\n        </Transition>\n      ]\n    )\n  }\n})\n"
  },
  {
    "path": "src/log/src/LogLine.tsx",
    "content": "import {\n  computed,\n  defineComponent,\n  h,\n  inject,\n  onMounted,\n  ref,\n  toRef,\n  watch\n} from 'vue'\nimport { logInjectionKey } from './context'\n\nexport default defineComponent({\n  props: {\n    line: {\n      type: String,\n      default: ''\n    }\n  },\n  setup(props) {\n    const { trimRef, highlightRef, languageRef, mergedHljsRef }\n      = inject(logInjectionKey)!\n    const selfRef = ref<HTMLElement | null>(null)\n    const maybeTrimmedLinesRef = computed(() => {\n      return trimRef.value ? props.line.trim() : props.line\n    })\n    function setInnerHTML(): void {\n      if (selfRef.value) {\n        selfRef.value.innerHTML = generateCodeHTML(\n          languageRef.value,\n          maybeTrimmedLinesRef.value\n        )\n      }\n    }\n    function generateCodeHTML(\n      language: string | undefined,\n      code: string\n    ): string {\n      const { value: hljs } = mergedHljsRef\n      if (hljs) {\n        if (language && hljs.getLanguage(language)) {\n          return hljs.highlight(code, { language }).value\n        }\n      }\n      return code\n    }\n    onMounted(() => {\n      if (highlightRef.value) {\n        setInnerHTML()\n      }\n    })\n    watch(toRef(props, 'line'), () => {\n      if (highlightRef.value) {\n        setInnerHTML()\n      }\n    })\n    return {\n      highlight: highlightRef,\n      selfRef,\n      maybeTrimmedLines: maybeTrimmedLinesRef\n    }\n  },\n  render() {\n    const { highlight, maybeTrimmedLines } = this\n    return <pre ref=\"selfRef\">{highlight ? null : maybeTrimmedLines}</pre>\n  }\n})\n"
  },
  {
    "path": "src/log/src/LogLoader.tsx",
    "content": "import type { PropType } from 'vue'\nimport type { LogSpinProps } from './public-types'\nimport { defineComponent, h } from 'vue'\nimport { NBaseLoading } from '../../_internal'\nimport { useLocale } from '../../_mixins'\n\nexport default defineComponent({\n  name: 'LogLoader',\n  props: {\n    clsPrefix: {\n      type: String,\n      required: true\n    },\n    spinProps: Object as PropType<LogSpinProps>\n  },\n  setup() {\n    return {\n      locale: useLocale('Log').localeRef\n    }\n  },\n  render() {\n    const { clsPrefix } = this\n    return (\n      <div class={`${clsPrefix}-log-loader`}>\n        <NBaseLoading\n          clsPrefix={clsPrefix}\n          strokeWidth={24}\n          scale={0.85}\n          {...this.spinProps}\n        />\n        <span class={`${clsPrefix}-log-loader__content`}>\n          {this.locale.loading}\n        </span>\n      </div>\n    )\n  }\n})\n"
  },
  {
    "path": "src/log/src/context.ts",
    "content": "import type { LogInjection } from './Log'\nimport { createInjectionKey } from '../../_utils'\n\nexport const logInjectionKey = createInjectionKey<LogInjection>('n-log')\n"
  },
  {
    "path": "src/log/src/public-types.ts",
    "content": "import type { SharedSpinProps } from '../../_internal'\n\nexport type LogSpinProps = SharedSpinProps\n"
  },
  {
    "path": "src/log/src/styles/index.cssr.ts",
    "content": "import { fadeInScaleUpTransition } from '../../../_styles/transitions/fade-in-scale-up.cssr'\nimport { c, cB, cE } from '../../../_utils/cssr'\n\n// vars:\n// --n-bezier\n// --n-loading-color\n// --n-loader-border\n// --n-loader-color\n// --n-loader-text-color\n// --n-loader-font-size\n// --n-loading-color\nexport default cB('log', `\n  position: relative;\n  box-sizing: border-box;\n  transition: border-color .3s var(--n-bezier);\n`, [\n  c('pre', `\n    white-space: pre-wrap;\n    word-break: break-word;\n    margin: 0;\n  `),\n  cB('log-loader', `\n    transition:\n      color .3s var(--n-bezier),\n      background-color .3s var(--n-bezier),\n      border-color .3s var(--n-bezier);\n    box-sizing: border-box;\n    position: absolute;\n    right: 16px;\n    top: 8px;\n    height: 34px;\n    border-radius: 17px;\n    line-height: 34px;\n    white-space: nowrap;\n    overflow: hidden;\n    border: var(--n-loader-border);\n    color: var(--n-loader-text-color);\n    background-color: var(--n-loader-color);\n    font-size: var(--n-loader-font-size);\n  `, [\n    fadeInScaleUpTransition(),\n    cE('content', `\n      display: inline-block;\n      vertical-align: bottom;\n      line-height: 34px;\n      padding-left: 40px;\n      padding-right: 20px;\n      white-space: nowrap;\n    `),\n    cB('base-loading', `\n      color: var(--n-loading-color);\n      position: absolute;\n      left: 12px;\n      top: calc(50% - 10px);\n      font-size: 20px;\n      width: 20px;\n      height: 20px;\n      display: inline-block;\n    `)\n  ])\n])\n"
  },
  {
    "path": "src/log/styles/dark.ts",
    "content": "import type { LogTheme } from './light'\nimport { scrollbarDark } from '../../_internal/scrollbar/styles'\nimport { commonDark } from '../../_styles/common'\nimport { codeDark } from '../../code/styles'\n\nconst logDark: LogTheme = {\n  name: 'Log',\n  common: commonDark,\n  peers: {\n    Scrollbar: scrollbarDark,\n    Code: codeDark\n  },\n  self(vars) {\n    const { textColor2, inputColor, fontSize, primaryColor } = vars\n    return {\n      loaderFontSize: fontSize,\n      loaderTextColor: textColor2,\n      loaderColor: inputColor,\n      loaderBorder: '1px solid #0000',\n      loadingColor: primaryColor\n    }\n  }\n}\n\nexport default logDark\n"
  },
  {
    "path": "src/log/styles/index.ts",
    "content": "export { default as logDark } from './dark'\nexport { default as logLight } from './light'\nexport type { LogTheme, LogThemeVars } from './light'\n"
  },
  {
    "path": "src/log/styles/light.ts",
    "content": "import type { ThemeCommonVars } from '../../_styles/common'\nimport { scrollbarLight } from '../../_internal/scrollbar/styles'\nimport { createTheme } from '../../_mixins'\nimport { commonLight } from '../../_styles/common'\nimport { codeLight } from '../../code/styles'\n\nfunction self(vars: ThemeCommonVars) {\n  const { textColor2, modalColor, borderColor, fontSize, primaryColor } = vars\n  return {\n    loaderFontSize: fontSize,\n    loaderTextColor: textColor2,\n    loaderColor: modalColor,\n    loaderBorder: `1px solid ${borderColor}`,\n    loadingColor: primaryColor\n  }\n}\n\nexport type LogThemeVars = ReturnType<typeof self>\n\nconst logLight = createTheme({\n  name: 'Log',\n  common: commonLight,\n  peers: {\n    Scrollbar: scrollbarLight,\n    Code: codeLight\n  },\n  self\n})\n\nexport default logLight\nexport type LogTheme = typeof logLight\n"
  },
  {
    "path": "src/log/tests/Log.spec.tsx",
    "content": "import type { LogInst } from '../index'\nimport { mount } from '@vue/test-utils'\nimport { defineComponent, h, nextTick, ref, watch } from 'vue'\nimport { NLog } from '../index'\n\ndescribe('n-log', () => {\n  it('should warn with language setted & no hljs is set', () => {\n    const spy = vi.spyOn(console, 'error').mockImplementation(() => {})\n    mount(NLog)\n    expect(spy).not.toHaveBeenCalled()\n    mount(NLog, {\n      props: {\n        language: 'kirby'\n      }\n    })\n    expect(spy).toHaveBeenCalled()\n  })\n\n  it('should work with `font-size` prop', async () => {\n    const fontSize = 20\n    const wrapper = mount(NLog, { props: { fontSize } })\n\n    expect(wrapper.find('.n-code').attributes('style')).toContain(\n      `--n-font-size: ${fontSize}px`\n    )\n    wrapper.unmount()\n  })\n\n  it('should work with `line-height` prop', async () => {\n    const lineHeight = 20\n    const wrapper = mount(NLog, { props: { lineHeight } })\n\n    expect(wrapper.find('.n-log').attributes('style')).toContain(\n      `line-height: ${lineHeight}`\n    )\n    wrapper.unmount()\n  })\n\n  it('should work with `lines` `log` prop', async () => {\n    const wrapper = mount(NLog, { props: { lines: ['test1', 'test2'] } })\n    expect(wrapper.find('.n-code').element.children.length).toBe(2)\n    expect(wrapper.find('.n-code').element.children[0].textContent).toBe(\n      'test1'\n    )\n    expect(wrapper.find('.n-code').element.children[1].textContent).toBe(\n      'test2'\n    )\n\n    await wrapper.setProps({ log: 'test3' })\n    expect(wrapper.find('.n-code').element.children.length).toBe(1)\n    expect(wrapper.find('.n-code').element.children[0].textContent).toBe(\n      'test3'\n    )\n    wrapper.unmount()\n  })\n\n  it('should work with `loading` prop', async () => {\n    const wrapper = mount(NLog)\n    expect(wrapper.find('.n-log-loader').exists()).toBe(false)\n\n    await wrapper.setProps({ loading: true })\n    expect(wrapper.find('.n-log-loader').exists()).toBe(true)\n    wrapper.unmount()\n  })\n\n  it('should work with `rows` prop', async () => {\n    const lineHeight = 20\n    const fontSize = 10\n    ;([5, 6, 7, 8] as const).forEach((rows) => {\n      const wrapper = mount(NLog, { props: { lineHeight, fontSize, rows } })\n      expect(wrapper.find('.n-log').attributes('style')).toContain(\n        `height: calc(${Math.floor(fontSize * lineHeight) * rows}px)`\n      )\n      wrapper.unmount()\n    })\n  })\n\n  it('should work with `trim` prop', async () => {\n    const wrapper = mount(NLog, {\n      props: { log: ' test1     ' }\n    })\n    expect(wrapper.find('pre').element.innerHTML).toBe(' test1     ')\n\n    await wrapper.setProps({ trim: true, log: ' test2     ' })\n    expect(wrapper.find('pre').element.innerHTML).toBe('test2')\n    wrapper.unmount()\n  })\n\n  it('should work with `scrollTo` `on-require-more` `on-reach-top` `on-reach-bottom` prop', async () => {\n    const lines = ['test1', 'test2', 'test3', 'test4', 'test5', 'test6']\n    const onRequireMore = vi.fn()\n    const onReachTop = vi.fn()\n    const onReachBottom = vi.fn()\n    const wrapper = mount(\n      defineComponent({\n        setup() {\n          const logInstRef = ref<LogInst | null>(null)\n          watch(logInstRef, (value) => {\n            if (value) {\n              value.scrollTo({ top: 0 })\n              value.scrollTo({ top: 1 })\n              value.scrollTo({ top: 999 })\n            }\n          })\n\n          return () =>\n            h(NLog, {\n              ref: logInstRef,\n              lines,\n              rows: 4,\n              onRequireMore,\n              onReachTop,\n              onReachBottom\n            })\n        }\n      }),\n      {\n        attachTo: document.body\n      }\n    )\n    await nextTick()\n    // https://github.com/jsdom/jsdom/issues/1422\n    wrapper\n      .find('.n-scrollbar-container')\n      .element\n      .dispatchEvent(new Event('scroll'))\n    expect(onRequireMore).toHaveBeenCalled()\n    expect(onReachTop).toHaveBeenCalled()\n    expect(onReachBottom).toHaveBeenCalled()\n    wrapper.unmount()\n  })\n})\n"
  },
  {
    "path": "src/log/tests/server.spec.tsx",
    "content": "import { setup } from '@css-render/vue3-ssr'\nimport { renderToString } from '@vue/server-renderer'\n/**\n * @vitest-environment node\n */\nimport { createSSRApp, h } from 'vue'\nimport { NLog } from '../..'\n\ndescribe('server side rendering', () => {\n  it('works', async () => {\n    const app = createSSRApp(() => <NLog />)\n    setup(app)\n    try {\n      await renderToString(app)\n    }\n    catch (e) {\n      expect(e).not.toBeTruthy()\n    }\n  })\n})\n"
  },
  {
    "path": "src/marquee/demos/enUS/auto-fill.demo.vue",
    "content": "<markdown>\n# Auto fill\n\nUse `auto-fill` prop to fill all the blank space that left.\n</markdown>\n\n<template>\n  <n-marquee auto-fill>\n    <n-image\n      width=\"80\"\n      height=\"80\"\n      src=\"https://07akioni.oss-cn-beijing.aliyuncs.com/07akioni.jpeg\"\n      style=\"margin-right: 24px\"\n    />\n  </n-marquee>\n</template>\n"
  },
  {
    "path": "src/marquee/demos/enUS/basic.demo.vue",
    "content": "<markdown>\n# Basic\n\nPut text into marquee:\n</markdown>\n\n<template>\n  <n-marquee>\n    <div style=\"margin-right: 64px\">\n      In 2020 Noel returned to the legendary Rockfield Studios in Wales for the\n      first time since the band recorded the album, looking back at his memories\n      and reflecting on the album’s legacy.\n    </div>\n  </n-marquee>\n</template>\n"
  },
  {
    "path": "src/marquee/demos/enUS/image.demo.vue",
    "content": "<markdown>\n# Image\n\nYou can put any content inside marquee.\n</markdown>\n\n<template>\n  <n-marquee>\n    <n-image\n      width=\"80\"\n      height=\"80\"\n      src=\"https://07akioni.oss-cn-beijing.aliyuncs.com/07akioni.jpeg\"\n      style=\"margin-right: 24px\"\n    />\n  </n-marquee>\n</template>\n"
  },
  {
    "path": "src/marquee/demos/enUS/index.demo-entry.md",
    "content": "# Marquee\n\nA trivia: There's a deprecated HTML Element called `marquee`.\n\nAvailable since `2.40.2`.\n\n## Demos\n\n```demo\nbasic.vue\nimage.vue\nauto-fill.vue\n```\n\n## API\n\n### Marquee Props\n\n| Name | Type | Default | Description | Version |\n| --- | --- | --- | --- | --- |\n| auto-fill | `boolean` | `false` | Whether to fill the blank of the container using its content repeatly. | 2.40.2 |\n| speed | `number` | `48` | The speed calculated as pixels/second. | 2.40.2 |\n\n### Marquee Slots\n\n| Name    | Parameters | Description | Version |\n| ------- | ---------- | ----------- | ------- |\n| default | `()`       | Content.    | 2.40.2  |\n"
  },
  {
    "path": "src/marquee/demos/zhCN/auto-fill.demo.vue",
    "content": "<markdown>\n# 自动填充\n\n使用 `auto-fill` 属性让内容铺满空白空间。\n</markdown>\n\n<template>\n  <n-marquee auto-fill>\n    <n-image\n      width=\"80\"\n      height=\"80\"\n      src=\"https://07akioni.oss-cn-beijing.aliyuncs.com/07akioni.jpeg\"\n      style=\"margin-right: 24px\"\n    />\n  </n-marquee>\n</template>\n"
  },
  {
    "path": "src/marquee/demos/zhCN/basic.demo.vue",
    "content": "<markdown>\n# 基础用法\n\n在跑马灯中输入文字：\n</markdown>\n\n<template>\n  <n-marquee>\n    谁用运气换呼吸 谁用灵魂换稻米 谁用运气换呼吸 谁用灵魂换稻米\n  </n-marquee>\n</template>\n"
  },
  {
    "path": "src/marquee/demos/zhCN/image.demo.vue",
    "content": "<markdown>\n# 图片\n\n你可以将任何内容放入跑马灯中。\n</markdown>\n\n<template>\n  <n-marquee>\n    <n-image\n      width=\"80\"\n      height=\"80\"\n      src=\"https://07akioni.oss-cn-beijing.aliyuncs.com/07akioni.jpeg\"\n      style=\"margin-right: 24px\"\n    />\n  </n-marquee>\n</template>\n"
  },
  {
    "path": "src/marquee/demos/zhCN/index.demo-entry.md",
    "content": "# 跑马灯 Marquee\n\n我有一个高中同学，当时他的口头禅是：“滚滚滚。”\n\n自 `2.40.2` 开始提供。\n\n## 演示\n\n```demo\nbasic.vue\nimage.vue\nauto-fill.vue\n```\n\n## API\n\n### Marquee Props\n\n| 名称      | 类型      | 默认值  | 说明                           | 版本   |\n| --------- | --------- | ------- | ------------------------------ | ------ |\n| auto-fill | `boolean` | `false` | 是否重复的用内容铺满容器的空白 | 2.40.2 |\n| speed     | `number`  | `48`    | 移动的速度，单位是像素每秒     | 2.40.2 |\n\n### Marquee Slots\n\n| 名称    | 参数 | 说明 | 版本   |\n| ------- | ---- | ---- | ------ |\n| default | `()` | 内容 | 2.40.2 |\n"
  },
  {
    "path": "src/marquee/index.ts",
    "content": "export { default as NMarquee } from './src/Marquee'\nexport type * from './src/public-types'\n"
  },
  {
    "path": "src/marquee/src/Marquee.tsx",
    "content": "import { repeat } from 'seemly'\nimport { computed, defineComponent, h, nextTick, ref } from 'vue'\nimport { VResizeObserver } from 'vueuc'\nimport { useConfig, useTheme } from '../../_mixins'\nimport { marqueeLight } from '../styles'\nimport { marqueeProps } from './props'\nimport style from './styles/index.cssr'\n\nexport default defineComponent({\n  name: 'Marquee',\n  props: marqueeProps,\n  setup(props) {\n    const { mergedClsPrefixRef } = useConfig(props)\n    useTheme(\n      'Marquee',\n      '-marquee',\n      style,\n      marqueeLight,\n      props,\n      mergedClsPrefixRef\n    )\n\n    const containerElRef = ref<HTMLDivElement | null>(null)\n\n    const contentWidthRef = ref(-1)\n    const containerWidthRef = ref(-1)\n\n    const playStateRef = ref<'paused' | 'running'>('running')\n\n    const repeatCountInOneGroupRef = computed(() => {\n      if (!props.autoFill)\n        return 1\n      const { value: contentWidth } = contentWidthRef\n      const { value: containerWidth } = containerWidthRef\n      if (contentWidth === -1 || containerWidth === -1)\n        return 1\n      return Math.ceil(containerWidthRef.value / contentWidth)\n    })\n\n    const durationRef = computed(() => {\n      const { value: contentWidth } = contentWidthRef\n      if (contentWidth === -1)\n        return 0\n      return (contentWidth * repeatCountInOneGroupRef.value) / props.speed\n    })\n\n    const animationCssVarsRef = computed(() => {\n      return {\n        '--n-play': playStateRef.value,\n        '--n-direction': 'normal',\n        '--n-duration': `${durationRef.value}s`,\n        '--n-delay': '0s',\n        '--n-iteration-count': 'infinite',\n        '--n-min-width': 'auto'\n      }\n    })\n\n    function resetScrollState() {\n      playStateRef.value = 'paused'\n      nextTick().then(() => {\n        void containerElRef.value?.offsetTop\n        playStateRef.value = 'running'\n      })\n    }\n\n    function handleContainerResize(entry: ResizeObserverEntry) {\n      containerWidthRef.value = entry.contentRect.width\n    }\n\n    function handleContentResize(entry: ResizeObserverEntry) {\n      contentWidthRef.value = entry.contentRect.width\n    }\n\n    function handleAnimationIteration() {\n      resetScrollState()\n    }\n\n    return {\n      mergedClsPrefix: mergedClsPrefixRef,\n      animationCssVars: animationCssVarsRef,\n      containerElRef,\n      repeatCountInOneGroup: repeatCountInOneGroupRef,\n      handleContainerResize,\n      handleContentResize,\n      handleAnimationIteration\n    }\n  },\n  render() {\n    const {\n      $slots,\n      mergedClsPrefix,\n      animationCssVars,\n      repeatCountInOneGroup,\n      handleAnimationIteration\n    } = this\n    const originalNode = (\n      <VResizeObserver onResize={this.handleContentResize}>\n        {{\n          default: () => (\n            <div\n              class={`${mergedClsPrefix}-marquee__item ${mergedClsPrefix}-marquee__original-item`}\n            >\n              {$slots}\n            </div>\n          )\n        }}\n      </VResizeObserver>\n    )\n    const mirrorNode = (\n      <div class={`${mergedClsPrefix}-marquee__item`}>{$slots}</div>\n    )\n    if (this.autoFill) {\n      return (\n        <VResizeObserver onResize={this.handleContainerResize}>\n          {{\n            default: () => (\n              <div\n                class={`${mergedClsPrefix}-marquee ${mergedClsPrefix}-marquee--auto-fill`}\n                ref=\"containerElRef\"\n                style={animationCssVars}\n              >\n                <div\n                  class={`${mergedClsPrefix}-marquee__group`}\n                  onAnimationiteration={handleAnimationIteration}\n                >\n                  {originalNode}\n                  {repeat(repeatCountInOneGroup - 1, mirrorNode)}\n                </div>\n                <div class={`${mergedClsPrefix}-marquee__group`}>\n                  {repeat(repeatCountInOneGroup, mirrorNode)}\n                </div>\n              </div>\n            )\n          }}\n        </VResizeObserver>\n      )\n    }\n    else {\n      return (\n        <div\n          class={[`${mergedClsPrefix}-marquee`]}\n          ref=\"containerElRef\"\n          style={animationCssVars}\n        >\n          <div\n            class={`${mergedClsPrefix}-marquee__group`}\n            onAnimationiteration={handleAnimationIteration}\n          >\n            {originalNode}\n          </div>\n          <div class={`${mergedClsPrefix}-marquee__group`}>{mirrorNode}</div>\n        </div>\n      )\n    }\n  }\n})\n"
  },
  {
    "path": "src/marquee/src/props.ts",
    "content": "import type { ThemeProps } from '../../_mixins'\nimport type { ExtractPublicPropTypes } from '../../_utils'\nimport type { MarqueeTheme } from '../styles'\nimport { useTheme } from '../../_mixins'\n\nexport const marqueeProps = {\n  ...(useTheme.props as ThemeProps<MarqueeTheme>),\n  autoFill: Boolean,\n  speed: {\n    type: Number,\n    default: 48\n  }\n}\n\nexport type MarqueeProps = ExtractPublicPropTypes<typeof marqueeProps>\n"
  },
  {
    "path": "src/marquee/src/public-types.ts",
    "content": "export type { MarqueeProps } from './props'\n"
  },
  {
    "path": "src/marquee/src/styles/index.cssr.ts",
    "content": "import { c, cB, cE, cNotM } from '../../../_utils/cssr'\n\n// vars:\n// --n-play\n// --n-direction\n// --n-duration\n// --n-delay\n// --n-iteration-count\n// --n-min-width\nexport default c([\n  cB('marquee', `\n    overflow: hidden;\n    display: flex;\n  `, [\n    cE('group', `\n      flex: 0 0 auto;\n      min-width: var(--n-min-width);\n      z-index: 1;\n      display: flex;\n      flex-direction: row;\n      align-items: center;\n      animation: n-marquee var(--n-duration) linear var(--n-delay) var(--n-iteration-count);\n      animation-play-state: var(--n-play);\n      animation-delay: var(--n-delay);\n      animation-direction: var(--n-direction);\n    `),\n    cNotM('auto-fill', [\n      cE('group', `min-width: 100%;`),\n      cE('item', `min-width: 100%;`)\n    ])\n  ]),\n  c('@keyframes n-marquee', {\n    from: {\n      transform: 'translateX(0)'\n    },\n    to: {\n      transform: 'translateX(-100%)'\n    }\n  })\n])\n"
  },
  {
    "path": "src/marquee/styles/dark.ts",
    "content": "import type { MarqueeTheme } from './light'\nimport { commonDark } from '../../_styles/common'\nimport { self } from './light'\n\nconst marqueeDark: MarqueeTheme = {\n  name: 'Marquee',\n  common: commonDark,\n  self\n}\n\nexport default marqueeDark\n"
  },
  {
    "path": "src/marquee/styles/index.ts",
    "content": "export { default as marqueeDark } from './dark'\nexport { default as marqueeLight } from './light'\nexport type { MarqueeTheme, MarqueeThemeVars } from './light'\n"
  },
  {
    "path": "src/marquee/styles/light.ts",
    "content": "import type { Theme } from '../../_mixins'\nimport { commonLight } from '../../_styles/common'\n\nexport function self() {\n  return {}\n}\n\nexport type MarqueeThemeVars = ReturnType<typeof self>\n\nconst marqueeLight: Theme<'Marquee', MarqueeThemeVars> = {\n  name: 'Marquee',\n  common: commonLight,\n  self\n}\n\nexport default marqueeLight\nexport type MarqueeTheme = typeof marqueeLight\n"
  },
  {
    "path": "src/marquee/tests/Marquee.spec.ts",
    "content": "import { mount } from '@vue/test-utils'\nimport { NMarquee } from '../index'\n\ndescribe('n-marquee', () => {\n  it('should work with import on demand', () => {\n    mount(NMarquee)\n  })\n})\n"
  },
  {
    "path": "src/marquee/tests/server.spec.tsx",
    "content": "import { setup } from '@css-render/vue3-ssr'\nimport { renderToString } from '@vue/server-renderer'\n/**\n * @vitest-environment node\n */\nimport { createSSRApp, h } from 'vue'\nimport { NEmpty } from '../..'\n\ndescribe('server side rendering', () => {\n  it('works', async () => {\n    const app = createSSRApp(() => <NEmpty />)\n    setup(app)\n    try {\n      await renderToString(app)\n    }\n    catch (e) {\n      expect(e).not.toBeTruthy()\n    }\n  })\n})\n"
  },
  {
    "path": "src/mention/demos/enUS/async.demo.vue",
    "content": "<markdown>\n# Load remote options\n\nLoad options asynchronously.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { MentionOption } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst options = ref<MentionOption[]>([])\nconst loading = ref(false)\nlet searchTimerId: number | null = null\n\nfunction handleSearch(pattern: string, prefix: string) {\n  if (searchTimerId !== null)\n    clearTimeout(searchTimerId)\n  console.log(pattern, prefix)\n  loading.value = true\n  searchTimerId = window.setTimeout(() => {\n    options.value = ['We', 'all', 'live', 'in', 'a', 'yellow', 'submarine'].map(\n      v => ({\n        label: pattern + v,\n        value: pattern + v\n      })\n    )\n    loading.value = false\n  }, 1500)\n}\n</script>\n\n<template>\n  <n-mention\n    :options=\"options\"\n    default-value=\"@\"\n    :loading=\"loading\"\n    @search=\"handleSearch\"\n  />\n</template>\n"
  },
  {
    "path": "src/mention/demos/enUS/autosize.demo.vue",
    "content": "<markdown>\n# Autosize\n</markdown>\n\n<script lang=\"ts\" setup>\nconst options = [\n  {\n    label: '07akioni',\n    value: '07akioni'\n  },\n  {\n    label: 'star-kirby',\n    value: 'star-kirby'\n  },\n  {\n    label: 'Guandong-Road',\n    value: 'Guandong-Road'\n  },\n  {\n    label: 'No.5-Yiheyuan-Road',\n    value: 'No.5-Yiheyuan-Road'\n  }\n]\n</script>\n\n<template>\n  <n-mention type=\"textarea\" :options=\"options\" autosize />\n</template>\n"
  },
  {
    "path": "src/mention/demos/enUS/basic.demo.vue",
    "content": "<markdown>\n# Basic usage\n\nIf `label` is a render function, the `value` property will be used for matching.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { MentionOption } from 'naive-ui'\nimport type { VNodeChild } from 'vue'\nimport { TelescopeOutline } from '@vicons/ionicons5'\nimport { NIcon } from 'naive-ui'\nimport { h } from 'vue'\n\nconst options = [\n  {\n    label: '07akioni',\n    value: '07akioni'\n  },\n  {\n    label: 'star-kirby',\n    value: 'star-kirby'\n  },\n  {\n    label: 'Guandong-Road',\n    value: 'Guandong-Road'\n  },\n  {\n    label: (option: MentionOption): VNodeChild =>\n      h('span', { style: 'display: flex; align-items: center;' }, [\n        h(NIcon, {\n          style: 'margin-right: 6px',\n          size: 18,\n          component: TelescopeOutline\n        }),\n        option.value\n      ]),\n    value: 'No.5-Yiheyuan-Road'\n  }\n]\n</script>\n\n<template>\n  <n-mention :options=\"options\" default-value=\"@\" />\n</template>\n"
  },
  {
    "path": "src/mention/demos/enUS/custom-prefix.demo.vue",
    "content": "<markdown>\n# Custom trigger prefix\n\nUse `prefix` to set the trigger character(s).\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { MentionOption } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst atOptions = [\n  {\n    label: '07akioni',\n    value: '07akioni'\n  },\n  {\n    label: 'star-kirby',\n    value: 'star-kirby'\n  },\n  {\n    label: 'Guandong-Road',\n    value: 'Guandong-Road'\n  },\n  {\n    label: 'No.5-Yiheyuan-Road',\n    value: 'No.5-Yiheyuan-Road'\n  }\n]\n\nconst sharpOptions = [\n  {\n    label: 'We',\n    value: 'We'\n  },\n  {\n    label: 'all',\n    value: 'all'\n  },\n  {\n    label: 'live',\n    value: 'live'\n  },\n  {\n    label: 'in',\n    value: 'in'\n  },\n  {\n    label: 'a',\n    value: 'a'\n  },\n  {\n    label: 'yellow',\n    value: 'yellow'\n  },\n  {\n    label: 'submarine',\n    value: 'submarine'\n  }\n]\n\nconst options = ref<MentionOption[]>([])\n\nfunction handleSearch(_: string, prefix: string) {\n  if (prefix === '@') {\n    options.value = atOptions\n  }\n  else {\n    options.value = sharpOptions\n  }\n}\n</script>\n\n<template>\n  <n-mention :options=\"options\" :prefix=\"['@', '#']\" @search=\"handleSearch\" />\n</template>\n"
  },
  {
    "path": "src/mention/demos/enUS/form.demo.vue",
    "content": "<markdown>\n# Work with form\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { FormInst } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst formInstRef = ref<FormInst | null>(null)\nconst formModel = ref({\n  cool: '',\n  veryCool: ''\n})\n\nconst rules = {\n  cool: {\n    trigger: ['input', 'blur'],\n    required: true,\n    message: 'Cool is required'\n  },\n  veryCool: {\n    trigger: ['input', 'blur'],\n    validator() {\n      if (!formModel.value.veryCool.includes('@07akioni')) {\n        return new Error('07akioni should be very cool!')\n      }\n    }\n  }\n}\n\nconst options = [\n  {\n    label: '07akioni',\n    value: '07akioni'\n  },\n  {\n    label: 'star-kirby',\n    value: 'star-kirby'\n  }\n]\n\nfunction handleButtonClick() {\n  formInstRef.value?.validate()\n}\n</script>\n\n<template>\n  <n-space vertical>\n    <n-form ref=\"formInstRef\" :model=\"formModel\" :rules=\"rules\">\n      <n-form-item label=\"Cool\" path=\"cool\">\n        <n-mention v-model:value=\"formModel.cool\" :options=\"options\" />\n      </n-form-item>\n      <n-form-item label=\"Very Cool\" path=\"veryCool\">\n        <n-mention\n          v-model:value=\"formModel.veryCool\"\n          type=\"textarea\"\n          :options=\"options\"\n        />\n      </n-form-item>\n    </n-form>\n    <n-button @click=\"handleButtonClick\">\n      Validate\n    </n-button>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/mention/demos/enUS/index.demo-entry.md",
    "content": "# Mention\n\nA year ago, my product manager asked me if I could implement this feature. Back then, I recommended just using multiple selects as a workaround.\n\n## Demos\n\n```demo\nbasic.vue\ntextarea.vue\nasync.vue\nautosize.vue\nform.vue\nrender-label.vue\ncustom-prefix.vue\nmanual-trigger.vue\nstatus.vue\n```\n\n## API\n\n### Mention Props\n\nMention requires `v2.2.0` and above.\n\n| Name | Type | Default | Description | Version |\n| --- | --- | --- | --- | --- |\n| autosize | `boolean \\| { maxRows?: number, minRows?: number }` | `false` | Autosize. |  |\n| options | `MentionOption[]` | `[]` | Mention options list. |  |\n| type | `'text' \\| 'textarea'` | `'text'` | Input type. |  |\n| separator | `string` | `' '` | Character to split mentions. The string length must be exactly 1. |  |\n| bordered | `boolean` | `true` | Whether to display the border of the input element. |  |\n| disabled | `boolean` | `false` | Whether to disable the input element. |  |\n| default-value | `string` | `''` | Default value when the value is not manually set. |  |\n| filter | `(pattern: string, option: MentionOption) => boolean` | Default filter method | Method to filter options corresponding to `pattern`. | 2.38.2 |\n| loading | `boolean` | `false` | Whether the selection panel of mentions is in a loading state. |  |\n| prefix | `string \\| string[]` | `'@'` | Prefix character(s) to trigger mentions. The string length(s) must be exactly 1. |  |\n| placeholder | `string` | `''` | Placeholder. |  |\n| placement | `'top-start' \\| 'top' \\| 'top-end' \\| 'right-start' \\| 'right' \\| 'right-end' \\| 'bottom-start' \\| 'bottom' \\| 'bottom-end' \\| 'left-start' \\| 'left' \\| 'left-end'` | `'bottom-start'` | Selection panel's placement . | 2.25.0 |\n| render-label | `(option: MentionOption) => VNodeChild` | `undefined` | Options' labels render function. |  |\n| scrollbar-props | `ScrollbarProps` | `undefined` | See [Scrollbar props](scrollbar#Scrollbar-Props) | 2.44.0 |\n| size | `'small' \\| 'medium' \\| 'large'` | `'medium'` | Input size. |  |\n| status | `'success' \\| 'warning' \\| 'error'` | `undefined` | Validation status. | 2.27.0 |\n| to | `string \\| HTMLElement \\| false` | `body` | Container node of the menu. `false` will keep it not detached. |  |\n| value | `string \\| null` | `undefined` | Manually set input value. |  |\n| on-update:show | `(show: boolean) => void` | `undefined` | Callback when the selection panel of mentions is shown or hidden. | 2.34.0 |\n| on-update:value | `(value: string) => void` | `undefined` | Triggered when the input box value is updated. |  |\n| on-select | `(option: MentionOption, prefix: string) => void` | `undefined` | Triggered when the input box is selected. |  |\n| on-focus | `(e: FocusEvent) => void` | `undefined` | Triggered when the input box is focussed on. |  |\n| on-search | `(pattern: string, prefix: string) => void` | `undefined` | Triggered when searching in the input box. |  |\n| on-blur | `(e: FocusEvent) => void` | `undefined` | Triggered when the input box loses focus. |  |\n\n### MentionOption Properties\n\n| Name | Type | Description |\n| --- | --- | --- |\n| class | `string` | Option class property. |\n| disabled | `boolean` | Option disabled state. |\n| label | `string \\| (option: MentionOption) => VNodeChild` | Option label. |\n| render | `(option: MentionOption) => VNodeChild` | Support custom options via `render` rendering function. |\n| style | `string` | Option style property. |\n| value | `string` | Option value. Must be unique. |\n\n### Mention Methods\n\n| Name  | Type         | Description                      |\n| ----- | ------------ | -------------------------------- |\n| focus | `() => void` | Manually focus on the component. |\n| blur  | `() => void` | Manually blur the component.     |\n\n### Mention Slots\n\n| Name  | Parameters | Description                 |\n| ----- | ---------- | --------------------------- |\n| empty | `()`       | Slot when menu has no data. |\n"
  },
  {
    "path": "src/mention/demos/enUS/manual-trigger.demo.vue",
    "content": "<markdown>\n# Manually trigger focus and blur\n\nYou may want to trigger `focus` and `blur` manually?\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { MentionInst, MentionOption } from 'naive-ui'\nimport type { VNodeChild } from 'vue'\nimport { HomeOutline as HomeIcon } from '@vicons/ionicons5'\nimport { NIcon } from 'naive-ui'\nimport { h, ref } from 'vue'\n\nconst myMention = ref<MentionInst | null>(null)\n\nfunction triggerBlur() {\n  myMention.value?.blur()\n}\n\nfunction triggerFocus() {\n  myMention.value?.focus()\n  setTimeout(triggerBlur, 1000)\n}\n\nconst options = [\n  {\n    label: '07akioni',\n    value: '07akioni'\n  },\n  {\n    label: 'star-kirby',\n    value: 'star-kirby'\n  },\n  {\n    label: 'Guandong-Road',\n    value: 'Guandong-Road'\n  },\n  {\n    label: (option: MentionOption): VNodeChild =>\n      h('span', { style: 'display: flex; align-items: center;' }, [\n        h(\n          NIcon,\n          { style: 'margin-right: 5px' },\n          { default: () => h(HomeIcon) }\n        ),\n        option.value\n      ]),\n    value: 'No.5-Yiheyuan-Road'\n  }\n]\n</script>\n\n<template>\n  <n-space>\n    <n-mention ref=\"myMention\" :options=\"options\" default-value=\"@\" />\n    <n-button @click=\"triggerFocus\">\n      Click to focus, and will blur after one second\n    </n-button>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/mention/demos/enUS/render-label.demo.vue",
    "content": "<markdown>\n# Render label\n\nIf the `option.label` property is not a string, the `option.value` property will be used for matching by default.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { MentionOption } from 'naive-ui'\nimport type { VNodeChild } from 'vue'\nimport { NAvatar } from 'naive-ui'\nimport { h } from 'vue'\n\nconst options = [\n  {\n    label: '07akioni',\n    value: '07akioni'\n  },\n  {\n    label: 'star-kirby',\n    value: 'star-kirby'\n  },\n  {\n    label: 'amadeus711',\n    value: 'amadeus711'\n  }\n]\n\nfunction renderLabel(option: MentionOption): VNodeChild {\n  return h('div', { style: 'display: flex; align-items: center;' }, [\n    h(NAvatar, {\n      style: 'margin-right: 8px;',\n      size: 24,\n      round: true,\n      src: 'https://07akioni.oss-cn-beijing.aliyuncs.com/07akioni.jpeg'\n    }),\n    option.value\n  ])\n}\n</script>\n\n<template>\n  <n-mention :options=\"options\" :render-label=\"renderLabel\" />\n</template>\n"
  },
  {
    "path": "src/mention/demos/enUS/status.demo.vue",
    "content": "<markdown>\n# Validation status\n\nValidation status can be applied outside form.\n</markdown>\n\n<template>\n  <n-space vertical>\n    <n-mention status=\"warning\" placeholder=\"\" />\n    <n-mention status=\"error\" placeholder=\"\" />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/mention/demos/enUS/textarea.demo.vue",
    "content": "<markdown>\n# Textarea\n\nThe input `type` can be set to `'textarea'`.\n</markdown>\n\n<script lang=\"ts\" setup>\nconst options = [\n  {\n    label: '07akioni',\n    value: '07akioni'\n  },\n  {\n    label: 'star-kirby',\n    value: 'star-kirby'\n  },\n  {\n    label: 'Guandong-Road',\n    value: 'Guandong-Road'\n  },\n  {\n    label: 'No.5-Yiheyuan-Road',\n    value: 'No.5-Yiheyuan-Road'\n  }\n]\n</script>\n\n<template>\n  <n-mention type=\"textarea\" :options=\"options\" />\n</template>\n"
  },
  {
    "path": "src/mention/demos/zhCN/async.demo.vue",
    "content": "<markdown>\n# 远程加载\n\n异步加载选项。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { MentionOption } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst options = ref<MentionOption[]>([])\nconst loading = ref(false)\nlet searchTimerId: number | null = null\n\nfunction handleSearch(pattern: string, prefix: string) {\n  if (searchTimerId !== null)\n    clearTimeout(searchTimerId)\n  console.log(pattern, prefix)\n  loading.value = true\n  searchTimerId = window.setTimeout(() => {\n    options.value = [\n      '它烫不了你的舌',\n      '也烧不了你的口',\n      '喝醉吧',\n      '不要回头'\n    ].map(v => ({\n      label: pattern + v,\n      value: pattern + v\n    }))\n    loading.value = false\n  }, 1500)\n}\n</script>\n\n<template>\n  <n-mention\n    :options=\"options\"\n    default-value=\"@\"\n    :loading=\"loading\"\n    @search=\"handleSearch\"\n  />\n</template>\n"
  },
  {
    "path": "src/mention/demos/zhCN/autosize.demo.vue",
    "content": "<markdown>\n# 自动换行\n</markdown>\n\n<script lang=\"ts\" setup>\nconst options = [\n  {\n    label: '07akioni',\n    value: '07akioni'\n  },\n  {\n    label: 'star-kirby',\n    value: 'star-kirby'\n  },\n  {\n    label: '广东路',\n    value: '广东路'\n  },\n  {\n    label: '颐和园路5号',\n    value: '颐和园路5号'\n  }\n]\n</script>\n\n<template>\n  <n-mention type=\"textarea\" :options=\"options\" autosize />\n</template>\n"
  },
  {
    "path": "src/mention/demos/zhCN/basic.demo.vue",
    "content": "<markdown>\n# 基本用法\n\n如果 `label` 是回调函数，输入匹配则会根据 `value` 进行匹配\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { MentionOption } from 'naive-ui'\nimport type { VNodeChild } from 'vue'\nimport { TelescopeOutline } from '@vicons/ionicons5'\nimport { NIcon } from 'naive-ui'\nimport { h } from 'vue'\n\nconst options = [\n  {\n    label: '07akioni',\n    value: '07akioni'\n  },\n  {\n    label: 'star-kirby',\n    value: 'star-kirby'\n  },\n  {\n    label: '广东路',\n    value: '广东路'\n  },\n  {\n    label: (option: MentionOption): VNodeChild =>\n      h('div', { style: 'display: flex; align-items: center;' }, [\n        h(NIcon, {\n          style: 'margin-right: 6px;',\n          size: 18,\n          component: TelescopeOutline\n        }),\n        option.value\n      ]),\n    value: '颐和园路5号'\n  }\n]\n</script>\n\n<template>\n  <n-mention :options=\"options\" default-value=\"@\" />\n</template>\n"
  },
  {
    "path": "src/mention/demos/zhCN/custom-prefix.demo.vue",
    "content": "<markdown>\n# 自定义触发字符\n\n使用 `prefix` 设定触发字符。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { MentionOption } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst atOptions = [\n  {\n    label: '07akioni',\n    value: '07akioni'\n  },\n  {\n    label: 'star-kirby',\n    value: 'star-kirby'\n  },\n  {\n    label: '广东路',\n    value: '广东路'\n  },\n  {\n    label: '颐和园路5号',\n    value: '颐和园路5号'\n  }\n]\n\nconst sharpOptions = [\n  {\n    label: '它烫不了你的舌',\n    value: '它烫不了你的舌'\n  },\n  {\n    label: '也烧不了你的口',\n    value: '也烧不了你的口'\n  },\n  {\n    label: '喝醉吧',\n    value: '喝醉吧'\n  },\n  {\n    label: '不要回头',\n    value: '不要回头'\n  }\n]\n\nconst options = ref<MentionOption[]>([])\n\nfunction handleSearch(_: string, prefix: string) {\n  if (prefix === '@') {\n    options.value = atOptions\n  }\n  else {\n    options.value = sharpOptions\n  }\n}\n</script>\n\n<template>\n  <n-mention :options=\"options\" :prefix=\"['@', '#']\" @search=\"handleSearch\" />\n</template>\n"
  },
  {
    "path": "src/mention/demos/zhCN/form.demo.vue",
    "content": "<markdown>\n# 配合表单\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { FormInst } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst formInstRef = ref<FormInst | null>(null)\nconst formModel = ref({\n  cool: '',\n  veryCool: ''\n})\n\nconst rules = {\n  cool: {\n    trigger: ['input', 'blur'],\n    required: true,\n    message: 'Cool is required'\n  },\n  veryCool: {\n    trigger: ['input', 'blur'],\n    validator() {\n      if (!formModel.value.veryCool.includes('@07akioni')) {\n        return new Error('07akioni should be very cool!')\n      }\n    }\n  }\n}\n\nconst options = [\n  {\n    label: '07akioni',\n    value: '07akioni'\n  },\n  {\n    label: 'star-kirby',\n    value: 'star-kirby'\n  }\n]\n\nfunction handleButtonClick() {\n  formInstRef.value?.validate()\n}\n</script>\n\n<template>\n  <n-space vertical>\n    <n-form ref=\"formInstRef\" :model=\"formModel\" :rules=\"rules\">\n      <n-form-item label=\"Cool\" path=\"cool\">\n        <n-mention v-model:value=\"formModel.cool\" :options=\"options\" />\n      </n-form-item>\n      <n-form-item label=\"Very Cool\" path=\"veryCool\">\n        <n-mention\n          v-model:value=\"formModel.veryCool\"\n          type=\"textarea\"\n          :options=\"options\"\n        />\n      </n-form-item>\n    </n-form>\n    <n-button @click=\"handleButtonClick\">\n      Validate\n    </n-button>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/mention/demos/zhCN/index.demo-entry.md",
    "content": "# 提及 Mention\n\n一年多之前产品经理问我能不能搞这个东西，当时我让他们用多选凑活一下。\n\n## 演示\n\n```demo\nbasic.vue\ntextarea.vue\nasync.vue\nautosize.vue\nform.vue\nrender-label.vue\ncustom-prefix.vue\nmanual-trigger.vue\nstatus.vue\n```\n\n## API\n\n### Mention Props\n\nMention 在 `v2.2.0` 及以后可用。\n\n| 名称 | 类型 | 默认值 | 说明 | 版本 |\n| --- | --- | --- | --- | --- |\n| autosize | `boolean \\| { maxRows?: number, minRows?: number }` | `false` | 自动换行 |  |\n| options | `MentionOption[]` | `[]` | 选项列表 |  |\n| type | `'text' \\| 'textarea'` | `'text'` | 输入框类型 |  |\n| separator | `string` | `' '` | 切分提及使用的字符，长度必须为 1 |  |\n| bordered | `boolean` | `true` | 是否显示输入框边框 |  |\n| disabled | `boolean` | `false` | 是否设置输入框为禁用状态 |  |\n| default-value | `string` | `''` | 输入框的默认值 |  |\n| filter | `(pattern: string, option: MentionOption) => boolean` | 内置的过滤函数 | 根据 `pattern` 决定显示那些选项的过滤函数 | 2.38.2 |\n| loading | `boolean` | `false` | 选择面板是否显示加载状态 |  |\n| prefix | `string \\| string[]` | `'@'` | 触发提及的前缀，长度必须为 1 |  |\n| placeholder | `string` | `''` | 输入框的占位符 |  |\n| placement | `'top-start' \\| 'top' \\| 'top-end' \\| 'right-start' \\| 'right' \\| 'right-end' \\| 'bottom-start' \\| 'bottom' \\| 'bottom-end' \\| 'left-start' \\| 'left' \\| 'left-end'` | `'bottom-start'` | 选择面板的弹出位置. | 2.25.0 |\n| render-label | `(option: MentionOption) => VNodeChild` | `undefined` | 选项标签渲染函数 |  |\n| scrollbar-props | `ScrollbarProps` | `undefined` | 属性参考 [Scrollbar props](scrollbar#Scrollbar-Props) | 2.44.0 |\n| size | `'small' \\| 'medium' \\| 'large'` | `'medium'` | 输入框的大小 |  |\n| status | `'success' \\| 'warning' \\| 'error'` | `undefined` | 验证状态 | 2.27.0 |\n| to | `string \\| HTMLElement \\| false` | `body` | 菜单的容器节点，`false` 会待在原地 |  |\n| value | `string \\| null` | `undefined` | 输入框的值 |  |\n| on-update:show | `(show: boolean) => void` | `undefined` | 选择面板显示状态发生变化时触发 | 2.34.0 |\n| on-update:value | `(value: string) => void` | `undefined` | 输入框值发生更新时触发 |  |\n| on-select | `(option: MentionOption, prefix: string) => void` | `undefined` | 输入框的选中时触发 |  |\n| on-focus | `(e: FocusEvent) => void` | `undefined` | 输入框获得焦点时触发 |  |\n| on-search | `(pattern: string, prefix: string) => void` | `undefined` | 输入框搜索时触发 |  |\n| on-blur | `(e: FocusEvent) => void` | `undefined` | 输入框失去焦点时触发 |  |\n\n### MentionOption Properties\n\n| 名称 | 类型 | 说明 |\n| --- | --- | --- |\n| class | `string` | 选项的自定义类名 |\n| disabled | `boolean` | 选项是否禁用 |\n| label | `string \\| (option: MentionOption) => VNodeChild` | 选项的标签 |\n| render | `(option: MentionOption) => VNodeChild` | 支持通过 `render` 渲染函数自定义选项 |\n| style | `string` | 选项的样式 |\n| value | `string` | 在选项中应该是唯一的 |\n\n### Mention Methods\n\n| Name  | Type         | Description |\n| ----- | ------------ | ----------- |\n| focus | `() => void` | 聚焦        |\n| blur  | `() => void` | 失焦        |\n\n### Mention Slots\n\n| 名称  | 参数 | 说明                |\n| ----- | ---- | ------------------- |\n| empty | `()` | 菜单无数据时的 slot |\n"
  },
  {
    "path": "src/mention/demos/zhCN/manual-trigger.demo.vue",
    "content": "<markdown>\n# 手动 Focus & Blur\n\n可能你想要手动 `focus` 和 `blur`。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { MentionInst, MentionOption } from 'naive-ui'\nimport type { VNodeChild } from 'vue'\nimport { HomeOutline as HomeIcon } from '@vicons/ionicons5'\nimport { NIcon } from 'naive-ui'\nimport { h, ref } from 'vue'\n\nconst myMention = ref<MentionInst | null>(null)\n\nfunction triggerBlur() {\n  myMention.value?.blur()\n}\n\nfunction triggerFocus() {\n  myMention.value?.focus()\n  setTimeout(triggerBlur, 1000)\n}\n\nconst options = [\n  {\n    label: '07akioni',\n    value: '07akioni'\n  },\n  {\n    label: 'star-kirby',\n    value: 'star-kirby'\n  },\n  {\n    label: '广东路',\n    value: '广东路'\n  },\n  {\n    label: (option: MentionOption): VNodeChild =>\n      h('div', { style: 'display: flex; align-items: center;' }, [\n        h(\n          NIcon,\n          { style: 'margin-right: 5px' },\n          { default: () => h(HomeIcon) }\n        ),\n        option.value\n      ]),\n    value: '颐和园路5号'\n  }\n]\n</script>\n\n<template>\n  <n-space>\n    <n-mention ref=\"myMention\" :options=\"options\" default-value=\"@\" />\n    <n-button @click=\"triggerFocus\">\n      点击聚焦，一秒后失去焦点\n    </n-button>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/mention/demos/zhCN/render-label.demo.vue",
    "content": "<markdown>\n# 控制菜单渲染\n\n如果选项的 `label` 不是字符串，默认情况下会使用 `value` 进行匹配。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { MentionOption } from 'naive-ui'\nimport type { VNodeChild } from 'vue'\nimport { NAvatar } from 'naive-ui'\nimport { h } from 'vue'\n\nconst options = [\n  {\n    label: '07akioni',\n    value: '07akioni'\n  },\n  {\n    label: 'star-kirby',\n    value: 'star-kirby'\n  },\n  {\n    label: 'amadeus711',\n    value: 'amadeus711'\n  }\n]\n\nfunction renderLabel(option: MentionOption): VNodeChild {\n  return h('div', { style: 'display: flex; align-items: center;' }, [\n    h(NAvatar, {\n      style: 'margin-right: 8px;',\n      size: 24,\n      round: true,\n      src: 'https://07akioni.oss-cn-beijing.aliyuncs.com/07akioni.jpeg'\n    }),\n    option.value\n  ])\n}\n</script>\n\n<template>\n  <n-mention :options=\"options\" :render-label=\"renderLabel\" />\n</template>\n"
  },
  {
    "path": "src/mention/demos/zhCN/status.demo.vue",
    "content": "<markdown>\n# 验证状态\n\n输入的验证状态可以脱离表单使用。\n</markdown>\n\n<template>\n  <n-space vertical>\n    <n-mention status=\"warning\" placeholder=\"\" />\n    <n-mention status=\"error\" placeholder=\"\" />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/mention/demos/zhCN/textarea.demo.vue",
    "content": "<markdown>\n# 文本区域\n\n将 `type` 设为 `'textarea'`。\n</markdown>\n\n<script lang=\"ts\" setup>\nconst options = [\n  {\n    label: '07akioni',\n    value: '07akioni'\n  },\n  {\n    label: 'star-kirby',\n    value: 'star-kirby'\n  },\n  {\n    label: '广东路',\n    value: '广东路'\n  },\n  {\n    label: '颐和园路5号',\n    value: '颐和园路5号'\n  }\n]\n</script>\n\n<template>\n  <n-mention type=\"textarea\" :options=\"options\" />\n</template>\n"
  },
  {
    "path": "src/mention/index.ts",
    "content": "export type { MentionInst, MentionOption } from './src/interface'\nexport { mentionProps, default as NMention } from './src/Mention'\nexport type { MentionProps, MentionSlots } from './src/Mention'\nexport type * from './src/public-types'\n"
  },
  {
    "path": "src/mention/src/Mention.tsx",
    "content": "import type { TreeNode } from 'treemate'\nimport type { CSSProperties, PropType, SlotsType, VNode } from 'vue'\nimport type { FollowerInst, FollowerPlacement } from 'vueuc'\nimport type { InternalSelectMenuRef, ScrollbarProps } from '../../_internal'\nimport type { RenderLabel } from '../../_internal/select-menu/src/interface'\nimport type { ThemeProps } from '../../_mixins'\nimport type { ExtractPublicPropTypes, MaybeArray } from '../../_utils'\nimport type { FormValidationStatus } from '../../form/src/public-types'\nimport type { InputInst } from '../../input'\nimport type {\n  SelectBaseOption,\n  SelectGroupOption,\n  SelectIgnoredOption\n} from '../../select/src/interface'\nimport type { MentionTheme } from '../styles'\nimport type { MentionOption } from './interface'\nimport type { MentionSize } from './public-types'\nimport { createTreeMate } from 'treemate'\nimport { useIsMounted, useMergedState } from 'vooks'\nimport {\n  computed,\n  defineComponent,\n  h,\n  nextTick,\n  ref,\n  toRef,\n  Transition\n} from 'vue'\nimport { VBinder, VFollower, VTarget } from 'vueuc'\nimport { NInternalSelectMenu } from '../../_internal'\nimport { useConfig, useFormItem, useTheme, useThemeClass } from '../../_mixins'\nimport { call, useAdjustedTo, warn } from '../../_utils'\nimport { NInput } from '../../input'\nimport { mentionLight } from '../styles'\nimport style from './styles/index.cssr'\nimport { getRelativePosition } from './utils'\n\nexport const mentionProps = {\n  ...(useTheme.props as ThemeProps<MentionTheme>),\n  to: useAdjustedTo.propTo,\n  autosize: [Boolean, Object] as PropType<\n    boolean | { maxRows?: number, minRows?: number }\n  >,\n  options: {\n    type: Array as PropType<MentionOption[]>,\n    default: []\n  },\n  filter: {\n    type: Function as PropType<\n      (pattern: string, option: MentionOption) => boolean\n    >,\n    default: (pattern: string, option: MentionOption) => {\n      if (!pattern)\n        return true\n      if (typeof option.label === 'string') {\n        return option.label.startsWith(pattern)\n      }\n      if (typeof option.value === 'string') {\n        return option.value.startsWith(pattern)\n      }\n      return false\n    }\n  },\n  type: {\n    type: String as PropType<'text' | 'textarea'>,\n    default: 'text'\n  },\n  separator: {\n    type: String,\n    validator: (separator: string) => {\n      if (separator.length !== 1) {\n        warn('mention', '`separator`\\'s length must be 1.')\n        return false\n      }\n      return true\n    },\n    default: ' '\n  },\n  bordered: {\n    type: Boolean as PropType<boolean | undefined>,\n    default: undefined\n  },\n  disabled: Boolean,\n  value: String as PropType<string | null>,\n  defaultValue: {\n    type: String,\n    default: ''\n  },\n  loading: Boolean,\n  prefix: {\n    type: [String, Array] as PropType<string | string[]>,\n    default: '@'\n  },\n  placeholder: {\n    type: String,\n    default: ''\n  },\n  placement: {\n    type: String as PropType<FollowerPlacement>,\n    default: 'bottom-start'\n  },\n  size: String as PropType<MentionSize>,\n  renderLabel: Function as PropType<RenderLabel>,\n  status: String as PropType<FormValidationStatus>,\n  'onUpdate:show': [Array, Function] as PropType<\n    MaybeArray<(show: boolean) => void>\n  >,\n  onUpdateShow: [Array, Function] as PropType<\n    MaybeArray<(show: boolean) => void>\n  >,\n  'onUpdate:value': [Array, Function] as PropType<\n    MaybeArray<(value: string) => void>\n  >,\n  onUpdateValue: [Array, Function] as PropType<\n    MaybeArray<(value: string) => void>\n  >,\n  onSearch: Function as PropType<(pattern: string, prefix: string) => void>,\n  onSelect: Function as PropType<\n    (option: MentionOption, prefix: string) => void\n  >,\n  onFocus: Function as PropType<(e: FocusEvent) => void>,\n  onBlur: Function as PropType<(e: FocusEvent) => void>,\n  scrollbarProps: Object as PropType<ScrollbarProps>,\n  // private\n  internalDebug: Boolean\n} as const\n\nexport type MentionProps = ExtractPublicPropTypes<typeof mentionProps>\n\nexport interface MentionSlots {\n  default?: () => VNode[]\n  empty?: () => VNode[]\n}\n\nexport default defineComponent({\n  name: 'Mention',\n  props: mentionProps,\n  slots: Object as SlotsType<MentionSlots>,\n  setup(props) {\n    const {\n      namespaceRef,\n      mergedClsPrefixRef,\n      mergedBorderedRef,\n      inlineThemeDisabled,\n      mergedComponentPropsRef\n    } = useConfig(props)\n    const themeRef = useTheme(\n      'Mention',\n      '-mention',\n      style,\n      mentionLight,\n      props,\n      mergedClsPrefixRef\n    )\n    const formItem = useFormItem(props, {\n      mergedSize: (NFormItem) => {\n        const { size } = props\n        if (size)\n          return size\n        const { mergedSize: formItemSize } = NFormItem || {}\n        if (formItemSize?.value)\n          return formItemSize.value as MentionSize\n        const configSize = mergedComponentPropsRef?.value?.Mention?.size\n        if (configSize)\n          return configSize\n        return 'medium'\n      }\n    })\n    const inputInstRef = ref<InputInst | null>(null)\n    const cursorRef = ref<HTMLElement | null>(null)\n    const followerRef = ref<FollowerInst | null>(null)\n    const wrapperElRef = ref<HTMLElement | null>(null)\n    const partialPatternRef = ref<string>('')\n    let cachedPrefix: string | null = null\n    // cached pattern end is for partial pattern\n    // for example @abc|def\n    // end is after `c`\n    let cachedPartialPatternStart: number | null = null\n    let cachedPartialPatternEnd: number | null = null\n    const filteredOptionsRef = computed(() => {\n      const { value: pattern } = partialPatternRef\n      return props.options.filter(option => props.filter(pattern, option))\n    })\n    const treeMateRef = computed(() => {\n      return createTreeMate<\n        SelectBaseOption,\n        SelectGroupOption,\n        SelectIgnoredOption\n        // We need to cast filteredOptionsRef's type since the render function\n        // is not compatible\n        // MentionOption { value: string, render?: (value: string) => VNodeChild }\n        // SelectOption { value: string | number, render?: (value: string | number) => VNodeChild }\n        // The 2 types are not compatible since `render`s are not compatible\n        // However we know it works...\n      >(filteredOptionsRef.value as any, {\n        getKey: (v) => {\n          return (v as any).value\n        }\n      })\n    })\n    const selectMenuInstRef = ref<InternalSelectMenuRef | null>(null)\n    const showMenuRef = ref(false)\n    const uncontrolledValueRef = ref(props.defaultValue)\n    const controlledValueRef = toRef(props, 'value')\n    const mergedValueRef = useMergedState(\n      controlledValueRef,\n      uncontrolledValueRef\n    )\n    const cssVarsRef = computed(() => {\n      const {\n        self: { menuBoxShadow }\n      } = themeRef.value\n      return {\n        '--n-menu-box-shadow': menuBoxShadow\n      }\n    })\n    const themeClassHandle = inlineThemeDisabled\n      ? useThemeClass('mention', undefined, cssVarsRef, props)\n      : undefined\n    function doUpdateShowMenu(show: boolean): void {\n      if (props.disabled)\n        return\n      const { onUpdateShow, 'onUpdate:show': _onUpdateShow } = props\n      if (onUpdateShow)\n        call(onUpdateShow, show)\n      if (_onUpdateShow)\n        call(_onUpdateShow, show)\n      if (!show) {\n        cachedPrefix = null\n        cachedPartialPatternStart = null\n        cachedPartialPatternEnd = null\n      }\n      showMenuRef.value = show\n    }\n    function doUpdateValue(value: string): void {\n      const { onUpdateValue, 'onUpdate:value': _onUpdateValue } = props\n      const { nTriggerFormChange, nTriggerFormInput } = formItem\n      if (_onUpdateValue) {\n        call(_onUpdateValue, value)\n      }\n      if (onUpdateValue) {\n        call(onUpdateValue, value)\n      }\n      nTriggerFormInput()\n      nTriggerFormChange()\n      uncontrolledValueRef.value = value\n    }\n    function getInputEl(): HTMLInputElement | HTMLTextAreaElement {\n      return props.type === 'text'\n        ? inputInstRef.value!.inputElRef!\n        : inputInstRef.value!.textareaElRef!\n    }\n    function deriveShowMenu(): void {\n      const inputEl = getInputEl()\n      if (document.activeElement !== inputEl) {\n        doUpdateShowMenu(false)\n        return\n      }\n      const { selectionEnd } = inputEl\n      if (selectionEnd === null) {\n        doUpdateShowMenu(false)\n        return\n      }\n      const inputValue = inputEl.value\n      const { separator } = props\n      const { prefix } = props\n      const prefixArray = typeof prefix === 'string' ? [prefix] : prefix\n      for (let i = selectionEnd - 1; i >= 0; --i) {\n        const char = inputValue[i]\n        if (char === separator || char === '\\n' || char === '\\r') {\n          doUpdateShowMenu(false)\n          return\n        }\n        if (prefixArray.includes(char)) {\n          const partialPattern = inputValue.slice(i + 1, selectionEnd)\n          doUpdateShowMenu(true)\n          props.onSearch?.(partialPattern, char)\n          partialPatternRef.value = partialPattern\n          cachedPrefix = char\n          cachedPartialPatternStart = i + 1\n          cachedPartialPatternEnd = selectionEnd\n          return\n        }\n      }\n      doUpdateShowMenu(false)\n    }\n    function syncCursor(): void {\n      const { value: cursorAnchor } = cursorRef\n      if (!cursorAnchor)\n        return\n      const inputEl = getInputEl()\n      const cursorPos: {\n        left: number\n        top: number\n        height: number\n      } = getRelativePosition(inputEl)\n      const inputRect = inputEl.getBoundingClientRect()\n      const wrapperRect = wrapperElRef.value!.getBoundingClientRect()\n      cursorAnchor.style.left = `${cursorPos.left + inputRect.left - wrapperRect.left}px`\n      cursorAnchor.style.top = `${cursorPos.top + inputRect.top - wrapperRect.top}px`\n      cursorAnchor.style.height = `${cursorPos.height}px`\n    }\n    function syncPosition(): void {\n      if (!showMenuRef.value)\n        return\n      followerRef.value?.syncPosition()\n    }\n    function handleInputUpdateValue(value: string): void {\n      doUpdateValue(value)\n      // Vue update is mirco task.\n      // So DOM must have been done when sync start in marco task.\n      // I can't use nextTick(), Chrome doesn't update scrollLeft of INPUT\n      // element is immediatelly updated. The behavior is wired but that's what\n      // happens.\n      syncAfterCursorMove()\n    }\n    function syncAfterCursorMove(): void {\n      setTimeout(() => {\n        syncCursor()\n        deriveShowMenu()\n        void nextTick().then(syncPosition)\n      }, 0)\n    }\n    function handleInputKeyDown(e: KeyboardEvent): void {\n      if (e.key === 'ArrowLeft' || e.key === 'ArrowRight') {\n        if (inputInstRef.value?.isCompositing)\n          return\n        syncAfterCursorMove()\n      }\n      else if (\n        e.key === 'ArrowUp'\n        || e.key === 'ArrowDown'\n        || e.key === 'Enter'\n      ) {\n        if (inputInstRef.value?.isCompositing)\n          return\n        const { value: selectMenuInst } = selectMenuInstRef\n        if (showMenuRef.value) {\n          if (selectMenuInst) {\n            e.preventDefault()\n            if (e.key === 'ArrowUp') {\n              selectMenuInst.prev()\n            }\n            else if (e.key === 'ArrowDown') {\n              selectMenuInst.next()\n            }\n            else {\n              // Enter\n              const pendingOptionTmNode = selectMenuInst.getPendingTmNode()\n              if (pendingOptionTmNode) {\n                handleSelect(pendingOptionTmNode)\n              }\n              else {\n                doUpdateShowMenu(false)\n              }\n            }\n          }\n        }\n        else {\n          syncAfterCursorMove()\n        }\n      }\n    }\n    function handleInputFocus(e: FocusEvent): void {\n      const { onFocus } = props\n      onFocus?.(e)\n      const { nTriggerFormFocus } = formItem\n      nTriggerFormFocus()\n      syncAfterCursorMove()\n    }\n    function focus(): void {\n      inputInstRef.value?.focus()\n    }\n    function blur(): void {\n      inputInstRef.value?.blur()\n    }\n    function handleInputBlur(e: FocusEvent): void {\n      const { onBlur } = props\n      onBlur?.(e)\n      const { nTriggerFormBlur } = formItem\n      nTriggerFormBlur()\n      doUpdateShowMenu(false)\n    }\n    function handleSelect(tmNode: TreeNode<SelectBaseOption>): void {\n      if (\n        cachedPrefix === null\n        || cachedPartialPatternStart === null\n        || cachedPartialPatternEnd === null\n      ) {\n        if (__DEV__) {\n          warn(\n            'mention',\n            'Cache works unexpectly, this is probably a bug. Please create an issue.'\n          )\n        }\n        return\n      }\n      const {\n        rawNode: { value = '' }\n      } = tmNode\n      const inputEl = getInputEl()\n      const inputValue = inputEl.value\n      const { separator } = props\n      const nextEndPart = inputValue.slice(cachedPartialPatternEnd)\n      const alreadySeparated = nextEndPart.startsWith(separator)\n      const nextMiddlePart = `${value}${alreadySeparated ? '' : separator}`\n      doUpdateValue(\n        inputValue.slice(0, cachedPartialPatternStart)\n        + nextMiddlePart\n        + nextEndPart\n      )\n      props.onSelect?.(tmNode.rawNode as MentionOption, cachedPrefix)\n      const nextSelectionEnd\n        = cachedPartialPatternStart\n          + nextMiddlePart.length\n          + (alreadySeparated ? 1 : 0)\n      void nextTick().then(() => {\n        // input value is updated\n        inputEl.selectionStart = nextSelectionEnd\n        inputEl.selectionEnd = nextSelectionEnd\n        deriveShowMenu()\n      })\n    }\n    function handleInputMouseDown(): void {\n      if (!props.disabled) {\n        syncAfterCursorMove()\n      }\n    }\n    return {\n      namespace: namespaceRef,\n      mergedClsPrefix: mergedClsPrefixRef,\n      mergedBordered: mergedBorderedRef,\n      mergedSize: formItem.mergedSizeRef,\n      mergedStatus: formItem.mergedStatusRef,\n      mergedTheme: themeRef,\n      treeMate: treeMateRef,\n      selectMenuInstRef,\n      inputInstRef,\n      cursorRef,\n      followerRef,\n      wrapperElRef,\n      showMenu: showMenuRef,\n      adjustedTo: useAdjustedTo(props),\n      isMounted: useIsMounted(),\n      mergedValue: mergedValueRef,\n      handleInputFocus,\n      handleInputBlur,\n      handleInputUpdateValue,\n      handleInputKeyDown,\n      handleSelect,\n      handleInputMouseDown,\n      focus,\n      blur,\n      cssVars: inlineThemeDisabled ? undefined : cssVarsRef,\n      themeClass: themeClassHandle?.themeClass,\n      onRender: themeClassHandle?.onRender\n    }\n  },\n  render() {\n    const { mergedTheme, mergedClsPrefix, $slots } = this\n    return (\n      <div class={`${mergedClsPrefix}-mention`} ref=\"wrapperElRef\">\n        <NInput\n          status={this.mergedStatus}\n          themeOverrides={mergedTheme.peerOverrides.Input}\n          theme={mergedTheme.peers.Input}\n          size={this.mergedSize}\n          autosize={this.autosize}\n          type={this.type}\n          ref=\"inputInstRef\"\n          placeholder={this.placeholder}\n          onMousedown={this.handleInputMouseDown}\n          onUpdateValue={this.handleInputUpdateValue}\n          onKeydown={this.handleInputKeyDown}\n          onFocus={this.handleInputFocus}\n          onBlur={this.handleInputBlur}\n          bordered={this.mergedBordered}\n          disabled={this.disabled}\n          value={this.mergedValue}\n        />\n        <VBinder>\n          {{\n            default: () => [\n              <VTarget>\n                {{\n                  default: () => {\n                    const style: CSSProperties = {\n                      position: 'absolute',\n                      width: 0\n                    }\n                    if (__DEV__ && this.internalDebug) {\n                      style.width = '1px'\n                      style.background = 'red'\n                    }\n                    return <div style={style} ref=\"cursorRef\" />\n                  }\n                }}\n              </VTarget>,\n              <VFollower\n                ref=\"followerRef\"\n                placement={this.placement}\n                show={this.showMenu}\n                containerClass={this.namespace}\n                to={this.adjustedTo}\n                teleportDisabled={this.adjustedTo === useAdjustedTo.tdkey}\n              >\n                {{\n                  default: () => (\n                    <Transition\n                      name=\"fade-in-scale-up-transition\"\n                      appear={this.isMounted}\n                    >\n                      {{\n                        default: () => {\n                          const { mergedTheme, onRender } = this\n                          onRender?.()\n                          return this.showMenu ? (\n                            <NInternalSelectMenu\n                              clsPrefix={mergedClsPrefix}\n                              theme={mergedTheme.peers.InternalSelectMenu}\n                              themeOverrides={\n                                mergedTheme.peerOverrides.InternalSelectMenu\n                              }\n                              autoPending\n                              ref=\"selectMenuInstRef\"\n                              class={[\n                                `${mergedClsPrefix}-mention-menu`,\n                                this.themeClass\n                              ]}\n                              loading={this.loading}\n                              treeMate={this.treeMate}\n                              virtualScroll={false}\n                              style={this.cssVars as any}\n                              onToggle={this.handleSelect}\n                              renderLabel={this.renderLabel}\n                              scrollbarProps={this.scrollbarProps}\n                            >\n                              {$slots}\n                            </NInternalSelectMenu>\n                          ) : null\n                        }\n                      }}\n                    </Transition>\n                  )\n                }}\n              </VFollower>\n            ]\n          }}\n        </VBinder>\n      </div>\n    )\n  }\n})\n"
  },
  {
    "path": "src/mention/src/interface.ts",
    "content": "import type { SelectBaseOption } from '../../select/src/interface'\n\nexport type MentionOption = SelectBaseOption<string>\n\nexport interface MentionInst {\n  focus: () => void\n  blur: () => void\n}\n"
  },
  {
    "path": "src/mention/src/public-types.ts",
    "content": "export type MentionSize = 'small' | 'medium' | 'large'\n"
  },
  {
    "path": "src/mention/src/styles/index.cssr.ts",
    "content": "import { fadeInScaleUpTransition } from '../../../_styles/transitions/fade-in-scale-up.cssr'\nimport { c, cB } from '../../../_utils/cssr'\n\n// --n-menu-box-shadow\nexport default c([\n  cB('mention', 'width: 100%; z-index: auto; position: relative;'),\n  cB('mention-menu', `\n    box-shadow: var(--n-menu-box-shadow);\n  `, [\n    fadeInScaleUpTransition({\n      originalTransition: 'background-color .3s var(--n-bezier), box-shadow .3s var(--n-bezier)'\n    })\n  ])\n])\n"
  },
  {
    "path": "src/mention/src/utils.ts",
    "content": "/**\n * The original package is https://www.npmjs.com/package/textarea-caret-ts\n * The original file is https://github.com/TheRealSyler/textarea-caret-position/blob/master/index.ts\n *\n * Here I modified it to make it works when input is scrolled.\n */\n\nimport { isBrowser } from '../../_utils'\n\nexport interface Position {\n  /**\n   * position in pixel.\n   */\n  top: number\n  /**\n   * position in pixel.\n   */\n  left: number\n  /**\n   * if true the position is relative to the inner window size, if false the position is relative to itself.\n   */\n  absolute: boolean\n  /**\n   * height in pixel.\n   */\n  height: number\n}\nexport interface Point {\n  /**\n   * left position.\n   */\n  left: number\n  /**\n   * top position.\n   */\n  top: number\n}\nexport interface Options {\n  /**\n   * Enables debug Mode.\n   */\n  debug?: boolean\n  /**\n   * usesSelection End Instead of selection Start.\n   */\n  useSelectionEnd?: boolean\n  /**\n   * if true the left position gets caped if left >= element Width.\n   */\n  checkWidthOverflow?: boolean\n}\n\n/**\n * Returns the Absolute (relative to the inner window size) position of the caret in the given element.\n * @param element Input (has to be type='text') or Text Area.\n */\nexport function getAbsolutePosition(\n  element: HTMLInputElement | HTMLTextAreaElement\n): Position {\n  const caretRelPost = getRelativePosition(element)\n  return {\n    left:\n      window.scrollX + element.getBoundingClientRect().left + caretRelPost.left,\n    top:\n      window.scrollY + element.getBoundingClientRect().top + caretRelPost.top,\n    absolute: true,\n    height: caretRelPost.height\n  }\n}\n/**\n * Returns the relative position of the caret in the given element.\n * @param element Input (has to be type='text') or Text Area.\n */\nexport function getRelativePosition(\n  element: HTMLInputElement | HTMLTextAreaElement,\n  options: Options = {\n    debug: false,\n    useSelectionEnd: false,\n    checkWidthOverflow: true\n  }\n): Position {\n  const selectionStart\n    = element.selectionStart !== null ? element.selectionStart : 0\n  const selectionEnd = element.selectionEnd !== null ? element.selectionEnd : 0\n  const position = options.useSelectionEnd ? selectionEnd : selectionStart\n  // We'll copy the properties below into the mirror div.\n  // Note that some browsers, such as Firefox, do not concatenate properties\n  // into their shorthand (e.g. padding-top, padding-bottom etc. -> padding),\n  // so we have to list every single property explicitly.\n  const properties: string[] = [\n    'direction', // RTL support\n    'boxSizing',\n    'width', // on Chrome and IE, exclude the scrollbar, so the mirror div wraps exactly as the textarea does\n    'height',\n    'overflowX',\n    'overflowY', // copy the scrollbar for IE\n    'borderTopWidth',\n    'borderRightWidth',\n    'borderBottomWidth',\n    'borderLeftWidth',\n    'borderStyle',\n    'paddingTop',\n    'paddingRight',\n    'paddingBottom',\n    'paddingLeft',\n    // https://developer.mozilla.org/en-US/docs/Web/CSS/font\n    'fontStyle',\n    'fontVariant',\n    'fontWeight',\n    'fontStretch',\n    'fontSize',\n    'fontSizeAdjust',\n    'lineHeight',\n    'fontFamily',\n    'textAlign',\n    'textTransform',\n    'textIndent',\n    'textDecoration', // might not make a difference, but better be safe\n    'letterSpacing',\n    'wordSpacing',\n    'tabSize',\n    'MozTabSize'\n  ]\n  // Firefox 1.0+\n  const isFirefox = navigator.userAgent.toLowerCase().includes('firefox')\n  if (!isBrowser) {\n    throw new Error(\n      'textarea-caret-position#getCaretPosition should only be called in a browser'\n    )\n  }\n\n  const debug = options?.debug\n  if (debug) {\n    const el = document.querySelector(\n      '#input-textarea-caret-position-mirror-div'\n    )\n    if (el?.parentNode)\n      el.parentNode.removeChild(el)\n  }\n\n  // The mirror div will replicate the textareas style\n  const div = document.createElement('div')\n  div.id = 'input-textarea-caret-position-mirror-div'\n  document.body.appendChild(div)\n\n  const style = div.style\n  const computed = window.getComputedStyle\n    ? window.getComputedStyle(element)\n    : (element as any).currentStyle // currentStyle for IE < 9\n\n  const isInput = element.nodeName === 'INPUT'\n\n  // Default textarea styles\n  style.whiteSpace = isInput ? 'nowrap' : 'pre-wrap'\n  if (!isInput)\n    style.wordWrap = 'break-word' // only for textarea-s\n\n  // Position off-screen\n  style.position = 'absolute' // required to return coordinates properly\n  if (!debug)\n    style.visibility = 'hidden' // not 'display: none' because we want rendering\n\n  // Transfer the element's properties to the div\n  properties.forEach((prop) => {\n    if (isInput && prop === 'lineHeight') {\n      // Special case for <input>s because text is rendered centered and line height may be != height\n      if (computed.boxSizing === 'border-box') {\n        const height = Number.parseInt(computed.height as string)\n        const outerHeight\n          = Number.parseInt(computed.paddingTop as string)\n            + Number.parseInt(computed.paddingBottom as string)\n            + Number.parseInt(computed.borderTopWidth as string)\n            + Number.parseInt(computed.borderBottomWidth as string)\n        const targetHeight\n          = outerHeight + Number.parseInt(computed.lineHeight as string)\n        if (height > targetHeight) {\n          style.lineHeight = `${height - outerHeight}px`\n        }\n        else if (height === targetHeight) {\n          style.lineHeight = computed.lineHeight\n        }\n        else {\n          style.lineHeight = '0'\n        }\n      }\n      else {\n        style.lineHeight = computed.height\n      }\n    }\n    else {\n      style[prop as any] = computed[prop]\n    }\n  })\n\n  if (isFirefox) {\n    // Firefox lies about the overflow property for textareas: https://bugzilla.mozilla.org/show_bug.cgi?id=984275\n    if (element.scrollHeight > Number.parseInt(computed.height as string)) {\n      style.overflowY = 'scroll'\n    }\n  }\n  else {\n    style.overflow = 'hidden' // for Chrome to not render a scrollbar; IE keeps overflowY = 'scroll'\n  }\n\n  div.textContent = element.value.substring(0, position)\n  // The second special handling for input type=\"text\" vs textarea:\n  // spaces need to be replaced with non-breaking spaces - http://stackoverflow.com/a/13402035/1269037\n  if (isInput && div.textContent) {\n    div.textContent = div.textContent.replace(/\\s/g, '\\u00A0')\n  }\n\n  const span = document.createElement('span')\n  // Wrapping must be replicated *exactly*, including when a long word gets\n  // onto the next line, with whitespace at the end of the line before (#7).\n  // The  *only* reliable way to do that is to copy the *entire* rest of the\n  // textareas content into the <span> created at the caret position.\n  // For inputs, just '.' would be enough, but no need to bother.\n  span.textContent = element.value.substring(position) || '.' // || because a completely empty faux span doesn't render at all\n  span.style.position = 'relative'\n  span.style.left = `${-element.scrollLeft}px`\n  span.style.top = `${-element.scrollTop}px`\n  div.appendChild(span)\n\n  const relativePosition = {\n    top: span.offsetTop + Number.parseInt(computed.borderTopWidth as string),\n    left: span.offsetLeft + Number.parseInt(computed.borderLeftWidth as string),\n    absolute: false,\n    // We don't use line-height since it may be too large for position. Eg. 34px\n    // for input\n    height: Number.parseInt(computed.fontSize as string) * 1.5\n  }\n\n  if (debug) {\n    span.style.backgroundColor = '#aaa'\n  }\n  else {\n    document.body.removeChild(div)\n  }\n\n  if (\n    relativePosition.left >= element.clientWidth\n    && options.checkWidthOverflow\n  ) {\n    relativePosition.left = element.clientWidth\n  }\n  return relativePosition\n}\n/**\n * sets the top and left css style of the element based on the absolute position of the caretElements caret,\n * @param offset offsets the position.\n * @param detectBoundary offsets the position if the position would be outside the window.\n * @param returnOnly if true the element position wont be set.\n */\nexport function setElementPositionBasedOnCaret(\n  element: HTMLElement,\n  caretElement: HTMLInputElement | HTMLTextAreaElement,\n  offset: Point = { top: 0, left: 0 },\n  margin: number = 2,\n  detectBoundary = true,\n  returnOnly = false\n): Point {\n  const pos = getAbsolutePosition(caretElement)\n  if (detectBoundary) {\n    pos.left\n      = pos.left + (element.clientWidth + margin) + offset.left\n        > window.scrollX + window.innerWidth\n        ? (pos.left\n            = window.scrollX + window.innerWidth - (element.clientWidth + margin))\n        : (pos.left += offset.left)\n    pos.top\n      = pos.top + (element.clientWidth + margin) + offset.top\n        > window.scrollY + window.innerHeight\n        ? (pos.top -= element.clientWidth + margin)\n        : (pos.top += offset.top)\n  }\n  else {\n    pos.top += offset.top\n    pos.left += offset.left\n  }\n  if (!returnOnly) {\n    element.style.top = `${pos.top}px`\n    element.style.left = `${pos.left}px`\n  }\n  return pos\n}\n"
  },
  {
    "path": "src/mention/styles/dark.ts",
    "content": "import type { MentionTheme } from './light'\nimport { internalSelectMenuDark } from '../../_internal/select-menu/styles'\nimport { commonDark } from '../../_styles/common'\nimport { inputDark } from '../../input/styles'\n\nconst listDark: MentionTheme = {\n  name: 'Mention',\n  common: commonDark,\n  peers: {\n    InternalSelectMenu: internalSelectMenuDark,\n    Input: inputDark\n  },\n  self(vars) {\n    const { boxShadow2 } = vars\n    return {\n      menuBoxShadow: boxShadow2\n    }\n  }\n}\n\nexport default listDark\n"
  },
  {
    "path": "src/mention/styles/index.ts",
    "content": "export { default as mentionDark } from './dark'\nexport { default as mentionLight } from './light'\nexport type { MentionTheme, MentionThemeVars } from './light'\n"
  },
  {
    "path": "src/mention/styles/light.ts",
    "content": "import type { ThemeCommonVars } from '../../_styles/common'\nimport { internalSelectMenuLight } from '../../_internal/select-menu/styles'\nimport { createTheme } from '../../_mixins'\nimport { commonLight } from '../../_styles/common'\nimport { inputLight } from '../../input/styles'\n\nfunction self(vars: ThemeCommonVars) {\n  const { boxShadow2 } = vars\n  return {\n    menuBoxShadow: boxShadow2\n  }\n}\n\nconst mentionLight = createTheme({\n  name: 'Mention',\n  common: commonLight,\n  peers: {\n    InternalSelectMenu: internalSelectMenuLight,\n    Input: inputLight\n  },\n  self\n})\n\nexport default mentionLight\nexport type MentionTheme = typeof mentionLight\nexport type MentionThemeVars = ReturnType<typeof self>\n"
  },
  {
    "path": "src/mention/tests/Mention.spec.ts",
    "content": "import { mount } from '@vue/test-utils'\nimport { h, nextTick } from 'vue'\nimport { NIcon } from '../../icon'\nimport { NMention } from '../index'\n\ndescribe('n-mention', () => {\n  beforeEach(() => {\n    vi.useFakeTimers()\n  })\n  afterEach(() => {\n    vi.clearAllTimers()\n    vi.useRealTimers()\n  })\n  const options = [\n    {\n      label: '07akioni',\n      value: '07akioni'\n    },\n    {\n      label: 'star-kirby',\n      value: 'star-kirby'\n    },\n    {\n      label: '广东路',\n      value: '广东路'\n    },\n    {\n      label: (option: any) =>\n        h('span', null, [\n          h(NIcon, { style: 'margin-right: 5px' }, { default: () => 'test' }),\n          option.value\n        ]),\n      value: '颐和园路5号'\n    }\n  ]\n  it('should work with import on demand', () => {\n    mount(NMention)\n  })\n\n  it('should work with `options` prop', async () => {\n    const wrapper = mount(NMention, {\n      attachTo: document.body,\n      props: { options }\n    })\n\n    wrapper.find('input').element.focus()\n    await wrapper.find('input').setValue('@')\n    await vi.advanceTimersByTimeAsync(150)\n    expect(document.querySelector('.n-mention-menu')).not.toEqual(null)\n    expect(document.querySelectorAll('.n-base-select-option').length).toBe(4)\n    wrapper.unmount()\n  })\n\n  it('should work with `autosize` prop', async () => {\n    const wrapper = mount(NMention, {\n      attachTo: document.body,\n      props: { options, autosize: true }\n    })\n\n    expect(wrapper.find('.n-input').classes()).toContain('n-input--autosize')\n    wrapper.unmount()\n  })\n\n  it('should work with `type` prop', async () => {\n    const wrapper = mount(NMention, {\n      attachTo: document.body,\n      props: { options }\n    })\n\n    expect(wrapper.find('.n-input').classes()).not.toContain(\n      'n-input--textarea'\n    )\n    expect(wrapper.find('input').exists()).toBe(true)\n\n    await wrapper.setProps({ type: 'text' })\n    expect(wrapper.find('input').exists()).toBe(true)\n\n    await wrapper.setProps({ type: 'textarea' })\n    expect(wrapper.find('.n-input').classes()).toContain('n-input--textarea')\n    expect(wrapper.find('textarea').exists()).toBe(true)\n    wrapper.unmount()\n  })\n\n  it('should work with `bordered` prop', async () => {\n    const wrapper = mount(NMention, {\n      attachTo: document.body,\n      props: { options }\n    })\n\n    expect(wrapper.find('.n-input__border').exists()).toBe(true)\n    expect(wrapper.find('.n-input__state-border').exists()).toBe(true)\n\n    await wrapper.setProps({ bordered: false })\n    expect(wrapper.find('.n-input__border').exists()).not.toBe(true)\n    expect(wrapper.find('.n-input__state-border').exists()).not.toBe(true)\n    wrapper.unmount()\n  })\n\n  it('should work with `disabled` prop', async () => {\n    const wrapper = mount(NMention, {\n      attachTo: document.body,\n      props: { options }\n    })\n\n    expect(wrapper.find('.n-input').classes()).not.toContain(\n      'n-input--disabled'\n    )\n\n    await wrapper.setProps({ disabled: true })\n    expect(wrapper.find('.n-input').classes()).toContain('n-input--disabled')\n    wrapper.unmount()\n  })\n\n  it('should work with `loading` prop', async () => {\n    const wrapper = mount(NMention, {\n      attachTo: document.body,\n      props: { options, loading: true }\n    })\n\n    wrapper.find('input').element.focus()\n    await wrapper.find('input').setValue('@')\n    await vi.advanceTimersByTimeAsync(150)\n    expect(document.querySelector('.n-base-select-menu__loading')).not.toEqual(\n      null\n    )\n    wrapper.unmount()\n  })\n\n  it('should work with `loading` prop 2', async () => {\n    const wrapper = mount(NMention, {\n      attachTo: document.body,\n      props: { options, loading: true }\n    })\n\n    wrapper.find('input').element.focus()\n    await wrapper.find('input').setValue('@')\n    await vi.advanceTimersByTimeAsync(150)\n    expect(document.querySelector('.n-base-select-menu__loading')).not.toEqual(\n      null\n    )\n    wrapper.unmount()\n  })\n\n  it('should work with `prefix` prop', async () => {\n    const wrapper = mount(NMention, {\n      attachTo: document.body,\n      props: { options, prefix: '#' }\n    })\n\n    wrapper.find('input').element.focus()\n    await wrapper.find('input').setValue('#')\n    await vi.advanceTimersByTimeAsync(150)\n    expect(document.querySelector('.n-mention-menu')).not.toEqual(null)\n    expect(document.querySelectorAll('.n-base-select-option').length).toBe(4)\n    wrapper.unmount()\n  })\n\n  it('should work with `on-update:value` prop', async () => {\n    const onUpdate = vi.fn()\n    const wrapper = mount(NMention, {\n      attachTo: document.body,\n      props: { options, 'on-update:value': onUpdate }\n    })\n\n    wrapper.find('input').element.focus()\n    await wrapper.find('input').setValue('@')\n    await vi.advanceTimersByTimeAsync(150)\n    expect(onUpdate).toHaveBeenCalled()\n    wrapper.unmount()\n  })\n\n  it('should work with `on-focus` prop', async () => {\n    const onFocus = vi.fn()\n    const wrapper = mount(NMention, {\n      attachTo: document.body,\n      props: { options, 'on-focus': onFocus }\n    })\n\n    wrapper.find('input').element.focus()\n    expect(onFocus).toHaveBeenCalled()\n    wrapper.unmount()\n  })\n\n  // Test with problems\n  // it('should work with `on-search` prop', async () => {\n  //   const onSearch = vi.fn()\n  //   const wrapper = mount(NMention, {\n  //     attachTo: document.body,\n  //     props: { options, 'on-search': onSearch, type: 'text' }\n  //   })\n\n  //   wrapper.find('input').element.focus()\n  //   await wrapper.find('input').setValue('@')\n  //   await sleep(150)\n  //   expect(onSearch).toHaveBeenCalled()\n  // })\n\n  it('should work with `on-blur` prop', async () => {\n    const onBlur = vi.fn()\n    const wrapper = mount(NMention, {\n      attachTo: document.body,\n      props: { options, 'on-blur': onBlur }\n    })\n\n    wrapper.find('input').element.focus()\n    wrapper.find('input').element.blur()\n    expect(onBlur).toHaveBeenCalled()\n    wrapper.unmount()\n  })\n\n  it('should work with `focus` method', async () => {\n    const wrapper = mount(NMention, {\n      attachTo: document.body,\n      props: { options }\n    })\n    wrapper.vm.focus()\n    await nextTick()\n    expect(wrapper.find('.n-input').classes()).toContain('n-input--focus')\n    wrapper.unmount()\n  })\n\n  it('should work with `blur` method', async () => {\n    const wrapper = mount(NMention, {\n      attachTo: document.body,\n      props: { options }\n    })\n    wrapper.vm.focus()\n    wrapper.vm.blur()\n    await nextTick()\n    expect(wrapper.find('.n-input').classes()).not.toContain('n-input--focus')\n    wrapper.unmount()\n  })\n})\n"
  },
  {
    "path": "src/mention/tests/server.spec.tsx",
    "content": "import { setup } from '@css-render/vue3-ssr'\nimport { renderToString } from '@vue/server-renderer'\n/**\n * @vitest-environment node\n */\nimport { createSSRApp, h } from 'vue'\nimport { NMention } from '../..'\n\ndescribe('server side rendering', () => {\n  it('works', async () => {\n    const app = createSSRApp(() => <NMention />)\n    setup(app)\n    try {\n      await renderToString(app)\n    }\n    catch (e) {\n      expect(e).not.toBeTruthy()\n    }\n  })\n})\n"
  },
  {
    "path": "src/menu/demos/enUS/accordion.demo.vue",
    "content": "<markdown>\n# Accordion\n\nLike an accordion. You can use `accordion` prop to switch this mode for the first-level menu.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { MenuOption } from 'naive-ui'\nimport type { Component } from 'vue'\nimport {\n  BagOutline as BagOutlineIcon,\n  FishOutline as FishIcon,\n  PawOutline as PawIcon\n} from '@vicons/ionicons5'\nimport { NIcon } from 'naive-ui'\nimport { h } from 'vue'\n\nfunction renderIcon(icon: Component) {\n  return () => h(NIcon, null, { default: () => h(icon) })\n}\n\nconst menuOptions: MenuOption[] = [\n  {\n    label: 'Fish',\n    key: 'fish',\n    icon: renderIcon(FishIcon),\n    children: [\n      {\n        label: 'Braise',\n        key: 'braise',\n        children: [\n          {\n            label: 'Spicy',\n            key: 'spicy'\n          }\n        ]\n      },\n      {\n        label: 'Steamed',\n        key: 'steamed',\n        children: [\n          {\n            label: 'No Green Onion',\n            key: 'no-green-onion'\n          }\n        ]\n      }\n    ]\n  },\n  {\n    label: 'Bear Paw',\n    key: 'bear-paw',\n    icon: renderIcon(PawIcon),\n    children: [\n      {\n        label: 'Protect Wild Animals',\n        key: 'protect-wild-animals'\n      }\n    ]\n  },\n  {\n    label: 'Both',\n    key: 'both',\n    icon: renderIcon(BagOutlineIcon),\n    children: [\n      {\n        label: 'You can\\'t have your cake and eat it',\n        key: 'can-not'\n      }\n    ]\n  }\n]\n\nconst defaultExpandedKeys = ['fish', 'braise']\n</script>\n\n<template>\n  <n-menu\n    :options=\"menuOptions\"\n    :default-expanded-keys=\"defaultExpandedKeys\"\n    accordion\n  />\n</template>\n"
  },
  {
    "path": "src/menu/demos/enUS/collapse.demo.vue",
    "content": "<markdown>\n# Collapsed menu\n\nUse collapsable vertical menu with layout sider. Use `collapsed` to control collapse status of menu. You must set `collapsed-width` to make it collapse in a right manner. There are still some other collapse related props you can modify: `icon-size`, `collapsed-icon-size`. For details see API table at the bottom of the page.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { MenuOption } from 'naive-ui'\nimport type { Component } from 'vue'\nimport {\n  BookOutline as BookIcon,\n  PersonOutline as PersonIcon,\n  WineOutline as WineIcon\n} from '@vicons/ionicons5'\nimport { NIcon } from 'naive-ui'\nimport { h, ref } from 'vue'\n\nfunction renderIcon(icon: Component) {\n  return () => h(NIcon, null, { default: () => h(icon) })\n}\n\nconst menuOptions: MenuOption[] = [\n  {\n    label: 'Hear the Wind Sing',\n    key: 'hear-the-wind-sing',\n    icon: renderIcon(BookIcon)\n  },\n  {\n    label: 'Pinball 1973',\n    key: 'pinball-1973',\n    icon: renderIcon(BookIcon),\n    disabled: true,\n    children: [\n      {\n        label: 'Rat',\n        key: 'rat'\n      }\n    ]\n  },\n  {\n    label: 'A Wild Sheep Chase',\n    key: 'a-wild-sheep-chase',\n    disabled: true,\n    icon: renderIcon(BookIcon)\n  },\n  {\n    label: 'Dance Dance Dance',\n    key: 'Dance Dance Dance',\n    icon: renderIcon(BookIcon),\n    children: [\n      {\n        type: 'group',\n        label: 'People',\n        key: 'people',\n        children: [\n          {\n            label: 'Narrator',\n            key: 'narrator',\n            icon: renderIcon(PersonIcon)\n          },\n          {\n            label: 'Sheep Man',\n            key: 'sheep-man',\n            icon: renderIcon(PersonIcon)\n          }\n        ]\n      },\n      {\n        label: 'Beverage',\n        key: 'beverage',\n        icon: renderIcon(WineIcon),\n        children: [\n          {\n            label: 'Whisky',\n            key: 'whisky'\n          }\n        ]\n      },\n      {\n        label: 'Food',\n        key: 'food',\n        children: [\n          {\n            label: 'Sandwich',\n            key: 'sandwich'\n          }\n        ]\n      },\n      {\n        label: 'The past increases. The future recedes.',\n        key: 'the-past-increases-the-future-recedes'\n      }\n    ]\n  }\n]\n\nconst activeKey = ref<string | null>(null)\nconst collapsed = ref(true)\n</script>\n\n<template>\n  <n-space vertical>\n    <n-switch v-model:value=\"collapsed\" />\n    <n-layout has-sider>\n      <n-layout-sider\n        bordered\n        collapse-mode=\"width\"\n        :collapsed-width=\"64\"\n        :width=\"240\"\n        :collapsed=\"collapsed\"\n        show-trigger\n        @collapse=\"collapsed = true\"\n        @expand=\"collapsed = false\"\n      >\n        <n-menu\n          v-model:value=\"activeKey\"\n          :collapsed=\"collapsed\"\n          :collapsed-width=\"64\"\n          :collapsed-icon-size=\"22\"\n          :options=\"menuOptions\"\n        />\n      </n-layout-sider>\n      <n-layout>\n        <span>Content</span>\n      </n-layout>\n    </n-layout>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/menu/demos/enUS/customize-field.demo.vue",
    "content": "<markdown>\n# Customizing field\n\nVarious data would come from backend, you can customize `key`, `label` and `children`'s field name.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { MenuOption } from 'naive-ui'\nimport type { Component } from 'vue'\nimport {\n  BookOutline as BookIcon,\n  PersonOutline as PersonIcon,\n  WineOutline as WineIcon\n} from '@vicons/ionicons5'\nimport { NIcon } from 'naive-ui'\nimport { h, ref } from 'vue'\n\nfunction renderIcon(icon: Component) {\n  return () => h(NIcon, null, { default: () => h(icon) })\n}\n\nconst menuOptions: MenuOption[] = [\n  {\n    whateverLabel: 'Hear the Wind Sing',\n    whateverKey: 'hear-the-wind-sing',\n    icon: renderIcon(BookIcon)\n  },\n  {\n    whateverLabel: 'Pinball 1973',\n    whateverKey: 'pinball-1973',\n    icon: renderIcon(BookIcon),\n    disabled: true,\n    whateverChildren: [\n      {\n        whateverLabel: 'Rat',\n        whateverKey: 'rat'\n      }\n    ]\n  },\n  {\n    whateverLabel: 'A Wild Sheep Chase',\n    whateverKey: 'a-wild-sheep-chase',\n    disabled: true,\n    icon: renderIcon(BookIcon)\n  },\n  {\n    whateverLabel: 'Dance Dance Dance',\n    whateverKey: 'Dance Dance Dance',\n    icon: renderIcon(BookIcon),\n    whateverChildren: [\n      {\n        type: 'group',\n        whateverLabel: 'People',\n        whateverKey: 'people',\n        whateverChildren: [\n          {\n            whateverLabel: 'Narrator',\n            whateverKey: 'narrator',\n            icon: renderIcon(PersonIcon)\n          },\n          {\n            whateverLabel: 'Sheep Man',\n            whateverKey: 'sheep-man',\n            icon: renderIcon(PersonIcon)\n          }\n        ]\n      },\n      {\n        whateverLabel: 'Beverage',\n        whateverKey: 'beverage',\n        icon: renderIcon(WineIcon),\n        whateverChildren: [\n          {\n            whateverLabel: 'Whisky',\n            whateverKey: 'whisky'\n          }\n        ]\n      },\n      {\n        whateverLabel: 'Food',\n        whateverKey: 'food',\n        whateverChildren: [\n          {\n            whateverLabel: 'Sandwich',\n            whateverKey: 'sandwich'\n          }\n        ]\n      },\n      {\n        whateverLabel: 'The past increases. The future recedes.',\n        whateverKey: 'the-past-increases-the-future-recedes'\n      }\n    ]\n  }\n]\n\nconst collapsed = ref(true)\n</script>\n\n<template>\n  <n-layout has-sider>\n    <n-layout-sider\n      bordered\n      collapse-mode=\"width\"\n      :collapsed-width=\"64\"\n      :width=\"240\"\n      :collapsed=\"collapsed\"\n      show-trigger\n      @collapse=\"collapsed = true\"\n      @expand=\"collapsed = false\"\n    >\n      <n-menu\n        :collapsed=\"collapsed\"\n        :collapsed-width=\"64\"\n        :collapsed-icon-size=\"22\"\n        :options=\"menuOptions\"\n        key-field=\"whateverKey\"\n        label-field=\"whateverLabel\"\n        children-field=\"whateverChildren\"\n      />\n    </n-layout-sider>\n    <n-layout />\n  </n-layout>\n</template>\n"
  },
  {
    "path": "src/menu/demos/enUS/default-expanded-keys.demo.vue",
    "content": "<markdown>\n# Expand submenu\n\nIf you don't set `default-expanded-keys`, menu will expand all the ascendant of selected option by default.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { MenuOption } from 'naive-ui'\nimport type { Component } from 'vue'\nimport {\n  BookOutline as BookIcon,\n  PersonOutline as PersonIcon,\n  WineOutline as WineIcon\n} from '@vicons/ionicons5'\nimport { NIcon, useMessage } from 'naive-ui'\nimport { h } from 'vue'\n\nfunction renderIcon(icon: Component) {\n  return () => h(NIcon, null, { default: () => h(icon) })\n}\n\nconst menuOptions: MenuOption[] = [\n  {\n    label: 'Hear the Wind Sing',\n    key: 'hear-the-wind-sing',\n    icon: renderIcon(BookIcon)\n  },\n  {\n    label: 'Pinball 1973',\n    key: 'pinball-1973',\n    icon: renderIcon(BookIcon),\n    disabled: true,\n    children: [\n      {\n        label: 'Rat',\n        key: 'rat'\n      }\n    ]\n  },\n  {\n    label: 'A Wild Sheep Chase',\n    key: 'a-wild-sheep-chase',\n    disabled: true,\n    icon: renderIcon(BookIcon)\n  },\n  {\n    label: 'Dance Dance Dance',\n    key: 'dance-dance-dance',\n    icon: renderIcon(BookIcon),\n    children: [\n      {\n        type: 'group',\n        label: 'People',\n        key: 'people',\n        children: [\n          {\n            label: 'Narrator',\n            key: 'narrator',\n            icon: renderIcon(PersonIcon)\n          },\n          {\n            label: 'Sheep Man',\n            key: 'sheep-man',\n            icon: renderIcon(PersonIcon)\n          }\n        ]\n      },\n      {\n        label: 'Beverage',\n        key: 'beverage',\n        icon: renderIcon(WineIcon),\n        children: [\n          {\n            label: 'Whisky',\n            key: 'whisky'\n          }\n        ]\n      },\n      {\n        label: 'Food',\n        key: 'food',\n        children: [\n          {\n            label: 'Sandwich',\n            key: 'sandwich'\n          }\n        ]\n      },\n      {\n        label: 'The past increases. The future recedes.',\n        key: 'the-past-increases-the-future-recedes'\n      }\n    ]\n  }\n]\n\nconst message = useMessage()\nconst defaultExpandedKeys = ['dance-dance-dance', 'food']\n\nfunction handleUpdateExpandedKeys(value: string[]) {\n  message.info(`[onUpdate:expandedKeys]: ${JSON.stringify(value)}`)\n}\n</script>\n\n<template>\n  <n-menu\n    :options=\"menuOptions\"\n    :default-expanded-keys=\"defaultExpandedKeys\"\n    @update:expanded-keys=\"handleUpdateExpandedKeys\"\n  />\n</template>\n"
  },
  {
    "path": "src/menu/demos/enUS/expand-selected-option.demo.vue",
    "content": "<markdown>\n# Show selected option\n\nIn some scenes, menu's value is passed from outside. The component is hard to understand what behavior is expected. You can use `showOption` method to make specified option displayed.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { MenuInst } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst accordion = ref(false)\nconst selectedKey = ref('1')\nconst menuInstRef = ref<MenuInst | null>(null)\n\nfunction selectAndExpand(key: string) {\n  selectedKey.value = key\n  menuInstRef.value?.showOption(key)\n}\n\nconst options = [\n  {\n    label: '1 parent',\n    key: '1 parent',\n    children: [\n      {\n        label: '1',\n        key: '1'\n      }\n    ]\n  },\n  {\n    label: '2 parent',\n    key: '2 parent',\n    children: [\n      {\n        label: '2',\n        key: '2'\n      }\n    ]\n  },\n  {\n    label: '3 parent',\n    key: '3 parent',\n    children: [\n      {\n        label: '3',\n        key: '3'\n      }\n    ]\n  }\n]\n</script>\n\n<template>\n  <n-space vertical>\n    <n-switch v-model:value=\"accordion\">\n      <template #checked>\n        Accrodion\n      </template>\n      <template #unchecked>\n        Normal\n      </template>\n    </n-switch>\n    <n-button @click=\"selectAndExpand('1')\">\n      Select 1st child\n    </n-button>\n    <n-button @click=\"selectAndExpand('2')\">\n      Select 2nd child\n    </n-button>\n    <n-button @click=\"selectAndExpand('3')\">\n      Select 3rd child\n    </n-button>\n    <n-menu\n      ref=\"menuInstRef\"\n      v-model:value=\"selectedKey\"\n      :options=\"options\"\n      :accordion=\"accordion\"\n    />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/menu/demos/enUS/horizontal.demo.vue",
    "content": "<markdown>\n# Horizontal\n\nA horiziontal menu which can automatically collapse its items.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { MenuOption } from 'naive-ui'\nimport type { Component } from 'vue'\nimport {\n  BookOutline as BookIcon,\n  PersonOutline as PersonIcon,\n  WineOutline as WineIcon\n} from '@vicons/ionicons5'\nimport { NIcon } from 'naive-ui'\nimport { h, ref } from 'vue'\n\nfunction renderIcon(icon: Component) {\n  return () => h(NIcon, null, { default: () => h(icon) })\n}\n\nconst menuOptions: MenuOption[] = [\n  {\n    label: () =>\n      h(\n        'a',\n        {\n          href: 'https://en.wikipedia.org/wiki/Hear_the_Wind_Sing',\n          target: '_blank',\n          rel: 'noopenner noreferrer'\n        },\n        'Hear the Wind Sing'\n      ),\n    key: 'hear-the-wind-sing',\n    icon: renderIcon(BookIcon)\n  },\n  {\n    label: 'Pinball 1973',\n    key: 'pinball-1973',\n    icon: renderIcon(BookIcon),\n    disabled: true,\n    children: [\n      {\n        label: 'Rat',\n        key: 'rat'\n      }\n    ]\n  },\n  {\n    label: 'A Wild Sheep Chase',\n    key: 'a-wild-sheep-chase',\n    disabled: true,\n    icon: renderIcon(BookIcon)\n  },\n  {\n    label: 'Dance Dance Dance',\n    key: 'Dance Dance Dance',\n    icon: renderIcon(BookIcon),\n    children: [\n      {\n        type: 'group',\n        label: 'People',\n        key: 'people',\n        children: [\n          {\n            label: 'Narrator',\n            key: 'narrator',\n            icon: renderIcon(PersonIcon)\n          },\n          {\n            label: 'Sheep Man',\n            key: 'sheep-man',\n            icon: renderIcon(PersonIcon)\n          }\n        ]\n      },\n      {\n        label: 'Beverage',\n        key: 'beverage',\n        icon: renderIcon(WineIcon),\n        children: [\n          {\n            label: 'Whisky',\n            key: 'whisky'\n          }\n        ]\n      },\n      {\n        label: 'Food',\n        key: 'food',\n        children: [\n          {\n            label: 'Sandwich',\n            key: 'sandwich'\n          }\n        ]\n      },\n      {\n        label: 'The past increases. The future recedes.',\n        key: 'the-past-increases-the-future-recedes'\n      }\n    ]\n  }\n]\n\nconst activeKey = ref<string | null>(null)\n</script>\n\n<template>\n  <n-split :default-size=\"0.8\">\n    <template #1>\n      <n-menu\n        v-model:value=\"activeKey\"\n        mode=\"horizontal\"\n        :options=\"menuOptions\"\n        responsive\n      />\n    </template>\n  </n-split>\n</template>\n"
  },
  {
    "path": "src/menu/demos/enUS/indent.demo.vue",
    "content": "<markdown>\n# Indent\n\nYou can specify `indent` & `root-indent` of the menu. `root-indent` only determines the first-leveled children.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { MenuOption } from 'naive-ui'\nimport type { Component } from 'vue'\nimport {\n  BookOutline as BookIcon,\n  PersonOutline as PersonIcon,\n  WineOutline as WineIcon\n} from '@vicons/ionicons5'\nimport { NIcon } from 'naive-ui'\nimport { h, ref } from 'vue'\n\nfunction renderIcon(icon: Component) {\n  return () => h(NIcon, null, { default: () => h(icon) })\n}\n\nconst menuOptions: MenuOption[] = [\n  {\n    label: 'Hear the Wind Sing',\n    key: 'hear-the-wind-sing',\n    icon: renderIcon(BookIcon)\n  },\n  {\n    label: 'Pinball 1973',\n    key: 'pinball-1973',\n    icon: renderIcon(BookIcon),\n    disabled: true,\n    children: [\n      {\n        label: 'Rat',\n        key: 'rat'\n      }\n    ]\n  },\n  {\n    label: 'A Wild Sheep Chase',\n    key: 'a-wild-sheep-chase',\n    disabled: true,\n    icon: renderIcon(BookIcon)\n  },\n  {\n    label: 'Dance Dance Dance',\n    key: 'Dance Dance Dance',\n    icon: renderIcon(BookIcon),\n    children: [\n      {\n        type: 'group',\n        label: 'People',\n        key: 'people',\n        children: [\n          {\n            label: 'Narrator',\n            key: 'narrator',\n            icon: renderIcon(PersonIcon)\n          },\n          {\n            label: 'Sheep Man',\n            key: 'sheep-man',\n            icon: renderIcon(PersonIcon)\n          }\n        ]\n      },\n      {\n        label: 'Beverage',\n        key: 'beverage',\n        icon: renderIcon(WineIcon),\n        children: [\n          {\n            label: 'Whisky',\n            key: 'whisky'\n          }\n        ]\n      },\n      {\n        label: 'Food',\n        key: 'food',\n        children: [\n          {\n            label: 'Sandwich',\n            key: 'sandwich'\n          }\n        ]\n      },\n      {\n        label: 'The past increases. The future recedes.',\n        key: 'the-past-increases-the-future-recedes'\n      }\n    ]\n  }\n]\n\nconst activeKey = ref(null)\n</script>\n\n<template>\n  <n-menu\n    v-model:value=\"activeKey\"\n    :root-indent=\"36\"\n    :indent=\"12\"\n    :options=\"menuOptions\"\n  />\n</template>\n"
  },
  {
    "path": "src/menu/demos/enUS/index.demo-entry.md",
    "content": "# Menu\n\n<!--single-column-->\n\nNo Food.\n\n## Demos\n\n```demo\nhorizontal.vue\nselect.vue\nrender-label.vue\ndefault-expanded-keys.vue\nindent.vue\ncollapse.vue\ninverted.vue\nlong-label.vue\naccordion.vue\nrouter-link.vue\ncustomize-field.vue\nexpand-selected-option.vue\nshow.vue\n```\n\n## API\n\n### Menu Props\n\n| Name | Type | Default | Description | Version |\n| --- | --- | --- | --- | --- |\n| accordion | `boolean` | `false` | Whether to use accordion mode. |  |\n| children-field | `string` | `'children'` | Field name of children. |  |\n| collapsed-icon-size | `number` | `24` | The icon size when menu is collapsed. If not set, menu will use `icon-size` in place of it. |  |\n| collapsed-width | `number` | `48` | The menu width after collapsed. |  |\n| collapsed | `boolean` | `false` | The collapsed status of menu, only works when menu is vertical. |  |\n| default-expand-all | `boolean` | `false` | Whether to expand all menus. When options is set asynchronously, you can set `watch-props` to `['defaultExpandedKeys']` to make it work. |  |\n| default-expanded-keys | `Array<string>` | `[]` | The default expanded submenu keys of menu in uncontrolled manner. |  |\n| default-value | `string \\| null` | `null` | Whether selected by default in uncontrolled mode. |  |\n| disabled-field | `string` | `'disabled'` | Field name of disabled. | 2.33.0 |\n| dropdown-placement | `'top-start' \\| 'top' \\| 'top-end' \\| 'right-start' \\| 'right' \\| 'right-end' \\| 'bottom-start' \\| 'bottom' \\| 'bottom-end' \\| 'left-start' \\| 'left' \\| 'left-end' \\| ` | `'top'` | Only effective in horizontal mode. |  |\n| dropdown-props | `DropdownProps` | `undefined` | The dropdown's props when menu is collapsed or horizontal mode，please see [Dropdown Props](dropdown#Dropdown-Props) |  |\n| expanded-keys | `Array<string>` | `undefined` | The expanded submenu keys. If set, menu will work in controlled manner and `default-expanded-names` won't work. |  |\n| expand-icon | `(option: MenuOption) => VNodeChild` | `undefined` | Render function that renders all expand icon. |  |\n| icon-size | `number` | `20` | The icon size when menu is not collapsed. |  |\n| indent | `number` | `32` | The indent of menu. |  |\n| inverted | `boolean` | `false` | Use inverted style. |  |\n| key-field | `string` | `'key'` | Field name of key. |  |\n| label-field | `string` | `'label'` | Field name of label. |  |\n| options | `Array<MenuOption \\| MenuDividerOption \\| MenuGroupOption>` | `[]` | Items data of menu. |  |\n| node-props | `(option: MenuOption \\| MenuGroupOption) => object` | `undefined` | Node's DOM attrs generator. | 2.28.3 |\n| mode | `'vertical' \\| 'horizontal'` | `'vertical'` | Menu layout. |  |\n| render-extra | `(option: MenuOption \\| MenuGroupOption) => VNodeChild` | `undefined` | Render function that renders all extras. |  |\n| render-icon | `(option: MenuOption) => VNodeChild` | `undefined` | Render function that renders all icons. |  |\n| render-label | `(option: MenuOption \\| MenuGroupOption) => VNodeChild` | `undefined` | Render function that renders all labels. |  |\n| responsive | `boolean` | `false` | Whether to collapsed menu items that overflows menu. Only work for menu with `mode='horizontal'`. | 2.36.0 |\n| root-indent | `number` | `undefined` | The indent of menu's first level children. If not set, menu will use `indent` in place of it. |  |\n| value | `string \\| null` | `undefined` | The selected item key of the menu. |  |\n| watch-props | `Array<'defaultValue' \\| 'defaultExpandedKeys'>` | `undefined` | Default prop names that needed to be watched. Components will be updated after the prop is changed. Note: the `watch-props` itself is not reactive. |  |\n| on-update:expanded-keys | `(keys: string[]) => void` | `undefined` | `keys` is the array of expanded menu options' `key`. |  |\n| on-update:value | `(key: string, item: MenuOption) => void` | `undefined` | Callback when select a menu item. `key` is the `key` of the selected menu item. `item` is then original data of the menu item. |  |\n\n### MenuOption Properties\n\n| Name | Type | Description | Version |\n| --- | --- | --- | --- |\n| children? | `Array<MenuOption \\| MenuGroupOption>` | Child menu options. |  |\n| disabled? | `boolean` | Whether to disable the menu item. |  |\n| extra? | `string \\| (() => VNodeChild)` | The extra parts of the menu item. |  |\n| icon? | `() => VNodeChild` | The icon for the menu item. |  |\n| key | `string` | The identifier of the menu item. |  |\n| label | `string \\| (() => VNodeChild)` | The label of the menu item. |  |\n| show? | `boolean` | Whether to show the menu item. | 2.32.2 |\n\n### MenuGroupOption Properties\n\n| Name | Type | Description | Version |\n| --- | --- | --- | --- |\n| children | `Array<MenuOption \\| MenuGroupOption>` | Group items, **required!** |  |\n| key | `string` | The identifier of the menu group. |  |\n| label | `string \\| (() => VNodeChild)` | The label of the menu item. |  |\n| show? | `boolean` | Whether to show the menu item. | 2.32.2 |\n| type | `'group'` | The type of the menu item, **required!** |  |\n\n### MenuDividerOption Properties\n\n| Name | Type | Description | Version |\n| --- | --- | --- | --- |\n| key | `string` | The identifier of the menu group. |  |\n| props | `HTMLAttributes` | Attributes of the divider. |  |\n| show? | `boolean` | Whether to show the menu item. | 2.32.2 |\n| type | `'divider'` | The type of the menu item, **required!** |  |\n\n### Menu Methods\n\n| Name | Type | Description | Version |\n| --- | --- | --- | --- |\n| deriveResponsiveState | `() => void` | Recalculate the collapsed state of the responsive menu content. When the width of the menu container is not solely determined by the external width, in the `responsive` mode, the menu content cannot automatically expand after being collapsed. You can call this method to ensure that the menu can be expanded again. | 2.36.0 |\n| showOption | `(key: string \\| number) => void` | Expand menu to show option with specified `key`. If `key` is not specified, selected option will be displayed. | 2.27.0 |\n"
  },
  {
    "path": "src/menu/demos/enUS/inverted.demo.vue",
    "content": "<markdown>\n# Inverted\n\nSet `inverted` to add contrast. Usually used with `n-layout`.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { MenuOption } from 'naive-ui'\nimport type { Component } from 'vue'\nimport {\n  BookOutline as BookIcon,\n  PersonOutline as PersonIcon,\n  WineOutline as WineIcon\n} from '@vicons/ionicons5'\nimport { NIcon } from 'naive-ui'\nimport { h, ref } from 'vue'\n\nfunction renderIcon(icon: Component) {\n  return () => h(NIcon, null, { default: () => h(icon) })\n}\n\nconst menuOptions: MenuOption[] = [\n  {\n    label: 'Hear the Wind Sing',\n    key: 'hear-the-wind-sing',\n    icon: renderIcon(BookIcon)\n  },\n  {\n    label: 'Pinball 1973',\n    key: 'pinball-1973',\n    icon: renderIcon(BookIcon),\n    disabled: true,\n    children: [\n      {\n        label: 'Rat',\n        key: 'rat'\n      }\n    ]\n  },\n  {\n    label: 'A Wild Sheep Chase',\n    key: 'a-wild-sheep-chase',\n    disabled: true,\n    icon: renderIcon(BookIcon)\n  },\n  {\n    label: 'Dance Dance Dance',\n    key: 'Dance Dance Dance',\n    icon: renderIcon(BookIcon),\n    children: [\n      {\n        type: 'group',\n        label: 'People',\n        key: 'people',\n        children: [\n          {\n            label: 'Narrator',\n            key: 'narrator',\n            icon: renderIcon(PersonIcon)\n          },\n          {\n            label: 'Sheep Man',\n            key: 'sheep-man',\n            icon: renderIcon(PersonIcon)\n          }\n        ]\n      },\n      {\n        label: 'Beverage',\n        key: 'beverage',\n        icon: renderIcon(WineIcon),\n        children: [\n          {\n            label: 'Whisky',\n            key: 'whisky'\n          }\n        ]\n      },\n      {\n        label: 'Food',\n        key: 'food',\n        children: [\n          {\n            label: 'Sandwich',\n            key: 'sandwich'\n          }\n        ]\n      },\n      {\n        label: 'The past increases. The future recedes.',\n        key: 'the-past-increases-the-future-recedes'\n      }\n    ]\n  }\n]\n\nconst inverted = ref(false)\n</script>\n\n<template>\n  <n-space vertical>\n    <n-space><n-switch v-model:value=\"inverted\" />inverted</n-space>\n    <n-layout has-sider>\n      <n-layout-sider\n        bordered\n        collapse-mode=\"width\"\n        :collapsed-width=\"64\"\n        :width=\"240\"\n        show-trigger\n        :inverted=\"inverted\"\n      >\n        <n-menu\n          :inverted=\"inverted\"\n          :collapsed-width=\"64\"\n          :collapsed-icon-size=\"22\"\n          :options=\"menuOptions\"\n        />\n      </n-layout-sider>\n      <n-layout>\n        <span>Content</span>\n      </n-layout>\n    </n-layout>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/menu/demos/enUS/long-label.demo.vue",
    "content": "<markdown>\n# Long label\n\nSet `label` to render function that renders `n-ellipsis`.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { MenuOption } from 'naive-ui'\nimport { NEllipsis } from 'naive-ui'\nimport { h } from 'vue'\n\nconst options: MenuOption[] = [\n  {\n    label: () =>\n      h(NEllipsis, null, {\n        default: () =>\n          'The lights are extinguished. Matter is transformed and the heavens have shifted. Clay figures vanish into the sea.'\n      }),\n    key: '1'\n  },\n  {\n    label: () =>\n      h(NEllipsis, null, {\n        default: () =>\n          'The darkness is like a boulder pressing down upon the breast.'\n      }),\n    key: '2'\n  }\n]\n</script>\n\n<template>\n  <n-menu :options=\"options\" style=\"width: 180px\" default-value=\"1\" />\n</template>\n"
  },
  {
    "path": "src/menu/demos/enUS/render-label.demo.vue",
    "content": "<markdown>\n# Batch customizing menu options\n\nThe `render-label`, `render-icon`, `expand-icon` can be used to batch render menu options.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { MenuOption } from 'naive-ui'\nimport { BookmarkOutline, CaretDownOutline } from '@vicons/ionicons5'\nimport { NIcon } from 'naive-ui'\nimport { h, ref } from 'vue'\n\nconst menuOptions: MenuOption[] = [\n  {\n    label: 'Hear the Wind Sing',\n    key: 'hear-the-wind-sing',\n    href: 'https://en.wikipedia.org/wiki/Hear_the_Wind_Sing'\n  },\n  {\n    label: 'Pinball 1973',\n    key: 'pinball-1973',\n    disabled: true,\n    children: [\n      {\n        label: 'Rat',\n        key: 'rat'\n      }\n    ]\n  },\n  {\n    label: 'A Wild Sheep Chase',\n    key: 'a-wild-sheep-chase',\n    disabled: true\n  },\n  {\n    label: 'Dance Dance Dance',\n    key: 'Dance Dance Dance',\n    children: [\n      {\n        type: 'group',\n        label: 'People',\n        key: 'people',\n        children: [\n          {\n            label: 'Narrator',\n            key: 'narrator'\n          },\n          {\n            label: 'Sheep Man',\n            key: 'sheep-man'\n          }\n        ]\n      },\n      {\n        label: 'Beverage',\n        key: 'beverage',\n        children: [\n          {\n            label: 'Whisky',\n            key: 'whisky',\n            href: 'https://en.wikipedia.org/wiki/Whisky'\n          }\n        ]\n      },\n      {\n        label: 'Food',\n        key: 'food',\n        children: [\n          {\n            label: 'Sandwich',\n            key: 'sandwich'\n          }\n        ]\n      },\n      {\n        label: 'The past increases. The future recedes.',\n        key: 'the-past-increases-the-future-recedes'\n      }\n    ]\n  }\n]\n\nconst collapsed = ref(true)\n\nfunction renderMenuLabel(option: MenuOption) {\n  if ('href' in option) {\n    return h('a', { href: option.href, target: '_blank' }, [\n      option.label as string\n    ])\n  }\n  return option.label as string\n}\n\nfunction renderMenuIcon(option: MenuOption) {\n  // return render placeholder for indent\n  if (option.key === 'sheep-man')\n    return true\n  // return falsy, don't render icon placeholder\n  if (option.key === 'food')\n    return null\n  return h(NIcon, null, { default: () => h(BookmarkOutline) })\n}\n\nfunction expandIcon() {\n  return h(NIcon, null, { default: () => h(CaretDownOutline) })\n}\n</script>\n\n<template>\n  <n-space vertical>\n    <n-switch v-model:value=\"collapsed\" />\n    <n-layout has-sider>\n      <n-layout-sider\n        bordered\n        collapse-mode=\"width\"\n        :collapsed-width=\"64\"\n        :width=\"240\"\n        :collapsed=\"collapsed\"\n        show-trigger\n        @collapse=\"collapsed = true\"\n        @expand=\"collapsed = false\"\n      >\n        <n-menu\n          :collapsed=\"collapsed\"\n          :collapsed-width=\"64\"\n          :collapsed-icon-size=\"22\"\n          :options=\"menuOptions\"\n          :render-label=\"renderMenuLabel\"\n          :render-icon=\"renderMenuIcon\"\n          :expand-icon=\"expandIcon\"\n        />\n      </n-layout-sider>\n      <n-layout>\n        <span>Content</span>\n      </n-layout>\n    </n-layout>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/menu/demos/enUS/router-link.demo.vue",
    "content": "<markdown>\n# Use vue-router\n\nUsually you can use vue-router here to accomplish routing. You can render `label` as `<router-link />` to set route.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { MenuOption } from 'naive-ui'\nimport type { Component } from 'vue'\nimport {\n  LogOutOutline as HomeIcon,\n  LaptopOutline as WorkIcon\n} from '@vicons/ionicons5'\nimport { NIcon } from 'naive-ui'\nimport { h } from 'vue'\nimport { RouterLink } from 'vue-router'\n\nfunction renderIcon(icon: Component) {\n  return () => h(NIcon, null, { default: () => h(icon) })\n}\n\nconst menuOptions: MenuOption[] = [\n  {\n    label: () =>\n      h(\n        RouterLink,\n        {\n          to: {\n            name: 'home',\n            params: {\n              lang: 'zh-CN'\n            }\n          }\n        },\n        { default: () => 'Go Home' }\n      ),\n    key: 'go-back-home',\n    icon: renderIcon(HomeIcon)\n  },\n  {\n    label: () =>\n      h(\n        RouterLink,\n        {\n          to: {\n            path: '/zh-CN/os-theme/components/code'\n          }\n        },\n        { default: () => 'Go to work' }\n      ),\n    key: 'go-to-work',\n    icon: renderIcon(WorkIcon)\n  }\n]\n</script>\n\n<template>\n  <n-menu :options=\"menuOptions\" />\n</template>\n"
  },
  {
    "path": "src/menu/demos/enUS/select.demo.vue",
    "content": "<markdown>\n# Select & routing\n\nUsually you can use vue-router here to accomplish routing. Also, you can render `label` as `<router-link />` or `<a />` to set route.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { MenuOption } from 'naive-ui'\nimport type { Component } from 'vue'\nimport {\n  BookOutline as BookIcon,\n  HomeOutline as HomeIcon,\n  PersonOutline as PersonIcon,\n  WineOutline as WineIcon\n} from '@vicons/ionicons5'\nimport { NIcon, useMessage } from 'naive-ui'\nimport { h } from 'vue'\nimport { RouterLink } from 'vue-router'\n\nfunction renderIcon(icon: Component) {\n  return () => h(NIcon, null, { default: () => h(icon) })\n}\n\nconst menuOptions: MenuOption[] = [\n  {\n    label: () =>\n      h(\n        RouterLink,\n        {\n          to: {\n            name: 'home',\n            params: {\n              lang: 'en-US'\n            }\n          }\n        },\n        { default: () => 'Going Home' }\n      ),\n    key: 'go-back-home',\n    icon: renderIcon(HomeIcon)\n  },\n  {\n    key: 'divider-1',\n    type: 'divider',\n    props: {\n      style: {\n        marginLeft: '32px'\n      }\n    }\n  },\n  {\n    label: () =>\n      h(\n        'a',\n        {\n          href: 'https://en.wikipedia.org/wiki/Hear_the_Wind_Sing',\n          target: '_blank',\n          rel: 'noopenner noreferrer'\n        },\n        'Hear the Wind Sing'\n      ),\n    key: 'hear-the-wind-sing',\n    icon: renderIcon(BookIcon)\n  },\n  {\n    label: 'Pinball 1973',\n    key: 'pinball-1973',\n    icon: renderIcon(BookIcon),\n    disabled: true,\n    children: [\n      {\n        label: 'Rat',\n        key: 'rat'\n      }\n    ]\n  },\n  {\n    label: 'A Wild Sheep Chase',\n    key: 'a-wild-sheep-chase',\n    disabled: true,\n    icon: renderIcon(BookIcon)\n  },\n  {\n    label: 'Dance Dance Dance',\n    key: 'Dance Dance Dance',\n    icon: renderIcon(BookIcon),\n    children: [\n      {\n        type: 'group',\n        label: 'People',\n        key: 'people',\n        children: [\n          {\n            label: 'Narrator',\n            key: 'narrator',\n            icon: renderIcon(PersonIcon)\n          },\n          {\n            label: 'Sheep Man',\n            key: 'sheep-man',\n            icon: renderIcon(PersonIcon)\n          }\n        ]\n      },\n      {\n        label: 'Beverage',\n        key: 'beverage',\n        icon: renderIcon(WineIcon),\n        children: [\n          {\n            label: 'Whisky',\n            key: 'whisky'\n          }\n        ]\n      },\n      {\n        label: 'Food',\n        key: 'food',\n        children: [\n          {\n            label: 'Sandwich',\n            key: 'sandwich'\n          }\n        ]\n      },\n      {\n        label: 'The past increases. The future recedes.',\n        key: 'the-past-increases-the-future-recedes'\n      }\n    ]\n  }\n]\n\nconst message = useMessage()\n\nfunction handleUpdateValue(key: string, item: MenuOption) {\n  message.info(`[onUpdate:value]: ${JSON.stringify(key)}`)\n  message.info(`[onUpdate:value]: ${JSON.stringify(item)}`)\n}\n</script>\n\n<template>\n  <n-menu :options=\"menuOptions\" @update:value=\"handleUpdateValue\" />\n</template>\n"
  },
  {
    "path": "src/menu/demos/enUS/show.demo.vue",
    "content": "<markdown>\n# Control option visibility\n\nIn some cases, different roles will see different options. You can use the `show` field to control the visibility of menu options.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { Component } from 'vue'\nimport {\n  BookOutline as BookIcon,\n  PersonOutline as PersonIcon\n} from '@vicons/ionicons5'\nimport { NIcon } from 'naive-ui'\nimport { computed, h, ref } from 'vue'\n\nconst accordion = ref(false)\n\nfunction renderIcon(icon: Component) {\n  return () => h(NIcon, null, { default: () => h(icon) })\n}\n\nconst options = computed(() => [\n  {\n    label: 'parent 1',\n    icon: renderIcon(PersonIcon),\n    key: '1',\n    children: [\n      {\n        label: '1.1',\n        key: '2'\n      }\n    ]\n  },\n  {\n    label: 'parent 2',\n    key: '3',\n    icon: renderIcon(BookIcon),\n    show: !accordion.value,\n    children: [\n      {\n        label: '2.1',\n        key: '4'\n      },\n      {\n        label: '2.2',\n        key: '5'\n      },\n      {\n        label: '2.3',\n        key: '6'\n      }\n    ]\n  }\n])\n</script>\n\n<template>\n  <n-space vertical>\n    <n-switch v-model:value=\"accordion\">\n      <template #checked>\n        Hide menu\n      </template>\n      <template #unchecked>\n        Show menu\n      </template>\n    </n-switch>\n    <n-menu :options=\"options\" />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/menu/demos/zhCN/accordion.demo.vue",
    "content": "<markdown>\n# 手风琴\n\n像一个手风琴。使用 `accordion` 属性对一级菜单使用该模式。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { MenuOption } from 'naive-ui'\nimport type { Component } from 'vue'\nimport {\n  BagOutline as BagOutlineIcon,\n  FishOutline as FishIcon,\n  PawOutline as PawIcon\n} from '@vicons/ionicons5'\nimport { NIcon } from 'naive-ui'\nimport { h } from 'vue'\n\nfunction renderIcon(icon: Component) {\n  return () => h(NIcon, null, { default: () => h(icon) })\n}\n\nconst menuOptions: MenuOption[] = [\n  {\n    label: '鱼',\n    key: 'fish',\n    icon: renderIcon(FishIcon),\n    children: [\n      {\n        label: '红烧',\n        key: 'braise',\n        children: [\n          {\n            label: '加辣',\n            key: 'spicy'\n          }\n        ]\n      },\n      {\n        label: '清蒸',\n        key: 'steamed',\n        children: [\n          {\n            label: '不要葱',\n            key: 'no-green-onion'\n          }\n        ]\n      }\n    ]\n  },\n  {\n    label: '熊掌',\n    key: 'bear-paw',\n    icon: renderIcon(PawIcon),\n    children: [\n      {\n        label: '保护野生动物',\n        key: 'protect-wild-animals'\n      }\n    ]\n  },\n  {\n    label: '两个都要',\n    key: 'both',\n    icon: renderIcon(BagOutlineIcon),\n    children: [\n      {\n        label: '鱼和熊掌不可兼得',\n        key: 'can-not'\n      }\n    ]\n  }\n]\n\nconst defaultExpandedKeys = ['fish', 'braise']\n</script>\n\n<template>\n  <n-menu\n    :options=\"menuOptions\"\n    :default-expanded-keys=\"defaultExpandedKeys\"\n    accordion\n  />\n</template>\n"
  },
  {
    "path": "src/menu/demos/zhCN/collapse.demo.vue",
    "content": "<markdown>\n# 压缩菜单\n\n可以让垂直菜单随着边栏压缩。使用 `collapsed` 属性控制菜单状态。必需设定 `collapsed-width` 来确保菜单正常显示。除此之外还有一些其他和压缩有关的属性：`icon-size`、`collapsed-icon-size`。详细信息参考页面底下的 API 文档。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { MenuOption } from 'naive-ui'\nimport type { Component } from 'vue'\nimport {\n  BookOutline as BookIcon,\n  PersonOutline as PersonIcon,\n  WineOutline as WineIcon\n} from '@vicons/ionicons5'\nimport { NIcon } from 'naive-ui'\nimport { h, ref } from 'vue'\n\nfunction renderIcon(icon: Component) {\n  return () => h(NIcon, null, { default: () => h(icon) })\n}\n\nconst menuOptions: MenuOption[] = [\n  {\n    label: '且听风吟',\n    key: 'hear-the-wind-sing',\n    icon: renderIcon(BookIcon)\n  },\n  {\n    label: '1973年的弹珠玩具',\n    key: 'pinball-1973',\n    icon: renderIcon(BookIcon),\n    disabled: true,\n    children: [\n      {\n        label: '鼠',\n        key: 'rat'\n      }\n    ]\n  },\n  {\n    label: '寻羊冒险记',\n    key: 'a-wild-sheep-chase',\n    disabled: true,\n    icon: renderIcon(BookIcon)\n  },\n  {\n    label: '舞，舞，舞',\n    key: 'dance-dance-dance',\n    icon: renderIcon(BookIcon),\n    children: [\n      {\n        type: 'group',\n        label: '人物',\n        key: 'people',\n        children: [\n          {\n            label: '叙事者',\n            key: 'narrator',\n            icon: renderIcon(PersonIcon)\n          },\n          {\n            label: '羊男',\n            key: 'sheep-man',\n            icon: renderIcon(PersonIcon)\n          }\n        ]\n      },\n      {\n        label: '饮品',\n        key: 'beverage',\n        icon: renderIcon(WineIcon),\n        children: [\n          {\n            label: '威士忌',\n            key: 'whisky'\n          }\n        ]\n      },\n      {\n        label: '食物',\n        key: 'food',\n        children: [\n          {\n            label: '三明治',\n            key: 'sandwich'\n          }\n        ]\n      },\n      {\n        label: '过去增多，未来减少',\n        key: 'the-past-increases-the-future-recedes'\n      }\n    ]\n  }\n]\n\nconst activeKey = ref<string | null>(null)\nconst collapsed = ref(true)\n</script>\n\n<template>\n  <n-space vertical>\n    <n-switch v-model:value=\"collapsed\" />\n    <n-layout has-sider>\n      <n-layout-sider\n        bordered\n        collapse-mode=\"width\"\n        :collapsed-width=\"64\"\n        :width=\"240\"\n        :collapsed=\"collapsed\"\n        show-trigger\n        @collapse=\"collapsed = true\"\n        @expand=\"collapsed = false\"\n      >\n        <n-menu\n          v-model:value=\"activeKey\"\n          :collapsed=\"collapsed\"\n          :collapsed-width=\"64\"\n          :collapsed-icon-size=\"22\"\n          :options=\"menuOptions\"\n        />\n      </n-layout-sider>\n      <n-layout>\n        <span>内容</span>\n      </n-layout>\n    </n-layout>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/menu/demos/zhCN/customize-field.demo.vue",
    "content": "<markdown>\n# 自定义字段\n\n后端会传来各种各样的数据，你可以自定义 `key`、`label` 和 `children` 的字段。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { MenuOption } from 'naive-ui'\nimport type { Component } from 'vue'\nimport {\n  BookOutline as BookIcon,\n  PersonOutline as PersonIcon,\n  WineOutline as WineIcon\n} from '@vicons/ionicons5'\nimport { NIcon } from 'naive-ui'\nimport { h, ref } from 'vue'\n\nfunction renderIcon(icon: Component) {\n  return () => h(NIcon, null, { default: () => h(icon) })\n}\n\nconst menuOptions: MenuOption[] = [\n  {\n    whateverLabel: '且听风吟',\n    whateverKey: 'hear-the-wind-sing',\n    icon: renderIcon(BookIcon)\n  },\n  {\n    whateverLabel: '1973年的弹珠玩具',\n    whateverKey: 'pinball-1973',\n    icon: renderIcon(BookIcon),\n    disabled: true,\n    whateverChildren: [\n      {\n        whateverLabel: '鼠',\n        whateverKey: 'rat'\n      }\n    ]\n  },\n  {\n    whateverLabel: '寻羊冒险记',\n    whateverKey: 'a-wild-sheep-chase',\n    disabled: true,\n    icon: renderIcon(BookIcon)\n  },\n  {\n    whateverLabel: '舞，舞，舞',\n    whateverKey: 'dance-dance-dance',\n    icon: renderIcon(BookIcon),\n    whateverChildren: [\n      {\n        type: 'group',\n        whateverLabel: '人物',\n        whateverKey: 'people',\n        whateverChildren: [\n          {\n            whateverLabel: '叙事者',\n            whateverKey: 'narrator',\n            icon: renderIcon(PersonIcon)\n          },\n          {\n            whateverLabel: '羊男',\n            whateverKey: 'sheep-man',\n            icon: renderIcon(PersonIcon)\n          }\n        ]\n      },\n      {\n        whateverLabel: '饮品',\n        whateverKey: 'beverage',\n        icon: renderIcon(WineIcon),\n        whateverChildren: [\n          {\n            whateverLabel: '威士忌',\n            whateverKey: 'whisky'\n          }\n        ]\n      },\n      {\n        whateverLabel: '食物',\n        whateverKey: 'food',\n        whateverChildren: [\n          {\n            whateverLabel: '三明治',\n            whateverKey: 'sandwich'\n          }\n        ]\n      },\n      {\n        whateverLabel: '过去增多，未来减少',\n        whateverKey: 'the-past-increases-the-future-recedes'\n      }\n    ]\n  }\n]\n\nconst collapsed = ref(true)\n</script>\n\n<template>\n  <n-layout has-sider>\n    <n-layout-sider\n      bordered\n      collapse-mode=\"width\"\n      :collapsed-width=\"64\"\n      :width=\"240\"\n      :collapsed=\"collapsed\"\n      show-trigger\n      @collapse=\"collapsed = true\"\n      @expand=\"collapsed = false\"\n    >\n      <n-menu\n        :collapsed=\"collapsed\"\n        :collapsed-width=\"64\"\n        :collapsed-icon-size=\"22\"\n        :options=\"menuOptions\"\n        key-field=\"whateverKey\"\n        label-field=\"whateverLabel\"\n        children-field=\"whateverChildren\"\n      />\n    </n-layout-sider>\n    <n-layout />\n  </n-layout>\n</template>\n"
  },
  {
    "path": "src/menu/demos/zhCN/debug.demo.vue",
    "content": "<markdown>\n# Debug\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { MenuOption } from 'naive-ui'\nimport type { Component } from 'vue'\nimport { BookOutline as BookIcon } from '@vicons/ionicons5'\nimport { NButton, NIcon, useMessage } from 'naive-ui'\nimport { h } from 'vue'\n\nfunction renderIcon(icon: Component) {\n  return () => h(NIcon, null, { default: () => h(icon) })\n}\n\nconst menuOptions: MenuOption[] = [\n  {\n    label: 'Hear the Wind Sing',\n    key: 'hear-the-wind-sing',\n    extra: () => h(NButton, {}, () => ' debug test'),\n    icon: renderIcon(BookIcon)\n  },\n  {\n    label: 'Pinball 1973',\n    key: 'pinball-1973',\n    extra: () => h(NButton, {}, () => 'debug 1937'),\n    children: [\n      {\n        label: 'Rat',\n        extra: '24',\n        key: 'rat'\n      }\n    ]\n  }\n]\n\nconst message = useMessage()\nconst defaultExpandedKeys = ['dance-dance-dance', 'food']\n\nfunction handleUpdateExpandedKeys(value: string[]) {\n  message.info(`[onUpdate:expandedKeys]: ${JSON.stringify(value)}`)\n}\n</script>\n\n<template>\n  <n-menu\n    :options=\"menuOptions\"\n    :default-expanded-keys=\"defaultExpandedKeys\"\n    @update:expanded-keys=\"handleUpdateExpandedKeys\"\n  />\n</template>\n"
  },
  {
    "path": "src/menu/demos/zhCN/default-expanded-keys.demo.vue",
    "content": "<markdown>\n# 展开子菜单\n\n如果你不设定 `default-expanded-keys`，菜单会默认展开选中项的全部父级。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { MenuOption } from 'naive-ui'\nimport type { Component } from 'vue'\nimport {\n  BookOutline as BookIcon,\n  PersonOutline as PersonIcon,\n  WineOutline as WineIcon\n} from '@vicons/ionicons5'\nimport { NIcon, useMessage } from 'naive-ui'\nimport { h } from 'vue'\n\nfunction renderIcon(icon: Component) {\n  return () => h(NIcon, null, { default: () => h(icon) })\n}\n\nconst menuOptions: MenuOption[] = [\n  {\n    label: '且听风吟',\n    key: 'hear-the-wind-sing',\n    icon: renderIcon(BookIcon)\n  },\n  {\n    label: '1973年的弹珠玩具',\n    key: 'pinball-1973',\n    icon: renderIcon(BookIcon),\n    disabled: true,\n    children: [\n      {\n        label: '鼠',\n        key: 'rat'\n      }\n    ]\n  },\n  {\n    label: '寻羊冒险记',\n    key: 'a-wild-sheep-chase',\n    icon: renderIcon(BookIcon),\n    disabled: true\n  },\n  {\n    label: '舞，舞，舞',\n    key: 'dance-dance-dance',\n    icon: renderIcon(BookIcon),\n    children: [\n      {\n        type: 'group',\n        label: '人物',\n        key: 'people',\n        children: [\n          {\n            label: '叙事者',\n            key: 'narrator',\n            icon: renderIcon(PersonIcon)\n          },\n          {\n            label: '羊男',\n            key: 'sheep-man',\n            icon: renderIcon(PersonIcon)\n          }\n        ]\n      },\n      {\n        label: '饮品',\n        key: 'beverage',\n        icon: renderIcon(WineIcon),\n        children: [\n          {\n            label: '威士忌',\n            key: 'whisky'\n          }\n        ]\n      },\n      {\n        label: '食物',\n        key: 'food',\n        children: [\n          {\n            label: '三明治',\n            key: 'sandwich'\n          }\n        ]\n      },\n      {\n        label: '过去增多，未来减少',\n        key: 'the-past-increases-the-future-recedes'\n      }\n    ]\n  }\n]\n\nconst message = useMessage()\nconst defaultExpandedKeys = ['dance-dance-dance', 'food']\n\nfunction handleUpdateExpandedKeys(keys: string[]) {\n  message.info(`[onUpdate:expandedKeys]: ${JSON.stringify(keys)}`)\n}\n</script>\n\n<template>\n  <n-menu\n    :options=\"menuOptions\"\n    :default-expanded-keys=\"defaultExpandedKeys\"\n    @update:expanded-keys=\"handleUpdateExpandedKeys\"\n  />\n</template>\n"
  },
  {
    "path": "src/menu/demos/zhCN/expand-selected-option.demo.vue",
    "content": "<markdown>\n# 展开选中的值\n\n在某些场景下，菜单的值是由外部传入的，组件很难理解用户展开的意图。你可以使用 `showOption` 的方法来让选中的值展开。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { MenuInst } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst accordionRef = ref(false)\nconst selectedKeyRef = ref('难吃')\nconst menuInstRef = ref<MenuInst | null>(null)\n\nfunction selectAndExpand(key: string) {\n  selectedKeyRef.value = key\n  menuInstRef.value?.showOption(key)\n}\n\nconst accordion = accordionRef\nconst selectedKey = selectedKeyRef\nconst options = [\n  {\n    label: '学五',\n    key: '学五',\n    children: [\n      {\n        label: '难吃',\n        key: '难吃'\n      }\n    ]\n  },\n  {\n    label: '学一',\n    key: '学一',\n    children: [\n      {\n        label: '也难吃',\n        key: '也难吃'\n      }\n    ]\n  },\n  {\n    label: '燕南',\n    key: '燕南',\n    children: [\n      {\n        label: '依然难吃',\n        key: '依然难吃'\n      }\n    ]\n  }\n]\n</script>\n\n<template>\n  <n-space vertical>\n    <n-switch v-model:value=\"accordion\">\n      <template #checked>\n        手风琴\n      </template>\n      <template #unchecked>\n        普通\n      </template>\n    </n-switch>\n    <n-button @click=\"selectAndExpand('难吃')\">\n      选中第一项\n    </n-button>\n    <n-button @click=\"selectAndExpand('也难吃')\">\n      选中第二项\n    </n-button>\n    <n-button @click=\"selectAndExpand('依然难吃')\">\n      选中第三项\n    </n-button>\n    <n-menu\n      ref=\"menuInstRef\"\n      v-model:value=\"selectedKey\"\n      :options=\"options\"\n      :accordion=\"accordion\"\n    />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/menu/demos/zhCN/horizontal.demo.vue",
    "content": "<markdown>\n# 水平菜单\n\n一个水平菜单，可以自动折叠。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { MenuOption } from 'naive-ui'\nimport type { Component } from 'vue'\nimport {\n  BookOutline as BookIcon,\n  PersonOutline as PersonIcon,\n  WineOutline as WineIcon\n} from '@vicons/ionicons5'\nimport { NIcon } from 'naive-ui'\nimport { h, ref } from 'vue'\n\nfunction renderIcon(icon: Component) {\n  return () => h(NIcon, null, { default: () => h(icon) })\n}\n\nconst menuOptions: MenuOption[] = [\n  {\n    label: () =>\n      h(\n        'a',\n        {\n          href: 'https://baike.baidu.com/item/%E4%B8%94%E5%90%AC%E9%A3%8E%E5%90%9F',\n          target: '_blank',\n          rel: 'noopenner noreferrer'\n        },\n        '且听风吟'\n      ),\n    key: 'hear-the-wind-sing',\n    icon: renderIcon(BookIcon)\n  },\n  {\n    label: '1973年的弹珠玩具',\n    key: 'pinball-1973',\n    icon: renderIcon(BookIcon),\n    disabled: true,\n    children: [\n      {\n        label: '鼠',\n        key: 'rat'\n      }\n    ]\n  },\n  {\n    label: '寻羊冒险记',\n    key: 'a-wild-sheep-chase',\n    icon: renderIcon(BookIcon),\n    disabled: true\n  },\n  {\n    label: '舞，舞，舞',\n    key: 'dance-dance-dance',\n    icon: renderIcon(BookIcon),\n    children: [\n      {\n        type: 'group',\n        label: '人物',\n        key: 'people',\n        children: [\n          {\n            label: '叙事者',\n            key: 'narrator',\n            icon: renderIcon(PersonIcon)\n          },\n          {\n            label: '羊男',\n            key: 'sheep-man',\n            icon: renderIcon(PersonIcon)\n          }\n        ]\n      },\n      {\n        label: '饮品',\n        key: 'beverage',\n        icon: renderIcon(WineIcon),\n        children: [\n          {\n            label: '威士忌',\n            key: 'whisky'\n          }\n        ]\n      },\n      {\n        label: '食物',\n        key: 'food',\n        children: [\n          {\n            label: '三明治',\n            key: 'sandwich'\n          }\n        ]\n      },\n      {\n        label: '过去增多，未来减少',\n        key: 'the-past-increases-the-future-recedes'\n      }\n    ]\n  }\n]\n\nconst activeKey = ref<string | null>(null)\n</script>\n\n<template>\n  <n-split :default-size=\"0.8\">\n    <template #1>\n      <n-menu\n        v-model:value=\"activeKey\"\n        mode=\"horizontal\"\n        :options=\"menuOptions\"\n        responsive\n      />\n    </template>\n  </n-split>\n</template>\n"
  },
  {
    "path": "src/menu/demos/zhCN/indent.demo.vue",
    "content": "<markdown>\n# 缩进\n\n你可以设定菜单的 `indent` & `root-indent`。`root-indent` 只决定第一层项目的缩进。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { MenuOption } from 'naive-ui'\nimport type { Component } from 'vue'\nimport {\n  BookOutline as BookIcon,\n  PersonOutline as PersonIcon,\n  WineOutline as WineIcon\n} from '@vicons/ionicons5'\nimport { NIcon } from 'naive-ui'\nimport { h, ref } from 'vue'\n\nfunction renderIcon(icon: Component) {\n  return () => h(NIcon, null, { default: () => h(icon) })\n}\n\nconst menuOptions: MenuOption[] = [\n  {\n    label: '且听风吟',\n    key: 'hear-the-wind-sing',\n    icon: renderIcon(BookIcon)\n  },\n  {\n    label: '1973年的弹珠玩具',\n    key: 'pinball-1973',\n    icon: renderIcon(BookIcon),\n    disabled: true,\n    children: [\n      {\n        label: '鼠',\n        key: 'rat'\n      }\n    ]\n  },\n  {\n    label: '寻羊冒险记',\n    key: 'a-wild-sheep-chase',\n    icon: renderIcon(BookIcon),\n    disabled: true\n  },\n  {\n    label: '舞，舞，舞',\n    key: 'dance-dance-dance',\n    icon: renderIcon(BookIcon),\n    children: [\n      {\n        type: 'group',\n        label: '人物',\n        key: 'people',\n        children: [\n          {\n            label: '叙事者',\n            key: 'narrator',\n            icon: renderIcon(PersonIcon)\n          },\n          {\n            label: '羊男',\n            key: 'sheep-man',\n            icon: renderIcon(PersonIcon)\n          }\n        ]\n      },\n      {\n        label: '饮品',\n        key: 'beverage',\n        icon: renderIcon(WineIcon),\n        children: [\n          {\n            label: '威士忌',\n            key: 'whisky'\n          }\n        ]\n      },\n      {\n        label: '食物',\n        key: 'food',\n        children: [\n          {\n            label: '三明治',\n            key: 'sandwich'\n          }\n        ]\n      },\n      {\n        label: '过去增多，未来减少',\n        key: 'the-past-increases-the-future-recedes'\n      }\n    ]\n  }\n]\n\nconst activeKey = ref<string | null>(null)\n</script>\n\n<template>\n  <n-menu\n    v-model:value=\"activeKey\"\n    :root-indent=\"36\"\n    :indent=\"12\"\n    :options=\"menuOptions\"\n  />\n</template>\n"
  },
  {
    "path": "src/menu/demos/zhCN/index.demo-entry.md",
    "content": "# 菜单 Menu\n\n没有吃的。\n\n<!--single-column-->\n\n## 演示\n\n```demo\nhorizontal.vue\nselect.vue\nrender-label.vue\ndefault-expanded-keys.vue\nindent.vue\ncollapse.vue\ninverted.vue\nlong-label.vue\naccordion.vue\nrouter-link.vue\ncustomize-field.vue\nexpand-selected-option.vue\nshow.vue\ndebug.vue\nshow-debug.vue\n```\n\n## API\n\n### Menu Props\n\n| 名称 | 类型 | 默认值 | 说明 | 版本 |\n| --- | --- | --- | --- | --- |\n| accordion | `boolean` | `false` | 是否使用手风琴模式 |  |\n| children-field | `string` | `'children'` | children 的字段名 |  |\n| collapsed-icon-size | `number` | `24` | 菜单折叠时图标的大小，如果未设定则使用 `icon-size` 代替 |  |\n| collapsed-width | `number` | `48` | 折叠后菜单的宽度 |  |\n| collapsed | `boolean` | `false` | 菜单是否折叠，值在菜单为垂直时有用 |  |\n| default-expand-all | `boolean` | `false` | 是否展开全部菜单，`options` 为异步获取时，`watch-props` 需要设置为 `['defaultExpandedKeys']` 才会生效 |  |\n| default-expanded-keys | `Array<string>` | `[]` | 在非受控状态下默认展开的子菜单标识符数组 |  |\n| default-value | `string \\| null` | `null` | 非受控模式下的默认值 |  |\n| disabled-field | `string` | `'disabled'` | disabled 的字段名 | 2.33.0 |\n| dropdown-placement | `'top-start' \\| 'top' \\| 'top-end' \\| 'right-start' \\| 'right' \\| 'right-end' \\| 'bottom-start' \\| 'bottom' \\| 'bottom-end' \\| 'left-start' \\| 'left' \\| 'left-end' \\| ` | `'top'` | 仅在 `mode='horizontal'` 模式下生效 |  |\n| dropdown-props | `DropdownProps` | `undefined` | 菜单折叠或 `mode='horizontal'` 模式时 Dropdown 的 props，请参考 [Dropdown Props](dropdown#Dropdown-Props) |  |\n| expanded-keys | `Array<string>` | `undefined` | 展开的子菜单标识符数组，如果设定了，菜单的展开将会进入受控状态，`default-expanded-keys` 不会生效 |  |\n| expand-icon | `(option: MenuOption) => VNodeChild` | `undefined` | 批量处理菜单展开图标的渲染 |  |\n| icon-size | `number` | `20` | 菜单未折叠时图标的大小 |  |\n| indent | `number` | `32` | 菜单每级的缩进 |  |\n| inverted | `boolean` | `false` | 使用反转样式 |  |\n| key-field | `string` | `'key'` | key 的字段名 |  |\n| label-field | `string` | `'label'` | label 的字段名 |  |\n| options | `Array<MenuOption \\| MenuDividerOption \\| MenuGroupOption>` | `[]` | 菜单的数据 |  |\n| node-props | `(option: MenuOption \\| MenuGroupOption) => object` | `undefined` | 节点的 DOM 属性生成函数 | 2.28.3 |\n| mode | `'vertical' \\| 'horizontal'` | `'vertical'` | 菜单的布局方式 |  |\n| render-extra | `(option: MenuOption \\| MenuGroupOption) => VNodeChild` | `undefined` | 批量处理菜单额外部分渲染 |  |\n| render-icon | `(option: MenuOption) => VNodeChild` | `undefined` | 批量处理菜单图标渲染 |  |\n| render-label | `(option: MenuOption \\| MenuGroupOption) => VNodeChild` | `undefined` | 批量处理菜单标签渲染 |  |\n| responsive | `boolean` | `false` | 是否收起溢出的菜单，仅对 `mode='horizontal'` 的菜单生效 | 2.36.0 |\n| root-indent | `number` | `32` | 菜单第一级的缩进，如果没有设定，使用 `indent` 代替 |  |\n| value | `string \\| null` | `undefined` | 菜单当前的选中值 |  |\n| watch-props | `Array<'defaultValue' \\| 'defaultExpandedKeys'>` | `undefined` | 需要检测变更的默认属性，检测后组件状态会更新。注意：`watch-props` 本身不是响应式的 |  |\n| on-update:expanded-keys | `(keys: string[]) => void` | `undefined` | `keys` 是展开菜单项的 `key` 的数组 |  |\n| on-update:value | `(key: string, item: MenuOption) => void` | `undefined` | 选中菜单的回调，`key` 是选中菜单项的 `key`，`item` 是菜单项原始数据 |  |\n\n#### MenuOption Properties\n\n| 名称 | 类型 | 说明 | 版本 |\n| --- | --- | --- | --- |\n| children? | `Array<MenuOption \\| MenuGroupOption>` | 子选项 |  |\n| disabled? | `boolean` | 是否禁用菜单项 |  |\n| extra? | `string \\| (() => VNodeChild)` | 菜单项的额外部分 |  |\n| icon? | `() => VNode` | 菜单项的图标 |  |\n| key | `string` | 菜单项的标识符 |  |\n| label | `string \\| (() => VNodeChild)` | 菜单项的内容 |  |\n| show? | `boolean` | 是否显示菜单项 | 2.32.2 |\n\n#### MenuGroupOption Properties\n\n| 名称 | 类型 | 说明 | 版本 |\n| --- | --- | --- | --- |\n| children | `Array<MenuOption \\| MenuGroupOption>` | 子菜单，**必填！** |  |\n| key | `string` | 菜单项的标识符 |  |\n| label | `string \\| (() => VNodeChild)` | 菜单项的内容 |  |\n| show? | `boolean` | 是否显示菜单项 | 2.32.2 |\n| type | `'group'` | 菜单项的类型，**必填！** |  |\n\n#### MenuDividerOption Properties\n\n| 名称  | 类型             | 说明                     | 版本   |\n| ----- | ---------------- | ------------------------ | ------ |\n| key   | `string`         | 菜单项的标识符           |        |\n| props | `HTMLAttributes` | 分割线的属性             |        |\n| show? | `boolean`        | 是否显示菜单项           | 2.32.2 |\n| type  | `'divider'`      | 菜单项的类型，**必填！** |        |\n\n### Menu Methods\n\n| 名称 | 类型 | 说明 | 版本 |\n| --- | --- | --- | --- |\n| deriveResponsiveState | `() => void` | 重新计算响应式菜单内容折叠状态。在菜单容器宽度并不完全由外部宽度决定的时候，在 `responsive` 情况下，菜单内容收起后无法自动展开，此时你可以调用此方法以保证菜单可以重新展开 | 2.36.0 |\n| showOption | `(key?: string \\| number) => void` | 展开菜单，确保设定的元素被显示，如果不传入 `key` 会展示当前选中元素 | 2.27.0 |\n"
  },
  {
    "path": "src/menu/demos/zhCN/inverted.demo.vue",
    "content": "<markdown>\n# 反转\n\n通过 `inverted` 来增加对比，一般和 `n-layout` 配合使用。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { MenuOption } from 'naive-ui'\nimport type { Component } from 'vue'\nimport {\n  BookOutline as BookIcon,\n  PersonOutline as PersonIcon,\n  WineOutline as WineIcon\n} from '@vicons/ionicons5'\nimport { NIcon } from 'naive-ui'\nimport { h, ref } from 'vue'\n\nfunction renderIcon(icon: Component) {\n  return () => h(NIcon, null, { default: () => h(icon) })\n}\n\nconst menuOptions: MenuOption[] = [\n  {\n    label: '且听风吟',\n    key: 'hear-the-wind-sing',\n    icon: renderIcon(BookIcon)\n  },\n  {\n    label: '1973年的弹珠玩具',\n    key: 'pinball-1973',\n    icon: renderIcon(BookIcon),\n    disabled: true,\n    children: [\n      {\n        label: '鼠',\n        key: 'rat'\n      }\n    ]\n  },\n  {\n    label: '寻羊冒险记',\n    key: 'a-wild-sheep-chase',\n    disabled: true,\n    icon: renderIcon(BookIcon)\n  },\n  {\n    label: '舞，舞，舞',\n    key: 'dance-dance-dance',\n    icon: renderIcon(BookIcon),\n    children: [\n      {\n        type: 'group',\n        label: '人物',\n        key: 'people',\n        children: [\n          {\n            label: '叙事者',\n            key: 'narrator',\n            icon: renderIcon(PersonIcon)\n          },\n          {\n            label: '羊男',\n            key: 'sheep-man',\n            icon: renderIcon(PersonIcon)\n          }\n        ]\n      },\n      {\n        label: '饮品',\n        key: 'beverage',\n        icon: renderIcon(WineIcon),\n        children: [\n          {\n            label: '威士忌',\n            key: 'whisky'\n          }\n        ]\n      },\n      {\n        label: '食物',\n        key: 'food',\n        children: [\n          {\n            label: '三明治',\n            key: 'sandwich'\n          }\n        ]\n      },\n      {\n        label: '过去增多，未来减少',\n        key: 'the-past-increases-the-future-recedes'\n      }\n    ]\n  }\n]\n\nconst inverted = ref(false)\n</script>\n\n<template>\n  <n-space vertical>\n    <n-space> <n-switch v-model:value=\"inverted\" />inverted</n-space>\n    <n-layout has-sider>\n      <n-layout-sider\n        bordered\n        collapse-mode=\"width\"\n        :collapsed-width=\"64\"\n        :width=\"240\"\n        show-trigger\n        :inverted=\"inverted\"\n      >\n        <n-menu\n          :inverted=\"inverted\"\n          :collapsed-width=\"64\"\n          :collapsed-icon-size=\"22\"\n          :options=\"menuOptions\"\n        />\n      </n-layout-sider>\n      <n-layout>\n        <span>内容</span>\n      </n-layout>\n    </n-layout>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/menu/demos/zhCN/long-label.demo.vue",
    "content": "<markdown>\n# 菜单内容很长\n\n将 `label` 设为渲染函数，结合 `n-ellipsis`。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { MenuOption } from 'naive-ui'\nimport { NEllipsis } from 'naive-ui'\nimport { h } from 'vue'\n\nconst options: MenuOption[] = [\n  {\n    label: () =>\n      h(NEllipsis, null, { default: () => '电灯熄灭 物换星移 泥牛入海' }),\n    key: '1'\n  },\n  {\n    label: () =>\n      h(NEllipsis, null, { default: () => '黑暗好像 一颗巨石 按在胸口' }),\n    key: '2'\n  }\n]\n</script>\n\n<template>\n  <n-menu :options=\"options\" style=\"width: 180px\" default-value=\"1\" />\n</template>\n"
  },
  {
    "path": "src/menu/demos/zhCN/render-label.demo.vue",
    "content": "<markdown>\n# 批量处理菜单渲染\n\n使用 `render-label`、`render-icon`、`expand-icon` 可以批量控制菜单的选项渲染。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { MenuOption } from 'naive-ui'\nimport { BookmarkOutline, CaretDownOutline } from '@vicons/ionicons5'\nimport { NIcon } from 'naive-ui'\nimport { h, ref } from 'vue'\n\nconst menuOptions: MenuOption[] = [\n  {\n    label: '且听风吟',\n    key: 'hear-the-wind-sing',\n    href: 'https://baike.baidu.com/item/%E4%B8%94%E5%90%AC%E9%A3%8E%E5%90%9F/3199'\n  },\n  {\n    label: '1973年的弹珠玩具',\n    key: 'pinball-1973',\n    disabled: true,\n    children: [\n      {\n        label: '鼠',\n        key: 'rat'\n      }\n    ]\n  },\n  {\n    label: '寻羊冒险记',\n    key: 'a-wild-sheep-chase',\n    disabled: true\n  },\n  {\n    label: '舞，舞，舞',\n    key: 'dance-dance-dance',\n    children: [\n      {\n        type: 'group',\n        label: '人物',\n        key: 'people',\n        children: [\n          {\n            label: '叙事者',\n            key: 'narrator'\n          },\n          {\n            label: '羊男',\n            key: 'sheep-man'\n          }\n        ]\n      },\n      {\n        label: '饮品',\n        key: 'beverage',\n        children: [\n          {\n            label: '威士忌',\n            key: 'whisky',\n            href: 'https://baike.baidu.com/item/%E5%A8%81%E5%A3%AB%E5%BF%8C%E9%85%92/2959816?fromtitle=%E5%A8%81%E5%A3%AB%E5%BF%8C&fromid=573&fr=aladdin'\n          }\n        ]\n      },\n      {\n        label: '食物',\n        key: 'food',\n        children: [\n          {\n            label: '三明治',\n            key: 'sandwich'\n          }\n        ]\n      },\n      {\n        label: '过去增多，未来减少',\n        key: 'the-past-increases-the-future-recedes'\n      }\n    ]\n  }\n]\n\nconst collapsed = ref(true)\n\nfunction renderMenuLabel(option: MenuOption) {\n  if ('href' in option) {\n    return h(\n      'a',\n      { href: option.href, target: '_blank' },\n      option.label as string\n    )\n  }\n  return option.label as string\n}\n\nfunction renderMenuIcon(option: MenuOption) {\n  // 渲染图标占位符以保持缩进\n  if (option.key === 'sheep-man')\n    return true\n  // 返回 falsy 值，不再渲染图标及占位符\n  if (option.key === 'food')\n    return null\n  return h(NIcon, null, { default: () => h(BookmarkOutline) })\n}\n\nfunction expandIcon() {\n  return h(NIcon, null, { default: () => h(CaretDownOutline) })\n}\n</script>\n\n<template>\n  <n-space vertical>\n    <n-switch v-model:value=\"collapsed\" />\n    <n-layout has-sider>\n      <n-layout-sider\n        bordered\n        collapse-mode=\"width\"\n        :collapsed-width=\"64\"\n        :width=\"240\"\n        :collapsed=\"collapsed\"\n        show-trigger\n        @collapse=\"collapsed = true\"\n        @expand=\"collapsed = false\"\n      >\n        <n-menu\n          :collapsed=\"collapsed\"\n          :collapsed-width=\"64\"\n          :collapsed-icon-size=\"22\"\n          :options=\"menuOptions\"\n          :render-label=\"renderMenuLabel\"\n          :render-icon=\"renderMenuIcon\"\n          :expand-icon=\"expandIcon\"\n        />\n      </n-layout-sider>\n      <n-layout>\n        <span>内容</span>\n      </n-layout>\n    </n-layout>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/menu/demos/zhCN/router-link.demo.vue",
    "content": "<markdown>\n# 使用 vue-router\n\n你可以在这个地方配合 vue-router 完成路由。通过将 `label` 渲染为 `<router-link />` 来改变路由。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { MenuOption } from 'naive-ui'\nimport type { Component } from 'vue'\nimport {\n  LogOutOutline as HomeIcon,\n  LaptopOutline as WorkIcon\n} from '@vicons/ionicons5'\nimport { NIcon } from 'naive-ui'\nimport { h } from 'vue'\nimport { RouterLink } from 'vue-router'\n\nfunction renderIcon(icon: Component) {\n  return () => h(NIcon, null, { default: () => h(icon) })\n}\n\nconst menuOptions: MenuOption[] = [\n  {\n    label: () =>\n      h(\n        RouterLink,\n        {\n          to: {\n            name: 'home',\n            params: {\n              lang: 'zh-CN'\n            }\n          }\n        },\n        { default: () => '回家' }\n      ),\n    key: 'go-back-home',\n    icon: renderIcon(HomeIcon)\n  },\n  {\n    label: () =>\n      h(\n        RouterLink,\n        {\n          to: {\n            path: '/zh-CN/os-theme/components/code'\n          }\n        },\n        { default: () => '上班' }\n      ),\n    key: 'go-to-work',\n    icon: renderIcon(WorkIcon)\n  }\n]\n</script>\n\n<template>\n  <n-menu :options=\"menuOptions\" />\n</template>\n"
  },
  {
    "path": "src/menu/demos/zhCN/select.demo.vue",
    "content": "<markdown>\n# 选中 & 路由\n\n你通常可以在这个地方配合 vue-router 完成路由。当然，你也可以通过将 `label` 渲染为 `<router-link />` 或 `<a />` 来改变路由。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { MenuOption } from 'naive-ui'\nimport type { Component } from 'vue'\nimport {\n  BookOutline as BookIcon,\n  HomeOutline as HomeIcon,\n  PersonOutline as PersonIcon,\n  WineOutline as WineIcon\n} from '@vicons/ionicons5'\nimport { NIcon, useMessage } from 'naive-ui'\nimport { h } from 'vue'\nimport { RouterLink } from 'vue-router'\n\nfunction renderIcon(icon: Component) {\n  return () => h(NIcon, null, { default: () => h(icon) })\n}\n\nconst menuOptions: MenuOption[] = [\n  {\n    label: () =>\n      h(\n        RouterLink,\n        {\n          to: {\n            name: 'home',\n            params: {\n              lang: 'zh-CN'\n            }\n          }\n        },\n        { default: () => '回家' }\n      ),\n    key: 'go-back-home',\n    icon: renderIcon(HomeIcon)\n  },\n  {\n    key: 'divider-1',\n    type: 'divider',\n    props: {\n      style: {\n        marginLeft: '32px'\n      }\n    }\n  },\n  {\n    label: () =>\n      h(\n        'a',\n        {\n          href: 'https://baike.baidu.com/item/%E4%B8%94%E5%90%AC%E9%A3%8E%E5%90%9F',\n          target: '_blank',\n          rel: 'noopenner noreferrer'\n        },\n        '且听风吟'\n      ),\n    key: 'hear-the-wind-sing',\n    icon: renderIcon(BookIcon)\n  },\n  {\n    label: '1973年的弹珠玩具',\n    key: 'pinball-1973',\n    icon: renderIcon(BookIcon),\n    disabled: true,\n    children: [\n      {\n        label: '鼠',\n        key: 'rat'\n      }\n    ]\n  },\n  {\n    label: '寻羊冒险记',\n    key: 'a-wild-sheep-chase',\n    icon: renderIcon(BookIcon),\n    disabled: true\n  },\n  {\n    label: '舞，舞，舞',\n    key: 'dance-dance-dance',\n    icon: renderIcon(BookIcon),\n    children: [\n      {\n        type: 'group',\n        label: '人物',\n        key: 'people',\n        children: [\n          {\n            label: '叙事者',\n            key: 'narrator',\n            icon: renderIcon(PersonIcon)\n          },\n          {\n            label: '羊男',\n            key: 'sheep-man',\n            icon: renderIcon(PersonIcon)\n          }\n        ]\n      },\n      {\n        label: '饮品',\n        key: 'beverage',\n        icon: renderIcon(WineIcon),\n        children: [\n          {\n            label: '威士忌',\n            key: 'whisky'\n          }\n        ]\n      },\n      {\n        label: '食物',\n        key: 'food',\n        children: [\n          {\n            label: '三明治',\n            key: 'sandwich'\n          }\n        ]\n      },\n      {\n        label: '过去增多，未来减少',\n        key: 'the-past-increases-the-future-recedes'\n      }\n    ]\n  }\n]\n\nconst message = useMessage()\n\nfunction handleUpdateValue(key: string, item: MenuOption) {\n  message.info(`[onUpdate:value]: ${JSON.stringify(key)}`)\n  message.info(`[onUpdate:value]: ${JSON.stringify(item)}`)\n}\n</script>\n\n<template>\n  <n-menu :options=\"menuOptions\" @update:value=\"handleUpdateValue\" />\n</template>\n"
  },
  {
    "path": "src/menu/demos/zhCN/show-debug.demo.vue",
    "content": "<markdown>\n# Show debug\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { MenuOption } from 'naive-ui'\nimport type { Component } from 'vue'\nimport {\n  BookOutline as BookIcon,\n  PersonOutline as PersonIcon,\n  WineOutline as WineIcon\n} from '@vicons/ionicons5'\nimport { NIcon } from 'naive-ui'\nimport { h, ref } from 'vue'\n\nfunction renderIcon(icon: Component) {\n  return () => h(NIcon, null, { default: () => h(icon) })\n}\n\nconst menuOptions: MenuOption[] = [\n  {\n    label: 'Hear the Wind Sing',\n    key: 'hear-the-wind-sing',\n    icon: renderIcon(BookIcon)\n  },\n  {\n    label: 'Pinball 1973',\n    key: 'pinball-1973',\n    icon: renderIcon(BookIcon),\n    disabled: true,\n    children: [\n      {\n        label: 'Rat',\n        key: 'rat'\n      }\n    ]\n  },\n  {\n    label: 'A Wild Sheep Chase',\n    key: 'a-wild-sheep-chase',\n    disabled: true,\n    icon: renderIcon(BookIcon)\n  },\n  {\n    label: 'Dance Dance Dance',\n    key: 'Dance Dance Dance',\n    icon: renderIcon(BookIcon),\n    children: [\n      {\n        type: 'group',\n        label: 'People',\n        key: 'people',\n        children: [\n          {\n            label: 'Narrator',\n            key: 'narrator',\n            icon: renderIcon(PersonIcon),\n            show: false\n          },\n          {\n            label: 'Sheep Man',\n            key: 'sheep-man',\n            icon: renderIcon(PersonIcon),\n            show: false\n          }\n        ]\n      },\n      {\n        label: 'Beverage',\n        key: 'beverage',\n        icon: renderIcon(WineIcon),\n        children: [\n          {\n            label: 'Whisky',\n            key: 'whisky'\n          }\n        ]\n      },\n      {\n        label: 'Food',\n        key: 'food',\n        children: [\n          {\n            label: 'Sandwich',\n            key: 'sandwich'\n          }\n        ]\n      },\n      {\n        label: 'The past increases. The future recedes.',\n        key: 'the-past-increases-the-future-recedes'\n      }\n    ]\n  }\n]\n\nconst activeKey = ref<string | null>(null)\nconst collapsed = ref(true)\n</script>\n\n<template>\n  <n-space vertical>\n    <n-switch v-model:value=\"collapsed\" />\n    <n-layout has-sider>\n      <n-layout-sider\n        bordered\n        collapse-mode=\"width\"\n        :collapsed-width=\"64\"\n        :width=\"240\"\n        :collapsed=\"collapsed\"\n        show-trigger\n        @collapse=\"collapsed = true\"\n        @expand=\"collapsed = false\"\n      >\n        <n-menu\n          v-model:value=\"activeKey\"\n          :collapsed=\"collapsed\"\n          :collapsed-width=\"64\"\n          :collapsed-icon-size=\"22\"\n          :options=\"menuOptions\"\n        />\n      </n-layout-sider>\n      <n-layout>\n        <span>Content</span>\n      </n-layout>\n    </n-layout>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/menu/demos/zhCN/show.demo.vue",
    "content": "<markdown>\n# 控制选项的显示隐藏\n\n在某种情况下，不同的角色会看到不同的菜单，你可以使用 `show` 属性来隐藏菜单。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { Component } from 'vue'\nimport {\n  BookOutline as BookIcon,\n  PersonOutline as PersonIcon\n} from '@vicons/ionicons5'\nimport { NIcon } from 'naive-ui'\nimport { computed, h, ref } from 'vue'\n\nconst accordion = ref(false)\n\nfunction renderIcon(icon: Component) {\n  return () => h(NIcon, null, { default: () => h(icon) })\n}\n\nconst options = computed(() => [\n  {\n    label: '提升效率的法宝',\n    icon: renderIcon(PersonIcon),\n    key: '1',\n    children: [\n      {\n        label: '如何提高产出',\n        key: '2'\n      }\n    ]\n  },\n  {\n    label: '摸鱼宝典',\n    key: '3',\n    icon: renderIcon(BookIcon),\n    show: !accordion.value,\n    children: [\n      {\n        label: '你摸鱼',\n        key: '4'\n      },\n      {\n        label: '我摸鱼',\n        key: '5'\n      },\n      {\n        label: '老板宝马变青桔',\n        key: '6'\n      }\n    ]\n  }\n])\n</script>\n\n<template>\n  <n-space vertical>\n    <n-switch v-model:value=\"accordion\">\n      <template #checked>\n        老板\n      </template>\n      <template #unchecked>\n        打工人\n      </template>\n    </n-switch>\n    <n-menu :options=\"options\" />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/menu/index.ts",
    "content": "export type {\n  MenuDividerOption,\n  MenuGroupOption,\n  MenuInst,\n  MenuNodeProps,\n  MenuOption\n} from './src/interface'\nexport { menuProps, default as NMenu } from './src/Menu'\nexport type { MenuProps } from './src/Menu'\n"
  },
  {
    "path": "src/menu/src/Menu.tsx",
    "content": "import type { Key } from 'treemate'\nimport type { ExtractPropTypes, PropType, VNode, VNodeChild } from 'vue'\nimport type { FollowerPlacement, VOverflowInst } from 'vueuc'\nimport type { ThemeProps } from '../../_mixins'\nimport type { MaybeArray } from '../../_utils'\nimport type { DropdownProps } from '../../dropdown'\nimport type { MenuTheme } from '../styles'\nimport type {\n  MenuGroupOption,\n  MenuIgnoredOption,\n  MenuInst,\n  MenuMixedOption,\n  MenuNodeProps,\n  MenuOption,\n  OnUpdateKeys,\n  OnUpdateKeysImpl,\n  OnUpdateValue,\n  OnUpdateValueImpl\n} from './interface'\nimport { createId } from 'seemly'\nimport { createTreeMate } from 'treemate'\nimport { useCompitable, useMergedState } from 'vooks'\nimport {\n  computed,\n  defineComponent,\n  h,\n  inject,\n  mergeProps,\n  provide,\n  ref,\n  toRef,\n  watchEffect\n} from 'vue'\nimport { VOverflow, VResizeObserver } from 'vueuc'\nimport { useConfig, useTheme, useThemeClass } from '../../_mixins'\nimport { call } from '../../_utils'\nimport { layoutSiderInjectionKey } from '../../layout/src/interface'\nimport { menuLight } from '../styles'\nimport { menuInjectionKey } from './context'\nimport style from './styles/index.cssr'\nimport { NSubmenu } from './Submenu'\nimport { useCheckDeprecated } from './useCheckDeprecated'\nimport { isIgnoredNode, itemRenderer } from './utils'\n\nexport const menuProps = {\n  ...(useTheme.props as ThemeProps<MenuTheme>),\n  options: {\n    type: Array as PropType<MenuMixedOption[]>,\n    default: () => []\n  },\n  collapsed: {\n    type: Boolean as PropType<boolean | undefined>,\n    default: undefined\n  },\n  collapsedWidth: {\n    type: Number,\n    default: 48\n  },\n  iconSize: {\n    type: Number,\n    default: 20\n  },\n  collapsedIconSize: {\n    type: Number,\n    default: 24\n  },\n  rootIndent: Number,\n  indent: {\n    type: Number,\n    default: 32\n  },\n  labelField: {\n    type: String,\n    default: 'label'\n  },\n  keyField: {\n    type: String,\n    default: 'key'\n  },\n  childrenField: {\n    type: String,\n    default: 'children'\n  },\n  disabledField: {\n    type: String,\n    default: 'disabled'\n  },\n  defaultExpandAll: Boolean,\n  defaultExpandedKeys: Array as PropType<Key[]>,\n  expandedKeys: Array as PropType<Key[]>,\n  value: [String, Number] as PropType<Key | null>,\n  defaultValue: {\n    type: [String, Number] as PropType<Key | null>,\n    default: null\n  },\n  mode: {\n    type: String as PropType<'vertical' | 'horizontal'>,\n    default: 'vertical'\n  },\n  watchProps: {\n    type: Array as PropType<Array<'defaultExpandedKeys' | 'defaultValue'>>,\n    default: undefined\n  },\n  disabled: Boolean,\n  show: {\n    type: Boolean,\n    default: true\n  },\n  inverted: Boolean,\n  'onUpdate:expandedKeys': [Function, Array] as PropType<\n    MaybeArray<OnUpdateKeys>\n  >,\n  onUpdateExpandedKeys: [Function, Array] as PropType<MaybeArray<OnUpdateKeys>>,\n  onUpdateValue: [Function, Array] as PropType<MaybeArray<OnUpdateValue>>,\n  'onUpdate:value': [Function, Array] as PropType<MaybeArray<OnUpdateValue>>,\n  expandIcon: Function as PropType<(option: MenuOption) => VNodeChild>,\n  renderIcon: Function as PropType<(option: MenuOption) => VNodeChild>,\n  renderLabel: Function as PropType<\n    (option: MenuOption | MenuGroupOption) => VNodeChild\n  >,\n  renderExtra: Function as PropType<\n    (option: MenuOption | MenuGroupOption) => VNodeChild\n  >,\n  dropdownProps: Object as PropType<DropdownProps>,\n  accordion: Boolean,\n  nodeProps: Function as PropType<MenuNodeProps>,\n  dropdownPlacement: {\n    type: String as PropType<FollowerPlacement>,\n    default: 'bottom'\n  },\n  responsive: Boolean,\n  // deprecated\n  items: Array as PropType<Array<MenuOption | MenuGroupOption>>,\n  onOpenNamesChange: [Function, Array] as PropType<MaybeArray<OnUpdateKeys>>,\n  onSelect: [Function, Array] as PropType<MaybeArray<OnUpdateValue>>,\n  onExpandedNamesChange: [Function, Array] as PropType<\n    MaybeArray<OnUpdateKeys>\n  >,\n  expandedNames: Array as PropType<Key[]>,\n  defaultExpandedNames: Array as PropType<Key[]>\n} as const\n\nexport type MenuSetupProps = ExtractPropTypes<typeof menuProps>\n\nexport type MenuProps = Partial<MenuSetupProps>\n\nexport default defineComponent({\n  name: 'Menu',\n  inheritAttrs: false,\n  props: menuProps,\n  setup(props) {\n    if (__DEV__) {\n      useCheckDeprecated(props)\n    }\n    const { mergedClsPrefixRef, inlineThemeDisabled } = useConfig(props)\n    const themeRef = useTheme(\n      'Menu',\n      '-menu',\n      style,\n      menuLight,\n      props,\n      mergedClsPrefixRef\n    )\n\n    const layoutSider = inject(layoutSiderInjectionKey, null)\n\n    const mergedCollapsedRef = computed(() => {\n      const { collapsed } = props\n      if (collapsed !== undefined)\n        return collapsed\n      if (layoutSider) {\n        const { collapseModeRef, collapsedRef } = layoutSider\n        if (collapseModeRef.value === 'width') {\n          return collapsedRef.value ?? false\n        }\n      }\n      return false\n    })\n\n    const treeMateRef = computed(() => {\n      const { keyField, childrenField, disabledField } = props\n      return createTreeMate<MenuOption, MenuGroupOption, MenuIgnoredOption>(\n        props.items || props.options,\n        {\n          getIgnored(node) {\n            return isIgnoredNode(node)\n          },\n          getChildren(node) {\n            return node[childrenField]\n          },\n          getDisabled(node) {\n            return (node as any)[disabledField]\n          },\n          getKey(node) {\n            return (node[keyField] as Key) ?? node.name\n          }\n        }\n      )\n    })\n    const treeKeysLevelOneRef = computed(\n      () => new Set(treeMateRef.value.treeNodes.map(e => e.key))\n    )\n\n    const { watchProps } = props\n\n    const uncontrolledValueRef = ref<Key | null>(null)\n    if (watchProps?.includes('defaultValue')) {\n      watchEffect(() => {\n        uncontrolledValueRef.value = props.defaultValue\n      })\n    }\n    else {\n      uncontrolledValueRef.value = props.defaultValue\n    }\n    const controlledValueRef = toRef(props, 'value')\n    const mergedValueRef = useMergedState(\n      controlledValueRef,\n      uncontrolledValueRef\n    )\n    const uncontrolledExpandedKeysRef = ref<Key[]>([])\n    const initUncontrolledExpandedKeys = (): void => {\n      uncontrolledExpandedKeysRef.value = props.defaultExpandAll\n        ? treeMateRef.value.getNonLeafKeys()\n        : props.defaultExpandedNames\n          || props.defaultExpandedKeys\n          || treeMateRef.value.getPath(mergedValueRef.value, {\n            includeSelf: false\n          }).keyPath\n    }\n    if (watchProps?.includes('defaultExpandedKeys')) {\n      watchEffect(initUncontrolledExpandedKeys)\n    }\n    else {\n      initUncontrolledExpandedKeys()\n    }\n    const controlledExpandedKeysRef = useCompitable(props, [\n      'expandedNames',\n      'expandedKeys'\n    ])\n    const mergedExpandedKeysRef = useMergedState(\n      controlledExpandedKeysRef,\n      uncontrolledExpandedKeysRef\n    )\n    const tmNodesRef = computed(() => treeMateRef.value.treeNodes)\n    const activePathRef = computed(() => {\n      return treeMateRef.value.getPath(mergedValueRef.value).keyPath\n    })\n    provide(menuInjectionKey, {\n      props,\n      mergedCollapsedRef,\n      mergedThemeRef: themeRef,\n      mergedValueRef,\n      mergedExpandedKeysRef,\n      activePathRef,\n      mergedClsPrefixRef,\n      isHorizontalRef: computed(() => props.mode === 'horizontal'),\n      invertedRef: toRef(props, 'inverted'),\n      doSelect,\n      toggleExpand\n    })\n    function doSelect(value: Key, item: MenuOption): void {\n      const {\n        'onUpdate:value': _onUpdateValue,\n        onUpdateValue,\n        onSelect\n      } = props\n      if (onUpdateValue) {\n        call(onUpdateValue as OnUpdateValueImpl, value, item)\n      }\n      if (_onUpdateValue) {\n        call(_onUpdateValue as OnUpdateValueImpl, value, item)\n      }\n      if (onSelect) {\n        call(onSelect as OnUpdateValueImpl, value, item)\n      }\n      uncontrolledValueRef.value = value\n    }\n    function doUpdateExpandedKeys(value: Key[]): void {\n      const {\n        'onUpdate:expandedKeys': _onUpdateExpandedKeys,\n        onUpdateExpandedKeys,\n        onExpandedNamesChange,\n        onOpenNamesChange\n      } = props\n      if (_onUpdateExpandedKeys) {\n        call(_onUpdateExpandedKeys as OnUpdateKeysImpl, value)\n      }\n      if (onUpdateExpandedKeys) {\n        call(onUpdateExpandedKeys as OnUpdateKeysImpl, value)\n      }\n      // deprecated\n      if (onExpandedNamesChange) {\n        call(onExpandedNamesChange as OnUpdateKeysImpl, value)\n      }\n      if (onOpenNamesChange) {\n        call(onOpenNamesChange as OnUpdateKeysImpl, value)\n      }\n      uncontrolledExpandedKeysRef.value = value\n    }\n    function toggleExpand(key: Key): void {\n      const currentExpandedKeys = Array.from(mergedExpandedKeysRef.value)\n      const index = currentExpandedKeys.findIndex(\n        expanededKey => expanededKey === key\n      )\n      if (~index) {\n        currentExpandedKeys.splice(index, 1)\n      }\n      else {\n        if (props.accordion) {\n          if (treeKeysLevelOneRef.value.has(key)) {\n            const closeKeyIndex = currentExpandedKeys.findIndex(e =>\n              treeKeysLevelOneRef.value.has(e)\n            )\n            if (closeKeyIndex > -1) {\n              currentExpandedKeys.splice(closeKeyIndex, 1)\n            }\n          }\n        }\n        currentExpandedKeys.push(key)\n      }\n      doUpdateExpandedKeys(currentExpandedKeys)\n    }\n    const showOption: MenuInst['showOption'] = (key?: Key): void => {\n      const selectedKeyPath = treeMateRef.value.getPath(\n        key ?? mergedValueRef.value,\n        {\n          includeSelf: false\n        }\n      ).keyPath\n      if (!selectedKeyPath.length)\n        return\n      const currentExpandedKeys = Array.from(mergedExpandedKeysRef.value)\n      const nextExpandedKeys = new Set([\n        ...currentExpandedKeys,\n        ...selectedKeyPath\n      ])\n      if (props.accordion) {\n        treeKeysLevelOneRef.value.forEach((firstLevelKey) => {\n          if (\n            nextExpandedKeys.has(firstLevelKey)\n            && !selectedKeyPath.includes(firstLevelKey)\n          ) {\n            nextExpandedKeys.delete(firstLevelKey)\n          }\n        })\n      }\n      doUpdateExpandedKeys(Array.from(nextExpandedKeys))\n    }\n    const cssVarsRef = computed(() => {\n      const { inverted } = props\n      const {\n        common: { cubicBezierEaseInOut },\n        self\n      } = themeRef.value\n      const {\n        borderRadius,\n        borderColorHorizontal,\n        fontSize,\n        itemHeight,\n        dividerColor\n      } = self\n      const vars: any = {\n        '--n-divider-color': dividerColor,\n        '--n-bezier': cubicBezierEaseInOut,\n        '--n-font-size': fontSize,\n        '--n-border-color-horizontal': borderColorHorizontal,\n        '--n-border-radius': borderRadius,\n        '--n-item-height': itemHeight\n      }\n      if (inverted) {\n        vars['--n-group-text-color'] = self.groupTextColorInverted\n        vars['--n-color'] = self.colorInverted\n        vars['--n-item-text-color'] = self.itemTextColorInverted\n        vars['--n-item-text-color-hover'] = self.itemTextColorHoverInverted\n        vars['--n-item-text-color-active'] = self.itemTextColorActiveInverted\n        vars['--n-item-text-color-child-active']\n          = self.itemTextColorChildActiveInverted\n        vars['--n-item-text-color-child-active-hover']\n          = self.itemTextColorChildActiveInverted\n        vars['--n-item-text-color-active-hover']\n          = self.itemTextColorActiveHoverInverted\n        vars['--n-item-icon-color'] = self.itemIconColorInverted\n        vars['--n-item-icon-color-hover'] = self.itemIconColorHoverInverted\n        vars['--n-item-icon-color-active'] = self.itemIconColorActiveInverted\n        vars['--n-item-icon-color-active-hover']\n          = self.itemIconColorActiveHoverInverted\n        vars['--n-item-icon-color-child-active']\n          = self.itemIconColorChildActiveInverted\n        vars['--n-item-icon-color-child-active-hover']\n          = self.itemIconColorChildActiveHoverInverted\n        vars['--n-item-icon-color-collapsed']\n          = self.itemIconColorCollapsedInverted\n        vars['--n-item-text-color-horizontal']\n          = self.itemTextColorHorizontalInverted\n        vars['--n-item-text-color-hover-horizontal']\n          = self.itemTextColorHoverHorizontalInverted\n        vars['--n-item-text-color-active-horizontal']\n          = self.itemTextColorActiveHorizontalInverted\n        vars['--n-item-text-color-child-active-horizontal']\n          = self.itemTextColorChildActiveHorizontalInverted\n        vars['--n-item-text-color-child-active-hover-horizontal']\n          = self.itemTextColorChildActiveHoverHorizontalInverted\n        vars['--n-item-text-color-active-hover-horizontal']\n          = self.itemTextColorActiveHoverHorizontalInverted\n        vars['--n-item-icon-color-horizontal']\n          = self.itemIconColorHorizontalInverted\n        vars['--n-item-icon-color-hover-horizontal']\n          = self.itemIconColorHoverHorizontalInverted\n        vars['--n-item-icon-color-active-horizontal']\n          = self.itemIconColorActiveHorizontalInverted\n        vars['--n-item-icon-color-active-hover-horizontal']\n          = self.itemIconColorActiveHoverHorizontalInverted\n        vars['--n-item-icon-color-child-active-horizontal']\n          = self.itemIconColorChildActiveHorizontalInverted\n        vars['--n-item-icon-color-child-active-hover-horizontal']\n          = self.itemIconColorChildActiveHoverHorizontalInverted\n        vars['--n-arrow-color'] = self.arrowColorInverted\n        vars['--n-arrow-color-hover'] = self.arrowColorHoverInverted\n        vars['--n-arrow-color-active'] = self.arrowColorActiveInverted\n        vars['--n-arrow-color-active-hover']\n          = self.arrowColorActiveHoverInverted\n        vars['--n-arrow-color-child-active']\n          = self.arrowColorChildActiveInverted\n        vars['--n-arrow-color-child-active-hover']\n          = self.arrowColorChildActiveHoverInverted\n        vars['--n-item-color-hover'] = self.itemColorHoverInverted\n        vars['--n-item-color-active'] = self.itemColorActiveInverted\n        vars['--n-item-color-active-hover'] = self.itemColorActiveHoverInverted\n        vars['--n-item-color-active-collapsed']\n          = self.itemColorActiveCollapsedInverted\n      }\n      else {\n        vars['--n-group-text-color'] = self.groupTextColor\n        vars['--n-color'] = self.color\n        vars['--n-item-text-color'] = self.itemTextColor\n        vars['--n-item-text-color-hover'] = self.itemTextColorHover\n        vars['--n-item-text-color-active'] = self.itemTextColorActive\n        vars['--n-item-text-color-child-active'] = self.itemTextColorChildActive\n        vars['--n-item-text-color-child-active-hover']\n          = self.itemTextColorChildActiveHover\n        vars['--n-item-text-color-active-hover'] = self.itemTextColorActiveHover\n        vars['--n-item-icon-color'] = self.itemIconColor\n        vars['--n-item-icon-color-hover'] = self.itemIconColorHover\n        vars['--n-item-icon-color-active'] = self.itemIconColorActive\n        vars['--n-item-icon-color-active-hover'] = self.itemIconColorActiveHover\n        vars['--n-item-icon-color-child-active'] = self.itemIconColorChildActive\n        vars['--n-item-icon-color-child-active-hover']\n          = self.itemIconColorChildActiveHover\n        vars['--n-item-icon-color-collapsed'] = self.itemIconColorCollapsed\n        vars['--n-item-text-color-horizontal'] = self.itemTextColorHorizontal\n        vars['--n-item-text-color-hover-horizontal']\n          = self.itemTextColorHoverHorizontal\n        vars['--n-item-text-color-active-horizontal']\n          = self.itemTextColorActiveHorizontal\n        vars['--n-item-text-color-child-active-horizontal']\n          = self.itemTextColorChildActiveHorizontal\n        vars['--n-item-text-color-child-active-hover-horizontal']\n          = self.itemTextColorChildActiveHoverHorizontal\n        vars['--n-item-text-color-active-hover-horizontal']\n          = self.itemTextColorActiveHoverHorizontal\n        vars['--n-item-icon-color-horizontal'] = self.itemIconColorHorizontal\n        vars['--n-item-icon-color-hover-horizontal']\n          = self.itemIconColorHoverHorizontal\n        vars['--n-item-icon-color-active-horizontal']\n          = self.itemIconColorActiveHorizontal\n        vars['--n-item-icon-color-active-hover-horizontal']\n          = self.itemIconColorActiveHoverHorizontal\n        vars['--n-item-icon-color-child-active-horizontal']\n          = self.itemIconColorChildActiveHorizontal\n        vars['--n-item-icon-color-child-active-hover-horizontal']\n          = self.itemIconColorChildActiveHoverHorizontal\n        vars['--n-arrow-color'] = self.arrowColor\n        vars['--n-arrow-color-hover'] = self.arrowColorHover\n        vars['--n-arrow-color-active'] = self.arrowColorActive\n        vars['--n-arrow-color-active-hover'] = self.arrowColorActiveHover\n        vars['--n-arrow-color-child-active'] = self.arrowColorChildActive\n        vars['--n-arrow-color-child-active-hover']\n          = self.arrowColorChildActiveHover\n        vars['--n-item-color-hover'] = self.itemColorHover\n        vars['--n-item-color-active'] = self.itemColorActive\n        vars['--n-item-color-active-hover'] = self.itemColorActiveHover\n        vars['--n-item-color-active-collapsed'] = self.itemColorActiveCollapsed\n      }\n      return vars\n    })\n    const themeClassHandle = inlineThemeDisabled\n      ? useThemeClass(\n          'menu',\n          computed(() => (props.inverted ? 'a' : 'b')),\n          cssVarsRef,\n          props\n        )\n      : undefined\n\n    const ellipsisNodeId = createId()\n    const overflowRef = ref<VOverflowInst | null>(null)\n    const counterRef = ref<HTMLElement | null>(null)\n    let isFirstResize = true\n    const onResize = (): void => {\n      if (isFirstResize) {\n        isFirstResize = false\n      }\n      else {\n        overflowRef.value?.sync({\n          showAllItemsBeforeCalculate: true\n        })\n      }\n    }\n    function getCounter(): HTMLElement | null {\n      return document.getElementById(ellipsisNodeId)\n    }\n    const ellipsisFromIndexRef = ref(-1)\n    function onUpdateCount(count: number): void {\n      ellipsisFromIndexRef.value = props.options.length - count\n    }\n    function onUpdateOverflow(overflow: boolean): void {\n      if (!overflow) {\n        ellipsisFromIndexRef.value = -1\n      }\n    }\n    const ellipsisOptionRef = computed<MenuOption>(() => {\n      const ellipsisFromIndex = ellipsisFromIndexRef.value\n      const option: MenuOption = {\n        children:\n          ellipsisFromIndex === -1 ? [] : props.options.slice(ellipsisFromIndex)\n      }\n      return option\n    })\n    const ellipsisTreeMateRef = computed(() => {\n      const { childrenField, disabledField, keyField } = props\n      return createTreeMate<MenuOption, MenuGroupOption, MenuIgnoredOption>(\n        [ellipsisOptionRef.value],\n        {\n          getIgnored(node) {\n            return isIgnoredNode(node)\n          },\n          getChildren(node) {\n            return node[childrenField]\n          },\n          getDisabled(node) {\n            return (node as any)[disabledField]\n          },\n          getKey(node) {\n            return (node[keyField] as Key) ?? node.name\n          }\n        }\n      )\n    })\n    const emptyTmNodeRef = computed(() => {\n      return createTreeMate<MenuOption, MenuGroupOption, MenuIgnoredOption>([\n        {}\n      ]).treeNodes[0]\n    })\n    function renderCounter(): VNodeChild {\n      if (ellipsisFromIndexRef.value === -1) {\n        // Only a placeholder\n        return (\n          <NSubmenu\n            root\n            level={0}\n            key=\"__ellpisisGroupPlaceholder__\"\n            internalKey=\"__ellpisisGroupPlaceholder__\"\n            title=\"···\"\n            tmNode={emptyTmNodeRef.value}\n            domId={ellipsisNodeId}\n            isEllipsisPlaceholder\n          />\n        )\n      }\n      const tmNode = ellipsisTreeMateRef.value.treeNodes[0]\n      const activePath = activePathRef.value\n      const childActive = !!tmNode.children?.some((tmNode) => {\n        return activePath.includes(tmNode.key)\n      })\n      return (\n        <NSubmenu\n          level={0}\n          root\n          key=\"__ellpisisGroup__\"\n          internalKey=\"__ellpisisGroup__\"\n          title=\"···\"\n          virtualChildActive={childActive}\n          tmNode={tmNode}\n          domId={ellipsisNodeId}\n          rawNodes={(tmNode.rawNode as MenuOption).children || []}\n          tmNodes={tmNode.children || []}\n          isEllipsisPlaceholder\n        />\n      )\n    }\n\n    return {\n      mergedClsPrefix: mergedClsPrefixRef,\n      controlledExpandedKeys: controlledExpandedKeysRef,\n      uncontrolledExpanededKeys: uncontrolledExpandedKeysRef,\n      mergedExpandedKeys: mergedExpandedKeysRef,\n      uncontrolledValue: uncontrolledValueRef,\n      mergedValue: mergedValueRef,\n      activePath: activePathRef,\n      tmNodes: tmNodesRef,\n      mergedTheme: themeRef,\n      mergedCollapsed: mergedCollapsedRef,\n      cssVars: inlineThemeDisabled ? undefined : cssVarsRef,\n      themeClass: themeClassHandle?.themeClass,\n      overflowRef,\n      counterRef,\n      updateCounter: () => {},\n      onResize,\n      onUpdateOverflow,\n      onUpdateCount,\n      renderCounter,\n      getCounter,\n      onRender: themeClassHandle?.onRender,\n      showOption,\n      deriveResponsiveState: onResize\n    } satisfies MenuInst & Record<string, unknown>\n  },\n  render() {\n    const { mergedClsPrefix, mode, themeClass, onRender } = this\n    onRender?.()\n    const renderMenuItemNodes = (): VNodeChild[] =>\n      this.tmNodes.map(tmNode => itemRenderer(tmNode, this.$props))\n    const horizontal = mode === 'horizontal'\n    const finalResponsive = horizontal && this.responsive\n    const renderMainNode = (): VNode =>\n      h(\n        'div',\n        mergeProps(this.$attrs, {\n          role: mode === 'horizontal' ? 'menubar' : 'menu',\n          class: [\n            `${mergedClsPrefix}-menu`,\n            themeClass,\n            `${mergedClsPrefix}-menu--${mode}`,\n            finalResponsive && `${mergedClsPrefix}-menu--responsive`,\n            this.mergedCollapsed && `${mergedClsPrefix}-menu--collapsed`\n          ],\n          style: this.cssVars\n        }),\n        finalResponsive ? (\n          <VOverflow\n            ref=\"overflowRef\"\n            onUpdateOverflow={this.onUpdateOverflow}\n            getCounter={this.getCounter}\n            onUpdateCount={this.onUpdateCount}\n            updateCounter={this.updateCounter}\n            style={{\n              width: '100%',\n              display: 'flex',\n              overflow: 'hidden'\n            }}\n          >\n            {{\n              default: renderMenuItemNodes,\n              counter: this.renderCounter\n            }}\n          </VOverflow>\n        ) : (\n          renderMenuItemNodes()\n        )\n      )\n    return finalResponsive ? (\n      <VResizeObserver onResize={this.onResize}>\n        {{ default: renderMainNode }}\n      </VResizeObserver>\n    ) : (\n      renderMainNode()\n    )\n  }\n})\n"
  },
  {
    "path": "src/menu/src/MenuDivider.tsx",
    "content": "import { defineComponent, h, inject } from 'vue'\nimport { menuInjectionKey } from './context'\n\nexport default defineComponent({\n  name: 'MenuDivider',\n  setup() {\n    const NMenu = inject(menuInjectionKey)!\n    const { mergedClsPrefixRef, isHorizontalRef } = NMenu\n    return () =>\n      isHorizontalRef.value ? null : (\n        <div class={`${mergedClsPrefixRef.value}-menu-divider`} />\n      )\n  }\n})\n"
  },
  {
    "path": "src/menu/src/MenuOption.tsx",
    "content": "import type { PropType } from 'vue'\nimport type { TmNode } from './interface'\nimport { useMemo } from 'vooks'\nimport { computed, defineComponent, h } from 'vue'\nimport { keysOf, render } from '../../_utils'\nimport { NTooltip } from '../../tooltip'\nimport NMenuOptionContent from './MenuOptionContent'\nimport { useMenuChild } from './use-menu-child'\nimport { useMenuChildProps } from './use-menu-child-props'\n\nexport const menuItemProps = {\n  ...useMenuChildProps,\n  tmNode: {\n    type: Object as PropType<TmNode>,\n    required: true\n  },\n  disabled: Boolean,\n  icon: Function,\n  onClick: Function\n} as const\n\nexport const menuItemPropKeys = keysOf(menuItemProps)\n\nexport const NMenuOption = defineComponent({\n  name: 'MenuOption',\n  props: menuItemProps,\n  setup(props) {\n    const MenuChild = useMenuChild(props)\n    const { NSubmenu, NMenu, NMenuOptionGroup } = MenuChild\n    const { props: menuProps, mergedClsPrefixRef, mergedCollapsedRef } = NMenu\n    const parentDisabledRef = NSubmenu\n      ? NSubmenu.mergedDisabledRef\n      : NMenuOptionGroup\n        ? NMenuOptionGroup.mergedDisabledRef\n        : { value: false }\n    const mergedDisabledRef = computed(() => {\n      return parentDisabledRef.value || props.disabled\n    })\n    function doClick(e: MouseEvent): void {\n      const { onClick } = props\n      if (onClick)\n        onClick(e)\n    }\n    function handleClick(e: MouseEvent): void {\n      if (!mergedDisabledRef.value) {\n        NMenu.doSelect(props.internalKey, props.tmNode.rawNode)\n        doClick(e)\n      }\n    }\n    return {\n      mergedClsPrefix: mergedClsPrefixRef,\n      dropdownPlacement: MenuChild.dropdownPlacement,\n      paddingLeft: MenuChild.paddingLeft,\n      iconMarginRight: MenuChild.iconMarginRight,\n      maxIconSize: MenuChild.maxIconSize,\n      activeIconSize: MenuChild.activeIconSize,\n      mergedTheme: NMenu.mergedThemeRef,\n      menuProps,\n      dropdownEnabled: useMemo(() => {\n        return (\n          props.root\n          && mergedCollapsedRef.value\n          && menuProps.mode !== 'horizontal'\n          && !mergedDisabledRef.value\n        )\n      }),\n      selected: useMemo(() => {\n        if (NMenu.mergedValueRef.value === props.internalKey)\n          return true\n        return false\n      }),\n      mergedDisabled: mergedDisabledRef,\n      handleClick\n    }\n  },\n  render() {\n    const {\n      mergedClsPrefix,\n      mergedTheme,\n      tmNode,\n      menuProps: { renderLabel, nodeProps }\n    } = this\n    const attrs = nodeProps?.(tmNode.rawNode)\n    return (\n      <div\n        {...attrs}\n        role=\"menuitem\"\n        class={[`${mergedClsPrefix}-menu-item`, attrs?.class]}\n      >\n        <NTooltip\n          theme={mergedTheme.peers.Tooltip}\n          themeOverrides={mergedTheme.peerOverrides.Tooltip}\n          trigger=\"hover\"\n          placement={this.dropdownPlacement}\n          disabled={!this.dropdownEnabled || this.title === undefined}\n          internalExtraClass={['menu-tooltip']}\n        >\n          {{\n            default: () =>\n              renderLabel ? renderLabel(tmNode.rawNode) : render(this.title),\n            trigger: () => (\n              <NMenuOptionContent\n                tmNode={tmNode}\n                clsPrefix={mergedClsPrefix}\n                paddingLeft={this.paddingLeft}\n                iconMarginRight={this.iconMarginRight}\n                maxIconSize={this.maxIconSize}\n                activeIconSize={this.activeIconSize}\n                selected={this.selected}\n                title={this.title}\n                extra={this.extra}\n                disabled={this.mergedDisabled}\n                icon={this.icon}\n                onClick={this.handleClick}\n              />\n            )\n          }}\n        </NTooltip>\n      </div>\n    )\n  }\n})\n"
  },
  {
    "path": "src/menu/src/MenuOptionContent.tsx",
    "content": "import type { PropType } from 'vue'\nimport type { TmNode } from './interface'\nimport { computed, defineComponent, h, inject } from 'vue'\nimport { NBaseIcon } from '../../_internal'\nimport { ChevronDownFilledIcon } from '../../_internal/icons'\nimport { render } from '../../_utils'\nimport { menuInjectionKey } from './context'\n\nexport default defineComponent({\n  name: 'MenuOptionContent',\n  props: {\n    collapsed: Boolean,\n    disabled: Boolean,\n    title: [String, Function],\n    icon: Function,\n    extra: [String, Function],\n    showArrow: Boolean,\n    childActive: Boolean,\n    hover: Boolean,\n    paddingLeft: Number,\n    selected: Boolean,\n    maxIconSize: {\n      type: Number,\n      required: true\n    },\n    activeIconSize: {\n      type: Number,\n      required: true\n    },\n    iconMarginRight: {\n      type: Number,\n      required: true\n    },\n    clsPrefix: {\n      type: String,\n      required: true\n    },\n    onClick: Function as PropType<(e: MouseEvent) => void>,\n    tmNode: {\n      type: Object as PropType<TmNode>,\n      required: true\n    },\n    isEllipsisPlaceholder: Boolean\n  },\n  setup(props) {\n    const { props: menuProps } = inject(menuInjectionKey)!\n    return {\n      menuProps,\n      style: computed(() => {\n        const { paddingLeft } = props\n        return { paddingLeft: paddingLeft && `${paddingLeft}px` }\n      }),\n      iconStyle: computed(() => {\n        const { maxIconSize, activeIconSize, iconMarginRight } = props\n        return {\n          width: `${maxIconSize}px`,\n          height: `${maxIconSize}px`,\n          fontSize: `${activeIconSize}px`,\n          marginRight: `${iconMarginRight}px`\n        }\n      })\n    }\n  },\n  render() {\n    const {\n      clsPrefix,\n      tmNode,\n      menuProps: { renderIcon, renderLabel, renderExtra, expandIcon }\n    } = this\n    const icon = renderIcon ? renderIcon(tmNode.rawNode) : render(this.icon)\n    return (\n      <div\n        onClick={(e) => {\n          this.onClick?.(e)\n        }}\n        role=\"none\"\n        class={[\n          `${clsPrefix}-menu-item-content`,\n          {\n            [`${clsPrefix}-menu-item-content--selected`]: this.selected,\n            [`${clsPrefix}-menu-item-content--collapsed`]: this.collapsed,\n            [`${clsPrefix}-menu-item-content--child-active`]: this.childActive,\n            [`${clsPrefix}-menu-item-content--disabled`]: this.disabled,\n            [`${clsPrefix}-menu-item-content--hover`]: this.hover\n          }\n        ]}\n        style={this.style}\n      >\n        {icon && (\n          <div\n            class={`${clsPrefix}-menu-item-content__icon`}\n            style={this.iconStyle}\n            role=\"none\"\n          >\n            {[icon]}\n          </div>\n        )}\n        <div class={`${clsPrefix}-menu-item-content-header`} role=\"none\">\n          {this.isEllipsisPlaceholder\n            ? this.title\n            : renderLabel\n              ? renderLabel(tmNode.rawNode)\n              : render(this.title)}\n          {this.extra || renderExtra ? (\n            <span class={`${clsPrefix}-menu-item-content-header__extra`}>\n              {' '}\n              {renderExtra ? renderExtra(tmNode.rawNode) : render(this.extra)}\n            </span>\n          ) : null}\n        </div>\n        {this.showArrow ? (\n          <NBaseIcon\n            ariaHidden={true}\n            class={`${clsPrefix}-menu-item-content__arrow`}\n            clsPrefix={clsPrefix}\n          >\n            {{\n              default: () =>\n                expandIcon ? (\n                  expandIcon(tmNode.rawNode)\n                ) : (\n                  <ChevronDownFilledIcon />\n                )\n            }}\n          </NBaseIcon>\n        ) : null}\n      </div>\n    )\n  }\n})\n"
  },
  {
    "path": "src/menu/src/MenuOptionGroup.tsx",
    "content": "import type { PropType } from 'vue'\nimport type { TmNode } from './interface'\nimport { computed, defineComponent, Fragment, h, inject, provide } from 'vue'\nimport { keysOf, render } from '../../_utils'\nimport { menuInjectionKey, menuItemGroupInjectionKey } from './context'\n\nimport { useMenuChild } from './use-menu-child'\nimport { useMenuChildProps } from './use-menu-child-props'\nimport { itemRenderer } from './utils'\n\nexport const menuItemGroupProps = {\n  ...useMenuChildProps,\n  tmNode: {\n    type: Object as PropType<TmNode>,\n    required: true\n  },\n  tmNodes: {\n    type: Array as PropType<TmNode[]>,\n    required: true\n  }\n} as const\n\nexport const menuItemGroupPropKeys = keysOf(menuItemGroupProps)\n\nexport const NMenuOptionGroup = defineComponent({\n  name: 'MenuOptionGroup',\n  props: menuItemGroupProps,\n  setup(props) {\n    const MenuChild = useMenuChild(props)\n    const { NSubmenu } = MenuChild\n    const mergedDisabledRef = computed(() => {\n      if (NSubmenu?.mergedDisabledRef.value)\n        return true\n      return props.tmNode.disabled\n    })\n    provide(menuItemGroupInjectionKey, {\n      paddingLeftRef: MenuChild.paddingLeft,\n      mergedDisabledRef\n    })\n    const { mergedClsPrefixRef, props: menuProps } = inject(menuInjectionKey)!\n    return function () {\n      const { value: mergedClsPrefix } = mergedClsPrefixRef\n      const paddingLeft = MenuChild.paddingLeft.value\n      const { nodeProps } = menuProps\n      const attrs = nodeProps?.(props.tmNode.rawNode)\n      return (\n        <div class={`${mergedClsPrefix}-menu-item-group`} role=\"group\">\n          <div\n            {...attrs}\n            class={[`${mergedClsPrefix}-menu-item-group-title`, attrs?.class]}\n            style={[\n              attrs?.style || '',\n              paddingLeft !== undefined ? `padding-left: ${paddingLeft}px;` : ''\n            ]}\n          >\n            {render(props.title)}\n            {props.extra ? (\n              <>\n                {' '}\n                {render(props.extra)}\n              </>\n            ) : null}\n          </div>\n          <div>\n            {props.tmNodes.map(tmNode => itemRenderer(tmNode, menuProps))}\n          </div>\n        </div>\n      )\n    }\n  }\n})\n"
  },
  {
    "path": "src/menu/src/Submenu.tsx",
    "content": "import type { PropType, VNode, VNodeChild } from 'vue'\nimport type { MenuMixedOption, TmNode } from './interface'\nimport { useMemo } from 'vooks'\nimport { computed, defineComponent, h, provide, ref } from 'vue'\nimport { NFadeInExpandTransition } from '../../_internal'\nimport { keysOf } from '../../_utils'\n\nimport { NDropdown } from '../../dropdown'\nimport { menuItemGroupInjectionKey, submenuInjectionKey } from './context'\nimport NMenuOptionContent from './MenuOptionContent'\nimport { useMenuChild } from './use-menu-child'\nimport { useMenuChildProps } from './use-menu-child-props'\nimport { itemRenderer } from './utils'\n\nexport const submenuProps = {\n  ...useMenuChildProps,\n  rawNodes: {\n    type: Array as PropType<MenuMixedOption[]>,\n    default: () => []\n  },\n  tmNodes: {\n    type: Array as PropType<TmNode[]>,\n    default: () => []\n  },\n  tmNode: {\n    type: Object as PropType<TmNode>,\n    required: true\n  },\n  disabled: Boolean,\n  icon: Function as PropType<() => VNodeChild>,\n  onClick: Function as PropType<() => void>,\n  domId: String,\n  virtualChildActive: {\n    type: Boolean,\n    default: undefined\n  },\n  isEllipsisPlaceholder: Boolean\n} as const\n\nexport const submenuPropKeys = keysOf(submenuProps)\n\nexport const NSubmenu = defineComponent({\n  name: 'Submenu',\n  props: submenuProps,\n  setup(props) {\n    const MenuChild = useMenuChild(props)\n    const { NMenu, NSubmenu } = MenuChild\n    const { props: menuProps, mergedCollapsedRef, mergedThemeRef } = NMenu\n    const mergedDisabledRef = computed(() => {\n      const { disabled } = props\n      if (NSubmenu?.mergedDisabledRef.value)\n        return true\n      if (menuProps.disabled)\n        return true\n      return disabled\n    })\n    const dropdownShowRef = ref(false)\n    provide(submenuInjectionKey, {\n      paddingLeftRef: MenuChild.paddingLeft,\n      mergedDisabledRef\n    })\n    provide(menuItemGroupInjectionKey, null)\n    function doClick(): void {\n      const { onClick } = props\n      if (onClick)\n        onClick()\n    }\n    function handleClick(): void {\n      if (!mergedDisabledRef.value) {\n        if (!mergedCollapsedRef.value) {\n          NMenu.toggleExpand(props.internalKey)\n        }\n        doClick()\n      }\n    }\n    function handlePopoverShowChange(value: boolean): void {\n      dropdownShowRef.value = value\n    }\n    return {\n      menuProps,\n      mergedTheme: mergedThemeRef,\n      doSelect: NMenu.doSelect,\n      inverted: NMenu.invertedRef,\n      isHorizontal: NMenu.isHorizontalRef,\n      mergedClsPrefix: NMenu.mergedClsPrefixRef,\n      maxIconSize: MenuChild.maxIconSize,\n      activeIconSize: MenuChild.activeIconSize,\n      iconMarginRight: MenuChild.iconMarginRight,\n      dropdownPlacement: MenuChild.dropdownPlacement,\n      dropdownShow: dropdownShowRef,\n      paddingLeft: MenuChild.paddingLeft,\n      mergedDisabled: mergedDisabledRef,\n      mergedValue: NMenu.mergedValueRef,\n      childActive: useMemo(() => {\n        return (\n          props.virtualChildActive\n          ?? NMenu.activePathRef.value.includes(props.internalKey)\n        )\n      }),\n      collapsed: computed(() => {\n        if (menuProps.mode === 'horizontal')\n          return false\n        if (mergedCollapsedRef.value) {\n          return true\n        }\n        return !NMenu.mergedExpandedKeysRef.value.includes(props.internalKey)\n      }),\n      dropdownEnabled: computed(() => {\n        return (\n          !mergedDisabledRef.value\n          && (menuProps.mode === 'horizontal' || mergedCollapsedRef.value)\n        )\n      }),\n      handlePopoverShowChange,\n      handleClick\n    }\n  },\n  render() {\n    const {\n      mergedClsPrefix,\n      menuProps: { renderIcon, renderLabel }\n    } = this\n    const createSubmenuItem = (): VNode => {\n      const {\n        isHorizontal,\n        paddingLeft,\n        collapsed,\n        mergedDisabled,\n        maxIconSize,\n        activeIconSize,\n        title,\n        childActive,\n        icon,\n        handleClick,\n        menuProps: { nodeProps },\n        dropdownShow,\n        iconMarginRight,\n        tmNode,\n        mergedClsPrefix,\n        isEllipsisPlaceholder,\n        extra\n      } = this\n      const attrs = nodeProps?.(tmNode.rawNode)\n      return (\n        <div\n          {...attrs}\n          class={[`${mergedClsPrefix}-menu-item`, attrs?.class]}\n          role=\"menuitem\"\n        >\n          <NMenuOptionContent\n            tmNode={tmNode}\n            paddingLeft={paddingLeft}\n            collapsed={collapsed}\n            disabled={mergedDisabled}\n            iconMarginRight={iconMarginRight}\n            maxIconSize={maxIconSize}\n            activeIconSize={activeIconSize}\n            title={title}\n            extra={extra}\n            showArrow={!isHorizontal}\n            childActive={childActive}\n            clsPrefix={mergedClsPrefix}\n            icon={icon}\n            hover={dropdownShow}\n            onClick={handleClick}\n            isEllipsisPlaceholder={isEllipsisPlaceholder}\n          />\n        </div>\n      )\n    }\n    const createSubmenuChildren = (): VNode => {\n      return (\n        <NFadeInExpandTransition>\n          {{\n            default: () => {\n              const { tmNodes, collapsed } = this\n              return !collapsed ? (\n                <div class={`${mergedClsPrefix}-submenu-children`} role=\"menu\">\n                  {tmNodes.map(item => itemRenderer(item, this.menuProps))}\n                </div>\n              ) : null\n            }\n          }}\n        </NFadeInExpandTransition>\n      )\n    }\n    return this.root ? (\n      <NDropdown\n        size=\"large\"\n        trigger=\"hover\"\n        {...this.menuProps?.dropdownProps}\n        themeOverrides={this.mergedTheme.peerOverrides.Dropdown}\n        theme={this.mergedTheme.peers.Dropdown}\n        builtinThemeOverrides={{\n          fontSizeLarge: '14px',\n          optionIconSizeLarge: '18px'\n        }}\n        value={this.mergedValue}\n        disabled={!this.dropdownEnabled}\n        placement={this.dropdownPlacement}\n        keyField={this.menuProps.keyField}\n        labelField={this.menuProps.labelField}\n        childrenField={this.menuProps.childrenField}\n        onUpdateShow={this.handlePopoverShowChange}\n        options={this.rawNodes}\n        onSelect={this.doSelect}\n        inverted={this.inverted}\n        renderIcon={renderIcon}\n        renderLabel={renderLabel}\n      >\n        {{\n          default: () => (\n            <div\n              class={`${mergedClsPrefix}-submenu`}\n              role=\"menu\"\n              aria-expanded={!this.collapsed}\n              id={this.domId}\n            >\n              {createSubmenuItem()}\n              {this.isHorizontal ? null : createSubmenuChildren()}\n            </div>\n          )\n        }}\n      </NDropdown>\n    ) : (\n      <div\n        class={`${mergedClsPrefix}-submenu`}\n        role=\"menu\"\n        aria-expanded={!this.collapsed}\n        id={this.domId}\n      >\n        {createSubmenuItem()}\n        {createSubmenuChildren()}\n      </div>\n    )\n  }\n})\n"
  },
  {
    "path": "src/menu/src/context.ts",
    "content": "import type {\n  MenuInjection,\n  MenuOptionGroupInjection,\n  SubmenuInjection\n} from './use-menu-child'\nimport { createInjectionKey } from '../../_utils'\n\nexport const menuInjectionKey = createInjectionKey<MenuInjection>('n-menu')\n\nexport const submenuInjectionKey = createInjectionKey<SubmenuInjection | null>(\n  'n-submenu'\n)\n\nexport const menuItemGroupInjectionKey\n  = createInjectionKey<MenuOptionGroupInjection | null>('n-menu-item-group')\n"
  },
  {
    "path": "src/menu/src/interface.ts",
    "content": "import type { TreeNode } from 'treemate'\nimport type { HTMLAttributes, VNodeChild } from 'vue'\n\nexport type Key = string | number\n\nexport interface MenuOptionSharedPart {\n  key?: Key\n  disabled?: boolean\n  icon?: () => VNodeChild\n  children?: Array<MenuOption | MenuGroupOption | MenuDividerOption>\n  extra?: string | (() => VNodeChild)\n  props?: HTMLAttributes\n  show?: boolean\n  [key: string]: unknown\n  /** @deprecated */\n  titleExtra?: string | (() => VNodeChild)\n}\n\n/**\n * @private\n */\nexport type MenuIgnoredOption = MenuDividerOption | MenuRenderOption\n\nexport interface MenuDividerOption {\n  type: 'divider'\n  key?: Key\n  props?: HTMLAttributes\n  [key: string]: unknown\n}\n\nexport interface MenuRenderOption {\n  type: 'render'\n  key?: Key\n  props?: HTMLAttributes\n  render?: () => VNodeChild\n  [key: string]: unknown\n}\n\nexport interface MenuGroupOptionBase extends MenuOptionSharedPart {\n  type: 'group'\n  children: Array<MenuOption | MenuDividerOption>\n}\n\nexport type MenuOption\n  = | (MenuOptionSharedPart & {\n    /** @deprecated */\n    title?: string | (() => VNodeChild)\n  })\n  | (MenuOptionSharedPart & { label?: string | (() => VNodeChild) })\n\nexport type MenuGroupOption\n  = | (MenuGroupOptionBase & {\n    /** @deprecated */\n    title?: string | (() => VNodeChild)\n  })\n  | (MenuGroupOptionBase & { label?: string | (() => VNodeChild) })\n\nexport type MenuMixedOption = MenuDividerOption | MenuOption | MenuGroupOption\n\nexport type TmNode = TreeNode<MenuOption, MenuGroupOption, MenuIgnoredOption>\n\nexport type OnUpdateValue = (\n  value: string & number & (string | number),\n  item: MenuOption\n) => void\n\nexport type OnUpdateKeys = (\n  keys: string[] & number[] & Array<string | number>\n) => void\n\nexport type OnUpdateValueImpl = (\n  value: string | number | (string | number),\n  item: MenuOption\n) => void\n\nexport type OnUpdateKeysImpl = (\n  keys: string[] | number[] | Array<string | number>\n) => void\n\nexport type MenuNodeProps = (\n  option: MenuOption | MenuGroupOption\n) => HTMLAttributes & Record<string, string | number | undefined>\n\nexport interface MenuInst {\n  showOption: (key?: Key) => void\n  deriveResponsiveState: () => void\n}\n"
  },
  {
    "path": "src/menu/src/styles/index.cssr.ts",
    "content": "import type { CNode, CNodeChildren, CProperties } from 'css-render'\nimport { fadeInHeightExpandTransition } from '../../../_styles/transitions/fade-in-height-expand.cssr'\nimport { c, cB, cE, cM, cNotM } from '../../../_utils/cssr'\n\nconst hoverStyleChildren = [\n  c('&::before', 'background-color: var(--n-item-color-hover);'),\n  cE('arrow', `\n    color: var(--n-arrow-color-hover);\n  `),\n  cE('icon', `\n    color: var(--n-item-icon-color-hover);\n  `),\n  cB('menu-item-content-header', `\n    color: var(--n-item-text-color-hover);\n  `, [\n    c('a', `\n      color: var(--n-item-text-color-hover);\n    `),\n    cE('extra', `\n      color: var(--n-item-text-color-hover);\n    `)\n  ])\n]\n\nconst horizontalHoverStyleChildren = [\n  cE('icon', `\n    color: var(--n-item-icon-color-hover-horizontal);\n  `),\n  cB('menu-item-content-header', `\n    color: var(--n-item-text-color-hover-horizontal);\n  `, [\n    c('a', `\n      color: var(--n-item-text-color-hover-horizontal);\n    `),\n    cE('extra', `\n      color: var(--n-item-text-color-hover-horizontal);\n    `)\n  ])\n]\n\n// vars:\n// --n-color\n// --n-group-text-color\n// --n-bezier\n// --n-font-size\n// --n-border-color-horizontal\n// --n-border-radius\n// --n-item-color-hover\n// --n-item-color-active\n// --n-item-color-active-hover\n// --n-item-color-active-collapsed\n// --n-arrow-color\n// --n-arrow-color-hover\n// --n-arrow-color-active\n// --n-arrow-color-active-hover\n// --n-arrow-color-child-active\n// --n-arrow-color-child-active-hover\n// --n-item-text-color\n// --n-item-text-color-hover\n// --n-item-text-color-active\n// --n-item-text-color-active-hover\n// --n-item-text-color-child-active\n// --n-item-text-color-child-active-hover\n// --n-item-text-color-horizontal\n// --n-item-text-color-hover-horizontal\n// --n-item-text-color-active-horizontal\n// --n-item-text-color-active-hover-horizontal\n// --n-item-text-color-child-active-horizontal\n// --n-item-text-color-child-active-hover-horizontal\n// --n-item-icon-color\n// --n-item-icon-color-hover\n// --n-item-icon-color-active\n// --n-item-icon-color-active-hover\n// --n-item-icon-color-child-active\n// --n-item-icon-color-child-active-hover\n// --n-item-icon-color-collapsed\n// --n-item-icon-color-horizontal\n// --n-item-icon-color-hover-horizontal\n// --n-item-icon-color-active-horizontal\n// --n-item-icon-color-active-hover-horizontal\n// --n-item-icon-color-child-active-horizontal\n// --n-item-icon-color-child-active-hover-horizontal\n// --n-item-height\nexport default c([\n  cB('menu', `\n    background-color: var(--n-color);\n    color: var(--n-item-text-color);\n    overflow: hidden;\n    transition: background-color .3s var(--n-bezier);\n    box-sizing: border-box;\n    font-size: var(--n-font-size);\n    padding-bottom: 6px;\n  `, [\n    cM('horizontal', `\n      max-width: 100%;\n      width: 100%;\n      display: flex;\n      overflow: hidden;\n      padding-bottom: 0;\n    `, [\n      cB('submenu', 'margin: 0;'),\n      cB('menu-item', 'margin: 0;'),\n      cB('menu-item-content', `\n        padding: 0 20px;\n        border-bottom: 2px solid #0000;\n      `, [\n        c('&::before', 'display: none;'),\n        cM('selected', 'border-bottom: 2px solid var(--n-border-color-horizontal)')\n      ]),\n      cB('menu-item-content', [\n        cM('selected', [\n          cE('icon', 'color: var(--n-item-icon-color-active-horizontal);'),\n          cB('menu-item-content-header', `\n            color: var(--n-item-text-color-active-horizontal);\n          `, [\n            c('a', 'color: var(--n-item-text-color-active-horizontal);'),\n            cE('extra', 'color: var(--n-item-text-color-active-horizontal);')\n          ])\n        ]),\n        cM('child-active', `\n          border-bottom: 2px solid var(--n-border-color-horizontal);\n        `, [\n          cB('menu-item-content-header', `\n            color: var(--n-item-text-color-child-active-horizontal);\n          `, [\n            c('a', `\n              color: var(--n-item-text-color-child-active-horizontal);\n            `),\n            cE('extra', `\n              color: var(--n-item-text-color-child-active-horizontal);\n            `)\n          ]),\n          cE('icon', `\n            color: var(--n-item-icon-color-child-active-horizontal);\n          `)\n        ]),\n        cNotM('disabled', [\n          cNotM('selected, child-active', [\n            c('&:focus-within', horizontalHoverStyleChildren)\n          ]),\n          cM('selected', [\n            hoverStyle(null, [\n              cE('icon', 'color: var(--n-item-icon-color-active-hover-horizontal);'),\n              cB('menu-item-content-header', `\n                color: var(--n-item-text-color-active-hover-horizontal);\n              `, [\n                c('a', 'color: var(--n-item-text-color-active-hover-horizontal);'),\n                cE('extra', 'color: var(--n-item-text-color-active-hover-horizontal);')\n              ])\n            ])\n          ]),\n          cM('child-active', [\n            hoverStyle(null, [\n              cE('icon', 'color: var(--n-item-icon-color-child-active-hover-horizontal);'),\n              cB('menu-item-content-header', `\n                color: var(--n-item-text-color-child-active-hover-horizontal);\n              `, [\n                c('a', 'color: var(--n-item-text-color-child-active-hover-horizontal);'),\n                cE('extra', 'color: var(--n-item-text-color-child-active-hover-horizontal);')\n              ])\n            ])\n          ]),\n          hoverStyle('border-bottom: 2px solid var(--n-border-color-horizontal);', horizontalHoverStyleChildren)\n        ]),\n        cB('menu-item-content-header', [\n          c('a', 'color: var(--n-item-text-color-horizontal);')\n        ])\n      ])\n    ]),\n    cNotM('responsive', [\n      cB('menu-item-content-header', `\n        overflow: hidden;\n        text-overflow: ellipsis;\n      `)\n    ]),\n    cM('collapsed', [\n      cB('menu-item-content', [\n        cM('selected', [\n          c('&::before', `\n            background-color: var(--n-item-color-active-collapsed) !important;\n          `)\n        ]),\n        cB('menu-item-content-header', 'opacity: 0;'),\n        cE('arrow', 'opacity: 0;'),\n        cE('icon', 'color: var(--n-item-icon-color-collapsed);')\n      ])\n    ]),\n    cB('menu-item', `\n      height: var(--n-item-height);\n      margin-top: 6px;\n      position: relative;\n    `),\n    cB('menu-item-content', `\n      box-sizing: border-box;\n      line-height: 1.75;\n      height: 100%;\n      display: grid;\n      grid-template-areas: \"icon content arrow\";\n      grid-template-columns: auto 1fr auto;\n      align-items: center;\n      cursor: pointer;\n      position: relative;\n      padding-right: 18px;\n      transition:\n        background-color .3s var(--n-bezier),\n        padding-left .3s var(--n-bezier),\n        border-color .3s var(--n-bezier);\n    `, [\n      c('> *', 'z-index: 1;'),\n      c('&::before', `\n        z-index: auto;\n        content: \"\";\n        background-color: #0000;\n        position: absolute;\n        left: 8px;\n        right: 8px;\n        top: 0;\n        bottom: 0;\n        pointer-events: none;\n        border-radius: var(--n-border-radius);\n        transition: background-color .3s var(--n-bezier);\n      `),\n      cM('disabled', `\n        opacity: .45;\n        cursor: not-allowed;\n      `),\n      cM('collapsed', [\n        cE('arrow', 'transform: rotate(0);')\n      ]),\n      cM('selected', [\n        c('&::before', 'background-color: var(--n-item-color-active);'),\n        cE('arrow', 'color: var(--n-arrow-color-active);'),\n        cE('icon', 'color: var(--n-item-icon-color-active);'),\n        cB('menu-item-content-header', `\n          color: var(--n-item-text-color-active);\n        `, [\n          c('a', 'color: var(--n-item-text-color-active);'),\n          cE('extra', 'color: var(--n-item-text-color-active);')\n        ])\n      ]),\n      cM('child-active', [\n        cB('menu-item-content-header', `\n          color: var(--n-item-text-color-child-active);\n        `, [\n          c('a', `\n            color: var(--n-item-text-color-child-active);\n          `),\n          cE('extra', `\n            color: var(--n-item-text-color-child-active);\n          `)\n        ]),\n        cE('arrow', `\n          color: var(--n-arrow-color-child-active);\n        `),\n        cE('icon', `\n          color: var(--n-item-icon-color-child-active);\n        `)\n      ]),\n      cNotM('disabled', [\n        cNotM('selected, child-active', [\n          c('&:focus-within', hoverStyleChildren)\n        ]),\n        cM('selected', [\n          hoverStyle(null, [\n            cE('arrow', 'color: var(--n-arrow-color-active-hover);'),\n            cE('icon', 'color: var(--n-item-icon-color-active-hover);'),\n            cB('menu-item-content-header', `\n              color: var(--n-item-text-color-active-hover);\n            `, [\n              c('a', 'color: var(--n-item-text-color-active-hover);'),\n              cE('extra', 'color: var(--n-item-text-color-active-hover);')\n            ])\n          ])\n        ]),\n        cM('child-active', [\n          hoverStyle(null, [\n            cE('arrow', 'color: var(--n-arrow-color-child-active-hover);'),\n            cE('icon', 'color: var(--n-item-icon-color-child-active-hover);'),\n            cB('menu-item-content-header', `\n              color: var(--n-item-text-color-child-active-hover);\n            `, [\n              c('a', 'color: var(--n-item-text-color-child-active-hover);'),\n              cE('extra', 'color: var(--n-item-text-color-child-active-hover);')\n            ])\n          ])\n        ]),\n        cM('selected', [\n          hoverStyle(null, [\n            c('&::before', 'background-color: var(--n-item-color-active-hover);')\n          ])\n        ]),\n        hoverStyle(null, hoverStyleChildren)\n      ]),\n      cE('icon', `\n        grid-area: icon;\n        color: var(--n-item-icon-color);\n        transition:\n          color .3s var(--n-bezier),\n          font-size .3s var(--n-bezier),\n          margin-right .3s var(--n-bezier);\n        box-sizing: content-box;\n        display: inline-flex;\n        align-items: center;\n        justify-content: center;\n      `),\n      cE('arrow', `\n        grid-area: arrow;\n        font-size: 16px;\n        color: var(--n-arrow-color);\n        transform: rotate(180deg);\n        opacity: 1;\n        transition:\n          color .3s var(--n-bezier),\n          transform 0.2s var(--n-bezier),\n          opacity 0.2s var(--n-bezier);\n      `),\n      cB('menu-item-content-header', `\n        grid-area: content;\n        transition:\n          color .3s var(--n-bezier),\n          opacity .3s var(--n-bezier);\n        opacity: 1;\n        white-space: nowrap;\n        color: var(--n-item-text-color);\n      `, [\n        c('a', `\n          outline: none;\n          text-decoration: none;\n          transition: color .3s var(--n-bezier);\n          color: var(--n-item-text-color);\n        `, [\n          c('&::before', `\n            content: \"\";\n            position: absolute;\n            left: 0;\n            right: 0;\n            top: 0;\n            bottom: 0;\n          `)\n        ]),\n        cE('extra', `\n          font-size: .93em;\n          color: var(--n-group-text-color);\n          transition: color .3s var(--n-bezier);\n        `)\n      ])\n    ]),\n    cB('submenu', `\n      cursor: pointer;\n      position: relative;\n      margin-top: 6px;\n    `, [\n      cB('menu-item-content', `\n        height: var(--n-item-height);\n      `),\n      cB('submenu-children', `\n        overflow: hidden;\n        padding: 0;\n      `, [\n        fadeInHeightExpandTransition({\n          duration: '.2s'\n        })\n      ])\n    ]),\n    cB('menu-item-group', [\n      cB('menu-item-group-title', `\n        margin-top: 6px;\n        color: var(--n-group-text-color);\n        cursor: default;\n        font-size: .93em;\n        height: 36px;\n        display: flex;\n        align-items: center;\n        transition:\n          padding-left .3s var(--n-bezier),\n          color .3s var(--n-bezier);\n      `)\n    ])\n  ]),\n  cB('menu-tooltip', [\n    c('a', `\n      color: inherit;\n      text-decoration: none;\n    `)\n  ]),\n  cB('menu-divider', `\n    transition: background-color .3s var(--n-bezier);\n    background-color: var(--n-divider-color);\n    height: 1px;\n    margin: 6px 18px;\n  `)\n])\n\nfunction hoverStyle(props: CProperties, children: CNodeChildren): CNode[] {\n  return [cM('hover', props, children), c('&:hover', props, children)]\n}\n"
  },
  {
    "path": "src/menu/src/use-menu-child-props.ts",
    "content": "import type { Key } from 'treemate'\nimport type { ExtractPropTypes, PropType, VNodeChild } from 'vue'\n\nexport const useMenuChildProps = {\n  internalKey: {\n    type: [String, Number] as PropType<Key>,\n    required: true\n  },\n  root: Boolean,\n  isGroup: Boolean,\n  level: {\n    type: Number,\n    required: true\n  },\n  title: [String, Function] as PropType<string | (() => VNodeChild)>,\n  extra: [String, Function] as PropType<string | (() => VNodeChild)>\n} as const\n\nexport type UseMenuChildProps = ExtractPropTypes<typeof useMenuChildProps>\n"
  },
  {
    "path": "src/menu/src/use-menu-child.ts",
    "content": "import type { Key } from 'treemate'\nimport type { ComputedRef, Ref } from 'vue'\nimport type { FollowerPlacement } from 'vueuc'\nimport type { MergedTheme } from '../../_mixins/use-theme'\nimport type { MenuTheme } from '../styles'\nimport type { OnUpdateValueImpl } from './interface'\nimport type { MenuSetupProps } from './Menu'\nimport type { UseMenuChildProps } from './use-menu-child-props'\nimport { computed, inject } from 'vue'\nimport {\n  menuInjectionKey,\n  menuItemGroupInjectionKey,\n  submenuInjectionKey\n} from './context'\n\nconst ICON_MARGIN_RIGHT = 8\n\nexport interface MenuInjection {\n  props: MenuSetupProps\n  mergedCollapsedRef: Ref<boolean>\n  invertedRef: Ref<boolean>\n  isHorizontalRef: Ref<boolean>\n  mergedClsPrefixRef: Ref<string>\n  mergedValueRef: Ref<Key | null>\n  mergedExpandedKeysRef: Ref<Key[]>\n  activePathRef: Ref<Key[]>\n  mergedThemeRef: Ref<MergedTheme<MenuTheme>>\n  doSelect: OnUpdateValueImpl\n  toggleExpand: (key: Key) => void\n}\n\nexport interface SubmenuInjection {\n  paddingLeftRef: Ref<number | undefined>\n  mergedDisabledRef: Ref<boolean>\n}\n\nexport interface MenuOptionGroupInjection {\n  paddingLeftRef: Ref<number | undefined>\n  mergedDisabledRef: Ref<boolean>\n}\n\nexport interface UseMenuChild {\n  dropdownPlacement: ComputedRef<FollowerPlacement>\n  activeIconSize: ComputedRef<number>\n  maxIconSize: ComputedRef<number>\n  paddingLeft: ComputedRef<number | undefined>\n  iconMarginRight: ComputedRef<number>\n  NMenu: MenuInjection\n  NSubmenu: SubmenuInjection | null\n  NMenuOptionGroup: MenuOptionGroupInjection | null\n}\n\nexport function useMenuChild(props: UseMenuChildProps): UseMenuChild {\n  const NMenu = inject(menuInjectionKey)!\n  const { props: menuProps, mergedCollapsedRef } = NMenu\n  const NSubmenu = inject(submenuInjectionKey, null)\n  const NMenuOptionGroup = inject<MenuOptionGroupInjection | null>(\n    menuItemGroupInjectionKey,\n    null\n  )\n  const horizontalRef = computed(() => {\n    return menuProps.mode === 'horizontal'\n  })\n  const dropdownPlacementRef = computed(() => {\n    if (horizontalRef.value) {\n      return menuProps.dropdownPlacement\n    }\n    if ('tmNodes' in props)\n      return 'right-start'\n    return 'right'\n  })\n  const maxIconSizeRef = computed(() => {\n    return Math.max(\n      menuProps.collapsedIconSize ?? menuProps.iconSize,\n      menuProps.iconSize\n    )\n  })\n  const activeIconSizeRef = computed(() => {\n    if (!horizontalRef.value && props.root && mergedCollapsedRef.value) {\n      return menuProps.collapsedIconSize ?? menuProps.iconSize\n    }\n    else {\n      return menuProps.iconSize\n    }\n  })\n  const paddingLeftRef = computed(() => {\n    if (horizontalRef.value)\n      return undefined\n    const { collapsedWidth, indent, rootIndent } = menuProps\n    const { root, isGroup } = props\n    const mergedRootIndent = rootIndent === undefined ? indent : rootIndent\n    if (root) {\n      if (mergedCollapsedRef.value) {\n        return collapsedWidth / 2 - maxIconSizeRef.value / 2\n      }\n      return mergedRootIndent\n    }\n    if (\n      NMenuOptionGroup\n      && typeof NMenuOptionGroup.paddingLeftRef.value === 'number'\n    ) {\n      return indent / 2 + NMenuOptionGroup.paddingLeftRef.value\n    }\n    if (NSubmenu && typeof NSubmenu.paddingLeftRef.value === 'number') {\n      return (isGroup ? indent / 2 : indent) + NSubmenu.paddingLeftRef.value\n    }\n    // Shouldn't reach here\n    return 0\n  })\n  const iconMarginRightRef = computed(() => {\n    const { collapsedWidth, indent, rootIndent } = menuProps\n    const { value: maxIconSize } = maxIconSizeRef\n    const { root } = props\n    if (horizontalRef.value)\n      return ICON_MARGIN_RIGHT\n    if (!root)\n      return ICON_MARGIN_RIGHT\n    if (!mergedCollapsedRef.value)\n      return ICON_MARGIN_RIGHT\n    const mergedRootIndent = rootIndent === undefined ? indent : rootIndent\n    return (\n      mergedRootIndent\n      + maxIconSize\n      + ICON_MARGIN_RIGHT\n      - (collapsedWidth + maxIconSize) / 2\n    )\n  })\n  return {\n    dropdownPlacement: dropdownPlacementRef,\n    activeIconSize: activeIconSizeRef,\n    maxIconSize: maxIconSizeRef,\n    paddingLeft: paddingLeftRef,\n    iconMarginRight: iconMarginRightRef,\n    NMenu,\n    NSubmenu,\n    NMenuOptionGroup\n  }\n}\n"
  },
  {
    "path": "src/menu/src/useCheckDeprecated.ts",
    "content": "import type { MenuSetupProps } from './Menu'\nimport { watchEffect } from 'vue'\nimport { warnOnce } from '../../_utils'\n\nexport function useCheckDeprecated(props: MenuSetupProps): void {\n  watchEffect(() => {\n    if (props.items) {\n      warnOnce('menu', '`items` is deprecated, please use `options` instead.')\n    }\n    if (props.onOpenNamesChange) {\n      warnOnce(\n        'menu',\n        '`on-open-names-change` is deprecated, please use `on-update:expanded-keys` instead.'\n      )\n    }\n    if (props.onSelect) {\n      warnOnce(\n        'menu',\n        '`on-select` is deprecated, please use `on-update:value` instead.'\n      )\n    }\n    if (props.onExpandedNamesChange) {\n      warnOnce(\n        'menu',\n        '`on-expanded-names-change` is deprecated, please use `on-update:expanded-keys` instead.'\n      )\n    }\n    if (props.expandedNames) {\n      warnOnce(\n        'menu',\n        '`expanded-names` is deprecated, please use `expanded-keys` instead.'\n      )\n    }\n    if (props.defaultExpandedNames) {\n      warnOnce(\n        'menu',\n        '`default-expanded-names` is deprecated, please use `default-expanded-keys` instead.'\n      )\n    }\n  })\n}\n"
  },
  {
    "path": "src/menu/src/utils.tsx",
    "content": "import type { TreeNode } from 'treemate'\nimport type { VNode, VNodeChild } from 'vue'\nimport type {\n  MenuGroupOption,\n  MenuIgnoredOption,\n  MenuMixedOption,\n  MenuOption\n} from './interface'\nimport type { MenuSetupProps } from './Menu'\nimport { h } from 'vue'\n\nimport { keep } from '../../_utils'\nimport NMenuDivider from './MenuDivider'\nimport { menuItemPropKeys, NMenuOption } from './MenuOption'\nimport { menuItemGroupPropKeys, NMenuOptionGroup } from './MenuOptionGroup'\nimport { NSubmenu, submenuPropKeys } from './Submenu'\n\nexport function isIgnoredNode(\n  rawNode: MenuMixedOption\n): rawNode is MenuIgnoredOption {\n  return rawNode.type === 'divider' || rawNode.type === 'render'\n}\n\nexport function isDividerNode(\n  rawNode: MenuMixedOption\n): rawNode is MenuIgnoredOption {\n  return rawNode.type === 'divider'\n}\n\nexport function itemRenderer(\n  tmNode: TreeNode<MenuOption, MenuGroupOption, MenuIgnoredOption>,\n  menuProps: MenuSetupProps\n): VNode | null {\n  const { rawNode } = tmNode\n  const { show } = rawNode\n  if (show === false) {\n    return null\n  }\n  if (isIgnoredNode(rawNode)) {\n    if (isDividerNode(rawNode)) {\n      return <NMenuDivider key={tmNode.key} {...rawNode.props} />\n    }\n    return null\n  }\n\n  const { labelField } = menuProps\n  const { key, level, isGroup } = tmNode\n  const props = {\n    ...rawNode,\n    title: (rawNode.title || rawNode[labelField]) as\n    | string\n    | (() => VNodeChild)\n    | undefined,\n    extra: rawNode.titleExtra || rawNode.extra,\n    key,\n    internalKey: key, // since key can't be used as a prop\n    level,\n    root: level === 0,\n    isGroup\n  }\n\n  if (tmNode.children) {\n    if (tmNode.isGroup) {\n      return h(\n        NMenuOptionGroup,\n        keep(props, menuItemGroupPropKeys, {\n          tmNode,\n          tmNodes: tmNode.children,\n          key\n        })\n      )\n    }\n    return h(\n      NSubmenu,\n      keep(props, submenuPropKeys, {\n        key,\n        rawNodes: rawNode[menuProps.childrenField] as any,\n        tmNodes: tmNode.children,\n        tmNode\n      })\n    )\n  }\n  else {\n    return h(\n      NMenuOption,\n      keep(props, menuItemPropKeys, {\n        key,\n        tmNode\n      })\n    )\n  }\n}\n"
  },
  {
    "path": "src/menu/styles/dark.ts",
    "content": "import type { MenuTheme } from './light'\nimport { changeColor } from 'seemly'\nimport { commonDark } from '../../_styles/common'\nimport { dropdownDark } from '../../dropdown/styles'\nimport { tooltipDark } from '../../tooltip/styles'\nimport { self } from './light'\n\nconst menuDark: MenuTheme = {\n  name: 'Menu',\n  common: commonDark,\n  peers: {\n    Tooltip: tooltipDark,\n    Dropdown: dropdownDark\n  },\n  self(vars) {\n    const { primaryColor, primaryColorSuppl } = vars\n    const commonSelf = self(vars)\n    commonSelf.itemColorActive = changeColor(primaryColor, { alpha: 0.15 })\n    commonSelf.itemColorActiveHover = changeColor(primaryColor, { alpha: 0.15 })\n    commonSelf.itemColorActiveCollapsed = changeColor(primaryColor, {\n      alpha: 0.15\n    })\n    commonSelf.itemColorActiveInverted = primaryColorSuppl\n    commonSelf.itemColorActiveHoverInverted = primaryColorSuppl\n    commonSelf.itemColorActiveCollapsedInverted = primaryColorSuppl\n    return commonSelf\n  }\n}\n\nexport default menuDark\n"
  },
  {
    "path": "src/menu/styles/index.ts",
    "content": "export { default as menuDark } from './dark'\nexport { default as menuLight } from './light'\nexport type { MenuTheme, MenuThemeVars } from './light'\n"
  },
  {
    "path": "src/menu/styles/light.ts",
    "content": "import type { ThemeCommonVars } from '../../_styles/common'\nimport { changeColor } from 'seemly'\nimport { createTheme } from '../../_mixins/use-theme'\nimport { commonLight } from '../../_styles/common'\nimport { dropdownLight } from '../../dropdown/styles'\nimport { tooltipLight } from '../../tooltip/styles'\n\nexport function createPartialInvertedVars(\n  color: string,\n  activeItemColor: string,\n  activeTextColor: string,\n  groupTextColor: string\n) {\n  return {\n    itemColorHoverInverted: '#0000',\n    itemColorActiveInverted: activeItemColor,\n    itemColorActiveHoverInverted: activeItemColor,\n    itemColorActiveCollapsedInverted: activeItemColor,\n    itemTextColorInverted: color,\n    itemTextColorHoverInverted: activeTextColor,\n    itemTextColorChildActiveInverted: activeTextColor,\n    itemTextColorChildActiveHoverInverted: activeTextColor,\n    itemTextColorActiveInverted: activeTextColor,\n    itemTextColorActiveHoverInverted: activeTextColor,\n    itemTextColorHorizontalInverted: color,\n    itemTextColorHoverHorizontalInverted: activeTextColor,\n    itemTextColorChildActiveHorizontalInverted: activeTextColor,\n    itemTextColorChildActiveHoverHorizontalInverted: activeTextColor,\n    itemTextColorActiveHorizontalInverted: activeTextColor,\n    itemTextColorActiveHoverHorizontalInverted: activeTextColor,\n    itemIconColorInverted: color,\n    itemIconColorHoverInverted: activeTextColor,\n    itemIconColorActiveInverted: activeTextColor,\n    itemIconColorActiveHoverInverted: activeTextColor,\n    itemIconColorChildActiveInverted: activeTextColor,\n    itemIconColorChildActiveHoverInverted: activeTextColor,\n    itemIconColorCollapsedInverted: color,\n    itemIconColorHorizontalInverted: color,\n    itemIconColorHoverHorizontalInverted: activeTextColor,\n    itemIconColorActiveHorizontalInverted: activeTextColor,\n    itemIconColorActiveHoverHorizontalInverted: activeTextColor,\n    itemIconColorChildActiveHorizontalInverted: activeTextColor,\n    itemIconColorChildActiveHoverHorizontalInverted: activeTextColor,\n    arrowColorInverted: color,\n    arrowColorHoverInverted: activeTextColor,\n    arrowColorActiveInverted: activeTextColor,\n    arrowColorActiveHoverInverted: activeTextColor,\n    arrowColorChildActiveInverted: activeTextColor,\n    arrowColorChildActiveHoverInverted: activeTextColor,\n    groupTextColorInverted: groupTextColor\n  }\n}\n\nexport function self(vars: ThemeCommonVars) {\n  const {\n    borderRadius,\n    textColor3,\n    primaryColor,\n    textColor2,\n    textColor1,\n    fontSize,\n    dividerColor,\n    hoverColor,\n    primaryColorHover\n  } = vars\n  return {\n    borderRadius,\n    color: '#0000',\n    groupTextColor: textColor3,\n    itemColorHover: hoverColor,\n    itemColorActive: changeColor(primaryColor, { alpha: 0.1 }),\n    itemColorActiveHover: changeColor(primaryColor, { alpha: 0.1 }),\n    itemColorActiveCollapsed: changeColor(primaryColor, { alpha: 0.1 }),\n    itemTextColor: textColor2,\n    itemTextColorHover: textColor2,\n    itemTextColorActive: primaryColor,\n    itemTextColorActiveHover: primaryColor,\n    itemTextColorChildActive: primaryColor,\n    itemTextColorChildActiveHover: primaryColor,\n    itemTextColorHorizontal: textColor2,\n    itemTextColorHoverHorizontal: primaryColorHover,\n    itemTextColorActiveHorizontal: primaryColor,\n    itemTextColorActiveHoverHorizontal: primaryColor,\n    itemTextColorChildActiveHorizontal: primaryColor,\n    itemTextColorChildActiveHoverHorizontal: primaryColor,\n    itemIconColor: textColor1,\n    itemIconColorHover: textColor1,\n    itemIconColorActive: primaryColor,\n    itemIconColorActiveHover: primaryColor,\n    itemIconColorChildActive: primaryColor,\n    itemIconColorChildActiveHover: primaryColor,\n    itemIconColorCollapsed: textColor1,\n    itemIconColorHorizontal: textColor1,\n    itemIconColorHoverHorizontal: primaryColorHover,\n    itemIconColorActiveHorizontal: primaryColor,\n    itemIconColorActiveHoverHorizontal: primaryColor,\n    itemIconColorChildActiveHorizontal: primaryColor,\n    itemIconColorChildActiveHoverHorizontal: primaryColor,\n    itemHeight: '42px',\n    arrowColor: textColor2,\n    arrowColorHover: textColor2,\n    arrowColorActive: primaryColor,\n    arrowColorActiveHover: primaryColor,\n    arrowColorChildActive: primaryColor,\n    arrowColorChildActiveHover: primaryColor,\n    colorInverted: '#0000',\n    borderColorHorizontal: '#0000',\n    fontSize,\n    dividerColor,\n    ...createPartialInvertedVars('#BBB', primaryColor, '#FFF', '#AAA')\n  }\n}\n\nexport type MenuThemeVars = ReturnType<typeof self>\n\nconst menuLight = createTheme({\n  name: 'Menu',\n  common: commonLight,\n  peers: {\n    Tooltip: tooltipLight,\n    Dropdown: dropdownLight\n  },\n  self\n})\n\nexport default menuLight\nexport type MenuTheme = typeof menuLight\n"
  },
  {
    "path": "src/menu/tests/Menu.spec.tsx",
    "content": "import type { MenuDividerOption, MenuGroupOption, MenuOption } from '../index'\n/* eslint-disable unused-imports/no-unused-vars */\nimport { HappyOutline } from '@vicons/ionicons5'\nimport { mount } from '@vue/test-utils'\nimport { sleep } from 'seemly'\nimport { Comment, h } from 'vue'\nimport { NIcon } from '../../icon'\nimport { NMenu } from '../index'\n\ndescribe('n-menu', () => {\n  it('should work with import on demand', () => {\n    mount(NMenu)\n  })\n\n  it('props.options type', () => {\n    const options: Array<MenuOption | MenuGroupOption | MenuDividerOption> = [\n      {\n        label: 'l',\n        key: 'key'\n      },\n      {\n        type: 'group',\n        key: 'group',\n        children: [\n          {\n            label: 'l',\n            key: 'key2'\n          },\n          {\n            type: 'divider',\n            key: 'key3'\n          }\n        ]\n      }\n    ]\n    mount(NMenu, { props: { options } })\n  })\n\n  it('props.onUpdateValue type', () => {\n    const stringCb = (v: string): void => {}\n    const numberCb = (v: number): void => {}\n    const snCb = (v: string | number): void => {}\n    const stringArrCb = (v: string[]): void => {}\n    const numberArrCb = (v: number[]): void => {}\n    const snArrCb = (v: Array<string | number>): void => {}\n    mount(NMenu, {\n      props: {\n        onUpdateValue: stringCb,\n        onUpdateExpandedKeys: stringArrCb\n      }\n    })\n    mount(NMenu, {\n      props: {\n        onUpdateValue: numberCb,\n        onUpdateExpandedKeys: numberArrCb\n      }\n    })\n    mount(NMenu, {\n      props: {\n        onUpdateValue: snCb,\n        onUpdateExpandedKeys: snArrCb\n      }\n    })\n  })\n\n  it('should work with `render-icon` props', async () => {\n    const options = [\n      {\n        label: 'fantasy',\n        key: 'fantasy'\n      },\n      {\n        label: 'mojito',\n        key: 'mojito'\n      },\n      {\n        label: 'initialj',\n        key: 'initialj'\n      }\n    ]\n    function renderMenuIcon(option: any): any {\n      // return comment vnode, render placeholder for indent\n      if (option.key === 'mojito')\n        return h(Comment)\n      // return falsy, don't render icon placeholder\n      if (option.key === 'initialj')\n        return null\n      // otherwise, render returns vnode\n      return h(NIcon, null, { default: () => h(HappyOutline) })\n    }\n    const wrapper = mount(NMenu, {\n      props: {\n        options,\n        renderIcon: renderMenuIcon\n      }\n    })\n    expect(wrapper.findAll('.n-menu-item-content__icon').length).toBe(2)\n    expect(wrapper.findAll('.n-icon').length).toBe(1)\n    wrapper.unmount()\n  })\n\n  it('should tooltip work with `render-label` props', async () => {\n    const options = [\n      {\n        label: () =>\n          h(\n            'a',\n            {\n              href: 'test1',\n              target: '_blank',\n              rel: 'test1'\n            },\n            'test1'\n          ),\n        key: 'test1'\n      },\n      {\n        label: 'test2',\n        key: 'test2'\n      }\n    ]\n    const renderLabel = (option: any): any => {\n      if (typeof option.label === 'function') {\n        return option.label()\n      }\n      return h(\n        'a',\n        {\n          href: option.key,\n          rel: option.key\n        },\n        { default: () => option.label }\n      )\n    }\n    const wrapper = mount(NMenu, {\n      props: {\n        options\n      }\n    })\n    expect(wrapper.find('[href=\"test1\"]').exists()).toBe(true)\n    expect(wrapper.find('[href=\"test2\"]').exists()).toBe(false)\n\n    await wrapper.setProps({ renderLabel })\n    expect(wrapper.find('[href=\"test1\"]').exists()).toBe(true)\n    expect(wrapper.find('[target=\"_blank\"]').exists()).toBe(true)\n    expect(wrapper.find('[href=\"test2\"]').exists()).toBe(true)\n    wrapper.unmount()\n  })\n\n  it('should dropdown work with `render-label` props', async () => {\n    const options = [\n      {\n        label: 'jj',\n        key: 'jj'\n      },\n      {\n        label: 'jay',\n        key: 'jay',\n        children: [\n          {\n            type: 'group',\n            label: 'song-group',\n            key: 'group',\n            children: [\n              {\n                label: 'fantasy',\n                key: 'fantasy'\n              },\n              {\n                label: 'mojito',\n                key: 'mojito'\n              }\n            ]\n          }\n        ]\n      }\n    ]\n    const renderLabel = (option: any): any => {\n      return h(\n        'a',\n        {\n          class: option.key,\n          href: option.key,\n          rel: option.key\n        },\n        { default: () => option.label }\n      )\n    }\n    const wrapper = mount(NMenu, {\n      props: {\n        options,\n        collapsed: true,\n        renderLabel\n      }\n    })\n    expect(wrapper.find('.n-submenu').exists()).toBe(true)\n    await wrapper.find('.n-submenu').trigger('mouseenter')\n    // Popover has delay, so we need to wait\n    await sleep(150)\n    expect(document.body.querySelector('.n-dropdown')).not.toEqual(null)\n    expect(document.querySelectorAll('a').length).toEqual(3)\n    expect(document.querySelectorAll('a.fantasy').length).toEqual(1)\n    wrapper.unmount()\n  })\n\n  it('should dropdown work with `render-icon` props', async () => {\n    const options = [\n      {\n        label: 'jj',\n        key: 'jj'\n      },\n      {\n        label: 'jay',\n        key: 'jay',\n        children: [\n          {\n            type: 'group',\n            label: 'song-group',\n            key: 'group',\n            children: [\n              {\n                label: 'fantasy',\n                key: 'fantasy'\n              },\n              {\n                label: 'mojito',\n                key: 'mojito'\n              }\n            ]\n          }\n        ]\n      }\n    ]\n    function renderMenuIcon(): any {\n      return h(NIcon, null, { default: () => h(HappyOutline) })\n    }\n    const wrapper = mount(NMenu, {\n      props: {\n        options,\n        collapsed: true,\n        renderIcon: renderMenuIcon\n      }\n    })\n    expect(wrapper.find('.n-submenu').exists()).toBe(true)\n    await wrapper.find('.n-submenu').trigger('mouseenter')\n    // Popover has delay, so we need to wait\n    await sleep(150)\n    expect(document.body.querySelector('.n-dropdown')).not.toEqual(null)\n    expect(document.querySelectorAll('.n-icon').length).toEqual(2)\n    wrapper.unmount()\n  })\n\n  it('should dropdown work with `expand-icon` props', () => {\n    const options = [\n      {\n        label: 'jj',\n        key: 'jj'\n      },\n      {\n        label: 'jay',\n        key: 'jay',\n        children: [\n          {\n            type: 'group',\n            label: 'song-group',\n            key: 'group',\n            children: [\n              {\n                label: 'fantasy',\n                key: 'fantasy'\n              },\n              {\n                label: 'mojito',\n                key: 'mojito'\n              }\n            ]\n          }\n        ]\n      }\n    ]\n    function renderExpandIcon(): any {\n      return h('span', { class: 'expand-icon' }, '1')\n    }\n    const wrapper = mount(NMenu, {\n      props: {\n        options,\n        expandIcon: renderExpandIcon\n      }\n    })\n    expect(wrapper.find('.expand-icon').text()).toEqual('1')\n    wrapper.unmount()\n  })\n\n  it('should dropdown work with `render-extra` props', async () => {\n    const options = [\n      {\n        label: 'jj',\n        key: 'jj'\n      },\n      {\n        label: 'jay',\n        key: 'jay',\n        children: [\n          {\n            type: 'group',\n            label: 'song-group',\n            key: 'group',\n            children: [\n              {\n                label: 'fantasy',\n                key: 'fantasy'\n              },\n              {\n                label: 'mojito',\n                key: 'mojito'\n              }\n            ]\n          }\n        ]\n      }\n    ]\n    function renderMenuExtra(): any {\n      return 'test'\n    }\n    const wrapper = mount(NMenu, {\n      props: {\n        defaultExpandAll: true,\n        options,\n        renderExtra: renderMenuExtra\n      }\n    })\n    expect(\n      wrapper.findAll('.n-menu-item-content-header__extra').length\n    ).toEqual(4)\n    wrapper.unmount()\n  })\n\n  it('should accept empty object in type-checking phase', () => {\n    ;<NMenu options={[{}]} />\n  })\n\n  it('should work with `defaultExpandedKeys` props', async () => {\n    const menuOptions = [\n      {\n        label: '且听风吟',\n        key: 'hear-the-wind-sing'\n      },\n      {\n        label: '舞，舞，舞',\n        key: 'dance-dance-dance',\n        children: [\n          {\n            label: '叙事者',\n            key: 'narrator'\n          },\n          {\n            label: '食物',\n            key: 'food',\n            children: [\n              {\n                label: '三明治',\n                key: 'sandwich'\n              }\n            ]\n          },\n          {\n            label: '过去增多，未来减少',\n            key: 'the-past-increases-the-future-recedes'\n          }\n        ]\n      }\n    ]\n    const defaultExpandedKeys = ['dance-dance-dance']\n    const wrapper = mount(NMenu, {\n      props: {\n        defaultExpandedKeys,\n        options: menuOptions\n      }\n    })\n    expect(wrapper.find('.n-submenu-children').element.children.length).toBe(3)\n    wrapper.unmount()\n  })\n\n  it('accepts proper options', () => {\n    ;(() => (\n      <NMenu\n        options={[\n          {\n            type: 'divider'\n          },\n          {\n            type: 'group',\n            key: 'foo'\n          },\n          {\n            key: 'blabla',\n            label: 'kirby'\n          },\n          {\n            key: 'xxxx',\n            children: [\n              {\n                type: 'divider'\n              },\n              {\n                type: 'group',\n                key: 'foo1'\n              },\n              {\n                key: 'blabla1',\n                label: 'kirby'\n              }\n            ]\n          }\n        ]}\n      />\n    ))()\n  })\n\n  it('should work with `hidden` prop', async () => {\n    const options = [\n      {\n        label: 'fantasy',\n        key: 'fantasy',\n        show: false\n      },\n      {\n        label: 'mojito',\n        key: 'mojito'\n      },\n      {\n        label: 'initialj',\n        key: 'initialj'\n      }\n    ]\n    const wrapper = mount(NMenu, {\n      props: {\n        options\n      }\n    })\n    expect(wrapper.findAll('.n-menu-item-content').length).toBe(2)\n    wrapper.unmount()\n  })\n\n  it('should work submenu extra', async () => {\n    const options: MenuOption[] = [\n      {\n        label: 'fantasy',\n        key: 'fantasy',\n        extra: 'bar',\n        children: [\n          {\n            label: 'foo',\n            key: 'foo'\n          }\n        ]\n      }\n    ]\n    const wrapper = mount(NMenu, {\n      props: {\n        options\n      }\n    })\n    expect(wrapper.html()).toContain('bar')\n    wrapper.unmount()\n  })\n})\n"
  },
  {
    "path": "src/menu/tests/server.spec.tsx",
    "content": "import { setup } from '@css-render/vue3-ssr'\nimport { renderToString } from '@vue/server-renderer'\n/**\n * @vitest-environment node\n */\nimport { createSSRApp, h } from 'vue'\nimport { NMenu } from '../..'\n\ndescribe('server side rendering', () => {\n  it('works', async () => {\n    const app = createSSRApp(() => <NMenu />)\n    setup(app)\n    try {\n      await renderToString(app)\n    }\n    catch (e) {\n      expect(e).not.toBeTruthy()\n    }\n  })\n})\n"
  },
  {
    "path": "src/message/demos/enUS/about-theme.demo.vue",
    "content": "<markdown>\n# Caveat about theme\n\nIf you don't specify the theme, the theme of created message will be the same as its `n-message-provider`.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { useMessage } from 'naive-ui'\n\nconst message = useMessage()\n\nfunction info() {\n  message.info('I don\\'t know why nobody told you how to unfold your love', {\n    duration: 5000\n  })\n}\n</script>\n\n<template>\n  <n-button @click=\"info\">\n    You can change the theme while the message is active\n  </n-button>\n</template>\n"
  },
  {
    "path": "src/message/demos/enUS/basic.demo.vue",
    "content": "<markdown>\n# Basic\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { useMessage } from 'naive-ui'\n\nconst message = useMessage()\n\nfunction info() {\n  message.info('I don\\'t know why nobody told you how to unfold your love', {\n    keepAliveOnHover: true\n  })\n}\n\nfunction error() {\n  message.error('Once upon a time you dressed so fine')\n}\n\nfunction warning() {\n  message.warning('How many roads must a man walk down')\n}\n\nfunction success() {\n  message.success('\\'Cause you walked hand in hand With another man in my place')\n}\n\nfunction loading() {\n  message.loading(\n    'If I were you, I will realize that I love you more than any other guy'\n  )\n}\n</script>\n\n<template>\n  <n-space>\n    <n-button @click=\"info\">\n      Info(Hover will keep alive)\n    </n-button>\n    <n-button @click=\"error\">\n      Error\n    </n-button>\n    <n-button @click=\"warning\">\n      Warning\n    </n-button>\n    <n-button @click=\"success\">\n      Success\n    </n-button>\n    <n-button @click=\"loading\">\n      Loading\n    </n-button>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/message/demos/enUS/closable.demo.vue",
    "content": "<markdown>\n# Closable\n\nSet `closable` to make message closable by a click.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { useMessage } from 'naive-ui'\n\nconst message = useMessage()\n\nfunction createMessage() {\n  message.info('I don\\'t know why nobody told you how to unfold your love', {\n    closable: true,\n    duration: 5000\n  })\n}\n</script>\n\n<template>\n  <n-button @click=\"createMessage\">\n    Create a Message\n  </n-button>\n</template>\n"
  },
  {
    "path": "src/message/demos/enUS/customize-message.demo.vue",
    "content": "<markdown>\n# Customize message\n\nSome users said that they want to use alert as message.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { MessageRenderMessage } from 'naive-ui'\nimport { NAlert, useMessage } from 'naive-ui'\nimport { h } from 'vue'\n\nconst renderMessage: MessageRenderMessage = (props) => {\n  const { type } = props\n  return h(\n    NAlert,\n    {\n      closable: props.closable,\n      onClose: props.onClose,\n      type: type === 'loading' ? 'default' : type,\n      title: 'Lorem ipsum dolor sit amet',\n      style: {\n        boxShadow: 'var(--n-box-shadow)',\n        maxWidth: 'calc(100vw - 32px)',\n        width: '480px'\n      }\n    },\n    {\n      default: () => props.content\n    }\n  )\n}\n\nconst { error } = useMessage()\n\nfunction handleClick() {\n  error('Lorem ipsum dolor sit amet, consectetur adipiscing elit', {\n    render: renderMessage,\n    closable: true\n  })\n}\n</script>\n\n<template>\n  <n-button @click=\"handleClick\">\n    Lpsum\n  </n-button>\n</template>\n"
  },
  {
    "path": "src/message/demos/enUS/icon.demo.vue",
    "content": "<markdown>\n# Icon\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { MdHourglass } from '@vicons/ionicons4'\nimport { NIcon, useMessage } from 'naive-ui'\nimport { h } from 'vue'\n\nconst message = useMessage()\n\nfunction createMessage() {\n  message.warning('I never needed anybody\\'s help in any way', {\n    icon: () => h(NIcon, null, { default: () => h(MdHourglass) })\n  })\n}\n</script>\n\n<template>\n  <n-button @click=\"createMessage\">\n    Hourglass Icon\n  </n-button>\n</template>\n"
  },
  {
    "path": "src/message/demos/enUS/index.demo-entry.md",
    "content": "# Message\n\nOracle from the top(always) of the browser.\n\n<n-space vertical size=\"large\">\n<n-alert type=\"warning\" title=\"Notice\"  :bordered=\"false\">\n  <n-ul align-text>\n    <li>\n      If you want to use <n-text code>useMessage</n-text> to use message, you need to put the component that calls its method inside <n-text code>n-message-provider</n-text> and use <n-text code>useMessage</n-text> to get the API.\n    </li>\n    <li>\n      If you want to know how to use it outside of <n-text code>setup</n-text>, please refer to Q & A at the bottom of this page.\n    </li>\n  </n-ul>\n</n-alert>\n\nFor example:\n\n```html\n<!-- App.vue -->\n<n-message-provider>\n  <content />\n</n-message-provider>\n```\n\n```js\nimport { useMessage } from 'naive-ui'\nimport { defineComponent } from 'vue'\n\n// content\nexport default defineComponent({\n  setup() {\n    const message = useMessage()\n    return {\n      warning() {\n        message.warning('...')\n      }\n    }\n  }\n})\n```\n\n</n-space>\n\n## Demos\n\n```demo\nbasic.vue\nicon.vue\ntiming.vue\nclosable.vue\nmodify-content.vue\nmanually-close.vue\nabout-theme.vue\nmultiple-line.vue\nplacement.vue\ncustomize-message.vue\nno-icon.vue\n```\n\n## API\n\n### MessageProvider Props\n\n| Name | Type | Default | Description | Version |\n| --- | --- | --- | --- | --- |\n| closable | `boolean` | `false` | Whether to show close icon on all messages. |  |\n| container-class | `string` | `undefined` | Message container class. | 2.36.0 |\n| container-style | `string \\| CSSProperties` | `undefined` | Message container style. |  |\n| duration | `number` | `3000` | Default duration of on all messages. |  |\n| keep-alive-on-hover | `boolean` | `false` | Whether to destroy while hovering on all messages. |  |\n| max | `number` | `undefined` | Limit the number of messages to display. |  |\n| placement | `top \\| top-left \\| top-right \\| bottom \\| bottom-left \\| bottom-right ` | `top` | Placement of all messages. |  |\n| to | `string \\| HTMLElement` | `'body'` | Container node of message container. |  |\n\n### MessageProvider Injection API\n\n#### MessageProvider Injection Methods\n\n| Name | Type | Description | Version |\n| --- | --- | --- | --- |\n| destroyAll | `() => void` | Destroy all popup messages. |  |\n| create | `(content: string \\| (() => VNodeChild), option?: MessageOption) => MessageReactive` | Use create type message. | 2.25.7 |\n| error | `(content: string \\| (() => VNodeChild), option?: MessageOption) => MessageReactive` | Use error type message. |  |\n| info | `(content: string \\| (() => VNodeChild), option?: MessageOption) => MessageReactive` | Use info type message. |  |\n| loading | `(content: string \\| (() => VNodeChild), option?: MessageOption) => MessageReactive` | Use loading type message. |  |\n| success | `(content: string \\| (() => VNodeChild), option?: MessageOption) => MessageReactive` | Use success type message. |  |\n| warning | `(content: string \\| (() => VNodeChild), option?: MessageOption) => MessageReactive` | Use warning type message. |  |\n\n#### MessageOption Properties\n\n| Name | Type | Description | Version |\n| --- | --- | --- | --- |\n| closable | `boolean` | Whether to show close icon. |  |\n| duration | `number` | The duration of the message. |  |\n| icon | `() => VNodeChild` | Message icon. |  |\n| keepAliveOnHover | `boolean` | Messages whether to destroy while hover. |  |\n| render | `MessageRenderMessage` | Render function of the entire message. | 2.24.0 |\n| showIcon | `boolean` | Whether to show icon. | 2.25.7 |\n| spinProps | `{ strokeWidth?: number, stroke?: string, scale?: number, radius?: number }` | Loading icon properties. | 2.44.0 |\n| type | `'info' \\| 'success' \\| 'warning' \\| 'error' \\| 'loading' \\| 'default'` | Message type. | `'default'` 2.25.7 |\n| onAfterLeave | `() => void` | Callback after message disappeared. |  |\n| onClose | `() => void` | Callback when close icon is clicked. |  |\n| onLeave | `() => void` | Callback when message start to disappear. |  |\n\n#### MessageRenderMessage Type\n\n```ts\ntype MessageRenderMessage = (props: {\n  content?: string | number | (() => VNodeChild)\n  icon?: () => VNodeChild\n  closable: boolean\n  type: 'info' | 'success' | 'warning' | 'error' | 'loading'\n  onClose?: () => void\n}) => VNodeChild\n```\n\n#### MessageReactive Properties\n\n| Name | Type | Description | Version |\n| --- | --- | --- | --- |\n| closable | `boolean` | Whether to show close icon. |  |\n| content | `string \\| (() => VNodeChild)` | Message content. |  |\n| destroy | `() => void` | Message destroy method. |  |\n| icon | `() => VNodeChild` | Message icon. |  |\n| keepAliveOnHover | `boolean` | Messages whether to destroy while hover |  |\n| showIcon | `boolean` | Whether to show icon. | 2.25.7 |\n| type | `'info' \\| 'success' \\| 'warning' \\| 'error' \\| 'loading' \\| 'default'` | Message type. | `'default'` 2.25.7 |\n| onAfterLeave | `() => void` | Callback after message disappeared. |  |\n| onLeave | `() => void` | Callback when message start to disappear. |  |\n\n#### MessageReactive Methods\n\n| Name    | Type | Description             |\n| ------- | ---- | ----------------------- |\n| destroy | `()` | Message destroy method. |\n\n## Q & A\n\n### Use Message Outside Setup\n\n#### Option 1\n\nUse [createDiscreteApi](discrete). If you want to use it, read its caveat carefully. You'd better not use `useMessage` and it together in a same app.\n\n#### Option 2\n\n<n-space vertical size=\"large\">\n<n-alert type=\"warning\" :bordered=\"false\">\n  You need to mount the return value of <n-text code>useMessage</n-text> to the window in the top-level setup and then call it. Before calling it, you need to make sure that message has been mounted successfully.\n</n-alert>\n\n```html\n<!-- App.vue -->\n<n-message-provider>\n  <content />\n</n-message-provider>\n```\n\n```html\n<!-- content.vue -->\n<template>...</template>\n\n<script>\n  import { useMessage } from 'naive-ui'\n  import { defineComponent } from 'vue'\n\n  // content\n  export default defineComponent({\n    setup() {\n      window.$message = useMessage()\n    }\n  })\n</script>\n```\n\n```js\n// xxx.js\nexport function handler() {\n  // You need to ensure that window.$message = message has been executed in setup\n  window.$message.success(\n    'Cause you walked hand in hand With another man in my place'\n  )\n}\n```\n\n</n-space>\n"
  },
  {
    "path": "src/message/demos/enUS/manually-close.demo.vue",
    "content": "<markdown>\n# Manually close\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { MessageReactive } from 'naive-ui'\nimport { useMessage } from 'naive-ui'\nimport { onBeforeUnmount } from 'vue'\n\nconst message = useMessage()\nlet messageReactive: MessageReactive | null = null\n\nfunction removeMessage() {\n  if (messageReactive) {\n    messageReactive.destroy()\n    messageReactive = null\n  }\n}\n\nonBeforeUnmount(removeMessage)\n\nfunction createMessage() {\n  if (!messageReactive) {\n    messageReactive = message.info('3 * 3 * 4 * 4 * ?', {\n      duration: 0\n    })\n  }\n}\n</script>\n\n<template>\n  <n-space>\n    <n-button @click=\"createMessage\">\n      Create\n    </n-button>\n    <n-button @click=\"removeMessage\">\n      Destroy\n    </n-button>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/message/demos/enUS/modify-content.demo.vue",
    "content": "<markdown>\n# Modify exist message\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { MessageReactive, MessageType } from 'naive-ui'\nimport { useMessage } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst message = useMessage()\nconst types: MessageType[] = ['success', 'info', 'warning', 'error', 'loading']\nconst countRef = ref(0)\nlet typeIndex = 0\nlet msgReactive: MessageReactive | null = null\n\nfunction plus() {\n  if (msgReactive) {\n    countRef.value++\n    msgReactive.content = `${countRef.value}`\n  }\n}\n\nfunction changeType() {\n  if (msgReactive) {\n    typeIndex = (typeIndex + 1) % types.length\n    msgReactive.type = types[typeIndex]\n  }\n}\n\nfunction createMessage() {\n  msgReactive = message.create(`${countRef.value}`, {\n    type: types[typeIndex],\n    duration: 10000\n  })\n}\n</script>\n\n<template>\n  <n-space>\n    <n-button @click=\"createMessage\">\n      Create a Message Firstly\n    </n-button>\n    <n-button @click=\"changeType\">\n      Change Type\n    </n-button>\n    <n-button @click=\"plus\">\n      Plus 1\n    </n-button>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/message/demos/enUS/multiple-line.demo.vue",
    "content": "<markdown>\n# Multiple line\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { useMessage } from 'naive-ui'\n\nconst message = useMessage()\n\nfunction info() {\n  message.info(\n    'I don\\'t know why nobody told you how to unfold your love. Once upon a time you dressed so fine. How many roads must a man walk down. \\'Cause you walked hand in hand With another man in my place. If I were you, I will realize that I love you more than any other guy.'\n  )\n}\n</script>\n\n<template>\n  <n-button @click=\"info\">\n    Multiple Line\n  </n-button>\n</template>\n"
  },
  {
    "path": "src/message/demos/enUS/no-icon.demo.vue",
    "content": "<markdown>\n# No icon\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { useMessage } from 'naive-ui'\n\nconst message = useMessage()\n\nfunction createMessage() {\n  message.warning('I never needed anybody\\'s help in any way', {\n    showIcon: false\n  })\n}\n</script>\n\n<template>\n  <n-button @click=\"createMessage\">\n    No icon\n  </n-button>\n</template>\n"
  },
  {
    "path": "src/message/demos/enUS/placement.demo.vue",
    "content": "<markdown>\n# Placement\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { MessageProviderProps } from 'naive-ui'\nimport { NButton, useMessage } from 'naive-ui'\nimport { defineComponent, h, ref } from 'vue'\n\ninterface Item {\n  placement: MessageProviderProps['placement']\n  text: string\n}\n\nconst placementRef = ref<MessageProviderProps['placement']>('top')\n\nfunction changePlacement(val: MessageProviderProps['placement']) {\n  placementRef.value = val\n}\n\n// Buttons component\nconst Buttons = defineComponent({\n  emits: ['changePlacement'],\n  setup(props, { emit }) {\n    const message = useMessage()\n    const placementArray: Item[] = [\n      { placement: 'top', text: 'Top' },\n      { placement: 'bottom', text: 'Bottom' },\n      { placement: 'top-left', text: 'TopLeft' },\n      { placement: 'top-right', text: 'TopRight' },\n      { placement: 'bottom-left', text: 'BottomLeft' },\n      { placement: 'bottom-right', text: 'BottomRight' }\n    ]\n\n    return () =>\n      placementArray.map((item: Item) =>\n        h(\n          NButton,\n          {\n            onClick: () => {\n              emit('changePlacement', item.placement)\n              message.info('How many roads must a man walk down')\n            },\n            style: {\n              marginRight: '10px'\n            }\n          },\n          { default: () => item.text }\n        )\n      )\n  }\n})\n</script>\n\n<template>\n  <n-message-provider :placement=\"placementRef\">\n    <Buttons @change-placement=\"changePlacement\" />\n  </n-message-provider>\n</template>\n"
  },
  {
    "path": "src/message/demos/enUS/timing.demo.vue",
    "content": "<markdown>\n# Timing\n\nSpecify the duration of messages.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { useMessage } from 'naive-ui'\n\nconst message = useMessage()\n\nfunction createMessage() {\n  message.info('I don\\'t know why nobody told you how to unfold your love', {\n    duration: 5000\n  })\n}\n</script>\n\n<template>\n  <n-button @click=\"createMessage\">\n    Last for 5 second\n  </n-button>\n</template>\n"
  },
  {
    "path": "src/message/demos/zhCN/about-theme.demo.vue",
    "content": "<markdown>\n# 关于主题的注意事项\n\n如果你不明确指明主题，被创建信息的主题会与对应 `n-message-provider` 的主题一致。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { useMessage } from 'naive-ui'\n\nconst message = useMessage()\n\nfunction info() {\n  message.info('I don\\'t know why nobody told you how to unfold your love', {\n    duration: 5000\n  })\n}\n</script>\n\n<template>\n  <n-button @click=\"info\">\n    你可以在 Message 还在的时候切换主题\n  </n-button>\n</template>\n"
  },
  {
    "path": "src/message/demos/zhCN/basic.demo.vue",
    "content": "<markdown>\n# 基础用法\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { useMessage } from 'naive-ui'\n\nconst message = useMessage()\n\nfunction info() {\n  message.info('I don\\'t know why nobody told you how to unfold your love', {\n    keepAliveOnHover: true\n  })\n}\n\nfunction error() {\n  message.error('Once upon a time you dressed so fine')\n}\n\nfunction warning() {\n  message.warning('How many roads must a man walk down')\n}\n\nfunction success() {\n  message.success('\\'Cause you walked hand in hand With another man in my place')\n}\n\nfunction loading() {\n  message.loading(\n    'If I were you, I will realize that I love you more than any other guy'\n  )\n}\n</script>\n\n<template>\n  <n-space>\n    <n-button @click=\"info\">\n      信息（Hover不消失）\n    </n-button>\n    <n-button @click=\"error\">\n      错误\n    </n-button>\n    <n-button @click=\"warning\">\n      警告\n    </n-button>\n    <n-button @click=\"success\">\n      成功\n    </n-button>\n    <n-button @click=\"loading\">\n      加载中\n    </n-button>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/message/demos/zhCN/closable.demo.vue",
    "content": "<markdown>\n# 可关闭\n\n设定 `closable` 使 Message 可以通过点击关闭。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { useMessage } from 'naive-ui'\n\nconst message = useMessage()\n\nfunction createMessage() {\n  message.info('I don\\'t know why nobody told you how to unfold your love', {\n    closable: true,\n    duration: 5000\n  })\n}\n</script>\n\n<template>\n  <n-button @click=\"createMessage\">\n    打开信息\n  </n-button>\n</template>\n"
  },
  {
    "path": "src/message/demos/zhCN/customize-message.demo.vue",
    "content": "<markdown>\n# 自定义信息渲染\n\n有些人表示特别想用 Alert 来当成 Message，当然换个别的也行。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { MessageRenderMessage } from 'naive-ui'\nimport { NAlert, useMessage } from 'naive-ui'\nimport { h } from 'vue'\n\nconst renderMessage: MessageRenderMessage = (props) => {\n  const { type } = props\n  return h(\n    NAlert,\n    {\n      closable: props.closable,\n      onClose: props.onClose,\n      type: type === 'loading' ? 'default' : type,\n      title: '你看你手上拿的是什么啊',\n      style: {\n        boxShadow: 'var(--n-box-shadow)',\n        maxWidth: 'calc(100vw - 32px)',\n        width: '480px'\n      }\n    },\n    {\n      default: () => props.content\n    }\n  )\n}\n\nconst { error } = useMessage()\n\nfunction handleClick() {\n  error('那东西我们早就不屑啦，哈哈哈', {\n    render: renderMessage,\n    closable: true\n  })\n}\n</script>\n\n<template>\n  <n-button @click=\"handleClick\">\n    No Party For Cao Dong\n  </n-button>\n</template>\n"
  },
  {
    "path": "src/message/demos/zhCN/icon.demo.vue",
    "content": "<markdown>\n# 图标\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { MdHourglass } from '@vicons/ionicons4'\nimport { NIcon, useMessage } from 'naive-ui'\nimport { h } from 'vue'\n\nconst message = useMessage()\n\nfunction createMessage() {\n  message.warning('I never needed anybody\\'s help in any way', {\n    icon: () => h(NIcon, null, { default: () => h(MdHourglass) })\n  })\n}\n</script>\n\n<template>\n  <n-button @click=\"createMessage\">\n    沙漏图标\n  </n-button>\n</template>\n"
  },
  {
    "path": "src/message/demos/zhCN/index.demo-entry.md",
    "content": "# 信息 Message\n\n（一般是）从浏览器顶部降下来的神谕。\n\n<n-space vertical size=\"large\">\n<n-alert type=\"warning\" title=\"提示\"  :bordered=\"false\">\n  <n-ul align-text>\n    <li>\n      如果你想通过 <n-text code>useMessage</n-text> 使用信息，你需要把调用其方法的组件放在 <n-text code>n-message-provider</n-text> 内部并且使用 <n-text code>useMessage</n-text> 去获取 API。    </li>\n    <li>\n      如果你想知道如何在 <n-text code>setup</n-text> 外使用，请参考页面最下方的 Q & A。\n    </li>\n  </n-ul>\n</n-alert>\n\n例如：\n\n```html\n<!-- App.vue -->\n<n-message-provider>\n  <content />\n</n-message-provider>\n```\n\n```js\nimport { useMessage } from 'naive-ui'\nimport { defineComponent } from 'vue'\n\n// content\nexport default defineComponent({\n  setup() {\n    const message = useMessage()\n    return {\n      warning() {\n        message.warning('...')\n      }\n    }\n  }\n})\n```\n\n</n-space>\n\n## 演示\n\n```demo\nbasic.vue\nicon.vue\ntiming.vue\nclosable.vue\nmodify-content.vue\nmanually-close.vue\nabout-theme.vue\nmultiple-line.vue\nplacement.vue\ncustomize-message.vue\nno-icon.vue\nrtl-debug.vue\n```\n\n## API\n\n### MessageProvider Props\n\n| 名称 | 类型 | 默认值 | 说明 | 版本 |\n| --- | --- | --- | --- | --- |\n| closable | `boolean` | `false` | 所有 Message 是否显示 close 图标 |  |\n| container-class | `string` | `undefined` | Message 容器的类名 | 2.36.0 |\n| container-style | `string \\| CSSProperties` | `undefined` | Message 容器的样式 |  |\n| duration | `number` | `3000` | 所有 Message 默认的持续时长 |  |\n| keep-alive-on-hover | `boolean` | `false` | 所有 Message 在悬浮信息上时是否不销毁 |  |\n| max | `number` | `undefined` | 限制提示信息显示的个数 |  |\n| placement | `top \\| top-left \\| top-right \\| bottom \\| bottom-left \\| bottom-right ` | `top` | 所有 Message 显示的位置 |  |\n| to | `string \\| HTMLElement` | `'body'` | Message 容器节点的位置 |  |\n\n### MessageProvider Injection API\n\n#### MessageProvider Injection Methods\n\n| 名称 | 类型 | 说明 | 版本 |\n| --- | --- | --- | --- |\n| destroyAll | `() => void` | 销毁所有弹出的信息 |  |\n| create | `(content: string \\| (() => VNodeChild), option?: MessageOption) => MessageReactive` | 调用 create 类型的信息 | 2.25.7 |\n| error | `(content: string \\| (() => VNodeChild), option?: MessageOption) => MessageReactive` | 调用 error 类型的信息 |  |\n| info | `(content: string \\| (() => VNodeChild), option?: MessageOption) => MessageReactive` | 调用 info 类型的信息 |  |\n| loading | `(content: string \\| (() => VNodeChild), option?: MessageOption) => MessageReactive` | 调用 loading 类型的信息 |  |\n| success | `(content: string \\| (() => VNodeChild), option?: MessageOption) => MessageReactive` | 调用 success 类型的信息 |  |\n| warning | `(content: string \\| (() => VNodeChild), option?: MessageOption) => MessageReactive` | 调用 warning 类型的信息 |  |\n\n#### MessageOption Properties\n\n| 名称 | 类型 | 说明 | 版本 |\n| --- | --- | --- | --- |\n| closable | `boolean` | 是否显示 close 图标 |  |\n| duration | `number` | 信息展示的时长 |  |\n| icon | `() => VNodeChild` | 信息图标 |  |\n| keepAliveOnHover | `boolean` | Hover 到信息上是否不销毁 |  |\n| render | `MessageRenderMessage` | 消息的渲染函数 | 2.24.0 |\n| showIcon | `boolean` | 是否展示图标 | 2.25.7 |\n| spinProps | `{ strokeWidth?: number, stroke?: string, scale?: number, radius?: number }` | 加载图标的属性 | 2.44.0 |\n| type | `'info' \\| 'success' \\| 'warning' \\| 'error' \\| 'loading' \\| 'default'` | 信息类型 | `'default'` 2.25.7 |\n| onAfterLeave | `() => void` | 信息消失动画结束的回调 |  |\n| onClose | `() => void` | 点击关闭图标的回调 |  |\n| onLeave | `() => void` | 信息开始消失的回调 |  |\n\n#### MessageRenderMessage Type\n\n```ts\ntype MessageRenderMessage = (props: {\n  content?: string | number | (() => VNodeChild)\n  icon?: () => VNodeChild\n  closable: boolean\n  type: 'info' | 'success' | 'warning' | 'error' | 'loading'\n  onClose?: () => void\n}) => VNodeChild\n```\n\n#### MessageReactive Properties\n\n| 名称 | 类型 | 说明 | 版本 |\n| --- | --- | --- | --- |\n| closable | `boolean` | 是否显示 close 图标 |  |\n| content | `string \\| (() => VNodeChild)` | 信息内容 |  |\n| destroy | `() => void` | 销毁信息的方法 |  |\n| icon | `() => VNodeChild` | 信息图标 |  |\n| keepAliveOnHover | `boolean` | Hover 到信息上是否不销毁 |  |\n| showIcon | `boolean` | 是否展示图标 | 2.25.7 |\n| type | `'info' \\| 'success' \\| 'warning' \\| 'error' \\| 'loading' \\| 'default'` | 信息类型 | `'default'` 2.25.7 |\n| onAfterLeave | `() => void` | 信息消失动画结束的回调 |  |\n| onLeave | `() => void` | 信息开始消失的回调 |  |\n\n#### MessageReactive Methods\n\n| 名称    | 类型 | 说明           |\n| ------- | ---- | -------------- |\n| destroy | `()` | 销毁信息的方法 |\n\n## Q & A\n\n### 在 setup 外使用\n\n#### 选择 1\n\n使用 [createDiscreteApi](discrete)。如果你想使用它，请认真阅读它的注意事项。你最好不要把它和 `useMessage` 在同一 App 中混用。\n\n#### 选择 2\n\n<n-space vertical size=\"large\">\n<n-alert type=\"warning\" :bordered=\"false\">\n  如果你想在 setup 外使用信息，你需要在顶层 setup 中把 <n-text code>useMessage</n-text> 返回的 message 值挂载到 window 下然后再调用，调用前需要确保 message 已经挂载成功。\n</n-alert>\n\n```html\n<!-- App.vue -->\n<n-message-provider>\n  <content />\n</n-message-provider>\n```\n\n```html\n<!-- content.vue -->\n<template>...</template>\n\n<script>\n  import { useMessage } from 'naive-ui'\n  import { defineComponent } from 'vue'\n\n  // content\n  export default defineComponent({\n    setup() {\n      window.$message = useMessage()\n    }\n  })\n</script>\n```\n\n```js\n// xxx.js\nexport function handler() {\n  // 需要确保已经在 setup 中执行了 window.$message = message\n  window.$message.success(\n    'Cause you walked hand in hand With another man in my place'\n  )\n}\n```\n\n</n-space>\n"
  },
  {
    "path": "src/message/demos/zhCN/manually-close.demo.vue",
    "content": "<markdown>\n# 手动关闭\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { MessageReactive } from 'naive-ui'\nimport { useMessage } from 'naive-ui'\nimport { onBeforeUnmount } from 'vue'\n\nconst message = useMessage()\nlet messageReactive: MessageReactive | null = null\n\nfunction removeMessage() {\n  if (messageReactive) {\n    messageReactive.destroy()\n    messageReactive = null\n  }\n}\n\nonBeforeUnmount(removeMessage)\n\nfunction createMessage() {\n  if (!messageReactive) {\n    messageReactive = message.info('3 * 3 * 4 * 4 * ?', {\n      duration: 0\n    })\n  }\n}\n</script>\n\n<template>\n  <n-space>\n    <n-button @click=\"createMessage\">\n      打开\n    </n-button>\n    <n-button @click=\"removeMessage\">\n      关闭\n    </n-button>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/message/demos/zhCN/modify-content.demo.vue",
    "content": "<markdown>\n# 修改创建的信息\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { MessageReactive, MessageType } from 'naive-ui'\nimport { useMessage } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst message = useMessage()\nconst types: MessageType[] = ['success', 'info', 'warning', 'error', 'loading']\nconst countRef = ref(0)\nlet typeIndex = 0\nlet msgReactive: MessageReactive | null = null\n\nfunction plus() {\n  if (msgReactive) {\n    countRef.value++\n    msgReactive.content = `${countRef.value}`\n  }\n}\n\nfunction changeType() {\n  if (msgReactive) {\n    typeIndex = (typeIndex + 1) % types.length\n    msgReactive.type = types[typeIndex]\n  }\n}\n\nfunction createMessage() {\n  msgReactive = message.create(`${countRef.value}`, {\n    type: types[typeIndex],\n    duration: 10000\n  })\n}\n</script>\n\n<template>\n  <n-space>\n    <n-button @click=\"createMessage\">\n      先开个信息\n    </n-button>\n    <n-button @click=\"changeType\">\n      改变类型\n    </n-button>\n    <n-button @click=\"plus\">\n      加一\n    </n-button>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/message/demos/zhCN/multiple-line.demo.vue",
    "content": "<markdown>\n# 多行\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { useMessage } from 'naive-ui'\n\nconst message = useMessage()\n\nfunction info() {\n  message.info(\n    'I don\\'t know why nobody told you how to unfold your love. Once upon a time you dressed so fine. How many roads must a man walk down. \\'Cause you walked hand in hand With another man in my place. If I were you, I will realize that I love you more than any other guy.'\n  )\n}\n</script>\n\n<template>\n  <n-button @click=\"info\">\n    多行\n  </n-button>\n</template>\n"
  },
  {
    "path": "src/message/demos/zhCN/no-icon.demo.vue",
    "content": "<markdown>\n# 无图标\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { useMessage } from 'naive-ui'\n\nconst message = useMessage()\n\nfunction createMessage() {\n  message.warning('I never needed anybody\\'s help in any way', {\n    showIcon: false\n  })\n}\n</script>\n\n<template>\n  <n-button @click=\"createMessage\">\n    无图标\n  </n-button>\n</template>\n"
  },
  {
    "path": "src/message/demos/zhCN/placement.demo.vue",
    "content": "<markdown>\n# 位置\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { MessageProviderProps } from 'naive-ui'\nimport type { VNode } from 'vue'\nimport { NButton, useMessage } from 'naive-ui'\nimport { defineComponent, h, ref } from 'vue'\n\ninterface Item {\n  placement: MessageProviderProps['placement']\n  text: string\n}\n\nconst Buttons = defineComponent({\n  emits: ['changePlacement'],\n  setup() {\n    const message = useMessage()\n    const placementArray: Item[] = [\n      { placement: 'top', text: '顶部' },\n      { placement: 'bottom', text: '底部' },\n      { placement: 'top-left', text: '左上' },\n      { placement: 'top-right', text: '右上' },\n      { placement: 'bottom-left', text: '左下' },\n      { placement: 'bottom-right', text: '右下' }\n    ]\n    return {\n      message,\n      placementArray\n    }\n  },\n  render(): VNode[] {\n    const { message, placementArray, $emit } = this\n    return placementArray.map((item: Item) =>\n      h(\n        NButton,\n        {\n          onClick: () => {\n            $emit('changePlacement', item.placement)\n            message.info('How many roads must a man walk down')\n          },\n          style: {\n            marginRight: '10px'\n          }\n        },\n        { default: () => item.text }\n      )\n    )\n  }\n})\n\nconst placementRef = ref<MessageProviderProps['placement']>('top')\n\nfunction changePlacement(val: MessageProviderProps['placement']) {\n  placementRef.value = val\n}\n\nconst placement = placementRef\n</script>\n\n<template>\n  <n-message-provider :placement=\"placement\">\n    <Buttons @change-placement=\"changePlacement\" />\n  </n-message-provider>\n</template>\n"
  },
  {
    "path": "src/message/demos/zhCN/rtl-debug.demo.vue",
    "content": "<markdown>\n# Rtl Debug\n</markdown>\n\n<script lang=\"ts\">\nimport { NButton, unstableMessageRtl, useMessage } from 'naive-ui'\nimport { defineComponent, h, ref } from 'vue'\n</script>\n\n<script lang=\"ts\" setup>\nconst MessageButton = defineComponent({\n  setup() {\n    const message = useMessage()\n    return {\n      message\n    }\n  },\n  render() {\n    return h(\n      NButton,\n      {\n        onClick: () => {\n          this.message.info(\n            'I don\\'t know why nobody told you how to unfold your love',\n            {\n              closable: true,\n              duration: 0\n            }\n          )\n        }\n      },\n      { default: () => 'Show some message' }\n    )\n  }\n})\n\nconst rtlEnabled = ref(true)\nconst rtlStyles = [unstableMessageRtl]\n</script>\n\n<template>\n  <n-space><n-switch v-model:value=\"rtlEnabled\" />Rtl</n-space>\n  <n-space>\n    <n-config-provider :rtl=\"rtlEnabled ? rtlStyles : undefined\">\n      <n-message-provider>\n        <MessageButton />\n      </n-message-provider>\n    </n-config-provider>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/message/demos/zhCN/timing.demo.vue",
    "content": "<markdown>\n# 时间\n\n设定 Message 的持续时间。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { useMessage } from 'naive-ui'\n\nconst message = useMessage()\n\nfunction createMessage() {\n  message.info('I don\\'t know why nobody told you how to unfold your love', {\n    duration: 5000\n  })\n}\n</script>\n\n<template>\n  <n-button @click=\"createMessage\">\n    持续 5 秒\n  </n-button>\n</template>\n"
  },
  {
    "path": "src/message/index.ts",
    "content": "export {\n  messageProviderProps,\n  default as NMessageProvider\n} from './src/MessageProvider'\nexport type {\n  MessageApiInjection as MessageApi,\n  MessageProviderInst,\n  MessageProviderProps,\n  MessageReactive\n} from './src/MessageProvider'\nexport type * from './src/public-types'\nexport type {\n  MessageOptions,\n  MessageRenderMessage,\n  MessageType\n} from './src/types'\nexport { useMessage } from './src/use-message'\n"
  },
  {
    "path": "src/message/src/Message.tsx",
    "content": "import type { CSSProperties, PropType, VNodeChild } from 'vue'\n/* eslint-disable no-cond-assign */\nimport type { MessageSpinProps } from './public-types'\nimport type { MessageRenderMessage, MessageType } from './types'\nimport { computed, defineComponent, h, inject } from 'vue'\nimport {\n  NBaseClose,\n  NBaseIcon,\n  NBaseLoading,\n  NIconSwitchTransition\n} from '../../_internal'\nimport {\n  ErrorIcon,\n  InfoIcon,\n  SuccessIcon,\n  WarningIcon\n} from '../../_internal/icons'\nimport { useConfig, useRtl, useTheme, useThemeClass } from '../../_mixins'\nimport { createKey, render } from '../../_utils'\nimport { messageLight } from '../styles'\nimport { messageProviderInjectionKey } from './context'\nimport { messageProps } from './message-props'\nimport style from './styles/index.cssr'\n\nconst iconRenderMap = {\n  info: () => <InfoIcon />,\n  success: () => <SuccessIcon />,\n  warning: () => <WarningIcon />,\n  error: () => <ErrorIcon />,\n  default: () => null\n}\n\nexport default defineComponent({\n  name: 'Message',\n  props: {\n    ...messageProps,\n    render: Function as PropType<MessageRenderMessage>\n  },\n  setup(props) {\n    const { inlineThemeDisabled, mergedRtlRef } = useConfig(props)\n    const { props: messageProviderProps, mergedClsPrefixRef } = inject(\n      messageProviderInjectionKey\n    )!\n    const rtlEnabledRef = useRtl('Message', mergedRtlRef, mergedClsPrefixRef)\n    const themeRef = useTheme(\n      'Message',\n      '-message',\n      style,\n      messageLight,\n      messageProviderProps,\n      mergedClsPrefixRef\n    )\n    const cssVarsRef = computed(() => {\n      const { type } = props\n      const {\n        common: { cubicBezierEaseInOut },\n        self: {\n          padding,\n          margin,\n          maxWidth,\n          iconMargin,\n          closeMargin,\n          closeSize,\n          iconSize,\n          fontSize,\n          lineHeight,\n          borderRadius,\n          border,\n          iconColorInfo,\n          iconColorSuccess,\n          iconColorWarning,\n          iconColorError,\n          iconColorLoading,\n          closeIconSize,\n          closeBorderRadius,\n          [createKey('textColor', type)]: textColor,\n          [createKey('boxShadow', type)]: boxShadow,\n          [createKey('color', type)]: color,\n          [createKey('closeColorHover', type)]: closeColorHover,\n          [createKey('closeColorPressed', type)]: closeColorPressed,\n          [createKey('closeIconColor', type)]: closeIconColor,\n          [createKey('closeIconColorPressed', type)]: closeIconColorPressed,\n          [createKey('closeIconColorHover', type)]: closeIconColorHover\n        }\n      } = themeRef.value\n      return {\n        '--n-bezier': cubicBezierEaseInOut,\n        '--n-margin': margin,\n        '--n-padding': padding,\n        '--n-max-width': maxWidth,\n        '--n-font-size': fontSize,\n        '--n-icon-margin': iconMargin,\n        '--n-icon-size': iconSize,\n        '--n-close-icon-size': closeIconSize,\n        '--n-close-border-radius': closeBorderRadius,\n        '--n-close-size': closeSize,\n        '--n-close-margin': closeMargin,\n        '--n-text-color': textColor,\n        '--n-color': color,\n        '--n-box-shadow': boxShadow,\n        '--n-icon-color-info': iconColorInfo,\n        '--n-icon-color-success': iconColorSuccess,\n        '--n-icon-color-warning': iconColorWarning,\n        '--n-icon-color-error': iconColorError,\n        '--n-icon-color-loading': iconColorLoading,\n        '--n-close-color-hover': closeColorHover,\n        '--n-close-color-pressed': closeColorPressed,\n        '--n-close-icon-color': closeIconColor,\n        '--n-close-icon-color-pressed': closeIconColorPressed,\n        '--n-close-icon-color-hover': closeIconColorHover,\n        '--n-line-height': lineHeight,\n        '--n-border-radius': borderRadius,\n        '--n-border': border\n      }\n    })\n    const themeClassHandle = inlineThemeDisabled\n      ? useThemeClass(\n          'message',\n          computed(() => props.type[0]),\n          cssVarsRef,\n          {}\n        )\n      : undefined\n    return {\n      mergedClsPrefix: mergedClsPrefixRef,\n      rtlEnabled: rtlEnabledRef,\n      messageProviderProps,\n      handleClose() {\n        props.onClose?.()\n      },\n      cssVars: inlineThemeDisabled ? undefined : cssVarsRef,\n      themeClass: themeClassHandle?.themeClass,\n      onRender: themeClassHandle?.onRender,\n      placement: messageProviderProps.placement\n    }\n  },\n  render() {\n    const {\n      render: renderMessage,\n      type,\n      closable,\n      content,\n      mergedClsPrefix,\n      cssVars,\n      themeClass,\n      onRender,\n      icon,\n      handleClose,\n      showIcon\n    } = this\n    onRender?.()\n    let iconNode: VNodeChild\n    return (\n      <div\n        class={[`${mergedClsPrefix}-message-wrapper`, themeClass]}\n        onMouseenter={this.onMouseenter}\n        onMouseleave={this.onMouseleave}\n        style={[\n          {\n            alignItems: this.placement.startsWith('top')\n              ? 'flex-start'\n              : 'flex-end'\n          },\n          cssVars as CSSProperties\n        ]}\n      >\n        {renderMessage ? (\n          renderMessage(this.$props)\n        ) : (\n          <div\n            class={[\n              `${mergedClsPrefix}-message ${mergedClsPrefix}-message--${type}-type`,\n              this.rtlEnabled && `${mergedClsPrefix}-message--rtl`\n            ]}\n          >\n            {(iconNode = createIconVNode(\n              icon,\n              type,\n              mergedClsPrefix,\n              this.spinProps\n            )) && showIcon ? (\n                  <div\n                    class={`${mergedClsPrefix}-message__icon ${mergedClsPrefix}-message__icon--${type}-type`}\n                  >\n                    <NIconSwitchTransition>\n                      {{\n                        default: () => iconNode\n                      }}\n                    </NIconSwitchTransition>\n                  </div>\n                ) : null}\n            <div class={`${mergedClsPrefix}-message__content`}>\n              {render(content)}\n            </div>\n            {closable ? (\n              <NBaseClose\n                clsPrefix={mergedClsPrefix}\n                class={`${mergedClsPrefix}-message__close`}\n                onClick={handleClose}\n                absolute\n              />\n            ) : null}\n          </div>\n        )}\n      </div>\n    )\n  }\n})\n\nfunction createIconVNode(\n  icon: undefined | (() => VNodeChild),\n  type: MessageType,\n  clsPrefix: string,\n  spinProps: MessageSpinProps | undefined\n): VNodeChild {\n  if (typeof icon === 'function') {\n    return icon()\n  }\n  else {\n    const innerIcon\n      = type === 'loading' ? (\n        <NBaseLoading\n          clsPrefix={clsPrefix}\n          strokeWidth={24}\n          scale={0.85}\n          {...spinProps}\n        />\n      ) : (\n        iconRenderMap[type]()\n      )\n    if (!innerIcon)\n      return null\n    return (\n      <NBaseIcon clsPrefix={clsPrefix} key={type}>\n        {{\n          default: () => innerIcon\n        }}\n      </NBaseIcon>\n    )\n  }\n}\n"
  },
  {
    "path": "src/message/src/MessageEnvironment.tsx",
    "content": "import type { PropType } from 'vue'\nimport { defineComponent, h, onMounted, ref } from 'vue'\nimport { NFadeInExpandTransition } from '../../_internal'\nimport NMessage from './Message'\nimport { messageProps } from './message-props'\n\nexport default defineComponent({\n  name: 'MessageEnvironment',\n  props: {\n    ...messageProps,\n    duration: {\n      type: Number,\n      default: 3000\n    },\n    onAfterLeave: Function,\n    onLeave: Function,\n    internalKey: {\n      type: String,\n      required: true\n    },\n    // private\n    onInternalAfterLeave: Function as PropType<(key: string) => void>,\n    // deprecated\n    onHide: Function,\n    onAfterHide: Function\n  },\n  setup(props) {\n    let timerId: number | null = null\n    const showRef = ref<boolean>(true)\n    onMounted(() => {\n      setHideTimeout()\n    })\n    function setHideTimeout(): void {\n      const { duration } = props\n      if (duration) {\n        timerId = window.setTimeout(hide, duration)\n      }\n    }\n    function handleMouseenter(e: MouseEvent): void {\n      if (e.currentTarget !== e.target)\n        return\n      if (timerId !== null) {\n        window.clearTimeout(timerId)\n        timerId = null\n      }\n    }\n    function handleMouseleave(e: MouseEvent): void {\n      if (e.currentTarget !== e.target)\n        return\n      setHideTimeout()\n    }\n    function hide(): void {\n      const { onHide } = props\n      showRef.value = false\n      if (timerId) {\n        window.clearTimeout(timerId)\n        timerId = null\n      }\n      // deprecated\n      if (onHide)\n        onHide()\n    }\n    function handleClose(): void {\n      const { onClose } = props\n      if (onClose)\n        onClose()\n      hide()\n    }\n    function handleAfterLeave(): void {\n      const { onAfterLeave, onInternalAfterLeave, onAfterHide, internalKey }\n        = props\n      if (onAfterLeave)\n        onAfterLeave()\n      if (onInternalAfterLeave)\n        onInternalAfterLeave(internalKey)\n      // deprecated\n      if (onAfterHide)\n        onAfterHide()\n    }\n    // deprecated\n    function deactivate(): void {\n      hide()\n    }\n\n    return {\n      show: showRef,\n      hide,\n      handleClose,\n      handleAfterLeave,\n      handleMouseleave,\n      handleMouseenter,\n      deactivate\n    }\n  },\n  render() {\n    return (\n      <NFadeInExpandTransition\n        appear\n        onAfterLeave={this.handleAfterLeave}\n        onLeave={this.onLeave}\n      >\n        {{\n          default: () => [\n            this.show ? (\n              <NMessage\n                content={this.content}\n                type={this.type}\n                icon={this.icon}\n                showIcon={this.showIcon}\n                closable={this.closable}\n                spinProps={this.spinProps}\n                onClose={this.handleClose}\n                onMouseenter={\n                  this.keepAliveOnHover ? this.handleMouseenter : undefined\n                }\n                onMouseleave={\n                  this.keepAliveOnHover ? this.handleMouseleave : undefined\n                }\n              />\n            ) : null\n          ]\n        }}\n      </NFadeInExpandTransition>\n    )\n  }\n})\n"
  },
  {
    "path": "src/message/src/MessageProvider.tsx",
    "content": "import type { CSSProperties, ExtractPropTypes, PropType, VNodeChild } from 'vue'\nimport type { ThemeProps } from '../../_mixins'\nimport type { ExtractPublicPropTypes } from '../../_utils'\nimport type { MessageTheme } from '../styles'\nimport type { MessageOptions, MessageType } from './types'\nimport { createId } from 'seemly'\nimport {\n  defineComponent,\n  Fragment,\n  h,\n  provide,\n  reactive,\n  ref,\n  Teleport\n} from 'vue'\nimport { useConfig, useTheme } from '../../_mixins'\nimport { omit } from '../../_utils'\nimport { messageApiInjectionKey, messageProviderInjectionKey } from './context'\nimport MessageEnvironment from './MessageEnvironment'\n\ntype ContentType = string | (() => VNodeChild)\n\nexport interface MessageApiInjection {\n  create: (content: ContentType, options?: MessageOptions) => MessageReactive\n  info: (content: ContentType, options?: MessageOptions) => MessageReactive\n  success: (content: ContentType, options?: MessageOptions) => MessageReactive\n  warning: (content: ContentType, options?: MessageOptions) => MessageReactive\n  error: (content: ContentType, options?: MessageOptions) => MessageReactive\n  loading: (content: ContentType, options?: MessageOptions) => MessageReactive\n  destroyAll: () => void\n}\n\nexport interface MessageReactive {\n  content?: ContentType\n  duration?: number\n  closable?: boolean\n  keepAliveOnHover?: boolean\n  type: MessageType\n  icon?: () => VNodeChild\n  showIcon?: boolean\n  onClose?: () => void\n  destroy: () => void\n}\n\ninterface PrivateMessageReactive extends MessageReactive {\n  key: string\n}\n\ninterface PrivateMessageRef extends MessageReactive {\n  key: string\n  hide: () => void\n}\n\nexport type MessageProviderInst = MessageApiInjection\n\nexport const messageProviderProps = {\n  ...(useTheme.props as ThemeProps<MessageTheme>),\n  to: [String, Object] as PropType<string | HTMLElement>,\n  duration: {\n    type: Number,\n    default: 3000\n  },\n  keepAliveOnHover: Boolean,\n  max: Number,\n  placement: {\n    type: String as PropType<\n      | 'top'\n      | 'top-left'\n      | 'top-right'\n      | 'bottom'\n      | 'bottom-left'\n      | 'bottom-right'\n    >,\n    default: 'top'\n  },\n  closable: Boolean,\n  containerClass: String,\n  containerStyle: [String, Object] as PropType<string | CSSProperties>\n}\n\nexport type MessageProviderProps = ExtractPublicPropTypes<\n  typeof messageProviderProps\n>\n\nexport type MessageProviderSetupProps = ExtractPropTypes<\n  typeof messageProviderProps\n>\n\nexport default defineComponent({\n  name: 'MessageProvider',\n  props: messageProviderProps,\n  setup(props) {\n    const { mergedClsPrefixRef } = useConfig(props)\n    const messageListRef = ref<PrivateMessageReactive[]>([])\n    const messageRefs = ref<Record<string, PrivateMessageRef>>({})\n    const api: MessageApiInjection = {\n      create(content: ContentType, options?: MessageOptions) {\n        return create(content, { type: 'default', ...options })\n      },\n      info(content: ContentType, options?: MessageOptions) {\n        return create(content, { ...options, type: 'info' })\n      },\n      success(content: ContentType, options?: MessageOptions) {\n        return create(content, { ...options, type: 'success' })\n      },\n      warning(content: ContentType, options?: MessageOptions) {\n        return create(content, { ...options, type: 'warning' })\n      },\n      error(content: ContentType, options?: MessageOptions) {\n        return create(content, { ...options, type: 'error' })\n      },\n      loading(content: ContentType, options?: MessageOptions) {\n        return create(content, { ...options, type: 'loading' })\n      },\n      destroyAll\n    }\n    provide(messageProviderInjectionKey, {\n      props,\n      mergedClsPrefixRef\n    })\n    provide(messageApiInjectionKey, api)\n    function create(\n      content: ContentType,\n      options: MessageOptions & { type: MessageType }\n    ): MessageReactive {\n      const key = createId()\n      const messageReactive = reactive({\n        ...options,\n        content,\n        key,\n        destroy: () => {\n          messageRefs.value[key]?.hide()\n        }\n      })\n      const { max } = props\n      if (max && messageListRef.value.length >= max) {\n        messageListRef.value.shift()\n      }\n      messageListRef.value.push(messageReactive)\n      return messageReactive\n    }\n    function handleAfterLeave(key: string): void {\n      messageListRef.value.splice(\n        messageListRef.value.findIndex(message => message.key === key),\n        1\n      )\n      delete messageRefs.value[key]\n    }\n    function destroyAll(): void {\n      Object.values(messageRefs.value).forEach((messageInstRef) => {\n        messageInstRef.hide()\n      })\n    }\n    return Object.assign(\n      {\n        mergedClsPrefix: mergedClsPrefixRef,\n        messageRefs,\n        messageList: messageListRef,\n        handleAfterLeave\n      },\n      api\n    )\n  },\n  render() {\n    return (\n      <>\n        {this.$slots.default?.()}\n        {this.messageList.length ? (\n          <Teleport to={this.to ?? 'body'}>\n            <div\n              class={[\n                `${this.mergedClsPrefix}-message-container`,\n                `${this.mergedClsPrefix}-message-container--${this.placement}`,\n                this.containerClass\n              ]}\n              key=\"message-container\"\n              style={this.containerStyle}\n            >\n              {this.messageList.map((message) => {\n                return (\n                  <MessageEnvironment\n                    ref={\n                      ((inst: PrivateMessageRef) => {\n                        if (inst) {\n                          this.messageRefs[message.key] = inst\n                        }\n                      }) as () => void\n                    }\n                    internalKey={message.key}\n                    onInternalAfterLeave={this.handleAfterLeave}\n                    {...omit(message, ['destroy'], undefined)}\n                    duration={\n                      message.duration === undefined\n                        ? this.duration\n                        : message.duration\n                    }\n                    keepAliveOnHover={\n                      message.keepAliveOnHover === undefined\n                        ? this.keepAliveOnHover\n                        : message.keepAliveOnHover\n                    }\n                    closable={\n                      message.closable === undefined\n                        ? this.closable\n                        : message.closable\n                    }\n                  />\n                )\n              })}\n            </div>\n          </Teleport>\n        ) : null}\n      </>\n    )\n  }\n})\n"
  },
  {
    "path": "src/message/src/context.ts",
    "content": "import type { Ref } from 'vue'\nimport type {\n  MessageApiInjection,\n  MessageProviderSetupProps\n} from './MessageProvider'\nimport { createInjectionKey } from '../../_utils'\n\nexport const messageApiInjectionKey\n  = createInjectionKey<MessageApiInjection>('n-message-api')\n\nexport const messageProviderInjectionKey = createInjectionKey<{\n  props: MessageProviderSetupProps\n  mergedClsPrefixRef: Ref<string>\n}>('n-message-provider')\n"
  },
  {
    "path": "src/message/src/message-props.ts",
    "content": "import type { ExtractPropTypes, PropType, VNodeChild } from 'vue'\nimport type { ExtractPublicPropTypes } from '../../_utils'\nimport type { MessageSpinProps } from './public-types'\nimport type { MessageType } from './types'\n\nexport const messageProps = {\n  icon: Function as PropType<() => VNodeChild>,\n  type: {\n    type: String as PropType<MessageType>,\n    default: 'info'\n  },\n  content: [String, Number, Function] as PropType<\n    string | number | (() => VNodeChild)\n  >,\n  showIcon: {\n    type: Boolean,\n    default: true\n  },\n  closable: Boolean,\n  keepAliveOnHover: Boolean,\n  spinProps: Object as PropType<MessageSpinProps>,\n  onClose: Function as PropType<() => void>,\n  onMouseenter: Function as PropType<(e: MouseEvent) => void>,\n  onMouseleave: Function as PropType<(e: MouseEvent) => void>\n} as const\n\nexport type MessageProps = ExtractPublicPropTypes<typeof messageProps>\nexport type MessageSetupProps = ExtractPropTypes<typeof messageProps>\n"
  },
  {
    "path": "src/message/src/public-types.ts",
    "content": "import type { SharedSpinProps } from '../../_internal'\n\nexport type MessageSpinProps = SharedSpinProps\n"
  },
  {
    "path": "src/message/src/styles/index.cssr.ts",
    "content": "import { fadeInHeightExpandTransition } from '../../../_styles/transitions/fade-in-height-expand.cssr'\nimport { iconSwitchTransition } from '../../../_styles/transitions/icon-switch.cssr'\nimport { c, cB, cE, cM } from '../../../_utils/cssr'\n\n// vars:\n// --n-margin\n// --n-bezier\n// --n-padding\n// --n-max-width\n// --n-font-size\n// --n-icon-margin\n// --n-icon-size\n// --n-text-color\n// --n-color\n// --n-box-shadow\n// --n-icon-color-default\n// --n-icon-color-info\n// --n-icon-color-success\n// --n-icon-color-warning\n// --n-icon-color-error\n// --n-icon-color-loading\n// --n-close-size\n// --n-close-icon-size\n// --n-close-margin\n// --n-close-color-hover\n// --n-close-color-pressed\n// --n-close-border-radius\n// --n-close-icon-color\n// --n-close-icon-color-pressed\n// --n-close-icon-color-hover\n// --n-border-radius\nexport default c([\n  cB('message-wrapper', `\n    margin: var(--n-margin);\n    z-index: 0;\n    transform-origin: top center;\n    display: flex;\n  `, [\n    fadeInHeightExpandTransition({\n      overflow: 'visible',\n      originalTransition: 'transform .3s var(--n-bezier)',\n      enterToProps: {\n        transform: 'scale(1)'\n      },\n      leaveToProps: {\n        transform: 'scale(0.85)'\n      }\n    })\n  ]),\n  cB('message', `\n    box-sizing: border-box;\n    display: flex;\n    align-items: center;\n    transition:\n      color .3s var(--n-bezier),\n      box-shadow .3s var(--n-bezier),\n      background-color .3s var(--n-bezier),\n      opacity .3s var(--n-bezier),\n      transform .3s var(--n-bezier),\n      margin-bottom .3s var(--n-bezier);\n    padding: var(--n-padding);\n    border-radius: var(--n-border-radius);\n    border: var(--n-border);\n    flex-wrap: nowrap;\n    overflow: hidden;\n    max-width: var(--n-max-width);\n    color: var(--n-text-color);\n    background-color: var(--n-color);\n    box-shadow: var(--n-box-shadow);\n  `, [\n    cE('content', `\n      display: inline-block;\n      line-height: var(--n-line-height);\n      font-size: var(--n-font-size);\n    `),\n    cE('icon', `\n      position: relative;\n      margin: var(--n-icon-margin);\n      height: var(--n-icon-size);\n      width: var(--n-icon-size);\n      font-size: var(--n-icon-size);\n      flex-shrink: 0;\n    `, [\n      ['default', 'info', 'success', 'warning', 'error', 'loading'].map(type =>\n        cM(`${type}-type`, [\n          c('> *', `\n            color: var(--n-icon-color-${type});\n            transition: color .3s var(--n-bezier);\n          `)\n        ])\n      ),\n      c('> *', `\n        position: absolute;\n        left: 0;\n        top: 0;\n        right: 0;\n        bottom: 0;\n      `, [iconSwitchTransition()])\n    ]),\n    cE('close', `\n      margin: var(--n-close-margin);\n      transition:\n        background-color .3s var(--n-bezier),\n        color .3s var(--n-bezier);\n      flex-shrink: 0;\n    `, [\n      c('&:hover', `\n        color: var(--n-close-icon-color-hover);\n      `),\n      c('&:active', `\n        color: var(--n-close-icon-color-pressed);\n      `)\n    ])\n  ]),\n  cB('message-container', `\n    z-index: 6000;\n    position: fixed;\n    height: 0;\n    overflow: visible;\n    display: flex;\n    flex-direction: column;\n    align-items: center;\n  `, [\n    cM('top', `\n      top: 12px;\n      left: 0;\n      right: 0;\n    `),\n    cM('top-left', `\n      top: 12px;\n      left: 12px;\n      right: 0;\n      align-items: flex-start;\n    `),\n    cM('top-right', `\n      top: 12px;\n      left: 0;\n      right: 12px;\n      align-items: flex-end;\n    `),\n    cM('bottom', `\n      bottom: 4px;\n      left: 0;\n      right: 0;\n      justify-content: flex-end;\n    `),\n    cM('bottom-left', `\n      bottom: 4px;\n      left: 12px;\n      right: 0;\n      justify-content: flex-end;\n      align-items: flex-start;\n    `),\n    cM('bottom-right', `\n      bottom: 4px;\n      left: 0;\n      right: 12px;\n      justify-content: flex-end;\n      align-items: flex-end;\n    `)\n  ])\n])\n"
  },
  {
    "path": "src/message/src/styles/rtl.cssr.ts",
    "content": "import { cB, cE, cM } from '../../../_utils/cssr'\n\nexport default cB('message', [\n  cM('rtl', `\n    direction: rtl;\n  `, [\n    cE('close', `\n      margin: 0 10px 0 0;\n    `),\n    cE('icon', `\n      margin: 0 0 0 10px;\n    `)\n  ])\n])\n"
  },
  {
    "path": "src/message/src/types.ts",
    "content": "import type { VNodeChild } from 'vue'\nimport type { MessageSetupProps } from './message-props'\nimport type { MessageSpinProps } from './public-types'\n\nexport type MessageType\n  = | 'info'\n    | 'success'\n    | 'warning'\n    | 'error'\n    | 'loading'\n    | 'default'\n\n// We should export keepAliveOnHover since it's not managed by users\nexport type RenderMessageProps = Pick<\n  MessageSetupProps,\n  'closable' | 'content' | 'icon' | 'onClose' | 'type'\n>\n\nexport type MessageRenderMessage = (props: RenderMessageProps) => VNodeChild\n\nexport interface MessageOptions {\n  type?: MessageType\n  render?: MessageRenderMessage\n  duration?: number\n  closable?: boolean\n  keepAliveOnHover?: boolean\n  icon?: () => VNodeChild\n  showIcon?: boolean\n  spinProps?: MessageSpinProps\n  onClose?: () => void\n  onLeave?: () => void\n  onAfterLeave?: () => void\n}\n"
  },
  {
    "path": "src/message/src/use-message.ts",
    "content": "import type { MessageApiInjection } from './MessageProvider'\nimport { inject } from 'vue'\nimport { throwError } from '../../_utils'\nimport { messageApiInjectionKey } from './context'\n\nexport function useMessage(): MessageApiInjection {\n  const api = inject(messageApiInjectionKey, null)\n  if (api === null) {\n    throwError(\n      'use-message',\n      'No outer <n-message-provider /> founded. See prerequisite in https://www.naiveui.com/en-US/os-theme/components/message for more details. If you want to use `useMessage` outside setup, please check https://www.naiveui.com/zh-CN/os-theme/components/message#Q-&-A.'\n    )\n  }\n  return api\n}\n"
  },
  {
    "path": "src/message/styles/_common.ts",
    "content": "export default {\n  margin: '0 0 8px 0',\n  padding: '10px 20px',\n  maxWidth: '720px',\n  minWidth: '420px',\n  iconMargin: '0 10px 0 0',\n  closeMargin: '0 0 0 10px',\n  closeSize: '20px',\n  closeIconSize: '16px',\n  iconSize: '20px',\n  fontSize: '14px'\n}\n"
  },
  {
    "path": "src/message/styles/dark.ts",
    "content": "import type { MessageTheme } from './light'\nimport { commonDark } from '../../_styles/common'\nimport { self } from './light'\n\nconst messageDark: MessageTheme = {\n  name: 'Message',\n  common: commonDark,\n  self\n}\n\nexport default messageDark\n"
  },
  {
    "path": "src/message/styles/index.ts",
    "content": "export { default as messageDark } from './dark'\nexport { default as messageLight } from './light'\nexport type { MessageTheme, MessageThemeVars } from './light'\nexport { messageRtl } from './rtl'\n"
  },
  {
    "path": "src/message/styles/light.ts",
    "content": "import type { Theme } from '../../_mixins/use-theme'\nimport type { ThemeCommonVars } from '../../_styles/common'\nimport { commonLight } from '../../_styles/common'\nimport commonVariables from './_common'\n\nexport function self(vars: ThemeCommonVars) {\n  const {\n    textColor2,\n    closeIconColor,\n    closeIconColorHover,\n    closeIconColorPressed,\n    infoColor,\n    successColor,\n    errorColor,\n    warningColor,\n    popoverColor,\n    boxShadow2,\n    primaryColor,\n    lineHeight,\n    borderRadius,\n    closeColorHover,\n    closeColorPressed\n  } = vars\n  return {\n    ...commonVariables,\n    closeBorderRadius: borderRadius,\n    textColor: textColor2,\n    textColorInfo: textColor2,\n    textColorSuccess: textColor2,\n    textColorError: textColor2,\n    textColorWarning: textColor2,\n    textColorLoading: textColor2,\n    color: popoverColor,\n    colorInfo: popoverColor,\n    colorSuccess: popoverColor,\n    colorError: popoverColor,\n    colorWarning: popoverColor,\n    colorLoading: popoverColor,\n    boxShadow: boxShadow2,\n    boxShadowInfo: boxShadow2,\n    boxShadowSuccess: boxShadow2,\n    boxShadowError: boxShadow2,\n    boxShadowWarning: boxShadow2,\n    boxShadowLoading: boxShadow2,\n    iconColor: textColor2,\n    iconColorInfo: infoColor,\n    iconColorSuccess: successColor,\n    iconColorWarning: warningColor,\n    iconColorError: errorColor,\n    iconColorLoading: primaryColor,\n    closeColorHover,\n    closeColorPressed,\n    closeIconColor,\n    closeIconColorHover,\n    closeIconColorPressed,\n    closeColorHoverInfo: closeColorHover,\n    closeColorPressedInfo: closeColorPressed,\n    closeIconColorInfo: closeIconColor,\n    closeIconColorHoverInfo: closeIconColorHover,\n    closeIconColorPressedInfo: closeIconColorPressed,\n    closeColorHoverSuccess: closeColorHover,\n    closeColorPressedSuccess: closeColorPressed,\n    closeIconColorSuccess: closeIconColor,\n    closeIconColorHoverSuccess: closeIconColorHover,\n    closeIconColorPressedSuccess: closeIconColorPressed,\n    closeColorHoverError: closeColorHover,\n    closeColorPressedError: closeColorPressed,\n    closeIconColorError: closeIconColor,\n    closeIconColorHoverError: closeIconColorHover,\n    closeIconColorPressedError: closeIconColorPressed,\n    closeColorHoverWarning: closeColorHover,\n    closeColorPressedWarning: closeColorPressed,\n    closeIconColorWarning: closeIconColor,\n    closeIconColorHoverWarning: closeIconColorHover,\n    closeIconColorPressedWarning: closeIconColorPressed,\n    closeColorHoverLoading: closeColorHover,\n    closeColorPressedLoading: closeColorPressed,\n    closeIconColorLoading: closeIconColor,\n    closeIconColorHoverLoading: closeIconColorHover,\n    closeIconColorPressedLoading: closeIconColorPressed,\n    loadingColor: primaryColor,\n    lineHeight,\n    borderRadius,\n    border: '0'\n  }\n}\n\nexport type MessageThemeVars = ReturnType<typeof self>\n\nconst messageLight: Theme<'Message', MessageThemeVars> = {\n  name: 'Message',\n  common: commonLight,\n  self\n}\n\nexport default messageLight\nexport type MessageTheme = typeof messageLight\n"
  },
  {
    "path": "src/message/styles/rtl.ts",
    "content": "import type { RtlItem } from '../../config-provider/src/internal-interface'\nimport rtlStyle from '../src/styles/rtl.cssr'\n\nexport const messageRtl: RtlItem = {\n  name: 'Message',\n  style: rtlStyle\n}\n"
  },
  {
    "path": "src/message/tests/Message.spec.tsx",
    "content": "import { mount } from '@vue/test-utils'\nimport { sleep } from 'seemly'\nimport { defineComponent, h, nextTick } from 'vue'\nimport { NMessageProvider, useMessage } from '../index'\n\nconst Provider = defineComponent({\n  render() {\n    return <NMessageProvider max={1}>{this.$slots}</NMessageProvider>\n  }\n})\n\nconst NoMaxProvider = defineComponent({\n  render() {\n    return <NMessageProvider>{this.$slots}</NMessageProvider>\n  }\n})\n\ndescribe('n-message', () => {\n  it('should work with import on demand', () => {\n    mount(NMessageProvider)\n  })\n  it('should have correct type', () => {\n    const Test = defineComponent({\n      setup() {\n        const message = useMessage()\n        message.info('string')\n        const messageReactive = message.info(() => 'string')\n        messageReactive.content = '123'\n      },\n      render() {\n        return null\n      }\n    })\n    const wrapper = mount(() => (\n      <Provider>{{ default: () => <Test /> }}</Provider>\n    ))\n    wrapper.unmount()\n  })\n  it('should work with showIcon', async () => {\n    const Test = defineComponent({\n      setup() {\n        const message = useMessage()\n\n        message.info('string')\n        message.info('string', {\n          showIcon: false\n        })\n      },\n      render() {\n        return null\n      }\n    })\n    const wrapper = mount(() => (\n      <NoMaxProvider>{{ default: () => <Test /> }}</NoMaxProvider>\n    ))\n\n    await nextTick()\n    expect(document.querySelectorAll('.n-message__icon').length).toBe(1)\n    expect(document.querySelectorAll('.n-message').length).toBe(2)\n\n    wrapper.unmount()\n  })\n})\n\ndescribe('message-provider', () => {\n  it('props.max', async () => {\n    const Test = defineComponent({\n      setup() {\n        const message = useMessage()\n        message.info('string')\n        message.info('string1')\n        message.info('string2')\n        message.info('string3')\n      },\n      render() {\n        return null\n      }\n    })\n    const wrapper = mount(NMessageProvider, {\n      props: {\n        max: 2\n      },\n      slots: {\n        default: () => <Test />\n      }\n    })\n    await nextTick()\n\n    expect(document.querySelectorAll('.n-message').length).toBe(2)\n    wrapper.unmount()\n  })\n  it('props.duration', async () => {\n    const Test = defineComponent({\n      setup() {\n        const message = useMessage()\n        message.info('string')\n      },\n      render() {\n        return null\n      }\n    })\n    const wrapper = mount(NMessageProvider, {\n      props: {\n        duration: 1000\n      },\n      slots: {\n        default: () => <Test />\n      }\n    })\n    await nextTick()\n    await sleep(500)\n    expect(document.querySelector('.n-message')).not.toEqual(null)\n    await sleep(1200)\n    expect(document.querySelector('.n-message')).toBe(null)\n    wrapper.unmount()\n  })\n  it('props.closable', async () => {\n    const Test = defineComponent({\n      setup() {\n        const message = useMessage()\n        message.info('string')\n      },\n      render() {\n        return null\n      }\n    })\n    const wrapper = mount(NMessageProvider, {\n      props: {\n        closable: true\n      },\n      slots: {\n        default: () => <Test />\n      }\n    })\n    await nextTick()\n    expect(document.querySelector('.n-message__close')).not.toBe(null)\n    wrapper.unmount()\n  })\n\n  it('props.container-style', async () => {\n    const Test = defineComponent({\n      setup() {\n        const message = useMessage()\n        message.info('string')\n      },\n      render() {\n        return null\n      }\n    })\n    const wrapper = mount(NMessageProvider, {\n      props: {\n        'container-style': 'padding: 24px'\n      },\n      slots: {\n        default: () => <Test />\n      }\n    })\n    await nextTick()\n    const container = document.querySelector('.n-message-container')\n    expect(container).not.toBe(null)\n    expect((container as HTMLElement).style.cssText).toContain('padding: 24px')\n    wrapper.unmount()\n  })\n})\n"
  },
  {
    "path": "src/message/tests/server.spec.tsx",
    "content": "import { setup } from '@css-render/vue3-ssr'\nimport { renderToString } from '@vue/server-renderer'\n/**\n * @vitest-environment node\n */\nimport { createSSRApp, defineComponent, h } from 'vue'\nimport { NMessageProvider, useMessage } from '../..'\n\ndescribe('server side rendering', () => {\n  it('works', async () => {\n    const Component = defineComponent({\n      setup() {\n        const message = useMessage()\n        expect(message).toBeTruthy()\n      },\n      render() {\n        return '07akioni'\n      }\n    })\n    const app = createSSRApp(() => (\n      <NMessageProvider>\n        {{\n          default: () => <Component />\n        }}\n      </NMessageProvider>\n    ))\n    setup(app)\n    try {\n      await renderToString(app)\n    }\n    catch (e) {\n      expect(e).not.toBeTruthy()\n    }\n  })\n})\n"
  },
  {
    "path": "src/modal/demos/enUS/basic.demo.vue",
    "content": "<markdown>\n# Basic\n\nBasic usage of modal. You can put anything in modal, a card for example.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst showModal = ref(false)\n</script>\n\n<template>\n  <n-button @click=\"showModal = true\">\n    Start me up\n  </n-button>\n  <n-modal v-model:show=\"showModal\">\n    <n-card\n      style=\"width: 600px\"\n      title=\"Modal\"\n      :bordered=\"false\"\n      size=\"huge\"\n      role=\"dialog\"\n      aria-modal=\"true\"\n    >\n      <template #header-extra>\n        Oops!\n      </template>\n      Content\n      <template #footer>\n        Footer\n      </template>\n    </n-card>\n  </n-modal>\n</template>\n"
  },
  {
    "path": "src/modal/demos/enUS/content-scrollable.demo.vue",
    "content": "<markdown>\n# Content Scrollable\n\nWhen using the Card preset, enable `content-scrollable` to keep scrolling inside the content area only. The header and footer stay fixed.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst showModal = ref(false)\n</script>\n\n<template>\n  <n-button @click=\"showModal = true\">\n    Open\n  </n-button>\n  <n-modal\n    v-model:show=\"showModal\"\n    preset=\"card\"\n    title=\"Content Scrollable\"\n    content-scrollable\n    :style=\"{ width: '600px', height: '400px' }\"\n    :segmented=\"{ content: true, footer: true }\"\n  >\n    <p v-for=\"i in 30\" :key=\"i\" style=\"margin: 0 0 8px 0\">\n      Line {{ i }} — only this area scrolls.\n    </p>\n    <template #footer>\n      Fixed footer area\n    </template>\n  </n-modal>\n</template>\n"
  },
  {
    "path": "src/modal/demos/enUS/controlled.demo.vue",
    "content": "<markdown>\n# Controlled\n\nModal can be controlled.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst showModal = ref(false)\nconst timeout = ref(6000)\n\nfunction countdown() {\n  if (timeout.value <= 0) {\n    showModal.value = false\n  }\n  else {\n    timeout.value -= 1000\n    setTimeout(countdown, 1000)\n  }\n}\n\nfunction handleClick() {\n  showModal.value = true\n  timeout.value = 6000\n\n  countdown()\n}\n</script>\n\n<template>\n  <n-button @click=\"handleClick\">\n    Start me up\n  </n-button>\n  <n-modal :show=\"showModal\">\n    <n-card\n      style=\"width: 600px\"\n      title=\"Modal\"\n      :bordered=\"false\"\n      size=\"huge\"\n      role=\"dialog\"\n      aria-modal=\"true\"\n    >\n      Countdown {{ timeout / 1000 }}s\n    </n-card>\n  </n-modal>\n</template>\n"
  },
  {
    "path": "src/modal/demos/enUS/custom-position.demo.vue",
    "content": "<markdown>\n# Customizing position\n\nUse fixed position to set the position of the modal.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst showModal = ref(false)\n</script>\n\n<template>\n  <n-button @click=\"showModal = true\">\n    Start me up\n  </n-button>\n  <n-modal v-model:show=\"showModal\">\n    <n-card\n      title=\"Modal\"\n      :bordered=\"false\"\n      size=\"huge\"\n      role=\"dialog\"\n      aria-modal=\"true\"\n      style=\"width: 600px; position: fixed; right: 100px; bottom: 100px\"\n    >\n      <template #header-extra>\n        Oops!\n      </template>\n      Content\n      <template #footer>\n        Footer\n      </template>\n    </n-card>\n  </n-modal>\n</template>\n"
  },
  {
    "path": "src/modal/demos/enUS/draggable.demo.vue",
    "content": "<markdown>\n# Draggable\n\nSet `draggable` to `true` to make modal draggable. If you want it to be dragged out of the window, you can set `draggable` to `{ bounds: 'none' }`.\n\nIf you want to completely customize the content of the modal, you can use the `draggableClass` in the `default` slot to set it on the element you want to trigger the drag.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { useModal } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst modal = useModal()\n\nconst showModal1 = ref(false)\nconst showModal2 = ref(false)\nconst showModal3 = ref(false)\nconst showModal4 = ref(false)\n\nfunction showDialogPreset() {\n  modal.create({\n    title: 'Dialog preset',\n    draggable: true,\n    preset: 'dialog',\n    content: 'Placeholder....'\n  })\n}\n\nfunction showCardPreset() {\n  modal.create({\n    title: 'Card preset',\n    draggable: true,\n    preset: 'card',\n    content: 'Placeholder....'\n  })\n}\n</script>\n\n<template>\n  <n-flex>\n    <n-button @click=\"showModal1 = !showModal1\">\n      Card preset\n    </n-button>\n    <n-button @click=\"showModal2 = !showModal2\">\n      Dialog preset\n    </n-button>\n    <n-button @click=\"showModal3 = !showModal3\">\n      No preset\n    </n-button>\n    <n-button @click=\"showDialogPreset\">\n      Imperative dialog preset\n    </n-button>\n    <n-button @click=\"showCardPreset\">\n      Imperative card preset\n    </n-button>\n    <n-button @click=\"showModal4 = !showModal4\">\n      Nested draggable\n    </n-button>\n  </n-flex>\n  <n-modal\n    v-model:show=\"showModal1\"\n    title=\"Card preset draggable\"\n    preset=\"card\"\n    draggable\n    :style=\"{ width: '800px' }\"\n  >\n    <div>Placeholder...</div>\n    <div>Placeholder...</div>\n    <div>Placeholder...</div>\n    <div>Placeholder...</div>\n    <div>Placeholder...</div>\n    <div>Placeholder...</div>\n    <div>Placeholder...</div>\n    <div>Placeholder...</div>\n    <div>Placeholder...</div>\n    <div>Placeholder...</div>\n  </n-modal>\n  <n-modal\n    v-model:show=\"showModal2\"\n    title=\"Dialog preset draggable\"\n    preset=\"dialog\"\n    draggable\n    :style=\"{ width: '800px' }\"\n  >\n    <div>Placeholder...</div>\n    <div>Placeholder...</div>\n    <div>Placeholder...</div>\n    <div>Placeholder...</div>\n    <div>Placeholder...</div>\n    <div>Placeholder...</div>\n    <div>Placeholder...</div>\n    <div>Placeholder...</div>\n    <div>Placeholder...</div>\n    <div>Placeholder...</div>\n  </n-modal>\n  <n-modal\n    v-model:show=\"showModal3\"\n    title=\"No preset draggable\"\n    draggable\n    :style=\"{ width: '800px' }\"\n  >\n    <template #default=\"{ draggableClass }\">\n      <n-card>\n        <div :class=\"draggableClass\">\n          Mouse down here to drag\n        </div>\n      </n-card>\n    </template>\n  </n-modal>\n  <n-modal\n    v-model:show=\"showModal4\"\n    title=\"Nested draggable\"\n    preset=\"card\"\n    :draggable=\"{ bounds: 'none' }\"\n    :style=\"{ width: '800px' }\"\n  >\n    <n-button @click=\"showDialogPreset\">\n      Create a new modal\n    </n-button>\n  </n-modal>\n</template>\n"
  },
  {
    "path": "src/modal/demos/enUS/index.demo-entry.md",
    "content": "# Modal\n\nIt just pops and shows you something.\n\n<n-space vertical size=\"large\">\n<n-alert type=\"warning\" title=\"Notice\" :bordered=\"false\">\n  <n-ul align-text>\n    <li>\n      If you want to use <n-text code>useModal</n-text> to create modal, you need to put the component that calls its method inside <n-text code>n-modal-provider</n-text> and use <n-text code>useModal</n-text> to get the API.\n    </li>\n    <li>\n      If you want to know how to use it outside of <n-text code>setup</n-text>, please refer to Q & A at the bottom of this page.\n    </li>\n  </n-ul>\n</n-alert>\n\nFor example:\n\n```html\n<!-- App.vue -->\n<n-modal-provider>\n  <content />\n</n-modal-provider>\n```\n\n```js\nimport { useModal } from 'naive-ui'\nimport { defineComponent } from 'vue'\n\n// content\nexport default defineComponent({\n  setup() {\n    const modal = useModal()\n    return {\n      showModal() {\n        modal.create({\n          title: 'Title',\n          content: 'Content'\n        })\n      }\n    }\n  }\n})\n```\n\n</n-space>\n\n## Demos\n\n```demo\nbasic.vue\ncontent-scrollable.vue\nreactive.vue\ncontrolled.vue\nmask-closable.vue\ncustom-position.vue\npreset-card.vue\npreset-confirm.vue\npreset-confirm-slot.vue\ntransform-origin.vue\ndraggable.vue\nmask-visible.vue\n```\n\n## API\n\n### ModalProvider Props\n\nProvided since `2.38.0`.\n\n| Name | Type | Default | Description | Version |\n| --- | --- | --- | --- | --- |\n| to | `string \\| HTMLElement` | `body` | Container node of the modal content. | 2.38.0 |\n\n### useModal API\n\nProvided since `2.38.0`.\n\n| Name | Type | Description | Version |\n| --- | --- | --- | --- |\n| create | `(options: ModalOptions) => ModalReactive` | Create a modal. | 2.38.0 |\n| destroyAll | `() => void` | Destroy all modals. | 2.38.0 |\n\n`ModalOptions` and `ModalReactive`'s properties are the same as `ModalProps` (properties should use camelCase, for example `auto-focus` property should use `autoFocus` as option property).\n\n### Modal Props\n\n| Name | Type | Default | Description | Version |\n| --- | --- | --- | --- | --- |\n| auto-focus | `boolean` | `true` | Whether to focus the first focusable element inside modal. | 2.24.2 |\n| block-scroll | `boolean` | `true` | Whether to disabled body scrolling when it's active. | 2.28.3 |\n| close-on-esc | `boolean` | `true` | Whether to close modal on Esc is pressed. | 2.24.2 |\n| display-directive | `'if' \\| 'show'` | `'if'` | Use which directive to control the rendering of modal body. |  |\n| draggable | `boolean \\| { bounds?: 'window' }` | `false` | Whether the modal is draggable. Make its position not bound inside window using `bounds === 'none'`. | 2.41.0 |\n| mask-closable | `boolean` | `true` | Whether to emit `hide` event when click mask. |  |\n| preset | `'dialog' \\| 'card'` | `undefined` | The preset of `n-modal`. |  |\n| show | `boolean` | `false` | Whether to show modal. |  |\n| show-mask | `boolean` | `true` | Whether to display the mask. If it's set to `false`, all mask-related APIs will be disabled, focus won't be limit inside modal (so keyboard event like Esc won't always work). | 2.43.0 |\n| to | `string \\| HTMLElement` | `body` | Container node of the modal content. |  |\n| transform-origin | `'mouse' \\| 'center'` | `'mouse'` | The transform origin of the modal's display animation. |  |\n| trap-focus | `boolean` | `true` | Whether to trap focus inside modal. | 2.24.2 |\n| z-index | `number` | `undefined` | Z index of the modal. | 2.24.0 |\n| on-after-enter | `() => void` | `undefined` | Callback after modal is opened. |  |\n| on-after-leave | `() => void` | `undefined` | Callback after modal is closed. |  |\n| on-esc | `() => void` | `undefined` | Callback fired when the escape key is pressed and focus is within modal. | 2.24.2 |\n| on-mask-click | `() => void` | `undefined` | Callback on mask is clicked. |  |\n| on-update:show | `(value: boolean) => void` | `undefined` | Callback when modal's display status is changed. |  |\n\n### ModalProvider Props\n\nProvided since 2.38.0.\n\n| Name | Type | Default | Description | Version |\n| --- | --- | --- | --- | --- |\n| to | `string \\| HTMLElement` | `body` | Container node of the modal content. | 2.38.0 |\n\n### Modal with Preset Card Props\n\nSee [Card props](card#Card-Props)\n\n### Modal with Preset Dialog Props\n\nSee [Dialog props](dialog#Dialog-Props)\n\n### Modal without Preset Slots\n\n| Name    | Parameters | Description               |\n| ------- | ---------- | ------------------------- |\n| default | `()`       | The content of the modal. |\n\n### Modal with Preset Card Slots\n\nSee [Card slots](card#Card-Slots)\n\n`default` slot's parameter is different, which is `(props: { draggableClass: string })`.\n\n### Modal with Preset Dialog Slots\n\nSee [Dialog slots](dialog#Dialog-Slots)\n\n`default` slot's parameter is different, which is `(props: { draggableClass: string })`.\n\n## Q & A\n\n### Use Modal Outside Setup\n\n#### Option 1\n\nUse [createDiscreteApi](discrete). If you want to use it, read its caveat carefully. You'd better not use `useModal` and it together in a same app.\n\n#### Option 2\n\n<n-space vertical size=\"large\">\n<n-alert type=\"warning\" :bordered=\"false\">\n  You need to mount the return value of <n-text code>useModal</n-text> to the window in the top-level setup and then call it. Before calling it, you need to make sure that modal has been mounted successfully.\n</n-alert>\n\n```html\n<!-- App.vue -->\n<n-modal-provider>\n  <content />\n</n-modal-provider>\n```\n\n```html\n<!-- content.vue -->\n<template>...</template>\n\n<script>\n  import { useModal } from 'naive-ui'\n  import { defineComponent } from 'vue'\n\n  // content\n  export default defineComponent({\n    setup() {\n      window.$modal = useModal()\n    }\n  })\n</script>\n```\n\n```js\n// xxx.js\nexport function handler() {\n  // You need to ensure that window.$modal = modal has been executed in setup\n  window.$modal.create({\n    title: 'Title',\n    content: 'Content'\n  })\n}\n```\n\n</n-space>\n"
  },
  {
    "path": "src/modal/demos/enUS/mask-closable.demo.vue",
    "content": "<markdown>\n# Mask closable\n\nUse `mask-closable=false` to make modal not emit the event which may close the modal.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { useMessage } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst message = useMessage()\nconst showModal = ref(false)\n\nfunction onPositiveClick() {\n  message.success('Submit')\n  showModal.value = false\n}\n\nfunction onNegativeClick() {\n  message.success('Cancel')\n  showModal.value = false\n}\n</script>\n\n<template>\n  <n-button @click=\"showModal = true\">\n    Start me up\n  </n-button>\n  <n-modal\n    v-model:show=\"showModal\"\n    :mask-closable=\"false\"\n    preset=\"dialog\"\n    title=\"Dialog\"\n    content=\"Are you sure?\"\n    positive-text=\"Confirm\"\n    negative-text=\"Cancel\"\n    @positive-click=\"onPositiveClick\"\n    @negative-click=\"onNegativeClick\"\n  />\n</template>\n"
  },
  {
    "path": "src/modal/demos/enUS/mask-visible.demo.vue",
    "content": "<markdown>\n# Mask visible\n\nYou can also hide the modal dialog's mask layer, which allows creating a floating panel.\n\nNote that in this case, all mask-related APIs will be disabled, focus won't be limit inside modal (so keyboard event like Esc won't always work).\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst showModal = ref(false)\n</script>\n\n<template>\n  <n-button @click=\"showModal = true\">\n    Floating Panel\n  </n-button>\n  <n-modal\n    v-model:show=\"showModal\"\n    style=\"width: 800px\"\n    preset=\"card\"\n    draggable\n    title=\"Floating Panel\"\n    :show-mask=\"false\"\n  >\n    Floating Panel\n  </n-modal>\n</template>\n"
  },
  {
    "path": "src/modal/demos/enUS/preset-card.demo.vue",
    "content": "<markdown>\n# Use preset card\n\nModal has some presets, which means you can use props & slots of the preset after set it.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst bodyStyle = {\n  width: '600px'\n}\nconst segmented = {\n  content: 'soft',\n  footer: 'soft'\n} as const\nconst showModal = ref(false)\n</script>\n\n<template>\n  <n-button @click=\"showModal = true\">\n    Start me up\n  </n-button>\n  <n-modal\n    v-model:show=\"showModal\"\n    class=\"custom-card\"\n    preset=\"card\"\n    :style=\"bodyStyle\"\n    title=\"Modal\"\n    :bordered=\"false\"\n    size=\"huge\"\n    :segmented=\"segmented\"\n  >\n    <template #header-extra>\n      Oops!\n    </template>\n    Content\n    <template #footer>\n      Footer\n    </template>\n  </n-modal>\n</template>\n"
  },
  {
    "path": "src/modal/demos/enUS/preset-confirm-slot.demo.vue",
    "content": "<markdown>\n# Use preset dialog (slot)\n\nSlots are also related to preset.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst showModal = ref(false)\n</script>\n\n<template>\n  <n-button @click=\"showModal = true\">\n    Start me up\n  </n-button>\n  <n-modal v-model:show=\"showModal\" preset=\"dialog\" title=\"Dialog\">\n    <template #header>\n      <div>title</div>\n    </template>\n    <div>content</div>\n    <template #action>\n      <div>action</div>\n    </template>\n  </n-modal>\n</template>\n"
  },
  {
    "path": "src/modal/demos/enUS/preset-confirm.demo.vue",
    "content": "<markdown>\n# Use preset dialog\n\nAn example of preset `dialog`.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { useMessage } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst message = useMessage()\nconst showModal = ref(false)\n\nfunction cancelCallback() {\n  message.success('Cancel')\n}\n\nfunction submitCallback() {\n  message.success('Submit')\n}\n</script>\n\n<template>\n  <n-button @click=\"showModal = true\">\n    Start me up\n  </n-button>\n  <n-modal\n    v-model:show=\"showModal\"\n    preset=\"dialog\"\n    title=\"Dialog\"\n    content=\"Are you sure?\"\n    positive-text=\"Submit\"\n    negative-text=\"Cancel\"\n    @positive-click=\"submitCallback\"\n    @negative-click=\"cancelCallback\"\n  />\n</template>\n"
  },
  {
    "path": "src/modal/demos/enUS/reactive.demo.vue",
    "content": "<markdown>\n# Imperative API\n\nProvided since `2.38.0`.\n\nYou can use `useModal.create` to create a modal. (Please make sure this API is called inside `n-modal-provider`.)\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { NButton, useMessage, useModal } from 'naive-ui'\nimport { h } from 'vue'\n\nconst modal = useModal()\nconst message = useMessage()\n\nfunction showDialogPreset() {\n  const m = modal.create({\n    title: 'Dialog perset',\n    preset: 'dialog',\n    content: 'Content'\n  })\n  message.info('Shut down in three seconds')\n  setTimeout(() => {\n    m.destroy()\n  }, 3000)\n}\n\nfunction showCardPreset() {\n  const m = modal.create({\n    title: 'Card preset',\n    preset: 'card',\n    style: {\n      width: '400px'\n    },\n    content: 'Content',\n    footer: () =>\n      h(NButton, { type: 'primary', onClick: () => m.destroy() }, () => 'Close')\n  })\n}\n\nfunction showAny() {\n  const m = modal.create({\n    style: {\n      width: '400px',\n      background: '#fff'\n    },\n    render() {\n      return h('div', [\n        'Content',\n        h(\n          NButton,\n          { type: 'primary', onClick: () => m.destroy() },\n          () => 'Close'\n        )\n      ])\n    }\n  })\n}\n</script>\n\n<template>\n  <n-flex>\n    <NButton @click=\"showDialogPreset\">\n      Start me up Dialog\n    </NButton>\n    <NButton @click=\"showCardPreset\">\n      Start me up Card\n    </NButton>\n    <NButton @click=\"showAny\">\n      Start me every thing\n    </NButton>\n  </n-flex>\n</template>\n"
  },
  {
    "path": "src/modal/demos/enUS/transform-origin.demo.vue",
    "content": "<markdown>\n# Transform origin\n\nAlthough the emerging animation from your click position is cool, sometimes we need a plain animation which occurs from the center of the screen. You can set `transfrom-origin` to `'center'` to achieve it.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst showModal = ref(false)\n</script>\n\n<template>\n  <n-button @click=\"showModal = true\">\n    Nothing\n  </n-button>\n  <n-modal v-model:show=\"showModal\" transform-origin=\"center\">\n    <n-card\n      style=\"width: 600px\"\n      title=\"Okay\"\n      :bordered=\"false\"\n      size=\"huge\"\n      role=\"dialog\"\n      aria-modal=\"true\"\n    >\n      <template #header-extra>\n        Great\n      </template>\n      Fine\n      <template #footer>\n        Nice\n      </template>\n    </n-card>\n  </n-modal>\n</template>\n"
  },
  {
    "path": "src/modal/demos/zhCN/a11y-debug.demo.vue",
    "content": "<markdown>\n# A11y debug\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst show = ref(false)\n</script>\n\n<template>\n  <n-button @click=\"show = !show\">\n    Toggle\n  </n-button>\n  <n-modal v-model:show=\"show\" preset=\"card\" title=\"A11Y\" style=\"width: 600px\">\n    <n-input placeholder=\"Gigigi\" />\n    <template #action>\n      <n-button>Something</n-button>\n    </template>\n  </n-modal>\n</template>\n"
  },
  {
    "path": "src/modal/demos/zhCN/basic.demo.vue",
    "content": "<markdown>\n# 基础用法\n\n模态框的基础用法，你可以把任何东西放进去，比如一个卡片。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst showModal = ref(false)\n</script>\n\n<template>\n  <n-button @click=\"showModal = true\">\n    来吧\n  </n-button>\n  <n-modal v-model:show=\"showModal\">\n    <n-card\n      style=\"width: 600px\"\n      title=\"模态框\"\n      :bordered=\"false\"\n      size=\"huge\"\n      role=\"dialog\"\n      aria-modal=\"true\"\n    >\n      <template #header-extra>\n        噢！\n      </template>\n      内容\n      <template #footer>\n        尾部\n      </template>\n    </n-card>\n  </n-modal>\n</template>\n"
  },
  {
    "path": "src/modal/demos/zhCN/content-scrollable.demo.vue",
    "content": "<markdown>\n# 内容滚动\n\n使用 Card 预设时，开启 `content-scrollable` 可以让滚动仅发生在内容区域，标题和底部保持固定。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst showModal = ref(false)\n</script>\n\n<template>\n  <n-button @click=\"showModal = true\">\n    打开\n  </n-button>\n  <n-modal\n    v-model:show=\"showModal\"\n    preset=\"card\"\n    title=\"Content Scrollable\"\n    content-scrollable\n    :style=\"{ width: '600px', height: '400px' }\"\n    :segmented=\"{ content: true, footer: true }\"\n  >\n    <p v-for=\"i in 30\" :key=\"i\" style=\"margin: 0 0 8px 0\">\n      第 {{ i }} 行内容，只有这里会滚动。\n    </p>\n    <template #footer>\n      固定在底部的操作区\n    </template>\n  </n-modal>\n</template>\n"
  },
  {
    "path": "src/modal/demos/zhCN/controlled.demo.vue",
    "content": "<markdown>\n# 受控显示\n\n模态框的显示可以是受控的。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst showModal = ref(false)\nconst timeout = ref(6000)\n\nfunction countdown() {\n  if (timeout.value <= 0) {\n    showModal.value = false\n  }\n  else {\n    timeout.value -= 1000\n    setTimeout(countdown, 1000)\n  }\n}\n\nfunction handleClick() {\n  showModal.value = true\n  timeout.value = 6000\n\n  countdown()\n}\n</script>\n\n<template>\n  <n-button @click=\"handleClick\">\n    来吧\n  </n-button>\n  <n-modal :show=\"showModal\">\n    <n-card\n      style=\"width: 600px\"\n      title=\"模态框\"\n      size=\"huge\"\n      :bordered=\"false\"\n      role=\"dialog\"\n      aria-modal=\"true\"\n    >\n      倒计时 {{ timeout / 1000 }} 秒\n    </n-card>\n  </n-modal>\n</template>\n"
  },
  {
    "path": "src/modal/demos/zhCN/custom-position.demo.vue",
    "content": "<markdown>\n# 调整位置\n\n通过固定定位设定 Modal 的位置。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst showModal = ref(false)\n</script>\n\n<template>\n  <n-button @click=\"showModal = true\">\n    来吧\n  </n-button>\n  <n-modal v-model:show=\"showModal\">\n    <n-card\n      title=\"模态框\"\n      :bordered=\"false\"\n      size=\"huge\"\n      role=\"dialog\"\n      aria-modal=\"true\"\n      style=\"width: 600px; position: fixed; right: 100px; bottom: 100px\"\n    >\n      <template #header-extra>\n        噢！\n      </template>\n      内容\n      <template #footer>\n        尾部\n      </template>\n    </n-card>\n  </n-modal>\n</template>\n"
  },
  {
    "path": "src/modal/demos/zhCN/dark-1-debug.demo.vue",
    "content": "<markdown>\n# Dark Debug 1\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { FormRules, FormSize } from 'naive-ui'\nimport { reactive, ref } from 'vue'\n\nconst drawerActive = ref(false)\nconst showModal = ref(false)\nconst size = ref<FormSize | undefined>('medium')\n\nconst rules: FormRules = {\n  inputValue: {\n    required: true,\n    trigger: ['blur', 'input'],\n    message: '请输入 inputValue'\n  },\n  textareaValue: {\n    required: true,\n    trigger: ['blur', 'input'],\n    message: '请输入 textareaValue'\n  },\n  selectValue: {\n    required: true,\n    trigger: ['blur', 'change'],\n    message: '请选择 selectValue'\n  },\n  multipleSelectValue: {\n    type: 'array',\n    required: true,\n    trigger: ['blur', 'change'],\n    message: '请选择 multipleSelectValue'\n  },\n  datetimeValue: {\n    type: 'number',\n    required: true,\n    trigger: ['blur', 'change'],\n    message: '请输入 datetimeValue'\n  },\n  nestedValue: {\n    path1: {\n      required: true,\n      trigger: ['blur', 'input'],\n      message: '请输入 nestedValue.path1'\n    },\n    path2: {\n      required: true,\n      trigger: ['blur', 'change'],\n      message: '请输入 nestedValue.path2'\n    }\n  },\n  checkboxGroupValue: {\n    type: 'array',\n    required: true,\n    trigger: 'change',\n    message: '请选择 checkboxGroupValue'\n  },\n  radioGroupValue: {\n    required: true,\n    trigger: 'change',\n    message: '请选择 radioGroupValue'\n  },\n  radioButtonGroupValue: {\n    required: true,\n    trigger: 'change',\n    message: '请选择 radioButtonGroupValue'\n  },\n  inputNumberValue: {\n    type: 'number',\n    required: true,\n    trigger: ['blur', 'change'],\n    message: '请输入 inputNumberValue'\n  },\n  timePickerValue: {\n    type: 'number',\n    required: true,\n    trigger: ['blur', 'change'],\n    message: '请输入 timePickerValue'\n  },\n  transferValue: {\n    type: 'array',\n    required: true,\n    trigger: 'change',\n    message: '请输入 transferValue'\n  }\n}\n\nconst model = reactive({\n  inputValue: null,\n  textareaValue: null,\n  selectValue: null,\n  multipleSelectValue: null,\n  datetimeValue: null,\n  nestedValue: {\n    path1: null,\n    path2: null\n  },\n  switchValue: false,\n  checkboxGroupValue: null,\n  radioGroupValue: null,\n  radioButtonGroupValue: null,\n  inputNumberValue: null,\n  timePickerValue: null,\n  sliderValue: 0,\n  transferValue: null\n})\n\nconst generalOptions = ['groode', 'veli good', 'emazing', 'lidiculous'].map(\n  v => ({\n    label: v,\n    value: v\n  })\n)\n</script>\n\n<template>\n  <n-button @click=\"showModal = !showModal\">\n    Toggle\n  </n-button>\n  <n-modal\n    v-model:show=\"showModal\"\n    title=\"Dark Modal Debug\"\n    preset=\"card\"\n    :style=\"{ marginTop: '24px', marginBottom: '24px', width: '800px' }\"\n  >\n    <n-radio-group\n      v-model:value=\"size\"\n      name=\"top-size\"\n      style=\"margin-bottom: 12px\"\n    >\n      <n-radio-button value=\"small\">\n        小\n      </n-radio-button>\n      <n-radio-button value=\"medium\">\n        中\n      </n-radio-button>\n      <n-radio-button value=\"large\">\n        大\n      </n-radio-button>\n    </n-radio-group>\n    <n-form :model=\"model\" :rules=\"rules\" :size=\"size\" label-placement=\"top\">\n      <n-row :gutter=\"24\">\n        <n-form-item-col :span=\"12\" label=\"Input\" path=\"inputValue\">\n          <n-input v-model:value=\"model.inputValue\" placeholder=\"Input\" />\n        </n-form-item-col>\n        <n-form-item-col :span=\"12\" label=\"Textarea\" path=\"textareaValue\">\n          <n-input\n            v-model:value=\"model.textareaValue\"\n            placeholder=\"Textarea\"\n            type=\"textarea\"\n            :autosize=\"{\n              minRows: 3,\n              maxRows: 5,\n            }\"\n          />\n        </n-form-item-col>\n      </n-row>\n      <n-row :gutter=\"24\">\n        <n-form-item-col :span=\"12\" label=\"Select\" path=\"selectValue\">\n          <n-select\n            v-model:value=\"model.selectValue\"\n            placeholder=\"Select\"\n            :options=\"generalOptions\"\n          />\n        </n-form-item-col>\n        <n-form-item-col\n          :span=\"12\"\n          label=\"Multiple Select\"\n          path=\"multipleSelectValue\"\n        >\n          <n-select\n            v-model:value=\"model.multipleSelectValue\"\n            placeholder=\"Select\"\n            :options=\"generalOptions\"\n            multiple\n          />\n        </n-form-item-col>\n      </n-row>\n      <n-row :gutter=\"24\">\n        <n-form-item-col :span=\"12\" label=\"Datetime\" path=\"datetimeValue\">\n          <n-date-picker v-model:value=\"model.datetimeValue\" type=\"datetime\" />\n        </n-form-item-col>\n        <n-form-item-col :span=\"12\" label=\"Switch\" path=\"switchValue\">\n          <n-switch v-model:value=\"model.switchValue\" />\n        </n-form-item-col>\n      </n-row>\n      <n-row :gutter=\"24\">\n        <n-form-item-col\n          :span=\"12\"\n          label=\"Checkbox Group\"\n          path=\"checkboxGroupValue\"\n        >\n          <n-checkbox-group v-model:value=\"model.checkboxGroupValue\">\n            <n-space>\n              <n-checkbox value=\"option1\">\n                Option 1\n              </n-checkbox>\n              <n-checkbox value=\"option2\">\n                Option 2\n              </n-checkbox>\n              <n-checkbox value=\"option3\">\n                Option 3\n              </n-checkbox>\n            </n-space>\n          </n-checkbox-group>\n        </n-form-item-col>\n        <n-form-item-col :span=\"12\" label=\"Radio Group\" path=\"radioGroupValue\">\n          <n-radio-group\n            v-model:value=\"model.radioGroupValue\"\n            name=\"radiogroup1\"\n          >\n            <n-space>\n              <n-radio value=\"radio1\">\n                Radio 1\n              </n-radio>\n              <n-radio value=\"radio2\">\n                Radio 2\n              </n-radio>\n              <n-radio value=\"radio3\">\n                Radio 3\n              </n-radio>\n            </n-space>\n          </n-radio-group>\n        </n-form-item-col>\n      </n-row>\n      <n-row :gutter=\"24\">\n        <n-form-item-col\n          :span=\"12\"\n          label=\"Radio Button Group\"\n          path=\"radioButtonGroupValue\"\n        >\n          <n-radio-group v-model:value=\"model.radioButtonGroupValue\">\n            <n-radio-button value=\"radio-button1\">\n              Radio Button 1\n            </n-radio-button>\n            <n-radio-button value=\"radio-button2\">\n              Radio Button 2\n            </n-radio-button>\n            <n-radio-button value=\"radio-button3\">\n              Radio Button 3\n            </n-radio-button>\n          </n-radio-group>\n        </n-form-item-col>\n        <n-form-item-col\n          :span=\"12\"\n          label=\"Input Number\"\n          path=\"inputNumberValue\"\n        >\n          <n-input-number v-model:value=\"model.inputNumberValue\" />\n        </n-form-item-col>\n      </n-row>\n      <n-row :gutter=\"24\">\n        <n-form-item-col :span=\"12\" label=\"Time Picker\" path=\"timePickerValue\">\n          <n-time-picker v-model:value=\"model.timePickerValue\" />\n        </n-form-item-col>\n        <n-form-item-col :span=\"12\" label=\"Slider\" path=\"sliderValue\">\n          <n-slider v-model:value=\"model.sliderValue\" />\n        </n-form-item-col>\n      </n-row>\n      <n-row :gutter=\"24\">\n        <n-form-item-col :span=\"24\" label=\"Transfer\" path=\"transferValue\">\n          <n-transfer\n            v-model:value=\"model.transferValue\"\n            :options=\"generalOptions\"\n          />\n        </n-form-item-col>\n      </n-row>\n      <n-row :gutter=\"24\">\n        <n-form-item-col\n          :span=\"12\"\n          label=\"Nested Path\"\n          path=\"nestedValue.path1\"\n        >\n          <n-input v-model:value=\"model.nestedValue.path1\" />\n        </n-form-item-col>\n        <n-form-item-col\n          :span=\"12\"\n          label=\"Nested Path\"\n          path=\"nestedValue.path2\"\n        >\n          <n-select\n            v-model:value=\"model.nestedValue.path2\"\n            :options=\"generalOptions\"\n          />\n        </n-form-item-col>\n      </n-row>\n      <n-row>\n        <n-col :span=\"24\">\n          <div style=\"display: flex; justify-content: flex-end\">\n            <n-button round type=\"primary\" @click=\"drawerActive = true\">\n              抽屉\n            </n-button>\n          </div>\n        </n-col>\n      </n-row>\n    </n-form>\n  </n-modal>\n  <n-drawer v-model:show=\"drawerActive\" :width=\"502\">\n    <n-drawer-content title=\"斥力装置和二踢脚\">\n      <n-form\n        :model=\"model\"\n        :rules=\"rules\"\n        :size=\"size\"\n        label-placement=\"left\"\n        label-align=\"left\"\n        :label-width=\"100\"\n      >\n        <n-form-item-row label=\"Input\" path=\"inputValue\">\n          <n-input v-model:value=\"model.inputValue\" placeholder=\"Input\" />\n        </n-form-item-row>\n        <n-form-item-row label=\"Textarea\" path=\"textareaValue\">\n          <n-input\n            v-model:value=\"model.textareaValue\"\n            placeholder=\"Textarea\"\n            type=\"textarea\"\n            :autosize=\"{\n              minRows: 3,\n              maxRows: 5,\n            }\"\n          />\n        </n-form-item-row>\n        <n-form-item-row label=\"Select\" path=\"selectValue\">\n          <n-select\n            v-model:value=\"model.selectValue\"\n            placeholder=\"Select\"\n            :options=\"generalOptions\"\n          />\n        </n-form-item-row>\n        <n-form-item-row label=\"Multiple Select\" path=\"multipleSelectValue\">\n          <n-select\n            v-model:value=\"model.multipleSelectValue\"\n            placeholder=\"Select\"\n            :options=\"generalOptions\"\n            multiple\n          />\n        </n-form-item-row>\n        <n-form-item-row label=\"Datetime\" path=\"datetimeValue\">\n          <n-date-picker\n            v-model:value=\"model.datetimeValue\"\n            type=\"datetime\"\n            clearable\n          />\n        </n-form-item-row>\n        <n-form-item-row label=\"Switch\" path=\"switchValue\">\n          <n-switch v-model:value=\"model.switchValue\" />\n        </n-form-item-row>\n        <n-form-item-row label=\"Checkbox Group\" path=\"checkboxGroupValue\">\n          <n-checkbox-group v-model:value=\"model.checkboxGroupValue\">\n            <n-space>\n              <n-checkbox value=\"option1\">\n                Option 1\n              </n-checkbox>\n              <n-checkbox value=\"option2\">\n                Option 2\n              </n-checkbox>\n              <n-checkbox value=\"option3\">\n                Option 3\n              </n-checkbox>\n            </n-space>\n          </n-checkbox-group>\n        </n-form-item-row>\n        <n-form-item-row label=\"Radio Group\" path=\"radioGroupValue\">\n          <n-radio-group\n            v-model:value=\"model.radioGroupValue\"\n            name=\"radiogroup2\"\n          >\n            <n-space>\n              <n-radio value=\"radio1\">\n                Radio 1\n              </n-radio>\n              <n-radio value=\"radio2\">\n                Radio 2\n              </n-radio>\n              <n-radio value=\"radio3\">\n                Radio 3\n              </n-radio>\n            </n-space>\n          </n-radio-group>\n        </n-form-item-row>\n        <n-form-item-row\n          label=\"Radio Button Group\"\n          path=\"radioButtonGroupValue\"\n        >\n          <n-radio-group v-model:value=\"model.radioButtonGroupValue\">\n            <n-radio-button value=\"radio-button1\">\n              Radio Button 1\n            </n-radio-button>\n            <n-radio-button value=\"radio-button2\">\n              Radio Button 2\n            </n-radio-button>\n            <n-radio-button value=\"radio-button3\">\n              Radio Button 3\n            </n-radio-button>\n          </n-radio-group>\n        </n-form-item-row>\n        <n-form-item-row label=\"Input Number\" path=\"inputNumberValue\">\n          <n-input-number v-model:value=\"model.inputNumberValue\" />\n        </n-form-item-row>\n        <n-form-item-row label=\"Time Picker\" path=\"timePickerValue\">\n          <n-time-picker v-model:value=\"model.timePickerValue\" />\n        </n-form-item-row>\n        <n-form-item-row label=\"Slider\" path=\"sliderValue\">\n          <n-slider v-model:value=\"model.sliderValue\" />\n        </n-form-item-row>\n        <n-form-item-row label=\"Transfer\" path=\"transferValue\">\n          <n-transfer\n            v-model:value=\"model.transferValue\"\n            :options=\"generalOptions\"\n          />\n        </n-form-item-row>\n        <n-form-item-row label=\"Nested Path\" path=\"nestedValue.path1\">\n          <n-input v-model:value=\"model.nestedValue.path1\" />\n        </n-form-item-row>\n        <n-form-item-row label=\"Nested Path\" path=\"nestedValue.path2\">\n          <n-select\n            v-model:value=\"model.nestedValue.path2\"\n            :options=\"generalOptions\"\n          />\n        </n-form-item-row>\n      </n-form>\n    </n-drawer-content>\n  </n-drawer>\n</template>\n"
  },
  {
    "path": "src/modal/demos/zhCN/dark-10-debug.demo.vue",
    "content": "<markdown>\n# pop debug 5\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst modalActive = ref(false)\n</script>\n\n<template>\n  <n-popover trigger=\"click\">\n    <template #trigger>\n      <n-button @click=\"modalActive = !modalActive\">\n        Toggle\n      </n-button>\n    </template>\n    <n-table :bordered=\"false\" :single-line=\"false\">\n      <thead>\n        <tr>\n          <th>Abandon</th>\n          <th>Abnormal</th>\n          <th>Abolish</th>\n          <th>...</th>\n          <th>It's hard to learn words</th>\n        </tr>\n      </thead>\n      <tbody>\n        <tr>\n          <td>放弃</td>\n          <td>反常的</td>\n          <td>彻底废除</td>\n          <td>...</td>\n          <td>Damn it! I can't remember those words.</td>\n        </tr>\n        <tr>\n          <td>...</td>\n          <td>...</td>\n          <td>...</td>\n          <td>...</td>\n          <td>...</td>\n        </tr>\n      </tbody>\n    </n-table>\n    <n-list>\n      <template #header>\n        hhh\n      </template>\n      <template #footer>\n        fff\n      </template>\n      <n-list-item>\n        <template #prefix>\n          <n-button>Prefix</n-button>\n        </template>\n        <template #suffix>\n          <n-button>Suffix</n-button>\n        </template>\n        <n-thing title=\"Thing\" title-extra=\"extra\" description=\"description\">\n          Biu<br>\n          Biu<br>\n          Biu<br>\n        </n-thing>\n      </n-list-item>\n      <n-list-item>\n        <n-thing title=\"Thing\" title-extra=\"extra\" description=\"description\">\n          Biu<br>\n          Biu<br>\n          Biu<br>\n        </n-thing>\n        <template #suffix>\n          <n-button>Suffix</n-button>\n        </template>\n      </n-list-item>\n    </n-list>\n    <n-list bordered>\n      <template #header>\n        hhh\n      </template>\n      <template #footer>\n        fff\n      </template>\n      <n-list-item>\n        <template #prefix>\n          <n-button>Prefix</n-button>\n        </template>\n        <template #suffix>\n          <n-button>Suffix</n-button>\n        </template>\n        <n-thing title=\"Thing\" title-extra=\"extra\" description=\"description\">\n          Biu<br>\n          Biu<br>\n          Biu<br>\n        </n-thing>\n      </n-list-item>\n      <n-list-item>\n        <n-thing title=\"Thing\" title-extra=\"extra\" description=\"description\">\n          Biu<br>\n          Biu<br>\n          Biu<br>\n        </n-thing>\n        <template #suffix>\n          <n-button>Suffix</n-button>\n        </template>\n      </n-list-item>\n    </n-list>\n    <n-descriptions bordered>\n      <n-descriptions-item>\n        <template #label>\n          Breakfast\n        </template>\n        Apple\n      </n-descriptions-item>\n      <n-descriptions-item label=\"Lunch\">\n        Apple\n      </n-descriptions-item>\n      <n-descriptions-item label=\"Supper\">\n        Apple\n      </n-descriptions-item>\n      <n-descriptions-item label=\"Why Long\">\n        Why <br>\n        Long <br>\n        Long <br>\n        Long <br>\n        Long <br>\n        Long\n      </n-descriptions-item>\n      <n-descriptions-item label=\"Why Long\">\n        Why <br>\n        Long <br>\n        Long <br>\n        Long <br>\n        Long <br>\n        Long\n      </n-descriptions-item>\n      <n-descriptions-item label=\"Why Long\">\n        Why <br>\n        Long <br>\n        Long <br>\n        Long <br>\n        Long <br>\n        Long\n      </n-descriptions-item>\n    </n-descriptions>\n    <n-descriptions label-placement=\"left\" bordered>\n      <n-descriptions-item>\n        <template #label>\n          Breakfast\n        </template>\n        Apple\n      </n-descriptions-item>\n      <n-descriptions-item label=\"Lunch\">\n        Apple\n      </n-descriptions-item>\n      <n-descriptions-item label=\"Supper\">\n        Apple\n      </n-descriptions-item>\n      <n-descriptions-item label=\"Why Long\">\n        Why <br>\n        Long <br>\n        Long <br>\n        Long <br>\n        Long <br>\n        Long\n      </n-descriptions-item>\n      <n-descriptions-item label=\"Why Long\">\n        Why <br>\n        Long <br>\n        Long <br>\n        Long <br>\n        Long <br>\n        Long\n      </n-descriptions-item>\n      <n-descriptions-item label=\"Why Long\">\n        Why <br>\n        Long <br>\n        Long <br>\n        Long <br>\n        Long <br>\n        Long\n      </n-descriptions-item>\n    </n-descriptions>\n    <n-descriptions>\n      <n-descriptions-item>\n        <template #label>\n          Breakfast\n        </template>\n        Apple\n      </n-descriptions-item>\n      <n-descriptions-item label=\"Lunch\">\n        Apple\n      </n-descriptions-item>\n      <n-descriptions-item label=\"Supper\">\n        Apple\n      </n-descriptions-item>\n      <n-descriptions-item label=\"Why Long\">\n        Why <br>\n        Long <br>\n        Long <br>\n        Long <br>\n        Long <br>\n        Long\n      </n-descriptions-item>\n      <n-descriptions-item label=\"Why Long\">\n        Why <br>\n        Long <br>\n        Long <br>\n        Long <br>\n        Long <br>\n        Long\n      </n-descriptions-item>\n      <n-descriptions-item label=\"Why Long\">\n        Why <br>\n        Long <br>\n        Long <br>\n        Long <br>\n        Long <br>\n        Long\n      </n-descriptions-item>\n    </n-descriptions>\n    <n-descriptions label-placement=\"left\">\n      <n-descriptions-item>\n        <template #label>\n          Breakfast\n        </template>\n        Apple\n      </n-descriptions-item>\n      <n-descriptions-item label=\"Lunch\">\n        Apple\n      </n-descriptions-item>\n      <n-descriptions-item label=\"Supper\">\n        Apple\n      </n-descriptions-item>\n      <n-descriptions-item label=\"Why Long\">\n        Why <br>\n        Long <br>\n        Long <br>\n        Long <br>\n        Long <br>\n        Long\n      </n-descriptions-item>\n      <n-descriptions-item label=\"Why Long\">\n        Why <br>\n        Long <br>\n        Long <br>\n        Long <br>\n        Long <br>\n        Long\n      </n-descriptions-item>\n      <n-descriptions-item label=\"Why Long\">\n        Why <br>\n        Long <br>\n        Long <br>\n        Long <br>\n        Long <br>\n        Long\n      </n-descriptions-item>\n    </n-descriptions>\n  </n-popover>\n</template>\n"
  },
  {
    "path": "src/modal/demos/zhCN/dark-2-debug.demo.vue",
    "content": "<markdown>\n# Dark Debug 2\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst modalActive = ref(false)\n</script>\n\n<template>\n  <n-button @click=\"modalActive = !modalActive\">\n    Toggle\n  </n-button>\n  <n-modal\n    v-model:show=\"modalActive\"\n    title=\"Dark Modal Debug\"\n    preset=\"card\"\n    :style=\"{ marginTop: '24px', marginBottom: '24px', width: '800px' }\"\n  >\n    <n-table :bordered=\"false\" :single-line=\"false\">\n      <thead>\n        <tr>\n          <th>Abandon</th>\n          <th>Abnormal</th>\n          <th>Abolish</th>\n          <th>...</th>\n          <th>It's hard to learn words</th>\n        </tr>\n      </thead>\n      <tbody>\n        <tr>\n          <td>放弃</td>\n          <td>反常的</td>\n          <td>彻底废除</td>\n          <td>...</td>\n          <td>Damn it! I can't remember those words.</td>\n        </tr>\n        <tr>\n          <td>...</td>\n          <td>...</td>\n          <td>...</td>\n          <td>...</td>\n          <td>...</td>\n        </tr>\n      </tbody>\n    </n-table>\n    <n-list>\n      <template #header>\n        hhh\n      </template>\n      <template #footer>\n        fff\n      </template>\n      <n-list-item>\n        <template #prefix>\n          <n-button>Prefix</n-button>\n        </template>\n        <template #suffix>\n          <n-button>Suffix</n-button>\n        </template>\n        <n-thing title=\"Thing\" title-extra=\"extra\" description=\"description\">\n          Biu<br>\n          Biu<br>\n          Biu<br>\n        </n-thing>\n      </n-list-item>\n      <n-list-item>\n        <n-thing title=\"Thing\" title-extra=\"extra\" description=\"description\">\n          Biu<br>\n          Biu<br>\n          Biu<br>\n        </n-thing>\n        <template #suffix>\n          <n-button>Suffix</n-button>\n        </template>\n      </n-list-item>\n    </n-list>\n    <n-list bordered>\n      <template #header>\n        hhh\n      </template>\n      <template #footer>\n        fff\n      </template>\n      <n-list-item>\n        <template #prefix>\n          <n-button>Prefix</n-button>\n        </template>\n        <template #suffix>\n          <n-button>Suffix</n-button>\n        </template>\n        <n-thing title=\"Thing\" title-extra=\"extra\" description=\"description\">\n          Biu<br>\n          Biu<br>\n          Biu<br>\n        </n-thing>\n      </n-list-item>\n      <n-list-item>\n        <n-thing title=\"Thing\" title-extra=\"extra\" description=\"description\">\n          Biu<br>\n          Biu<br>\n          Biu<br>\n        </n-thing>\n        <template #suffix>\n          <n-button>Suffix</n-button>\n        </template>\n      </n-list-item>\n    </n-list>\n    <n-descriptions bordered>\n      <n-descriptions-item>\n        <template #label>\n          Breakfast\n        </template>\n        Apple\n      </n-descriptions-item>\n      <n-descriptions-item label=\"Lunch\">\n        Apple\n      </n-descriptions-item>\n      <n-descriptions-item label=\"Supper\">\n        Apple\n      </n-descriptions-item>\n      <n-descriptions-item label=\"Why Long\">\n        Why <br>\n        Long <br>\n        Long <br>\n        Long <br>\n        Long <br>\n        Long\n      </n-descriptions-item>\n      <n-descriptions-item label=\"Why Long\">\n        Why <br>\n        Long <br>\n        Long <br>\n        Long <br>\n        Long <br>\n        Long\n      </n-descriptions-item>\n      <n-descriptions-item label=\"Why Long\">\n        Why <br>\n        Long <br>\n        Long <br>\n        Long <br>\n        Long <br>\n        Long\n      </n-descriptions-item>\n    </n-descriptions>\n    <n-descriptions label-placement=\"left\" bordered>\n      <n-descriptions-item>\n        <template #label>\n          Breakfast\n        </template>\n        Apple\n      </n-descriptions-item>\n      <n-descriptions-item label=\"Lunch\">\n        Apple\n      </n-descriptions-item>\n      <n-descriptions-item label=\"Supper\">\n        Apple\n      </n-descriptions-item>\n      <n-descriptions-item label=\"Why Long\">\n        Why <br>\n        Long <br>\n        Long <br>\n        Long <br>\n        Long <br>\n        Long\n      </n-descriptions-item>\n      <n-descriptions-item label=\"Why Long\">\n        Why <br>\n        Long <br>\n        Long <br>\n        Long <br>\n        Long <br>\n        Long\n      </n-descriptions-item>\n      <n-descriptions-item label=\"Why Long\">\n        Why <br>\n        Long <br>\n        Long <br>\n        Long <br>\n        Long <br>\n        Long\n      </n-descriptions-item>\n    </n-descriptions>\n    <n-descriptions>\n      <n-descriptions-item>\n        <template #label>\n          Breakfast\n        </template>\n        Apple\n      </n-descriptions-item>\n      <n-descriptions-item label=\"Lunch\">\n        Apple\n      </n-descriptions-item>\n      <n-descriptions-item label=\"Supper\">\n        Apple\n      </n-descriptions-item>\n      <n-descriptions-item label=\"Why Long\">\n        Why <br>\n        Long <br>\n        Long <br>\n        Long <br>\n        Long <br>\n        Long\n      </n-descriptions-item>\n      <n-descriptions-item label=\"Why Long\">\n        Why <br>\n        Long <br>\n        Long <br>\n        Long <br>\n        Long <br>\n        Long\n      </n-descriptions-item>\n      <n-descriptions-item label=\"Why Long\">\n        Why <br>\n        Long <br>\n        Long <br>\n        Long <br>\n        Long <br>\n        Long\n      </n-descriptions-item>\n    </n-descriptions>\n  </n-modal>\n</template>\n"
  },
  {
    "path": "src/modal/demos/zhCN/dark-3-debug.demo.vue",
    "content": "<markdown>\n# Dark Debug 3\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { DataTableColumns } from 'naive-ui'\nimport { repeat } from 'seemly'\nimport { computed, h, ref } from 'vue'\n\nconst showModal = ref(false)\n\nconst columns: DataTableColumns<{\n  key: number\n  name: string\n  age: number\n  address: string\n}> = [\n  {\n    type: 'selection',\n    disabled(row) {\n      return row.name === 'Edward King 3'\n    },\n    fixed: 'left'\n  },\n  {\n    title: 'Name',\n    key: 'name',\n    width: 200,\n    fixed: 'left',\n    filter: 'default',\n    filterOptions: [\n      {\n        label: 'Edward King 0',\n        value: 'Edward King 0'\n      },\n      {\n        label: 'Edward King 1',\n        value: 'Edward King 1'\n      },\n      {\n        label: 'Edward King 2',\n        value: 'Edward King 2'\n      },\n      {\n        label: 'Edward King 3',\n        value: 'Edward King 3'\n      }\n    ]\n  },\n  {\n    fixed: 'left',\n    title: 'Age',\n    key: 'age',\n    width: 100\n  },\n  {\n    title: 'Row',\n    key: 'row',\n    render(row, index) {\n      return h('span', ['row ', index])\n    }\n  },\n  {\n    title: 'Row1',\n    key: 'row1',\n    render(row, index) {\n      return h('span', ['row ', index])\n    }\n  },\n  {\n    title: 'Row2',\n    key: 'row2',\n    render(row, index) {\n      return h('span', ['row ', index])\n    }\n  },\n  {\n    title: 'Address',\n    key: 'address',\n    width: 200,\n    fixed: 'right'\n  }\n]\n\nconst data = repeat(46, undefined).map((_, index) => ({\n  key: index,\n  name: `Edward King ${index % 4}`,\n  age: 32 + (index % 3),\n  address: `London, Park Lane no. ${index}`\n}))\n\nconst pagination = computed(() => {\n  return { pageSize: 10 }\n})\n</script>\n\n<template>\n  <n-button @click=\"showModal = !showModal\">\n    Toggle\n  </n-button>\n  <n-modal\n    v-model:show=\"showModal\"\n    title=\"Dark Modal Debug\"\n    preset=\"card\"\n    :style=\"{ marginTop: '24px', marginBottom: '24px', width: '800px' }\"\n  >\n    <n-data-table\n      :columns=\"columns\"\n      :data=\"data\"\n      :pagination=\"pagination\"\n      :max-height=\"250\"\n      :scroll-x=\"1800\"\n    />\n  </n-modal>\n</template>\n"
  },
  {
    "path": "src/modal/demos/zhCN/dark-4-debug.demo.vue",
    "content": "<markdown>\n# Dark Debug 4\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst showModal = ref(false)\n</script>\n\n<template>\n  <n-button @click=\"showModal = !showModal\">\n    Toggle\n  </n-button>\n  <n-modal\n    v-model:show=\"showModal\"\n    title=\"Dark Modal Debug\"\n    preset=\"card\"\n    :style=\"{ marginTop: '24px', marginBottom: '24px', width: '800px' }\"\n  >\n    <n-popover trigger=\"click\">\n      <template #trigger>\n        <n-button style=\"margin: 0\">\n          悬浮\n        </n-button>\n      </template>\n      <span>或许不想知道你的花园长得咋样</span>\n    </n-popover>\n  </n-modal>\n</template>\n"
  },
  {
    "path": "src/modal/demos/zhCN/dark-5-debug.demo.vue",
    "content": "<markdown>\n# Dark Debug 5\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst showModal = ref(false)\n</script>\n\n<template>\n  <n-button @click=\"showModal = !showModal\">\n    Toggle\n  </n-button>\n  <n-modal\n    v-model:show=\"showModal\"\n    title=\"Dark Modal Debug\"\n    preset=\"card\"\n    :style=\"{ marginTop: '24px', marginBottom: '24px', width: '800px' }\"\n  >\n    <n-calendar />\n  </n-modal>\n</template>\n"
  },
  {
    "path": "src/modal/demos/zhCN/dark-6-debug.demo.vue",
    "content": "<markdown>\n# pop debug 1\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { FormRules, FormSize } from 'naive-ui'\nimport { reactive, ref } from 'vue'\n\nconst size = ref<FormSize | undefined>('medium')\n\nconst rules: FormRules = {\n  inputValue: {\n    required: true,\n    trigger: ['blur', 'input'],\n    message: '请输入 inputValue'\n  },\n  textareaValue: {\n    required: true,\n    trigger: ['blur', 'input'],\n    message: '请输入 textareaValue'\n  },\n  selectValue: {\n    required: true,\n    trigger: ['blur', 'change'],\n    message: '请选择 selectValue'\n  },\n  multipleSelectValue: {\n    type: 'array',\n    required: true,\n    trigger: ['blur', 'change'],\n    message: '请选择 multipleSelectValue'\n  },\n  datetimeValue: {\n    type: 'number',\n    required: true,\n    trigger: ['blur', 'change'],\n    message: '请输入 datetimeValue'\n  },\n  nestedValue: {\n    path1: {\n      required: true,\n      trigger: ['blur', 'input'],\n      message: '请输入 nestedValue.path1'\n    },\n    path2: {\n      required: true,\n      trigger: ['blur', 'change'],\n      message: '请输入 nestedValue.path2'\n    }\n  },\n  checkboxGroupValue: {\n    type: 'array',\n    required: true,\n    trigger: 'change',\n    message: '请选择 checkboxGroupValue'\n  },\n  radioGroupValue: {\n    required: true,\n    trigger: 'change',\n    message: '请选择 radioGroupValue'\n  },\n  radioButtonGroupValue: {\n    required: true,\n    trigger: 'change',\n    message: '请选择 radioButtonGroupValue'\n  },\n  inputNumberValue: {\n    type: 'number',\n    required: true,\n    trigger: ['blur', 'change'],\n    message: '请输入 inputNumberValue'\n  },\n  timePickerValue: {\n    type: 'number',\n    required: true,\n    trigger: ['blur', 'change'],\n    message: '请输入 timePickerValue'\n  },\n  transferValue: {\n    type: 'array',\n    required: true,\n    trigger: 'change',\n    message: '请输入 transferValue'\n  }\n}\n\nconst model = reactive({\n  inputValue: null,\n  textareaValue: null,\n  selectValue: null,\n  multipleSelectValue: null,\n  datetimeValue: null,\n  nestedValue: {\n    path1: null,\n    path2: null\n  },\n  switchValue: false,\n  checkboxGroupValue: null,\n  radioGroupValue: null,\n  radioButtonGroupValue: null,\n  inputNumberValue: null,\n  timePickerValue: null,\n  sliderValue: 0,\n  transferValue: null\n})\n\nconst generalOptions = ['groode', 'veli good', 'emazing', 'lidiculous'].map(\n  v => ({\n    label: v,\n    value: v\n  })\n)\n</script>\n\n<template>\n  <n-popover trigger=\"click\">\n    <template #trigger>\n      <n-button>Toggle</n-button>\n    </template>\n    <n-radio-group\n      v-model:value=\"size\"\n      name=\"top-size\"\n      style=\"margin-bottom: 12px\"\n    >\n      <n-radio-button value=\"small\">\n        小\n      </n-radio-button>\n      <n-radio-button value=\"medium\">\n        中\n      </n-radio-button>\n      <n-radio-button value=\"large\">\n        大\n      </n-radio-button>\n    </n-radio-group>\n    <n-form :model=\"model\" :rules=\"rules\" :size=\"size\" label-placement=\"top\">\n      <n-row :gutter=\"24\">\n        <n-form-item-col :span=\"12\" label=\"Input\" path=\"inputValue\">\n          <n-input v-model:value=\"model.inputValue\" placeholder=\"Input\" />\n        </n-form-item-col>\n        <n-form-item-col :span=\"12\" label=\"Textarea\" path=\"textareaValue\">\n          <n-input\n            v-model:value=\"model.textareaValue\"\n            placeholder=\"Textarea\"\n            type=\"textarea\"\n            :autosize=\"{\n              minRows: 3,\n              maxRows: 5,\n            }\"\n          />\n        </n-form-item-col>\n      </n-row>\n      <n-row :gutter=\"24\">\n        <n-form-item-col :span=\"12\" label=\"Select\" path=\"selectValue\">\n          <n-select\n            v-model:value=\"model.selectValue\"\n            placeholder=\"Select\"\n            :options=\"generalOptions\"\n          />\n        </n-form-item-col>\n        <n-form-item-col\n          :span=\"12\"\n          label=\"Multiple Select\"\n          path=\"multipleSelectValue\"\n        >\n          <n-select\n            v-model:value=\"model.multipleSelectValue\"\n            placeholder=\"Select\"\n            :options=\"generalOptions\"\n            multiple\n          />\n        </n-form-item-col>\n      </n-row>\n      <n-row :gutter=\"24\">\n        <n-form-item-col :span=\"12\" label=\"Datetime\" path=\"datetimeValue\">\n          <n-date-picker v-model:value=\"model.datetimeValue\" type=\"datetime\" />\n        </n-form-item-col>\n        <n-form-item-col :span=\"12\" label=\"Switch\" path=\"switchValue\">\n          <n-switch v-model:value=\"model.switchValue\" />\n        </n-form-item-col>\n      </n-row>\n      <n-row :gutter=\"24\">\n        <n-form-item-col\n          :span=\"12\"\n          label=\"Checkbox Group\"\n          path=\"checkboxGroupValue\"\n        >\n          <n-checkbox-group v-model:value=\"model.checkboxGroupValue\">\n            <n-space>\n              <n-checkbox value=\"option1\">\n                Option 1\n              </n-checkbox>\n              <n-checkbox value=\"option2\">\n                Option 2\n              </n-checkbox>\n              <n-checkbox value=\"option3\">\n                Option 3\n              </n-checkbox>\n            </n-space>\n          </n-checkbox-group>\n        </n-form-item-col>\n        <n-form-item-col :span=\"12\" label=\"Radio Group\" path=\"radioGroupValue\">\n          <n-radio-group\n            v-model:value=\"model.radioGroupValue\"\n            name=\"radiogroup1\"\n          >\n            <n-space>\n              <n-radio value=\"radio1\">\n                Radio 1\n              </n-radio>\n              <n-radio value=\"radio2\">\n                Radio 2\n              </n-radio>\n              <n-radio value=\"radio3\">\n                Radio 3\n              </n-radio>\n            </n-space>\n          </n-radio-group>\n        </n-form-item-col>\n      </n-row>\n      <n-row :gutter=\"24\">\n        <n-form-item-col\n          :span=\"12\"\n          label=\"Radio Button Group\"\n          path=\"radioButtonGroupValue\"\n        >\n          <n-radio-group v-model:value=\"model.radioButtonGroupValue\">\n            <n-radio-button value=\"radio-button1\">\n              Radio Button 1\n            </n-radio-button>\n            <n-radio-button value=\"radio-button2\">\n              Radio Button 2\n            </n-radio-button>\n            <n-radio-button value=\"radio-button3\">\n              Radio Button 3\n            </n-radio-button>\n          </n-radio-group>\n        </n-form-item-col>\n        <n-form-item-col\n          :span=\"12\"\n          label=\"Input Number\"\n          path=\"inputNumberValue\"\n        >\n          <n-input-number v-model:value=\"model.inputNumberValue\" />\n        </n-form-item-col>\n      </n-row>\n      <n-row :gutter=\"24\">\n        <n-form-item-col :span=\"12\" label=\"Time Picker\" path=\"timePickerValue\">\n          <n-time-picker v-model:value=\"model.timePickerValue\" />\n        </n-form-item-col>\n        <n-form-item-col :span=\"12\" label=\"Slider\" path=\"sliderValue\">\n          <n-slider v-model:value=\"model.sliderValue\" />\n        </n-form-item-col>\n      </n-row>\n      <n-row :gutter=\"24\">\n        <n-form-item-col :span=\"24\" label=\"Transfer\" path=\"transferValue\">\n          <n-transfer\n            v-model:value=\"model.transferValue\"\n            :options=\"generalOptions\"\n          />\n        </n-form-item-col>\n      </n-row>\n      <n-row :gutter=\"24\">\n        <n-form-item-col\n          :span=\"12\"\n          label=\"Nested Path\"\n          path=\"nestedValue.path1\"\n        >\n          <n-input v-model:value=\"model.nestedValue.path1\" />\n        </n-form-item-col>\n        <n-form-item-col\n          :span=\"12\"\n          label=\"Nested Path\"\n          path=\"nestedValue.path2\"\n        >\n          <n-select\n            v-model:value=\"model.nestedValue.path2\"\n            :options=\"generalOptions\"\n          />\n        </n-form-item-col>\n      </n-row>\n    </n-form>\n  </n-popover>\n</template>\n"
  },
  {
    "path": "src/modal/demos/zhCN/dark-7-debug.demo.vue",
    "content": "<markdown>\n# pop debug 2\n</markdown>\n\n<template>\n  <n-popover trigger=\"click\">\n    <template #trigger>\n      <n-button>Toggle</n-button>\n    </template>\n    <n-calendar />\n  </n-popover>\n</template>\n"
  },
  {
    "path": "src/modal/demos/zhCN/dark-8-debug.demo.vue",
    "content": "<markdown>\n# pop debug 3\n</markdown>\n\n<template>\n  <n-popover trigger=\"click\">\n    <template #trigger>\n      <n-button>Toggle</n-button>\n    </template>\n    <n-card>Go gogo</n-card>\n  </n-popover>\n</template>\n"
  },
  {
    "path": "src/modal/demos/zhCN/dark-9-debug.demo.vue",
    "content": "<markdown>\n# pop debug 4\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { DataTableColumns } from 'naive-ui'\nimport { repeat } from 'seemly'\nimport { computed, h } from 'vue'\n\nconst columns: DataTableColumns<{\n  key: number\n  name: string\n  age: number\n  address: string\n}> = [\n  {\n    type: 'selection',\n    disabled(row) {\n      return row.name === 'Edward King 3'\n    },\n    fixed: 'left'\n  },\n  {\n    title: 'Name',\n    key: 'name',\n    width: 200,\n    fixed: 'left',\n    filter: 'default',\n    filterOptions: [\n      {\n        label: 'Edward King 0',\n        value: 'Edward King 0'\n      },\n      {\n        label: 'Edward King 1',\n        value: 'Edward King 1'\n      },\n      {\n        label: 'Edward King 2',\n        value: 'Edward King 2'\n      },\n      {\n        label: 'Edward King 3',\n        value: 'Edward King 3'\n      }\n    ]\n  },\n  {\n    fixed: 'left',\n    title: 'Age',\n    key: 'age',\n    width: 100\n  },\n  {\n    title: 'Row',\n    key: 'row',\n    render(row, index) {\n      return h('span', ['row ', index])\n    }\n  },\n  {\n    title: 'Row1',\n    key: 'row1',\n    render(row, index) {\n      return h('span', ['row ', index])\n    }\n  },\n  {\n    title: 'Row2',\n    key: 'row2',\n    render(row, index) {\n      return h('span', ['row ', index])\n    }\n  },\n  {\n    title: 'Address',\n    key: 'address',\n    width: 200,\n    fixed: 'right'\n  }\n]\n\nconst data = repeat(46, undefined).map((_, index) => ({\n  key: index,\n  name: `Edward King ${index % 4}`,\n  age: 32 + (index % 3),\n  address: `London, Park Lane no. ${index}`\n}))\n\nconst pagination = computed(() => {\n  return { pageSize: 10 }\n})\n</script>\n\n<template>\n  <n-popover trigger=\"click\" :width=\"600\">\n    <template #trigger>\n      <n-button>Toggle</n-button>\n    </template>\n    <n-data-table\n      :columns=\"columns\"\n      :data=\"data\"\n      :pagination=\"pagination\"\n      :max-height=\"250\"\n      :scroll-x=\"1800\"\n    />\n  </n-popover>\n</template>\n"
  },
  {
    "path": "src/modal/demos/zhCN/draggable.demo.vue",
    "content": "<markdown>\n# 可拖拽\n\n设定 `draggable` 属性为 `true`，弹窗即可拖拽。如果你希望弹窗可以被拖出 window 的范围，可以设置 `draggable` 为 `{ bounds: 'none' }`。\n\n如果你希望拖拽完全自定义 modal 的内容，你可以使用 `default` 插槽内的 `draggableClass`，设定在你希望触发拖拽的元素上。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { useModal } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst modal = useModal()\n\nconst showModal1 = ref(false)\nconst showModal2 = ref(false)\nconst showModal3 = ref(false)\nconst showModal4 = ref(false)\n\nfunction showDialogPreset() {\n  modal.create({\n    title: 'Dialog 预设拖拽',\n    draggable: true,\n    preset: 'dialog',\n    content: '无意义的内容....'\n  })\n}\n\nfunction showCardPreset() {\n  modal.create({\n    title: 'Card 预设拖拽',\n    draggable: true,\n    preset: 'card',\n    content: '无意义的内容....'\n  })\n}\n</script>\n\n<template>\n  <n-flex>\n    <n-button @click=\"showModal1 = !showModal1\">\n      card 预设\n    </n-button>\n    <n-button @click=\"showModal2 = !showModal2\">\n      dialog 预设\n    </n-button>\n    <n-button @click=\"showModal3 = !showModal3\">\n      无预设\n    </n-button>\n    <n-button @click=\"showDialogPreset\">\n      dialog 预设（命令式 Api）\n    </n-button>\n    <n-button @click=\"showCardPreset\">\n      card 预设（命令式 Api）\n    </n-button>\n    <n-button @click=\"showModal4 = !showModal4\">\n      弹窗嵌套\n    </n-button>\n  </n-flex>\n  <n-modal\n    v-model:show=\"showModal1\"\n    title=\"card 预设拖拽\"\n    preset=\"card\"\n    draggable\n    :style=\"{ width: '800px' }\"\n  >\n    <div>无意义的内容...</div>\n    <div>无意义的内容...</div>\n    <div>无意义的内容...</div>\n    <div>无意义的内容...</div>\n    <div>无意义的内容...</div>\n    <div>无意义的内容...</div>\n    <div>无意义的内容...</div>\n    <div>无意义的内容...</div>\n    <div>无意义的内容...</div>\n    <div>无意义的内容...</div>\n  </n-modal>\n  <n-modal\n    v-model:show=\"showModal2\"\n    title=\"dialog 预设拖拽\"\n    preset=\"dialog\"\n    draggable\n    :style=\"{ width: '800px' }\"\n  >\n    <div>无意义的内容...</div>\n    <div>无意义的内容...</div>\n    <div>无意义的内容...</div>\n    <div>无意义的内容...</div>\n    <div>无意义的内容...</div>\n    <div>无意义的内容...</div>\n    <div>无意义的内容...</div>\n    <div>无意义的内容...</div>\n    <div>无意义的内容...</div>\n    <div>无意义的内容...</div>\n  </n-modal>\n  <n-modal\n    v-model:show=\"showModal3\"\n    title=\"无预设拖拽\"\n    draggable\n    :style=\"{ width: '800px' }\"\n  >\n    <template #default=\"{ draggableClass }\">\n      <n-card>\n        <div :class=\"draggableClass\">\n          点我拖拽\n        </div>\n      </n-card>\n    </template>\n  </n-modal>\n  <n-modal\n    v-model:show=\"showModal4\"\n    title=\"嵌套弹窗拖拽\"\n    preset=\"card\"\n    :draggable=\"{ bounds: 'none' }\"\n    :style=\"{ width: '800px' }\"\n  >\n    <n-button @click=\"showDialogPreset\">\n      再开一个弹窗\n    </n-button>\n  </n-modal>\n</template>\n"
  },
  {
    "path": "src/modal/demos/zhCN/drawer-debug.demo.vue",
    "content": "<markdown>\n# Drawer Debug\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { FormRules, FormSize } from 'naive-ui'\nimport { reactive, ref } from 'vue'\n\nconst drawerActive = ref(false)\nconst showModal = ref(false)\nconst size = ref<FormSize | undefined>('medium')\n\nconst rules: FormRules = {\n  inputValue: {\n    required: true,\n    trigger: ['blur', 'input'],\n    message: '请输入 inputValue'\n  },\n  textareaValue: {\n    required: true,\n    trigger: ['blur', 'input'],\n    message: '请输入 textareaValue'\n  },\n  selectValue: {\n    required: true,\n    trigger: ['blur', 'change'],\n    message: '请选择 selectValue'\n  },\n  multipleSelectValue: {\n    type: 'array',\n    required: true,\n    trigger: ['blur', 'change'],\n    message: '请选择 multipleSelectValue'\n  },\n  datetimeValue: {\n    type: 'number',\n    required: true,\n    trigger: ['blur', 'change'],\n    message: '请输入 datetimeValue'\n  },\n  nestedValue: {\n    path1: {\n      required: true,\n      trigger: ['blur', 'input'],\n      message: '请输入 nestedValue.path1'\n    },\n    path2: {\n      required: true,\n      trigger: ['blur', 'change'],\n      message: '请输入 nestedValue.path2'\n    }\n  },\n  checkboxGroupValue: {\n    type: 'array',\n    required: true,\n    trigger: 'change',\n    message: '请选择 checkboxGroupValue'\n  },\n  radioGroupValue: {\n    required: true,\n    trigger: 'change',\n    message: '请选择 radioGroupValue'\n  },\n  radioButtonGroupValue: {\n    required: true,\n    trigger: 'change',\n    message: '请选择 radioButtonGroupValue'\n  },\n  inputNumberValue: {\n    type: 'number',\n    required: true,\n    trigger: ['blur', 'change'],\n    message: '请输入 inputNumberValue'\n  },\n  timePickerValue: {\n    type: 'number',\n    required: true,\n    trigger: ['blur', 'change'],\n    message: '请输入 timePickerValue'\n  },\n  transferValue: {\n    type: 'array',\n    required: true,\n    trigger: 'change',\n    message: '请输入 transferValue'\n  }\n}\n\nconst model = reactive({\n  inputValue: null,\n  textareaValue: null,\n  selectValue: null,\n  multipleSelectValue: null,\n  datetimeValue: null,\n  nestedValue: {\n    path1: null,\n    path2: null\n  },\n  switchValue: false,\n  checkboxGroupValue: null,\n  radioGroupValue: null,\n  radioButtonGroupValue: null,\n  inputNumberValue: null,\n  timePickerValue: null,\n  sliderValue: 0,\n  transferValue: null\n})\n\nconst generalOptions = ['groode', 'veli good', 'emazing', 'lidiculous'].map(\n  v => ({\n    label: v,\n    value: v\n  })\n)\n</script>\n\n<template>\n  <n-button @click=\"showModal = !showModal\">\n    Toggle\n  </n-button>\n  <n-modal\n    v-model:show=\"showModal\"\n    title=\"Dark Modal Debug\"\n    preset=\"card\"\n    :style=\"{ marginTop: '24px', marginBottom: '24px', width: '800px' }\"\n  >\n    <n-button @click=\"drawerActive = !drawerActive\">\n      Open Drawer\n    </n-button>\n    <n-drawer v-model:show=\"drawerActive\" width=\"600\">\n      <n-radio-group\n        v-model:value=\"size\"\n        name=\"top-size\"\n        style=\"margin-bottom: 12px\"\n      >\n        <n-radio-button value=\"small\">\n          小\n        </n-radio-button>\n        <n-radio-button value=\"medium\">\n          中\n        </n-radio-button>\n        <n-radio-button value=\"large\">\n          大\n        </n-radio-button>\n      </n-radio-group>\n      <n-form :model=\"model\" :rules=\"rules\" :size=\"size\" label-placement=\"top\">\n        <n-row :gutter=\"24\">\n          <n-form-item-col :span=\"12\" label=\"Input\" path=\"inputValue\">\n            <n-input v-model:value=\"model.inputValue\" placeholder=\"Input\" />\n          </n-form-item-col>\n          <n-form-item-col :span=\"12\" label=\"Textarea\" path=\"textareaValue\">\n            <n-input\n              v-model:value=\"model.textareaValue\"\n              placeholder=\"Textarea\"\n              type=\"textarea\"\n              :autosize=\"{\n                minRows: 3,\n                maxRows: 5,\n              }\"\n            />\n          </n-form-item-col>\n        </n-row>\n        <n-row :gutter=\"24\">\n          <n-form-item-col :span=\"12\" label=\"Select\" path=\"selectValue\">\n            <n-select\n              v-model:value=\"model.selectValue\"\n              placeholder=\"Select\"\n              :options=\"generalOptions\"\n            />\n          </n-form-item-col>\n          <n-form-item-col\n            :span=\"12\"\n            label=\"Multiple Select\"\n            path=\"multipleSelectValue\"\n          >\n            <n-select\n              v-model:value=\"model.multipleSelectValue\"\n              placeholder=\"Select\"\n              :options=\"generalOptions\"\n              multiple\n            />\n          </n-form-item-col>\n        </n-row>\n        <n-row :gutter=\"24\">\n          <n-form-item-col :span=\"12\" label=\"Datetime\" path=\"datetimeValue\">\n            <n-date-picker\n              v-model:value=\"model.datetimeValue\"\n              type=\"datetime\"\n            />\n          </n-form-item-col>\n          <n-form-item-col :span=\"12\" label=\"Switch\" path=\"switchValue\">\n            <n-switch v-model:value=\"model.switchValue\" />\n          </n-form-item-col>\n        </n-row>\n        <n-row :gutter=\"24\">\n          <n-form-item-col\n            :span=\"12\"\n            label=\"Checkbox Group\"\n            path=\"checkboxGroupValue\"\n          >\n            <n-checkbox-group v-model:value=\"model.checkboxGroupValue\">\n              <n-space>\n                <n-checkbox value=\"option1\">\n                  Option 1\n                </n-checkbox>\n                <n-checkbox value=\"option2\">\n                  Option 2\n                </n-checkbox>\n                <n-checkbox value=\"option3\">\n                  Option 3\n                </n-checkbox>\n              </n-space>\n            </n-checkbox-group>\n          </n-form-item-col>\n          <n-form-item-col\n            :span=\"12\"\n            label=\"Radio Group\"\n            path=\"radioGroupValue\"\n          >\n            <n-radio-group\n              v-model:value=\"model.radioGroupValue\"\n              name=\"radiogroup1\"\n            >\n              <n-space>\n                <n-radio value=\"radio1\">\n                  Radio 1\n                </n-radio>\n                <n-radio value=\"radio2\">\n                  Radio 2\n                </n-radio>\n                <n-radio value=\"radio3\">\n                  Radio 3\n                </n-radio>\n              </n-space>\n            </n-radio-group>\n          </n-form-item-col>\n        </n-row>\n        <n-row :gutter=\"24\">\n          <n-form-item-col\n            :span=\"12\"\n            label=\"Radio Button Group\"\n            path=\"radioButtonGroupValue\"\n          >\n            <n-radio-group v-model:value=\"model.radioButtonGroupValue\">\n              <n-radio-button value=\"radio-button1\">\n                Radio Button 1\n              </n-radio-button>\n              <n-radio-button value=\"radio-button2\">\n                Radio Button 2\n              </n-radio-button>\n              <n-radio-button value=\"radio-button3\">\n                Radio Button 3\n              </n-radio-button>\n            </n-radio-group>\n          </n-form-item-col>\n          <n-form-item-col\n            :span=\"12\"\n            label=\"Input Number\"\n            path=\"inputNumberValue\"\n          >\n            <n-input-number v-model:value=\"model.inputNumberValue\" />\n          </n-form-item-col>\n        </n-row>\n        <n-row :gutter=\"24\">\n          <n-form-item-col\n            :span=\"12\"\n            label=\"Time Picker\"\n            path=\"timePickerValue\"\n          >\n            <n-time-picker v-model:value=\"model.timePickerValue\" />\n          </n-form-item-col>\n          <n-form-item-col :span=\"12\" label=\"Slider\" path=\"sliderValue\">\n            <n-slider v-model:value=\"model.sliderValue\" />\n          </n-form-item-col>\n        </n-row>\n        <n-row :gutter=\"24\">\n          <n-form-item-col :span=\"24\" label=\"Transfer\" path=\"transferValue\">\n            <n-transfer\n              v-model:value=\"model.transferValue\"\n              :options=\"generalOptions\"\n            />\n          </n-form-item-col>\n        </n-row>\n        <n-row :gutter=\"24\">\n          <n-form-item-col\n            :span=\"12\"\n            label=\"Nested Path\"\n            path=\"nestedValue.path1\"\n          >\n            <n-input v-model:value=\"model.nestedValue.path1\" />\n          </n-form-item-col>\n          <n-form-item-col\n            :span=\"12\"\n            label=\"Nested Path\"\n            path=\"nestedValue.path2\"\n          >\n            <n-select\n              v-model:value=\"model.nestedValue.path2\"\n              :options=\"generalOptions\"\n            />\n          </n-form-item-col>\n        </n-row>\n      </n-form>\n    </n-drawer>\n  </n-modal>\n</template>\n"
  },
  {
    "path": "src/modal/demos/zhCN/index.demo-entry.md",
    "content": "# 模态框 Modal\n\n它会弹出来，然后给你看点东西。\n\n<n-space vertical size=\"large\">\n<n-alert type=\"warning\" title=\"提示\" :bordered=\"false\">\n  <n-ul align-text>\n    <li>\n      如果你想通过 <n-text code>useModal</n-text> 使用模态框，你需要把调用其方法的组件放在 <n-text code>n-modal-provider</n-text> 内部并且使用 <n-text code>useModal</n-text> 去获取 API。\n    </li>\n    <li>\n      如果你想知道如何在 <n-text code>setup</n-text> 外使用，请参考页面最下方的 Q & A。\n    </li>\n  </n-ul>\n</n-alert>\n\n例如：\n\n```html\n<!-- App.vue -->\n<n-modal-provider>\n  <content />\n</n-modal-provider>\n```\n\n```js\nimport { useModal } from 'naive-ui'\nimport { defineComponent } from 'vue'\n\n// content\nexport default defineComponent({\n  setup() {\n    const modal = useModal()\n    return {\n      showModal() {\n        modal.create({\n          title: '标题',\n          content: '内容'\n        })\n      }\n    }\n  }\n})\n```\n\n</n-space>\n\n## 演示\n\n```demo\nbasic.vue\ncontent-scrollable.vue\nreactive.vue\ncontrolled.vue\nmask-closable.vue\ncustom-position.vue\npreset-card.vue\npreset-confirm.vue\npreset-confirm-slot.vue\ntransform-origin.vue\ndraggable.vue\nmask-visible.vue\nnested-debug.vue\na11y-debug.vue\nraw-debug.vue\ndark-1-debug.vue\ndark-2-debug.vue\ndark-3-debug.vue\ndark-4-debug.vue\ndark-5-debug.vue\ndrawer-debug.vue\ndark-6-debug.vue\ndark-7-debug.vue\ndark-8-debug.vue\ndark-9-debug.vue\ndark-10-debug.vue\nmask-click-debug.vue\n```\n\n## API\n\n### ModalProvider Props\n\n自 `2.38.0` 开始提供。\n\n| 名称 | 类型                    | 默认值 | 说明           | 版本   |\n| ---- | ----------------------- | ------ | -------------- | ------ |\n| to   | `string \\| HTMLElement` | `body` | 模态的挂载位置 | 2.38.0 |\n\n### useModal API\n\n自 `2.38.0` 开始提供。\n\n| 名称 | 类型 | 说明 | 版本 |\n| --- | --- | --- | --- |\n| create | `(options: ModalOptions) => ModalReactive` | 创建模态框 | 2.38.0 |\n| destroyAll | `() => void` | 销毁所有弹出的模态框 | 2.38.0 |\n\n`ModalOptions` 的属性和 `ModalReactive` 属性同 `ModalProps`（属性应使用 camelCase，例如 `auto-focus` 对应 `autoFocus`）。\n\n### Modal Props\n\n| 名称 | 类型 | 默认值 | 说明 | 版本 |\n| --- | --- | --- | --- | --- |\n| auto-focus | `boolean` | `true` | 是否自动聚焦 Modal 第一个可聚焦的元素 | 2.24.2 |\n| block-scroll | `boolean` | `true` | 是否在打开时禁用 body 滚动 | 2.28.3 |\n| close-on-esc | `boolean` | `true` | 是否在摁下 Esc 键的时候关闭 Modal | 2.24.2 |\n| display-directive | `'if' \\| 'show'` | `'if'` | 使用何种指令控制模态框主体的条件渲染 |  |\n| draggable | `boolean \\| { bounds?: 'none' }` | `false` | 是否可拖拽，`bounds === 'none'` 时拖拽可超出视口 | 2.41.0 |\n| mask-closable | `boolean` | `true` | 点击遮罩时是否发出 `update:show` 事件 |  |\n| preset | `'dialog' \\| 'card'` | `undefined` | 模态框使用何种预设 |  |\n| show | `boolean` | `false` | 是否展示 Modal |  |\n| show-mask | `boolean` | `true` | 是否显示遮罩层，如果设为 `false`，遮罩层相关的 API 将不起作用，焦点也不会被限制在 Modal 内部（这会导致键盘事件例如 Esc 不总是生效）。 | 2.43.0 |\n| to | `string \\| HTMLElement` | `body` | Modal 的挂载位置 |  |\n| transform-origin | `'mouse' \\| 'center'` | `'mouse'` | 模态框动画出现的位置 |  |\n| trap-focus | `boolean` | `true` | 是否将焦点锁定在 Modal 内部 | 2.24.2 |\n| z-index | `number` | `undefined` | Modal 的 z-index | 2.24.0 |\n| on-after-enter | `() => void` | `undefined` | Modal 出现后的回调 |  |\n| on-after-leave | `() => void` | `undefined` | Modal 关闭后的回调 |  |\n| on-esc | `() => void` | `undefined` | 焦点在 Modal 内部时按下 Esc 键的回调 | 2.24.2 |\n| on-mask-click | `() => void` | `undefined` | 点击遮罩时的回调 |  |\n| on-update:show | `(value: boolean) => void` | `undefined` | 模态框更新是否展示状态的回调 |  |\n\n### Modal（Card 预设）Props\n\n参考 [Card props](card#Card-Props)\n\n### Modal（Dialog 预设）Props\n\n参考 [Dialog props](dialog#Dialog-Props)\n\n### Modal（无预设）Slots\n\n| 名称    | 参数 | 说明         |\n| ------- | ---- | ------------ |\n| default | `()` | 模态框的内容 |\n\n### Modal（Card 预设）Slots\n\n参考 [Card slots](card#Card-Slots)\n\n注意，`default` slot 参数类型为 `(props: { draggableClass: string })`\n\n### Modal（Dialog 预设）Slots\n\n参考 [Dialog slots](dialog#Dialog-Slots)\n\n注意，`default` slot 参数类型为 `(props: { draggableClass: string })`\n\n## Q & A\n\n### 在 setup 外使用\n\n#### 选择 1\n\n使用 [createDiscreteApi](discrete)。如果你想使用它，请认真阅读它的注意事项。你最好不要把它和 `useModal` 在同一 App 中混用。\n\n#### 选择 2\n\n<n-space vertical size=\"large\">\n<n-alert type=\"warning\" :bordered=\"false\">\n  如果你想在 setup 外使用模态框，你需要在顶层 setup 中把 <n-text code>useModal</n-text> 返回的 modal 值挂载到 window 下然后再调用，调用前需要确保 modal 已经挂载成功。\n</n-alert>\n\n```html\n<!-- App.vue -->\n<n-modal-provider>\n  <content />\n</n-modal-provider>\n```\n\n```html\n<!-- content.vue -->\n<template>...</template>\n\n<script>\n  import { useModal } from 'naive-ui'\n  import { defineComponent } from 'vue'\n\n  // content\n  export default defineComponent({\n    setup() {\n      window.$modal = useModal()\n    }\n  })\n</script>\n```\n\n```js\n// xxx.js\nexport function handler() {\n  // 需要确保已经在 setup 中执行了 window.$modal = modal\n  window.$modal.create({\n    title: '标题',\n    content: '内容'\n  })\n}\n```\n\n</n-space>\n"
  },
  {
    "path": "src/modal/demos/zhCN/mask-click-debug.demo.vue",
    "content": "<markdown>\n# Mask click debug\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { NButton, NImage, NModal, NSpace } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst showModalOne = ref(false)\nconst showModalTwo = ref(false)\n\nfunction handleCloseOne() {\n  showModalOne.value = false\n}\n\nfunction handleCloseTwo() {\n  showModalTwo.value = false\n}\n</script>\n\n<template>\n  <NSpace justify=\"center\">\n    <NButton type=\"primary\" @click=\"showModalOne = true\">\n      Show Modal One\n    </NButton>\n  </NSpace>\n  <NModal\n    :show=\"showModalOne\"\n    preset=\"dialog\"\n    title=\"Modal One\"\n    type=\"success\"\n    @mask-click=\"handleCloseOne\"\n  >\n    <NSpace vertical justify=\"center\">\n      <NButton type=\"info\" @click=\"showModalTwo = true\">\n        Show Modal Two\n      </NButton>\n      <NImage\n        width=\"100\"\n        src=\"https://07akioni.oss-cn-beijing.aliyuncs.com/07akioni.jpeg\"\n        preview-src=\"https://07akioni.oss-cn-beijing.aliyuncs.com/07akioni.jpeg\"\n      />\n      try to show the second modal\n    </NSpace>\n  </NModal>\n  <NModal\n    :show=\"showModalTwo\"\n    preset=\"dialog\"\n    title=\"Modal Two\"\n    type=\"info\"\n    @mask-click=\"handleCloseTwo\"\n  >\n    try to click the mask\n  </NModal>\n</template>\n\n<style></style>\n"
  },
  {
    "path": "src/modal/demos/zhCN/mask-closable.demo.vue",
    "content": "<markdown>\n# 遮罩关闭\n\n使用 `mask-closable=false` 使点击遮罩层不发出关闭事件。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { useMessage } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst message = useMessage()\nconst showModal = ref(false)\n\nfunction onNegativeClick() {\n  message.success('Cancel')\n  showModal.value = false\n}\n\nfunction onPositiveClick() {\n  message.success('Submit')\n  showModal.value = false\n}\n</script>\n\n<template>\n  <n-button @click=\"showModal = true\">\n    来吧\n  </n-button>\n  <n-modal\n    v-model:show=\"showModal\"\n    :mask-closable=\"false\"\n    preset=\"dialog\"\n    title=\"确认\"\n    content=\"你确认\"\n    positive-text=\"确认\"\n    negative-text=\"算了\"\n    @positive-click=\"onPositiveClick\"\n    @negative-click=\"onNegativeClick\"\n  />\n</template>\n"
  },
  {
    "path": "src/modal/demos/zhCN/mask-visible.demo.vue",
    "content": "<markdown>\n# 不显示遮罩层\n\n也可以不显示模态框的遮罩层，可以拿来做一个悬浮窗。\n\n注意，此时遮罩层相关的 API 将不起作用，焦点也不会被限制在 Modal 内部（这会导致键盘事件例如 Esc 不总是生效）。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst showModal = ref(false)\n</script>\n\n<template>\n  <n-button @click=\"showModal = true\">\n    来个悬浮窗\n  </n-button>\n  <n-modal\n    v-model:show=\"showModal\"\n    style=\"width: 800px\"\n    preset=\"card\"\n    draggable\n    title=\"悬浮窗\"\n    :show-mask=\"false\"\n  >\n    悬浮窗\n  </n-modal>\n</template>\n"
  },
  {
    "path": "src/modal/demos/zhCN/nested-debug.demo.vue",
    "content": "<markdown>\n# Nested debug\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst show1 = ref(false)\nconst show2 = ref(false)\n</script>\n\n<template>\n  <n-button @click=\"show1 = !show1\">\n    show1\n  </n-button>\n  <n-modal v-model:show=\"show1\" preset=\"card\" style=\"width: 600px\">\n    <n-button @click=\"show2 = !show2\">\n      show1\n    </n-button>\n    <n-modal v-model:show=\"show2\" preset=\"card\" style=\"width: 600px\">\n      <n-select :options=\"[{ value: '1', label: '1' }]\" />\n    </n-modal>\n  </n-modal>\n</template>\n"
  },
  {
    "path": "src/modal/demos/zhCN/preset-card.demo.vue",
    "content": "<markdown>\n# 使用 Card 预设\n\n模态框有一些预设，让你在设定之后可以使用对应的 slots 还有 props。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst bodyStyle = {\n  width: '600px'\n}\nconst segmented = {\n  content: 'soft',\n  footer: 'soft'\n} as const\nconst showModal = ref(false)\n</script>\n\n<template>\n  <n-button @click=\"showModal = true\">\n    来吧\n  </n-button>\n  <n-modal\n    v-model:show=\"showModal\"\n    class=\"custom-card\"\n    preset=\"card\"\n    :style=\"bodyStyle\"\n    title=\"卡片预设\"\n    size=\"huge\"\n    :bordered=\"false\"\n    :segmented=\"segmented\"\n  >\n    <template #header-extra>\n      噢!\n    </template>\n    内容\n    <template #footer>\n      尾部\n    </template>\n  </n-modal>\n</template>\n"
  },
  {
    "path": "src/modal/demos/zhCN/preset-confirm-slot.demo.vue",
    "content": "<markdown>\n# 使用 Dialog 预设的插槽\n\n插槽也会随着预设变动。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst showModal = ref(false)\n</script>\n\n<template>\n  <n-button @click=\"showModal = true\">\n    来吧\n  </n-button>\n  <n-modal v-model:show=\"showModal\" preset=\"dialog\" title=\"Dialog\">\n    <template #header>\n      <div>标题</div>\n    </template>\n    <div>内容</div>\n    <template #action>\n      <div>操作</div>\n    </template>\n  </n-modal>\n</template>\n"
  },
  {
    "path": "src/modal/demos/zhCN/preset-confirm.demo.vue",
    "content": "<markdown>\n# 使用 Dialog 预设\n\n`dialog` 预设的例子。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { useMessage } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst message = useMessage()\nconst showModal = ref(false)\n\nfunction cancelCallback() {\n  message.success('Cancel')\n}\n\nfunction submitCallback() {\n  message.success('Submit')\n}\n</script>\n\n<template>\n  <n-button @click=\"showModal = true\">\n    来吧\n  </n-button>\n  <n-modal\n    v-model:show=\"showModal\"\n    preset=\"dialog\"\n    title=\"确认\"\n    content=\"你确认?\"\n    positive-text=\"确认\"\n    negative-text=\"算了\"\n    @positive-click=\"submitCallback\"\n    @negative-click=\"cancelCallback\"\n  />\n</template>\n"
  },
  {
    "path": "src/modal/demos/zhCN/raw-debug.demo.vue",
    "content": "<markdown>\n# Raw Debug\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst showModal = ref(false)\n</script>\n\n<template>\n  <n-button @click=\"showModal = true\">\n    来吧\n  </n-button>\n  <n-modal v-model:show=\"showModal\">\n    <div class=\"box1\">\n      <input>\n      <div class=\"box2\">\n        123\n      </div>\n    </div>\n  </n-modal>\n</template>\n"
  },
  {
    "path": "src/modal/demos/zhCN/reactive.demo.vue",
    "content": "<markdown>\n# 命令式 API\n\n自 `2.38.0` 开始提供。\n\n你可以使用 `useModal.create` 来打开一个模态框。（请确保使用此 API 的组件被 `n-modal-provider` 包含。）\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { NButton, useMessage, useModal } from 'naive-ui'\nimport { h } from 'vue'\n\nconst modal = useModal()\nconst message = useMessage()\n\nfunction showDialogPreset() {\n  const m = modal.create({\n    title: 'Dialog 预设',\n    preset: 'dialog',\n    content: '内容'\n  })\n  message.info('三秒钟后关闭')\n  setTimeout(() => {\n    m.destroy()\n  }, 3000)\n}\n\nfunction showCardPreset() {\n  const m = modal.create({\n    title: 'Card 预设',\n    preset: 'card',\n    style: {\n      width: '400px'\n    },\n    content: '内容',\n    footer: () =>\n      h(NButton, { type: 'primary', onClick: () => m.destroy() }, () => '关闭')\n  })\n}\n\nfunction showAny() {\n  const m = modal.create({\n    style: {\n      width: '400px',\n      background: '#fff'\n    },\n    render() {\n      return h('div', [\n        '随便啥',\n        h(\n          NButton,\n          { type: 'primary', onClick: () => m.destroy() },\n          () => '关闭'\n        )\n      ])\n    }\n  })\n}\n</script>\n\n<template>\n  <n-flex>\n    <NButton @click=\"showDialogPreset\">\n      来吧 Dialog\n    </NButton>\n    <NButton @click=\"showCardPreset\">\n      来吧 Card\n    </NButton>\n    <NButton @click=\"showAny\">\n      来吧 随便啥\n    </NButton>\n  </n-flex>\n</template>\n"
  },
  {
    "path": "src/modal/demos/zhCN/transform-origin.demo.vue",
    "content": "<markdown>\n# 变换原点\n\n虽然从点击位置展开模态框的动画很好看，但是有时候我们需要简单点的从屏幕中间开始的动画。你可以把 `transform-origin` 设为 `'center'` 来达成这个效果。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst showModal = ref(false)\n</script>\n\n<template>\n  <n-button @click=\"showModal = true\">\n    没什么\n  </n-button>\n  <n-modal v-model:show=\"showModal\" transform-origin=\"center\">\n    <n-card\n      style=\"width: 600px\"\n      title=\"好的\"\n      :bordered=\"false\"\n      size=\"huge\"\n      role=\"dialog\"\n      aria-modal=\"true\"\n    >\n      <template #header-extra>\n        行\n      </template>\n      可以\n      <template #footer>\n        不错\n      </template>\n    </n-card>\n  </n-modal>\n</template>\n"
  },
  {
    "path": "src/modal/index.ts",
    "content": "export { useModal, useModalReactiveList } from './src/composables'\nexport { modalProps, default as NModal } from './src/Modal'\n\nexport type { ModalProps, ModalSlots } from './src/Modal'\nexport { modalProviderProps, NModalProvider } from './src/ModalProvider'\nexport type {\n  ModalApiInjection as ModalApi,\n  ModalOptions,\n  ModalProviderInst,\n  ModalProviderProps,\n  ModalReactive\n} from './src/ModalProvider'\n"
  },
  {
    "path": "src/modal/src/BodyWrapper.tsx",
    "content": "import type {\n  ComponentPublicInstance,\n  DirectiveArguments,\n  PropType,\n  SlotsType,\n  VNode,\n  VNodeChild\n} from 'vue'\nimport type { ScrollbarInst } from '../../_internal'\nimport type { ModalDraggableOptions } from './interface'\nimport type { ModalSlots } from './Modal'\nimport { clickoutside } from 'vdirs'\nimport {\n  cloneVNode,\n  computed,\n  defineComponent,\n  h,\n  inject,\n  mergeProps,\n  nextTick,\n  normalizeClass,\n  provide,\n  ref,\n  toRef,\n  Transition,\n  vShow,\n  watch,\n  withDirectives\n} from 'vue'\nimport { VFocusTrap } from 'vueuc'\nimport { NScrollbar } from '../../_internal'\nimport {\n  getFirstSlotVNodeWithTypedProps,\n  keep,\n  useLockHtmlScroll,\n  warn\n} from '../../_utils'\nimport { NCard } from '../../card'\nimport { cardBasePropKeys } from '../../card/src/Card'\nimport { NDialog } from '../../dialog/src/Dialog'\nimport { dialogPropKeys } from '../../dialog/src/dialogProps'\nimport { drawerBodyInjectionKey } from '../../drawer/src/interface'\nimport { popoverBodyInjectionKey } from '../../popover/src/interface'\nimport { useDragModal } from './composables'\nimport { modalBodyInjectionKey, modalInjectionKey } from './interface'\nimport { presetProps } from './presetProps'\n\nexport default defineComponent({\n  name: 'ModalBody',\n  inheritAttrs: false,\n  slots: Object as SlotsType<ModalSlots>,\n  props: {\n    show: {\n      type: Boolean,\n      required: true\n    },\n    preset: String as PropType<'confirm' | 'dialog' | 'card'>,\n    displayDirective: {\n      type: String as PropType<'if' | 'show'>,\n      required: true\n    },\n    trapFocus: {\n      type: Boolean,\n      default: true\n    },\n    autoFocus: {\n      type: Boolean,\n      default: true\n    },\n    blockScroll: Boolean,\n    draggable: {\n      type: [Boolean, Object] as PropType<boolean | ModalDraggableOptions>,\n      default: false\n    },\n    maskHidden: Boolean,\n    ...presetProps,\n    renderMask: Function as PropType<() => VNodeChild>,\n    // events\n    onClickoutside: Function as PropType<(e: MouseEvent) => void>,\n    onBeforeLeave: {\n      type: Function,\n      required: true\n    },\n    onAfterLeave: {\n      type: Function,\n      required: true\n    },\n    onPositiveClick: {\n      type: Function,\n      required: true\n    },\n    onNegativeClick: {\n      type: Function,\n      required: true\n    },\n    onClose: {\n      type: Function,\n      required: true\n    },\n    onAfterEnter: Function as PropType<(el: HTMLElement) => void>,\n    onEsc: Function as PropType<(e: KeyboardEvent) => void>\n  },\n  setup(props) {\n    const bodyRef = ref<HTMLElement | ComponentPublicInstance | null>(null)\n    const scrollbarRef = ref<ScrollbarInst | null>(null)\n    const displayedRef = ref(props.show)\n    const transformOriginXRef = ref<number | null>(null)\n    const transformOriginYRef = ref<number | null>(null)\n    const NModal = inject(modalInjectionKey)!\n    let mousePosition: { x: number, y: number } | null = null\n    watch(\n      toRef(props, 'show'),\n      (value) => {\n        if (value) {\n          mousePosition = NModal.getMousePosition()\n        }\n      },\n      {\n        immediate: true\n      }\n    )\n\n    const { stopDrag, startDrag, draggableRef, draggableClassRef }\n      = useDragModal(toRef(props, 'draggable'), {\n        onEnd: (el) => {\n          syncTransformOrigin(el)\n        }\n      })\n\n    const dialogTitleClassRef = computed(() => {\n      return normalizeClass([props.titleClass, draggableClassRef.value])\n    })\n\n    const cardHeaderClassRef = computed(() => {\n      return normalizeClass([props.headerClass, draggableClassRef.value])\n    })\n\n    watch(toRef(props, 'show'), (value) => {\n      if (value)\n        displayedRef.value = true\n    })\n\n    useLockHtmlScroll(computed(() => props.blockScroll && displayedRef.value))\n\n    function styleTransformOrigin(): string {\n      if (NModal.transformOriginRef.value === 'center') {\n        return ''\n      }\n      const { value: transformOriginX } = transformOriginXRef\n      const { value: transformOriginY } = transformOriginYRef\n      if (transformOriginX === null || transformOriginY === null) {\n        return ''\n      }\n      else if (scrollbarRef.value) {\n        const scrollTop = scrollbarRef.value.containerScrollTop\n        return `${transformOriginX}px ${transformOriginY + scrollTop}px`\n      }\n      return ''\n    }\n\n    function syncTransformOrigin(el: HTMLElement): void {\n      if (NModal.transformOriginRef.value === 'center') {\n        return\n      }\n      if (!mousePosition) {\n        return\n      }\n      if (!scrollbarRef.value)\n        return\n      const scrollTop = scrollbarRef.value.containerScrollTop\n      const { offsetLeft, offsetTop } = el\n      const top = mousePosition.y\n      const left = mousePosition.x\n      transformOriginXRef.value = -(offsetLeft - left)\n      transformOriginYRef.value = -(offsetTop - top - scrollTop)\n      el.style.transformOrigin = styleTransformOrigin()\n    }\n    function handleEnter(el: HTMLElement): void {\n      void nextTick(() => {\n        syncTransformOrigin(el)\n      })\n    }\n    function handleBeforeLeave(el: HTMLElement): void {\n      el.style.transformOrigin = styleTransformOrigin()\n      props.onBeforeLeave()\n    }\n    function handleAfterEnter(el: Element): void {\n      const element = el as HTMLElement\n      draggableRef.value && startDrag(element)\n      props.onAfterEnter && props.onAfterEnter(element)\n    }\n    function handleAfterLeave(): void {\n      displayedRef.value = false\n      transformOriginXRef.value = null\n      transformOriginYRef.value = null\n      stopDrag()\n      props.onAfterLeave()\n    }\n    function handleCloseClick(): void {\n      const { onClose } = props\n      if (onClose) {\n        onClose()\n      }\n    }\n    function handleNegativeClick(): void {\n      props.onNegativeClick()\n    }\n    function handlePositiveClick(): void {\n      props.onPositiveClick()\n    }\n    const childNodeRef = ref<VNode | null>(null)\n    watch(childNodeRef, (node) => {\n      if (node) {\n        void nextTick(() => {\n          const el = node.el as HTMLElement | null\n          if (el && bodyRef.value !== el) {\n            bodyRef.value = el\n          }\n        })\n      }\n    })\n\n    provide(modalBodyInjectionKey, bodyRef)\n    provide(drawerBodyInjectionKey, null)\n    provide(popoverBodyInjectionKey, null)\n    return {\n      mergedTheme: NModal.mergedThemeRef,\n      appear: NModal.appearRef,\n      isMounted: NModal.isMountedRef,\n      mergedClsPrefix: NModal.mergedClsPrefixRef,\n      bodyRef,\n      scrollbarRef,\n      draggableClass: draggableClassRef,\n      displayed: displayedRef,\n      childNodeRef,\n      cardHeaderClass: cardHeaderClassRef,\n      dialogTitleClass: dialogTitleClassRef,\n      handlePositiveClick,\n      handleNegativeClick,\n      handleCloseClick,\n      handleAfterEnter,\n      handleAfterLeave,\n      handleBeforeLeave,\n      handleEnter\n    }\n  },\n  render() {\n    const {\n      $slots,\n      $attrs,\n      handleEnter,\n      handleAfterEnter,\n      handleAfterLeave,\n      handleBeforeLeave,\n      preset,\n      mergedClsPrefix\n    } = this\n    let childNode: VNode | null = null\n    if (!preset) {\n      childNode = getFirstSlotVNodeWithTypedProps('default', $slots.default, {\n        draggableClass: this.draggableClass\n      })\n      if (!childNode) {\n        warn('modal', 'default slot is empty')\n        return\n      }\n      childNode = cloneVNode(childNode)\n      childNode.props = mergeProps(\n        {\n          class: `${mergedClsPrefix}-modal`\n        },\n        $attrs,\n        childNode.props || {}\n      )\n    }\n    return this.displayDirective === 'show' || this.displayed || this.show\n      ? withDirectives(\n          <div\n            role=\"none\"\n            class={[\n              `${mergedClsPrefix}-modal-body-wrapper`,\n              this.maskHidden\n              && `${mergedClsPrefix}-modal-body-wrapper--mask-hidden`\n            ]}\n          >\n            <NScrollbar\n              ref=\"scrollbarRef\"\n              theme={this.mergedTheme.peers.Scrollbar}\n              themeOverrides={this.mergedTheme.peerOverrides.Scrollbar}\n              contentClass={`${mergedClsPrefix}-modal-scroll-content`}\n            >\n              {{\n                default: () => [\n                  this.renderMask?.(),\n                  <VFocusTrap\n                    disabled={!this.trapFocus || this.maskHidden}\n                    active={this.show}\n                    onEsc={this.onEsc}\n                    autoFocus={this.autoFocus}\n                  >\n                    {{\n                      default: () => (\n                        <Transition\n                          name=\"fade-in-scale-up-transition\"\n                          appear={this.appear ?? this.isMounted}\n                          onEnter={handleEnter as any}\n                          onAfterEnter={handleAfterEnter}\n                          onAfterLeave={handleAfterLeave}\n                          onBeforeLeave={handleBeforeLeave as any}\n                        >\n                          {{\n                            default: () => {\n                              const dirs: DirectiveArguments = [\n                                [vShow, this.show]\n                              ]\n                              const { onClickoutside } = this\n                              if (onClickoutside) {\n                                dirs.push([\n                                  clickoutside,\n                                  this.onClickoutside,\n                                  undefined as unknown as string,\n                                  { capture: true }\n                                ])\n                              }\n                              return withDirectives(\n                                (this.preset === 'confirm'\n                                  || this.preset === 'dialog' ? (\n                                      <NDialog\n                                        {...this.$attrs}\n                                        class={[\n                                          `${mergedClsPrefix}-modal`,\n                                          this.$attrs.class\n                                        ]}\n                                        ref=\"bodyRef\"\n                                        theme={this.mergedTheme.peers.Dialog}\n                                        themeOverrides={\n                                          this.mergedTheme.peerOverrides.Dialog\n                                        }\n                                        {...keep(this.$props, dialogPropKeys)}\n                                        titleClass={this.dialogTitleClass}\n                                        aria-modal=\"true\"\n                                      >\n                                        {$slots}\n                                      </NDialog>\n                                    ) : this.preset === 'card' ? (\n                                      <NCard\n                                        {...this.$attrs}\n                                        ref=\"bodyRef\"\n                                        class={[\n                                          `${mergedClsPrefix}-modal`,\n                                          this.$attrs.class\n                                        ]}\n                                        theme={this.mergedTheme.peers.Card}\n                                        themeOverrides={\n                                          this.mergedTheme.peerOverrides.Card\n                                        }\n                                        {...keep(this.$props, cardBasePropKeys)}\n                                        headerClass={this.cardHeaderClass}\n                                        aria-modal=\"true\"\n                                        role=\"dialog\"\n                                      >\n                                        {$slots}\n                                      </NCard>\n                                    ) : (\n                                      (this.childNodeRef = childNode)\n                                    )) as any,\n                                dirs\n                              )\n                            }\n                          }}\n                        </Transition>\n                      )\n                    }}\n                  </VFocusTrap>\n                ]\n              }}\n            </NScrollbar>\n          </div>,\n          [\n            [\n              vShow,\n              this.displayDirective === 'if' || this.displayed || this.show\n            ]\n          ]\n        )\n      : null\n  }\n})\n"
  },
  {
    "path": "src/modal/src/Modal.tsx",
    "content": "import type { CSSProperties, PropType, SlotsType, VNode } from 'vue'\nimport type { ThemeProps } from '../../_mixins'\nimport type { ExtractPublicPropTypes, MaybeArray } from '../../_utils'\nimport type { CardSlots } from '../../card'\nimport type { DialogSlots } from '../../dialog'\nimport type { ModalTheme } from '../styles'\nimport type { ModalDraggableOptions } from './interface'\nimport { getPreciseEventTarget } from 'seemly'\nimport { zindexable } from 'vdirs'\nimport { useClicked, useClickPosition, useIsMounted } from 'vooks'\nimport {\n  computed,\n  defineComponent,\n  h,\n  inject,\n  provide,\n  ref,\n  toRef,\n  Transition,\n  withDirectives\n} from 'vue'\nimport { VLazyTeleport } from 'vueuc'\nimport { useConfig, useTheme, useThemeClass } from '../../_mixins'\nimport {\n  call,\n  eventEffectNotPerformed,\n  keep,\n  useIsComposing,\n  warnOnce\n} from '../../_utils'\nimport { dialogProviderInjectionKey } from '../../dialog/src/context'\nimport { modalLight } from '../styles'\nimport NModalBodyWrapper from './BodyWrapper'\nimport { modalInjectionKey, modalProviderInjectionKey } from './interface'\nimport { presetProps, presetPropsKeys } from './presetProps'\nimport style from './styles/index.cssr'\n\nexport const modalProps = {\n  ...(useTheme.props as ThemeProps<ModalTheme>),\n  show: Boolean,\n  showMask: {\n    type: Boolean,\n    default: true\n  },\n  maskClosable: {\n    type: Boolean,\n    default: true\n  },\n  preset: String as PropType<'confirm' | 'dialog' | 'card'>,\n  to: [String, Object] as PropType<string | HTMLElement>,\n  displayDirective: {\n    type: String as PropType<'if' | 'show'>,\n    default: 'if'\n  },\n  transformOrigin: {\n    type: String as PropType<'center' | 'mouse'>,\n    default: 'mouse'\n  },\n  zIndex: Number,\n  autoFocus: {\n    type: Boolean,\n    default: true\n  },\n  trapFocus: {\n    type: Boolean,\n    default: true\n  },\n  closeOnEsc: {\n    type: Boolean,\n    default: true\n  },\n  blockScroll: { type: Boolean, default: true },\n  ...presetProps,\n  draggable: [Boolean, Object] as PropType<boolean | ModalDraggableOptions>,\n  // events\n  onEsc: Function as PropType<() => void>,\n  'onUpdate:show': [Function, Array] as PropType<\n    MaybeArray<(value: boolean) => void>\n  >,\n  onUpdateShow: [Function, Array] as PropType<\n    MaybeArray<(value: boolean) => void>\n  >,\n  onAfterEnter: Function as PropType<() => void>,\n  onBeforeLeave: Function as PropType<() => void>,\n  onAfterLeave: Function as PropType<() => void>,\n  onClose: Function as PropType<() => Promise<boolean> | boolean | any>,\n  onPositiveClick: Function as PropType<() => Promise<boolean> | boolean | any>,\n  onNegativeClick: Function as PropType<() => Promise<boolean> | boolean | any>,\n  onMaskClick: Function as PropType<(e: MouseEvent) => void>,\n  // private\n  internalDialog: Boolean,\n  internalModal: Boolean,\n  internalAppear: {\n    type: Boolean as PropType<boolean | undefined>,\n    default: undefined\n  },\n  // deprecated\n  overlayStyle: [String, Object] as PropType<string | CSSProperties>,\n  onBeforeHide: Function as PropType<() => void>,\n  onAfterHide: Function as PropType<() => void>,\n  onHide: Function as PropType<(value: false) => void>,\n  unstableShowMask: {\n    type: Boolean,\n    default: undefined\n  }\n}\n\nexport type ModalProps = ExtractPublicPropTypes<typeof modalProps>\n\nexport type ModalSlots = Omit<CardSlots & DialogSlots, 'default'> & {\n  default?: (props: { draggableClass: string }) => VNode[]\n}\n\nexport default defineComponent({\n  name: 'Modal',\n  inheritAttrs: false,\n  props: modalProps,\n  slots: Object as SlotsType<ModalSlots>,\n  setup(props) {\n    if (__DEV__) {\n      if (props.onHide) {\n        warnOnce('modal', '`on-hide` is deprecated.')\n      }\n      if (props.onAfterHide) {\n        warnOnce(\n          'modal',\n          '`on-after-hide` is deprecated, please use `on-after-leave` instead.'\n        )\n      }\n      if (props.onBeforeHide) {\n        warnOnce(\n          'modal',\n          '`on-before-hide` is deprecated, please use `on-before-leave` instead.'\n        )\n      }\n      if (props.overlayStyle) {\n        warnOnce(\n          'modal',\n          '`overlay-style` is deprecated, please use `style` instead.'\n        )\n      }\n      if (props.unstableShowMask) {\n        warnOnce(\n          'modal',\n          '`unstable-show-mask` has been removed, please use `show-mask` instead.'\n        )\n      }\n    }\n    const containerRef = ref<HTMLElement | null>(null)\n    const { mergedClsPrefixRef, namespaceRef, inlineThemeDisabled }\n      = useConfig(props)\n    const themeRef = useTheme(\n      'Modal',\n      '-modal',\n      style,\n      modalLight,\n      props,\n      mergedClsPrefixRef\n    )\n    const clickedRef = useClicked(64)\n    const clickedPositionRef = useClickPosition()\n    const isMountedRef = useIsMounted()\n    const NDialogProvider = props.internalDialog\n      ? inject(dialogProviderInjectionKey, null)\n      : null\n    const NModalProvider = props.internalModal\n      ? inject(modalProviderInjectionKey, null)\n      : null\n    const isComposingRef = useIsComposing()\n\n    function doUpdateShow(show: boolean): void {\n      const { onUpdateShow, 'onUpdate:show': _onUpdateShow, onHide } = props\n      if (onUpdateShow)\n        call(onUpdateShow, show)\n      if (_onUpdateShow)\n        call(_onUpdateShow, show)\n      // deprecated\n      if (onHide && !show)\n        onHide(show)\n    }\n    function handleCloseClick(): void {\n      const { onClose } = props\n      if (onClose) {\n        void Promise.resolve(onClose()).then((value) => {\n          if (value === false)\n            return\n          doUpdateShow(false)\n        })\n      }\n      else {\n        doUpdateShow(false)\n      }\n    }\n    function handlePositiveClick(): void {\n      const { onPositiveClick } = props\n      if (onPositiveClick) {\n        void Promise.resolve(onPositiveClick()).then((value) => {\n          if (value === false)\n            return\n          doUpdateShow(false)\n        })\n      }\n      else {\n        doUpdateShow(false)\n      }\n    }\n    function handleNegativeClick(): void {\n      const { onNegativeClick } = props\n      if (onNegativeClick) {\n        void Promise.resolve(onNegativeClick()).then((value) => {\n          if (value === false)\n            return\n          doUpdateShow(false)\n        })\n      }\n      else {\n        doUpdateShow(false)\n      }\n    }\n    function handleBeforeLeave(): void {\n      const { onBeforeLeave, onBeforeHide } = props\n      if (onBeforeLeave)\n        call(onBeforeLeave)\n      // deprecated\n      if (onBeforeHide)\n        onBeforeHide()\n    }\n    function handleAfterLeave(): void {\n      const { onAfterLeave, onAfterHide } = props\n      if (onAfterLeave)\n        call(onAfterLeave)\n      // deprecated\n      if (onAfterHide)\n        onAfterHide()\n    }\n    function handleClickoutside(e: MouseEvent): void {\n      const { onMaskClick } = props\n      if (onMaskClick) {\n        onMaskClick(e)\n      }\n      if (props.maskClosable) {\n        if (\n          containerRef.value?.contains(getPreciseEventTarget(e) as Node | null)\n        ) {\n          doUpdateShow(false)\n        }\n      }\n    }\n    function handleEsc(e: KeyboardEvent): void {\n      props.onEsc?.()\n      if (props.show && props.closeOnEsc && eventEffectNotPerformed(e)) {\n        if (!isComposingRef.value) {\n          doUpdateShow(false)\n        }\n      }\n    }\n    provide(modalInjectionKey, {\n      getMousePosition: () => {\n        const mergedProvider = NDialogProvider || NModalProvider\n        if (mergedProvider) {\n          const { clickedRef, clickedPositionRef } = mergedProvider\n          if (clickedRef.value && clickedPositionRef.value) {\n            return clickedPositionRef.value\n          }\n        }\n        if (clickedRef.value) {\n          return clickedPositionRef.value\n        }\n        return null\n      },\n      mergedClsPrefixRef,\n      mergedThemeRef: themeRef,\n      isMountedRef,\n      appearRef: toRef(props, 'internalAppear'),\n      transformOriginRef: toRef(props, 'transformOrigin')\n    })\n    const cssVarsRef = computed(() => {\n      const {\n        common: { cubicBezierEaseOut },\n        self: { boxShadow, color, textColor }\n      } = themeRef.value\n      return {\n        '--n-bezier-ease-out': cubicBezierEaseOut,\n        '--n-box-shadow': boxShadow,\n        '--n-color': color,\n        '--n-text-color': textColor\n      }\n    })\n    const themeClassHandle = inlineThemeDisabled\n      ? useThemeClass('theme-class', undefined, cssVarsRef, props)\n      : undefined\n    return {\n      mergedClsPrefix: mergedClsPrefixRef,\n      namespace: namespaceRef,\n      isMounted: isMountedRef,\n      containerRef,\n      presetProps: computed(() => {\n        const pickedProps = keep(props, presetPropsKeys)\n        // TODO: remove as any after vue fix the issue introduced in 3.2.27\n        return pickedProps as any\n      }),\n      handleEsc,\n      handleAfterLeave,\n      handleClickoutside,\n      handleBeforeLeave,\n      doUpdateShow,\n      handleNegativeClick,\n      handlePositiveClick,\n      handleCloseClick,\n      cssVars: inlineThemeDisabled ? undefined : cssVarsRef,\n      themeClass: themeClassHandle?.themeClass,\n      onRender: themeClassHandle?.onRender\n    }\n  },\n  render() {\n    const { mergedClsPrefix } = this\n    return (\n      <VLazyTeleport to={this.to} show={this.show}>\n        {{\n          default: () => {\n            this.onRender?.()\n            const { showMask } = this\n            return withDirectives(\n              <div\n                role=\"none\"\n                ref=\"containerRef\"\n                class={[\n                  `${mergedClsPrefix}-modal-container`,\n                  this.themeClass,\n                  this.namespace\n                ]}\n                style={this.cssVars as CSSProperties}\n              >\n                <NModalBodyWrapper\n                  style={this.overlayStyle}\n                  {...this.$attrs}\n                  ref=\"bodyWrapper\"\n                  displayDirective={this.displayDirective}\n                  show={this.show}\n                  preset={this.preset}\n                  autoFocus={this.autoFocus}\n                  trapFocus={this.trapFocus}\n                  draggable={this.draggable}\n                  blockScroll={this.blockScroll}\n                  maskHidden={!showMask}\n                  {...this.presetProps}\n                  onEsc={this.handleEsc}\n                  onClose={this.handleCloseClick}\n                  onNegativeClick={this.handleNegativeClick}\n                  onPositiveClick={this.handlePositiveClick}\n                  onBeforeLeave={this.handleBeforeLeave}\n                  onAfterEnter={this.onAfterEnter}\n                  onAfterLeave={this.handleAfterLeave}\n                  onClickoutside={\n                    showMask ? undefined : this.handleClickoutside\n                  }\n                  renderMask={\n                    showMask\n                      ? () => (\n                          <Transition\n                            name=\"fade-in-transition\"\n                            key=\"mask\"\n                            appear={this.internalAppear ?? this.isMounted}\n                          >\n                            {{\n                              default: () => {\n                                return this.show ? (\n                                  <div\n                                    aria-hidden\n                                    ref=\"containerRef\"\n                                    class={`${mergedClsPrefix}-modal-mask`}\n                                    onClick={this.handleClickoutside}\n                                  />\n                                ) : null\n                              }\n                            }}\n                          </Transition>\n                        )\n                      : undefined\n                  }\n                >\n                  {this.$slots}\n                </NModalBodyWrapper>\n              </div>,\n              [\n                [\n                  zindexable,\n                  {\n                    zIndex: this.zIndex,\n                    enabled: this.show\n                  }\n                ]\n              ]\n            )\n          }\n        }}\n      </VLazyTeleport>\n    )\n  }\n})\n"
  },
  {
    "path": "src/modal/src/ModalEnvironment.tsx",
    "content": "import type { PropType } from 'vue'\n// use absolute path to make sure no circular ref of style\n// this -> modal-index -> modal-style\nimport { defineComponent, h, ref } from 'vue'\nimport NModal, { modalProps } from './Modal'\n\nexport const NModalEnvironment = defineComponent({\n  name: 'ModalEnvironment',\n  props: {\n    ...modalProps,\n    internalKey: {\n      type: String,\n      required: true\n    },\n    // private\n    onInternalAfterLeave: {\n      type: Function as PropType<(key: string) => void>,\n      required: true\n    }\n  },\n  setup(props) {\n    const showRef = ref(true)\n    function handleAfterLeave(): void {\n      const { onInternalAfterLeave, internalKey, onAfterLeave } = props\n      if (onInternalAfterLeave)\n        onInternalAfterLeave(internalKey)\n      if (onAfterLeave)\n        onAfterLeave()\n    }\n    function handlePositiveClick(): void {\n      const { onPositiveClick } = props\n      if (onPositiveClick) {\n        void Promise.resolve(onPositiveClick()).then((result) => {\n          if (result === false)\n            return\n          hide()\n        })\n      }\n      else {\n        hide()\n      }\n    }\n    function handleNegativeClick(): void {\n      const { onNegativeClick } = props\n      if (onNegativeClick) {\n        void Promise.resolve(onNegativeClick()).then((result) => {\n          if (result === false)\n            return\n          hide()\n        })\n      }\n      else {\n        hide()\n      }\n    }\n    function handleCloseClick(): void {\n      const { onClose } = props\n      if (onClose) {\n        void Promise.resolve(onClose()).then((result) => {\n          if (result === false)\n            return\n          hide()\n        })\n      }\n      else {\n        hide()\n      }\n    }\n    function handleMaskClick(e: MouseEvent): void {\n      const { onMaskClick, maskClosable } = props\n      if (onMaskClick) {\n        onMaskClick(e)\n        if (maskClosable) {\n          hide()\n        }\n      }\n    }\n    function handleEsc(): void {\n      const { onEsc } = props\n      if (onEsc) {\n        onEsc()\n      }\n    }\n    function hide(): void {\n      showRef.value = false\n    }\n    function handleUpdateShow(value: boolean): void {\n      showRef.value = value\n    }\n    return {\n      show: showRef,\n      hide,\n      handleUpdateShow,\n      handleAfterLeave,\n      handleCloseClick,\n      handleNegativeClick,\n      handlePositiveClick,\n      handleMaskClick,\n      handleEsc\n    }\n  },\n  render() {\n    const {\n      handleUpdateShow,\n      handleAfterLeave,\n      handleMaskClick,\n      handleEsc,\n      show\n    } = this\n    return (\n      <NModal\n        {...this.$props}\n        show={show}\n        onUpdateShow={handleUpdateShow}\n        onMaskClick={handleMaskClick}\n        onEsc={handleEsc}\n        onAfterLeave={handleAfterLeave}\n        internalAppear\n        internalModal\n      >\n        {this.$slots}\n      </NModal>\n    )\n  }\n})\n"
  },
  {
    "path": "src/modal/src/ModalProvider.ts",
    "content": "import type {\n  CSSProperties,\n  DefineComponent,\n  ExtractPropTypes,\n  PropType,\n  Ref,\n  VNodeChild\n} from 'vue'\nimport type { ExtractPublicPropTypes, Mutable } from '../../_utils'\nimport type { modalProps } from './Modal'\nimport { createId } from 'seemly'\nimport { useClicked, useClickPosition } from 'vooks'\nimport { defineComponent, Fragment, h, provide, reactive, ref } from 'vue'\nimport { omit } from '../../_utils'\nimport {\n  modalApiInjectionKey,\n  modalProviderInjectionKey,\n  modalReactiveListInjectionKey\n} from './context'\nimport { NModalEnvironment } from './ModalEnvironment'\n\nexport type ModalOptions = Mutable<\n  Omit<Partial<ExtractPropTypes<typeof modalProps>>, 'internalStyle'> & {\n    class?: any\n    style?: string | CSSProperties\n    render?: () => VNodeChild\n  }\n>\n\nexport type ModalReactive = {\n  readonly key: string\n  readonly destroy: () => void\n} & ModalOptions\n\n// FIXME\n// If style is used as CSSProperties, typescript 4.4.2 will throw tons of errors\n// Fxxx\ntype TypeSafeModalReactive = ModalReactive & {\n  class?: any\n  style?: any\n}\n\nexport interface ModalApiInjection {\n  destroyAll: () => void\n  create: (options: ModalOptions) => ModalReactive\n}\n\nexport interface ModalProviderInjection {\n  clickedRef: Ref<boolean>\n  clickedPositionRef: Ref<{ x: number, y: number } | null>\n}\n\nexport type ModalReactiveListInjection = Ref<ModalReactive[]>\n\ninterface ModalInst {\n  hide: () => void\n}\n\nexport type ModalProviderInst = ModalApiInjection\n\nexport const modalProviderProps = {\n  to: [String, Object] as PropType<string | HTMLElement>\n}\n\nexport type ModalProviderProps = ExtractPublicPropTypes<\n  typeof modalProviderProps\n>\n\nexport const NModalProvider: DefineComponent<{ to?: string | HTMLElement }>\n  = defineComponent({\n    name: 'ModalProvider',\n    props: modalProviderProps,\n    setup() {\n      const modalListRef = ref<TypeSafeModalReactive[]>([])\n      const modalInstRefs: Record<string, ModalInst | undefined> = {}\n      function create(options: ModalOptions = {}): ModalReactive {\n        const key = createId()\n        const modalReactive = reactive({\n          ...options,\n          key,\n          destroy: () => {\n            modalInstRefs[`n-modal-${key}`]?.hide()\n          }\n        })\n        modalListRef.value.push(modalReactive)\n        return modalReactive\n      }\n\n      function handleAfterLeave(key: string): void {\n        const { value: modalList } = modalListRef\n        modalList.splice(\n          modalList.findIndex(modal => modal.key === key),\n          1\n        )\n      }\n\n      function destroyAll(): void {\n        Object.values(modalInstRefs).forEach((modalInstRef) => {\n          modalInstRef?.hide()\n        })\n      }\n\n      const api = {\n        create,\n        destroyAll\n      }\n\n      provide(modalApiInjectionKey, api)\n      provide(modalProviderInjectionKey, {\n        clickedRef: useClicked(64),\n        clickedPositionRef: useClickPosition()\n      })\n      provide(modalReactiveListInjectionKey, modalListRef)\n      return {\n        ...api,\n        modalList: modalListRef,\n        modalInstRefs,\n        handleAfterLeave\n      }\n    },\n    render() {\n      return h(Fragment, null, [\n        this.modalList.map(modal =>\n          h(\n            NModalEnvironment,\n            omit(modal, ['destroy', 'render'], {\n              to: modal.to ?? this.to,\n              ref: ((inst: ModalInst | null) => {\n                if (inst === null) {\n                  delete this.modalInstRefs[`n-modal-${modal.key}`]\n                }\n                else {\n                  this.modalInstRefs[`n-modal-${modal.key}`] = inst\n                }\n              }) as any,\n              internalKey: modal.key,\n              onInternalAfterLeave: this.handleAfterLeave\n            }),\n            {\n              default: modal.render\n            }\n          )\n        ),\n        this.$slots.default?.()\n      ])\n    }\n  })\n"
  },
  {
    "path": "src/modal/src/composables.ts",
    "content": "import type { Ref } from 'vue'\nimport type { ModalDraggableOptions } from './interface'\nimport type { ModalApiInjection, ModalReactive } from './ModalProvider'\nimport { off, on } from 'evtd'\nimport { computed, inject, onUnmounted } from 'vue'\nimport { throwError } from '../../_utils'\nimport { modalApiInjectionKey, modalReactiveListInjectionKey } from './context'\n\nexport function useModal(): ModalApiInjection {\n  const modal = inject(modalApiInjectionKey, null)\n  if (modal === null) {\n    throwError('use-modal', 'No outer <n-modal-provider /> founded.')\n  }\n  return modal\n}\n\nexport function useModalReactiveList(): Ref<readonly ModalReactive[]> {\n  const modalReactiveList = inject(modalReactiveListInjectionKey, null)\n  if (modalReactiveList === null) {\n    throwError(\n      'use-modal-reactive-list',\n      'No outer <n-modal-provider /> founded.'\n    )\n  }\n  return modalReactiveList\n}\n\nexport const DRAGGABLE_CLASS = 'n-draggable'\n\ninterface UseDragModalOptions {\n  onEnd: (el: HTMLElement) => void\n}\nexport function useDragModal(\n  draggablePropsRef: Ref<boolean | ModalDraggableOptions>,\n  options: UseDragModalOptions\n) {\n  let cleanup: undefined | (() => void)\n\n  const draggableRef = computed(() => {\n    return draggablePropsRef.value !== false\n  })\n\n  const draggableClassRef = computed(() => {\n    return draggableRef.value ? DRAGGABLE_CLASS : ''\n  })\n\n  const boundsToWindowRef = computed(() => {\n    const draggableProps = draggablePropsRef.value\n    if (draggableProps === true || draggableProps === false) {\n      return true\n    }\n    else if (draggableProps) {\n      return draggableProps.bounds !== 'none'\n    }\n    else {\n      return true\n    }\n  })\n\n  function startDrag(modal: HTMLElement) {\n    const header = modal.querySelector(`.${DRAGGABLE_CLASS}`) as HTMLElement\n    if (!header || !draggableClassRef.value) {\n      return\n    }\n\n    let maxMoveX = 0\n    let minMoveX = 0\n    let maxMoveY = 0\n    let minMoveY = 0\n    let prevMoveY = 0\n    let prevMoveX = 0\n    let mousedownEvent: MouseEvent | undefined\n    let rafId: number | null = null\n    let pendingPosition: { x: number, y: number } | null = null\n\n    function handleMouseDown(event: MouseEvent) {\n      event.preventDefault()\n      mousedownEvent = event\n      const { x, y, right, bottom } = modal.getBoundingClientRect()\n\n      minMoveX = x\n      minMoveY = y\n      maxMoveX = window.innerWidth - right\n      maxMoveY = window.innerHeight - bottom\n\n      const { left, top } = modal.style\n      prevMoveY = +top.slice(0, -2)\n      prevMoveX = +left.slice(0, -2)\n    }\n\n    function updatePosition() {\n      if (pendingPosition) {\n        modal.style.top = `${pendingPosition.y}px`\n        modal.style.left = `${pendingPosition.x}px`\n        pendingPosition = null\n      }\n      rafId = null\n    }\n\n    function handleMouseMove(event: MouseEvent) {\n      if (!mousedownEvent)\n        return\n\n      const { clientX: downX, clientY: downY } = mousedownEvent\n\n      let moveX = event.clientX - downX\n      let moveY = event.clientY - downY\n      if (boundsToWindowRef.value) {\n        if (moveX > maxMoveX) {\n          moveX = maxMoveX\n        }\n        else if (-moveX > minMoveX) {\n          moveX = -minMoveX\n        }\n\n        if (moveY > maxMoveY) {\n          moveY = maxMoveY\n        }\n        else if (-moveY > minMoveY) {\n          moveY = -minMoveY\n        }\n      }\n      const x = moveX + prevMoveX\n      const y = moveY + prevMoveY\n\n      pendingPosition = { x, y }\n\n      if (!rafId) {\n        rafId = requestAnimationFrame(updatePosition)\n      }\n    }\n\n    function handleMouseUp() {\n      mousedownEvent = undefined\n      if (rafId) {\n        cancelAnimationFrame(rafId)\n        rafId = null\n      }\n      if (pendingPosition) {\n        modal.style.top = `${pendingPosition.y}px`\n        modal.style.left = `${pendingPosition.x}px`\n        pendingPosition = null\n      }\n      options.onEnd(modal)\n    }\n\n    on('mousedown', header, handleMouseDown)\n    on('mousemove', window, handleMouseMove)\n    on('mouseup', window, handleMouseUp)\n\n    cleanup = () => {\n      if (rafId) {\n        cancelAnimationFrame(rafId)\n      }\n      off('mousedown', header, handleMouseDown)\n      off('mousemove', window, handleMouseMove)\n      off('mouseup', window, handleMouseUp)\n    }\n  }\n\n  function stopDrag() {\n    if (cleanup) {\n      cleanup()\n      cleanup = undefined\n    }\n  }\n\n  onUnmounted(stopDrag)\n  return {\n    stopDrag,\n    startDrag,\n    draggableRef,\n    draggableClassRef\n  }\n}\n"
  },
  {
    "path": "src/modal/src/context.ts",
    "content": "import type {\n  ModalApiInjection,\n  ModalProviderInjection,\n  ModalReactiveListInjection\n} from './ModalProvider'\nimport { createInjectionKey } from '../../_utils'\n\nexport const modalProviderInjectionKey\n  = createInjectionKey<ModalProviderInjection>('n-modal-provider')\n\nexport const modalApiInjectionKey\n  = createInjectionKey<ModalApiInjection>('n-modal-api')\n\nexport const modalReactiveListInjectionKey\n  = createInjectionKey<ModalReactiveListInjection>('n-modal-reactive-list')\n"
  },
  {
    "path": "src/modal/src/interface.ts",
    "content": "import type { ComponentPublicInstance, Ref } from 'vue'\nimport type { MergedTheme } from '../../_mixins'\nimport type { ModalTheme } from '../styles'\nimport { createInjectionKey } from '../../_utils/vue/create-injection-key'\n\nexport type ModalBodyInjection = Ref<\n  HTMLElement | ComponentPublicInstance | null\n> | null\n\nexport const modalBodyInjectionKey\n  = createInjectionKey<ModalBodyInjection>('n-modal-body')\n\nexport interface ModalProviderInjection {\n  clickedRef: Ref<boolean>\n  clickedPositionRef: Ref<{ x: number, y: number } | null>\n}\n\nexport const modalProviderInjectionKey\n  = createInjectionKey<ModalProviderInjection>('n-modal-provider')\n\nexport interface ModalInjection {\n  getMousePosition: () => {\n    x: number\n    y: number\n  } | null\n  mergedClsPrefixRef: Ref<string>\n  mergedThemeRef: Ref<MergedTheme<ModalTheme>>\n  isMountedRef: Ref<boolean>\n  appearRef: Ref<boolean | undefined>\n  transformOriginRef: Ref<'mouse' | 'center'>\n}\n\nexport const modalInjectionKey = createInjectionKey<ModalInjection>('n-modal')\n\nexport interface ModalDraggableOptions {\n  /**\n   * If set to 'none', the modal's position will not be bounded to the window.\n   */\n  bounds?: 'none'\n}\n"
  },
  {
    "path": "src/modal/src/presetProps.ts",
    "content": "import { keysOf } from '../../_utils'\nimport { cardBaseProps } from '../../card/src/Card'\nimport { dialogProps } from '../../dialog/src/dialogProps'\n\nconst presetProps = {\n  ...cardBaseProps,\n  // put dialog props after since I want the card to unbordered by default\n  ...dialogProps\n}\n\nconst presetPropsKeys = keysOf(presetProps)\n\nexport { presetProps, presetPropsKeys }\n"
  },
  {
    "path": "src/modal/src/styles/index.cssr.ts",
    "content": "import { fadeInScaleUpTransition } from '../../../_styles/transitions/fade-in-scale-up.cssr'\nimport { fadeInTransition } from '../../../_styles/transitions/fade-in.cssr'\nimport { c, cB, cM, } from '../../../_utils/cssr'\nimport { DRAGGABLE_CLASS } from '../composables'\n\n// vars:\n// --n-bezier-ease-out\n// --n-box-shadow\n// --n-color\n// --n-text-color\nexport default c([\n  cB('modal-container', `\n    position: fixed;\n    left: 0;\n    top: 0;\n    height: 0;\n    width: 0;\n    display: flex;\n  `),\n  cB('modal-mask', `\n    position: fixed;\n    left: 0;\n    right: 0;\n    top: 0;\n    bottom: 0;\n    background-color: rgba(0, 0, 0, .4);\n  `, [\n    fadeInTransition({\n      enterDuration: '.25s',\n      leaveDuration: '.25s',\n      enterCubicBezier: 'var(--n-bezier-ease-out)',\n      leaveCubicBezier: 'var(--n-bezier-ease-out)'\n    })\n  ]),\n  cB('modal-body-wrapper', `\n    position: fixed;\n    left: 0;\n    right: 0;\n    top: 0;\n    bottom: 0;\n    overflow: visible;\n  `, [\n    cB('modal-scroll-content', `\n      min-height: 100%;\n      display: flex;\n      position: relative;\n    `),\n    cM('mask-hidden', `pointer-events: none;`, [\n      cB('modal-scroll-content', [\n        c('> *', `\n          pointer-events: all;\n        `)\n      ])\n    ])\n  ]),\n  cB('modal', `\n    position: relative;\n    align-self: center;\n    color: var(--n-text-color);\n    margin: auto;\n    box-shadow: var(--n-box-shadow);\n  `, [\n    fadeInScaleUpTransition({\n      duration: '.25s',\n      enterScale: '.5'\n    }),\n    c(`.${DRAGGABLE_CLASS}`, `\n      cursor: move;\n      user-select: none;\n    `),\n  ])\n])\n"
  },
  {
    "path": "src/modal/styles/dark.ts",
    "content": "import type { ModalTheme } from './light'\nimport { scrollbarDark } from '../../_internal/scrollbar/styles'\nimport { commonDark } from '../../_styles/common'\nimport { cardDark } from '../../card/styles'\nimport { dialogDark } from '../../dialog/styles'\nimport { self } from './light'\n\nconst modalDark: ModalTheme = {\n  name: 'Modal',\n  common: commonDark,\n  peers: {\n    Scrollbar: scrollbarDark,\n    Dialog: dialogDark,\n    Card: cardDark\n  },\n  self\n}\n\nexport default modalDark\n"
  },
  {
    "path": "src/modal/styles/index.ts",
    "content": "export { default as modalDark } from './dark'\nexport { default as modalLight } from './light'\nexport type { ModalTheme, ModalThemeVars } from './light'\n"
  },
  {
    "path": "src/modal/styles/light.ts",
    "content": "import type { ThemeCommonVars } from '../../_styles/common'\nimport { scrollbarLight } from '../../_internal/scrollbar/styles'\nimport { createTheme } from '../../_mixins'\nimport { commonLight } from '../../_styles/common'\nimport { cardLight } from '../../card/styles'\nimport { dialogLight } from '../../dialog/styles'\n\nexport function self(vars: ThemeCommonVars) {\n  const { modalColor, textColor2, boxShadow3 } = vars\n  return {\n    color: modalColor,\n    textColor: textColor2,\n    boxShadow: boxShadow3\n  }\n}\n\nexport type ModalThemeVars = ReturnType<typeof self>\n\nconst modalLight = createTheme({\n  name: 'Modal',\n  common: commonLight,\n  peers: {\n    Scrollbar: scrollbarLight,\n    Dialog: dialogLight,\n    Card: cardLight\n  },\n  self\n})\n\nexport default modalLight\nexport type ModalTheme = typeof modalLight\n"
  },
  {
    "path": "src/modal/tests/Modal.spec.tsx",
    "content": "import type { ModalProps } from '../index'\nimport { mount } from '@vue/test-utils'\nimport { vi } from 'vitest'\nimport { defineComponent, h, nextTick, ref, unref } from 'vue'\nimport { NButton } from '../../button'\nimport { NModal } from '../index'\n\nfunction mountModal({\n  modalProps,\n  show\n}: {\n  modalProps?: ModalProps\n  show?: boolean\n}) {\n  return mount(\n    defineComponent({\n      setup() {\n        const showRef = ref(!!show)\n        const handleUpdateShow = (value: boolean) => {\n          showRef.value = value\n        }\n        return () => [\n          <NButton\n            onClick={() => {\n              showRef.value = true\n            }}\n          >\n            {{ default: () => 'Show' }}\n          </NButton>,\n          <NModal\n            show={unref(showRef)}\n            onUpdateShow={handleUpdateShow}\n            {...modalProps}\n          >\n            {{\n              default: () => <div>test</div>\n            }}\n          </NModal>\n        ]\n      }\n    }),\n    {\n      attachTo: document.body,\n      global: {\n        stubs: {\n          teleport: false,\n          transition: false\n        }\n      }\n    }\n  )\n}\n\ndescribe('n-modal', () => {\n  it('should work with import on demand', () => {\n    mount(NModal)\n  })\n\n  it('should work with `display-directive` prop', async () => {\n    let wrapper = mountModal({})\n    expect(document.querySelector('.n-modal-body-wrapper')).toEqual(null)\n    await wrapper.find('button').trigger('click')\n    expect(document.querySelector('.n-modal-body-wrapper')).not.toEqual(null)\n    const rafSpy = vi\n      .spyOn(window, 'requestAnimationFrame')\n      .mockImplementation((cb: FrameRequestCallback): number => {\n        cb(0)\n        return 0\n      })\n\n    document\n      .querySelector('.n-modal-mask')\n      ?.dispatchEvent(new MouseEvent('click', { bubbles: true }))\n    await nextTick()\n    expect(document.querySelector('.n-modal-body-wrapper')).toEqual(null)\n    wrapper.unmount()\n    wrapper = mountModal({ modalProps: { displayDirective: 'show' } })\n    expect(document.querySelector('.n-modal-body-wrapper')).toEqual(null)\n    await wrapper.find('button').trigger('click')\n    expect(document.querySelector('.n-modal-body-wrapper')).not.toEqual(null)\n\n    document\n      .querySelector('.n-modal-mask')\n      ?.dispatchEvent(new MouseEvent('click', { bubbles: true }))\n    await nextTick()\n    expect(\n      document.querySelector('.n-modal-body-wrapper')?.children.length\n    ).not.toBe(0)\n    expect(\n      document.querySelector('.n-modal-body-wrapper')?.getAttribute('style')\n    ).toContain('display: none')\n\n    wrapper.unmount()\n    rafSpy.mockRestore()\n  })\n\n  it('should work with `preset` prop', async () => {\n    let wrapper = mountModal({ modalProps: { preset: 'card' } })\n    expect(document.querySelector('.n-modal-body-wrapper')).toEqual(null)\n    await wrapper.find('button').trigger('click')\n    expect(document.querySelector('.n-modal-body-wrapper')).not.toEqual(null)\n    expect(document.querySelector('.n-card')).not.toEqual(null)\n    wrapper.unmount()\n\n    wrapper = mountModal({ modalProps: { preset: 'dialog' } })\n    expect(document.querySelector('.n-modal-body-wrapper')).toEqual(null)\n    await wrapper.find('button').trigger('click')\n    expect(document.querySelector('.n-modal-body-wrapper')).not.toEqual(null)\n    expect(document.querySelector('.n-dialog')).not.toEqual(null)\n    wrapper.unmount()\n  })\n})\n"
  },
  {
    "path": "src/modal/tests/server.spec.tsx",
    "content": "import { setup } from '@css-render/vue3-ssr'\nimport { renderToString } from '@vue/server-renderer'\n/**\n * @vitest-environment node\n */\nimport { createSSRApp, h } from 'vue'\nimport { NModal } from '../..'\n\ndescribe('server side rendering', () => {\n  it('works', async () => {\n    const app = createSSRApp(() => <NModal />)\n    setup(app)\n    try {\n      await renderToString(app)\n    }\n    catch (e) {\n      expect(e).not.toBeTruthy()\n    }\n  })\n})\n"
  },
  {
    "path": "src/notification/demos/enUS/basic.demo.vue",
    "content": "<markdown>\n# Basic\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { NAvatar, NButton, useMessage, useNotification } from 'naive-ui'\nimport { h } from 'vue'\n\nconst message = useMessage()\nconst notification = useNotification()\n\nfunction handleClick1() {\n  notification.create({\n    title: 'Wouldn\\'t it be Nice',\n    description: 'From the Beach Boys',\n    content: `Wouldn't it be nice if we were older\nThen we wouldn't have to wait so long\nAnd wouldn't it be nice to live together\nIn the kind of world where we belong\nYou know its gonna make it that much better\nWhen we can say goodnight and stay together\nWouldn't it be nice if we could wake up\nIn the morning when the day is new\nAnd after having spent the day together\nHold each other close the whole night through`,\n    meta: '2019-5-27 15:11',\n    avatar: () =>\n      h(NAvatar, {\n        size: 'small',\n        round: true,\n        src: 'https://07akioni.oss-cn-beijing.aliyuncs.com/07akioni.jpeg'\n      }),\n    onAfterLeave: () => {\n      message.success('Wouldn\\'t it be Nice')\n    }\n  })\n}\n\nfunction handleClick2() {\n  let markAsRead = false\n  const n = notification.create({\n    title: 'Satisfaction',\n    content: `I cant get no satisfaction\nI cant get no satisfaction\nCause I try and I try and I try and I try\nI cant get no, I cant get no`,\n    meta: '2019-5-27 15:11',\n    action: () =>\n      h(\n        NButton,\n        {\n          text: true,\n          type: 'primary',\n          onClick: () => {\n            markAsRead = true\n            n.destroy()\n          }\n        },\n        {\n          default: () => 'Mark as Read'\n        }\n      ),\n    onClose: () => {\n      if (!markAsRead) {\n        message.warning('Please mark as read')\n        return false\n      }\n    }\n  })\n}\n</script>\n\n<template>\n  <n-space>\n    <NButton @click=\"handleClick1\">\n      Wouldn't it be Nice\n    </NButton>\n    <NButton @click=\"handleClick2\">\n      Satisfaction\n    </NButton>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/notification/demos/enUS/change-content.demo.vue",
    "content": "<markdown>\n# Change Content Dynamically\n\nYou can change any parts of notifications existed.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { NotificationReactive } from 'naive-ui'\nimport { NAvatar, useNotification } from 'naive-ui'\nimport { h, ref } from 'vue'\n\nconst notification = useNotification()\nconst nRef = ref<NotificationReactive | null>(null)\n\nfunction open() {\n  nRef.value = notification.create({\n    title: 'Wouldn\\'t it be Nice',\n    description: 'From the Beach Boys',\n    content: `Wouldn't it be nice if we were older\nThen we wouldn't have to wait so long\nAnd wouldn't it be nice to live together\nIn the kind of world where we belong\nYou know its gonna make it that much better\nWhen we can say goodnight and stay together\nWouldn't it be nice if we could wake up\nIn the morning when the day is new\nAnd after having spent the day together\nHold each other close the whole night through`,\n    meta: '2019-5-27 15:11',\n    avatar: () =>\n      h(NAvatar, {\n        size: 'small',\n        round: true,\n        src: 'https://07akioni.oss-cn-beijing.aliyuncs.com/07akioni.jpeg'\n      }),\n    onClose: () => {\n      nRef.value = null\n    }\n  })\n}\n\nfunction change() {\n  if (nRef.value) {\n    nRef.value.content = () =>\n      h('img', {\n        src: 'https://07akioni.oss-cn-beijing.aliyuncs.com/07akioni.jpeg',\n        style: 'width: 100%;'\n      })\n  }\n}\n</script>\n\n<template>\n  <n-space>\n    <n-button @click=\"open\">\n      Open it\n    </n-button>\n    <n-button :disabled=\"!nRef\" @click=\"change\">\n      Change it\n    </n-button>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/notification/demos/enUS/closable.demo.vue",
    "content": "<markdown>\n# Unclosable\n\nYou can make it unclosable.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { useNotification } from 'naive-ui'\n\nconst notification = useNotification()\n\nfunction handleClick() {\n  notification.create({\n    title: 'Close Me if You Can',\n    duration: 2000,\n    closable: false,\n    onAfterLeave: () => {\n      notification.create({\n        title: 'Ha Ha Ha Ha!',\n        duration: 2000,\n        closable: false,\n        onAfterLeave: () => {\n          notification.create({\n            title: 'No, You Can\\'t',\n            duration: 2000,\n            closable: false\n          })\n        }\n      })\n    }\n  })\n}\n</script>\n\n<template>\n  <n-button @click=\"handleClick\">\n    Unclosable\n  </n-button>\n</template>\n"
  },
  {
    "path": "src/notification/demos/enUS/duration.demo.vue",
    "content": "<markdown>\n# Duration\n\nAuto close.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { useNotification } from 'naive-ui'\n\nconst notification = useNotification()\n\nfunction handleClick() {\n  let count = 10\n  const n = notification.create({\n    title: 'What is Pingshan Road + rain ?',\n    content: `You have ${count} seconds to answer the question.`,\n    duration: 10000,\n    closable: false,\n    onAfterEnter: () => {\n      const minusCount = () => {\n        count--\n        n.content = `You have ${count} seconds to answer the question.`\n        if (count > 0) {\n          window.setTimeout(minusCount, 1000)\n        }\n      }\n      window.setTimeout(minusCount, 1000)\n    },\n    onAfterLeave: () => {\n      notification.create({\n        title: 'The Answer is Pingshan River!',\n        content: 'Oops, that is not even an anti-humor.',\n        duration: 10000\n      })\n    }\n  })\n}\n</script>\n\n<template>\n  <n-button @click=\"handleClick\">\n    Duration: 10000\n  </n-button>\n</template>\n"
  },
  {
    "path": "src/notification/demos/enUS/index.demo-entry.md",
    "content": "# Notification\n\nIf something is to be telled to somebody.\n\nNotification component is always with low piority so I can make a lot of useless animations on it.\n\n<n-space vertical size=\"large\">\n<n-alert title=\"Prerequisite\" type=\"warning\" :bordered=\"false\">\n  If you want to use notification, you need to wrap the component where you call related methods inside <n-text code>n-notification-provider</n-text> and use <n-text code>useNotification</n-text> to get the API.\n</n-alert>\n\nFor example:\n\n```html\n<!-- App.vue -->\n<n-notification-provider>\n  <content />\n</n-notification-provider>\n```\n\n```js\nimport { useNotification } from 'naive-ui'\nimport { defineComponent } from 'vue'\n\n// content\nexport default defineComponent({\n  setup() {\n    const notification = useNotification()\n    return {\n      warning() {\n        notification.warning({\n          content: '...'\n        })\n      }\n    }\n  }\n})\n```\n\n</n-space>\n\n## Demos\n\n```demo\nbasic.vue\ntype.vue\nchange-content.vue\nscrollable.vue\nclosable.vue\nduration.vue\nmax.vue\nplacement.vue\n```\n\n## API\n\n### NotificationProvider Props\n\n| Name | Type | Default | Description | Version |\n| --- | --- | --- | --- | --- |\n| container-class | `string` | `undefined` | Class of notification container. | 2.36.0 |\n| container-style | `string \\| Object` | `undefined` | Style of notification container. | 2.25.0 |\n| placement | `'top' \\| 'bottom' \\|'top-right' \\| 'top-left' \\| 'bottom-left' \\| 'bottom-right'` | `'top-right'` | Placement of all notifications. | `'top' \\| 'bottom'` 2.29.0 |\n| max | `number` | `undefined` | Limit the number of notifications to display. |  |\n| scrollable | `boolean` | `true` | Whether notification can be scroll. Unavailable when `placement` equals `'top'` or `'bottom'`. |  |\n| to | `string \\| HTMLElement` | `'body'` | Container node of notification container. |  |\n\n### notification Injection Methods\n\n| Name | Type | Description |\n| --- | --- | --- |\n| create | `(option: NotificationOption) => NotificationReactive` | Create a notification. |\n| destroyAll | `() => void` | Destroy all popup notifications. |\n| error | `(option: NotificationOption) => NotificationReactive` | Use `error` type notification. |\n| info | `(option: NotificationOption) => NotificationReactive` | Use `info` type notification. |\n| success | `(option: NotificationOption) => NotificationReactive` | Use `success` type notification. |\n| warning | `(option: NotificationOption) => NotificationReactive` | Use `warning` type notification. |\n\n### NotificationOption Properties\n\n| Name | Type | Default | Description | Version |\n| --- | --- | --- | --- | --- |\n| action | `string \\| (() => VNodeChild)` | `undefined` | Content of the operation area,, can be a render function. |  |\n| avatar | `() => VNodeChild` | `undefined` | Content of the `avatar`. |  |\n| closable | `boolean` | `true` | Whether to show close icon. |  |\n| content | `string \\| (() => VNodeChild)` | `undefined` | Content, can be a render function. |  |\n| description | `string \\| (() => VNodeChild)` | `undefined` | Content of the `description`, can be a render function. |  |\n| duration | `number` | `undefined` | If not set, it won't automatically close. Unit is millisecond. |  |\n| keepAliveOnHover | `boolean` | `false` | Whether to keep the notification when mouse hover. | 2.32.0 |\n| meta | `string \\| (() => VNodeChild)` | `undefined` | Content of the `meta`, can be a render function. |  |\n| title | `string \\| (() => VNodeChild)` | `undefined` | Content of the `title`, can be a render function. |  |\n| onAfterEnter | `Function` | `undefined` | Callback triggered after Transition's enter animation executed. |  |\n| onAfterLeave | `Function` | `undefined` | Callback triggered after Transition's leave animation executed. |  |\n| onClose | `() => boolean \\| Promise<boolean>` | `undefined` | The callback of notification closing. Returning `false`, promise resolve `false` or promise reject will cancel this closing. |  |\n| onLeave | `Function` | `undefined` | Callback triggered when Transition's leave animation executed. |  |\n\n### NotificationReactive API\n\n#### NotificationReactive Properties\n\nProperties of NotificationReactive can be dynamically changed.\n\n| Name | Type | Description |\n| --- | --- | --- |\n| action | `string \\| (() => VNodeChild)` | Content of the operation area,, can be a render function. |\n| avatar | `() => VNodeChild` | Content of the `avatar`, can be a render function. |\n| closable | `boolean` | Whether to show close icon. |\n| content | `string \\| (() => VNodeChild)` | Content, can be a render function. |\n| description | `string \\| (() => VNodeChild)` | Content of the `description`, can be a render function. |\n| duration | `number` | If not set, it won't automatically close. Unit is millisecond. |\n| meta | `string \\| (() => VNodeChild)` | Content of the `meta`, can be a render function. |\n| title | `string \\| (() => VNodeChild)` | Content of the `title`, can be a render function. |\n| onAfterEnter | `Function` | Callback triggered after Transition's enter animation executed. |\n| onAfterLeave | `Function` | Callback triggered after Transition's leave animation executed. |\n| onClose | `() => boolean \\| Promise<boolean>` | The callback of notification closing. Returning `false`, promise resolve `false` or promise reject will cancel this closing. |\n| onLeave | `Function` | Callback triggered when Transition's leave animation executed. |\n\n#### NotificationReactive Methods\n\n| Name    | Type | Description               |\n| ------- | ---- | ------------------------- |\n| destroy | `()` | Destroy the notification. |\n"
  },
  {
    "path": "src/notification/demos/enUS/max.demo.vue",
    "content": "<markdown>\n# Max\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { NButton, useNotification } from 'naive-ui'\nimport { h, ref } from 'vue'\n\nfunction NotificationButton() {\n  const notification = useNotification()\n  const index = ref(0)\n\n  return h(\n    NButton,\n    {\n      onClick: () => {\n        index.value++\n        notification.info({\n          title: `Notification index: ${index.value}`,\n          content: 'You can limit the index of notifications'\n        })\n      }\n    },\n    { default: () => 'Max notification count: 3' }\n  )\n}\n</script>\n\n<template>\n  <n-notification-provider :max=\"3\">\n    <NotificationButton />\n  </n-notification-provider>\n</template>\n"
  },
  {
    "path": "src/notification/demos/enUS/placement.demo.vue",
    "content": "<markdown>\n# Placement\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { NotificationPlacement } from 'naive-ui'\nimport { NButton, NSpace, useNotification } from 'naive-ui'\nimport { h, ref } from 'vue'\n\nconst placementRef = ref<NotificationPlacement>('top-right')\n\nfunction handlePlacementChange(val: NotificationPlacement) {\n  placementRef.value = val\n}\n\nfunction PlacementButtons(props: {\n  onPlacementChange?: (placement: NotificationPlacement) => void\n}) {\n  const notification = useNotification()\n  const placementList = [\n    { placement: 'top-left' as const, text: 'Top left' },\n    { placement: 'top-right' as const, text: 'Top right' },\n    { placement: 'bottom-left' as const, text: 'Bottom left' },\n    { placement: 'bottom-right' as const, text: 'Bottom right' },\n    { placement: 'bottom' as const, text: 'Bottom' },\n    { placement: 'top' as const, text: 'Top' }\n  ]\n\n  return h(NSpace, null, {\n    default: () =>\n      placementList.map(item =>\n        h(\n          NButton,\n          {\n            onClick: () => {\n              props.onPlacementChange?.(item.placement)\n              notification.info({\n                title: item.placement,\n                content: 'You can change the placement'\n              })\n            }\n          },\n          { default: () => item.text }\n        )\n      )\n  })\n}\n</script>\n\n<template>\n  <n-notification-provider :placement=\"placementRef\">\n    <PlacementButtons :on-placement-change=\"handlePlacementChange\" />\n  </n-notification-provider>\n</template>\n"
  },
  {
    "path": "src/notification/demos/enUS/scrollable.demo.vue",
    "content": "<markdown>\n# Scrollable\n\nChange the property will cause all existing notifications to be cleaned, so please make sure you change this property at proper time.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { useNotification } from 'naive-ui'\n\nconst notification = useNotification()\n\nfunction handleClick() {\n  ;[1, 2, 3, 4, 5].forEach(() =>\n    notification.create({\n      title: 'Many Notifications',\n      content: `Try to scroll\nTry to scroll\nTry to scroll\nTry to scroll\nTry to scroll\nTry to scroll\nTry to scroll`\n    })\n  )\n}\n</script>\n\n<template>\n  <n-button @click=\"handleClick\">\n    See how it scrolls\n  </n-button>\n</template>\n"
  },
  {
    "path": "src/notification/demos/enUS/type.demo.vue",
    "content": "<markdown>\n# Type\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { NotificationType } from 'naive-ui'\nimport { useNotification } from 'naive-ui'\n\nconst notification = useNotification()\n\nfunction notify(type: NotificationType) {\n  notification[type]({\n    content: 'What to say?',\n    meta: 'I don\\'t know',\n    duration: 2500,\n    keepAliveOnHover: true\n  })\n}\n</script>\n\n<template>\n  <n-space>\n    <n-button @click=\"notify('info')\">\n      Info\n    </n-button>\n    <n-button @click=\"notify('success')\">\n      Success\n    </n-button>\n    <n-button @click=\"notify('warning')\">\n      Warning\n    </n-button>\n    <n-button @click=\"notify('error')\">\n      Error\n    </n-button>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/notification/demos/zhCN/basic.demo.vue",
    "content": "<markdown>\n# 基础用法\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { NAvatar, NButton, useMessage, useNotification } from 'naive-ui'\nimport { h } from 'vue'\n\nconst message = useMessage()\nconst notification = useNotification()\n\nfunction handleClick1() {\n  notification.create({\n    title: 'Wouldn\\'t it be Nice',\n    description: 'From the Beach Boys',\n    content: `Wouldn't it be nice if we were older\nThen we wouldn't have to wait so long\nAnd wouldn't it be nice to live together\nIn the kind of world where we belong\nYou know its gonna make it that much better\nWhen we can say goodnight and stay together\nWouldn't it be nice if we could wake up\nIn the morning when the day is new\nAnd after having spent the day together\nHold each other close the whole night through`,\n    meta: '2019-5-27 15:11',\n    avatar: () =>\n      h(NAvatar, {\n        size: 'small',\n        round: true,\n        src: 'https://07akioni.oss-cn-beijing.aliyuncs.com/07akioni.jpeg'\n      }),\n    onAfterLeave: () => {\n      message.success('Wouldn\\'t it be Nice')\n    }\n  })\n}\n\nfunction handleClick2() {\n  let markAsRead = false\n  const n = notification.create({\n    title: 'Satisfaction',\n    content: `I cant get no satisfaction\nI cant get no satisfaction\nCause I try and I try and I try and I try\nI cant get no, I cant get no`,\n    meta: '2019-5-27 15:11',\n    action: () =>\n      h(\n        NButton,\n        {\n          text: true,\n          type: 'primary',\n          onClick: () => {\n            markAsRead = true\n            n.destroy()\n          }\n        },\n        {\n          default: () => '已读'\n        }\n      ),\n    onClose: () => {\n      if (!markAsRead) {\n        message.warning('请设为已读')\n        return false\n      }\n    }\n  })\n}\n</script>\n\n<template>\n  <n-space>\n    <NButton @click=\"handleClick1\">\n      Wouldn't it be Nice\n    </NButton>\n    <NButton @click=\"handleClick2\">\n      Satisfaction\n    </NButton>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/notification/demos/zhCN/change-content.demo.vue",
    "content": "<markdown>\n# 动态修改内容\n\n你可以修改已经存在的通知\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { NotificationReactive } from 'naive-ui'\nimport { NAvatar, useNotification } from 'naive-ui'\nimport { h, ref } from 'vue'\n\nconst notification = useNotification()\nconst nRef = ref<NotificationReactive | null>(null)\n\nfunction open() {\n  nRef.value = notification.create({\n    title: 'Wouldn\\'t it be Nice',\n    description: 'From the Beach Boys',\n    content: `Wouldn't it be nice if we were older\nThen we wouldn't have to wait so long\nAnd wouldn't it be nice to live together\nIn the kind of world where we belong\nYou know its gonna make it that much better\nWhen we can say goodnight and stay together\nWouldn't it be nice if we could wake up\nIn the morning when the day is new\nAnd after having spent the day together\nHold each other close the whole night through`,\n    meta: '2019-5-27 15:11',\n    avatar: () =>\n      h(NAvatar, {\n        size: 'small',\n        round: true,\n        src: 'https://07akioni.oss-cn-beijing.aliyuncs.com/07akioni.jpeg'\n      }),\n    onClose: () => {\n      nRef.value = null\n    }\n  })\n}\n\nfunction change() {\n  if (nRef.value) {\n    nRef.value.content = () =>\n      h('img', {\n        src: 'https://07akioni.oss-cn-beijing.aliyuncs.com/07akioni.jpeg',\n        style: 'width: 100%;'\n      })\n  }\n}\n</script>\n\n<template>\n  <n-space>\n    <n-button @click=\"open\">\n      打开它\n    </n-button>\n    <n-button :disabled=\"!nRef\" @click=\"change\">\n      改它\n    </n-button>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/notification/demos/zhCN/closable.demo.vue",
    "content": "<markdown>\n# 不可关闭\n\n通知可以不能被关闭\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { useNotification } from 'naive-ui'\n\nconst notification = useNotification()\n\nfunction handleClick() {\n  notification.create({\n    title: 'Close Me if You Can',\n    duration: 2000,\n    closable: false,\n    onAfterLeave: () => {\n      notification.create({\n        title: 'Ha Ha Ha Ha!',\n        duration: 2000,\n        closable: false,\n        onAfterLeave: () => {\n          notification.create({\n            title: 'No, You Can\\'t',\n            duration: 2000,\n            closable: false\n          })\n        }\n      })\n    }\n  })\n}\n</script>\n\n<template>\n  <n-button @click=\"handleClick\">\n    不能关闭\n  </n-button>\n</template>\n"
  },
  {
    "path": "src/notification/demos/zhCN/duration.demo.vue",
    "content": "<markdown>\n# 持续时间\n\n自动关闭。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { useNotification } from 'naive-ui'\n\nconst notification = useNotification()\n\nfunction handleClick() {\n  let count = 10\n  const n = notification.create({\n    title: '平山道 + 雨 = 什么？',\n    content: `你有 ${count} 秒来回答这个问题`,\n    duration: 10000,\n    closable: false,\n    onAfterEnter: () => {\n      const minusCount = () => {\n        count--\n        n.content = `你有 ${count} 秒来回答这个问题`\n        if (count > 0) {\n          window.setTimeout(minusCount, 1000)\n        }\n      }\n      window.setTimeout(minusCount, 1000)\n    },\n    onAfterLeave: () => {\n      notification.create({\n        title: '答案是平山河',\n        content: '这其实连个冷笑话都算不上',\n        duration: 10000\n      })\n    }\n  })\n}\n</script>\n\n<template>\n  <n-button @click=\"handleClick\">\n    持续时间 10000ms\n  </n-button>\n</template>\n"
  },
  {
    "path": "src/notification/demos/zhCN/error-debug.demo.vue",
    "content": "<markdown>\n# Error debug\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { useNotification } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst notification = useNotification()\n// const message = useMessage()\nconsole.log(notification)\n\nconst urlToAnalyse = ref()\n\nfunction analyzeWebsite() {\n  // fetch website content from url\n  // return content\n  setTimeout(() => {\n    // message.error('oooo')\n    notification.error({\n      content:\n        'Website doesn\\'t allow to be fetched => Blocked by CORS policy: \\'No Access-Control-Allow-Origin\\' header found on that website.'\n    })\n  }, 500)\n}\n</script>\n\n<template>\n  <n-card>\n    <n-input\n      v-model:value=\"urlToAnalyse\"\n      placeholder=\"URL website to analyse\"\n    />\n    <n-button class=\"w-100\" @click=\"analyzeWebsite()\">\n      Analyse\n    </n-button>\n  </n-card>\n</template>\n"
  },
  {
    "path": "src/notification/demos/zhCN/index.demo-entry.md",
    "content": "# 通知 Notification\n\n通知某人。\n\n像是通知组件这种东西优先级不那么高，所以我可以弄一堆没什么用的动画上去。\n\n<n-space vertical size=\"large\">\n<n-alert title=\"使用前提\" type=\"warning\" :bordered=\"false\">\n  如果你想使用通知，你需要把调用其方法的组件放在 <n-text code>n-notification-provider</n-text> 内部并且使用 <n-text code>useNotification</n-text> 来获取 API。\n</n-alert>\n例如：\n\n```html\n<!-- App.vue -->\n<n-notification-provider>\n  <content />\n</n-notification-provider>\n```\n\n```js\nimport { useNotification } from 'naive-ui'\nimport { defineComponent } from 'vue'\n\n// content\nexport default defineComponent({\n  setup() {\n    const notification = useNotification()\n    return {\n      warning() {\n        notification.warning({\n          content: '...'\n        })\n      }\n    }\n  }\n})\n```\n\n</n-space>\n\n## 演示\n\n```demo\nbasic.vue\ntype.vue\nchange-content.vue\nscrollable.vue\nclosable.vue\nduration.vue\nmax.vue\nplacement.vue\nerror-debug.vue\nrtl-debug.vue\n```\n\n## API\n\n### NotificationProvider Props\n\n| 名称 | 类型 | 默认值 | 说明 | 版本 |\n| --- | --- | --- | --- | --- |\n| container-class | `string` | `undefined` | 容器的类名 | 2.36.0 |\n| container-style | `string \\| Object` | `undefined` | 容器的样式 | 2.25.0 |\n| max | `number` | `undefined` | 限制通知框显示的个数 |  |\n| placement | `'top' \\| 'bottom' \\| 'top-right' \\| 'top-left' \\| 'bottom-left' \\| 'bottom-right'` | `top-right` | 所有通知框显示的位置 | `'top' \\| 'bottom'` 2.29.0 |\n| scrollable | `boolean` | `true` | 通知是否可滚动，对于 `placement` 为 `'top'` 和 `'bottom'` 不生效 |  |\n| to | `string \\| HTMLElement` | `'body'` | `Notification` 容器节点的位置 |  |\n\n### notification Injection Methods\n\n| 名称 | 类型 | 说明 |\n| --- | --- | --- |\n| create | `(option: NotificationOption) => NotificationReactive` | 创建通知框 |\n| destroyAll | `() => void` | 销毁所有弹出的通知框 |\n| error | `(option: NotificationOption) => NotificationReactive` | 调用 `error` 类型的通知框 |\n| info | `(option: NotificationOption) => NotificationReactive` | 调用 `info` 类型的通知框 |\n| success | `(option: NotificationOption) => NotificationReactive` | 调用 `success` 类型的通知框 |\n| warning | `(option: NotificationOption) => NotificationReactive` | 调用 `warning` 类型的通知框 |\n\n### NotificationOption Properties\n\n| 名称 | 类型 | 默认值 | 说明 | 版本 |\n| --- | --- | --- | --- | --- |\n| action | `string \\| (() => VNodeChild)` | `undefined` | 操作区域的内容,可以是 render 函数 |  |\n| avatar | `() => VNodeChild` | `undefined` | 头像区域的内容 |  |\n| closable | `boolean` | `true` | 是否显示 close 图标 |  |\n| content | `string \\| (() => VNodeChild)` | `undefined` | 通知框内容，可以是 render 函数 |  |\n| description | `string \\| (() => VNodeChild)` | `undefined` | 描述的内容，可以是 render 函数 |  |\n| duration | `number` | `undefined` | 如果没有设定则不会自动关闭，单位毫秒 |  |\n| keepAliveOnHover | `boolean` | `false` | 当鼠标移入时是否保持通知框显示 | 2.32.0 |\n| meta | `string \\| (() => VNodeChild)` | `undefined` | `meta` 信息，可以是 render 函数 |\n| title | `string \\| (() => VNodeChild)` | `undefined` | `title` 信息，可以是 render 函数 |\n| onAfterEnter | `Function` | `undefined` | 过渡动画进入执行完后执行的回调 |  |\n| onAfterLeave | `Function` | `undefined` | 过渡动画离开执行完后执行的回调 |  |\n| onClose | `() => boolean \\| Promise<boolean>` | `undefined` | 关闭通知的回调，返回 `false`、Promise resolve `false` 或者 reject 会取消这次关闭 |  |\n| onLeave | `Function` | `undefined` | 过渡动画离开时执行的回调 |  |\n\n### NotificationReactive API\n\n#### NotificationReactive Properties\n\nNotificationReactive 实例的属性可以被动态改变。\n\n| 名称 | 类型 | 说明 |\n| --- | --- | --- |\n| action | `string \\| (() => VNodeChild)` | 操作区域的内容,可以是 render 函数 |\n| avatar | `() => VNodeChild` | 头像区域的内容，可以是 render 函数 |\n| closable | `boolean` | 是否显示 close 图标 |\n| content | `string \\| (() => VNodeChild)` | 通知框内容，可以是 render 函数 |\n| description | `string \\| (() => VNodeChild)` | 描述的内容，可以是 render 函数 |\n| duration | `number` | 如果没有设定则不会自动关闭，单位毫秒 |\n| meta | `string \\| (() => VNodeChild)` | `meta` 信息，可以是 render 函数 |\n| title | `string \\| (() => VNodeChild)` | `title` 信息，可以是 render 函数 |\n| onAfterEnter | `Function` | 过渡动画进入执行完后执行的回调 |\n| onAfterLeave | `Function` | 过渡动画离开进入执行完后执行的回调 |\n| onClose | `() => boolean \\| Promise<boolean>` | 关闭通知的回调。返回 `false`、Promise resolve `false` 或者 reject 会取消这次关闭 |\n| onLeave | `Function` | 过渡动画离开动画执行时的回调 |\n\n#### NotificationReactive Methods\n\n| 名称    | 类型 | 说明       |\n| ------- | ---- | ---------- |\n| destroy | `()` | 销毁该通知 |\n"
  },
  {
    "path": "src/notification/demos/zhCN/max.demo.vue",
    "content": "<markdown>\n# 限制数量\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { NButton, useNotification } from 'naive-ui'\nimport { h, ref } from 'vue'\n\nfunction NotificationButton() {\n  const notification = useNotification()\n  const index = ref(0)\n\n  return h(\n    NButton,\n    {\n      onClick: () => {\n        index.value++\n        notification.info({\n          title: `通知框序号: ${index.value}`,\n          content: '你可以限制通知框的数量'\n        })\n      }\n    },\n    { default: () => '最多允许 3 个通知' }\n  )\n}\n</script>\n\n<template>\n  <n-notification-provider :max=\"3\">\n    <NotificationButton />\n  </n-notification-provider>\n</template>\n"
  },
  {
    "path": "src/notification/demos/zhCN/placement.demo.vue",
    "content": "<markdown>\n# 弹出位置\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { NotificationPlacement } from 'naive-ui'\nimport { NButton, NSpace, useNotification } from 'naive-ui'\nimport { h, ref } from 'vue'\n\nconst placementRef = ref<NotificationPlacement>('top-right')\n\nfunction handlePlacementChange(val: NotificationPlacement) {\n  placementRef.value = val\n}\n\nfunction PlacementButtons(props: {\n  onPlacementChange?: (placement: NotificationPlacement) => void\n}) {\n  const notification = useNotification()\n  const placementList = [\n    { placement: 'top-left' as const, text: '左上' },\n    { placement: 'top-right' as const, text: '右上' },\n    { placement: 'bottom-left' as const, text: '左下' },\n    { placement: 'bottom-right' as const, text: '右下' },\n    { placement: 'bottom' as const, text: '下' },\n    { placement: 'top' as const, text: '上' }\n  ]\n\n  return h(NSpace, null, {\n    default: () =>\n      placementList.map(item =>\n        h(\n          NButton,\n          {\n            onClick: () => {\n              props.onPlacementChange?.(item.placement)\n              notification.info({\n                title: item.placement,\n                content: 'You can change the placement'\n              })\n            }\n          },\n          { default: () => item.text }\n        )\n      )\n  })\n}\n</script>\n\n<template>\n  <n-notification-provider :placement=\"placementRef\">\n    <PlacementButtons :on-placement-change=\"handlePlacementChange\" />\n  </n-notification-provider>\n</template>\n"
  },
  {
    "path": "src/notification/demos/zhCN/rtl-debug.demo.vue",
    "content": "<markdown>\n# Rtl Debug\n</markdown>\n\n<script lang=\"ts\" setup>\nimport {\n  NAvatar,\n  NButton,\n  unstableNotificationRtl,\n  useNotification\n} from 'naive-ui'\nimport { h, ref } from 'vue'\n\nconst rtlEnabled = ref(true)\nconst rtlStyles = [unstableNotificationRtl]\n\nfunction NotificationButton() {\n  const notification = useNotification()\n\n  return h(\n    NButton,\n    {\n      onClick: () => {\n        notification.create({\n          title: 'Rtl Notification',\n          content: 'No avatar and icon'\n        })\n        notification.info({\n          title: 'Rtl Notification',\n          content: 'Info icon'\n        })\n        notification.create({\n          title: 'Rtl Notification',\n          description: 'Whit avatar and description',\n          content: `Wouldn't it be nice if we were older\nThen we wouldn't have to wait so long\nAnd wouldn't it be nice to live together\nIn the kind of world where we belong\nYou know its gonna make it that much better\nWhen we can say goodnight and stay together\nWouldn't it be nice if we could wake up\nIn the morning when the day is new\nAnd after having spent the day together\nHold each other close the whole night through`,\n          meta: '2019-5-27 15:11',\n          avatar: () =>\n            h(NAvatar, {\n              size: 'small',\n              round: true,\n              src: 'https://07akioni.oss-cn-beijing.aliyuncs.com/07akioni.jpeg'\n            })\n        })\n        const n = notification.create({\n          title: 'Rtl Notification + Button',\n          content: `I cant get no satisfaction\nI cant get no satisfaction\nCause I try and I try and I try and I try\nI cant get no, I cant get no`,\n          meta: '2019-5-27 15:11',\n          action: () =>\n            h(\n              NButton,\n              {\n                text: true,\n                type: 'primary',\n                onClick: () => {\n                  n.destroy()\n                }\n              },\n              {\n                default: () => 'close'\n              }\n            )\n        })\n      }\n    },\n    { default: () => 'Show some notification' }\n  )\n}\n</script>\n\n<template>\n  <n-space><n-switch v-model:value=\"rtlEnabled\" />Rtl</n-space>\n  <n-space>\n    <n-config-provider :rtl=\"rtlEnabled ? rtlStyles : undefined\">\n      <n-notification-provider>\n        <NotificationButton />\n      </n-notification-provider>\n    </n-config-provider>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/notification/demos/zhCN/scrollable.demo.vue",
    "content": "<markdown>\n# 可滚动\n\n改变这个属性会导致已经存在全部通知被清空，确保你在合适的时机修改了这个属性。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { useNotification } from 'naive-ui'\n\nconst notification = useNotification()\n\nfunction handleClick() {\n  ;[1, 2, 3, 4, 5].forEach(() =>\n    notification.create({\n      title: '很多个通知',\n      content: `试着滚起来\n试着滚起来\n试着滚起来\n试着滚起来\n试着滚起来\n试着滚起来\n试着滚起来`\n    })\n  )\n}\n</script>\n\n<template>\n  <n-button @click=\"handleClick\">\n    看看这个东西怎么滚动\n  </n-button>\n</template>\n"
  },
  {
    "path": "src/notification/demos/zhCN/type.demo.vue",
    "content": "<markdown>\n# 类型\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { NotificationType } from 'naive-ui'\nimport { useNotification } from 'naive-ui'\n\nconst notification = useNotification()\n\nfunction notify(type: NotificationType) {\n  notification[type]({\n    content: '说点啥呢',\n    meta: '想不出来',\n    duration: 2500,\n    keepAliveOnHover: true\n  })\n}\n</script>\n\n<template>\n  <n-space>\n    <n-button @click=\"notify('info')\">\n      信息\n    </n-button>\n    <n-button @click=\"notify('success')\">\n      成功\n    </n-button>\n    <n-button @click=\"notify('warning')\">\n      警告\n    </n-button>\n    <n-button @click=\"notify('error')\">\n      错误\n    </n-button>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/notification/index.ts",
    "content": "export type { NotificationOptions } from './src/NotificationEnvironment'\nexport {\n  default as NNotificationProvider,\n  notificationProviderProps\n} from './src/NotificationProvider'\nexport type {\n  NotificationApiInjection as NotificationApi,\n  NotificationPlacement,\n  NotificationProviderInst,\n  NotificationProviderProps,\n  NotificationReactive,\n  NotificationType\n} from './src/NotificationProvider'\nexport { useNotification } from './src/use-notification'\n"
  },
  {
    "path": "src/notification/src/Notification.tsx",
    "content": "import type { CSSProperties, PropType, VNodeChild } from 'vue'\nimport { getPadding } from 'seemly'\nimport { computed, defineComponent, h, inject } from 'vue'\nimport { NBaseClose, NBaseIcon } from '../../_internal'\nimport {\n  ErrorIcon,\n  InfoIcon,\n  SuccessIcon,\n  WarningIcon\n} from '../../_internal/icons'\nimport { useConfig, useRtl, useThemeClass } from '../../_mixins'\nimport { createKey, keysOf, render } from '../../_utils'\nimport { notificationProviderInjectionKey } from './context'\n\nconst iconRenderMap = {\n  info: () => <InfoIcon />,\n  success: () => <SuccessIcon />,\n  warning: () => <WarningIcon />,\n  error: () => <ErrorIcon />,\n  default: () => null\n}\n\nexport const notificationProps = {\n  closable: {\n    type: Boolean,\n    default: true\n  },\n  type: {\n    type: String as PropType<\n      'info' | 'success' | 'warning' | 'error' | 'default'\n    >,\n    default: 'default'\n  },\n  avatar: Function as PropType<() => VNodeChild>,\n  title: [String, Function] as PropType<string | (() => VNodeChild)>,\n  description: [String, Function] as PropType<string | (() => VNodeChild)>,\n  content: [String, Function] as PropType<string | (() => VNodeChild)>,\n  meta: [String, Function] as PropType<string | (() => VNodeChild)>,\n  action: [String, Function] as PropType<string | (() => VNodeChild)>,\n  onClose: {\n    type: Function as PropType<() => void>,\n    required: true\n  },\n  keepAliveOnHover: Boolean,\n  onMouseenter: Function as PropType<(e: MouseEvent) => void>,\n  onMouseleave: Function as PropType<(e: MouseEvent) => void>\n} as const\n\nexport const notificationPropKeys = keysOf(notificationProps)\n\nexport const Notification = defineComponent({\n  name: 'Notification',\n  props: notificationProps,\n  setup(props) {\n    const {\n      mergedClsPrefixRef,\n      mergedThemeRef,\n      props: providerProps\n    } = inject(notificationProviderInjectionKey)!\n    const { inlineThemeDisabled, mergedRtlRef } = useConfig()\n    const rtlEnabledRef = useRtl(\n      'Notification',\n      mergedRtlRef,\n      mergedClsPrefixRef\n    )\n    const cssVarsRef = computed(() => {\n      const { type } = props\n      const {\n        self: {\n          color,\n          textColor,\n          closeIconColor,\n          closeIconColorHover,\n          closeIconColorPressed,\n          headerTextColor,\n          descriptionTextColor,\n          actionTextColor,\n          borderRadius,\n          headerFontWeight,\n          boxShadow,\n          lineHeight,\n          fontSize,\n          closeMargin,\n          closeSize,\n          width,\n          padding,\n          closeIconSize,\n          closeBorderRadius,\n          closeColorHover,\n          closeColorPressed,\n          titleFontSize,\n          metaFontSize,\n          descriptionFontSize,\n          [createKey('iconColor', type)]: iconColor\n        },\n        common: { cubicBezierEaseOut, cubicBezierEaseIn, cubicBezierEaseInOut }\n      } = mergedThemeRef.value\n      const { left, right, top, bottom } = getPadding(padding)\n      return {\n        '--n-color': color,\n        '--n-font-size': fontSize,\n        '--n-text-color': textColor,\n        '--n-description-text-color': descriptionTextColor,\n        '--n-action-text-color': actionTextColor,\n        '--n-title-text-color': headerTextColor,\n        '--n-title-font-weight': headerFontWeight,\n        '--n-bezier': cubicBezierEaseInOut,\n        '--n-bezier-ease-out': cubicBezierEaseOut,\n        '--n-bezier-ease-in': cubicBezierEaseIn,\n        '--n-border-radius': borderRadius,\n        '--n-box-shadow': boxShadow,\n        '--n-close-border-radius': closeBorderRadius,\n        '--n-close-color-hover': closeColorHover,\n        '--n-close-color-pressed': closeColorPressed,\n        '--n-close-icon-color': closeIconColor,\n        '--n-close-icon-color-hover': closeIconColorHover,\n        '--n-close-icon-color-pressed': closeIconColorPressed,\n        '--n-line-height': lineHeight,\n        '--n-icon-color': iconColor,\n        '--n-close-margin': closeMargin,\n        '--n-close-size': closeSize,\n        '--n-close-icon-size': closeIconSize,\n        '--n-width': width,\n        '--n-padding-left': left,\n        '--n-padding-right': right,\n        '--n-padding-top': top,\n        '--n-padding-bottom': bottom,\n        '--n-title-font-size': titleFontSize,\n        '--n-meta-font-size': metaFontSize,\n        '--n-description-font-size': descriptionFontSize\n      }\n    })\n    const themeClassHandle = inlineThemeDisabled\n      ? useThemeClass(\n          'notification',\n          computed(() => props.type[0]),\n          cssVarsRef,\n          providerProps\n        )\n      : undefined\n    return {\n      mergedClsPrefix: mergedClsPrefixRef,\n      showAvatar: computed(() => {\n        return props.avatar || props.type !== 'default'\n      }),\n      handleCloseClick() {\n        props.onClose()\n      },\n      rtlEnabled: rtlEnabledRef,\n      cssVars: inlineThemeDisabled ? undefined : cssVarsRef,\n      themeClass: themeClassHandle?.themeClass,\n      onRender: themeClassHandle?.onRender\n    }\n  },\n  render() {\n    const { mergedClsPrefix } = this\n    this.onRender?.()\n    return (\n      <div\n        class={[`${mergedClsPrefix}-notification-wrapper`, this.themeClass]}\n        onMouseenter={this.onMouseenter}\n        onMouseleave={this.onMouseleave}\n        style={this.cssVars as CSSProperties}\n      >\n        <div\n          class={[\n            `${mergedClsPrefix}-notification`,\n            this.rtlEnabled && `${mergedClsPrefix}-notification--rtl`,\n            this.themeClass,\n            {\n              [`${mergedClsPrefix}-notification--closable`]: this.closable,\n              [`${mergedClsPrefix}-notification--show-avatar`]: this.showAvatar\n            }\n          ]}\n          style={this.cssVars as CSSProperties}\n        >\n          {this.showAvatar ? (\n            <div class={`${mergedClsPrefix}-notification__avatar`}>\n              {this.avatar ? (\n                render(this.avatar)\n              ) : this.type !== 'default' ? (\n                <NBaseIcon clsPrefix={mergedClsPrefix}>\n                  {{ default: () => iconRenderMap[this.type]() }}\n                </NBaseIcon>\n              ) : null}\n            </div>\n          ) : null}\n          {this.closable ? (\n            <NBaseClose\n              clsPrefix={mergedClsPrefix}\n              class={`${mergedClsPrefix}-notification__close`}\n              onClick={this.handleCloseClick}\n            />\n          ) : null}\n          <div ref=\"bodyRef\" class={`${mergedClsPrefix}-notification-main`}>\n            {this.title ? (\n              <div class={`${mergedClsPrefix}-notification-main__header`}>\n                {render(this.title)}\n              </div>\n            ) : null}\n            {this.description ? (\n              <div class={`${mergedClsPrefix}-notification-main__description`}>\n                {render(this.description)}\n              </div>\n            ) : null}\n            {this.content ? (\n              <pre class={`${mergedClsPrefix}-notification-main__content`}>\n                {render(this.content)}\n              </pre>\n            ) : null}\n            {this.meta || this.action ? (\n              <div class={`${mergedClsPrefix}-notification-main-footer`}>\n                {this.meta ? (\n                  <div\n                    class={`${mergedClsPrefix}-notification-main-footer__meta`}\n                  >\n                    {render(this.meta)}\n                  </div>\n                ) : null}\n                {this.action ? (\n                  <div\n                    class={`${mergedClsPrefix}-notification-main-footer__action`}\n                  >\n                    {render(this.action)}\n                  </div>\n                ) : null}\n              </div>\n            ) : null}\n          </div>\n        </div>\n      </div>\n    )\n  }\n})\n"
  },
  {
    "path": "src/notification/src/NotificationContainer.tsx",
    "content": "import type { PropType } from 'vue'\nimport type { NotificationPlacement } from './NotificationProvider'\nimport { defineComponent, h, inject, ref, watchEffect } from 'vue'\nimport { NScrollbar } from '../../_internal'\nimport { notificationProviderInjectionKey } from './context'\n\nexport const NotificationContainer = defineComponent({\n  name: 'NotificationContainer',\n  props: {\n    scrollable: {\n      type: Boolean,\n      required: true\n    },\n    placement: {\n      type: String as PropType<NotificationPlacement>,\n      required: true\n    }\n  },\n  setup() {\n    const { mergedThemeRef, mergedClsPrefixRef, wipTransitionCountRef }\n      = inject(notificationProviderInjectionKey)!\n    const selfRef = ref<HTMLElement | null>(null)\n    watchEffect(() => {\n      if (wipTransitionCountRef.value > 0) {\n        selfRef?.value?.classList.add('transitioning')\n      }\n      else {\n        selfRef?.value?.classList.remove('transitioning')\n      }\n    })\n    return {\n      selfRef,\n      mergedTheme: mergedThemeRef,\n      mergedClsPrefix: mergedClsPrefixRef,\n      transitioning: wipTransitionCountRef\n    }\n  },\n  render() {\n    const { $slots, scrollable, mergedClsPrefix, mergedTheme, placement } = this\n    return (\n      <div\n        ref=\"selfRef\"\n        class={[\n          `${mergedClsPrefix}-notification-container`,\n          scrollable && `${mergedClsPrefix}-notification-container--scrollable`,\n          `${mergedClsPrefix}-notification-container--${placement}`\n        ]}\n      >\n        {scrollable ? (\n          <NScrollbar\n            theme={mergedTheme.peers.Scrollbar}\n            themeOverrides={mergedTheme.peerOverrides.Scrollbar}\n            contentStyle={{ overflow: 'hidden' }}\n          >\n            {$slots}\n          </NScrollbar>\n        ) : (\n          $slots\n        )}\n      </div>\n    )\n  }\n})\n"
  },
  {
    "path": "src/notification/src/NotificationEnvironment.tsx",
    "content": "import type { ExtractPropTypes, PropType } from 'vue'\nimport {\n  defineComponent,\n  h,\n  inject,\n  nextTick,\n  onMounted,\n  ref,\n  Transition\n} from 'vue'\nimport { keep } from '../../_utils'\nimport { notificationProviderInjectionKey } from './context'\nimport {\n  Notification,\n  notificationPropKeys,\n  notificationProps\n} from './Notification'\n\nexport const notificationEnvOptions = {\n  ...notificationProps,\n  duration: Number,\n  onClose: Function as PropType<() => Promise<boolean> | boolean | any>,\n  onLeave: Function as PropType<() => void>,\n  onAfterEnter: Function as PropType<() => void>,\n  onAfterLeave: Function as PropType<() => void>,\n  /** @deprecated */\n  onHide: Function as PropType<() => void>,\n  /** @deprecated */\n  onAfterShow: Function as PropType<() => void>,\n  /** @deprecated */\n  onAfterHide: Function as PropType<() => void>\n} as const\n\nexport type NotificationOptions = Partial<\n  ExtractPropTypes<typeof notificationEnvOptions>\n>\n\nexport const NotificationEnvironment = defineComponent({\n  name: 'NotificationEnvironment',\n  props: {\n    ...notificationEnvOptions,\n    // private\n    internalKey: {\n      type: String,\n      required: true\n    },\n    onInternalAfterLeave: {\n      type: Function as PropType<(key: string) => void>,\n      required: true\n    }\n  },\n  setup(props) {\n    const { wipTransitionCountRef } = inject(notificationProviderInjectionKey)!\n    const showRef = ref(true)\n    let timerId: number | null = null\n    function hide(): void {\n      showRef.value = false\n      if (timerId) {\n        window.clearTimeout(timerId)\n      }\n    }\n    function handleBeforeEnter(el: HTMLElement): void {\n      wipTransitionCountRef.value++\n      void nextTick(() => {\n        el.style.height = `${el.offsetHeight}px`\n        el.style.maxHeight = '0'\n        el.style.transition = 'none'\n        void el.offsetHeight\n        el.style.transition = ''\n        el.style.maxHeight = el.style.height\n      })\n    }\n    function handleAfterEnter(el: HTMLElement): void {\n      wipTransitionCountRef.value--\n      el.style.height = ''\n      el.style.maxHeight = ''\n      const { onAfterEnter, onAfterShow } = props\n      if (onAfterEnter)\n        onAfterEnter()\n      // deprecated\n      if (onAfterShow)\n        onAfterShow()\n    }\n    function handleBeforeLeave(el: HTMLElement): void {\n      wipTransitionCountRef.value++\n      el.style.maxHeight = `${el.offsetHeight}px`\n      el.style.height = `${el.offsetHeight}px`\n      void el.offsetHeight\n    }\n    function handleLeave(el: HTMLElement): void {\n      const { onHide } = props\n      if (onHide)\n        onHide()\n      el.style.maxHeight = '0'\n      void el.offsetHeight\n    }\n    function handleAfterLeave(): void {\n      wipTransitionCountRef.value--\n      const { onAfterLeave, onInternalAfterLeave, onAfterHide, internalKey }\n        = props\n      if (onAfterLeave)\n        onAfterLeave()\n      onInternalAfterLeave(internalKey)\n      // deprecated\n      if (onAfterHide)\n        onAfterHide()\n    }\n    function setHideTimeout(): void {\n      const { duration } = props\n      if (duration) {\n        timerId = window.setTimeout(hide, duration)\n      }\n    }\n    function handleMouseenter(e: MouseEvent): void {\n      if (e.currentTarget !== e.target)\n        return\n      if (timerId !== null) {\n        window.clearTimeout(timerId)\n        timerId = null\n      }\n    }\n    function handleMouseleave(e: MouseEvent): void {\n      if (e.currentTarget !== e.target)\n        return\n      setHideTimeout()\n    }\n    function handleClose(): void {\n      const { onClose } = props\n      if (onClose) {\n        void Promise.resolve(onClose()).then((feedback) => {\n          if (feedback === false)\n            return\n          hide()\n        })\n      }\n      else {\n        hide()\n      }\n    }\n    onMounted(() => {\n      if (props.duration) {\n        timerId = window.setTimeout(hide, props.duration)\n      }\n    })\n    return {\n      show: showRef,\n      hide,\n      handleClose,\n      handleAfterLeave,\n      handleLeave,\n      handleBeforeLeave,\n      handleAfterEnter,\n      handleBeforeEnter,\n      handleMouseenter,\n      handleMouseleave\n    }\n  },\n  render() {\n    return (\n      <Transition\n        name=\"notification-transition\"\n        appear={true}\n        // convert to any since Element is not compatible with HTMLElement\n        onBeforeEnter={this.handleBeforeEnter as any}\n        onAfterEnter={this.handleAfterEnter as any}\n        onBeforeLeave={this.handleBeforeLeave as any}\n        onLeave={this.handleLeave as any}\n        onAfterLeave={this.handleAfterLeave as any}\n      >\n        {{\n          default: () => {\n            return this.show ? (\n              <Notification\n                {...keep(this.$props, notificationPropKeys)}\n                onClose={this.handleClose}\n                onMouseenter={\n                  this.duration && this.keepAliveOnHover\n                    ? this.handleMouseenter\n                    : undefined\n                }\n                onMouseleave={\n                  this.duration && this.keepAliveOnHover\n                    ? this.handleMouseleave\n                    : undefined\n                }\n              />\n            ) : null\n          }\n        }}\n      </Transition>\n    )\n  }\n})\n"
  },
  {
    "path": "src/notification/src/NotificationProvider.tsx",
    "content": "import type { CSSProperties, ExtractPropTypes, PropType, Ref } from 'vue'\nimport type { MergedTheme, ThemeProps } from '../../_mixins'\nimport type { ExtractPublicPropTypes, Mutable } from '../../_utils'\nimport type { NotificationTheme } from '../styles'\nimport type { NotificationOptions } from './NotificationEnvironment'\nimport { createId } from 'seemly'\nimport {\n  defineComponent,\n  Fragment,\n  h,\n  provide,\n  reactive,\n  ref,\n  Teleport\n} from 'vue'\nimport { useConfig, useTheme } from '../../_mixins'\nimport { createInjectionKey, omit } from '../../_utils'\nimport { notificationLight } from '../styles'\nimport { notificationProviderInjectionKey } from './context'\nimport { NotificationContainer } from './NotificationContainer'\nimport { NotificationEnvironment } from './NotificationEnvironment'\nimport style from './styles/index.cssr'\n\nexport type NotificationPlacement\n  = | 'top-left'\n    | 'top-right'\n    | 'bottom-left'\n    | 'bottom-right'\n    | 'top'\n    | 'bottom'\n\nexport interface NotificationProviderInjection {\n  props: ExtractPropTypes<typeof notificationProviderProps>\n  mergedClsPrefixRef: Ref<string>\n  mergedThemeRef: Ref<MergedTheme<NotificationTheme>>\n  wipTransitionCountRef: Ref<number>\n}\n\ntype Create = (options: NotificationOptions) => NotificationReactive\ntype TypedCreate = (\n  options: Omit<NotificationOptions, 'type'>\n) => NotificationReactive\n\nexport interface NotificationApiInjection {\n  create: Create\n  info: TypedCreate\n  success: TypedCreate\n  warning: TypedCreate\n  error: TypedCreate\n  /** @deprecated */\n  open: Create\n  destroyAll: () => void\n}\n\nexport type NotificationProviderInst = NotificationApiInjection\n\nexport const notificationApiInjectionKey\n  = createInjectionKey<NotificationApiInjection>('n-notification-api')\n\nexport type NotificationType = 'info' | 'success' | 'warning' | 'error'\n\nexport type NotificationReactive = {\n  readonly key: string\n  readonly destroy: () => void\n  /** @deprecated */\n  readonly hide: () => void\n  /** @deprecated */\n  readonly deactivate: () => void\n} & Mutable<NotificationOptions>\n\ninterface NotificationRef {\n  hide: () => void\n}\n\nexport const notificationProviderProps = {\n  ...(useTheme.props as ThemeProps<NotificationTheme>),\n  containerClass: String,\n  containerStyle: [String, Object] as PropType<string | CSSProperties>,\n  to: [String, Object] as PropType<string | HTMLElement>,\n  scrollable: {\n    type: Boolean,\n    default: true\n  },\n  max: Number,\n  placement: {\n    type: String as PropType<NotificationPlacement>,\n    default: 'top-right'\n  },\n  keepAliveOnHover: Boolean\n}\n\nexport type NotificationProviderProps = ExtractPublicPropTypes<\n  typeof notificationProviderProps\n>\n\nexport default defineComponent({\n  name: 'NotificationProvider',\n  props: notificationProviderProps,\n  setup(props) {\n    const { mergedClsPrefixRef } = useConfig(props)\n    const notificationListRef = ref<NotificationReactive[]>([])\n    const notificationRefs: Record<string, NotificationRef> = {}\n    const leavingKeySet = new Set<string>()\n    function create(options: NotificationOptions): NotificationReactive {\n      const key = createId()\n      const destroy = (): void => {\n        leavingKeySet.add(key)\n        // If you push n + 1 message when max is n, notificationRefs[key] maybe not be set\n        if (notificationRefs[key]) {\n          notificationRefs[key].hide()\n        }\n      }\n      const notificationReactive = reactive({\n        ...options,\n        key,\n        destroy,\n        hide: destroy,\n        deactivate: destroy\n      })\n      const { max } = props\n      if (max && notificationListRef.value.length - leavingKeySet.size >= max) {\n        let someoneMountedRemoved = false\n        let index = 0\n        for (const notification of notificationListRef.value) {\n          if (!leavingKeySet.has(notification.key)) {\n            if (notificationRefs[notification.key]) {\n              notification.destroy()\n              someoneMountedRemoved = true\n            }\n            break\n          }\n          index++\n        }\n        if (!someoneMountedRemoved) {\n          notificationListRef.value.splice(index, 1)\n        }\n      }\n      notificationListRef.value.push(notificationReactive)\n      return notificationReactive\n    }\n    const apis = (['info', 'success', 'warning', 'error'] as const).map(\n      (type: NotificationType) => {\n        return (options: Omit<NotificationOptions, 'type'>) =>\n          create({ ...options, type })\n      }\n    )\n    function handleAfterLeave(key: string): void {\n      leavingKeySet.delete(key)\n      notificationListRef.value.splice(\n        notificationListRef.value.findIndex(\n          notification => notification.key === key\n        ),\n        1\n      )\n    }\n    const themeRef = useTheme(\n      'Notification',\n      '-notification',\n      style,\n      notificationLight,\n      props,\n      mergedClsPrefixRef\n    )\n    const api = {\n      create,\n      info: apis[0],\n      success: apis[1],\n      warning: apis[2],\n      error: apis[3],\n      open,\n      destroyAll\n    }\n    const wipTransitionCountRef = ref(0)\n    provide(notificationApiInjectionKey, api)\n    provide(notificationProviderInjectionKey, {\n      props,\n      mergedClsPrefixRef,\n      mergedThemeRef: themeRef,\n      wipTransitionCountRef\n    })\n    // deprecated\n    function open(options: NotificationOptions): NotificationReactive {\n      return create(options)\n    }\n    function destroyAll(): void {\n      Object.values(notificationListRef.value).forEach((notification) => {\n        notification.hide()\n      })\n    }\n    return Object.assign(\n      {\n        mergedClsPrefix: mergedClsPrefixRef,\n        notificationList: notificationListRef,\n        notificationRefs,\n        handleAfterLeave\n      },\n      api\n    )\n  },\n  render() {\n    const { placement } = this\n    return (\n      <>\n        {this.$slots.default?.()}\n        {this.notificationList.length ? (\n          <Teleport to={this.to ?? 'body'}>\n            <NotificationContainer\n              class={this.containerClass}\n              style={this.containerStyle}\n              scrollable={\n                this.scrollable && placement !== 'top' && placement !== 'bottom'\n              }\n              placement={placement}\n            >\n              {{\n                default: () => {\n                  return this.notificationList.map((notification) => {\n                    return (\n                      <NotificationEnvironment\n                        ref={\n                          ((inst: NotificationRef) => {\n                            const refKey = notification.key\n                            if (inst === null) {\n                              delete this.notificationRefs[refKey]\n                            }\n                            else {\n                              this.notificationRefs[refKey] = inst\n                            }\n                          }) as any\n                        }\n                        {...omit(notification, [\n                          'destroy',\n                          'hide',\n                          'deactivate'\n                        ])}\n                        internalKey={notification.key}\n                        onInternalAfterLeave={this.handleAfterLeave}\n                        keepAliveOnHover={\n                          notification.keepAliveOnHover === undefined\n                            ? this.keepAliveOnHover\n                            : notification.keepAliveOnHover\n                        }\n                      />\n                    )\n                  })\n                }\n              }}\n            </NotificationContainer>\n          </Teleport>\n        ) : null}\n      </>\n    )\n  }\n})\n"
  },
  {
    "path": "src/notification/src/context.ts",
    "content": "import type { NotificationProviderInjection } from './NotificationProvider'\nimport { createInjectionKey } from '../../_utils'\n\nexport const notificationProviderInjectionKey\n  = createInjectionKey<NotificationProviderInjection>('n-notification-provider')\n"
  },
  {
    "path": "src/notification/src/styles/index.cssr.ts",
    "content": "import type { CNode } from 'css-render'\nimport { c, cB, cE, cM } from '../../../_utils/cssr'\n\n// vars:\n// --n-color\n// --n-text-color\n// --n-description-text-color\n// --n-action-text-color\n// --n-title-text-color\n// --n-title-font-weight\n// --n-title-font-size\n// --n-meta-font-size\n// --n-description-font-size\n// --n-bezier\n// --n-bezier-ease-out\n// --n-bezier-ease-in\n// --n-border-radius\n// --n-box-shadow\n// --n-close-margin\n// --n-close-size\n// --n-close-icon-size\n// --n-close-color-hover\n// --n-close-color-pressed\n// --n-close-icon-color\n// --n-close-icon-color-hover\n// --n-close-icon-color-pressed\n// --n-line-height\n// --n-icon-color\n// --n-width\n// --n-padding-top\n// --n-padding-bottom\n// --n-padding-left\n// --n-padding-right\nexport default c([\n  cB('notification-container', `\n    z-index: 4000;\n    position: fixed;\n    overflow: visible;\n    display: flex;\n    flex-direction: column;\n    align-items: flex-end;\n  `, [\n    c('>', [\n      cB('scrollbar', `\n        width: initial;\n        overflow: visible;\n        height: -moz-fit-content !important;\n        height: fit-content !important;\n        max-height: 100vh !important;\n      `, [\n        c('>', [\n          cB('scrollbar-container', `\n            height: -moz-fit-content !important;\n            height: fit-content !important;\n            max-height: 100vh !important;\n          `, [\n            cB('scrollbar-content', `\n              padding-top: 12px;\n              padding-bottom: 33px;\n            `)\n          ])\n        ])\n      ])\n    ]),\n    cM('top, top-right, top-left', `\n      top: 12px;\n    `, [\n      c('&.transitioning >', [\n        cB('scrollbar', [\n          c('>', [\n            cB('scrollbar-container', `\n              min-height: 100vh !important;\n            `)\n          ])\n        ])\n      ])\n    ]),\n    cM('bottom, bottom-right, bottom-left', `\n      bottom: 12px;\n    `, [\n      c('>', [\n        cB('scrollbar', [\n          c('>', [\n            cB('scrollbar-container', [\n              cB('scrollbar-content', `\n                padding-bottom: 12px;\n              `)\n            ])\n          ])\n        ])\n      ]),\n      cB('notification-wrapper', `\n        display: flex;\n        align-items: flex-end;\n        margin-bottom: 0;\n        margin-top: 12px;\n      `)\n    ]),\n    cM('top, bottom', `\n      left: 50%;\n      transform: translateX(-50%);\n    `, [\n      cB('notification-wrapper', [\n        c('&.notification-transition-enter-from, &.notification-transition-leave-to', `\n          transform: scale(0.85);\n        `),\n        c('&.notification-transition-leave-from, &.notification-transition-enter-to', `\n          transform: scale(1);\n        `)\n      ])\n    ]),\n    cM('top', [\n      cB('notification-wrapper', `\n        transform-origin: top center;\n      `)\n    ]),\n    cM('bottom', [\n      cB('notification-wrapper', `\n        transform-origin: bottom center;\n      `)\n    ]),\n    cM('top-right, bottom-right', [\n      cB('notification', `\n        margin-left: 28px;\n        margin-right: 16px;\n      `)\n    ]),\n    cM('top-left, bottom-left', [\n      cB('notification', `\n        margin-left: 16px;\n        margin-right: 28px;\n      `)\n    ]),\n    cM('top-right', `\n      right: 0;\n    `, [\n      placementTransformStyle('top-right')\n    ]),\n    cM('top-left', `\n      left: 0;\n    `, [\n      placementTransformStyle('top-left')\n    ]),\n    cM('bottom-right', `\n      right: 0;\n    `, [\n      placementTransformStyle('bottom-right')\n    ]),\n    cM('bottom-left', `\n      left: 0;\n    `, [\n      placementTransformStyle('bottom-left')\n    ]),\n    cM('scrollable', [\n      cM('top-right', `\n        top: 0;\n      `),\n      cM('top-left', `\n        top: 0;\n      `),\n      cM('bottom-right', `\n        bottom: 0;\n      `),\n      cM('bottom-left', `\n        bottom: 0;\n      `)\n    ]),\n    cB('notification-wrapper', `\n      margin-bottom: 12px;\n    `, [\n      c('&.notification-transition-enter-from, &.notification-transition-leave-to', `\n        opacity: 0;\n        margin-top: 0 !important;\n        margin-bottom: 0 !important;\n      `),\n      c('&.notification-transition-leave-from, &.notification-transition-enter-to', `\n        opacity: 1;\n      `),\n      c('&.notification-transition-leave-active', `\n        transition:\n          background-color .3s var(--n-bezier),\n          color .3s var(--n-bezier),\n          opacity .3s var(--n-bezier),\n          transform .3s var(--n-bezier-ease-in),\n          max-height .3s var(--n-bezier),\n          margin-top .3s linear,\n          margin-bottom .3s linear,\n          box-shadow .3s var(--n-bezier);\n      `),\n      c('&.notification-transition-enter-active', `\n        transition:\n          background-color .3s var(--n-bezier),\n          color .3s var(--n-bezier),\n          opacity .3s var(--n-bezier),\n          transform .3s var(--n-bezier-ease-out),\n          max-height .3s var(--n-bezier),\n          margin-top .3s linear,\n          margin-bottom .3s linear,\n          box-shadow .3s var(--n-bezier);\n      `)\n    ]),\n    cB('notification', `\n      background-color: var(--n-color);\n      color: var(--n-text-color);\n      transition:\n        background-color .3s var(--n-bezier),\n        color .3s var(--n-bezier),\n        opacity .3s var(--n-bezier),\n        box-shadow .3s var(--n-bezier);\n      font-family: inherit;\n      font-size: var(--n-font-size);\n      font-weight: 400;\n      position: relative;\n      display: flex;\n      overflow: hidden;\n      flex-shrink: 0;\n      padding-left: var(--n-padding-left);\n      padding-right: var(--n-padding-right);\n      width: var(--n-width);\n      max-width: calc(100vw - 16px - 16px);\n      border-radius: var(--n-border-radius);\n      box-shadow: var(--n-box-shadow);\n      box-sizing: border-box;\n      opacity: 1;\n    `, [\n      cE('avatar', [\n        cB('icon', `\n          color: var(--n-icon-color);\n        `),\n        cB('base-icon', `\n          color: var(--n-icon-color);\n        `)\n      ]),\n      cM('show-avatar', [\n        cB('notification-main', `\n          margin-left: 40px;\n          width: calc(100% - 40px);  \n        `)\n      ]),\n      cM('closable', [\n        cB('notification-main', [\n          c('> *:first-child', `\n            padding-right: 20px;\n          `)\n        ]),\n        cE('close', `\n          position: absolute;\n          top: 0;\n          right: 0;\n          margin: var(--n-close-margin);\n          transition:\n            background-color .3s var(--n-bezier),\n            color .3s var(--n-bezier);\n        `)\n      ]),\n      cE('avatar', `\n        position: absolute;\n        top: var(--n-padding-top);\n        left: var(--n-padding-left);\n        width: 28px;\n        height: 28px;\n        font-size: 28px;\n        display: flex;\n        align-items: center;\n        justify-content: center;\n      `, [\n        cB('icon', 'transition: color .3s var(--n-bezier);')\n      ]),\n      cB('notification-main', `\n        padding-top: var(--n-padding-top);\n        padding-bottom: var(--n-padding-bottom);\n        box-sizing: border-box;\n        display: flex;\n        flex-direction: column;\n        margin-left: 8px;\n        width: calc(100% - 8px);\n      `, [\n        cB('notification-main-footer', `\n          display: flex;\n          align-items: center;\n          justify-content: space-between;\n          margin-top: 12px;\n        `, [\n          cE('meta', `\n            font-size: var(--n-meta-font-size);\n            transition: color .3s var(--n-bezier-ease-out);\n            color: var(--n-description-text-color);\n          `),\n          cE('action', `\n            cursor: pointer;\n            transition: color .3s var(--n-bezier-ease-out);\n            color: var(--n-action-text-color);\n          `)\n        ]),\n        cE('header', `\n          font-weight: var(--n-title-font-weight);\n          font-size: var(--n-title-font-size);\n          transition: color .3s var(--n-bezier-ease-out);\n          color: var(--n-title-text-color);\n        `),\n        cE('description', `\n          margin-top: 8px;\n          font-size: var(--n-description-font-size);\n          white-space: pre-wrap;\n          word-wrap: break-word;\n          transition: color .3s var(--n-bezier-ease-out);\n          color: var(--n-description-text-color);\n        `),\n        cE('content', `\n          line-height: var(--n-line-height);\n          margin: 12px 0 0 0;\n          font-family: inherit;\n          white-space: pre-wrap;\n          word-wrap: break-word;\n          transition: color .3s var(--n-bezier-ease-out);\n          color: var(--n-text-color);\n        `, [\n          c('&:first-child', 'margin: 0;')\n        ])\n      ])\n    ])\n  ])\n])\n\nfunction placementTransformStyle(placement: string): CNode {\n  const direction = placement.split('-')[1]\n  const transformXEnter = direction === 'left' ? 'calc(-100%)' : 'calc(100%)'\n  const transformXLeave = '0'\n  return cB('notification-wrapper', [\n    c('&.notification-transition-enter-from, &.notification-transition-leave-to', `\n      transform: translate(${transformXEnter}, 0);\n    `),\n    c('&.notification-transition-leave-from, &.notification-transition-enter-to', `\n      transform: translate(${transformXLeave}, 0);\n    `)\n  ])\n}\n"
  },
  {
    "path": "src/notification/src/styles/rtl.cssr.ts",
    "content": "import { c, cB, cE, cM } from '../../../_utils/cssr'\n\nexport default cB('notification', [\n  cM('rtl', `\n    direction: rtl;\n  `, [\n    cB('notification-main', `\n      margin-left: unset;\n      margin-right: 8px;\n    `, [\n      cE('header', `\n        margin: var(--n-icon-margin);\n        margin-right: 0;\n      `)\n    ]),\n    cE('avatar', `\n      left: unset;\n      right: var(--n-padding-left);\n    `),\n    cM('show-avatar', [\n      cB('notification-main', `\n        margin-right: 40px;\n        margin-reft: unset;\n      `)\n    ]),\n    cM('closable', [\n      cB('notification-main', [\n        c('> *:first-child', `\n          padding-left: 20px;\n          padding-right: unset;\n        `)\n      ]),\n      cE('close', `\n        right: unset;\n        left: 0;\n      `)\n    ])\n  ])\n])\n"
  },
  {
    "path": "src/notification/src/use-notification.ts",
    "content": "import type { NotificationApiInjection } from './NotificationProvider'\nimport { inject } from 'vue'\nimport { throwError } from '../../_utils'\nimport { notificationApiInjectionKey } from './NotificationProvider'\n\nexport function useNotification(): NotificationApiInjection {\n  const api = inject(notificationApiInjectionKey, null)\n  if (api === null) {\n    throwError('use-notification', 'No outer `n-notification-provider` found.')\n  }\n  return api\n}\n"
  },
  {
    "path": "src/notification/styles/_common.ts",
    "content": "export default {\n  closeMargin: '16px 12px',\n  closeSize: '20px',\n  closeIconSize: '16px',\n  width: '365px',\n  padding: '16px',\n  titleFontSize: '16px',\n  metaFontSize: '12px',\n  descriptionFontSize: '12px'\n}\n"
  },
  {
    "path": "src/notification/styles/dark.ts",
    "content": "import type { NotificationTheme } from './light'\nimport { scrollbarDark } from '../../_internal/scrollbar/styles'\nimport { commonDark } from '../../_styles/common'\nimport { self } from './light'\n\nconst notificationDark: NotificationTheme = {\n  name: 'Notification',\n  common: commonDark,\n  peers: {\n    Scrollbar: scrollbarDark\n  },\n  self\n}\n\nexport default notificationDark\n"
  },
  {
    "path": "src/notification/styles/index.ts",
    "content": "export { default as notificationDark } from './dark'\nexport { default as notificationLight } from './light'\nexport type { NotificationTheme, NotificationThemeVars } from './light'\nexport { notificationRtl } from './rtl'\n"
  },
  {
    "path": "src/notification/styles/light.ts",
    "content": "import type { ThemeCommonVars } from '../../_styles/common'\nimport { scrollbarLight } from '../../_internal/scrollbar/styles'\nimport { createTheme } from '../../_mixins'\nimport { commonLight } from '../../_styles/common'\nimport commonVars from './_common'\n\nexport function self(vars: ThemeCommonVars) {\n  const {\n    textColor2,\n    successColor,\n    infoColor,\n    warningColor,\n    errorColor,\n    popoverColor,\n    closeIconColor,\n    closeIconColorHover,\n    closeIconColorPressed,\n    closeColorHover,\n    closeColorPressed,\n    textColor1,\n    textColor3,\n    borderRadius,\n    fontWeightStrong,\n    boxShadow2,\n    lineHeight,\n    fontSize\n  } = vars\n  return {\n    ...commonVars,\n    borderRadius,\n    lineHeight,\n    fontSize,\n    headerFontWeight: fontWeightStrong,\n    iconColor: textColor2,\n    iconColorSuccess: successColor,\n    iconColorInfo: infoColor,\n    iconColorWarning: warningColor,\n    iconColorError: errorColor,\n    color: popoverColor,\n    textColor: textColor2,\n    closeIconColor,\n    closeIconColorHover,\n    closeIconColorPressed,\n    closeBorderRadius: borderRadius,\n    closeColorHover,\n    closeColorPressed,\n    headerTextColor: textColor1,\n    descriptionTextColor: textColor3,\n    actionTextColor: textColor2,\n    boxShadow: boxShadow2\n  }\n}\n\nexport type NotificationThemeVars = ReturnType<typeof self>\n\nconst notificationLight = createTheme({\n  name: 'Notification',\n  common: commonLight,\n  peers: {\n    Scrollbar: scrollbarLight\n  },\n  self\n})\n\nexport default notificationLight\nexport type NotificationTheme = typeof notificationLight\n"
  },
  {
    "path": "src/notification/styles/rtl.ts",
    "content": "import type { RtlItem } from '../../config-provider/src/internal-interface'\nimport rtlStyle from '../src/styles/rtl.cssr'\n\nexport const notificationRtl: RtlItem = {\n  name: 'Notification',\n  style: rtlStyle\n}\n"
  },
  {
    "path": "src/notification/tests/Notification.spec.tsx",
    "content": "import type { Ref } from 'vue'\nimport type { NotificationReactive } from '../index'\nimport { mount } from '@vue/test-utils'\nimport { sleep } from 'seemly'\nimport { defineComponent, h, nextTick, onMounted, ref } from 'vue'\nimport { NNotificationProvider, useNotification } from '../index'\n\nconst Provider = defineComponent({\n  render() {\n    return <NNotificationProvider>{this.$slots}</NNotificationProvider>\n  }\n})\n\ndescribe('n-notification', () => {\n  it('should work with import on demand', () => {\n    mount(NNotificationProvider)\n  })\n  it('should have correct type', () => {\n    const Test = defineComponent({\n      setup() {\n        const notification = useNotification()\n        notification.info({\n          title: 'info'\n        })\n        const notificationReactive = notification.success({\n          title: 'success'\n        })\n        notificationReactive.title = 'cool'\n      },\n      render() {\n        return null\n      }\n    })\n    const wrapper = mount(() => (\n      <Provider>{{ default: () => <Test /> }}</Provider>\n    ))\n    wrapper.unmount()\n  })\n\n  it('can change content', async () => {\n    const changeContent = vi.fn((nRef: Ref) => {\n      nRef.value.content = 'change info'\n    })\n    const Test = defineComponent({\n      setup() {\n        const nRef = ref<NotificationReactive | null>(null)\n        const notification = useNotification()\n        nRef.value = notification.info({\n          title: 'info',\n          content: 'info'\n        })\n        setTimeout(() => {\n          if (nRef.value) {\n            changeContent(nRef)\n          }\n        })\n      },\n      render() {\n        return null\n      }\n    })\n    const wrapper = mount(() => (\n      <Provider>{{ default: () => <Test /> }}</Provider>\n    ))\n    await nextTick()\n    expect(\n      document.querySelector('.n-notification-main__content')?.textContent\n    ).toEqual('info')\n    await sleep(1000)\n    expect(changeContent).toHaveBeenCalled()\n    expect(\n      document.querySelector('.n-notification-main__content')?.textContent\n    ).toEqual('change info')\n    wrapper.unmount()\n  })\n\n  it('should work with duration', async () => {\n    const Test = defineComponent({\n      setup() {\n        const notification = useNotification()\n        notification.info({\n          title: 'info',\n          content: 'info',\n          duration: 1000\n        })\n      },\n      render() {\n        return null\n      }\n    })\n    const wrapper = mount(() => (\n      <Provider>{{ default: () => <Test /> }}</Provider>\n    ))\n    await nextTick()\n    await sleep(500)\n    expect(document.querySelector('.n-notification')).not.toEqual(null)\n    await sleep(1200)\n    expect(document.querySelector('.n-notification')).toBe(null)\n    wrapper.unmount()\n  })\n})\n\ndescribe('notification-provider', () => {\n  it('props.max', async () => {\n    const Test = defineComponent({\n      setup() {\n        const notification = useNotification()\n        onMounted(() => {\n          notification.info({\n            title: 'info',\n            content: 'info'\n          })\n          notification.info({\n            title: 'info',\n            content: 'info'\n          })\n          notification.info({\n            title: 'info',\n            content: 'info'\n          })\n        })\n      },\n      render() {\n        return null\n      }\n    })\n    const wrapper = mount(NNotificationProvider, {\n      props: {\n        max: 2\n      },\n      slots: {\n        default: () => <Test />\n      }\n    })\n    await nextTick()\n    expect(document.querySelectorAll('.n-notification').length).toBe(2)\n    wrapper.unmount()\n  })\n  it('should work with `placement` prop', async () => {\n    const Test = defineComponent({\n      setup() {\n        const notification = useNotification()\n        notification.info({\n          title: 'info',\n          content: 'info'\n        })\n      },\n      render() {\n        return null\n      }\n    })\n    const wrapper = mount(NNotificationProvider, {\n      slots: {\n        default: () => <Test />\n      }\n    })\n    await nextTick()\n    const container = document.querySelector('.n-notification-container')!\n    expect(container).not.toBeFalsy()\n    expect(\n      container.classList.contains('n-notification-container--top-right')\n    ).toEqual(true)\n    await wrapper.setProps({ placement: 'top-left' })\n    expect(\n      container.classList.contains('n-notification-container--top-left')\n    ).toEqual(true)\n    await wrapper.setProps({ placement: 'bottom-right' })\n    expect(\n      container.classList.contains('n-notification-container--bottom-right')\n    ).toEqual(true)\n    await wrapper.setProps({ placement: 'bottom-left' })\n    expect(\n      container.classList.contains('n-notification-container--bottom-left')\n    ).toEqual(true)\n    wrapper.unmount()\n  })\n  it('should work with `destroyAll` method', async () => {\n    const Test = defineComponent({\n      setup() {\n        const notification = useNotification()\n        onMounted(() => {\n          notification.info({\n            title: 'info',\n            content: 'info'\n          })\n          notification.info({\n            title: 'info',\n            content: 'info'\n          })\n          notification.destroyAll()\n        })\n      },\n      render() {\n        return null\n      }\n    })\n    const wrapper = mount(NNotificationProvider, {\n      slots: {\n        default: () => <Test />\n      }\n    })\n    await nextTick()\n    expect(wrapper.find('.notification-container').exists()).toBe(false)\n    wrapper.unmount()\n  })\n})\n"
  },
  {
    "path": "src/number-animation/demos/enUS/basic.demo.vue",
    "content": "<markdown>\n# Basic\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { NumberAnimationInst } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst numberAnimationInstRef = ref<NumberAnimationInst | null>(null)\nfunction handleClick() {\n  numberAnimationInstRef.value?.play()\n}\n</script>\n\n<template>\n  <n-statistic label=\"Well\" tabular-nums>\n    <n-number-animation\n      ref=\"numberAnimationInstRef\"\n      :from=\"9.96\"\n      :to=\"0.07\"\n      :active=\"false\"\n      :precision=\"2\"\n    />\n  </n-statistic>\n  <n-button @click=\"handleClick\">\n    Play\n  </n-button>\n</template>\n"
  },
  {
    "path": "src/number-animation/demos/enUS/finish.demo.vue",
    "content": "<markdown>\n# Finish callback\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { NumberAnimationInst } from 'naive-ui'\nimport { useMessage } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst numberAnimationInstRef = ref<NumberAnimationInst | null>(null)\nconst message = useMessage()\n\nfunction handleClick() {\n  numberAnimationInstRef.value?.play()\n}\n\nfunction handleFinish() {\n  message.success('Finished')\n}\n</script>\n\n<template>\n  <n-statistic label=\"Post message on finish\" tabular-nums>\n    <n-number-animation\n      ref=\"numberAnimationInstRef\"\n      show-separator\n      :from=\"0\"\n      :to=\"100000000\"\n      :active=\"false\"\n      @finish=\"handleFinish\"\n    />\n  </n-statistic>\n  <n-button @click=\"handleClick\">\n    Play\n  </n-button>\n</template>\n"
  },
  {
    "path": "src/number-animation/demos/enUS/index.demo-entry.md",
    "content": "# Number Animation\n\nTween the number.\n\n## Demos\n\n```demo\nbasic.vue\nprecision.vue\nseparator.vue\nintl.vue\nfinish.vue\n```\n\n## API\n\n### NumberAnimation Props\n\n| Name | Type | Default | Description | Version |\n| --- | --- | --- | --- | --- |\n| active | `boolean` | `true` | Whether to play the animation. | 2.23.2 |\n| duration | `number` | `3000` | The duration of | 2.23.2 |\n| from | `number` | `0` | Start value of the animation | 2.23.2 |\n| locale | `string` | Follows config provider. | Language of the number. | 2.24.2 |\n| precision | `number` | `0` | Decimal precision of the displayed value. | 2.23.2 |\n| show-separator | `boolean` | `false` | Whether to show separator. | 2.23.2 |\n| to | `number` | `undefined` | Target value. | 2.23.2 |\n| on-finish | `() => void` | `undefined` | The callback on animation is finished. | 2.31.0 |\n\n### NumberAnimation Methods\n\n| Name | Parameters | Description         | Version |\n| ---- | ---------- | ------------------- | ------- |\n| play | `()`       | Play the animation. | 2.23.2  |\n"
  },
  {
    "path": "src/number-animation/demos/enUS/intl.demo.vue",
    "content": "<markdown>\n# I18n\n\nUse `locale` to set i18n language.\n\nPlease note that, the feature uses `Intl` API. For compitability refers to [format](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/NumberFormat/format) and [formatToParts](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/NumberFormat/formatToParts).\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { NumberAnimationInst } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst numberAnimationInstRef = ref<NumberAnimationInst | null>(null)\nfunction handleClick() {\n  numberAnimationInstRef.value?.play()\n}\n</script>\n\n<template>\n  <n-statistic label=\"ru-RU\" tabular-nums>\n    <n-number-animation\n      ref=\"numberAnimationInstRef\"\n      :from=\"0.0\"\n      :to=\"699700.699\"\n      :active=\"false\"\n      :precision=\"3\"\n      locale=\"ru-RU\"\n      show-separator\n    />\n  </n-statistic>\n  <n-button @click=\"handleClick\">\n    Play\n  </n-button>\n</template>\n"
  },
  {
    "path": "src/number-animation/demos/enUS/precision.demo.vue",
    "content": "<markdown>\n# Precision\n\nUse `precision` to set precision.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { NumberAnimationInst } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst numberAnimationInstRef = ref<NumberAnimationInst | null>(null)\nfunction handleClick() {\n  numberAnimationInstRef.value?.play()\n}\n</script>\n\n<template>\n  <n-statistic label=\"JNM\" tabular-nums>\n    <n-number-animation\n      ref=\"numberAnimationInstRef\"\n      :from=\"0.0\"\n      :to=\"24.0\"\n      :active=\"false\"\n      :precision=\"2\"\n    />\n  </n-statistic>\n  <n-button @click=\"handleClick\">\n    Play\n  </n-button>\n</template>\n"
  },
  {
    "path": "src/number-animation/demos/enUS/separator.demo.vue",
    "content": "<markdown>\n# Separator\n\nThe number is too large to count the digits.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { NumberAnimationInst } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst numberAnimationInstRef = ref<NumberAnimationInst | null>(null)\nfunction handleClick() {\n  numberAnimationInstRef.value?.play()\n}\n</script>\n\n<template>\n  <n-statistic label=\"A little goal\" tabular-nums>\n    <n-number-animation\n      ref=\"numberAnimationInstRef\"\n      show-separator\n      :from=\"0\"\n      :to=\"100000000\"\n      :active=\"false\"\n    />\n  </n-statistic>\n  <n-button @click=\"handleClick\">\n    Play\n  </n-button>\n</template>\n"
  },
  {
    "path": "src/number-animation/demos/zhCN/basic.demo.vue",
    "content": "<markdown>\n# 基础用法\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { NumberAnimationInst } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst numberAnimationInstRef = ref<NumberAnimationInst | null>(null)\nfunction handleClick() {\n  numberAnimationInstRef.value?.play()\n}\n</script>\n\n<template>\n  <n-statistic label=\"你一共处理了\" tabular-nums>\n    <n-number-animation ref=\"numberAnimationInstRef\" :from=\"0\" :to=\"12039\" />\n    <template #suffix>\n      条群消息\n    </template>\n  </n-statistic>\n  <n-space vertical>\n    花时间、花精力、花心思，愿你每一份努力都不负所望\n    <n-button @click=\"handleClick\">\n      播放\n    </n-button>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/number-animation/demos/zhCN/finish.demo.vue",
    "content": "<markdown>\n# 结束的回调\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { NumberAnimationInst } from 'naive-ui'\nimport { useMessage } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst numberAnimationInstRef = ref<NumberAnimationInst | null>(null)\nconst message = useMessage()\n\nfunction handleClick() {\n  numberAnimationInstRef.value?.play()\n}\n\nfunction handleFinish() {\n  message.success('Finished')\n}\n</script>\n\n<template>\n  <n-statistic label=\"完成之后发个消息\" tabular-nums>\n    <n-number-animation\n      ref=\"numberAnimationInstRef\"\n      show-separator\n      :from=\"0\"\n      :to=\"100000000\"\n      :active=\"false\"\n      @finish=\"handleFinish\"\n    />\n  </n-statistic>\n  <n-button @click=\"handleClick\">\n    开始\n  </n-button>\n</template>\n"
  },
  {
    "path": "src/number-animation/demos/zhCN/index.demo-entry.md",
    "content": "# 数值动画 Number Animation\n\n这个动画，那么有科技感，快请到我们的大屏上来。\n\n## 演示\n\n```demo\nbasic.vue\nprecision.vue\nseparator.vue\nintl.vue\nfinish.vue\n```\n\n## API\n\n### NumberAnimation Props\n\n| 名称 | 类型 | 默认值 | 说明 | 版本 |\n| --- | --- | --- | --- | --- |\n| active | `boolean` | `true` | 是否开始动画 | 2.23.2 |\n| duration | `number` | `3000` | 动画持续时间 | 2.23.2 |\n| from | `number` | `0` | 数值动画起始值 | 2.23.2 |\n| locale | `string` | 跟随 config provider | 国际化的语言 | 2.24.2 |\n| precision | `number` | `0` | 精度，保留小数点后几位 | 2.23.2 |\n| show-separator | `boolean` | `false` | 是否显示分隔符 | 2.23.2 |\n| to | `number` | `undefined` | 目标值 | 2.23.2 |\n| on-finish | `() => void` | `undefined` | 动画结束的回调 | 2.31.0 |\n\n### NumberAnimation Methods\n\n| 名称 | 参数 | 说明     | 版本   |\n| ---- | ---- | -------- | ------ |\n| play | `()` | 播放动画 | 2.23.2 |\n"
  },
  {
    "path": "src/number-animation/demos/zhCN/intl.demo.vue",
    "content": "<markdown>\n# 国际化\n\n使用 `locale` 设定国际化语言。\n\n需要注意的是，该功能使用了 `Intl` API，兼容性请参考 [format](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/NumberFormat/format) 和 [formatToParts](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/NumberFormat/formatToParts)。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { NumberAnimationInst } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst numberAnimationInstRef = ref<NumberAnimationInst | null>(null)\nfunction handleClick() {\n  numberAnimationInstRef.value?.play()\n}\n</script>\n\n<template>\n  <n-statistic label=\"你可能不知道俄语的小数点是逗号\" tabular-nums>\n    <n-number-animation\n      ref=\"numberAnimationInstRef\"\n      :from=\"0.0\"\n      :to=\"699700.699\"\n      :active=\"false\"\n      :precision=\"3\"\n      locale=\"ru-RU\"\n      show-separator\n    />\n  </n-statistic>\n  <n-button @click=\"handleClick\">\n    播放\n  </n-button>\n</template>\n"
  },
  {
    "path": "src/number-animation/demos/zhCN/precision.demo.vue",
    "content": "<markdown>\n# 精度\n\n使用 `precision` 设定精度。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { NumberAnimationInst } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst numberAnimationInstRef = ref<NumberAnimationInst | null>(null)\nfunction handleClick() {\n  numberAnimationInstRef.value?.play()\n}\n</script>\n\n<template>\n  <n-statistic label=\"JJJJNM\" tabular-nums>\n    <n-number-animation\n      ref=\"numberAnimationInstRef\"\n      :from=\"0.0\"\n      :to=\"24.0\"\n      :active=\"false\"\n      :precision=\"2\"\n    />\n  </n-statistic>\n  <n-button @click=\"handleClick\">\n    播放\n  </n-button>\n</template>\n"
  },
  {
    "path": "src/number-animation/demos/zhCN/separator.demo.vue",
    "content": "<markdown>\n# 分隔符\n\n欢乐豆太多的时候容易数不清有几位。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { NumberAnimationInst } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst numberAnimationInstRef = ref<NumberAnimationInst | null>(null)\nfunction handleClick() {\n  numberAnimationInstRef.value?.play()\n}\n</script>\n\n<template>\n  <n-statistic label=\"一个小目标\" tabular-nums>\n    <n-number-animation\n      ref=\"numberAnimationInstRef\"\n      show-separator\n      :from=\"0\"\n      :to=\"100000000\"\n      :active=\"false\"\n    />\n  </n-statistic>\n  <n-button @click=\"handleClick\">\n    播放\n  </n-button>\n</template>\n"
  },
  {
    "path": "src/number-animation/index.ts",
    "content": "export {\n  default as NNumberAnimation,\n  numberAnimationProps\n} from './src/NumberAnimation'\nexport type { NumberAnimationProps } from './src/NumberAnimation'\nexport type { NumberAnimationInst } from './src/NumberAnimation'\n"
  },
  {
    "path": "src/number-animation/src/NumberAnimation.tsx",
    "content": "import type { PropType } from 'vue'\nimport type { ExtractPublicPropTypes } from '../../_utils'\nimport { round } from 'lodash-es'\nimport { computed, defineComponent, onMounted, ref, watchEffect } from 'vue'\nimport { useLocale } from '../../_mixins'\nimport { tween } from './utils'\n\nexport const numberAnimationProps = {\n  to: {\n    type: Number,\n    default: 0\n  },\n  precision: {\n    type: Number,\n    default: 0\n  },\n  showSeparator: Boolean,\n  locale: String,\n  from: { type: Number, default: 0 },\n  active: {\n    type: Boolean,\n    default: true\n  },\n  duration: {\n    type: Number,\n    default: 2000\n  },\n  onFinish: Function as PropType<() => void>\n}\n\nexport type NumberAnimationProps = ExtractPublicPropTypes<\n  typeof numberAnimationProps\n>\n\nexport interface NumberAnimationInst {\n  play: () => void\n}\n\nexport default defineComponent({\n  name: 'NumberAnimation',\n  props: numberAnimationProps,\n  setup(props) {\n    const { localeRef } = useLocale('name')\n    const { duration } = props\n    const displayedValueRef = ref(props.from)\n    const mergedLocaleRef = computed(() => {\n      const { locale } = props\n      if (locale !== undefined)\n        return locale\n      return localeRef.value\n    })\n    let animating = false\n    const onUpdate = (currentValue: number): void => {\n      displayedValueRef.value = currentValue\n    }\n    const onFinish = (): void => {\n      displayedValueRef.value = props.to\n      animating = false\n      props.onFinish?.()\n    }\n    const animate = (\n      from: number = props.from,\n      to: number = props.to\n    ): void => {\n      animating = true\n      displayedValueRef.value = props.from\n      if (from !== to) {\n        tween({\n          from,\n          to,\n          duration,\n          onUpdate,\n          onFinish\n        })\n      }\n    }\n    const formattedValueRef = computed(() => {\n      const formatted: string = round(\n        displayedValueRef.value,\n        props.precision\n      ).toFixed(props.precision)\n      const splitValue = formatted.split('.')\n      const numberFormatter = new Intl.NumberFormat(mergedLocaleRef.value)\n      const decimalSeparator = numberFormatter\n        .formatToParts(0.5)\n        .find(part => part.type === 'decimal')\n        ?.value\n      const integer = props.showSeparator\n        ? numberFormatter.format(Number(splitValue[0]))\n        : splitValue[0]\n      const decimal = splitValue[1]\n      return {\n        integer,\n        decimal,\n        decimalSeparator\n      }\n    })\n    function play(): void {\n      if (animating)\n        return\n      animate()\n    }\n    onMounted(() => {\n      watchEffect(() => {\n        if (props.active)\n          animate()\n      })\n    })\n    const exposedMethods: NumberAnimationInst = { play }\n    return {\n      formattedValue: formattedValueRef,\n      ...exposedMethods\n    }\n  },\n  render() {\n    const {\n      formattedValue: { integer, decimal, decimalSeparator }\n    } = this\n    return [integer, decimal ? decimalSeparator : null, decimal]\n  }\n})\n"
  },
  {
    "path": "src/number-animation/src/utils.ts",
    "content": "const easeOut = (t: number): number => 1 - (1 - t) ** 5\n\n// Tween\nexport interface TweenProps {\n  from: number\n  to: number\n  duration: number\n  onUpdate: (currentValue: number) => void\n  onFinish: () => void\n}\n\nexport function tween(props: TweenProps): void {\n  const { from, to, duration, onUpdate, onFinish } = props\n  const startTime = performance.now()\n  const tick = (): void => {\n    const current = performance.now()\n    const elapsedTime = Math.min(current - startTime, duration)\n    const currentValue = from + (to - from) * easeOut(elapsedTime / duration)\n    if (elapsedTime === duration) {\n      onFinish()\n      return\n    }\n    onUpdate(currentValue)\n    requestAnimationFrame(tick)\n  }\n  tick()\n}\n"
  },
  {
    "path": "src/number-animation/tests/NumericAnimation.spec.ts",
    "content": "import { mount } from '@vue/test-utils'\nimport { sleep } from 'seemly'\nimport { NNumberAnimation } from '../index'\n\ndescribe('n-number-animation', () => {\n  it('should work with import on demand', () => {\n    mount(NNumberAnimation)\n  })\n\n  it('should work with `to` prop', async () => {\n    const wrapper = mount(NNumberAnimation, {\n      props: { to: 110, from: 110 }\n    })\n\n    expect(wrapper.text()).toBe('110')\n    wrapper.unmount()\n  })\n\n  it('should work with `from` prop', async () => {\n    const wrapper = mount(NNumberAnimation, {\n      props: { to: 110, from: 10, active: false }\n    })\n\n    expect(wrapper.text()).toBe('10')\n    wrapper.unmount()\n  })\n\n  it('should work with `active` prop', async () => {\n    let wrapper = mount(NNumberAnimation, {\n      props: { to: 110, from: 10 }\n    })\n\n    await sleep(25)\n    expect(wrapper.text()).not.toBe('10')\n    wrapper.unmount()\n\n    wrapper = mount(NNumberAnimation, {\n      props: { to: 110, from: 10, active: false }\n    })\n\n    await sleep(25)\n    expect(wrapper.text()).toBe('10')\n    wrapper.unmount()\n  })\n\n  it('should work with `duration` prop', async () => {\n    const wrapper = mount(NNumberAnimation, {\n      props: { to: 110, from: 10, duration: 20 }\n    })\n    expect(wrapper.text()).not.toBe('110')\n\n    await sleep(100)\n    expect(wrapper.text()).toBe('110')\n    wrapper.unmount()\n  })\n\n  it('should work with `precision` prop', async () => {\n    const wrapper = mount(NNumberAnimation, {\n      props: { to: 10, from: 10, active: false }\n    })\n    expect(wrapper.text()).toBe('10')\n\n    await wrapper.setProps({ precision: 2 })\n    expect(wrapper.text()).toBe('10.00')\n    wrapper.unmount()\n  })\n\n  it('should work with `show-separator` prop', async () => {\n    const wrapper = mount(NNumberAnimation, {\n      props: { to: 1000000, from: 1000000, active: false }\n    })\n    expect(wrapper.text()).toBe('1000000')\n\n    await wrapper.setProps({ showSeparator: true })\n    expect(wrapper.text()).toBe('1,000,000')\n    wrapper.unmount()\n  })\n})\n"
  },
  {
    "path": "src/number-animation/tests/server.spec.tsx",
    "content": "import { setup } from '@css-render/vue3-ssr'\nimport { renderToString } from '@vue/server-renderer'\n/**\n * @vitest-environment node\n */\nimport { createSSRApp, h } from 'vue'\nimport { NNumberAnimation } from '../..'\n\ndescribe('server side rendering', () => {\n  it('works', async () => {\n    const app = createSSRApp(() => <NNumberAnimation />)\n    setup(app)\n    try {\n      await renderToString(app)\n    }\n    catch (e) {\n      expect(e).not.toBeTruthy()\n    }\n  })\n})\n"
  },
  {
    "path": "src/page-header/demos/enUS/basic.demo.vue",
    "content": "<markdown>\n# Basic\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { useMessage } from 'naive-ui'\n\nconst message = useMessage()\n\nfunction handleBack() {\n  message.info('[onBack]')\n}\n\nconst options = [\n  {\n    label: 'More episodes',\n    key: '1'\n  },\n  {\n    label: 'More episodes',\n    key: '2'\n  },\n  {\n    label: 'More episodes',\n    key: '3'\n  }\n]\n</script>\n\n<template>\n  <n-page-header subtitle=\"A podcast to improve designs\" @back=\"handleBack\">\n    <n-grid :cols=\"5\">\n      <n-gi>\n        <n-statistic label=\"Episodes\" value=\"125\" />\n      </n-gi>\n      <n-gi>\n        <n-statistic label=\"Guests\" value=\"22\" />\n      </n-gi>\n      <n-gi>\n        <n-statistic label=\"Apologies\" value=\"36\" />\n      </n-gi>\n      <n-gi>\n        <n-statistic label=\"Topics\" value=\"83\" />\n      </n-gi>\n      <n-gi>\n        <n-statistic label=\"Reference Links\" value=\"2,346\" />\n      </n-gi>\n    </n-grid>\n    <template #title>\n      <a\n        href=\"https://anyway.fm/\"\n        style=\"text-decoration: none; color: inherit\"\n      >\n        Anyway.FM\n      </a>\n    </template>\n    <template #header>\n      <n-breadcrumb>\n        <n-breadcrumb-item>Podcast</n-breadcrumb-item>\n        <n-breadcrumb-item>Best Collection</n-breadcrumb-item>\n        <n-breadcrumb-item>Ultimate Best Collection</n-breadcrumb-item>\n        <n-breadcrumb-item>Anyway.FM</n-breadcrumb-item>\n      </n-breadcrumb>\n    </template>\n    <template #avatar>\n      <n-avatar\n        src=\"https://cdnimg103.lizhi.fm/user/2017/02/04/2583325032200238082_160x160.jpg\"\n      />\n    </template>\n    <template #extra>\n      <n-space>\n        <n-button>Refresh</n-button>\n        <n-dropdown :options=\"options\" placement=\"bottom-start\">\n          <n-button :bordered=\"false\" style=\"padding: 0 4px\">\n            ···\n          </n-button>\n        </n-dropdown>\n      </n-space>\n    </template>\n    <template #footer>\n      As of April 3, 2021\n    </template>\n  </n-page-header>\n</template>\n"
  },
  {
    "path": "src/page-header/demos/enUS/index.demo-entry.md",
    "content": "<!--single-column-->\n\n# PageHeader\n\nI hope this component has all the slots you need!\n\n## Demos\n\n```demo\nbasic.vue\n```\n\n## API\n\n### PageHeader Props\n\n| Name | Type | Default | Description |\n| --- | --- | --- | --- |\n| extra | `string` | `undefined` | Extra text information. Is overwritten by the `extra` slot so only use one. |\n| subtitle | `string` | `undefined` | Subtitle. |\n| title | `string` | `undefined` | Title. |\n| on-back | `() => void` | `undefined` | Callback for when the back button is pressed. |\n\n### PageHeader Slots\n\n| Name     | Parameters | Description           | Version |\n| -------- | ---------- | --------------------- | ------- |\n| avatar   | `()`       | Image information.    |         |\n| header   | `()`       | Header information.   |         |\n| default  | `()`       | Content.              |         |\n| extra    | `()`       | Extra information.    |         |\n| footer   | `()`       | Footer information.   |         |\n| subtitle | `()`       | Subtitle information. |         |\n| title    | `()`       | Title information.    |         |\n| back     | `()`       | Back icon.            | 2.24.2  |\n"
  },
  {
    "path": "src/page-header/demos/zhCN/basic.demo.vue",
    "content": "<markdown>\n# 基础用法\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { useMessage } from 'naive-ui'\n\nconst message = useMessage()\n\nfunction handleBack() {\n  message.info('[onBack]')\n}\n\nconst options = [\n  {\n    label: '催更',\n    key: '1'\n  },\n  {\n    label: '催更',\n    key: '2'\n  },\n  {\n    label: '催更',\n    key: '3'\n  }\n]\n</script>\n\n<template>\n  <n-page-header subtitle=\"让你的听觉更懂视觉\" @back=\"handleBack\">\n    <n-grid :cols=\"5\">\n      <n-gi>\n        <n-statistic label=\"正片\" value=\"125 集\" />\n      </n-gi>\n      <n-gi>\n        <n-statistic label=\"嘉宾\" value=\"22 位\" />\n      </n-gi>\n      <n-gi>\n        <n-statistic label=\"道歉\" value=\"36 次\" />\n      </n-gi>\n      <n-gi>\n        <n-statistic label=\"话题\" value=\"83 个\" />\n      </n-gi>\n      <n-gi>\n        <n-statistic label=\"参考链接\" value=\"2,346 个\" />\n      </n-gi>\n    </n-grid>\n    <template #title>\n      <a href=\"https://anyway.fm/\" style=\"text-decoration: none; color: inherit\">Anyway.FM</a>\n    </template>\n    <template #header>\n      <n-breadcrumb>\n        <n-breadcrumb-item>播客</n-breadcrumb-item>\n        <n-breadcrumb-item>精选</n-breadcrumb-item>\n        <n-breadcrumb-item>超级精选</n-breadcrumb-item>\n        <n-breadcrumb-item>Anyway.FM</n-breadcrumb-item>\n      </n-breadcrumb>\n    </template>\n    <template #avatar>\n      <n-avatar\n        src=\"https://cdnimg103.lizhi.fm/user/2017/02/04/2583325032200238082_160x160.jpg\"\n      />\n    </template>\n    <template #extra>\n      <n-space>\n        <n-button>催更</n-button>\n        <n-dropdown :options=\"options\" placement=\"bottom-start\">\n          <n-button :bordered=\"false\" style=\"padding: 0 4px\">\n            ···\n          </n-button>\n        </n-dropdown>\n      </n-space>\n    </template>\n    <template #footer>\n      截止到 2021 年 4 月 3 日\n    </template>\n  </n-page-header>\n</template>\n"
  },
  {
    "path": "src/page-header/demos/zhCN/index.demo-entry.md",
    "content": "<!--single-column-->\n\n# 页头 PageHeader\n\n我感觉你很可能用不上这个组件，因为根据你拿到的设计稿很可能是重写一个简单。\n\n## 演示\n\n```demo\nbasic.vue\nrtl-debug.vue\n```\n\n## API\n\n### PageHeader Props\n\n| 名称 | 类型 | 默认值 | 说明 |\n| --- | --- | --- | --- |\n| extra | `string` | `undefined` | 额外的文本信息，当使用 `extra` 插槽时该参数无效 |\n| subtitle | `string` | `undefined` | 副标题 |\n| title | `string` | `undefined` | 主标题 |\n| on-back | `() => void` | `undefined` | 点击返回按钮的回调 |\n\n### PageHeader Slots\n\n| 名称     | 参数 | 说明       | 版本   |\n| -------- | ---- | ---------- | ------ |\n| avatar   | `()` | 图片信息   |        |\n| header   | `()` | 头部信息   |        |\n| default  | `()` | 内容       |        |\n| extra    | `()` | 额外信息   |        |\n| footer   | `()` | 底部信息   |        |\n| subtitle | `()` | 副标题信息 |        |\n| title    | `()` | 标题信息   |        |\n| back     | `()` | 返回图标   | 2.24.2 |\n"
  },
  {
    "path": "src/page-header/demos/zhCN/rtl-debug.demo.vue",
    "content": "<markdown>\n# Rtl Debug\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { unstablePageHeaderRtl, useMessage } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst message = useMessage()\nconst rtlEnabled = ref(false)\nconst rtlStyles = [unstablePageHeaderRtl]\n\nfunction handleBack() {\n  message.info('[onBack]')\n}\n\nconst options = [\n  {\n    label: '催更',\n    key: '1'\n  },\n  {\n    label: '催更',\n    key: '2'\n  },\n  {\n    label: '催更',\n    key: '3'\n  }\n]\n</script>\n\n<template>\n  <n-space vertical>\n    <n-space><n-switch v-model:value=\"rtlEnabled\" />Rtl</n-space>\n    <n-config-provider :rtl=\"rtlEnabled ? rtlStyles : undefined\">\n      <n-page-header subtitle=\"让你的听觉更懂视觉\" @back=\"handleBack\">\n        <n-grid :cols=\"5\">\n          <n-gi>\n            <n-statistic label=\"正片\" value=\"125 集\" />\n          </n-gi>\n          <n-gi>\n            <n-statistic label=\"嘉宾\" value=\"22 位\" />\n          </n-gi>\n          <n-gi>\n            <n-statistic label=\"道歉\" value=\"36 次\" />\n          </n-gi>\n          <n-gi>\n            <n-statistic label=\"话题\" value=\"83 个\" />\n          </n-gi>\n          <n-gi>\n            <n-statistic label=\"参考链接\" value=\"2,346 个\" />\n          </n-gi>\n        </n-grid>\n        <template #title>\n          <a\n            href=\"https://anyway.fm/\"\n            style=\"text-decoration: none; color: inherit\"\n          >Anyway.FM</a>\n        </template>\n        <template #header>\n          <n-breadcrumb>\n            <n-breadcrumb-item>播客</n-breadcrumb-item>\n            <n-breadcrumb-item>精选</n-breadcrumb-item>\n            <n-breadcrumb-item>超级精选</n-breadcrumb-item>\n            <n-breadcrumb-item>Anyway.FM</n-breadcrumb-item>\n          </n-breadcrumb>\n        </template>\n        <template #avatar>\n          <n-avatar\n            src=\"https://cdnimg103.lizhi.fm/user/2017/02/04/2583325032200238082_160x160.jpg\"\n          />\n        </template>\n        <template #extra>\n          <n-space>\n            <n-button>催更</n-button>\n            <n-dropdown :options=\"options\" placement=\"bottom-start\">\n              <n-button :bordered=\"false\" style=\"padding: 0 4px\">\n                ···\n              </n-button>\n            </n-dropdown>\n          </n-space>\n        </template>\n        <template #footer>\n          截止到 2021 年 4 月 3 日\n        </template>\n      </n-page-header>\n    </n-config-provider>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/page-header/index.ts",
    "content": "export { default as NPageHeader, pageHeaderProps } from './src/PageHeader'\nexport type { PageHeaderProps, PageHeaderSlots } from './src/PageHeader'\n"
  },
  {
    "path": "src/page-header/src/PageHeader.tsx",
    "content": "import type { PropType, SlotsType, VNode } from 'vue'\nimport type { ThemeProps } from '../../_mixins'\nimport type { ExtractPublicPropTypes } from '../../_utils'\nimport type { PageHeaderTheme } from '../styles/light'\nimport { computed, defineComponent, h } from 'vue'\nimport { NBaseIcon } from '../../_internal'\nimport { ArrowBackIcon } from '../../_internal/icons'\nimport { useConfig, useTheme, useThemeClass } from '../../_mixins'\nimport { useRtl } from '../../_mixins/use-rtl'\nimport { pageHeaderLight } from '../styles/light'\nimport style from './styles/index.cssr'\n\nexport const pageHeaderProps = {\n  ...(useTheme.props as ThemeProps<PageHeaderTheme>),\n  title: String,\n  subtitle: String,\n  extra: String,\n  onBack: Function as PropType<() => void>\n}\n\nexport type PageHeaderProps = ExtractPublicPropTypes<typeof pageHeaderProps>\n\nexport interface PageHeaderSlots {\n  avatar?: () => VNode[]\n  header?: () => VNode[]\n  default?: () => VNode[]\n  extra?: () => VNode[]\n  footer?: () => VNode[]\n  subtitle?: () => VNode[]\n  title?: () => VNode[]\n  back?: () => VNode[]\n}\n\nexport default defineComponent({\n  name: 'PageHeader',\n  props: pageHeaderProps,\n  slots: Object as SlotsType<PageHeaderSlots>,\n  setup(props) {\n    const { mergedClsPrefixRef, mergedRtlRef, inlineThemeDisabled }\n      = useConfig(props)\n    const themeRef = useTheme(\n      'PageHeader',\n      '-page-header',\n      style,\n      pageHeaderLight,\n      props,\n      mergedClsPrefixRef\n    )\n    const rtlEnabledRef = useRtl('PageHeader', mergedRtlRef, mergedClsPrefixRef)\n    const cssVarsRef = computed(() => {\n      const {\n        self: {\n          titleTextColor,\n          subtitleTextColor,\n          backColor,\n          fontSize,\n          titleFontSize,\n          backSize,\n          titleFontWeight,\n          backColorHover,\n          backColorPressed\n        },\n        common: { cubicBezierEaseInOut }\n      } = themeRef.value\n      return {\n        '--n-title-text-color': titleTextColor,\n        '--n-title-font-size': titleFontSize,\n        '--n-title-font-weight': titleFontWeight,\n        '--n-font-size': fontSize,\n        '--n-back-size': backSize,\n        '--n-subtitle-text-color': subtitleTextColor,\n        '--n-back-color': backColor,\n        '--n-back-color-hover': backColorHover,\n        '--n-back-color-pressed': backColorPressed,\n        '--n-bezier': cubicBezierEaseInOut\n      }\n    })\n    const themeClassHandle = inlineThemeDisabled\n      ? useThemeClass('page-header', undefined, cssVarsRef, props)\n      : undefined\n    return {\n      rtlEnabled: rtlEnabledRef,\n      mergedClsPrefix: mergedClsPrefixRef,\n      cssVars: inlineThemeDisabled ? undefined : cssVarsRef,\n      themeClass: themeClassHandle?.themeClass,\n      onRender: themeClassHandle?.onRender\n    }\n  },\n  render() {\n    const { onBack, title, subtitle, extra, mergedClsPrefix, cssVars, $slots }\n      = this\n    this.onRender?.()\n    const {\n      title: titleSlot,\n      subtitle: subtitleSlot,\n      extra: extraSlot,\n      default: defaultSlot,\n      header: headerSlot,\n      avatar: avatarSlot,\n      footer: footerSlot,\n      back: backSlot\n    } = $slots\n    const showBack = onBack\n    const showTitle = title || titleSlot\n    const showSubtitle = subtitle || subtitleSlot\n    const showExtra = extra || extraSlot\n    return (\n      <div\n        style={cssVars as any}\n        class={[\n          `${mergedClsPrefix}-page-header-wrapper`,\n          this.themeClass,\n          this.rtlEnabled && `${mergedClsPrefix}-page-header-wrapper--rtl`\n        ]}\n      >\n        {headerSlot ? (\n          <div class={`${mergedClsPrefix}-page-header-header`} key=\"breadcrumb\">\n            {headerSlot()}\n          </div>\n        ) : null}\n        {(showBack || avatarSlot || showTitle || showSubtitle || showExtra) && (\n          <div class={`${mergedClsPrefix}-page-header`} key=\"header\">\n            <div class={`${mergedClsPrefix}-page-header__main`} key=\"back\">\n              {showBack ? (\n                <div\n                  class={`${mergedClsPrefix}-page-header__back`}\n                  onClick={onBack}\n                >\n                  {backSlot ? (\n                    backSlot()\n                  ) : (\n                    <NBaseIcon clsPrefix={mergedClsPrefix}>\n                      {{\n                        default: () => <ArrowBackIcon />\n                      }}\n                    </NBaseIcon>\n                  )}\n                </div>\n              ) : null}\n              {avatarSlot ? (\n                <div class={`${mergedClsPrefix}-page-header__avatar`}>\n                  {avatarSlot()}\n                </div>\n              ) : null}\n              {showTitle ? (\n                <div\n                  class={`${mergedClsPrefix}-page-header__title`}\n                  key=\"title\"\n                >\n                  {title || titleSlot!()}\n                </div>\n              ) : null}\n              {showSubtitle ? (\n                <div\n                  class={`${mergedClsPrefix}-page-header__subtitle`}\n                  key=\"subtitle\"\n                >\n                  {subtitle || subtitleSlot!()}\n                </div>\n              ) : null}\n            </div>\n            {showExtra ? (\n              <div class={`${mergedClsPrefix}-page-header__extra`}>\n                {extra || extraSlot!()}\n              </div>\n            ) : null}\n          </div>\n        )}\n        {defaultSlot ? (\n          <div class={`${mergedClsPrefix}-page-header-content`} key=\"content\">\n            {defaultSlot()}\n          </div>\n        ) : null}\n        {footerSlot ? (\n          <div class={`${mergedClsPrefix}-page-header-footer`} key=\"footer\">\n            {footerSlot()}\n          </div>\n        ) : null}\n      </div>\n    )\n  }\n})\n"
  },
  {
    "path": "src/page-header/src/styles/index.cssr.ts",
    "content": "import { c, cB, cE } from '../../../_utils/cssr'\n\n// vars:\n// --n-title-font-size\n// --n-title-text-color\n// --n-font-size\n// --n-subtitle-text-color\n// --n-back-color\n// --n-back-color-hover\n// --n-back-color-pressed\n// --n-back-size\n// --n-title-font-weight\n// --n-bezier\nexport default c([\n  cB('page-header-header', `\n    margin-bottom: 20px;\n  `),\n  cB('page-header', `\n    display: flex;\n    align-items: center;\n    justify-content: space-between;\n    line-height: 1.5;\n    font-size: var(--n-font-size);\n  `, [\n    cE('main', `\n      display: flex;\n      flex-wrap: nowrap;\n      align-items: center;\n    `),\n    cE('back', `\n      display: flex;\n      margin-right: 16px;\n      font-size: var(--n-back-size);\n      cursor: pointer;\n      color: var(--n-back-color);\n      transition: color .3s var(--n-bezier);\n    `, [\n      c('&:hover', 'color: var(--n-back-color-hover);'),\n      c('&:active', 'color: var(--n-back-color-pressed);')\n    ]),\n    cE('avatar', `\n      display: flex;\n      margin-right: 12px\n    `),\n    cE('title', `\n      margin-right: 16px;\n      transition: color .3s var(--n-bezier);\n      font-size: var(--n-title-font-size);\n      font-weight: var(--n-title-font-weight);\n      color: var(--n-title-text-color);\n    `),\n    cE('subtitle', `\n      font-size: 14px;\n      transition: color .3s var(--n-bezier);\n      color: var(--n-subtitle-text-color);\n    `)\n  ]),\n  cB('page-header-content', `\n    font-size: var(--n-font-size);\n  `, [\n    c('&:not(:first-child)', 'margin-top: 20px;')\n  ]),\n  cB('page-header-footer', `\n    font-size: var(--n-font-size);\n  `, [\n    c('&:not(:first-child)', 'margin-top: 20px;')\n  ])\n])\n"
  },
  {
    "path": "src/page-header/src/styles/rtl.cssr.ts",
    "content": "import { cB, cE, cM } from '../../../_utils/cssr'\n\nexport default cB('page-header-wrapper', [\n  cM('rtl', [\n    cB('page-header-header', `\n      direction: rtl;\n    `),\n    cB('page-header', `\n      direction: rtl;\n    `, [\n      cE('back', `\n        margin-right: 0;\n        margin-left: 16px;\n      `),\n      cE('avatar', `\n        margin-right: 0;\n        margin-left: 12px;\n      `),\n      cE('title', `\n        margin-right: 0;\n        margin-left: 16px;\n      `)\n    ]),\n    cB('page-header-content', `\n      direction: rtl;\n    `),\n    cB('page-header-footer', `\n      direction: rtl;\n    `)\n  ])\n])\n"
  },
  {
    "path": "src/page-header/styles/_common.ts",
    "content": "export default {\n  titleFontSize: '18px',\n  backSize: '22px'\n}\n"
  },
  {
    "path": "src/page-header/styles/dark.ts",
    "content": "import type { PageHeaderTheme } from './light'\nimport { commonDark } from '../../_styles/common'\nimport { self } from './light'\n\nexport const pageHeaderDark: PageHeaderTheme = {\n  name: 'PageHeader',\n  common: commonDark,\n  self\n}\n"
  },
  {
    "path": "src/page-header/styles/index.ts",
    "content": "export { pageHeaderDark } from './dark'\nexport { pageHeaderLight } from './light'\nexport type { PageHeaderTheme, PageHeaderThemeVars } from './light'\nexport { default as pageHeaderRtl } from './rtl'\n"
  },
  {
    "path": "src/page-header/styles/light.ts",
    "content": "import type { ThemeCommonVars } from '../../_styles/common'\nimport { createTheme } from '../../_mixins'\nimport { commonLight } from '../../_styles/common'\nimport common from './_common'\n\nexport function self(vars: ThemeCommonVars) {\n  const {\n    textColor1,\n    textColor2,\n    textColor3,\n    fontSize,\n    fontWeightStrong,\n    primaryColorHover,\n    primaryColorPressed\n  } = vars\n  return {\n    ...common,\n    titleFontWeight: fontWeightStrong,\n    fontSize,\n    titleTextColor: textColor1,\n    backColor: textColor2,\n    backColorHover: primaryColorHover,\n    backColorPressed: primaryColorPressed,\n    subtitleTextColor: textColor3\n  }\n}\n\nexport const pageHeaderLight = createTheme({\n  name: 'PageHeader',\n  common: commonLight,\n  self\n})\n\nexport type PageHeaderThemeVars = ReturnType<typeof self>\nexport type PageHeaderTheme = typeof pageHeaderLight\n"
  },
  {
    "path": "src/page-header/styles/rtl.ts",
    "content": "import rtlStyle from '../src/styles/rtl.cssr'\n\nexport default {\n  name: 'PageHeader',\n  style: rtlStyle\n}\n"
  },
  {
    "path": "src/page-header/tests/PageHeader.spec.tsx",
    "content": "import { mount } from '@vue/test-utils'\nimport { NPageHeader } from '../index'\n\ndescribe('n-page-header', () => {\n  it('should work with page header', () => {\n    mount(NPageHeader)\n  })\n\n  it('should work with `title` prop', async () => {\n    const wrapper = mount(NPageHeader, { props: { title: 'test-title' } })\n\n    expect(wrapper.find('.n-page-header__title').exists()).toBe(true)\n    expect(wrapper.find('.n-page-header__title').html()).toContain('test-title')\n    wrapper.unmount()\n  })\n\n  it('should work with `extra` prop', async () => {\n    const wrapper = mount(NPageHeader, { props: { extra: 'test-extra' } })\n\n    expect(wrapper.find('.n-page-header__extra').exists()).toBe(true)\n    expect(wrapper.find('.n-page-header__extra').html()).toContain('test-extra')\n    wrapper.unmount()\n  })\n\n  it('should work with `subtitle` prop', async () => {\n    const wrapper = mount(NPageHeader, { props: { subtitle: 'test-subtitle' } })\n\n    expect(wrapper.find('.n-page-header__subtitle').exists()).toBe(true)\n    expect(wrapper.find('.n-page-header__subtitle').html()).toContain(\n      'test-subtitle'\n    )\n    wrapper.unmount()\n  })\n\n  it('should work with `on-back` prop', async () => {\n    const handleOnBack = vi.fn()\n    const wrapper = mount(NPageHeader, { props: { onBack: handleOnBack } })\n\n    expect(wrapper.find('.n-page-header__back').exists()).toBe(true)\n    await wrapper.find('.n-page-header__back').trigger('click')\n    expect(handleOnBack).toHaveBeenCalled()\n    wrapper.unmount()\n  })\n\n  it('should work with slots', async () => {\n    const wrapper = mount(NPageHeader, {\n      props: { onBack: () => {} },\n      slots: {\n        avatar: () => 'avatar-slot',\n        header: () => 'header-slot',\n        default: () => 'default-slot',\n        extra: () => 'extra-slot',\n        footer: () => 'footer-slot',\n        subtitle: () => 'subtitle-slot',\n        title: () => 'title-slot',\n        back: () => 'back-slot'\n      }\n    })\n\n    expect(wrapper.find('.n-page-header__avatar').exists()).toBe(true)\n    expect(wrapper.find('.n-page-header__avatar').html()).toContain(\n      'avatar-slot'\n    )\n    expect(wrapper.find('.n-page-header-header').exists()).toBe(true)\n    expect(wrapper.find('.n-page-header-header').html()).toContain(\n      'header-slot'\n    )\n    expect(wrapper.find('.n-page-header-content').exists()).toBe(true)\n    expect(wrapper.find('.n-page-header-content').html()).toContain(\n      'default-slot'\n    )\n    expect(wrapper.find('.n-page-header__extra').exists()).toBe(true)\n    expect(wrapper.find('.n-page-header__extra').html()).toContain('extra-slot')\n    expect(wrapper.find('.n-page-header-footer').exists()).toBe(true)\n    expect(wrapper.find('.n-page-header-footer').html()).toContain(\n      'footer-slot'\n    )\n    expect(wrapper.find('.n-page-header__subtitle').exists()).toBe(true)\n    expect(wrapper.find('.n-page-header__subtitle').html()).toContain(\n      'subtitle-slot'\n    )\n    expect(wrapper.find('.n-page-header__title').exists()).toBe(true)\n    expect(wrapper.find('.n-page-header__title').html()).toContain('title-slot')\n    expect(wrapper.find('.n-page-header__back').exists()).toBe(true)\n    expect(wrapper.find('.n-page-header__back').html()).toContain('back-slot')\n    wrapper.unmount()\n  })\n})\n"
  },
  {
    "path": "src/page-header/tests/server.spec.tsx",
    "content": "import { setup } from '@css-render/vue3-ssr'\nimport { renderToString } from '@vue/server-renderer'\n/**\n * @vitest-environment node\n */\nimport { createSSRApp, h } from 'vue'\nimport { NPageHeader } from '../..'\n\ndescribe('server side rendering', () => {\n  it('works', async () => {\n    const app = createSSRApp(() => <NPageHeader />)\n    setup(app)\n    try {\n      await renderToString(app)\n    }\n    catch (e) {\n      expect(e).not.toBeTruthy()\n    }\n  })\n})\n"
  },
  {
    "path": "src/pagination/demos/enUS/basic.demo.vue",
    "content": "<markdown>\n# Basic\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst page = ref(2)\n</script>\n\n<template>\n  <n-pagination v-model:page=\"page\" :page-count=\"100\" />\n</template>\n"
  },
  {
    "path": "src/pagination/demos/enUS/disabled.demo.vue",
    "content": "<markdown>\n# Disabled\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst page = ref(2)\nconst pageSize = ref(20)\nconst disabled = ref(true)\n</script>\n\n<template>\n  <n-space vertical>\n    <n-pagination\n      v-model:page=\"page\"\n      v-model:page-size=\"pageSize\"\n      :page-count=\"100\"\n      show-size-picker\n      :page-sizes=\"[10, 20, 30, 40]\"\n      show-quick-jumper\n      :disabled=\"disabled\"\n    />\n    <n-switch v-model:value=\"disabled\" />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/pagination/demos/enUS/index.demo-entry.md",
    "content": "# Pagination\n\n<!--single-column-->\n\nLong data's friend.\n\n## Demos\n\n```demo\nbasic.vue\nsimple.vue\nslot.vue\nquick-jumper.vue\nsize.vue\nsize-picker.vue\ndisabled.vue\nitem-count.vue\nprev.vue\nprefix.vue\npage-size-option.vue\n```\n\n## API\n\n### Pagination Props\n\n| Name | Type | Default | Description | Version |\n| --- | --- | --- | --- | --- |\n| default-page | `number` | `1` | Current page in uncontrolled mode. |  |\n| default-page-size | `number` | `10` | Page size in uncontrolled mode. |  |\n| disabled | `boolean` | `false` | Whether to disable the pagination. |  |\n| display-order | `Array<'pages' \\| 'size-picker' \\| 'quick-jumper'>` | `['pages', 'size-picker', 'quick-jumper']` | Display order of different parts. | 2.32.2 |\n| goto | `() => VNodeChild` | `undefined` | Fast jump content render function. | 2.34.3 |\n| item-count | `number` | `undefined` | Total number. |  |\n| next | `(info: PaginationInfo) => VNodeChild` | `undefined` | Next page. |  |\n| prev | `(info: PaginationInfo) => VNodeChild` | `undefined` | Previous page. |  |\n| label | `PaginationRenderLabel` | `undefined` | Item content. | 2.24.0 |\n| page-count | `number` | `1` | Total pages. |  |\n| page-sizes | `Array<number \\| PaginationSizeOption>` | `[10]` | Number of items per page, can be customize. |  |\n| page-size | `number` | `undefined` | Page size in controlled mode. |  |\n| page-slot | `number` | `9` | The number of pages displayed. |  |\n| page | `number` | `undefined` | Current page in controlled mode. |  |\n| prefix | `(info: PaginationInfo) => VNodeChild` | `undefined` | Paging prefix. |  |\n| scrollbar-props | `ScrollbarProps` | `undefined` | See [Scrollbar props](scrollbar#Scrollbar-Props) | 2.44.0 |\n| select-props | `SelectProps` | `undefined` | Page size select's props. | 2.34.3 |\n| show-quick-jumper | `boolean` | `false` | Whether to show quick jump input. |  |\n| show-quick-jump-dropdown | `boolean` | `true` | Whether to show quick jump dropdown. If you have too many pages, it could cause performance issue to create quick jump dropdown data. You can set it to `false` to enhance render performance. | 2.37.0 |\n| size | `'small' \\| 'medium' \\| 'large'` | `'medium'` | size of page item. | 2.29.0 |\n| simple | `boolean` | `false` | Whether to use simple mode. | 2.32.2 |\n| suffix | `(info: PaginationInfo) => VNodeChild` | `undefined` | Page suffix. |  |\n| show-size-picker | `boolean` | `false` | Whether to show the selector of the number of items per page. |  |\n| to | `string \\| HTMLElement \\| false` | `body` | Container node of the pop menu. `false` will keep it not detached. | 2.33.4 |\n| on-update:page | `(page: number) => void` | `undefined` | Callback function when the current page changes. |  |\n| on-update:page-size | `(pageSize: number) => void` | `undefined` | Callback function when the current page size changes. |  |\n\n#### PaginationRenderLabel Type\n\n```ts\ntype PaginationRenderLabel = (\n  info:\n    | {\n      type: 'fast-backward' | 'fast-forward'\n      node: VNode\n      active: boolean\n    }\n    | {\n      type: 'page'\n      node: number\n      active: boolean\n    }\n) => VNodeChild\n```\n\n#### PaginationInfo Type\n\n```ts\ninterface PaginationInfo {\n  startIndex: number\n  endIndex: number\n  page: number\n  pageSize: number\n  pageCount: number\n  itemCount: number | undefined\n}\n```\n\n### Pagination Slots\n\n| Name | Parameters | Description | Version |\n| --- | --- | --- | --- |\n| goto | `()` | Fast jump text before quick jumper. | 2.27.0 |\n| label | The same as `PaginationRenderLabel`'s parameters | Item content. | 2.24.0 |\n| next | `(info: PaginationInfo)` | Next page. |  |\n| prev | `(info: PaginationInfo)` | Previous page. |  |\n| prefix | `(info: PaginationInfo)` | Page prefix. |  |\n| suffix | `(info: PaginationInfo)` | Page suffix. |  |\n"
  },
  {
    "path": "src/pagination/demos/enUS/item-count.demo.vue",
    "content": "<markdown>\n# Use item count\n\nSometime you don't want set `page-count`. At that time you may use `item-count` and `page-size`.\n</markdown>\n\n<template>\n  <n-pagination\n    :item-count=\"201\"\n    :page-sizes=\"[10, 20, 30, 40]\"\n    show-size-picker\n  />\n</template>\n"
  },
  {
    "path": "src/pagination/demos/enUS/page-size-option.demo.vue",
    "content": "<markdown>\n# Custom page size options\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst pageSizes = [\n  {\n    label: '10 per page',\n    value: 10\n  },\n  {\n    label: '20 per page',\n    value: 20\n  },\n  {\n    label: '30 per page',\n    value: 30\n  },\n  {\n    label: '40 per page',\n    value: 40\n  }\n]\n\nconst page = ref(2)\nconst pageSize = ref(20)\n</script>\n\n<template>\n  <n-pagination\n    v-model:page=\"page\"\n    v-model:page-size=\"pageSize\"\n    :page-count=\"100\"\n    show-size-picker\n    :page-sizes=\"pageSizes\"\n  />\n</template>\n"
  },
  {
    "path": "src/pagination/demos/enUS/prefix.demo.vue",
    "content": "<markdown>\n# Prefix & suffix\n\nYou may want to add something before and after.\n</markdown>\n\n<template>\n  <n-pagination :item-count=\"101\">\n    <template #prefix=\"{ itemCount, startIndex }\">\n      From Item No.{{ startIndex }}, Total is {{ itemCount }}\n    </template>\n    <template #suffix=\"{ endIndex }\">\n      To Item No.{{ endIndex }}\n    </template>\n  </n-pagination>\n</template>\n"
  },
  {
    "path": "src/pagination/demos/enUS/prev.demo.vue",
    "content": "<markdown>\n# Customize the previous and next button\n</markdown>\n\n<template>\n  <n-pagination :page-count=\"101\">\n    <template #prev>\n      Go Prev\n    </template>\n    <template #next>\n      Go Next\n    </template>\n  </n-pagination>\n</template>\n"
  },
  {
    "path": "src/pagination/demos/enUS/quick-jumper.demo.vue",
    "content": "<markdown>\n# Quick jumper\n\nYou can customize the content to jump to (press `Enter` to jump quickly).\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst page = ref(2)\n</script>\n\n<template>\n  <n-space vertical>\n    <n-pagination :page-count=\"100\" show-quick-jumper>\n      <template #goto>\n        Go!\n      </template>\n    </n-pagination>\n    <n-pagination v-model:page=\"page\" :page-count=\"100\" show-quick-jumper>\n      <template #goto>\n        Go!\n      </template>\n    </n-pagination>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/pagination/demos/enUS/simple.demo.vue",
    "content": "<markdown>\n# Simple mode\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst page = ref(2)\n</script>\n\n<template>\n  <n-pagination v-model:page=\"page\" :page-count=\"100\" simple />\n</template>\n"
  },
  {
    "path": "src/pagination/demos/enUS/size-picker.demo.vue",
    "content": "<markdown>\n# Size picker\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst page = ref(2)\nconst pageSize = ref(20)\n</script>\n\n<template>\n  <n-pagination\n    v-model:page=\"page\"\n    v-model:page-size=\"pageSize\"\n    :page-count=\"100\"\n    show-size-picker\n    :page-sizes=\"[10, 20, 30, 40]\"\n  />\n</template>\n"
  },
  {
    "path": "src/pagination/demos/enUS/size.demo.vue",
    "content": "<markdown>\n# Size\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst page = ref(2)\n</script>\n\n<template>\n  <n-space vertical>\n    <n-pagination\n      v-model:page=\"page\"\n      :page-count=\"100\"\n      size=\"small\"\n      show-quick-jumper\n      show-size-picker\n    />\n    <n-pagination\n      v-model:page=\"page\"\n      :page-count=\"100\"\n      size=\"medium\"\n      show-quick-jumper\n      show-size-picker\n    />\n    <n-pagination\n      v-model:page=\"page\"\n      :page-count=\"100\"\n      size=\"large\"\n      show-quick-jumper\n      show-size-picker\n    />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/pagination/demos/enUS/slot.demo.vue",
    "content": "<markdown>\n# Page slot\n\nThe pagination has a property `page-slot`, try it and you will understand. It aims to solving misclicks caused by the length changing of pagination.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst page = ref(2)\n</script>\n\n<template>\n  <n-space vertical>\n    <n-pagination v-model:page=\"page\" :page-count=\"100\" />\n    <n-pagination v-model:page=\"page\" :page-count=\"100\" :page-slot=\"8\" />\n    <n-pagination v-model:page=\"page\" :page-count=\"100\" :page-slot=\"7\" />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/pagination/demos/zhCN/basic.demo.vue",
    "content": "<markdown>\n# 基础用法\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst page = ref(2)\n</script>\n\n<template>\n  <n-pagination v-model:page=\"page\" :page-count=\"100\" />\n</template>\n"
  },
  {
    "path": "src/pagination/demos/zhCN/disabled.demo.vue",
    "content": "<markdown>\n# 禁用\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst page = ref(2)\nconst pageSize = ref(20)\nconst disabled = ref(true)\n</script>\n\n<template>\n  <n-space vertical>\n    <n-pagination\n      v-model:page=\"page\"\n      v-model:page-size=\"pageSize\"\n      :page-count=\"100\"\n      show-size-picker\n      :page-sizes=\"[10, 20, 30, 40]\"\n      show-quick-jumper\n      :disabled=\"disabled\"\n    />\n    <n-switch v-model:value=\"disabled\" />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/pagination/demos/zhCN/display-order.demo.vue",
    "content": "<markdown>\n# 展示顺序\n\n你可以通过 `display-order` 来调整展示顺序。\n</markdown>\n\n<template>\n  <n-pagination\n    :display-order=\"['quick-jumper', 'pages', 'size-picker']\"\n    :page-count=\"100\"\n    show-quick-jumper\n    show-size-picker\n  />\n</template>\n"
  },
  {
    "path": "src/pagination/demos/zhCN/index.demo-entry.md",
    "content": "# 分页 Pagination\n\n<!--single-column-->\n\n长数据之友。\n\n## 演示\n\n```demo\nbasic.vue\nsimple.vue\nslot.vue\nquick-jumper.vue\nsize.vue\nsize-picker.vue\ndisabled.vue\nitem-count.vue\nprev.vue\nprefix.vue\npage-size-option.vue\ndisplay-order.vue\nrtl-debug.vue\n```\n\n## API\n\n### Pagination Props\n\n| 名称 | 类型 | 默认值 | 说明 | 版本 |\n| --- | --- | --- | --- | --- |\n| default-page | `number` | `1` | 非受控模式下的当前页 |  |\n| default-page-size | `number` | `10` | 非受控模式下的分页大小 |  |\n| disabled | `boolean` | `false` | 是否禁用 |  |\n| display-order | `Array<'pages' \\| 'size-picker' \\| 'quick-jumper'>` | `['pages', 'size-picker', 'quick-jumper']` | 不同部分的展示顺序 | 2.32.2 |\n| goto | `() => VNodeChild` | `undefined` | 渲染快速跳转的文本内容 | 2.34.3 |\n| item-count | `number` | `undefined` | 总条数 |  |\n| next | `(info: PaginationInfo) => VNodeChild` | `undefined` | 下一页 |  |\n| prev | `(info: PaginationInfo) => VNodeChild` | `undefined` | 上一页 |  |\n| label | `PaginationRenderLabel` | `undefined` | 每一项的内容 | 2.24.0 |\n| page-count | `number` | `1` | 总页数 |  |\n| page-sizes | `Array<number \\| PaginationSizeOption>` | `[10]` | 每页条数， 可自定义 |  |\n| page-size | `number` | `undefined` | 受控模式下的分页大小 |  |\n| page-slot | `number` | `9` | 页码显示的个数 |  |\n| page | `number` | `undefined` | 受控模式下的当前页 |  |\n| prefix | `(info: PaginationInfo) => VNodeChild` | `undefined` | 分页前缀 |  |\n| scrollbar-props | `ScrollbarProps` | `undefined` | 属性参考 [Scrollbar props](scrollbar#Scrollbar-Props) | 2.44.0 |\n| select-props | `SelectProps` | `undefined` | 分页大小选择器的属性 | 2.34.3 |\n| show-quick-jumper | `boolean` | `false` | 是否显示快速跳转 |  |\n| size | `'small' \\| 'medium' \\| 'large'` | `'medium'` | 分页按钮的大小 | 2.29.0 |\n| simple | `boolean` | `false` | 是否显示为简单分页 | 2.32.2 |\n| suffix | `(info: PaginationInfo) => VNodeChild` | `undefined` | 分页后缀 |  |\n| show-size-picker | `boolean` | `false` | 是否显示每页条数的选择器 |  |\n| show-quick-jump-dropdown | `boolean` | `true` | 展示快速跳转的下拉菜单。如果页数过多，可能导致分页的数据创建性能消耗较高，可以通过设为 `false` 来提升性能 | 2.37.0 |\n| to | `string \\| HTMLElement \\| false` | `body` | 弹出菜单的容器节点，`false` 会待在原地 | 2.33.4 |\n| on-update:page | `(page: number) => void` | `undefined` | 当前页发生改变时的回调函数 |  |\n| on-update:page-size | `(pageSize: number) => void` | `undefined` | 当前分页大小发生改变时的回调函数 |  |\n\n#### PaginationRenderLabel Type\n\n```ts\ntype PaginationRenderLabel = (\n  info:\n    | {\n      type: 'fast-backward' | 'fast-forward'\n      node: VNode\n      active: boolean\n    }\n    | {\n      type: 'page'\n      node: number\n      active: boolean\n    }\n) => VNodeChild\n```\n\n#### PaginationInfo Type\n\n```ts\ninterface PaginationInfo {\n  startIndex: number\n  endIndex: number\n  page: number\n  pageSize: number\n  pageCount: number\n  itemCount: number | undefined\n}\n```\n\n### Pagination Slots\n\n| 名称   | 参数                            | 说明               | 版本   |\n| ------ | ------------------------------- | ------------------ | ------ |\n| goto   | `()`                            | 快速跳转的文本内容 | 2.27.0 |\n| label  | 同 `PaginationRenderLabel` 参数 | 每一项的内容       | 2.24.0 |\n| next   | `(info: PaginationInfo)`        | 下一页             |        |\n| prev   | `(info: PaginationInfo)`        | 上一页             |        |\n| prefix | `(info: PaginationInfo)`        | 分页前缀           |        |\n| suffix | `(info: PaginationInfo)`        | 分页后缀           |        |\n"
  },
  {
    "path": "src/pagination/demos/zhCN/item-count.demo.vue",
    "content": "<markdown>\n# 使用元素个数控制分页\n\n有的时候你不想传递 `page-count`，这个时候你可以设定 `item-count` 和 `page-size`。\n</markdown>\n\n<template>\n  <n-pagination\n    :item-count=\"201\"\n    :page-sizes=\"[10, 20, 30, 40]\"\n    show-size-picker\n  />\n</template>\n"
  },
  {
    "path": "src/pagination/demos/zhCN/page-size-option.demo.vue",
    "content": "<markdown>\n# 自定义 PageSizes 选项\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst pageSizes = [\n  {\n    label: '10 每页',\n    value: 10\n  },\n  {\n    label: '20 每页',\n    value: 20\n  },\n  {\n    label: '30 每页',\n    value: 30\n  },\n  {\n    label: '40 每页',\n    value: 40\n  }\n]\n\nconst page = ref(2)\nconst pageSize = ref(20)\n</script>\n\n<template>\n  <n-pagination\n    v-model:page=\"page\"\n    v-model:page-size=\"pageSize\"\n    :page-count=\"100\"\n    show-size-picker\n    :page-sizes=\"pageSizes\"\n  />\n</template>\n"
  },
  {
    "path": "src/pagination/demos/zhCN/prefix.demo.vue",
    "content": "<markdown>\n# 前后缀\n\n你可能想在前后都加点啥。\n</markdown>\n\n<template>\n  <n-pagination :item-count=\"101\">\n    <template #prefix=\"{ itemCount, startIndex }\">\n      从第 {{ startIndex }} 项开始, 共 {{ itemCount }} 项\n    </template>\n    <template #suffix=\"{ endIndex }\">\n      从第 {{ endIndex }} 项结束\n    </template>\n  </n-pagination>\n</template>\n"
  },
  {
    "path": "src/pagination/demos/zhCN/prev.demo.vue",
    "content": "<markdown>\n# 自定义上一步和下一步\n</markdown>\n\n<template>\n  <n-pagination :page-count=\"101\">\n    <template #prev>\n      往回走\n    </template>\n    <template #next>\n      继续走\n    </template>\n  </n-pagination>\n</template>\n"
  },
  {
    "path": "src/pagination/demos/zhCN/quick-jumper.demo.vue",
    "content": "<markdown>\n# 快速跳跃\n\n自定义跳至的内容（按 `Enter` 进行快速跳跃）。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst page = ref(2)\n</script>\n\n<template>\n  <n-space vertical>\n    <n-pagination v-model:page=\"page\" :page-count=\"100\" show-quick-jumper>\n      <template #goto>\n        请回答\n      </template>\n    </n-pagination>\n    <n-pagination v-model:page=\"page\" :page-count=\"100\" show-quick-jumper>\n      <template #goto>\n        请回答\n      </template>\n    </n-pagination>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/pagination/demos/zhCN/rtl-debug.demo.vue",
    "content": "<markdown>\n# Rtl Debug\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { unstablePaginationRtl } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst rtlEnabled = ref(false)\nconst rtlStyles = [unstablePaginationRtl]\nconst page = ref(2)\n</script>\n\n<template>\n  <n-space vertical>\n    <n-space><n-switch v-model:value=\"rtlEnabled\" />Rtl</n-space>\n    <n-config-provider :rtl=\"rtlEnabled ? rtlStyles : undefined\">\n      <n-pagination\n        v-model:page=\"page\"\n        :page-count=\"100\"\n        show-size-picker\n        show-quick-jumper\n      />\n    </n-config-provider>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/pagination/demos/zhCN/simple.demo.vue",
    "content": "<markdown>\n# 简单分页\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst page = ref(2)\n</script>\n\n<template>\n  <n-pagination v-model:page=\"page\" :page-count=\"100\" simple />\n</template>\n"
  },
  {
    "path": "src/pagination/demos/zhCN/size-picker.demo.vue",
    "content": "<markdown>\n# 每页条数\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst page = ref(2)\nconst pageSize = ref(20)\n</script>\n\n<template>\n  <n-pagination\n    v-model:page=\"page\"\n    v-model:page-size=\"pageSize\"\n    :page-count=\"100\"\n    show-size-picker\n    :page-sizes=\"[10, 20, 30, 40]\"\n  />\n</template>\n"
  },
  {
    "path": "src/pagination/demos/zhCN/size.demo.vue",
    "content": "<markdown>\n# 尺寸\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst page = ref(2)\n</script>\n\n<template>\n  <n-space vertical>\n    <n-pagination\n      v-model:page=\"page\"\n      :page-count=\"100\"\n      size=\"small\"\n      show-quick-jumper\n      show-size-picker\n    />\n    <n-pagination\n      v-model:page=\"page\"\n      :page-count=\"100\"\n      size=\"medium\"\n      show-quick-jumper\n      show-size-picker\n    />\n    <n-pagination\n      v-model:page=\"page\"\n      :page-count=\"100\"\n      size=\"large\"\n      show-quick-jumper\n      show-size-picker\n    />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/pagination/demos/zhCN/slot.demo.vue",
    "content": "<markdown>\n# 页面槽位\n\n分页有一个属性 `page-slot`，试一下你就能理解它在做什么了。这个概念主要是为了解决由于分页长度变化导致的误点击问题。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst page = ref(2)\n</script>\n\n<template>\n  <n-space vertical>\n    <n-pagination v-model:page=\"page\" :page-count=\"100\" />\n    <n-pagination v-model:page=\"page\" :page-count=\"100\" :page-slot=\"8\" />\n    <n-pagination v-model:page=\"page\" :page-count=\"100\" :page-slot=\"7\" />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/pagination/index.ts",
    "content": "export type {\n  PaginationInfo,\n  PaginationRenderLabel,\n  PaginationSizeOption\n} from './src/interface'\nexport { default as NPagination, paginationProps } from './src/Pagination'\nexport type { PaginationProps, PaginationSlots } from './src/Pagination'\nexport type * from './src/public-types'\n"
  },
  {
    "path": "src/pagination/src/Pagination.tsx",
    "content": "import type { CSSProperties, PropType, SlotsType, VNode, VNodeChild } from 'vue'\nimport type { ScrollbarProps } from '../../_internal/scrollbar/src/Scrollbar'\nimport type { ThemeProps } from '../../_mixins'\nimport type { ExtractPublicPropTypes, MaybeArray } from '../../_utils'\nimport type { InputSize } from '../../input/src/public-types'\nimport type { SelectProps } from '../../select'\nimport type { SelectSize } from '../../select/src/public-types'\nimport type { PaginationTheme } from '../styles'\nimport type {\n  PaginationInfo,\n  PaginationLabelInfo,\n  PaginationRenderLabel,\n  PaginationSizeOption,\n  RenderGoto,\n  RenderNext,\n  RenderPrefix,\n  RenderPrev,\n  RenderSuffix\n} from './interface'\nimport type { PaginationSize } from './public-types'\nimport type { PageItem } from './utils'\nimport { useMergedState } from 'vooks'\nimport {\n  computed,\n  defineComponent,\n  Fragment,\n  h,\n  nextTick,\n  ref,\n  toRef,\n  watchEffect\n} from 'vue'\nimport { NBaseIcon } from '../../_internal'\nimport {\n  BackwardIcon,\n  FastBackwardIcon,\n  FastForwardIcon,\n  ForwardIcon,\n  MoreIcon\n} from '../../_internal/icons'\nimport { useConfig, useLocale, useTheme, useThemeClass } from '../../_mixins'\nimport { useRtl } from '../../_mixins/use-rtl'\nimport {\n  call,\n  createKey,\n  resolveSlot,\n  smallerSize,\n  useAdjustedTo,\n  warn,\n  warnOnce\n} from '../../_utils'\nimport { NInput } from '../../input'\nimport { NPopselect } from '../../popselect'\nimport { NSelect } from '../../select'\nimport { paginationLight } from '../styles'\nimport style from './styles/index.cssr'\nimport { createPageItemsInfo, getDefaultPageSize } from './utils'\n\nexport const paginationProps = {\n  ...(useTheme.props as ThemeProps<PaginationTheme>),\n  simple: Boolean,\n  page: Number,\n  defaultPage: {\n    type: Number,\n    default: 1\n  },\n  itemCount: Number,\n  pageCount: Number,\n  defaultPageCount: {\n    type: Number,\n    default: 1\n  },\n  showSizePicker: Boolean,\n  pageSize: Number,\n  defaultPageSize: Number,\n  pageSizes: {\n    type: Array as PropType<Array<number | PaginationSizeOption>>,\n    default() {\n      return [10]\n    }\n  },\n  showQuickJumper: Boolean,\n  size: String as PropType<PaginationSize>,\n  disabled: Boolean,\n  pageSlot: {\n    type: Number,\n    default: 9\n  },\n  selectProps: Object as PropType<SelectProps>,\n  prev: Function as PropType<RenderPrev>,\n  next: Function as PropType<RenderNext>,\n  goto: Function as PropType<RenderGoto>,\n  prefix: Function as PropType<RenderPrefix>,\n  suffix: Function as PropType<RenderSuffix>,\n  label: Function as PropType<PaginationRenderLabel>,\n  displayOrder: {\n    type: Array as PropType<Array<'pages' | 'size-picker' | 'quick-jumper'>>,\n    default: ['pages', 'size-picker', 'quick-jumper']\n  },\n  to: useAdjustedTo.propTo,\n  showQuickJumpDropdown: { type: Boolean, default: true },\n  scrollbarProps: Object as PropType<ScrollbarProps>,\n  'onUpdate:page': [Function, Array] as PropType<\n    MaybeArray<(page: number) => void>\n  >,\n  onUpdatePage: [Function, Array] as PropType<\n    MaybeArray<(page: number) => void>\n  >,\n  'onUpdate:pageSize': [Function, Array] as PropType<\n    MaybeArray<(pageSize: number) => void>\n  >,\n  onUpdatePageSize: [Function, Array] as PropType<\n    MaybeArray<(pageSize: number) => void>\n  >,\n  /** @deprecated */\n  onPageSizeChange: [Function, Array] as PropType<\n    MaybeArray<(pageSize: number) => void>\n  >,\n  /** @deprecated */\n  onChange: [Function, Array] as PropType<MaybeArray<(page: number) => void>>\n} as const\n\nexport type PaginationProps = ExtractPublicPropTypes<typeof paginationProps>\n\nexport interface PaginationSlots {\n  default?: () => VNode[]\n  goto?: () => VNode[]\n  label?: (props: PaginationLabelInfo) => VNode[]\n  next?: (props: PaginationInfo) => VNode\n  prev?: (props: PaginationInfo) => VNode\n  prefix?: (props: PaginationInfo) => VNode\n  suffix?: (props: PaginationInfo) => VNode\n}\n\nexport default defineComponent({\n  name: 'Pagination',\n  props: paginationProps,\n  slots: Object as SlotsType<PaginationSlots>,\n  setup(props) {\n    if (__DEV__) {\n      watchEffect(() => {\n        if (props.pageCount !== undefined && props.itemCount !== undefined) {\n          warn(\n            'pagination',\n            '`page-count` and `item-count` should\\'t be specified together. Only `item-count` will take effect.'\n          )\n        }\n        if (props.onPageSizeChange) {\n          warnOnce(\n            'pagination',\n            '`on-page-size-change` is deprecated, please use `on-update:page-size` instead.'\n          )\n        }\n        if (props.onChange) {\n          warnOnce(\n            'pagination',\n            '`on-change` is deprecated, please use `on-update:page` instead.'\n          )\n        }\n      })\n    }\n    const {\n      mergedComponentPropsRef,\n      mergedClsPrefixRef,\n      inlineThemeDisabled,\n      mergedRtlRef\n    } = useConfig(props)\n    const mergedSizeRef = computed<PaginationSize>(() => {\n      return (\n        props.size\n        || mergedComponentPropsRef?.value?.Pagination?.size\n        || 'medium'\n      )\n    })\n    const themeRef = useTheme(\n      'Pagination',\n      '-pagination',\n      style,\n      paginationLight,\n      props,\n      mergedClsPrefixRef\n    )\n    const { localeRef } = useLocale('Pagination')\n    const selfRef = ref<HTMLElement | null>(null)\n    const uncontrolledPageRef = ref(props.defaultPage)\n    const uncontrolledPageSizeRef = ref(getDefaultPageSize(props))\n    const mergedPageRef = useMergedState(\n      toRef(props, 'page'),\n      uncontrolledPageRef\n    )\n    const mergedPageSizeRef = useMergedState(\n      toRef(props, 'pageSize'),\n      uncontrolledPageSizeRef\n    )\n    const mergedPageCountRef = computed(() => {\n      // item count has high priority, for it can affect prefix slot rendering\n      const { itemCount } = props\n      if (itemCount !== undefined) {\n        return Math.max(1, Math.ceil(itemCount / mergedPageSizeRef.value))\n      }\n      const { pageCount } = props\n      if (pageCount !== undefined)\n        return Math.max(pageCount, 1)\n      return 1\n    })\n    const jumperValueRef = ref('')\n    watchEffect(() => {\n      void props.simple\n      jumperValueRef.value = String(mergedPageRef.value)\n    })\n\n    const fastForwardActiveRef = ref(false)\n    const fastBackwardActiveRef = ref(false)\n    const showFastForwardMenuRef = ref(false)\n    const showFastBackwardMenuRef = ref(false)\n\n    const handleFastForwardMouseenter = (): void => {\n      if (props.disabled)\n        return\n      fastForwardActiveRef.value = true\n      disableTransitionOneTick()\n    }\n    const handleFastForwardMouseleave = (): void => {\n      if (props.disabled)\n        return\n      fastForwardActiveRef.value = false\n      disableTransitionOneTick()\n    }\n    const handleFastBackwardMouseenter = (): void => {\n      fastBackwardActiveRef.value = true\n      disableTransitionOneTick()\n    }\n    const handleFastBackwardMouseleave = (): void => {\n      fastBackwardActiveRef.value = false\n      disableTransitionOneTick()\n    }\n    const handleMenuSelect = (value: number): void => {\n      doUpdatePage(value)\n    }\n\n    const pageItemsInfo = computed(() =>\n      createPageItemsInfo(\n        mergedPageRef.value,\n        mergedPageCountRef.value,\n        props.pageSlot,\n        props.showQuickJumpDropdown\n      )\n    )\n\n    watchEffect(() => {\n      if (!pageItemsInfo.value.hasFastBackward) {\n        fastBackwardActiveRef.value = false\n        showFastBackwardMenuRef.value = false\n      }\n      else if (!pageItemsInfo.value.hasFastForward) {\n        fastForwardActiveRef.value = false\n        showFastForwardMenuRef.value = false\n      }\n    })\n\n    const pageSizeOptionsRef = computed(() => {\n      const suffix = localeRef.value.selectionSuffix\n      return props.pageSizes.map((size) => {\n        if (typeof size === 'number') {\n          return {\n            label: `${size} / ${suffix}`,\n            value: size\n          }\n        }\n        else {\n          return size\n        }\n      })\n    })\n    const inputSizeRef = computed<InputSize>(() => {\n      return (\n        mergedComponentPropsRef?.value?.Pagination?.inputSize\n        || smallerSize(mergedSizeRef.value)\n      )\n    })\n    const selectSizeRef = computed<SelectSize>(() => {\n      return (\n        mergedComponentPropsRef?.value?.Pagination?.selectSize\n        || smallerSize(mergedSizeRef.value)\n      )\n    })\n    const startIndexRef = computed(() => {\n      return (mergedPageRef.value - 1) * mergedPageSizeRef.value\n    })\n    const endIndexRef = computed(() => {\n      const endIndex = mergedPageRef.value * mergedPageSizeRef.value - 1\n      const { itemCount } = props\n      if (itemCount !== undefined) {\n        return endIndex > itemCount - 1 ? itemCount - 1 : endIndex\n      }\n      return endIndex\n    })\n    const mergedItemCountRef = computed(() => {\n      const { itemCount } = props\n      if (itemCount !== undefined)\n        return itemCount\n      return (props.pageCount || 1) * mergedPageSizeRef.value\n    })\n    const rtlEnabledRef = useRtl('Pagination', mergedRtlRef, mergedClsPrefixRef)\n\n    function disableTransitionOneTick(): void {\n      void nextTick(() => {\n        const { value: selfEl } = selfRef\n        if (!selfEl)\n          return\n        selfEl.classList.add('transition-disabled')\n        void selfRef.value?.offsetWidth\n        selfEl.classList.remove('transition-disabled')\n      })\n    }\n    function doUpdatePage(page: number): void {\n      if (page === mergedPageRef.value)\n        return\n      const {\n        'onUpdate:page': _onUpdatePage,\n        onUpdatePage,\n        onChange,\n        simple\n      } = props\n      if (_onUpdatePage)\n        call(_onUpdatePage, page)\n      if (onUpdatePage)\n        call(onUpdatePage, page)\n      // deprecated\n      if (onChange)\n        call(onChange, page)\n      uncontrolledPageRef.value = page\n      if (simple) {\n        jumperValueRef.value = String(page)\n      }\n    }\n    function doUpdatePageSize(pageSize: number): void {\n      if (pageSize === mergedPageSizeRef.value)\n        return\n      const {\n        'onUpdate:pageSize': _onUpdatePageSize,\n        onUpdatePageSize,\n        onPageSizeChange\n      } = props\n      if (_onUpdatePageSize)\n        call(_onUpdatePageSize, pageSize)\n      if (onUpdatePageSize)\n        call(onUpdatePageSize, pageSize)\n      // deprecated\n      if (onPageSizeChange)\n        call(onPageSizeChange, pageSize)\n      uncontrolledPageSizeRef.value = pageSize\n      // update new page when overflows.\n      // we may have different update strategy, but i've no time to impl it\n      if (mergedPageCountRef.value < mergedPageRef.value) {\n        doUpdatePage(mergedPageCountRef.value)\n      }\n    }\n    function forward(): void {\n      if (props.disabled)\n        return\n      const page = Math.min(mergedPageRef.value + 1, mergedPageCountRef.value)\n      doUpdatePage(page)\n    }\n    function backward(): void {\n      if (props.disabled)\n        return\n      const page = Math.max(mergedPageRef.value - 1, 1)\n      doUpdatePage(page)\n    }\n    function fastForward(): void {\n      if (props.disabled)\n        return\n      const page = Math.min(\n        pageItemsInfo.value.fastForwardTo,\n        mergedPageCountRef.value\n      )\n      doUpdatePage(page)\n    }\n    function fastBackward(): void {\n      if (props.disabled)\n        return\n      const page = Math.max(pageItemsInfo.value.fastBackwardTo, 1)\n      doUpdatePage(page)\n    }\n    function handleSizePickerChange(value: number): void {\n      doUpdatePageSize(value)\n    }\n    function doQuickJump(): void {\n      const page = Number.parseInt(jumperValueRef.value)\n      if (Number.isNaN(page))\n        return\n      doUpdatePage(Math.max(1, Math.min(page, mergedPageCountRef.value)))\n      if (!props.simple) {\n        jumperValueRef.value = ''\n      }\n    }\n    function handleQuickJumperChange(): void {\n      doQuickJump()\n    }\n    function handlePageItemClick(pageItem: PageItem): void {\n      if (props.disabled)\n        return\n      switch (pageItem.type) {\n        case 'page':\n          doUpdatePage(pageItem.label)\n          break\n        case 'fast-backward':\n          fastBackward()\n          break\n        case 'fast-forward':\n          fastForward()\n          break\n      }\n    }\n    function handleJumperInput(value: string): void {\n      jumperValueRef.value = value.replace(/\\D+/g, '')\n    }\n    watchEffect(() => {\n      void mergedPageRef.value\n      void mergedPageSizeRef.value\n      disableTransitionOneTick()\n    })\n    const cssVarsRef = computed(() => {\n      const size = mergedSizeRef.value\n      const {\n        self: {\n          buttonBorder,\n          buttonBorderHover,\n          buttonBorderPressed,\n          buttonIconColor,\n          buttonIconColorHover,\n          buttonIconColorPressed,\n          itemTextColor,\n          itemTextColorHover,\n          itemTextColorPressed,\n          itemTextColorActive,\n          itemTextColorDisabled,\n          itemColor,\n          itemColorHover,\n          itemColorPressed,\n          itemColorActive,\n          itemColorActiveHover,\n          itemColorDisabled,\n          itemBorder,\n          itemBorderHover,\n          itemBorderPressed,\n          itemBorderActive,\n          itemBorderDisabled,\n          itemBorderRadius,\n          jumperTextColor,\n          jumperTextColorDisabled,\n          buttonColor,\n          buttonColorHover,\n          buttonColorPressed,\n          [createKey('itemPadding', size)]: itemPadding,\n          [createKey('itemMargin', size)]: itemMargin,\n          [createKey('inputWidth', size)]: inputWidth,\n          [createKey('selectWidth', size)]: selectWidth,\n          [createKey('inputMargin', size)]: inputMargin,\n          [createKey('selectMargin', size)]: selectMargin,\n          [createKey('jumperFontSize', size)]: jumperFontSize,\n          [createKey('prefixMargin', size)]: prefixMargin,\n          [createKey('suffixMargin', size)]: suffixMargin,\n          [createKey('itemSize', size)]: itemSize,\n          [createKey('buttonIconSize', size)]: buttonIconSize,\n          [createKey('itemFontSize', size)]: itemFontSize,\n          [`${createKey('itemMargin', size)}Rtl` as const]: itemMarginRtl,\n          [`${createKey('inputMargin', size)}Rtl` as const]: inputMarginRtl\n        },\n        common: { cubicBezierEaseInOut }\n      } = themeRef.value\n      return {\n        '--n-prefix-margin': prefixMargin,\n        '--n-suffix-margin': suffixMargin,\n        '--n-item-font-size': itemFontSize,\n        '--n-select-width': selectWidth,\n        '--n-select-margin': selectMargin,\n        '--n-input-width': inputWidth,\n        '--n-input-margin': inputMargin,\n        '--n-input-margin-rtl': inputMarginRtl,\n        '--n-item-size': itemSize,\n        '--n-item-text-color': itemTextColor,\n        '--n-item-text-color-disabled': itemTextColorDisabled,\n        '--n-item-text-color-hover': itemTextColorHover,\n        '--n-item-text-color-active': itemTextColorActive,\n        '--n-item-text-color-pressed': itemTextColorPressed,\n        '--n-item-color': itemColor,\n        '--n-item-color-hover': itemColorHover,\n        '--n-item-color-disabled': itemColorDisabled,\n        '--n-item-color-active': itemColorActive,\n        '--n-item-color-active-hover': itemColorActiveHover,\n        '--n-item-color-pressed': itemColorPressed,\n        '--n-item-border': itemBorder,\n        '--n-item-border-hover': itemBorderHover,\n        '--n-item-border-disabled': itemBorderDisabled,\n        '--n-item-border-active': itemBorderActive,\n        '--n-item-border-pressed': itemBorderPressed,\n        '--n-item-padding': itemPadding,\n        '--n-item-border-radius': itemBorderRadius,\n        '--n-bezier': cubicBezierEaseInOut,\n        '--n-jumper-font-size': jumperFontSize,\n        '--n-jumper-text-color': jumperTextColor,\n        '--n-jumper-text-color-disabled': jumperTextColorDisabled,\n        '--n-item-margin': itemMargin,\n        '--n-item-margin-rtl': itemMarginRtl,\n        '--n-button-icon-size': buttonIconSize,\n        '--n-button-icon-color': buttonIconColor,\n        '--n-button-icon-color-hover': buttonIconColorHover,\n        '--n-button-icon-color-pressed': buttonIconColorPressed,\n        '--n-button-color-hover': buttonColorHover,\n        '--n-button-color': buttonColor,\n        '--n-button-color-pressed': buttonColorPressed,\n        '--n-button-border': buttonBorder,\n        '--n-button-border-hover': buttonBorderHover,\n        '--n-button-border-pressed': buttonBorderPressed\n      }\n    })\n    const themeClassHandle = inlineThemeDisabled\n      ? useThemeClass(\n          'pagination',\n          computed(() => {\n            let hash = ''\n            hash += mergedSizeRef.value[0]\n            return hash\n          }),\n          cssVarsRef,\n          props\n        )\n      : undefined\n    return {\n      rtlEnabled: rtlEnabledRef,\n      mergedClsPrefix: mergedClsPrefixRef,\n      locale: localeRef,\n      selfRef,\n      mergedPage: mergedPageRef,\n      pageItems: computed(() => {\n        return pageItemsInfo.value.items\n      }),\n      mergedItemCount: mergedItemCountRef,\n      jumperValue: jumperValueRef,\n      pageSizeOptions: pageSizeOptionsRef,\n      mergedPageSize: mergedPageSizeRef,\n      inputSize: inputSizeRef,\n      selectSize: selectSizeRef,\n      mergedTheme: themeRef,\n      mergedPageCount: mergedPageCountRef,\n      startIndex: startIndexRef,\n      endIndex: endIndexRef,\n      showFastForwardMenu: showFastForwardMenuRef,\n      showFastBackwardMenu: showFastBackwardMenuRef,\n      fastForwardActive: fastForwardActiveRef,\n      fastBackwardActive: fastBackwardActiveRef,\n      handleMenuSelect,\n      handleFastForwardMouseenter,\n      handleFastForwardMouseleave,\n      handleFastBackwardMouseenter,\n      handleFastBackwardMouseleave,\n      handleJumperInput,\n      handleBackwardClick: backward,\n      handleForwardClick: forward,\n      handlePageItemClick,\n      handleSizePickerChange,\n      handleQuickJumperChange,\n      cssVars: inlineThemeDisabled ? undefined : cssVarsRef,\n      themeClass: themeClassHandle?.themeClass,\n      onRender: themeClassHandle?.onRender\n    }\n  },\n  render() {\n    // it's ok to expand all prop here since no slots' deps\n    const {\n      $slots,\n      mergedClsPrefix,\n      disabled,\n      cssVars,\n      mergedPage,\n      mergedPageCount,\n      pageItems,\n      showSizePicker,\n      showQuickJumper,\n      mergedTheme,\n      locale,\n      inputSize,\n      selectSize,\n      mergedPageSize,\n      pageSizeOptions,\n      jumperValue,\n      simple,\n      prev,\n      next,\n      prefix,\n      suffix,\n      label,\n      goto,\n      handleJumperInput,\n      handleSizePickerChange,\n      handleBackwardClick,\n      handlePageItemClick,\n      handleForwardClick,\n      handleQuickJumperChange,\n      onRender\n    } = this\n    onRender?.()\n    const renderPrefix = prefix || $slots.prefix\n    const renderSuffix = suffix || $slots.suffix\n    const renderPrev = prev || $slots.prev\n    const renderNext = next || $slots.next\n    const renderLabel = label || $slots.label\n    return (\n      <div\n        ref=\"selfRef\"\n        class={[\n          `${mergedClsPrefix}-pagination`,\n          this.themeClass,\n          this.rtlEnabled && `${mergedClsPrefix}-pagination--rtl`,\n          disabled && `${mergedClsPrefix}-pagination--disabled`,\n          simple && `${mergedClsPrefix}-pagination--simple`\n        ]}\n        style={cssVars as CSSProperties}\n      >\n        {renderPrefix ? (\n          <div class={`${mergedClsPrefix}-pagination-prefix`}>\n            {renderPrefix({\n              page: mergedPage,\n              pageSize: mergedPageSize,\n              pageCount: mergedPageCount,\n              startIndex: this.startIndex,\n              endIndex: this.endIndex,\n              itemCount: this.mergedItemCount\n            })}\n          </div>\n        ) : null}\n        {this.displayOrder.map((part) => {\n          switch (part) {\n            case 'pages':\n              return (\n                <Fragment>\n                  <div\n                    class={[\n                      `${mergedClsPrefix}-pagination-item`,\n                      !renderPrev\n                      && `${mergedClsPrefix}-pagination-item--button`,\n                      (mergedPage <= 1\n                        || mergedPage > mergedPageCount\n                        || disabled)\n                      && `${mergedClsPrefix}-pagination-item--disabled`\n                    ]}\n                    onClick={handleBackwardClick}\n                  >\n                    {renderPrev ? (\n                      renderPrev({\n                        page: mergedPage,\n                        pageSize: mergedPageSize,\n                        pageCount: mergedPageCount,\n                        startIndex: this.startIndex,\n                        endIndex: this.endIndex,\n                        itemCount: this.mergedItemCount\n                      })\n                    ) : (\n                      <NBaseIcon clsPrefix={mergedClsPrefix}>\n                        {{\n                          default: () =>\n                            this.rtlEnabled ? <ForwardIcon /> : <BackwardIcon />\n                        }}\n                      </NBaseIcon>\n                    )}\n                  </div>\n                  {simple ? (\n                    <Fragment>\n                      <div class={`${mergedClsPrefix}-pagination-quick-jumper`}>\n                        <NInput\n                          value={jumperValue}\n                          onUpdateValue={handleJumperInput}\n                          size={inputSize}\n                          placeholder=\"\"\n                          disabled={disabled}\n                          theme={mergedTheme.peers.Input}\n                          themeOverrides={mergedTheme.peerOverrides.Input}\n                          onChange={handleQuickJumperChange}\n                        />\n                      </div>\n                      &nbsp;/\n                      {' '}\n                      {mergedPageCount}\n                    </Fragment>\n                  ) : (\n                    pageItems.map((pageItem, index) => {\n                      let contentNode: VNodeChild\n                      let onMouseenter: undefined | (() => void)\n                      let onMouseleave: undefined | (() => void)\n                      const { type } = pageItem\n                      switch (type) {\n                        case 'page':\n                          // eslint-disable-next-line no-case-declarations\n                          const pageNode = pageItem.label\n                          if (renderLabel) {\n                            contentNode = renderLabel({\n                              type: 'page',\n                              node: pageNode,\n                              active: pageItem.active\n                            })\n                          }\n                          else {\n                            contentNode = pageNode\n                          }\n                          break\n                        case 'fast-forward':\n                          // eslint-disable-next-line no-case-declarations\n                          const fastForwardNode = this.fastForwardActive ? (\n                            <NBaseIcon clsPrefix={mergedClsPrefix}>\n                              {{\n                                default: () =>\n                                  this.rtlEnabled ? (\n                                    <FastBackwardIcon />\n                                  ) : (\n                                    <FastForwardIcon />\n                                  )\n                              }}\n                            </NBaseIcon>\n                          ) : (\n                            <NBaseIcon clsPrefix={mergedClsPrefix}>\n                              {{ default: () => <MoreIcon /> }}\n                            </NBaseIcon>\n                          )\n                          if (renderLabel) {\n                            contentNode = renderLabel({\n                              type: 'fast-forward',\n                              node: fastForwardNode,\n                              active:\n                                this.fastForwardActive\n                                || this.showFastForwardMenu\n                            })\n                          }\n                          else {\n                            contentNode = fastForwardNode\n                          }\n                          onMouseenter = this.handleFastForwardMouseenter\n                          onMouseleave = this.handleFastForwardMouseleave\n                          break\n                        case 'fast-backward':\n                          // eslint-disable-next-line no-case-declarations\n                          const fastBackwardNode = this.fastBackwardActive ? (\n                            <NBaseIcon clsPrefix={mergedClsPrefix}>\n                              {{\n                                default: () =>\n                                  this.rtlEnabled ? (\n                                    <FastForwardIcon />\n                                  ) : (\n                                    <FastBackwardIcon />\n                                  )\n                              }}\n                            </NBaseIcon>\n                          ) : (\n                            <NBaseIcon clsPrefix={mergedClsPrefix}>\n                              {{ default: () => <MoreIcon /> }}\n                            </NBaseIcon>\n                          )\n                          if (renderLabel) {\n                            contentNode = renderLabel({\n                              type: 'fast-backward',\n                              node: fastBackwardNode,\n                              active:\n                                this.fastBackwardActive\n                                || this.showFastBackwardMenu\n                            })\n                          }\n                          else {\n                            contentNode = fastBackwardNode\n                          }\n                          onMouseenter = this.handleFastBackwardMouseenter\n                          onMouseleave = this.handleFastBackwardMouseleave\n                          break\n                      }\n                      const itemNode = (\n                        <div\n                          key={index}\n                          class={[\n                            `${mergedClsPrefix}-pagination-item`,\n                            pageItem.active\n                            && `${mergedClsPrefix}-pagination-item--active`,\n                            type !== 'page'\n                            && ((type === 'fast-backward'\n                              && this.showFastBackwardMenu)\n                            || (type === 'fast-forward'\n                              && this.showFastForwardMenu))\n                            && `${mergedClsPrefix}-pagination-item--hover`,\n                            disabled\n                            && `${mergedClsPrefix}-pagination-item--disabled`,\n                            type === 'page'\n                            && `${mergedClsPrefix}-pagination-item--clickable`\n                          ]}\n                          onClick={() => {\n                            handlePageItemClick(pageItem)\n                          }}\n                          onMouseenter={onMouseenter}\n                          onMouseleave={onMouseleave}\n                        >\n                          {contentNode}\n                        </div>\n                      )\n                      if (\n                        type === 'page'\n                        && !pageItem.mayBeFastBackward\n                        && !pageItem.mayBeFastForward\n                      ) {\n                        return itemNode\n                      }\n                      else {\n                        const key\n                          = pageItem.type === 'page'\n                            ? pageItem.mayBeFastBackward\n                              ? 'fast-backward'\n                              : 'fast-forward'\n                            : pageItem.type\n                        if (pageItem.type !== 'page' && !pageItem.options) {\n                          return itemNode\n                        }\n                        return (\n                          <NPopselect\n                            to={this.to}\n                            key={key}\n                            disabled={disabled}\n                            trigger=\"hover\"\n                            virtualScroll\n                            style={{ width: '60px' }}\n                            theme={mergedTheme.peers.Popselect}\n                            themeOverrides={mergedTheme.peerOverrides.Popselect}\n                            builtinThemeOverrides={{\n                              peers: {\n                                InternalSelectMenu: {\n                                  height: 'calc(var(--n-option-height) * 4.6)'\n                                }\n                              }\n                            }}\n                            nodeProps={() => ({\n                              style: {\n                                justifyContent: 'center'\n                              }\n                            })}\n                            show={\n                              type === 'page'\n                                ? false\n                                : type === 'fast-backward'\n                                  ? this.showFastBackwardMenu\n                                  : this.showFastForwardMenu\n                            }\n                            onUpdateShow={(value) => {\n                              if (type === 'page')\n                                return\n                              if (value) {\n                                if (type === 'fast-backward') {\n                                  this.showFastBackwardMenu = value\n                                }\n                                else {\n                                  this.showFastForwardMenu = value\n                                }\n                              }\n                              else {\n                                this.showFastBackwardMenu = false\n                                this.showFastForwardMenu = false\n                              }\n                            }}\n                            options={\n                              pageItem.type !== 'page' && pageItem.options\n                                ? pageItem.options\n                                : []\n                            }\n                            onUpdateValue={this.handleMenuSelect}\n                            scrollable\n                            scrollbarProps={this.scrollbarProps}\n                            showCheckmark={false}\n                          >\n                            {{ default: () => itemNode }}\n                          </NPopselect>\n                        )\n                      }\n                    })\n                  )}\n                  <div\n                    class={[\n                      `${mergedClsPrefix}-pagination-item`,\n                      !renderNext\n                      && `${mergedClsPrefix}-pagination-item--button`,\n                      {\n                        [`${mergedClsPrefix}-pagination-item--disabled`]:\n                          mergedPage < 1\n                          || mergedPage >= mergedPageCount\n                          || disabled\n                      }\n                    ]}\n                    onClick={handleForwardClick}\n                  >\n                    {renderNext ? (\n                      renderNext({\n                        page: mergedPage,\n                        pageSize: mergedPageSize,\n                        pageCount: mergedPageCount,\n                        itemCount: this.mergedItemCount,\n                        startIndex: this.startIndex,\n                        endIndex: this.endIndex\n                      })\n                    ) : (\n                      <NBaseIcon clsPrefix={mergedClsPrefix}>\n                        {{\n                          default: () =>\n                            this.rtlEnabled ? <BackwardIcon /> : <ForwardIcon />\n                        }}\n                      </NBaseIcon>\n                    )}\n                  </div>\n                </Fragment>\n              )\n            case 'size-picker': {\n              return !simple && showSizePicker ? (\n                <NSelect\n                  consistentMenuWidth={false}\n                  placeholder=\"\"\n                  showCheckmark={false}\n                  to={this.to}\n                  {...this.selectProps}\n                  size={selectSize}\n                  options={pageSizeOptions}\n                  value={mergedPageSize}\n                  disabled={disabled}\n                  scrollbarProps={this.scrollbarProps}\n                  theme={mergedTheme.peers.Select}\n                  themeOverrides={mergedTheme.peerOverrides.Select}\n                  onUpdateValue={handleSizePickerChange}\n                />\n              ) : null\n            }\n            case 'quick-jumper':\n              return !simple && showQuickJumper ? (\n                <div class={`${mergedClsPrefix}-pagination-quick-jumper`}>\n                  {goto\n                    ? goto()\n                    : resolveSlot(this.$slots.goto, () => [locale.goto])}\n                  <NInput\n                    value={jumperValue}\n                    onUpdateValue={handleJumperInput}\n                    size={inputSize}\n                    placeholder=\"\"\n                    disabled={disabled}\n                    theme={mergedTheme.peers.Input}\n                    themeOverrides={mergedTheme.peerOverrides.Input}\n                    onChange={handleQuickJumperChange}\n                  />\n                </div>\n              ) : null\n            default:\n              return null\n          }\n        })}\n        {renderSuffix ? (\n          <div class={`${mergedClsPrefix}-pagination-suffix`}>\n            {renderSuffix({\n              page: mergedPage,\n              pageSize: mergedPageSize,\n              pageCount: mergedPageCount,\n              startIndex: this.startIndex,\n              endIndex: this.endIndex,\n              itemCount: this.mergedItemCount\n            })}\n          </div>\n        ) : null}\n      </div>\n    )\n  }\n})\n"
  },
  {
    "path": "src/pagination/src/interface.ts",
    "content": "import type { VNodeChild } from 'vue'\nimport type { SelectBaseOption } from '../../select/src/interface'\n\nexport type PaginationInfo = Parameters<RenderPrefix>[0]\n\nexport type RenderPrefix = (info: {\n  startIndex: number\n  endIndex: number\n  page: number\n  pageSize: number\n  pageCount: number\n  itemCount: number | undefined\n}) => VNodeChild\n\nexport type PaginationSizeOption = SelectBaseOption<number, string>\nexport type RenderSuffix = RenderPrefix\nexport type RenderNext = RenderPrefix\nexport type RenderPrev = RenderPrefix\nexport type RenderGoto = () => VNodeChild\n\nexport type PaginationRenderLabel = (\n  info:\n    | {\n      type: 'fast-backward' | 'fast-forward'\n      node: VNodeChild\n      active: boolean\n    }\n    | {\n      type: 'page'\n      node: number\n      active: boolean\n    }\n) => VNodeChild\n\nexport type PaginationLabelInfo = Parameters<PaginationRenderLabel>[0]\n"
  },
  {
    "path": "src/pagination/src/public-types.ts",
    "content": "export type PaginationSize = 'small' | 'medium' | 'large'\n"
  },
  {
    "path": "src/pagination/src/styles/index.cssr.ts",
    "content": "import { c, cB, cM, cNotM } from '../../../_utils/cssr'\n\nconst hoverStyleProps = `\n  background: var(--n-item-color-hover);\n  color: var(--n-item-text-color-hover);\n  border: var(--n-item-border-hover);\n`\n\nconst hoverStyleChildren = [\n  cM('button', `\n    background: var(--n-button-color-hover);\n    border: var(--n-button-border-hover);\n    color: var(--n-button-icon-color-hover);\n  `)\n]\n\n// vars:\n// --n-item-font-size\n// --n-select-width\n// --n-input-width\n// --n-input-margin\n// --n-item-size\n// --n-item-text-color\n// --n-item-text-color-disabled\n// --n-item-text-color-hover\n// --n-item-text-color-active\n// --n-item-color\n// --n-item-color-hover\n// --n-item-color-disabled\n// --n-item-color-active\n// --n-item-color-active-hover\n// --n-item-border\n// --n-item-border-hover\n// --n-item-border-disabled\n// --n-item-border-active\n// --n-item-padding\n// --n-item-font-size\n// --n-item-border-radius\n// --n-bezier\n// --n-jumper-font-size\n// --n-jumper-text-color\n// --n-jumper-text-color-disabled\n// --n-item-margin\n// --n-button-icon-size\n// --n-button-icon-color\n// --n-button-icon-color-hover\n// --n-button-icon-color-pressed\n// --n-prefix-margin\n// --n-suffix-margin\n// --n-button-color\n// --n-button-color-hover\n// --n-button-color-pressed\nexport default cB('pagination', `\n  display: flex;\n  vertical-align: middle;\n  font-size: var(--n-item-font-size);\n  flex-wrap: nowrap;\n`, [\n  cB('pagination-prefix', `\n    display: flex;\n    align-items: center;\n    margin: var(--n-prefix-margin);\n  `),\n  cB('pagination-suffix', `\n    display: flex;\n    align-items: center;\n    margin: var(--n-suffix-margin);\n  `),\n  c('> *:not(:first-child)', `\n    margin: var(--n-item-margin);\n  `),\n  cB('select', `\n    width: var(--n-select-width);\n  `),\n  c('&.transition-disabled', [\n    cB('pagination-item', 'transition: none!important;')\n  ]),\n  cB('pagination-quick-jumper', `\n    white-space: nowrap;\n    display: flex;\n    color: var(--n-jumper-text-color);\n    transition: color .3s var(--n-bezier);\n    align-items: center;\n    font-size: var(--n-jumper-font-size);\n  `, [\n    cB('input', `\n      margin: var(--n-input-margin);\n      width: var(--n-input-width);\n    `)\n  ]),\n  cB('pagination-item', `\n    position: relative;\n    cursor: pointer;\n    user-select: none;\n    -webkit-user-select: none;\n    display: flex;\n    align-items: center;\n    justify-content: center;\n    box-sizing: border-box;\n    min-width: var(--n-item-size);\n    height: var(--n-item-size);\n    padding: var(--n-item-padding);\n    background-color: var(--n-item-color);\n    color: var(--n-item-text-color);\n    border-radius: var(--n-item-border-radius);\n    border: var(--n-item-border);\n    fill: var(--n-button-icon-color);\n    transition:\n      color .3s var(--n-bezier),\n      border-color .3s var(--n-bezier),\n      background-color .3s var(--n-bezier),\n      fill .3s var(--n-bezier);\n  `, [\n    cM('button', `\n      background: var(--n-button-color);\n      color: var(--n-button-icon-color);\n      border: var(--n-button-border);\n      padding: 0;\n    `, [\n      cB('base-icon', `\n        font-size: var(--n-button-icon-size);\n      `)\n    ]),\n    cNotM('disabled', [\n      cM('hover', hoverStyleProps, hoverStyleChildren),\n      c('&:hover', hoverStyleProps, hoverStyleChildren),\n      c('&:active', `\n        background: var(--n-item-color-pressed);\n        color: var(--n-item-text-color-pressed);\n        border: var(--n-item-border-pressed);\n      `, [\n        cM('button', `\n          background: var(--n-button-color-pressed);\n          border: var(--n-button-border-pressed);\n          color: var(--n-button-icon-color-pressed);\n        `)\n      ]),\n      cM('active', `\n        background: var(--n-item-color-active);\n        color: var(--n-item-text-color-active);\n        border: var(--n-item-border-active);\n      `, [\n        c('&:hover', `\n          background: var(--n-item-color-active-hover);\n        `)\n      ])\n    ]),\n    cM('disabled', `\n      cursor: not-allowed;\n      color: var(--n-item-text-color-disabled);\n    `, [\n      cM('active, button', `\n        background-color: var(--n-item-color-disabled);\n        border: var(--n-item-border-disabled);\n      `)\n    ])\n  ]),\n  cM('disabled', `\n    cursor: not-allowed;\n  `, [\n    cB('pagination-quick-jumper', `\n      color: var(--n-jumper-text-color-disabled);\n    `)\n  ]),\n  cM('simple', `\n    display: flex;\n    align-items: center;\n    flex-wrap: nowrap;\n  `, [\n    cB('pagination-quick-jumper', [\n      cB('input', `\n        margin: 0;\n      `)\n    ])\n  ])\n])\n"
  },
  {
    "path": "src/pagination/src/styles/rtl.cssr.ts",
    "content": "import { c, cB, cM } from '../../../_utils/cssr'\n\nexport default cB('pagination', [\n  cM('rtl', `\n    direction: rtl;\n  `, [\n    c('> *:not(:first-child)', `\n      margin: var(--n-item-margin-rtl);\n    `),\n    cB('pagination-quick-jumper', [\n      cB('input', `\n        margin: var(--n-input-margin-rtl);\n      `)\n    ])\n  ])\n])\n"
  },
  {
    "path": "src/pagination/src/utils.ts",
    "content": "import type { PaginationProps } from './Pagination'\n\nexport function getDefaultPageSize(\n  paginationProps: PaginationProps | false\n): number {\n  if (!paginationProps)\n    return 10\n  const { defaultPageSize } = paginationProps\n  if (defaultPageSize !== undefined)\n    return defaultPageSize\n  const pageSizeOption = paginationProps.pageSizes?.[0]\n  if (typeof pageSizeOption === 'number')\n    return pageSizeOption\n  return pageSizeOption?.value || 10\n}\n\nfunction createPageItemsInfo(\n  currentPage: number,\n  pageCount: number,\n  pageSlot: number,\n  showQuickJumpDropdown: boolean\n): {\n  hasFastBackward: boolean\n  hasFastForward: boolean\n  fastBackwardTo: number\n  fastForwardTo: number\n  items: PageItem[]\n} {\n  let hasFastBackward = false\n  let hasFastForward = false\n  let fastBackwardTo = 1\n  let fastForwardTo = pageCount\n  if (pageCount === 1) {\n    return {\n      hasFastBackward: false,\n      hasFastForward: false,\n      fastForwardTo,\n      fastBackwardTo,\n      items: [\n        {\n          type: 'page',\n          label: 1,\n          active: currentPage === 1,\n          mayBeFastBackward: false,\n          mayBeFastForward: false\n        }\n      ]\n    }\n  }\n  if (pageCount === 2) {\n    return {\n      hasFastBackward: false,\n      hasFastForward: false,\n      fastForwardTo,\n      fastBackwardTo,\n      items: [\n        {\n          type: 'page',\n          label: 1,\n          active: currentPage === 1,\n          mayBeFastBackward: false,\n          mayBeFastForward: false\n        },\n        {\n          type: 'page',\n          label: 2,\n          active: currentPage === 2,\n          mayBeFastBackward: true,\n          mayBeFastForward: false\n        }\n      ]\n    }\n  }\n  const firstPage = 1\n  const lastPage = pageCount\n  let middleStart = currentPage\n  let middleEnd = currentPage\n  const middleDelta = (pageSlot - 5) / 2\n  middleEnd += Math.ceil(middleDelta)\n  middleEnd = Math.min(\n    Math.max(middleEnd, firstPage + pageSlot - 3),\n    lastPage - 2\n  )\n  middleStart -= Math.floor(middleDelta)\n  middleStart = Math.max(\n    Math.min(middleStart, lastPage - pageSlot + 3),\n    firstPage + 2\n  )\n  let leftSplit = false\n  let rightSplit = false\n  if (middleStart > firstPage + 2)\n    leftSplit = true\n  if (middleEnd < lastPage - 2)\n    rightSplit = true\n  const items: PageItem[] = []\n  items.push({\n    type: 'page',\n    label: 1,\n    active: currentPage === 1,\n    mayBeFastBackward: false,\n    mayBeFastForward: false\n  })\n  if (leftSplit) {\n    hasFastBackward = true\n    fastBackwardTo = middleStart - 1\n    items.push({\n      type: 'fast-backward',\n      active: false,\n      label: undefined,\n      options: showQuickJumpDropdown\n        ? createRange(firstPage + 1, middleStart - 1)\n        : null\n    })\n  }\n  else if (lastPage >= firstPage + 1) {\n    items.push({\n      type: 'page',\n      label: firstPage + 1,\n      mayBeFastBackward: true,\n      mayBeFastForward: false,\n      active: currentPage === firstPage + 1\n    })\n  }\n  for (let i = middleStart; i <= middleEnd; ++i) {\n    items.push({\n      type: 'page',\n      label: i,\n      mayBeFastBackward: false,\n      mayBeFastForward: false,\n      active: currentPage === i\n    })\n  }\n  if (rightSplit) {\n    hasFastForward = true\n    fastForwardTo = middleEnd + 1\n    items.push({\n      type: 'fast-forward',\n      active: false,\n      label: undefined,\n      options: showQuickJumpDropdown\n        ? createRange(middleEnd + 1, lastPage - 1)\n        : null\n    })\n  }\n  else if (\n    middleEnd === lastPage - 2\n    && items[items.length - 1].label !== lastPage - 1\n  ) {\n    items.push({\n      type: 'page',\n      mayBeFastForward: true,\n      mayBeFastBackward: false,\n      label: lastPage - 1,\n      active: currentPage === lastPage - 1\n    })\n  }\n  if (items[items.length - 1].label !== lastPage) {\n    items.push({\n      type: 'page',\n      mayBeFastForward: false,\n      mayBeFastBackward: false,\n      label: lastPage,\n      active: currentPage === lastPage\n    })\n  }\n  return {\n    hasFastBackward,\n    hasFastForward,\n    fastBackwardTo,\n    fastForwardTo,\n    items\n  }\n}\n\nexport type PageItem\n  = | {\n    type: 'fast-backward' | 'fast-forward'\n    label: undefined\n    active: false\n    options: Array<{ label: string, value: number }> | null\n  }\n  | {\n    type: 'page'\n    label: number\n    active: boolean\n    mayBeFastForward: boolean\n    mayBeFastBackward: boolean\n  }\n\nfunction createRange(\n  from: number,\n  to: number\n): Array<{ label: string, value: number }> {\n  const range: Array<{ label: string, value: number }> = []\n  for (let i = from; i <= to; ++i) {\n    range.push({\n      label: `${i}`,\n      value: i\n    })\n  }\n  return range\n}\n\nexport { createPageItemsInfo }\n"
  },
  {
    "path": "src/pagination/styles/_common.ts",
    "content": "export default {\n  itemPaddingSmall: '0 4px',\n  itemMarginSmall: '0 0 0 8px',\n  itemMarginSmallRtl: '0 8px 0 0',\n  itemPaddingMedium: '0 4px',\n  itemMarginMedium: '0 0 0 8px',\n  itemMarginMediumRtl: '0 8px 0 0',\n  itemPaddingLarge: '0 4px',\n  itemMarginLarge: '0 0 0 8px',\n  itemMarginLargeRtl: '0 8px 0 0',\n  buttonIconSizeSmall: '14px',\n  buttonIconSizeMedium: '16px',\n  buttonIconSizeLarge: '18px',\n  inputWidthSmall: '60px',\n  selectWidthSmall: 'unset',\n  inputMarginSmall: '0 0 0 8px',\n  inputMarginSmallRtl: '0 8px 0 0',\n  selectMarginSmall: '0 0 0 8px',\n  prefixMarginSmall: '0 8px 0 0',\n  suffixMarginSmall: '0 0 0 8px',\n  inputWidthMedium: '60px',\n  selectWidthMedium: 'unset',\n  inputMarginMedium: '0 0 0 8px',\n  inputMarginMediumRtl: '0 8px 0 0',\n  selectMarginMedium: '0 0 0 8px',\n  prefixMarginMedium: '0 8px 0 0',\n  suffixMarginMedium: '0 0 0 8px',\n  inputWidthLarge: '60px',\n  selectWidthLarge: 'unset',\n  inputMarginLarge: '0 0 0 8px',\n  inputMarginLargeRtl: '0 8px 0 0',\n  selectMarginLarge: '0 0 0 8px',\n  prefixMarginLarge: '0 8px 0 0',\n  suffixMarginLarge: '0 0 0 8px'\n}\n"
  },
  {
    "path": "src/pagination/styles/dark.ts",
    "content": "import type { PaginationTheme } from './light'\nimport { changeColor } from 'seemly'\nimport { commonDark } from '../../_styles/common'\nimport { inputDark } from '../../input/styles'\nimport { popselectDark } from '../../popselect/styles'\nimport { selectDark } from '../../select/styles'\nimport { self } from './light'\n\nconst paginationDark: PaginationTheme = {\n  name: 'Pagination',\n  common: commonDark,\n  peers: {\n    Select: selectDark,\n    Input: inputDark,\n    Popselect: popselectDark\n  },\n  self(vars) {\n    const { primaryColor, opacity3 } = vars\n    const borderColorActive = changeColor(primaryColor, {\n      alpha: Number(opacity3)\n    })\n    const commonSelf = self(vars)\n    commonSelf.itemBorderActive = `1px solid ${borderColorActive}`\n    commonSelf.itemBorderDisabled = '1px solid #0000'\n    return commonSelf\n  }\n}\n\nexport default paginationDark\n"
  },
  {
    "path": "src/pagination/styles/index.ts",
    "content": "export { default as paginationDark } from './dark'\nexport { default as paginationLight } from './light'\nexport type { PaginationTheme, PaginationThemeVars } from './light'\nexport { paginationRtl } from './rtl'\n"
  },
  {
    "path": "src/pagination/styles/light.ts",
    "content": "import type { ThemeCommonVars } from '../../_styles/common'\nimport { createTheme } from '../../_mixins'\nimport { commonLight } from '../../_styles/common'\nimport { inputLight } from '../../input/styles'\nimport { popselectLight } from '../../popselect/styles'\nimport { selectLight } from '../../select/styles'\nimport commonVariables from './_common'\n\nexport function self(vars: ThemeCommonVars) {\n  const {\n    textColor2,\n    primaryColor,\n    primaryColorHover,\n    primaryColorPressed,\n    inputColorDisabled,\n    textColorDisabled,\n    borderColor,\n    borderRadius,\n    // item font size\n    fontSizeTiny,\n    fontSizeSmall,\n    fontSizeMedium,\n    // item size\n    heightTiny,\n    heightSmall,\n    heightMedium\n  } = vars\n\n  return {\n    ...commonVariables,\n    buttonColor: '#0000',\n    buttonColorHover: '#0000',\n    buttonColorPressed: '#0000',\n    buttonBorder: `1px solid ${borderColor}`,\n    buttonBorderHover: `1px solid ${borderColor}`,\n    buttonBorderPressed: `1px solid ${borderColor}`,\n    buttonIconColor: textColor2,\n    buttonIconColorHover: textColor2,\n    buttonIconColorPressed: textColor2,\n    itemTextColor: textColor2,\n    itemTextColorHover: primaryColorHover,\n    itemTextColorPressed: primaryColorPressed,\n    itemTextColorActive: primaryColor,\n    itemTextColorDisabled: textColorDisabled,\n    itemColor: '#0000',\n    itemColorHover: '#0000',\n    itemColorPressed: '#0000',\n    itemColorActive: '#0000',\n    itemColorActiveHover: '#0000',\n    itemColorDisabled: inputColorDisabled,\n    itemBorder: '1px solid #0000',\n    itemBorderHover: '1px solid #0000',\n    itemBorderPressed: '1px solid #0000',\n    itemBorderActive: `1px solid ${primaryColor}`,\n    itemBorderDisabled: `1px solid ${borderColor}`,\n    itemBorderRadius: borderRadius,\n    itemSizeSmall: heightTiny,\n    itemSizeMedium: heightSmall,\n    itemSizeLarge: heightMedium,\n    itemFontSizeSmall: fontSizeTiny,\n    itemFontSizeMedium: fontSizeSmall,\n    itemFontSizeLarge: fontSizeMedium,\n    jumperFontSizeSmall: fontSizeTiny,\n    jumperFontSizeMedium: fontSizeSmall,\n    jumperFontSizeLarge: fontSizeMedium,\n    jumperTextColor: textColor2,\n    jumperTextColorDisabled: textColorDisabled\n  }\n}\n\nexport type PaginationThemeVars = ReturnType<typeof self>\n\nconst paginationLight = createTheme({\n  name: 'Pagination',\n  common: commonLight,\n  peers: {\n    Select: selectLight,\n    Input: inputLight,\n    Popselect: popselectLight\n  },\n  self\n})\n\nexport default paginationLight\nexport type PaginationTheme = typeof paginationLight\n"
  },
  {
    "path": "src/pagination/styles/rtl.ts",
    "content": "import type { RtlItem } from '../../config-provider/src/internal-interface'\nimport { inputRtl } from '../../input/styles/rtl'\nimport { selectRtl } from '../../select/styles'\nimport rtlStyle from '../src/styles/rtl.cssr'\n\nexport const paginationRtl: RtlItem = {\n  name: 'Pagination',\n  style: rtlStyle,\n  peers: [inputRtl, selectRtl]\n}\n"
  },
  {
    "path": "src/pagination/tests/Pagination.spec.tsx",
    "content": "import type { PaginationInfo, PaginationRenderLabel } from '../index'\nimport { mount } from '@vue/test-utils'\nimport { h } from 'vue'\nimport { NPagination } from '../index'\n\ndescribe('n-pagination', () => {\n  it('should work with import on demand', () => {\n    mount(NPagination)\n  })\n  it('should work with `size` prop', async () => {\n    const wrapper = mount(NPagination, {\n      props: {\n        pageCount: 20\n      }\n    })\n    expect(wrapper.attributes('style')).toContain('--n-item-size: 28px;')\n\n    await wrapper.setProps({ size: 'small' })\n    expect(wrapper.attributes('style')).toContain('--n-item-size: 22px;')\n\n    await wrapper.setProps({ size: 'large' })\n    expect(wrapper.attributes('style')).toContain('--n-item-size: 34px;')\n    wrapper.unmount()\n  })\n  it('props.itemCount', async () => {\n    const wrapper = mount(NPagination, {\n      props: {\n        itemCount: 1,\n        pageSize: 10\n      }\n    })\n    expect(wrapper.findAll('.n-pagination-item').length).toEqual(3)\n    await wrapper.setProps({\n      itemCount: 11\n    })\n    expect(wrapper.findAll('.n-pagination-item').length).toEqual(4)\n    wrapper.unmount()\n  })\n  it('should work with corrent pagination info', async () => {\n    let paginationInfo: PaginationInfo | undefined\n    const wrapper = mount(NPagination, {\n      props: {\n        itemCount: 1,\n        pageSize: 10,\n        prefix: (info: PaginationInfo) => {\n          paginationInfo = info\n        }\n      }\n    })\n    expect(wrapper.findAll('.n-pagination-item').length).toEqual(3)\n    expect(paginationInfo?.itemCount).toBe(1)\n    expect(paginationInfo?.page).toBe(1)\n    expect(paginationInfo?.pageCount).toBe(1)\n    expect(paginationInfo?.pageSize).toBe(10)\n    expect(paginationInfo?.startIndex).toBe(0)\n    expect(paginationInfo?.endIndex).toBe(0)\n    await wrapper.setProps({\n      itemCount: 12,\n      pageSize: 5,\n      page: 3\n    })\n    expect(paginationInfo?.itemCount).toBe(12)\n    expect(paginationInfo?.pageSize).toBe(5)\n    expect(paginationInfo?.page).toBe(3)\n    expect(paginationInfo?.pageCount).toBe(3)\n    expect(paginationInfo?.startIndex).toBe(10)\n    expect(paginationInfo?.endIndex).toBe(11)\n    wrapper.unmount()\n  })\n  it('should work with prev slot', async () => {\n    const wrapper = mount(NPagination, {\n      slots: {\n        prev: () => 'Prev'\n      }\n    })\n    expect(wrapper.find('.n-pagination-item').text()).toContain('Prev')\n    wrapper.unmount()\n  })\n  it('page-sizes should has correct type', () => {\n    ;(() => (\n      <NPagination\n        pageSizes={[\n          10,\n          {\n            label: '20',\n            value: 20\n          }\n        ]}\n      />\n    ))()\n  })\n  it('has currect default page size', () => {\n    const wrapper = mount(() => (\n      <NPagination pageSizes={[23, 22]} showSizePicker />\n    ))\n    expect(wrapper.find('.n-base-selection-input__content').text()).toContain(\n      '23'\n    )\n    wrapper.unmount()\n  })\n})\nit('should work with label slot', async () => {\n  const labelSlot: PaginationRenderLabel = (props) => {\n    if (props.type === 'page')\n      return `(${props.node})`\n    return props.node\n  }\n  const wrapper = mount(NPagination, {\n    slots: {\n      label: labelSlot\n    }\n  })\n  await wrapper.setProps({\n    itemCount: 1\n  })\n  expect(wrapper.findAll('.n-pagination-item')[1].text()).toContain('(1)')\n  wrapper.unmount()\n})\n"
  },
  {
    "path": "src/pagination/tests/server.spec.tsx",
    "content": "import { setup } from '@css-render/vue3-ssr'\nimport { renderToString } from '@vue/server-renderer'\n/**\n * @vitest-environment node\n */\nimport { createSSRApp, h } from 'vue'\nimport { NPagination } from '../..'\n\ndescribe('server side rendering', () => {\n  it('works', async () => {\n    const app = createSSRApp(() => <NPagination />)\n    setup(app)\n    try {\n      await renderToString(app)\n    }\n    catch (e) {\n      expect(e).not.toBeTruthy()\n    }\n  })\n})\n"
  },
  {
    "path": "src/pagination/tests/utils.spec.ts",
    "content": "import type { PageItem } from '../src/utils'\nimport { createPageItemsInfo } from '../src/utils'\n\nfunction createFastBackwardItem(options: number[]): PageItem {\n  return {\n    type: 'fast-backward',\n    active: false,\n    label: undefined,\n    options: options.map(v => ({\n      label: `${v}`,\n      value: v\n    }))\n  }\n}\n\nfunction createFastForwardItem(options: number[]): PageItem {\n  return {\n    type: 'fast-forward',\n    active: false,\n    label: undefined,\n    options: options.map(v => ({\n      label: `${v}`,\n      value: v\n    }))\n  }\n}\n\nfunction createPageItem(options: {\n  label: number\n  currentPage: number\n  pageCount: number\n}): PageItem {\n  return {\n    type: 'page',\n    active: options.label === options.currentPage,\n    mayBeFastBackward: options.label === 2,\n    mayBeFastForward:\n      options.label > 2 && options.pageCount === options.label + 1,\n    label: options.label\n  }\n}\n\ndescribe('pagination', () => {\n  describe('utils', () => {\n    describe('#createPageItemsInfo', () => {\n      it('should work when less than 9 total pages', () => {\n        expect(createPageItemsInfo(1, 1, 9, true).items).toEqual(\n          [1].map(v =>\n            createPageItem({\n              label: v,\n              currentPage: 1,\n              pageCount: 1\n            })\n          )\n        )\n        expect(createPageItemsInfo(1, 2, 9, true).items).toEqual(\n          [1, 2].map(v =>\n            createPageItem({\n              label: v,\n              currentPage: 1,\n              pageCount: 2\n            })\n          )\n        )\n        expect(createPageItemsInfo(2, 2, 9, true).items).toEqual(\n          [1, 2].map(v =>\n            createPageItem({\n              label: v,\n              currentPage: 2,\n              pageCount: 2\n            })\n          )\n        )\n        expect(createPageItemsInfo(1, 3, 9, true).items).toEqual(\n          [1, 2, 3].map(v =>\n            createPageItem({\n              label: v,\n              currentPage: 1,\n              pageCount: 3\n            })\n          )\n        )\n        expect(createPageItemsInfo(2, 3, 9, true).items).toEqual(\n          [1, 2, 3].map(v =>\n            createPageItem({\n              label: v,\n              currentPage: 2,\n              pageCount: 3\n            })\n          )\n        )\n        expect(createPageItemsInfo(3, 3, 9, true).items).toEqual(\n          [1, 2, 3].map(v =>\n            createPageItem({\n              label: v,\n              currentPage: 3,\n              pageCount: 3\n            })\n          )\n        )\n        expect(createPageItemsInfo(1, 4, 9, true).items).toEqual(\n          [1, 2, 3, 4].map(v =>\n            createPageItem({\n              label: v,\n              currentPage: 1,\n              pageCount: 4\n            })\n          )\n        )\n        expect(createPageItemsInfo(2, 4, 9, true).items).toEqual(\n          [1, 2, 3, 4].map(v =>\n            createPageItem({\n              label: v,\n              currentPage: 2,\n              pageCount: 4\n            })\n          )\n        )\n        expect(createPageItemsInfo(3, 4, 9, true).items).toEqual(\n          [1, 2, 3, 4].map(v =>\n            createPageItem({\n              label: v,\n              currentPage: 3,\n              pageCount: 4\n            })\n          )\n        )\n        expect(createPageItemsInfo(4, 4, 9, true).items).toEqual(\n          [1, 2, 3, 4].map(v =>\n            createPageItem({\n              label: v,\n              currentPage: 4,\n              pageCount: 4\n            })\n          )\n        )\n        expect(createPageItemsInfo(1, 5, 9, true).items).toEqual(\n          [1, 2, 3, 4, 5].map(v =>\n            createPageItem({\n              label: v,\n              currentPage: 1,\n              pageCount: 5\n            })\n          )\n        )\n        expect(createPageItemsInfo(2, 5, 9, true).items).toEqual(\n          [1, 2, 3, 4, 5].map(v =>\n            createPageItem({\n              label: v,\n              currentPage: 2,\n              pageCount: 5\n            })\n          )\n        )\n        expect(createPageItemsInfo(3, 5, 9, true).items).toEqual(\n          [1, 2, 3, 4, 5].map(v =>\n            createPageItem({\n              label: v,\n              currentPage: 3,\n              pageCount: 5\n            })\n          )\n        )\n        expect(createPageItemsInfo(4, 5, 9, true).items).toEqual(\n          [1, 2, 3, 4, 5].map(v =>\n            createPageItem({\n              label: v,\n              currentPage: 4,\n              pageCount: 5\n            })\n          )\n        )\n        expect(createPageItemsInfo(5, 5, 9, true).items).toEqual(\n          [1, 2, 3, 4, 5].map(v =>\n            createPageItem({\n              label: v,\n              currentPage: 5,\n              pageCount: 5\n            })\n          )\n        )\n        expect(createPageItemsInfo(1, 6, 9, true).items).toEqual(\n          [1, 2, 3, 4, 5, 6].map(v =>\n            createPageItem({\n              label: v,\n              currentPage: 1,\n              pageCount: 6\n            })\n          )\n        )\n        expect(createPageItemsInfo(2, 6, 9, true).items).toEqual(\n          [1, 2, 3, 4, 5, 6].map(v =>\n            createPageItem({\n              label: v,\n              currentPage: 2,\n              pageCount: 6\n            })\n          )\n        )\n        expect(createPageItemsInfo(3, 6, 9, true).items).toEqual(\n          [1, 2, 3, 4, 5, 6].map(v =>\n            createPageItem({\n              label: v,\n              currentPage: 3,\n              pageCount: 6\n            })\n          )\n        )\n        expect(createPageItemsInfo(4, 6, 9, true).items).toEqual(\n          [1, 2, 3, 4, 5, 6].map(v =>\n            createPageItem({\n              label: v,\n              currentPage: 4,\n              pageCount: 6\n            })\n          )\n        )\n        expect(createPageItemsInfo(5, 6, 9, true).items).toEqual(\n          [1, 2, 3, 4, 5, 6].map(v =>\n            createPageItem({\n              label: v,\n              currentPage: 5,\n              pageCount: 6\n            })\n          )\n        )\n        expect(createPageItemsInfo(6, 6, 9, true).items).toEqual(\n          [1, 2, 3, 4, 5, 6].map(v =>\n            createPageItem({\n              label: v,\n              currentPage: 6,\n              pageCount: 6\n            })\n          )\n        )\n        expect(createPageItemsInfo(1, 7, 9, true).items).toEqual(\n          [1, 2, 3, 4, 5, 6, 7].map(v =>\n            createPageItem({\n              label: v,\n              currentPage: 1,\n              pageCount: 7\n            })\n          )\n        )\n        expect(createPageItemsInfo(2, 7, 9, true).items).toEqual(\n          [1, 2, 3, 4, 5, 6, 7].map(v =>\n            createPageItem({\n              label: v,\n              currentPage: 2,\n              pageCount: 7\n            })\n          )\n        )\n        expect(createPageItemsInfo(3, 7, 9, true).items).toEqual(\n          [1, 2, 3, 4, 5, 6, 7].map(v =>\n            createPageItem({\n              label: v,\n              currentPage: 3,\n              pageCount: 7\n            })\n          )\n        )\n        expect(createPageItemsInfo(4, 7, 9, true).items).toEqual(\n          [1, 2, 3, 4, 5, 6, 7].map(v =>\n            createPageItem({\n              label: v,\n              currentPage: 4,\n              pageCount: 7\n            })\n          )\n        )\n        expect(createPageItemsInfo(5, 7, 9, true).items).toEqual(\n          [1, 2, 3, 4, 5, 6, 7].map(v =>\n            createPageItem({\n              label: v,\n              currentPage: 5,\n              pageCount: 7\n            })\n          )\n        )\n        expect(createPageItemsInfo(6, 7, 9, true).items).toEqual(\n          [1, 2, 3, 4, 5, 6, 7].map(v =>\n            createPageItem({\n              label: v,\n              currentPage: 6,\n              pageCount: 7\n            })\n          )\n        )\n        expect(createPageItemsInfo(7, 7, 9, true).items).toEqual(\n          [1, 2, 3, 4, 5, 6, 7].map(v =>\n            createPageItem({\n              label: v,\n              currentPage: 7,\n              pageCount: 7\n            })\n          )\n        )\n        expect(createPageItemsInfo(1, 8, 9, true).items).toEqual(\n          [1, 2, 3, 4, 5, 6, 7, 8].map(v =>\n            createPageItem({\n              label: v,\n              currentPage: 1,\n              pageCount: 8\n            })\n          )\n        )\n        expect(createPageItemsInfo(2, 8, 9, true).items).toEqual(\n          [1, 2, 3, 4, 5, 6, 7, 8].map(v =>\n            createPageItem({\n              label: v,\n              currentPage: 2,\n              pageCount: 8\n            })\n          )\n        )\n        expect(createPageItemsInfo(3, 8, 9, true).items).toEqual(\n          [1, 2, 3, 4, 5, 6, 7, 8].map(v =>\n            createPageItem({\n              label: v,\n              currentPage: 3,\n              pageCount: 8\n            })\n          )\n        )\n        expect(createPageItemsInfo(4, 8, 9, true).items).toEqual(\n          [1, 2, 3, 4, 5, 6, 7, 8].map(v =>\n            createPageItem({\n              label: v,\n              currentPage: 4,\n              pageCount: 8\n            })\n          )\n        )\n        expect(createPageItemsInfo(5, 8, 9, true).items).toEqual(\n          [1, 2, 3, 4, 5, 6, 7, 8].map(v =>\n            createPageItem({\n              label: v,\n              currentPage: 5,\n              pageCount: 8\n            })\n          )\n        )\n        expect(createPageItemsInfo(6, 8, 9, true).items).toEqual(\n          [1, 2, 3, 4, 5, 6, 7, 8].map(v =>\n            createPageItem({\n              label: v,\n              currentPage: 6,\n              pageCount: 8\n            })\n          )\n        )\n        expect(createPageItemsInfo(7, 8, 9, true).items).toEqual(\n          [1, 2, 3, 4, 5, 6, 7, 8].map(v =>\n            createPageItem({\n              label: v,\n              currentPage: 7,\n              pageCount: 8\n            })\n          )\n        )\n        expect(createPageItemsInfo(8, 8, 9, true).items).toEqual(\n          [1, 2, 3, 4, 5, 6, 7, 8].map(v =>\n            createPageItem({\n              label: v,\n              currentPage: 8,\n              pageCount: 8\n            })\n          )\n        )\n        expect(createPageItemsInfo(1, 9, 9, true).items).toEqual(\n          [1, 2, 3, 4, 5, 6, 7, 8, 9].map(v =>\n            createPageItem({\n              label: v,\n              currentPage: 1,\n              pageCount: 9\n            })\n          )\n        )\n        expect(createPageItemsInfo(2, 9, 9, true).items).toEqual(\n          [1, 2, 3, 4, 5, 6, 7, 8, 9].map(v =>\n            createPageItem({\n              label: v,\n              currentPage: 2,\n              pageCount: 9\n            })\n          )\n        )\n        expect(createPageItemsInfo(3, 9, 9, true).items).toEqual(\n          [1, 2, 3, 4, 5, 6, 7, 8, 9].map(v =>\n            createPageItem({\n              label: v,\n              currentPage: 3,\n              pageCount: 9\n            })\n          )\n        )\n        expect(createPageItemsInfo(4, 9, 9, true).items).toEqual(\n          [1, 2, 3, 4, 5, 6, 7, 8, 9].map(v =>\n            createPageItem({\n              label: v,\n              currentPage: 4,\n              pageCount: 9\n            })\n          )\n        )\n        expect(createPageItemsInfo(5, 9, 9, true).items).toEqual(\n          [1, 2, 3, 4, 5, 6, 7, 8, 9].map(v =>\n            createPageItem({\n              label: v,\n              currentPage: 5,\n              pageCount: 9\n            })\n          )\n        )\n        expect(createPageItemsInfo(6, 9, 9, true).items).toEqual(\n          [1, 2, 3, 4, 5, 6, 7, 8, 9].map(v =>\n            createPageItem({\n              label: v,\n              currentPage: 6,\n              pageCount: 9\n            })\n          )\n        )\n        expect(createPageItemsInfo(7, 9, 9, true).items).toEqual(\n          [1, 2, 3, 4, 5, 6, 7, 8, 9].map(v =>\n            createPageItem({\n              label: v,\n              currentPage: 7,\n              pageCount: 9\n            })\n          )\n        )\n        expect(createPageItemsInfo(8, 9, 9, true).items).toEqual(\n          [1, 2, 3, 4, 5, 6, 7, 8, 9].map(v =>\n            createPageItem({\n              label: v,\n              currentPage: 8,\n              pageCount: 9\n            })\n          )\n        )\n        expect(createPageItemsInfo(9, 9, 9, true).items).toEqual(\n          [1, 2, 3, 4, 5, 6, 7, 8, 9].map(v =>\n            createPageItem({\n              label: v,\n              currentPage: 9,\n              pageCount: 9\n            })\n          )\n        )\n      })\n      it('should work when totalPage is 10', () => {\n        expect(createPageItemsInfo(1, 10, 9, true).items).toEqual(\n          [1, 2, 3, 4, 5, 6, 7, -1, 10].map((v) => {\n            if (v === -1)\n              return createFastForwardItem([8, 9])\n            if (v === -2)\n              return createFastBackwardItem([])\n            return createPageItem({ label: v, currentPage: 1, pageCount: 10 })\n          })\n        )\n        expect(createPageItemsInfo(2, 10, 9, true).items).toEqual(\n          [1, 2, 3, 4, 5, 6, 7, -1, 10].map((v) => {\n            if (v === -1)\n              return createFastForwardItem([8, 9])\n            if (v === -2)\n              return createFastBackwardItem([])\n            return createPageItem({ label: v, currentPage: 2, pageCount: 10 })\n          })\n        )\n        expect(createPageItemsInfo(3, 10, 9, true).items).toEqual(\n          [1, 2, 3, 4, 5, 6, 7, -1, 10].map((v) => {\n            if (v === -1)\n              return createFastForwardItem([8, 9])\n            if (v === -2)\n              return createFastBackwardItem([])\n            return createPageItem({ label: v, currentPage: 3, pageCount: 10 })\n          })\n        )\n        expect(createPageItemsInfo(4, 10, 9, true).items).toEqual(\n          [1, 2, 3, 4, 5, 6, 7, -1, 10].map((v) => {\n            if (v === -1)\n              return createFastForwardItem([8, 9])\n            if (v === -2)\n              return createFastBackwardItem([])\n            return createPageItem({ label: v, currentPage: 4, pageCount: 10 })\n          })\n        )\n        expect(createPageItemsInfo(5, 10, 9, true).items).toEqual(\n          [1, 2, 3, 4, 5, 6, 7, -1, 10].map((v) => {\n            if (v === -1)\n              return createFastForwardItem([8, 9])\n            if (v === -2)\n              return createFastBackwardItem([])\n            return createPageItem({ label: v, currentPage: 5, pageCount: 10 })\n          })\n        )\n        expect(createPageItemsInfo(6, 10, 9, true).items).toEqual(\n          [1, -2, 4, 5, 6, 7, 8, 9, 10].map((v) => {\n            if (v === -1)\n              return createFastForwardItem([])\n            if (v === -2)\n              return createFastBackwardItem([2, 3])\n            return createPageItem({ label: v, currentPage: 6, pageCount: 10 })\n          })\n        )\n        expect(createPageItemsInfo(7, 10, 9, true).items).toEqual(\n          [1, -2, 4, 5, 6, 7, 8, 9, 10].map((v) => {\n            if (v === -1)\n              return createFastForwardItem([])\n            if (v === -2)\n              return createFastBackwardItem([2, 3])\n            return createPageItem({ label: v, currentPage: 7, pageCount: 10 })\n          })\n        )\n        expect(createPageItemsInfo(8, 10, 9, true).items).toEqual(\n          [1, -2, 4, 5, 6, 7, 8, 9, 10].map((v) => {\n            if (v === -1)\n              return createFastForwardItem([])\n            if (v === -2)\n              return createFastBackwardItem([2, 3])\n            return createPageItem({ label: v, currentPage: 8, pageCount: 10 })\n          })\n        )\n        expect(createPageItemsInfo(9, 10, 9, true).items).toEqual(\n          [1, -2, 4, 5, 6, 7, 8, 9, 10].map((v) => {\n            if (v === -1)\n              return createFastForwardItem([])\n            if (v === -2)\n              return createFastBackwardItem([2, 3])\n            return createPageItem({ label: v, currentPage: 9, pageCount: 10 })\n          })\n        )\n        expect(createPageItemsInfo(10, 10, 9, true).items).toEqual(\n          [1, -2, 4, 5, 6, 7, 8, 9, 10].map((v) => {\n            if (v === -1)\n              return createFastForwardItem([])\n            if (v === -2)\n              return createFastBackwardItem([2, 3])\n            return createPageItem({ label: v, currentPage: 10, pageCount: 10 })\n          })\n        )\n      })\n      it('should work when totalPage is 11', () => {\n        expect(createPageItemsInfo(1, 11, 9, true).items).toEqual(\n          [1, 2, 3, 4, 5, 6, 7, -1, 11].map((v) => {\n            if (v === -1)\n              return createFastForwardItem([8, 9, 10])\n            if (v === -2)\n              return createFastBackwardItem([])\n            return createPageItem({ label: v, currentPage: 1, pageCount: 11 })\n          })\n        )\n        expect(createPageItemsInfo(2, 11, 9, true).items).toEqual(\n          [1, 2, 3, 4, 5, 6, 7, -1, 11].map((v) => {\n            if (v === -1)\n              return createFastForwardItem([8, 9, 10])\n            if (v === -2)\n              return createFastBackwardItem([])\n            return createPageItem({ label: v, currentPage: 2, pageCount: 11 })\n          })\n        )\n        expect(createPageItemsInfo(3, 11, 9, true).items).toEqual(\n          [1, 2, 3, 4, 5, 6, 7, -1, 11].map((v) => {\n            if (v === -1)\n              return createFastForwardItem([8, 9, 10])\n            if (v === -2)\n              return createFastBackwardItem([])\n            return createPageItem({ label: v, currentPage: 3, pageCount: 11 })\n          })\n        )\n        expect(createPageItemsInfo(4, 11, 9, true).items).toEqual(\n          [1, 2, 3, 4, 5, 6, 7, -1, 11].map((v) => {\n            if (v === -1)\n              return createFastForwardItem([8, 9, 10])\n            if (v === -2)\n              return createFastBackwardItem([])\n            return createPageItem({ label: v, currentPage: 4, pageCount: 11 })\n          })\n        )\n        expect(createPageItemsInfo(5, 11, 9, true).items).toEqual(\n          [1, 2, 3, 4, 5, 6, 7, -1, 11].map((v) => {\n            if (v === -1)\n              return createFastForwardItem([8, 9, 10])\n            if (v === -2)\n              return createFastBackwardItem([])\n            return createPageItem({ label: v, currentPage: 5, pageCount: 11 })\n          })\n        )\n        expect(createPageItemsInfo(6, 11, 9, true).items).toEqual(\n          [1, -2, 4, 5, 6, 7, 8, -1, 11].map((v) => {\n            if (v === -1)\n              return createFastForwardItem([9, 10])\n            if (v === -2)\n              return createFastBackwardItem([2, 3])\n            return createPageItem({ label: v, currentPage: 6, pageCount: 11 })\n          })\n        )\n        expect(createPageItemsInfo(7, 11, 9, true).items).toEqual(\n          [1, -2, 5, 6, 7, 8, 9, 10, 11].map((v) => {\n            if (v === -1)\n              return createFastForwardItem([])\n            if (v === -2)\n              return createFastBackwardItem([2, 3, 4])\n            return createPageItem({ label: v, currentPage: 7, pageCount: 11 })\n          })\n        )\n        expect(createPageItemsInfo(8, 11, 9, true).items).toEqual(\n          [1, -2, 5, 6, 7, 8, 9, 10, 11].map((v) => {\n            if (v === -1)\n              return createFastForwardItem([])\n            if (v === -2)\n              return createFastBackwardItem([2, 3, 4])\n            return createPageItem({ label: v, currentPage: 8, pageCount: 11 })\n          })\n        )\n        expect(createPageItemsInfo(9, 11, 9, true).items).toEqual(\n          [1, -2, 5, 6, 7, 8, 9, 10, 11].map((v) => {\n            if (v === -1)\n              return createFastForwardItem([])\n            if (v === -2)\n              return createFastBackwardItem([2, 3, 4])\n            return createPageItem({ label: v, currentPage: 9, pageCount: 11 })\n          })\n        )\n        expect(createPageItemsInfo(10, 11, 9, true).items).toEqual(\n          [1, -2, 5, 6, 7, 8, 9, 10, 11].map((v) => {\n            if (v === -1)\n              return createFastForwardItem([])\n            if (v === -2)\n              return createFastBackwardItem([2, 3, 4])\n            return createPageItem({ label: v, currentPage: 10, pageCount: 11 })\n          })\n        )\n        expect(createPageItemsInfo(11, 11, 9, true).items).toEqual(\n          [1, -2, 5, 6, 7, 8, 9, 10, 11].map((v) => {\n            if (v === -1)\n              return createFastForwardItem([])\n            if (v === -2)\n              return createFastBackwardItem([2, 3, 4])\n            return createPageItem({ label: v, currentPage: 11, pageCount: 11 })\n          })\n        )\n      })\n    })\n  })\n})\n"
  },
  {
    "path": "src/popconfirm/demos/enUS/actions.demo.vue",
    "content": "<markdown>\n# Actions\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { useMessage } from 'naive-ui'\n\nconst message = useMessage()\n\nfunction handlePositiveClick() {\n  message.info('Yes')\n}\n\nfunction handleNegativeClick() {\n  message.info('No')\n}\n</script>\n\n<template>\n  <n-space>\n    <n-popconfirm\n      @positive-click=\"handlePositiveClick\"\n      @negative-click=\"handleNegativeClick\"\n    >\n      <template #trigger>\n        <n-button>Quote</n-button>\n      </template>\n      Things pass us by. Nobody can catch them. That's the way we live our\n      lives.\n    </n-popconfirm>\n    <n-popconfirm :negative-text=\"null\" @positive-click=\"handlePositiveClick\">\n      <template #trigger>\n        <n-button>Only Confirm</n-button>\n      </template>\n      Things pass us by. Nobody can catch them. That's the way we live our\n      lives.\n    </n-popconfirm>\n    <n-popconfirm :positive-text=\"null\" @negative-click=\"handleNegativeClick\">\n      <template #trigger>\n        <n-button>Only Cancel</n-button>\n      </template>\n      Things pass us by. Nobody can catch them. That's the way we live our\n      lives.\n    </n-popconfirm>\n    <n-popconfirm :positive-text=\"null\" :negative-text=\"null\">\n      <template #trigger>\n        <n-button>Nothing</n-button>\n      </template>\n      Things pass us by. Nobody can catch them. That's the way we live our\n      lives.\n    </n-popconfirm>\n    <n-popconfirm>\n      <template #trigger>\n        <n-button>Custom action</n-button>\n      </template>\n      <template #action>\n        Custom Action\n      </template>\n      Things pass us by. Nobody can catch them. That's the way we live our\n      lives.\n    </n-popconfirm>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/popconfirm/demos/enUS/basic.demo.vue",
    "content": "<markdown>\n# Basic\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { useMessage } from 'naive-ui'\n\nconst message = useMessage()\n\nfunction handlePositiveClick() {\n  message.info('Yes')\n}\n\nfunction handleNegativeClick() {\n  message.info('No')\n}\n</script>\n\n<template>\n  <n-popconfirm\n    @positive-click=\"handlePositiveClick\"\n    @negative-click=\"handleNegativeClick\"\n  >\n    <template #trigger>\n      <n-button>Quote</n-button>\n    </template>\n    Things pass us by. Nobody can catch them. That's the way we live our lives.\n  </n-popconfirm>\n</template>\n"
  },
  {
    "path": "src/popconfirm/demos/enUS/custom-action.demo.vue",
    "content": "<markdown>\n# Custom Action\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst show = ref(false)\n</script>\n\n<template>\n  <n-space>\n    <n-popconfirm v-model:show=\"show\">\n      <template #trigger>\n        <n-button>Quote</n-button>\n      </template>\n      For example, if I were to write about elephants, I'd have had no idea what\n      words to use.\n      <template #action>\n        <n-button size=\"small\" @click=\"show = false\">\n          Maybe\n        </n-button>\n      </template>\n    </n-popconfirm>\n    <n-popconfirm positive-text=\"Oops!\">\n      <template #trigger>\n        <n-button>Quote</n-button>\n      </template>\n      For example, if I were to write about elephants, I'd have had no idea what\n      words to use.\n    </n-popconfirm>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/popconfirm/demos/enUS/custom-icon.demo.vue",
    "content": "<markdown>\n# Custom Icon\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { MdHand as HandIcon } from '@vicons/ionicons4'\n</script>\n\n<template>\n  <n-popconfirm positive-text=\"ok\" negative-text=\"not ok\">\n    <template #icon>\n      <n-icon color=\"red\">\n        <HandIcon />\n      </n-icon>\n    </template>\n    <template #trigger>\n      <n-button>Quit Game</n-button>\n    </template>\n    How can you be strong without purchasing?\n  </n-popconfirm>\n</template>\n"
  },
  {
    "path": "src/popconfirm/demos/enUS/event.demo.vue",
    "content": "<markdown>\n# Event\n\n`positive-click` & `negative-click`\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { useMessage } from 'naive-ui'\n\nconst message = useMessage()\n\nfunction handlePositiveClick() {\n  message.info('positive click')\n}\n\nfunction handleNegativeClick() {\n  message.info('negative click')\n}\n</script>\n\n<template>\n  <n-popconfirm\n    @positive-click=\"handlePositiveClick\"\n    @negative-click=\"handleNegativeClick\"\n  >\n    <template #trigger>\n      <n-button>Quit Game</n-button>\n    </template>\n    I heared that players will still be abused after purchasing in some games\n    when I watch Bilibili.\n  </n-popconfirm>\n</template>\n"
  },
  {
    "path": "src/popconfirm/demos/enUS/index.demo-entry.md",
    "content": "# Popconfirm\n\nA confirm, poped.\n\n## Demos\n\n```demo\nbasic.vue\ncustom-action.vue\ncustom-icon.vue\nevent.vue\nno-icon.vue\nactions.vue\n```\n\n## API\n\n### Popconfirm Props\n\n| Name | Type | Default | Description | Version |\n| --- | --- | --- | --- | --- |\n| negative-button-props | `ButtonProps` | `undefined` | Cancel button's DOM props | 2.27.0 |\n| negative-text | `string \\| null` | `'Cancel'` | Cancel button text. | 2.28.0 |\n| positive-button-props | `ButtonProps` | `undefined` | Confirm button's DOM props | 2.27.0 |\n| positive-text | `string \\| null` | `'Confirm'` | Confirm button text. | 2.28.0 |\n| show-icon | `boolean` | `true` | Whether to show icon. |  |\n| on-positive-click | `() => boolean \\| Promise<boolean> \\| any` | `undefined` | Callback of confirmation. |  |\n| on-negative-click | `() => boolean \\| Promise<boolean> \\| any` | `undefined` | Callback of cancel. |  |\n\nFor more props, see [popover](popover#Popover-Props).\n\n### Popconfirm Slots\n\n| Name    | Parameters | Description         |\n| ------- | ---------- | ------------------- |\n| action  | `()`       | Custom action.      |\n| default | `()`       | Popconfirm content. |\n| icon    | `()`       | Popconfirm icon.    |\n\n### Popconfirm Methods\n\nSee [popover](popover#Popover-Methods).\n"
  },
  {
    "path": "src/popconfirm/demos/enUS/no-icon.demo.vue",
    "content": "<markdown>\n# No icon\n</markdown>\n\n<template>\n  <n-popconfirm :show-icon=\"false\">\n    <template #trigger>\n      <n-button>No icon</n-button>\n    </template>\n    As is\n  </n-popconfirm>\n</template>\n"
  },
  {
    "path": "src/popconfirm/demos/zhCN/actions.demo.vue",
    "content": "<markdown>\n# 操作\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { useMessage } from 'naive-ui'\n\nconst message = useMessage()\n\nfunction handlePositiveClick() {\n  message.info('是的')\n}\n\nfunction handleNegativeClick() {\n  message.info('并不')\n}\n</script>\n\n<template>\n  <n-space>\n    <n-popconfirm\n      @positive-click=\"handlePositiveClick\"\n      @negative-click=\"handleNegativeClick\"\n    >\n      <template #trigger>\n        <n-button>引用</n-button>\n      </template>\n      一切都将一去杳然，任何人都无法将其捕获。\n    </n-popconfirm>\n    <n-popconfirm :negative-text=\"null\" @positive-click=\"handlePositiveClick\">\n      <template #trigger>\n        <n-button>只有确定</n-button>\n      </template>\n      一切都将一去杳然，任何人都无法将其捕获。\n    </n-popconfirm>\n    <n-popconfirm :positive-text=\"null\" @negative-click=\"handleNegativeClick\">\n      <template #trigger>\n        <n-button>只有取消</n-button>\n      </template>\n      一切都将一去杳然，任何人都无法将其捕获。\n    </n-popconfirm>\n    <n-popconfirm :positive-text=\"null\" :negative-text=\"null\">\n      <template #trigger>\n        <n-button>什么也没有</n-button>\n      </template>\n      一切都将一去杳然，任何人都无法将其捕获。\n    </n-popconfirm>\n    <n-popconfirm>\n      <template #trigger>\n        <n-button>自定义 action</n-button>\n      </template>\n      <template #action>\n        自定义 action\n      </template>\n      一切都将一去杳然，任何人都无法将其捕获。\n    </n-popconfirm>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/popconfirm/demos/zhCN/basic.demo.vue",
    "content": "<markdown>\n# 基础用法\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { useMessage } from 'naive-ui'\n\nconst message = useMessage()\n\nfunction handlePositiveClick() {\n  message.info('是的')\n}\n\nfunction handleNegativeClick() {\n  message.info('并不')\n}\n</script>\n\n<template>\n  <n-popconfirm\n    @positive-click=\"handlePositiveClick\"\n    @negative-click=\"handleNegativeClick\"\n  >\n    <template #trigger>\n      <n-button>引用</n-button>\n    </template>\n    一切都将一去杳然，任何人都无法将其捕获。\n  </n-popconfirm>\n</template>\n"
  },
  {
    "path": "src/popconfirm/demos/zhCN/custom-action.demo.vue",
    "content": "<markdown>\n# 自定义操作\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst show = ref(false)\n</script>\n\n<template>\n  <n-space>\n    <n-popconfirm v-model:show=\"show\">\n      <template #trigger>\n        <n-button>引用</n-button>\n      </template>\n      譬如，我或许可以就大象本身写一点什么，但对象的驯化却不知从何写起。\n      <template #action>\n        <n-button size=\"small\" @click=\"show = false\">\n          或许吧\n        </n-button>\n      </template>\n    </n-popconfirm>\n    <n-popconfirm positive-text=\"噢!\">\n      <template #trigger>\n        <n-button>引用</n-button>\n      </template>\n      譬如，我或许可以就大象本身写一点什么，但对象的驯化却不知从何写起。\n    </n-popconfirm>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/popconfirm/demos/zhCN/custom-icon.demo.vue",
    "content": "<markdown>\n# 自定义图标\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { MdHand as HandIcon } from '@vicons/ionicons4'\n</script>\n\n<template>\n  <n-popconfirm positive-text=\"ok\" negative-text=\"not ok\">\n    <template #icon>\n      <n-icon color=\"red\">\n        <HandIcon />\n      </n-icon>\n    </template>\n    <template #trigger>\n      <n-button>退出游戏</n-button>\n    </template>\n    不充钱怎么变强？\n  </n-popconfirm>\n</template>\n"
  },
  {
    "path": "src/popconfirm/demos/zhCN/event.demo.vue",
    "content": "<markdown>\n# 事件\n\n`positive-click` & `negative-click`\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { useMessage } from 'naive-ui'\n\nconst message = useMessage()\n\nfunction handlePositiveClick() {\n  message.info('positive click')\n}\n\nfunction handleNegativeClick() {\n  message.info('negative click')\n}\n</script>\n\n<template>\n  <n-popconfirm\n    @positive-click=\"handlePositiveClick\"\n    @negative-click=\"handleNegativeClick\"\n  >\n    <template #trigger>\n      <n-button>退出游戏</n-button>\n    </template>\n    我看 B 站的时候，听说有些游戏冲钱也是找罪受。\n  </n-popconfirm>\n</template>\n"
  },
  {
    "path": "src/popconfirm/demos/zhCN/index.demo-entry.md",
    "content": "# 弹出确认 Popconfirm\n\n一个确认，弹出来的。\n\n## 演示\n\n```demo\nbasic.vue\ncustom-action.vue\ncustom-icon.vue\nevent.vue\nno-icon.vue\nactions.vue\n```\n\n## API\n\n### Popconfirm Props\n\n| 名称 | 类型 | 默认值 | 说明 | 版本 |\n| --- | --- | --- | --- | --- |\n| negative-button-props | `ButtonProps` | `undefined` | 取消按钮的属性 | 2.27.0 |\n| negative-text | `string \\| null` | `'取消'` | 取消按钮文字 | 2.28.0 |\n| positive-button-props | `ButtonProps` | `undefined` | 确定按钮的属性 | 2.27.0 |\n| positive-text | `string \\| null` | `'确认'` | 确定按钮文字 | 2.28.0 |\n| show-icon | `boolean` | `true` | 是否显示图标 |  |\n| on-positive-click | `() => boolean \\| Promise<boolean> \\| any` | `undefined` | 点击确定的回调函数 |  |\n| on-negative-click | `() => boolean \\| Promise<boolean> \\| any` | `undefined` | 点击取消的回调函数 |  |\n\n更多 props 请参考 [popover](popover#Popover-Props).\n\n### Popconfirm Slots\n\n| 名称    | 参数 | 说明           |\n| ------- | ---- | -------------- |\n| action  | `()` | 自定义操作     |\n| default | `()` | 弹出确认的内容 |\n| icon    | `()` | 弹出确认的图标 |\n\n### Popconfirm Methods\n\nSee [popover](popover#Popover-Methods)\n"
  },
  {
    "path": "src/popconfirm/demos/zhCN/no-icon.demo.vue",
    "content": "<markdown>\n# 没有图标\n</markdown>\n\n<template>\n  <n-popconfirm :show-icon=\"false\">\n    <template #trigger>\n      <n-button>没图标</n-button>\n    </template>\n    就是这样\n  </n-popconfirm>\n</template>\n"
  },
  {
    "path": "src/popconfirm/index.ts",
    "content": "export type { PopconfirmInst } from './src/interface'\nexport { default as NPopconfirm, popconfirmProps } from './src/Popconfirm'\nexport type { PopconfirmProps, PopconfirmSlots } from './src/Popconfirm'\n"
  },
  {
    "path": "src/popconfirm/src/Popconfirm.tsx",
    "content": "import type { ExtractPropTypes, PropType, SlotsType, VNode } from 'vue'\nimport type { ThemeProps } from '../../_mixins'\nimport type { ExtractPublicPropTypes } from '../../_utils'\nimport type { ButtonProps } from '../../button'\nimport type { PopoverTrigger } from '../../popover'\nimport type { InternalPopoverInst } from '../../popover/src/interface'\nimport type { PopconfirmTheme } from '../styles'\nimport type { PopconfirmInst } from './interface'\nimport { defineComponent, h, provide, ref } from 'vue'\nimport { useConfig, useTheme } from '../../_mixins'\nimport { call, keep, omit } from '../../_utils'\nimport { NPopover } from '../../popover'\nimport { popoverBaseProps } from '../../popover/src/Popover'\nimport { popconfirmLight } from '../styles'\nimport { popconfirmInjectionKey } from './interface'\nimport PopconfirmPanel, { panelPropKeys } from './PopconfirmPanel'\nimport style from './styles/index.cssr'\n\nexport const popconfirmProps = {\n  ...(useTheme.props as ThemeProps<PopconfirmTheme>),\n  ...popoverBaseProps,\n  positiveText: String as PropType<string | null>,\n  negativeText: String as PropType<string | null>,\n  showIcon: {\n    type: Boolean,\n    default: true\n  },\n  trigger: {\n    type: String as PropType<PopoverTrigger>,\n    default: 'click'\n  },\n  positiveButtonProps: Object as PropType<ButtonProps>,\n  negativeButtonProps: Object as PropType<ButtonProps>,\n  onPositiveClick: Function as PropType<\n    (e: MouseEvent) => Promise<boolean> | boolean | any\n  >,\n  onNegativeClick: Function as PropType<\n    (e: MouseEvent) => Promise<boolean> | boolean | any\n  >\n}\n\nexport type PopconfirmProps = ExtractPublicPropTypes<typeof popconfirmProps>\n\nexport type PopconfirmSetupProps = ExtractPropTypes<typeof popconfirmProps>\n\nexport interface PopconfirmSlots {\n  action?: () => VNode[]\n  default?: () => VNode[]\n  icon?: () => VNode[]\n  trigger?: () => VNode[]\n}\n\nexport default defineComponent({\n  name: 'Popconfirm',\n  props: popconfirmProps,\n  slots: Object as SlotsType<PopconfirmSlots>,\n  __popover__: true,\n  setup(props) {\n    const { mergedClsPrefixRef } = useConfig()\n    const themeRef = useTheme(\n      'Popconfirm',\n      '-popconfirm',\n      style,\n      popconfirmLight,\n      props,\n      mergedClsPrefixRef\n    )\n    const popoverInstRef = ref<InternalPopoverInst | null>(null)\n    function handlePositiveClick(e: MouseEvent): void {\n      if (!popoverInstRef.value?.getMergedShow())\n        return\n      const { onPositiveClick, 'onUpdate:show': onUpdateShow } = props\n      void Promise.resolve(onPositiveClick ? onPositiveClick(e) : true).then(\n        (value) => {\n          if (value === false)\n            return\n          popoverInstRef.value?.setShow(false)\n          if (onUpdateShow)\n            call(onUpdateShow, false)\n        }\n      )\n    }\n    function handleNegativeClick(e: MouseEvent): void {\n      if (!popoverInstRef.value?.getMergedShow())\n        return\n      const { onNegativeClick, 'onUpdate:show': onUpdateShow } = props\n      void Promise.resolve(onNegativeClick ? onNegativeClick(e) : true).then(\n        (value) => {\n          if (value === false)\n            return\n          popoverInstRef.value?.setShow(false)\n          if (onUpdateShow)\n            call(onUpdateShow, false)\n        }\n      )\n    }\n    provide(popconfirmInjectionKey, {\n      mergedThemeRef: themeRef,\n      mergedClsPrefixRef,\n      props\n    })\n    const returned = {\n      setShow(value: boolean) {\n        popoverInstRef.value?.setShow(value)\n      },\n      syncPosition() {\n        popoverInstRef.value?.syncPosition()\n      },\n      mergedTheme: themeRef,\n      popoverInstRef,\n      handlePositiveClick,\n      handleNegativeClick\n    }\n    return returned satisfies PopconfirmInst\n  },\n  render() {\n    const { $slots: slots, $props: props, mergedTheme } = this\n    return (\n      <NPopover\n        {...omit(props, panelPropKeys)}\n        theme={mergedTheme.peers.Popover}\n        themeOverrides={mergedTheme.peerOverrides.Popover}\n        internalExtraClass={['popconfirm']}\n        ref=\"popoverInstRef\"\n      >\n        {{\n          trigger: slots.trigger,\n          default: () => {\n            const panelProps = keep(props, panelPropKeys)\n            return (\n              <PopconfirmPanel\n                {...panelProps}\n                onPositiveClick={this.handlePositiveClick}\n                onNegativeClick={this.handleNegativeClick}\n              >\n                {slots}\n              </PopconfirmPanel>\n            )\n          }\n        }}\n      </NPopover>\n    )\n  }\n})\n"
  },
  {
    "path": "src/popconfirm/src/PopconfirmPanel.tsx",
    "content": "import type { CSSProperties, PropType } from 'vue'\nimport { computed, defineComponent, h, inject, toRef } from 'vue'\nimport { NBaseIcon } from '../../_internal'\nimport { WarningIcon } from '../../_internal/icons'\nimport { useConfig, useLocale, useThemeClass } from '../../_mixins'\nimport { keysOf, resolveSlot, resolveWrappedSlot } from '../../_utils'\nimport { NButton } from '../../button'\nimport { popconfirmInjectionKey } from './interface'\n\nexport const panelProps = {\n  positiveText: String as PropType<string | null>,\n  negativeText: String as PropType<string | null>,\n  showIcon: {\n    type: Boolean,\n    default: true\n  },\n  onPositiveClick: {\n    type: Function as PropType<(e: MouseEvent) => void>,\n    required: true\n  },\n  onNegativeClick: {\n    type: Function as PropType<(e: MouseEvent) => void>,\n    required: true\n  }\n} as const\n\nexport const panelPropKeys = keysOf(panelProps)\n\nexport default defineComponent({\n  name: 'NPopconfirmPanel',\n  props: panelProps,\n  setup(props) {\n    const { localeRef } = useLocale('Popconfirm')\n    const { inlineThemeDisabled } = useConfig()\n    const {\n      mergedClsPrefixRef,\n      mergedThemeRef,\n      props: popconfirmProps\n    } = inject(popconfirmInjectionKey)!\n    const cssVarsRef = computed(() => {\n      const {\n        common: { cubicBezierEaseInOut },\n        self: { fontSize, iconSize, iconColor }\n      } = mergedThemeRef.value\n      return {\n        '--n-bezier': cubicBezierEaseInOut,\n        '--n-font-size': fontSize,\n        '--n-icon-size': iconSize,\n        '--n-icon-color': iconColor\n      }\n    })\n    const themeClassHandle = inlineThemeDisabled\n      ? useThemeClass(\n          'popconfirm-panel',\n          undefined,\n          cssVarsRef,\n          popconfirmProps\n        )\n      : undefined\n    return {\n      ...useLocale('Popconfirm'),\n      mergedClsPrefix: mergedClsPrefixRef,\n      cssVars: inlineThemeDisabled ? undefined : cssVarsRef,\n      localizedPositiveText: computed(() => {\n        return props.positiveText || localeRef.value.positiveText\n      }),\n      localizedNegativeText: computed(() => {\n        return props.negativeText || localeRef.value.negativeText\n      }),\n      positiveButtonProps: toRef(popconfirmProps, 'positiveButtonProps'),\n      negativeButtonProps: toRef(popconfirmProps, 'negativeButtonProps'),\n      handlePositiveClick(e: MouseEvent) {\n        props.onPositiveClick(e)\n      },\n      handleNegativeClick(e: MouseEvent) {\n        props.onNegativeClick(e)\n      },\n      themeClass: themeClassHandle?.themeClass,\n      onRender: themeClassHandle?.onRender\n    }\n  },\n  render() {\n    const { mergedClsPrefix, showIcon, $slots } = this\n    const actionContentNode = resolveSlot($slots.action, () =>\n      this.negativeText === null && this.positiveText === null\n        ? []\n        : [\n            this.negativeText !== null && (\n              <NButton\n                size=\"small\"\n                onClick={this.handleNegativeClick}\n                {...this.negativeButtonProps}\n              >\n                {{ default: () => this.localizedNegativeText }}\n              </NButton>\n            ),\n            this.positiveText !== null && (\n              <NButton\n                size=\"small\"\n                type=\"primary\"\n                onClick={this.handlePositiveClick}\n                {...this.positiveButtonProps}\n              >\n                {{ default: () => this.localizedPositiveText }}\n              </NButton>\n            )\n          ])\n    this.onRender?.()\n    return (\n      <div\n        class={[`${mergedClsPrefix}-popconfirm__panel`, this.themeClass]}\n        style={this.cssVars as CSSProperties}\n      >\n        {resolveWrappedSlot($slots.default, children =>\n          showIcon || children ? (\n            <div class={`${mergedClsPrefix}-popconfirm__body`}>\n              {showIcon ? (\n                <div class={`${mergedClsPrefix}-popconfirm__icon`}>\n                  {resolveSlot($slots.icon, () => [\n                    <NBaseIcon clsPrefix={mergedClsPrefix}>\n                      {{ default: () => <WarningIcon /> }}\n                    </NBaseIcon>\n                  ])}\n                </div>\n              ) : null}\n              {children}\n            </div>\n          ) : null)}\n        {actionContentNode ? (\n          <div class={[`${mergedClsPrefix}-popconfirm__action`]}>\n            {actionContentNode}\n          </div>\n        ) : null}\n      </div>\n    )\n  }\n})\n"
  },
  {
    "path": "src/popconfirm/src/interface.ts",
    "content": "import type { Ref } from 'vue'\nimport type { MergedTheme } from '../../_mixins'\nimport type { PopoverInst } from '../../popover'\nimport type { PopconfirmTheme } from '../styles'\nimport type { PopconfirmSetupProps } from './Popconfirm'\nimport { createInjectionKey } from '../../_utils'\n\nexport type PopconfirmInst = PopoverInst\n\nexport interface PopconfirmInjection {\n  mergedThemeRef: Ref<MergedTheme<PopconfirmTheme>>\n  mergedClsPrefixRef: Ref<string>\n  props: PopconfirmSetupProps\n}\n\nexport const popconfirmInjectionKey\n  = createInjectionKey<PopconfirmInjection>('n-popconfirm')\n"
  },
  {
    "path": "src/popconfirm/src/styles/index.cssr.ts",
    "content": "import { c, cB, cE } from '../../../_utils/cssr'\n\n// vars:\n// --n-font-size\n// --n-icon-size\n// --n-bezier\n// --n-icon-color\nexport default cB('popconfirm', [\n  cE('body', `\n    font-size: var(--n-font-size);\n    display: flex;\n    align-items: center;\n    flex-wrap: nowrap;\n    position: relative;\n  `, [\n    cE('icon', `\n      display: flex;\n      font-size: var(--n-icon-size);\n      color: var(--n-icon-color);\n      transition: color .3s var(--n-bezier);\n      margin: 0 8px 0 0;\n    `)\n  ]),\n  cE('action', `\n    display: flex;\n    justify-content: flex-end;\n  `, [\n    c('&:not(:first-child)', 'margin-top: 8px'),\n    cB('button', [\n      c('&:not(:last-child)', 'margin-right: 8px;')\n    ])\n  ])\n])\n"
  },
  {
    "path": "src/popconfirm/styles/_common.ts",
    "content": "export default {\n  iconSize: '22px'\n}\n"
  },
  {
    "path": "src/popconfirm/styles/dark.ts",
    "content": "import type { PopconfirmTheme } from './light'\nimport { commonDark } from '../../_styles/common'\nimport { buttonDark } from '../../button/styles'\nimport { popoverDark } from '../../popover/styles'\nimport { self } from './light'\n\nconst popconfirmDark: PopconfirmTheme = {\n  name: 'Popconfirm',\n  common: commonDark,\n  peers: {\n    Button: buttonDark,\n    Popover: popoverDark\n  },\n  self\n}\n\nexport default popconfirmDark\n"
  },
  {
    "path": "src/popconfirm/styles/index.ts",
    "content": "export { default as popconfirmDark } from './dark'\nexport { default as popconfirmLight } from './light'\nexport type { PopconfirmTheme, PopconfirmThemeVars } from './light'\n"
  },
  {
    "path": "src/popconfirm/styles/light.ts",
    "content": "import type { ThemeCommonVars } from '../../_styles/common'\nimport { createTheme } from '../../_mixins'\nimport { commonLight } from '../../_styles/common'\nimport { buttonLight } from '../../button/styles'\nimport { popoverLight } from '../../popover/styles'\n\nimport commonVars from './_common'\n\nexport function self(vars: ThemeCommonVars) {\n  const { fontSize, warningColor } = vars\n  return {\n    ...commonVars,\n    fontSize,\n    iconColor: warningColor\n  }\n}\n\nexport type PopconfirmThemeVars = ReturnType<typeof self>\n\nconst popconfirmLight = createTheme({\n  name: 'Popconfirm',\n  common: commonLight,\n  peers: {\n    Button: buttonLight,\n    Popover: popoverLight\n  },\n  self\n})\n\nexport default popconfirmLight\nexport type PopconfirmTheme = typeof popconfirmLight\n"
  },
  {
    "path": "src/popconfirm/tests/Popconfirm.spec.ts",
    "content": "import { mount } from '@vue/test-utils'\nimport { h, nextTick } from 'vue'\nimport { NButton } from '../../button'\nimport { NPopconfirm } from '../index'\n\ndescribe('n-popconfirm', () => {\n  it('should work with import on demand', () => {\n    mount(NPopconfirm, {\n      slots: {\n        trigger: () => 'star kirby'\n      }\n    })\n  })\n\n  it('should work with `negative-text` `positive-text`', async () => {\n    const wrapper = mount(NPopconfirm, {\n      attachTo: document.body,\n      props: {\n        'negative-text': 'negative',\n        'positive-text': 'positive'\n      },\n      slots: {\n        default: () => 'test-text',\n        trigger: () => h(NButton, null, { default: () => 'test-button' })\n      }\n    })\n\n    await wrapper.find('button').trigger('click')\n    expect(document.querySelectorAll('.n-button__content')[1].textContent).toBe(\n      'negative'\n    )\n    expect(document.querySelectorAll('.n-button__content')[2].textContent).toBe(\n      'positive'\n    )\n    wrapper.unmount()\n  })\n\n  it('should work with `show-icon` prop', async () => {\n    const wrapper = mount(NPopconfirm, {\n      attachTo: document.body,\n      props: {\n        showIcon: false\n      },\n      slots: {\n        default: () => 'test-text',\n        trigger: () => h(NButton, null, { default: () => 'test-button' })\n      }\n    })\n\n    await wrapper.find('button').trigger('click')\n    expect(document.querySelector('.n-popconfirm__icon')).toBe(null)\n    wrapper.unmount()\n  })\n\n  it('should work with `on-positive-click` prop', async () => {\n    const onClick = vi.fn()\n    const wrapper = mount(NPopconfirm, {\n      attachTo: document.body,\n      props: {\n        onPositiveClick: onClick\n      },\n      slots: {\n        default: () => 'test-text',\n        trigger: () => h(NButton, null, { default: () => 'test-button' })\n      }\n    })\n\n    await wrapper.find('button').trigger('click')\n    document\n      .querySelectorAll('.n-button')[2]\n      ?.dispatchEvent(new MouseEvent('click'))\n    await nextTick()\n    expect(onClick).toHaveBeenCalled()\n    wrapper.unmount()\n  })\n\n  it('should work with `on-negative-click` prop', async () => {\n    const onClick = vi.fn()\n    const wrapper = mount(NPopconfirm, {\n      attachTo: document.body,\n      props: {\n        onNegativeClick: onClick\n      },\n      slots: {\n        default: () => 'test-text',\n        trigger: () => h(NButton, null, { default: () => 'test-button' })\n      }\n    })\n\n    await wrapper.find('button').trigger('click')\n    document\n      .querySelectorAll('.n-button')[1]\n      ?.dispatchEvent(new MouseEvent('click'))\n    await nextTick()\n    expect(onClick).toHaveBeenCalled()\n    wrapper.unmount()\n  })\n\n  it('should work with slot', async () => {\n    const wrapper = mount(NPopconfirm, {\n      attachTo: document.body,\n      slots: {\n        default: () => 'test-text',\n        trigger: () => h(NButton, null, { default: () => 'test-button' }),\n        action: () => 'test-action',\n        icon: () => 'test-icon'\n      }\n    })\n\n    await wrapper.find('button').trigger('click')\n    expect(document.querySelector('.n-popconfirm__icon')?.textContent).toBe(\n      'test-icon'\n    )\n    expect(\n      document.querySelector('.n-popconfirm__body')?.textContent\n    ).toContain('test-text')\n    expect(document.querySelector('.n-popconfirm__action')?.textContent).toBe(\n      'test-action'\n    )\n    wrapper.unmount()\n  })\n})\n"
  },
  {
    "path": "src/popconfirm/tests/server.spec.tsx",
    "content": "import { setup } from '@css-render/vue3-ssr'\nimport { renderToString } from '@vue/server-renderer'\n/**\n * @vitest-environment node\n */\nimport { createSSRApp, h } from 'vue'\nimport { NPopconfirm } from '../..'\n\ndescribe('server side rendering', () => {\n  it('works', async () => {\n    const app = createSSRApp(() => (\n      <NPopconfirm>\n        {{\n          trigger: () => 'kirby'\n        }}\n      </NPopconfirm>\n    ))\n    setup(app)\n    try {\n      await renderToString(app)\n    }\n    catch (e) {\n      expect(e).not.toBeTruthy()\n    }\n  })\n})\n"
  },
  {
    "path": "src/popover/demos/enUS/basic.demo.vue",
    "content": "<markdown>\n# Basic\n</markdown>\n\n<template>\n  <n-popover trigger=\"hover\">\n    <template #trigger>\n      <n-button> Hover </n-button>\n    </template>\n    <span>Maybe I don't really want to know how your garden grows</span>\n  </n-popover>\n</template>\n"
  },
  {
    "path": "src/popover/demos/enUS/delay.demo.vue",
    "content": "<markdown>\n# Delay\n</markdown>\n\n<template>\n  <n-popover trigger=\"hover\" :delay=\"500\" :duration=\"500\">\n    <template #trigger>\n      <n-button> Delay 500, Duration 500 </n-button>\n    </template>\n    <span>\n      Lately did you ever feel the pain In the morning rain As it soaks it to\n      the bone\n    </span>\n  </n-popover>\n</template>\n"
  },
  {
    "path": "src/popover/demos/enUS/event.demo.vue",
    "content": "<markdown>\n# Event\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { useMessage } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst message = useMessage()\nconst showPopover = ref(false)\n\nfunction handleUpdateShow(show: boolean) {\n  message.success(show ? 'show' : 'hide')\n}\n</script>\n\n<template>\n  <n-space>\n    <n-popover\n      placement=\"bottom\"\n      trigger=\"hover\"\n      @update:show=\"handleUpdateShow\"\n    >\n      <template #trigger>\n        <n-button>Hover</n-button>\n      </template>\n      <span>I wish they all could be California girls</span>\n    </n-popover>\n    <n-popover\n      placement=\"bottom\"\n      trigger=\"click\"\n      @update:show=\"handleUpdateShow\"\n    >\n      <template #trigger>\n        <n-button>Click</n-button>\n      </template>\n      <span>I wish they all could be California girls</span>\n    </n-popover>\n    <n-popover\n      :show=\"showPopover\"\n      placement=\"bottom\"\n      trigger=\"manual\"\n      @update:show=\"handleUpdateShow\"\n    >\n      <template #trigger>\n        <n-button @click=\"showPopover = !showPopover\">\n          Manual\n        </n-button>\n      </template>\n      <span>I wish they all could be California girls</span>\n    </n-popover>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/popover/demos/enUS/flip.demo.vue",
    "content": "<markdown>\n# Adjust the popover\n\nUse `flip` to decide whether to adjust, use `shift` to decide whether to shift.\n</markdown>\n\n<template>\n  <n-popover\n    trigger=\"click\"\n    placement=\"bottom-start\"\n    :flip=\"true\"\n    :flip-level=\"1\"\n  >\n    <template #trigger>\n      <n-button> Offset </n-button>\n    </template>\n    <span>\n      The default is to adjust within the existing position. If the existing\n      position is not satisfied, then you can set `shift` prop, which will be\n      offset appropriately at the same latitude. Note: if the popover is large\n      enough, any offset will be blocked!\n    </span>\n  </n-popover>\n</template>\n"
  },
  {
    "path": "src/popover/demos/enUS/index.demo-entry.md",
    "content": "# Popover\n\nPop some hidden message around content. There isn't much builtin styles in popover. It's more up to you to fill the content.\n\nIf you just want to display some basic text message, see [Tooltip](tooltip) instead.\n\n## Demos\n\n```demo\nbasic.vue\ntrigger.vue\ndelay.vue\nno-arrow.vue\nevent.vue\nplacement.vue\nraw-content.vue\nstyle.vue\ntrigger-width.vue\nmanual-position.vue\nslots.vue\n```\n\n## API\n\n### Popover Props\n\n| Name | Type | Default | Description | Version |\n| --- | --- | --- | --- | --- |\n| animated | `boolean` | `true` | Use animation when popping up. |  |\n| arrow-point-to-center | `boolean` | `false` | Whether the arrow points to center of the trigger element. | 2.26.0 |\n| arrow-class | `string` | `undefined` | Arrow class of the popover. | 2.36.0 |\n| arrow-style | `string \\| Object` | `undefined` | Arrow style of the popover. |  |\n| arrow-wrapper-class | `string` | `undefined` | Arrow class of the popover wrapper. | 2.36.0 |\n| arrow-wrapper-style | `string \\| Object` | `undefined` | Arrow style of the popover wrapper. | 2.36.0 |\n| content-class | `string` | `undefined` | Content class of the popover. | 2.36.0 |\n| content-style | `string \\| Object` | `undefined` | Content style of the popover. | 2.28.3 |\n| delay | `number` | `100` | Popover showing delay when trigger is `hover`. |  |\n| disabled | `boolean` | `false` | Whether the popover can't be activated. |  |\n| display-directive | `'if' \\| 'show'` | `'if'` | The conditionally render directive to show popover content. `if` means using `v-if` to render content, `show` means using `v-show` to render content. |  |\n| duration | `number` | `100` | Popover vanish delay when trigger is `hover`. |  |\n| flip | `boolean` | `true` | Whether to flip the popover when there is no space for current placement. |  |\n| footer-class | `string` | `undefined` | Footer class of the popover. | 2.36.0 |\n| footer-style | `string \\| Object` | `undefined` | Footer style of the popover. | 2.31.0 |\n| header-class | `string` | `undefined` | Header class of the popover. | 2.36.0 |\n| header-style | `string \\| Object` | `undefined` | Header style of the popover. | 2.28.3 |\n| keep-alive-on-hover | `boolean` | `true` | Whether to keep popover shown when hover on popover itself with `trigger=\"hover\"`. | 2.25.0 |\n| overlap | `boolean` | `false` | Overlap trigger element. |  |\n| placement | `'top-start' \\| 'top' \\| 'top-end' \\| 'right-start' \\| 'right' \\| 'right-end' \\| 'bottom-start' \\| 'bottom' \\| 'bottom-end' \\| 'left-start' \\| 'left' \\| 'left-end' \\| ` | `'top'` | Popover placement. |  |\n| raw | `boolean` | `false` | Whether to use no default styles. |  |\n| scrollable | `boolean` | `false` | Whether the popover's content is scrollable. | 2.28.3 |\n| show-arrow | `boolean` | `true` | Whether to show arrow if set. |  |\n| show | `boolean` | `undefined` | Whether to show popover. |  |\n| to | `string \\| HTMLElement \\| false` | `'body'` | Container node of the popover content. `false` will keep it at trigger container. |  |\n| trigger | `'hover' \\| 'click' \\| 'focus' \\| 'manual'` | `'hover'` | The popover trigger type. |  |\n| width | `number \\| 'trigger'` | `undefined` | `'trigger'` means popover's width will follow its trigger's width. |  |\n| x | `number` | `undefined` | The CSS `left` pixel value when popover manually positioned (x, y need to be set together). |  |\n| y | `number` | `undefined` | The CSS `top` pixel value when popover manually positioned (x, y need to be set together). |  |\n| z-index | `number` | `undefined` | The z-index of the popover. |  |\n| on-clickoutside | `(e: MouseEvent) => void` | `undefined` | Callback function triggered when clickoutside. |  |\n| on-update:show | `(value: boolean) => void` | `undefined` | Callback on show status changes. |  |\n\n### Popover Slots\n\n| Name | Parameters | Description | Version |\n| --- | --- | --- | --- |\n| trigger | `()` | The element or component that triggers popover. |  |\n| footer | `()` | The footer content of the popover. | 2.31.0 |\n| header | `()` | The header content of the popover. | 2.28.3 |\n| default | `()` | The content inside popover. |  |\n\n### Popover Methods\n\n| Name         | Parameters        | Description                           |\n| ------------ | ----------------- | ------------------------------------- |\n| setShow      | `(show: boolean)` | Set show status in uncontrolled mode. |\n| syncPosition | `()`              | Sync popover position.                |\n"
  },
  {
    "path": "src/popover/demos/enUS/manual-position.demo.vue",
    "content": "<markdown>\n# Manually positioned\n\nWarn: when manually positioned, the `trigger` prop must be `'manual'`.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst x = ref(0)\nconst y = ref(0)\nconst showPopover = ref(false)\n\nfunction handleClick(e: MouseEvent) {\n  if (showPopover.value) {\n    showPopover.value = false\n  }\n  else {\n    showPopover.value = true\n    x.value = e.clientX\n    y.value = e.clientY\n  }\n}\n</script>\n\n<template>\n  <div\n    style=\"width: 200px; height: 200px; background-color: rgba(0, 128, 0, 0.5)\"\n    @click=\"handleClick\"\n  />\n  <n-popover :show=\"showPopover\" :x=\"x\" :y=\"y\" trigger=\"manual\">\n    Cool!\n  </n-popover>\n</template>\n"
  },
  {
    "path": "src/popover/demos/enUS/no-arrow.demo.vue",
    "content": "<markdown>\n# No arrow\n</markdown>\n\n<template>\n  <n-popover trigger=\"hover\" :show-arrow=\"false\">\n    <template #trigger>\n      <n-button> Hover </n-button>\n    </template>\n    <span>Like a rect</span>\n  </n-popover>\n</template>\n"
  },
  {
    "path": "src/popover/demos/enUS/placement.demo.vue",
    "content": "<markdown>\n# Placement\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst overlap = ref(false)\n</script>\n\n<template>\n  <n-switch v-model:value=\"overlap\" /> Overlap Trigger Element\n  <n-divider />\n  <div class=\"popover-grid\">\n    <n-popover :overlap=\"overlap\" placement=\"top-start\" trigger=\"click\">\n      <template #trigger>\n        <n-button size=\"small\" style=\"grid-area: 1 / 1 / 2 / 2\">\n          Top Start\n        </n-button>\n      </template>\n      <div class=\"large-text\">\n        Oops!\n      </div>\n    </n-popover>\n    <n-popover :overlap=\"overlap\" placement=\"top\" trigger=\"click\">\n      <template #trigger>\n        <n-button size=\"small\" style=\"grid-area: 1 / 2 / 2 / 3\">\n          Top\n        </n-button>\n      </template>\n      <div class=\"large-text\">\n        Oops!\n      </div>\n    </n-popover>\n    <n-popover :overlap=\"overlap\" placement=\"top-end\" trigger=\"click\">\n      <template #trigger>\n        <n-button size=\"small\" style=\"grid-area: 1 / 3 / 2 / 4\">\n          Top End\n        </n-button>\n      </template>\n      <div class=\"large-text\">\n        Oops!\n      </div>\n    </n-popover>\n    <n-popover :overlap=\"overlap\" placement=\"left-start\" trigger=\"click\">\n      <template #trigger>\n        <n-button size=\"small\" style=\"grid-area: 2 / 1 / 3 / 2\">\n          Left Start\n        </n-button>\n      </template>\n      <div class=\"large-text\">\n        Oops!\n      </div>\n    </n-popover>\n    <n-popover :overlap=\"overlap\" placement=\"left\" trigger=\"click\">\n      <template #trigger>\n        <n-button size=\"small\" style=\"grid-area: 3 / 1 / 4 / 2\">\n          Left\n        </n-button>\n      </template>\n      <div class=\"large-text\">\n        Oops!\n      </div>\n    </n-popover>\n    <n-popover :overlap=\"overlap\" placement=\"left-end\" trigger=\"click\">\n      <template #trigger>\n        <n-button size=\"small\" style=\"grid-area: 4 / 1 / 5 / 2\">\n          Left End\n        </n-button>\n      </template>\n      <div class=\"large-text\">\n        Oops!\n      </div>\n    </n-popover>\n    <n-popover :overlap=\"overlap\" placement=\"right-start\" trigger=\"click\">\n      <template #trigger>\n        <n-button size=\"small\" style=\"grid-area: 2 / 3 / 3 / 4\">\n          Right Start\n        </n-button>\n      </template>\n      <div class=\"large-text\">\n        Oops!\n      </div>\n    </n-popover>\n    <n-popover :overlap=\"overlap\" placement=\"right\" trigger=\"click\">\n      <template #trigger>\n        <n-button size=\"small\" style=\"grid-area: 3 / 3 / 4 / 4\">\n          Right\n        </n-button>\n      </template>\n      <div class=\"large-text\">\n        Oops!\n      </div>\n    </n-popover>\n    <n-popover :overlap=\"overlap\" placement=\"right-end\" trigger=\"click\">\n      <template #trigger>\n        <n-button size=\"small\" style=\"grid-area: 4 / 3 / 5 / 4\">\n          Right End\n        </n-button>\n      </template>\n      <div class=\"large-text\">\n        Oops!\n      </div>\n    </n-popover>\n    <n-popover :overlap=\"overlap\" placement=\"bottom-start\" trigger=\"click\">\n      <template #trigger>\n        <n-button size=\"small\" style=\"grid-area: 5 / 1 / 6 / 2\">\n          Bottom Start\n        </n-button>\n      </template>\n      <div class=\"large-text\">\n        Oops!\n      </div>\n    </n-popover>\n    <n-popover :overlap=\"overlap\" placement=\"bottom\" trigger=\"click\">\n      <template #trigger>\n        <n-button size=\"small\" style=\"grid-area: 5 / 2 / 6 / 3\">\n          Bottom\n        </n-button>\n      </template>\n      <div class=\"large-text\">\n        Oops!\n      </div>\n    </n-popover>\n    <n-popover :overlap=\"overlap\" placement=\"bottom-end\" trigger=\"click\">\n      <template #trigger>\n        <n-button size=\"small\" style=\"grid-area: 5 / 3 / 6 / 4\">\n          Bottom End\n        </n-button>\n      </template>\n      <div class=\"large-text\">\n        Oops\n      </div>\n    </n-popover>\n  </div>\n</template>\n\n<style>\n.popover-grid {\n  display: grid;\n  grid-template-columns: auto auto auto auto auto;\n  grid-gap: 12px;\n  justify-content: center;\n  align-items: center;\n}\n\n.large-text {\n  font-size: 48px;\n}\n</style>\n"
  },
  {
    "path": "src/popover/demos/enUS/raw-content.demo.vue",
    "content": "<markdown>\n# Raw content\n</markdown>\n\n<template>\n  <n-popover trigger=\"hover\" raw :show-arrow=\"false\">\n    <template #trigger>\n      <n-button> Hover </n-button>\n    </template>\n    <div\n      style=\"\n        width: 100px;\n        height: 100px;\n        background-color: red;\n        transform-origin: inherit;\n      \"\n    >\n      Who kicks a hole in the sky so the heaven cry over me.\n    </div>\n  </n-popover>\n</template>\n"
  },
  {
    "path": "src/popover/demos/enUS/slots.demo.vue",
    "content": "<markdown>\n# Slots\n\nUse `header` or `footer` slot to customize header or footer.\n</markdown>\n\n<template>\n  <n-popover trigger=\"click\">\n    <template #trigger>\n      <n-button>There's a divider</n-button>\n    </template>\n    <template #header>\n      <n-text strong depth=\"1\">\n        Divider is on the bottom.\n      </n-text>\n    </template>\n    Content.\n    <template #footer>\n      Divider is on the top.\n    </template>\n  </n-popover>\n</template>\n"
  },
  {
    "path": "src/popover/demos/enUS/style.demo.vue",
    "content": "<markdown>\n# Style\n\nYou can use `style` to set popover's style. You can set `scrollable` to make popover's content scrollable. If popover is scrollable, You can use `content-style` to set popover's content style.\n</markdown>\n\n<template>\n  <n-space>\n    <n-popover style=\"width: 500px\" trigger=\"click\">\n      <template #trigger>\n        <n-button> Width 500px </n-button>\n      </template>\n      Looks like a bar\n    </n-popover>\n    <n-popover style=\"max-width: 100px\" trigger=\"click\">\n      <template #trigger>\n        <n-button> Max width 100px </n-button>\n      </template>\n      Who kicks a hole in the sky so the heaven cry over me.\n    </n-popover>\n    <n-popover style=\"max-height: 240px\" trigger=\"click\" scrollable>\n      <template #trigger>\n        <n-button>Max height 240px</n-button>\n      </template>\n      Put whatever you want.<br>\n      Put whatever you want.<br>\n      Put whatever you want.<br>\n      Put whatever you want.<br>\n      Put whatever you want.<br>\n      Put whatever you want.<br>\n      Put whatever you want.<br>\n      Put whatever you want.<br>\n      Put whatever you want.<br>\n      Put whatever you want.<br>\n      Put whatever you want.<br>\n      Put whatever you want.<br>\n    </n-popover>\n    <n-popover style=\"padding: 0\" trigger=\"click\">\n      <template #trigger>\n        <n-button> No padding </n-button>\n      </template>\n      Put whatever you want.\n    </n-popover>\n    <n-popover\n      style=\"max-height: 240px\"\n      content-style=\"padding: 0;\"\n      trigger=\"click\"\n      scrollable\n    >\n      <template #trigger>\n        <n-button>Scrollable & no padding</n-button>\n      </template>\n      Put whatever you want.<br>\n      Put whatever you want.<br>\n      Put whatever you want.<br>\n      Put whatever you want.<br>\n      Put whatever you want.<br>\n      Put whatever you want.<br>\n      Put whatever you want.<br>\n      Put whatever you want.<br>\n      Put whatever you want.<br>\n      Put whatever you want.<br>\n      Put whatever you want.<br>\n      Put whatever you want.<br>\n    </n-popover>\n    <n-popover\n      trigger=\"click\"\n      content-style=\"padding: 0;\"\n      header-style=\"padding: 0;\"\n    >\n      <template #trigger>\n        <n-button>With header & no padding</n-button>\n      </template>\n      <template #header>\n        <n-text strong depth=\"1\">\n          Divider is on the bottom.\n        </n-text>\n      </template>\n      Divider is on the top.\n    </n-popover>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/popover/demos/enUS/trigger-width.demo.vue",
    "content": "<markdown>\n# Use trigger width\n\nSet `width=\"trigger\"` to make popover's width the same as its trigger.\n</markdown>\n\n<template>\n  <n-popover width=\"trigger\">\n    <template #trigger>\n      <n-button>I would like to leave this city</n-button>\n    </template>\n    This old town don't smell too pretty and I can feel the warning signs\n    running around my mind\n  </n-popover>\n</template>\n"
  },
  {
    "path": "src/popover/demos/enUS/trigger.demo.vue",
    "content": "<markdown>\n# Trigger\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst showPopover = ref(false)\n</script>\n\n<template>\n  <n-space>\n    <n-popover trigger=\"hover\">\n      <template #trigger>\n        <n-button>Hover</n-button>\n      </template>\n      <span>I wish they all could be California girls</span>\n    </n-popover>\n    <n-popover trigger=\"hover\" :keep-alive-on-hover=\"false\">\n      <template #trigger>\n        <n-button>Hover (ignore popup)</n-button>\n      </template>\n      <span>I wish they all could be California girls</span>\n    </n-popover>\n    <n-popover trigger=\"click\">\n      <template #trigger>\n        <n-button>Click</n-button>\n      </template>\n      <span>I wish they all could be California girls</span>\n    </n-popover>\n    <n-popover trigger=\"focus\">\n      <template #trigger>\n        <n-button>Focus</n-button>\n      </template>\n      <span>I wish they all could be California girls</span>\n    </n-popover>\n    <n-popover trigger=\"manual\" :show=\"showPopover\">\n      <template #trigger>\n        <n-button @click=\"showPopover = !showPopover\">\n          Manual\n        </n-button>\n      </template>\n      <span>I wish they all could be California girls</span>\n    </n-popover>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/popover/demos/zhCN/basic.demo.vue",
    "content": "<markdown>\n# 基础用法\n</markdown>\n\n<template>\n  <n-popover trigger=\"hover\">\n    <template #trigger>\n      <n-button>悬浮</n-button>\n    </template>\n    <span>或许不想知道你的花园长得咋样</span>\n  </n-popover>\n</template>\n"
  },
  {
    "path": "src/popover/demos/zhCN/center-arrow-debug.demo.vue",
    "content": "<markdown>\n# Center arrow debug\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst overlap = ref(false)\n</script>\n\n<template>\n  <n-switch v-model:value=\"overlap\" /> 覆盖触发元素\n  <n-divider />\n  <div class=\"popover-grid center-arrow-debug\">\n    <n-popover\n      :overlap=\"overlap\"\n      arrow-point-to-center\n      placement=\"top-start\"\n      trigger=\"click\"\n    >\n      <template #trigger>\n        <n-button size=\"small\" style=\"grid-area: 1 / 1 / 2 / 2\">\n          Top Start\n        </n-button>\n      </template>\n      <div class=\"large-text\">\n        啊！\n      </div>\n    </n-popover>\n    <n-popover\n      :overlap=\"overlap\"\n      arrow-point-to-center\n      placement=\"top\"\n      trigger=\"click\"\n    >\n      <template #trigger>\n        <n-button size=\"small\" style=\"grid-area: 1 / 2 / 2 / 3\">\n          Top\n        </n-button>\n      </template>\n      <div class=\"large-text\">\n        啊！\n      </div>\n    </n-popover>\n    <n-popover\n      :overlap=\"overlap\"\n      arrow-point-to-center\n      placement=\"top-end\"\n      trigger=\"click\"\n    >\n      <template #trigger>\n        <n-button size=\"small\" style=\"grid-area: 1 / 3 / 2 / 4\">\n          Top End\n        </n-button>\n      </template>\n      <div class=\"large-text\">\n        啊！\n      </div>\n    </n-popover>\n    <n-popover\n      :overlap=\"overlap\"\n      arrow-point-to-center\n      placement=\"left-start\"\n      trigger=\"click\"\n      style=\"--v-target-height: 40px\"\n    >\n      <template #trigger>\n        <n-button size=\"small\" style=\"grid-area: 2 / 1 / 3 / 2\">\n          Left Start\n        </n-button>\n      </template>\n      <div class=\"large-text\">\n        啊！\n      </div>\n    </n-popover>\n    <n-popover\n      :overlap=\"overlap\"\n      arrow-point-to-center\n      placement=\"left\"\n      trigger=\"click\"\n    >\n      <template #trigger>\n        <n-button size=\"small\" style=\"grid-area: 3 / 1 / 4 / 2\">\n          Left\n        </n-button>\n      </template>\n      <div class=\"large-text\">\n        啊！\n      </div>\n    </n-popover>\n    <n-popover\n      :overlap=\"overlap\"\n      arrow-point-to-center\n      placement=\"left-end\"\n      trigger=\"click\"\n      style=\"--v-target-height: 40px\"\n    >\n      <template #trigger>\n        <n-button size=\"small\" style=\"grid-area: 4 / 1 / 5 / 2\">\n          Left End\n        </n-button>\n      </template>\n      <div class=\"large-text\">\n        啊！\n      </div>\n    </n-popover>\n    <n-popover\n      :overlap=\"overlap\"\n      arrow-point-to-center\n      placement=\"right-start\"\n      trigger=\"click\"\n      style=\"--v-target-height: 40px\"\n    >\n      <template #trigger>\n        <n-button size=\"small\" style=\"grid-area: 2 / 3 / 3 / 4\">\n          Right Start\n        </n-button>\n      </template>\n      <div class=\"large-text\">\n        啊！\n      </div>\n    </n-popover>\n    <n-popover\n      :overlap=\"overlap\"\n      arrow-point-to-center\n      placement=\"right\"\n      trigger=\"click\"\n    >\n      <template #trigger>\n        <n-button size=\"small\" style=\"grid-area: 3 / 3 / 4 / 4\">\n          Right\n        </n-button>\n      </template>\n      <div class=\"large-text\">\n        啊！\n      </div>\n    </n-popover>\n    <n-popover\n      :overlap=\"overlap\"\n      arrow-point-to-center\n      placement=\"right-end\"\n      trigger=\"click\"\n      style=\"--v-target-height: 40px\"\n    >\n      <template #trigger>\n        <n-button size=\"small\" style=\"grid-area: 4 / 3 / 5 / 4\">\n          Right End\n        </n-button>\n      </template>\n      <div class=\"large-text\">\n        啊！\n      </div>\n    </n-popover>\n    <n-popover\n      :overlap=\"overlap\"\n      arrow-point-to-center\n      placement=\"bottom-start\"\n      trigger=\"click\"\n    >\n      <template #trigger>\n        <n-button size=\"small\" style=\"grid-area: 5 / 1 / 6 / 2\">\n          Bottom Start\n        </n-button>\n      </template>\n      <div class=\"large-text\">\n        啊！\n      </div>\n    </n-popover>\n    <n-popover\n      :overlap=\"overlap\"\n      arrow-point-to-center\n      placement=\"bottom\"\n      trigger=\"click\"\n    >\n      <template #trigger>\n        <n-button size=\"small\" style=\"grid-area: 5 / 2 / 6 / 3\">\n          Bottom\n        </n-button>\n      </template>\n      <div class=\"large-text\">\n        啊！\n      </div>\n    </n-popover>\n    <n-popover\n      :overlap=\"overlap\"\n      arrow-point-to-center\n      placement=\"bottom-end\"\n      trigger=\"click\"\n    >\n      <template #trigger>\n        <n-button size=\"small\" style=\"grid-area: 5 / 3 / 6 / 4\">\n          Bottom End\n        </n-button>\n      </template>\n      <div class=\"large-text\">\n        啊！\n      </div>\n    </n-popover>\n  </div>\n</template>\n\n<style>\n.popover-grid {\n  display: grid;\n  grid-template-columns: auto auto auto auto auto;\n  grid-gap: 12px;\n  justify-content: center;\n  align-items: center;\n}\n\n.large-text {\n  font-size: 48px;\n}\n\n.center-arrow-debug .n-button {\n  height: 40px;\n}\n</style>\n"
  },
  {
    "path": "src/popover/demos/zhCN/delay.demo.vue",
    "content": "<markdown>\n# 延迟\n</markdown>\n\n<template>\n  <n-popover trigger=\"hover\" :delay=\"500\" :duration=\"500\">\n    <template #trigger>\n      <n-button>延迟 500ms, 持续 500ms</n-button>\n    </template>\n    <span>\n      Lately did you ever feel the pain In the morning rain as it soaks it to\n      the bone\n    </span>\n  </n-popover>\n</template>\n"
  },
  {
    "path": "src/popover/demos/zhCN/event.demo.vue",
    "content": "<markdown>\n# 事件\n</markdown>\n\n<script lang=\"ts\">\nimport { useMessage } from 'naive-ui'\nimport { defineComponent, ref } from 'vue'\n\nexport default defineComponent({\n  setup() {\n    const message = useMessage()\n    return {\n      showPopover: ref(false),\n      handleUpdateShow(show: boolean) {\n        message.success(show ? 'show' : 'hide')\n      }\n    }\n  }\n})\n</script>\n\n<template>\n  <n-space>\n    <n-popover\n      placement=\"bottom\"\n      trigger=\"hover\"\n      @update:show=\"handleUpdateShow\"\n    >\n      <template #trigger>\n        <n-button>悬浮</n-button>\n      </template>\n      <span>我希望她们都是加州女孩</span>\n    </n-popover>\n    <n-popover\n      placement=\"bottom\"\n      trigger=\"click\"\n      @update:show=\"handleUpdateShow\"\n    >\n      <template #trigger>\n        <n-button>点击</n-button>\n      </template>\n      <span>我希望她们都是加州女孩</span>\n    </n-popover>\n    <n-popover\n      :show=\"showPopover\"\n      placement=\"bottom\"\n      trigger=\"manual\"\n      @update:show=\"handleUpdateShow\"\n    >\n      <template #trigger>\n        <n-button @click=\"showPopover = !showPopover\">\n          点击\n        </n-button>\n      </template>\n      <span>我希望她们都是加州女孩</span>\n    </n-popover>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/popover/demos/zhCN/flip.demo.vue",
    "content": "<markdown>\n# 弹出信息的位置调整\n\n使用 `flip` 决定是否调整，使用 `shift` 决定是否偏移\n</markdown>\n\n<template>\n  <n-popover trigger=\"click\" placement=\"bottom\" shift>\n    <template #trigger>\n      <n-button> 我要调整 </n-button>\n    </template>\n    <span>\n      默认是在已有位置内调整，如若已有位置不满足还是被遮挡了，可以设置`shift`属性，会在同纬度进行适当偏移的。注意：如果弹出信息足够大，怎么偏移都是会被遮挡哦！注意：如果弹出信息足够大，怎么偏移都是会被遮挡哦！注意：如果弹出信息足够大，怎么偏移都是会被遮挡哦！\n    </span>\n  </n-popover>\n</template>\n"
  },
  {
    "path": "src/popover/demos/zhCN/hoist-debug.demo.vue",
    "content": "<markdown>\n# Hoist Debug\n</markdown>\n\n<script lang=\"ts\" setup>\nconst options = [\n  {\n    label: '123',\n    value: '123'\n  }\n]\n</script>\n\n<template>\n  Style is the only prop of button and it's static, so the props of button vNode\n  is hoisted. Every button shares the same vNode props. // Remove key on debug\n  <n-popselect v-for=\"i in 3\" :key=\"i\" :options=\"options\">\n    <button style=\"color: red\">\n      {{ i }}\n    </button>\n  </n-popselect>\n</template>\n"
  },
  {
    "path": "src/popover/demos/zhCN/index.demo-entry.md",
    "content": "# 弹出信息 Popover\n\nPopover 在内容周围弹出一些隐藏的信息。Popover 里面没什么内置样式，在里面填什么主要靠你了。\n\n如果你只想展示一些基本的文本内容，使用 [Tooltip](tooltip)。\n\n## 演示\n\n```demo\nbasic.vue\ntrigger.vue\ndelay.vue\nno-arrow.vue\nevent.vue\nplacement.vue\nraw-content.vue\nstyle.vue\ntrigger-width.vue\nmanual-position.vue\nslots.vue\nwidth-debug.vue\nhoist-debug.vue\nnested-debug.vue\nnested2-debug.vue\nnested3-debug.vue\nzindex-debug.vue\ncenter-arrow-debug.vue\nrtl-debug.vue\n```\n\n## API\n\n### Popover Props\n\n| 名称 | 类型 | 默认值 | 说明 | 版本 |\n| --- | --- | --- | --- | --- |\n| animated | `boolean` | `true` | 弹出弹窗时使用动画 |  |\n| arrow-class | `string` | `undefined` | popover 的箭头类名 | 2.36.0 |\n| arrow-style | `Object` | `undefined` | popover 的箭头样式 |  |\n| arrow-wrapper-class | `string` | `undefined` | popover 的容器类名 | 2.36.0 |\n| arrow-wrapper-style | `Object` | `undefined` | popover 的容器样式 | 2.36.0 |\n| arrow-point-to-center | `boolean` | `false` | 箭头是否指向触发元素中心 | 2.26.0 |\n| content-class | `string` | `undefined` | popover 内容的类名 | 2.36.0 |\n| content-style | `string \\| Object` | `undefined` | popover 内容的样式 | 2.28.3 |\n| delay | `number` | `100` | 悬浮触发弹出信息的延迟 |  |\n| disabled | `boolean` | `false` | 是否不能激活弹出信息 |  |\n| display-directive | `'if' \\| 'show'` | `'if'` | 条件渲染使用的指令，`if` 会让内容被使用 `v-if` 渲染，`show` 会让内容被使用 `v-show` 渲染 |  |\n| duration | `number` | `100` | 悬浮关闭弹出信息的延迟 |  |\n| flip | `boolean` | `true` | 是否在当前放置方式不能提供足够空间的时候调整弹出信息的位置 |  |\n| footer-class | `string` | `undefined` | popover footer 的类名 | 2.36.0 |\n| footer-style | `string \\| Object` | `undefined` | popover footer 的样式 | 2.31.0 |\n| header-class | `string` | `undefined` | popover header 的类名 | 2.36.0 |\n| header-style | `string \\| Object` | `undefined` | popover header 的样式 | 2.28.3 |\n| keep-alive-on-hover | `boolean` | `true` | 是否在 trigger 为 hover 的时候，悬浮在 popover 时保持 popover 显示 | 2.25.0 |\n| overlap | `boolean` | `false` | 覆盖触发元素 |  |\n| placement | `'top-start' \\| 'top' \\| 'top-end' \\| 'right-start' \\| 'right' \\| 'right-end' \\| 'bottom-start' \\| 'bottom' \\| 'bottom-end' \\| 'left-start' \\| 'left' \\| 'left-end' \\| ` | `'top'` | popover 的弹出位置 |  |\n| raw | `boolean` | `false` | 是否不添加默认样式 |  |\n| scrollable | `boolean` | `false` | popover 内容是否可滚动 | 2.28.3 |\n| show-arrow | `boolean` | `true` | 是否显示箭头 |  |\n| show | `boolean` | `undefined` | 是否展示 popover |  |\n| to | `string \\| HTMLElement \\| false` | `'body'` | 弹出内容的目标容器位置，`false` 会待在原地 |  |\n| trigger | `'hover' \\| 'click' \\| 'focus' \\| 'manual'` | `'hover'` | popover 的触发方式 |  |\n| width | `number \\| 'trigger'` | `undefined` | `'trigger'` 表示 popover 的宽度会和它的触发元素一致 |  |\n| x | `number` | `undefined` | 手动控制位置时弹出内容的 CSS `left` 的像素值（x，y 都设置才能生效） |  |\n| y | `number` | `undefined` | 手动控制位置时弹出内容的 CSS `top` 的像素值（x，y 都设置才能生效） |  |\n| z-index | `number` | `undefined` | Popover 的 z-index |  |\n| on-clickoutside | `(e: MouseEvent) => void` | `undefined` | clickoutside 时触发的回调函数 |  |\n| on-update:show | `(value: boolean) => void` | `undefined` | 显示状态改变的回调函数 |  |\n\n### Popover Slots\n\n| 名称    | 参数 | 说明                     | 版本   |\n| ------- | ---- | ------------------------ | ------ |\n| trigger | `()` | 触发弹出信息的组件或元素 |        |\n| footer  | `()` | 弹出的 footer 内容       | 2.31.0 |\n| header  | `()` | 弹出的 header 内容       |        |\n| default | `()` | 弹出的内容               |        |\n\n### Popover Methods\n\n| 名称         | 参数              | 说明                             |\n| ------------ | ----------------- | -------------------------------- |\n| setShow      | `(show: boolean)` | 非受控模式下控制是否显示 popover |\n| syncPosition | `()`              | 同步 popover 位置                |\n"
  },
  {
    "path": "src/popover/demos/zhCN/manual-position.demo.vue",
    "content": "<markdown>\n# 手动定位\n\n注意：手动定位时，`trigger` 属性必须为 `'manual'`\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst x = ref(0)\nconst y = ref(0)\nconst showPopover = ref(false)\n\nfunction handleClick(e: MouseEvent) {\n  if (showPopover.value) {\n    showPopover.value = false\n  }\n  else {\n    showPopover.value = true\n    x.value = e.clientX\n    y.value = e.clientY\n  }\n}\n</script>\n\n<template>\n  <div\n    style=\"width: 200px; height: 200px; background-color: rgba(0, 128, 0, 0.5)\"\n    @click=\"handleClick\"\n  />\n  <n-popover :show=\"showPopover\" :x=\"x\" :y=\"y\" trigger=\"manual\">\n    厉害！\n  </n-popover>\n</template>\n"
  },
  {
    "path": "src/popover/demos/zhCN/nested-debug.demo.vue",
    "content": "<markdown>\n# Nested Debug\n</markdown>\n\n<script lang=\"ts\" setup>\nconst dataList = [\n  'Lorem',\n  'Lorem',\n  'Lorem ipsum, dolor sit amet consectetur adipisicing elit. Vero eveniet exercitationem quasi. Sequi quia natus quam ipsa sit autem eveniet harum tempore, eius placeat temporibus nobis veritatis vero totam possimus.',\n  'jflakjdflksjflkajdlkfjaslkfjklasjdflkasjflkjsadlkf'\n]\n</script>\n\n<template>\n  <n-popover trigger=\"click\" placement=\"bottom-end\">\n    <template #trigger>\n      <div>\n        <n-tag>hover</n-tag>\n      </div>\n    </template>\n    <n-list bordered>\n      <n-list-item v-for=\"(item, index) in dataList\" :key=\"index\">\n        <n-ellipsis style=\"max-width: 300px\">\n          {{ item }}\n        </n-ellipsis>\n      </n-list-item>\n    </n-list>\n  </n-popover>\n</template>\n"
  },
  {
    "path": "src/popover/demos/zhCN/nested2-debug.demo.vue",
    "content": "<markdown>\n# Nested Debug\n</markdown>\n\n<template>\n  <n-tooltip placement=\"bottom\">\n    <template #trigger>\n      <n-popover trigger=\"click\">\n        <template #trigger>\n          <n-button>Test</n-button>\n        </template>\n        Popover\n      </n-popover>\n    </template>\n    Tooltip\n  </n-tooltip>\n  <n-tooltip trigger=\"hover\">\n    <template #trigger>\n      <n-popconfirm>\n        <template #trigger>\n          <n-button>tooltip内嵌popconfirm</n-button>\n        </template>\n        一切都将一去杳然，任何人都无法将其捕获。\n      </n-popconfirm>\n    </template>\n    如果它长得像鸭子，走起来像鸭子，叫起来也像鸭子，那它一定是个鸭子。\n  </n-tooltip>\n</template>\n"
  },
  {
    "path": "src/popover/demos/zhCN/nested3-debug.demo.vue",
    "content": "<markdown>\n# Nested Debug 3\n</markdown>\n\n<template>\n  <n-tooltip placement=\"bottom\" trigger=\"click\">\n    <template #trigger>\n      <n-button>VShow</n-button>\n    </template>\n    <n-popover trigger=\"click\">\n      <template #trigger>\n        Test\n      </template>\n      Popover\n    </n-popover>\n  </n-tooltip>\n  <n-tooltip placement=\"bottom\" trigger=\"click\">\n    <template #trigger>\n      <n-button>VIf</n-button>\n    </template>\n    <n-popover trigger=\"click\">\n      <template #trigger>\n        Test\n      </template>\n      Popover\n    </n-popover>\n  </n-tooltip>\n</template>\n"
  },
  {
    "path": "src/popover/demos/zhCN/no-arrow.demo.vue",
    "content": "<markdown>\n# 不要箭头\n</markdown>\n\n<template>\n  <n-popover trigger=\"hover\" :show-arrow=\"false\">\n    <template #trigger>\n      <n-button>悬浮</n-button>\n    </template>\n    <span>没有箭头就是矩形了</span>\n  </n-popover>\n</template>\n"
  },
  {
    "path": "src/popover/demos/zhCN/placement.demo.vue",
    "content": "<markdown>\n# 位置\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst overlap = ref(false)\n</script>\n\n<template>\n  <n-switch v-model:value=\"overlap\" /> 覆盖触发元素\n  <n-divider />\n  <div class=\"popover-grid\">\n    <n-popover :overlap=\"overlap\" placement=\"top-start\" trigger=\"click\">\n      <template #trigger>\n        <n-button size=\"small\" style=\"grid-area: 1 / 1 / 2 / 2\">\n          Top Start\n        </n-button>\n      </template>\n      <div class=\"large-text\">\n        啊！\n      </div>\n    </n-popover>\n    <n-popover :overlap=\"overlap\" placement=\"top\" trigger=\"click\">\n      <template #trigger>\n        <n-button size=\"small\" style=\"grid-area: 1 / 2 / 2 / 3\">\n          Top\n        </n-button>\n      </template>\n      <div class=\"large-text\">\n        啊！\n      </div>\n    </n-popover>\n    <n-popover :overlap=\"overlap\" placement=\"top-end\" trigger=\"click\">\n      <template #trigger>\n        <n-button size=\"small\" style=\"grid-area: 1 / 3 / 2 / 4\">\n          Top End\n        </n-button>\n      </template>\n      <div class=\"large-text\">\n        啊！\n      </div>\n    </n-popover>\n    <n-popover :overlap=\"overlap\" placement=\"left-start\" trigger=\"click\">\n      <template #trigger>\n        <n-button size=\"small\" style=\"grid-area: 2 / 1 / 3 / 2\">\n          Left Start\n        </n-button>\n      </template>\n      <div class=\"large-text\">\n        啊！\n      </div>\n    </n-popover>\n    <n-popover :overlap=\"overlap\" placement=\"left\" trigger=\"click\">\n      <template #trigger>\n        <n-button size=\"small\" style=\"grid-area: 3 / 1 / 4 / 2\">\n          Left\n        </n-button>\n      </template>\n      <div class=\"large-text\">\n        啊！\n      </div>\n    </n-popover>\n    <n-popover :overlap=\"overlap\" placement=\"left-end\" trigger=\"click\">\n      <template #trigger>\n        <n-button size=\"small\" style=\"grid-area: 4 / 1 / 5 / 2\">\n          Left End\n        </n-button>\n      </template>\n      <div class=\"large-text\">\n        啊！\n      </div>\n    </n-popover>\n    <n-popover :overlap=\"overlap\" placement=\"right-start\" trigger=\"click\">\n      <template #trigger>\n        <n-button size=\"small\" style=\"grid-area: 2 / 3 / 3 / 4\">\n          Right Start\n        </n-button>\n      </template>\n      <div class=\"large-text\">\n        啊！\n      </div>\n    </n-popover>\n    <n-popover :overlap=\"overlap\" placement=\"right\" trigger=\"click\">\n      <template #trigger>\n        <n-button size=\"small\" style=\"grid-area: 3 / 3 / 4 / 4\">\n          Right\n        </n-button>\n      </template>\n      <div class=\"large-text\">\n        啊！\n      </div>\n    </n-popover>\n    <n-popover :overlap=\"overlap\" placement=\"right-end\" trigger=\"click\">\n      <template #trigger>\n        <n-button size=\"small\" style=\"grid-area: 4 / 3 / 5 / 4\">\n          Right End\n        </n-button>\n      </template>\n      <div class=\"large-text\">\n        啊！\n      </div>\n    </n-popover>\n    <n-popover :overlap=\"overlap\" placement=\"bottom-start\" trigger=\"click\">\n      <template #trigger>\n        <n-button size=\"small\" style=\"grid-area: 5 / 1 / 6 / 2\">\n          Bottom Start\n        </n-button>\n      </template>\n      <div class=\"large-text\">\n        啊！\n      </div>\n    </n-popover>\n    <n-popover :overlap=\"overlap\" placement=\"bottom\" trigger=\"click\">\n      <template #trigger>\n        <n-button size=\"small\" style=\"grid-area: 5 / 2 / 6 / 3\">\n          Bottom\n        </n-button>\n      </template>\n      <div class=\"large-text\">\n        啊！\n      </div>\n    </n-popover>\n    <n-popover :overlap=\"overlap\" placement=\"bottom-end\" trigger=\"click\">\n      <template #trigger>\n        <n-button size=\"small\" style=\"grid-area: 5 / 3 / 6 / 4\">\n          Bottom End\n        </n-button>\n      </template>\n      <div class=\"large-text\">\n        啊！\n      </div>\n    </n-popover>\n  </div>\n</template>\n\n<style>\n.popover-grid {\n  display: grid;\n  grid-template-columns: auto auto auto auto auto;\n  grid-gap: 12px;\n  justify-content: center;\n  align-items: center;\n}\n\n.large-text {\n  font-size: 48px;\n}\n</style>\n"
  },
  {
    "path": "src/popover/demos/zhCN/raw-content.demo.vue",
    "content": "<markdown>\n# 不用基础样式\n</markdown>\n\n<template>\n  <n-popover trigger=\"hover\" raw :show-arrow=\"false\">\n    <template #trigger>\n      <n-button style=\"margin: 0\">\n        悬浮\n      </n-button>\n    </template>\n    <div\n      style=\"\n        width: 100px;\n        height: 100px;\n        background-color: red;\n        transform-origin: inherit;\n      \"\n    >\n      Who kicks a hole in the sky so the heaven cry over me.\n    </div>\n  </n-popover>\n</template>\n"
  },
  {
    "path": "src/popover/demos/zhCN/rtl-debug.demo.vue",
    "content": "<markdown>\n# Rtl Debug\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { unstablePopoverRtl } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst rtlEnabled = ref(false)\nconst rtlStyles = [unstablePopoverRtl]\n</script>\n\n<template>\n  <n-space vertical>\n    <n-space><n-switch v-model:value=\"rtlEnabled\" />Rtl</n-space>\n    <n-config-provider :rtl=\"rtlEnabled ? rtlStyles : undefined\">\n      <n-popover trigger=\"click\">\n        <template #trigger>\n          <n-button>悬浮</n-button>\n        </template>\n        <template #header>\n          <span>header</span>\n        </template>\n        <template #footer>\n          <span>footer</span>\n        </template>\n        <span>或许不想知道你的花园长得咋样</span>\n      </n-popover>\n    </n-config-provider>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/popover/demos/zhCN/slots.demo.vue",
    "content": "<markdown>\n# 插槽\n\n使用 `header` 与 `footer` 插槽来自定义标题或底部内容。\n</markdown>\n\n<template>\n  <n-popover trigger=\"click\">\n    <template #trigger>\n      <n-button>提供这个接口是因为分割线不好写</n-button>\n    </template>\n    <template #header>\n      <n-text strong depth=\"1\">\n        下面就是分割线\n      </n-text>\n    </template>\n    内容\n    <template #footer>\n      上面就是分割线\n    </template>\n  </n-popover>\n</template>\n"
  },
  {
    "path": "src/popover/demos/zhCN/style.demo.vue",
    "content": "<markdown>\n# 样式\n\n可以用 `style` 来设置 popover 的样式；你可以使用 `scrollable` 让 popover 内容可以滚动；在 `:scrollable=\"true\"` 的情况下，你可以用 `content-style` 设定 popover 内容的样式。\n</markdown>\n\n<template>\n  <n-space>\n    <n-popover style=\"width: 500px\" trigger=\"click\">\n      <template #trigger>\n        <n-button>宽度 500px</n-button>\n      </template>\n      长得像根条一样\n    </n-popover>\n    <n-popover style=\"max-width: 100px\" trigger=\"click\">\n      <template #trigger>\n        <n-button> 最大宽度 100px </n-button>\n      </template>\n      内容长度不确定的时候，设置最大宽度可能更好看\n    </n-popover>\n    <n-popover style=\"max-height: 240px\" trigger=\"click\" scrollable>\n      <template #trigger>\n        <n-button>最大高度 240px</n-button>\n      </template>\n      演员失业 电缆失窃<br>\n      共享富裕 共享恐惧<br>\n      东方睡衣 涌上街头<br>\n      街头嘈杂 公共聋哑<br>\n      紧急换电缆 循环追捕令<br>\n      紧急换电缆 循环追捕令<br>\n      我有迷魂 额头滚烫<br>\n      我有迷魂 人间明暗<br>\n      鸟兽暗语 危险消息<br>\n      自然友谊 自然躲避<br>\n      西郊有密林 助君出重围<br>\n      西郊有密林 助君出重围\n    </n-popover>\n    <n-popover\n      style=\"max-height: 240px\"\n      content-style=\"padding: 0;\"\n      trigger=\"click\"\n      scrollable\n    >\n      <template #trigger>\n        <n-button>可滚动 & 无 padding</n-button>\n      </template>\n      演员失业 电缆失窃<br>\n      共享富裕 共享恐惧<br>\n      东方睡衣 涌上街头<br>\n      街头嘈杂 公共聋哑<br>\n      紧急换电缆 循环追捕令<br>\n      紧急换电缆 循环追捕令<br>\n      我有迷魂 额头滚烫<br>\n      我有迷魂 人间明暗<br>\n      鸟兽暗语 危险消息<br>\n      自然友谊 自然躲避<br>\n      西郊有密林 助君出重围<br>\n      西郊有密林 助君出重围\n    </n-popover>\n    <n-popover\n      trigger=\"click\"\n      content-style=\"padding: 0;\"\n      header-style=\"padding: 0;\"\n    >\n      <template #trigger>\n        <n-button>有 header & 无 padding</n-button>\n      </template>\n      <template #header>\n        <n-text strong depth=\"1\">\n          下面就是分割线\n        </n-text>\n      </template>\n      上面就是分割线\n    </n-popover>\n    <n-popover style=\"padding: 0\" trigger=\"click\">\n      <template #trigger>\n        <n-button>没有 padding</n-button>\n      </template>\n      你可以随便放点什么\n    </n-popover>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/popover/demos/zhCN/trigger-width.demo.vue",
    "content": "<markdown>\n# 使用触发元素的宽度\n\n设定 `width=\"trigger\"` 使 popover 的宽度等于触发元素。\n</markdown>\n\n<template>\n  <n-popover width=\"trigger\">\n    <template #trigger>\n      <n-button>I would like to leave this city</n-button>\n    </template>\n    This old town don't smell too pretty and I can feel the warning signs\n    running around my mind\n  </n-popover>\n</template>\n"
  },
  {
    "path": "src/popover/demos/zhCN/trigger.demo.vue",
    "content": "<markdown>\n# 触发方式\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst showPopover = ref(false)\n</script>\n\n<template>\n  <n-space>\n    <n-popover trigger=\"hover\">\n      <template #trigger>\n        <n-button>悬浮</n-button>\n      </template>\n      <span>I wish they all could be California girls</span>\n    </n-popover>\n    <n-popover trigger=\"hover\" :keep-alive-on-hover=\"false\">\n      <template #trigger>\n        <n-button>悬浮（忽略主体）</n-button>\n      </template>\n      <span>I wish they all could be California girls</span>\n    </n-popover>\n    <n-popover trigger=\"click\">\n      <template #trigger>\n        <n-button>点击</n-button>\n      </template>\n      <span>I wish they all could be California girls</span>\n    </n-popover>\n    <n-popover trigger=\"focus\">\n      <template #trigger>\n        <n-button>聚焦</n-button>\n      </template>\n      <span>I wish they all could be California girls</span>\n    </n-popover>\n    <n-popover trigger=\"manual\" :show=\"showPopover\">\n      <template #trigger>\n        <n-button @click=\"showPopover = !showPopover\">\n          手动\n        </n-button>\n      </template>\n      <span>I wish they all could be California girls</span>\n    </n-popover>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/popover/demos/zhCN/width-debug.demo.vue",
    "content": "<markdown>\n# Width debug\n</markdown>\n\n<template>\n  <n-popover style=\"max-width: 200px\">\n    <template #trigger>\n      <n-button>1</n-button>\n    </template>\n    111111 111111 111111 111111 111111 111111 111111 111111 111111 111111 111111\n    111111 111111 111111 111111\n  </n-popover>\n  <n-popover :style=\"{ maxWidth: '200px' }\">\n    <template #trigger>\n      <n-button>2</n-button>\n    </template>\n    111111 111111 111111 111111 111111 111111 111111 111111 111111 111111 111111\n    111111 111111 111111 111111\n  </n-popover>\n  <n-popover style=\"max-width: 200px\">\n    <template #trigger>\n      3\n    </template>\n    111111 111111 111111 111111 111111 111111 111111 111111 111111 111111 111111\n    111111 111111 111111 111111\n  </n-popover>\n  <n-popover :style=\"{ width: '100px' }\">\n    <template #trigger>\n      <n-button>5</n-button>\n    </template>\n    111111 111111 111111 111111 111111 111111 111111 111111 111111 111111 111111\n    111111 111111 111111 111111\n  </n-popover>\n  <n-popover style=\"width: 100px\">\n    <template #trigger>\n      6\n    </template>\n    111111 111111 111111 111111 111111 111111 111111 111111 111111 111111 111111\n    111111 111111 111111 111111\n  </n-popover>\n  <n-tooltip style=\"max-width: 200px\">\n    <template #trigger>\n      <n-button>1</n-button>\n    </template>\n    111111 111111 111111 111111 111111 111111 111111 111111 111111 111111 111111\n    111111 111111 111111 111111\n  </n-tooltip>\n  <n-tooltip :style=\"{ maxWidth: '200px' }\">\n    <template #trigger>\n      <n-button>2</n-button>\n    </template>\n    111111 111111 111111 111111 111111 111111 111111 111111 111111 111111 111111\n    111111 111111 111111 111111\n  </n-tooltip>\n  <n-tooltip style=\"max-width: 200px\">\n    <template #trigger>\n      3\n    </template>\n    111111 111111 111111 111111 111111 111111 111111 111111 111111 111111 111111\n    111111 111111 111111 111111\n  </n-tooltip>\n  <n-tooltip :style=\"{ width: '100px' }\">\n    <template #trigger>\n      <n-button>5</n-button>\n    </template>\n    111111 111111 111111 111111 111111 111111 111111 111111 111111 111111 111111\n    111111 111111 111111 111111\n  </n-tooltip>\n  <n-tooltip style=\"width: 100px\">\n    <template #trigger>\n      6\n    </template>\n    111111 111111 111111 111111 111111 111111 111111 111111 111111 111111 111111\n    111111 111111 111111 111111\n  </n-tooltip>\n</template>\n"
  },
  {
    "path": "src/popover/demos/zhCN/zindex-debug.demo.vue",
    "content": "<markdown>\n# Zindex debug\n</markdown>\n\n<script lang=\"ts\" setup></script>\n\n<template>\n  <n-space>\n    <n-popover trigger=\"click\" :z-index=\"3000\">\n      <template #trigger>\n        <n-button>Hover</n-button>\n      </template>\n      <span>I wish they all could be California girls</span>\n      <n-popover trigger=\"click\" :z-index=\"3000\">\n        <template #trigger>\n          <n-button>Click</n-button>\n        </template>\n        <span>I wish they all could be California girls</span>\n      </n-popover>\n    </n-popover>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/popover/index.ts",
    "content": "export type { PopoverInst, PopoverTrigger } from './src/interface'\nexport { default as NPopover, popoverProps } from './src/Popover'\nexport type { PopoverProps, PopoverSlots } from './src/Popover'\nexport type { FollowerPlacement as PopoverPlacement } from 'vueuc'\n"
  },
  {
    "path": "src/popover/src/Popover.tsx",
    "content": "import type {\n  ComputedRef,\n  CSSProperties,\n  PropType,\n  Ref,\n  SlotsType,\n  VNode\n} from 'vue'\nimport type { BinderInst, FollowerPlacement } from 'vueuc'\nimport type { ThemeProps } from '../../_mixins'\nimport type {\n  ExtractInternalPropTypes,\n  ExtractPublicPropTypes,\n  MaybeArray\n} from '../../_utils'\nimport type { PopoverTheme } from '../styles'\nimport type {\n  InternalPopoverInst,\n  InternalRenderBody,\n  PopoverTrigger\n} from './interface'\nimport { zindexable } from 'vdirs'\nimport { useCompitable, useIsMounted, useMemo, useMergedState } from 'vooks'\nimport {\n  cloneVNode,\n  computed,\n  defineComponent,\n  h,\n  provide,\n  ref,\n  Text,\n  toRef,\n  watchEffect,\n  withDirectives\n} from 'vue'\nimport { VBinder, VTarget } from 'vueuc'\nimport { useTheme } from '../../_mixins'\nimport {\n  call,\n  getFirstSlotVNode,\n  keep,\n  useAdjustedTo,\n  warnOnce\n} from '../../_utils'\nimport NPopoverBody, { popoverBodyProps } from './PopoverBody'\n\nconst bodyPropKeys = Object.keys(popoverBodyProps) as Array<\n  keyof typeof popoverBodyProps\n>\n\nconst triggerEventMap = {\n  focus: ['onFocus', 'onBlur'],\n  click: ['onClick'],\n  hover: ['onMouseenter', 'onMouseleave'],\n  manual: [],\n  nested: ['onFocus', 'onBlur', 'onMouseenter', 'onMouseleave', 'onClick']\n} as const\n\nexport interface TriggerEventHandlers {\n  onClick: (e: MouseEvent) => void\n  onMouseenter: (e: MouseEvent) => void\n  onMouseleave: (e: MouseEvent) => void\n  onFocus: (e: FocusEvent) => void\n  onBlur: (e: FocusEvent) => void\n}\n\nfunction appendEvents(\n  vNode: VNode,\n  trigger: PopoverTrigger | 'nested',\n  events: TriggerEventHandlers\n): void {\n  triggerEventMap[trigger].forEach((eventName) => {\n    if (!vNode.props) {\n      vNode.props = {}\n    }\n    else {\n      vNode.props = Object.assign({}, vNode.props)\n    }\n    const originalHandler = vNode.props[eventName]\n    const handler = events[eventName]\n    if (!originalHandler) {\n      vNode.props[eventName] = handler\n    }\n    else {\n      vNode.props[eventName] = (...args: unknown[]) => {\n        originalHandler(...args)\n        ;(handler as any)(...args)\n      }\n    }\n  })\n}\n\ninterface BodyInstance {\n  syncPosition: () => void\n  [key: string]: unknown\n}\n\nexport interface PopoverInjection {\n  handleMouseLeave: (e: MouseEvent) => void\n  handleMouseEnter: (e: MouseEvent) => void\n  handleMouseMoveOutside: (e: MouseEvent) => void\n  handleClickOutside: (e: MouseEvent) => void\n  handleKeydown: (e: KeyboardEvent) => void\n  getTriggerElement: () => HTMLElement\n  setBodyInstance: (value: BodyInstance | null) => void\n  zIndexRef: Ref<number | undefined>\n  internalRenderBodyRef: Ref<InternalRenderBody | undefined>\n  positionManuallyRef: ComputedRef<boolean>\n  isMountedRef: Ref<boolean>\n  extraClassRef: Ref<string[]>\n}\n\nexport const popoverBaseProps = {\n  show: {\n    type: Boolean as PropType<boolean | undefined>,\n    default: undefined\n  },\n  defaultShow: Boolean,\n  showArrow: {\n    type: Boolean,\n    default: true\n  },\n  trigger: {\n    type: String as PropType<PopoverTrigger>,\n    default: 'hover'\n  },\n  delay: {\n    type: Number,\n    default: 100\n  },\n  duration: {\n    type: Number,\n    default: 100\n  },\n  raw: Boolean,\n  placement: {\n    type: String as PropType<FollowerPlacement>,\n    default: 'top'\n  },\n  x: Number,\n  y: Number,\n  arrowPointToCenter: Boolean,\n  disabled: Boolean,\n  getDisabled: Function as PropType<() => boolean>,\n  displayDirective: {\n    type: String as PropType<'if' | 'show'>,\n    default: 'if'\n  },\n  arrowClass: String,\n  arrowStyle: [String, Object] as PropType<string | CSSProperties>,\n  arrowWrapperClass: String,\n  arrowWrapperStyle: [String, Object] as PropType<string | CSSProperties>,\n  flip: {\n    type: Boolean,\n    default: true\n  },\n  animated: {\n    type: Boolean,\n    default: true\n  },\n  width: {\n    type: [Number, String] as PropType<number | 'trigger'>,\n    default: undefined\n  },\n  overlap: Boolean,\n  keepAliveOnHover: {\n    type: Boolean,\n    default: true\n  },\n  zIndex: Number,\n  to: useAdjustedTo.propTo,\n  scrollable: Boolean,\n  contentClass: String,\n  contentStyle: [Object, String] as PropType<CSSProperties | string>,\n  headerClass: String,\n  headerStyle: [Object, String] as PropType<CSSProperties | string>,\n  footerClass: String,\n  footerStyle: [Object, String] as PropType<CSSProperties | string>,\n  // events\n  onClickoutside: Function as PropType<(e: MouseEvent) => void>,\n  'onUpdate:show': [Function, Array] as PropType<\n    MaybeArray<(value: boolean) => void>\n  >,\n  onUpdateShow: [Function, Array] as PropType<\n    MaybeArray<(value: boolean) => void>\n  >,\n  // internal\n  internalDeactivateImmediately: Boolean,\n  internalSyncTargetWithParent: Boolean,\n  internalInheritedEventHandlers: {\n    type: Array as PropType<TriggerEventHandlers[]>,\n    default: () => []\n  },\n  internalTrapFocus: Boolean,\n  internalExtraClass: {\n    type: Array as PropType<string[]>,\n    default: () => []\n  },\n  // deprecated\n  onShow: [Function, Array] as PropType<\n    MaybeArray<(value: boolean) => void> | undefined\n  >,\n  onHide: [Function, Array] as PropType<\n    MaybeArray<(value: boolean) => void> | undefined\n  >,\n  arrow: {\n    type: Boolean as PropType<boolean | undefined>,\n    default: undefined\n  },\n  minWidth: Number,\n  maxWidth: Number\n}\n\nexport const popoverProps = {\n  ...(useTheme.props as ThemeProps<PopoverTheme>),\n  ...popoverBaseProps,\n  internalOnAfterLeave: Function as PropType<() => void>,\n  internalRenderBody: Function as PropType<InternalRenderBody>\n}\n\nexport type PopoverProps = ExtractPublicPropTypes<typeof popoverBaseProps>\nexport type PopoverInternalProps = ExtractInternalPropTypes<typeof popoverProps>\n\nexport interface PopoverSlots {\n  trigger?: () => VNode[]\n  footer?: () => VNode[]\n  header?: () => VNode[]\n  default?: () => VNode[]\n}\n\nexport default defineComponent({\n  name: 'Popover',\n  inheritAttrs: false,\n  props: popoverProps,\n  slots: Object as SlotsType<PopoverSlots>,\n  __popover__: true,\n  setup(props) {\n    if (__DEV__) {\n      watchEffect(() => {\n        if (props.maxWidth !== undefined) {\n          warnOnce(\n            'popover',\n            '`max-width` is deprecated, please use `style` instead.'\n          )\n        }\n        if (props.minWidth !== undefined) {\n          warnOnce(\n            'popover',\n            '`min-width` is deprecated, please use `style` instead.'\n          )\n        }\n        if (props.arrow !== undefined) {\n          warnOnce(\n            'popover',\n            '`arrow` is deprecated, please use `showArrow` instead.'\n          )\n        }\n        if (props.onHide !== undefined) {\n          warnOnce(\n            'popover',\n            '`on-hide` is deprecated, please use `on-update:show` instead.'\n          )\n        }\n        if (props.onShow !== undefined) {\n          warnOnce(\n            'popover',\n            '`on-show` is deprecated, please use `on-update:show` instead.'\n          )\n        }\n      })\n    }\n    const isMountedRef = useIsMounted()\n    const binderInstRef = ref<BinderInst | null>(null)\n    // setup show\n    const controlledShowRef = computed(() => props.show)\n    const uncontrolledShowRef = ref(props.defaultShow)\n    const mergedShowWithoutDisabledRef = useMergedState(\n      controlledShowRef,\n      uncontrolledShowRef\n    )\n    const mergedShowConsideringDisabledPropRef = useMemo(() => {\n      if (props.disabled)\n        return false\n      return mergedShowWithoutDisabledRef.value\n    })\n    const getMergedDisabled = (): boolean => {\n      if (props.disabled)\n        return true\n      const { getDisabled } = props\n      if (getDisabled?.())\n        return true\n      return false\n    }\n    const getMergedShow = (): boolean => {\n      if (getMergedDisabled())\n        return false\n      return mergedShowWithoutDisabledRef.value\n    }\n    // setup show-arrow\n    const compatibleShowArrowRef = useCompitable(props, ['arrow', 'showArrow'])\n    const mergedShowArrowRef = computed(() => {\n      if (props.overlap)\n        return false\n      return compatibleShowArrowRef.value\n    })\n    // bodyInstance\n    let bodyInstance: BodyInstance | null = null\n    const showTimerIdRef = ref<number | null>(null)\n    const hideTimerIdRef = ref<number | null>(null)\n    const positionManuallyRef = useMemo(() => {\n      return props.x !== undefined && props.y !== undefined\n    })\n    // methods\n    function doUpdateShow(value: boolean): void {\n      const {\n        'onUpdate:show': _onUpdateShow,\n        onUpdateShow,\n        onShow,\n        onHide\n      } = props\n      uncontrolledShowRef.value = value\n      if (_onUpdateShow) {\n        call(_onUpdateShow, value)\n      }\n      if (onUpdateShow) {\n        call(onUpdateShow, value)\n      }\n      if (value && onShow) {\n        call(onShow, true)\n      }\n      if (value && onHide) {\n        call(onHide, false)\n      }\n    }\n    function syncPosition(): void {\n      if (bodyInstance) {\n        bodyInstance.syncPosition()\n      }\n    }\n    function clearShowTimer(): void {\n      const { value: showTimerId } = showTimerIdRef\n      if (showTimerId) {\n        window.clearTimeout(showTimerId)\n        showTimerIdRef.value = null\n      }\n    }\n    function clearHideTimer(): void {\n      const { value: hideTimerId } = hideTimerIdRef\n      if (hideTimerId) {\n        window.clearTimeout(hideTimerId)\n        hideTimerIdRef.value = null\n      }\n    }\n    function handleFocus(): void {\n      const mergedDisabled = getMergedDisabled()\n      if (props.trigger === 'focus' && !mergedDisabled) {\n        if (getMergedShow())\n          return\n        doUpdateShow(true)\n      }\n    }\n    function handleBlur(): void {\n      const mergedDisabled = getMergedDisabled()\n      if (props.trigger === 'focus' && !mergedDisabled) {\n        if (!getMergedShow())\n          return\n        doUpdateShow(false)\n      }\n    }\n    function handleMouseEnter(): void {\n      const mergedDisabled = getMergedDisabled()\n      if (props.trigger === 'hover' && !mergedDisabled) {\n        clearHideTimer()\n        if (showTimerIdRef.value !== null)\n          return\n        if (getMergedShow())\n          return\n        const delayCallback = (): void => {\n          doUpdateShow(true)\n          showTimerIdRef.value = null\n        }\n        const { delay } = props\n        if (delay === 0) {\n          delayCallback()\n        }\n        else {\n          showTimerIdRef.value = window.setTimeout(delayCallback, delay)\n        }\n      }\n    }\n    function handleMouseLeave(): void {\n      const mergedDisabled = getMergedDisabled()\n      if (props.trigger === 'hover' && !mergedDisabled) {\n        clearShowTimer()\n        if (hideTimerIdRef.value !== null)\n          return\n        if (!getMergedShow())\n          return\n        const delayedCallback = (): void => {\n          doUpdateShow(false)\n          hideTimerIdRef.value = null\n        }\n        const { duration } = props\n        if (duration === 0) {\n          delayedCallback()\n        }\n        else {\n          hideTimerIdRef.value = window.setTimeout(delayedCallback, duration)\n        }\n      }\n    }\n    // will be called in popover-content\n    function handleMouseMoveOutside(): void {\n      handleMouseLeave()\n    }\n    // will be called in popover-content\n    function handleClickOutside(e: MouseEvent): void {\n      if (!getMergedShow())\n        return\n      if (props.trigger === 'click') {\n        clearShowTimer()\n        clearHideTimer()\n        doUpdateShow(false)\n      }\n      props.onClickoutside?.(e)\n    }\n    function handleClick(): void {\n      if (props.trigger === 'click' && !getMergedDisabled()) {\n        clearShowTimer()\n        clearHideTimer()\n        const nextShow = !getMergedShow()\n        doUpdateShow(nextShow)\n      }\n    }\n    function handleKeydown(e: KeyboardEvent): void {\n      if (!props.internalTrapFocus)\n        return\n      if (e.key === 'Escape') {\n        clearShowTimer()\n        clearHideTimer()\n        doUpdateShow(false)\n      }\n    }\n    function setShow(value: boolean): void {\n      uncontrolledShowRef.value = value\n    }\n    function getTriggerElement(): HTMLElement {\n      return binderInstRef.value?.targetRef as HTMLElement\n    }\n    function setBodyInstance(value: BodyInstance | null): void {\n      bodyInstance = value\n    }\n    provide<PopoverInjection>('NPopover', {\n      getTriggerElement,\n      handleKeydown,\n      handleMouseEnter,\n      handleMouseLeave,\n      handleClickOutside,\n      handleMouseMoveOutside,\n      setBodyInstance,\n      positionManuallyRef,\n      isMountedRef,\n      zIndexRef: toRef(props, 'zIndex'),\n      extraClassRef: toRef(props, 'internalExtraClass'),\n      internalRenderBodyRef: toRef(props, 'internalRenderBody')\n    })\n    watchEffect(() => {\n      if (mergedShowWithoutDisabledRef.value && getMergedDisabled()) {\n        doUpdateShow(false)\n      }\n    })\n    const returned = {\n      binderInstRef,\n      positionManually: positionManuallyRef,\n      mergedShowConsideringDisabledProp: mergedShowConsideringDisabledPropRef,\n      // if to show popover body\n      uncontrolledShow: uncontrolledShowRef,\n      mergedShowArrow: mergedShowArrowRef,\n      getMergedShow,\n      setShow,\n      handleClick,\n      handleMouseEnter,\n      handleMouseLeave,\n      handleFocus,\n      handleBlur,\n      syncPosition\n    }\n    return returned satisfies InternalPopoverInst\n  },\n  render() {\n    const { positionManually, $slots: slots } = this\n    let triggerVNode: VNode | null\n    let popoverInside = false\n    if (!positionManually) {\n      triggerVNode = getFirstSlotVNode(slots, 'trigger')\n      if (triggerVNode) {\n        triggerVNode = cloneVNode(triggerVNode)\n        triggerVNode\n          = triggerVNode.type === Text ? h('span', [triggerVNode]) : triggerVNode\n        const handlers = {\n          onClick: this.handleClick,\n          onMouseenter: this.handleMouseEnter,\n          onMouseleave: this.handleMouseLeave,\n          onFocus: this.handleFocus,\n          onBlur: this.handleBlur\n        }\n        if ((triggerVNode.type as any)?.__popover__) {\n          popoverInside = true\n          // We assume that there's no DOM event handlers on popover element\n          if (!triggerVNode.props) {\n            triggerVNode.props = {\n              internalSyncTargetWithParent: true,\n              internalInheritedEventHandlers: []\n            }\n          }\n          triggerVNode.props.internalSyncTargetWithParent = true\n          if (!triggerVNode.props.internalInheritedEventHandlers) {\n            triggerVNode.props.internalInheritedEventHandlers = [handlers]\n          }\n          else {\n            triggerVNode.props.internalInheritedEventHandlers = [\n              handlers,\n              ...triggerVNode.props.internalInheritedEventHandlers\n            ]\n          }\n        }\n        else {\n          const { internalInheritedEventHandlers } = this\n          const ascendantAndCurrentHandlers: TriggerEventHandlers[] = [\n            handlers,\n            ...internalInheritedEventHandlers\n          ]\n          const mergedHandlers: TriggerEventHandlers = {\n            onBlur: (e: FocusEvent) => {\n              ascendantAndCurrentHandlers.forEach((_handlers) => {\n                _handlers.onBlur(e)\n              })\n            },\n            onFocus: (e: FocusEvent) => {\n              ascendantAndCurrentHandlers.forEach((_handlers) => {\n                _handlers.onFocus(e)\n              })\n            },\n            onClick: (e: MouseEvent) => {\n              ascendantAndCurrentHandlers.forEach((_handlers) => {\n                _handlers.onClick(e)\n              })\n            },\n            onMouseenter: (e: MouseEvent) => {\n              ascendantAndCurrentHandlers.forEach((_handlers) => {\n                _handlers.onMouseenter(e)\n              })\n            },\n            onMouseleave: (e: MouseEvent) => {\n              ascendantAndCurrentHandlers.forEach((_handlers) => {\n                _handlers.onMouseleave(e)\n              })\n            }\n          }\n          appendEvents(\n            triggerVNode,\n            internalInheritedEventHandlers\n              ? 'nested'\n              : positionManually\n                ? 'manual'\n                : this.trigger,\n            mergedHandlers\n          )\n        }\n      }\n    }\n    return (\n      <VBinder\n        ref=\"binderInstRef\"\n        syncTarget={!popoverInside}\n        syncTargetWithParent={this.internalSyncTargetWithParent}\n      >\n        {{\n          default: () => {\n            // We need to subscribe it. Sometimes rerender won't ge triggered.\n            // `mergedShowConsideringDisabledProp` is not the final disabled status.\n            // In ellpisis it's dynamic.\n            void this.mergedShowConsideringDisabledProp\n            const mergedShow = this.getMergedShow()\n            return [\n              this.internalTrapFocus && mergedShow\n                ? withDirectives(\n                    <div\n                      style={{\n                        position: 'fixed',\n                        top: 0,\n                        right: 0,\n                        bottom: 0,\n                        left: 0\n                      }}\n                    />,\n                    [\n                      [\n                        zindexable,\n                        {\n                          enabled: mergedShow,\n                          zIndex: this.zIndex\n                        }\n                      ]\n                    ]\n                  )\n                : null,\n              positionManually\n                ? null\n                : h(VTarget, null, {\n                    default: () => triggerVNode\n                  }),\n              h(\n                NPopoverBody,\n                keep(this.$props, bodyPropKeys, {\n                  ...this.$attrs,\n                  showArrow: this.mergedShowArrow,\n                  show: mergedShow\n                }),\n                {\n                  default: () => this.$slots.default?.(),\n                  header: () => this.$slots.header?.(),\n                  footer: () => this.$slots.footer?.()\n                }\n              )\n            ]\n          }\n        }}\n      </VBinder>\n    )\n  }\n})\n"
  },
  {
    "path": "src/popover/src/PopoverBody.tsx",
    "content": "import type {\n  CSSProperties,\n  DirectiveArguments,\n  PropType,\n  VNode,\n  VNodeChild\n} from 'vue'\nimport type { FollowerInst, FollowerPlacement } from 'vueuc'\nimport type { ThemeProps } from '../../_mixins'\nimport type { PopoverTheme } from '../styles'\nimport type { PopoverTrigger } from './interface'\nimport type { PopoverInjection } from './Popover'\nimport { getPreciseEventTarget } from 'seemly'\nimport { clickoutside, mousemoveoutside } from 'vdirs'\nimport {\n  computed,\n  defineComponent,\n  Fragment,\n  h,\n  inject,\n  mergeProps,\n  onBeforeUnmount,\n  provide,\n  ref,\n  toRef,\n  Transition,\n  vShow,\n  watch,\n  watchEffect,\n  withDirectives\n} from 'vue'\nimport { VFocusTrap, VFollower } from 'vueuc'\nimport { NxScrollbar } from '../../_internal/scrollbar'\nimport { useConfig, useRtl, useTheme, useThemeClass } from '../../_mixins'\nimport {\n  formatLength,\n  isJsdom,\n  isSlotEmpty,\n  resolveWrappedSlot,\n  useAdjustedTo\n} from '../../_utils'\nimport { drawerBodyInjectionKey } from '../../drawer/src/interface'\nimport { modalBodyInjectionKey } from '../../modal/src/interface'\nimport { popoverLight } from '../styles'\nimport { popoverBodyInjectionKey } from './interface'\nimport style from './styles/index.cssr'\n\nexport const popoverBodyProps = {\n  ...(useTheme.props as ThemeProps<PopoverTheme>),\n  to: useAdjustedTo.propTo,\n  show: Boolean,\n  trigger: String as PropType<PopoverTrigger>,\n  showArrow: Boolean,\n  delay: Number,\n  duration: Number,\n  raw: Boolean,\n  arrowPointToCenter: Boolean,\n  arrowClass: String,\n  arrowStyle: [String, Object] as PropType<string | CSSProperties>,\n  arrowWrapperClass: String,\n  arrowWrapperStyle: [String, Object] as PropType<string | CSSProperties>,\n  displayDirective: String as PropType<'if' | 'show'>,\n  x: Number,\n  y: Number,\n  flip: Boolean,\n  overlap: Boolean,\n  placement: String as PropType<FollowerPlacement>,\n  width: [Number, String] as PropType<number | 'trigger'>,\n  keepAliveOnHover: Boolean,\n  scrollable: Boolean,\n  contentClass: String,\n  contentStyle: [Object, String] as PropType<CSSProperties | string>,\n  headerClass: String,\n  headerStyle: [Object, String] as PropType<CSSProperties | string>,\n  footerClass: String,\n  footerStyle: [Object, String] as PropType<CSSProperties | string>,\n  // private\n  internalDeactivateImmediately: Boolean,\n  animated: Boolean,\n  onClickoutside: Function as PropType<(e: MouseEvent) => void>,\n  internalTrapFocus: Boolean,\n  internalOnAfterLeave: Function as PropType<() => void>,\n  // deprecated\n  minWidth: Number,\n  maxWidth: Number\n}\n\ninterface RenderArrowProps {\n  arrowClass: string | undefined\n  arrowStyle: string | CSSProperties | undefined\n  arrowWrapperClass: string | undefined\n  arrowWrapperStyle: string | CSSProperties | undefined\n  clsPrefix: string\n}\n\nexport function renderArrow({\n  arrowClass,\n  arrowStyle,\n  arrowWrapperClass,\n  arrowWrapperStyle,\n  clsPrefix\n}: RenderArrowProps): VNode | null {\n  return (\n    <div\n      key=\"__popover-arrow__\"\n      style={arrowWrapperStyle}\n      class={[`${clsPrefix}-popover-arrow-wrapper`, arrowWrapperClass]}\n    >\n      <div\n        class={[`${clsPrefix}-popover-arrow`, arrowClass]}\n        style={arrowStyle}\n      />\n    </div>\n  )\n}\n\nexport default defineComponent({\n  name: 'PopoverBody',\n  inheritAttrs: false,\n  props: popoverBodyProps,\n  setup(props, { slots, attrs }) {\n    const {\n      namespaceRef,\n      mergedClsPrefixRef,\n      inlineThemeDisabled,\n      mergedRtlRef\n    } = useConfig(props)\n    const themeRef = useTheme(\n      'Popover',\n      '-popover',\n      style,\n      popoverLight,\n      props,\n      mergedClsPrefixRef\n    )\n\n    const rtlEnabledRef = useRtl('Popover', mergedRtlRef, mergedClsPrefixRef)\n\n    const followerRef = ref<FollowerInst | null>(null)\n    const NPopover = inject<PopoverInjection>('NPopover') as PopoverInjection\n    const bodyRef = ref<HTMLElement | null>(null)\n    const followerEnabledRef = ref(props.show)\n    const displayedRef = ref(false)\n    watchEffect(() => {\n      const { show } = props\n      if (show && !isJsdom() && !props.internalDeactivateImmediately) {\n        displayedRef.value = true\n      }\n    })\n    const directivesRef = computed<DirectiveArguments>(() => {\n      const { trigger, onClickoutside } = props\n      const directives: DirectiveArguments = []\n      const {\n        positionManuallyRef: { value: positionManually }\n      } = NPopover\n      if (!positionManually) {\n        if (trigger === 'click' && !onClickoutside) {\n          directives.push([\n            clickoutside,\n            handleClickOutside,\n            undefined as unknown as string,\n            { capture: true }\n          ])\n        }\n        if (trigger === 'hover') {\n          directives.push([mousemoveoutside, handleMouseMoveOutside])\n        }\n      }\n      if (onClickoutside) {\n        directives.push([\n          clickoutside,\n          handleClickOutside,\n          undefined as unknown as string,\n          { capture: true }\n        ])\n      }\n      if (\n        props.displayDirective === 'show'\n        || (props.animated && displayedRef.value)\n      ) {\n        directives.push([vShow, props.show])\n      }\n      return directives\n    })\n\n    const cssVarsRef = computed(() => {\n      const {\n        common: { cubicBezierEaseInOut, cubicBezierEaseIn, cubicBezierEaseOut },\n        self: {\n          space,\n          spaceArrow,\n          padding,\n          fontSize,\n          textColor,\n          dividerColor,\n          color,\n          boxShadow,\n          borderRadius,\n          arrowHeight,\n          arrowOffset,\n          arrowOffsetVertical\n        }\n      } = themeRef.value\n\n      return {\n        '--n-box-shadow': boxShadow,\n        '--n-bezier': cubicBezierEaseInOut,\n        '--n-bezier-ease-in': cubicBezierEaseIn,\n        '--n-bezier-ease-out': cubicBezierEaseOut,\n        '--n-font-size': fontSize,\n        '--n-text-color': textColor,\n        '--n-color': color,\n        '--n-divider-color': dividerColor,\n        '--n-border-radius': borderRadius,\n        '--n-arrow-height': arrowHeight,\n        '--n-arrow-offset': arrowOffset,\n        '--n-arrow-offset-vertical': arrowOffsetVertical,\n        '--n-padding': padding,\n        '--n-space': space,\n        '--n-space-arrow': spaceArrow\n      }\n    })\n    const styleRef = computed(() => {\n      const width\n        = props.width === 'trigger' ? undefined : formatLength(props.width)\n      const style: CSSProperties[] = []\n      if (width) {\n        style.push({ width })\n      }\n      const { maxWidth, minWidth } = props\n      if (maxWidth) {\n        style.push({ maxWidth: formatLength(maxWidth) })\n      }\n      if (minWidth) {\n        style.push({ maxWidth: formatLength(minWidth) })\n      }\n      if (!inlineThemeDisabled) {\n        style.push(cssVarsRef.value)\n      }\n      return style\n    })\n    const themeClassHandle = inlineThemeDisabled\n      ? useThemeClass('popover', undefined, cssVarsRef, props)\n      : undefined\n    NPopover.setBodyInstance({\n      syncPosition\n    })\n    onBeforeUnmount(() => {\n      NPopover.setBodyInstance(null)\n    })\n    watch(toRef(props, 'show'), (value) => {\n      // If no animation, no transition component will be applied to the\n      // component. So we need to trigger follower manaully.\n      if (props.animated)\n        return\n      if (value) {\n        followerEnabledRef.value = true\n      }\n      else {\n        followerEnabledRef.value = false\n      }\n    })\n    function syncPosition(): void {\n      followerRef.value?.syncPosition()\n    }\n    function handleMouseEnter(e: MouseEvent): void {\n      if (props.trigger === 'hover' && props.keepAliveOnHover && props.show) {\n        NPopover.handleMouseEnter(e)\n      }\n    }\n    function handleMouseLeave(e: MouseEvent): void {\n      if (props.trigger === 'hover' && props.keepAliveOnHover) {\n        NPopover.handleMouseLeave(e)\n      }\n    }\n    function handleMouseMoveOutside(e: MouseEvent): void {\n      if (\n        props.trigger === 'hover'\n        && !getTriggerElement().contains(getPreciseEventTarget(e) as Node | null)\n      ) {\n        NPopover.handleMouseMoveOutside(e)\n      }\n    }\n    function handleClickOutside(e: MouseEvent): void {\n      if (\n        (props.trigger === 'click'\n          && !getTriggerElement().contains(\n            getPreciseEventTarget(e) as Node | null\n          ))\n          || props.onClickoutside\n      ) {\n        NPopover.handleClickOutside(e)\n      }\n    }\n    function getTriggerElement(): HTMLElement {\n      return NPopover.getTriggerElement()\n    }\n    provide(popoverBodyInjectionKey, bodyRef)\n    provide(drawerBodyInjectionKey, null)\n    provide(modalBodyInjectionKey, null)\n\n    function renderContentNode(): VNode | null {\n      themeClassHandle?.onRender()\n      const shouldRenderDom\n        = props.displayDirective === 'show'\n          || props.show\n          || (props.animated && displayedRef.value)\n      if (!shouldRenderDom) {\n        return null\n      }\n      let contentNode: VNode\n      const renderBody = NPopover.internalRenderBodyRef.value\n      const { value: mergedClsPrefix } = mergedClsPrefixRef\n      if (!renderBody) {\n        const { value: extraClass } = NPopover.extraClassRef\n        const { internalTrapFocus } = props\n        const hasHeaderOrFooter\n          = !isSlotEmpty(slots.header) || !isSlotEmpty(slots.footer)\n        const renderContentInnerNode = (): VNodeChild[] => {\n          const body = hasHeaderOrFooter ? (\n            <>\n              {resolveWrappedSlot(slots.header, (children) => {\n                return children ? (\n                  <div\n                    class={[\n                      `${mergedClsPrefix}-popover__header`,\n                      props.headerClass\n                    ]}\n                    style={props.headerStyle}\n                  >\n                    {children}\n                  </div>\n                ) : null\n              })}\n              {resolveWrappedSlot(slots.default, (children) => {\n                return children ? (\n                  <div\n                    class={[\n                      `${mergedClsPrefix}-popover__content`,\n                      props.contentClass\n                    ]}\n                    style={props.contentStyle}\n                  >\n                    {slots}\n                  </div>\n                ) : null\n              })}\n              {resolveWrappedSlot(slots.footer, (children) => {\n                return children ? (\n                  <div\n                    class={[\n                      `${mergedClsPrefix}-popover__footer`,\n                      props.footerClass\n                    ]}\n                    style={props.footerStyle}\n                  >\n                    {children}\n                  </div>\n                ) : null\n              })}\n            </>\n          ) : props.scrollable ? (\n            slots.default?.()\n          ) : (\n            <div\n              class={[\n                `${mergedClsPrefix}-popover__content`,\n                props.contentClass\n              ]}\n              style={props.contentStyle}\n            >\n              {slots}\n            </div>\n          )\n          const maybeScrollableBody = props.scrollable ? (\n            <NxScrollbar\n              themeOverrides={themeRef.value.peerOverrides.Scrollbar}\n              theme={themeRef.value.peers.Scrollbar}\n              contentClass={\n                hasHeaderOrFooter\n                  ? undefined\n                  : `${mergedClsPrefix}-popover__content ${\n                    props.contentClass ?? ''\n                  }`\n              }\n              contentStyle={hasHeaderOrFooter ? undefined : props.contentStyle}\n            >\n              {{\n                default: () => body\n              }}\n            </NxScrollbar>\n          ) : (\n            body\n          )\n          const arrow = props.showArrow\n            ? renderArrow({\n                arrowClass: props.arrowClass,\n                arrowStyle: props.arrowStyle,\n                arrowWrapperClass: props.arrowWrapperClass,\n                arrowWrapperStyle: props.arrowWrapperStyle,\n                clsPrefix: mergedClsPrefix\n              })\n            : null\n          return [maybeScrollableBody, arrow]\n        }\n        contentNode = h(\n          'div',\n          mergeProps(\n            {\n              class: [\n                `${mergedClsPrefix}-popover`,\n                `${mergedClsPrefix}-popover-shared`,\n                rtlEnabledRef?.value && `${mergedClsPrefix}-popover--rtl`,\n                themeClassHandle?.themeClass.value,\n                extraClass.map(v => `${mergedClsPrefix}-${v}`),\n                {\n                  [`${mergedClsPrefix}-popover--scrollable`]: props.scrollable,\n                  [`${mergedClsPrefix}-popover--show-header-or-footer`]:\n                    hasHeaderOrFooter,\n                  [`${mergedClsPrefix}-popover--raw`]: props.raw,\n                  [`${mergedClsPrefix}-popover-shared--overlap`]: props.overlap,\n                  [`${mergedClsPrefix}-popover-shared--show-arrow`]:\n                    props.showArrow,\n                  [`${mergedClsPrefix}-popover-shared--center-arrow`]:\n                    props.arrowPointToCenter\n                }\n              ],\n              ref: bodyRef,\n              style: styleRef.value,\n              onKeydown: NPopover.handleKeydown,\n              onMouseenter: handleMouseEnter,\n              onMouseleave: handleMouseLeave\n            },\n            attrs\n          ),\n          internalTrapFocus ? (\n            <VFocusTrap active={props.show} autoFocus>\n              {{ default: renderContentInnerNode }}\n            </VFocusTrap>\n          ) : (\n            renderContentInnerNode()\n          )\n        )\n      }\n      else {\n        contentNode = renderBody(\n          // The popover class and overlap class must exists, they will be used\n          // to place the body & transition animation.\n          // Shadow class exists for reuse box-shadow.\n          [\n            `${mergedClsPrefix}-popover-shared`,\n            rtlEnabledRef?.value && `${mergedClsPrefix}-popover--rtl`,\n            themeClassHandle?.themeClass.value,\n            props.overlap && `${mergedClsPrefix}-popover-shared--overlap`,\n            props.showArrow && `${mergedClsPrefix}-popover-shared--show-arrow`,\n            props.arrowPointToCenter\n            && `${mergedClsPrefix}-popover-shared--center-arrow`\n          ],\n          bodyRef,\n          styleRef.value,\n          handleMouseEnter,\n          handleMouseLeave\n        )\n      }\n      return withDirectives(contentNode, directivesRef.value)\n    }\n\n    return {\n      displayed: displayedRef,\n      namespace: namespaceRef,\n      isMounted: NPopover.isMountedRef,\n      zIndex: NPopover.zIndexRef,\n      followerRef,\n      adjustedTo: useAdjustedTo(props),\n      followerEnabled: followerEnabledRef,\n      renderContentNode\n    }\n  },\n  render() {\n    return (\n      <VFollower\n        ref=\"followerRef\"\n        zIndex={this.zIndex}\n        show={this.show}\n        enabled={this.followerEnabled}\n        to={this.adjustedTo}\n        x={this.x}\n        y={this.y}\n        flip={this.flip}\n        placement={this.placement}\n        containerClass={this.namespace}\n        overlap={this.overlap}\n        width={this.width === 'trigger' ? 'target' : undefined}\n        teleportDisabled={this.adjustedTo === useAdjustedTo.tdkey}\n      >\n        {{\n          default: () => {\n            return this.animated ? (\n              <Transition\n                name=\"popover-transition\"\n                appear={this.isMounted}\n                // Don't use watch to enable follower, since the transition may\n                // make position sync timing very subtle and buggy.\n                onEnter={() => {\n                  this.followerEnabled = true\n                }}\n                onAfterLeave={() => {\n                  this.internalOnAfterLeave?.()\n                  this.followerEnabled = false\n                  this.displayed = false\n                }}\n              >\n                {{\n                  default: this.renderContentNode\n                }}\n              </Transition>\n            ) : (\n              this.renderContentNode()\n            )\n          }\n        }}\n      </VFollower>\n    )\n  }\n})\n"
  },
  {
    "path": "src/popover/src/interface.ts",
    "content": "import type { CSSProperties, Ref, VNode } from 'vue'\nimport { createInjectionKey } from '../../_utils/vue/create-injection-key'\n\nexport type PopoverTrigger = 'click' | 'hover' | 'focus' | 'manual'\n\nexport interface PopoverInst {\n  syncPosition: () => void\n  setShow: (value: boolean) => void\n}\n\nexport type InternalPopoverInst = PopoverInst & {\n  getMergedShow: () => boolean\n}\n\nexport type PopoverBodyInjection = Ref<HTMLElement | null> | null\n\nexport const popoverBodyInjectionKey\n  = createInjectionKey<PopoverBodyInjection>('n-popover-body')\n\nexport type InternalRenderBody = (\n  className: any,\n  ref: Ref<HTMLElement | null>,\n  style: CSSProperties[],\n  onMouseenter: (e: MouseEvent) => void,\n  onMouseleave: (e: MouseEvent) => void\n) => VNode\n"
  },
  {
    "path": "src/popover/src/styles/index.cssr.ts",
    "content": "import type { CNode } from 'css-render'\nimport type { FollowerPlacement } from 'vueuc'\nimport { map } from 'lodash-es'\nimport { c, cB, cCB, cE, cM, cNotM } from '../../../_utils/cssr'\n\nconst oppositePlacement = {\n  top: 'bottom',\n  bottom: 'top',\n  left: 'right',\n  right: 'left'\n}\n\nconst arrowSize = 'var(--n-arrow-height) * 1.414'\n\n// vars:\n// --n-bezier\n// --n-bezier-ease-in\n// --n-bezier-ease-out\n// --n-font-size\n// --n-text-color\n// --n-color\n// --n-border-radius\n// --n-arrow-height\n// --n-arrow-offset\n// --n-arrow-offset-vertical\n// --n-padding\n// --n-space\n// --n-space-arrow\n// --n-divider-color\nexport default c([\n  cB('popover', `\n    transition:\n      box-shadow .3s var(--n-bezier),\n      background-color .3s var(--n-bezier),\n      color .3s var(--n-bezier);\n    position: relative;\n    font-size: var(--n-font-size);\n    color: var(--n-text-color);\n    box-shadow: var(--n-box-shadow);\n    word-break: break-word;\n  `, [\n    c('>', [\n      cB('scrollbar', `\n        height: inherit;\n        max-height: inherit;\n      `)\n    ]),\n    cNotM('raw', `\n      background-color: var(--n-color);\n      border-radius: var(--n-border-radius);\n    `, [\n      cNotM('scrollable', [\n        cNotM('show-header-or-footer', 'padding: var(--n-padding);')\n      ])\n    ]),\n    cE('header', `\n      padding: var(--n-padding);\n      border-bottom: 1px solid var(--n-divider-color);\n      transition: border-color .3s var(--n-bezier);\n    `),\n    cE('footer', `\n      padding: var(--n-padding);\n      border-top: 1px solid var(--n-divider-color);\n      transition: border-color .3s var(--n-bezier);\n    `),\n    cM('scrollable, show-header-or-footer', [\n      cE('content', `\n        padding: var(--n-padding);\n      `)\n    ])\n  ]),\n  cB('popover-shared', `\n    transform-origin: inherit;\n  `, [\n    cB('popover-arrow-wrapper', `\n      position: absolute;\n      overflow: hidden;\n      pointer-events: none;\n    `, [\n      cB('popover-arrow', `\n        transition: background-color .3s var(--n-bezier);\n        position: absolute;\n        display: block;\n        width: calc(${arrowSize});\n        height: calc(${arrowSize});\n        box-shadow: 0 0 8px 0 rgba(0, 0, 0, .12);\n        transform: rotate(45deg);\n        background-color: var(--n-color);\n        pointer-events: all;\n      `)\n    ]),\n    // body transition\n    c('&.popover-transition-enter-from, &.popover-transition-leave-to', `\n      opacity: 0;\n      transform: scale(.85);\n    `),\n    c('&.popover-transition-enter-to, &.popover-transition-leave-from', `\n      transform: scale(1);\n      opacity: 1;\n    `),\n    c('&.popover-transition-enter-active', `\n      transition:\n        box-shadow .3s var(--n-bezier),\n        background-color .3s var(--n-bezier),\n        color .3s var(--n-bezier),\n        opacity .15s var(--n-bezier-ease-out),\n        transform .15s var(--n-bezier-ease-out);\n    `),\n    c('&.popover-transition-leave-active', `\n      transition:\n        box-shadow .3s var(--n-bezier),\n        background-color .3s var(--n-bezier),\n        color .3s var(--n-bezier),\n        opacity .15s var(--n-bezier-ease-in),\n        transform .15s var(--n-bezier-ease-in);\n    `)\n  ]),\n  placementStyle('top-start', `\n    top: calc(${arrowSize} / -2);\n    left: calc(${getArrowOffset('top-start')} - var(--v-offset-left));\n  `),\n  placementStyle('top', `\n    top: calc(${arrowSize} / -2);\n    transform: translateX(calc(${arrowSize} / -2)) rotate(45deg);\n    left: 50%;\n  `),\n  placementStyle('top-end', `\n    top: calc(${arrowSize} / -2);\n    right: calc(${getArrowOffset('top-end')} + var(--v-offset-left));\n  `),\n  placementStyle('bottom-start', `\n    bottom: calc(${arrowSize} / -2);\n    left: calc(${getArrowOffset('bottom-start')} - var(--v-offset-left));\n  `),\n  placementStyle('bottom', `\n    bottom: calc(${arrowSize} / -2);\n    transform: translateX(calc(${arrowSize} / -2)) rotate(45deg);\n    left: 50%;\n  `),\n  placementStyle('bottom-end', `\n    bottom: calc(${arrowSize} / -2);\n    right: calc(${getArrowOffset('bottom-end')} + var(--v-offset-left));\n  `),\n  placementStyle('left-start', `\n    left: calc(${arrowSize} / -2);\n    top: calc(${getArrowOffset('left-start')} - var(--v-offset-top));\n  `),\n  placementStyle('left', `\n    left: calc(${arrowSize} / -2);\n    transform: translateY(calc(${arrowSize} / -2)) rotate(45deg);\n    top: 50%;\n  `),\n  placementStyle('left-end', `\n    left: calc(${arrowSize} / -2);\n    bottom: calc(${getArrowOffset('left-end')} + var(--v-offset-top));\n  `),\n  placementStyle('right-start', `\n    right: calc(${arrowSize} / -2);\n    top: calc(${getArrowOffset('right-start')} - var(--v-offset-top));\n  `),\n  placementStyle('right', `\n    right: calc(${arrowSize} / -2);\n    transform: translateY(calc(${arrowSize} / -2)) rotate(45deg);\n    top: 50%;\n  `),\n  placementStyle('right-end', `\n    right: calc(${arrowSize} / -2);\n    bottom: calc(${getArrowOffset('right-end')} + var(--v-offset-top));\n  `),\n  ...map(\n    {\n      top: ['right-start', 'left-start'],\n      right: ['top-end', 'bottom-end'],\n      bottom: ['right-end', 'left-end'],\n      left: ['top-start', 'bottom-start']\n    },\n    (placements, direction): CNode[] => {\n      const isVertical = ['right', 'left'].includes(direction)\n      const sizeType = isVertical ? 'width' : 'height'\n      return placements.map((placement) => {\n        const isReverse = placement.split('-')[1] === 'end'\n        const targetSize = `var(--v-target-${sizeType}, 0px)`\n        const centerOffset = `calc((${targetSize} - ${arrowSize}) / 2)`\n        const offset = getArrowOffset(placement as FollowerPlacement)\n        return c(`[v-placement=\"${placement}\"] >`, [\n          cB('popover-shared', [\n            cM('center-arrow', [\n              cB(\n                'popover-arrow',\n                `${direction}: calc(max(${centerOffset}, ${offset}) ${\n                  isReverse ? '+' : '-'\n                } var(--v-offset-${isVertical ? 'left' : 'top'}));`\n              )\n            ])\n          ])\n        ])\n      })\n    }\n  )\n])\n\nfunction getArrowOffset(placement: FollowerPlacement): string {\n  return ['top', 'bottom'].includes(placement.split('-')[0])\n    ? 'var(--n-arrow-offset)'\n    : 'var(--n-arrow-offset-vertical)'\n}\n\nfunction placementStyle(\n  placement: FollowerPlacement,\n  arrowStyleLiteral: string\n): CNode {\n  const position = placement.split('-')[0] as\n    | 'top'\n    | 'right'\n    | 'bottom'\n    | 'left'\n  const sizeStyle = ['top', 'bottom'].includes(position)\n    ? 'height: var(--n-space-arrow);'\n    : 'width: var(--n-space-arrow);'\n  return c(`[v-placement=\"${placement}\"] >`, [\n    cB('popover-shared', `\n      margin-${oppositePlacement[position]}: var(--n-space);\n    `, [\n      cM('show-arrow', `\n        margin-${oppositePlacement[position]}: var(--n-space-arrow);\n      `),\n      cM('overlap', `\n        margin: 0;\n      `),\n      cCB('popover-arrow-wrapper', `\n        right: 0;\n        left: 0;\n        top: 0;\n        bottom: 0;\n        ${position}: 100%;\n        ${oppositePlacement[position]}: auto;\n        ${sizeStyle}\n      `, [\n        cB('popover-arrow', arrowStyleLiteral)\n      ])\n    ])\n  ])\n}\n"
  },
  {
    "path": "src/popover/src/styles/rtl.cssr.ts",
    "content": "import { cB, cM } from '../../../_utils/cssr'\n\nexport default cB('popover', [\n  cM('rtl', `\n    direction: rtl;\n    text-align: right;\n  `)\n])\n"
  },
  {
    "path": "src/popover/styles/_common.ts",
    "content": "export default {\n  space: '6px',\n  spaceArrow: '10px',\n  arrowOffset: '10px',\n  arrowOffsetVertical: '10px',\n  arrowHeight: '6px',\n  padding: '8px 14px'\n}\n"
  },
  {
    "path": "src/popover/styles/dark.ts",
    "content": "import type { PopoverTheme } from './light'\nimport { scrollbarDark } from '../../_internal/scrollbar/styles'\nimport { commonDark } from '../../_styles/common'\nimport { self } from './light'\n\nconst popoverDark: PopoverTheme = {\n  name: 'Popover',\n  common: commonDark,\n  peers: {\n    Scrollbar: scrollbarDark\n  },\n  self\n}\n\nexport default popoverDark\n"
  },
  {
    "path": "src/popover/styles/index.ts",
    "content": "export { default as popoverDark } from './dark'\nexport { default as popoverLight } from './light'\nexport type { PopoverTheme, PopoverThemeVars } from './light'\nexport { popoverRtl } from './rtl'\n"
  },
  {
    "path": "src/popover/styles/light.ts",
    "content": "import type { ThemeCommonVars } from '../../_styles/common'\nimport { scrollbarLight } from '../../_internal/scrollbar/styles'\nimport { createTheme } from '../../_mixins'\nimport { commonLight } from '../../_styles/common'\nimport commonVariables from './_common'\n\nexport function self(vars: ThemeCommonVars) {\n  const {\n    boxShadow2,\n    popoverColor,\n    textColor2,\n    borderRadius,\n    fontSize,\n    dividerColor\n  } = vars\n  return {\n    ...commonVariables,\n    fontSize,\n    borderRadius,\n    color: popoverColor,\n    dividerColor,\n    textColor: textColor2,\n    boxShadow: boxShadow2\n  }\n}\n\nexport type PopoverThemeVars = ReturnType<typeof self>\n\nconst popoverLight = createTheme({\n  name: 'Popover',\n  common: commonLight,\n  peers: {\n    Scrollbar: scrollbarLight\n  },\n  self\n})\n\nexport type PopoverTheme = typeof popoverLight\nexport default popoverLight\n"
  },
  {
    "path": "src/popover/styles/rtl.ts",
    "content": "import type { RtlItem } from '../../config-provider/src/internal-interface'\nimport { scrollbarRtl } from '../../_internal/scrollbar/styles/rtl'\nimport rtlStyle from '../src/styles/rtl.cssr'\n\nexport const popoverRtl: RtlItem = {\n  name: 'Popover',\n  style: rtlStyle,\n  peers: [scrollbarRtl]\n}\n"
  },
  {
    "path": "src/popover/tests/Popover.spec.tsx",
    "content": "import type { PopoverInst } from '../index'\nimport { mount } from '@vue/test-utils'\nimport { createId } from 'seemly'\nimport { defineComponent, Fragment, h, nextTick } from 'vue'\nimport { NPopover } from '../index'\n\nconst popoverBodyHeader = '.n-popover__header'\nconst popoverBodyFooter = '.n-popover__footer'\n\nasync function sleep(ms: number): Promise<void> {\n  await new Promise((resolve) => {\n    setTimeout(resolve, ms)\n  })\n}\n\ndescribe('n-popover', () => {\n  it('should work with import on demand', () => {\n    mount(NPopover, {\n      slots: {\n        trigger: () => 'star kirby',\n        default: () => <div>star kirby</div>\n      }\n    })\n  })\n\n  const TriggerComponent1 = defineComponent({\n    name: 'TriggerComponent1',\n    render() {\n      return <div>GoGoGo</div>\n    }\n  })\n\n  ;(['hover', 'click'] as const).forEach((trigger) => {\n    // test trigger node\n    ;['text', 'div', 'Fragment', TriggerComponent1].forEach((type) => {\n      const classNameHash: string = `${trigger}-${typeof type === 'string' ? type : type.name}`\n      it(`trigger node ${classNameHash}`, async () => {\n        // hover trigger, click trigger\n        const triggerEvent = trigger === 'hover' ? 'mouseenter' : 'click'\n        const hideTriggerEvent = trigger === 'hover' ? 'mouseleave' : 'click'\n        // text node, element node\n        const triggerNode\n          = type === 'text' ? (\n            'star kirby'\n          ) : type === 'Fragment' ? (\n            <>\n              {h(\n                type as any,\n                { class: `star-kirby-${classNameHash}-trigger` },\n                {}\n              )}\n            </>\n          ) : (\n            h(type as any, { class: `star-kirby-${classNameHash}-trigger` }, {})\n          )\n        const wrapper = mount(NPopover, {\n          attachTo: document.body,\n          props: {\n            trigger,\n            delay: 0,\n            duration: 0\n          },\n          slots: {\n            trigger: () => triggerNode,\n            default: () => (\n              <div class={`star-kirby-${classNameHash}-content`}></div>\n            )\n          }\n        })\n        const triggerNodeWrapper\n          = type === 'text'\n            ? wrapper.find('span')\n            : wrapper.find(`.star-kirby-${classNameHash}-trigger`)\n\n        await triggerNodeWrapper.trigger(triggerEvent)\n        expect(\n          document.querySelector(`.star-kirby-${classNameHash}-content`)\n        ).not.toEqual(null)\n\n        await triggerNodeWrapper.trigger(hideTriggerEvent)\n        expect(\n          document.querySelector(`.star-kirby-${classNameHash}-content`)\n        ).toEqual(null)\n\n        const inst = wrapper.vm as PopoverInst\n\n        inst.setShow(true)\n        await nextTick()\n        expect(\n          document.querySelector(`.star-kirby-${classNameHash}-content`)\n        ).not.toEqual(null)\n\n        inst.setShow(false)\n        await nextTick()\n        expect(\n          document.querySelector(`.star-kirby-${classNameHash}-content`)\n        ).toEqual(null)\n\n        wrapper.unmount()\n      })\n    })\n  })\n\n  it('delay & duration', async () => {\n    const id = createId()\n    const triggerClass = `trigger-${id}`\n    const contentClass = `content-${id}`\n    const wrapper = mount(NPopover, {\n      attachTo: document.body,\n      props: {\n        trigger: 'hover',\n        delay: 100,\n        duration: 100\n      },\n      slots: {\n        trigger: () => <div class={triggerClass}></div>,\n        default: () => <div class={contentClass}></div>\n      }\n    })\n    await wrapper.find(`.${triggerClass}`).trigger('mouseenter')\n    expect(document.querySelector(`.${contentClass}`)).toEqual(null)\n    await sleep(150)\n    expect(document.querySelector(`.${contentClass}`)).not.toEqual(null)\n    await wrapper.find(`.${triggerClass}`).trigger('mouseleave')\n    expect(document.querySelector(`.${contentClass}`)).not.toEqual(null)\n    await sleep(150)\n    expect(document.querySelector(`.${contentClass}`)).toEqual(null)\n    wrapper.unmount()\n  })\n\n  it('header & footer slots', () => {\n    const wrapper = mount(NPopover, {\n      attachTo: document.body,\n      props: {\n        show: true\n      },\n      slots: {\n        trigger: () => <div>click</div>,\n        header: () => <div>I am title</div>,\n        default: () => <div>star kirby</div>,\n        footer: () => <div>I am footer</div>\n      }\n    })\n    expect(document.querySelector(popoverBodyHeader)?.textContent).toEqual(\n      'I am title'\n    )\n    expect(document.querySelector(popoverBodyFooter)?.textContent).toEqual(\n      'I am footer'\n    )\n    wrapper.unmount()\n  })\n})\n"
  },
  {
    "path": "src/popover/tests/server.spec.tsx",
    "content": "import { setup } from '@css-render/vue3-ssr'\nimport { renderToString } from '@vue/server-renderer'\n/**\n * @vitest-environment node\n */\nimport { createSSRApp, h } from 'vue'\nimport { NPopover } from '../..'\n\ndescribe('server side rendering', () => {\n  it('works', async () => {\n    const app = createSSRApp(() => (\n      <NPopover>\n        {{\n          trigger: () => 'kirby'\n        }}\n      </NPopover>\n    ))\n    setup(app)\n    try {\n      await renderToString(app)\n    }\n    catch (e) {\n      console.error(e)\n      expect(e).not.toBeTruthy()\n    }\n  })\n})\n"
  },
  {
    "path": "src/popselect/demos/enUS/basic.demo.vue",
    "content": "<markdown>\n# Basic\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst value = ref('Drive My Car')\nconst options = [\n  {\n    label: 'Drive My Car',\n    value: 'Drive My Car'\n  },\n  {\n    label: 'Norwegian Wood',\n    value: 'Norwegian Wood'\n  },\n  {\n    label: 'You Won\\'t See',\n    value: 'You Won\\'t See',\n    disabled: true\n  },\n  {\n    label: 'Nowhere Man',\n    value: 'Nowhere Man'\n  },\n  {\n    label: 'Think For Yourself',\n    value: 'Think For Yourself'\n  },\n  {\n    label: 'The Word',\n    value: 'The Word'\n  },\n  {\n    label: 'Michelle',\n    value: 'Michelle',\n    disabled: true\n  },\n  {\n    label: 'What goes on',\n    value: 'What goes on'\n  },\n  {\n    label: 'Girl',\n    value: 'Girl'\n  },\n  {\n    label: 'I\\'m looking through you',\n    value: 'I\\'m looking through you'\n  },\n  {\n    label: 'In My Life',\n    value: 'In My Life'\n  },\n  {\n    label: 'Wait',\n    value: 'Wait'\n  }\n]\n</script>\n\n<template>\n  <n-popselect v-model:value=\"value\" :options=\"options\">\n    <n-button>{{ value || 'Popselect' }}</n-button>\n  </n-popselect>\n</template>\n"
  },
  {
    "path": "src/popselect/demos/enUS/cancelable.demo.vue",
    "content": "<markdown>\n# Cancelable\n\nMake single value popselect cancelable.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst value = ref('song1')\nconst options = [\n  {\n    label: 'Everybody\\'s Got Something to Hide Except Me and My Monkey',\n    value: 'song0',\n    disabled: true\n  },\n  {\n    label: 'Drive My Car',\n    value: 'song1'\n  },\n  {\n    label: 'Norwegian Wood',\n    value: 'song2'\n  },\n  {\n    label: 'You Won\\'t See',\n    value: 'song3',\n    disabled: true\n  },\n  {\n    label: 'Nowhere Man',\n    value: 'song4'\n  },\n  {\n    label: 'Think For Yourself',\n    value: 'song5'\n  },\n  {\n    label: 'The Word',\n    value: 'song6'\n  },\n  {\n    label: 'Michelle',\n    value: 'song7',\n    disabled: true\n  },\n  {\n    label: 'What goes on',\n    value: 'song8'\n  },\n  {\n    label: 'Girl',\n    value: 'song9'\n  },\n  {\n    label: 'I\\'m looking through you',\n    value: 'song10'\n  },\n  {\n    label: 'In My Life',\n    value: 'song11'\n  },\n  {\n    label: 'Wait',\n    value: 'song12'\n  }\n]\n</script>\n\n<template>\n  <n-popselect v-model:value=\"value\" cancelable :options=\"options\">\n    <n-button>{{ value || 'Popselect' }}</n-button>\n  </n-popselect>\n</template>\n"
  },
  {
    "path": "src/popselect/demos/enUS/index.demo-entry.md",
    "content": "# Popselect\n\nIf you want select some options but don't want a picker, you can use popselect instead.\n\n## Demos\n\n```demo\nbasic.vue\nsize.vue\nscrollable.vue\nmultiple.vue\nslot.vue\n```\n\n## API\n\n### Popselect Props\n\n| Name | Type | Default | Description | Version |\n| --- | --- | --- | --- | --- |\n| multiple | `boolean` | `false` | Whether to select multiple values. |  |\n| node-props | `(option: SelectOption \\| SelectGroupOption) => object` | `undefined` | Option's DOM attrs generator. | 2.30.4 |\n| options | `Array<SelectOption \\| SelectGroupOption>` | `[]` | For details of configuration options, see [Select](select#SelectOption-Properties) |  |\n| render-label | `(option: SelectOption \\| SelectGroupOption) => VNodeChild` | `undefined` | Render function of all the options. |  |\n| scrollable | `boolean` | `false` | Whether the select menu is scrollable. |  |\n| scrollbar-props | `ScrollbarProps` | `undefined` | See [Scrollbar props](scrollbar#Scrollbar-Props) | 2.44.0 |\n| size | `'small' \\| 'medium' \\| 'large'` | `'medium'` | Size of the Popselect. |  |\n| value | `string \\| number \\| Array<string \\| number> \\| null` | `null` | Value in controlled mode. |  |\n| virtual-scroll | `boolean` | `false` | Whether to enable virtual scrolling. | 2.30.4 |\n| on-update:value | `(value: string \\| number \\| Array<string \\| number> \\| null, option: SelectBaseOption \\| null \\| Array<SelectBaseOption>) => void` | `undefined` | Callback of value updating. |  |\n\nFor SelectOption & SelectGroupOption, see [Select](select#SelectOption-Properties)\n\nFor other props, see [Popover](popover#Popover-Props)\n\n### Popselect Slots\n\n| Name   | Parameters | Description                            | Version |\n| ------ | ---------- | -------------------------------------- | ------- |\n| header | `()`       | Header menu slot.                      | 2.36.0  |\n| action | `()`       | Options menu slot.                     | 2.22.0  |\n| empty  | `()`       | Empty state slot for the options menu. | 2.22.0  |\n"
  },
  {
    "path": "src/popselect/demos/enUS/multiple.demo.vue",
    "content": "<markdown>\n# Multiple\n\nSelect multiple value in popselect.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst values = ref([])\nconst options = [\n  {\n    label: 'Drive My Car',\n    value: 'Drive My Car'\n  },\n  {\n    label: 'Norwegian Wood',\n    value: 'Norwegian Wood'\n  },\n  {\n    label: 'You Won\\'t See',\n    value: 'You Won\\'t See'\n  },\n  {\n    label: 'Nowhere Man',\n    value: 'Nowhere Man'\n  },\n  {\n    label: 'Think For Yourself',\n    value: 'Think For Yourself'\n  },\n  {\n    label: 'The Word',\n    value: 'The Word'\n  }\n]\n</script>\n\n<template>\n  <n-popselect v-model:value=\"values\" multiple :options=\"options\">\n    <n-button>{{ values.join(', ') || 'Popselect' }}</n-button>\n  </n-popselect>\n</template>\n"
  },
  {
    "path": "src/popselect/demos/enUS/scrollable.demo.vue",
    "content": "<markdown>\n# Scrollable\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst value = ref('Drive My Car')\nconst options = [\n  {\n    label: 'Drive My Car',\n    value: 'Drive My Car'\n  },\n  {\n    label: 'Norwegian Wood',\n    value: 'Norwegian Wood'\n  },\n  {\n    label: 'You Won\\'t See',\n    value: 'You Won\\'t See',\n    disabled: true\n  },\n  {\n    label: 'Nowhere Man',\n    value: 'Nowhere Man'\n  },\n  {\n    label: 'Think For Yourself',\n    value: 'Think For Yourself'\n  },\n  {\n    label: 'The Word',\n    value: 'The Word'\n  },\n  {\n    label: 'Michelle',\n    value: 'Michelle',\n    disabled: true\n  },\n  {\n    label: 'What goes on',\n    value: 'What goes on'\n  },\n  {\n    label: 'Girl',\n    value: 'Girl'\n  },\n  {\n    label: 'I\\'m looking through you',\n    value: 'I\\'m looking through you'\n  },\n  {\n    label: 'In My Life',\n    value: 'In My Life'\n  },\n  {\n    label: 'Wait',\n    value: 'Wait'\n  }\n]\n</script>\n\n<template>\n  <n-popselect\n    v-model:value=\"value\"\n    :options=\"options\"\n    size=\"medium\"\n    scrollable\n  >\n    <n-button style=\"margin-right: 8px\">\n      {{ value || 'Popselect' }}\n    </n-button>\n  </n-popselect>\n</template>\n"
  },
  {
    "path": "src/popselect/demos/enUS/size.demo.vue",
    "content": "<markdown>\n# Size\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst value = ref('Drive My Car')\nconst options = [\n  {\n    label: 'Drive My Car',\n    value: 'Drive My Car'\n  },\n  {\n    label: 'Norwegian Wood',\n    value: 'Norwegian Wood'\n  },\n  {\n    label: 'You Won\\'t See',\n    value: 'You Won\\'t See',\n    disabled: true\n  },\n  {\n    label: 'Nowhere Man',\n    value: 'Nowhere Man'\n  },\n  {\n    label: 'Think For Yourself',\n    value: 'Think For Yourself'\n  },\n  {\n    label: 'The Word',\n    value: 'The Word'\n  },\n  {\n    label: 'Michelle',\n    value: 'Michelle',\n    disabled: true\n  },\n  {\n    label: 'What goes on',\n    value: 'What goes on'\n  },\n  {\n    label: 'Girl',\n    value: 'Girl'\n  },\n  {\n    label: 'I\\'m looking through you',\n    value: 'I\\'m looking through you'\n  },\n  {\n    label: 'In My Life',\n    value: 'In My Life'\n  },\n  {\n    label: 'Wait',\n    value: 'Wait'\n  }\n]\n</script>\n\n<template>\n  <n-space>\n    <n-popselect v-model:value=\"value\" :options=\"options\" size=\"medium\">\n      <n-button>\n        {{ value || 'Popselect' }}\n      </n-button>\n    </n-popselect>\n    <n-popselect v-model:value=\"value\" :options=\"options\" size=\"large\">\n      <n-button>{{ value || 'Popselect' }}</n-button>\n    </n-popselect>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/popselect/demos/enUS/slot.demo.vue",
    "content": "<markdown>\n# Slot\n\nIs there anybody who needs slots in a select menu?\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst value = ref('Empty')\n</script>\n\n<template>\n  <n-popselect v-model:value=\"value\" :options=\"[]\" trigger=\"click\">\n    <n-button>{{ value || 'Popselect' }}</n-button>\n    <template #header>\n      Don't know what to put\n    </template>\n    <template #empty>\n      Nothing to see, here is empty.\n    </template>\n    <template #action>\n      If you click this demo, you may need it.\n    </template>\n  </n-popselect>\n</template>\n"
  },
  {
    "path": "src/popselect/demos/zhCN/basic.demo.vue",
    "content": "<markdown>\n# 基础用法\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst value = ref('Drive My Car')\nconst options = [\n  {\n    label: 'Drive My Car',\n    value: 'Drive My Car'\n  },\n  {\n    label: 'Norwegian Wood',\n    value: 'Norwegian Wood'\n  },\n  {\n    label: 'You Won\\'t See',\n    value: 'You Won\\'t See',\n    disabled: true\n  },\n  {\n    label: 'Nowhere Man',\n    value: 'Nowhere Man'\n  },\n  {\n    label: 'Think For Yourself',\n    value: 'Think For Yourself'\n  },\n  {\n    label: 'The Word',\n    value: 'The Word'\n  },\n  {\n    label: 'Michelle',\n    value: 'Michelle',\n    disabled: true\n  },\n  {\n    label: 'What goes on',\n    value: 'What goes on'\n  },\n  {\n    label: 'Girl',\n    value: 'Girl'\n  },\n  {\n    label: 'I\\'m looking through you',\n    value: 'I\\'m looking through you'\n  },\n  {\n    label: 'In My Life',\n    value: 'In My Life'\n  },\n  {\n    label: 'Wait',\n    value: 'Wait'\n  }\n]\n</script>\n\n<template>\n  <n-popselect v-model:value=\"value\" :options=\"options\" trigger=\"click\">\n    <n-button>{{ value || '弹出选择' }}</n-button>\n  </n-popselect>\n</template>\n"
  },
  {
    "path": "src/popselect/demos/zhCN/cancelable.demo.vue",
    "content": "<markdown>\n# 可取消\n\n单值的弹出选择可以取消选中值。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst value = ref('song1')\nconst options = [\n  {\n    label: 'Everybody\\'s Got Something to Hide Except Me and My Monkey',\n    value: 'song0',\n    disabled: true\n  },\n  {\n    label: 'Drive My Car',\n    value: 'song1'\n  },\n  {\n    label: 'Norwegian Wood',\n    value: 'song2'\n  },\n  {\n    label: 'You Won\\'t See',\n    value: 'song3',\n    disabled: true\n  },\n  {\n    label: 'Nowhere Man',\n    value: 'song4'\n  },\n  {\n    label: 'Think For Yourself',\n    value: 'song5'\n  },\n  {\n    label: 'The Word',\n    value: 'song6'\n  },\n  {\n    label: 'Michelle',\n    value: 'song7',\n    disabled: true\n  },\n  {\n    label: 'What goes on',\n    value: 'song8'\n  },\n  {\n    label: 'Girl',\n    value: 'song9'\n  },\n  {\n    label: 'I\\'m looking through you',\n    value: 'song10'\n  },\n  {\n    label: 'In My Life',\n    value: 'song11'\n  },\n  {\n    label: 'Wait',\n    value: 'song12'\n  }\n]\n</script>\n\n<template>\n  <n-popselect v-model:value=\"value\" cancelable :options=\"options\">\n    <n-button>{{ value || '弹出选择' }}</n-button>\n  </n-popselect>\n</template>\n"
  },
  {
    "path": "src/popselect/demos/zhCN/index.demo-entry.md",
    "content": "# 弹出选择 Popselect\n\n如果你想选择一些数据，还不想看到那个框子，可以使用 Popselect。\n\n## 演示\n\n```demo\nbasic.vue\nsize.vue\nscrollable.vue\nmultiple.vue\nslot.vue\n```\n\n## API\n\n### Popselect Props\n\n| 名称 | 类型 | 默认值 | 说明 | 版本 |\n| --- | --- | --- | --- | --- |\n| multiple | `boolean` | `false` | 是否为多选 |  |\n| node-props | `(option: SelectOption \\| SelectGroupOption) => object` | `undefined` | 选项的 DOM 属性生成函数 | 2.30.4 |\n| options | `Array<SelectOption \\| SelectGroupOption>` | `[]` | 配置选项内容，详情参考 [Select](select#SelectOption-Properties) |  |\n| scrollable | `boolean` | `false` | 选择菜单是否可滚动 |  |\n| scrollbar-props | `ScrollbarProps` | `undefined` | 属性参考 [Scrollbar props](scrollbar#Scrollbar-Props) | 2.44.0 |\n| render-label | `(option: SelectOption \\| SelectGroupOption) => VNodeChild` | `undefined` | 控制全部选项的渲染 |  |\n| size | `'small' \\| 'medium' \\| 'large'` | `'medium'` | 组件尺寸 |  |\n| value | `string \\| number \\| Array<string \\| number> \\| null` | `null` | 受控模式下的值 |  |\n| virtual-scroll | `boolean` | `false` | 是否启用虚拟滚动 | 2.30.4 |\n| on-update:value | `(value: string \\| number \\| Array<string \\| number> \\| null, option: SelectBaseOption \\| null \\| Array<SelectBaseOption>) => void` | `undefined` | 值更新的回调 |  |\n\n对于 SelectOption & SelectGroupOption，参考 [Select](select#SelectOption-Properties)\n\n对于其他 props，参考 [Popover](popover#Popover-Props)\n\n### Popselect Slots\n\n| 名称   | 参数 | 说明                | 版本   |\n| ------ | ---- | ------------------- | ------ |\n| header | `()` | 菜单头部区域的 slot | 2.36.0 |\n| action | `()` | 菜单操作区域的 slot | 2.22.0 |\n| empty  | `()` | 菜单无数据时的 slot | 2.22.0 |\n"
  },
  {
    "path": "src/popselect/demos/zhCN/multiple.demo.vue",
    "content": "<markdown>\n# 多选\n\n在弹出选择选中多个值。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst value = ref<string[] | null>(null)\nconst options = [\n  {\n    label: 'Go Let It Out',\n    value: 'Go Let It Out'\n  },\n  {\n    label: 'Who Feels Love?',\n    value: 'Who Feels Love?'\n  },\n  {\n    label: 'Sunday Morning Call',\n    value: 'Sunday Morning Call',\n    disabled: true\n  },\n  {\n    label: 'Roll It Over',\n    value: 'Roll It Over'\n  }\n]\n</script>\n\n<template>\n  <n-popselect v-model:value=\"value\" multiple :options=\"options\">\n    <n-button>\n      {{ Array.isArray(value) && value.length ? value : '没了' }}\n    </n-button>\n  </n-popselect>\n</template>\n"
  },
  {
    "path": "src/popselect/demos/zhCN/scrollable.demo.vue",
    "content": "<markdown>\n# 让它滚动\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst value = ref('Drive My Car')\nconst options = [\n  {\n    label: 'Drive My Car',\n    value: 'Drive My Car'\n  },\n  {\n    label: 'Norwegian Wood',\n    value: 'Norwegian Wood'\n  },\n  {\n    label: 'You Won\\'t See',\n    value: 'You Won\\'t See',\n    disabled: true\n  },\n  {\n    label: 'Nowhere Man',\n    value: 'Nowhere Man'\n  },\n  {\n    label: 'Think For Yourself',\n    value: 'Think For Yourself'\n  },\n  {\n    label: 'The Word',\n    value: 'The Word'\n  },\n  {\n    label: 'Michelle',\n    value: 'Michelle',\n    disabled: true\n  },\n  {\n    label: 'What goes on',\n    value: 'What goes on'\n  },\n  {\n    label: 'Girl',\n    value: 'Girl'\n  },\n  {\n    label: 'I\\'m looking through you',\n    value: 'I\\'m looking through you'\n  },\n  {\n    label: 'In My Life',\n    value: 'In My Life'\n  },\n  {\n    label: 'Wait',\n    value: 'Wait'\n  }\n]\n</script>\n\n<template>\n  <n-popselect\n    v-model:value=\"value\"\n    :options=\"options\"\n    size=\"medium\"\n    scrollable\n  >\n    <n-button style=\"margin-right: 8px\">\n      {{ value || 'Popselect' }}\n    </n-button>\n  </n-popselect>\n</template>\n"
  },
  {
    "path": "src/popselect/demos/zhCN/size.demo.vue",
    "content": "<markdown>\n# 尺寸\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst value = ref('Drive My Car')\nconst options = [\n  {\n    label: 'Drive My Car',\n    value: 'Drive My Car'\n  },\n  {\n    label: 'Norwegian Wood',\n    value: 'Norwegian Wood'\n  },\n  {\n    label: 'You Won\\'t See',\n    value: 'You Won\\'t See',\n    disabled: true\n  },\n  {\n    label: 'Nowhere Man',\n    value: 'Nowhere Man'\n  },\n  {\n    label: 'Think For Yourself',\n    value: 'Think For Yourself'\n  },\n  {\n    label: 'The Word',\n    value: 'The Word'\n  },\n  {\n    label: 'Michelle',\n    value: 'Michelle',\n    disabled: true\n  },\n  {\n    label: 'What goes on',\n    value: 'What goes on'\n  },\n  {\n    label: 'Girl',\n    value: 'Girl'\n  },\n  {\n    label: 'I\\'m looking through you',\n    value: 'I\\'m looking through you'\n  },\n  {\n    label: 'In My Life',\n    value: 'In My Life'\n  },\n  {\n    label: 'Wait',\n    value: 'Wait'\n  }\n]\n</script>\n\n<template>\n  <n-space>\n    <n-popselect v-model:value=\"value\" :options=\"options\" size=\"medium\">\n      <n-button>\n        {{ value || 'Popselect' }}\n      </n-button>\n    </n-popselect>\n    <n-popselect v-model:value=\"value\" :options=\"options\" size=\"large\">\n      <n-button>{{ value || 'Popselect' }}</n-button>\n    </n-popselect>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/popselect/demos/zhCN/slot.demo.vue",
    "content": "<markdown>\n# 插槽\n\n有人要在选择菜单里用插槽吗？\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst value = ref('空的')\n</script>\n\n<template>\n  <n-popselect v-model:value=\"value\" :options=\"[]\" trigger=\"click\">\n    <n-button>{{ value || '弹出选择' }}</n-button>\n    <template #header>\n      不知道放些什么\n    </template>\n    <template #empty>\n      没啥看的，这里是空的\n    </template>\n    <template #action>\n      如果你点开了这个例子，你可能需要它\n    </template>\n  </n-popselect>\n</template>\n"
  },
  {
    "path": "src/popselect/index.ts",
    "content": "export type { PopselectInst } from './src/interface'\nexport { default as NPopselect, popselectProps } from './src/Popselect'\nexport type { PopselectProps, PopselectSlots } from './src/Popselect'\nexport type * from './src/public-types'\n"
  },
  {
    "path": "src/popselect/src/Popselect.tsx",
    "content": "import type { ExtractPropTypes, PropType, SlotsType, VNode } from 'vue'\nimport type { ScrollbarProps } from '../../_internal/scrollbar/src/Scrollbar'\nimport type { ThemeProps } from '../../_mixins'\nimport type { ExtractPublicPropTypes } from '../../_utils'\nimport type { PopoverInst, PopoverTrigger } from '../../popover'\nimport type { PopoverInternalProps } from '../../popover/src/Popover'\nimport type { PopselectTheme } from '../styles'\nimport type { PopselectInst } from './interface'\nimport { defineComponent, h, provide, ref } from 'vue'\nimport { useConfig, useTheme } from '../../_mixins'\nimport { createRefSetter, keep, mergeEventHandlers, omit } from '../../_utils'\nimport { NPopover } from '../../popover'\nimport { popoverBaseProps } from '../../popover/src/Popover'\nimport { popselectLight } from '../styles'\nimport { popselectInjectionKey } from './interface'\nimport NPopselectPanel, { panelPropKeys, panelProps } from './PopselectPanel'\n\nexport const popselectProps = {\n  ...(useTheme.props as ThemeProps<PopselectTheme>),\n  ...omit(popoverBaseProps, ['showArrow', 'arrow']),\n  placement: {\n    ...popoverBaseProps.placement,\n    default: 'bottom'\n  },\n  trigger: {\n    type: String as PropType<PopoverTrigger>,\n    default: 'hover'\n  },\n  ...panelProps,\n  scrollbarProps: Object as PropType<ScrollbarProps>\n}\n\nexport type PopselectSetupProps = ExtractPropTypes<typeof popselectProps>\nexport type PopselectProps = ExtractPublicPropTypes<typeof popselectProps>\n\nexport interface PopselectSlots {\n  default?: () => VNode[]\n  header?: () => VNode[]\n  action?: () => VNode[]\n  empty?: () => VNode[]\n}\n\nexport default defineComponent({\n  name: 'Popselect',\n  props: popselectProps,\n  slots: Object as SlotsType<PopselectSlots>,\n  inheritAttrs: false,\n  __popover__: true,\n  setup(props) {\n    const { mergedClsPrefixRef } = useConfig(props)\n    const themeRef = useTheme(\n      'Popselect',\n      '-popselect',\n      undefined,\n      popselectLight,\n      props,\n      mergedClsPrefixRef\n    )\n    const popoverInstRef = ref<PopoverInst | null>(null)\n    function syncPosition(): void {\n      popoverInstRef.value?.syncPosition()\n    }\n    function setShow(value: boolean): void {\n      popoverInstRef.value?.setShow(value)\n    }\n    provide(popselectInjectionKey, {\n      props,\n      mergedThemeRef: themeRef,\n      syncPosition,\n      setShow\n    })\n    const exposedMethods: PopselectInst = {\n      syncPosition,\n      setShow\n    }\n    return {\n      ...exposedMethods,\n      popoverInstRef,\n      mergedTheme: themeRef\n    }\n  },\n  render() {\n    const { mergedTheme } = this\n    const popoverProps: PopoverInternalProps & { ref: string } = {\n      theme: mergedTheme.peers.Popover,\n      themeOverrides: mergedTheme.peerOverrides.Popover,\n      builtinThemeOverrides: {\n        padding: '0'\n      },\n      ref: 'popoverInstRef',\n      internalRenderBody: (\n        className,\n        ref,\n        style,\n        onMouseenter,\n        onMouseleave\n      ) => {\n        const { $attrs } = this\n        return (\n          <NPopselectPanel\n            {...$attrs}\n            class={[$attrs.class, className]}\n            style={[$attrs.style, ...style]}\n            {...keep(this.$props, panelPropKeys)}\n            ref={createRefSetter(ref)}\n            onMouseenter={mergeEventHandlers([\n              onMouseenter,\n              $attrs.onMouseenter as ((e: MouseEvent) => void) | undefined\n            ])}\n            onMouseleave={mergeEventHandlers([\n              onMouseleave,\n              $attrs.onMouseleave as ((e: MouseEvent) => void) | undefined\n            ])}\n          >\n            {{\n              header: () => this.$slots.header?.(),\n              action: () => this.$slots.action?.(),\n              empty: () => this.$slots.empty?.()\n            }}\n          </NPopselectPanel>\n        )\n      }\n    }\n    return (\n      <NPopover\n        {...omit(this.$props, panelPropKeys)}\n        {...popoverProps}\n        internalDeactivateImmediately\n      >\n        {{\n          trigger: () => this.$slots.default?.()\n        }}\n      </NPopover>\n    )\n  }\n})\n"
  },
  {
    "path": "src/popselect/src/PopselectPanel.tsx",
    "content": "import type { TreeNode } from 'treemate'\nimport type { PropType } from 'vue'\nimport type {\n  NodeProps,\n  RenderLabel\n} from '../../_internal/select-menu/src/interface'\nimport type { MaybeArray } from '../../_utils'\nimport type {\n  OnUpdateValue,\n  OnUpdateValueImpl,\n  SelectBaseOption,\n  SelectGroupOption,\n  SelectIgnoredOption,\n  SelectMixedOption,\n  Value,\n  ValueAtom\n} from '../../select/src/interface'\nimport type { PopselectSize } from './public-types'\nimport { happensIn } from 'seemly'\nimport { createTreeMate } from 'treemate'\nimport {\n  computed,\n  defineComponent,\n  h,\n  inject,\n  nextTick,\n  toRef,\n  watch,\n  watchEffect\n} from 'vue'\nimport { NInternalSelectMenu } from '../../_internal'\nimport { useConfig, useTheme, useThemeClass } from '../../_mixins'\nimport { call, keysOf, warn } from '../../_utils'\nimport { createTmOptions } from '../../select/src/utils'\nimport { popselectLight } from '../styles'\nimport { popselectInjectionKey } from './interface'\nimport style from './styles/index.cssr'\n\nexport const panelProps = {\n  multiple: Boolean,\n  value: {\n    type: [String, Number, Array] as PropType<Value | null>,\n    default: null\n  },\n  cancelable: Boolean,\n  options: {\n    type: Array as PropType<SelectMixedOption[]>,\n    default: () => []\n  },\n  size: String as PropType<PopselectSize>,\n  scrollable: Boolean,\n  'onUpdate:value': [Function, Array] as PropType<MaybeArray<OnUpdateValue>>,\n  onUpdateValue: [Function, Array] as PropType<MaybeArray<OnUpdateValue>>,\n  onMouseenter: Function as PropType<(e: MouseEvent) => void>,\n  onMouseleave: Function as PropType<(e: MouseEvent) => void>,\n  renderLabel: Function as PropType<RenderLabel>,\n  showCheckmark: {\n    type: Boolean,\n    default: undefined\n  },\n  nodeProps: Function as PropType<NodeProps>,\n  virtualScroll: Boolean,\n  // deprecated\n  onChange: [Function, Array] as PropType<MaybeArray<OnUpdateValue> | undefined>\n} as const\n\nexport const panelPropKeys = keysOf(panelProps)\n\nexport default defineComponent({\n  name: 'PopselectPanel',\n  props: panelProps,\n  setup(props) {\n    if (__DEV__) {\n      watchEffect(() => {\n        if (props.onChange !== undefined) {\n          warn(\n            'popselect',\n            '`on-change` is deprecated, please use `on-update:value` instead.'\n          )\n        }\n      })\n    }\n\n    const NPopselect = inject(popselectInjectionKey)!\n\n    const { mergedClsPrefixRef, inlineThemeDisabled, mergedComponentPropsRef }\n      = useConfig(props)\n    const mergedSizeRef = computed<PopselectSize>(() => {\n      return (\n        props.size\n        || mergedComponentPropsRef?.value?.Popselect?.size\n        || 'medium'\n      )\n    })\n\n    const themeRef = useTheme(\n      'Popselect',\n      '-pop-select',\n      style,\n      popselectLight,\n      NPopselect.props,\n      mergedClsPrefixRef\n    )\n\n    const treeMateRef = computed(() => {\n      return createTreeMate<\n        SelectBaseOption,\n        SelectGroupOption,\n        SelectIgnoredOption\n      >(props.options, createTmOptions('value', 'children'))\n    })\n\n    function doUpdateValue(\n      value: Value | null,\n      option: SelectBaseOption | null | SelectBaseOption[]\n    ): void {\n      const {\n        onUpdateValue,\n        'onUpdate:value': _onUpdateValue,\n        onChange\n      } = props\n      if (onUpdateValue)\n        call(onUpdateValue as OnUpdateValueImpl, value, option)\n      if (_onUpdateValue) {\n        call(_onUpdateValue as OnUpdateValueImpl, value, option)\n      }\n      if (onChange)\n        call(onChange as OnUpdateValueImpl, value, option)\n    }\n    function handleToggle(tmNode: TreeNode<SelectBaseOption>): void {\n      toggle(tmNode.key)\n    }\n    function handleMenuMousedown(e: MouseEvent): void {\n      if (\n        !happensIn(e, 'action')\n        && !happensIn(e, 'empty')\n        && !happensIn(e, 'header')\n      ) {\n        e.preventDefault()\n      }\n    }\n    function toggle(value: ValueAtom): void {\n      const {\n        value: { getNode }\n      } = treeMateRef\n      if (props.multiple) {\n        if (Array.isArray(props.value)) {\n          const newValue: ValueAtom[] = []\n          const newOptions: SelectBaseOption[] = []\n          let shouldAddValue = true\n          props.value.forEach((v) => {\n            if (v === value) {\n              shouldAddValue = false\n              return\n            }\n            const tmNode = getNode(v)\n            if (tmNode) {\n              newValue.push(tmNode.key)\n              newOptions.push(tmNode.rawNode)\n            }\n          })\n          if (shouldAddValue) {\n            newValue.push(value)\n            newOptions.push(getNode(value)!.rawNode)\n          }\n          doUpdateValue(newValue, newOptions)\n        }\n        else {\n          const tmNode = getNode(value)\n          if (tmNode) {\n            doUpdateValue([value], [tmNode.rawNode])\n          }\n        }\n      }\n      else {\n        if (props.value === value && props.cancelable) {\n          doUpdateValue(null, null)\n        }\n        else {\n          const tmNode = getNode(value)\n          if (tmNode) {\n            doUpdateValue(value, tmNode.rawNode)\n          }\n          const { 'onUpdate:show': _onUpdateShow, onUpdateShow }\n            = NPopselect.props\n          if (_onUpdateShow)\n            call(_onUpdateShow, false)\n          if (onUpdateShow)\n            call(onUpdateShow, false)\n          NPopselect.setShow(false)\n        }\n      }\n      void nextTick(() => {\n        NPopselect.syncPosition()\n      })\n    }\n    watch(toRef(props, 'options'), () => {\n      void nextTick(() => {\n        NPopselect.syncPosition()\n      })\n    })\n    const cssVarsRef = computed(() => {\n      const {\n        self: { menuBoxShadow }\n      } = themeRef.value\n      return {\n        '--n-menu-box-shadow': menuBoxShadow\n      }\n    })\n    const themeClassHandle = inlineThemeDisabled\n      ? useThemeClass('select', undefined, cssVarsRef, NPopselect.props)\n      : undefined\n\n    return {\n      mergedTheme: NPopselect.mergedThemeRef,\n      mergedClsPrefix: mergedClsPrefixRef,\n      treeMate: treeMateRef,\n      handleToggle,\n      handleMenuMousedown,\n      cssVars: inlineThemeDisabled ? undefined : cssVarsRef,\n      themeClass: themeClassHandle?.themeClass,\n      onRender: themeClassHandle?.onRender,\n      mergedSize: mergedSizeRef,\n      scrollbarProps: NPopselect.props.scrollbarProps\n    }\n  },\n  render() {\n    this.onRender?.()\n    return (\n      <NInternalSelectMenu\n        clsPrefix={this.mergedClsPrefix}\n        focusable\n        nodeProps={this.nodeProps}\n        class={[`${this.mergedClsPrefix}-popselect-menu`, this.themeClass]}\n        style={this.cssVars}\n        theme={this.mergedTheme.peers.InternalSelectMenu}\n        themeOverrides={this.mergedTheme.peerOverrides.InternalSelectMenu}\n        multiple={this.multiple}\n        treeMate={this.treeMate}\n        size={this.mergedSize}\n        value={this.value}\n        virtualScroll={this.virtualScroll}\n        scrollable={this.scrollable}\n        scrollbarProps={this.scrollbarProps}\n        renderLabel={this.renderLabel}\n        onToggle={this.handleToggle}\n        onMouseenter={this.onMouseenter}\n        onMouseleave={this.onMouseenter}\n        onMousedown={this.handleMenuMousedown}\n        showCheckmark={this.showCheckmark}\n      >\n        {{\n          header: () => this.$slots.header?.() || [],\n          action: () => this.$slots.action?.() || [],\n          empty: () => this.$slots.empty?.() || []\n        }}\n      </NInternalSelectMenu>\n    )\n  }\n})\n"
  },
  {
    "path": "src/popselect/src/interface.ts",
    "content": "import type { Ref } from 'vue'\nimport type { MergedTheme } from '../../_mixins'\nimport type { PopoverInst } from '../../popover/src/interface'\nimport type { PopselectTheme } from '../styles'\nimport type { PopselectSetupProps } from './Popselect'\nimport { createInjectionKey } from '../../_utils'\n\nexport interface PopselectInjection {\n  props: PopselectSetupProps\n  mergedThemeRef: Ref<MergedTheme<PopselectTheme>>\n  setShow: (value: boolean) => void\n  syncPosition: () => void\n}\n\nexport type PopselectInst = PopoverInst\n\nexport const popselectInjectionKey\n  = createInjectionKey<PopselectInjection>('n-popselect')\n"
  },
  {
    "path": "src/popselect/src/public-types.ts",
    "content": "export type PopselectSize = 'small' | 'medium' | 'large' | 'huge'\n"
  },
  {
    "path": "src/popselect/src/styles/index.cssr.ts",
    "content": "import { cB } from '../../../_utils/cssr'\n\n// --n-menu-box-shadow\nexport default cB('popselect-menu', `\n  box-shadow: var(--n-menu-box-shadow);\n`)\n"
  },
  {
    "path": "src/popselect/styles/dark.ts",
    "content": "import type { PopselectTheme } from './light'\nimport { internalSelectMenuDark } from '../../_internal/select-menu/styles'\nimport { commonDark } from '../../_styles/common'\nimport { popoverDark } from '../../popover/styles'\n\nconst popselect: PopselectTheme = {\n  name: 'Popselect',\n  common: commonDark,\n  peers: {\n    Popover: popoverDark,\n    InternalSelectMenu: internalSelectMenuDark\n  }\n}\n\nexport default popselect\n"
  },
  {
    "path": "src/popselect/styles/index.ts",
    "content": "export { default as popselectDark } from './dark'\nexport { default as popselectLight } from './light'\nexport type { PopselectTheme, PopselectThemeVars } from './light'\n"
  },
  {
    "path": "src/popselect/styles/light.ts",
    "content": "import type { ThemeCommonVars } from '../../config-provider'\nimport { internalSelectMenuLight } from '../../_internal/select-menu/styles'\nimport { createTheme } from '../../_mixins'\nimport { commonLight } from '../../_styles/common'\nimport { popoverLight } from '../../popover/styles'\n\nexport function self(vars: ThemeCommonVars) {\n  const { boxShadow2 } = vars\n  return {\n    menuBoxShadow: boxShadow2\n  }\n}\n\nconst popselectLight = createTheme({\n  name: 'Popselect',\n  common: commonLight,\n  peers: {\n    Popover: popoverLight,\n    InternalSelectMenu: internalSelectMenuLight\n  },\n  self\n})\n\nexport interface PopselectThemeVars {}\nexport default popselectLight\nexport type PopselectTheme = typeof popselectLight\n"
  },
  {
    "path": "src/popselect/tests/Popselect.spec.ts",
    "content": "import { mount } from '@vue/test-utils'\nimport { h } from 'vue'\nimport { NScrollbar } from '../../_internal'\nimport { NPopselect } from '../index'\n\ndescribe('n-popselect', () => {\n  it('should work with import on demand', () => {\n    mount(NPopselect, {\n      slots: {\n        default: () => 'star kirby'\n      }\n    })\n  })\n\n  it('should be active after clicked and options `disabled`', async () => {\n    const wrapper = mount(NPopselect, {\n      attachTo: document.body,\n      props: {\n        trigger: 'click',\n        value: '',\n        options: [\n          { label: 'Drive My Car', value: 'Drive My Car' },\n          { label: 'Norwegian Wood', value: 'Norwegian Wood' },\n          { label: 'Nowhere Man', value: 'Nowhere Man', disabled: true }\n        ]\n      },\n      slots: {\n        default: () => h('button', { class: 'test-btn' }, '点击打开')\n      }\n    })\n\n    await wrapper.find('.test-btn').trigger('click')\n    expect(\n      document.querySelector('.n-base-select-option--disabled')?.textContent\n    ).toBe('Nowhere Man')\n    expect(document.querySelector('.n-base-select-menu')).not.toEqual(null)\n\n    await wrapper.find('.test-btn').trigger('click')\n    expect(document.querySelector('.n-base-select-menu')).toEqual(null)\n\n    wrapper.unmount()\n  })\n\n  it('should work with `multiple` and `scrollable` prop', async () => {\n    const wrapper = mount(NPopselect, {\n      attachTo: document.body,\n      props: {\n        multiple: true,\n        trigger: 'click',\n        value: '',\n        options: [\n          { label: 'Drive My Car', value: 'Drive My Car' },\n          { label: 'Norwegian Wood', value: 'Norwegian Wood' },\n          { label: 'Nowhere Man', value: 'Nowhere Man' }\n        ]\n      },\n      slots: {\n        default: () => h('button', { class: 'test-btn' }, '点击打开')\n      }\n    })\n\n    await wrapper.find('.test-btn').trigger('click')\n    expect(document.querySelector('.n-base-select-menu--multiple')).not.toEqual(\n      null\n    )\n\n    await wrapper.setProps({ scrollable: true })\n    expect(wrapper.findComponent(NScrollbar).exists()).not.toEqual(null)\n\n    wrapper.unmount()\n  })\n})\n"
  },
  {
    "path": "src/popselect/tests/server.spec.tsx",
    "content": "import { setup } from '@css-render/vue3-ssr'\nimport { renderToString } from '@vue/server-renderer'\n/**\n * @vitest-environment node\n */\nimport { createSSRApp, h } from 'vue'\nimport { NPopselect } from '../..'\n\ndescribe('server side rendering', () => {\n  it('works', async () => {\n    const app = createSSRApp(() => (\n      <NPopselect>\n        {{\n          default: () => 'kirby'\n        }}\n      </NPopselect>\n    ))\n    setup(app)\n    try {\n      await renderToString(app)\n    }\n    catch (e) {\n      expect(e).not.toBeTruthy()\n    }\n  })\n})\n"
  },
  {
    "path": "src/preset.ts",
    "content": "import * as components from './components'\nimport create from './create'\n\nconst naive = create({\n  components: Object.keys(components).map(\n    key => components[key as keyof typeof components]\n  )\n})\n\nexport default naive\nexport const install = naive.install\n"
  },
  {
    "path": "src/progress/demos/enUS/circle-offset.demo.vue",
    "content": "<markdown>\n# Offset\n\nCircular progress can have `offset-degree`.\n</markdown>\n\n<template>\n  <n-progress type=\"circle\" :percentage=\"80\" :offset-degree=\"120\" />\n</template>\n"
  },
  {
    "path": "src/progress/demos/enUS/circle.demo.vue",
    "content": "<markdown>\n# Circle\n\nProgress can be a circle. It can be `default`, `info`, `success`, `warning` or `error` status.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst percentage = ref(0)\n\nfunction add() {\n  percentage.value += 10\n  if (percentage.value > 100) {\n    percentage.value = 0\n  }\n}\n\nfunction minus() {\n  percentage.value -= 10\n  if (percentage.value < 0) {\n    percentage.value = 100\n  }\n}\n</script>\n\n<template>\n  <n-space vertical>\n    <n-space>\n      <n-progress type=\"circle\" :percentage=\"percentage\" />\n      <n-progress type=\"circle\" status=\"info\" :percentage=\"percentage\" />\n      <n-progress type=\"circle\" status=\"success\" :percentage=\"percentage\" />\n      <n-progress type=\"circle\" status=\"warning\" :percentage=\"percentage\" />\n      <n-progress type=\"circle\" status=\"error\" :percentage=\"percentage\" />\n    </n-space>\n    <n-space>\n      <n-button @click=\"minus\">\n        Minus 10%\n      </n-button>\n      <n-button @click=\"add\">\n        Add 10%\n      </n-button>\n    </n-space>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/progress/demos/enUS/color.demo.vue",
    "content": "<markdown>\n# Customize color\n\nIf you are not satisfied with builtin colors.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { useThemeVars } from 'naive-ui'\nimport { changeColor } from 'seemly'\n\nconst themeVars = useThemeVars()\n</script>\n\n<template>\n  <n-progress\n    style=\"margin: 0 8px 12px 0\"\n    type=\"circle\"\n    :percentage=\"20\"\n    :color=\"themeVars.successColor\"\n    :rail-color=\"changeColor(themeVars.successColor, { alpha: 0.2 })\"\n    :indicator-text-color=\"themeVars.successColor\"\n  />\n  <n-progress\n    style=\"width: 120px; margin: 0 8px 12px 0\"\n    type=\"multiple-circle\"\n    :stroke-width=\"10\"\n    :circle-gap=\"10\"\n    :percentage=\"[50, 25]\"\n    :color=\"[themeVars.infoColor, themeVars.infoColor]\"\n    :rail-color=\"[\n      changeColor(themeVars.infoColor, { alpha: 0.2 }),\n      changeColor(themeVars.infoColor, { alpha: 0.2 }),\n    ]\"\n  />\n  <n-progress\n    type=\"line\"\n    indicator-placement=\"inside\"\n    :color=\"themeVars.errorColor\"\n    :rail-color=\"changeColor(themeVars.errorColor, { alpha: 0.2 })\"\n    :percentage=\"20\"\n  />\n  <n-progress\n    type=\"line\"\n    :color=\"themeVars.warningColor\"\n    :rail-color=\"changeColor(themeVars.warningColor, { alpha: 0.2 })\"\n    :percentage=\"20\"\n    :indicator-text-color=\"themeVars.warningColor\"\n  />\n</template>\n"
  },
  {
    "path": "src/progress/demos/enUS/custom-indicator.demo.vue",
    "content": "<markdown>\n# Custom indicator\n\nYou can custom the indicator.\n</markdown>\n\n<template>\n  <n-progress type=\"circle\" :percentage=\"20\">\n    <span style=\"text-align: center\">20% is small</span>\n  </n-progress>\n  <n-progress type=\"line\" status=\"success\" :percentage=\"20\">\n    Don't put too much content here.\n  </n-progress>\n</template>\n"
  },
  {
    "path": "src/progress/demos/enUS/dashboard.demo.vue",
    "content": "<markdown>\n# Dashboard\n\nMaybe you also need `gap-degree` and `gap-offset-degree` properties to customize the dashboard.\n</markdown>\n\n<template>\n  <n-space>\n    <n-progress type=\"dashboard\" gap-position=\"bottom\" :percentage=\"80\" />\n    <n-progress\n      type=\"dashboard\"\n      :gap-offset-degree=\"120\"\n      :gap-degree=\"120\"\n      :percentage=\"80\"\n    />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/progress/demos/enUS/gradient.demo.vue",
    "content": "<markdown>\n# Linear Gradient\n\nYou may want to use color combinations.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { useThemeVars } from 'naive-ui'\nimport { changeColor } from 'seemly'\nimport { ref } from 'vue'\n\nconst percentage = ref(80)\nconst themeVars = useThemeVars()\n</script>\n\n<template>\n  <n-flex vertical>\n    <n-progress\n      type=\"line\"\n      :percentage=\"percentage\"\n      :show-indicator=\"false\"\n      :color=\"{ stops: ['white', 'pink'] }\"\n    />\n    <n-flex>\n      <n-progress\n        type=\"circle\"\n        :percentage=\"percentage\"\n        :color=\"{ stops: ['#E3F2FD', '#2080f0'] }\"\n      />\n      <n-progress\n        style=\"width: 120px; margin: 0 8px 12px 0\"\n        type=\"multiple-circle\"\n        :stroke-width=\"10\"\n        :circle-gap=\"10\"\n        :percentage=\"[80, 70]\"\n        :color=\"[\n          { stops: ['white', '#18a058'] },\n          { stops: ['#E3F2FD', '#2080f0'] },\n        ]\"\n        :rail-color=\"[\n          changeColor(themeVars.infoColor, { alpha: 0.2 }),\n          changeColor(themeVars.infoColor, { alpha: 0.2 }),\n        ]\"\n      />\n    </n-flex>\n  </n-flex>\n</template>\n"
  },
  {
    "path": "src/progress/demos/enUS/height.demo.vue",
    "content": "<markdown>\n# Height & border radius\n\nIn case you aren't satisfied with height & border-radius.\n</markdown>\n\n<template>\n  <n-space vertical>\n    <n-progress\n      type=\"line\"\n      :percentage=\"50\"\n      :height=\"24\"\n      :border-radius=\"4\"\n      :fill-border-radius=\"0\"\n    />\n    <n-progress\n      type=\"line\"\n      status=\"error\"\n      :percentage=\"50\"\n      :height=\"24\"\n      border-radius=\"12px 0 12px 0\"\n      fill-border-radius=\"12px 0 12px 0\"\n    >\n      A Kind of Art\n    </n-progress>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/progress/demos/enUS/index.demo-entry.md",
    "content": "# Progress\n\nI have no words to say but there still should be a placeholder to make layout looks spread.\n\n## Demos\n\n```demo\ncircle.vue\nline.vue\ncircle-offset.vue\nmultiple-circle.vue\ndashboard.vue\ncustom-indicator.vue\ncolor.vue\nno-indicator.vue\nheight.vue\nprocessing.vue\ngradient.vue\n```\n\n## API\n\n### Progress Props\n\n| Name | Type | Default | Description | Version |\n| --- | --- | --- | --- | --- |\n| border-radius | `number \\| string` | `undefined` | `'line'` typed progress's border-radius. Keep half of default height if not passed. |  |\n| circle-gap | `number` | `1` | The gap between circles when type is `'multiple-circle'`, suppose `viewbox` size is `100`. |  |\n| color | `string \\| string[] \\| { stops: string[] } \\| Array<{ stops: string[] }>` | `undefined` | Progress color. `{ stops: string[] }` indicates a gradient color. `stops` array must have length of 2. The first element is gradient start color. The second element is gradient end color. | `stops` since 2.40.2 |\n| fill-border-radius | `number \\| string` | `undefined` | `'line'` typed progress's fill's border-radius. Keep `border-radius` if not passed. |  |\n| gap-degree | `number` | `75` | The gap degree of half circle, 0 ~ 360. | 2.25.2 |\n| gap-offset-degree | `number` | `0` | The gap offset degree. | 2.25.2 |\n| height | `number` | `undefined` | `'line'` typed progress's height. Keep default height if not passed. |  |\n| indicator-placement | `'inside' \\| 'outside'` | `'outside'` | Indicator placement. |  |\n| indicator-text-color | `string` | `undefined` | Indicator text color. |  |\n| offset-degress | `number` | `0` | Offset degree of circular progress, only works with `circle` typed progress. | 2.24.0 |\n| percentage | `number \\| number[]` | `0` | Percentage value. |  |\n| processing | `boolean` | `false` | Processing status. |  |\n| rail-color | `string \\| string[]` | `undefined` | Rail color. |  |\n| rail-style | `string \\| CSS \\| Array<string \\| CSS>` | `undefined` | Rail style. |  |\n| show-indicator | `boolean` | `true` | Whether to display indicators. |  |\n| status | `'default' \\| 'success' \\| 'error' \\| 'warning' \\| 'info'` | `'default'` | Progress status. |  |\n| stroke-width | `number` | `7` | Progress width. |  |\n| type | `'line' \\| 'circle' \\| 'multiple-circle' \\| 'dashboard'` | `line` | Progress type. | `'dashboard'` 2.25.2 |\n| unit | `string` | `%` | Progress unit. |  |\n\n### Progress Slots\n\n| Name    | Parameters | Description                                     |\n| ------- | ---------- | ----------------------------------------------- |\n| default | `()`       | Content will replace default indicator content. |\n"
  },
  {
    "path": "src/progress/demos/enUS/line.demo.vue",
    "content": "<markdown>\n# Line\n\nIn fact, progress of line type don't need four different styles. However, since UI has designed it, I finally implemented them all. It also support `default`, `info`, `success`, `warning` or `error` status.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst percentage = ref(0)\n\nfunction add() {\n  percentage.value += 10\n  if (percentage.value > 100) {\n    percentage.value = 0\n  }\n}\n\nfunction minus() {\n  percentage.value -= 10\n  if (percentage.value < 0) {\n    percentage.value = 100\n  }\n}\n</script>\n\n<template>\n  <n-space vertical>\n    <n-progress type=\"line\" :percentage=\"percentage\" :show-indicator=\"false\" />\n    <n-progress type=\"line\" :percentage=\"percentage\" />\n    <n-progress\n      type=\"line\"\n      :percentage=\"percentage\"\n      indicator-placement=\"inside\"\n    />\n    <n-progress\n      type=\"line\"\n      status=\"info\"\n      :percentage=\"percentage\"\n      :show-indicator=\"false\"\n    />\n    <n-progress type=\"line\" status=\"info\" :percentage=\"percentage\" />\n    <n-progress\n      type=\"line\"\n      status=\"info\"\n      :percentage=\"percentage\"\n      indicator-placement=\"inside\"\n    />\n    <n-progress\n      type=\"line\"\n      status=\"success\"\n      :percentage=\"percentage\"\n      :show-indicator=\"false\"\n    />\n    <n-progress type=\"line\" status=\"success\" :percentage=\"percentage\" />\n    <n-progress\n      type=\"line\"\n      status=\"success\"\n      :percentage=\"percentage\"\n      indicator-placement=\"inside\"\n    />\n    <n-progress\n      type=\"line\"\n      status=\"warning\"\n      :percentage=\"percentage\"\n      :show-indicator=\"false\"\n    />\n    <n-progress type=\"line\" status=\"warning\" :percentage=\"percentage\" />\n    <n-progress\n      type=\"line\"\n      status=\"warning\"\n      :percentage=\"percentage\"\n      indicator-placement=\"inside\"\n    />\n    <n-progress\n      type=\"line\"\n      status=\"error\"\n      :percentage=\"percentage\"\n      :show-indicator=\"false\"\n    />\n    <n-progress type=\"line\" status=\"error\" :percentage=\"percentage\" />\n    <n-progress\n      type=\"line\"\n      status=\"error\"\n      :percentage=\"percentage\"\n      indicator-placement=\"inside\"\n    />\n    <n-space>\n      <n-button @click=\"minus\">\n        Minus 10%\n      </n-button>\n      <n-button @click=\"add\">\n        Add 10%\n      </n-button>\n    </n-space>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/progress/demos/enUS/multiple-circle.demo.vue",
    "content": "<markdown>\n# Multiple circle\n\nMaybe your product manager will need it.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst percentage = ref(0)\n\nfunction add() {\n  percentage.value += 10\n  if (percentage.value > 100) {\n    percentage.value = 0\n  }\n}\n\nfunction minus() {\n  percentage.value -= 10\n  if (percentage.value < 0) {\n    percentage.value = 100\n  }\n}\n</script>\n\n<template>\n  <n-space vertical>\n    <n-el>\n      <n-progress\n        type=\"multiple-circle\"\n        :stroke-width=\"6\"\n        :circle-gap=\"0.5\"\n        :percentage=\"[\n          percentage,\n          (percentage + 10) % 100,\n          (percentage + 20) % 100,\n          (percentage + 30) % 100,\n        ]\"\n        :color=\"[\n          'var(--info-color)',\n          'var(--success-color)',\n          'var(--warning-color)',\n          'var(--error-color)',\n        ]\"\n        :rail-style=\"[\n          { stroke: 'var(--info-color)', opacity: 0.3 },\n          { stroke: 'var(--success-color)', opacity: 0.3 },\n          { stroke: 'var(--warning-color)', opacity: 0.3 },\n          { stroke: 'var(--error-color)', opacity: 0.3 },\n        ]\"\n      >\n        <div style=\"text-align: center\">\n          Circle racing!\n        </div>\n      </n-progress>\n    </n-el>\n    <n-space>\n      <n-button @click=\"minus\">\n        Minus 10%\n      </n-button>\n      <n-button @click=\"add\">\n        Add 10%\n      </n-button>\n    </n-space>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/progress/demos/enUS/no-indicator.demo.vue",
    "content": "<markdown>\n# No indicator\n\nIf you don't want indicator.\n</markdown>\n\n<template>\n  <n-progress\n    style=\"margin: 0 8px 12px 0\"\n    type=\"circle\"\n    :show-indicator=\"false\"\n    status=\"success\"\n    :percentage=\"20\"\n  />\n  <n-progress\n    style=\"width: 120px; margin: 0 8px 12px 0\"\n    type=\"multiple-circle\"\n    :percentage=\"[50, 25]\"\n    :show-indicator=\"false\"\n  />\n  <n-progress\n    type=\"line\"\n    :show-indicator=\"false\"\n    status=\"success\"\n    :percentage=\"20\"\n  />\n</template>\n"
  },
  {
    "path": "src/progress/demos/enUS/processing.demo.vue",
    "content": "<markdown>\n# Processing\n</markdown>\n\n<template>\n  <n-progress\n    type=\"line\"\n    :percentage=\"60\"\n    indicator-placement=\"inside\"\n    processing\n  />\n</template>\n"
  },
  {
    "path": "src/progress/demos/zhCN/circle-offset.demo.vue",
    "content": "<markdown>\n# 偏移\n\n环状的进度可以偏移。\n</markdown>\n\n<template>\n  <n-progress type=\"circle\" :percentage=\"80\" :offset-degree=\"120\" />\n</template>\n"
  },
  {
    "path": "src/progress/demos/zhCN/circle.demo.vue",
    "content": "<markdown>\n# 圈\n\n进度可以是个圈，它支持 `default`、`info`、`success`、`warning` 和 `error` 的 `status`。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst percentage = ref(0)\n\nfunction add() {\n  percentage.value += 10\n  if (percentage.value > 100) {\n    percentage.value = 0\n  }\n}\n\nfunction minus() {\n  percentage.value -= 10\n  if (percentage.value < 0) {\n    percentage.value = 100\n  }\n}\n</script>\n\n<template>\n  <n-space vertical>\n    <n-space>\n      <n-progress type=\"circle\" :percentage=\"percentage\" />\n      <n-progress type=\"circle\" status=\"info\" :percentage=\"percentage\" />\n      <n-progress type=\"circle\" status=\"success\" :percentage=\"percentage\" />\n      <n-progress type=\"circle\" status=\"warning\" :percentage=\"percentage\" />\n      <n-progress type=\"circle\" status=\"error\" :percentage=\"percentage\" />\n    </n-space>\n    <n-space>\n      <n-button @click=\"minus\">\n        减 10%\n      </n-button>\n      <n-button @click=\"add\">\n        加 10%\n      </n-button>\n    </n-space>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/progress/demos/zhCN/color.demo.vue",
    "content": "<markdown>\n# 自定义颜色\n\n如果你觉得内置的颜色不行 🙅‍♂️。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { useThemeVars } from 'naive-ui'\nimport { changeColor } from 'seemly'\n\nconst themeVars = useThemeVars()\n</script>\n\n<template>\n  <n-progress\n    style=\"margin: 0 8px 12px 0\"\n    type=\"circle\"\n    :percentage=\"20\"\n    :color=\"themeVars.successColor\"\n    :rail-color=\"changeColor(themeVars.successColor, { alpha: 0.2 })\"\n    :indicator-text-color=\"themeVars.successColor\"\n  />\n  <n-progress\n    style=\"width: 120px; margin: 0 8px 12px 0\"\n    type=\"multiple-circle\"\n    :stroke-width=\"10\"\n    :circle-gap=\"10\"\n    :percentage=\"[50, 25]\"\n    :color=\"[themeVars.infoColor, themeVars.infoColor]\"\n    :rail-color=\"[\n      changeColor(themeVars.infoColor, { alpha: 0.2 }),\n      changeColor(themeVars.infoColor, { alpha: 0.2 }),\n    ]\"\n  />\n  <n-progress\n    type=\"line\"\n    indicator-placement=\"inside\"\n    :color=\"themeVars.errorColor\"\n    :rail-color=\"changeColor(themeVars.errorColor, { alpha: 0.2 })\"\n    :percentage=\"20\"\n  />\n  <n-progress\n    type=\"line\"\n    :color=\"themeVars.warningColor\"\n    :rail-color=\"changeColor(themeVars.warningColor, { alpha: 0.2 })\"\n    :percentage=\"20\"\n    :indicator-text-color=\"themeVars.warningColor\"\n  />\n</template>\n"
  },
  {
    "path": "src/progress/demos/zhCN/custom-indicator.demo.vue",
    "content": "<markdown>\n# 自定义指示标\n\n你可以自定义指示标内容。\n</markdown>\n\n<template>\n  <n-progress type=\"circle\" :percentage=\"20\">\n    <span style=\"text-align: center\">20% 很小</span>\n  </n-progress>\n  <n-progress type=\"line\" status=\"success\" :percentage=\"20\">\n    别在这里写太长的内容，不然线会很短\n  </n-progress>\n</template>\n"
  },
  {
    "path": "src/progress/demos/zhCN/dashboard.demo.vue",
    "content": "<markdown>\n# 仪表盘\n\n可能你还需要`gap-degree` 和 `gap-offset-degree` 两个属性来自定义仪表盘。\n</markdown>\n\n<template>\n  <n-space>\n    <n-progress type=\"dashboard\" gap-position=\"bottom\" :percentage=\"80\" />\n    <n-progress\n      type=\"dashboard\"\n      :gap-offset-degree=\"120\"\n      :gap-degree=\"120\"\n      :percentage=\"80\"\n    />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/progress/demos/zhCN/gradient.demo.vue",
    "content": "<markdown>\n# 渐变色\n\n你或许想要不用颜色的组合。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { useThemeVars } from 'naive-ui'\nimport { changeColor } from 'seemly'\nimport { ref } from 'vue'\n\nconst percentage = ref(80)\nconst themeVars = useThemeVars()\n</script>\n\n<template>\n  <n-flex vertical>\n    <n-progress\n      type=\"line\"\n      :percentage=\"percentage\"\n      :show-indicator=\"false\"\n      :color=\"{ stops: ['white', 'pink'] }\"\n    />\n    <n-flex>\n      <n-progress\n        type=\"circle\"\n        :percentage=\"percentage\"\n        :color=\"{ stops: ['#E3F2FD', '#2080f0'] }\"\n      />\n      <n-progress\n        style=\"width: 120px; margin: 0 8px 12px 0\"\n        type=\"multiple-circle\"\n        :stroke-width=\"10\"\n        :circle-gap=\"10\"\n        :percentage=\"[80, 70]\"\n        :color=\"[\n          { stops: ['white', '#18a058'] },\n          { stops: ['#E3F2FD', '#2080f0'] },\n        ]\"\n        :rail-color=\"[\n          changeColor(themeVars.infoColor, { alpha: 0.2 }),\n          changeColor(themeVars.infoColor, { alpha: 0.2 }),\n        ]\"\n      />\n    </n-flex>\n  </n-flex>\n</template>\n"
  },
  {
    "path": "src/progress/demos/zhCN/height.demo.vue",
    "content": "<markdown>\n# 高度 & 圆角\n\n如果你对高度和圆角不满意。\n</markdown>\n\n<template>\n  <n-space vertical>\n    <n-progress\n      type=\"line\"\n      :percentage=\"50\"\n      :height=\"24\"\n      :border-radius=\"4\"\n      :fill-border-radius=\"0\"\n    />\n    <n-progress\n      type=\"line\"\n      status=\"error\"\n      :percentage=\"50\"\n      :height=\"24\"\n      border-radius=\"12px 12px 0 0\"\n      fill-border-radius=\"12px 0 12px 12px\"\n    >\n      一种艺术\n    </n-progress>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/progress/demos/zhCN/index.demo-entry.md",
    "content": "# 进度 Progress\n\n不知道说点啥，但是还是得写点东西，让这个页面看起来舒展一点。\n\n## 演示\n\n```demo\ncircle.vue\nline.vue\ncircle-offset.vue\nmultiple-circle.vue\ndashboard.vue\ncustom-indicator.vue\ncolor.vue\nno-indicator.vue\nheight.vue\nprocessing.vue\ngradient.vue\n```\n\n## API\n\n### Progress Props\n\n| 名称 | 类型 | 默认值 | 说明 | 版本 |\n| --- | --- | --- | --- | --- |\n| border-radius | `number \\| string` | `undefined` | `'line'` 类型进度条的圆角半径，不填写则维持高度的一半 |  |\n| circle-gap | `number` | `1` | 当类型是 `'multiple-circle'` 的时候圈之间的距离，假设 `viewbox` 的尺寸是 `100` |  |\n| color | `string \\| string[] \\| { stops: string[] } \\| Array<{ stops: string[] }>` | `undefined` | 进度条颜色，`{ stops: string[] }` 表示渐变色，`stops` 数组长度必须为 2，第一个元素为渐变的起始颜色，第二个元素为渐变的终止颜色 | 2.40.2 开始支持 `stops` |\n| fill-border-radius | `number \\| string` | `undefined` | `'line'` 类型进度条填充的圆角半径，不填写则维持 `border-radius` |  |\n| gap-degree | `number` | `75` | 仪表盘进度条缺口角度，取值范围 0 ~ 360 | 2.25.2 |\n| gap-offset-degree | `number` | `0` | 仪表盘进度条缺口位置 | 2.25.2 |\n| height | `number` | `undefined` | `'line'` 类型进度条的高度，不填写则维持默认高度 |  |\n| indicator-placement | `'inside' \\| 'outside'` | `'outside'` | `'line'` 类型设置指示标位置 |  |\n| indicator-text-color | `string` | `undefined` | 指示标文本颜色 |  |\n| offset-degree | `number` | `0` | 进度的偏移角度，只对 `'circle'` 类型生效 | 2.24.0 |\n| percentage | `number \\| number[]` | `0` | 百分比的值 |  |\n| processing | `boolean` | `false` | 处理中状态 |  |\n| rail-color | `string \\| string[]` | `undefined` | 轨道的颜色 |  |\n| rail-style | `string \\| CSS \\| Array<string \\| CSS>` | `undefined` | 轨道的对象 |  |\n| show-indicator | `boolean` | `true` | 是否显示指示标 |  |\n| status | `'default' \\| 'success' \\| 'error' \\| 'warning' \\| 'info'` | `'default'` | 进度条状态 |  |\n| stroke-width | `number` | `7` | 进度条宽度 |  |\n| type | `'line' \\| 'circle' \\| 'multiple-circle' \\| 'dashboard'` | `'line'` | 进度条类型 | `'dashboard'` 2.25.2 |\n| unit | `string` | `%` | 进度条单位 |  |\n\n### Progress Slots\n\n| 名称    | 参数 | 说明           |\n| ------- | ---- | -------------- |\n| default | `()` | 指示标里的内容 |\n"
  },
  {
    "path": "src/progress/demos/zhCN/line.demo.vue",
    "content": "<markdown>\n# 线型\n\n事实上线型的进度条不需要这么多种样子，但是既然 UI 画了，我也就实现了。它支持 `default`、`info`、`success`、`warning` 和 `error` 的 `status`。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst percentage = ref(0)\n\nfunction add() {\n  percentage.value += 10\n  if (percentage.value > 100) {\n    percentage.value = 0\n  }\n}\n\nfunction minus() {\n  percentage.value -= 10\n  if (percentage.value < 0) {\n    percentage.value = 100\n  }\n}\n</script>\n\n<template>\n  <n-space vertical>\n    <n-progress type=\"line\" :percentage=\"percentage\" :show-indicator=\"false\" />\n    <n-progress type=\"line\" :percentage=\"percentage\" />\n    <n-progress\n      type=\"line\"\n      :percentage=\"percentage\"\n      indicator-placement=\"inside\"\n    />\n    <n-progress\n      type=\"line\"\n      status=\"info\"\n      :percentage=\"percentage\"\n      :show-indicator=\"false\"\n    />\n    <n-progress type=\"line\" status=\"info\" :percentage=\"percentage\" />\n    <n-progress\n      type=\"line\"\n      status=\"info\"\n      :percentage=\"percentage\"\n      indicator-placement=\"inside\"\n    />\n    <n-progress\n      type=\"line\"\n      status=\"success\"\n      :percentage=\"percentage\"\n      :show-indicator=\"false\"\n    />\n    <n-progress type=\"line\" status=\"success\" :percentage=\"percentage\" />\n    <n-progress\n      type=\"line\"\n      status=\"success\"\n      :percentage=\"percentage\"\n      indicator-placement=\"inside\"\n    />\n    <n-progress\n      type=\"line\"\n      status=\"warning\"\n      :percentage=\"percentage\"\n      :show-indicator=\"false\"\n    />\n    <n-progress type=\"line\" status=\"warning\" :percentage=\"percentage\" />\n    <n-progress\n      type=\"line\"\n      status=\"warning\"\n      :percentage=\"percentage\"\n      indicator-placement=\"inside\"\n    />\n    <n-progress\n      type=\"line\"\n      status=\"error\"\n      :percentage=\"percentage\"\n      :show-indicator=\"false\"\n    />\n    <n-progress type=\"line\" status=\"error\" :percentage=\"percentage\" />\n    <n-progress\n      type=\"line\"\n      status=\"error\"\n      :percentage=\"percentage\"\n      indicator-placement=\"inside\"\n    />\n    <n-space>\n      <n-button @click=\"minus\">\n        减 10%\n      </n-button>\n      <n-button @click=\"add\">\n        加 10%\n      </n-button>\n    </n-space>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/progress/demos/zhCN/multiple-circle.demo.vue",
    "content": "<markdown>\n# 好几个圈\n\n或许你们的产品经理想要这种效果。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst percentage = ref(0)\n\nfunction add() {\n  percentage.value += 10\n  if (percentage.value > 100) {\n    percentage.value = 0\n  }\n}\n\nfunction minus() {\n  percentage.value -= 10\n  if (percentage.value < 0) {\n    percentage.value = 100\n  }\n}\n</script>\n\n<template>\n  <n-space vertical>\n    <n-el>\n      <n-progress\n        type=\"multiple-circle\"\n        :stroke-width=\"6\"\n        :circle-gap=\"0.5\"\n        :percentage=\"[\n          percentage,\n          (percentage + 10) % 100,\n          (percentage + 20) % 100,\n          (percentage + 30) % 100,\n        ]\"\n        :color=\"[\n          'var(--info-color)',\n          'var(--success-color)',\n          'var(--warning-color)',\n          'var(--error-color)',\n        ]\"\n        :rail-style=\"[\n          { stroke: 'var(--info-color)', opacity: 0.3 },\n          { stroke: 'var(--success-color)', opacity: 0.3 },\n          { stroke: 'var(--warning-color)', opacity: 0.3 },\n          { stroke: 'var(--error-color)', opacity: 0.3 },\n        ]\"\n      >\n        <div style=\"text-align: center\">\n          圈圈赛跑！\n        </div>\n      </n-progress>\n    </n-el>\n    <n-space>\n      <n-button @click=\"minus\">\n        减 10%\n      </n-button>\n      <n-button @click=\"add\">\n        加 10%\n      </n-button>\n    </n-space>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/progress/demos/zhCN/no-indicator.demo.vue",
    "content": "<markdown>\n# 不要指示标\n\n不要也可以。\n</markdown>\n\n<template>\n  <n-progress\n    style=\"margin: 0 8px 12px 0\"\n    type=\"circle\"\n    :show-indicator=\"false\"\n    status=\"success\"\n    :percentage=\"20\"\n  />\n  <n-progress\n    style=\"width: 120px; margin: 0 8px 12px 0\"\n    type=\"multiple-circle\"\n    :percentage=\"[50, 25]\"\n    :show-indicator=\"false\"\n  />\n  <n-progress\n    type=\"line\"\n    :show-indicator=\"false\"\n    status=\"success\"\n    :percentage=\"20\"\n  />\n</template>\n"
  },
  {
    "path": "src/progress/demos/zhCN/processing.demo.vue",
    "content": "<markdown>\n# 进行时\n</markdown>\n\n<template>\n  <n-progress\n    type=\"line\"\n    :percentage=\"60\"\n    indicator-placement=\"inside\"\n    processing\n  />\n</template>\n"
  },
  {
    "path": "src/progress/index.ts",
    "content": "export { default as NProgress, progressProps } from './src/Progress'\nexport type { ProgressProps } from './src/Progress'\nexport type * from './src/public-types'\n"
  },
  {
    "path": "src/progress/src/Circle.tsx",
    "content": "import type { CSSProperties, PropType } from 'vue'\nimport type { ProgressGradient, ProgressStatus } from './public-types'\nimport { hash } from 'css-render'\nimport { computed, defineComponent, h } from 'vue'\nimport { NBaseIcon } from '../../_internal'\nimport {\n  ErrorIcon,\n  InfoIcon,\n  SuccessIcon,\n  WarningIcon\n} from '../../_internal/icons'\n\nconst iconMap = {\n  success: <SuccessIcon />,\n  error: <ErrorIcon />,\n  warning: <WarningIcon />,\n  info: <InfoIcon />\n}\n\nexport default defineComponent({\n  name: 'ProgressCircle',\n  props: {\n    clsPrefix: {\n      type: String,\n      required: true\n    },\n    status: {\n      type: String as PropType<ProgressStatus>,\n      required: true\n    },\n    strokeWidth: {\n      type: Number,\n      required: true\n    },\n    fillColor: [String, Object] as PropType<string | ProgressGradient>,\n    railColor: String,\n    railStyle: [String, Object] as PropType<string | CSSProperties>,\n    percentage: {\n      type: Number,\n      default: 0\n    },\n    offsetDegree: {\n      type: Number,\n      default: 0\n    },\n    showIndicator: {\n      type: Boolean,\n      required: true\n    },\n    indicatorTextColor: String,\n    unit: String,\n    viewBoxWidth: {\n      type: Number,\n      required: true\n    },\n    gapDegree: {\n      type: Number as PropType<number>,\n      required: true\n    },\n    gapOffsetDegree: {\n      type: Number,\n      default: 0\n    }\n  },\n  setup(props, { slots }) {\n    const gradientIdRef = computed(() => {\n      const base = 'gradient'\n      const { fillColor } = props\n      if (typeof fillColor === 'object') {\n        return `${base}-${hash(JSON.stringify(fillColor))}`\n      }\n      return base\n    })\n    function getPathStyles(\n      percent: number,\n      offsetDegree: number,\n      strokeColor?: string | ProgressGradient,\n      type?: 'rail' | 'fill'\n    ): { pathString: string, pathStyle: CSSProperties } {\n      const { gapDegree, viewBoxWidth, strokeWidth } = props\n      const radius = 50\n      const beginPositionX = 0\n      const beginPositionY = radius\n      const endPositionX = 0\n      const endPositionY = 2 * radius\n      const centerX = 50 + strokeWidth / 2\n      const pathString = `M ${centerX},${centerX} m ${beginPositionX},${beginPositionY}\n      a ${radius},${radius} 0 1 1 ${endPositionX},${-endPositionY}\n      a ${radius},${radius} 0 1 1 ${-endPositionX},${endPositionY}`\n      const len = Math.PI * 2 * radius\n      const pathStyle: CSSProperties = {\n        stroke:\n          type === 'rail'\n            ? (strokeColor as string)\n            : typeof props.fillColor === 'object'\n              ? `url(#${gradientIdRef.value})`\n              : (strokeColor as string),\n        strokeDasharray: `${(Math.min(percent, 100) / 100) * (len - gapDegree)}px ${\n          viewBoxWidth * 8\n        }px`,\n        strokeDashoffset: `-${gapDegree / 2}px`,\n        transformOrigin: offsetDegree ? 'center' : undefined,\n        transform: offsetDegree ? `rotate(${offsetDegree}deg)` : undefined\n      }\n      return {\n        pathString,\n        pathStyle\n      }\n    }\n\n    const createGradientNode = (): false | JSX.Element => {\n      const isGradient = typeof props.fillColor === 'object'\n      const from = isGradient ? props.fillColor.stops[0] : ''\n      const to = isGradient ? props.fillColor.stops[1] : ''\n      return (\n        isGradient && (\n          <defs>\n            <linearGradient\n              id={gradientIdRef.value}\n              x1=\"0%\"\n              y1=\"100%\"\n              x2=\"100%\"\n              y2=\"0%\"\n            >\n              <stop offset=\"0%\" stop-color={from} />\n              <stop offset=\"100%\" stop-color={to} />\n            </linearGradient>\n          </defs>\n        )\n      )\n    }\n\n    return () => {\n      const {\n        fillColor,\n        railColor,\n        strokeWidth,\n        offsetDegree,\n        status,\n        percentage,\n        showIndicator,\n        indicatorTextColor,\n        unit,\n        gapOffsetDegree,\n        clsPrefix\n      } = props\n      const { pathString: railPathString, pathStyle: railPathStyle }\n        = getPathStyles(100, 0, railColor, 'rail')\n      const { pathString: fillPathString, pathStyle: fillPathStyle }\n        = getPathStyles(percentage, offsetDegree, fillColor, 'fill')\n      const viewBoxSize = 100 + strokeWidth\n      return (\n        <div class={`${clsPrefix}-progress-content`} role=\"none\">\n          <div class={`${clsPrefix}-progress-graph`} aria-hidden>\n            <div\n              class={`${clsPrefix}-progress-graph-circle`}\n              style={{\n                transform: gapOffsetDegree\n                  ? `rotate(${gapOffsetDegree}deg)`\n                  : undefined\n              }}\n            >\n              <svg viewBox={`0 0 ${viewBoxSize} ${viewBoxSize}`}>\n                {createGradientNode()}\n                <g>\n                  <path\n                    class={`${clsPrefix}-progress-graph-circle-rail`}\n                    d={railPathString}\n                    stroke-width={strokeWidth}\n                    stroke-linecap=\"round\"\n                    fill=\"none\"\n                    style={railPathStyle}\n                  />\n                </g>\n                <g>\n                  <path\n                    class={[\n                      `${clsPrefix}-progress-graph-circle-fill`,\n                      percentage === 0\n                      && `${clsPrefix}-progress-graph-circle-fill--empty`\n                    ]}\n                    d={fillPathString}\n                    stroke-width={strokeWidth}\n                    stroke-linecap=\"round\"\n                    fill=\"none\"\n                    style={fillPathStyle}\n                  />\n                </g>\n              </svg>\n            </div>\n          </div>\n          {showIndicator ? (\n            <div>\n              {slots.default ? (\n                <div class={`${clsPrefix}-progress-custom-content`} role=\"none\">\n                  {slots.default()}\n                </div>\n              ) : status !== 'default' ? (\n                <div class={`${clsPrefix}-progress-icon`} aria-hidden>\n                  <NBaseIcon clsPrefix={clsPrefix}>\n                    {{\n                      default: () => iconMap[status]\n                    }}\n                  </NBaseIcon>\n                </div>\n              ) : (\n                <div\n                  class={`${clsPrefix}-progress-text`}\n                  style={{\n                    color: indicatorTextColor\n                  }}\n                  role=\"none\"\n                >\n                  <span class={`${clsPrefix}-progress-text__percentage`}>\n                    {percentage}\n                  </span>\n                  <span class={`${clsPrefix}-progress-text__unit`}>{unit}</span>\n                </div>\n              )}\n            </div>\n          ) : null}\n        </div>\n      )\n    }\n  }\n})\n"
  },
  {
    "path": "src/progress/src/Line.tsx",
    "content": "import type { CSSProperties, PropType } from 'vue'\nimport type { ProgressGradient, ProgressStatus } from './public-types'\nimport { computed, defineComponent, h } from 'vue'\nimport { NBaseIcon } from '../../_internal'\nimport {\n  ErrorIcon as ErrorCircleIcon,\n  InfoIcon as InfoCircleIcon,\n  SuccessIcon as SuccessCircleIcon,\n  WarningIcon\n} from '../../_internal/icons'\nimport { formatLength } from '../../_utils'\n\nconst iconMap = {\n  success: <SuccessCircleIcon />,\n  error: <ErrorCircleIcon />,\n  warning: <WarningIcon />,\n  info: <InfoCircleIcon />\n}\n\nexport default defineComponent({\n  name: 'ProgressLine',\n  props: {\n    clsPrefix: {\n      type: String,\n      required: true\n    },\n    percentage: {\n      type: Number,\n      default: 0\n    },\n    railColor: String,\n    railStyle: [String, Object] as PropType<string | CSSProperties>,\n    fillColor: [String, Object] as PropType<string | ProgressGradient>,\n    status: {\n      type: String as PropType<ProgressStatus>,\n      required: true\n    },\n    indicatorPlacement: {\n      type: String as PropType<'inside' | 'outside'>,\n      required: true\n    },\n    indicatorTextColor: String,\n    unit: {\n      type: String,\n      default: '%'\n    },\n    processing: {\n      type: Boolean,\n      required: true\n    },\n    showIndicator: {\n      type: Boolean,\n      required: true\n    },\n    height: [String, Number],\n    railBorderRadius: [String, Number],\n    fillBorderRadius: [String, Number]\n  },\n  setup(props, { slots }) {\n    const styleHeightRef = computed(() => {\n      return formatLength(props.height)\n    })\n    const styleFillColorRef = computed(() => {\n      return typeof props.fillColor === 'object'\n        ? `linear-gradient(to right, ${props.fillColor?.stops[0]} , ${props.fillColor?.stops[1]})`\n        : props.fillColor\n    })\n    const styleRailBorderRadiusRef = computed(() => {\n      if (props.railBorderRadius !== undefined) {\n        return formatLength(props.railBorderRadius)\n      }\n      if (props.height !== undefined) {\n        return formatLength(props.height, { c: 0.5 })\n      }\n      return ''\n    })\n    const styleFillBorderRadiusRef = computed(() => {\n      if (props.fillBorderRadius !== undefined) {\n        return formatLength(props.fillBorderRadius)\n      }\n      if (props.railBorderRadius !== undefined) {\n        return formatLength(props.railBorderRadius)\n      }\n      if (props.height !== undefined) {\n        return formatLength(props.height, { c: 0.5 })\n      }\n      return ''\n    })\n    return () => {\n      const {\n        indicatorPlacement,\n        railColor,\n        railStyle,\n        percentage,\n        unit,\n        indicatorTextColor,\n        status,\n        showIndicator,\n        processing,\n        clsPrefix\n      } = props\n      return (\n        <div class={`${clsPrefix}-progress-content`} role=\"none\">\n          <div class={`${clsPrefix}-progress-graph`} aria-hidden>\n            <div\n              class={[\n                `${clsPrefix}-progress-graph-line`,\n                {\n                  [`${clsPrefix}-progress-graph-line--indicator-${indicatorPlacement}`]: true\n                }\n              ]}\n            >\n              <div\n                class={`${clsPrefix}-progress-graph-line-rail`}\n                style={\n                  [\n                    {\n                      backgroundColor: railColor,\n                      height: styleHeightRef.value,\n                      borderRadius: styleRailBorderRadiusRef.value\n                    },\n                    railStyle\n                  ] as any\n                }\n              >\n                <div\n                  class={[\n                    `${clsPrefix}-progress-graph-line-fill`,\n                    processing\n                    && `${clsPrefix}-progress-graph-line-fill--processing`\n                  ]}\n                  style={{\n                    maxWidth: `${props.percentage}%`,\n                    background: styleFillColorRef.value,\n                    height: styleHeightRef.value,\n                    lineHeight: styleHeightRef.value,\n                    borderRadius: styleFillBorderRadiusRef.value\n                  }}\n                >\n                  {indicatorPlacement === 'inside' ? (\n                    <div\n                      class={`${clsPrefix}-progress-graph-line-indicator`}\n                      style={{\n                        color: indicatorTextColor\n                      }}\n                    >\n                      {slots.default ? slots.default() : `${percentage}${unit}`}\n                    </div>\n                  ) : null}\n                </div>\n              </div>\n            </div>\n          </div>\n          {showIndicator && indicatorPlacement === 'outside' ? (\n            <div>\n              {slots.default ? (\n                <div\n                  class={`${clsPrefix}-progress-custom-content`}\n                  style={{\n                    color: indicatorTextColor\n                  }}\n                  role=\"none\"\n                >\n                  {slots.default()}\n                </div>\n              ) : status === 'default' ? (\n                <div\n                  role=\"none\"\n                  class={`${clsPrefix}-progress-icon ${clsPrefix}-progress-icon--as-text`}\n                  style={{\n                    color: indicatorTextColor\n                  }}\n                >\n                  {percentage}\n                  {unit}\n                </div>\n              ) : (\n                <div class={`${clsPrefix}-progress-icon`} aria-hidden>\n                  <NBaseIcon clsPrefix={clsPrefix}>\n                    {{ default: () => iconMap[status] }}\n                  </NBaseIcon>\n                </div>\n              )}\n            </div>\n          ) : null}\n        </div>\n      )\n    }\n  }\n})\n"
  },
  {
    "path": "src/progress/src/MultipleCircle.tsx",
    "content": "import type { CSSProperties, PropType } from 'vue'\nimport type { ProgressGradient } from './public-types'\nimport { computed, defineComponent, h } from 'vue'\n\nfunction circlePath(r: number, sw: number, vw: number = 100): string {\n  return `m ${vw / 2} ${vw / 2 - r} a ${r} ${r} 0 1 1 0 ${\n    2 * r\n  } a ${r} ${r} 0 1 1 0 -${2 * r}`\n}\n\nexport default defineComponent({\n  name: 'ProgressMultipleCircle',\n  props: {\n    clsPrefix: {\n      type: String,\n      required: true\n    },\n    viewBoxWidth: {\n      type: Number,\n      required: true\n    },\n    percentage: {\n      type: Array as PropType<number[]>,\n      default: [0]\n    },\n    strokeWidth: {\n      type: Number,\n      required: true\n    },\n    circleGap: {\n      type: Number,\n      required: true\n    },\n    showIndicator: {\n      type: Boolean,\n      required: true\n    },\n    fillColor: {\n      type: Array as PropType<string[] | ProgressGradient[]>,\n      default: () => []\n    },\n    railColor: {\n      type: Array as PropType<string[]>,\n      default: () => []\n    },\n    railStyle: {\n      type: Array as PropType<Array<string | CSSProperties>>,\n      default: () => []\n    }\n  },\n  setup(props, { slots }) {\n    const strokeDasharrayRef = computed(() => {\n      const strokeDasharrays = props.percentage.map(\n        (v, i) =>\n          `${\n            ((Math.PI * v) / 100)\n            * (props.viewBoxWidth / 2\n              - (props.strokeWidth / 2) * (1 + 2 * i)\n              - props.circleGap * i)\n            * 2\n          }, ${props.viewBoxWidth * 8}`\n      )\n      return strokeDasharrays\n    })\n\n    const createGradientNode = (\n      p: number,\n      index: number\n    ): false | JSX.Element => {\n      const item = props.fillColor[index]\n      const form = typeof item === 'object' ? item.stops[0] : ''\n      const to = typeof item === 'object' ? item.stops[1] : ''\n      return (\n        typeof props.fillColor[index] === 'object' && (\n          <linearGradient\n            id={`gradient-${index}`}\n            x1=\"100%\"\n            y1=\"0%\"\n            x2=\"0%\"\n            y2=\"100%\"\n          >\n            <stop offset=\"0%\" stop-color={form} />\n            <stop offset=\"100%\" stop-color={to} />\n          </linearGradient>\n        )\n      )\n    }\n\n    return () => {\n      const {\n        viewBoxWidth,\n        strokeWidth,\n        circleGap,\n        showIndicator,\n        fillColor,\n        railColor,\n        railStyle,\n        percentage,\n        clsPrefix\n      } = props\n      return (\n        <div class={`${clsPrefix}-progress-content`} role=\"none\">\n          <div class={`${clsPrefix}-progress-graph`} aria-hidden>\n            <div class={`${clsPrefix}-progress-graph-circle`}>\n              <svg viewBox={`0 0 ${viewBoxWidth} ${viewBoxWidth}`}>\n                <defs>\n                  {percentage.map((p, index) => {\n                    return createGradientNode(p, index)\n                  })}\n                </defs>\n                {percentage.map((p, index) => {\n                  return (\n                    <g key={index}>\n                      <path\n                        class={`${clsPrefix}-progress-graph-circle-rail`}\n                        d={circlePath(\n                          viewBoxWidth / 2\n                          - (strokeWidth / 2) * (1 + 2 * index)\n                          - circleGap * index,\n                          strokeWidth,\n                          viewBoxWidth\n                        )}\n                        stroke-width={strokeWidth}\n                        stroke-linecap=\"round\"\n                        fill=\"none\"\n                        style={\n                          [\n                            {\n                              strokeDashoffset: 0,\n                              stroke: railColor[index]\n                            },\n                            railStyle[index]\n                          ] as any\n                        }\n                      />\n                      <path\n                        class={[\n                          `${clsPrefix}-progress-graph-circle-fill`,\n                          p === 0\n                          && `${clsPrefix}-progress-graph-circle-fill--empty`\n                        ]}\n                        d={circlePath(\n                          viewBoxWidth / 2\n                          - (strokeWidth / 2) * (1 + 2 * index)\n                          - circleGap * index,\n                          strokeWidth,\n                          viewBoxWidth\n                        )}\n                        stroke-width={strokeWidth}\n                        stroke-linecap=\"round\"\n                        fill=\"none\"\n                        style={{\n                          strokeDasharray: strokeDasharrayRef.value[index],\n                          strokeDashoffset: 0,\n                          stroke:\n                            typeof fillColor[index] === 'object'\n                              ? `url(#gradient-${index})`\n                              : fillColor[index]\n                        }}\n                      />\n                    </g>\n                  )\n                })}\n              </svg>\n            </div>\n          </div>\n          {showIndicator && slots.default ? (\n            <div>\n              <div class={`${clsPrefix}-progress-text`}>{slots.default()}</div>\n            </div>\n          ) : null}\n        </div>\n      )\n    }\n  }\n})\n"
  },
  {
    "path": "src/progress/src/Progress.tsx",
    "content": "import type { CSSProperties, PropType } from 'vue'\nimport type { ThemeProps } from '../../_mixins'\nimport type { ExtractPublicPropTypes } from '../../_utils'\nimport type { ProgressTheme } from '../styles'\nimport type { ProgressGradient, ProgressStatus } from './public-types'\nimport { computed, defineComponent, h } from 'vue'\nimport { useConfig, useTheme, useThemeClass } from '../../_mixins'\nimport { createKey } from '../../_utils'\nimport { progressLight } from '../styles'\nimport Circle from './Circle'\nimport Line from './Line'\nimport MultipleCircle from './MultipleCircle'\nimport style from './styles/index.cssr'\n\nexport const progressProps = {\n  ...(useTheme.props as ThemeProps<ProgressTheme>),\n  processing: Boolean,\n  type: {\n    type: String as PropType<\n      'line' | 'circle' | 'multiple-circle' | 'dashboard'\n    >,\n    default: 'line'\n  },\n  gapDegree: Number,\n  gapOffsetDegree: Number,\n  status: {\n    type: String as PropType<ProgressStatus>,\n    default: 'default'\n  },\n  railColor: [String, Array] as PropType<string | string[]>,\n  railStyle: [String, Array] as PropType<\n    string | CSSProperties | Array<string | CSSProperties>\n  >,\n  color: [String, Array, Object] as PropType<\n    string | string[] | ProgressGradient | ProgressGradient[]\n  >,\n  viewBoxWidth: {\n    type: Number,\n    default: 100\n  },\n  strokeWidth: {\n    type: Number,\n    default: 7\n  },\n  percentage: [Number, Array] as PropType<number | number[]>,\n  unit: {\n    type: String,\n    default: '%'\n  },\n  showIndicator: {\n    type: Boolean,\n    default: true\n  },\n  indicatorPosition: {\n    type: String as PropType<'inside' | 'outside'>,\n    default: 'outside'\n  },\n  indicatorPlacement: {\n    type: String as PropType<'inside' | 'outside'>,\n    default: 'outside'\n  },\n  indicatorTextColor: String,\n  circleGap: {\n    type: Number,\n    default: 1\n  },\n  height: Number,\n  borderRadius: [String, Number] as PropType<string | number>,\n  fillBorderRadius: [String, Number] as PropType<string | number>,\n  offsetDegree: Number\n} as const\n\nexport type ProgressProps = ExtractPublicPropTypes<typeof progressProps>\n\nexport default defineComponent({\n  name: 'Progress',\n  props: progressProps,\n  setup(props) {\n    const mergedIndicatorPlacementRef = computed(() => {\n      return props.indicatorPlacement || props.indicatorPosition\n    })\n    const gapDeg = computed(() => {\n      if (props.gapDegree || props.gapDegree === 0) {\n        return props.gapDegree\n      }\n      if (props.type === 'dashboard') {\n        return 75\n      }\n      return undefined\n    })\n    const { mergedClsPrefixRef, inlineThemeDisabled } = useConfig(props)\n    const themeRef = useTheme(\n      'Progress',\n      '-progress',\n      style,\n      progressLight,\n      props,\n      mergedClsPrefixRef\n    )\n    const cssVarsRef = computed(() => {\n      const { status } = props\n      const {\n        common: { cubicBezierEaseInOut },\n        self: {\n          fontSize,\n          fontSizeCircle,\n          railColor,\n          railHeight,\n          iconSizeCircle,\n          iconSizeLine,\n          textColorCircle,\n          textColorLineInner,\n          textColorLineOuter,\n          lineBgProcessing,\n          fontWeightCircle,\n          [createKey('iconColor', status)]: iconColor,\n          [createKey('fillColor', status)]: fillColor\n        }\n      } = themeRef.value\n      return {\n        '--n-bezier': cubicBezierEaseInOut,\n        '--n-fill-color': fillColor,\n        '--n-font-size': fontSize,\n        '--n-font-size-circle': fontSizeCircle,\n        '--n-font-weight-circle': fontWeightCircle,\n        '--n-icon-color': iconColor,\n        '--n-icon-size-circle': iconSizeCircle,\n        '--n-icon-size-line': iconSizeLine,\n        '--n-line-bg-processing': lineBgProcessing,\n        '--n-rail-color': railColor,\n        '--n-rail-height': railHeight,\n        '--n-text-color-circle': textColorCircle,\n        '--n-text-color-line-inner': textColorLineInner,\n        '--n-text-color-line-outer': textColorLineOuter\n      }\n    })\n    const themeClassHandle = inlineThemeDisabled\n      ? useThemeClass(\n          'progress',\n          computed(() => props.status[0]),\n          cssVarsRef,\n          props\n        )\n      : undefined\n    return {\n      mergedClsPrefix: mergedClsPrefixRef,\n      mergedIndicatorPlacement: mergedIndicatorPlacementRef,\n      gapDeg,\n      cssVars: inlineThemeDisabled ? undefined : cssVarsRef,\n      themeClass: themeClassHandle?.themeClass,\n      onRender: themeClassHandle?.onRender\n    }\n  },\n  render() {\n    // it's ok to expand all prop here since no slots' deps\n    const {\n      type,\n      cssVars,\n      indicatorTextColor,\n      showIndicator,\n      status,\n      railColor,\n      railStyle,\n      color,\n      percentage,\n      viewBoxWidth,\n      strokeWidth,\n      mergedIndicatorPlacement,\n      unit,\n      borderRadius,\n      fillBorderRadius,\n      height,\n      processing,\n      circleGap,\n      mergedClsPrefix,\n      gapDeg,\n      gapOffsetDegree,\n      themeClass,\n      $slots,\n      onRender\n    } = this\n    onRender?.()\n    return (\n      <div\n        class={[\n          themeClass,\n          `${mergedClsPrefix}-progress`,\n          `${mergedClsPrefix}-progress--${type}`,\n          `${mergedClsPrefix}-progress--${status}`\n        ]}\n        style={cssVars as CSSProperties}\n        aria-valuemax={100}\n        aria-valuemin={0}\n        aria-valuenow={percentage as number}\n        role={\n          type === 'circle' || type === 'line' || type === 'dashboard'\n            ? 'progressbar'\n            : 'none'\n        }\n      >\n        {type === 'circle' || type === 'dashboard' ? (\n          <Circle\n            clsPrefix={mergedClsPrefix}\n            status={status}\n            showIndicator={showIndicator}\n            indicatorTextColor={indicatorTextColor}\n            railColor={railColor as any}\n            fillColor={color as any}\n            railStyle={railStyle as any}\n            offsetDegree={this.offsetDegree}\n            percentage={percentage as number}\n            viewBoxWidth={viewBoxWidth}\n            strokeWidth={strokeWidth}\n            gapDegree={\n              gapDeg === undefined ? (type === 'dashboard' ? 75 : 0) : gapDeg\n            }\n            gapOffsetDegree={gapOffsetDegree}\n            unit={unit}\n          >\n            {$slots}\n          </Circle>\n        ) : type === 'line' ? (\n          <Line\n            clsPrefix={mergedClsPrefix}\n            status={status}\n            showIndicator={showIndicator}\n            indicatorTextColor={indicatorTextColor}\n            railColor={railColor as any}\n            fillColor={color as any}\n            railStyle={railStyle as any}\n            percentage={percentage as number}\n            processing={processing}\n            indicatorPlacement={mergedIndicatorPlacement}\n            unit={unit}\n            fillBorderRadius={fillBorderRadius}\n            railBorderRadius={borderRadius}\n            height={height}\n          >\n            {$slots}\n          </Line>\n        ) : type === 'multiple-circle' ? (\n          <MultipleCircle\n            clsPrefix={mergedClsPrefix}\n            strokeWidth={strokeWidth}\n            railColor={railColor as any}\n            fillColor={color as any}\n            railStyle={railStyle as any}\n            viewBoxWidth={viewBoxWidth}\n            percentage={percentage as number[]}\n            showIndicator={showIndicator}\n            circleGap={circleGap}\n          >\n            {$slots}\n          </MultipleCircle>\n        ) : null}\n      </div>\n    )\n  }\n})\n"
  },
  {
    "path": "src/progress/src/public-types.ts",
    "content": "export type ProgressStatus\n  = | 'success'\n    | 'error'\n    | 'warning'\n    | 'info'\n    | 'default'\nexport interface ProgressGradient {\n  stops: string[]\n}\n"
  },
  {
    "path": "src/progress/src/styles/index.cssr.ts",
    "content": "import { c, cB, cM } from '../../../_utils/cssr'\n\n// vars\n// --n-bezier\n// --n-fill-color\n// --n-font-size\n// --n-font-size-circle\n// --n-font-weight-circle\n// --n-icon-color\n// --n-icon-size-circle\n// --n-icon-size-line\n// --n-line-bg-processing\n// --n-rail-color\n// --n-rail-height\n// --n-text-color-circle\n// --n-text-color-line-inner\n// --n-text-color-line-outer\nexport default c([\n  cB('progress', {\n    display: 'inline-block'\n  }, [\n    cB('progress-icon', `\n      color: var(--n-icon-color);\n      transition: color .3s var(--n-bezier);\n    `),\n    cM('line', `\n      width: 100%;\n      display: block;\n    `, [\n      cB('progress-content', `\n        display: flex;\n        align-items: center;\n      `, [\n        cB('progress-graph', {\n          flex: 1\n        })\n      ]),\n      cB('progress-custom-content', {\n        marginLeft: '14px'\n      }),\n      cB('progress-icon', `\n        width: 30px;\n        padding-left: 14px;\n        height: var(--n-icon-size-line);\n        line-height: var(--n-icon-size-line);\n        font-size: var(--n-icon-size-line);\n      `, [\n        cM('as-text', `\n          color: var(--n-text-color-line-outer);\n          text-align: center;\n          width: 40px;\n          font-size: var(--n-font-size);\n          padding-left: 4px;\n          transition: color .3s var(--n-bezier);\n        `)\n      ])\n    ]),\n    cM('circle, dashboard', {\n      width: '120px'\n    }, [\n      cB('progress-custom-content', `\n        position: absolute;\n        left: 50%;\n        top: 50%;\n        transform: translateX(-50%) translateY(-50%);\n        display: flex;\n        align-items: center;\n        justify-content: center;\n      `),\n      cB('progress-text', `\n        position: absolute;\n        left: 50%;\n        top: 50%;\n        transform: translateX(-50%) translateY(-50%);\n        display: flex;\n        align-items: center;\n        color: inherit;\n        font-size: var(--n-font-size-circle);\n        color: var(--n-text-color-circle);\n        font-weight: var(--n-font-weight-circle);\n        transition: color .3s var(--n-bezier);\n        white-space: nowrap;\n      `),\n      cB('progress-icon', `\n        position: absolute;\n        left: 50%;\n        top: 50%;\n        transform: translateX(-50%) translateY(-50%);\n        display: flex;\n        align-items: center;\n        color: var(--n-icon-color);\n        font-size: var(--n-icon-size-circle);\n      `)\n    ]),\n    cM('multiple-circle', `\n      width: 200px;\n      color: inherit;\n    `, [\n      cB('progress-text', `\n        font-weight: var(--n-font-weight-circle);\n        color: var(--n-text-color-circle);\n        position: absolute;\n        left: 50%;\n        top: 50%;\n        transform: translateX(-50%) translateY(-50%);\n        display: flex;\n        align-items: center;\n        justify-content: center;\n        transition: color .3s var(--n-bezier);\n      `)\n    ]),\n    cB('progress-content', {\n      position: 'relative'\n    }),\n    cB('progress-graph', {\n      position: 'relative'\n    }, [\n      cB('progress-graph-circle', [\n        c('svg', {\n          verticalAlign: 'bottom'\n        }),\n        cB('progress-graph-circle-fill', `\n          stroke: var(--n-fill-color);\n          transition:\n            opacity .3s var(--n-bezier),\n            stroke .3s var(--n-bezier),\n            stroke-dasharray .3s var(--n-bezier);\n        `, [\n          cM('empty', {\n            opacity: 0\n          })\n        ]),\n        cB('progress-graph-circle-rail', `\n          transition: stroke .3s var(--n-bezier);\n          overflow: hidden;\n          stroke: var(--n-rail-color);\n        `)\n      ]),\n      cB('progress-graph-line', [\n        cM('indicator-inside', [\n          cB('progress-graph-line-rail', `\n            height: 16px;\n            line-height: 16px;\n            border-radius: 10px;\n          `, [\n            cB('progress-graph-line-fill', `\n              height: inherit;\n              border-radius: 10px;\n            `),\n            cB('progress-graph-line-indicator', `\n              background: #0000;\n              white-space: nowrap;\n              text-align: right;\n              margin-left: 14px;\n              margin-right: 14px;\n              height: inherit;\n              font-size: 12px;\n              color: var(--n-text-color-line-inner);\n              transition: color .3s var(--n-bezier);\n            `)\n          ])\n        ]),\n        cM('indicator-inside-label', `\n          height: 16px;\n          display: flex;\n          align-items: center;\n        `, [\n          cB('progress-graph-line-rail', `\n            flex: 1;\n            transition: background-color .3s var(--n-bezier);\n          `),\n          cB('progress-graph-line-indicator', `\n            background: var(--n-fill-color);\n            font-size: 12px;\n            transform: translateZ(0);\n            display: flex;\n            vertical-align: middle;\n            height: 16px;\n            line-height: 16px;\n            padding: 0 10px;\n            border-radius: 10px;\n            position: absolute;\n            white-space: nowrap;\n            color: var(--n-text-color-line-inner);\n            transition:\n              right .2s var(--n-bezier),\n              color .3s var(--n-bezier),\n              background-color .3s var(--n-bezier);\n          `)\n        ]),\n        cB('progress-graph-line-rail', `\n          position: relative;\n          overflow: hidden;\n          height: var(--n-rail-height);\n          border-radius: 5px;\n          background-color: var(--n-rail-color);\n          transition: background-color .3s var(--n-bezier);\n        `, [\n          cB('progress-graph-line-fill', `\n            background: var(--n-fill-color);\n            position: relative;\n            border-radius: 5px;\n            height: inherit;\n            width: 100%;\n            max-width: 0%;\n            transition:\n              background-color .3s var(--n-bezier),\n              max-width .2s var(--n-bezier);\n          `, [\n            cM('processing', [\n              c('&::after', `\n                content: \"\";\n                background-image: var(--n-line-bg-processing);\n                animation: progress-processing-animation 2s var(--n-bezier) infinite;\n              `)\n            ])\n          ])\n        ])\n      ])\n    ])\n  ]),\n  c('@keyframes progress-processing-animation', `\n    0% {\n      position: absolute;\n      left: 0;\n      top: 0;\n      bottom: 0;\n      right: 100%;\n      opacity: 1;\n    }\n    66% {\n      position: absolute;\n      left: 0;\n      top: 0;\n      bottom: 0;\n      right: 0;\n      opacity: 0;\n    }\n    100% {\n      position: absolute;\n      left: 0;\n      top: 0;\n      bottom: 0;\n      right: 0;\n      opacity: 0;\n    }\n  `)\n])\n"
  },
  {
    "path": "src/progress/styles/dark.ts",
    "content": "import type { ProgressTheme } from './light'\nimport { commonDark } from '../../_styles/common'\nimport { self } from './light'\n\nconst progressDark: ProgressTheme = {\n  name: 'Progress',\n  common: commonDark,\n  self(vars) {\n    const commonSelf = self(vars)\n    commonSelf.textColorLineInner = 'rgb(0, 0, 0)'\n    commonSelf.lineBgProcessing\n      = 'linear-gradient(90deg, rgba(255, 255, 255, .3) 0%, rgba(255, 255, 255, .5) 100%)'\n    return commonSelf\n  }\n}\n\nexport default progressDark\n"
  },
  {
    "path": "src/progress/styles/index.ts",
    "content": "export { default as progressDark } from './dark'\nexport { default as progressLight } from './light'\nexport type { ProgressTheme, ProgressThemeVars } from './light'\n"
  },
  {
    "path": "src/progress/styles/light.ts",
    "content": "import type { Theme } from '../../_mixins/use-theme'\nimport type { ThemeCommonVars } from '../../_styles/common'\nimport { commonLight } from '../../_styles/common'\n\nexport function self(vars: ThemeCommonVars) {\n  const {\n    infoColor,\n    successColor,\n    warningColor,\n    errorColor,\n    textColor2,\n    progressRailColor,\n    fontSize,\n    fontWeight\n  } = vars\n  return {\n    fontSize,\n    fontSizeCircle: '28px',\n    fontWeightCircle: fontWeight,\n    railColor: progressRailColor,\n    railHeight: '8px',\n    iconSizeCircle: '36px',\n    iconSizeLine: '18px',\n    iconColor: infoColor,\n    iconColorInfo: infoColor,\n    iconColorSuccess: successColor,\n    iconColorWarning: warningColor,\n    iconColorError: errorColor,\n    textColorCircle: textColor2,\n    textColorLineInner: 'rgb(255, 255, 255)',\n    textColorLineOuter: textColor2,\n    fillColor: infoColor,\n    fillColorInfo: infoColor,\n    fillColorSuccess: successColor,\n    fillColorWarning: warningColor,\n    fillColorError: errorColor,\n    lineBgProcessing:\n      'linear-gradient(90deg, rgba(255, 255, 255, .3) 0%, rgba(255, 255, 255, .5) 100%)'\n  }\n}\n\nexport type ProgressThemeVars = ReturnType<typeof self>\n\nconst progressLight: Theme<'Progress', ProgressThemeVars> = {\n  name: 'Progress',\n  common: commonLight,\n  self\n}\n\nexport default progressLight\nexport type ProgressTheme = typeof progressLight\n"
  },
  {
    "path": "src/progress/tests/Progress.spec.ts",
    "content": "import { mount } from '@vue/test-utils'\nimport { SuccessIcon } from '../../_internal/icons'\nimport { NProgress } from '../index'\n\ndescribe('n-progress', () => {\n  it('should work with import on demand', () => {\n    mount(NProgress)\n  })\n\n  it('should work with `type` prop', async () => {\n    ;(['line', 'circle', 'multiple-circle'] as const).forEach((item) => {\n      const wrapper = mount(NProgress, { props: { type: item } })\n      expect(wrapper.find('.n-progress').classes()).toContain(\n        `n-progress--${item}`\n      )\n      wrapper.unmount()\n    })\n  })\n\n  it('should work with `color`, `rail-color`, `indicator-text-color` prop', async () => {\n    const wrapper = mount(NProgress, {\n      props: {\n        color: 'rgb(51, 51, 51)',\n        'rail-color': 'rgb(68, 68, 68)',\n        'indicator-text-color': 'rgb(85, 85, 85)'\n      },\n      slots: {\n        default: () => 'test'\n      }\n    })\n    expect(\n      wrapper.find('.n-progress-graph-line-fill').attributes('style')\n    ).toContain('max-width: 0%; background: rgb(51, 51, 51);')\n    expect(\n      wrapper.find('.n-progress-graph-line-rail').attributes('style')\n    ).toContain('background-color: rgb(68, 68, 68);')\n    expect(\n      wrapper.find('.n-progress-custom-content').attributes('style')\n    ).toContain('color: rgb(85, 85, 85);')\n    wrapper.unmount()\n  })\n\n  it('should work with `border-radius`, `fill-border-radius` prop', async () => {\n    const wrapper = mount(NProgress, {\n      props: {\n        'border-radius': '12px',\n        'fill-border-radius': '13px'\n      },\n      slots: {\n        default: () => 'test'\n      }\n    })\n    expect(\n      wrapper.find('.n-progress-graph-line-rail').attributes('style')\n    ).toContain('border-radius: 12px')\n    expect(\n      wrapper.find('.n-progress-graph-line-fill').attributes('style')\n    ).toContain('border-radius: 13px')\n    wrapper.unmount()\n  })\n\n  it('should work with `height` prop', async () => {\n    const wrapper = mount(NProgress, {\n      props: {\n        height: 24\n      }\n    })\n    expect(\n      wrapper.find('.n-progress-graph-line-rail').attributes('style')\n    ).toContain('height: 24')\n    wrapper.unmount()\n  })\n\n  it('should work with `processing` prop', async () => {\n    const wrapper = mount(NProgress, {\n      props: {\n        processing: true\n      }\n    })\n    expect(wrapper.find('.n-progress-graph-line-fill').classes()).toContain(\n      'n-progress-graph-line-fill--processing'\n    )\n    wrapper.unmount()\n  })\n\n  it('should work with slot', async () => {\n    const wrapper = mount(NProgress, {\n      slots: {\n        default: () => 'test'\n      }\n    })\n    expect(wrapper.find('.n-progress-custom-content').exists()).toBe(true)\n    expect(wrapper.find('.n-progress-custom-content').text()).toBe('test')\n\n    await wrapper.setProps({ showIndicator: false, type: 'circle' })\n    expect(wrapper.find('.n-progress-custom-content').exists()).toBe(false)\n\n    await wrapper.setProps({ showIndicator: true })\n    expect(wrapper.find('.n-progress-custom-content').exists()).toBe(true)\n    wrapper.unmount()\n  })\n\n  it('should show icon with `circle` type', () => {\n    const wrapper = mount(NProgress, {\n      props: {\n        type: 'circle',\n        showIndicator: true,\n        status: 'success'\n      }\n    })\n\n    expect(wrapper.findComponent(SuccessIcon).exists()).toBe(true)\n    wrapper.unmount()\n  })\n\n  it('should show icon with `line` type', () => {\n    const wrapper = mount(NProgress, {\n      props: {\n        type: 'line',\n        showIndicator: true,\n        indicatorPlacement: 'outside',\n        status: 'success'\n      }\n    })\n\n    expect(wrapper.findComponent(SuccessIcon).exists()).toBe(true)\n    wrapper.unmount()\n  })\n\n  it('should show correct style with `line` type', async () => {\n    const wrapper = mount(NProgress, {\n      props: {\n        type: 'line',\n        percentage: 50,\n        borderRadius: 50\n      }\n    })\n\n    expect(\n      wrapper.find('.n-progress-graph-line-rail').attributes('style')\n    ).toContain('border-radius: 50px;')\n\n    await wrapper.setProps({ indicatorPlacement: 'inside' })\n    expect(wrapper.find('.n-progress-graph-line-indicator').exists()).toBe(true)\n    expect(wrapper.find('.n-progress-graph-line-indicator').text()).toBe('50%')\n    wrapper.unmount()\n  })\n\n  it('should show correct style with `multiple-circle` type', async () => {\n    const wrapper = mount(NProgress, {\n      props: {\n        type: 'multiple-circle'\n      },\n      slots: {\n        default: () => 'test'\n      }\n    })\n\n    expect(wrapper.find('.n-progress-text').exists()).toBe(true)\n    wrapper.unmount()\n  })\n})\n"
  },
  {
    "path": "src/progress/tests/server.spec.tsx",
    "content": "import { setup } from '@css-render/vue3-ssr'\nimport { renderToString } from '@vue/server-renderer'\n/**\n * @vitest-environment node\n */\nimport { createSSRApp, h } from 'vue'\nimport { NProgress } from '../..'\n\ndescribe('server side rendering', () => {\n  it('works', async () => {\n    const app = createSSRApp(() => <NProgress />)\n    setup(app)\n    try {\n      await renderToString(app)\n    }\n    catch (e) {\n      expect(e).not.toBeTruthy()\n    }\n  })\n})\n"
  },
  {
    "path": "src/qr-code/demos/enUS/basic.demo.vue",
    "content": "<markdown>\n  # Basic\n\n  A basic QR Code.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst text = ref('The rain dampened the sky')\n</script>\n\n<template>\n  <n-space vertical>\n    <n-qr-code :value=\"text\" />\n    <n-input v-model:value=\"text\" :maxlength=\"60\" type=\"text\" />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/qr-code/demos/enUS/color.demo.vue",
    "content": "<markdown>\n  # Color\n\n  Let the QR code no longer monotonous.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst color = ref('#225A95FF')\n</script>\n\n<template>\n  <n-flex>\n    <n-qr-code value=\"https://www.naiveui.com/\" color=\"#18a058\" />\n    <n-qr-code\n      value=\"https://www.naiveui.com/\"\n      color=\"#409eff\"\n      background-color=\"#F5F5F5\"\n    />\n  </n-flex>\n  <n-flex vertical>\n    <n-color-picker v-model:value=\"color\" />\n    <n-qr-code\n      value=\"https://www.naiveui.com/\"\n      :color=\"color\"\n      background-color=\"#F5F5F5\"\n    />\n  </n-flex>\n</template>\n"
  },
  {
    "path": "src/qr-code/demos/enUS/download.demo.vue",
    "content": "<markdown>\n  # Download\n\n  Download two-dimensional code code implementation, you can also choose to right-click the picture to save it.\n</markdown>\n\n<script lang=\"ts\" setup>\nfunction handleDownloadQRCode() {\n  const canvas = document\n    .querySelector('#qr-code')\n    ?.querySelector<HTMLCanvasElement>('canvas')\n  if (canvas) {\n    const url = canvas.toDataURL()\n    const a = document.createElement('a')\n    a.download = 'QRCode.png'\n    a.href = url\n    document.body.appendChild(a)\n    a.click()\n    document.body.removeChild(a)\n  }\n}\n</script>\n\n<template>\n  <n-space vertical>\n    <n-qr-code id=\"qr-code\" value=\"https://www.naiveui.com/\" />\n    <n-button @click=\"handleDownloadQRCode\">\n      Download\n    </n-button>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/qr-code/demos/enUS/error-correction.demo.vue",
    "content": "<markdown>\n  # Error correction\n\n  Use `error-correction-level` to set the error correction level.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst errorCorrectionLevel = ref('M')\nconst errorCorrectionOptions = [\n  { value: 'L', label: 'L' },\n  { value: 'M', label: 'M' },\n  { value: 'Q', label: 'Q' },\n  { value: 'H', label: 'H' }\n]\n</script>\n\n<template>\n  <n-space vertical>\n    <n-qr-code\n      value=\"Like a humorous magician, he skillfully turns tedious information into a mysterious QR code\"\n      :error-correction-level=\"errorCorrectionLevel\"\n    />\n    <n-radio-group v-model:value=\"errorCorrectionLevel\">\n      <n-radio-button\n        v-for=\"errorCorrection in errorCorrectionOptions\"\n        :key=\"errorCorrection.value\"\n        :value=\"errorCorrection.value\"\n        :label=\"errorCorrection.label\"\n      />\n    </n-radio-group>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/qr-code/demos/enUS/icon.demo.vue",
    "content": "<markdown>\n  # Icon\n\n  You can put some representative icons.\n</markdown>\n\n<script lang=\"ts\" setup></script>\n\n<template>\n  <n-space>\n    <n-qr-code\n      value=\"https://www.naiveui.com/\"\n      icon-src=\"https://07akioni.oss-cn-beijing.aliyuncs.com/07akioni.jpeg\"\n      error-correction-level=\"H\"\n    />\n    <n-qr-code\n      value=\"https://www.naiveui.com/\"\n      icon-src=\"https://07akioni.oss-cn-beijing.aliyuncs.com/07akioni.jpeg\"\n      icon-background-color=\"#333\"\n      error-correction-level=\"H\"\n    />\n    <n-qr-code\n      value=\"https://www.naiveui.com/\"\n      icon-src=\"https://07akioni.oss-cn-beijing.aliyuncs.com/07akioni.jpeg\"\n      :icon-size=\"32\"\n      error-correction-level=\"H\"\n    />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/qr-code/demos/enUS/index.demo-entry.md",
    "content": "# QR Code\n\nIt is always only valid for a short time.\n\nAvailable since `2.36.0`.\n\n## Demos\n\n```demo\nbasic.vue\nicon.vue\nsize.vue\ncolor.vue\nerror-correction.vue\ndownload.vue\ntype.vue\n```\n\n## API\n\n### QR Code Props\n\n| Name | Type | Default | Description | Version |\n| --- | --- | --- | --- | --- |\n| background-color | `string` | `'#FFF'` | QR code background color, Values need to be in `hex` format. | 2.36.0 |\n| color | `string` | `'#000'` | QR code color, Values need to be in `hex` format. | 2.36.0 |\n| error-correction-level | `'L'` \\| `'M'` \\| `'Q'` \\| `'H'` | `'M'` | QR code error correction level. | 2.36.0 |\n| icon-border-radius | `number` | `4` | Icon background's border-radius | 2.36.0 |\n| icon-background-color | `string` | `'#FFF'` | Icon's background color. | 2.36.0 |\n| icon-size | `number` | `40` | Icon's size. | 2.36.0 |\n| icon-src | `string` | `undefined` | Icon's URL. | 2.36.0 |\n| padding | `number \\| string` | `12` | Padding size of the QR Code. | 2.36.0 |\n| value | `string` | `''` | Text information. | 2.36.0 |\n| size | `number` | `100` | Size of the qrcode. | 2.36.0 |\n| type | `'canvas'` \\| `'svg'` | `'canvas'` | Customize Render Type. | 2.38.2 |\n\n### About QR code error correction level\n\nThe error correction level of the two-dimensional code refers to the error correction capability used in the generation of the two-dimensional code, which determines the ability of the two-dimensional code to be correctly decoded when it is damaged or partially invisible.\n\nTwo-dimensional code standards (such as QR codes) define four error correction levels: L, M, Q, and H. Each level provides different error correction capabilities and tolerance.\n\n- `L (Low)`: Provides approximately `7%` recovery capability.\n\n- `M (Middle)`: Provides approximately `15%` recovery capacity.\n\n- `Q (High)`: Provides approximately `25%` recovery capacity.\n\n- `H (Max)`: Provides approximately `30%` recovery capacity.\n\nSelecting a higher error correction level can improve the fault tolerance of the two-dimensional code, that is, it can still be correctly decoded under a certain degree of damage or deformation, but at the same time, it will increase the density of the two-dimensional code, making the two-dimensional code occupy a larger space.\n"
  },
  {
    "path": "src/qr-code/demos/enUS/size.demo.vue",
    "content": "<markdown>\n  # Size\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst text = ref('The rain dampened the sky')\n\nconst size = ref(110)\n\nfunction add() {\n  size.value += 10\n  if (size.value > 200) {\n    size.value = 110\n  }\n}\n\nfunction minus() {\n  size.value -= 10\n  if (size.value < 20) {\n    size.value = 110\n  }\n}\n</script>\n\n<template>\n  <n-space vertical>\n    <n-space>\n      <n-button @click=\"minus\">\n        Minus 10px\n      </n-button>\n      <n-button @click=\"add\">\n        Add 10px\n      </n-button>\n    </n-space>\n    <n-qr-code :value=\"text\" :size=\"size\" />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/qr-code/demos/enUS/type.demo.vue",
    "content": "<markdown>\n# Customize Render Type\n\nCustomize rendering output by setting `type`, providing two options: `canvas` and `svg`.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst text = ref('The rain dampened the sky')\n</script>\n\n<template>\n  <n-space>\n    <n-qr-code :value=\"text\" type=\"canvas\" />\n    <n-qr-code :value=\"text\" type=\"svg\" />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/qr-code/demos/zhCN/basic.demo.vue",
    "content": "<markdown>\n# 基础用法\n\n基础二维码。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst text = ref('雨淋湿了天空')\n</script>\n\n<template>\n  <n-space vertical>\n    <n-qr-code :value=\"text\" />\n    <n-input v-model:value=\"text\" :maxlength=\"60\" type=\"text\" />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/qr-code/demos/zhCN/color.demo.vue",
    "content": "<markdown>\n  # 颜色\n\n  让二维码不再单调乏味。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst color = ref('#225A95FF')\n</script>\n\n<template>\n  <n-flex>\n    <n-qr-code value=\"https://www.naiveui.com/\" color=\"#18a058\" />\n    <n-qr-code\n      value=\"https://www.naiveui.com/\"\n      color=\"#409eff\"\n      background-color=\"#F5F5F5\"\n    />\n  </n-flex>\n  <n-flex vertical>\n    <n-color-picker v-model:value=\"color\" />\n    <n-qr-code\n      value=\"https://www.naiveui.com/\"\n      :color=\"color\"\n      background-color=\"#F5F5F5\"\n    />\n  </n-flex>\n</template>\n"
  },
  {
    "path": "src/qr-code/demos/zhCN/download.demo.vue",
    "content": "<markdown>\n  # 下载\n\n下载二维码的代码实现，你也可以选择右键图片另存为。\n</markdown>\n\n<script lang=\"ts\" setup>\nfunction handleDownloadQRCode() {\n  const canvas = document\n    .querySelector('#qr-code')\n    ?.querySelector<HTMLCanvasElement>('canvas')\n  if (canvas) {\n    const url = canvas.toDataURL()\n    const a = document.createElement('a')\n    a.download = 'QRCode.png'\n    a.href = url\n    document.body.appendChild(a)\n    a.click()\n    document.body.removeChild(a)\n  }\n}\n</script>\n\n<template>\n  <n-space vertical>\n    <n-qr-code id=\"qr-code\" value=\"https://www.naiveui.com/\" />\n    <n-button @click=\"handleDownloadQRCode\">\n      下载\n    </n-button>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/qr-code/demos/zhCN/error-correction.demo.vue",
    "content": "<markdown>\n  # 纠错\n\n  使用 `error-correction-level` 来设定纠错级别。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst errorCorrectionLevel = ref('M')\nconst errorCorrectionOptions = [\n  { value: 'L', label: 'L' },\n  { value: 'M', label: 'M' },\n  { value: 'Q', label: 'Q' },\n  { value: 'H', label: 'H' }\n]\n</script>\n\n<template>\n  <n-space vertical>\n    <n-qr-code\n      value=\"犹如一位幽默风趣的魔术师，巧妙地将繁琐的信息变成了一个神秘的二维码\"\n      :error-correction-level=\"errorCorrectionLevel\"\n    />\n    <n-radio-group v-model:value=\"errorCorrectionLevel\">\n      <n-radio-button\n        v-for=\"errorCorrection in errorCorrectionOptions\"\n        :key=\"errorCorrection.value\"\n        :value=\"errorCorrection.value\"\n        :label=\"errorCorrection.label\"\n      />\n    </n-radio-group>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/qr-code/demos/zhCN/icon.demo.vue",
    "content": "<markdown>\n  # 图标\n\n可以放一些代表性的图标。\n</markdown>\n\n<script lang=\"ts\" setup></script>\n\n<template>\n  <n-space>\n    <n-qr-code\n      value=\"https://www.naiveui.com/\"\n      icon-src=\"https://07akioni.oss-cn-beijing.aliyuncs.com/07akioni.jpeg\"\n      error-correction-level=\"H\"\n    />\n    <n-qr-code\n      value=\"https://www.naiveui.com/\"\n      icon-src=\"https://07akioni.oss-cn-beijing.aliyuncs.com/07akioni.jpeg\"\n      icon-background-color=\"#333\"\n      error-correction-level=\"H\"\n    />\n    <n-qr-code\n      value=\"https://www.naiveui.com/\"\n      icon-src=\"https://07akioni.oss-cn-beijing.aliyuncs.com/07akioni.jpeg\"\n      type=\"svg\"\n      :icon-size=\"32\"\n      error-correction-level=\"H\"\n    />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/qr-code/demos/zhCN/index.demo-entry.md",
    "content": "# 二维码 QR Code\n\n总是即将过期。\n\n自 `2.36.0` 开始提供。\n\n## 演示\n\n```demo\nbasic.vue\nicon.vue\nsize.vue\ncolor.vue\nerror-correction.vue\ndownload.vue\ntype.vue\n```\n\n## API\n\n### QR Code Props\n\n| 名称 | 类型 | 默认值 | 说明 | 版本 |\n| --- | --- | --- | --- | --- |\n| background-color | `string` | `'#FFF'` | 二维码背景颜色，值需要采用 `hex` 格式 | 2.36.0 |\n| color | `string` | `'#000'` | 二维码颜色，值需要采用 `hex` 格式 | 2.36.0 |\n| error-correction-level | `'L'` \\| `'M'` \\| `'Q'` \\| `'H'` | `'M'` | 二维码纠错级别 | 2.36.0 |\n| icon-background-color | `string` | `'#FFF'` | 图标背景颜色 | 2.36.0 |\n| icon-border-radius | `number` | `4` | 图标背景圆角大小 | 2.36.0 |\n| icon-size | `number` | `40` | 图标大小 | 2.36.0 |\n| icon-src | `string` | `undefined` | 图标地址 | 2.36.0 |\n| padding | `number \\| string` | `12` | 二维码填充大小 | 2.36.0 |\n| value | `string` | `''` | 文本信息 | 2.36.0 |\n| size | `number` | `100` | 二维码大小 | 2.36.0 |\n| type | `'canvas'` \\| `'svg'` | `'canvas'` | 自定义二维码渲染类型 | 2.38.2 |\n\n### 关于二维码纠错级别\n\n二维码纠错级别是指在生成二维码时所使用的错误纠正能力，它决定了二维码在受到损坏或部分不可见时，仍然可以正确解码的能力。\n\n二维码标准（如 QR 码）定义了四个纠错级别：L、M、Q 和 H。每个级别提供不同的纠错能力和容错性。\n\n- `L（低）`：提供约 `7%` 的恢复能力\n- `M（中）`：提供约 `15%` 的恢复能力\n- `Q（高）`：提供约 `25%` 的恢复能力\n- `H（最高）`：提供约 `30%` 的恢复能力\n\n选择更高的纠错级别可以提高二维码的容错性，即在一定程度的损坏或变形下仍然能够正确解码，但同时会增加二维码的密度，使得二维码所占空间更大。\n"
  },
  {
    "path": "src/qr-code/demos/zhCN/size.demo.vue",
    "content": "<markdown>\n  # 尺寸\n\n  它就像疯狂千层饼，无论大小，都会引领你进入另一个神秘的信息空间。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst text = ref('The rain dampened the sky')\n\nconst size = ref(110)\n\nfunction add() {\n  size.value += 10\n  if (size.value > 200) {\n    size.value = 110\n  }\n}\n\nfunction minus() {\n  size.value -= 10\n  if (size.value < 20) {\n    size.value = 110\n  }\n}\n</script>\n\n<template>\n  <n-space vertical>\n    <n-space>\n      <n-button @click=\"minus\">\n        减 10\n      </n-button>\n      <n-button @click=\"add\">\n        加 10\n      </n-button>\n    </n-space>\n    <n-qr-code :value=\"text\" :size=\"size\" />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/qr-code/demos/zhCN/type.demo.vue",
    "content": "<markdown>\n# 自定义渲染类型\n\n通过设置 `type` 自定义渲染结果，提供 `canvas` 和 `svg` 两个选项。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst text = ref('雨淋湿了天空')\n</script>\n\n<template>\n  <n-space>\n    <n-qr-code :value=\"text\" type=\"canvas\" />\n    <n-qr-code :value=\"text\" type=\"svg\" />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/qr-code/index.ts",
    "content": "export { default as NQrCode, qrCodeProps } from './src/QrCode'\nexport type { QrCodeProps } from './src/QrCode'\n"
  },
  {
    "path": "src/qr-code/src/QrCode.tsx",
    "content": "import type { PropType } from 'vue'\nimport type { ThemeProps } from '../../_mixins'\nimport type { ExtractPublicPropTypes } from '../../_utils'\nimport type { QrCodeTheme } from '../styles'\nimport { computed, defineComponent, h, onMounted, ref, watchEffect } from 'vue'\nimport { useConfig, useTheme, useThemeClass } from '../../_mixins'\nimport { qrcodeLight } from '../styles'\nimport qrcodegen from './qrcodegen'\nimport style from './styles/index.cssr'\n\ntype Modules = ReturnType<qrcodegen.QrCode['getModules']>\n\nconst ERROR_CORRECTION_LEVEL: Record<string, qrcodegen.QrCode.Ecc> = {\n  L: qrcodegen.QrCode.Ecc.LOW,\n  M: qrcodegen.QrCode.Ecc.MEDIUM,\n  Q: qrcodegen.QrCode.Ecc.QUARTILE,\n  H: qrcodegen.QrCode.Ecc.HIGH\n}\n\nexport const qrCodeProps = {\n  ...(useTheme.props as ThemeProps<QrCodeTheme>),\n  value: String,\n  color: {\n    type: String,\n    default: '#000'\n  },\n  backgroundColor: {\n    type: String,\n    default: '#FFF'\n  },\n  iconSrc: String,\n  iconSize: {\n    type: Number,\n    default: 40\n  },\n  iconBackgroundColor: {\n    type: String,\n    default: '#FFF'\n  },\n  iconBorderRadius: {\n    type: Number,\n    default: 4\n  },\n  size: {\n    type: Number,\n    default: 100\n  },\n  padding: {\n    type: [Number, String] as PropType<string | number>,\n    default: 12\n  },\n  errorCorrectionLevel: {\n    type: String,\n    default: 'M'\n  },\n  type: {\n    type: String,\n    default: 'canvas'\n  }\n} as const\n\nexport type QrCodeProps = ExtractPublicPropTypes<typeof qrCodeProps>\n\n// For retina display\nconst UPSCALE_RATIO = 2\n\nexport default defineComponent({\n  name: 'QrCode',\n  props: qrCodeProps,\n  setup(props) {\n    const { mergedClsPrefixRef, inlineThemeDisabled } = useConfig(props)\n\n    const themeRef = useTheme(\n      'QrCode',\n      '-qr-code',\n      style,\n      qrcodeLight,\n      props,\n      mergedClsPrefixRef\n    )\n\n    const cssVarsRef = computed(() => {\n      return {\n        '--n-border-radius': themeRef.value.self.borderRadius\n      }\n    })\n\n    const themeClassHandle = inlineThemeDisabled\n      ? useThemeClass('qr-code', undefined, cssVarsRef, props)\n      : undefined\n\n    const canvasRef = ref<HTMLCanvasElement>()\n\n    const qr = computed(() => {\n      const errorCorrectionLevel\n        = ERROR_CORRECTION_LEVEL[props.errorCorrectionLevel]\n      return qrcodegen.QrCode.encodeText(\n        props.value ?? '-',\n        errorCorrectionLevel\n      )\n    })\n\n    onMounted(() => {\n      const imageLoadedTrigger = ref(0)\n      let loadedIcon: HTMLImageElement | null = null\n      watchEffect(() => {\n        if (props.type === 'svg')\n          return\n        void imageLoadedTrigger.value\n        drawCanvas(\n          qr.value,\n          props.size,\n          props.color,\n          props.backgroundColor,\n          loadedIcon\n            ? {\n                icon: loadedIcon,\n                iconBorderRadius: props.iconBorderRadius,\n                iconSize: props.iconSize,\n                iconBackgroundColor: props.iconBackgroundColor\n              }\n            : null\n        )\n      })\n\n      watchEffect(() => {\n        if (props.type === 'svg')\n          return\n        const { iconSrc } = props\n        if (iconSrc) {\n          let aborted = false\n          const img = new Image()\n          img.src = iconSrc\n          img.onload = () => {\n            if (aborted)\n              return\n            loadedIcon = img\n            imageLoadedTrigger.value++\n          }\n          return () => {\n            aborted = true\n          }\n        }\n      })\n    })\n\n    function drawCanvas(\n      qr: qrcodegen.QrCode,\n      size: number,\n      foregroundColor: string,\n      backgroundColor: string,\n      iconConfig: {\n        icon: HTMLImageElement\n        iconBorderRadius: number\n        iconSize: number\n        iconBackgroundColor: string\n      } | null\n    ): void {\n      const canvas = canvasRef.value\n      if (!canvas)\n        return\n      const canvasWidth = size * UPSCALE_RATIO\n      const width = qr.size\n      const scale = canvasWidth / width\n      canvas.width = canvasWidth\n      canvas.height = canvasWidth\n      const ctx = canvas.getContext('2d')\n      if (!ctx)\n        return\n      ctx.clearRect(0, 0, canvas.width, canvas.height)\n      for (let y = 0; y < qr.size; y++) {\n        for (let x = 0; x < qr.size; x++) {\n          ctx.fillStyle = qr.getModule(x, y) ? foregroundColor : backgroundColor\n          const startX = Math.floor(x * scale)\n          const endX = Math.ceil((x + 1) * scale)\n          const startY = Math.floor(y * scale)\n          const endY = Math.ceil((y + 1) * scale)\n          ctx.fillRect(startX, startY, endX - startX, endY - startY)\n        }\n      }\n      if (iconConfig) {\n        const { icon, iconBackgroundColor, iconBorderRadius, iconSize }\n          = iconConfig\n        const finalIconSize = iconSize * UPSCALE_RATIO\n        const centerX = (canvas.width - finalIconSize) / 2\n        const centerY = (canvas.height - finalIconSize) / 2\n        ctx.fillStyle = iconBackgroundColor\n        ctx.beginPath()\n        ctx.roundRect(\n          centerX,\n          centerY,\n          finalIconSize,\n          finalIconSize,\n          iconBorderRadius * UPSCALE_RATIO\n        )\n        ctx.fill()\n        const aspectRatio = icon.width / icon.height\n        const scaledWidth\n          = aspectRatio >= 1 ? finalIconSize : finalIconSize * aspectRatio\n        const scaledHeight\n          = aspectRatio <= 1 ? finalIconSize : finalIconSize / aspectRatio\n        const left = centerX + (finalIconSize - scaledWidth) / 2\n        const top = centerY + (finalIconSize - scaledHeight) / 2\n        ctx.drawImage(icon, left, top, scaledWidth, scaledHeight)\n      }\n    }\n\n    function generatePath(modules: Modules, margin: number = 0): string {\n      const ops: string[] = []\n      modules.forEach((row, y) => {\n        let start: number | null = null\n        row.forEach((cell, x) => {\n          if (!cell && start !== null) {\n            // M0 0h7v1H0z injects the space with the move and drops the comma,\n            // saving a char per operation\n            ops.push(\n              `M${start + margin} ${y + margin}h${x - start}v1H${start + margin}z`\n            )\n            start = null\n            return\n          }\n\n          // end of row, clean up or skip\n          if (x === row.length - 1) {\n            if (!cell) {\n              // We would have closed the op above already so this can only mean\n              // 2+ light modules in a row.\n              return\n            }\n            if (start === null) {\n              // Just a single dark module.\n              ops.push(`M${x + margin},${y + margin} h1v1H${x + margin}z`)\n            }\n            else {\n              // Otherwise finish the current line.\n              ops.push(\n                `M${start + margin},${y + margin} h${x + 1 - start}v1H${\n                  start + margin\n                }z`\n              )\n            }\n            return\n          }\n\n          if (cell && start === null) {\n            start = x\n          }\n        })\n      })\n      return ops.join('')\n    }\n\n    function svgInfo(\n      qr: qrcodegen.QrCode,\n      size: number,\n      iconConfig: {\n        iconSrc: string\n        iconBorderRadius: number\n        iconSize: number\n        iconBackgroundColor: string\n      } | null\n    ): {\n      innerHtml: string\n      numCells: number\n    } {\n      const cells = qr.getModules()\n      const numCells = cells.length\n      const cellsToDraw = cells\n      let svgInnerHtml = ''\n      const path1Html = `<path fill=\"transparent\" d=\"M0,0 h${numCells}v${numCells}H0z\" shape-rendering=\"crispEdges\"></path>`\n      const path2Html = `<path fill=\"${props.color}\" d=\"${generatePath(cellsToDraw, 0)}\" shape-rendering=\"crispEdges\"></path>`\n      let iconHtml = ''\n      if (iconConfig) {\n        const { iconSrc, iconSize } = iconConfig\n\n        const DEFAULT_IMG_SCALE = 0.1\n        const defaultSize = Math.floor(size * DEFAULT_IMG_SCALE)\n        const scale = numCells / size\n        const h = (iconSize || defaultSize) * scale\n        const w = (iconSize || defaultSize) * scale\n        const x = cells.length / 2 - w / 2\n        const y = cells.length / 2 - h / 2\n        iconHtml += `<image href=\"${iconSrc}\" width=\"${w}\" height=\"${h}\" x=\"${x}\" y=\"${y}\" preserveAspectRatio=\"none\"></image>`\n      }\n      svgInnerHtml += path1Html\n      svgInnerHtml += path2Html\n      svgInnerHtml += iconHtml\n      return {\n        innerHtml: svgInnerHtml,\n        numCells\n      }\n    }\n\n    const svgInfoRef = computed(() =>\n      svgInfo(\n        qr.value,\n        props.size,\n        props.iconSrc\n          ? {\n              iconSrc: props.iconSrc,\n              iconBorderRadius: props.iconBorderRadius,\n              iconSize: props.iconSize,\n              iconBackgroundColor: props.iconBackgroundColor\n            }\n          : null\n      )\n    )\n\n    return {\n      canvasRef,\n      mergedClsPrefix: mergedClsPrefixRef,\n      cssVars: inlineThemeDisabled ? undefined : cssVarsRef,\n      themeClass: themeClassHandle?.themeClass,\n      svgInfo: svgInfoRef\n    }\n  },\n  render() {\n    const {\n      mergedClsPrefix,\n      backgroundColor,\n      padding,\n      cssVars,\n      themeClass,\n      size,\n      type\n    } = this\n\n    return (\n      <div\n        class={[`${mergedClsPrefix}-qr-code`, themeClass]}\n        style={{\n          padding: typeof padding === 'number' ? `${padding}px` : padding,\n          backgroundColor,\n          width: `${size}px`,\n          height: `${size}px`,\n          ...cssVars\n        }}\n      >\n        {type === 'canvas' ? (\n          <canvas\n            ref=\"canvasRef\"\n            style={{\n              width: `${size}px`,\n              height: `${size}px`\n            }}\n          />\n        ) : (\n          <svg\n            height={size}\n            width={size}\n            viewBox={`0 0 ${this.svgInfo.numCells} ${this.svgInfo.numCells}`}\n            role=\"img\"\n            innerHTML={this.svgInfo.innerHtml}\n          />\n        )}\n      </div>\n    )\n  }\n})\n"
  },
  {
    "path": "src/qr-code/src/qrcodegen.ts",
    "content": "/* eslint-disable ts/no-namespace */\n/*\n * QR Code generator library (TypeScript)\n *\n * Copyright (c) Project Nayuki. (MIT License)\n * https://www.nayuki.io/page/qr-code-generator-library\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of\n * this software and associated documentation files (the \"Software\"), to deal in\n * the Software without restriction, including without limitation the rights to\n * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of\n * the Software, and to permit persons to whom the Software is furnished to do so,\n * subject to the following conditions:\n * - The above copyright notice and this permission notice shall be included in\n *   all copies or substantial portions of the Software.\n * - The Software is provided \"as is\", without warranty of any kind, express or\n *   implied, including but not limited to the warranties of merchantability,\n *   fitness for a particular purpose and noninfringement. In no event shall the\n *   authors or copyright holders be liable for any claim, damages or other\n *   liability, whether in an action of contract, tort or otherwise, arising from,\n *   out of or in connection with the Software or the use or other dealings in the\n *   Software.\n */\n\n'use strict'\n\nnamespace qrcodegen {\n  type bit = number\n  type byte = number\n  type int = number\n\n  /* ---- QR Code symbol class ---- */\n\n  /*\n   * A QR Code symbol, which is a type of two-dimension barcode.\n   * Invented by Denso Wave and described in the ISO/IEC 18004 standard.\n   * Instances of this class represent an immutable square grid of dark and light cells.\n   * The class provides static factory functions to create a QR Code from text or binary data.\n   * The class covers the QR Code Model 2 specification, supporting all versions (sizes)\n   * from 1 to 40, all 4 error correction levels, and 4 character encoding modes.\n   *\n   * Ways to create a QR Code object:\n   * - High level: Take the payload data and call QrCode.encodeText() or QrCode.encodeBinary().\n   * - Mid level: Custom-make the list of segments and call QrCode.encodeSegments().\n   * - Low level: Custom-make the array of data codeword bytes (including\n   *   segment headers and final padding, excluding error correction codewords),\n   *   supply the appropriate version number, and call the QrCode() constructor.\n   * (Note that all ways require supplying the desired error correction level.)\n   */\n  export class QrCode {\n    /* -- Static factory functions (high level) -- */\n\n    // Returns a QR Code representing the given Unicode text string at the given error correction level.\n    // As a conservative upper bound, this function is guaranteed to succeed for strings that have 738 or fewer\n    // Unicode code points (not UTF-16 code units) if the low error correction level is used. The smallest possible\n    // QR Code version is automatically chosen for the output. The ECC level of the result may be higher than the\n    // ecl argument if it can be done without increasing the version.\n    public static encodeText(text: string, ecl: QrCode.Ecc): QrCode {\n      const segs: QrSegment[] = qrcodegen.QrSegment.makeSegments(text)\n      return QrCode.encodeSegments(segs, ecl)\n    }\n\n    // Returns a QR Code representing the given binary data at the given error correction level.\n    // This function always encodes using the binary segment mode, not any text mode. The maximum number of\n    // bytes allowed is 2953. The smallest possible QR Code version is automatically chosen for the output.\n    // The ECC level of the result may be higher than the ecl argument if it can be done without increasing the version.\n    public static encodeBinary(\n      data: Readonly<byte[]>,\n      ecl: QrCode.Ecc\n    ): QrCode {\n      const seg: QrSegment = qrcodegen.QrSegment.makeBytes(data)\n      return QrCode.encodeSegments([seg], ecl)\n    }\n\n    /* -- Static factory functions (mid level) -- */\n\n    // Returns a QR Code representing the given segments with the given encoding parameters.\n    // The smallest possible QR Code version within the given range is automatically\n    // chosen for the output. Iff boostEcl is true, then the ECC level of the result\n    // may be higher than the ecl argument if it can be done without increasing the\n    // version. The mask number is either between 0 to 7 (inclusive) to force that\n    // mask, or -1 to automatically choose an appropriate mask (which may be slow).\n    // This function allows the user to create a custom sequence of segments that switches\n    // between modes (such as alphanumeric and byte) to encode text in less space.\n    // This is a mid-level API; the high-level API is encodeText() and encodeBinary().\n    public static encodeSegments(\n      segs: Readonly<QrSegment[]>,\n      ecl: QrCode.Ecc,\n      minVersion: int = 1,\n      maxVersion: int = 40,\n      mask: int = -1,\n      boostEcl: boolean = true\n    ): QrCode {\n      if (\n        !(\n          QrCode.MIN_VERSION <= minVersion\n          && minVersion <= maxVersion\n          && maxVersion <= QrCode.MAX_VERSION\n        )\n        || mask < -1\n        || mask > 7\n      ) {\n        throw new RangeError('Invalid value')\n      }\n\n      // Find the minimal version number to use\n      let version: int\n      let dataUsedBits: int\n      for (version = minVersion; ; version++) {\n        const dataCapacityBits: int\n          = QrCode.getNumDataCodewords(version, ecl) * 8 // Number of data bits available\n        const usedBits: number = QrSegment.getTotalBits(segs, version)\n        if (usedBits <= dataCapacityBits) {\n          dataUsedBits = usedBits\n          break // This version number is found to be suitable\n        }\n        if (version >= maxVersion) {\n          // All versions in the range could not fit the given data\n          throw new RangeError('Data too long')\n        }\n      }\n\n      // Increase the error correction level while the data still fits in the current version number\n      for (const newEcl of [\n        QrCode.Ecc.MEDIUM,\n        QrCode.Ecc.QUARTILE,\n        QrCode.Ecc.HIGH\n      ]) {\n        // From low to high\n        if (\n          boostEcl\n          && dataUsedBits <= QrCode.getNumDataCodewords(version, newEcl) * 8\n        ) {\n          ecl = newEcl\n        }\n      }\n\n      // Concatenate all segments to create the data bit string\n      const bb: bit[] = []\n      for (const seg of segs) {\n        appendBits(seg.mode.modeBits, 4, bb)\n        appendBits(seg.numChars, seg.mode.numCharCountBits(version), bb)\n        for (const b of seg.getData()) {\n          bb.push(b)\n        }\n      }\n\n      // Add terminator and pad up to a byte if applicable\n      const dataCapacityBits: int = QrCode.getNumDataCodewords(version, ecl) * 8\n      appendBits(0, Math.min(4, dataCapacityBits - bb.length), bb)\n      appendBits(0, (8 - (bb.length % 8)) % 8, bb)\n\n      // Pad with alternating bytes until data capacity is reached\n      for (\n        let padByte = 0xEC;\n        bb.length < dataCapacityBits;\n        padByte ^= 0xEC ^ 0x11\n      ) {\n        appendBits(padByte, 8, bb)\n      }\n\n      // Pack bits into bytes in big endian\n      const dataCodewords: byte[] = []\n      while (dataCodewords.length * 8 < bb.length) {\n        dataCodewords.push(0)\n      }\n      bb.forEach(\n        (b: bit, i: int) => (dataCodewords[i >>> 3] |= b << (7 - (i & 7)))\n      )\n\n      // Create the QR Code object\n      return new QrCode(version, ecl, dataCodewords, mask)\n    }\n\n    /* -- Fields -- */\n\n    // The width and height of this QR Code, measured in modules, between\n    // 21 and 177 (inclusive). This is equal to version * 4 + 17.\n    public readonly size: int\n\n    // The index of the mask pattern used in this QR Code, which is between 0 and 7 (inclusive).\n    // Even if a QR Code is created with automatic masking requested (mask = -1),\n    // the resulting object still has a mask value between 0 and 7.\n    public readonly mask: int\n\n    // The modules of this QR Code (false = light, true = dark).\n    // Immutable after constructor finishes. Accessed through getModule().\n    private readonly modules: boolean[][] = []\n\n    // Indicates function modules that are not subjected to masking. Discarded when constructor finishes.\n    private readonly isFunction: boolean[][] = []\n\n    /* -- Constructor (low level) and fields -- */\n\n    // Creates a new QR Code with the given version number,\n    // error correction level, data codeword bytes, and mask number.\n    // This is a low-level API that most users should not use directly.\n    // A mid-level API is the encodeSegments() function.\n    public constructor(\n      // The version number of this QR Code, which is between 1 and 40 (inclusive).\n      // This determines the size of this barcode.\n      public readonly version: int,\n\n      // The error correction level used in this QR Code.\n      public readonly errorCorrectionLevel: QrCode.Ecc,\n\n      dataCodewords: Readonly<byte[]>,\n\n      msk: int\n    ) {\n      // Check scalar arguments\n      if (version < QrCode.MIN_VERSION || version > QrCode.MAX_VERSION) {\n        throw new RangeError('Version value out of range')\n      }\n      if (msk < -1 || msk > 7) {\n        throw new RangeError('Mask value out of range')\n      }\n      this.size = version * 4 + 17\n\n      // Initialize both grids to be size*size arrays of Boolean false\n      const row: boolean[] = []\n      for (let i = 0; i < this.size; i++) {\n        row.push(false)\n      }\n      for (let i = 0; i < this.size; i++) {\n        this.modules.push(row.slice()) // Initially all light\n        this.isFunction.push(row.slice())\n      }\n\n      // Compute ECC, draw modules\n      this.drawFunctionPatterns()\n      const allCodewords: byte[] = this.addEccAndInterleave(dataCodewords)\n      this.drawCodewords(allCodewords)\n\n      // Do masking\n      if (msk === -1) {\n        // Automatically choose best mask\n        let minPenalty: int = 1000000000\n        for (let i = 0; i < 8; i++) {\n          this.applyMask(i)\n          this.drawFormatBits(i)\n          const penalty: int = this.getPenaltyScore()\n          if (penalty < minPenalty) {\n            msk = i\n            minPenalty = penalty\n          }\n          this.applyMask(i) // Undoes the mask due to XOR\n        }\n      }\n      this.mask = msk\n      this.applyMask(msk) // Apply the final choice of mask\n      this.drawFormatBits(msk) // Overwrite old format bits\n\n      this.isFunction = []\n    }\n\n    /* -- Accessor methods -- */\n\n    // Returns the color of the module (pixel) at the given coordinates, which is false\n    // for light or true for dark. The top left corner has the coordinates (x=0, y=0).\n    // If the given coordinates are out of bounds, then false (light) is returned.\n    public getModule(x: int, y: int): boolean {\n      return (\n        x >= 0 && x < this.size && y >= 0 && y < this.size && this.modules[y][x]\n      )\n    }\n\n    // Modified to expose modules for easy access\n    public getModules(): boolean[][] {\n      return this.modules\n    }\n\n    /* -- Private helper methods for constructor: Drawing function modules -- */\n\n    // Reads this object's version field, and draws and marks all function modules.\n    private drawFunctionPatterns(): void {\n      // Draw horizontal and vertical timing patterns\n      for (let i = 0; i < this.size; i++) {\n        this.setFunctionModule(6, i, i % 2 === 0)\n        this.setFunctionModule(i, 6, i % 2 === 0)\n      }\n\n      // Draw 3 finder patterns (all corners except bottom right; overwrites some timing modules)\n      this.drawFinderPattern(3, 3)\n      this.drawFinderPattern(this.size - 4, 3)\n      this.drawFinderPattern(3, this.size - 4)\n\n      // Draw numerous alignment patterns\n      const alignPatPos: int[] = this.getAlignmentPatternPositions()\n      const numAlign: int = alignPatPos.length\n      for (let i = 0; i < numAlign; i++) {\n        for (let j = 0; j < numAlign; j++) {\n          // Don't draw on the three finder corners\n          if (\n            !(\n              (i === 0 && j === 0)\n              || (i === 0 && j === numAlign - 1)\n              || (i === numAlign - 1 && j === 0)\n            )\n          ) {\n            this.drawAlignmentPattern(alignPatPos[i], alignPatPos[j])\n          }\n        }\n      }\n\n      // Draw configuration data\n      this.drawFormatBits(0) // Dummy mask value; overwritten later in the constructor\n      this.drawVersion()\n    }\n\n    // Draws two copies of the format bits (with its own error correction code)\n    // based on the given mask and this object's error correction level field.\n    private drawFormatBits(mask: int): void {\n      // Calculate error correction code and pack bits\n      const data: int = (this.errorCorrectionLevel.formatBits << 3) | mask // errCorrLvl is uint2, mask is uint3\n      let rem: int = data\n      for (let i = 0; i < 10; i++) {\n        rem = (rem << 1) ^ ((rem >>> 9) * 0x537)\n      }\n      const bits = ((data << 10) | rem) ^ 0x5412 // uint15\n\n      // Draw first copy\n      for (let i = 0; i <= 5; i++) {\n        this.setFunctionModule(8, i, getBit(bits, i))\n      }\n      this.setFunctionModule(8, 7, getBit(bits, 6))\n      this.setFunctionModule(8, 8, getBit(bits, 7))\n      this.setFunctionModule(7, 8, getBit(bits, 8))\n      for (let i = 9; i < 15; i++) {\n        this.setFunctionModule(14 - i, 8, getBit(bits, i))\n      }\n\n      // Draw second copy\n      for (let i = 0; i < 8; i++) {\n        this.setFunctionModule(this.size - 1 - i, 8, getBit(bits, i))\n      }\n      for (let i = 8; i < 15; i++) {\n        this.setFunctionModule(8, this.size - 15 + i, getBit(bits, i))\n      }\n      this.setFunctionModule(8, this.size - 8, true) // Always dark\n    }\n\n    // Draws two copies of the version bits (with its own error correction code),\n    // based on this object's version field, iff 7 <= version <= 40.\n    private drawVersion(): void {\n      if (this.version < 7) {\n        return\n      }\n\n      // Calculate error correction code and pack bits\n      let rem: int = this.version // version is uint6, in the range [7, 40]\n      for (let i = 0; i < 12; i++) {\n        rem = (rem << 1) ^ ((rem >>> 11) * 0x1F25)\n      }\n      const bits: int = (this.version << 12) | rem // uint18\n\n      // Draw two copies\n      for (let i = 0; i < 18; i++) {\n        const color: boolean = getBit(bits, i)\n        const a: int = this.size - 11 + (i % 3)\n        const b: int = Math.floor(i / 3)\n        this.setFunctionModule(a, b, color)\n        this.setFunctionModule(b, a, color)\n      }\n    }\n\n    // Draws a 9*9 finder pattern including the border separator,\n    // with the center module at (x, y). Modules can be out of bounds.\n    private drawFinderPattern(x: int, y: int): void {\n      for (let dy = -4; dy <= 4; dy++) {\n        for (let dx = -4; dx <= 4; dx++) {\n          const dist: int = Math.max(Math.abs(dx), Math.abs(dy)) // Chebyshev/infinity norm\n          const xx: int = x + dx\n          const yy: int = y + dy\n          if (xx >= 0 && xx < this.size && yy >= 0 && yy < this.size) {\n            this.setFunctionModule(xx, yy, dist !== 2 && dist !== 4)\n          }\n        }\n      }\n    }\n\n    // Draws a 5*5 alignment pattern, with the center module\n    // at (x, y). All modules must be in bounds.\n    private drawAlignmentPattern(x: int, y: int): void {\n      for (let dy = -2; dy <= 2; dy++) {\n        for (let dx = -2; dx <= 2; dx++) {\n          this.setFunctionModule(\n            x + dx,\n            y + dy,\n            Math.max(Math.abs(dx), Math.abs(dy)) !== 1\n          )\n        }\n      }\n    }\n\n    // Sets the color of a module and marks it as a function module.\n    // Only used by the constructor. Coordinates must be in bounds.\n    private setFunctionModule(x: int, y: int, isDark: boolean): void {\n      this.modules[y][x] = isDark\n      this.isFunction[y][x] = true\n    }\n\n    /* -- Private helper methods for constructor: Codewords and masking -- */\n\n    // Returns a new byte string representing the given data with the appropriate error correction\n    // codewords appended to it, based on this object's version and error correction level.\n    private addEccAndInterleave(data: Readonly<byte[]>): byte[] {\n      const ver: int = this.version\n      const ecl: QrCode.Ecc = this.errorCorrectionLevel\n      if (data.length !== QrCode.getNumDataCodewords(ver, ecl)) {\n        throw new RangeError('Invalid argument')\n      }\n\n      // Calculate parameter numbers\n      const numBlocks: int\n        = QrCode.NUM_ERROR_CORRECTION_BLOCKS[ecl.ordinal][ver]\n      const blockEccLen: int = QrCode.ECC_CODEWORDS_PER_BLOCK[ecl.ordinal][ver]\n      const rawCodewords: int = Math.floor(QrCode.getNumRawDataModules(ver) / 8)\n      const numShortBlocks: int = numBlocks - (rawCodewords % numBlocks)\n      const shortBlockLen: int = Math.floor(rawCodewords / numBlocks)\n\n      // Split data into blocks and append ECC to each block\n      const blocks: byte[][] = []\n      const rsDiv: byte[] = QrCode.reedSolomonComputeDivisor(blockEccLen)\n      for (let i = 0, k = 0; i < numBlocks; i++) {\n        const dat: byte[] = data.slice(\n          k,\n          k + shortBlockLen - blockEccLen + (i < numShortBlocks ? 0 : 1)\n        )\n        k += dat.length\n        const ecc: byte[] = QrCode.reedSolomonComputeRemainder(dat, rsDiv)\n        if (i < numShortBlocks) {\n          dat.push(0)\n        }\n        blocks.push(dat.concat(ecc))\n      }\n\n      // Interleave (not concatenate) the bytes from every block into a single sequence\n      const result: byte[] = []\n      for (let i = 0; i < blocks[0].length; i++) {\n        blocks.forEach((block, j) => {\n          // Skip the padding byte in short blocks\n          if (i !== shortBlockLen - blockEccLen || j >= numShortBlocks) {\n            result.push(block[i])\n          }\n        })\n      }\n      return result\n    }\n\n    // Draws the given sequence of 8-bit codewords (data and error correction) onto the entire\n    // data area of this QR Code. Function modules need to be marked off before this is called.\n    private drawCodewords(data: Readonly<byte[]>): void {\n      if (\n        data.length\n        !== Math.floor(QrCode.getNumRawDataModules(this.version) / 8)\n      ) {\n        throw new RangeError('Invalid argument')\n      }\n      let i: int = 0 // Bit index into the data\n      // Do the funny zigzag scan\n      for (let right = this.size - 1; right >= 1; right -= 2) {\n        // Index of right column in each column pair\n        if (right === 6) {\n          right = 5\n        }\n        for (let vert = 0; vert < this.size; vert++) {\n          // Vertical counter\n          for (let j = 0; j < 2; j++) {\n            const x: int = right - j // Actual x coordinate\n            const upward: boolean = ((right + 1) & 2) === 0\n            const y: int = upward ? this.size - 1 - vert : vert // Actual y coordinate\n            if (!this.isFunction[y][x] && i < data.length * 8) {\n              this.modules[y][x] = getBit(data[i >>> 3], 7 - (i & 7))\n              i++\n            }\n            // If this QR Code has any remainder bits (0 to 7), they were assigned as\n            // 0/false/light by the constructor and are left unchanged by this method\n          }\n        }\n      }\n    }\n\n    // XORs the codeword modules in this QR Code with the given mask pattern.\n    // The function modules must be marked and the codeword bits must be drawn\n    // before masking. Due to the arithmetic of XOR, calling applyMask() with\n    // the same mask value a second time will undo the mask. A final well-formed\n    // QR Code needs exactly one (not zero, two, etc.) mask applied.\n    private applyMask(mask: int): void {\n      if (mask < 0 || mask > 7) {\n        throw new RangeError('Mask value out of range')\n      }\n      for (let y = 0; y < this.size; y++) {\n        for (let x = 0; x < this.size; x++) {\n          let invert: boolean\n          switch (mask) {\n            case 0:\n              invert = (x + y) % 2 === 0\n              break\n            case 1:\n              invert = y % 2 === 0\n              break\n            case 2:\n              invert = x % 3 === 0\n              break\n            case 3:\n              invert = (x + y) % 3 === 0\n              break\n            case 4:\n              invert = (Math.floor(x / 3) + Math.floor(y / 2)) % 2 === 0\n              break\n            case 5:\n              invert = ((x * y) % 2) + ((x * y) % 3) === 0\n              break\n            case 6:\n              invert = (((x * y) % 2) + ((x * y) % 3)) % 2 === 0\n              break\n            case 7:\n              invert = (((x + y) % 2) + ((x * y) % 3)) % 2 === 0\n              break\n            default:\n              throw new Error('Unreachable')\n          }\n          if (!this.isFunction[y][x] && invert) {\n            this.modules[y][x] = !this.modules[y][x]\n          }\n        }\n      }\n    }\n\n    // Calculates and returns the penalty score based on state of this QR Code's current modules.\n    // This is used by the automatic mask choice algorithm to find the mask pattern that yields the lowest score.\n    private getPenaltyScore(): int {\n      let result: int = 0\n\n      // Adjacent modules in row having same color, and finder-like patterns\n      for (let y = 0; y < this.size; y++) {\n        let runColor = false\n        let runX = 0\n        const runHistory = [0, 0, 0, 0, 0, 0, 0]\n        for (let x = 0; x < this.size; x++) {\n          if (this.modules[y][x] === runColor) {\n            runX++\n            if (runX === 5) {\n              result += QrCode.PENALTY_N1\n            }\n            else if (runX > 5) {\n              result++\n            }\n          }\n          else {\n            this.finderPenaltyAddHistory(runX, runHistory)\n            if (!runColor) {\n              result\n                += this.finderPenaltyCountPatterns(runHistory) * QrCode.PENALTY_N3\n            }\n            runColor = this.modules[y][x]\n            runX = 1\n          }\n        }\n        result\n          += this.finderPenaltyTerminateAndCount(runColor, runX, runHistory)\n            * QrCode.PENALTY_N3\n      }\n      // Adjacent modules in column having same color, and finder-like patterns\n      for (let x = 0; x < this.size; x++) {\n        let runColor = false\n        let runY = 0\n        const runHistory = [0, 0, 0, 0, 0, 0, 0]\n        for (let y = 0; y < this.size; y++) {\n          if (this.modules[y][x] === runColor) {\n            runY++\n            if (runY === 5) {\n              result += QrCode.PENALTY_N1\n            }\n            else if (runY > 5) {\n              result++\n            }\n          }\n          else {\n            this.finderPenaltyAddHistory(runY, runHistory)\n            if (!runColor) {\n              result\n                += this.finderPenaltyCountPatterns(runHistory) * QrCode.PENALTY_N3\n            }\n            runColor = this.modules[y][x]\n            runY = 1\n          }\n        }\n        result\n          += this.finderPenaltyTerminateAndCount(runColor, runY, runHistory)\n            * QrCode.PENALTY_N3\n      }\n\n      // 2*2 blocks of modules having same color\n      for (let y = 0; y < this.size - 1; y++) {\n        for (let x = 0; x < this.size - 1; x++) {\n          const color: boolean = this.modules[y][x]\n          if (\n            color === this.modules[y][x + 1]\n            && color === this.modules[y + 1][x]\n            && color === this.modules[y + 1][x + 1]\n          ) {\n            result += QrCode.PENALTY_N2\n          }\n        }\n      }\n\n      // Balance of dark and light modules\n      let dark: int = 0\n      for (const row of this.modules) {\n        dark = row.reduce((sum, color) => sum + (color ? 1 : 0), dark)\n      }\n      const total: int = this.size * this.size // Note that size is odd, so dark/total != 1/2\n      // Compute the smallest integer k >= 0 such that (45-5k)% <= dark/total <= (55+5k)%\n      const k: int = Math.ceil(Math.abs(dark * 20 - total * 10) / total) - 1\n      result += k * QrCode.PENALTY_N4\n      return result\n    }\n\n    /* -- Private helper functions -- */\n\n    // Returns an ascending list of positions of alignment patterns for this version number.\n    // Each position is in the range [0,177), and are used on both the x and y axes.\n    // This could be implemented as lookup table of 40 variable-length lists of integers.\n    private getAlignmentPatternPositions(): int[] {\n      if (this.version === 1) {\n        return []\n      }\n      else {\n        const numAlign: int = Math.floor(this.version / 7) + 2\n        const step: int\n          = this.version === 32\n            ? 26\n            : Math.ceil((this.version * 4 + 4) / (numAlign * 2 - 2)) * 2\n        const result: int[] = [6]\n        for (let pos = this.size - 7; result.length < numAlign; pos -= step) {\n          result.splice(1, 0, pos)\n        }\n        return result\n      }\n    }\n\n    // Returns the number of data bits that can be stored in a QR Code of the given version number, after\n    // all function modules are excluded. This includes remainder bits, so it might not be a multiple of 8.\n    // The result is in the range [208, 29648]. This could be implemented as a 40-entry lookup table.\n    private static getNumRawDataModules(ver: int): int {\n      if (ver < QrCode.MIN_VERSION || ver > QrCode.MAX_VERSION) {\n        throw new RangeError('Version number out of range')\n      }\n      let result: int = (16 * ver + 128) * ver + 64\n      if (ver >= 2) {\n        const numAlign: int = Math.floor(ver / 7) + 2\n        result -= (25 * numAlign - 10) * numAlign - 55\n        if (ver >= 7) {\n          result -= 36\n        }\n      }\n      return result\n    }\n\n    // Returns the number of 8-bit data (i.e. not error correction) codewords contained in any\n    // QR Code of the given version number and error correction level, with remainder bits discarded.\n    // This stateless pure function could be implemented as a (40*4)-cell lookup table.\n    private static getNumDataCodewords(ver: int, ecl: QrCode.Ecc): int {\n      return (\n        Math.floor(QrCode.getNumRawDataModules(ver) / 8)\n        - QrCode.ECC_CODEWORDS_PER_BLOCK[ecl.ordinal][ver]\n        * QrCode.NUM_ERROR_CORRECTION_BLOCKS[ecl.ordinal][ver]\n      )\n    }\n\n    // Returns a Reed-Solomon ECC generator polynomial for the given degree. This could be\n    // implemented as a lookup table over all possible parameter values, instead of as an algorithm.\n    private static reedSolomonComputeDivisor(degree: int): byte[] {\n      if (degree < 1 || degree > 255) {\n        throw new RangeError('Degree out of range')\n      }\n      // Polynomial coefficients are stored from highest to lowest power, excluding the leading term which is always 1.\n      // For example the polynomial x^3 + 255x^2 + 8x + 93 is stored as the uint8 array [255, 8, 93].\n      const result: byte[] = []\n      for (let i = 0; i < degree - 1; i++) {\n        result.push(0)\n      }\n      result.push(1) // Start off with the monomial x^0\n\n      // Compute the product polynomial (x - r^0) * (x - r^1) * (x - r^2) * ... * (x - r^{degree-1}),\n      // and drop the highest monomial term which is always 1x^degree.\n      // Note that r = 0x02, which is a generator element of this field GF(2^8/0x11D).\n      let root = 1\n      for (let i = 0; i < degree; i++) {\n        // Multiply the current product by (x - r^i)\n        for (let j = 0; j < result.length; j++) {\n          result[j] = QrCode.reedSolomonMultiply(result[j], root)\n          if (j + 1 < result.length) {\n            result[j] ^= result[j + 1]\n          }\n        }\n        root = QrCode.reedSolomonMultiply(root, 0x02)\n      }\n      return result\n    }\n\n    // Returns the Reed-Solomon error correction codeword for the given data and divisor polynomials.\n    private static reedSolomonComputeRemainder(\n      data: Readonly<byte[]>,\n      divisor: Readonly<byte[]>\n    ): byte[] {\n      const result: byte[] = divisor.map(_ => 0)\n      for (const b of data) {\n        // Polynomial division\n        const factor: byte = b ^ (result.shift() as byte)\n        result.push(0)\n        divisor.forEach(\n          (coef, i) => (result[i] ^= QrCode.reedSolomonMultiply(coef, factor))\n        )\n      }\n      return result\n    }\n\n    // Returns the product of the two given field elements modulo GF(2^8/0x11D). The arguments and result\n    // are unsigned 8-bit integers. This could be implemented as a lookup table of 256*256 entries of uint8.\n    private static reedSolomonMultiply(x: byte, y: byte): byte {\n      if (x >>> 8 !== 0 || y >>> 8 !== 0) {\n        throw new RangeError('Byte out of range')\n      }\n      // Russian peasant multiplication\n      let z: int = 0\n      for (let i = 7; i >= 0; i--) {\n        z = (z << 1) ^ ((z >>> 7) * 0x11D)\n        z ^= ((y >>> i) & 1) * x\n      }\n      return z\n    }\n\n    // Can only be called immediately after a light run is added, and\n    // returns either 0, 1, or 2. A helper function for getPenaltyScore().\n    private finderPenaltyCountPatterns(runHistory: Readonly<int[]>): int {\n      const n: int = runHistory[1]\n      const core: boolean\n        = n > 0\n          && runHistory[2] === n\n          && runHistory[3] === n * 3\n          && runHistory[4] === n\n          && runHistory[5] === n\n      return (\n        (core && runHistory[0] >= n * 4 && runHistory[6] >= n ? 1 : 0)\n        + (core && runHistory[6] >= n * 4 && runHistory[0] >= n ? 1 : 0)\n      )\n    }\n\n    // Must be called at the end of a line (row or column) of modules. A helper function for getPenaltyScore().\n    private finderPenaltyTerminateAndCount(\n      currentRunColor: boolean,\n      currentRunLength: int,\n      runHistory: int[]\n    ): int {\n      if (currentRunColor) {\n        // Terminate dark run\n        this.finderPenaltyAddHistory(currentRunLength, runHistory)\n        currentRunLength = 0\n      }\n      currentRunLength += this.size // Add light border to final run\n      this.finderPenaltyAddHistory(currentRunLength, runHistory)\n      return this.finderPenaltyCountPatterns(runHistory)\n    }\n\n    // Pushes the given value to the front and drops the last value. A helper function for getPenaltyScore().\n    private finderPenaltyAddHistory(\n      currentRunLength: int,\n      runHistory: int[]\n    ): void {\n      if (runHistory[0] === 0) {\n        currentRunLength += this.size\n      } // Add light border to initial run\n      runHistory.pop()\n      runHistory.unshift(currentRunLength)\n    }\n\n    /* -- Constants and tables -- */\n\n    // The minimum version number supported in the QR Code Model 2 standard.\n    public static readonly MIN_VERSION: int = 1\n    // The maximum version number supported in the QR Code Model 2 standard.\n    public static readonly MAX_VERSION: int = 40\n\n    // For use in getPenaltyScore(), when evaluating which mask is best.\n    private static readonly PENALTY_N1: int = 3\n    private static readonly PENALTY_N2: int = 3\n    private static readonly PENALTY_N3: int = 40\n    private static readonly PENALTY_N4: int = 10\n\n    private static readonly ECC_CODEWORDS_PER_BLOCK: int[][] = [\n      // Version: (note that index 0 is for padding, and is set to an illegal value)\n      // 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40    Error correction level\n      [\n        -1,\n        7,\n        10,\n        15,\n        20,\n        26,\n        18,\n        20,\n        24,\n        30,\n        18,\n        20,\n        24,\n        26,\n        30,\n        22,\n        24,\n        28,\n        30,\n        28,\n        28,\n        28,\n        28,\n        30,\n        30,\n        26,\n        28,\n        30,\n        30,\n        30,\n        30,\n        30,\n        30,\n        30,\n        30,\n        30,\n        30,\n        30,\n        30,\n        30,\n        30\n      ], // Low\n      [\n        -1,\n        10,\n        16,\n        26,\n        18,\n        24,\n        16,\n        18,\n        22,\n        22,\n        26,\n        30,\n        22,\n        22,\n        24,\n        24,\n        28,\n        28,\n        26,\n        26,\n        26,\n        26,\n        28,\n        28,\n        28,\n        28,\n        28,\n        28,\n        28,\n        28,\n        28,\n        28,\n        28,\n        28,\n        28,\n        28,\n        28,\n        28,\n        28,\n        28,\n        28\n      ], // Medium\n      [\n        -1,\n        13,\n        22,\n        18,\n        26,\n        18,\n        24,\n        18,\n        22,\n        20,\n        24,\n        28,\n        26,\n        24,\n        20,\n        30,\n        24,\n        28,\n        28,\n        26,\n        30,\n        28,\n        30,\n        30,\n        30,\n        30,\n        28,\n        30,\n        30,\n        30,\n        30,\n        30,\n        30,\n        30,\n        30,\n        30,\n        30,\n        30,\n        30,\n        30,\n        30\n      ], // Quartile\n      [\n        -1,\n        17,\n        28,\n        22,\n        16,\n        22,\n        28,\n        26,\n        26,\n        24,\n        28,\n        24,\n        28,\n        22,\n        24,\n        24,\n        30,\n        28,\n        28,\n        26,\n        28,\n        30,\n        24,\n        30,\n        30,\n        30,\n        30,\n        30,\n        30,\n        30,\n        30,\n        30,\n        30,\n        30,\n        30,\n        30,\n        30,\n        30,\n        30,\n        30,\n        30\n      ] // High\n    ]\n\n    private static readonly NUM_ERROR_CORRECTION_BLOCKS: int[][] = [\n      // Version: (note that index 0 is for padding, and is set to an illegal value)\n      // 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40    Error correction level\n      [\n        -1,\n        1,\n        1,\n        1,\n        1,\n        1,\n        2,\n        2,\n        2,\n        2,\n        4,\n        4,\n        4,\n        4,\n        4,\n        6,\n        6,\n        6,\n        6,\n        7,\n        8,\n        8,\n        9,\n        9,\n        10,\n        12,\n        12,\n        12,\n        13,\n        14,\n        15,\n        16,\n        17,\n        18,\n        19,\n        19,\n        20,\n        21,\n        22,\n        24,\n        25\n      ], // Low\n      [\n        -1,\n        1,\n        1,\n        1,\n        2,\n        2,\n        4,\n        4,\n        4,\n        5,\n        5,\n        5,\n        8,\n        9,\n        9,\n        10,\n        10,\n        11,\n        13,\n        14,\n        16,\n        17,\n        17,\n        18,\n        20,\n        21,\n        23,\n        25,\n        26,\n        28,\n        29,\n        31,\n        33,\n        35,\n        37,\n        38,\n        40,\n        43,\n        45,\n        47,\n        49\n      ], // Medium\n      [\n        -1,\n        1,\n        1,\n        2,\n        2,\n        4,\n        4,\n        6,\n        6,\n        8,\n        8,\n        8,\n        10,\n        12,\n        16,\n        12,\n        17,\n        16,\n        18,\n        21,\n        20,\n        23,\n        23,\n        25,\n        27,\n        29,\n        34,\n        34,\n        35,\n        38,\n        40,\n        43,\n        45,\n        48,\n        51,\n        53,\n        56,\n        59,\n        62,\n        65,\n        68\n      ], // Quartile\n      [\n        -1,\n        1,\n        1,\n        2,\n        4,\n        4,\n        4,\n        5,\n        6,\n        8,\n        8,\n        11,\n        11,\n        16,\n        16,\n        18,\n        16,\n        19,\n        21,\n        25,\n        25,\n        25,\n        34,\n        30,\n        32,\n        35,\n        37,\n        40,\n        42,\n        45,\n        48,\n        51,\n        54,\n        57,\n        60,\n        63,\n        66,\n        70,\n        74,\n        77,\n        81\n      ] // High\n    ]\n  }\n\n  // Appends the given number of low-order bits of the given value\n  // to the given buffer. Requires 0 <= len <= 31 and 0 <= val < 2^len.\n  function appendBits(val: int, len: int, bb: bit[]): void {\n    if (len < 0 || len > 31 || val >>> len !== 0) {\n      throw new RangeError('Value out of range')\n    }\n    for (\n      let i = len - 1;\n      i >= 0;\n      i-- // Append bit by bit\n    ) {\n      bb.push((val >>> i) & 1)\n    }\n  }\n\n  // Returns true iff the i'th bit of x is set to 1.\n  function getBit(x: int, i: int): boolean {\n    return ((x >>> i) & 1) !== 0\n  }\n\n  /* ---- Data segment class ---- */\n\n  /*\n   * A segment of character/binary/control data in a QR Code symbol.\n   * Instances of this class are immutable.\n   * The mid-level way to create a segment is to take the payload data\n   * and call a static factory function such as QrSegment.makeNumeric().\n   * The low-level way to create a segment is to custom-make the bit buffer\n   * and call the QrSegment() constructor with appropriate values.\n   * This segment class imposes no length restrictions, but QR Codes have restrictions.\n   * Even in the most favorable conditions, a QR Code can only hold 7089 characters of data.\n   * Any segment longer than this is meaningless for the purpose of generating QR Codes.\n   */\n  export class QrSegment {\n    /* -- Static factory functions (mid level) -- */\n\n    // Returns a segment representing the given binary data encoded in\n    // byte mode. All input byte arrays are acceptable. Any text string\n    // can be converted to UTF-8 bytes and encoded as a byte mode segment.\n    public static makeBytes(data: Readonly<byte[]>): QrSegment {\n      const bb: bit[] = []\n      for (const b of data) {\n        appendBits(b, 8, bb)\n      }\n      return new QrSegment(QrSegment.Mode.BYTE, data.length, bb)\n    }\n\n    // Returns a segment representing the given string of decimal digits encoded in numeric mode.\n    public static makeNumeric(digits: string): QrSegment {\n      if (!QrSegment.isNumeric(digits)) {\n        throw new RangeError('String contains non-numeric characters')\n      }\n      const bb: bit[] = []\n      for (let i = 0; i < digits.length;) {\n        // Consume up to 3 digits per iteration\n        const n: int = Math.min(digits.length - i, 3)\n        appendBits(Number.parseInt(digits.substr(i, n), 10), n * 3 + 1, bb)\n        i += n\n      }\n      return new QrSegment(QrSegment.Mode.NUMERIC, digits.length, bb)\n    }\n\n    // Returns a segment representing the given text string encoded in alphanumeric mode.\n    // The characters allowed are: 0 to 9, A to Z (uppercase only), space,\n    // dollar, percent, asterisk, plus, hyphen, period, slash, colon.\n    public static makeAlphanumeric(text: string): QrSegment {\n      if (!QrSegment.isAlphanumeric(text)) {\n        throw new RangeError(\n          'String contains unencodable characters in alphanumeric mode'\n        )\n      }\n      const bb: bit[] = []\n      let i: int\n      for (i = 0; i + 2 <= text.length; i += 2) {\n        // Process groups of 2\n        let temp: int\n          = QrSegment.ALPHANUMERIC_CHARSET.indexOf(text.charAt(i)) * 45\n        temp += QrSegment.ALPHANUMERIC_CHARSET.indexOf(text.charAt(i + 1))\n        appendBits(temp, 11, bb)\n      }\n      if (i < text.length) {\n        // 1 character remaining\n        appendBits(\n          QrSegment.ALPHANUMERIC_CHARSET.indexOf(text.charAt(i)),\n          6,\n          bb\n        )\n      }\n      return new QrSegment(QrSegment.Mode.ALPHANUMERIC, text.length, bb)\n    }\n\n    // Returns a new mutable list of zero or more segments to represent the given Unicode text string.\n    // The result may use various segment modes and switch modes to optimize the length of the bit stream.\n    public static makeSegments(text: string): QrSegment[] {\n      // Select the most efficient segment encoding automatically\n      if (text === '') {\n        return []\n      }\n      else if (QrSegment.isNumeric(text)) {\n        return [QrSegment.makeNumeric(text)]\n      }\n      else if (QrSegment.isAlphanumeric(text)) {\n        return [QrSegment.makeAlphanumeric(text)]\n      }\n      else {\n        return [QrSegment.makeBytes(QrSegment.toUtf8ByteArray(text))]\n      }\n    }\n\n    // Returns a segment representing an Extended Channel Interpretation\n    // (ECI) designator with the given assignment value.\n    public static makeEci(assignVal: int): QrSegment {\n      const bb: bit[] = []\n      if (assignVal < 0) {\n        throw new RangeError('ECI assignment value out of range')\n      }\n      else if (assignVal < 1 << 7) {\n        appendBits(assignVal, 8, bb)\n      }\n      else if (assignVal < 1 << 14) {\n        appendBits(0b10, 2, bb)\n        appendBits(assignVal, 14, bb)\n      }\n      else if (assignVal < 1000000) {\n        appendBits(0b110, 3, bb)\n        appendBits(assignVal, 21, bb)\n      }\n      else {\n        throw new RangeError('ECI assignment value out of range')\n      }\n      return new QrSegment(QrSegment.Mode.ECI, 0, bb)\n    }\n\n    // Tests whether the given string can be encoded as a segment in numeric mode.\n    // A string is encodable iff each character is in the range 0 to 9.\n    public static isNumeric(text: string): boolean {\n      return QrSegment.NUMERIC_REGEX.test(text)\n    }\n\n    // Tests whether the given string can be encoded as a segment in alphanumeric mode.\n    // A string is encodable iff each character is in the following set: 0 to 9, A to Z\n    // (uppercase only), space, dollar, percent, asterisk, plus, hyphen, period, slash, colon.\n    public static isAlphanumeric(text: string): boolean {\n      return QrSegment.ALPHANUMERIC_REGEX.test(text)\n    }\n\n    /* -- Constructor (low level) and fields -- */\n\n    // Creates a new QR Code segment with the given attributes and data.\n    // The character count (numChars) must agree with the mode and the bit buffer length,\n    // but the constraint isn't checked. The given bit buffer is cloned and stored.\n    public constructor(\n      // The mode indicator of this segment.\n      public readonly mode: QrSegment.Mode,\n\n      // The length of this segment's unencoded data. Measured in characters for\n      // numeric/alphanumeric/kanji mode, bytes for byte mode, and 0 for ECI mode.\n      // Always zero or positive. Not the same as the data's bit length.\n      public readonly numChars: int,\n\n      // The data bits of this segment. Accessed through getData().\n      private readonly bitData: bit[]\n    ) {\n      if (numChars < 0) {\n        throw new RangeError('Invalid argument')\n      }\n      this.bitData = bitData.slice() // Make defensive copy\n    }\n\n    /* -- Methods -- */\n\n    // Returns a new copy of the data bits of this segment.\n    public getData(): bit[] {\n      return this.bitData.slice() // Make defensive copy\n    }\n\n    // (Package-private) Calculates and returns the number of bits needed to encode the given segments at\n    // the given version. The result is infinity if a segment has too many characters to fit its length field.\n    public static getTotalBits(\n      segs: Readonly<QrSegment[]>,\n      version: int\n    ): number {\n      let result: number = 0\n      for (const seg of segs) {\n        const ccbits: int = seg.mode.numCharCountBits(version)\n        if (seg.numChars >= 1 << ccbits) {\n          return Infinity\n        } // The segment's length doesn't fit the field's bit width\n        result += 4 + ccbits + seg.bitData.length\n      }\n      return result\n    }\n\n    // Returns a new array of bytes representing the given string encoded in UTF-8.\n    private static toUtf8ByteArray(str: string): byte[] {\n      str = encodeURI(str)\n      const result: byte[] = []\n      for (let i = 0; i < str.length; i++) {\n        if (str.charAt(i) !== '%') {\n          result.push(str.charCodeAt(i))\n        }\n        else {\n          result.push(Number.parseInt(str.substr(i + 1, 2), 16))\n          i += 2\n        }\n      }\n      return result\n    }\n\n    /* -- Constants -- */\n\n    // Describes precisely all strings that are encodable in numeric mode.\n    private static readonly NUMERIC_REGEX: RegExp = /^[0-9]*$/\n\n    // Describes precisely all strings that are encodable in alphanumeric mode.\n    private static readonly ALPHANUMERIC_REGEX: RegExp = /^[A-Z0-9 $%*+./:-]*$/\n\n    // The set of all legal characters in alphanumeric mode,\n    // where each character value maps to the index in the string.\n    private static readonly ALPHANUMERIC_CHARSET: string\n      = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ $%*+-./:'\n  }\n}\n\n/* ---- Public helper enumeration ---- */\nnamespace qrcodegen.QrCode {\n  type int = number\n\n  /*\n   * The error correction level in a QR Code symbol. Immutable.\n   */\n  export class Ecc {\n    /* -- Constants -- */\n\n    public static readonly LOW = new Ecc(0, 1) // The QR Code can tolerate about  7% erroneous codewords\n    public static readonly MEDIUM = new Ecc(1, 0) // The QR Code can tolerate about 15% erroneous codewords\n    public static readonly QUARTILE = new Ecc(2, 3) // The QR Code can tolerate about 25% erroneous codewords\n    public static readonly HIGH = new Ecc(3, 2) // The QR Code can tolerate about 30% erroneous codewords\n\n    /* -- Constructor and fields -- */\n\n    private constructor(\n      // In the range 0 to 3 (unsigned 2-bit integer).\n      public readonly ordinal: int,\n      // (Package-private) In the range 0 to 3 (unsigned 2-bit integer).\n      public readonly formatBits: int\n    ) {}\n  }\n}\n\n/* ---- Public helper enumeration ---- */\nnamespace qrcodegen.QrSegment {\n  type int = number\n\n  /*\n   * Describes how a segment's data bits are interpreted. Immutable.\n   */\n  export class Mode {\n    /* -- Constants -- */\n\n    public static readonly NUMERIC = new Mode(0x1, [10, 12, 14])\n    public static readonly ALPHANUMERIC = new Mode(0x2, [9, 11, 13])\n    public static readonly BYTE = new Mode(0x4, [8, 16, 16])\n    public static readonly KANJI = new Mode(0x8, [8, 10, 12])\n    public static readonly ECI = new Mode(0x7, [0, 0, 0])\n\n    /* -- Constructor and fields -- */\n\n    private constructor(\n      // The mode indicator bits, which is a uint4 value (range 0 to 15).\n      public readonly modeBits: int,\n      // Number of character count bits for three different version ranges.\n      private readonly numBitsCharCount: [int, int, int]\n    ) {}\n\n    /* -- Method -- */\n\n    // (Package-private) Returns the bit width of the character count field for a segment in\n    // this mode in a QR Code at the given version number. The result is in the range [0, 16].\n    public numCharCountBits(ver: int): int {\n      return this.numBitsCharCount[Math.floor((ver + 7) / 17)]\n    }\n  }\n}\n\nexport default qrcodegen\n"
  },
  {
    "path": "src/qr-code/src/styles/index.cssr.ts",
    "content": "import { c, cB } from '../../../_utils/cssr'\n\n// vars:\n// --n-border-radius\nexport default c([\n  cB('qr-code', `\n    background: #fff;\n    border-radius: var(--n-border-radius);\n    display: inline-flex;\n  `)\n])\n"
  },
  {
    "path": "src/qr-code/styles/dark.ts",
    "content": "import type { QrCodeTheme } from './light'\nimport { commonDark } from '../../_styles/common'\n\nconst qrcodeDark: QrCodeTheme = {\n  name: 'QrCode',\n  common: commonDark,\n  self: (vars) => {\n    return {\n      borderRadius: vars.borderRadius\n    }\n  }\n}\n\nexport default qrcodeDark\n"
  },
  {
    "path": "src/qr-code/styles/index.ts",
    "content": "export { default as qrcodeDark } from './dark'\nexport { default as qrcodeLight } from './light'\nexport type { QrCodeTheme, QrCodeThemeVars } from './light'\n"
  },
  {
    "path": "src/qr-code/styles/light.ts",
    "content": "import type { Theme } from '../../_mixins'\nimport type { ThemeCommonVars } from '../../_styles/common'\nimport { commonLight } from '../../_styles/common'\n\nfunction self(vars: ThemeCommonVars) {\n  return {\n    borderRadius: vars.borderRadius\n  }\n}\n\nexport type QrCodeThemeVars = ReturnType<typeof self>\n\nconst themeLight: Theme<'QrCode', QrCodeThemeVars> = {\n  name: 'QrCode',\n  common: commonLight,\n  self\n}\n\nexport default themeLight\nexport type QrCodeTheme = typeof themeLight\n"
  },
  {
    "path": "src/radio/demos/enUS/basic.demo.vue",
    "content": "<markdown>\n# Basic\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst checkedValueRef = ref<string | null>(null)\nconst disabled = ref(true)\nconst checkedValue = checkedValueRef\n\nfunction handleChange(e: Event) {\n  checkedValueRef.value = (e.target as HTMLInputElement).value\n}\n</script>\n\n<template>\n  <n-space>\n    <n-radio\n      :checked=\"checkedValue === 'Definitely Maybe'\"\n      value=\"Definitely Maybe\"\n      name=\"basic-demo\"\n      @change=\"handleChange\"\n    >\n      Definitely Maybe\n    </n-radio>\n    <n-radio\n      :checked=\"checkedValue === 'Be Here Now'\"\n      value=\"Be Here Now\"\n      name=\"basic-demo\"\n      @change=\"handleChange\"\n    >\n      Be Here Now\n    </n-radio>\n    <n-radio\n      :checked=\"checkedValue === 'Be Here Now'\"\n      value=\"Be Here Now\"\n      :disabled=\"disabled\"\n      name=\"basic-demo\"\n      label=\"Be Here Now\"\n      @change=\"handleChange\"\n    />\n    <n-switch v-model:value=\"disabled\" />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/radio/demos/enUS/button-group.demo.vue",
    "content": "<markdown>\n# Button group\n\nSometimes a radio button group can look more elegant.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst value = ref(null)\nconst disabled2 = ref(false)\nconst disabled1 = ref(false)\nconst songs = [\n  {\n    value: 'Rock\\'n\\'Roll Star',\n    label: 'Rock\\'n\\'Roll Star'\n  },\n  {\n    value: 'Shakermaker',\n    label: 'Shakermaker'\n  },\n  {\n    value: 'Live Forever',\n    label: 'Live Forever'\n  },\n  {\n    value: 'Up in the Sky',\n    label: 'Up in the Sky'\n  },\n  {\n    value: '...',\n    label: '...'\n  }\n].map((s) => {\n  s.value = s.value.toLowerCase()\n  return s\n})\n</script>\n\n<template>\n  <n-space vertical>\n    <n-radio-group v-model:value=\"value\" name=\"radiobuttongroup1\">\n      <n-radio-button\n        v-for=\"song in songs\"\n        :key=\"song.value\"\n        :value=\"song.value\"\n        :disabled=\"\n          (song.label === 'Live Forever' && disabled1)\n            || (song.label === 'Shakermaker' && disabled2)\n        \"\n        :label=\"song.label\"\n      />\n    </n-radio-group>\n    <n-space>\n      <n-checkbox v-model:checked=\"disabled2\" style=\"margin-right: 12px\">\n        Disable Shakemaker\n      </n-checkbox>\n      <n-checkbox v-model:checked=\"disabled1\">\n        Disable Live Forever\n      </n-checkbox>\n    </n-space>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/radio/demos/enUS/group.demo.vue",
    "content": "<markdown>\n# Group\n\nA radio group looks elegant.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst value = ref(null)\nconst songs = [\n  {\n    value: 'Rock\\'n\\'Roll Star',\n    label: 'Rock\\'n\\'Roll Star'\n  },\n  {\n    value: 'Shakermaker',\n    label: 'Shakermaker'\n  },\n  {\n    value: 'Live Forever',\n    label: 'Live Forever'\n  },\n  {\n    value: 'Up in the Sky',\n    label: 'Up in the Sky'\n  },\n  {\n    value: '...',\n    label: '...'\n  }\n].map((s) => {\n  s.value = s.value.toLowerCase()\n  return s\n})\n</script>\n\n<template>\n  <n-radio-group v-model:value=\"value\" name=\"radiogroup\">\n    <n-space>\n      <n-radio\n        v-for=\"song in songs\"\n        :key=\"song.value\"\n        :value=\"song.value\"\n        :label=\"song.label\"\n      />\n    </n-space>\n  </n-radio-group>\n</template>\n"
  },
  {
    "path": "src/radio/demos/enUS/index.demo-entry.md",
    "content": "# Radio\n\n<!--single-column-->\n\nWhen I was young, I loved listening to the radio, such as FM 106.8 or FM 92.1.\n\n## Demos\n\n```demo\nbasic.vue\ngroup.vue\nbutton-group.vue\nsize.vue\n```\n\n## API\n\n### Radio Props, RadioButton Props\n\n| Name | Type | Default | Description | Version |\n| --- | --- | --- | --- | --- |\n| checked | `boolean` | `undefined` | Checked state. |  |\n| default-checked | `boolean` | `false` | Default checked state. |  |\n| disabled | `boolean` | `false` | Disabled state. |  |\n| label | `string` | `undefined` | Radio label. If not set, render default slot content, if both, use default slot content first. | 2.28.0 |\n| name | `string` | `undefined` | The name attribute of the radio element. If not set, name of `radio-group` will be used. |\n| size | `'small' \\| 'medium' \\| 'large'` | `'medium'` | Size. |  |\n| value | `string \\| number \\| boolean` | `'on'` | Checked value. | `boolean` 2.33.0 |\n| on-update:checked | `(check: boolean) => void` | `undefined` | Callback method triggered when a selection change occurs. |  |\n\n### RadioGroup Props\n\n| Name | Type | Default | Description |\n| --- | --- | --- | --- |\n| disabled | `boolean` | `false` | Disabled state. |\n| name | `string` | `undefined` | The name attribute of the radio elements inside the group. |\n| size | `'small' \\| 'medium' \\| 'large'` | `'medium'` | Size. |\n| value | `string \\| number \\| boolean \\| null` | `null` | Checked value. |\n| default-value | `string \\| number \\| boolean \\| null` | `null` | Default checked value. |\n| on-update:value | `(value: string \\| number \\| boolean) => void` | `undefined` | Callback method triggered when a selection change occurs. |\n"
  },
  {
    "path": "src/radio/demos/enUS/size.demo.vue",
    "content": "<markdown>\n# Size\n\nChoose the size you want.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst value = ref(null)\nconst disabled2 = ref(false)\nconst disabled1 = ref(false)\nconst songs = [\n  {\n    value: 'Rock\\'n\\'Roll Star',\n    label: 'Rock\\'n\\'Roll Star'\n  },\n  {\n    value: 'Shakermaker',\n    label: 'Shakermaker'\n  },\n  {\n    value: 'Live Forever',\n    label: 'Live Forever'\n  },\n  {\n    value: 'Up in the Sky',\n    label: 'Up in the Sky'\n  },\n  {\n    value: '...',\n    label: '...'\n  }\n].map((s) => {\n  s.value = s.value.toLowerCase()\n  return s\n})\n</script>\n\n<template>\n  <n-space vertical>\n    <n-radio-group v-model:value=\"value\" name=\"radiobuttongroup2\" size=\"medium\">\n      <n-radio-button\n        v-for=\"song in songs\"\n        :key=\"song.value\"\n        :value=\"song.value\"\n        :disabled=\"\n          (song.label === 'Live Forever' && disabled1)\n            || (song.label === 'Shakermaker' && disabled2)\n        \"\n      >\n        {{ song.label }}\n      </n-radio-button>\n    </n-radio-group>\n    <n-radio-group v-model:value=\"value\" name=\"radiobuttongroup3\" size=\"large\">\n      <n-radio-button\n        v-for=\"song in songs\"\n        :key=\"song.value\"\n        :value=\"song.value\"\n        :disabled=\"\n          (song.label === 'Live Forever' && disabled1)\n            || (song.label === 'Shakermaker' && disabled2)\n        \"\n      >\n        {{ song.label }}\n      </n-radio-button>\n    </n-radio-group>\n    <n-space>\n      <n-checkbox v-model:checked=\"disabled2\" style=\"margin-right: 12px\">\n        Disable Shakemaker\n      </n-checkbox>\n      <n-checkbox v-model:checked=\"disabled1\">\n        Disable Live Forever\n      </n-checkbox>\n    </n-space>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/radio/demos/zhCN/basic.demo.vue",
    "content": "<markdown>\n# 基础用法\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst checkedValueRef = ref<string | null>(null)\nconst disabled = ref(true)\nconst checkedValue = checkedValueRef\n\nfunction handleChange(e: Event) {\n  checkedValueRef.value = (e.target as HTMLInputElement).value\n}\n</script>\n\n<template>\n  <n-space>\n    <n-radio\n      :checked=\"checkedValue === 'Definitely Maybe'\"\n      value=\"Definitely Maybe\"\n      name=\"basic-demo\"\n      @change=\"handleChange\"\n    >\n      Definitely Maybe\n    </n-radio>\n    <n-radio\n      :checked=\"checkedValue === 'Be Here Now'\"\n      value=\"Be Here Now\"\n      name=\"basic-demo\"\n      @change=\"handleChange\"\n    >\n      Be Here Now\n    </n-radio>\n    <n-radio\n      :checked=\"checkedValue === 'Be Here Now'\"\n      value=\"Be Here Now\"\n      :disabled=\"disabled\"\n      name=\"basic-demo\"\n      label=\" Be Here Now\"\n      @change=\"handleChange\"\n    />\n    <n-switch v-model:value=\"disabled\" />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/radio/demos/zhCN/button-group.demo.vue",
    "content": "<markdown>\n# 按钮组\n\n有的时候用按钮显得更优雅一点。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst value = ref(null)\nconst disabled2 = ref(false)\nconst disabled1 = ref(false)\nconst songs = [\n  {\n    value: 'Rock\\'n\\'Roll Star',\n    label: 'Rock\\'n\\'Roll Star'\n  },\n  {\n    value: 'Shakermaker',\n    label: 'Shakermaker'\n  },\n  {\n    value: 'Live Forever',\n    label: 'Live Forever'\n  },\n  {\n    value: 'Up in the Sky',\n    label: 'Up in the Sky'\n  },\n  {\n    value: '...',\n    label: '...'\n  }\n].map((s) => {\n  s.value = s.value.toLowerCase()\n  return s\n})\n</script>\n\n<template>\n  <n-space vertical>\n    <n-radio-group v-model:value=\"value\" name=\"radiobuttongroup1\">\n      <n-radio-button\n        v-for=\"song in songs\"\n        :key=\"song.value\"\n        :value=\"song.value\"\n        :disabled=\"\n          (song.label === 'Live Forever' && disabled1)\n            || (song.label === 'Shakermaker' && disabled2)\n        \"\n        :label=\"song.label\"\n      />\n    </n-radio-group>\n    <n-space>\n      <n-checkbox v-model:checked=\"disabled2\" style=\"margin-right: 12px\">\n        禁用 Shakemaker\n      </n-checkbox>\n      <n-checkbox v-model:checked=\"disabled1\">\n        禁用 Live Forever\n      </n-checkbox>\n    </n-space>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/radio/demos/zhCN/group.demo.vue",
    "content": "<markdown>\n# 选项组\n\n一个选项组看起来就挺舒服。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst value = ref(null)\nconst songs = [\n  {\n    value: 'Rock\\'n\\'Roll Star',\n    label: 'Rock\\'n\\'Roll Star'\n  },\n  {\n    value: 'Shakermaker',\n    label: 'Shakermaker'\n  },\n  {\n    value: 'Live Forever',\n    label: 'Live Forever'\n  },\n  {\n    value: 'Up in the Sky',\n    label: 'Up in the Sky'\n  },\n  {\n    value: '...',\n    label: '...'\n  }\n].map((s) => {\n  s.value = s.value.toLowerCase()\n  return s\n})\n</script>\n\n<template>\n  <n-radio-group v-model:value=\"value\" name=\"radiogroup\">\n    <n-space>\n      <n-radio v-for=\"song in songs\" :key=\"song.value\" :value=\"song.value\">\n        {{ song.label }}\n      </n-radio>\n    </n-space>\n  </n-radio-group>\n</template>\n"
  },
  {
    "path": "src/radio/demos/zhCN/index.demo-entry.md",
    "content": "# 单选 Radio\n\n<!--single-column-->\n\n我还小的时候，很喜欢听收音机，比如 FM 106.8 或者 FM 92.1。\n\n## 演示\n\n```demo\nbasic.vue\ngroup.vue\nbutton-group.vue\nsize.vue\nradio-focus-debug.vue\nrtl-debug.vue\nuncontrolled-debug.vue\ntooltip-debug.vue\n```\n\n## API\n\n### Radio Props, RadioButton Props\n\n| 名称 | 类型 | 默认值 | 说明 | 版本 |\n| --- | --- | --- | --- | --- |\n| checked | `boolean` | `undefined` | 选中状态 |  |\n| default-checked | `boolean` | `false` | 默认选中的状态 |  |\n| disabled | `boolean` | `false` | 禁用状态 |  |\n| label | `string` | `undefined` | 标签 | 2.28.0 |\n| name | `string` | `undefined` | 单选按钮 radio 元素的 name 属性。如果没有设定会使用 `n-radio-group` 的 `name` |  |\n| size | `'small' \\| 'medium' \\| 'large'` | `'medium'` | 大小 |  |\n| value | `string \\| number \\| boolean` | `'on'` | 选中的值 | `boolean` 2.33.0 |\n| on-update:checked | `(checked: boolean) => void` | `undefined` | 发生变化时触发的回调方法 |  |\n\n### RadioGroup Props\n\n| 名称 | 类型 | 默认值 | 说明 |\n| --- | --- | --- | --- |\n| disabled | `boolean` | `false` | 禁用状态 |\n| name | `string` | `undefined` | 选项组内部 radio 元素的 name 属性 |\n| size | `'small' \\| 'medium' \\| 'large'` | `'medium'` | 大小 |\n| value | `string \\| number \\| boolean \\| null` | `null` | 选中的值 |\n| default-value | `string \\| number \\| boolean \\| null` | `null` | 默认选中的值 |\n| on-update:value | `(value: string \\| number \\| boolean) => void` | `undefined` | 发生变化时触发的回调方法 |\n"
  },
  {
    "path": "src/radio/demos/zhCN/radio-focus-debug.demo.vue",
    "content": "<markdown>\n# 基础用法\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst value = ref(null)\n</script>\n\n<template>\n  <n-radio v-model:value-value=\"value\" value=\"Definitely Maybe\">\n    <n-input />\n  </n-radio>\n</template>\n"
  },
  {
    "path": "src/radio/demos/zhCN/rtl-debug.demo.vue",
    "content": "<markdown>\n# Rtl Debug\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { unstableRadioRtl, unstableSpaceRtl } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst checkedValueRef = ref<string | null>(null)\nconst rtlEnabled = ref(false)\nconst rtlStyles = [unstableRadioRtl, unstableSpaceRtl]\nconst checkedValue = checkedValueRef\nconst value = ref(null)\nconst songs = [\n  {\n    value: 'Rock\\'n\\'Roll Star',\n    label: 'Rock\\'n\\'Roll Star'\n  },\n  {\n    value: 'Shakermaker',\n    label: 'Shakermaker'\n  },\n  {\n    value: 'Live Forever',\n    label: 'Live Forever'\n  },\n  {\n    value: 'Up in the Sky',\n    label: 'Up in the Sky'\n  },\n  {\n    value: '...',\n    label: '...'\n  }\n].map((s) => {\n  s.value = s.value.toLowerCase()\n  return s\n})\n\nfunction handleChange(e: Event) {\n  checkedValueRef.value = (e.target as HTMLInputElement).value\n}\n</script>\n\n<template>\n  <n-space vertical>\n    <n-space><n-switch v-model:value=\"rtlEnabled\" />Rtl</n-space>\n    <n-config-provider :rtl=\"rtlEnabled ? rtlStyles : undefined\">\n      <n-space>\n        <n-radio\n          :checked=\"checkedValue === 'Definitely Maybe'\"\n          value=\"Definitely Maybe\"\n          name=\"basic-demo\"\n          @change=\"handleChange\"\n        >\n          Definitely Maybe\n        </n-radio>\n        <n-radio-group v-model:value=\"value\" name=\"radiobuttongroup1\">\n          <n-radio-button\n            v-for=\"song in songs\"\n            :key=\"song.value\"\n            :value=\"song.value\"\n          >\n            {{ song.label }}\n          </n-radio-button>\n        </n-radio-group>\n      </n-space>\n    </n-config-provider>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/radio/demos/zhCN/size.demo.vue",
    "content": "<markdown>\n# 尺寸\n\n任君挑选。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst value = ref(null)\nconst disabled2 = ref(false)\nconst disabled1 = ref(false)\nconst songs = [\n  {\n    value: 'Rock\\'n\\'Roll Star',\n    label: 'Rock\\'n\\'Roll Star'\n  },\n  {\n    value: 'Shakermaker',\n    label: 'Shakermaker'\n  },\n  {\n    value: 'Live Forever',\n    label: 'Live Forever'\n  },\n  {\n    value: 'Up in the Sky',\n    label: 'Up in the Sky'\n  },\n  {\n    value: '...',\n    label: '...'\n  }\n].map((s) => {\n  s.value = s.value.toLowerCase()\n  return s\n})\n</script>\n\n<template>\n  <n-space vertical>\n    <n-radio-group v-model:value=\"value\" name=\"radiobuttongroup2\" size=\"medium\">\n      <n-radio-button\n        v-for=\"song in songs\"\n        :key=\"song.value\"\n        :value=\"song.value\"\n        :disabled=\"\n          (song.label === 'Live Forever' && disabled1)\n            || (song.label === 'Shakermaker' && disabled2)\n        \"\n      >\n        {{ song.label }}\n      </n-radio-button>\n    </n-radio-group>\n    <n-radio-group v-model:value=\"value\" name=\"radiobuttongroup3\" size=\"large\">\n      <n-radio-button\n        v-for=\"song in songs\"\n        :key=\"song.value\"\n        :value=\"song.value\"\n        :disabled=\"\n          (song.label === 'Live Forever' && disabled1)\n            || (song.label === 'Shakermaker' && disabled2)\n        \"\n      >\n        {{ song.label }}\n      </n-radio-button>\n    </n-radio-group>\n    <n-space>\n      <n-checkbox v-model:checked=\"disabled2\" style=\"margin-right: 12px\">\n        禁用 Shakemaker\n      </n-checkbox>\n      <n-checkbox v-model:checked=\"disabled1\">\n        禁用 Live Forever\n      </n-checkbox>\n    </n-space>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/radio/demos/zhCN/tooltip-debug.demo.vue",
    "content": "<markdown>\n# Tooltip debug\n</markdown>\n\n<script setup lang=\"ts\">\nimport { NRadio, NRadioGroup, NSpace, NTooltip } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst mode = ref('direct')\nconst modeOptions = [\n  { label: '直接', value: 'direct' },\n  { label: '拆分', value: 'paragraph' }\n]\n</script>\n\n<template>\n  <div class=\"rd-2\">\n    <NRadioGroup v-model:value=\"mode\" name=\"radiogroup\">\n      <NSpace>\n        <NRadio v-for=\"i in modeOptions\" :key=\"i.value\" :value=\"i.value\">\n          {{ i.label }}\n          <NTooltip placement=\"top\">\n            <template #trigger>\n              <span style=\"color: red\">提示</span>\n            </template>\n            <div>\n              reloaded using link preload but not used within a few seconds from\n              the window's load event. Pleas\n            </div>\n          </NTooltip>\n        </NRadio>\n      </NSpace>\n    </NRadioGroup>\n  </div>\n</template>\n\n<style scoped></style>\n"
  },
  {
    "path": "src/radio/demos/zhCN/uncontrolled-debug.demo.vue",
    "content": "<markdown>\n# Uncontrolled Debug\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { useDialog } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst radioVal = ref(1)\nconst dialog = useDialog()\n\nfunction handleUpdateValue(val: number) {\n  dialog.info({\n    title: '提示',\n    content: '是否改变',\n    onPositiveClick: () => {\n      radioVal.value = val\n    },\n    positiveText: '确定',\n    negativeText: '取消'\n  })\n}\n</script>\n\n<template>\n  <NRadioGroup :value=\"radioVal\" @update:value=\"handleUpdateValue\">\n    <NRadio :value=\"1\">\n      change 1\n    </NRadio>\n    <NRadio :value=\"2\">\n      change 2\n    </NRadio>\n  </NRadioGroup>\n</template>\n"
  },
  {
    "path": "src/radio/index.ts",
    "content": "export type * from './src/public-types'\nexport { default as NRadio, radioProps } from './src/Radio'\nexport type { RadioProps } from './src/Radio'\nexport { default as NRadioButton, radioButtonProps } from './src/RadioButton'\nexport type { RadioButtonProps } from './src/RadioButton'\nexport { default as NRadioGroup, radioGroupProps } from './src/RadioGroup'\nexport type { RadioGroupProps } from './src/RadioGroup'\n"
  },
  {
    "path": "src/radio/src/Radio.tsx",
    "content": "import type { CSSProperties } from 'vue'\nimport type { ThemeProps } from '../../_mixins'\nimport type { ExtractPublicPropTypes } from '../../_utils'\nimport type { RadioTheme } from '../styles'\nimport { computed, defineComponent, h } from 'vue'\nimport { useConfig, useTheme, useThemeClass } from '../../_mixins'\nimport { useRtl } from '../../_mixins/use-rtl'\nimport { createKey, resolveWrappedSlot } from '../../_utils'\nimport { radioLight } from '../styles'\nimport style from './styles/radio.cssr'\nimport { radioBaseProps, setup } from './use-radio'\n\nexport const radioProps = {\n  ...(useTheme.props as ThemeProps<RadioTheme>),\n  ...radioBaseProps\n} as const\n\nexport type RadioProps = ExtractPublicPropTypes<typeof radioProps>\n\nexport default defineComponent({\n  name: 'Radio',\n  props: radioProps,\n  setup(props) {\n    const radio = setup(props)\n    const themeRef = useTheme(\n      'Radio',\n      '-radio',\n      style,\n      radioLight,\n      props,\n      radio.mergedClsPrefix\n    )\n    const cssVarsRef = computed(() => {\n      const {\n        mergedSize: { value: size }\n      } = radio\n      const {\n        common: { cubicBezierEaseInOut },\n        self: {\n          boxShadow,\n          boxShadowActive,\n          boxShadowDisabled,\n          boxShadowFocus,\n          boxShadowHover,\n          color,\n          colorDisabled,\n          colorActive,\n          textColor,\n          textColorDisabled,\n          dotColorActive,\n          dotColorDisabled,\n          labelPadding,\n          labelLineHeight,\n          labelFontWeight,\n          [createKey('fontSize', size)]: fontSize,\n          [createKey('radioSize', size)]: radioSize\n        }\n      } = themeRef.value\n      return {\n        '--n-bezier': cubicBezierEaseInOut,\n        '--n-label-line-height': labelLineHeight,\n        '--n-label-font-weight': labelFontWeight,\n        '--n-box-shadow': boxShadow,\n        '--n-box-shadow-active': boxShadowActive,\n        '--n-box-shadow-disabled': boxShadowDisabled,\n        '--n-box-shadow-focus': boxShadowFocus,\n        '--n-box-shadow-hover': boxShadowHover,\n        '--n-color': color,\n        '--n-color-active': colorActive,\n        '--n-color-disabled': colorDisabled,\n        '--n-dot-color-active': dotColorActive,\n        '--n-dot-color-disabled': dotColorDisabled,\n        '--n-font-size': fontSize,\n        '--n-radio-size': radioSize,\n        '--n-text-color': textColor,\n        '--n-text-color-disabled': textColorDisabled,\n        '--n-label-padding': labelPadding\n      }\n    })\n    const { inlineThemeDisabled, mergedClsPrefixRef, mergedRtlRef }\n      = useConfig(props)\n    const rtlEnabledRef = useRtl('Radio', mergedRtlRef, mergedClsPrefixRef)\n    const themeClassHandle = inlineThemeDisabled\n      ? useThemeClass(\n          'radio',\n          computed(() => radio.mergedSize.value[0]),\n          cssVarsRef,\n          props\n        )\n      : undefined\n    return Object.assign(radio, {\n      rtlEnabled: rtlEnabledRef,\n      cssVars: inlineThemeDisabled ? undefined : cssVarsRef,\n      themeClass: themeClassHandle?.themeClass,\n      onRender: themeClassHandle?.onRender\n    })\n  },\n  render() {\n    const { $slots, mergedClsPrefix, onRender, label } = this\n    onRender?.()\n    return (\n      <label\n        class={[\n          `${mergedClsPrefix}-radio`,\n          this.themeClass,\n          this.rtlEnabled && `${mergedClsPrefix}-radio--rtl`,\n          this.mergedDisabled && `${mergedClsPrefix}-radio--disabled`,\n          this.renderSafeChecked && `${mergedClsPrefix}-radio--checked`,\n          this.focus && `${mergedClsPrefix}-radio--focus`\n        ]}\n        style={this.cssVars as CSSProperties}\n      >\n        <div class={`${mergedClsPrefix}-radio__dot-wrapper`}>\n          &nbsp;\n          <div\n            class={[\n              `${mergedClsPrefix}-radio__dot`,\n              this.renderSafeChecked && `${mergedClsPrefix}-radio__dot--checked`\n            ]}\n          />\n          <input\n            ref=\"inputRef\"\n            type=\"radio\"\n            class={`${mergedClsPrefix}-radio-input`}\n            value={this.value}\n            name={this.mergedName}\n            checked={this.renderSafeChecked}\n            disabled={this.mergedDisabled}\n            onChange={this.handleRadioInputChange}\n            onFocus={this.handleRadioInputFocus}\n            onBlur={this.handleRadioInputBlur}\n          />\n        </div>\n        {resolveWrappedSlot($slots.default, (children) => {\n          if (!children && !label)\n            return null\n          return (\n            <div ref=\"labelRef\" class={`${mergedClsPrefix}-radio__label`}>\n              {children || label}\n            </div>\n          )\n        })}\n      </label>\n    )\n  }\n})\n"
  },
  {
    "path": "src/radio/src/RadioButton.tsx",
    "content": "import type { ExtractPublicPropTypes } from '../../_utils'\nimport { defineComponent, h } from 'vue'\nimport { resolveWrappedSlot } from '../../_utils'\nimport { radioBaseProps, setup } from './use-radio'\n\nexport const radioButtonProps = radioBaseProps\nexport type RadioButtonProps = ExtractPublicPropTypes<typeof radioBaseProps>\n\nexport default defineComponent({\n  name: 'RadioButton',\n  props: radioBaseProps,\n  setup,\n  render() {\n    const { mergedClsPrefix } = this\n    return (\n      <label\n        class={[\n          `${mergedClsPrefix}-radio-button`,\n          this.mergedDisabled && `${mergedClsPrefix}-radio-button--disabled`,\n          this.renderSafeChecked && `${mergedClsPrefix}-radio-button--checked`,\n          this.focus && [`${mergedClsPrefix}-radio-button--focus`]\n        ]}\n      >\n        <input\n          ref=\"inputRef\"\n          type=\"radio\"\n          class={`${mergedClsPrefix}-radio-input`}\n          value={this.value}\n          name={this.mergedName}\n          checked={this.renderSafeChecked}\n          disabled={this.mergedDisabled}\n          onChange={this.handleRadioInputChange}\n          onFocus={this.handleRadioInputFocus}\n          onBlur={this.handleRadioInputBlur}\n        />\n        <div class={`${mergedClsPrefix}-radio-button__state-border`} />\n        {resolveWrappedSlot(this.$slots.default, (children) => {\n          if (!children && !this.label)\n            return null\n          return (\n            <div ref=\"labelRef\" class={`${mergedClsPrefix}-radio__label`}>\n              {children || this.label}\n            </div>\n          )\n        })}\n      </label>\n    )\n  }\n})\n"
  },
  {
    "path": "src/radio/src/RadioGroup.tsx",
    "content": "import type { CSSProperties, PropType, VNode, VNodeChild } from 'vue'\nimport type { ThemeProps } from '../../_mixins'\nimport type { ExtractPublicPropTypes, MaybeArray } from '../../_utils'\nimport type { RadioTheme } from '../styles'\nimport type { OnUpdateValue, OnUpdateValueImpl } from './interface'\nimport type { RadioBaseProps } from './use-radio'\nimport { useMergedState } from 'vooks'\nimport { computed, defineComponent, h, provide, ref, toRef } from 'vue'\nimport { useConfig, useFormItem, useTheme, useThemeClass } from '../../_mixins'\nimport { useRtl } from '../../_mixins/use-rtl'\nimport { call, createKey, flatten, getSlot, warn } from '../../_utils'\nimport { radioLight } from '../styles'\nimport style from './styles/radio-group.cssr'\nimport { radioGroupInjectionKey } from './use-radio'\n\nfunction mapSlot(\n  defaultSlot: VNode[],\n  value: string | number | boolean | null,\n  clsPrefix: string\n): {\n  children: VNodeChild[]\n  isButtonGroup: boolean\n} {\n  const children: VNode[] = []\n  let isButtonGroup = false\n  for (let i = 0; i < defaultSlot.length; ++i) {\n    const wrappedInstance = defaultSlot[i]\n    const name = (wrappedInstance.type as any)?.name\n    if (name === 'RadioButton') {\n      isButtonGroup = true\n    }\n    if (__DEV__ && isButtonGroup && name !== 'RadioButton') {\n      warn(\n        'radio-group',\n        '`n-radio-group` in button mode only takes `n-radio-button` as children.'\n      )\n      continue\n    }\n    const instanceProps: RadioBaseProps = wrappedInstance.props as any\n    if (name !== 'RadioButton') {\n      children.push(wrappedInstance)\n      continue\n    }\n    if (i === 0) {\n      children.push(wrappedInstance)\n    }\n    else {\n      const lastInstanceProps: RadioBaseProps = children[children.length - 1]\n        .props as any\n      const lastInstanceChecked = value === lastInstanceProps.value\n      const lastInstanceDisabled: boolean | undefined\n        = lastInstanceProps.disabled\n      const currentInstanceChecked = value === instanceProps.value\n      const currentInstanceDisabled = instanceProps.disabled\n      /**\n       * Priority of button splitor:\n       * !disabled  checked >\n       *  disabled  checked >\n       * !disabled !checked >\n       *  disabled !checked\n       */\n      const lastInstancePriority: number\n        = (lastInstanceChecked ? 2 : 0) + (!lastInstanceDisabled ? 1 : 0)\n      const currentInstancePriority\n        = (currentInstanceChecked ? 2 : 0) + (!currentInstanceDisabled ? 1 : 0)\n      const lastInstanceClass = {\n        [`${clsPrefix}-radio-group__splitor--disabled`]: lastInstanceDisabled,\n        [`${clsPrefix}-radio-group__splitor--checked`]: lastInstanceChecked\n      }\n      const currentInstanceClass = {\n        [`${clsPrefix}-radio-group__splitor--disabled`]:\n          currentInstanceDisabled,\n        [`${clsPrefix}-radio-group__splitor--checked`]: currentInstanceChecked\n      }\n      const splitorClass\n        = lastInstancePriority < currentInstancePriority\n          ? currentInstanceClass\n          : lastInstanceClass\n      children.push(\n        <div class={[`${clsPrefix}-radio-group__splitor`, splitorClass]} />,\n        wrappedInstance\n      )\n    }\n  }\n  return {\n    children,\n    isButtonGroup\n  }\n}\n\nexport const radioGroupProps = {\n  ...(useTheme.props as ThemeProps<RadioTheme>),\n  name: String,\n  value: [String, Number, Boolean] as PropType<\n    string | number | boolean | null\n  >,\n  defaultValue: {\n    type: [String, Number, Boolean] as PropType<\n      string | number | boolean | null\n    >,\n    default: null\n  },\n  size: String as PropType<'small' | 'medium' | 'large'>,\n  disabled: {\n    type: Boolean as PropType<boolean | undefined>,\n    default: undefined\n  },\n  'onUpdate:value': [Function, Array] as PropType<MaybeArray<OnUpdateValue>>,\n  onUpdateValue: [Function, Array] as PropType<MaybeArray<OnUpdateValue>>\n} as const\n\nexport type RadioGroupProps = ExtractPublicPropTypes<typeof radioGroupProps>\n\nexport default defineComponent({\n  name: 'RadioGroup',\n  props: radioGroupProps,\n  setup(props) {\n    const selfElRef = ref<HTMLDivElement | null>(null)\n    const {\n      mergedSizeRef,\n      mergedDisabledRef,\n      nTriggerFormChange,\n      nTriggerFormInput,\n      nTriggerFormBlur,\n      nTriggerFormFocus\n    } = useFormItem(props)\n    const { mergedClsPrefixRef, inlineThemeDisabled, mergedRtlRef }\n      = useConfig(props)\n    const themeRef = useTheme(\n      'Radio',\n      '-radio-group',\n      style,\n      radioLight,\n      props,\n      mergedClsPrefixRef\n    )\n    const uncontrolledValueRef = ref(props.defaultValue)\n    const controlledValueRef = toRef(props, 'value')\n    const mergedValueRef = useMergedState(\n      controlledValueRef,\n      uncontrolledValueRef\n    )\n    function doUpdateValue(value: string | number | boolean): void {\n      const { onUpdateValue, 'onUpdate:value': _onUpdateValue } = props\n      if (onUpdateValue) {\n        call(onUpdateValue as OnUpdateValueImpl, value)\n      }\n      if (_onUpdateValue) {\n        call(_onUpdateValue as OnUpdateValueImpl, value)\n      }\n      uncontrolledValueRef.value = value\n      nTriggerFormChange()\n      nTriggerFormInput()\n    }\n    function handleFocusin(e: FocusEvent): void {\n      const { value: selfEl } = selfElRef\n      if (!selfEl)\n        return\n      if (selfEl.contains(e.relatedTarget as HTMLElement | null))\n        return\n      nTriggerFormFocus()\n    }\n    function handleFocusout(e: FocusEvent): void {\n      const { value: selfEl } = selfElRef\n      if (!selfEl)\n        return\n      if (selfEl.contains(e.relatedTarget as HTMLElement | null))\n        return\n      nTriggerFormBlur()\n    }\n    provide(radioGroupInjectionKey, {\n      mergedClsPrefixRef,\n      nameRef: toRef(props, 'name'),\n      valueRef: mergedValueRef,\n      disabledRef: mergedDisabledRef,\n      mergedSizeRef,\n      doUpdateValue\n    })\n    const rtlEnabledRef = useRtl('Radio', mergedRtlRef, mergedClsPrefixRef)\n    const cssVarsRef = computed(() => {\n      const { value: size } = mergedSizeRef\n      const {\n        common: { cubicBezierEaseInOut },\n        self: {\n          buttonBorderColor,\n          buttonBorderColorActive,\n          buttonBorderRadius,\n          buttonBoxShadow,\n          buttonBoxShadowFocus,\n          buttonBoxShadowHover,\n          buttonColor,\n          buttonColorActive,\n          buttonTextColor,\n          buttonTextColorActive,\n          buttonTextColorHover,\n          opacityDisabled,\n          [createKey('buttonHeight', size)]: height,\n          [createKey('fontSize', size)]: fontSize\n        }\n      } = themeRef.value\n      return {\n        '--n-font-size': fontSize,\n        '--n-bezier': cubicBezierEaseInOut,\n        '--n-button-border-color': buttonBorderColor,\n        '--n-button-border-color-active': buttonBorderColorActive,\n        '--n-button-border-radius': buttonBorderRadius,\n        '--n-button-box-shadow': buttonBoxShadow,\n        '--n-button-box-shadow-focus': buttonBoxShadowFocus,\n        '--n-button-box-shadow-hover': buttonBoxShadowHover,\n        '--n-button-color': buttonColor,\n        '--n-button-color-active': buttonColorActive,\n        '--n-button-text-color': buttonTextColor,\n        '--n-button-text-color-hover': buttonTextColorHover,\n        '--n-button-text-color-active': buttonTextColorActive,\n        '--n-height': height,\n        '--n-opacity-disabled': opacityDisabled\n      }\n    })\n    const themeClassHandle = inlineThemeDisabled\n      ? useThemeClass(\n          'radio-group',\n          computed(() => mergedSizeRef.value[0]),\n          cssVarsRef,\n          props\n        )\n      : undefined\n    return {\n      selfElRef,\n      rtlEnabled: rtlEnabledRef,\n      mergedClsPrefix: mergedClsPrefixRef,\n      mergedValue: mergedValueRef,\n      handleFocusout,\n      handleFocusin,\n      cssVars: inlineThemeDisabled ? undefined : cssVarsRef,\n      themeClass: themeClassHandle?.themeClass,\n      onRender: themeClassHandle?.onRender\n    }\n  },\n  render() {\n    const { mergedValue, mergedClsPrefix, handleFocusin, handleFocusout } = this\n    const { children, isButtonGroup } = mapSlot(\n      flatten(getSlot(this)),\n      mergedValue,\n      mergedClsPrefix\n    )\n    this.onRender?.()\n    return (\n      <div\n        onFocusin={handleFocusin}\n        onFocusout={handleFocusout}\n        ref=\"selfElRef\"\n        class={[\n          `${mergedClsPrefix}-radio-group`,\n          this.rtlEnabled && `${mergedClsPrefix}-radio-group--rtl`,\n          this.themeClass,\n          isButtonGroup && `${mergedClsPrefix}-radio-group--button-group`\n        ]}\n        style={this.cssVars as CSSProperties}\n      >\n        {children}\n      </div>\n    )\n  }\n})\n"
  },
  {
    "path": "src/radio/src/interface.ts",
    "content": "export type OnUpdateValue = (value: string & number & boolean) => void\n\nexport type OnUpdateValueImpl = (value: string | number | boolean) => void\n"
  },
  {
    "path": "src/radio/src/public-types.ts",
    "content": "export type RadioSize = 'small' | 'medium' | 'large'\n"
  },
  {
    "path": "src/radio/src/styles/radio-group.cssr.ts",
    "content": "import { c, cB, cE, cM, cNotM } from '../../../_utils/cssr'\n\n// vars:\n// --n-bezier\n// --n-button-border-color\n// --n-button-border-color-active\n// --n-height\n// --n-opacity-disabled\n// --n-font-size\nexport default cB('radio-group', `\n  display: inline-block;\n  font-size: var(--n-font-size);\n`, [\n  cE('splitor', `\n    display: inline-block;\n    vertical-align: bottom;\n    width: 1px;\n    transition:\n      background-color .3s var(--n-bezier),\n      opacity .3s var(--n-bezier);\n    background: var(--n-button-border-color);\n  `, [\n    cM('checked', {\n      backgroundColor: 'var(--n-button-border-color-active)'\n    }),\n    cM('disabled', {\n      opacity: 'var(--n-opacity-disabled)'\n    })\n  ]),\n  cM('button-group', `\n    white-space: nowrap;\n    height: var(--n-height);\n    line-height: var(--n-height);\n  `, [\n    cB('radio-button', {\n      height: 'var(--n-height)',\n      lineHeight: 'var(--n-height)'\n    }),\n    cE('splitor', {\n      height: 'var(--n-height)'\n    })\n  ]),\n  cB('radio-button', `\n    vertical-align: bottom;\n    outline: none;\n    position: relative;\n    user-select: none;\n    -webkit-user-select: none;\n    display: inline-block;\n    box-sizing: border-box;\n    padding-left: 14px;\n    padding-right: 14px;\n    white-space: nowrap;\n    transition:\n      background-color .3s var(--n-bezier),\n      opacity .3s var(--n-bezier),\n      border-color .3s var(--n-bezier),\n      color .3s var(--n-bezier);\n    background: var(--n-button-color);\n    color: var(--n-button-text-color);\n    border-top: 1px solid var(--n-button-border-color);\n    border-bottom: 1px solid var(--n-button-border-color);\n  `, [\n    cB('radio-input', `\n      pointer-events: none;\n      position: absolute;\n      border: 0;\n      border-radius: inherit;\n      left: 0;\n      right: 0;\n      top: 0;\n      bottom: 0;\n      opacity: 0;\n      z-index: 1;\n    `),\n    cE('state-border', `\n      z-index: 1;\n      pointer-events: none;\n      position: absolute;\n      box-shadow: var(--n-button-box-shadow);\n      transition: box-shadow .3s var(--n-bezier);\n      left: -1px;\n      bottom: -1px;\n      right: -1px;\n      top: -1px;\n    `),\n    c('&:first-child', `\n      border-top-left-radius: var(--n-button-border-radius);\n      border-bottom-left-radius: var(--n-button-border-radius);\n      border-left: 1px solid var(--n-button-border-color);\n    `, [\n      cE('state-border', `\n        border-top-left-radius: var(--n-button-border-radius);\n        border-bottom-left-radius: var(--n-button-border-radius);\n      `)\n    ]),\n    c('&:last-child', `\n      border-top-right-radius: var(--n-button-border-radius);\n      border-bottom-right-radius: var(--n-button-border-radius);\n      border-right: 1px solid var(--n-button-border-color);\n    `, [\n      cE('state-border', `\n        border-top-right-radius: var(--n-button-border-radius);\n        border-bottom-right-radius: var(--n-button-border-radius);\n      `)\n    ]),\n    cNotM('disabled', `\n      cursor: pointer;\n    `, [\n      c('&:hover', [\n        cE('state-border', `\n          transition: box-shadow .3s var(--n-bezier);\n          box-shadow: var(--n-button-box-shadow-hover);\n        `),\n        cNotM('checked', {\n          color: 'var(--n-button-text-color-hover)'\n        })\n      ]),\n      cM('focus', [\n        c('&:not(:active)', [\n          cE('state-border', {\n            boxShadow: 'var(--n-button-box-shadow-focus)'\n          })\n        ])\n      ])\n    ]),\n    cM('checked', `\n      background: var(--n-button-color-active);\n      color: var(--n-button-text-color-active);\n      border-color: var(--n-button-border-color-active);\n    `),\n    cM('disabled', `\n      cursor: not-allowed;\n      opacity: var(--n-opacity-disabled);\n    `)\n  ])\n])\n"
  },
  {
    "path": "src/radio/src/styles/radio.cssr.ts",
    "content": "import { c, cB, cE, cM, cNotM } from '../../../_utils/cssr'\n\n// vars:\n// --n-bezier\n// --n-box-shadow\n// --n-box-shadow-active\n// --n-box-shadow-disabled\n// --n-box-shadow-focus\n// --n-box-shadow-hover\n// --n-color\n// --n-color-disabled\n// --n-dot-color-active\n// --n-dot-color-disabled\n// --n-font-size\n// --n-radio-size\n// --n-text-color\n// --n-text-color-disabled\n// --n-label-padding\n// --n-label-line-height\n// --n-color-active\nexport default cB('radio', `\n  line-height: var(--n-label-line-height);\n  outline: none;\n  position: relative;\n  user-select: none;\n  -webkit-user-select: none;\n  display: inline-flex;\n  align-items: flex-start;\n  flex-wrap: nowrap;\n  font-size: var(--n-font-size);\n  word-break: break-word;\n`, [\n  cM('checked', [\n    cE('dot', `\n      background-color: var(--n-color-active);\n    `)\n  ]),\n  cE('dot-wrapper', `\n    position: relative;\n    flex-shrink: 0;\n    flex-grow: 0;\n    width: var(--n-radio-size);\n  `),\n  cB('radio-input', `\n    position: absolute;\n    border: 0;\n    width: 0;\n    height: 0;\n    opacity: 0;\n    margin: 0;\n  `),\n  cE('dot', `\n    position: absolute;\n    top: 50%;\n    left: 0;\n    transform: translateY(-50%);\n    height: var(--n-radio-size);\n    width: var(--n-radio-size);\n    background: var(--n-color);\n    box-shadow: var(--n-box-shadow);\n    border-radius: 50%;\n    transition:\n      background-color .3s var(--n-bezier),\n      box-shadow .3s var(--n-bezier);\n  `, [\n    c('&::before', `\n      content: \"\";\n      opacity: 0;\n      position: absolute;\n      left: 4px;\n      top: 4px;\n      height: calc(100% - 8px);\n      width: calc(100% - 8px);\n      border-radius: 50%;\n      transform: scale(.8);\n      background: var(--n-dot-color-active);\n      transition: \n        opacity .3s var(--n-bezier),\n        background-color .3s var(--n-bezier),\n        transform .3s var(--n-bezier);\n    `),\n    cM('checked', {\n      boxShadow: 'var(--n-box-shadow-active)'\n    }, [\n      c('&::before', `\n        opacity: 1;\n        transform: scale(1);\n      `)\n    ])\n  ]),\n  cE('label', `\n    color: var(--n-text-color);\n    padding: var(--n-label-padding);\n    font-weight: var(--n-label-font-weight);\n    display: inline-block;\n    transition: color .3s var(--n-bezier);\n  `),\n  cNotM('disabled', `\n    cursor: pointer;\n  `, [\n    c('&:hover', [\n      cE('dot', {\n        boxShadow: 'var(--n-box-shadow-hover)'\n      })\n    ]),\n    cM('focus', [\n      c('&:not(:active)', [\n        cE('dot', {\n          boxShadow: 'var(--n-box-shadow-focus)'\n        })\n      ])\n    ])\n  ]),\n  cM('disabled', `\n    cursor: not-allowed;\n  `, [\n    cE('dot', {\n      boxShadow: 'var(--n-box-shadow-disabled)',\n      backgroundColor: 'var(--n-color-disabled)'\n    }, [\n      c('&::before', {\n        backgroundColor: 'var(--n-dot-color-disabled)'\n      }),\n      cM('checked', `\n        opacity: 1;\n      `)\n    ]),\n    cE('label', {\n      color: 'var(--n-text-color-disabled)'\n    }),\n    cB('radio-input', `\n      cursor: not-allowed;\n    `)\n  ])\n])\n"
  },
  {
    "path": "src/radio/src/styles/rtl.cssr.ts",
    "content": "import { c, cB, cE, cM } from '../../../_utils/cssr'\n\nexport default c([\n  cB('radio', [\n    cM('rtl', `\n      direction: rtl;\n    `)\n  ]),\n  cB('radio-group', [\n    cM('rtl', `\n      direction: rtl;\n    `, [\n      cB('radio-button', [\n        c('&:first-child', `\n          border-radius: 0 var(--n-button-border-radius) var(--n-button-border-radius) 0;\n          border-right: 1px solid var(--n-button-border-color);\n          border-left: 0;\n        `, [\n          cE('state-border', `\n            border-radius: 0 var(--n-button-border-radius) var(--n-button-border-radius) 0;\n          `)\n        ]),\n        c('&:last-child', `\n          border-radius: var(--n-button-border-radius) 0 0 var(--n-button-border-radius);\n          border-left: 1px solid var(--n-button-border-color);\n          border-right: 0;\n        `, [\n          cE('state-border', `\n            border-radius: var(--n-button-border-radius) 0 0 var(--n-button-border-radius);\n          `)\n        ]),\n        cM('checked', `\n          border-color: var(--n-button-border-color-active);\n        `)\n      ])\n    ])\n  ])\n])\n"
  },
  {
    "path": "src/radio/src/use-radio.ts",
    "content": "import type { ComputedRef, ExtractPropTypes, PropType, Ref } from 'vue'\nimport type { MaybeArray } from '../../_utils'\nimport type { OnUpdateValue, OnUpdateValueImpl } from './interface'\nimport type { RadioSize } from './public-types'\nimport { useMemo, useMergedState } from 'vooks'\nimport { inject, ref, toRef, watchEffect } from 'vue'\nimport { useConfig, useFormItem } from '../../_mixins'\nimport { call, createInjectionKey, warnOnce } from '../../_utils'\n\nexport const radioBaseProps = {\n  name: String,\n  value: {\n    type: [String, Number, Boolean] as PropType<string | number | boolean>,\n    default: 'on'\n  },\n  checked: {\n    type: Boolean as PropType<boolean | undefined>,\n    default: undefined\n  },\n  defaultChecked: Boolean,\n  disabled: {\n    type: Boolean as PropType<boolean | undefined>,\n    default: undefined\n  },\n  label: String,\n  size: String as PropType<RadioSize>,\n  onUpdateChecked: [Function, Array] as PropType<\n    undefined | MaybeArray<(value: boolean) => void>\n  >,\n  'onUpdate:checked': [Function, Array] as PropType<\n    undefined | MaybeArray<(value: boolean) => void>\n  >,\n  // deprecated\n  checkedValue: {\n    type: Boolean as PropType<boolean | undefined>,\n    default: undefined\n  }\n} as const\n\nexport interface RadioGroupInjection {\n  mergedClsPrefixRef: Ref<string>\n  nameRef: Ref<string | undefined>\n  valueRef: Ref<string | number | boolean | null>\n  mergedSizeRef: Ref<RadioSize>\n  disabledRef: Ref<boolean>\n  doUpdateValue: OnUpdateValue\n}\n\nexport const radioGroupInjectionKey\n  = createInjectionKey<RadioGroupInjection>('n-radio-group')\n\nexport interface UseRadio {\n  mergedClsPrefix: Ref<string>\n  inputRef: Ref<HTMLElement | null>\n  labelRef: Ref<HTMLElement | null>\n  mergedName: Ref<string | undefined>\n  mergedDisabled: Ref<boolean>\n  renderSafeChecked: Ref<boolean>\n  focus: Ref<boolean>\n  mergedSize: ComputedRef<RadioSize>\n  handleRadioInputChange: () => void\n  handleRadioInputBlur: () => void\n  handleRadioInputFocus: () => void\n}\n\nfunction setup(props: ExtractPropTypes<typeof radioBaseProps>): UseRadio {\n  if (__DEV__) {\n    watchEffect(() => {\n      if (props.checkedValue !== undefined) {\n        warnOnce(\n          'radio',\n          '`checked-value` is deprecated, please use `checked` instead.'\n        )\n      }\n    })\n  }\n  const NRadioGroup = inject(radioGroupInjectionKey, null)\n  const { mergedClsPrefixRef, mergedComponentPropsRef } = useConfig(props)\n  const formItem = useFormItem(props, {\n    mergedSize(NFormItem) {\n      const { size } = props\n      if (size !== undefined)\n        return size\n      if (NRadioGroup) {\n        const {\n          mergedSizeRef: { value: mergedSize }\n        } = NRadioGroup\n        if (mergedSize !== undefined) {\n          return mergedSize\n        }\n      }\n      if (NFormItem) {\n        return NFormItem.mergedSize.value\n      }\n      const configSize = mergedComponentPropsRef?.value?.Radio?.size\n      if (configSize)\n        return configSize\n      return 'medium'\n    },\n    mergedDisabled(NFormItem) {\n      if (props.disabled)\n        return true\n      if (NRadioGroup?.disabledRef.value)\n        return true\n      if (NFormItem?.disabled.value)\n        return true\n      return false\n    }\n  })\n  const { mergedSizeRef, mergedDisabledRef } = formItem\n  const inputRef = ref<HTMLInputElement | null>(null)\n  const labelRef = ref<HTMLElement | null>(null)\n  const uncontrolledCheckedRef = ref(props.defaultChecked)\n  const controlledCheckedRef = toRef(props, 'checked')\n  const mergedCheckedRef = useMergedState(\n    controlledCheckedRef,\n    uncontrolledCheckedRef\n  )\n  const renderSafeCheckedRef = useMemo(() => {\n    if (NRadioGroup)\n      return NRadioGroup.valueRef.value === props.value\n    return mergedCheckedRef.value\n  })\n  const mergedNameRef = useMemo(() => {\n    const { name } = props\n    if (name !== undefined)\n      return name\n    if (NRadioGroup)\n      return NRadioGroup.nameRef.value\n  })\n  const focusRef = ref(false)\n  function doUpdateChecked(): void {\n    if (NRadioGroup) {\n      const { doUpdateValue } = NRadioGroup\n      const { value } = props\n      call(doUpdateValue as OnUpdateValueImpl, value)\n    }\n    else {\n      const { onUpdateChecked, 'onUpdate:checked': _onUpdateChecked } = props\n      const { nTriggerFormInput, nTriggerFormChange } = formItem\n      if (onUpdateChecked)\n        call(onUpdateChecked, true)\n      if (_onUpdateChecked)\n        call(_onUpdateChecked, true)\n      nTriggerFormInput()\n      nTriggerFormChange()\n      uncontrolledCheckedRef.value = true\n    }\n  }\n  function toggle(): void {\n    if (mergedDisabledRef.value)\n      return\n    if (!renderSafeCheckedRef.value) {\n      doUpdateChecked()\n    }\n  }\n  function handleRadioInputChange(): void {\n    toggle()\n    // Restore element check prop's value to current state, since if doesn't\n    // reflect current VNode. If not, bug will happens in component with element\n    // that has internal state such as <input />.\n    if (inputRef.value) {\n      inputRef.value.checked = renderSafeCheckedRef.value\n    }\n  }\n  function handleRadioInputBlur(): void {\n    focusRef.value = false\n  }\n  function handleRadioInputFocus(): void {\n    focusRef.value = true\n  }\n  return {\n    mergedClsPrefix: NRadioGroup\n      ? NRadioGroup.mergedClsPrefixRef\n      : mergedClsPrefixRef,\n    inputRef,\n    labelRef,\n    mergedName: mergedNameRef,\n    mergedDisabled: mergedDisabledRef,\n    renderSafeChecked: renderSafeCheckedRef,\n    focus: focusRef,\n    mergedSize: mergedSizeRef,\n    handleRadioInputChange,\n    handleRadioInputBlur,\n    handleRadioInputFocus\n  }\n}\n\nexport type RadioBaseProps = ExtractPropTypes<typeof radioBaseProps>\nexport { setup }\n"
  },
  {
    "path": "src/radio/styles/_common.ts",
    "content": "export default {\n  radioSizeSmall: '14px',\n  radioSizeMedium: '16px',\n  radioSizeLarge: '18px',\n  labelPadding: '0 8px',\n  labelFontWeight: '400'\n}\n"
  },
  {
    "path": "src/radio/styles/dark.ts",
    "content": "import type { RadioTheme } from './light'\nimport { changeColor } from 'seemly'\nimport { commonDark } from '../../_styles/common'\nimport commonVariables from './_common'\n\nconst radioDark: RadioTheme = {\n  name: 'Radio',\n  common: commonDark,\n  self(vars) {\n    const {\n      borderColor,\n      primaryColor,\n      baseColor,\n      textColorDisabled,\n      inputColorDisabled,\n      textColor2,\n      opacityDisabled,\n      borderRadius,\n      fontSizeSmall,\n      fontSizeMedium,\n      fontSizeLarge,\n      heightSmall,\n      heightMedium,\n      heightLarge,\n      lineHeight\n    } = vars\n    return {\n      ...commonVariables,\n      labelLineHeight: lineHeight,\n      buttonHeightSmall: heightSmall,\n      buttonHeightMedium: heightMedium,\n      buttonHeightLarge: heightLarge,\n      fontSizeSmall,\n      fontSizeMedium,\n      fontSizeLarge,\n      boxShadow: `inset 0 0 0 1px ${borderColor}`,\n      boxShadowActive: `inset 0 0 0 1px ${primaryColor}`,\n      boxShadowFocus: `inset 0 0 0 1px ${primaryColor}, 0 0 0 2px ${changeColor(\n        primaryColor,\n        { alpha: 0.3 }\n      )}`,\n      boxShadowHover: `inset 0 0 0 1px ${primaryColor}`,\n      boxShadowDisabled: `inset 0 0 0 1px ${borderColor}`,\n      color: '#0000',\n      colorDisabled: inputColorDisabled,\n      colorActive: '#0000',\n      textColor: textColor2,\n      textColorDisabled,\n      dotColorActive: primaryColor,\n      dotColorDisabled: borderColor,\n      buttonBorderColor: borderColor,\n      buttonBorderColorActive: primaryColor,\n      buttonBorderColorHover: primaryColor,\n      buttonColor: '#0000',\n      buttonColorActive: primaryColor,\n      buttonTextColor: textColor2,\n      buttonTextColorActive: baseColor,\n      buttonTextColorHover: primaryColor,\n      opacityDisabled,\n      buttonBoxShadowFocus: `inset 0 0 0 1px ${primaryColor}, 0 0 0 2px ${changeColor(\n        primaryColor,\n        { alpha: 0.3 }\n      )}`,\n      buttonBoxShadowHover: `inset 0 0 0 1px ${primaryColor}`,\n      buttonBoxShadow: 'inset 0 0 0 1px #0000',\n      buttonBorderRadius: borderRadius\n    }\n  }\n}\n\nexport default radioDark\n"
  },
  {
    "path": "src/radio/styles/index.ts",
    "content": "export { default as radioDark } from './dark'\nexport { default as radioLight } from './light'\nexport type { RadioTheme, RadioThemeVars } from './light'\nexport { radioRtl } from './rtl'\n"
  },
  {
    "path": "src/radio/styles/light.ts",
    "content": "import type { Theme } from '../../_mixins/use-theme'\nimport type { ThemeCommonVars } from '../../_styles/common'\nimport { changeColor } from 'seemly'\nimport { commonLight } from '../../_styles/common'\nimport commonVariables from './_common'\n\nfunction self(vars: ThemeCommonVars) {\n  const {\n    borderColor,\n    primaryColor,\n    baseColor,\n    textColorDisabled,\n    inputColorDisabled,\n    textColor2,\n    opacityDisabled,\n    borderRadius,\n    fontSizeSmall,\n    fontSizeMedium,\n    fontSizeLarge,\n    heightSmall,\n    heightMedium,\n    heightLarge,\n    lineHeight\n  } = vars\n  return {\n    ...commonVariables,\n    labelLineHeight: lineHeight,\n    buttonHeightSmall: heightSmall,\n    buttonHeightMedium: heightMedium,\n    buttonHeightLarge: heightLarge,\n    fontSizeSmall,\n    fontSizeMedium,\n    fontSizeLarge,\n    boxShadow: `inset 0 0 0 1px ${borderColor}`,\n    boxShadowActive: `inset 0 0 0 1px ${primaryColor}`,\n    boxShadowFocus: `inset 0 0 0 1px ${primaryColor}, 0 0 0 2px ${changeColor(\n      primaryColor,\n      { alpha: 0.2 }\n    )}`,\n    boxShadowHover: `inset 0 0 0 1px ${primaryColor}`,\n    boxShadowDisabled: `inset 0 0 0 1px ${borderColor}`,\n    color: baseColor,\n    colorDisabled: inputColorDisabled,\n    colorActive: '#0000',\n    textColor: textColor2,\n    textColorDisabled,\n    dotColorActive: primaryColor,\n    dotColorDisabled: borderColor,\n    buttonBorderColor: borderColor,\n    buttonBorderColorActive: primaryColor,\n    buttonBorderColorHover: borderColor,\n    buttonColor: baseColor,\n    buttonColorActive: baseColor,\n    buttonTextColor: textColor2,\n    buttonTextColorActive: primaryColor,\n    buttonTextColorHover: primaryColor,\n    opacityDisabled,\n    buttonBoxShadowFocus: `inset 0 0 0 1px ${primaryColor}, 0 0 0 2px ${changeColor(\n      primaryColor,\n      { alpha: 0.3 }\n    )}`,\n    buttonBoxShadowHover: 'inset 0 0 0 1px #0000',\n    buttonBoxShadow: 'inset 0 0 0 1px #0000',\n    buttonBorderRadius: borderRadius\n  }\n}\n\nexport type RadioThemeVars = ReturnType<typeof self>\n\nconst radioLight: Theme<'Radio', RadioThemeVars> = {\n  name: 'Radio',\n  common: commonLight,\n  self\n}\n\nexport default radioLight\nexport type RadioTheme = typeof radioLight\n"
  },
  {
    "path": "src/radio/styles/rtl.ts",
    "content": "import type { RtlItem } from '../../config-provider/src/internal-interface'\nimport rtlStyle from '../src/styles/rtl.cssr'\n\nexport const radioRtl: RtlItem = {\n  name: 'Radio',\n  style: rtlStyle\n}\n"
  },
  {
    "path": "src/radio/tests/Radio.spec.ts",
    "content": "import { mount } from '@vue/test-utils'\nimport { h } from 'vue'\nimport { NRadio, NRadioGroup } from '../index'\n\ndescribe('n-radio', () => {\n  it('should work with import on demand', () => {\n    mount(NRadio)\n  })\n\n  it('should work with `checked` prop', async () => {\n    const wrapper = mount(NRadio, { props: { checked: false } })\n    expect(wrapper.find('.n-radio').classes()).not.toContain('n-radio--checked')\n    await wrapper.setProps({ checked: true })\n    expect(wrapper.find('.n-radio').classes()).toContain('n-radio--checked')\n    wrapper.unmount()\n  })\n\n  it('should work with `defaultChecked` prop', async () => {\n    let wrapper = mount(NRadio, { props: { defaultChecked: true } })\n    expect(wrapper.find('.n-radio').classes()).toContain('n-radio--checked')\n\n    wrapper = mount(NRadio, { props: { defaultChecked: false } })\n    expect(wrapper.find('.n-radio').classes()).not.toContain('n-radio--checked')\n    wrapper.unmount()\n  })\n\n  it('should work with `disabled` prop', async () => {\n    const wrapper = mount(NRadio, { props: { disabled: false } })\n    expect(wrapper.find('.n-radio').classes()).not.toContain(\n      'n-radio--disabled'\n    )\n    await wrapper.setProps({ disabled: true })\n    expect(wrapper.find('.n-radio').classes()).toContain('n-radio--disabled')\n    wrapper.unmount()\n  })\n\n  it('should work with `name` prop', async () => {\n    const wrapper = mount(NRadio, { props: { name: 'randomName111' } })\n\n    const radio = wrapper.find('input[type=radio]')\n\n    expect(radio.attributes('name')).toEqual('randomName111')\n\n    await wrapper.setProps({ name: 'randomName222' })\n\n    expect(radio.attributes('name')).toEqual('randomName222')\n    wrapper.unmount()\n  })\n\n  it('should render default slot content', async () => {\n    const wrapper = mount(NRadio, { slots: { default: 'MySlotContent' } })\n\n    const radio = wrapper.find('.n-radio__label')\n\n    expect(radio.text()).toContain('MySlotContent')\n    wrapper.unmount()\n  })\n\n  it('should work with `label` prop', async () => {\n    const wrapper = mount(NRadio, { props: { label: 'MyRandomLabel' } })\n\n    const radio = wrapper.find('.n-radio__label')\n\n    expect(radio.text()).toContain('MyRandomLabel')\n\n    await wrapper.setProps({ label: 'MyNewRandomLabel' })\n\n    expect(radio.text()).toContain('MyNewRandomLabel')\n    wrapper.unmount()\n  })\n\n  it('should render default slot content in priority of label', async () => {\n    const wrapper = mount(NRadio, {\n      props: { label: 'MyRandomLabel' },\n      slots: { default: 'MySlotContent' }\n    })\n\n    const radio = wrapper.find('.n-radio__label')\n\n    expect(radio.text()).not.toContain('MyRandomLabel')\n    expect(radio.text()).toContain('MySlotContent')\n    wrapper.unmount()\n  })\n\n  it('should work with `size` prop', async () => {\n    ;(['small', 'medium', 'large'] as const).forEach((size) => {\n      const wrapper = mount(NRadio, { props: { size } })\n      expect(wrapper.find('.n-radio').attributes('style')).toMatchSnapshot()\n      wrapper.unmount()\n    })\n  })\n\n  it('should work with `onUpdate:checked` prop', async () => {\n    const onUpdate1 = vi.fn()\n    const onUpdate2 = vi.fn()\n    const wrapper = mount(NRadio, {\n      props: { 'onUpdate:checked': onUpdate1, onUpdateChecked: onUpdate2 },\n      // special case for trigger click with radio input need `attachTo`\n      // https://github.com/vuejs/test-utils/issues/1470\n      attachTo: document.body\n    })\n\n    await wrapper.find('.n-radio').trigger('click')\n    expect(onUpdate1).toHaveBeenCalled()\n    expect(onUpdate2).toHaveBeenCalled()\n    wrapper.unmount()\n  })\n})\n\ndescribe('n-radio-group', () => {\n  it('should work with import on demand', () => {\n    mount(NRadioGroup, {\n      slots: {\n        default: () => [\n          h(NRadio, null, { default: () => 'test-item1' }),\n          h(NRadio, null, { default: () => 'test-item2' })\n        ]\n      }\n    })\n  })\n\n  it('should work with `disabled` prop', async () => {\n    const wrapper = mount(NRadioGroup, {\n      slots: {\n        default: () => [\n          h(NRadio, null, { default: () => 'test-item1' }),\n          h(NRadio, null, { default: () => 'test-item2' })\n        ]\n      }\n    })\n    expect(wrapper.find('.n-radio--disabled').exists()).not.toBe(true)\n\n    await wrapper.setProps({ disabled: true })\n    expect(wrapper.findAll('.n-radio')[0].classes()).toContain(\n      'n-radio--disabled'\n    )\n    expect(wrapper.findAll('.n-radio')[1].classes()).toContain(\n      'n-radio--disabled'\n    )\n    wrapper.unmount()\n  })\n\n  it('should work with `name` prop', async () => {\n    const wrapper = mount(NRadioGroup, {\n      props: {\n        name: 'randomName111'\n      },\n      slots: {\n        default: () => [\n          h(NRadio, null, { default: () => 'test-item1' }),\n          h(NRadio, null, { default: () => 'test-item2' })\n        ]\n      }\n    })\n\n    const radio1 = wrapper.findAll('input[type=radio]')[0]\n    const radio2 = wrapper.findAll('input[type=radio]')[1]\n\n    expect(radio1.attributes('name')).toEqual('randomName111')\n    expect(radio2.attributes('name')).toEqual('randomName111')\n\n    await wrapper.setProps({ name: 'randomName222' })\n\n    expect(radio1.attributes('name')).toEqual('randomName222')\n    expect(radio2.attributes('name')).toEqual('randomName222')\n    wrapper.unmount()\n  })\n\n  it('should work with `size` prop', async () => {\n    ;(['small', 'medium', 'large'] as const).forEach((size) => {\n      const wrapper = mount(NRadioGroup, {\n        props: {\n          size\n        },\n        slots: {\n          default: () => [\n            h(NRadio, null, { default: () => 'test-item1' }),\n            h(NRadio, null, { default: () => 'test-item2' })\n          ]\n        }\n      })\n      expect(\n        wrapper.find('.n-radio-group').attributes('style')\n      ).toMatchSnapshot()\n      wrapper.unmount()\n    })\n  })\n\n  it('should work with `value` prop', async () => {\n    const wrapper = mount(NRadioGroup, {\n      props: {\n        value: 'test1'\n      },\n      slots: {\n        default: () => [\n          h(NRadio, { value: 'test1' }, { default: () => 'test-item1' }),\n          h(NRadio, { value: 'test2' }, { default: () => 'test-item2' })\n        ]\n      }\n    })\n    expect(wrapper.findAll('.n-radio')[0].classes()).toContain(\n      'n-radio--checked'\n    )\n    expect(wrapper.findAll('.n-radio')[1].classes()).not.toContain(\n      'n-radio--checked'\n    )\n\n    await wrapper.setProps({ value: 'test2' })\n    expect(wrapper.findAll('.n-radio')[1].classes()).toContain(\n      'n-radio--checked'\n    )\n    expect(wrapper.findAll('.n-radio')[0].classes()).not.toContain(\n      'n-radio--checked'\n    )\n    wrapper.unmount()\n  })\n\n  it('should work with `on-update:value` prop', async () => {\n    const onUpdate = vi.fn()\n    const wrapper = mount(NRadioGroup, {\n      attachTo: document.body,\n      props: {\n        onUpdateValue: onUpdate\n      },\n      slots: {\n        default: () => [\n          h(NRadio, { value: 'test1' }, { default: () => 'test-item1' }),\n          h(NRadio, { value: 'test2' }, { default: () => 'test-item2' })\n        ]\n      }\n    })\n\n    await wrapper.findAll('.n-radio')[1].trigger('click')\n    expect(onUpdate).toHaveBeenCalled()\n    wrapper.unmount()\n  })\n})\n"
  },
  {
    "path": "src/radio/tests/__snapshots__/Radio.spec.ts.snap",
    "content": "// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html\n\nexports[`n-radio > should work with \\`size\\` prop 1`] = `\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-label-line-height: 1.6; --n-label-font-weight: 400; --n-box-shadow: inset 0 0 0 1px rgb(224, 224, 230); --n-box-shadow-active: inset 0 0 0 1px #18a058; --n-box-shadow-disabled: inset 0 0 0 1px rgb(224, 224, 230); --n-box-shadow-focus: inset 0 0 0 1px #18a058, 0 0 0 2px rgba(24, 160, 88, 0.2); --n-box-shadow-hover: inset 0 0 0 1px #18a058; --n-color: #FFF; --n-color-active: #0000; --n-color-disabled: rgb(250, 250, 252); --n-dot-color-active: #18a058; --n-dot-color-disabled: rgb(224, 224, 230); --n-font-size: 14px; --n-radio-size: 14px; --n-text-color: rgb(51, 54, 57); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-label-padding: 0 8px;\"`;\n\nexports[`n-radio > should work with \\`size\\` prop 2`] = `\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-label-line-height: 1.6; --n-label-font-weight: 400; --n-box-shadow: inset 0 0 0 1px rgb(224, 224, 230); --n-box-shadow-active: inset 0 0 0 1px #18a058; --n-box-shadow-disabled: inset 0 0 0 1px rgb(224, 224, 230); --n-box-shadow-focus: inset 0 0 0 1px #18a058, 0 0 0 2px rgba(24, 160, 88, 0.2); --n-box-shadow-hover: inset 0 0 0 1px #18a058; --n-color: #FFF; --n-color-active: #0000; --n-color-disabled: rgb(250, 250, 252); --n-dot-color-active: #18a058; --n-dot-color-disabled: rgb(224, 224, 230); --n-font-size: 14px; --n-radio-size: 16px; --n-text-color: rgb(51, 54, 57); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-label-padding: 0 8px;\"`;\n\nexports[`n-radio > should work with \\`size\\` prop 3`] = `\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-label-line-height: 1.6; --n-label-font-weight: 400; --n-box-shadow: inset 0 0 0 1px rgb(224, 224, 230); --n-box-shadow-active: inset 0 0 0 1px #18a058; --n-box-shadow-disabled: inset 0 0 0 1px rgb(224, 224, 230); --n-box-shadow-focus: inset 0 0 0 1px #18a058, 0 0 0 2px rgba(24, 160, 88, 0.2); --n-box-shadow-hover: inset 0 0 0 1px #18a058; --n-color: #FFF; --n-color-active: #0000; --n-color-disabled: rgb(250, 250, 252); --n-dot-color-active: #18a058; --n-dot-color-disabled: rgb(224, 224, 230); --n-font-size: 15px; --n-radio-size: 18px; --n-text-color: rgb(51, 54, 57); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-label-padding: 0 8px;\"`;\n\nexports[`n-radio-group > should work with \\`size\\` prop 1`] = `\"--n-font-size: 14px; --n-bezier: cubic-bezier(.4, 0, .2, 1); --n-button-border-color: rgb(224, 224, 230); --n-button-border-color-active: #18a058; --n-button-border-radius: 3px; --n-button-box-shadow: inset 0 0 0 1px #0000; --n-button-box-shadow-focus: inset 0 0 0 1px #18a058, 0 0 0 2px rgba(24, 160, 88, 0.3); --n-button-box-shadow-hover: inset 0 0 0 1px #0000; --n-button-color: #FFF; --n-button-color-active: #FFF; --n-button-text-color: rgb(51, 54, 57); --n-button-text-color-hover: #18a058; --n-button-text-color-active: #18a058; --n-height: 28px; --n-opacity-disabled: 0.5;\"`;\n\nexports[`n-radio-group > should work with \\`size\\` prop 2`] = `\"--n-font-size: 14px; --n-bezier: cubic-bezier(.4, 0, .2, 1); --n-button-border-color: rgb(224, 224, 230); --n-button-border-color-active: #18a058; --n-button-border-radius: 3px; --n-button-box-shadow: inset 0 0 0 1px #0000; --n-button-box-shadow-focus: inset 0 0 0 1px #18a058, 0 0 0 2px rgba(24, 160, 88, 0.3); --n-button-box-shadow-hover: inset 0 0 0 1px #0000; --n-button-color: #FFF; --n-button-color-active: #FFF; --n-button-text-color: rgb(51, 54, 57); --n-button-text-color-hover: #18a058; --n-button-text-color-active: #18a058; --n-height: 34px; --n-opacity-disabled: 0.5;\"`;\n\nexports[`n-radio-group > should work with \\`size\\` prop 3`] = `\"--n-font-size: 15px; --n-bezier: cubic-bezier(.4, 0, .2, 1); --n-button-border-color: rgb(224, 224, 230); --n-button-border-color-active: #18a058; --n-button-border-radius: 3px; --n-button-box-shadow: inset 0 0 0 1px #0000; --n-button-box-shadow-focus: inset 0 0 0 1px #18a058, 0 0 0 2px rgba(24, 160, 88, 0.3); --n-button-box-shadow-hover: inset 0 0 0 1px #0000; --n-button-color: #FFF; --n-button-color-active: #FFF; --n-button-text-color: rgb(51, 54, 57); --n-button-text-color-hover: #18a058; --n-button-text-color-active: #18a058; --n-height: 40px; --n-opacity-disabled: 0.5;\"`;\n"
  },
  {
    "path": "src/radio/tests/server.spec.tsx",
    "content": "import { setup } from '@css-render/vue3-ssr'\nimport { renderToString } from '@vue/server-renderer'\n/**\n * @vitest-environment node\n */\nimport { createSSRApp, h } from 'vue'\nimport { NRadio } from '../..'\n\ndescribe('server side rendering', () => {\n  it('works', async () => {\n    const app = createSSRApp(() => <NRadio />)\n    setup(app)\n    try {\n      await renderToString(app)\n    }\n    catch (e) {\n      expect(e).not.toBeTruthy()\n    }\n  })\n})\n"
  },
  {
    "path": "src/rate/demos/enUS/allow-half.demo.vue",
    "content": "<markdown>\n# Allow Selecting Half Star\n</markdown>\n\n<template>\n  <n-rate allow-half />\n</template>\n"
  },
  {
    "path": "src/rate/demos/enUS/basic.demo.vue",
    "content": "<markdown>\n# Basic\n</markdown>\n\n<template>\n  <n-rate />\n</template>\n"
  },
  {
    "path": "src/rate/demos/enUS/clearable.demo.vue",
    "content": "<markdown>\n# Clearable\n\nAfter `clearable` is set, you can click at current value's corresponding value to reset value to `null`.\n</markdown>\n\n<template>\n  <n-rate clearable allow-half />\n</template>\n"
  },
  {
    "path": "src/rate/demos/enUS/color.demo.vue",
    "content": "<markdown>\n# Color\n\nThis can end in disaster.\n</markdown>\n\n<template>\n  <n-rate color=\"#4fb233\" />\n</template>\n"
  },
  {
    "path": "src/rate/demos/enUS/icon.demo.vue",
    "content": "<markdown>\n# Icon\n\nThe content of the default slot will be used as the icon.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { CashOutline as CashIcon } from '@vicons/ionicons5'\n</script>\n\n<template>\n  <n-rate>\n    <n-icon size=\"20\">\n      <CashIcon />\n    </n-icon>\n  </n-rate>\n</template>\n"
  },
  {
    "path": "src/rate/demos/enUS/index.demo-entry.md",
    "content": "# Rate\n\nHint: If you are not very confident, think twice before changing the star's color. That can lead to a disaster.\n\n## Demos\n\n```demo\nbasic.vue\nsize.vue\ncolor.vue\nicon.vue\nallow-half.vue\nreadonly.vue\nclearable.vue\n```\n\n## API\n\n### Rate Props\n\n| Name | Type | Default | Description | Version |\n| --- | --- | --- | --- | --- |\n| allow-half | `boolean` | `false` | Allow activating half of the icon. |  |\n| clearable | `boolean` | `false` | Whether the rate is clearable. Value will be set to `null` if you click on current value's corresponding icon. | 2.33.0 |\n| color | `string` | `undefined` | Activated icon color. This supports the formats: `#FFF`, `#FFFFFF`, `yellow`, `rgb(0, 0, 0)`. |  |\n| count | `number` | `5` | Number of icons (max rating). |  |\n| default-value | `number \\| null` | `null` | Default value of activated icons. Before 2.33.0 default value is `null`. | 2.33.0 `null` |\n| readonly | `boolean` | `false` | Readonly state. |  |\n| size | `'small' \\| 'medium' \\| 'large' \\| number` | `'medium'` | Icon size. |  |\n| value | `number \\| null` | `undefined` | Value of activated icons. |  |\n| on-clear | `() => void` | `undefined` | Callback on value is cleared. | 2.33.0 |\n| on-update:value | `(value: number) => void` | `undefined` | Callback on the value (rating) is changed. |  |\n\n### Rate Slots\n\n| Name    | Parameters                  | Description             |\n| ------- | --------------------------- | ----------------------- |\n| default | `(info: { index: number })` | The icon of the rating. |\n"
  },
  {
    "path": "src/rate/demos/enUS/readonly.demo.vue",
    "content": "<markdown>\n# Readonly\n</markdown>\n\n<template>\n  <n-rate readonly :default-value=\"3\" />\n</template>\n"
  },
  {
    "path": "src/rate/demos/enUS/size.demo.vue",
    "content": "<markdown>\n# Size\n\nRate has `small`, `medium` and `large` size. Also you can use number to specify the size.\n</markdown>\n\n<template>\n  <n-space align=\"center\">\n    <n-rate size=\"small\" />\n    <n-rate size=\"medium\" />\n    <n-rate size=\"large\" />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/rate/demos/zhCN/allow-half.demo.vue",
    "content": "<markdown>\n# 允许半颗\n</markdown>\n\n<template>\n  <n-rate allow-half />\n</template>\n"
  },
  {
    "path": "src/rate/demos/zhCN/basic.demo.vue",
    "content": "<markdown>\n# 基础用法\n</markdown>\n\n<template>\n  <n-rate />\n</template>\n"
  },
  {
    "path": "src/rate/demos/zhCN/clearable.demo.vue",
    "content": "<markdown>\n# 可清空\n\n设定 `clearable` 后 `n-rate` 可清空，在你点击当前值对应的图标后值会被设为 `null`。\n</markdown>\n\n<template>\n  <n-rate clearable allow-half />\n</template>\n"
  },
  {
    "path": "src/rate/demos/zhCN/color.demo.vue",
    "content": "<markdown>\n# 颜色\n\n灾难就是这么发生的。\n</markdown>\n\n<template>\n  <n-rate color=\"#4fb233\" />\n</template>\n"
  },
  {
    "path": "src/rate/demos/zhCN/icon.demo.vue",
    "content": "<markdown>\n# 图标\n\n默认插槽的内容会被用作图标。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { CashOutline as CashIcon } from '@vicons/ionicons5'\n</script>\n\n<template>\n  <n-rate>\n    <n-icon size=\"20\">\n      <CashIcon />\n    </n-icon>\n  </n-rate>\n</template>\n"
  },
  {
    "path": "src/rate/demos/zhCN/index.demo-entry.md",
    "content": "# 评分 Rate\n\n没有把握的话不要给星星换颜色，那会是个灾难。\n\n## 演示\n\n```demo\nbasic.vue\nsize.vue\ncolor.vue\nicon.vue\nallow-half.vue\nreadonly.vue\nclearable.vue\n```\n\n## API\n\n### Rate Props\n\n| 名称 | 类型 | 默认值 | 说明 | 版本 |\n| --- | --- | --- | --- | --- |\n| allow-half | `boolean` | `false` | 允许只激活一半图标 |  |\n| clearable | `boolean` | `false` | 是否可清空，在点击当前值对应的图标后值会被设为 `null` | 2.33.0 |\n| color | `string` | `undefined` | 已激活图标颜色（支持形如 `#FFF`， `#FFFFFF`， `yellow`，`rgb(0, 0, 0)` 的颜色） |  |\n| count | `number` | `5` | 图标个数 |  |\n| default-value | `number \\| null` | `null` | 默认已激活图标个数，2.33.0 前默认值为 `0` | 2.33.0 开始支持 `null` |\n| readonly | `boolean` | `false` | 只读，交互失效 |  |\n| size | `'small' \\| 'medium' \\| 'large' \\| number` | `'medium'` | 图标尺寸 |  |\n| value | `number \\| null` | `undefined` | 已激活图标个数 |  |\n| on-clear | `() => void` | `undefined` | 清除当前值的回调 | 2.33.0 |\n| on-update:value | `(value: number) => void` | `undefined` | 激活图标个数改变时触发 |  |\n\n### Rate Slots\n\n| 名称    | 参数                        | 说明       |\n| ------- | --------------------------- | ---------- |\n| default | `(info: { index: number })` | 评分的图标 |\n"
  },
  {
    "path": "src/rate/demos/zhCN/readonly.demo.vue",
    "content": "<markdown>\n# 只读\n</markdown>\n\n<template>\n  <n-rate readonly :default-value=\"3\" />\n</template>\n"
  },
  {
    "path": "src/rate/demos/zhCN/size.demo.vue",
    "content": "<markdown>\n# 尺寸\n\n有 `small`、`medium` 和 `large` 尺寸。\n</markdown>\n\n<template>\n  <n-space align=\"center\">\n    <n-rate size=\"small\" />\n    <n-rate size=\"medium\" />\n    <n-rate size=\"large\" />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/rate/index.ts",
    "content": "export type * from './src/public-types'\nexport { default as NRate, rateProps } from './src/Rate'\nexport type { RateProps } from './src/Rate'\n"
  },
  {
    "path": "src/rate/src/Rate.tsx",
    "content": "import type { CSSProperties, PropType } from 'vue'\nimport type { ThemeProps } from '../../_mixins'\nimport type { ExtractPublicPropTypes, MaybeArray } from '../../_utils'\nimport type { RateTheme } from '../styles'\nimport type { RateOnUpdateValue, RateOnUpdateValueImpl } from './interface'\nimport type { RateSize } from './public-types'\nimport { useMergedState } from 'vooks'\nimport { computed, defineComponent, h, ref, renderList, toRef } from 'vue'\nimport { NBaseIcon } from '../../_internal'\nimport { useConfig, useFormItem, useTheme, useThemeClass } from '../../_mixins'\nimport { call, color2Class, createKey } from '../../_utils'\nimport { rateLight } from '../styles'\nimport renderStarIcon from './StarIcon'\nimport style from './styles/index.cssr'\n\nexport const rateProps = {\n  ...(useTheme.props as ThemeProps<RateTheme>),\n  allowHalf: Boolean,\n  count: {\n    type: Number,\n    default: 5\n  },\n  value: Number,\n  defaultValue: {\n    type: Number as PropType<number | null>,\n    default: null\n  },\n  readonly: Boolean,\n  size: [String, Number] as PropType<RateSize>,\n  clearable: Boolean,\n  color: String,\n  onClear: Function as PropType<() => void>,\n  'onUpdate:value': [Function, Array] as PropType<\n    MaybeArray<RateOnUpdateValue>\n  >,\n  onUpdateValue: [Function, Array] as PropType<MaybeArray<RateOnUpdateValue>>\n} as const\n\nexport type RateProps = ExtractPublicPropTypes<typeof rateProps>\n\nexport default defineComponent({\n  name: 'Rate',\n  props: rateProps,\n  setup(props) {\n    const { mergedClsPrefixRef, inlineThemeDisabled, mergedComponentPropsRef }\n      = useConfig(props)\n    const themeRef = useTheme(\n      'Rate',\n      '-rate',\n      style,\n      rateLight,\n      props,\n      mergedClsPrefixRef\n    )\n    const controlledValueRef = toRef(props, 'value')\n    const uncontrolledValueRef = ref(props.defaultValue)\n    const hoverIndexRef = ref<number | null>(null)\n    const formItem = useFormItem<RateSize>(props, {\n      mergedSize(NFormItem) {\n        if (props.size !== undefined)\n          return props.size\n        if (NFormItem) {\n          return NFormItem.mergedSize.value as RateSize\n        }\n        const configSize = mergedComponentPropsRef?.value?.Rate?.size\n        if (configSize !== undefined)\n          return configSize\n        return 'medium'\n      }\n    })\n    const mergedValue = useMergedState(controlledValueRef, uncontrolledValueRef)\n    function doUpdateValue(value: number | null): void {\n      const { 'onUpdate:value': _onUpdateValue, onUpdateValue } = props\n      const { nTriggerFormChange, nTriggerFormInput } = formItem\n      if (_onUpdateValue) {\n        call(_onUpdateValue as RateOnUpdateValueImpl, value)\n      }\n      if (onUpdateValue) {\n        call(onUpdateValue as RateOnUpdateValueImpl, value)\n      }\n      uncontrolledValueRef.value = value\n      nTriggerFormChange()\n      nTriggerFormInput()\n    }\n    function getDerivedValue(index: number, e: MouseEvent): number {\n      if (props.allowHalf) {\n        if (\n          e.offsetX\n          >= Math.floor((e.currentTarget as HTMLDivElement).offsetWidth / 2)\n        ) {\n          return index + 1\n        }\n        else {\n          return index + 0.5\n        }\n      }\n      else {\n        return index + 1\n      }\n    }\n    let cleared = false\n    function handleMouseMove(index: number, e: MouseEvent): void {\n      if (cleared)\n        return\n      hoverIndexRef.value = getDerivedValue(index, e)\n    }\n    function handleMouseLeave(): void {\n      hoverIndexRef.value = null\n    }\n    function handleClick(index: number, e: MouseEvent): void {\n      const { clearable } = props\n      const derivedValue = getDerivedValue(index, e)\n      if (clearable && derivedValue === mergedValue.value) {\n        cleared = true\n        props.onClear?.()\n        hoverIndexRef.value = null\n        doUpdateValue(null)\n      }\n      else {\n        doUpdateValue(derivedValue)\n      }\n    }\n    function handleMouseEnterSomeStar(): void {\n      cleared = false\n    }\n    const { mergedSizeRef: _mergedSizeRef } = formItem\n\n    const mergedSizeRef = computed(() => {\n      const size = _mergedSizeRef.value\n      const { self } = themeRef.value\n      if (typeof size === 'number') {\n        return `${size}px`\n      }\n      else {\n        return self[createKey('size', size)]\n      }\n    })\n    const cssVarsRef = computed(() => {\n      const {\n        common: { cubicBezierEaseInOut },\n        self\n      } = themeRef.value\n      const { itemColor, itemColorActive } = self\n      const { color } = props\n      return {\n        '--n-bezier': cubicBezierEaseInOut,\n        '--n-item-color': itemColor,\n        '--n-item-color-active': color || itemColorActive,\n        '--n-item-size': mergedSizeRef.value\n      }\n    })\n    const themeClassHandle = inlineThemeDisabled\n      ? useThemeClass(\n          'rate',\n          computed(() => {\n            const size = mergedSizeRef.value\n            const { color } = props\n            let hash = ''\n            if (size) {\n              hash += size[0]\n            }\n            if (color) {\n              hash += color2Class(color)\n            }\n            return hash\n          }),\n          cssVarsRef,\n          props\n        )\n      : undefined\n\n    return {\n      mergedClsPrefix: mergedClsPrefixRef,\n      mergedValue,\n      hoverIndex: hoverIndexRef,\n      handleMouseMove,\n      handleClick,\n      handleMouseLeave,\n      handleMouseEnterSomeStar,\n      cssVars: inlineThemeDisabled ? undefined : cssVarsRef,\n      themeClass: themeClassHandle?.themeClass,\n      onRender: themeClassHandle?.onRender\n    }\n  },\n  render() {\n    const {\n      readonly,\n      hoverIndex,\n      mergedValue,\n      mergedClsPrefix,\n      onRender,\n      $slots: { default: defaultSlot }\n    } = this\n    onRender?.()\n    return (\n      <div\n        class={[\n          `${mergedClsPrefix}-rate`,\n          {\n            [`${mergedClsPrefix}-rate--readonly`]: readonly\n          },\n          this.themeClass\n        ]}\n        style={this.cssVars as CSSProperties}\n        onMouseleave={this.handleMouseLeave}\n      >\n        {renderList(this.count, (_, index) => {\n          const icon = defaultSlot ? (\n            defaultSlot({ index })\n          ) : (\n            <NBaseIcon clsPrefix={mergedClsPrefix}>\n              {{ default: renderStarIcon }}\n            </NBaseIcon>\n          )\n          const entireStarActive\n            = hoverIndex !== null\n              ? index + 1 <= hoverIndex\n              : index + 1 <= (mergedValue || 0)\n          return (\n            <div\n              key={index}\n              class={[\n                `${mergedClsPrefix}-rate__item`,\n                entireStarActive && `${mergedClsPrefix}-rate__item--active`\n              ]}\n              onClick={\n                readonly\n                  ? undefined\n                  : (e) => {\n                      this.handleClick(index, e)\n                    }\n              }\n              onMouseenter={this.handleMouseEnterSomeStar}\n              onMousemove={\n                readonly\n                  ? undefined\n                  : (e) => {\n                      this.handleMouseMove(index, e)\n                    }\n              }\n            >\n              {icon}\n              {this.allowHalf ? (\n                <div\n                  class={[\n                    `${mergedClsPrefix}-rate__half`,\n                    {\n                      [`${mergedClsPrefix}-rate__half--active`]:\n                        !entireStarActive && hoverIndex !== null\n                          ? index + 0.5 <= hoverIndex\n                          : index + 0.5 <= (mergedValue || 0)\n                    }\n                  ]}\n                >\n                  {icon}\n                </div>\n              ) : null}\n            </div>\n          )\n        })}\n      </div>\n    )\n  }\n})\n"
  },
  {
    "path": "src/rate/src/StarIcon.tsx",
    "content": "import { h } from 'vue'\n\nexport default () => (\n  <svg viewBox=\"0 0 512 512\">\n    <path d=\"M394 480a16 16 0 01-9.39-3L256 383.76 127.39 477a16 16 0 01-24.55-18.08L153 310.35 23 221.2a16 16 0 019-29.2h160.38l48.4-148.95a16 16 0 0130.44 0l48.4 149H480a16 16 0 019.05 29.2L359 310.35l50.13 148.53A16 16 0 01394 480z\" />\n  </svg>\n)\n"
  },
  {
    "path": "src/rate/src/interface.ts",
    "content": "export type RateOnUpdateValue = (value: number & null) => void\nexport type RateOnUpdateValueImpl = (value: number | null) => void\n"
  },
  {
    "path": "src/rate/src/public-types.ts",
    "content": "export type RateSize = number | 'small' | 'medium' | 'large'\n"
  },
  {
    "path": "src/rate/src/styles/index.cssr.ts",
    "content": "import { c, cB, cE, cM, cNotM } from '../../../_utils/cssr'\n\n// vars:\n// --n-bezier\n// --n-item-color\n// --n-item-color-active\nexport default cB('rate', {\n  display: 'inline-flex',\n  flexWrap: 'nowrap'\n}, [\n  c('&:hover', [\n    cE('item', `\n      transition:\n        transform .1s var(--n-bezier),\n        color .3s var(--n-bezier);\n    `)\n  ]),\n  cE('item', `\n    position: relative;\n    display: flex;\n    transition:\n      transform .1s var(--n-bezier),\n      color .3s var(--n-bezier);\n    transform: scale(1);\n    font-size: var(--n-item-size);\n    color: var(--n-item-color);\n  `, [\n    c('&:not(:first-child)', `\n      margin-left: 6px;\n    `),\n    cM('active', `\n      color: var(--n-item-color-active);\n    `)\n  ]),\n  cNotM('readonly', `\n    cursor: pointer;\n  `, [\n    cE('item', [\n      c('&:hover', `\n        transform: scale(1.05);\n      `),\n      c('&:active', `\n        transform: scale(0.96);\n      `)\n    ])\n  ]),\n  cE('half', `\n    display: flex;\n    transition: inherit;\n    position: absolute;\n    top: 0;\n    left: 0;\n    bottom: 0;\n    width: 50%;\n    overflow: hidden;\n    color: rgba(255, 255, 255, 0);\n  `, [\n    cM('active', `\n      color: var(--n-item-color-active);\n    `)\n  ])\n])\n"
  },
  {
    "path": "src/rate/styles/dark.ts",
    "content": "import type { RateTheme } from './light'\nimport { commonDark } from '../../_styles/common'\n\nconst rateDark: RateTheme = {\n  name: 'Rate',\n  common: commonDark,\n  self(vars) {\n    const { railColor } = vars\n    return {\n      itemColor: railColor,\n      itemColorActive: '#CCAA33',\n      itemSize: '20px',\n      sizeSmall: '16px',\n      sizeMedium: '20px',\n      sizeLarge: '24px'\n    }\n  }\n}\n\nexport default rateDark\n"
  },
  {
    "path": "src/rate/styles/index.ts",
    "content": "export { default as rateDark } from './dark'\nexport { default as rateLight } from './light'\nexport type { RateTheme, RateThemeVars } from './light'\n"
  },
  {
    "path": "src/rate/styles/light.ts",
    "content": "import type { Theme } from '../../_mixins'\nimport type { ThemeCommonVars } from '../../_styles/common'\nimport { commonLight } from '../../_styles/common'\n\nfunction self(vars: ThemeCommonVars) {\n  const { railColor } = vars\n  return {\n    itemColor: railColor,\n    itemColorActive: '#FFCC33',\n    sizeSmall: '16px',\n    sizeMedium: '20px',\n    sizeLarge: '24px'\n  }\n}\n\nexport type RateThemeVars = ReturnType<typeof self>\n\nconst themeLight: Theme<'Rate', RateThemeVars> = {\n  name: 'Rate',\n  common: commonLight,\n  self\n}\n\nexport default themeLight\nexport type RateTheme = typeof themeLight\n"
  },
  {
    "path": "src/rate/tests/Rate.spec.ts",
    "content": "import { mount } from '@vue/test-utils'\nimport { NRate } from '../index'\n\ndescribe('n-rate', () => {\n  it('should work with import on demand', () => {\n    mount(NRate)\n  })\n\n  it('should work with `count` prop', async () => {\n    const wrapper = mount(NRate)\n\n    await wrapper.setProps({ count: 10 })\n    expect(wrapper.findAll('.n-rate__item').length).toBe(10)\n\n    wrapper.unmount()\n  })\n\n  it('should work with `value` prop', async () => {\n    const wrapper = mount(NRate)\n\n    await wrapper.setProps({ value: 3, count: 10 })\n    expect(wrapper.findAll('.n-rate__item--active').length).toBe(3)\n    await wrapper.setProps({ value: 10 })\n    expect(wrapper.findAll('.n-rate__item--active').length).toBe(10)\n\n    wrapper.unmount()\n  })\n\n  it('should work with `defaultValue` prop', async () => {\n    const wrapper = mount(NRate, { props: { defaultValue: 8, count: 10 } })\n\n    expect(wrapper.findAll('.n-rate__item--active').length).toBe(8)\n\n    wrapper.unmount()\n  })\n\n  it('should work with `size` prop', async () => {\n    const wrapper = mount(NRate)\n\n    await wrapper.setProps({ size: 20 })\n    expect(wrapper.find('.n-rate').attributes('style')).toContain(\n      '--n-item-size: 20px'\n    )\n\n    for (const size of ['small', 'medium', 'large'] as const) {\n      await wrapper.setProps({ size })\n      expect(wrapper.find('.n-rate').attributes('style')).toMatchSnapshot()\n    }\n\n    wrapper.unmount()\n  })\n\n  it('should work with `color` prop', async () => {\n    const wrapper = mount(NRate)\n\n    await wrapper.setProps({ color: '#4fb233' })\n    expect(wrapper.find('.n-rate').attributes('style')).toContain(\n      '--n-item-color-active: #4fb233'\n    )\n\n    wrapper.unmount()\n  })\n\n  it('should work with `onUpdateValue` prop', async () => {\n    const onUpdateValue = vi.fn()\n    const onUpdateValue2 = vi.fn()\n    const wrapper = mount(NRate)\n\n    const testNumber = 2\n\n    await wrapper.setProps({ onUpdateValue, 'onUpdate:value': onUpdateValue })\n    await wrapper.findAll('.n-rate__item')[testNumber].trigger('click')\n    expect(onUpdateValue).toHaveBeenCalledWith(testNumber + 1)\n    expect(onUpdateValue).toHaveBeenCalledTimes(2)\n\n    await wrapper.setProps({\n      onUpdateValue: [onUpdateValue, onUpdateValue2],\n      'onUpdate:value': [onUpdateValue, onUpdateValue2]\n    })\n    await wrapper.findAll('.n-rate__item')[testNumber].trigger('click')\n    expect(onUpdateValue).toHaveBeenCalledWith(testNumber + 1)\n    expect(onUpdateValue2).toHaveBeenCalledWith(testNumber + 1)\n    expect(onUpdateValue).toHaveBeenCalledTimes(4)\n\n    wrapper.unmount()\n  })\n\n  it('should work with `readonly` prop', async () => {\n    const wrapper = mount(NRate)\n\n    await wrapper.setProps({ readonly: true })\n\n    expect(wrapper.find('.n-rate').classes()).toContain('n-rate--readonly')\n\n    await wrapper.setProps({ readonly: true, value: 3 })\n    expect(wrapper.findAll('.n-rate__item--active').length).toBe(3)\n\n    await wrapper.findAll('.n-rate__item')[3].trigger('click')\n    expect(wrapper.findAll('.n-rate__item--active').length).toBe(3)\n\n    await wrapper.findAll('.n-rate__item')[3].trigger('mousemove')\n    expect(wrapper.findAll('.n-rate__item--active').length).toBe(3)\n\n    wrapper.unmount()\n  })\n\n  it('should work with `allowHalf` prop', async () => {\n    const onUpdateValue = vi.fn()\n    const wrapper = mount(NRate, {\n      props: {\n        allowHalf: true,\n        onUpdateValue\n      }\n    })\n\n    const rateIndex = 2\n    const offsetWidth = 20\n    const rateItems = wrapper.findAll('.n-rate__item')\n    expect(rateItems.length).toBeGreaterThan(rateIndex)\n\n    const targetRate = rateItems[rateIndex]\n    Object.defineProperty(targetRate.element, 'offsetWidth', {\n      value: offsetWidth,\n      configurable: true\n    })\n\n    await targetRate.trigger('click', { offsetX: offsetWidth / 3 })\n    expect(onUpdateValue).toHaveBeenNthCalledWith(1, rateIndex + 0.5)\n    expect(onUpdateValue).toHaveBeenCalledTimes(1)\n    expect(wrapper.findAll('.n-rate__item--active').length).toBe(2)\n\n    wrapper.unmount()\n  })\n\n  it('should work with `clearable` prop', async () => {\n    const wrapper = mount(NRate)\n    await wrapper.setProps({ clearable: true })\n\n    const testNumber = 2\n\n    await wrapper.findAll('.n-rate__item')[testNumber].trigger('click')\n    expect(wrapper.findAll('.n-rate__item--active').length).toEqual(\n      testNumber + 1\n    )\n\n    await wrapper.findAll('.n-rate__item')[testNumber].trigger('click')\n    vi.waitFor(() => {\n      expect(wrapper.findAll('.n-rate__item--active').length).toEqual(0)\n    })\n    wrapper.unmount()\n  })\n})\n"
  },
  {
    "path": "src/rate/tests/__snapshots__/Rate.spec.ts.snap",
    "content": "// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html\n\nexports[`n-rate > should work with \\`size\\` prop 1`] = `\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-item-color: rgb(219, 219, 223); --n-item-color-active: #FFCC33; --n-item-size: 16px;\"`;\n\nexports[`n-rate > should work with \\`size\\` prop 2`] = `\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-item-color: rgb(219, 219, 223); --n-item-color-active: #FFCC33; --n-item-size: 20px;\"`;\n\nexports[`n-rate > should work with \\`size\\` prop 3`] = `\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-item-color: rgb(219, 219, 223); --n-item-color-active: #FFCC33; --n-item-size: 24px;\"`;\n"
  },
  {
    "path": "src/rate/tests/server.spec.tsx",
    "content": "import { setup } from '@css-render/vue3-ssr'\nimport { renderToString } from '@vue/server-renderer'\n/**\n * @vitest-environment node\n */\nimport { createSSRApp, h } from 'vue'\nimport { NRate } from '../..'\n\ndescribe('server side rendering', () => {\n  it('works', async () => {\n    const app = createSSRApp(() => <NRate />)\n    setup(app)\n    try {\n      await renderToString(app)\n    }\n    catch (e) {\n      expect(e).not.toBeTruthy()\n    }\n  })\n})\n"
  },
  {
    "path": "src/result/demos/enUS/custom.demo.vue",
    "content": "<markdown>\n# Customizing icon\n\nPut whatever you like inside.\n</markdown>\n\n<template>\n  <n-result\n    title=\"Lpsum\"\n    description=\"Neque porro quisquam est qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit...\"\n  >\n    <template #icon>\n      <div style=\"width: 300px\">\n        Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod\n        tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim\n        veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea\n        commodo consequat. Duis aute irure dolor in reprehenderit in voluptate\n        velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint\n        occaecat cupidatat non proident, sunt in culpa qui officia deserunt\n        mollit anim id est laborum.\n      </div>\n    </template>\n  </n-result>\n</template>\n"
  },
  {
    "path": "src/result/demos/enUS/error.demo.vue",
    "content": "<markdown>\n# Error\n</markdown>\n\n<template>\n  <n-result status=\"error\" title=\"Error\" description=\"It's red\">\n    <template #footer>\n      <n-button>I Don't Like It</n-button>\n    </template>\n  </n-result>\n</template>\n"
  },
  {
    "path": "src/result/demos/enUS/index.demo-entry.md",
    "content": "# Result\n\nResult is for showing result.\n\nMany thanks to [twemoji](https://github.com/twitter/twemoji) for creating those high quality icons.\n\n## Demos\n\n```demo\ns-404.vue\ns-403.vue\ns-500.vue\ns-418.vue\ninfo.vue\nsuccess.vue\nwarning.vue\nerror.vue\nsize.vue\ncustom.vue\n```\n\n## API\n\n### Result Props\n\n| Name | Type | Default | Description |\n| --- | --- | --- | --- |\n| description | `string` | `undefined` | Description. |\n| size | `'small' \\| 'medium' \\| 'large' \\| 'huge'` | `'medium'` | Size. |\n| status | `'info' \\| 'success' \\| 'warning' \\| 'error' \\| '404' \\| '403' \\| '500' \\| '418'` | `'info'` | Status. |\n| title | `string` | `undefined` | Title. |\n\n### Result Slots\n\n| Name | Parameters | Description | Version |\n| --- | --- | --- | --- |\n| default | `()` | Results page content information. |  |\n| footer | `()` | Information at the bottom of the results page. |  |\n| icon | `()` | Custom icon content area. | 2.24.0 |\n"
  },
  {
    "path": "src/result/demos/enUS/info.demo.vue",
    "content": "<markdown>\n# Info\n</markdown>\n\n<template>\n  <n-result\n    status=\"info\"\n    title=\"Information\"\n    description=\"In this era, info is about money and money is about info.\"\n  >\n    <template #footer>\n      <n-button>I Want Information</n-button>\n    </template>\n  </n-result>\n</template>\n"
  },
  {
    "path": "src/result/demos/enUS/s-403.demo.vue",
    "content": "<markdown>\n# 403\n</markdown>\n\n<template>\n  <n-result\n    status=\"403\"\n    title=\"403 Forbidden\"\n    description=\"Some of the doors are always close to you.\"\n  >\n    <template #footer>\n      <n-button>Take It Easy</n-button>\n    </template>\n  </n-result>\n</template>\n"
  },
  {
    "path": "src/result/demos/enUS/s-404.demo.vue",
    "content": "<markdown>\n# 404\n</markdown>\n\n<template>\n  <n-result\n    status=\"404\"\n    title=\"404 Not Found\"\n    description=\"You know life is always ridiculous.\"\n  >\n    <template #footer>\n      <n-button>Find Something Funny</n-button>\n    </template>\n  </n-result>\n</template>\n"
  },
  {
    "path": "src/result/demos/enUS/s-418.demo.vue",
    "content": "<markdown>\n# 418\n</markdown>\n\n<template>\n  <n-result\n    status=\"418\"\n    title=\"418 I'm a Teapot\"\n    description=\"In Chinese, teapot is a kind of 'Beiju', which means 'tragedy'.\"\n  >\n    <template #footer>\n      <n-button>It Is Easy to Take the Truth</n-button>\n    </template>\n  </n-result>\n</template>\n"
  },
  {
    "path": "src/result/demos/enUS/s-500.demo.vue",
    "content": "<markdown>\n# 500\n</markdown>\n\n<template>\n  <n-result\n    status=\"500\"\n    title=\"500 Server Error\"\n    description=\"Server error may prove that you need hiring more developers.\"\n  >\n    <template #footer>\n      <n-button>Speard Money Out</n-button>\n    </template>\n  </n-result>\n</template>\n"
  },
  {
    "path": "src/result/demos/enUS/size.demo.vue",
    "content": "<markdown>\n# Size\n</markdown>\n\n<template>\n  <n-result\n    status=\"404\"\n    title=\"Huge! Huge!\"\n    description=\"Like this\"\n    size=\"huge\"\n  >\n    <template #footer>\n      <n-button>Just So So</n-button>\n    </template>\n  </n-result>\n</template>\n"
  },
  {
    "path": "src/result/demos/enUS/success.demo.vue",
    "content": "<markdown>\n# Success\n</markdown>\n\n<template>\n  <n-result status=\"success\" title=\"Success\" description=\"child of failure\">\n    <template #footer>\n      <n-button>I like it</n-button>\n    </template>\n  </n-result>\n</template>\n"
  },
  {
    "path": "src/result/demos/enUS/warning.demo.vue",
    "content": "<markdown>\n# Warning\n</markdown>\n\n<template>\n  <n-result\n    status=\"warning\"\n    title=\"Warning\"\n    description=\"People seldom see it until it comes true.\"\n  >\n    <template #footer>\n      <n-button>Hmm, Truly Sad, Isn't It?</n-button>\n    </template>\n  </n-result>\n</template>\n"
  },
  {
    "path": "src/result/demos/zhCN/custom.demo.vue",
    "content": "<markdown>\n# 自定义图标\n\n可以随便放一些东西，不一定是图标。\n</markdown>\n\n<template>\n  <n-result\n    title=\"如何成功\"\n    description=\"写好报告，搞乱项目，增本降效，做大蛋糕\"\n  >\n    <template #icon>\n      <div style=\"width: 300px\">\n        底层逻辑是打通信息屏障，创建行业新生态。顶层设计时聚焦用户感知赛道，通过差异化和颗粒度达到引爆点。交付价值是在垂直领域采取复用大发达成持久收益。抽离透传归因分析作为抓手为产品赋能，体验度量作为闭环的评判标准。亮点是载体，优势是链路。思考整个生命周期，完善逻辑考虑资源倾斜。方法论是组合拳达到平台化标准。\n      </div>\n    </template>\n  </n-result>\n</template>\n"
  },
  {
    "path": "src/result/demos/zhCN/error.demo.vue",
    "content": "<markdown>\n# 错误\n</markdown>\n\n<template>\n  <n-result status=\"error\" title=\"错误\" description=\"它是红的\">\n    <template #footer>\n      <n-button>还是离它远点吧</n-button>\n    </template>\n  </n-result>\n</template>\n"
  },
  {
    "path": "src/result/demos/zhCN/index.demo-entry.md",
    "content": "# 结果页 Result\n\n结果页是展示结果的。\n\n感谢 [twemoji](https://github.com/twitter/twemoji) 创造了这么多好看的图标。\n\n## 演示\n\n```demo\ns-404.vue\ns-403.vue\ns-500.vue\ns-418.vue\ninfo.vue\nsuccess.vue\nwarning.vue\nsize.vue\ncustom.vue\n```\n\n## API\n\n### Result Props\n\n| 名称 | 类型 | 默认值 | 说明 |\n| --- | --- | --- | --- |\n| description | `string` | `undefined` | 描述信息 |\n| size | `'small' \\| 'medium' \\| 'large' \\| 'huge'` | `'medium'` | 大小 |\n| status | `'info' \\| 'success' \\| 'warning' \\| 'error' \\| '404' \\| '403' \\| '500' \\| '418'` | `'info'` | 状态 |\n| title | `string` | `undefined` | 标题 |\n\n### Result Slots\n\n| 名称    | 参数 | 说明               | 版本   |\n| ------- | ---- | ------------------ | ------ |\n| default | `()` | 结果页内容信息     |        |\n| footer  | `()` | 结果页底部信息     |        |\n| icon    | `()` | 自定义图标内容区域 | 2.24.0 |\n"
  },
  {
    "path": "src/result/demos/zhCN/info.demo.vue",
    "content": "<markdown>\n# 信息\n</markdown>\n\n<template>\n  <n-result\n    status=\"info\"\n    title=\"信息\"\n    description=\"在这个年代，信息就是金钱，金钱就是信息。\"\n  >\n    <template #footer>\n      <n-button>我需要信息</n-button>\n    </template>\n  </n-result>\n</template>\n"
  },
  {
    "path": "src/result/demos/zhCN/s-403.demo.vue",
    "content": "<markdown>\n# 403\n</markdown>\n\n<template>\n  <n-result\n    status=\"403\"\n    title=\"403 禁止访问\"\n    description=\"总有些门是对你关闭的\"\n  >\n    <template #footer>\n      <n-button>放轻松</n-button>\n    </template>\n  </n-result>\n</template>\n"
  },
  {
    "path": "src/result/demos/zhCN/s-404.demo.vue",
    "content": "<markdown>\n# 404\n</markdown>\n\n<template>\n  <n-result status=\"404\" title=\"404 资源不存在\" description=\"生活总归带点荒谬\">\n    <template #footer>\n      <n-button>找点乐子吧</n-button>\n    </template>\n  </n-result>\n</template>\n"
  },
  {
    "path": "src/result/demos/zhCN/s-418.demo.vue",
    "content": "<markdown>\n# 418\n</markdown>\n\n<template>\n  <n-result status=\"418\" title=\"418 我是个杯具\" description=\"一切尽在不言中\">\n    <template #footer>\n      <n-button>接受真相就是这么简单</n-button>\n    </template>\n  </n-result>\n</template>\n"
  },
  {
    "path": "src/result/demos/zhCN/s-500.demo.vue",
    "content": "<markdown>\n# 500\n</markdown>\n\n<template>\n  <n-result\n    status=\"500\"\n    title=\"500 服务器错误\"\n    description=\"服务器出错可能说明该雇更多程序员了\"\n  >\n    <template #footer>\n      <n-button>散财消灾</n-button>\n    </template>\n  </n-result>\n</template>\n"
  },
  {
    "path": "src/result/demos/zhCN/size.demo.vue",
    "content": "<markdown>\n# 尺寸\n</markdown>\n\n<template>\n  <n-result status=\"404\" title=\"大！大！啊\" description=\"这么大\" size=\"huge\">\n    <template #footer>\n      <n-button>哦</n-button>\n    </template>\n  </n-result>\n</template>\n"
  },
  {
    "path": "src/result/demos/zhCN/success.demo.vue",
    "content": "<markdown>\n# 成功\n</markdown>\n\n<template>\n  <n-result status=\"success\" title=\"成功\" description=\"失败的孩子\">\n    <template #footer>\n      <n-button>我喜欢</n-button>\n    </template>\n  </n-result>\n</template>\n"
  },
  {
    "path": "src/result/demos/zhCN/warning.demo.vue",
    "content": "<markdown>\n# 警告\n</markdown>\n\n<template>\n  <n-result\n    status=\"warning\"\n    title=\"警告\"\n    description=\"在它变成错误以前一般不会有人管它\"\n  >\n    <template #footer>\n      <n-button>听起来有那么点悲伤，哈哈哈</n-button>\n    </template>\n  </n-result>\n</template>\n"
  },
  {
    "path": "src/result/index.ts",
    "content": "export type * from './src/public-types'\nexport { default as NResult, resultProps } from './src/Result'\nexport type { ResultProps, ResultSlots } from './src/Result'\n"
  },
  {
    "path": "src/result/src/403.tsx",
    "content": "import { h } from 'vue'\n\nexport function render403() {\n  return (\n    <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 36 36\">\n      <path\n        fill=\"#EF9645\"\n        d=\"M15.5 2.965c1.381 0 2.5 1.119 2.5 2.5v.005L20.5.465c1.381 0 2.5 1.119 2.5 2.5V4.25l2.5-1.535c1.381 0 2.5 1.119 2.5 2.5V8.75L29 18H15.458L15.5 2.965z\"\n      />\n      <path\n        fill=\"#FFDC5D\"\n        d=\"M4.625 16.219c1.381-.611 3.354.208 4.75 2.188.917 1.3 1.187 3.151 2.391 3.344.46.073 1.234-.313 1.234-1.397V4.5s0-2 2-2 2 2 2 2v11.633c0-.029 1-.064 1-.082V2s0-2 2-2 2 2 2 2v14.053c0 .017 1 .041 1 .069V4.25s0-2 2-2 2 2 2 2v12.638c0 .118 1 .251 1 .398V8.75s0-2 2-2 2 2 2 2V24c0 6.627-5.373 12-12 12-4.775 0-8.06-2.598-9.896-5.292C8.547 28.423 8.096 26.051 8 25.334c0 0-.123-1.479-1.156-2.865-1.469-1.969-2.5-3.156-3.125-3.866-.317-.359-.625-1.707.906-2.384z\"\n      />\n    </svg>\n  )\n}\n"
  },
  {
    "path": "src/result/src/404.tsx",
    "content": "import { h } from 'vue'\n\nexport function render404() {\n  return (\n    <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 36 36\">\n      <circle fill=\"#FFCB4C\" cx=\"18\" cy=\"17.018\" r=\"17\" />\n      <path\n        fill=\"#65471B\"\n        d=\"M14.524 21.036c-.145-.116-.258-.274-.312-.464-.134-.46.13-.918.59-1.021 4.528-1.021 7.577 1.363 7.706 1.465.384.306.459.845.173 1.205-.286.358-.828.401-1.211.097-.11-.084-2.523-1.923-6.182-1.098-.274.061-.554-.016-.764-.184z\"\n      />\n      <ellipse fill=\"#65471B\" cx=\"13.119\" cy=\"11.174\" rx=\"2.125\" ry=\"2.656\" />\n      <ellipse fill=\"#65471B\" cx=\"24.375\" cy=\"12.236\" rx=\"2.125\" ry=\"2.656\" />\n      <path\n        fill=\"#F19020\"\n        d=\"M17.276 35.149s1.265-.411 1.429-1.352c.173-.972-.624-1.167-.624-1.167s1.041-.208 1.172-1.376c.123-1.101-.861-1.363-.861-1.363s.97-.4 1.016-1.539c.038-.959-.995-1.428-.995-1.428s5.038-1.221 5.556-1.341c.516-.12 1.32-.615 1.069-1.694-.249-1.08-1.204-1.118-1.697-1.003-.494.115-6.744 1.566-8.9 2.068l-1.439.334c-.54.127-.785-.11-.404-.512.508-.536.833-1.129.946-2.113.119-1.035-.232-2.313-.433-2.809-.374-.921-1.005-1.649-1.734-1.899-1.137-.39-1.945.321-1.542 1.561.604 1.854.208 3.375-.833 4.293-2.449 2.157-3.588 3.695-2.83 6.973.828 3.575 4.377 5.876 7.952 5.048l3.152-.681z\"\n      />\n      <path\n        fill=\"#65471B\"\n        d=\"M9.296 6.351c-.164-.088-.303-.224-.391-.399-.216-.428-.04-.927.393-1.112 4.266-1.831 7.699-.043 7.843.034.433.231.608.747.391 1.154-.216.405-.74.546-1.173.318-.123-.063-2.832-1.432-6.278.047-.257.109-.547.085-.785-.042zm12.135 3.75c-.156-.098-.286-.243-.362-.424-.187-.442.023-.927.468-1.084 4.381-1.536 7.685.48 7.823.567.415.26.555.787.312 1.178-.242.39-.776.495-1.191.238-.12-.072-2.727-1.621-6.267-.379-.266.091-.553.046-.783-.096z\"\n      />\n    </svg>\n  )\n}\n"
  },
  {
    "path": "src/result/src/418.tsx",
    "content": "import { h } from 'vue'\n\nexport function render418() {\n  return (\n    <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 36 36\">\n      <ellipse fill=\"#292F33\" cx=\"18\" cy=\"26\" rx=\"18\" ry=\"10\" />\n      <ellipse fill=\"#66757F\" cx=\"18\" cy=\"24\" rx=\"18\" ry=\"10\" />\n      <path\n        fill=\"#E1E8ED\"\n        d=\"M18 31C3.042 31 1 16 1 12h34c0 2-1.958 19-17 19z\"\n      />\n      <path\n        fill=\"#77B255\"\n        d=\"M35 12.056c0 5.216-7.611 9.444-17 9.444S1 17.271 1 12.056C1 6.84 8.611 3.611 18 3.611s17 3.229 17 8.445z\"\n      />\n      <ellipse fill=\"#A6D388\" cx=\"18\" cy=\"13\" rx=\"15\" ry=\"7\" />\n      <path\n        d=\"M21 17c-.256 0-.512-.098-.707-.293-2.337-2.337-2.376-4.885-.125-8.262.739-1.109.9-2.246.478-3.377-.461-1.236-1.438-1.996-1.731-2.077-.553 0-.958-.443-.958-.996 0-.552.491-.995 1.043-.995.997 0 2.395 1.153 3.183 2.625 1.034 1.933.91 4.039-.351 5.929-1.961 2.942-1.531 4.332-.125 5.738.391.391.391 1.023 0 1.414-.195.196-.451.294-.707.294zm-6-2c-.256 0-.512-.098-.707-.293-2.337-2.337-2.376-4.885-.125-8.262.727-1.091.893-2.083.494-2.947-.444-.961-1.431-1.469-1.684-1.499-.552 0-.989-.447-.989-1 0-.552.458-1 1.011-1 .997 0 2.585.974 3.36 2.423.481.899 1.052 2.761-.528 5.131-1.961 2.942-1.531 4.332-.125 5.738.391.391.391 1.023 0 1.414-.195.197-.451.295-.707.295z\"\n        fill=\"#5C913B\"\n      />\n    </svg>\n  )\n}\n"
  },
  {
    "path": "src/result/src/500.tsx",
    "content": "import { h } from 'vue'\n\nexport function render500() {\n  return (\n    <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 36 36\">\n      <path\n        fill=\"#FFCC4D\"\n        d=\"M36 18c0 9.941-8.059 18-18 18-9.94 0-18-8.059-18-18C0 8.06 8.06 0 18 0c9.941 0 18 8.06 18 18\"\n      />\n      <ellipse fill=\"#664500\" cx=\"18\" cy=\"27\" rx=\"5\" ry=\"6\" />\n      <path\n        fill=\"#664500\"\n        d=\"M5.999 11c-.208 0-.419-.065-.599-.2-.442-.331-.531-.958-.2-1.4C8.462 5.05 12.816 5 13 5c.552 0 1 .448 1 1 0 .551-.445.998-.996 1-.155.002-3.568.086-6.204 3.6-.196.262-.497.4-.801.4zm24.002 0c-.305 0-.604-.138-.801-.4-2.64-3.521-6.061-3.598-6.206-3.6-.55-.006-.994-.456-.991-1.005C22.006 5.444 22.45 5 23 5c.184 0 4.537.05 7.8 4.4.332.442.242 1.069-.2 1.4-.18.135-.39.2-.599.2zm-16.087 4.5l1.793-1.793c.391-.391.391-1.023 0-1.414s-1.023-.391-1.414 0L12.5 14.086l-1.793-1.793c-.391-.391-1.023-.391-1.414 0s-.391 1.023 0 1.414l1.793 1.793-1.793 1.793c-.391.391-.391 1.023 0 1.414.195.195.451.293.707.293s.512-.098.707-.293l1.793-1.793 1.793 1.793c.195.195.451.293.707.293s.512-.098.707-.293c.391-.391.391-1.023 0-1.414L13.914 15.5zm11 0l1.793-1.793c.391-.391.391-1.023 0-1.414s-1.023-.391-1.414 0L23.5 14.086l-1.793-1.793c-.391-.391-1.023-.391-1.414 0s-.391 1.023 0 1.414l1.793 1.793-1.793 1.793c-.391.391-.391 1.023 0 1.414.195.195.451.293.707.293s.512-.098.707-.293l1.793-1.793 1.793 1.793c.195.195.451.293.707.293s.512-.098.707-.293c.391-.391.391-1.023 0-1.414L24.914 15.5z\"\n      />\n    </svg>\n  )\n}\n"
  },
  {
    "path": "src/result/src/Result.tsx",
    "content": "import type { CSSProperties, PropType, SlotsType, VNode } from 'vue'\nimport type { ThemeProps } from '../../_mixins'\nimport type { ExtractPublicPropTypes } from '../../_utils'\nimport type { ResultTheme } from '../styles'\nimport type { ResultSize } from './public-types'\nimport { computed, defineComponent, h } from 'vue'\nimport { NBaseIcon } from '../../_internal'\nimport {\n  ErrorIcon,\n  InfoIcon,\n  SuccessIcon,\n  WarningIcon\n} from '../../_internal/icons'\nimport { useConfig, useTheme, useThemeClass } from '../../_mixins'\nimport { createKey } from '../../_utils'\nimport { resultLight } from '../styles'\nimport { render403 } from './403'\nimport { render404 } from './404'\nimport { render418 } from './418'\nimport { render500 } from './500'\nimport style from './styles/index.cssr'\n\nconst iconRenderMap = {\n  403: render403,\n  404: render404,\n  418: render418,\n  500: render500,\n  info: () => <InfoIcon />,\n  success: () => <SuccessIcon />,\n  warning: () => <WarningIcon />,\n  error: () => <ErrorIcon />\n}\n\nexport const resultProps = {\n  ...(useTheme.props as ThemeProps<ResultTheme>),\n  size: String as PropType<ResultSize>,\n  status: {\n    type: String as PropType<\n      'info' | 'success' | 'warning' | 'error' | '404' | '403' | '500' | '418'\n    >,\n    default: 'info'\n  },\n  title: String,\n  description: String\n}\n\nexport type ResultProps = ExtractPublicPropTypes<typeof resultProps>\n\nexport interface ResultSlots {\n  default?: () => VNode[]\n  footer?: () => VNode[]\n  icon?: () => VNode[]\n}\n\nexport default defineComponent({\n  name: 'Result',\n  props: resultProps,\n  slots: Object as SlotsType<ResultSlots>,\n  setup(props) {\n    const { mergedClsPrefixRef, inlineThemeDisabled, mergedComponentPropsRef }\n      = useConfig(props)\n    const mergedSizeRef = computed(() => {\n      return (\n        props.size || mergedComponentPropsRef?.value?.Result?.size || 'medium'\n      )\n    })\n    const themeRef = useTheme(\n      'Result',\n      '-result',\n      style,\n      resultLight,\n      props,\n      mergedClsPrefixRef\n    )\n    const cssVarsRef = computed(() => {\n      const { status } = props\n      const size = mergedSizeRef.value\n      const {\n        common: { cubicBezierEaseInOut },\n        self: {\n          textColor,\n          lineHeight,\n          titleTextColor,\n          titleFontWeight,\n          [createKey('iconColor', status)]: iconColor,\n          [createKey('fontSize', size)]: fontSize,\n          [createKey('titleFontSize', size)]: titleFontSize,\n          [createKey('iconSize', size)]: iconSize\n        }\n      } = themeRef.value\n      return {\n        '--n-bezier': cubicBezierEaseInOut,\n        '--n-font-size': fontSize,\n        '--n-icon-size': iconSize,\n        '--n-line-height': lineHeight,\n        '--n-text-color': textColor,\n        '--n-title-font-size': titleFontSize,\n        '--n-title-font-weight': titleFontWeight,\n        '--n-title-text-color': titleTextColor,\n        '--n-icon-color': iconColor || ''\n      }\n    })\n    const themeClassHandle = inlineThemeDisabled\n      ? useThemeClass(\n          'result',\n          computed(() => {\n            const { status } = props\n            const size = mergedSizeRef.value\n            let hash = ''\n            if (size) {\n              hash += size[0]\n            }\n            if (status) {\n              hash += status[0]\n            }\n            return hash\n          }),\n          cssVarsRef,\n          props\n        )\n      : undefined\n\n    return {\n      mergedClsPrefix: mergedClsPrefixRef,\n      cssVars: inlineThemeDisabled ? undefined : cssVarsRef,\n      themeClass: themeClassHandle?.themeClass,\n      onRender: themeClassHandle?.onRender\n    }\n  },\n  render() {\n    const { status, $slots, mergedClsPrefix, onRender } = this\n    onRender?.()\n    return (\n      <div\n        class={[`${mergedClsPrefix}-result`, this.themeClass]}\n        style={this.cssVars as CSSProperties}\n      >\n        <div class={`${mergedClsPrefix}-result-icon`}>\n          {$slots.icon?.() || (\n            <NBaseIcon clsPrefix={mergedClsPrefix}>\n              {{ default: () => iconRenderMap[status]() }}\n            </NBaseIcon>\n          )}\n        </div>\n        <div class={`${mergedClsPrefix}-result-header`}>\n          {this.title ? (\n            <div class={`${mergedClsPrefix}-result-header__title`}>\n              {this.title}\n            </div>\n          ) : null}\n          {this.description ? (\n            <div class={`${mergedClsPrefix}-result-header__description`}>\n              {this.description}\n            </div>\n          ) : null}\n        </div>\n        {$slots.default && (\n          <div class={`${mergedClsPrefix}-result-content`}>{$slots}</div>\n        )}\n        {$slots.footer && (\n          <div class={`${mergedClsPrefix}-result-footer`}>\n            {$slots.footer()}\n          </div>\n        )}\n      </div>\n    )\n  }\n})\n"
  },
  {
    "path": "src/result/src/public-types.ts",
    "content": "export type ResultSize = 'small' | 'medium' | 'large' | 'huge'\n"
  },
  {
    "path": "src/result/src/styles/index.cssr.ts",
    "content": "import { cB, cE } from '../../../_utils/cssr'\n\n// --n-bezier\n// --n-font-size\n// --n-icon-size\n// --n-line-height\n// --n-text-color\n// --n-title-font-size\n// --n-title-font-weight\n// --n-title-text-color\nexport default cB('result', `\n  color: var(--n-text-color);\n  line-height: var(--n-line-height);\n  font-size: var(--n-font-size);\n  transition:\n    color .3s var(--n-bezier);\n`, [\n  cB('result-icon', `\n    display: flex;\n    justify-content: center;\n    transition: color .3s var(--n-bezier);\n  `, [\n    cE('status-image', `\n      font-size: var(--n-icon-size);\n      width: 1em;\n      height: 1em;\n    `),\n    cB('base-icon', `\n      color: var(--n-icon-color);\n      font-size: var(--n-icon-size);\n    `)\n  ]),\n  cB('result-content', {\n    marginTop: '24px'\n  }),\n  cB('result-footer', `\n    margin-top: 24px;\n    text-align: center;\n  `),\n  cB('result-header', [\n    cE('title', `\n      margin-top: 16px;\n      font-weight: var(--n-title-font-weight);\n      transition: color .3s var(--n-bezier);\n      text-align: center;\n      color: var(--n-title-text-color);\n      font-size: var(--n-title-font-size);\n    `),\n    cE('description', `\n      margin-top: 4px;\n      text-align: center;\n      font-size: var(--n-font-size);\n    `)\n  ])\n])\n"
  },
  {
    "path": "src/result/styles/_common.ts",
    "content": "export default {\n  titleFontSizeSmall: '26px',\n  titleFontSizeMedium: '32px',\n  titleFontSizeLarge: '40px',\n  titleFontSizeHuge: '48px',\n  fontSizeSmall: '14px',\n  fontSizeMedium: '14px',\n  fontSizeLarge: '15px',\n  fontSizeHuge: '16px',\n  iconSizeSmall: '64px',\n  iconSizeMedium: '80px',\n  iconSizeLarge: '100px',\n  iconSizeHuge: '125px',\n  iconColor418: undefined,\n  iconColor404: undefined,\n  iconColor403: undefined,\n  iconColor500: undefined\n}\n"
  },
  {
    "path": "src/result/styles/dark.ts",
    "content": "import type { ResultTheme } from './light'\nimport { commonDark } from '../../_styles/common'\nimport { self } from './light'\n\nconst resultDark: ResultTheme = {\n  name: 'Result',\n  common: commonDark,\n  self\n}\n\nexport default resultDark\n"
  },
  {
    "path": "src/result/styles/index.ts",
    "content": "export { default as resultDark } from './dark'\nexport { default as resultLight } from './light'\nexport type { ResultTheme, ResultThemeVars } from './light'\n"
  },
  {
    "path": "src/result/styles/light.ts",
    "content": "import type { Theme } from '../../_mixins'\nimport type { ThemeCommonVars } from '../../_styles/common'\nimport { commonLight } from '../../_styles/common'\nimport commonVariables from './_common'\n\nexport function self(vars: ThemeCommonVars) {\n  const {\n    textColor2,\n    textColor1,\n    errorColor,\n    successColor,\n    infoColor,\n    warningColor,\n    lineHeight,\n    fontWeightStrong\n  } = vars\n  return {\n    ...commonVariables,\n    lineHeight,\n    titleFontWeight: fontWeightStrong,\n    titleTextColor: textColor1,\n    textColor: textColor2,\n    iconColorError: errorColor,\n    iconColorSuccess: successColor,\n    iconColorInfo: infoColor,\n    iconColorWarning: warningColor\n  }\n}\n\nexport type ResultThemeVars = ReturnType<typeof self>\n\nconst resultLight: Theme<'Result', ResultThemeVars> = {\n  name: 'Result',\n  common: commonLight,\n  self\n}\n\nexport default resultLight\nexport type ResultTheme = typeof resultLight\n"
  },
  {
    "path": "src/result/tests/Result.spec.ts",
    "content": "import { mount } from '@vue/test-utils'\nimport { NResult } from '../index'\n\ndescribe('n-result', () => {\n  it('should work with import on demand', () => {\n    mount(NResult)\n  })\n\n  it('should work with `description` prop', async () => {\n    const wrapper = mount(NResult, {\n      props: { description: 'test-description' }\n    })\n    expect(wrapper.find('.n-result-header__description').exists()).toBe(true)\n    expect(wrapper.find('.n-result-header__description').text()).toBe(\n      'test-description'\n    )\n    wrapper.unmount()\n  })\n\n  it('should work with `title` prop', async () => {\n    const wrapper = mount(NResult, {\n      props: { title: 'test-title' }\n    })\n    expect(wrapper.find('.n-result-header__title').exists()).toBe(true)\n    expect(wrapper.find('.n-result-header__title').text()).toBe('test-title')\n    wrapper.unmount()\n  })\n\n  it('should work with `size` prop', async () => {\n    ;(['small', 'medium', 'large', 'huge'] as const).forEach((item) => {\n      const wrapper = mount(NResult, {\n        props: { size: item }\n      })\n      expect(wrapper.find('.n-result').attributes('style')).toMatchSnapshot()\n      wrapper.unmount()\n    })\n  })\n\n  it('should work with slots', async () => {\n    const wrapper = mount(NResult, {\n      slots: {\n        default: () => 'test-default',\n        icon: () => 'test-custom-icon',\n        footer: () => 'test-footer'\n      }\n    })\n    expect(wrapper.find('.n-result-content').exists()).toBe(true)\n    expect(wrapper.find('.n-result-content').text()).toBe('test-default')\n    expect(wrapper.find('.n-result-icon').text()).toBe('test-custom-icon')\n    expect(wrapper.find('.n-result-footer').exists()).toBe(true)\n    expect(wrapper.find('.n-result-footer').text()).toBe('test-footer')\n    wrapper.unmount()\n  })\n\n  it('should work with `status` prop', async () => {\n    const wrapper = mount(NResult, {\n      props: { status: 'success' }\n    })\n    expect(wrapper.find('.n-result-icon').exists()).toBe(true)\n    wrapper.unmount()\n  })\n})\n"
  },
  {
    "path": "src/result/tests/__snapshots__/Result.spec.ts.snap",
    "content": "// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html\n\nexports[`n-result > should work with \\`size\\` prop 1`] = `\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-font-size: 14px; --n-icon-size: 64px; --n-line-height: 1.6; --n-text-color: rgb(51, 54, 57); --n-title-font-size: 26px; --n-title-font-weight: 500; --n-title-text-color: rgb(31, 34, 37); --n-icon-color: #2080f0;\"`;\n\nexports[`n-result > should work with \\`size\\` prop 2`] = `\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-font-size: 14px; --n-icon-size: 80px; --n-line-height: 1.6; --n-text-color: rgb(51, 54, 57); --n-title-font-size: 32px; --n-title-font-weight: 500; --n-title-text-color: rgb(31, 34, 37); --n-icon-color: #2080f0;\"`;\n\nexports[`n-result > should work with \\`size\\` prop 3`] = `\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-font-size: 15px; --n-icon-size: 100px; --n-line-height: 1.6; --n-text-color: rgb(51, 54, 57); --n-title-font-size: 40px; --n-title-font-weight: 500; --n-title-text-color: rgb(31, 34, 37); --n-icon-color: #2080f0;\"`;\n\nexports[`n-result > should work with \\`size\\` prop 4`] = `\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-font-size: 16px; --n-icon-size: 125px; --n-line-height: 1.6; --n-text-color: rgb(51, 54, 57); --n-title-font-size: 48px; --n-title-font-weight: 500; --n-title-text-color: rgb(31, 34, 37); --n-icon-color: #2080f0;\"`;\n"
  },
  {
    "path": "src/result/tests/server.spec.tsx",
    "content": "import { setup } from '@css-render/vue3-ssr'\nimport { renderToString } from '@vue/server-renderer'\n/**\n * @vitest-environment node\n */\nimport { createSSRApp, h } from 'vue'\nimport { NResult } from '../..'\n\ndescribe('server side rendering', () => {\n  it('works', async () => {\n    const app = createSSRApp(() => <NResult />)\n    setup(app)\n    try {\n      await renderToString(app)\n    }\n    catch (e) {\n      expect(e).not.toBeTruthy()\n    }\n  })\n})\n"
  },
  {
    "path": "src/scrollbar/demos/enUS/basic.demo.vue",
    "content": "<markdown>\n# Basic\n</markdown>\n\n<template>\n  <n-scrollbar style=\"max-height: 120px\">\n    And as I sat there, brooding on the old unknown world, I thought of Gatsby’s\n    wonder when he first picked out the green light at the end of Daisy’s dock.\n    He had come a long way to this blue lawn and his dream must have seemed so\n    close that he could hardly fail to grasp it. He did not know that it was\n    already behind him, somewhere back in that vast obscurity beyond the city,\n    where the dark fields of the republic rolled on under the night.<br><br>\n\n    Gatsby believed in the green light, the orgastic future that year by year\n    recedes before us. It eluded us then, but that’s no matter—tomorrow we will\n    run faster, stretch out our arms farther. . . . And one fine morning——<br><br>\n\n    So we beat on, boats against the current, borne back ceaselessly into the\n    past.\n  </n-scrollbar>\n</template>\n"
  },
  {
    "path": "src/scrollbar/demos/enUS/custom.demo.vue",
    "content": "<markdown>\n# Custom scrollbar style\n\nYou can use `theme-overrides` to control the style of the scrollbar.\n</markdown>\n\n<template>\n  <n-config-provider\n    :theme-overrides=\"{\n      Scrollbar: {\n        width: '8px',\n        railInsetHorizontal: '4px 4px 4px auto',\n        borderRadius: 0,\n      },\n    }\"\n  >\n    <n-scrollbar style=\"max-height: 120px\">\n      我们在田野上面找猪<br>\n      想象中已找到了三只<br>\n      小鸟在白云上面追逐<br>\n      它们在树底下跳舞<br>\n      啦啦啦啦啦啦啦啦咧<br>\n      啦啦啦啦咧<br>\n      我们在想象中度过了许多年<br>\n      想象中我们是如此的疯狂<br>\n      我们在城市里面找猪<br>\n      想象中已找到了几百万只<br>\n      小鸟在公园里面唱歌<br>\n      它们独自在想象里跳舞<br>\n      啦啦啦啦啦啦啦啦咧<br>\n      啦啦啦啦咧<br>\n      我们在想象中度过了许多年<br>\n      许多年之后我们又开始想象<br>\n      啦啦啦啦啦啦啦啦咧\n    </n-scrollbar>\n  </n-config-provider>\n</template>\n"
  },
  {
    "path": "src/scrollbar/demos/enUS/index.demo-entry.md",
    "content": "# Scrollbar\n\nIt looks better but I'm sure it's not as reliable as native scrollbar.\n\n## Demos\n\n```demo\nbasic.vue\nx.vue\ntrigger.vue\nno-sync.vue\ncustom.vue\nplacement.vue\n```\n\n## API\n\n### Scrollbar Props\n\n| Name | Type | Default | Description | Version |\n| --- | --- | --- | --- | --- |\n| content-class | `string` | `undefined` | Class name of content div. | 2.38.2 |\n| content-style | `string \\| object` | `undefined` | Style of content div. | 2.38.2 |\n| size | `number` | `undefined` | Size of scrollbar. | 2.34.4 |\n| trigger | `'hover' \\| 'none'` | `'hover'` | Trigger of show scrollbar. `'none'` means always show it. | 2.29.1 |\n| x-scrollable | `boolean` | `false` | Whether it can scroll horizontally. |  |\n| x-placement | `'top' \\| 'bottom'` | `bottom` | Scrollbar placement when scrolling horizontally. | 2.40.0 |\n| y-placement | `'left' \\| 'right'` | `right` | Scrollbar placement when scrolling vertically. | 2.40.0 |\n| on-scroll | `(e: Event) => void` | `undefined` | Callback on scroll. |  |\n\n### Scrollbar Slots\n\n| Name    | Parameters | Description     |\n| ------- | ---------- | --------------- |\n| default | `()`       | Scroll content. |\n\n### Scrollbar Methods\n\n| Name | Type | Description |\n| --- | --- | --- |\n| scrollBy | `(options: { left?: number, top?: number, behavior?: ScrollBehavior }): void & (x: number, y: number) => void` | Scroll content by specific distance. |\n| scrollTo | `(options: { left?: number, top?: number, behavior?: ScrollBehavior }): void & (x: number, y: number) => void` | Scroll content. |\n"
  },
  {
    "path": "src/scrollbar/demos/enUS/no-sync.demo.vue",
    "content": "<markdown>\n# Mouse dragging cannot scroll to the bottom\n\nWhen the last element has a `margin-bottom`, dragging the scrollbar with the mouse cannot scroll to the bottom. This is caused by the native scrolling behavior of the browser. `n-scrollbar` cannot automatically handle this issue. You can solve this problem by setting `content-style` to `overflow: hidden;`.\n</markdown>\n\n<template>\n  <n-scrollbar style=\"max-height: 120px\">\n    Without content-style\n    <p style=\"margin-bottom: 90px\">\n      margin-bottom: 90px\n    </p>\n    <p style=\"margin-bottom: 90px\">\n      margin-bottom: 90px\n    </p>\n  </n-scrollbar>\n  <n-divider />\n  <n-scrollbar style=\"max-height: 120px\" content-style=\"overflow: hidden;\">\n    content-style=\"overflow: hidden;\"\n    <p style=\"margin-bottom: 90px\">\n      margin-bottom: 90px\n    </p>\n    <p style=\"margin-bottom: 90px\">\n      margin-bottom: 90px\n    </p>\n  </n-scrollbar>\n</template>\n"
  },
  {
    "path": "src/scrollbar/demos/enUS/placement.demo.vue",
    "content": "<markdown>\n# Placement\n\nThe placement of the scrollbar is controlled by `y-placement` and `x-placement`.\n</markdown>\n\n<template>\n  <NSpace>\n    <n-scrollbar style=\"max-height: 120px\" y-placement=\"left\">\n      And as I sat there, brooding on the old unknown world, I thought of\n      Gatsby’s wonder when he first picked out the green light at the end of\n      Daisy’s dock. He had come a long way to this blue lawn and his dream must\n      have seemed so close that he could hardly fail to grasp it. He did not\n      know that it was already behind him, somewhere back in that vast obscurity\n      beyond the city, where the dark fields of the republic rolled on under the\n      night.<br><br>\n\n      Gatsby believed in the green light, the orgastic future that year by year\n      recedes before us. It eluded us then, but that’s no matter—tomorrow we\n      will run faster, stretch out our arms farther. . . . And one fine\n      morning——<br><br>\n\n      So we beat on, boats against the current, borne back ceaselessly into the\n      past.\n    </n-scrollbar>\n    <n-scrollbar x-scrollable x-placement=\"top\" style=\"white-space: nowrap\">\n      And as I sat there, brooding on the old unknown world, I thought of\n      Gatsby’s wonder when he first picked out the green light at the end of\n      Daisy’s dock. He had come a long way to this blue lawn and his dream must\n      have seemed so close that he could hardly fail to grasp it. He did not\n      know that it was already behind him, somewhere back in that vast obscurity\n      beyond the city, where the dark fields of the republic rolled on under the\n      night. Gatsby believed in the green light, the orgastic future that year\n      by year recedes before us. It eluded us then, but that’s no\n      matter—tomorrow we will run faster, stretch out our arms farther. . . .\n      And one fine morning—— So we beat on, boats against the current, borne\n      back ceaselessly into the past.\n    </n-scrollbar>\n  </NSpace>\n</template>\n"
  },
  {
    "path": "src/scrollbar/demos/enUS/trigger.demo.vue",
    "content": "<markdown>\n# Trigger\n\nYou can set different scrollbar trigger. Setting `trigger=\"none\"` will make scrollbar always shown. Setting `trigger=\"hover\"` will make scrollbar shown on mouse hover.\n</markdown>\n\n<template>\n  <n-scrollbar style=\"max-height: 120px\" trigger=\"none\">\n    And as I sat there, brooding on the old unknown world, I thought of Gatsby’s\n    wonder when he first picked out the green light at the end of Daisy’s dock.\n    He had come a long way to this blue lawn and his dream must have seemed so\n    close that he could hardly fail to grasp it. He did not know that it was\n    already behind him, somewhere back in that vast obscurity beyond the city,\n    where the dark fields of the republic rolled on under the night.<br><br>\n\n    Gatsby believed in the green light, the orgastic future that year by year\n    recedes before us. It eluded us then, but that’s no matter—tomorrow we will\n    run faster, stretch out our arms farther. . . . And one fine morning——<br><br>\n\n    So we beat on, boats against the current, borne back ceaselessly into the\n    past.\n  </n-scrollbar>\n</template>\n"
  },
  {
    "path": "src/scrollbar/demos/enUS/x.demo.vue",
    "content": "<markdown>\n# Scroll horizontally\n</markdown>\n\n<template>\n  <n-scrollbar x-scrollable>\n    <div style=\"white-space: nowrap; padding: 12px\">\n      And as I sat there, brooding on the old unknown world, I thought of\n      Gatsby’s wonder when he first picked out the green light at the end of\n      Daisy’s dock. He had come a long way to this blue lawn and his dream must\n      have seemed so close that he could hardly fail to grasp it. He did not\n      know that it was already behind him, somewhere back in that vast obscurity\n      beyond the city, where the dark fields of the republic rolled on under the\n      night. Gatsby believed in the green light, the orgastic future that year\n      by year recedes before us. It eluded us then, but that’s no\n      matter—tomorrow we will run faster, stretch out our arms farther. . . .\n      And one fine morning—— So we beat on, boats against the current, borne\n      back ceaselessly into the past.\n    </div>\n  </n-scrollbar>\n</template>\n"
  },
  {
    "path": "src/scrollbar/demos/zhCN/basic.demo.vue",
    "content": "<markdown>\n# 基础用法\n</markdown>\n\n<template>\n  <n-scrollbar style=\"max-height: 120px\">\n    我们在田野上面找猪<br>\n    想象中已找到了三只<br>\n    小鸟在白云上面追逐<br>\n    它们在树底下跳舞<br>\n    啦啦啦啦啦啦啦啦咧<br>\n    啦啦啦啦咧<br>\n    我们在想象中度过了许多年<br>\n    想象中我们是如此的疯狂<br>\n    我们在城市里面找猪<br>\n    想象中已找到了几百万只<br>\n    小鸟在公园里面唱歌<br>\n    它们独自在想象里跳舞<br>\n    啦啦啦啦啦啦啦啦咧<br>\n    啦啦啦啦咧<br>\n    我们在想象中度过了许多年<br>\n    许多年之后我们又开始想象<br>\n    啦啦啦啦啦啦啦啦咧\n  </n-scrollbar>\n</template>\n"
  },
  {
    "path": "src/scrollbar/demos/zhCN/custom.demo.vue",
    "content": "<markdown>\n# 自定义样式\n\n你可以通过 `theme-overrides` 去控制滚动条的样式。\n</markdown>\n\n<template>\n  <n-config-provider\n    :theme-overrides=\"{\n      Scrollbar: {\n        width: '8px',\n        railInsetHorizontal: '4px 4px 4px auto',\n        borderRadius: 0,\n      },\n    }\"\n  >\n    <n-scrollbar style=\"max-height: 120px\">\n      我们在田野上面找猪<br>\n      想象中已找到了三只<br>\n      小鸟在白云上面追逐<br>\n      它们在树底下跳舞<br>\n      啦啦啦啦啦啦啦啦咧<br>\n      啦啦啦啦咧<br>\n      我们在想象中度过了许多年<br>\n      想象中我们是如此的疯狂<br>\n      我们在城市里面找猪<br>\n      想象中已找到了几百万只<br>\n      小鸟在公园里面唱歌<br>\n      它们独自在想象里跳舞<br>\n      啦啦啦啦啦啦啦啦咧<br>\n      啦啦啦啦咧<br>\n      我们在想象中度过了许多年<br>\n      许多年之后我们又开始想象<br>\n      啦啦啦啦啦啦啦啦咧\n    </n-scrollbar>\n  </n-config-provider>\n</template>\n"
  },
  {
    "path": "src/scrollbar/demos/zhCN/index.demo-entry.md",
    "content": "# 滚动条 Scrollbar\n\n看起来好看点，但是我能保证这个没有原生滚动条可靠。\n\n## 演示\n\n```demo\nbasic.vue\nx.vue\ntrigger.vue\nno-sync.vue\nrtl-debug.vue\ncustom.vue\nplacement.vue\n```\n\n## API\n\n### Scrollbar Props\n\n| 名称 | 类型 | 默认值 | 说明 | 版本 |\n| --- | --- | --- | --- | --- |\n| content-class | `string` | `undefined` | 内容 div 的类名 | 2.38.2 |\n| content-style | `string \\| object` | `undefined` | 内容 div 的 style | 2.38.2 |\n| size | `number` | `undefined` | 滚动条的大小 | 2.34.4 |\n| trigger | `'hover' \\| 'none'` | `'hover'` | 显示滚动条的时机，`'none'` 表示一直显示 | 2.29.1 |\n| x-scrollable | `boolean` | `false` | 是否可以横向滚动 |  |\n| x-placement | `'top' \\| 'bottom'` | `bottom` | 横向滚动时滚动条的位置 | 2.40.0 |\n| y-placement | `'left' \\| 'right'` | `right` | 纵向滚动时滚动条的位置 | 2.40.0 |\n| on-scroll | `(e: Event) => void` | `undefined` | 滚动的回调 |  |\n\n### Scrollbar Slots\n\n| 名称    | 参数 | 说明     |\n| ------- | ---- | -------- |\n| default | `()` | 滚动内容 |\n\n### Scrollbar Methods\n\n| 名称 | 类型 | 说明 |\n| --- | --- | --- |\n| scrollBy | `(options: { left?: number, top?: number, behavior?: ScrollBehavior }): void & (x: number, y: number) => void` | 滚动特定距离 |\n| scrollTo | `(options: { left?: number, top?: number, behavior?: ScrollBehavior }): void & (x: number, y: number) => void` | 滚动内容 |\n"
  },
  {
    "path": "src/scrollbar/demos/zhCN/no-sync.demo.vue",
    "content": "<markdown>\n# 鼠标拖动滚不到最下面\n\n在最后一个元素含有 `margin-bottom` 的情况下，通过鼠标拖动滚动条，滚动不到最下面。这是浏览器的原生滚动行为导致的，`n-scrollbar` 无法自动的处理这种问题，你可以通过设定 `content-style` 为 `'overflow: hidden;'` 来解决这个问题。\n</markdown>\n\n<template>\n  <n-scrollbar style=\"max-height: 120px\">\n    不设定 content-style\n    <p style=\"margin-bottom: 90px\">\n      margin-bottom: 90px\n    </p>\n    <p style=\"margin-bottom: 90px\">\n      margin-bottom: 90px\n    </p>\n  </n-scrollbar>\n  <n-divider />\n  <n-scrollbar style=\"max-height: 120px\" content-style=\"overflow: hidden;\">\n    content-style=\"overflow: hidden;\"\n    <p style=\"margin-bottom: 90px\">\n      margin-bottom: 90px\n    </p>\n    <p style=\"margin-bottom: 90px\">\n      margin-bottom: 90px\n    </p>\n  </n-scrollbar>\n</template>\n"
  },
  {
    "path": "src/scrollbar/demos/zhCN/placement.demo.vue",
    "content": "<markdown>\n# 滚动条位置\n\n通过 `y-placement` 和 `x-placement` 去控制滚动条的位置。\n</markdown>\n\n<template>\n  <NSpace>\n    <n-scrollbar style=\"max-height: 120px\" y-placement=\"left\">\n      我们在田野上面找猪<br>\n      想象中已找到了三只<br>\n      小鸟在白云上面追逐<br>\n      它们在树底下跳舞<br>\n      啦啦啦啦啦啦啦啦咧<br>\n      啦啦啦啦咧<br>\n      我们在想象中度过了许多年<br>\n      想象中我们是如此的疯狂<br>\n      我们在城市里面找猪<br>\n      想象中已找到了几百万只<br>\n      小鸟在公园里面唱歌<br>\n      它们独自在想象里跳舞<br>\n      啦啦啦啦啦啦啦啦咧<br>\n      啦啦啦啦咧<br>\n      我们在想象中度过了许多年<br>\n      许多年之后我们又开始想象<br>\n      啦啦啦啦啦啦啦啦咧\n    </n-scrollbar>\n    <n-scrollbar x-scrollable x-placement=\"top\" style=\"white-space: nowrap\">\n      我们在田野上面找猪 想象中已找到了三只 小鸟在白云上面追逐 它们在树底下跳舞\n      啦啦啦啦啦啦啦啦咧 啦啦啦啦咧 我们在想象中度过了许多年\n      想象中我们是如此的疯狂 我们在城市里面找猪 想象中已找到了几百万只\n      小鸟在公园里面唱歌 它们独自在想象里跳舞 啦啦啦啦啦啦啦啦咧 啦啦啦啦咧\n      我们在想象中度过了许多年 许多年之后我们又开始想象 啦啦啦啦啦啦啦啦咧\n    </n-scrollbar>\n  </NSpace>\n</template>\n"
  },
  {
    "path": "src/scrollbar/demos/zhCN/rtl-debug.demo.vue",
    "content": "<markdown>\n# Rtl Debug\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { unstableScrollbarRtl } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst rtlEnabled = ref(true)\nconst rtlStyles = [unstableScrollbarRtl]\n</script>\n\n<template>\n  <n-config-provider :rtl=\"rtlEnabled ? rtlStyles : undefined\">\n    <div :dir=\"rtlEnabled ? 'rtl' : 'ltr'\">\n      <n-space>\n        <n-scrollbar style=\"max-height: 90px\" trigger=\"none\">\n          لورم ایپسوم متن ساختگی با تولید سادگی نامفهوم از صنعت چاپ و با استفاده\n          از طراحان گرافیک است. چاپگرها و متون بلکه روزنامه و مجله در ستون و\n          سطرآنچنان که لازم است و برای شرایط فعلی تکنولوژی مورد نیاز و کاربردهای\n          متنوع با هدف بهبود ابزارهای کاربردی می باشد. کتابهای زیادی در شصت و سه\n          درصد گذشته، حال و آینده شناخت فراوان جامعه و متخصصان را می طلبد تا با\n          نرم افزارها شناخت بیشتری را برای طراحان رایانه ای علی الخصوص طراحان\n          خلاقی و فرهنگ پیشرو در زبان فارسی ایجاد کرد. در این صورت می توان امید\n          داشت که تمام و دشواری موجود در ارائه راهکارها و شرایط سخت تایپ به\n          پایان رسد وزمان مورد نیاز شامل حروفچینی دستاوردهای اصلی و جوابگوی\n          سوالات پیوسته اهل دنیای موجود طراحی اساسا مورد استفاده قرار گیرد.\n        </n-scrollbar>\n        <n-scrollbar x-scrollable trigger=\"none\">\n          <div style=\"white-space: nowrap; padding: 12px\">\n            لورم ایپسوم متن ساختگی با تولید سادگی نامفهوم از صنعت چاپ و با\n            استفاده از طراحان گرافیک است. چاپگرها و متون بلکه روزنامه و مجله در\n            ستون و سطرآنچنان که لازم است و برای شرایط فعلی تکنولوژی مورد نیاز و\n            کاربردهای متنوع با هدف بهبود ابزارهای کاربردی می باشد. کتابهای زیادی\n            در شصت و سه درصد گذشته، حال و آینده شناخت فراوان جامعه و متخصصان را\n            می طلبد تا با نرم افزارها شناخت بیشتری را برای طراحان رایانه ای علی\n            الخصوص طراحان خلاقی و فرهنگ پیشرو در زبان فارسی ایجاد کرد. در این\n            صورت می توان امید داشت که تمام و دشواری موجود در ارائه راهکارها و\n            شرایط سخت تایپ به پایان رسد وزمان مورد نیاز شامل حروفچینی دستاوردهای\n            اصلی و جوابگوی سوالات پیوسته اهل دنیای موجود طراحی اساسا مورد\n            استفاده قرار گیرد.\n          </div>\n        </n-scrollbar>\n      </n-space>\n    </div>\n  </n-config-provider>\n</template>\n"
  },
  {
    "path": "src/scrollbar/demos/zhCN/trigger.demo.vue",
    "content": "<markdown>\n# 触发方式\n\n你可以设定不同的触发方式，`trigger=\"none\"` 会让滚动条一直显示，`trigger=\"hover\"` 会让滚动条在鼠标悬浮的时候显示。\n</markdown>\n\n<template>\n  <n-scrollbar style=\"max-height: 120px\" trigger=\"none\">\n    我们在田野上面找猪<br>\n    想象中已找到了三只<br>\n    小鸟在白云上面追逐<br>\n    它们在树底下跳舞<br>\n    啦啦啦啦啦啦啦啦咧<br>\n    啦啦啦啦咧<br>\n    我们在想象中度过了许多年<br>\n    想象中我们是如此的疯狂<br>\n    我们在城市里面找猪<br>\n    想象中已找到了几百万只<br>\n    小鸟在公园里面唱歌<br>\n    它们独自在想象里跳舞<br>\n    啦啦啦啦啦啦啦啦咧<br>\n    啦啦啦啦咧<br>\n    我们在想象中度过了许多年<br>\n    许多年之后我们又开始想象<br>\n    啦啦啦啦啦啦啦啦咧\n  </n-scrollbar>\n</template>\n"
  },
  {
    "path": "src/scrollbar/demos/zhCN/x.demo.vue",
    "content": "<markdown>\n# 横向滚动\n</markdown>\n\n<template>\n  <n-scrollbar x-scrollable>\n    <div style=\"white-space: nowrap; padding: 12px\">\n      我们在田野上面找猪 想象中已找到了三只 小鸟在白云上面追逐 它们在树底下跳舞\n      啦啦啦啦啦啦啦啦咧 啦啦啦啦咧 我们在想象中度过了许多年\n      想象中我们是如此的疯狂 我们在城市里面找猪 想象中已找到了几百万只\n      小鸟在公园里面唱歌 它们独自在想象里跳舞 啦啦啦啦啦啦啦啦咧 啦啦啦啦咧\n      我们在想象中度过了许多年 许多年之后我们又开始想象 啦啦啦啦啦啦啦啦咧\n    </div>\n  </n-scrollbar>\n</template>\n"
  },
  {
    "path": "src/scrollbar/index.ts",
    "content": "export { default as NScrollbar, scrollbarProps } from './src/Scrollbar'\nexport type { ScrollbarInst, ScrollbarProps } from './src/Scrollbar'\n"
  },
  {
    "path": "src/scrollbar/src/Scrollbar.tsx",
    "content": "import type { PropType } from 'vue'\nimport type { ScrollbarInst as InternalScrollbarInst } from '../../_internal'\nimport type { ScrollbarTheme } from '../../_internal/scrollbar/styles'\nimport type { ThemeProps } from '../../_mixins'\nimport type { ExtractPublicPropTypes } from '../../_utils'\nimport { defineComponent, h, ref } from 'vue'\nimport { NScrollbar } from '../../_internal'\nimport { useTheme } from '../../_mixins'\n\nexport interface ScrollTo {\n  (x: number, y: number): void\n  (options: { left?: number, top?: number, behavior?: ScrollBehavior }): void\n}\n\nexport type ScrollBy = ScrollTo\n\nexport interface ScrollbarInst {\n  scrollTo: ScrollTo\n  scrollBy: ScrollBy\n}\n\nexport const scrollbarProps = {\n  ...(useTheme.props as ThemeProps<ScrollbarTheme>),\n  trigger: String as PropType<'none' | 'hover'>,\n  xScrollable: Boolean,\n  onScroll: Function as PropType<(e: Event) => void>,\n  contentClass: String,\n  contentStyle: [Object, String] as PropType<string | Record<string, any>>,\n  size: Number,\n  yPlacement: {\n    type: String as PropType<'left' | 'right'>,\n    default: 'right'\n  },\n  xPlacement: {\n    type: String as PropType<'top' | 'bottom'>,\n    default: 'bottom'\n  }\n} as const\n\nexport type ScrollbarProps = ExtractPublicPropTypes<typeof scrollbarProps>\n\nconst Scrollbar = defineComponent({\n  name: 'Scrollbar',\n  props: scrollbarProps,\n  setup() {\n    const scrollbarInstRef = ref<InternalScrollbarInst | null>(null)\n    const exposedMethods: ScrollbarInst = {\n      scrollTo: (...args: any[]) => {\n        scrollbarInstRef.value?.scrollTo(args[0], args[1])\n      },\n      scrollBy: (...args: any[]) => {\n        scrollbarInstRef.value?.scrollBy(args[0], args[1])\n      }\n    }\n    return {\n      ...exposedMethods,\n      scrollbarInstRef\n    }\n  },\n  render() {\n    return (\n      <NScrollbar ref=\"scrollbarInstRef\" {...this.$props}>\n        {this.$slots}\n      </NScrollbar>\n    )\n  }\n})\n\nexport default Scrollbar\n"
  },
  {
    "path": "src/scrollbar/tests/Scrollbar.spec.ts",
    "content": "import { mount } from '@vue/test-utils'\nimport { NScrollbar } from '../index'\n\ndescribe('n-scrollbar', () => {\n  it('should work with import on demand', () => {\n    mount(NScrollbar)\n  })\n\n  it('should work with `default` slot', () => {\n    const text = 'test-default'\n    const wrapper = mount(NScrollbar, {\n      attrs: { style: 'max-height: 120px' },\n      slots: { default: () => text }\n    })\n\n    expect(wrapper.find('.n-scrollbar-rail').exists()).toBe(true)\n    expect(wrapper.find('.n-scrollbar-content').text()).toBe(text)\n    wrapper.unmount()\n  })\n})\n"
  },
  {
    "path": "src/scrollbar/tests/server.spec.tsx",
    "content": "import { setup } from '@css-render/vue3-ssr'\nimport { renderToString } from '@vue/server-renderer'\n/**\n * @vitest-environment node\n */\nimport { createSSRApp, h } from 'vue'\nimport { NScrollbar } from '../'\n\ndescribe('server side rendering', () => {\n  it('works', async () => {\n    const app = createSSRApp(() => <NScrollbar />)\n    setup(app)\n    try {\n      await renderToString(app)\n    }\n    catch (e) {\n      expect(e).not.toBeTruthy()\n    }\n  })\n})\n"
  },
  {
    "path": "src/select/demos/enUS/action.demo.vue",
    "content": "<markdown>\n# Action slot\n\nIs there anybody who needs an action slot on a select menu?\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst value = ref(null)\nconst options = [\n  {\n    label: 'Everybody\\'s Got Something to Hide Except Me and My Monkey',\n    value: 'song0',\n    disabled: true\n  },\n  {\n    label: 'Drive My Car',\n    value: 'song1'\n  },\n  {\n    label: 'Norwegian Wood',\n    value: 'song2'\n  },\n  {\n    label: 'You Won\\'t See',\n    value: 'song3',\n    disabled: true\n  }\n]\n</script>\n\n<template>\n  <n-select v-model:value=\"value\" :options=\"options\">\n    <template #header>\n      Don't know what to put\n    </template>\n    <template #action>\n      If you click this demo, you may need it.\n    </template>\n  </n-select>\n</template>\n"
  },
  {
    "path": "src/select/demos/enUS/add-tooltip.demo.vue",
    "content": "<markdown>\n# Add tooltip to option\n\nUse the `render-option` property to control rendering of the entire option.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { SelectOption } from 'naive-ui'\nimport type { VNode } from 'vue'\nimport { NTooltip } from 'naive-ui'\nimport { h, ref } from 'vue'\n\nfunction renderOption({ node, option }: { node: VNode, option: SelectOption }) {\n  return h(NTooltip, null, {\n    trigger: () => node,\n    default: () => `Rubber Soul -${option.label}`\n  })\n}\n\nconst options = ref([\n  {\n    label: 'Everybody\\'s Got Something to Hide Except Me and My Monkey',\n    value: 'song0',\n    disabled: true\n  },\n  {\n    label: 'Drive My Car',\n    value: 'song1'\n  },\n  {\n    label: 'Norwegian Wood',\n    value: 'song2'\n  },\n  {\n    label: 'You Won\\'t See',\n    value: 'song3',\n    disabled: true\n  },\n  {\n    label: 'Nowhere Man',\n    value: 'song4'\n  },\n  {\n    label: 'Think For Yourself',\n    value: 'song5'\n  },\n  {\n    label: 'The Word',\n    value: 'song6'\n  },\n  {\n    label: 'Michelle',\n    value: 'song7',\n    disabled: true\n  },\n  {\n    label: 'What goes on',\n    value: 'song8'\n  },\n  {\n    label: 'Girl',\n    value: 'song9'\n  },\n  {\n    label: 'I\\'m looking through you',\n    value: 'song10'\n  },\n  {\n    label: 'In My Life',\n    value: 'song11'\n  },\n  {\n    label: 'Wait',\n    value: 'song12'\n  }\n])\n</script>\n\n<template>\n  <n-select :options=\"options\" :render-option=\"renderOption\" />\n</template>\n"
  },
  {
    "path": "src/select/demos/enUS/basic.demo.vue",
    "content": "<markdown>\n# Basic\n\nBasic usage of `n-select`.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst value = ref(null)\nconst options = [\n  {\n    label: 'Everybody\\'s Got Something to Hide Except Me and My Monkey',\n    value: 'song0',\n    disabled: true\n  },\n  {\n    label: 'Drive My Car',\n    value: 'song1'\n  },\n  {\n    label: 'Norwegian Wood',\n    value: 'song2'\n  },\n  {\n    label: 'You Won\\'t See',\n    value: 'song3',\n    disabled: true\n  },\n  {\n    label: 'Nowhere Man',\n    value: 'song4'\n  },\n  {\n    label: 'Think For Yourself',\n    value: 'song5'\n  },\n  {\n    label: 'The Word',\n    value: 'song6'\n  },\n  {\n    label: 'Michelle',\n    value: 'song7',\n    disabled: true\n  },\n  {\n    label: 'What goes on',\n    value: 'song8'\n  },\n  {\n    label: 'Girl',\n    value: 'song9'\n  },\n  {\n    label: 'I\\'m looking through you',\n    value: 'song10'\n  },\n  {\n    label: 'In My Life',\n    value: 'song11'\n  },\n  {\n    label: 'Wait',\n    value: 'song12'\n  }\n]\n</script>\n\n<template>\n  <n-space vertical>\n    <n-select v-model:value=\"value\" :options=\"options\" />\n    <n-select v-model:value=\"value\" disabled :options=\"options\" />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/select/demos/enUS/clearable.demo.vue",
    "content": "<markdown>\n# Clearable\n\nMake the select clearable. Remember you can only clear a select that has a value.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst selectedValue = ref(null)\nconst selectedArray = ref([])\nconst options = [\n  {\n    label: 'Drive My Car',\n    value: 'song1'\n  },\n  {\n    label: 'Norwegian Wood',\n    value: 'song2'\n  },\n  {\n    label: 'You Won\\'t See',\n    value: 'song3'\n  },\n  {\n    label: 'Nowhere Man',\n    value: 'song4'\n  },\n  {\n    label: 'Think For Yourself',\n    value: 'song5'\n  },\n  {\n    label: 'The Word',\n    value: 'song6'\n  },\n  {\n    label: 'Michelle',\n    value: 'song7'\n  },\n  {\n    label: 'What goes on',\n    value: 'song8'\n  },\n  {\n    label: 'Girl',\n    value: 'song9'\n  },\n  {\n    label: 'I\\'m looking through you',\n    value: 'song10'\n  },\n  {\n    label: 'In My Life',\n    value: 'song11'\n  },\n  {\n    label: 'Wait',\n    value: 'song12'\n  }\n]\n</script>\n\n<template>\n  <n-space vertical>\n    <n-select v-model:value=\"selectedValue\" :options=\"options\" clearable />\n    <n-select\n      v-model:value=\"selectedArray\"\n      multiple\n      :options=\"options\"\n      clearable\n    />\n    <n-select\n      v-model:value=\"selectedValue\"\n      :options=\"options\"\n      filterable\n      clearable\n    />\n    <n-select\n      v-model:value=\"selectedArray\"\n      multiple\n      :options=\"options\"\n      filterable\n      clearable\n    />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/select/demos/enUS/custom-field.demo.vue",
    "content": "<markdown>\n# Customizing field\n\nVarious data would come from backend.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { SelectGroupOption, SelectOption } from 'naive-ui'\n\nconst options: Array<SelectOption | SelectGroupOption> = [\n  {\n    type: 'group',\n    whateverLabel: 'Rubber Soul',\n    key: 'Rubber Soul',\n    whateverChildren: [\n      {\n        whateverLabel:\n          'Everybody\\'s Got Something to Hide Except Me and My Monkey',\n        whateverValue: 'song0',\n        disabled: true\n      },\n      {\n        whateverLabel: 'Drive My Car',\n        whateverValue: 'song1'\n      },\n      {\n        whateverLabel: 'Norwegian Wood',\n        whateverValue: 'song2'\n      },\n      {\n        whateverLabel: 'You Won\\'t See',\n        whateverValue: 'song3',\n        disabled: true\n      },\n      {\n        whateverLabel: 'Nowhere Man',\n        whateverValue: 'song4'\n      },\n      {\n        whateverLabel: 'Think For Yourself',\n        whateverValue: 'song5'\n      },\n      {\n        whateverLabel: 'The Word',\n        whateverValue: 'song6'\n      },\n      {\n        whateverLabel: 'Michelle',\n        whateverValue: 'song7',\n        disabled: true\n      },\n      {\n        whateverLabel: 'What goes on',\n        whateverValue: 'song8'\n      },\n      {\n        whateverLabel: 'Girl',\n        whateverValue: 'song9'\n      },\n      {\n        whateverLabel: 'I\\'m looking through you',\n        whateverValue: 'song10'\n      },\n      {\n        whateverLabel: 'In My Life',\n        whateverValue: 'song11'\n      },\n      {\n        whateverLabel: 'Wait',\n        whateverValue: 'song12'\n      }\n    ]\n  },\n  {\n    type: 'group',\n    whateverLabel: 'Let It Be',\n    key: 'Let It Be Album',\n    whateverChildren: [\n      {\n        whateverLabel: 'Two Of Us',\n        whateverValue: 'Two Of Us'\n      },\n      {\n        whateverLabel: 'Dig A Pony',\n        whateverValue: 'Dig A Pony'\n      },\n      {\n        whateverLabel: 'Across The Universe',\n        whateverValue: 'Across The Universe'\n      },\n      {\n        whateverLabel: 'I Me Mine',\n        whateverValue: 'I Me Mine'\n      },\n      {\n        whateverLabel: 'Dig It',\n        whateverValue: 'Dig It'\n      },\n      {\n        whateverLabel: 'Let It Be',\n        whateverValue: 'Let It Be'\n      },\n      {\n        whateverLabel: 'Maggie Mae',\n        whateverValue: 'Maggie Mae'\n      },\n      {\n        whateverLabel: 'I\\'ve Got A Feeling',\n        whateverValue: 'I\\'ve Got A Feeling'\n      },\n      {\n        whateverLabel: 'One After 909',\n        whateverValue: 'One After 909'\n      },\n      {\n        whateverLabel: 'The Long And Winding Road',\n        whateverValue: 'The Long And Winding Road'\n      },\n      {\n        whateverLabel: 'For You Blue',\n        whateverValue: 'For You Blue'\n      },\n      {\n        whateverLabel: 'Get Back',\n        whateverValue: 'Get Back'\n      }\n    ]\n  }\n]\n</script>\n\n<template>\n  <n-space vertical>\n    <n-select\n      label-field=\"whateverLabel\"\n      value-field=\"whateverValue\"\n      children-field=\"whateverChildren\"\n      filterable\n      :options=\"options\"\n    />\n    <n-select\n      label-field=\"whateverLabel\"\n      value-field=\"whateverValue\"\n      children-field=\"whateverChildren\"\n      filterable\n      multiple\n      :options=\"options\"\n    />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/select/demos/enUS/custom-option.demo.vue",
    "content": "<markdown>\n# Customize option rendering\n\nAfter much deliberation, I decided to drop the slot API for rendering options; however, using `render-label`, `style`, and/or `class` properties you can do almost anything.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { SelectGroupOption, SelectOption } from 'naive-ui'\nimport type { VNodeChild } from 'vue'\nimport { MdMusicalNote as MusicIcon } from '@vicons/ionicons4'\nimport { NIcon } from 'naive-ui'\nimport { h } from 'vue'\n\nconst options: Array<SelectOption | SelectGroupOption> = [\n  {\n    type: 'group',\n    label: 'Rubber Soul',\n    key: 'Rubber Soul Album',\n    children: [\n      {\n        label: 'Everybody\\'s Got Something to Hide Except Me and My Monkey',\n        value: 'song0',\n        disabled: true\n      },\n      {\n        label: 'Drive My Car',\n        value: 'song1',\n        style: {\n          color: 'red'\n        }\n      },\n      {\n        label: 'Norwegian Wood',\n        value: 'song2'\n      },\n      {\n        label: 'You Won\\'t See',\n        value: 'song3',\n        disabled: true\n      },\n      {\n        label: 'Nowhere Man',\n        value: 'song4'\n      },\n      {\n        label: 'Think For Yourself',\n        value: 'song5'\n      },\n      {\n        label: 'The Word',\n        value: 'song6'\n      },\n      {\n        label: 'Michelle',\n        value: 'song7',\n        disabled: true\n      },\n      {\n        label: 'What goes on',\n        value: 'song8'\n      },\n      {\n        label: 'Girl',\n        value: 'song9'\n      },\n      {\n        label: 'I\\'m looking through you',\n        value: 'song10'\n      },\n      {\n        label: 'In My Life',\n        value: 'song11'\n      },\n      {\n        label: 'Wait',\n        value: 'song12'\n      }\n    ]\n  },\n  {\n    type: 'group',\n    label: 'Let It Be',\n    key: 'Let It Be Album',\n    children: [\n      {\n        label: 'Two Of Us',\n        value: 'Two Of Us'\n      },\n      {\n        label: 'Dig A Pony',\n        value: 'Dig A Pony'\n      },\n      {\n        label: 'Across The Universe',\n        value: 'Across The Universe'\n      },\n      {\n        label: 'I Me Mine',\n        value: 'I Me Mine'\n      },\n      {\n        label: 'Dig It',\n        value: 'Dig It'\n      },\n      {\n        label: 'Let It Be',\n        value: 'Let It Be'\n      },\n      {\n        label: 'Maggie Mae',\n        value: 'Maggie Mae'\n      },\n      {\n        label: 'I\\'ve Got A Feeling',\n        value: 'I\\'ve Got A Feeling'\n      },\n      {\n        label: 'One After 909',\n        value: 'One After 909'\n      },\n      {\n        label: 'The Long And Winding Road',\n        value: 'The Long And Winding Road'\n      },\n      {\n        label: 'For You Blue',\n        value: 'For You Blue'\n      },\n      {\n        label: 'Get Back',\n        value: 'Get Back'\n      }\n    ]\n  }\n]\n\nfunction renderLabel(option: SelectOption): VNodeChild {\n  if (option.type === 'group')\n    return `${option.label}(Cool!)`\n  return [\n    h(\n      NIcon,\n      {\n        style: {\n          verticalAlign: '-0.15em',\n          marginRight: '4px'\n        }\n      },\n      {\n        default: () => h(MusicIcon)\n      }\n    ),\n    option.label as string\n  ]\n}\n</script>\n\n<template>\n  <n-select :options=\"options\" :render-label=\"renderLabel\" />\n</template>\n"
  },
  {
    "path": "src/select/demos/enUS/custom-suffix.demo.vue",
    "content": "<markdown>\n# Customize arrow\n\nMake arrow a bit different.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport Flash16Regular from '@vicons/fluent/Flash16Regular'\nimport FlashCheckmark16Regular from '@vicons/fluent/FlashCheckmark16Regular'\nimport { MdSearch } from '@vicons/ionicons4'\nimport { ref } from 'vue'\n\nconst show1 = ref(false)\nconst show2 = ref(false)\nconst options = [\n  {\n    label: 'Drive My Car',\n    value: 'song1'\n  },\n  {\n    label: 'Norwegian Wood',\n    value: 'song2'\n  },\n  {\n    label: 'You Won\\'t See',\n    value: 'song3'\n  },\n  {\n    label: 'Nowhere Man',\n    value: 'song4'\n  },\n  {\n    label: 'Think For Yourself',\n    value: 'song5'\n  },\n  {\n    label: 'The Word',\n    value: 'song6'\n  },\n  {\n    label: 'Michelle',\n    value: 'song7'\n  },\n  {\n    label: 'What goes on',\n    value: 'song8'\n  },\n  {\n    label: 'Girl',\n    value: 'song9'\n  },\n  {\n    label: 'I\\'m looking through you',\n    value: 'song10'\n  },\n  {\n    label: 'In My Life',\n    value: 'song11'\n  },\n  {\n    label: 'Wait',\n    value: 'song12'\n  }\n]\n</script>\n\n<template>\n  <n-space vertical>\n    <n-select\n      v-model:show=\"show1\"\n      placeholder=\"Please select a song\"\n      :options=\"options\"\n    >\n      <template #arrow>\n        <transition name=\"slide-left\">\n          <FlashCheckmark16Regular v-if=\"show1\" />\n          <Flash16Regular v-else />\n        </transition>\n      </template>\n    </n-select>\n    <n-select\n      v-model:show=\"show2\"\n      filterable\n      placeholder=\"Please select a song\"\n      :options=\"options\"\n    >\n      <template v-if=\"show2\" #arrow>\n        <MdSearch />\n      </template>\n    </n-select>\n  </n-space>\n</template>\n\n<style>\n:deep(.slide-left-enter-active),\n:deep(.slide-left-leave-active) {\n  transition:\n    transform 0.3s ease,\n    opacity 0.3s ease;\n}\n\n:deep(.slide-left-enter-from),\n:deep(.slide-left-leave-to) {\n  position: absolute;\n  opacity: 0;\n}\n\n:deep(.slide-left-enter-from) {\n  transform: translateX(-10px);\n}\n\n:deep(.slide-left-leave-to) {\n  transform: translateX(10px);\n}\n</style>\n"
  },
  {
    "path": "src/select/demos/enUS/events.demo.vue",
    "content": "<markdown>\n# UpdateValue event\n\nWhy make the `update:value` event an example? Because there's so little to write.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { SelectOption } from 'naive-ui'\nimport { useMessage } from 'naive-ui'\n\nconst message = useMessage()\n\nfunction handleUpdateValue(value: string, option: SelectOption) {\n  message.info(`value: ${JSON.stringify(value)}`)\n  message.info(`option: ${JSON.stringify(option)}`)\n}\n\nconst options = [\n  {\n    label: 'Drive My Car',\n    value: 'song1'\n  },\n  {\n    label: 'Norwegian Wood',\n    value: 'song2'\n  },\n  {\n    label: 'You Won\\'t See',\n    value: 'song3'\n  },\n  {\n    label: 'Nowhere Man',\n    value: 'song4'\n  },\n  {\n    label: 'Think For Yourself',\n    value: 'song5'\n  },\n  {\n    label: 'The Word',\n    value: 'song6'\n  },\n  {\n    label: 'Michelle',\n    value: 'song7'\n  },\n  {\n    label: 'What goes on',\n    value: 'song8'\n  },\n  {\n    label: 'Girl',\n    value: 'song9'\n  },\n  {\n    label: 'I\\'m looking through you',\n    value: 'song10'\n  },\n  {\n    label: 'In My Life',\n    value: 'song11'\n  },\n  {\n    label: 'Wait',\n    value: 'song12'\n  }\n]\n</script>\n\n<template>\n  <n-space vertical>\n    <n-select\n      placeholder=\"Please select a song\"\n      :options=\"options\"\n      @update:value=\"handleUpdateValue\"\n    />\n    <n-select\n      multiple\n      placeholder=\"Please Select Songs\"\n      :options=\"options\"\n      @update:value=\"handleUpdateValue\"\n    />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/select/demos/enUS/fallback-option.demo.vue",
    "content": "<markdown>\n# Fallback option\n\nIf you don't need fallback options, setting `fallback-option` to `false` ensures that only an option with a matching value will be displayed. If no option has that value, the selected value will be cleared.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { SelectOption } from 'naive-ui'\nimport { ref } from 'vue'\n\nfunction trim(value: string): SelectOption {\n  return {\n    label: value.split(' ')[0],\n    value\n  }\n}\n\nconst singleValue = ref('A Nowhere Value')\nconst multipleValue = ref(['First Nowhere Value', 'Second Nowhere Value'])\nconst options = [\n  {\n    label: 'Everybody\\'s Got Something to Hide Except Me and My Monkey',\n    value: 'song0',\n    disabled: true\n  },\n  {\n    label: 'Drive My Car',\n    value: 'song1'\n  },\n  {\n    label: 'Norwegian Wood',\n    value: 'song2'\n  },\n  {\n    label: 'You Won\\'t See',\n    value: 'song3',\n    disabled: true\n  },\n  {\n    label: 'Nowhere Man',\n    value: 'song4'\n  },\n  {\n    label: 'Think For Yourself',\n    value: 'song5'\n  },\n  {\n    label: 'The Word',\n    value: 'song6'\n  },\n  {\n    label: 'Michelle',\n    value: 'song7',\n    disabled: true\n  },\n  {\n    label: 'What goes on',\n    value: 'song8'\n  },\n  {\n    label: 'Girl',\n    value: 'song9'\n  },\n  {\n    label: 'I\\'m looking through you',\n    value: 'song10'\n  },\n  {\n    label: 'In My Life',\n    value: 'song11'\n  },\n  {\n    label: 'Wait',\n    value: 'song12'\n  }\n]\n</script>\n\n<template>\n  <n-space vertical>\n    <n-select v-model:value=\"singleValue\" :options=\"options\" />\n    <n-select\n      v-model:value=\"multipleValue\"\n      multiple\n      :fallback-option=\"trim\"\n      :options=\"options\"\n    />\n    <n-select\n      v-model:value=\"singleValue\"\n      placeholder=\"No Fallback\"\n      :fallback-option=\"false\"\n      :options=\"options\"\n    />\n    <n-select\n      v-model:value=\"multipleValue\"\n      placeholder=\"No Fallback\"\n      multiple\n      :fallback-option=\"false\"\n      :options=\"options\"\n    />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/select/demos/enUS/filterable.demo.vue",
    "content": "<markdown>\n# Filterable\n\nGo go go, Filter.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst selectedValue = ref(null)\nconst selectedValues = ref(null)\nconst options = [\n  {\n    label: 'Drive My Car',\n    value: 'song1'\n  },\n  {\n    label: 'Norwegian Wood',\n    value: 'song2'\n  },\n  {\n    label: 'You Won\\'t See',\n    value: 'song3'\n  },\n  {\n    label: 'Nowhere Man',\n    value: 'song4'\n  },\n  {\n    label: 'Think For Yourself',\n    value: 'song5'\n  },\n  {\n    label: 'The Word',\n    value: 'song6'\n  },\n  {\n    label: 'Michelle',\n    value: 'song7'\n  },\n  {\n    label: 'What goes on',\n    value: 'song8'\n  },\n  {\n    label: 'Girl',\n    value: 'song9'\n  },\n  {\n    label: 'I\\'m looking through you',\n    value: 'song10'\n  },\n  {\n    label: 'In My Life',\n    value: 'song11'\n  },\n  {\n    label: 'Wait',\n    value: 'song12'\n  }\n]\n</script>\n\n<template>\n  <n-space vertical>\n    <n-select\n      v-model:value=\"selectedValue\"\n      filterable\n      placeholder=\"Please select a song\"\n      :options=\"options\"\n    />\n    <n-select\n      v-model:value=\"selectedValues\"\n      multiple\n      filterable\n      placeholder=\"Please Select Songs\"\n      :options=\"options\"\n    />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/select/demos/enUS/focus.demo.vue",
    "content": "<markdown>\n# Focus & blur manually\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { SelectInst } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst selectInstRef = ref<SelectInst | null>(null)\n\nfunction handleClick() {\n  selectInstRef.value?.focus()\n  setTimeout(() => {\n    selectInstRef.value?.blur()\n  }, 1000)\n}\n</script>\n\n<template>\n  <n-space item-style=\"display: flex; align-item: center;\">\n    <n-button @click=\"handleClick\">\n      Focus then blur in 1 second\n    </n-button>\n    <n-select ref=\"selectInstRef\" style=\"width: 200px\" />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/select/demos/enUS/group.demo.vue",
    "content": "<markdown>\n# Group\n\nOptions can also be grouped together.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { SelectGroupOption, SelectOption } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst value = ref(null)\nconst options: Array<SelectOption | SelectGroupOption> = [\n  {\n    type: 'group',\n    label: 'Rubber Soul',\n    key: 'Rubber Soul',\n    children: [\n      {\n        label: 'Everybody\\'s Got Something to Hide Except Me and My Monkey',\n        value: 'song0',\n        disabled: true\n      },\n      {\n        label: 'Drive My Car',\n        value: 'song1'\n      },\n      {\n        label: 'Norwegian Wood',\n        value: 'song2'\n      },\n      {\n        label: 'You Won\\'t See',\n        value: 'song3',\n        disabled: true\n      },\n      {\n        label: 'Nowhere Man',\n        value: 'song4'\n      },\n      {\n        label: 'Think For Yourself',\n        value: 'song5'\n      },\n      {\n        label: 'The Word',\n        value: 'song6'\n      },\n      {\n        label: 'Michelle',\n        value: 'song7',\n        disabled: true\n      },\n      {\n        label: 'What goes on',\n        value: 'song8'\n      },\n      {\n        label: 'Girl',\n        value: 'song9'\n      },\n      {\n        label: 'I\\'m looking through you',\n        value: 'song10'\n      },\n      {\n        label: 'In My Life',\n        value: 'song11'\n      },\n      {\n        label: 'Wait',\n        value: 'song12'\n      }\n    ]\n  },\n  {\n    type: 'group',\n    label: 'Let It Be',\n    key: 'Let It Be Album',\n    children: [\n      {\n        label: 'Two Of Us',\n        value: 'Two Of Us'\n      },\n      {\n        label: 'Dig A Pony',\n        value: 'Dig A Pony'\n      },\n      {\n        label: 'Across The Universe',\n        value: 'Across The Universe'\n      },\n      {\n        label: 'I Me Mine',\n        value: 'I Me Mine'\n      },\n      {\n        label: 'Dig It',\n        value: 'Dig It'\n      },\n      {\n        label: 'Let It Be',\n        value: 'Let It Be'\n      },\n      {\n        label: 'Maggie Mae',\n        value: 'Maggie Mae'\n      },\n      {\n        label: 'I\\'ve Got A Feeling',\n        value: 'I\\'ve Got A Feeling'\n      },\n      {\n        label: 'One After 909',\n        value: 'One After 909'\n      },\n      {\n        label: 'The Long And Winding Road',\n        value: 'The Long And Winding Road'\n      },\n      {\n        label: 'For You Blue',\n        value: 'For You Blue'\n      },\n      {\n        label: 'Get Back',\n        value: 'Get Back'\n      }\n    ]\n  }\n]\n</script>\n\n<template>\n  <n-select v-model:value=\"value\" filterable :options=\"options\" />\n</template>\n"
  },
  {
    "path": "src/select/demos/enUS/index.demo-entry.md",
    "content": "# Select\n\nSelect something!\n\n## Demo\n\n```demo\nbasic.vue\nsize.vue\nmultiple.vue\nevents.vue\nfilterable.vue\ntag.vue\nmenu-width.vue\nremote.vue\nremote-multiple.vue\nclearable.vue\nscroll-event.vue\ngroup.vue\nmany-options.vue\ncustom-option.vue\ncustom-suffix.vue\naction.vue\nfallback-option.vue\nmax-tag-count.vue\nadd-tooltip.vue\nrender-tag.vue\nfocus.vue\nrender-person.vue\ntag-input.vue\ncustom-field.vue\n```\n\n## API\n\n### Select Props\n\n| Name | Type | Default | Description | Version |\n| --- | --- | --- | --- | --- |\n| consistent-menu-width | `boolean` | `true` | Whether the menu keeps its width the same as the select trigger element. Setting it to `false` will also disable `virtual-scroll`. |  |\n| children-field | `string` | `'children'` | Field name of group option children. | 2.29.1 |\n| clearable | `boolean` | `false` | Whether the value is clearable. |  |\n| clear-created-options-on-clear | `boolean` | `true` | When `tag` and `clearable` are enabled, whether to clear created options when clearing. | 2.44.0 |\n| clear-filter-after-select | `boolean` | `true` | When multiple and filter is true, whether to clear filter keyword after select an option. | 2.25.2 |\n| default-value | `Array<string \\| number> \\| string \\| number \\| null` | `null` | Default value. |  |\n| disabled | `boolean` | `false` | Whether to disable the select. |  |\n| ellipsis-tag-popover-props | `PopoverProps` | `undefined` | `popover` props of the preview ellipsis tag. | 2.37.0 |\n| fallback-option | `false \\| (value: string \\| number) => SelectOption` | `value => ({ label: '' + value, value })` | The option to be created using the value which has no corresponding option value. If set to `false`, the fallback option won't be created and displayed. |  |\n| filterable | `boolean` | `false` | Whether options can be filtered. |  |\n| filter | `(pattern: string, option: Object) => boolean` | String search method. | Filter function. |  |\n| ignore-composition | `boolean` | `true` | Ingore IME's composition status. By default `filter` won't be triggered by input event under compositions. | 2.33.4 |\n| input-props | `InputHTMLAttributes` | `undefined` | The attributes of input element in the trigger. It only works when the select is filterable. |  |\n| keyboard | `boolean` | `true` | Whether to allow keyboard control. | 2.34.4 |\n| label-field | `string` | `'label'` | Field name of option label. | 2.29.1 |\n| loading | `boolean` | `false` | Whether to show a loading state. |  |\n| max-tag-count | `number \\| 'responsive'` | `undefined` | Maximum selected values to display while in `multiple` mode. `responsive` will keep all the tags in single line. |  |\n| menu-props | `HTMLAttributes` | `undefined` | The menu's dom props. |  |\n| menu-size | `'tiny' \\| 'small' \\| 'medium' \\| 'large'` | `'medium'` | Size of select menu. | 2.40.0 |\n| multiple | `boolean` | `false` | Whether to allow selecting multiple values. |  |\n| node-props | `(option: SelectOption \\| SelectGroupOption) => object` | `undefined` | Option's DOM attrs generator. | 2.32.2 |\n| options | `Array<SelectOption \\| SelectGroupOption>` | `[]` | Options that can be selected. For more details see SelectOption Properties (below). |  |\n| placeholder | `string` | `'Please Select' (i18n)` | Placeholder. |  |\n| placement | `'top-start' \\| 'top' \\| 'top-end' \\| 'right-start' \\| 'right' \\| 'right-end' \\| 'bottom-start' \\| 'bottom' \\| 'bottom-end' \\| 'left-start' \\| 'left' \\| 'left-end'` | `'bottom-start'` | Option menu's placement. | 2.25.0 |\n| remote | `boolean` | `false` | Allows options to be fetched asynchronously. Note that if `remote` is set, `filter` & `tag` won't work on `options`. |  |\n| render-label | `(option: SelectOption \\| SelectGroupOption, selected: boolean) => VNodeChild` | `undefined` | Render function for each option label. |  |\n| render-option | `(info: { node: VNode, option: SelectOption \\| SelectGroupOption, selected: boolean }) => VNodeChild` | `undefined` | Render function for each option. |  |\n| render-tag | `(props: { option: SelectBaseOption, handleClose: () => void }) => VNodeChild` | `undefined` | Render function for each option tag. |  |\n| reset-menu-on-options-change | `boolean` | `true` | Whether to reset menu staus on options change, for example, scroll status. | 2.24.2 |\n| scrollbar-props | `ScrollbarProps` | `undefined` | See [Scrollbar props](scrollbar#Scrollbar-Props) | 2.44.0 |\n| show | `boolean` | `undefined` | Whether to show/open the option menu. |  |\n| show-arrow | `boolean` | `true` | Whether to show the dropdown arrow. |  |\n| show-checkmark | `boolean` | `true` | Whether to show checkmark. | 2.33.4 |\n| show-on-focus | `boolean` | `false` | Whether to show menu on focus. | 2.34.3 |\n| size | `'tiny' \\| 'small' \\| 'medium' \\| 'large'` | `'medium'` | Size of the select input. |  |\n| status | `'success' \\| 'warning' \\| 'error'` | `undefined` | Validation status. | 2.27.0 |\n| tag | `boolean` | `false` | Whether users can create new options. This should be used with `filterable`. |  |\n| to | `string \\| HTMLElement \\| false` | `body` | Container node of the menu. `false` will keep it not detached. |  |\n| value | `Array<string \\| number> \\| string \\| number \\| null` | `undefined` | Value when being manually set. |  |\n| value-field | `string` | `'value'` | Field name of option value. | 2.29.1 |\n| virtual-scroll | `boolean` | `true` | Whether to enable virtual scrolling. |  |\n| on-blur | `() => void` | `undefined` | Callback triggered when the selection element is blurred. |  |\n| on-clear | `() => void` | `undefined` | Callback triggered when the selection element is cleared. |  |\n| on-create | `(label: string) => SelectOption` | `label => ({ label, value: label })` | How to create an option when you type in a custom option. Note that `filter` will be applied to the created option too. And you'd better make sure that the value of the created option is not the same as any other option. Should be used with `tag` prop. |  |\n| on-focus | `() => void` | `undefined` | Callback triggered when the selection element is focussed on. |  |\n| on-scroll | `(e: ScrollEvent) => void` | `undefined` | Callback triggered when the options menu is scrolled. |  |\n| on-search | `(value: string) => void` | `undefined` | Callback triggered when a search is conducted. |  |\n| on-update:show | `(show: boolean) => void` | `undefined` | Callback on menu open status change. | 2.24.2 |\n| on-update:value | `(value: Array \\| string \\| number \\| null, option: SelectBaseOption \\| null \\| SelectBaseOption[]) => void` | `undefined` | Callback triggered when the selected value is updated. |  |\n\n#### SelectOption Properties\n\n| Name | Type | Description |\n| --- | --- | --- |\n| class | `string` | Customize the option's class. |\n| disabled | `boolean` | Whether to disable the option. |\n| label | `string \\| ((option: SelectOption, selected: boolean) => VNodeChild)` | Label of the option. Note that if you are using the `render` function, the default filter will filter the option. |\n| render | `(info: { node: VNode, option: SelectOption, selected: boolean }) => VNodeChild` | Render the entire option. |\n| style | `string \\| CSSProperties` | Customize the option's style. |\n| value | `string \\| number` | Should be unique for each option. |\n\n#### SelectGroupOption Properties\n\n| Name | Type | Description |\n| --- | --- | --- |\n| children | `Array<SelectOption>` | Child select options. |\n| label | `string \\| ((option: SelectGroupOption) => VNodeChild)` | Label of the group. |\n| key | `string \\| number` | Should be unique for each option. |\n| render | `(info: { node: VNode, option: SelectOption, selected: boolean }) => VNodeChild` | Render the entire option. |\n| type | `'group'` | Type of the group option. |\n\n### Select Slots\n\n| Name   | Parameters | Description                            | Version |\n| ------ | ---------- | -------------------------------------- | ------- |\n| header | `()`       | Header menu slot.                      | 2.37.0  |\n| action | `()`       | Options menu slot.                     |         |\n| empty  | `()`       | Empty state slot for the options menu. |         |\n| arrow  | `()`       | Arrow icon slot.                       | 2.24.2  |\n\n### Select Methods\n\n| Name       | Type         | Description  | Version |\n| ---------- | ------------ | ------------ | ------- |\n| focus      | `() => void` | Focus.       | 2.24.2  |\n| focusInput | `() => void` | Input focus. | 2.35.0  |\n| blur       | `() => void` | Blur.        | 2.24.2  |\n| blurInput  | `() => void` | Input blur.  | 2.35.0  |\n"
  },
  {
    "path": "src/select/demos/enUS/many-options.demo.vue",
    "content": "<markdown>\n# Lots of options\n\n1000 times the answer to everything.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { repeat } from 'seemly'\nimport { ref } from 'vue'\n\nconst value = ref(null)\nconst values = ref(null)\nconst options = repeat(42000, undefined).map((_, i) => ({\n  label: String(i),\n  value: i\n}))\n</script>\n\n<template>\n  <n-space vertical>\n    <n-select v-model:value=\"value\" :options=\"options\" />\n    <n-select v-model:value=\"values\" multiple :options=\"options\" />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/select/demos/enUS/max-tag-count.demo.vue",
    "content": "<markdown>\n# Max tag count\n\nMaximum selected options to display. This can be a fixed number or the string `responsive` to set a responsive max count.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst value = ref(null)\nconst options = [\n  {\n    label: 'Everybody\\'s Got Something to Hide Except Me and My Monkey',\n    value: 'song0',\n    disabled: true\n  },\n  {\n    label: 'Drive My Car',\n    value: 'song1'\n  },\n  {\n    label: 'Norwegian Wood',\n    value: 'song2'\n  },\n  {\n    label: 'You Won\\'t See',\n    value: 'song3',\n    disabled: true\n  },\n  {\n    label: 'Nowhere Man',\n    value: 'song4'\n  },\n  {\n    label: 'Think For Yourself',\n    value: 'song5'\n  },\n  {\n    label: 'The Word',\n    value: 'song6'\n  },\n  {\n    label: 'Michelle',\n    value: 'song7',\n    disabled: true\n  },\n  {\n    label: 'What goes on',\n    value: 'song8'\n  },\n  {\n    label: 'Girl',\n    value: 'song9'\n  },\n  {\n    label: 'I\\'m looking through you',\n    value: 'song10'\n  },\n  {\n    label: 'In My Life',\n    value: 'song11'\n  },\n  {\n    label: 'Wait',\n    value: 'song12'\n  }\n]\n</script>\n\n<template>\n  <n-space vertical>\n    <n-select\n      v-model:value=\"value\"\n      placeholder=\"maxTagCount = responsive\"\n      multiple\n      :options=\"options\"\n      max-tag-count=\"responsive\"\n    />\n    <n-select\n      v-model:value=\"value\"\n      placeholder=\"maxTagCount = 3\"\n      multiple\n      :options=\"options\"\n      :max-tag-count=\"3\"\n    />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/select/demos/enUS/menu-width.demo.vue",
    "content": "<markdown>\n# Menu width\n\nThe options menu width can be made to fit its content. Using this disables virtual scrolling.\n</markdown>\n\n<script lang=\"ts\" setup>\nconst options = [\n  {\n    label: 'Everybody\\'s Got Something to Hide Except Me and My Monkey',\n    value: 'song0',\n    disabled: true\n  },\n  {\n    label: 'Drive My Car',\n    value: 'song1'\n  },\n  {\n    label: 'Norwegian Wood',\n    value: 'song2'\n  },\n  {\n    label: 'You Won\\'t See',\n    value: 'song3',\n    disabled: true\n  },\n  {\n    label: 'Nowhere Man',\n    value: 'song4'\n  },\n  {\n    label: 'Think For Yourself',\n    value: 'song5'\n  },\n  {\n    label: 'The Word',\n    value: 'song6'\n  },\n  {\n    label: 'Michelle',\n    value: 'song7',\n    disabled: true\n  },\n  {\n    label: 'What goes on',\n    value: 'song8'\n  },\n  {\n    label: 'Girl',\n    value: 'song9'\n  },\n  {\n    label: 'I\\'m looking through you',\n    value: 'song10'\n  },\n  {\n    label: 'In My Life',\n    value: 'song11'\n  },\n  {\n    label: 'Wait',\n    value: 'song12'\n  }\n]\n</script>\n\n<template>\n  <n-space vertical>\n    <n-select :options=\"options\" :consistent-menu-width=\"false\" />\n    <n-select multiple :options=\"options\" :consistent-menu-width=\"false\" />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/select/demos/enUS/multiple.demo.vue",
    "content": "<markdown>\n# Multiple select\n\nAllow the selection of multiple values.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst value = ref(['song3'])\nconst options = [\n  {\n    label: 'Everybody\\'s Got Something to Hide Except Me and My Monkey',\n    value: 'song0',\n    disabled: true\n  },\n  {\n    label: 'Drive My Car',\n    value: 'song1'\n  },\n  {\n    label: 'Norwegian Wood',\n    value: 'song2'\n  },\n  {\n    label: 'You Won\\'t See',\n    value: 'song3',\n    disabled: true\n  },\n  {\n    label: 'Nowhere Man',\n    value: 'song4'\n  },\n  {\n    label: 'Think For Yourself',\n    value: 'song5'\n  },\n  {\n    label: 'The Word',\n    value: 'song6'\n  },\n  {\n    label: 'Michelle',\n    value: 'song7',\n    disabled: true\n  },\n  {\n    label: 'What goes on',\n    value: 'song8'\n  },\n  {\n    label: 'Girl',\n    value: 'song9'\n  },\n  {\n    label: 'I\\'m looking through you',\n    value: 'song10'\n  },\n  {\n    label: 'In My Life',\n    value: 'song11'\n  },\n  {\n    label: 'Wait',\n    value: 'song12'\n  }\n]\n</script>\n\n<template>\n  <n-space vertical>\n    <n-select v-model:value=\"value\" multiple :options=\"options\" />\n    <n-select v-model:value=\"value\" multiple disabled :options=\"options\" />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/select/demos/enUS/remote-multiple.demo.vue",
    "content": "<markdown>\n# Remote (multiple)\n\nAsynchronous options example for a multiple select case.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { SelectOption } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst optionsData = [\n  {\n    label: 'Drive My Car',\n    value: 'song1'\n  },\n  {\n    label: 'Norwegian Wood',\n    value: 'song2'\n  },\n  {\n    label: 'You Won\\'t See',\n    value: 'song3'\n  },\n  {\n    label: 'Nowhere Man',\n    value: 'song4'\n  },\n  {\n    label: 'Think For Yourself',\n    value: 'song5'\n  },\n  {\n    label: 'The Word',\n    value: 'song6'\n  },\n  {\n    label: 'Michelle',\n    value: 'song7'\n  },\n  {\n    label: 'What goes on',\n    value: 'song8'\n  },\n  {\n    label: 'Girl',\n    value: 'song9'\n  },\n  {\n    label: 'I\\'m looking through you',\n    value: 'song10'\n  },\n  {\n    label: 'In My Life',\n    value: 'song11'\n  },\n  {\n    label: 'Wait',\n    value: 'song12'\n  }\n]\n\nconst selectedValues = ref(null)\nconst loadingRef = ref(false)\nconst optionsRef = ref<SelectOption[]>([])\n\nfunction handleSearch(query: string) {\n  if (!query.length) {\n    optionsRef.value = []\n    return\n  }\n  loadingRef.value = true\n  window.setTimeout(() => {\n    optionsRef.value = optionsData.filter(item => ~item.label.indexOf(query))\n    loadingRef.value = false\n  }, 1000)\n}\n</script>\n\n<template>\n  <n-select\n    v-model:value=\"selectedValues\"\n    multiple\n    filterable\n    placeholder=\"Search Songs\"\n    :options=\"optionsRef\"\n    :loading=\"loadingRef\"\n    clearable\n    remote\n    :clear-filter-after-select=\"false\"\n    @search=\"handleSearch\"\n  />\n</template>\n"
  },
  {
    "path": "src/select/demos/enUS/remote.demo.vue",
    "content": "<markdown>\n# Remote (single)\n\nAsynchronous example for a single select case.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { SelectOption } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst optionsData = [\n  {\n    label: 'Drive My Car',\n    value: 'song1'\n  },\n  {\n    label: 'Norwegian Wood',\n    value: 'song2'\n  },\n  {\n    label: 'You Won\\'t See',\n    value: 'song3'\n  },\n  {\n    label: 'Nowhere Man',\n    value: 'song4'\n  },\n  {\n    label: 'Think For Yourself',\n    value: 'song5'\n  },\n  {\n    label: 'The Word',\n    value: 'song6'\n  },\n  {\n    label: 'Michelle',\n    value: 'song7'\n  },\n  {\n    label: 'What goes on',\n    value: 'song8'\n  },\n  {\n    label: 'Girl',\n    value: 'song9'\n  },\n  {\n    label: 'I\\'m looking through you',\n    value: 'song10'\n  },\n  {\n    label: 'In My Life',\n    value: 'song11'\n  },\n  {\n    label: 'Wait',\n    value: 'song12'\n  }\n]\n\nconst value = ref(null)\nconst loadingRef = ref(false)\nconst optionsRef = ref<SelectOption[]>([])\n\nfunction handleSearch(query: string) {\n  if (!query.length) {\n    optionsRef.value = []\n    return\n  }\n  loadingRef.value = true\n  window.setTimeout(() => {\n    optionsRef.value = optionsData.filter(item => ~item.label.indexOf(query))\n    loadingRef.value = false\n  }, 1000)\n}\n</script>\n\n<template>\n  <n-select\n    v-model:value=\"value\"\n    filterable\n    placeholder=\"Search Songs\"\n    :options=\"optionsRef\"\n    :loading=\"loadingRef\"\n    clearable\n    remote\n    @search=\"handleSearch\"\n  />\n</template>\n"
  },
  {
    "path": "src/select/demos/enUS/render-person.demo.vue",
    "content": "<markdown>\n# Select person\n\nI've found that people often want to make a people picker. Here is an example that shows you how that can be done with a select.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { SelectRenderLabel, SelectRenderTag } from 'naive-ui'\nimport { NAvatar, NTag, NText } from 'naive-ui'\nimport { h } from 'vue'\n\nconst renderMultipleSelectTag: SelectRenderTag = ({ option, handleClose }) => {\n  return h(\n    NTag,\n    {\n      style: {\n        padding: '0 6px 0 4px'\n      },\n      round: true,\n      closable: true,\n      onClose: (e) => {\n        e.stopPropagation()\n        handleClose()\n      }\n    },\n    {\n      default: () =>\n        h(\n          'div',\n          {\n            style: {\n              display: 'flex',\n              alignItems: 'center'\n            }\n          },\n          [\n            h(NAvatar, {\n              src: 'https://07akioni.oss-cn-beijing.aliyuncs.com/07akioni.jpeg',\n              round: true,\n              size: 22,\n              style: {\n                marginRight: '4px'\n              }\n            }),\n            option.label as string\n          ]\n        )\n    }\n  )\n}\n\nconst renderSingleSelectTag: SelectRenderTag = ({ option }) => {\n  return h(\n    'div',\n    {\n      style: {\n        display: 'flex',\n        alignItems: 'center'\n      }\n    },\n    [\n      h(NAvatar, {\n        src: 'https://07akioni.oss-cn-beijing.aliyuncs.com/07akioni.jpeg',\n        round: true,\n        size: 24,\n        style: {\n          marginRight: '12px'\n        }\n      }),\n      option.label as string\n    ]\n  )\n}\n\nconst renderLabel: SelectRenderLabel = (option) => {\n  return h(\n    'div',\n    {\n      style: {\n        display: 'flex',\n        alignItems: 'center'\n      }\n    },\n    [\n      h(NAvatar, {\n        src: 'https://07akioni.oss-cn-beijing.aliyuncs.com/07akioni.jpeg',\n        round: true,\n        size: 'small'\n      }),\n      h(\n        'div',\n        {\n          style: {\n            marginLeft: '12px',\n            padding: '4px 0'\n          }\n        },\n        [\n          h('div', null, [option.label as string]),\n          h(\n            NText,\n            { depth: 3, tag: 'div' },\n            {\n              default: () => 'description'\n            }\n          )\n        ]\n      )\n    ]\n  )\n}\n\nconst options = [\n  {\n    label: '07akioni',\n    value: '07akioni'\n  },\n  {\n    label: '08akioni',\n    value: '08akioni'\n  },\n  {\n    label: '09akioni',\n    value: '09akioni'\n  }\n]\n</script>\n\n<template>\n  <n-space vertical>\n    <n-select\n      :options=\"options\"\n      :render-label=\"renderLabel\"\n      :render-tag=\"renderSingleSelectTag\"\n    />\n    <n-select\n      :options=\"options\"\n      :render-label=\"renderLabel\"\n      :render-tag=\"renderSingleSelectTag\"\n      filterable\n    />\n    <n-select\n      multiple\n      :options=\"options\"\n      :render-label=\"renderLabel\"\n      :render-tag=\"renderMultipleSelectTag\"\n    />\n    <n-select\n      multiple\n      :options=\"options\"\n      :render-label=\"renderLabel\"\n      :render-tag=\"renderMultipleSelectTag\"\n      filterable\n    />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/select/demos/enUS/render-tag.demo.vue",
    "content": "<markdown>\n# Customize tag rendering\n\nGive the tag a little color.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { SelectRenderTag } from 'naive-ui'\nimport { NTag } from 'naive-ui'\nimport { h, ref } from 'vue'\n\nconst value = ref([])\nconst options = [\n  {\n    label: 'Daze today',\n    value: 'value1',\n    type: 'success'\n  },\n  {\n    label: 'Work is not finished',\n    value: 'value2',\n    type: 'warning'\n  },\n  {\n    label: 'Work overtime in the evening',\n    value: 'value3',\n    type: 'error'\n  }\n]\n\nconst renderTag: SelectRenderTag = ({ option, handleClose }) => {\n  return h(\n    NTag,\n    {\n      type: option.type as 'success' | 'warning' | 'error',\n      closable: true,\n      onMousedown: (e: FocusEvent) => {\n        e.preventDefault()\n      },\n      onClose: (e: MouseEvent) => {\n        e.stopPropagation()\n        handleClose()\n      }\n    },\n    { default: () => option.label }\n  )\n}\n</script>\n\n<template>\n  <n-select\n    v-model:value=\"value\"\n    multiple\n    :render-tag=\"renderTag\"\n    :options=\"options\"\n  />\n</template>\n"
  },
  {
    "path": "src/select/demos/enUS/scroll-event.demo.vue",
    "content": "<markdown>\n# Scroll event\n\nA colleague of mine wanted to use a scroll event for loading options asynchronously. Here's that example.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst optionsRef = ref([\n  {\n    label: 'Drive My Car',\n    value: 'song1'\n  },\n  {\n    label: 'Norwegian Wood',\n    value: 'song2'\n  },\n  {\n    label: 'You Won\\'t See',\n    value: 'song3'\n  },\n  {\n    label: 'Nowhere Man',\n    value: 'song4'\n  },\n  {\n    label: 'Think For Yourseld',\n    value: 'song5'\n  },\n  {\n    label: 'The Word',\n    value: 'song6'\n  },\n  {\n    label: 'Michelle',\n    value: 'song7'\n  },\n  {\n    label: 'What goes on',\n    value: 'song8'\n  },\n  {\n    label: 'Girl',\n    value: 'song9'\n  },\n  {\n    label: 'I\\'m looking through you',\n    value: 'song10'\n  },\n  {\n    label: 'In My Life',\n    value: 'song11'\n  },\n  {\n    label: 'Wait',\n    value: 'song12'\n  }\n])\n\nfunction handleScroll(e: Event) {\n  const currentTarget = e.currentTarget as HTMLElement\n  if (\n    currentTarget.scrollTop + currentTarget.offsetHeight\n    >= currentTarget.scrollHeight\n  ) {\n    optionsRef.value.push(\n      {\n        label: `v1-${optionsRef.value.length}`,\n        value: `v1-${optionsRef.value.length}`\n      },\n      {\n        label: `v2-${optionsRef.value.length}`,\n        value: `v2-${optionsRef.value.length}`\n      }\n    )\n  }\n}\n</script>\n\n<template>\n  <n-select\n    :options=\"optionsRef\"\n    :reset-menu-on-options-change=\"false\"\n    @scroll=\"handleScroll\"\n  />\n</template>\n"
  },
  {
    "path": "src/select/demos/enUS/size.demo.vue",
    "content": "<markdown>\n# Size\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst value = ref(null)\nconst options = [\n  {\n    label: 'Everybody\\'s Got Something to Hide Except Me and My Monkey',\n    value: 'song0',\n    disabled: true\n  },\n  {\n    label: 'Drive My Car',\n    value: 'song1'\n  },\n  {\n    label: 'Norwegian Wood',\n    value: 'song2'\n  },\n  {\n    label: 'You Won\\'t See',\n    value: 'song3',\n    disabled: true\n  },\n  {\n    label: 'Nowhere Man',\n    value: 'song4'\n  },\n  {\n    label: 'Think For Yourself',\n    value: 'song5'\n  },\n  {\n    label: 'The Word',\n    value: 'song6'\n  },\n  {\n    label: 'Michelle',\n    value: 'song7',\n    disabled: true\n  },\n  {\n    label: 'What goes on',\n    value: 'song8'\n  },\n  {\n    label: 'Girl',\n    value: 'song9'\n  },\n  {\n    label: 'I\\'m looking through you',\n    value: 'song10'\n  },\n  {\n    label: 'In My Life',\n    value: 'song11'\n  },\n  {\n    label: 'Wait',\n    value: 'song12'\n  }\n]\n</script>\n\n<template>\n  <n-space vertical>\n    <n-select v-model:value=\"value\" size=\"tiny\" :options=\"options\" />\n    <n-select v-model:value=\"value\" size=\"small\" :options=\"options\" />\n    <n-select v-model:value=\"value\" size=\"medium\" :options=\"options\" />\n    <n-select v-model:value=\"value\" size=\"large\" :options=\"options\" />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/select/demos/enUS/status.demo.vue",
    "content": "<markdown>\n# Validation status\n\nValidation status can be applied outside form.\n</markdown>\n\n<template>\n  <n-space vertical>\n    <n-select status=\"warning\" placeholder=\"\" />\n    <n-select status=\"error\" placeholder=\"\" />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/select/demos/enUS/tag-input.demo.vue",
    "content": "<markdown>\n# Use as tag input box\n\nUse `tag` and `:show=\"false\"` to use select as a tag input box.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst multipleSelectValue = ref(null)\n</script>\n\n<template>\n  <n-select\n    v-model:value=\"multipleSelectValue\"\n    filterable\n    multiple\n    tag\n    placeholder=\"Input, press enter to create tag\"\n    :show-arrow=\"false\"\n    :show=\"false\"\n  />\n</template>\n"
  },
  {
    "path": "src/select/demos/enUS/tag.demo.vue",
    "content": "<markdown>\n# Create option dynamically\n\nUse `tag` & `filterable` properties to create options dynamically.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst multipleSelectValue = ref(null)\nconst selectValue = ref(null)\nconst options = [\n  {\n    label: 'Everybody\\'s Got Something to Hide Except Me and My Monkey',\n    value: 'song0',\n    disabled: true\n  },\n  {\n    label: 'Drive My Car',\n    value: 'song1'\n  },\n  {\n    label: 'Norwegian Wood',\n    value: 'song2'\n  },\n  {\n    label: 'You Won\\'t See',\n    value: 'song3',\n    disabled: true\n  },\n  {\n    label: 'Nowhere Man',\n    value: 'song4'\n  },\n  {\n    label: 'Think For Yourself',\n    value: 'song5'\n  },\n  {\n    label: 'The Word',\n    value: 'song6'\n  },\n  {\n    label: 'Michelle',\n    value: 'song7',\n    disabled: true\n  },\n  {\n    label: 'What goes on',\n    value: 'song8'\n  },\n  {\n    label: 'Girl',\n    value: 'song9'\n  },\n  {\n    label: 'I\\'m looking through you',\n    value: 'song10'\n  },\n  {\n    label: 'In My Life',\n    value: 'song11'\n  },\n  {\n    label: 'Wait',\n    value: 'song12'\n  }\n]\n</script>\n\n<template>\n  <n-space vertical>\n    <n-select\n      v-model:value=\"multipleSelectValue\"\n      filterable\n      multiple\n      tag\n      :options=\"options\"\n    />\n    <n-select v-model:value=\"selectValue\" filterable tag :options=\"options\" />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/select/demos/zhCN/action.demo.vue",
    "content": "<markdown>\n# 操作插槽\n\n有人要在选择菜单里用这个插槽吗？\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst value = ref(null)\nconst options = [\n  {\n    label: 'Everybody\\'s Got Something to Hide Except Me and My Monkey',\n    value: 'song0',\n    disabled: true\n  },\n  {\n    label: 'Drive My Car',\n    value: 'song1'\n  },\n  {\n    label: 'Norwegian Wood',\n    value: 'song2'\n  },\n  {\n    label: 'You Won\\'t See',\n    value: 'song3',\n    disabled: true\n  }\n]\n</script>\n\n<template>\n  <n-select v-model:value=\"value\" :options=\"options\">\n    <template #header>\n      不知道放些什么\n    </template>\n    <template #action>\n      如果你点开了这个例子，你可能需要它\n    </template>\n  </n-select>\n</template>\n"
  },
  {
    "path": "src/select/demos/zhCN/add-tooltip.demo.vue",
    "content": "<markdown>\n# 给选项增加 Tooltip\n\n`render-option` 可以让你控制整个选项的渲染。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { SelectOption } from 'naive-ui'\nimport type { VNode } from 'vue'\nimport { NTooltip } from 'naive-ui'\nimport { h, ref } from 'vue'\n\nfunction renderOption({ node, option }: { node: VNode, option: SelectOption }) {\n  return h(NTooltip, null, {\n    trigger: () => node,\n    default: () => `Rubber Soul -${option.label}`\n  })\n}\n\nconst options = ref([\n  {\n    label: 'Everybody\\'s Got Something to Hide Except Me and My Monkey',\n    value: 'song0',\n    disabled: true\n  },\n  {\n    label: 'Drive My Car',\n    value: 'song1'\n  },\n  {\n    label: 'Norwegian Wood',\n    value: 'song2'\n  },\n  {\n    label: 'You Won\\'t See',\n    value: 'song3',\n    disabled: true\n  },\n  {\n    label: 'Nowhere Man',\n    value: 'song4'\n  },\n  {\n    label: 'Think For Yourself',\n    value: 'song5'\n  },\n  {\n    label: 'The Word',\n    value: 'song6'\n  },\n  {\n    label: 'Michelle',\n    value: 'song7',\n    disabled: true\n  },\n  {\n    label: 'What goes on',\n    value: 'song8'\n  },\n  {\n    label: 'Girl',\n    value: 'song9'\n  },\n  {\n    label: 'I\\'m looking through you',\n    value: 'song10'\n  },\n  {\n    label: 'In My Life',\n    value: 'song11'\n  },\n  {\n    label: 'Wait',\n    value: 'song12'\n  }\n])\n</script>\n\n<template>\n  <n-select :options=\"options\" :render-option=\"renderOption\" />\n</template>\n"
  },
  {
    "path": "src/select/demos/zhCN/basic.demo.vue",
    "content": "<markdown>\n# 基础用法\n\n选择器的基础用法。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst value = ref(null)\nconst options = [\n  {\n    label: 'Everybody\\'s Got Something to Hide Except Me and My Monkey',\n    value: 'song0',\n    disabled: true\n  },\n  {\n    label: 'Drive My Car',\n    value: 'song1'\n  },\n  {\n    label: 'Norwegian Wood',\n    value: 'song2'\n  },\n  {\n    label: 'You Won\\'t See',\n    value: 'song3',\n    disabled: true\n  },\n  {\n    label: 'Nowhere Man',\n    value: 'song4'\n  },\n  {\n    label: 'Think For Yourself',\n    value: 'song5'\n  },\n  {\n    label: 'The Word',\n    value: 'song6'\n  },\n  {\n    label: 'Michelle',\n    value: 'song7',\n    disabled: true\n  },\n  {\n    label: 'What goes on',\n    value: 'song8'\n  },\n  {\n    label: 'Girl',\n    value: 'song9'\n  },\n  {\n    label: 'I\\'m looking through you',\n    value: 'song10'\n  },\n  {\n    label: 'In My Life',\n    value: 'song11'\n  },\n  {\n    label: 'Wait',\n    value: 'song12'\n  }\n]\n</script>\n\n<template>\n  <n-space vertical>\n    <n-select v-model:value=\"value\" :options=\"options\" />\n    <n-select v-model:value=\"value\" disabled :options=\"options\" />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/select/demos/zhCN/clearable.demo.vue",
    "content": "<markdown>\n# 可清空\n\n注意只有选了值才能清空值。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst selectedValue = ref(null)\nconst selectedArray = ref([])\nconst options = [\n  {\n    label: 'Drive My Car',\n    value: 'song1'\n  },\n  {\n    label: 'Norwegian Wood',\n    value: 'song2'\n  },\n  {\n    label: 'You Won\\'t See',\n    value: 'song3'\n  },\n  {\n    label: 'Nowhere Man',\n    value: 'song4'\n  },\n  {\n    label: 'Think For Yourself',\n    value: 'song5'\n  },\n  {\n    label: 'The Word',\n    value: 'song6'\n  },\n  {\n    label: 'Michelle',\n    value: 'song7'\n  },\n  {\n    label: 'What goes on',\n    value: 'song8'\n  },\n  {\n    label: 'Girl',\n    value: 'song9'\n  },\n  {\n    label: 'I\\'m looking through you',\n    value: 'song10'\n  },\n  {\n    label: 'In My Life',\n    value: 'song11'\n  },\n  {\n    label: 'Wait',\n    value: 'song12'\n  }\n]\n</script>\n\n<template>\n  <n-space vertical>\n    <n-select v-model:value=\"selectedValue\" :options=\"options\" clearable />\n    <n-select\n      v-model:value=\"selectedArray\"\n      multiple\n      :options=\"options\"\n      clearable\n    />\n    <n-select\n      v-model:value=\"selectedValue\"\n      :options=\"options\"\n      filterable\n      clearable\n    />\n    <n-select\n      v-model:value=\"selectedArray\"\n      multiple\n      :options=\"options\"\n      filterable\n      clearable\n    />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/select/demos/zhCN/create-debug.demo.vue",
    "content": "<markdown>\n# Create debug\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst multipleSelectValue = ref(null)\nconst selectValue = ref(null)\nconst options = [\n  {\n    label: 'Everybody\\'s Got Something to Hide Except Me and My Monkey',\n    value: 'song0',\n    disabled: true\n  },\n  {\n    label: 'Drive My Car',\n    value: 'song1'\n  },\n  {\n    label: 'Norwegian Wood',\n    value: 'song2'\n  },\n  {\n    label: 'You Won\\'t See',\n    value: 'song3',\n    disabled: true\n  },\n  {\n    label: 'Nowhere Man',\n    value: 'song4'\n  },\n  {\n    label: 'Think For Yourself',\n    value: 'song5'\n  },\n  {\n    label: 'The Word',\n    value: 'song6'\n  },\n  {\n    label: 'Michelle',\n    value: 'song7',\n    disabled: true\n  },\n  {\n    label: 'What goes on',\n    value: 'song8'\n  },\n  {\n    label: 'Girl',\n    value: 'song9'\n  },\n  {\n    label: 'I\\'m looking through you',\n    value: 'song10'\n  },\n  {\n    label: 'In My Life',\n    value: 'song11'\n  },\n  {\n    label: 'Wait',\n    value: 'song12'\n  }\n]\n</script>\n\n<template>\n  <n-space vertical>\n    <n-select\n      v-model:value=\"multipleSelectValue\"\n      filterable\n      multiple\n      tag\n      :options=\"options\"\n    />\n    <n-select v-model:value=\"selectValue\" filterable tag :options=\"options\" />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/select/demos/zhCN/custom-field.demo.vue",
    "content": "<markdown>\n# 自定义字段\n\n后端会传来各种各样的数据。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { SelectGroupOption, SelectOption } from 'naive-ui'\n\nconst options: Array<SelectGroupOption | SelectOption> = [\n  {\n    type: 'group',\n    whateverLabel: 'Rubber Soul',\n    key: 'Rubber Soul',\n    whateverChildren: [\n      {\n        whateverLabel:\n          'Everybody\\'s Got Something to Hide Except Me and My Monkey',\n        whateverValue: 'song0',\n        disabled: true\n      },\n      {\n        whateverLabel: 'Drive My Car',\n        whateverValue: 'song1'\n      },\n      {\n        whateverLabel: 'Norwegian Wood',\n        whateverValue: 'song2'\n      },\n      {\n        whateverLabel: 'You Won\\'t See',\n        whateverValue: 'song3',\n        disabled: true\n      },\n      {\n        whateverLabel: 'Nowhere Man',\n        whateverValue: 'song4'\n      },\n      {\n        whateverLabel: 'Think For Yourself',\n        whateverValue: 'song5'\n      },\n      {\n        whateverLabel: 'The Word',\n        whateverValue: 'song6'\n      },\n      {\n        whateverLabel: 'Michelle',\n        whateverValue: 'song7',\n        disabled: true\n      },\n      {\n        whateverLabel: 'What goes on',\n        whateverValue: 'song8'\n      },\n      {\n        whateverLabel: 'Girl',\n        whateverValue: 'song9'\n      },\n      {\n        whateverLabel: 'I\\'m looking through you',\n        whateverValue: 'song10'\n      },\n      {\n        whateverLabel: 'In My Life',\n        whateverValue: 'song11'\n      },\n      {\n        whateverLabel: 'Wait',\n        whateverValue: 'song12'\n      }\n    ]\n  },\n  {\n    type: 'group',\n    whateverLabel: 'Let It Be',\n    key: 'Let It Be Album',\n    whateverChildren: [\n      {\n        whateverLabel: 'Two Of Us',\n        whateverValue: 'Two Of Us'\n      },\n      {\n        whateverLabel: 'Dig A Pony',\n        whateverValue: 'Dig A Pony'\n      },\n      {\n        whateverLabel: 'Across The Universe',\n        whateverValue: 'Across The Universe'\n      },\n      {\n        whateverLabel: 'I Me Mine',\n        whateverValue: 'I Me Mine'\n      },\n      {\n        whateverLabel: 'Dig It',\n        whateverValue: 'Dig It'\n      },\n      {\n        whateverLabel: 'Let It Be',\n        whateverValue: 'Let It Be'\n      },\n      {\n        whateverLabel: 'Maggie Mae',\n        whateverValue: 'Maggie Mae'\n      },\n      {\n        whateverLabel: 'I\\'ve Got A Feeling',\n        whateverValue: 'I\\'ve Got A Feeling'\n      },\n      {\n        whateverLabel: 'One After 909',\n        whateverValue: 'One After 909'\n      },\n      {\n        whateverLabel: 'The Long And Winding Road',\n        whateverValue: 'The Long And Winding Road'\n      },\n      {\n        whateverLabel: 'For You Blue',\n        whateverValue: 'For You Blue'\n      },\n      {\n        whateverLabel: 'Get Back',\n        whateverValue: 'Get Back'\n      }\n    ]\n  }\n]\n</script>\n\n<template>\n  <n-space vertical>\n    <n-select\n      label-field=\"whateverLabel\"\n      value-field=\"whateverValue\"\n      children-field=\"whateverChildren\"\n      filterable\n      :options=\"options\"\n    />\n    <n-select\n      label-field=\"whateverLabel\"\n      value-field=\"whateverValue\"\n      children-field=\"whateverChildren\"\n      filterable\n      multiple\n      :options=\"options\"\n    />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/select/demos/zhCN/custom-option.demo.vue",
    "content": "<markdown>\n# 自定义选项渲染\n\n经过了很久的思考，我决定放弃支持 slot API。当然，还是提供自定义渲染选项的方式。(例子中使用了 `render-label` 属性，但是你可以直接使用 `option` 的 `style` 或 `class` 选项)\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { SelectGroupOption, SelectOption } from 'naive-ui'\nimport type { VNodeChild } from 'vue'\nimport { MdMusicalNote as MusicIcon } from '@vicons/ionicons4'\nimport { NIcon } from 'naive-ui'\nimport { h } from 'vue'\n\nconst options: Array<SelectOption | SelectGroupOption> = [\n  {\n    type: 'group',\n    label: 'Rubber Soul',\n    key: 'Rubber Soul Album',\n    children: [\n      {\n        label: 'Everybody\\'s Got Something to Hide Except Me and My Monkey',\n        value: 'song0',\n        disabled: true\n      },\n      {\n        label: 'Drive My Car',\n        value: 'song1',\n        style: {\n          color: 'red'\n        }\n      },\n      {\n        label: 'Norwegian Wood',\n        value: 'song2'\n      },\n      {\n        label: 'You Won\\'t See',\n        value: 'song3',\n        disabled: true\n      },\n      {\n        label: 'Nowhere Man',\n        value: 'song4'\n      },\n      {\n        label: 'Think For Yourself',\n        value: 'song5'\n      },\n      {\n        label: 'The Word',\n        value: 'song6'\n      },\n      {\n        label: 'Michelle',\n        value: 'song7',\n        disabled: true\n      },\n      {\n        label: 'What goes on',\n        value: 'song8'\n      },\n      {\n        label: 'Girl',\n        value: 'song9'\n      },\n      {\n        label: 'I\\'m looking through you',\n        value: 'song10'\n      },\n      {\n        label: 'In My Life',\n        value: 'song11'\n      },\n      {\n        label: 'Wait',\n        value: 'song12'\n      }\n    ]\n  },\n  {\n    type: 'group',\n    label: 'Let It Be',\n    key: 'Let It Be Album',\n    children: [\n      {\n        label: 'Two Of Us',\n        value: 'Two Of Us'\n      },\n      {\n        label: 'Dig A Pony',\n        value: 'Dig A Pony'\n      },\n      {\n        label: 'Across The Universe',\n        value: 'Across The Universe'\n      },\n      {\n        label: 'I Me Mine',\n        value: 'I Me Mine'\n      },\n      {\n        label: 'Dig It',\n        value: 'Dig It'\n      },\n      {\n        label: 'Let It Be',\n        value: 'Let It Be'\n      },\n      {\n        label: 'Maggie Mae',\n        value: 'Maggie Mae'\n      },\n      {\n        label: 'I\\'ve Got A Feeling',\n        value: 'I\\'ve Got A Feeling'\n      },\n      {\n        label: 'One After 909',\n        value: 'One After 909'\n      },\n      {\n        label: 'The Long And Winding Road',\n        value: 'The Long And Winding Road'\n      },\n      {\n        label: 'For You Blue',\n        value: 'For You Blue'\n      },\n      {\n        label: 'Get Back',\n        value: 'Get Back'\n      }\n    ]\n  }\n]\n\nfunction renderLabel(option: SelectOption): VNodeChild {\n  if (option.type === 'group')\n    return `${option.label}(Cool!)`\n  return [\n    h(\n      NIcon,\n      {\n        style: {\n          verticalAlign: '-0.15em',\n          marginRight: '4px'\n        }\n      },\n      {\n        default: () => h(MusicIcon)\n      }\n    ),\n    option.label as string\n  ]\n}\n</script>\n\n<template>\n  <n-select :options=\"options\" :render-label=\"renderLabel\" />\n</template>\n"
  },
  {
    "path": "src/select/demos/zhCN/custom-suffix.demo.vue",
    "content": "<markdown>\n# 自定义箭头\n\n整点不一样的。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport Flash16Regular from '@vicons/fluent/Flash16Regular'\nimport FlashCheckmark16Regular from '@vicons/fluent/FlashCheckmark16Regular'\nimport { MdSearch } from '@vicons/ionicons4'\nimport { ref } from 'vue'\n\nconst show1 = ref(false)\nconst show2 = ref(false)\nconst options = [\n  {\n    label: 'Drive My Car',\n    value: 'song1'\n  },\n  {\n    label: 'Norwegian Wood',\n    value: 'song2'\n  },\n  {\n    label: 'You Won\\'t See',\n    value: 'song3'\n  },\n  {\n    label: 'Nowhere Man',\n    value: 'song4'\n  },\n  {\n    label: 'Think For Yourself',\n    value: 'song5'\n  },\n  {\n    label: 'The Word',\n    value: 'song6'\n  },\n  {\n    label: 'Michelle',\n    value: 'song7'\n  },\n  {\n    label: 'What goes on',\n    value: 'song8'\n  },\n  {\n    label: 'Girl',\n    value: 'song9'\n  },\n  {\n    label: 'I\\'m looking through you',\n    value: 'song10'\n  },\n  {\n    label: 'In My Life',\n    value: 'song11'\n  },\n  {\n    label: 'Wait',\n    value: 'song12'\n  }\n]\n</script>\n\n<template>\n  <n-space vertical>\n    <n-select v-model:show=\"show1\" placeholder=\"选择歌曲\" :options=\"options\">\n      <template #arrow>\n        <transition name=\"slide-left\">\n          <FlashCheckmark16Regular v-if=\"show1\" />\n          <Flash16Regular v-else />\n        </transition>\n      </template>\n    </n-select>\n    <n-select\n      v-model:show=\"show2\"\n      filterable\n      placeholder=\"选择歌曲\"\n      :options=\"options\"\n    >\n      <template v-if=\"show2\" #arrow>\n        <MdSearch />\n      </template>\n    </n-select>\n  </n-space>\n</template>\n\n<style>\n:deep(.slide-left-enter-active),\n:deep(.slide-left-leave-active) {\n  transition:\n    transform 0.3s ease,\n    opacity 0.3s ease;\n}\n\n:deep(.slide-left-enter-from),\n:deep(.slide-left-leave-to) {\n  position: absolute;\n  opacity: 0;\n}\n\n:deep(.slide-left-enter-from) {\n  transform: translateX(-10px);\n}\n\n:deep(.slide-left-leave-to) {\n  transform: translateX(10px);\n}\n</style>\n"
  },
  {
    "path": "src/select/demos/zhCN/empty-debug.demo.vue",
    "content": "<markdown>\n# Empty debug\n</markdown>\n\n<template>\n  <n-select>\n    <template #empty>\n      <n-input />\n    </template>\n  </n-select>\n</template>\n"
  },
  {
    "path": "src/select/demos/zhCN/events.demo.vue",
    "content": "<markdown>\n# UpdateValue 事件\n\n为什么 `update:value` 事件还是个例子？因为一开始的时候没什么可写的。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { SelectOption } from 'naive-ui'\nimport { useMessage } from 'naive-ui'\n\nconst message = useMessage()\n\nfunction handleUpdateValue(value: string, option: SelectOption) {\n  message.info(`value: ${JSON.stringify(value)}`)\n  message.info(`option: ${JSON.stringify(option)}`)\n}\n\nconst options = [\n  {\n    label: 'Drive My Car',\n    value: 'song1'\n  },\n  {\n    label: 'Norwegian Wood',\n    value: 'song2'\n  },\n  {\n    label: 'You Won\\'t See',\n    value: 'song3'\n  },\n  {\n    label: 'Nowhere Man',\n    value: 'song4'\n  },\n  {\n    label: 'Think For Yourself',\n    value: 'song5'\n  },\n  {\n    label: 'The Word',\n    value: 'song6'\n  },\n  {\n    label: 'Michelle',\n    value: 'song7'\n  },\n  {\n    label: 'What goes on',\n    value: 'song8'\n  },\n  {\n    label: 'Girl',\n    value: 'song9'\n  },\n  {\n    label: 'I\\'m looking through you',\n    value: 'song10'\n  },\n  {\n    label: 'In My Life',\n    value: 'song11'\n  },\n  {\n    label: 'Wait',\n    value: 'song12'\n  }\n]\n</script>\n\n<template>\n  <n-space vertical>\n    <n-select\n      placeholder=\"选择歌曲\"\n      :options=\"options\"\n      @update:value=\"handleUpdateValue\"\n    />\n    <n-select\n      multiple\n      placeholder=\"选择歌曲\"\n      :options=\"options\"\n      @update:value=\"handleUpdateValue\"\n    />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/select/demos/zhCN/fallback-option.demo.vue",
    "content": "<markdown>\n# 回退选项\n\n如果你不需要回退选项，将 `fallback-option` 设为 `false` 即可，这时只有出现在选项中的值才会被视为合法值，在操作的过程中不合法的值会被清除掉。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { SelectOption } from 'naive-ui'\nimport { ref } from 'vue'\n\nfunction trim(value: string): SelectOption {\n  return {\n    label: value.slice(0, 2),\n    value\n  }\n}\n\nconst singleValue = ref('一个不知哪里来的值')\nconst multipleValue = ref(['一个不知哪里来的值', '两个不知哪里来的值'])\nconst options = [\n  {\n    label: 'Everybody\\'s Got Something to Hide Except Me and My Monkey',\n    value: 'song0',\n    disabled: true\n  },\n  {\n    label: 'Drive My Car',\n    value: 'song1'\n  },\n  {\n    label: 'Norwegian Wood',\n    value: 'song2'\n  },\n  {\n    label: 'You Won\\'t See',\n    value: 'song3',\n    disabled: true\n  },\n  {\n    label: 'Nowhere Man',\n    value: 'song4'\n  },\n  {\n    label: 'Think For Yourself',\n    value: 'song5'\n  },\n  {\n    label: 'The Word',\n    value: 'song6'\n  },\n  {\n    label: 'Michelle',\n    value: 'song7',\n    disabled: true\n  },\n  {\n    label: 'What goes on',\n    value: 'song8'\n  },\n  {\n    label: 'Girl',\n    value: 'song9'\n  },\n  {\n    label: 'I\\'m looking through you',\n    value: 'song10'\n  },\n  {\n    label: 'In My Life',\n    value: 'song11'\n  },\n  {\n    label: 'Wait',\n    value: 'song12'\n  }\n]\n</script>\n\n<template>\n  <n-space vertical>\n    <n-select v-model:value=\"singleValue\" :options=\"options\" />\n    <n-select\n      v-model:value=\"multipleValue\"\n      multiple\n      :fallback-option=\"trim\"\n      :options=\"options\"\n    />\n    <n-select\n      v-model:value=\"singleValue\"\n      placeholder=\"无回退选项\"\n      :fallback-option=\"false\"\n      :options=\"options\"\n    />\n    <n-select\n      v-model:value=\"multipleValue\"\n      placeholder=\"无回退选项\"\n      multiple\n      :fallback-option=\"false\"\n      :options=\"options\"\n    />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/select/demos/zhCN/filterable-debug.demo.vue",
    "content": "<markdown>\n# Filterable debug\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { SelectFilter } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst selectedValue = ref('song1')\nconst selectedValues = ref(['song1'])\n\nconst filter: SelectFilter = (pattern, option) => {\n  console.log(pattern, option)\n  return pattern === '1'\n}\n\nconst options = [\n  {\n    label: 'Drive My Carfehjuwagheiuwhfiuawgheiawufhiuawghueiwahfaiuwgewiuafhw',\n    value: 'song1'\n  },\n  {\n    label: 'Norwegian Wood',\n    value: 'song2'\n  },\n  {\n    label: 'You Won\\'t See',\n    value: 'song3'\n  },\n  {\n    label: 'Nowhere Man',\n    value: 'song4'\n  },\n  {\n    label: 'Think For Yourself',\n    value: 'song5'\n  },\n  {\n    label: 'The Word',\n    value: 'song6'\n  },\n  {\n    label: 'Michelle',\n    value: 'song7'\n  },\n  {\n    label: 'What goes on',\n    value: 'song8'\n  },\n  {\n    label: 'Girl',\n    value: 'song9'\n  },\n  {\n    label: 'I\\'m looking through you',\n    value: 'song10'\n  },\n  {\n    label: 'In My Life',\n    value: 'song11'\n  },\n  {\n    label: 'Wait',\n    value: 'song12'\n  }\n]\n</script>\n\n<template>\n  <n-space vertical>\n    <n-select\n      v-model:value=\"selectedValue\"\n      style=\"width: 200px\"\n      filterable\n      placeholder=\"选择歌曲\"\n      :filter=\"filter\"\n      :consistent-menu-width=\"false\"\n      :options=\"options\"\n    />\n    <n-select\n      v-model:value=\"selectedValues\"\n      style=\"width: 200px\"\n      multiple\n      filterable\n      placeholder=\"选择歌曲\"\n      :filter=\"filter\"\n      :consistent-menu-width=\"false\"\n      :options=\"options\"\n    />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/select/demos/zhCN/filterable.demo.vue",
    "content": "<markdown>\n# 可过滤\n\n上吧！过滤器。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst selectedValue = ref(null)\nconst selectedValues = ref(null)\nconst options = [\n  {\n    label: 'Drive My Car',\n    value: 'song1'\n  },\n  {\n    label: 'Norwegian Wood',\n    value: 'song2'\n  },\n  {\n    label: 'You Won\\'t See',\n    value: 'song3'\n  },\n  {\n    label: 'Nowhere Man',\n    value: 'song4'\n  },\n  {\n    label: 'Think For Yourself',\n    value: 'song5'\n  },\n  {\n    label: 'The Word',\n    value: 'song6'\n  },\n  {\n    label: 'Michelle',\n    value: 'song7'\n  },\n  {\n    label: 'What goes on',\n    value: 'song8'\n  },\n  {\n    label: 'Girl',\n    value: 'song9'\n  },\n  {\n    label: 'I\\'m looking through you',\n    value: 'song10'\n  },\n  {\n    label: 'In My Life',\n    value: 'song11'\n  },\n  {\n    label: 'Wait',\n    value: 'song12'\n  }\n]\n</script>\n\n<template>\n  <n-space vertical>\n    <n-select\n      v-model:value=\"selectedValue\"\n      filterable\n      placeholder=\"选择歌曲\"\n      :options=\"options\"\n    />\n    <n-select\n      v-model:value=\"selectedValues\"\n      multiple\n      filterable\n      placeholder=\"选择歌曲\"\n      :options=\"options\"\n    />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/select/demos/zhCN/focus.demo.vue",
    "content": "<markdown>\n# 手动 focus & blur\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { SelectInst } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst selectInstRef = ref<SelectInst | null>(null)\n\nfunction handleClick() {\n  selectInstRef.value?.focus()\n  setTimeout(() => {\n    selectInstRef.value?.blur()\n  }, 1000)\n}\n</script>\n\n<template>\n  <n-space item-style=\"display: flex; align-item: center;\">\n    <n-button @click=\"handleClick\">\n      聚焦，一秒后失效\n    </n-button>\n    <n-select ref=\"selectInstRef\" style=\"width: 200px\" />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/select/demos/zhCN/fullscreen-debug.demo.vue",
    "content": "<markdown>\n# Fullscreen debug\n</markdown>\n\n<script lang=\"ts\" setup>\nfunction fullscreen() {\n  document.getElementById('fs')?.requestFullscreen()\n}\n</script>\n\n<template>\n  <div id=\"fs\" style=\"overflow: scroll; max-height: 300px\">\n    <div style=\"height: 200vh\">\n      <n-select />\n      <button @click=\"fullscreen\">\n        fullscreen\n      </button>\n    </div>\n  </div>\n</template>\n"
  },
  {
    "path": "src/select/demos/zhCN/group.demo.vue",
    "content": "<markdown>\n# 选项组\n\n把选项集合成组。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { SelectGroupOption, SelectOption } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst value = ref(null)\nconst options: Array<SelectOption | SelectGroupOption> = [\n  {\n    type: 'group',\n    label: 'Rubber Soul',\n    key: 'Rubber Soul',\n    children: [\n      {\n        label: 'Everybody\\'s Got Something to Hide Except Me and My Monkey',\n        value: 'song0',\n        disabled: true\n      },\n      {\n        label: 'Drive My Car',\n        value: 'song1'\n      },\n      {\n        label: 'Norwegian Wood',\n        value: 'song2'\n      },\n      {\n        label: 'You Won\\'t See',\n        value: 'song3',\n        disabled: true\n      },\n      {\n        label: 'Nowhere Man',\n        value: 'song4'\n      },\n      {\n        label: 'Think For Yourself',\n        value: 'song5'\n      },\n      {\n        label: 'The Word',\n        value: 'song6'\n      },\n      {\n        label: 'Michelle',\n        value: 'song7',\n        disabled: true\n      },\n      {\n        label: 'What goes on',\n        value: 'song8'\n      },\n      {\n        label: 'Girl',\n        value: 'song9'\n      },\n      {\n        label: 'I\\'m looking through you',\n        value: 'song10'\n      },\n      {\n        label: 'In My Life',\n        value: 'song11'\n      },\n      {\n        label: 'Wait',\n        value: 'song12'\n      }\n    ]\n  },\n  {\n    type: 'group',\n    label: 'Let It Be',\n    key: 'Let It Be Album',\n    children: [\n      {\n        label: 'Two Of Us',\n        value: 'Two Of Us'\n      },\n      {\n        label: 'Dig A Pony',\n        value: 'Dig A Pony'\n      },\n      {\n        label: 'Across The Universe',\n        value: 'Across The Universe'\n      },\n      {\n        label: 'I Me Mine',\n        value: 'I Me Mine'\n      },\n      {\n        label: 'Dig It',\n        value: 'Dig It'\n      },\n      {\n        label: 'Let It Be',\n        value: 'Let It Be'\n      },\n      {\n        label: 'Maggie Mae',\n        value: 'Maggie Mae'\n      },\n      {\n        label: 'I\\'ve Got A Feeling',\n        value: 'I\\'ve Got A Feeling'\n      },\n      {\n        label: 'One After 909',\n        value: 'One After 909'\n      },\n      {\n        label: 'The Long And Winding Road',\n        value: 'The Long And Winding Road'\n      },\n      {\n        label: 'For You Blue',\n        value: 'For You Blue'\n      },\n      {\n        label: 'Get Back',\n        value: 'Get Back'\n      }\n    ]\n  }\n]\n</script>\n\n<template>\n  <n-select v-model:value=\"value\" filterable :options=\"options\" />\n</template>\n"
  },
  {
    "path": "src/select/demos/zhCN/index.demo-entry.md",
    "content": "# 选择器 Select\n\n选点啥！\n\n## 演示\n\n```demo\nbasic.vue\nsize.vue\nmultiple.vue\nevents.vue\nfilterable.vue\ntag.vue\nmenu-width.vue\nremote.vue\nremote-multiple.vue\nclearable.vue\nscroll-event.vue\ngroup.vue\nmany-options.vue\ncustom-option.vue\ncustom-suffix.vue\naction.vue\nfallback-option.vue\nmax-tag-count.vue\nadd-tooltip.vue\nrender-tag.vue\nfocus.vue\nrender-person.vue\ntag-input.vue\nstatus.vue\nrtl-debug.vue\nplaceholder-debug.vue\nmenu-debug.vue\nrender-debug.vue\nspin-debug.vue\noptions-change-debug.vue\nfilterable-debug.vue\nempty-debug.vue\nfullscreen-debug.vue\ncustom-field.vue\ncreate-debug.vue\n```\n\n## API\n\n### Select Props\n\n| 名称 | 类型 | 默认值 | 说明 | 版本 |\n| --- | --- | --- | --- | --- |\n| consistent-menu-width | `boolean` | `true` | 菜单宽度是否和选择触发器一致，设为 `false` 会使 `virtual-scroll` 失效 |  |\n| children-field | `string` | `'children'` | 选项组 children 的字段名 | 2.29.1 |\n| clearable | `boolean` | `false` | 是否可清空 |  |\n| clear-created-options-on-clear | `boolean` | `true` | 在开启 `tag` 且可清空时，点击清空是否同时清空通过 tag 创建的选项 | 2.44.0 |\n| clear-filter-after-select | `boolean` | `true` | 是否在可过滤和多选的情况下选中一个选项后保留当前的搜索关键词 | 2.25.2 |\n| default-value | `Array<string \\| number> \\| string \\| number \\| null` | `null` | 非受控模式下的默认值 |  |\n| disabled | `boolean` | `false` | 是否禁用 |  |\n| ellipsis-tag-popover-props | `PopoverProps` | `undefined` | 选中选项过多省略显示时，预览弹出 `popover` 的属性 | 2.37.0 |\n| fallback-option | `false \\| (value: string \\| number) => SelectOption` | `value => ({ label: '' + value, value })` | 在传入的选项中没有对应当前值的选项时，这个值应该对应的选项。如果设为 `false`，不会为找不到对应选项的值生成回退选项也不会显示它，未在选项中的值会被视为不合法，操作过程中会被组件清除掉 |  |\n| filterable | `boolean` | `false` | 是否可以过滤 |  |\n| filter | `(pattern: string, option: object) => boolean` | 一个简单的字符串搜索算法 | 过滤器函数 |  |\n| ignore-composition | `boolean` | `true` | 忽略输入法 Composition 状态，默认情况下 `filter` 在输入法输入的过程中不会触发 | 2.33.4 |\n| input-props | `InputHTMLAttributes` | `undefined` | 触发器中 input 元素的属性，只在可过滤时有意义 |  |\n| keyboard | `boolean` | `true` | 是否支持键盘操作 | 2.34.4 |\n| label-field | `string` | `'label'` | 选项 label 的字段名 | 2.29.1 |\n| loading | `boolean` | `false` | 是否为加载状态 |  |\n| max-tag-count | `number \\| 'responsive'` | `undefined` | 多选标签的最大显示数量，`responsive` 会将所有标签保持在一行 |  |\n| menu-props | `HTMLAttributes` | `undefined` | 菜单的 DOM 属性 |  |\n| menu-size | `'tiny' \\| 'small' \\| 'medium' \\| 'large'` | `'medium'` | 菜单的尺寸 | 2.40.0 |\n| multiple | `boolean` | `false` | 是否为多选 |  |\n| node-props | `(option: SelectOption \\| SelectGroupOption) => object` | `undefined` | 选项的 DOM 属性生成函数 | 2.32.2 |\n| options | `Array<SelectOption \\| SelectGroupOption>` | `[]` | 配置选项内容，详情见 SelectOption Properties |  |\n| placeholder | `string` | `'请选择' (i18n)` | 提示信息 |  |\n| placement | `'top-start' \\| 'top' \\| 'top-end' \\| 'right-start' \\| 'right' \\| 'right-end' \\| 'bottom-start' \\| 'bottom' \\| 'bottom-end' \\| 'left-start' \\| 'left' \\| 'left-end'` | `'bottom-start'` | 菜单的弹出位置 | 2.25.0 |\n| remote | `boolean` | `false` | 是否要异步获取选项。注意如果设定了，那么 `filter` 和 `tag` 都不会对 `options` 生效。这个时候你在全权控制 `options` |  |\n| render-label | `(option: SelectOption \\| SelectGroupOption, selected: boolean) => VNodeChild` | `undefined` | 选项标签渲染函数 |  |\n| render-option | `(info: { node: VNode, option: SelectOption \\| SelectGroupOption, selected: boolean }) => VNodeChild` | `undefined` | 选项的渲染函数 |  |\n| render-tag | `(props: { option: SelectBaseOption, handleClose: () => void }) => VNodeChild` | `undefined` | 控制标签的渲染 |  |\n| reset-menu-on-options-change | `boolean` | `true` | 是否在选项变化时重置菜单状态，例如滚动状态 | 2.24.2 |\n| scrollbar-props | `ScrollbarProps` | `undefined` | 属性参考 [Scrollbar props](scrollbar#Scrollbar-Props) | 2.44.0 |\n| show | `boolean` | `undefined` | 是否展示菜单 |  |\n| show-arrow | `boolean` | `true` | 是否展示箭头 |  |\n| show-checkmark | `boolean` | `true` | 是否展示对勾 | 2.33.4 |\n| show-on-focus | `boolean` | `false` | 聚焦时是否展示菜单 | 2.34.3 |\n| size | `'tiny' \\| 'small' \\| 'medium' \\| 'large'` | `'medium'` | 组件尺寸 |  |\n| status | `'success' \\| 'warning' \\| 'error'` | `undefined` | 验证状态 | 2.27.0 |\n| tag | `boolean` | `false` | 是否可以创建新的选项，需要和 `filterable` 一起使用 |  |\n| to | `string \\| HTMLElement \\| false` | `body` | 菜单的容器节点，`false` 会待在原地 |  |\n| value | `Array<string \\| number> \\| string \\| number \\| null` | `undefined` | 受控模式下的值 |  |\n| value-field | `string` | `'value'` | 选项 value 的字段名 | 2.29.1 |\n| virtual-scroll | `boolean` | `true` | 是否启用虚拟滚动 |  |\n| on-blur | `() => void` | `undefined` | `blur` 时执行的回调 |  |\n| on-clear | `() => void` | `undefined` | `clear` 时执行的回调 |  |\n| on-create | `(label: string) => SelectOption` | `label => ({ label, value: label })` | 在输入内容时如何创建一个选项。注意 `filter` 对这个生成的选项同样会生效。同时确保这个选项和其他选项的 `value` 不要有重复，应该和 `tag` 属性一起被使用 |  |\n| on-focus | `() => void` | `undefined` | `focus` 时执行的回调 |  |\n| on-scroll | `(e: ScrollEvent) => void` | `undefined` | 滚动时执行的回调 |  |\n| on-search | `(value: string) => void` | `undefined` | 搜索时执行的回调 |  |\n| on-update:show | `(show: boolean) => void` | `undefined` | 菜单打开状态变化的回调 | 2.24.2 |\n| on-update:value | `(value: Array \\| string \\| number \\| null, option: SelectBaseOption \\| null \\| SelectBaseOption[]) => void` | `undefined` | 值更新时执行的回调 |  |\n\n#### SelectOption Properties\n\n| 名称 | 类型 | 说明 |\n| --- | --- | --- |\n| class | `string` | 自定义一个选项的类名 |\n| disabled | `boolean` | 是否禁用一个选项 |\n| label | `string \\| ((option: SelectOption, selected: boolean) => VNodeChild)` | 选项的标签，注意如果你使用了渲染函数，默认的过滤器将会过滤该选项 |\n| render | `(info: { node: VNode, option: SelectOption, selected: boolean }) => VNodeChild` | 渲染整个选项 |\n| style | `string \\| CSSProperties` | 自定义一个选项的样式 |\n| value | `string \\| number` | 在选项中应该是唯一的 |\n\n#### SelectGroupOption Properties\n\n| 名称 | 类型 | 说明 |\n| --- | --- | --- |\n| children | `Array<SelectOption>` | 子选项组 |\n| label | `string \\| ((option: SelectGroupOption) => VNodeChild)` | 选项组的标签 |\n| key | `string \\| number` | 在选项中应该是唯一的 |\n| render | `(info: { node: VNode, option: SelectOption, selected: boolean }) => VNodeChild` | 渲染整个选项 |\n| type | `'group'` | 选项组的类型 |\n\n### Select Slots\n\n| 名称   | 参数 | 说明                | 版本   |\n| ------ | ---- | ------------------- | ------ |\n| header | `()` | 菜单头部区域的 slot | 2.37.0 |\n| action | `()` | 菜单操作区域的 slot |        |\n| empty  | `()` | 菜单无数据时的 slot |        |\n| arrow  | `()` | 箭头的 slot         | 2.24.2 |\n\n### Select Methods\n\n| 名称       | 类型         | 说明     | 版本   |\n| ---------- | ------------ | -------- | ------ |\n| focus      | `() => void` | 聚焦     | 2.24.2 |\n| focusInput | `() => void` | 输入聚焦 | 2.35.0 |\n| blur       | `() => void` | 失焦     | 2.24.2 |\n| blurInput  | `() => void` | 输入失焦 | 2.35.0 |\n"
  },
  {
    "path": "src/select/demos/zhCN/many-options.demo.vue",
    "content": "<markdown>\n# 许多选项\n\n1000 倍宇宙的终极答案个数的选项。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { repeat } from 'seemly'\nimport { ref } from 'vue'\n\nconst value = ref(null)\nconst values = ref(null)\nconst options = repeat(42000, undefined).map((_, i) => ({\n  label: String(i),\n  value: i\n}))\n</script>\n\n<template>\n  <n-space vertical>\n    <n-select v-model:value=\"value\" :options=\"options\" />\n    <n-select v-model:value=\"values\" multiple :options=\"options\" />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/select/demos/zhCN/max-tag-count.demo.vue",
    "content": "<markdown>\n# 最大标签数量\n\n可以设定固定的数量，或者使用 `responsive` 设定响应式的最大标签数量。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst value = ref(null)\nconst options = [\n  {\n    label: 'Everybody\\'s Got Something to Hide Except Me and My Monkey',\n    value: 'song0',\n    disabled: true\n  },\n  {\n    label: 'Drive My Car',\n    value: 'song1'\n  },\n  {\n    label: 'Norwegian Wood',\n    value: 'song2'\n  },\n  {\n    label: 'You Won\\'t See',\n    value: 'song3',\n    disabled: true\n  },\n  {\n    label: 'Nowhere Man',\n    value: 'song4'\n  },\n  {\n    label: 'Think For Yourself',\n    value: 'song5'\n  },\n  {\n    label: 'The Word',\n    value: 'song6'\n  },\n  {\n    label: 'Michelle',\n    value: 'song7',\n    disabled: true\n  },\n  {\n    label: 'What goes on',\n    value: 'song8'\n  },\n  {\n    label: 'Girl',\n    value: 'song9'\n  },\n  {\n    label: 'I\\'m looking through you',\n    value: 'song10'\n  },\n  {\n    label: 'In My Life',\n    value: 'song11'\n  },\n  {\n    label: 'Wait',\n    value: 'song12'\n  }\n]\n</script>\n\n<template>\n  <n-space vertical>\n    <n-select\n      v-model:value=\"value\"\n      placeholder=\"maxTagCount = responsive\"\n      multiple\n      :options=\"options\"\n      max-tag-count=\"responsive\"\n      size=\"small\"\n    />\n    <n-select\n      v-model:value=\"value\"\n      placeholder=\"maxTagCount = 3\"\n      multiple\n      :options=\"options\"\n      :max-tag-count=\"3\"\n    />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/select/demos/zhCN/menu-debug.demo.vue",
    "content": "<markdown>\n# Menu Debug\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst value = ref('song0')\nconst value1 = ref(['song0', 'song1', 'song11'])\nconst options = [\n  {\n    label: 'Everybody\\'s Got Something to Hide Except Me and My Monkey',\n    value: 'song0',\n    disabled: true\n  },\n  {\n    label: 'Drive My Car',\n    value: 'song1'\n  },\n  {\n    label: 'Norwegian Wood',\n    value: 'song2'\n  },\n  {\n    label: 'You Won\\'t See',\n    value: 'song3',\n    disabled: true\n  },\n  {\n    label: 'Nowhere Man',\n    value: 'song4'\n  },\n  {\n    label: 'Think For Yourself',\n    value: 'song5'\n  },\n  {\n    label: 'The Word',\n    value: 'song6'\n  },\n  {\n    label: 'Michelle',\n    value: 'song7',\n    disabled: true\n  },\n  {\n    label: 'What goes on',\n    value: 'song8'\n  },\n  {\n    label: 'Girl',\n    value: 'song9'\n  },\n  {\n    label: 'I\\'m looking through you',\n    value: 'song10'\n  },\n  {\n    label: 'In My Life',\n    value: 'song11'\n  },\n  {\n    label: 'Wait',\n    value: 'song12'\n  }\n]\n</script>\n\n<template>\n  <n-space vertical>\n    <n-select v-model:value=\"value\" debug :options=\"options\" />\n    <n-select v-model:value=\"value\" disabled :options=\"options\" />\n    <n-select v-model:value=\"value1\" debug multiple :options=\"options\" />\n    <n-select v-model:value=\"value1\" multiple disabled :options=\"options\" />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/select/demos/zhCN/menu-width.demo.vue",
    "content": "<markdown>\n# 菜单宽度\n\n菜单宽度可以跟随菜单内容（这种情况下无法进行虚拟滚动）。\n</markdown>\n\n<script lang=\"ts\" setup>\nconst options = [\n  {\n    label: 'Everybody\\'s Got Something to Hide Except Me and My Monkey',\n    value: 'song0',\n    disabled: true\n  },\n  {\n    label: 'Drive My Car',\n    value: 'song1'\n  },\n  {\n    label: 'Norwegian Wood',\n    value: 'song2'\n  },\n  {\n    label: 'You Won\\'t See',\n    value: 'song3',\n    disabled: true\n  },\n  {\n    label: 'Nowhere Man',\n    value: 'song4'\n  },\n  {\n    label: 'Think For Yourself',\n    value: 'song5'\n  },\n  {\n    label: 'The Word',\n    value: 'song6'\n  },\n  {\n    label: 'Michelle',\n    value: 'song7',\n    disabled: true\n  },\n  {\n    label: 'What goes on',\n    value: 'song8'\n  },\n  {\n    label: 'Girl',\n    value: 'song9'\n  },\n  {\n    label: 'I\\'m looking through you',\n    value: 'song10'\n  },\n  {\n    label: 'In My Life',\n    value: 'song11'\n  },\n  {\n    label: 'Wait',\n    value: 'song12'\n  }\n]\n</script>\n\n<template>\n  <n-space vertical>\n    <n-select :options=\"options\" :consistent-menu-width=\"false\" />\n    <n-select multiple :options=\"options\" :consistent-menu-width=\"false\" />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/select/demos/zhCN/multiple.demo.vue",
    "content": "<markdown>\n# 多选\n\n多选值。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst value = ref(['song3'])\nconst options = [\n  {\n    label: 'Everybody\\'s Got Something to Hide Except Me and My Monkey',\n    value: 'song0',\n    disabled: true\n  },\n  {\n    label: 'Drive My Car',\n    value: 'song1'\n  },\n  {\n    label: 'Norwegian Wood',\n    value: 'song2'\n  },\n  {\n    label: 'You Won\\'t See',\n    value: 'song3',\n    disabled: true\n  },\n  {\n    label: 'Nowhere Man',\n    value: 'song4'\n  },\n  {\n    label: 'Think For Yourself',\n    value: 'song5'\n  },\n  {\n    label: 'The Word',\n    value: 'song6'\n  },\n  {\n    label: 'Michelle',\n    value: 'song7',\n    disabled: true\n  },\n  {\n    label: 'What goes on',\n    value: 'song8'\n  },\n  {\n    label: 'Girl',\n    value: 'song9'\n  },\n  {\n    label: 'I\\'m looking through you',\n    value: 'song10'\n  },\n  {\n    label: 'In My Life',\n    value: 'song11'\n  },\n  {\n    label: 'Wait',\n    value: 'song12'\n  }\n]\n</script>\n\n<template>\n  <n-space vertical>\n    <n-select v-model:value=\"value\" multiple :options=\"options\" />\n    <n-select v-model:value=\"value\" multiple disabled :options=\"options\" />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/select/demos/zhCN/options-change-debug.demo.vue",
    "content": "<markdown>\n# Options Change Debug\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { SelectOption } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst value = ref(null)\nconst options = ref<SelectOption[]>([\n  {\n    label: 'Everybody\\'s Got Something to Hide Except Me and My Monkey',\n    value: 'song0'\n  },\n  {\n    label: 'Drive My Car',\n    value: 'song1'\n  },\n  {\n    label: 'Norwegian Wood',\n    value: 'song2'\n  },\n  {\n    label: 'You Won\\'t See',\n    value: 'song3'\n  }\n])\n\nfunction handleClick() {\n  options.value = [\n    {\n      label: 'Everybody\\'s Got Something to Hide Except Me and My Monkey',\n      value: 'song0'\n    },\n    {\n      label: 'Drive My Car',\n      value: 'song1',\n      disabled: true\n    },\n    {\n      label: 'Norwegian Wood',\n      value: 'song2',\n      disabled: true\n    },\n    {\n      label: 'You Won\\'t See',\n      value: 'song3'\n    }\n  ]\n}\n</script>\n\n<template>\n  <n-space vertical>\n    <n-button @click=\"handleClick\">\n      reset\n    </n-button>\n    <n-select v-model:value=\"value\" multiple :options=\"options\" />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/select/demos/zhCN/placeholder-debug.demo.vue",
    "content": "<markdown>\n# Placehoder Debug\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst options = [\n  {\n    value: '1',\n    label: '1'\n  }\n]\nconst value1 = ref(null)\nconst value2 = ref(null)\n</script>\n\n<template>\n  <n-space vertical>\n    <n-select\n      v-model:value=\"value1\"\n      placeholder=\"\"\n      :options=\"options\"\n      style=\"width: 200px\"\n    />\n    <n-select\n      v-model:value=\"value2\"\n      multiple\n      placeholder=\"\"\n      :options=\"options\"\n      style=\"width: 200px\"\n    />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/select/demos/zhCN/remote-multiple.demo.vue",
    "content": "<markdown>\n# 异步加载（多选）\n\n异步多选的例子。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { SelectOption } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst options = [\n  {\n    label: 'Drive My Car',\n    value: 'song1'\n  },\n  {\n    label: 'Norwegian Wood',\n    value: 'song2'\n  },\n  {\n    label: 'You Won\\'t See',\n    value: 'song3'\n  },\n  {\n    label: 'Nowhere Man',\n    value: 'song4'\n  },\n  {\n    label: 'Think For Yourself',\n    value: 'song5'\n  },\n  {\n    label: 'The Word',\n    value: 'song6'\n  },\n  {\n    label: 'Michelle',\n    value: 'song7'\n  },\n  {\n    label: 'What goes on',\n    value: 'song8'\n  },\n  {\n    label: 'Girl',\n    value: 'song9'\n  },\n  {\n    label: 'I\\'m looking through you',\n    value: 'song10'\n  },\n  {\n    label: 'In My Life',\n    value: 'song11'\n  },\n  {\n    label: 'Wait',\n    value: 'song12'\n  }\n]\n\nconst selectedValues = ref(null)\nconst loadingRef = ref(false)\nconst optionsRef = ref<SelectOption[]>([])\n\nfunction handleSearch(query: string) {\n  if (!query.length) {\n    optionsRef.value = []\n    return\n  }\n  loadingRef.value = true\n  window.setTimeout(() => {\n    optionsRef.value = options.filter(item => ~item.label.indexOf(query))\n    loadingRef.value = false\n  }, 1000)\n}\n</script>\n\n<template>\n  <n-select\n    v-model:value=\"selectedValues\"\n    multiple\n    filterable\n    placeholder=\"搜索歌曲\"\n    :options=\"optionsRef\"\n    :loading=\"loadingRef\"\n    clearable\n    remote\n    :clear-filter-after-select=\"false\"\n    @search=\"handleSearch\"\n  />\n</template>\n"
  },
  {
    "path": "src/select/demos/zhCN/remote.demo.vue",
    "content": "<markdown>\n# 异步加载（单选）\n\n异步单选的例子。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { SelectOption } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst options = [\n  {\n    label: 'Drive My Car',\n    value: 'song1'\n  },\n  {\n    label: 'Norwegian Wood',\n    value: 'song2'\n  },\n  {\n    label: 'You Won\\'t See',\n    value: 'song3'\n  },\n  {\n    label: 'Nowhere Man',\n    value: 'song4'\n  },\n  {\n    label: 'Think For Yourself',\n    value: 'song5'\n  },\n  {\n    label: 'The Word',\n    value: 'song6'\n  },\n  {\n    label: 'Michelle',\n    value: 'song7'\n  },\n  {\n    label: 'What goes on',\n    value: 'song8'\n  },\n  {\n    label: 'Girl',\n    value: 'song9'\n  },\n  {\n    label: 'I\\'m looking through you',\n    value: 'song10'\n  },\n  {\n    label: 'In My Life',\n    value: 'song11'\n  },\n  {\n    label: 'Wait',\n    value: 'song12'\n  }\n]\n\nconst value = ref(null)\nconst loadingRef = ref(false)\nconst optionsRef = ref<SelectOption[]>([])\n\nfunction handleSearch(query: string) {\n  if (!query.length) {\n    optionsRef.value = []\n    return\n  }\n  loadingRef.value = true\n  window.setTimeout(() => {\n    optionsRef.value = options.filter(item => ~item.label.indexOf(query))\n    loadingRef.value = false\n  }, 1000)\n}\n</script>\n\n<template>\n  <n-select\n    v-model:value=\"value\"\n    filterable\n    placeholder=\"搜索歌曲\"\n    :options=\"optionsRef\"\n    :loading=\"loadingRef\"\n    clearable\n    remote\n    @search=\"handleSearch\"\n  />\n</template>\n"
  },
  {
    "path": "src/select/demos/zhCN/render-debug.demo.vue",
    "content": "<markdown>\n# Render Debug\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { SelectGroupOption, SelectOption } from 'naive-ui'\nimport type { VNode } from 'vue'\nimport { NTooltip } from 'naive-ui'\nimport { h, ref } from 'vue'\n\nconst value = ref(null)\n\nconst options: Array<SelectOption | SelectGroupOption> = [\n  {\n    type: 'group',\n    label: 'Rubber Soul',\n    key: 'Rubber Soul',\n    render: ({ node }: { node: VNode }) => {\n      return h(NTooltip, null, {\n        trigger: () => node,\n        default: () => '用户需要这种功能我也很无奈1'\n      })\n    },\n    children: [\n      {\n        label: () =>\n          'Everybody\\'s Got Something to Hide Except Me and My Monkey',\n        value: 'song0',\n        disabled: true\n      },\n      {\n        label: 'Drive My Car',\n        value: 'song1',\n        render: ({ node }: { node: VNode }) => {\n          return h(NTooltip, null, {\n            trigger: () => node,\n            default: () => '用户需要这种功能我也很无奈2'\n          })\n        }\n      },\n      {\n        label: 'Norwegian Wood',\n        value: 'song2'\n      },\n      {\n        label: 'You Won\\'t See',\n        value: 'song3',\n        disabled: true\n      },\n      {\n        label: 'Nowhere Man',\n        value: 'song4'\n      },\n      {\n        label: 'Think For Yourself',\n        value: 'song5'\n      },\n      {\n        label: 'The Word',\n        value: 'song6'\n      },\n      {\n        label: 'Michelle',\n        value: 'song7',\n        disabled: true\n      },\n      {\n        label: 'What goes on',\n        value: 'song8'\n      },\n      {\n        label: 'Girl',\n        value: 'song9'\n      },\n      {\n        label: 'I\\'m looking through you',\n        value: 'song10'\n      },\n      {\n        label: 'In My Life',\n        value: 'song11'\n      },\n      {\n        label: 'Wait',\n        value: 'song12'\n      }\n    ]\n  }\n]\n</script>\n\n<template>\n  <n-select v-model:value=\"value\" filterable :options=\"options\" />\n</template>\n"
  },
  {
    "path": "src/select/demos/zhCN/render-person.demo.vue",
    "content": "<markdown>\n# 选择人员\n\n我发现很多场景需要把 Select 改为一个人员选择器，这是一个教你如何定制的演示。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { SelectRenderLabel, SelectRenderTag } from 'naive-ui'\nimport { NAvatar, NTag, NText } from 'naive-ui'\nimport { h } from 'vue'\n\nconst renderMultipleSelectTag: SelectRenderTag = ({ option, handleClose }) => {\n  return h(\n    NTag,\n    {\n      style: {\n        padding: '0 6px 0 4px'\n      },\n      round: true,\n      closable: true,\n      onClose: (e) => {\n        e.stopPropagation()\n        handleClose()\n      }\n    },\n    {\n      default: () =>\n        h(\n          'div',\n          {\n            style: {\n              display: 'flex',\n              alignItems: 'center'\n            }\n          },\n          [\n            h(NAvatar, {\n              src: 'https://07akioni.oss-cn-beijing.aliyuncs.com/07akioni.jpeg',\n              round: true,\n              size: 22,\n              style: {\n                marginRight: '4px'\n              }\n            }),\n            option.label as string\n          ]\n        )\n    }\n  )\n}\n\nconst renderSingleSelectTag: SelectRenderTag = ({ option }) => {\n  return h(\n    'div',\n    {\n      style: {\n        display: 'flex',\n        alignItems: 'center'\n      }\n    },\n    [\n      h(NAvatar, {\n        src: 'https://07akioni.oss-cn-beijing.aliyuncs.com/07akioni.jpeg',\n        round: true,\n        size: 24,\n        style: {\n          marginRight: '12px'\n        }\n      }),\n      option.label as string\n    ]\n  )\n}\n\nconst renderLabel: SelectRenderLabel = (option) => {\n  return h(\n    'div',\n    {\n      style: {\n        display: 'flex',\n        alignItems: 'center'\n      }\n    },\n    [\n      h(NAvatar, {\n        src: 'https://07akioni.oss-cn-beijing.aliyuncs.com/07akioni.jpeg',\n        round: true,\n        size: 'small'\n      }),\n      h(\n        'div',\n        {\n          style: {\n            marginLeft: '12px',\n            padding: '4px 0'\n          }\n        },\n        [\n          h('div', null, [option.label as string]),\n          h(\n            NText,\n            { depth: 3, tag: 'div' },\n            {\n              default: () => 'description'\n            }\n          )\n        ]\n      )\n    ]\n  )\n}\n\nconst options = [\n  {\n    label: '07akioni',\n    value: '07akioni'\n  },\n  {\n    label: '08akioni',\n    value: '08akioni'\n  },\n  {\n    label: '09akioni',\n    value: '09akioni'\n  }\n]\n</script>\n\n<template>\n  <n-space vertical>\n    <n-select\n      :options=\"options\"\n      :render-label=\"renderLabel\"\n      :render-tag=\"renderSingleSelectTag\"\n    />\n    <n-select\n      :options=\"options\"\n      :render-label=\"renderLabel\"\n      :render-tag=\"renderSingleSelectTag\"\n      filterable\n    />\n    <n-select\n      multiple\n      :options=\"options\"\n      :render-label=\"renderLabel\"\n      :render-tag=\"renderMultipleSelectTag\"\n    />\n    <n-select\n      multiple\n      :options=\"options\"\n      :render-label=\"renderLabel\"\n      :render-tag=\"renderMultipleSelectTag\"\n      filterable\n    />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/select/demos/zhCN/render-tag.demo.vue",
    "content": "<markdown>\n# 自定义标签渲染\n\n给标签一点颜色看看。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { SelectRenderTag } from 'naive-ui'\nimport { NTag } from 'naive-ui'\nimport { h, ref } from 'vue'\n\nconst value = ref([])\n\nconst renderTag: SelectRenderTag = ({ option, handleClose }) => {\n  return h(\n    NTag,\n    {\n      type: option.type as 'success' | 'warning' | 'error',\n      closable: true,\n      onMousedown: (e: FocusEvent) => {\n        e.preventDefault()\n      },\n      onClose: (e: MouseEvent) => {\n        e.stopPropagation()\n        handleClose()\n      }\n    },\n    { default: () => option.label }\n  )\n}\n\nconst options = [\n  {\n    label: '今天在摸鱼',\n    value: 'value1',\n    type: 'success'\n  },\n  {\n    label: '工作没做完',\n    value: 'value2',\n    type: 'warning'\n  },\n  {\n    label: '晚上要加班',\n    value: 'value3',\n    type: 'error'\n  }\n]\n</script>\n\n<template>\n  <n-select\n    v-model:value=\"value\"\n    multiple\n    :render-tag=\"renderTag\"\n    :options=\"options\"\n  />\n</template>\n"
  },
  {
    "path": "src/select/demos/zhCN/rtl-debug.demo.vue",
    "content": "<markdown>\n# Rtl Debug\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { unstableSelectRtl } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst rtlEnabled = ref(false)\nconst rtlStyles = [unstableSelectRtl]\nconst options = [\n  {\n    label: 'Everybody\\'s Got Something to Hide Except Me and My Monkey',\n    value: 'song0',\n    disabled: true\n  },\n  {\n    label: 'Drive My Car',\n    value: 'song1'\n  },\n  {\n    label: 'Norwegian Wood',\n    value: 'song2'\n  },\n  {\n    label: 'You Won\\'t See',\n    value: 'song3',\n    disabled: true\n  },\n  {\n    label: 'Nowhere Man',\n    value: 'song4'\n  },\n  {\n    label: 'Think For Yourself',\n    value: 'song5'\n  },\n  {\n    label: 'The Word',\n    value: 'song6'\n  },\n  {\n    label: 'Michelle',\n    value: 'song7',\n    disabled: true\n  },\n  {\n    label: 'What goes on',\n    value: 'song8'\n  },\n  {\n    label: 'Girl',\n    value: 'song9'\n  },\n  {\n    label: 'I\\'m looking through you',\n    value: 'song10'\n  },\n  {\n    label: 'In My Life',\n    value: 'song11'\n  },\n  {\n    label: 'Wait',\n    value: 'song12'\n  }\n]\n</script>\n\n<template>\n  <n-space vertical>\n    <n-space><n-switch v-model:value=\"rtlEnabled\" />Rtl</n-space>\n    <n-config-provider :rtl=\"rtlEnabled ? rtlStyles : undefined\">\n      <n-flex vertical>\n        <n-select :options=\"options\" />\n        <n-select multiple :options=\"options\" />\n      </n-flex>\n    </n-config-provider>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/select/demos/zhCN/scroll-event.demo.vue",
    "content": "<markdown>\n# 滚动事件\n\n同事说要用这个来触发做异步加载。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst optionsRef = ref([\n  {\n    label: 'Drive My Car',\n    value: 'song1'\n  },\n  {\n    label: 'Norwegian Wood',\n    value: 'song2'\n  },\n  {\n    label: 'You Won\\'t See',\n    value: 'song3'\n  },\n  {\n    label: 'Nowhere Man',\n    value: 'song4'\n  },\n  {\n    label: 'Think For Yourseld',\n    value: 'song5'\n  },\n  {\n    label: 'The Word',\n    value: 'song6'\n  },\n  {\n    label: 'Michelle',\n    value: 'song7'\n  },\n  {\n    label: 'What goes on',\n    value: 'song8'\n  },\n  {\n    label: 'Girl',\n    value: 'song9'\n  },\n  {\n    label: 'I\\'m looking through you',\n    value: 'song10'\n  },\n  {\n    label: 'In My Life',\n    value: 'song11'\n  },\n  {\n    label: 'Wait',\n    value: 'song12'\n  }\n])\n\nfunction handleScroll(e: Event) {\n  const currentTarget = e.currentTarget as HTMLElement\n  if (\n    currentTarget.scrollTop + currentTarget.offsetHeight\n    >= currentTarget.scrollHeight\n  ) {\n    optionsRef.value.push(\n      {\n        label: `v1-${optionsRef.value.length}`,\n        value: `v1-${optionsRef.value.length}`\n      },\n      {\n        label: `v2-${optionsRef.value.length}`,\n        value: `v2-${optionsRef.value.length}`\n      }\n    )\n  }\n}\n</script>\n\n<template>\n  <n-select\n    :options=\"optionsRef\"\n    :reset-menu-on-options-change=\"false\"\n    @scroll=\"handleScroll\"\n  />\n</template>\n"
  },
  {
    "path": "src/select/demos/zhCN/size.demo.vue",
    "content": "<markdown>\n# 尺寸\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst value = ref(null)\nconst options = [\n  {\n    label: 'Everybody\\'s Got Something to Hide Except Me and My Monkey',\n    value: 'song0',\n    disabled: true\n  },\n  {\n    label: 'Drive My Car',\n    value: 'song1'\n  },\n  {\n    label: 'Norwegian Wood',\n    value: 'song2'\n  },\n  {\n    label: 'You Won\\'t See',\n    value: 'song3',\n    disabled: true\n  },\n  {\n    label: 'Nowhere Man',\n    value: 'song4'\n  },\n  {\n    label: 'Think For Yourself',\n    value: 'song5'\n  },\n  {\n    label: 'The Word',\n    value: 'song6'\n  },\n  {\n    label: 'Michelle',\n    value: 'song7',\n    disabled: true\n  },\n  {\n    label: 'What goes on',\n    value: 'song8'\n  },\n  {\n    label: 'Girl',\n    value: 'song9'\n  },\n  {\n    label: 'I\\'m looking through you',\n    value: 'song10'\n  },\n  {\n    label: 'In My Life',\n    value: 'song11'\n  },\n  {\n    label: 'Wait',\n    value: 'song12'\n  }\n]\n</script>\n\n<template>\n  <n-space vertical>\n    <n-select v-model:value=\"value\" size=\"tiny\" :options=\"options\" />\n    <n-select v-model:value=\"value\" size=\"small\" :options=\"options\" />\n    <n-select v-model:value=\"value\" size=\"medium\" :options=\"options\" />\n    <n-select v-model:value=\"value\" size=\"large\" :options=\"options\" />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/select/demos/zhCN/spin-debug.demo.vue",
    "content": "<markdown>\n# Spin Debug\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst selectedValue = ref('song1')\nconst options = [\n  {\n    label: 'Drive My Car',\n    value: 'song1'\n  },\n  {\n    label: 'Norwegian Wood',\n    value: 'song2'\n  },\n  {\n    label: 'You Won\\'t See',\n    value: 'song3'\n  },\n  {\n    label: 'Nowhere Man',\n    value: 'song4'\n  },\n  {\n    label: 'Think For Yourself',\n    value: 'song5'\n  },\n  {\n    label: 'The Word',\n    value: 'song6'\n  },\n  {\n    label: 'Michelle',\n    value: 'song7'\n  },\n  {\n    label: 'What goes on',\n    value: 'song8'\n  },\n  {\n    label: 'Girl',\n    value: 'song9'\n  },\n  {\n    label: 'I\\'m looking through you',\n    value: 'song10'\n  },\n  {\n    label: 'In My Life',\n    value: 'song11'\n  },\n  {\n    label: 'Wait',\n    value: 'song12'\n  }\n]\n</script>\n\n<template>\n  <n-spin :show=\"false\">\n    <n-select v-model:value=\"selectedValue\" :options=\"options\" clearable />\n  </n-spin>\n</template>\n"
  },
  {
    "path": "src/select/demos/zhCN/status.demo.vue",
    "content": "<markdown>\n# 验证状态\n\n输入的验证状态可以脱离表单使用。\n</markdown>\n\n<template>\n  <n-space vertical>\n    <n-select status=\"warning\" placeholder=\"\" />\n    <n-select status=\"error\" placeholder=\"\" />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/select/demos/zhCN/tag-input.demo.vue",
    "content": "<markdown>\n# 作为 Tag 框输入使用\n\n使用 `tag` 和 `:show=\"false\"` 来作为 Tag 框输入使用。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst multipleSelectValue = ref(null)\n</script>\n\n<template>\n  <n-select\n    v-model:value=\"multipleSelectValue\"\n    filterable\n    multiple\n    tag\n    placeholder=\"输入，按回车确认\"\n    :show-arrow=\"false\"\n    :show=\"false\"\n  />\n</template>\n"
  },
  {
    "path": "src/select/demos/zhCN/tag.demo.vue",
    "content": "<markdown>\n# 动态创建选项\n\n使用 `tag` & `filterable` 来允许动态创建选项。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst multipleSelectValue = ref(null)\nconst selectValue = ref(null)\nconst options = [\n  {\n    label: 'Everybody\\'s Got Something to Hide Except Me and My Monkey',\n    value: 'song0',\n    disabled: true\n  },\n  {\n    label: 'Drive My Car',\n    value: 'song1'\n  },\n  {\n    label: 'Norwegian Wood',\n    value: 'song2'\n  },\n  {\n    label: 'You Won\\'t See',\n    value: 'song3',\n    disabled: true\n  },\n  {\n    label: 'Nowhere Man',\n    value: 'song4'\n  },\n  {\n    label: 'Think For Yourself',\n    value: 'song5'\n  },\n  {\n    label: 'The Word',\n    value: 'song6'\n  },\n  {\n    label: 'Michelle',\n    value: 'song7',\n    disabled: true\n  },\n  {\n    label: 'What goes on',\n    value: 'song8'\n  },\n  {\n    label: 'Girl',\n    value: 'song9'\n  },\n  {\n    label: 'I\\'m looking through you',\n    value: 'song10'\n  },\n  {\n    label: 'In My Life',\n    value: 'song11'\n  },\n  {\n    label: 'Wait',\n    value: 'song12'\n  }\n]\n</script>\n\n<template>\n  <n-space vertical>\n    <n-select\n      v-model:value=\"multipleSelectValue\"\n      filterable\n      multiple\n      tag\n      :options=\"options\"\n    />\n    <n-select v-model:value=\"selectValue\" filterable tag :options=\"options\" />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/select/index.ts",
    "content": "export type {\n  NodeProps as SelectNodeProps,\n  RenderLabelImpl as SelectRenderLabel,\n  RenderOptionImpl as SelectRenderOption\n} from '../_internal/select-menu/src/interface'\nexport type { RenderTag as SelectRenderTag } from '../_internal/selection/src/interface'\nexport type {\n  SelectFilter,\n  SelectGroupOption,\n  SelectInst,\n  SelectOption\n} from './src/interface'\nexport type * from './src/public-types'\nexport { default as NSelect, selectProps } from './src/Select'\nexport type { SelectProps, SelectSlots } from './src/Select'\n"
  },
  {
    "path": "src/select/src/Select.tsx",
    "content": "import type { TreeNode } from 'treemate'\nimport type {\n  HTMLAttributes,\n  InputHTMLAttributes,\n  PropType,\n  SlotsType,\n  VNode\n} from 'vue'\nimport type { FollowerInst, FollowerPlacement } from 'vueuc'\nimport type {\n  InternalSelectionInst,\n  InternalSelectMenuRef,\n  ScrollbarProps\n} from '../../_internal'\nimport type {\n  NodeProps,\n  RenderLabel,\n  RenderOption\n} from '../../_internal/select-menu/src/interface'\nimport type { RenderTag } from '../../_internal/selection/src/interface'\nimport type { ThemeProps } from '../../_mixins'\nimport type { ExtractPublicPropTypes, MaybeArray } from '../../_utils'\nimport type { FormValidationStatus } from '../../form/src/public-types'\nimport type { PopoverProps } from '../../popover'\nimport type { SelectTheme } from '../styles'\nimport type {\n  OnUpdateValue,\n  OnUpdateValueImpl,\n  SelectBaseOption,\n  SelectFallbackOption,\n  SelectFallbackOptionImpl,\n  SelectFilter,\n  SelectGroupOption,\n  SelectIgnoredOption,\n  SelectInst,\n  SelectMixedOption,\n  SelectOption,\n  Value,\n  ValueAtom\n} from './interface'\nimport type { SelectSize } from './public-types'\nimport { getPreciseEventTarget, happensIn } from 'seemly'\nimport { createTreeMate } from 'treemate'\nimport { clickoutside } from 'vdirs'\nimport { useCompitable, useIsMounted, useMergedState } from 'vooks'\nimport {\n  computed,\n  defineComponent,\n  h,\n  ref,\n  toRef,\n  Transition,\n  vShow,\n  watch,\n  watchEffect,\n  withDirectives\n} from 'vue'\nimport { VBinder, VFollower, VTarget } from 'vueuc'\nimport { NInternalSelection, NInternalSelectMenu } from '../../_internal'\nimport {\n  useConfig,\n  useFormItem,\n  useLocale,\n  useTheme,\n  useThemeClass\n} from '../../_mixins'\nimport {\n  call,\n  markEventEffectPerformed,\n  useAdjustedTo,\n  warnOnce\n} from '../../_utils'\nimport { selectLight } from '../styles'\nimport style from './styles/index.cssr'\nimport {\n  createTmOptions,\n  createValOptMap,\n  filterOptions,\n  patternMatched\n} from './utils'\n\nexport const selectProps = {\n  ...(useTheme.props as ThemeProps<SelectTheme>),\n  to: useAdjustedTo.propTo,\n  bordered: {\n    type: Boolean as PropType<boolean | undefined>,\n    default: undefined\n  },\n  clearable: Boolean,\n  clearCreatedOptionsOnClear: {\n    type: Boolean,\n    default: true\n  },\n  clearFilterAfterSelect: {\n    type: Boolean,\n    default: true\n  },\n  options: {\n    type: Array as PropType<SelectMixedOption[]>,\n    default: () => []\n  },\n  defaultValue: {\n    type: [String, Number, Array] as PropType<Value | null>,\n    default: null\n  },\n  keyboard: {\n    type: Boolean,\n    default: true\n  },\n  value: [String, Number, Array] as PropType<Value | null>,\n  placeholder: String,\n  menuProps: Object as PropType<HTMLAttributes>,\n  multiple: Boolean,\n  size: String as PropType<SelectSize>,\n  menuSize: {\n    type: String as PropType<SelectSize>\n  },\n  filterable: Boolean,\n  disabled: {\n    type: Boolean as PropType<boolean | undefined>,\n    default: undefined\n  },\n  remote: Boolean,\n  loading: Boolean,\n  filter: Function as PropType<SelectFilter>,\n  placement: {\n    type: String as PropType<FollowerPlacement>,\n    default: 'bottom-start'\n  },\n  widthMode: {\n    type: String,\n    default: 'trigger'\n  },\n  tag: Boolean,\n  onCreate: Function as PropType<(label: string) => SelectOption>,\n  fallbackOption: {\n    type: [Function, Boolean] as PropType<\n      SelectFallbackOption | false | undefined\n    >,\n    default: undefined\n  },\n  show: {\n    type: Boolean as PropType<boolean | undefined>,\n    default: undefined\n  },\n  showArrow: {\n    type: Boolean,\n    default: true\n  },\n  maxTagCount: [Number, String] as PropType<number | 'responsive'>,\n  ellipsisTagPopoverProps: Object as PropType<PopoverProps>,\n  consistentMenuWidth: {\n    type: Boolean,\n    default: true\n  },\n  virtualScroll: {\n    type: Boolean,\n    default: true\n  },\n  labelField: {\n    type: String,\n    default: 'label'\n  },\n  valueField: {\n    type: String,\n    default: 'value'\n  },\n  childrenField: {\n    type: String,\n    default: 'children'\n  },\n  renderLabel: Function as PropType<RenderLabel>,\n  renderOption: Function as PropType<RenderOption>,\n  renderTag: Function as PropType<RenderTag>,\n  'onUpdate:value': [Function, Array] as PropType<\n    MaybeArray<OnUpdateValue> | undefined\n  >,\n  inputProps: Object as PropType<InputHTMLAttributes>,\n  nodeProps: Function as PropType<NodeProps>,\n  ignoreComposition: { type: Boolean, default: true },\n  showOnFocus: Boolean,\n  // for jsx\n  onUpdateValue: [Function, Array] as PropType<\n    MaybeArray<OnUpdateValue> | undefined\n  >,\n  onBlur: [Function, Array] as PropType<\n    MaybeArray<(e: FocusEvent) => void> | undefined\n  >,\n  onClear: [Function, Array] as PropType<MaybeArray<() => void> | undefined>,\n  onFocus: [Function, Array] as PropType<\n    MaybeArray<(e: FocusEvent) => void> | undefined\n  >,\n  onScroll: [Function, Array] as PropType<\n    MaybeArray<(e: Event) => void> | undefined\n  >,\n  onSearch: [Function, Array] as PropType<\n    MaybeArray<(value: string) => void> | undefined\n  >,\n  onUpdateShow: [Function, Array] as PropType<\n    MaybeArray<(value: boolean) => void>\n  >,\n  'onUpdate:show': [Function, Array] as PropType<\n    MaybeArray<(value: boolean) => void>\n  >,\n  displayDirective: {\n    type: String as PropType<'if' | 'show'>,\n    default: 'show'\n  },\n  resetMenuOnOptionsChange: {\n    type: Boolean,\n    default: true\n  },\n  status: String as PropType<FormValidationStatus>,\n  showCheckmark: {\n    type: Boolean,\n    default: true\n  },\n  scrollbarProps: Object as PropType<ScrollbarProps>,\n  /** deprecated */\n  onChange: [Function, Array] as PropType<MaybeArray<OnUpdateValue>>,\n  items: Array as PropType<SelectMixedOption[]>\n} as const\n\nexport type SelectProps = ExtractPublicPropTypes<typeof selectProps>\n\nexport interface SelectSlots {\n  default?: () => VNode[]\n  header?: () => VNode[]\n  action?: () => VNode[]\n  empty?: () => VNode[]\n  arrow?: () => VNode[]\n}\n\nexport default defineComponent({\n  name: 'Select',\n  props: selectProps,\n  slots: Object as SlotsType<SelectSlots>,\n  setup(props) {\n    if (__DEV__) {\n      watchEffect(() => {\n        if (props.items !== undefined) {\n          warnOnce(\n            'select',\n            '`items` is deprecated, please use `options` instead.'\n          )\n        }\n        if (props.onChange !== undefined) {\n          warnOnce(\n            'select',\n            '`on-change` is deprecated, please use `on-update:value` instead.'\n          )\n        }\n      })\n    }\n\n    const {\n      mergedClsPrefixRef,\n      mergedBorderedRef,\n      namespaceRef,\n      inlineThemeDisabled,\n      mergedComponentPropsRef\n    } = useConfig(props)\n    const themeRef = useTheme(\n      'Select',\n      '-select',\n      style,\n      selectLight,\n      props,\n      mergedClsPrefixRef\n    )\n    const uncontrolledValueRef = ref(props.defaultValue)\n    const controlledValueRef = toRef(props, 'value')\n    const mergedValueRef = useMergedState(\n      controlledValueRef,\n      uncontrolledValueRef\n    )\n    const focusedRef = ref(false)\n    const patternRef = ref('')\n    const compitableOptionsRef = useCompitable(props, ['items', 'options'])\n    const createdOptionsRef = ref<SelectOption[]>([])\n    const beingCreatedOptionsRef = ref<SelectOption[]>([])\n    const localOptionsRef = computed<SelectMixedOption[]>(() => {\n      return (\n        beingCreatedOptionsRef.value.concat(\n          createdOptionsRef.value\n        ) as SelectMixedOption[]\n      ).concat(compitableOptionsRef.value)\n    })\n    const resolvedFilterRef = computed(() => {\n      const { filter } = props\n      if (filter)\n        return filter\n      const { labelField, valueField } = props\n      return (pattern: string, option: SelectBaseOption): boolean => {\n        if (!option)\n          return false\n        const label = option[labelField]\n        if (typeof label === 'string') {\n          return patternMatched(pattern, label)\n        }\n        const value = option[valueField]\n        if (typeof value === 'string') {\n          return patternMatched(pattern, value)\n        }\n        if (typeof value === 'number') {\n          return patternMatched(pattern, String(value))\n        }\n        return false\n      }\n    })\n    const filteredOptionsRef = computed(() => {\n      if (props.remote) {\n        return compitableOptionsRef.value\n      }\n      else {\n        const { value: localOptions } = localOptionsRef\n        const { value: pattern } = patternRef\n        if (!pattern.length || !props.filterable) {\n          return localOptions\n        }\n        else {\n          return filterOptions(\n            localOptions,\n            resolvedFilterRef.value,\n            pattern,\n            props.childrenField\n          )\n        }\n      }\n    })\n    const treeMateRef = computed(() => {\n      const { valueField, childrenField } = props\n      const options = createTmOptions(valueField, childrenField)\n      return createTreeMate<\n        SelectOption,\n        SelectGroupOption,\n        SelectIgnoredOption\n      >(filteredOptionsRef.value, options)\n    })\n    const valOptMapRef = computed(() =>\n      createValOptMap(\n        localOptionsRef.value,\n        props.valueField,\n        props.childrenField\n      )\n    )\n    const uncontrolledShowRef = ref(false)\n    const mergedShowRef = useMergedState(\n      toRef(props, 'show'),\n      uncontrolledShowRef\n    )\n    const triggerRef = ref<InternalSelectionInst | null>(null)\n    const followerRef = ref<FollowerInst | null>(null)\n    const menuRef = ref<InternalSelectMenuRef | null>(null)\n    const { localeRef } = useLocale('Select')\n    const localizedPlaceholderRef = computed<string>(() => {\n      return props.placeholder ?? localeRef.value.placeholder\n    })\n\n    const emptyArray: SelectOption[] = []\n    const memoValOptMapRef = ref(new Map<string | number, SelectOption>())\n\n    const wrappedFallbackOptionRef = computed(() => {\n      const { fallbackOption } = props\n      if (fallbackOption === undefined) {\n        const { labelField, valueField } = props\n        return (value: string | number) => ({\n          [labelField]: String(value),\n          [valueField]: value\n        })\n      }\n      if (fallbackOption === false)\n        return false\n      return (value: string | number) => {\n        return Object.assign(\n          (fallbackOption as SelectFallbackOptionImpl)(value),\n          {\n            value\n          }\n        ) as SelectOption\n      }\n    })\n    function getMergedOptions(values: ValueAtom[]): SelectOption[] {\n      const remote = props.remote\n      const { value: memoValOptMap } = memoValOptMapRef\n      const { value: valOptMap } = valOptMapRef\n      const { value: wrappedFallbackOption } = wrappedFallbackOptionRef\n      const options: SelectOption[] = []\n      values.forEach((value) => {\n        if (valOptMap.has(value)) {\n          options.push(valOptMap.get(value)!)\n        }\n        else if (remote && memoValOptMap.has(value)) {\n          options.push(memoValOptMap.get(value)!)\n        }\n        else if (wrappedFallbackOption) {\n          const option = wrappedFallbackOption(value)\n          if (option) {\n            options.push(option)\n          }\n        }\n      })\n      return options\n    }\n    const selectedOptionsRef = computed(() => {\n      if (props.multiple) {\n        const { value: values } = mergedValueRef\n        if (!Array.isArray(values))\n          return []\n        return getMergedOptions(values)\n      }\n      return null\n    })\n    const selectedOptionRef = computed<SelectOption | null>(() => {\n      const { value: mergedValue } = mergedValueRef\n      if (!props.multiple && !Array.isArray(mergedValue)) {\n        if (mergedValue === null)\n          return null\n        return getMergedOptions([mergedValue])[0] || null\n      }\n      return null\n    })\n\n    const formItem = useFormItem(props, {\n      mergedSize: (NFormItem) => {\n        const { size } = props\n        if (size)\n          return size\n        const { mergedSize: formItemSize } = NFormItem || {}\n        if (formItemSize?.value)\n          return formItemSize.value as SelectSize\n        const configSize = mergedComponentPropsRef?.value?.Select?.size\n        if (configSize)\n          return configSize\n        return 'medium'\n      }\n    })\n    const { mergedSizeRef, mergedDisabledRef, mergedStatusRef } = formItem\n    function doUpdateValue(\n      value: string | number | Array<string | number> | null,\n      option: SelectOption | null | SelectOption[]\n    ): void {\n      const {\n        onChange,\n        'onUpdate:value': _onUpdateValue,\n        onUpdateValue\n      } = props\n      const { nTriggerFormChange, nTriggerFormInput } = formItem\n      if (onChange)\n        call(onChange as OnUpdateValueImpl, value, option)\n      if (onUpdateValue)\n        call(onUpdateValue as OnUpdateValueImpl, value, option)\n      if (_onUpdateValue) {\n        call(_onUpdateValue as OnUpdateValueImpl, value, option)\n      }\n      uncontrolledValueRef.value = value\n      nTriggerFormChange()\n      nTriggerFormInput()\n    }\n    function doBlur(e: FocusEvent): void {\n      const { onBlur } = props\n      const { nTriggerFormBlur } = formItem\n      if (onBlur)\n        call(onBlur, e)\n      nTriggerFormBlur()\n    }\n    function doClear(): void {\n      const { onClear } = props\n      if (onClear)\n        call(onClear)\n    }\n    function doFocus(e: FocusEvent): void {\n      const { onFocus, showOnFocus } = props\n      const { nTriggerFormFocus } = formItem\n      if (onFocus)\n        call(onFocus, e)\n      nTriggerFormFocus()\n      if (showOnFocus) {\n        openMenu()\n      }\n    }\n    function doSearch(value: string): void {\n      const { onSearch } = props\n      if (onSearch)\n        call(onSearch, value)\n    }\n    function doScroll(e: Event): void {\n      const { onScroll } = props\n      if (onScroll)\n        call(onScroll, e)\n    }\n    // remote related methods\n    function updateMemorizedOptions(): void {\n      const { remote, multiple } = props\n      if (remote) {\n        const { value: memoValOptMap } = memoValOptMapRef\n        if (multiple) {\n          const { valueField } = props\n          selectedOptionsRef.value?.forEach((option) => {\n            memoValOptMap.set(\n              option[valueField] as NonNullable<SelectOption['value']>,\n              option\n            )\n          })\n        }\n        else {\n          const option = selectedOptionRef.value\n          if (option) {\n            memoValOptMap.set(\n              option[props.valueField] as NonNullable<SelectOption['value']>,\n              option\n            )\n          }\n        }\n      }\n    }\n    // menu related methods\n    function doUpdateShow(value: boolean): void {\n      const { onUpdateShow, 'onUpdate:show': _onUpdateShow } = props\n      if (onUpdateShow)\n        call(onUpdateShow, value)\n      if (_onUpdateShow)\n        call(_onUpdateShow, value)\n      uncontrolledShowRef.value = value\n    }\n    function openMenu(): void {\n      if (!mergedDisabledRef.value) {\n        doUpdateShow(true)\n        uncontrolledShowRef.value = true\n        if (props.filterable) {\n          focusSelectionInput()\n        }\n      }\n    }\n    function closeMenu(): void {\n      doUpdateShow(false)\n    }\n    function handleMenuAfterLeave(): void {\n      patternRef.value = ''\n      beingCreatedOptionsRef.value = emptyArray\n    }\n    const activeWithoutMenuOpenRef = ref(false)\n    function onTriggerInputFocus(): void {\n      if (props.filterable) {\n        activeWithoutMenuOpenRef.value = true\n      }\n    }\n    function onTriggerInputBlur(): void {\n      if (props.filterable) {\n        activeWithoutMenuOpenRef.value = false\n        if (!mergedShowRef.value) {\n          handleMenuAfterLeave()\n        }\n      }\n    }\n    function handleTriggerClick(): void {\n      if (mergedDisabledRef.value)\n        return\n      if (!mergedShowRef.value) {\n        openMenu()\n      }\n      else {\n        if (!props.filterable) {\n          // already focused, don't need to return focus\n          closeMenu()\n        }\n        else {\n          focusSelectionInput()\n        }\n      }\n    }\n    function handleTriggerBlur(e: FocusEvent): void {\n      if (menuRef.value?.selfRef?.contains(e.relatedTarget as Node | null)) {\n        return\n      }\n      focusedRef.value = false\n      doBlur(e)\n      // outside select, don't need to return focus\n      closeMenu()\n    }\n    function handleTriggerFocus(e: FocusEvent): void {\n      doFocus(e)\n      focusedRef.value = true\n    }\n    function handleMenuFocus(): void {\n      focusedRef.value = true\n    }\n    function handleMenuBlur(e: FocusEvent): void {\n      if (triggerRef.value?.$el.contains(e.relatedTarget as Node | null))\n        return\n      focusedRef.value = false\n      doBlur(e)\n      // outside select, don't need to return focus\n      closeMenu()\n    }\n    function handleMenuTabOut(): void {\n      triggerRef.value?.focus()\n      closeMenu()\n    }\n    function handleMenuClickOutside(e: MouseEvent): void {\n      if (mergedShowRef.value) {\n        if (\n          !triggerRef.value?.$el.contains(\n            getPreciseEventTarget(e) as Node | null\n          )\n        ) {\n          // outside select, don't need to return focus\n          closeMenu()\n        }\n      }\n    }\n    function createClearedMultipleSelectValue(\n      value: string | number | Array<string | number> | null\n    ): Array<string | number> {\n      if (!Array.isArray(value))\n        return []\n      if (wrappedFallbackOptionRef.value) {\n        // if option has a fallback, I can't help user to clear some unknown value\n        return Array.from(value)\n      }\n      else {\n        // if there's no option fallback, unappeared options are treated as invalid\n        const { remote } = props\n        const { value: valOptMap } = valOptMapRef\n        if (remote) {\n          const { value: memoValOptMap } = memoValOptMapRef\n          return value.filter(v => valOptMap.has(v) || memoValOptMap.has(v))\n        }\n        else {\n          return value.filter(v => valOptMap.has(v))\n        }\n      }\n    }\n    function handleToggleByTmNode(tmNode: TreeNode<SelectOption>): void {\n      handleToggleByOption(tmNode.rawNode)\n    }\n    function handleToggleByOption(option: SelectOption): void {\n      if (mergedDisabledRef.value)\n        return\n      const { tag, remote, clearFilterAfterSelect, valueField } = props\n      if (tag && !remote) {\n        const { value: beingCreatedOptions } = beingCreatedOptionsRef\n        const beingCreatedOption = beingCreatedOptions[0] || null\n        if (beingCreatedOption) {\n          const createdOptions = createdOptionsRef.value\n          if (!createdOptions.length) {\n            createdOptionsRef.value = [beingCreatedOption]\n          }\n          else {\n            createdOptions.push(beingCreatedOption)\n          }\n          beingCreatedOptionsRef.value = emptyArray\n        }\n      }\n      if (remote) {\n        memoValOptMapRef.value.set(\n          option[valueField] as NonNullable<SelectOption['value']>,\n          option\n        )\n      }\n      if (props.multiple) {\n        const changedValue = createClearedMultipleSelectValue(\n          mergedValueRef.value\n        )\n        const index = changedValue.findIndex(\n          value =>\n            value === (option[valueField] as NonNullable<SelectOption['value']>)\n        )\n        if (~index) {\n          changedValue.splice(index, 1)\n          if (tag && !remote) {\n            const createdOptionIndex = getCreatedOptionIndex(\n              option[valueField] as NonNullable<SelectOption['value']>\n            )\n            if (~createdOptionIndex) {\n              createdOptionsRef.value.splice(createdOptionIndex, 1)\n              if (clearFilterAfterSelect)\n                patternRef.value = ''\n            }\n          }\n        }\n        else {\n          changedValue.push(\n            option[valueField] as NonNullable<SelectOption['value']>\n          )\n          if (clearFilterAfterSelect)\n            patternRef.value = ''\n        }\n        doUpdateValue(changedValue, getMergedOptions(changedValue))\n      }\n      else {\n        if (tag && !remote) {\n          const createdOptionIndex = getCreatedOptionIndex(\n            option[valueField] as NonNullable<SelectOption['value']>\n          )\n          if (~createdOptionIndex) {\n            createdOptionsRef.value = [\n              createdOptionsRef.value[createdOptionIndex]\n            ]\n          }\n          else {\n            createdOptionsRef.value = emptyArray\n          }\n        }\n        focusSelection()\n        closeMenu()\n        doUpdateValue(\n          option[valueField] as NonNullable<SelectOption['value']>,\n          option\n        )\n      }\n    }\n    function getCreatedOptionIndex(optionValue: string | number): number {\n      const createdOptions = createdOptionsRef.value\n      return createdOptions.findIndex(\n        createdOption =>\n          (createdOption[props.valueField] as NonNullable<\n            SelectOption['value']\n          >) === optionValue\n      )\n    }\n    function handlePatternInput(e: InputEvent): void {\n      if (!mergedShowRef.value) {\n        openMenu()\n      }\n      const { value } = e.target as unknown as HTMLInputElement\n      patternRef.value = value\n      const { tag, remote } = props\n      doSearch(value)\n      if (tag && !remote) {\n        if (!value) {\n          beingCreatedOptionsRef.value = emptyArray\n          return\n        }\n        const { onCreate } = props\n        const optionBeingCreated = onCreate\n          ? onCreate(value)\n          : { [props.labelField]: value, [props.valueField]: value }\n        const { valueField, labelField } = props\n        if (\n          compitableOptionsRef.value.some((option) => {\n            return (\n              option[valueField] === optionBeingCreated[valueField]\n              || option[labelField] === optionBeingCreated[labelField]\n            )\n          })\n          || createdOptionsRef.value.some((option) => {\n            return (\n              option[valueField] === optionBeingCreated[valueField]\n              || option[labelField] === optionBeingCreated[labelField]\n            )\n          })\n        ) {\n          beingCreatedOptionsRef.value = emptyArray\n        }\n        else {\n          beingCreatedOptionsRef.value = [optionBeingCreated]\n        }\n      }\n    }\n    function handleClear(e: MouseEvent): void {\n      e.stopPropagation()\n      const { multiple, tag, remote, clearCreatedOptionsOnClear } = props\n      if (!multiple && props.filterable) {\n        closeMenu()\n      }\n      if (tag && !remote && clearCreatedOptionsOnClear) {\n        createdOptionsRef.value = emptyArray\n      }\n      doClear()\n      if (multiple) {\n        doUpdateValue([], [])\n      }\n      else {\n        doUpdateValue(null, null)\n      }\n    }\n    function handleMenuMousedown(e: MouseEvent): void {\n      if (\n        !happensIn(e, 'action')\n        && !happensIn(e, 'empty')\n        && !happensIn(e, 'header')\n      ) {\n        e.preventDefault()\n      }\n    }\n    // scroll events on menu\n    function handleMenuScroll(e: Event): void {\n      doScroll(e)\n    }\n    // keyboard events\n    // also for menu keydown\n    function handleKeydown(e: KeyboardEvent): void {\n      if (!props.keyboard) {\n        e.preventDefault()\n        return\n      }\n      switch (e.key) {\n        case ' ':\n          if (props.filterable) {\n            break\n          }\n          else {\n            e.preventDefault()\n          }\n        // eslint-disable-next-line no-fallthrough\n        case 'Enter':\n          if (!triggerRef.value?.isComposing) {\n            if (mergedShowRef.value) {\n              const pendingTmNode = menuRef.value?.getPendingTmNode()\n              if (pendingTmNode) {\n                handleToggleByTmNode(pendingTmNode)\n              }\n              else if (!props.filterable) {\n                closeMenu()\n                focusSelection()\n              }\n            }\n            else {\n              openMenu()\n              if (props.tag && activeWithoutMenuOpenRef.value) {\n                const beingCreatedOption = beingCreatedOptionsRef.value[0]\n                if (beingCreatedOption) {\n                  const optionValue = beingCreatedOption[\n                    props.valueField\n                  ] as NonNullable<SelectOption['value']>\n                  const { value: mergedValue } = mergedValueRef\n                  if (props.multiple) {\n                    if (\n                      Array.isArray(mergedValue)\n                      && mergedValue.includes(optionValue as never)\n                    ) {\n                      // do nothing\n                    }\n                    else {\n                      handleToggleByOption(beingCreatedOption)\n                    }\n                  }\n                  else {\n                    handleToggleByOption(beingCreatedOption)\n                  }\n                }\n              }\n            }\n          }\n          e.preventDefault()\n          break\n        case 'ArrowUp':\n          e.preventDefault()\n          if (props.loading)\n            return\n          if (mergedShowRef.value) {\n            menuRef.value?.prev()\n          }\n          break\n        case 'ArrowDown':\n          e.preventDefault()\n          if (props.loading)\n            return\n          if (mergedShowRef.value) {\n            menuRef.value?.next()\n          }\n          else {\n            openMenu()\n          }\n          break\n        case 'Escape':\n          if (mergedShowRef.value) {\n            markEventEffectPerformed(e)\n            closeMenu()\n          }\n          triggerRef.value?.focus()\n          break\n      }\n    }\n    function focusSelection(): void {\n      triggerRef.value?.focus()\n    }\n    function focusSelectionInput(): void {\n      triggerRef.value?.focusInput()\n    }\n    function handleTriggerOrMenuResize(): void {\n      if (!mergedShowRef.value)\n        return\n      followerRef.value?.syncPosition()\n    }\n    updateMemorizedOptions()\n    watch(toRef(props, 'options'), updateMemorizedOptions)\n\n    const exposedMethods: SelectInst = {\n      focus: () => {\n        triggerRef.value?.focus()\n      },\n      focusInput: () => {\n        triggerRef.value?.focusInput()\n      },\n      blur: () => {\n        triggerRef.value?.blur()\n      },\n      blurInput: () => {\n        triggerRef.value?.blurInput()\n      }\n    }\n    const cssVarsRef = computed(() => {\n      const {\n        self: { menuBoxShadow }\n      } = themeRef.value\n      return {\n        '--n-menu-box-shadow': menuBoxShadow\n      }\n    })\n    const themeClassHandle = inlineThemeDisabled\n      ? useThemeClass('select', undefined, cssVarsRef, props)\n      : undefined\n    return {\n      ...exposedMethods,\n      mergedStatus: mergedStatusRef,\n      mergedClsPrefix: mergedClsPrefixRef,\n      mergedBordered: mergedBorderedRef,\n      namespace: namespaceRef,\n      treeMate: treeMateRef,\n      isMounted: useIsMounted(),\n      triggerRef,\n      menuRef,\n      pattern: patternRef,\n      uncontrolledShow: uncontrolledShowRef,\n      mergedShow: mergedShowRef,\n      adjustedTo: useAdjustedTo(props),\n      uncontrolledValue: uncontrolledValueRef,\n      mergedValue: mergedValueRef,\n      followerRef,\n      localizedPlaceholder: localizedPlaceholderRef,\n      selectedOption: selectedOptionRef,\n      selectedOptions: selectedOptionsRef,\n      mergedSize: mergedSizeRef,\n      mergedDisabled: mergedDisabledRef,\n      focused: focusedRef,\n      activeWithoutMenuOpen: activeWithoutMenuOpenRef,\n      inlineThemeDisabled,\n      onTriggerInputFocus,\n      onTriggerInputBlur,\n      handleTriggerOrMenuResize,\n      handleMenuFocus,\n      handleMenuBlur,\n      handleMenuTabOut,\n      handleTriggerClick,\n      handleToggle: handleToggleByTmNode,\n      handleDeleteOption: handleToggleByOption,\n      handlePatternInput,\n      handleClear,\n      handleTriggerBlur,\n      handleTriggerFocus,\n      handleKeydown,\n      handleMenuAfterLeave,\n      handleMenuClickOutside,\n      handleMenuScroll,\n      handleMenuKeydown: handleKeydown,\n      handleMenuMousedown,\n      mergedTheme: themeRef,\n      cssVars: inlineThemeDisabled ? undefined : cssVarsRef,\n      themeClass: themeClassHandle?.themeClass,\n      onRender: themeClassHandle?.onRender\n    }\n  },\n  render() {\n    return (\n      <div class={`${this.mergedClsPrefix}-select`}>\n        <VBinder>\n          {{\n            default: () => [\n              <VTarget>\n                {{\n                  default: () => (\n                    <NInternalSelection\n                      ref=\"triggerRef\"\n                      inlineThemeDisabled={this.inlineThemeDisabled}\n                      status={this.mergedStatus}\n                      inputProps={this.inputProps}\n                      clsPrefix={this.mergedClsPrefix}\n                      showArrow={this.showArrow}\n                      maxTagCount={this.maxTagCount}\n                      ellipsisTagPopoverProps={this.ellipsisTagPopoverProps}\n                      bordered={this.mergedBordered}\n                      active={this.activeWithoutMenuOpen || this.mergedShow}\n                      pattern={this.pattern}\n                      placeholder={this.localizedPlaceholder}\n                      selectedOption={this.selectedOption}\n                      selectedOptions={this.selectedOptions}\n                      multiple={this.multiple}\n                      renderTag={this.renderTag}\n                      renderLabel={this.renderLabel}\n                      filterable={this.filterable}\n                      clearable={this.clearable}\n                      disabled={this.mergedDisabled}\n                      size={this.mergedSize}\n                      theme={this.mergedTheme.peers.InternalSelection}\n                      labelField={this.labelField}\n                      valueField={this.valueField}\n                      themeOverrides={\n                        this.mergedTheme.peerOverrides.InternalSelection\n                      }\n                      loading={this.loading}\n                      focused={this.focused}\n                      onClick={this.handleTriggerClick}\n                      onDeleteOption={this.handleDeleteOption}\n                      onPatternInput={this.handlePatternInput}\n                      onClear={this.handleClear}\n                      onBlur={this.handleTriggerBlur}\n                      onFocus={this.handleTriggerFocus}\n                      onKeydown={this.handleKeydown}\n                      onPatternBlur={this.onTriggerInputBlur}\n                      onPatternFocus={this.onTriggerInputFocus}\n                      onResize={this.handleTriggerOrMenuResize}\n                      ignoreComposition={this.ignoreComposition}\n                    >\n                      {{\n                        arrow: () => [this.$slots.arrow?.()]\n                      }}\n                    </NInternalSelection>\n                  )\n                }}\n              </VTarget>,\n              <VFollower\n                ref=\"followerRef\"\n                show={this.mergedShow}\n                to={this.adjustedTo}\n                teleportDisabled={this.adjustedTo === useAdjustedTo.tdkey}\n                containerClass={this.namespace}\n                width={this.consistentMenuWidth ? 'target' : undefined}\n                minWidth=\"target\"\n                placement={this.placement}\n              >\n                {{\n                  default: () => (\n                    <Transition\n                      name=\"fade-in-scale-up-transition\"\n                      appear={this.isMounted}\n                      onAfterLeave={this.handleMenuAfterLeave}\n                    >\n                      {{\n                        default: () => {\n                          if (\n                            !(\n                              this.mergedShow\n                              || this.displayDirective === 'show'\n                            )\n                          ) {\n                            return null\n                          }\n                          this.onRender?.()\n                          return withDirectives(\n                            <NInternalSelectMenu\n                              {...this.menuProps}\n                              ref=\"menuRef\"\n                              onResize={this.handleTriggerOrMenuResize}\n                              inlineThemeDisabled={this.inlineThemeDisabled}\n                              virtualScroll={\n                                this.consistentMenuWidth && this.virtualScroll\n                              }\n                              class={[\n                                `${this.mergedClsPrefix}-select-menu`,\n                                this.themeClass,\n                                this.menuProps?.class\n                              ]}\n                              clsPrefix={this.mergedClsPrefix}\n                              focusable\n                              labelField={this.labelField}\n                              valueField={this.valueField}\n                              autoPending={true}\n                              nodeProps={this.nodeProps}\n                              theme={this.mergedTheme.peers.InternalSelectMenu}\n                              themeOverrides={\n                                this.mergedTheme.peerOverrides\n                                  .InternalSelectMenu\n                              }\n                              treeMate={this.treeMate}\n                              multiple={this.multiple}\n                              size={this.menuSize}\n                              renderOption={this.renderOption}\n                              renderLabel={this.renderLabel}\n                              value={this.mergedValue}\n                              style={[this.menuProps?.style, this.cssVars]}\n                              onToggle={this.handleToggle}\n                              onScroll={this.handleMenuScroll}\n                              onFocus={this.handleMenuFocus}\n                              onBlur={this.handleMenuBlur}\n                              onKeydown={this.handleMenuKeydown}\n                              onTabOut={this.handleMenuTabOut}\n                              onMousedown={this.handleMenuMousedown}\n                              show={this.mergedShow}\n                              showCheckmark={this.showCheckmark}\n                              resetMenuOnOptionsChange={\n                                this.resetMenuOnOptionsChange\n                              }\n                              scrollbarProps={this.scrollbarProps}\n                            >\n                              {{\n                                empty: () => [this.$slots.empty?.()],\n                                header: () => [this.$slots.header?.()],\n                                action: () => [this.$slots.action?.()]\n                              }}\n                            </NInternalSelectMenu>,\n                            this.displayDirective === 'show'\n                              ? [\n                                  [vShow, this.mergedShow],\n                                  [\n                                    clickoutside,\n                                    this.handleMenuClickOutside,\n                                    undefined as unknown as string,\n                                    { capture: true }\n                                  ]\n                                ]\n                              : [\n                                  [\n                                    clickoutside,\n                                    this.handleMenuClickOutside,\n                                    undefined as unknown as string,\n                                    { capture: true }\n                                  ]\n                                ]\n                          )\n                        }\n                      }}\n                    </Transition>\n                  )\n                }}\n              </VFollower>\n            ]\n          }}\n        </VBinder>\n      </div>\n    )\n  }\n})\n"
  },
  {
    "path": "src/select/src/interface.ts",
    "content": "import type { TreeMate } from 'treemate'\nimport type { CSSProperties, VNode, VNodeChild } from 'vue'\n\nexport type SelectMixedOption\n  = | SelectBaseOption\n    | SelectGroupOption\n    | SelectIgnoredOption\n\nexport interface SelectBaseOption<\n  V = string | number,\n  L = string | ((option: SelectBaseOption<V>, selected: boolean) => VNodeChild)\n> {\n  value?: V\n  label?: L\n  class?: string\n  style?: string | CSSProperties\n  disabled?: boolean\n  render?: (info: {\n    node: VNode\n    option: SelectBaseOption<V>\n    selected: boolean\n  }) => VNodeChild\n  [k: string]: unknown\n}\n\nexport interface SelectGroupOptionBase {\n  label?: string | ((option: SelectGroupOption) => VNodeChild)\n  type: 'group'\n  children?: SelectBaseOption[]\n  render?: (info: { node: VNode, option: SelectGroupOption }) => VNodeChild\n  [k: string]: unknown\n}\n\nexport interface SelectIgnoredOption {\n  type: 'ignored'\n  value: string | number\n  [k: string]: unknown\n}\n\nexport type ValueAtom = string | number\nexport type Value = ValueAtom | string[] | number[] | ValueAtom[]\nexport type OnUpdateValue = (\n  value: string\n    & number\n    & ValueAtom\n    & string[]\n    & number[]\n    & ValueAtom[]\n    & (ValueAtom | null)\n    & (string[] | null)\n    & (number[] | null)\n    & (ValueAtom[] | null),\n  option: SelectBaseOption & null & SelectBaseOption[]\n) => void\nexport type OnUpdateValueImpl = (\n  value:\n    | ValueAtom\n    | string[]\n    | number[]\n    | ValueAtom[]\n    | (ValueAtom | null)\n    | (string[] | null)\n    | (number[] | null)\n    | (ValueAtom[] | null),\n  option: SelectBaseOption | null | SelectBaseOption[]\n) => void\nexport type SelectTreeMate = TreeMate<\n  SelectBaseOption,\n  SelectGroupOption,\n  SelectIgnoredOption\n>\n\n// Public interfaces\nexport type SelectOption = SelectBaseOption<string | number>\nexport type SelectGroupOption\n  = | (SelectGroupOptionBase & {\n    /** @deprecated should use key and label instead */\n    name?: string\n  })\n  | (SelectGroupOptionBase & {\n    key: string | number\n  })\n\nexport interface SelectInst {\n  focus: () => void\n  blur: () => void\n  focusInput: () => void\n  blurInput: () => void\n}\n\nexport type SelectFallbackOption = (value: string & number) => SelectOption\nexport type SelectFallbackOptionImpl = (value: string | number) => SelectOption\nexport type SelectFilter = (pattern: string, option: SelectOption) => boolean\n"
  },
  {
    "path": "src/select/src/public-types.ts",
    "content": "export type SelectSize = 'tiny' | 'small' | 'medium' | 'large'\n"
  },
  {
    "path": "src/select/src/styles/index.cssr.ts",
    "content": "import { fadeInScaleUpTransition } from '../../../_styles/transitions/fade-in-scale-up.cssr'\nimport { c, cB } from '../../../_utils/cssr'\n\n// --n-menu-box-shadow\nexport default c([\n  cB('select', `\n    z-index: auto;\n    outline: none;\n    width: 100%;\n    position: relative;\n    font-weight: var(--n-font-weight);\n  `),\n  cB('select-menu', `\n    margin: 4px 0;\n    box-shadow: var(--n-menu-box-shadow);\n  `, [\n    fadeInScaleUpTransition({\n      originalTransition: 'background-color .3s var(--n-bezier), box-shadow .3s var(--n-bezier)'\n    })\n  ])\n])\n"
  },
  {
    "path": "src/select/src/utils.ts",
    "content": "import type { TreeMateOptions } from 'treemate'\nimport type {\n  SelectBaseOption,\n  SelectGroupOption,\n  SelectIgnoredOption,\n  SelectMixedOption,\n  SelectOption\n} from './interface'\n\nexport function getIsGroup(option: SelectMixedOption): boolean {\n  return option.type === 'group'\n}\n\nexport function getIgnored(option: SelectMixedOption): boolean {\n  return option.type === 'ignored'\n}\n\nexport function patternMatched(pattern: string, value: string): boolean {\n  try {\n    return !!(\n      1 + value.toString().toLowerCase().indexOf(pattern.trim().toLowerCase())\n    )\n  }\n  catch {\n    return false\n  }\n}\n\nexport function createTmOptions(\n  valueField: string,\n  childrenField: string\n): TreeMateOptions<SelectBaseOption, SelectGroupOption, SelectIgnoredOption> {\n  const options: TreeMateOptions<\n    SelectBaseOption,\n    SelectGroupOption,\n    SelectIgnoredOption\n  > = {\n    getIsGroup,\n    getIgnored,\n    getKey(option: SelectMixedOption): string | number {\n      if (getIsGroup(option)) {\n        return (\n          ((option as SelectGroupOption).name as any)\n          || (option as SelectGroupOption).key\n          || 'key-required'\n        )\n      }\n      // Required for non-custom label & value field\n      return (option as SelectBaseOption | SelectIgnoredOption)[\n        valueField\n      ] as NonNullable<SelectOption['value']>\n    },\n    getChildren(option) {\n      return option[childrenField] as SelectBaseOption[]\n    }\n  }\n  return options\n}\n\nexport function filterOptions(\n  originalOpts: SelectMixedOption[],\n  filter: (pattern: string, option: SelectBaseOption) => boolean,\n  pattern: string,\n  childrenField: string\n): SelectMixedOption[] {\n  if (!filter)\n    return originalOpts\n  function traverse(options: SelectMixedOption[]): SelectMixedOption[] {\n    if (!Array.isArray(options))\n      return []\n    const filteredOptions: SelectMixedOption[] = []\n    for (const option of options) {\n      if (getIsGroup(option)) {\n        const children = traverse(option[childrenField] as SelectBaseOption[])\n        if (children.length) {\n          filteredOptions.push(\n            Object.assign({}, option, {\n              [childrenField]: children\n            })\n          )\n        }\n      }\n      else if (getIgnored(option)) {\n        continue\n      }\n      else if (filter(pattern, option as SelectBaseOption)) {\n        filteredOptions.push(option)\n      }\n    }\n    return filteredOptions\n  }\n  return traverse(originalOpts)\n}\n\nexport function createValOptMap(\n  options: SelectMixedOption[],\n  valueField: string,\n  childrenField: string\n): Map<string | number, SelectBaseOption> {\n  const valOptMap = new Map<string | number, SelectBaseOption>()\n  options.forEach((option) => {\n    if (getIsGroup(option)) {\n      ;(option[childrenField] as SelectBaseOption[]).forEach(\n        (selectGroupOption: SelectBaseOption) => {\n          valOptMap.set(\n            selectGroupOption[valueField] as NonNullable<\n              SelectBaseOption['value']\n            >,\n            selectGroupOption\n          )\n        }\n      )\n    }\n    else {\n      valOptMap.set(\n        option[valueField] as NonNullable<SelectBaseOption['value']>,\n        option as SelectBaseOption\n      )\n    }\n  })\n  return valOptMap\n}\n"
  },
  {
    "path": "src/select/styles/dark.ts",
    "content": "import type { SelectTheme } from './light'\nimport { internalSelectMenuDark } from '../../_internal/select-menu/styles'\nimport { internalSelectionDark } from '../../_internal/selection/styles'\nimport { commonDark } from '../../_styles/common'\nimport { self } from './light'\n\nconst selectDark: SelectTheme = {\n  name: 'Select',\n  common: commonDark,\n  peers: {\n    InternalSelection: internalSelectionDark,\n    InternalSelectMenu: internalSelectMenuDark\n  },\n  self\n}\n\nexport default selectDark\n"
  },
  {
    "path": "src/select/styles/index.ts",
    "content": "export { default as selectDark } from './dark'\nexport { default as selectLight } from './light'\nexport type { SelectTheme, SelectThemeVars } from './light'\nexport { selectRtl } from './rtl'\n"
  },
  {
    "path": "src/select/styles/light.ts",
    "content": "import type { ThemeCommonVars } from '../../_styles/common'\nimport { internalSelectMenuLight } from '../../_internal/select-menu/styles'\nimport { internalSelectionLight } from '../../_internal/selection/styles'\nimport { createTheme } from '../../_mixins'\nimport { commonLight } from '../../_styles/common'\n\nexport function self(vars: ThemeCommonVars) {\n  const { boxShadow2 } = vars\n  return {\n    menuBoxShadow: boxShadow2\n  }\n}\n\nconst selectLight = createTheme({\n  name: 'Select',\n  common: commonLight,\n  peers: {\n    InternalSelection: internalSelectionLight,\n    InternalSelectMenu: internalSelectMenuLight\n  },\n  self\n})\n\nexport default selectLight\nexport type SelectThemeVars = ReturnType<typeof self>\nexport type SelectTheme = typeof selectLight\n"
  },
  {
    "path": "src/select/styles/rtl.ts",
    "content": "import type { RtlItem } from '../../config-provider/src/internal-interface'\nimport { scrollbarRtl } from '../../_internal/scrollbar/styles'\nimport { internalSelectMenuRtl } from '../../_internal/select-menu/styles'\nimport { internalSelectionRtl } from '../../_internal/selection/styles'\nimport { c } from '../../_utils/cssr'\nimport { tagRtl } from '../../tag/styles'\n\nexport const selectRtl: RtlItem = {\n  name: 'Select',\n  style: c([]),\n  peers: [internalSelectionRtl, internalSelectMenuRtl, tagRtl, scrollbarRtl]\n}\n"
  },
  {
    "path": "src/select/tests/Select.spec.tsx",
    "content": "import type { VNode } from 'vue'\nimport type { SelectGroupOption, SelectOption, SelectProps } from '../index'\nimport type { SelectBaseOption } from '../src/interface'\nimport { mount } from '@vue/test-utils'\nimport { h, nextTick } from 'vue'\nimport { NInternalSelection, NInternalSelectMenu } from '../../_internal'\nimport { NTag } from '../../tag'\nimport { NSelect } from '../index'\n\ndescribe('n-select', () => {\n  it('should work with import on demand', () => {\n    mount(NSelect)\n  })\n  it('show menu when trigger clicked', async () => {\n    const wrapper = mount(NSelect)\n    const inputWrapper = wrapper.findComponent(NInternalSelection)\n    expect(wrapper.findComponent(NInternalSelectMenu).exists()).toEqual(false)\n    await inputWrapper.trigger('click')\n    expect(wrapper.findComponent(NInternalSelectMenu).isVisible()).toEqual(true)\n    await inputWrapper.trigger('click')\n    expect(wrapper.findComponent(NInternalSelectMenu).isVisible()).toEqual(\n      false\n    )\n    wrapper.unmount()\n  })\n  it('props.show', () => {\n    const wrapper = mount(NSelect, {\n      props: {\n        show: true\n      }\n    })\n    expect(wrapper.findComponent(NInternalSelectMenu).exists()).toEqual(true)\n    wrapper.unmount()\n  })\n  describe('props.option', () => {\n    it('has correct type', () => {\n      const options: SelectProps['options'] = [\n        {\n          label: 'cool1',\n          value: 'cool1'\n        },\n        {\n          type: 'group',\n          label: 'cool',\n          key: 'group cool',\n          children: [\n            {\n              label: 'cool2',\n              value: 'cool2'\n            }\n          ]\n        }\n      ]\n      mount(() => <NSelect options={options} />).unmount()\n    })\n    it('option.label as render function', () => {\n      const options: SelectProps['options'] = [\n        {\n          label: () => 'cool1+1',\n          value: 'cool1'\n        },\n        {\n          type: 'group',\n          label: () => 'cool1+2',\n          key: 'group cool',\n          children: [\n            {\n              label: () => 'cool1+3',\n              value: 'cool2'\n            }\n          ]\n        }\n      ]\n      const wrapper = mount(NSelect, {\n        props: {\n          options,\n          show: true,\n          virtualScroll: false\n        }\n      })\n      const menuWrapper = wrapper.findComponent(NInternalSelectMenu)\n      expect(\n        ['cool1+1', 'cool1+2', 'cool1+3'].every(label =>\n          menuWrapper.text().includes(label)\n        )\n      ).toEqual(true)\n      wrapper.unmount()\n    })\n    it('option.render', () => {\n      const options: SelectProps['options'] = [\n        {\n          label: 'cool1',\n          value: 'cool1',\n          render: ({ node, option }: { node: VNode, option: SelectOption }) => {\n            expect(option.label).toEqual('cool1')\n            return <div class=\"cool1\">{node}</div>\n          }\n        },\n        {\n          type: 'group',\n          label: 'cool2',\n          key: 'group cool',\n          render: ({\n            node,\n            option\n          }: {\n            node: VNode\n            option: SelectGroupOption\n          }) => {\n            expect(option.label).toEqual('cool2')\n            return <div class=\"cool2\">{node}</div>\n          },\n          children: [\n            {\n              label: 'cool3',\n              value: 'cool3',\n              render: ({ node, option }) => {\n                expect(option.label).toEqual('cool3')\n                return <div class=\"cool3\">{node}</div>\n              }\n            }\n          ]\n        }\n      ]\n      const wrapper = mount(NSelect, {\n        props: {\n          options,\n          show: true,\n          virtualScroll: false\n        }\n      })\n      const menuWrapper = wrapper.findComponent(NInternalSelectMenu)\n      expect(menuWrapper.find('.cool1').exists()).toEqual(true)\n      expect(menuWrapper.find('.cool2').exists()).toEqual(true)\n      expect(menuWrapper.find('.cool3').exists()).toEqual(true)\n      wrapper.unmount()\n    })\n    it('props.renderOption', () => {\n      const renderOption: SelectProps['renderOption'] = ({\n        node,\n        option\n      }: {\n        node: VNode\n        option: SelectOption | SelectGroupOption\n      }) => <div class={option.label}>{node}</div>\n      const options: SelectProps['options'] = [\n        {\n          label: 'cool1',\n          value: 'cool1'\n        },\n        {\n          type: 'group',\n          label: 'cool2',\n          key: 'group cool',\n          children: [\n            {\n              label: 'cool3',\n              value: 'cool3',\n              render: ({ node, option }) => {\n                expect(option.label).toEqual('cool3')\n                return <div class=\"cool3\">{node}</div>\n              }\n            }\n          ]\n        }\n      ]\n      const wrapper = mount(NSelect, {\n        props: {\n          options,\n          show: true,\n          virtualScroll: false,\n          renderOption\n        }\n      })\n      const menuWrapper = wrapper.findComponent(NInternalSelectMenu)\n      expect(menuWrapper.find('.cool1').exists()).toEqual(true)\n      expect(menuWrapper.find('.cool2').exists()).toEqual(true)\n      expect(menuWrapper.find('.cool3').exists()).toEqual(true)\n      wrapper.unmount()\n    })\n  })\n\n  it('should work with `render-tag` prop', async () => {\n    const options = [\n      {\n        label: 'test',\n        value: 'test',\n        type: 'success'\n      }\n    ]\n\n    const wrapper = mount(NSelect, {\n      props: {\n        defaultValue: ['test'],\n        options,\n        multiple: true,\n        virtualScroll: false,\n        renderTag: ({\n          option,\n          handleClose\n        }: {\n          option: SelectBaseOption\n          handleClose: () => void\n        }) => {\n          return h(\n            NTag,\n            {\n              type: option.type as 'success',\n              closable: true,\n              onClose: handleClose\n            },\n            { default: () => option.label }\n          )\n        }\n      }\n    })\n\n    expect(wrapper.find('.n-base-selection-tag-wrapper').exists()).toBe(true)\n    expect(wrapper.findComponent(NTag).exists()).toBe(true)\n    expect(wrapper.findComponent(NTag).props('type')).toContain('success')\n    await wrapper.find('.n-tag__close').trigger('click')\n    expect(wrapper.findComponent(NTag).exists()).toBe(false)\n    wrapper.unmount()\n  })\n\n  it('should work with `render-label` prop', async () => {\n    const options = [\n      {\n        label: 'test',\n        value: 'test'\n      }\n    ]\n\n    const wrapper = mount(NSelect, {\n      attachTo: document.body,\n      props: {\n        defaultValue: 'test',\n        options,\n        virtualScroll: false,\n        renderLabel: (option: SelectOption) => {\n          return `render-${String(option.label)}`\n        }\n      }\n    })\n\n    expect(wrapper.find('.n-base-selection-input').text()).toBe('render-test')\n    await wrapper.setProps({ show: true })\n    await nextTick()\n    expect(\n      document.querySelector('.n-base-select-option--selected')?.innerHTML\n    ).toContain('render-test')\n    wrapper.unmount()\n  })\n\n  it('should work with `disabled` prop', async () => {\n    const wrapper = mount(NSelect)\n\n    expect(wrapper.find('.n-base-selection').classes()).not.toContain(\n      'n-base-selection--disabled'\n    )\n    await wrapper.setProps({\n      disabled: true\n    })\n    expect(wrapper.find('.n-base-selection').classes()).toContain(\n      'n-base-selection--disabled'\n    )\n    wrapper.unmount()\n  })\n\n  it('should work with `filterable` prop', async () => {\n    const wrapper = mount(NSelect)\n\n    expect(wrapper.find('input').exists()).not.toBe(true)\n    expect(wrapper.find('.n-base-selection-input').exists()).not.toBe(true)\n    await wrapper.setProps({\n      filterable: true\n    })\n    expect(wrapper.find('input').exists()).toBe(true)\n    expect(wrapper.find('.n-base-selection-input').exists()).toBe(true)\n    wrapper.unmount()\n  })\n\n  it('should work with `loading` prop', async () => {\n    const wrapper = mount(NSelect)\n\n    expect(wrapper.find('.n-base-loading__container').exists()).not.toBe(true)\n    await wrapper.setProps({\n      loading: true\n    })\n    expect(wrapper.find('.n-base-loading__container').exists()).toBe(true)\n    wrapper.unmount()\n  })\n\n  it('should work with `multiple` prop', async () => {\n    const wrapper = mount(NSelect)\n\n    expect(wrapper.find('.n-base-selection').classes()).not.toContain(\n      'n-base-selection--multiple'\n    )\n    await wrapper.setProps({\n      multiple: true\n    })\n    expect(wrapper.find('.n-base-selection').classes()).toContain(\n      'n-base-selection--multiple'\n    )\n    wrapper.unmount()\n  })\n\n  it('should work with `placeholder` prop', async () => {\n    const wrapper = mount(NSelect, {\n      props: {\n        placeholder: 'test'\n      }\n    })\n    expect(wrapper.find('.n-base-selection-placeholder').text()).toBe('test')\n    wrapper.unmount()\n  })\n\n  it('should work with `size` prop', async () => {\n    ;(['small', 'medium', 'large'] as const).forEach((i) => {\n      const wrapper = mount(NSelect, { props: { size: i } })\n      expect(\n        wrapper.find('.n-base-selection').attributes('style')\n      ).toMatchSnapshot()\n      wrapper.unmount()\n    })\n  })\n\n  it('should work with `themeOverrides` prop', async () => {\n    const selectThemeOverrides = {\n      peers: {\n        InternalSelectMenu: {\n          peers: {\n            Empty: {\n              textColor: '#4fb233'\n            }\n          }\n        }\n      }\n    }\n    const wrapper = mount(NSelect, {\n      props: {\n        themeOverrides: selectThemeOverrides,\n        show: true\n      }\n    })\n    const menuWrapper = wrapper.findComponent(NInternalSelectMenu)\n    expect(\n      menuWrapper\n        .find('.n-base-select-menu__empty .n-empty')\n        .attributes('style')\n    ).toContain('--n-text-color: #4fb233;')\n    wrapper.unmount()\n  })\n\n  it('should work with `menuProps` prop', () => {\n    const menuProps = {\n      class: 'menu-test',\n      style: {\n        background: 'rgb(79, 178, 51)'\n      }\n    }\n    const wrapper = mount(NSelect, {\n      props: {\n        menuProps,\n        show: true\n      }\n    })\n    const menuWrapper = wrapper.findComponent(NInternalSelectMenu)\n    expect(menuWrapper.attributes('style')).toContain(\n      'background: rgb(79, 178, 51);'\n    )\n    expect(menuWrapper.classes()).toContain('menu-test')\n    wrapper.unmount()\n  })\n\n  it('should work with `action` slot', () => {\n    const wrapper = mount(NSelect, {\n      props: {\n        show: true\n      },\n      slots: {\n        action: () => 'test-action-slot'\n      }\n    })\n    const menuWrapper = wrapper.findComponent(NInternalSelectMenu)\n    expect(menuWrapper.find('.n-base-select-menu__action').exists()).toBe(true)\n    expect(menuWrapper.find('.n-base-select-menu__action').text()).toContain(\n      'test-action-slot'\n    )\n    wrapper.unmount()\n  })\n\n  it('should work with `empty` slot', () => {\n    const wrapper = mount(NSelect, {\n      props: {\n        show: true\n      },\n      slots: {\n        empty: () => 'test-empty-slot'\n      }\n    })\n    const menuWrapper = wrapper.findComponent(NInternalSelectMenu)\n    expect(menuWrapper.find('.n-base-select-menu__empty').exists()).toBe(true)\n    expect(menuWrapper.find('.n-base-select-menu__empty').text()).toContain(\n      'test-empty-slot'\n    )\n    wrapper.unmount()\n  })\n})\n"
  },
  {
    "path": "src/select/tests/__snapshots__/Select.spec.tsx.snap",
    "content": "// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html\n\nexports[`n-select > should work with \\`size\\` prop 1`] = `\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-border: 1px solid rgb(224, 224, 230); --n-border-active: 1px solid #18a058; --n-border-focus: 1px solid #36ad6a; --n-border-hover: 1px solid #36ad6a; --n-border-radius: 3px; --n-box-shadow-active: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-box-shadow-hover: none; --n-caret-color: #18a058; --n-color: rgba(255, 255, 255, 1); --n-color-active: rgba(255, 255, 255, 1); --n-color-disabled: rgb(250, 250, 252); --n-font-size: 14px; --n-height: 28px; --n-padding-single-top: 0; --n-padding-multiple-top: 3px; --n-padding-single-right: 26px; --n-padding-multiple-right: 26px; --n-padding-single-left: 12px; --n-padding-multiple-left: 12px; --n-padding-single-bottom: 0; --n-padding-multiple-bottom: 0; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-text-color: rgb(51, 54, 57); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-arrow-color: rgba(194, 194, 194, 1); --n-arrow-color-disabled: rgba(209, 209, 209, 1); --n-loading-color: #18a058; --n-color-active-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-box-shadow-active-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-box-shadow-hover-warning: none; --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-border-active-warning: 1px solid #f0a020; --n-color-active-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-box-shadow-active-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-box-shadow-hover-error: none; --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-border-active-error: 1px solid #d03050; --n-clear-size: 16px; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-arrow-size: 16px; --n-font-weight: 400;\"`;\n\nexports[`n-select > should work with \\`size\\` prop 2`] = `\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-border: 1px solid rgb(224, 224, 230); --n-border-active: 1px solid #18a058; --n-border-focus: 1px solid #36ad6a; --n-border-hover: 1px solid #36ad6a; --n-border-radius: 3px; --n-box-shadow-active: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-box-shadow-hover: none; --n-caret-color: #18a058; --n-color: rgba(255, 255, 255, 1); --n-color-active: rgba(255, 255, 255, 1); --n-color-disabled: rgb(250, 250, 252); --n-font-size: 14px; --n-height: 34px; --n-padding-single-top: 0; --n-padding-multiple-top: 3px; --n-padding-single-right: 26px; --n-padding-multiple-right: 26px; --n-padding-single-left: 12px; --n-padding-multiple-left: 12px; --n-padding-single-bottom: 0; --n-padding-multiple-bottom: 0; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-text-color: rgb(51, 54, 57); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-arrow-color: rgba(194, 194, 194, 1); --n-arrow-color-disabled: rgba(209, 209, 209, 1); --n-loading-color: #18a058; --n-color-active-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-box-shadow-active-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-box-shadow-hover-warning: none; --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-border-active-warning: 1px solid #f0a020; --n-color-active-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-box-shadow-active-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-box-shadow-hover-error: none; --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-border-active-error: 1px solid #d03050; --n-clear-size: 16px; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-arrow-size: 16px; --n-font-weight: 400;\"`;\n\nexports[`n-select > should work with \\`size\\` prop 3`] = `\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-border: 1px solid rgb(224, 224, 230); --n-border-active: 1px solid #18a058; --n-border-focus: 1px solid #36ad6a; --n-border-hover: 1px solid #36ad6a; --n-border-radius: 3px; --n-box-shadow-active: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-box-shadow-hover: none; --n-caret-color: #18a058; --n-color: rgba(255, 255, 255, 1); --n-color-active: rgba(255, 255, 255, 1); --n-color-disabled: rgb(250, 250, 252); --n-font-size: 15px; --n-height: 40px; --n-padding-single-top: 0; --n-padding-multiple-top: 3px; --n-padding-single-right: 26px; --n-padding-multiple-right: 26px; --n-padding-single-left: 12px; --n-padding-multiple-left: 12px; --n-padding-single-bottom: 0; --n-padding-multiple-bottom: 0; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-text-color: rgb(51, 54, 57); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-arrow-color: rgba(194, 194, 194, 1); --n-arrow-color-disabled: rgba(209, 209, 209, 1); --n-loading-color: #18a058; --n-color-active-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-box-shadow-active-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-box-shadow-hover-warning: none; --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-border-active-warning: 1px solid #f0a020; --n-color-active-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-box-shadow-active-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-box-shadow-hover-error: none; --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-border-active-error: 1px solid #d03050; --n-clear-size: 16px; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-arrow-size: 16px; --n-font-weight: 400;\"`;\n"
  },
  {
    "path": "src/select/tests/server.spec.tsx",
    "content": "import { setup } from '@css-render/vue3-ssr'\nimport { renderToString } from '@vue/server-renderer'\n/**\n * @vitest-environment node\n */\nimport { createSSRApp, h } from 'vue'\nimport { NSelect } from '../..'\n\ndescribe('server side rendering', () => {\n  it('works', async () => {\n    const app = createSSRApp(() => <NSelect />)\n    setup(app)\n    try {\n      await renderToString(app)\n    }\n    catch (e) {\n      expect(e).not.toBeTruthy()\n    }\n  })\n})\n"
  },
  {
    "path": "src/shims-vue.d.ts",
    "content": "// shims-vue.d.ts\ndeclare module '*.vue' {\n  import type { DefineComponent } from 'vue'\n\n  const component: DefineComponent<\n    Record<string, unknown>,\n    Record<string, unknown>,\n    any\n  >\n  export default component\n}\n"
  },
  {
    "path": "src/skeleton/demos/enUS/basic.demo.vue",
    "content": "<markdown>\n# Basic usage\n\nUse `text` to create text skeleton.\n</markdown>\n\n<template>\n  <n-skeleton text :repeat=\"2\" /> <n-skeleton text style=\"width: 60%\" />\n</template>\n"
  },
  {
    "path": "src/skeleton/demos/enUS/box.demo.vue",
    "content": "<markdown>\n# Box\n\nUse it as a box.\n</markdown>\n\n<template>\n  <n-space vertical>\n    <n-skeleton height=\"40px\" width=\"33%\" />\n    <n-skeleton height=\"40px\" width=\"66%\" :sharp=\"false\" />\n    <n-skeleton height=\"40px\" round />\n    <n-skeleton height=\"40px\" circle />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/skeleton/demos/enUS/index.demo-entry.md",
    "content": "# Skeleton\n\nA twinkle placeholder.\n\n## Demos\n\n```demo\nbasic.vue\nbox.vue\nsize.vue\n```\n\n## API\n\n### Skeleton Props\n\n| Name | Type | Default | Description |\n| --- | --- | --- | --- |\n| text | `boolean` | `false` | Text skeleton. |\n| round | `boolean` | `false` | Round skeleton. |\n| circle | `boolean` | `false` | Circle skeleton. |\n| height | `string \\| number` | `undefined` | Skeleton height. |\n| width | `string \\| number` | `undefined` | Skeleton width. |\n| size | `'small' \\| 'medium' \\| 'large'` | `undefined` | Skeleton size. |\n| repeat | `string \\| number` | `1` | Repeat frequency. |\n| animated | `boolean` | `true` | Whether to enable animation. |\n| sharp | `boolean` | `true` | Whether to display as a right angled skeleton. |\n"
  },
  {
    "path": "src/skeleton/demos/enUS/size.demo.vue",
    "content": "<markdown>\n# Size\n\nUse `size` to make its height the same as other components.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst loading = ref(true)\n</script>\n\n<template>\n  <n-space vertical>\n    <n-space><n-switch v-model:value=\"loading\" />Loading</n-space>\n    <n-space>\n      <n-skeleton v-if=\"loading\" :width=\"146\" :sharp=\"false\" size=\"medium\" />\n      <n-button v-else>\n        Won't you fly high\n      </n-button>\n      <n-skeleton v-if=\"loading\" :width=\"132\" round size=\"medium\" />\n      <n-button v-else round>\n        free bird, yeah\n      </n-button>\n      <n-skeleton v-if=\"loading\" circle size=\"medium\" />\n      <n-button v-else circle>\n        ?\n      </n-button>\n    </n-space>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/skeleton/demos/zhCN/basic.demo.vue",
    "content": "<markdown>\n# 基础用法\n\n使用 `text` 设定文本骨架。\n</markdown>\n\n<template>\n  <n-skeleton text :repeat=\"2\" /> <n-skeleton text style=\"width: 60%\" />\n</template>\n"
  },
  {
    "path": "src/skeleton/demos/zhCN/box.demo.vue",
    "content": "<markdown>\n# 盒子\n\n把它当成个块用。\n</markdown>\n\n<template>\n  <n-space vertical>\n    <n-skeleton height=\"40px\" width=\"33%\" />\n    <n-skeleton height=\"40px\" width=\"66%\" :sharp=\"false\" />\n    <n-skeleton height=\"40px\" round />\n    <n-skeleton height=\"40px\" circle />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/skeleton/demos/zhCN/index.demo-entry.md",
    "content": "# 骨架屏 Skeleton\n\n可以闪的占位符。\n\n## 演示\n\n```demo\nbasic.vue\nbox.vue\nsize.vue\n```\n\n## API\n\n### Skeleton Props\n\n| 名称 | 类型 | 默认值 | 说明 |\n| --- | --- | --- | --- |\n| text | `boolean` | `false` | 文本骨架 |\n| round | `boolean` | `false` | 圆角骨架 |\n| circle | `boolean` | `false` | 圆形骨架 |\n| height | `string \\| number` | `undefined` | 骨架高度 |\n| width | `string \\| number` | `undefined` | 骨架宽度 |\n| size | `'small' \\| 'medium' \\| 'large'` | `undefined` | 骨架大小 |\n| repeat | `string \\| number` | `1` | 重复次数 |\n| animated | `boolean` | `true` | 是否启用动画 |\n| sharp | `boolean` | `true` | 是否显示为直角骨架 |\n"
  },
  {
    "path": "src/skeleton/demos/zhCN/size.demo.vue",
    "content": "<markdown>\n# 尺寸\n\n使用 `size` 装成其他组件。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst loading = ref(true)\n</script>\n\n<template>\n  <n-space vertical>\n    <n-space><n-switch v-model:value=\"loading\" />加载</n-space>\n    <n-space>\n      <n-skeleton v-if=\"loading\" :width=\"146\" :sharp=\"false\" size=\"medium\" />\n      <n-button v-else>\n        Won't you fly high\n      </n-button>\n      <n-skeleton v-if=\"loading\" :width=\"132\" round size=\"medium\" />\n      <n-button v-else round>\n        free bird, yeah\n      </n-button>\n      <n-skeleton v-if=\"loading\" circle size=\"medium\" />\n      <n-button v-else circle>\n        ?\n      </n-button>\n    </n-space>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/skeleton/index.ts",
    "content": "export type * from './src/public-types'\nexport { default as NSkeleton, skeletonProps } from './src/Skeleton'\nexport type { SkeletonProps } from './src/Skeleton'\n"
  },
  {
    "path": "src/skeleton/src/Skeleton.tsx",
    "content": "import type { PropType } from 'vue'\nimport type { ThemeProps } from '../../_mixins'\nimport type { ExtractPublicPropTypes } from '../../_utils'\nimport type { SkeletonTheme } from '../styles'\nimport type { SkeletonSize } from './public-types'\nimport { pxfy, repeat } from 'seemly'\nimport { computed, defineComponent, Fragment, h, mergeProps } from 'vue'\nimport { useConfig, useTheme } from '../../_mixins'\nimport { createKey, useHoudini } from '../../_utils'\nimport { skeletonLight } from '../styles'\nimport style from './styles/index.cssr'\n\nexport const skeletonProps = {\n  ...(useTheme.props as ThemeProps<SkeletonTheme>),\n  text: Boolean,\n  round: Boolean,\n  circle: Boolean,\n  height: [String, Number] as PropType<string | number>,\n  width: [String, Number] as PropType<string | number>,\n  size: String as PropType<SkeletonSize>,\n  repeat: {\n    type: Number,\n    default: 1\n  },\n  animated: {\n    type: Boolean,\n    default: true\n  },\n  sharp: {\n    type: Boolean,\n    default: true\n  }\n} as const\n\nexport type SkeletonProps = ExtractPublicPropTypes<typeof skeletonProps>\n\nexport default defineComponent({\n  name: 'Skeleton',\n  inheritAttrs: false,\n  props: skeletonProps,\n  setup(props) {\n    useHoudini()\n    const { mergedClsPrefixRef, mergedComponentPropsRef } = useConfig(props)\n    const mergedSizeRef = computed(() => {\n      return props.size || mergedComponentPropsRef?.value?.Skeleton?.size\n    })\n    const themeRef = useTheme(\n      'Skeleton',\n      '-skeleton',\n      style,\n      skeletonLight,\n      props,\n      mergedClsPrefixRef\n    )\n    return {\n      mergedClsPrefix: mergedClsPrefixRef,\n      style: computed(() => {\n        const theme = themeRef.value\n        const {\n          common: { cubicBezierEaseInOut }\n        } = theme\n        const selfThemeVars = theme.self\n        const { color, colorEnd, borderRadius } = selfThemeVars\n        let sizeHeight: string | undefined\n        const { circle, sharp, round, width, height, text, animated } = props\n        const mergedSize = mergedSizeRef.value\n        if (mergedSize !== undefined) {\n          sizeHeight = selfThemeVars[createKey('height', mergedSize)]\n        }\n        const mergedWidth = circle ? (width ?? height ?? sizeHeight) : width\n        const mergedHeight = (circle ? (width ?? height) : height) ?? sizeHeight\n        return {\n          display: text ? 'inline-block' : '',\n          verticalAlign: text ? '-0.125em' : '',\n          borderRadius: circle\n            ? '50%'\n            : round\n              ? '4096px'\n              : sharp\n                ? ''\n                : borderRadius,\n          width:\n            typeof mergedWidth === 'number' ? pxfy(mergedWidth) : mergedWidth,\n          height:\n            typeof mergedHeight === 'number'\n              ? pxfy(mergedHeight)\n              : mergedHeight,\n          animation: !animated ? 'none' : '',\n          '--n-bezier': cubicBezierEaseInOut,\n          '--n-color-start': color,\n          '--n-color-end': colorEnd\n        }\n      })\n    }\n  },\n  render() {\n    const { repeat: repeatProp, style, mergedClsPrefix, $attrs } = this\n    // BUG:\n    // Chrome devtools can't read the element\n    // Maybe it's a bug of chrome\n    const child = h(\n      'div',\n      mergeProps(\n        {\n          class: `${mergedClsPrefix}-skeleton`,\n          style\n        },\n        $attrs\n      )\n    )\n    if (repeatProp > 1) {\n      return <>{repeat(repeatProp, null).map(_ => [child, '\\n'])}</>\n    }\n    return child\n  }\n})\n"
  },
  {
    "path": "src/skeleton/src/bug.md",
    "content": "## Chrome Devtool can't read prop of skeleton\n\n## ??? a `\\n` must be added when use it repeatly\n\n```html\n<style>\n  .a-skeleton {\n    display: inline-block;\n    height: 1em;\n    width: 100%;\n    background: green;\n  }\n\n  .a-space {\n    border: 1px solid black;\n  }\n</style>\n<div class=\"a-space\" style=\"display: flex; flex-flow: column wrap;\">\n  <div style=\"max-width: 100%\">\n    <div class=\"a-skeleton\"></div>\n    <div class=\"a-skeleton\"></div>\n    <div class=\"a-skeleton\"></div>\n  </div>\n</div>\n```\n"
  },
  {
    "path": "src/skeleton/src/public-types.ts",
    "content": "export type SkeletonSize = 'small' | 'medium' | 'large'\n"
  },
  {
    "path": "src/skeleton/src/styles/index.cssr.ts",
    "content": "import { c, cB } from '../../../_utils/cssr'\n\n// vars:\n// --n-color-start\n// --n-color-end\n// --n-bezier\nexport default c([\n  cB('skeleton', `\n    height: 1em;\n    width: 100%;\n    transition:\n      --n-color-start .3s var(--n-bezier),\n      --n-color-end .3s var(--n-bezier),\n      background-color .3s var(--n-bezier);\n    animation: 2s skeleton-loading infinite cubic-bezier(0.36, 0, 0.64, 1);\n    background-color: var(--n-color-start);\n  `),\n  c('@keyframes skeleton-loading', `\n    0% {\n      background: var(--n-color-start);\n    }\n    40% {\n      background: var(--n-color-end);\n    }\n    80% {\n      background: var(--n-color-start);\n    }\n    100% {\n      background: var(--n-color-start);\n    }\n  `)\n])\n"
  },
  {
    "path": "src/skeleton/styles/dark.ts",
    "content": "import type { SkeletonTheme } from './light'\nimport { commonDark } from '../../_styles/common'\n\nexport const skeletonDark: SkeletonTheme = {\n  name: 'Skeleton',\n  common: commonDark,\n  self(vars) {\n    const { heightSmall, heightMedium, heightLarge, borderRadius } = vars\n    return {\n      color: 'rgba(255, 255, 255, 0.12)',\n      colorEnd: 'rgba(255, 255, 255, 0.18)',\n      borderRadius,\n      heightSmall,\n      heightMedium,\n      heightLarge\n    }\n  }\n}\n"
  },
  {
    "path": "src/skeleton/styles/index.ts",
    "content": "export { skeletonDark } from './dark'\nexport { skeletonLight } from './light'\nexport type { SkeletonTheme, SkeletonThemeVars } from './light'\n"
  },
  {
    "path": "src/skeleton/styles/light.ts",
    "content": "import type { Theme } from '../../_mixins'\nimport type { ThemeCommonVars } from '../../_styles/common'\nimport { commonLight } from '../../_styles/common'\n\nfunction self(vars: ThemeCommonVars) {\n  const { heightSmall, heightMedium, heightLarge, borderRadius } = vars\n  return {\n    color: '#eee',\n    colorEnd: '#ddd',\n    borderRadius,\n    heightSmall,\n    heightMedium,\n    heightLarge\n  }\n}\n\nexport type SkeletonThemeVars = ReturnType<typeof self>\n\nexport const skeletonLight: Theme<'Skeleton', SkeletonThemeVars> = {\n  name: 'Skeleton',\n  common: commonLight,\n  self\n}\n\nexport type SkeletonTheme = typeof skeletonLight\n"
  },
  {
    "path": "src/skeleton/tests/Skeleton.spec.tsx",
    "content": "import { mount } from '@vue/test-utils'\nimport { NSkeleton } from '../index'\n\ndescribe('n-skeleton', () => {\n  it('should work with import on demand', () => {\n    mount(NSkeleton)\n  })\n\n  it('should work with `text` prop', async () => {\n    const wrapper = mount(NSkeleton, {\n      props: {\n        text: true\n      }\n    })\n    expect(wrapper.find('.n-skeleton').attributes('style')).toMatchSnapshot()\n    wrapper.unmount()\n  })\n\n  it('should work with box', async () => {\n    const wrapper = mount(NSkeleton)\n    expect(wrapper.find('.n-skeleton').attributes('style')).toMatchSnapshot()\n    wrapper.unmount()\n  })\n\n  it('should work with `sharp` prop', async () => {\n    const wrapper = mount(NSkeleton, {\n      props: {\n        sharp: false\n      }\n    })\n    expect(wrapper.find('.n-skeleton').attributes('style')).toMatchSnapshot()\n    wrapper.unmount()\n  })\n\n  it('should work with `round` prop', async () => {\n    const wrapper = mount(NSkeleton, {\n      props: {\n        round: true\n      }\n    })\n    expect(wrapper.find('.n-skeleton').attributes('style')).toMatchSnapshot()\n    wrapper.unmount()\n  })\n\n  it('should work with `circle` prop', async () => {\n    const wrapper = mount(NSkeleton, {\n      props: {\n        circle: true\n      }\n    })\n    expect(wrapper.find('.n-skeleton').attributes('style')).toMatchSnapshot()\n    wrapper.unmount()\n  })\n\n  it('should work with `repeat` prop', async () => {\n    const wrapper = mount(NSkeleton, {\n      props: {\n        repeat: 2\n      }\n    })\n    expect(wrapper.findAll('.n-skeleton').length).toBe(2)\n    wrapper.unmount()\n  })\n\n  it('should work with `size` prop', async () => {\n    const wrapper = mount(NSkeleton)\n\n    await wrapper.setProps({ size: 'small' })\n    expect(wrapper.find('.n-skeleton').attributes('style')).toMatchSnapshot()\n\n    await wrapper.setProps({ size: 'medium' })\n    expect(wrapper.find('.n-skeleton').attributes('style')).toMatchSnapshot()\n\n    await wrapper.setProps({ size: 'large' })\n    expect(wrapper.find('.n-skeleton').attributes('style')).toMatchSnapshot()\n    wrapper.unmount()\n  })\n\n  it('should show correct width', () => {\n    const wrapper = mount(NSkeleton, {\n      props: {\n        circle: false,\n        width: 100\n      }\n    })\n\n    expect(wrapper.find('.n-skeleton').attributes('style')).toContain(\n      'width: 100px;'\n    )\n    wrapper.unmount()\n  })\n\n  it('should show correct height', () => {\n    const wrapper = mount(NSkeleton, {\n      props: {\n        circle: false,\n        height: 100\n      }\n    })\n\n    expect(wrapper.find('.n-skeleton').attributes('style')).toContain(\n      'height: 100px;'\n    )\n    wrapper.unmount()\n  })\n\n  it('should show correct animation', () => {\n    const wrapper = mount(NSkeleton, {\n      props: {\n        animated: false\n      }\n    })\n\n    expect(wrapper.find('.n-skeleton').attributes('style')).toContain(\n      'animation: none;'\n    )\n    wrapper.unmount()\n  })\n})\n"
  },
  {
    "path": "src/skeleton/tests/__snapshots__/Skeleton.spec.tsx.snap",
    "content": "// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html\n\nexports[`n-skeleton > should work with \\`circle\\` prop 1`] = `\"border-radius: 50%; --n-bezier: cubic-bezier(.4, 0, .2, 1); --n-color-start: #eee; --n-color-end: #ddd;\"`;\n\nexports[`n-skeleton > should work with \\`round\\` prop 1`] = `\"border-radius: 4096px; --n-bezier: cubic-bezier(.4, 0, .2, 1); --n-color-start: #eee; --n-color-end: #ddd;\"`;\n\nexports[`n-skeleton > should work with \\`sharp\\` prop 1`] = `\"border-radius: 3px; --n-bezier: cubic-bezier(.4, 0, .2, 1); --n-color-start: #eee; --n-color-end: #ddd;\"`;\n\nexports[`n-skeleton > should work with \\`size\\` prop 1`] = `\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-color-start: #eee; --n-color-end: #ddd; height: 28px;\"`;\n\nexports[`n-skeleton > should work with \\`size\\` prop 2`] = `\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-color-start: #eee; --n-color-end: #ddd; height: 34px;\"`;\n\nexports[`n-skeleton > should work with \\`size\\` prop 3`] = `\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-color-start: #eee; --n-color-end: #ddd; height: 40px;\"`;\n\nexports[`n-skeleton > should work with \\`text\\` prop 1`] = `\"display: inline-block; vertical-align: -0.125em; --n-bezier: cubic-bezier(.4, 0, .2, 1); --n-color-start: #eee; --n-color-end: #ddd;\"`;\n\nexports[`n-skeleton > should work with box 1`] = `\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-color-start: #eee; --n-color-end: #ddd;\"`;\n"
  },
  {
    "path": "src/skeleton/tests/server.spec.tsx",
    "content": "import { setup } from '@css-render/vue3-ssr'\nimport { renderToString } from '@vue/server-renderer'\n/**\n * @vitest-environment node\n */\nimport { createSSRApp, h } from 'vue'\nimport { NSkeleton } from '../..'\n\ndescribe('server side rendering', () => {\n  it('works', async () => {\n    const app = createSSRApp(() => <NSkeleton />)\n    setup(app)\n    try {\n      await renderToString(app)\n    }\n    catch (e) {\n      expect(e).not.toBeTruthy()\n    }\n  })\n})\n"
  },
  {
    "path": "src/slider/demos/enUS/basic.demo.vue",
    "content": "<markdown>\n# Basic\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst value = ref(50)\n</script>\n\n<template>\n  <n-space vertical>\n    <n-slider v-model:value=\"value\" :step=\"10\" />\n    <n-input-number v-model:value=\"value\" size=\"small\" />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/slider/demos/enUS/custom-marks.demo.vue",
    "content": "<markdown>\n# Custom Mark\n\nYou can use `marks` prop to customize handle button.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport Temperature16Regular from '@vicons/fluent/Temperature16Regular'\nimport { NFlex, NIcon } from 'naive-ui'\nimport { h, ref } from 'vue'\n\nfunction renderMark(value: number, color: string) {\n  return h(\n    NFlex,\n    { style: { width: '120px' } },\n    {\n      default: () => [\n        h(NIcon, { size: 24, color, component: Temperature16Regular }),\n        h('span', { style: { color } }, `${value}°C`)\n      ]\n    }\n  )\n}\n\nconst value = ref([20, 70])\nconst marks = {\n  0: '0°C',\n  20: '20°C',\n  60: '60°C',\n  100: '100°C'\n}\nconst customMarks = {\n  0: () => renderMark(0, '#0048BA'),\n  20: () => renderMark(20, '#00BFFF'),\n  60: () => renderMark(60, '#FFA500'),\n  100: () => renderMark(100, '#FF4500')\n}\n</script>\n\n<template>\n  <n-space style=\"height: 300px; justify-content: space-evenly\">\n    <n-slider v-model:value=\"value\" :marks=\"marks\" vertical range />\n    <n-slider v-model:value=\"value\" :marks=\"customMarks\" vertical range />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/slider/demos/enUS/custom-thumb.demo.vue",
    "content": "<markdown>\n# Customize handle\n\nYou can use `handle` slot to customize handle button.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport AnimalCat24Regular from '@vicons/fluent/AnimalCat24Regular'\nimport { ref } from 'vue'\n\nconst value = ref(50)\n</script>\n\n<template>\n  <n-space vertical>\n    <n-slider v-model:value=\"value\" :step=\"10\">\n      <template #thumb>\n        <n-icon-wrapper :size=\"24\" :border-radius=\"12\">\n          <n-icon :size=\"18\" :component=\"AnimalCat24Regular\" />\n        </n-icon-wrapper>\n      </template>\n    </n-slider>\n    <n-input-number v-model:value=\"value\" size=\"small\" />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/slider/demos/enUS/disable-tooltip.demo.vue",
    "content": "<markdown>\n# Disable tooltip\n\nSet `:tooltip=\"false\"` to disabled the tooltip.\n</markdown>\n\n<template>\n  <n-slider :step=\"10\" :tooltip=\"false\" />\n</template>\n"
  },
  {
    "path": "src/slider/demos/enUS/disabled.demo.vue",
    "content": "<markdown>\n# Disabled\n</markdown>\n\n<template>\n  <n-slider :default-value=\"50\" disabled />\n</template>\n"
  },
  {
    "path": "src/slider/demos/enUS/format.demo.vue",
    "content": "<markdown>\n# Format tooltip\n</markdown>\n\n<script lang=\"ts\" setup>\nconst formatTooltip = (value: number) => `${value}%`\n</script>\n\n<template>\n  <n-slider :default-value=\"50\" :step=\"10\" :format-tooltip=\"formatTooltip\" />\n</template>\n"
  },
  {
    "path": "src/slider/demos/enUS/index.demo-entry.md",
    "content": "# Slider\n\nAs far as I know, it is always used as a volume control.\n\n## Demos\n\n```demo\nbasic.vue\nrange.vue\nmark.vue\nrestrict-selectable-values.vue\ndisabled.vue\ndisable-tooltip.vue\nformat.vue\nreverse.vue\nvertical.vue\nshow-tooltip.vue\nmultiple-debug.vue\ncustom-thumb.vue\ncustom-marks.vue\n```\n\n## API\n\n### Slider Props\n\n| Name | Type | Default | Description | Version |\n| --- | --- | --- | --- | --- |\n| default-value | `number \\| [number, number] \\| null` | `null` | Default value. |  |\n| disabled | `boolean` | `false` | Whether the slider is disabled. |  |\n| format-tooltip | `(value: number) => string \\| number` | `undefined` | Format tooltip. |  |\n| keyboard | `boolean` | `true` | Whether the slider can be controlled keyboard. | 2.33.0 |\n| marks | `{ [markValue: number]: string \\| (() => VNodeChild) }` | `undefined` | Marks of the slider | Render function since 2.40.0 |\n| max | `number` | `100` | Max value of the slider. |  |\n| min | `number` | `0` | Min value of the slider. |  |\n| placement | `'top-start' \\| 'top' \\| 'top-end' \\| 'right-start' \\| 'right' \\| 'right-end' \\| 'bottom-start' \\| 'bottom' \\| 'bottom-end' \\| 'left-start' \\| 'left' \\| 'left-end'` | `undefined` | Tooltip's placement | 2.25.0 |\n| range | `boolean` | `false` | Whether the slider uses range value. |  |\n| reverse | `boolean` | `false` | Whether to reverse the track. |  |\n| show-tooltip | `boolean` | `false` | Whether to always show tooltip. Only work with non-range slider. | 2.24.2 |\n| step | `number \\| 'mark'` | `1` | Step of the slider. |  |\n| tooltip | `boolean` | `true` | Whether to show tooltip. |  |\n| vertical | `boolean` | `false` | Whether to enable vertical mode. |  |\n| value | `number \\| [number, number] \\| null` | `undefined` | Value of the slider. |  |\n| on-update:value | `(value: number \\| [number, number]) => void` | `undefined` | Callback on value update. |  |\n| on-dragstart | `() => void` | `undefined` | Callback function of dragging start. | 2.36.0 |\n| on-dragend | `() => void` | `undefined` | Callback function of dragging end. | 2.36.0 |\n\n### Slider Slots\n\n| Name  | Parameters | Description          | Version |\n| ----- | ---------- | -------------------- | ------- |\n| thumb | `()`       | Thumb of the slider. | 2.30.4  |\n"
  },
  {
    "path": "src/slider/demos/enUS/mark.demo.vue",
    "content": "<markdown>\n# Mark\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst value = ref([50, 70])\nconst marks = {\n  34: 'Amazing',\n  75: 'Good'\n}\n</script>\n\n<template>\n  <n-space vertical>\n    <n-slider v-model:value=\"value\" range :marks=\"marks\" :step=\"10\" />\n    <n-space>\n      <n-input-number v-model:value=\"value[0]\" size=\"small\" />\n      <n-input-number v-model:value=\"value[1]\" size=\"small\" />\n    </n-space>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/slider/demos/enUS/multiple-debug.demo.vue",
    "content": "<markdown>\n# More than 2 handles\n\nAlthough I don't know where it can be used, but it looks cool.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst value = ref([50, 70, 80, 90])\n</script>\n\n<template>\n  <n-space vertical>\n    <n-slider v-model:value=\"value\" range :step=\"1\" />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/slider/demos/enUS/range.demo.vue",
    "content": "<markdown>\n# Range\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst value = ref([50, 70])\n</script>\n\n<template>\n  <n-space vertical>\n    <n-slider v-model:value=\"value\" range :step=\"1\" />\n    <n-space>\n      <n-input-number v-model:value=\"value[0]\" size=\"small\" />\n      <n-input-number v-model:value=\"value[1]\" size=\"small\" />\n    </n-space>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/slider/demos/enUS/restrict-selectable-values.demo.vue",
    "content": "<markdown>\n# Restrict selectable values\n\nSet `step=\"mark\"` to restrict the selectable values to those provided by the mark prop.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst value = ref(0)\nconst marks = {\n  0: '0°C',\n  20: '20°C',\n  37: '37°C',\n  100: '100°C'\n}\n</script>\n\n<template>\n  <n-space vertical>\n    <n-slider v-model:value=\"value\" :marks=\"marks\" step=\"mark\" />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/slider/demos/enUS/reverse.demo.vue",
    "content": "<markdown>\n# Reverse\n\nSet `reverse` to invert the track.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst value = ref(0)\n</script>\n\n<template>\n  <n-space vertical>\n    <n-slider v-model:value=\"value\" :step=\"10\" reverse />\n    <n-input-number v-model:value=\"value\" size=\"small\" />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/slider/demos/enUS/show-tooltip.demo.vue",
    "content": "<markdown>\n# Always show tooltip\n\nSet `show-tooltip` to always show tooltip.\n</markdown>\n\n<template>\n  <n-slider show-tooltip />\n</template>\n"
  },
  {
    "path": "src/slider/demos/enUS/vertical.demo.vue",
    "content": "<markdown>\n# Vertical\n\nSet `vertical` to enable the vertical mode. Its height depends on the height of the container by default, and you can also customize the height.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst value = ref([20, 70])\nconst marks = {\n  0: '0°C',\n  20: '20°C',\n  37: '37°C',\n  100: '100°C'\n}\n</script>\n\n<template>\n  <n-space style=\"height: 300px; justify-content: center\">\n    <n-slider :default-value=\"77\" vertical />\n    <n-slider :default-value=\"20\" vertical reverse />\n    <n-slider :default-value=\"30\" vertical disabled />\n    <n-slider v-model:value=\"value\" :marks=\"marks\" vertical range />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/slider/demos/zhCN/basic.demo.vue",
    "content": "<markdown>\n# 基础用法\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst value = ref(50)\n</script>\n\n<template>\n  <n-space vertical>\n    <n-slider v-model:value=\"value\" :step=\"10\" />\n    <n-input-number v-model:value=\"value\" size=\"small\" />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/slider/demos/zhCN/custom-marks.demo.vue",
    "content": "<markdown>\n# 自定义标记\n\n可以使用 `marks` 插槽自定义刻度。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport Temperature16Regular from '@vicons/fluent/Temperature16Regular'\nimport { NFlex, NIcon } from 'naive-ui'\nimport { h, ref } from 'vue'\n\nfunction renderMark(value: number, color: string) {\n  return h(\n    NFlex,\n    { style: { width: '120px' } },\n    {\n      default: () => [\n        h(NIcon, { size: 24, color, component: Temperature16Regular }),\n        h('span', { style: { color } }, `${value}°C`)\n      ]\n    }\n  )\n}\n\nconst value = ref([20, 70])\nconst marks = {\n  0: '0°C',\n  20: '20°C',\n  60: '60°C',\n  100: '100°C'\n}\nconst customMarks = {\n  0: () => renderMark(0, '#0048BA'),\n  20: () => renderMark(20, '#00BFFF'),\n  60: () => renderMark(60, '#FFA500'),\n  100: () => renderMark(100, '#FF4500')\n}\n</script>\n\n<template>\n  <n-space style=\"height: 300px; justify-content: space-evenly\">\n    <n-slider v-model:value=\"value\" :marks=\"marks\" vertical range />\n    <n-slider v-model:value=\"value\" :marks=\"customMarks\" vertical range />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/slider/demos/zhCN/custom-thumb.demo.vue",
    "content": "<markdown>\n# 自定义标识\n\n可以使用 `thumb` 插槽自定义滑块按钮。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport AnimalCat24Regular from '@vicons/fluent/AnimalCat24Regular'\nimport { ref } from 'vue'\n\nconst value = ref(50)\n</script>\n\n<template>\n  <n-space vertical>\n    <n-slider v-model:value=\"value\" :step=\"10\">\n      <template #thumb>\n        <n-icon-wrapper :size=\"24\" :border-radius=\"12\">\n          <n-icon :size=\"18\" :component=\"AnimalCat24Regular\" />\n        </n-icon-wrapper>\n      </template>\n    </n-slider>\n    <n-input-number v-model:value=\"value\" size=\"small\" />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/slider/demos/zhCN/disable-tooltip.demo.vue",
    "content": "<markdown>\n# 禁用 Tooltip\n\n设定 `:tooltip=\"false\"` 来禁用 tooltip。\n</markdown>\n\n<template>\n  <n-slider :step=\"10\" :tooltip=\"false\" />\n</template>\n"
  },
  {
    "path": "src/slider/demos/zhCN/disabled.demo.vue",
    "content": "<markdown>\n# 禁用\n</markdown>\n\n<template>\n  <n-slider :default-value=\"50\" disabled />\n</template>\n"
  },
  {
    "path": "src/slider/demos/zhCN/format.demo.vue",
    "content": "<markdown>\n# 格式化弹出提示\n</markdown>\n\n<script lang=\"ts\" setup>\nconst formatTooltip = (value: number) => `${value}%`\n</script>\n\n<template>\n  <n-slider :default-value=\"50\" :step=\"10\" :format-tooltip=\"formatTooltip\" />\n</template>\n"
  },
  {
    "path": "src/slider/demos/zhCN/index.demo-entry.md",
    "content": "# 滑动选择 Slider\n\n就我所知，这东西一般就用来控制音量。\n\n## 演示\n\n```demo\nbasic.vue\nrange.vue\nmark.vue\nrestrict-selectable-values.vue\ndisabled.vue\ndisable-tooltip.vue\nformat.vue\nreverse.vue\nvertical.vue\nshow-tooltip.vue\nmultiple-debug.vue\ncustom-thumb.vue\ncustom-marks.vue\nkeyboard-debug.vue\n```\n\n## API\n\n### Slider Props\n\n| 名称 | 类型 | 默认值 | 说明 | 版本 |\n| --- | --- | --- | --- | --- |\n| default-value | `number \\| [number, number] \\| null` | `null` | 默认值 |  |\n| disabled | `boolean` | `false` | 是否禁用 |  |\n| format-tooltip | `(value: number) => string \\| number` | `undefined` | 格式化 tooltip |  |\n| keyboard | `boolean` | `true` | 是否可键盘控制 | 2.33.0 |\n| marks | `{ [markValue: number]: string \\| (() => VNodeChild) }` | `undefined` | Slider 上的标记 | 2.40.0 支持 render 函数 |\n| max | `number` | `100` | 最大值 |  |\n| min | `number` | `0` | 最小值 |  |\n| placement | `'top-start' \\| 'top' \\| 'top-end' \\| 'right-start' \\| 'right' \\| 'right-end' \\| 'bottom-start' \\| 'bottom' \\| 'bottom-end' \\| 'left-start' \\| 'left' \\| 'left-end'` | `undefined` | Tooltip 的弹出位置 | 2.25.0 |\n| range | `boolean` | `false` | 是否选择范围值 |  |\n| reverse | `boolean` | `false` | 是否倒转轨道 |  |\n| show-tooltip | `boolean` | `false` | 是否一直显示 tooltip，仅对非 range 生效 | 2.24.2 |\n| step | `number \\| 'mark'` | `1` | 步长 |  |\n| tooltip | `boolean` | `true` | 是否展示 tooltip |  |\n| vertical | `boolean` | `false` | 是否启用垂直模式 |  |\n| value | `number \\| [number, number] \\| null` | `undefined` | 值 |  |\n| on-update:value | `(value: number \\| [number, number]) => void` | `undefined` | 值更新的回调 |  |\n| on-dragstart | `() => void` | `undefined` | 开始拖拽的回调函数 | 2.36.0 |\n| on-dragend | `() => void` | `undefined` | 拖拽结束的回调函数 | 2.36.0 |\n\n### Slider Slots\n\n| 名称  | 参数 | 说明     | 版本   |\n| ----- | ---- | -------- | ------ |\n| thumb | `()` | 滑块按钮 | 2.30.4 |\n"
  },
  {
    "path": "src/slider/demos/zhCN/keyboard-debug.demo.vue",
    "content": "<markdown>\n# 键盘事件\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst value = ref(50)\nconst keyboard = ref(false)\n</script>\n\n<template>\n  <n-space vertical>\n    <n-switch v-model:value=\"keyboard\" />\n    <n-slider v-model:value=\"value\" :step=\"10\" :keyboard=\"keyboard\" />\n    <n-input-number v-model:value=\"value\" size=\"small\" />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/slider/demos/zhCN/mark.demo.vue",
    "content": "<markdown>\n# 标记\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst value = ref([50, 70])\nconst marks = {\n  34: '太棒了',\n  75: '不错'\n}\n</script>\n\n<template>\n  <n-space vertical>\n    <n-slider v-model:value=\"value\" range :marks=\"marks\" :step=\"10\" />\n    <n-space>\n      <n-input-number v-model:value=\"value[0]\" size=\"small\" />\n      <n-input-number v-model:value=\"value[1]\" size=\"small\" />\n    </n-space>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/slider/demos/zhCN/multiple-debug.demo.vue",
    "content": "<markdown>\n# 多于两个滑块\n\n虽然我也不知道有啥用，但是这看起来很屌。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst value = ref([50, 70, 80, 90])\n</script>\n\n<template>\n  <n-space vertical>\n    <n-slider v-model:value=\"value\" range :step=\"1\" />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/slider/demos/zhCN/range.demo.vue",
    "content": "<markdown>\n# 范围\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst value = ref([50, 70])\n</script>\n\n<template>\n  <n-space vertical>\n    <n-slider v-model:value=\"value\" range :step=\"1\" />\n    <n-space>\n      <n-input-number v-model:value=\"value[0]\" size=\"small\" />\n      <n-input-number v-model:value=\"value[1]\" size=\"small\" />\n    </n-space>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/slider/demos/zhCN/restrict-selectable-values.demo.vue",
    "content": "<markdown>\n# 限制可选值\n\n设定 `step=\"mark\"` 将可选值限制为标记属性所提供的值。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst value = ref(0)\nconst marks = {\n  0: '0°C',\n  20: '20°C',\n  37: '37°C',\n  100: '100°C'\n}\n</script>\n\n<template>\n  <n-space vertical>\n    <n-slider v-model:value=\"value\" :marks=\"marks\" step=\"mark\" />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/slider/demos/zhCN/reverse.demo.vue",
    "content": "<markdown>\n# 倒转\n\n设定 `reverse` 可以将轨道倒转过来。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst value = ref(0)\n</script>\n\n<template>\n  <n-space vertical>\n    <n-slider v-model:value=\"value\" :step=\"10\" reverse />\n    <n-input-number v-model:value=\"value\" size=\"small\" />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/slider/demos/zhCN/show-tooltip.demo.vue",
    "content": "<markdown>\n# 始终显示 Tooltip\n\n设定 `show-tooltip` 来让 Tooltip 被一直显示。\n</markdown>\n\n<template>\n  <n-slider show-tooltip />\n</template>\n"
  },
  {
    "path": "src/slider/demos/zhCN/vertical.demo.vue",
    "content": "<markdown>\n# 垂直\n\n设定 `vertical` 来启用垂直模式，它的高度默认依赖于容器的高度，你也可以自定义高度。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst value = ref([20, 70])\nconst marks = {\n  0: '0°C',\n  20: '20°C',\n  37: '37°C',\n  100: '100°C'\n}\n</script>\n\n<template>\n  <n-space style=\"height: 300px; justify-content: center\">\n    <n-slider :default-value=\"77\" vertical />\n    <n-slider :default-value=\"20\" vertical reverse />\n    <n-slider :default-value=\"30\" vertical disabled />\n    <n-slider v-model:value=\"value\" :marks=\"marks\" vertical range />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/slider/index.ts",
    "content": "export { default as NSlider, sliderProps } from './src/Slider'\nexport type { SliderProps, SliderSlots } from './src/Slider'\n"
  },
  {
    "path": "src/slider/src/Slider.tsx",
    "content": "import type {\n  ComponentPublicInstance,\n  CSSProperties,\n  PropType,\n  SlotsType,\n  VNode,\n  VNodeChild\n} from 'vue'\nimport type { FollowerInst, FollowerPlacement } from 'vueuc'\nimport type { ThemeProps } from '../../_mixins'\nimport type { ExtractPublicPropTypes, MaybeArray } from '../../_utils'\nimport type { SliderTheme } from '../styles'\nimport type { OnUpdateValueImpl } from './interface'\nimport { off, on } from 'evtd'\nimport { useIsMounted, useMergedState } from 'vooks'\nimport {\n  computed,\n  defineComponent,\n  h,\n  nextTick,\n  onBeforeUnmount,\n  ref,\n  toRef,\n  Transition,\n  watch\n} from 'vue'\nimport { VBinder, VFollower, VTarget } from 'vueuc'\nimport { useConfig, useFormItem, useTheme, useThemeClass } from '../../_mixins'\nimport { call, resolveSlot, useAdjustedTo } from '../../_utils'\nimport { sliderLight } from '../styles'\nimport style from './styles/index.cssr'\nimport { isTouchEvent, useRefs } from './utils'\n\nexport interface ClosestMark {\n  value: number\n  distance: number\n  index: number\n}\n\n// ref: https://developer.mozilla.org/zh-CN/docs/Web/API/MouseEvent/button\nconst eventButtonLeft = 0\n\nexport const sliderProps = {\n  ...(useTheme.props as ThemeProps<SliderTheme>),\n  to: useAdjustedTo.propTo,\n  defaultValue: {\n    type: [Number, Array] as PropType<number | number[]>,\n    default: 0\n  },\n  marks: Object as PropType<Record<string, string | (() => VNodeChild)>>,\n  disabled: {\n    type: Boolean as PropType<boolean | undefined>,\n    default: undefined\n  },\n  formatTooltip: Function as PropType<(value: number) => string | number>,\n  keyboard: {\n    type: Boolean,\n    default: true\n  },\n  min: {\n    type: Number,\n    default: 0\n  },\n  max: {\n    type: Number,\n    default: 100\n  },\n  step: {\n    type: [Number, String] as PropType<number | 'mark'>,\n    default: 1\n  },\n  range: Boolean,\n  value: [Number, Array] as PropType<number | number[]>,\n  placement: String as PropType<FollowerPlacement>,\n  showTooltip: {\n    type: Boolean as PropType<boolean | undefined>,\n    default: undefined\n  },\n  tooltip: {\n    type: Boolean,\n    default: true\n  },\n  vertical: Boolean,\n  reverse: Boolean,\n  'onUpdate:value': [Function, Array] as PropType<\n    MaybeArray<(value: number & number[]) => void>\n  >,\n  onUpdateValue: [Function, Array] as PropType<\n    MaybeArray<(value: number & number[]) => void>\n  >,\n  onDragstart: [Function] as PropType<() => void>,\n  onDragend: [Function] as PropType<() => void>\n} as const\n\nexport type SliderProps = ExtractPublicPropTypes<typeof sliderProps>\n\nexport interface SliderSlots {\n  thumb?: () => VNode[]\n  default?: () => VNode[]\n}\n\nexport default defineComponent({\n  name: 'Slider',\n  props: sliderProps,\n  slots: Object as SlotsType<SliderSlots>,\n  setup(props) {\n    const { mergedClsPrefixRef, namespaceRef, inlineThemeDisabled }\n      = useConfig(props)\n    const themeRef = useTheme(\n      'Slider',\n      '-slider',\n      style,\n      sliderLight,\n      props,\n      mergedClsPrefixRef\n    )\n\n    // dom ref\n    const handleRailRef = ref<HTMLElement | null>(null)\n    const [handleRefs, setHandleRefs] = useRefs<HTMLElement>()\n    const [followerRefs, setFollowerRefs] = useRefs<\n      FollowerInst & ComponentPublicInstance\n    >()\n    const followerEnabledIndexSetRef = ref<Set<number>>(new Set())\n\n    // data ref\n    const formItem = useFormItem(props)\n    const { mergedDisabledRef } = formItem\n    const precisionRef = computed(() => {\n      const { step } = props\n      if (Number(step) <= 0 || step === 'mark')\n        return 0\n      const stepString = step.toString()\n      let precision = 0\n      if (stepString.includes('.')) {\n        precision = stepString.length - stepString.indexOf('.') - 1\n      }\n      return precision\n    })\n    const uncontrolledValueRef = ref(props.defaultValue)\n    const controlledValueRef = toRef(props, 'value')\n    const mergedValueRef = useMergedState(\n      controlledValueRef,\n      uncontrolledValueRef\n    )\n    const arrifiedValueRef = computed(() => {\n      const { value: mergedValue } = mergedValueRef\n      return ((props.range ? mergedValue : [mergedValue]) as number[]).map(\n        clampValue\n      )\n    })\n    const handleCountExceeds2Ref = computed(\n      () => arrifiedValueRef.value.length > 2\n    )\n    const mergedPlacementRef = computed(() => {\n      return props.placement === undefined\n        ? props.vertical\n          ? 'right'\n          : 'top'\n        : props.placement\n    })\n    const markValuesRef = computed(() => {\n      const { marks } = props\n      return marks ? Object.keys(marks).map(Number.parseFloat) : null\n    })\n\n    // status ref\n    const activeIndexRef = ref(-1)\n    const previousIndexRef = ref(-1)\n    const hoverIndexRef = ref(-1)\n    const draggingRef = ref(false)\n\n    // style ref\n    const dotTransitionDisabledRef = ref(false)\n    const styleDirectionRef = computed(() => {\n      const { vertical, reverse } = props\n      const left = reverse ? 'right' : 'left'\n      const bottom = reverse ? 'top' : 'bottom'\n      return vertical ? bottom : left\n    })\n    const fillStyleRef = computed(() => {\n      if (handleCountExceeds2Ref.value)\n        return\n      const values = arrifiedValueRef.value\n      const start = valueToPercentage(\n        props.range ? Math.min(...values) : props.min\n      )\n      const end = valueToPercentage(\n        props.range ? Math.max(...values) : values[0]\n      )\n      const { value: styleDirection } = styleDirectionRef\n      return props.vertical\n        ? {\n            [styleDirection]: `${start}%`,\n            height: `${end - start}%`\n          }\n        : {\n            [styleDirection]: `${start}%`,\n            width: `${end - start}%`\n          }\n    })\n    const markInfosRef = computed(() => {\n      const mergedMarks: Array<{\n        active: boolean\n        label: string | (() => VNodeChild)\n        key: number\n        style: CSSProperties\n      }> = []\n      const { marks } = props\n      if (marks) {\n        const orderValues = arrifiedValueRef.value.slice()\n        orderValues.sort((a, b) => a - b)\n        const { value: styleDirection } = styleDirectionRef\n        const { value: handleCountExceeds2 } = handleCountExceeds2Ref\n        const { range } = props\n        const isActive = handleCountExceeds2\n          ? () => false\n          : (num: number): boolean =>\n              range\n                ? num >= orderValues[0]\n                && num <= orderValues[orderValues.length - 1]\n                : num <= orderValues[0]\n        for (const key of Object.keys(marks)) {\n          const num = Number(key)\n          mergedMarks.push({\n            active: isActive(num),\n            key: num,\n            label: marks[key],\n            style: {\n              [styleDirection]: `${valueToPercentage(num)}%`\n            }\n          })\n        }\n      }\n      return mergedMarks\n    })\n\n    function getHandleStyle(value: number, index: number): Record<string, any> {\n      const percentage = valueToPercentage(value)\n      const { value: styleDirection } = styleDirectionRef\n      return {\n        [styleDirection]: `${percentage}%`,\n        zIndex: index === activeIndexRef.value ? 1 : 0\n      }\n    }\n    function isShowTooltip(index: number): boolean {\n      return (\n        props.showTooltip\n        || hoverIndexRef.value === index\n        || (activeIndexRef.value === index && draggingRef.value)\n      )\n    }\n    function shouldKeepTooltipTransition(index: number): boolean {\n      if (!draggingRef.value)\n        return true\n      return !(\n        activeIndexRef.value === index && previousIndexRef.value === index\n      )\n    }\n    function focusActiveHandle(index: number): void {\n      if (~index) {\n        activeIndexRef.value = index\n        handleRefs.get(index)?.focus()\n      }\n    }\n    function syncPosition(): void {\n      followerRefs.forEach((inst, index) => {\n        if (isShowTooltip(index))\n          inst.syncPosition()\n      })\n    }\n    function doUpdateValue(value: number | number[]): void {\n      const { 'onUpdate:value': _onUpdateValue, onUpdateValue } = props\n      const { nTriggerFormInput, nTriggerFormChange } = formItem\n      if (onUpdateValue)\n        call(onUpdateValue as OnUpdateValueImpl, value)\n      if (_onUpdateValue)\n        call(_onUpdateValue as OnUpdateValueImpl, value)\n      uncontrolledValueRef.value = value\n      nTriggerFormInput()\n      nTriggerFormChange()\n    }\n    function dispatchValueUpdate(value: number | number[]): void {\n      const { range } = props\n      if (range) {\n        if (Array.isArray(value)) {\n          const { value: oldValues } = arrifiedValueRef\n          if (value.join() !== oldValues.join()) {\n            doUpdateValue(value)\n          }\n        }\n      }\n      else if (!Array.isArray(value)) {\n        const oldValue = arrifiedValueRef.value[0]\n        if (oldValue !== value) {\n          doUpdateValue(value)\n        }\n      }\n    }\n    function doDispatchValue(value: number, index: number): void {\n      if (props.range) {\n        const values = arrifiedValueRef.value.slice()\n        values.splice(index, 1, value)\n        dispatchValueUpdate(values)\n      }\n      else {\n        dispatchValueUpdate(value)\n      }\n    }\n\n    // value conversion\n    function sanitizeValue(\n      value: number,\n      currentValue: number,\n      stepBuffer?: number\n    ): number {\n      const stepping = stepBuffer !== undefined\n      if (!stepBuffer) {\n        stepBuffer = value - currentValue > 0 ? 1 : -1\n      }\n      const markValues = markValuesRef.value || []\n      const { step } = props\n      if (step === 'mark') {\n        const closestMark = getClosestMark(\n          value,\n          markValues.concat(currentValue),\n          stepping ? stepBuffer : undefined\n        )\n        return closestMark ? closestMark.value : currentValue\n      }\n      if (step <= 0)\n        return currentValue\n      const { value: precision } = precisionRef\n      let closestMark\n      // if it is a stepping, priority will be given to the marks\n      // on the rail, otherwise take the nearest one\n      if (stepping) {\n        const currentStep = Number((currentValue / step).toFixed(precision))\n        const actualStep = Math.floor(currentStep)\n        const leftStep = currentStep > actualStep ? actualStep : actualStep - 1\n        const rightStep = currentStep < actualStep ? actualStep : actualStep + 1\n        closestMark = getClosestMark(\n          currentValue,\n          [\n            Number((leftStep * step).toFixed(precision)),\n            Number((rightStep * step).toFixed(precision)),\n            ...markValues\n          ],\n          stepBuffer\n        )\n      }\n      else {\n        const roundValue = getRoundValue(value)\n        closestMark = getClosestMark(value, [...markValues, roundValue])\n      }\n      return closestMark ? clampValue(closestMark.value) : currentValue\n    }\n    function clampValue(value: number): number {\n      return Math.min(props.max, Math.max(props.min, value))\n    }\n    function valueToPercentage(value: number): number {\n      const { max, min } = props\n      return ((value - min) / (max - min)) * 100\n    }\n    function percentageToValue(percentage: number): number {\n      const { max, min } = props\n      return min + (max - min) * percentage\n    }\n    function getRoundValue(value: number): number {\n      const { step, min } = props\n      if (Number(step) <= 0 || step === 'mark')\n        return value\n      const newValue = Math.round((value - min) / step) * step + min\n      return Number(newValue.toFixed(precisionRef.value))\n    }\n    function getClosestMark(\n      currentValue: number,\n      markValues = markValuesRef.value,\n      buffer?: number\n    ): ClosestMark | null {\n      if (!markValues?.length)\n        return null\n      let closestMark: ClosestMark | null = null\n      let index = -1\n      while (++index < markValues.length) {\n        const diff = markValues[index] - currentValue\n        const distance = Math.abs(diff)\n        if (\n          // find marks in the same direction\n          (buffer === undefined || diff * buffer > 0)\n          && (closestMark === null || distance < closestMark.distance)\n        ) {\n          closestMark = {\n            index,\n            distance,\n            value: markValues[index]\n          }\n        }\n      }\n      return closestMark\n    }\n    function getPointValue(event: MouseEvent | TouchEvent): number | undefined {\n      const railEl = handleRailRef.value\n      if (!railEl)\n        return\n      const touchEvent = isTouchEvent(event) ? event.touches[0] : event\n      const railRect = railEl.getBoundingClientRect()\n      let percentage: number\n      if (props.vertical) {\n        percentage = (railRect.bottom - touchEvent.clientY) / railRect.height\n      }\n      else {\n        percentage = (touchEvent.clientX - railRect.left) / railRect.width\n      }\n      if (props.reverse) {\n        percentage = 1 - percentage\n      }\n      return percentageToValue(percentage)\n    }\n\n    // dom event handle\n    function handleRailKeyDown(e: KeyboardEvent): void {\n      if (mergedDisabledRef.value || !props.keyboard)\n        return\n      const { vertical, reverse } = props\n      switch (e.key) {\n        case 'ArrowUp':\n          e.preventDefault()\n          handleStepValue(vertical && reverse ? -1 : 1)\n          break\n        case 'ArrowRight':\n          e.preventDefault()\n          handleStepValue(!vertical && reverse ? -1 : 1)\n          break\n        case 'ArrowDown':\n          e.preventDefault()\n          handleStepValue(vertical && reverse ? 1 : -1)\n          break\n        case 'ArrowLeft':\n          e.preventDefault()\n          handleStepValue(!vertical && reverse ? 1 : -1)\n          break\n      }\n    }\n    function handleStepValue(ratio: number): void {\n      const activeIndex = activeIndexRef.value\n      if (activeIndex === -1)\n        return\n      const { step } = props\n      const currentValue = arrifiedValueRef.value[activeIndex]\n      const nextValue\n        = Number(step) <= 0 || step === 'mark'\n          ? currentValue\n          : currentValue + step * ratio\n      doDispatchValue(\n        // Avoid the number of value does not change when `step` is null\n        sanitizeValue(nextValue, currentValue, ratio > 0 ? 1 : -1),\n        activeIndex\n      )\n    }\n    function handleRailMouseDown(event: MouseEvent | TouchEvent): void {\n      if (mergedDisabledRef.value)\n        return\n      if (!isTouchEvent(event) && event.button !== eventButtonLeft) {\n        return\n      }\n      const pointValue = getPointValue(event)\n      if (pointValue === undefined)\n        return\n      const values = arrifiedValueRef.value.slice()\n      const activeIndex = props.range\n        ? (getClosestMark(pointValue, values)?.index ?? -1)\n        : 0\n      if (activeIndex !== -1) {\n        // avoid triggering scrolling on touch\n        event.preventDefault()\n        focusActiveHandle(activeIndex)\n        startDragging()\n        doDispatchValue(\n          sanitizeValue(pointValue, arrifiedValueRef.value[activeIndex]),\n          activeIndex\n        )\n      }\n    }\n    function startDragging(): void {\n      if (!draggingRef.value) {\n        draggingRef.value = true\n        if (props.onDragstart)\n          call(props.onDragstart)\n        on('touchend', document, handleMouseUp)\n        on('mouseup', document, handleMouseUp)\n        on('touchmove', document, handleMouseMove)\n        on('mousemove', document, handleMouseMove)\n      }\n    }\n    function stopDragging(): void {\n      if (draggingRef.value) {\n        draggingRef.value = false\n        if (props.onDragend)\n          call(props.onDragend)\n        off('touchend', document, handleMouseUp)\n        off('mouseup', document, handleMouseUp)\n        off('touchmove', document, handleMouseMove)\n        off('mousemove', document, handleMouseMove)\n      }\n    }\n    function handleMouseMove(event: MouseEvent | TouchEvent): void {\n      const { value: activeIndex } = activeIndexRef\n      if (!draggingRef.value || activeIndex === -1) {\n        stopDragging()\n        return\n      }\n      const pointValue = getPointValue(event)\n      if (pointValue === undefined)\n        return\n      doDispatchValue(\n        sanitizeValue(pointValue, arrifiedValueRef.value[activeIndex]),\n        activeIndex\n      )\n    }\n    function handleMouseUp(): void {\n      stopDragging()\n    }\n    function handleHandleFocus(index: number): void {\n      activeIndexRef.value = index\n      // Wake focus style\n      if (!mergedDisabledRef.value) {\n        hoverIndexRef.value = index\n      }\n    }\n    function handleHandleBlur(index: number): void {\n      if (activeIndexRef.value === index) {\n        activeIndexRef.value = -1\n        stopDragging()\n      }\n      if (hoverIndexRef.value === index) {\n        hoverIndexRef.value = -1\n      }\n    }\n    function handleHandleMouseEnter(index: number): void {\n      hoverIndexRef.value = index\n    }\n    function handleHandleMouseLeave(index: number): void {\n      if (hoverIndexRef.value === index) {\n        hoverIndexRef.value = -1\n      }\n    }\n    watch(\n      activeIndexRef,\n      (_, previous) => void nextTick(() => (previousIndexRef.value = previous))\n    )\n    watch(mergedValueRef, () => {\n      if (props.marks) {\n        if (dotTransitionDisabledRef.value)\n          return\n        dotTransitionDisabledRef.value = true\n        void nextTick(() => {\n          dotTransitionDisabledRef.value = false\n        })\n      }\n      void nextTick(syncPosition)\n    })\n    onBeforeUnmount(() => {\n      stopDragging()\n    })\n    const cssVarsRef = computed(() => {\n      const {\n        self: {\n          markFontSize,\n          railColor,\n          railColorHover,\n          fillColor,\n          fillColorHover,\n          handleColor,\n          opacityDisabled,\n          dotColor,\n          dotColorModal,\n          handleBoxShadow,\n          handleBoxShadowHover,\n          handleBoxShadowActive,\n          handleBoxShadowFocus,\n          dotBorder,\n          dotBoxShadow,\n          railHeight,\n          railWidthVertical,\n          handleSize,\n          dotHeight,\n          dotWidth,\n          dotBorderRadius,\n          fontSize,\n          dotBorderActive,\n          dotColorPopover\n        },\n        common: { cubicBezierEaseInOut }\n      } = themeRef.value\n      return {\n        '--n-bezier': cubicBezierEaseInOut,\n        '--n-dot-border': dotBorder,\n        '--n-dot-border-active': dotBorderActive,\n        '--n-dot-border-radius': dotBorderRadius,\n        '--n-dot-box-shadow': dotBoxShadow,\n        '--n-dot-color': dotColor,\n        '--n-dot-color-modal': dotColorModal,\n        '--n-dot-color-popover': dotColorPopover,\n        '--n-dot-height': dotHeight,\n        '--n-dot-width': dotWidth,\n        '--n-fill-color': fillColor,\n        '--n-fill-color-hover': fillColorHover,\n        '--n-font-size': fontSize,\n        '--n-handle-box-shadow': handleBoxShadow,\n        '--n-handle-box-shadow-active': handleBoxShadowActive,\n        '--n-handle-box-shadow-focus': handleBoxShadowFocus,\n        '--n-handle-box-shadow-hover': handleBoxShadowHover,\n        '--n-handle-color': handleColor,\n        '--n-handle-size': handleSize,\n        '--n-opacity-disabled': opacityDisabled,\n        '--n-rail-color': railColor,\n        '--n-rail-color-hover': railColorHover,\n        '--n-rail-height': railHeight,\n        '--n-rail-width-vertical': railWidthVertical,\n        '--n-mark-font-size': markFontSize\n      }\n    })\n    const themeClassHandle = inlineThemeDisabled\n      ? useThemeClass('slider', undefined, cssVarsRef, props)\n      : undefined\n    const indicatorCssVarsRef = computed(() => {\n      const {\n        self: {\n          fontSize,\n          indicatorColor,\n          indicatorBoxShadow,\n          indicatorTextColor,\n          indicatorBorderRadius\n        }\n      } = themeRef.value\n      return {\n        '--n-font-size': fontSize,\n        '--n-indicator-border-radius': indicatorBorderRadius,\n        '--n-indicator-box-shadow': indicatorBoxShadow,\n        '--n-indicator-color': indicatorColor,\n        '--n-indicator-text-color': indicatorTextColor\n      }\n    })\n    const indicatorThemeClassHandle = inlineThemeDisabled\n      ? useThemeClass('slider-indicator', undefined, indicatorCssVarsRef, props)\n      : undefined\n\n    return {\n      mergedClsPrefix: mergedClsPrefixRef,\n      namespace: namespaceRef,\n      uncontrolledValue: uncontrolledValueRef,\n      mergedValue: mergedValueRef,\n      mergedDisabled: mergedDisabledRef,\n      mergedPlacement: mergedPlacementRef,\n      isMounted: useIsMounted(),\n      adjustedTo: useAdjustedTo(props),\n      dotTransitionDisabled: dotTransitionDisabledRef,\n      markInfos: markInfosRef,\n      isShowTooltip,\n      shouldKeepTooltipTransition,\n      handleRailRef,\n      setHandleRefs,\n      setFollowerRefs,\n      fillStyle: fillStyleRef,\n      getHandleStyle,\n      activeIndex: activeIndexRef,\n      arrifiedValues: arrifiedValueRef,\n      followerEnabledIndexSet: followerEnabledIndexSetRef,\n      handleRailMouseDown,\n      handleHandleFocus,\n      handleHandleBlur,\n      handleHandleMouseEnter,\n      handleHandleMouseLeave,\n      handleRailKeyDown,\n      indicatorCssVars: inlineThemeDisabled ? undefined : indicatorCssVarsRef,\n      indicatorThemeClass: indicatorThemeClassHandle?.themeClass,\n      indicatorOnRender: indicatorThemeClassHandle?.onRender,\n      cssVars: inlineThemeDisabled ? undefined : cssVarsRef,\n      themeClass: themeClassHandle?.themeClass,\n      onRender: themeClassHandle?.onRender\n    }\n  },\n  render() {\n    const { mergedClsPrefix, themeClass, formatTooltip } = this\n    this.onRender?.()\n    return (\n      <div\n        class={[\n          `${mergedClsPrefix}-slider`,\n          themeClass,\n          {\n            [`${mergedClsPrefix}-slider--disabled`]: this.mergedDisabled,\n            [`${mergedClsPrefix}-slider--active`]: this.activeIndex !== -1,\n            [`${mergedClsPrefix}-slider--with-mark`]: this.marks,\n            [`${mergedClsPrefix}-slider--vertical`]: this.vertical,\n            [`${mergedClsPrefix}-slider--reverse`]: this.reverse\n          }\n        ]}\n        style={this.cssVars as CSSProperties}\n        onKeydown={this.handleRailKeyDown}\n        onMousedown={this.handleRailMouseDown}\n        onTouchstart={this.handleRailMouseDown}\n      >\n        <div class={`${mergedClsPrefix}-slider-rail`}>\n          <div\n            class={`${mergedClsPrefix}-slider-rail__fill`}\n            style={this.fillStyle}\n          />\n          {this.marks ? (\n            <div\n              class={[\n                `${mergedClsPrefix}-slider-dots`,\n                this.dotTransitionDisabled\n                && `${mergedClsPrefix}-slider-dots--transition-disabled`\n              ]}\n            >\n              {this.markInfos.map(mark => (\n                <div\n                  key={mark.key}\n                  class={[\n                    `${mergedClsPrefix}-slider-dot`,\n                    {\n                      [`${mergedClsPrefix}-slider-dot--active`]: mark.active\n                    }\n                  ]}\n                  style={mark.style}\n                />\n              ))}\n            </div>\n          ) : null}\n          <div ref=\"handleRailRef\" class={`${mergedClsPrefix}-slider-handles`}>\n            {this.arrifiedValues.map((value, index) => {\n              const showTooltip = this.isShowTooltip(index)\n              return (\n                <VBinder>\n                  {{\n                    default: () => [\n                      <VTarget>\n                        {{\n                          default: () => (\n                            <div\n                              ref={this.setHandleRefs(index)}\n                              class={`${mergedClsPrefix}-slider-handle-wrapper`}\n                              tabindex={this.mergedDisabled ? -1 : 0}\n                              role=\"slider\"\n                              aria-valuenow={value}\n                              aria-valuemin={this.min}\n                              aria-valuemax={this.max}\n                              aria-orientation={\n                                this.vertical ? 'vertical' : 'horizontal'\n                              }\n                              aria-disabled={this.disabled}\n                              style={this.getHandleStyle(value, index)}\n                              onFocus={() => {\n                                this.handleHandleFocus(index)\n                              }}\n                              onBlur={() => {\n                                this.handleHandleBlur(index)\n                              }}\n                              onMouseenter={() => {\n                                this.handleHandleMouseEnter(index)\n                              }}\n                              onMouseleave={() => {\n                                this.handleHandleMouseLeave(index)\n                              }}\n                            >\n                              {resolveSlot(this.$slots.thumb, () => [\n                                <div\n                                  class={`${mergedClsPrefix}-slider-handle`}\n                                />\n                              ])}\n                            </div>\n                          )\n                        }}\n                      </VTarget>,\n                      this.tooltip && (\n                        <VFollower\n                          ref={this.setFollowerRefs(index)}\n                          show={showTooltip}\n                          to={this.adjustedTo}\n                          enabled={\n                            (this.showTooltip && !this.range)\n                            || this.followerEnabledIndexSet.has(index)\n                          }\n                          teleportDisabled={\n                            this.adjustedTo === useAdjustedTo.tdkey\n                          }\n                          placement={this.mergedPlacement}\n                          containerClass={this.namespace}\n                        >\n                          {{\n                            default: () => (\n                              <Transition\n                                name=\"fade-in-scale-up-transition\"\n                                appear={this.isMounted}\n                                css={this.shouldKeepTooltipTransition(index)}\n                                onEnter={() => {\n                                  this.followerEnabledIndexSet.add(index)\n                                }}\n                                onAfterLeave={() => {\n                                  this.followerEnabledIndexSet.delete(index)\n                                }}\n                              >\n                                {{\n                                  default: () => {\n                                    if (showTooltip) {\n                                      this.indicatorOnRender?.()\n                                      return (\n                                        <div\n                                          class={[\n                                            `${mergedClsPrefix}-slider-handle-indicator`,\n                                            this.indicatorThemeClass,\n                                            `${mergedClsPrefix}-slider-handle-indicator--${this.mergedPlacement}`\n                                          ]}\n                                          style={\n                                            this\n                                              .indicatorCssVars as CSSProperties\n                                          }\n                                        >\n                                          {typeof formatTooltip === 'function'\n                                            ? formatTooltip(value)\n                                            : value}\n                                        </div>\n                                      )\n                                    }\n                                    return null\n                                  }\n                                }}\n                              </Transition>\n                            )\n                          }}\n                        </VFollower>\n                      )\n                    ]\n                  }}\n                </VBinder>\n              )\n            })}\n          </div>\n          {this.marks ? (\n            <div class={`${mergedClsPrefix}-slider-marks`}>\n              {this.markInfos.map(mark => (\n                <div\n                  key={mark.key}\n                  class={`${mergedClsPrefix}-slider-mark`}\n                  style={mark.style}\n                >\n                  {typeof mark.label === 'function' ? mark.label() : mark.label}\n                </div>\n              ))}\n            </div>\n          ) : null}\n        </div>\n      </div>\n    )\n  }\n})\n"
  },
  {
    "path": "src/slider/src/interface.ts",
    "content": "export type OnUpdateValueImpl = (value: number | number[]) => void\n"
  },
  {
    "path": "src/slider/src/styles/index.cssr.ts",
    "content": "import { fadeInScaleUpTransition } from '../../../_styles/transitions/fade-in-scale-up.cssr'\nimport { c, cB, cE, cM, insideModal, insidePopover } from '../../../_utils/cssr'\n\n// vars:\n// --n-bezier\n// --n-dot-border\n// --n-dot-border-active\n// --n-dot-border-radius\n// --n-dot-box-shadow\n// --n-dot-color\n// --n-dot-color-modal\n// --n-dot-color-popover\n// --n-dot-height\n// --n-dot-width\n// --n-fill-color\n// --n-fill-color-hover\n// --n-font-size\n// --n-handle-box-shadow\n// --n-handle-box-shadow-active\n// --n-handle-box-shadow-focus\n// --n-handle-box-shadow-hover\n// --n-handle-color\n// --n-handle-size\n// --n-indicator-border-radius\n// --n-indicator-box-shadow\n// --n-indicator-color\n// --n-indicator-text-color\n// --n-rail-color\n// --n-rail-color-hover\n// --n-rail-height\n// --n-rail-width-vertical\n// --n-mark-font-size\nexport default c([\n  cB('slider', `\n    display: block;\n    padding: calc((var(--n-handle-size) - var(--n-rail-height)) / 2) 0;\n    position: relative;\n    z-index: 0;\n    width: 100%;\n    cursor: pointer;\n    user-select: none;\n    -webkit-user-select: none;\n  `, [\n    cM('reverse', [\n      cB('slider-handles', [\n        cB('slider-handle-wrapper', `\n          transform: translate(50%, -50%);\n        `)\n      ]),\n      cB('slider-dots', [\n        cB('slider-dot', `\n          transform: translateX(50%, -50%);\n        `)\n      ]),\n      cM('vertical', [\n        cB('slider-handles', [\n          cB('slider-handle-wrapper', `\n            transform: translate(-50%, -50%);\n          `)\n        ]),\n        cB('slider-marks', [\n          cB('slider-mark', `\n            transform: translateY(calc(-50% + var(--n-dot-height) / 2));\n          `)\n        ]),\n        cB('slider-dots', [\n          cB('slider-dot', `\n            transform: translateX(-50%) translateY(0);\n          `)\n        ])\n      ])\n    ]),\n    cM('vertical', `\n      box-sizing: content-box;\n      padding: 0 calc((var(--n-handle-size) - var(--n-rail-height)) / 2);\n      width: var(--n-rail-width-vertical);\n      height: 100%;\n    `, [\n      cB('slider-handles', `\n        top: calc(var(--n-handle-size) / 2);\n        right: 0;\n        bottom: calc(var(--n-handle-size) / 2);\n        left: 0;\n      `, [\n        cB('slider-handle-wrapper', `\n          top: unset;\n          left: 50%;\n          transform: translate(-50%, 50%);\n        `)\n      ]),\n      cB('slider-rail', `\n        height: 100%;\n      `, [\n        cE('fill', `\n          top: unset;\n          right: 0;\n          bottom: unset;\n          left: 0;\n        `)\n      ]),\n      cM('with-mark', `\n        width: var(--n-rail-width-vertical);\n        margin: 0 32px 0 8px;\n      `),\n      cB('slider-marks', `\n        top: calc(var(--n-handle-size) / 2);\n        right: unset;\n        bottom: calc(var(--n-handle-size) / 2);\n        left: 22px;\n        font-size: var(--n-mark-font-size);\n      `, [\n        cB('slider-mark', `\n          transform: translateY(50%);\n          white-space: nowrap;\n        `)\n      ]),\n      cB('slider-dots', `\n        top: calc(var(--n-handle-size) / 2);\n        right: unset;\n        bottom: calc(var(--n-handle-size) / 2);\n        left: 50%;\n      `, [\n        cB('slider-dot', `\n          transform: translateX(-50%) translateY(50%);\n        `)\n      ])\n    ]),\n    cM('disabled', `\n      cursor: not-allowed;\n      opacity: var(--n-opacity-disabled);\n    `, [\n      cB('slider-handle', `\n        cursor: not-allowed;\n      `)\n    ]),\n    cM('with-mark', `\n      width: 100%;\n      margin: 8px 0 32px 0;\n    `),\n    c('&:hover', [\n      cB('slider-rail', {\n        backgroundColor: 'var(--n-rail-color-hover)'\n      }, [\n        cE('fill', {\n          backgroundColor: 'var(--n-fill-color-hover)'\n        })\n      ]),\n      cB('slider-handle', {\n        boxShadow: 'var(--n-handle-box-shadow-hover)'\n      })\n    ]),\n    cM('active', [\n      cB('slider-rail', {\n        backgroundColor: 'var(--n-rail-color-hover)'\n      }, [\n        cE('fill', {\n          backgroundColor: 'var(--n-fill-color-hover)'\n        })\n      ]),\n      cB('slider-handle', {\n        boxShadow: 'var(--n-handle-box-shadow-hover)'\n      })\n    ]),\n    cB('slider-marks', `\n      position: absolute;\n      top: 18px;\n      left: calc(var(--n-handle-size) / 2);\n      right: calc(var(--n-handle-size) / 2);\n    `, [\n      cB('slider-mark', `\n        position: absolute;\n        transform: translateX(-50%);\n        white-space: nowrap;\n      `)\n    ]),\n    cB('slider-rail', `\n      width: 100%;\n      position: relative;\n      height: var(--n-rail-height);\n      background-color: var(--n-rail-color);\n      transition: background-color .3s var(--n-bezier);\n      border-radius: calc(var(--n-rail-height) / 2);\n    `, [\n      cE('fill', `\n        position: absolute;\n        top: 0;\n        bottom: 0;\n        border-radius: calc(var(--n-rail-height) / 2);\n        transition: background-color .3s var(--n-bezier);\n        background-color: var(--n-fill-color);\n      `)\n    ]),\n    cB('slider-handles', `\n      position: absolute;\n      top: 0;\n      right: calc(var(--n-handle-size) / 2);\n      bottom: 0;\n      left: calc(var(--n-handle-size) / 2);\n    `, [\n      cB('slider-handle-wrapper', `\n        outline: none;\n        position: absolute;\n        top: 50%;\n        transform: translate(-50%, -50%);\n        cursor: pointer;\n        display: flex;\n      `, [\n        cB('slider-handle', `\n          height: var(--n-handle-size);\n          width: var(--n-handle-size);\n          border-radius: 50%;\n          overflow: hidden;\n          transition: box-shadow .2s var(--n-bezier), background-color .3s var(--n-bezier);\n          background-color: var(--n-handle-color);\n          box-shadow: var(--n-handle-box-shadow);\n        `, [\n          c('&:hover', `\n            box-shadow: var(--n-handle-box-shadow-hover);\n          `)\n        ]),\n        c('&:focus', [\n          cB('slider-handle', `\n            box-shadow: var(--n-handle-box-shadow-focus);\n          `, [\n            c('&:hover', `\n              box-shadow: var(--n-handle-box-shadow-active);\n            `)\n          ])\n        ])\n      ])\n    ]),\n    cB('slider-dots', `\n      position: absolute;\n      top: 50%;\n      left: calc(var(--n-handle-size) / 2);\n      right: calc(var(--n-handle-size) / 2);\n    `, [\n      cM('transition-disabled', [\n        cB('slider-dot', 'transition: none;')\n      ]),\n      cB('slider-dot', `\n        transition:\n          border-color .3s var(--n-bezier),\n          box-shadow .3s var(--n-bezier),\n          background-color .3s var(--n-bezier);\n        position: absolute;\n        transform: translate(-50%, -50%);\n        height: var(--n-dot-height);\n        width:  var(--n-dot-width);\n        border-radius: var(--n-dot-border-radius);\n        overflow: hidden;\n        box-sizing: border-box;\n        border: var(--n-dot-border);\n        background-color: var(--n-dot-color);\n      `, [\n        cM('active', 'border: var(--n-dot-border-active);')\n      ])\n    ])\n  ]),\n  cB('slider-handle-indicator', `\n    font-size: var(--n-font-size);\n    padding: 6px 10px;\n    border-radius: var(--n-indicator-border-radius);\n    color: var(--n-indicator-text-color);\n    background-color: var(--n-indicator-color);\n    box-shadow: var(--n-indicator-box-shadow);\n  `, [\n    fadeInScaleUpTransition()\n  ]),\n  cB('slider-handle-indicator', `\n    font-size: var(--n-font-size);\n    padding: 6px 10px;\n    border-radius: var(--n-indicator-border-radius);\n    color: var(--n-indicator-text-color);\n    background-color: var(--n-indicator-color);\n    box-shadow: var(--n-indicator-box-shadow);\n  `, [\n    cM('top', `\n      margin-bottom: 12px;\n    `),\n    cM('right', `\n      margin-left: 12px;\n    `),\n    cM('bottom', `\n      margin-top: 12px;\n    `),\n    cM('left', `\n      margin-right: 12px;\n    `),\n    fadeInScaleUpTransition()\n  ]),\n  insideModal(\n    cB('slider', [\n      cB('slider-dot', 'background-color: var(--n-dot-color-modal);')\n    ])\n  ),\n  insidePopover(\n    cB('slider', [\n      cB('slider-dot', 'background-color: var(--n-dot-color-popover);')\n    ])\n  )\n])\n"
  },
  {
    "path": "src/slider/src/utils.ts",
    "content": "import type { ComponentPublicInstance } from 'vue'\nimport { onBeforeUpdate } from 'vue'\n\nexport function isTouchEvent(e: MouseEvent | TouchEvent): e is TouchEvent {\n  return window.TouchEvent && e instanceof window.TouchEvent\n}\n\ntype RefType = HTMLElement | ComponentPublicInstance\ntype RefKey = number\ntype RefsValue<T extends RefType> = Map<RefKey, T>\nexport function useRefs<T extends RefType>(): [\n  RefsValue<T>,\n  (key: RefKey) => (el: any) => void\n] {\n  const refs = new Map()\n  const setRefs = (index: RefKey) => (el: any) => {\n    refs.set(index, el)\n  }\n\n  onBeforeUpdate(() => {\n    refs.clear()\n  })\n\n  return [refs, setRefs]\n}\n"
  },
  {
    "path": "src/slider/styles/_common.ts",
    "content": "export default {\n  railHeight: '4px',\n  railWidthVertical: '4px',\n  handleSize: '18px',\n  dotHeight: '8px',\n  dotWidth: '8px',\n  dotBorderRadius: '4px'\n}\n"
  },
  {
    "path": "src/slider/styles/dark.ts",
    "content": "import type { SliderTheme } from './light'\nimport { commonDark } from '../../_styles/common'\nimport sizeVariables from './_common'\n\nconst sliderDark: SliderTheme = {\n  name: 'Slider',\n  common: commonDark,\n  self(vars) {\n    const boxShadow = '0 2px 8px 0 rgba(0, 0, 0, 0.12)'\n    const {\n      railColor,\n      modalColor,\n      primaryColorSuppl,\n      popoverColor,\n      textColor2,\n      cardColor,\n      borderRadius,\n      fontSize,\n      opacityDisabled\n    } = vars\n    return {\n      ...sizeVariables,\n      fontSize,\n      markFontSize: fontSize,\n      railColor,\n      railColorHover: railColor,\n      fillColor: primaryColorSuppl,\n      fillColorHover: primaryColorSuppl,\n      opacityDisabled,\n      handleColor: '#FFF',\n      dotColor: cardColor,\n      dotColorModal: modalColor,\n      dotColorPopover: popoverColor,\n      handleBoxShadow: '0px 2px 4px 0 rgba(0, 0, 0, 0.4)',\n      handleBoxShadowHover: '0px 2px 4px 0 rgba(0, 0, 0, 0.4)',\n      handleBoxShadowActive: '0px 2px 4px 0 rgba(0, 0, 0, 0.4)',\n      handleBoxShadowFocus: '0px 2px 4px 0 rgba(0, 0, 0, 0.4)',\n      indicatorColor: popoverColor,\n      indicatorBoxShadow: boxShadow,\n      indicatorTextColor: textColor2,\n      indicatorBorderRadius: borderRadius,\n      dotBorder: `2px solid ${railColor}`,\n      dotBorderActive: `2px solid ${primaryColorSuppl}`,\n      dotBoxShadow: ''\n    }\n  }\n}\n\nexport default sliderDark\n"
  },
  {
    "path": "src/slider/styles/index.ts",
    "content": "export { default as sliderDark } from './dark'\nexport { default as sliderLight } from './light'\nexport type { SliderTheme, SliderThemeVars } from './light'\n"
  },
  {
    "path": "src/slider/styles/light.ts",
    "content": "import type { Theme } from '../../_mixins'\nimport type { ThemeCommonVars } from '../../_styles/common'\nimport { commonLight } from '../../_styles/common'\nimport sizeVariables from './_common'\n\nfunction self(vars: ThemeCommonVars) {\n  const indicatorColor = 'rgba(0, 0, 0, .85)'\n  const boxShadow = '0 2px 8px 0 rgba(0, 0, 0, 0.12)'\n  const {\n    railColor,\n    primaryColor,\n    baseColor,\n    cardColor,\n    modalColor,\n    popoverColor,\n    borderRadius,\n    fontSize,\n    opacityDisabled\n  } = vars\n\n  return {\n    ...sizeVariables,\n    fontSize,\n    markFontSize: fontSize,\n    railColor,\n    railColorHover: railColor,\n    fillColor: primaryColor,\n    fillColorHover: primaryColor,\n    opacityDisabled,\n    handleColor: '#FFF',\n    dotColor: cardColor,\n    dotColorModal: modalColor,\n    dotColorPopover: popoverColor,\n    handleBoxShadow:\n      '0 1px 4px 0 rgba(0, 0, 0, 0.3), inset 0 0 1px 0 rgba(0, 0, 0, 0.05)',\n    handleBoxShadowHover:\n      '0 1px 4px 0 rgba(0, 0, 0, 0.3), inset 0 0 1px 0 rgba(0, 0, 0, 0.05)',\n    handleBoxShadowActive:\n      '0 1px 4px 0 rgba(0, 0, 0, 0.3), inset 0 0 1px 0 rgba(0, 0, 0, 0.05)',\n    handleBoxShadowFocus:\n      '0 1px 4px 0 rgba(0, 0, 0, 0.3), inset 0 0 1px 0 rgba(0, 0, 0, 0.05)',\n    indicatorColor,\n    indicatorBoxShadow: boxShadow,\n    indicatorTextColor: baseColor,\n    indicatorBorderRadius: borderRadius,\n    dotBorder: `2px solid ${railColor}`,\n    dotBorderActive: `2px solid ${primaryColor}`,\n    dotBoxShadow: ''\n  }\n}\n\nexport type SliderThemeVars = ReturnType<typeof self>\n\nconst sliderLight: Theme<'Slider', SliderThemeVars> = {\n  name: 'Slider',\n  common: commonLight,\n  self\n}\n\nexport default sliderLight\nexport type SliderTheme = typeof sliderLight\n"
  },
  {
    "path": "src/slider/tests/Slider.spec.ts",
    "content": "/* eslint-disable unused-imports/no-unused-vars */\nimport { mount } from '@vue/test-utils'\nimport { nextTick } from 'vue'\nimport { NSlider } from '../index'\n\ndescribe('n-slider', () => {\n  it('should work with import on demand', () => {\n    mount(NSlider)\n  })\n\n  it('should work with `defaultValue`', async () => {\n    const wrapper = mount(NSlider, {\n      props: {\n        defaultValue: 23\n      }\n    })\n\n    const sliderRailFill = wrapper.find('.n-slider-rail__fill')\n    expect((sliderRailFill.element as HTMLElement).style.width).toEqual('23%')\n    wrapper.unmount()\n  })\n\n  it('should work with `marks`', async () => {\n    const wrapper = mount(NSlider, {\n      props: {\n        marks: {\n          34: '太棒了',\n          75: '不错'\n        }\n      }\n    })\n\n    const sliderDots = wrapper.findAll('.n-slider-dot')\n    expect(sliderDots.length).toBe(2)\n    expect((sliderDots[0].element as HTMLElement).style.left).toEqual('34%')\n    expect((sliderDots[1].element as HTMLElement).style.left).toEqual('75%')\n\n    const sliderMarks = wrapper.findAll('.n-slider-mark')\n    expect(sliderMarks.length).toBe(2)\n\n    expect((sliderMarks[0].element as HTMLElement).style.left).toEqual('34%')\n    expect(sliderMarks[0].text()).toEqual('太棒了')\n\n    expect((sliderMarks[1].element as HTMLElement).style.left).toEqual('75%')\n    expect(sliderMarks[1].text()).toEqual('不错')\n    wrapper.unmount()\n  })\n\n  it('accept correct callback types', () => {\n    function onUpdateValue1(value: number): void {}\n    function onUpdateValue2(value: number[]): void {}\n    mount(NSlider, {\n      props: {\n        onUpdateValue: onUpdateValue1\n      }\n    })\n    mount(NSlider, {\n      props: {\n        onUpdateValue: onUpdateValue2\n      }\n    })\n  })\n\n  it('should work with `disabled` prop', async () => {\n    const wrapper = mount(NSlider)\n\n    await wrapper.setProps({ disabled: true })\n    expect(wrapper.find('.n-slider').classes()).toContain('n-slider--disabled')\n    wrapper.unmount()\n  })\n\n  it('should work with `marks` prop', async () => {\n    const wrapper = mount(NSlider, {\n      props: {\n        marks: {\n          30: 'test1',\n          70: 'test2'\n        }\n      }\n    })\n\n    expect(wrapper.findAll('.n-slider-mark').length).toBe(2)\n    expect(wrapper.findAll('.n-slider-mark')[0].attributes('style')).toContain(\n      'left: 30%'\n    )\n    expect(wrapper.findAll('.n-slider-mark')[0].text()).toContain('test1')\n    expect(wrapper.findAll('.n-slider-mark')[1].attributes('style')).toContain(\n      'left: 70%'\n    )\n    expect(wrapper.findAll('.n-slider-mark')[1].text()).toContain('test2')\n    wrapper.unmount()\n  })\n\n  it('should work with `min` & `max` prop', async () => {\n    const wrapper = mount(NSlider, {\n      props: {\n        min: 1,\n        max: 101,\n        defaultValue: 24\n      }\n    })\n\n    const sliderRailFill = wrapper.find('.n-slider-rail__fill')\n    const element = sliderRailFill.element as HTMLElement\n    expect(element.style.left).toEqual('0%')\n    expect(element.style.width).toEqual('23%')\n    wrapper.unmount()\n  })\n\n  it('should work with `range` & `defaultValue` prop', async () => {\n    const wrapper = mount(NSlider, {\n      props: {\n        range: true,\n        defaultValue: [24, 49]\n      }\n    })\n\n    expect(wrapper.findAll('.n-slider-handle-wrapper').length).toBe(2)\n\n    const sliderRailFill = wrapper.find('.n-slider-rail__fill')\n    const element = sliderRailFill.element as HTMLElement\n    expect(element.style.left).toEqual('24%')\n    expect(element.style.width).toEqual('25%')\n    wrapper.unmount()\n  })\n\n  it('should work with `range` & `min` & `max` prop', async () => {\n    const wrapper = mount(NSlider, {\n      props: {\n        range: true,\n        min: 1,\n        max: 101,\n        defaultValue: [25, 65]\n      }\n    })\n\n    const sliderRailFill = wrapper.find('.n-slider-rail__fill')\n    const element = sliderRailFill.element as HTMLElement\n    expect(element.style.left).toEqual('24%')\n    expect(element.style.width).toEqual('40%')\n    wrapper.unmount()\n  })\n\n  it('should work with `vertical` prop', async () => {\n    const wrapper = mount(NSlider, {\n      props: {\n        defaultValue: 77,\n        vertical: true\n      }\n    })\n\n    const sliderRailFill = wrapper.find('.n-slider-rail__fill')\n    const firstHandle = wrapper.find('.n-slider-handle-wrapper')\n    expect((sliderRailFill.element as HTMLElement).style.height).toEqual('77%')\n    expect((firstHandle.element as HTMLElement).style.bottom).toEqual('77%')\n    wrapper.unmount()\n  })\n\n  it('should work with `range` & `vertical` prop', async () => {\n    const wrapper = mount(NSlider, {\n      props: {\n        range: true,\n        defaultValue: [24, 49],\n        vertical: true\n      }\n    })\n\n    const sliderRailFill = wrapper.find('.n-slider-rail__fill')\n    const element = sliderRailFill.element as HTMLElement\n    expect(element.style.bottom).toEqual('24%')\n    expect(element.style.height).toEqual('25%')\n    expect(\n      wrapper.findAll('.n-slider-handle-wrapper')[0].attributes('style')\n    ).toContain('bottom: 24%')\n    expect(\n      wrapper.findAll('.n-slider-handle-wrapper')[1].attributes('style')\n    ).toContain('bottom: 49%')\n    wrapper.unmount()\n  })\n\n  it('should work with `reverse` prop', async () => {\n    const wrapper = mount(NSlider)\n\n    expect(wrapper.find('.n-slider').classes()).not.toContain(\n      'n-slider--reverse'\n    )\n\n    await wrapper.setProps({ reverse: true })\n    expect(wrapper.find('.n-slider').classes()).toContain('n-slider--reverse')\n    wrapper.unmount()\n  })\n\n  it('should slided to the specific mark when step is `mark`', async () => {\n    const wrapper = mount(NSlider, {\n      props: {\n        defaultValue: 0,\n        step: 'mark',\n        marks: {\n          30: '30',\n          70: '70'\n        }\n      }\n    })\n    const mouseDown = new MouseEvent('mousedown', {\n      clientX: 25\n    })\n    const slider = wrapper.find('.n-slider')\n    const handle = wrapper.find('.n-slider-handle-wrapper')\n    ;(slider.element as HTMLElement).style.width = '100px'\n    ;(slider.element as HTMLElement).dispatchEvent(mouseDown)\n    await nextTick()\n    expect((handle.element as HTMLElement).style.left).toEqual('30%')\n    wrapper.unmount()\n  })\n\n  it('should have the aria role of \"slider\"', () => {\n    const wrapper = mount(NSlider)\n    expect(wrapper.find('.n-slider-handle-wrapper').attributes('role')).toBe(\n      'slider'\n    )\n    wrapper.unmount()\n  })\n\n  it('should be some aria properties for \"slider\"', () => {\n    const wrapper = mount(NSlider, {\n      props: {\n        defaultValue: 50,\n        disabled: true\n      }\n    })\n    const handle = wrapper.find('.n-slider-handle-wrapper')\n    expect(handle.attributes('aria-valuenow')).toBe('50')\n    expect(handle.attributes('aria-valuemin')).toBe('0')\n    expect(handle.attributes('aria-valuemax')).toBe('100')\n    expect(handle.attributes('aria-orientation')).toBe('horizontal')\n    expect(handle.attributes('aria-disabled')).toBe('true')\n    wrapper.unmount()\n  })\n})\n"
  },
  {
    "path": "src/slider/tests/server.spec.tsx",
    "content": "import { setup } from '@css-render/vue3-ssr'\nimport { renderToString } from '@vue/server-renderer'\n/**\n * @vitest-environment node\n */\nimport { createSSRApp, h } from 'vue'\nimport { NSlider } from '../..'\n\ndescribe('server side rendering', () => {\n  it('works', async () => {\n    const app = createSSRApp(() => <NSlider />)\n    setup(app)\n    try {\n      await renderToString(app)\n    }\n    catch (e) {\n      expect(e).not.toBeTruthy()\n    }\n  })\n})\n"
  },
  {
    "path": "src/space/demos/enUS/basic.demo.vue",
    "content": "<markdown>\n# Basic\n</markdown>\n\n<template>\n  <n-space>\n    <n-button>Oops!</n-button>\n    <n-button>Oops!</n-button>\n    <n-button>Oops!</n-button>\n    <n-button>Long! Long! Cross the line!</n-button>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/space/demos/enUS/center.demo.vue",
    "content": "<markdown>\n# From Center\n</markdown>\n\n<template>\n  <n-space justify=\"center\">\n    <n-button>Oops!</n-button>\n    <n-button>Oops!</n-button>\n    <n-button>Oops!</n-button>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/space/demos/enUS/from-end.demo.vue",
    "content": "<markdown>\n# From End\n</markdown>\n\n<template>\n  <n-space justify=\"end\">\n    <n-button>Oops!</n-button>\n    <n-button>Oops!</n-button>\n    <n-button>Oops!</n-button>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/space/demos/enUS/index.demo-entry.md",
    "content": "# Space\n\nA great invention (which is not invented by me).\n\nIf you don't have compatibility issues for `gap` CSS property, it's suggested to use [Flex](flex).\n\n## Demos\n\n```demo\nbasic.vue\nvertical.vue\nfrom-end.vue\nspace-between.vue\nspace-around.vue\ncenter.vue\nreverse.vue\n```\n\n## API\n\n### Space Props\n\n| Name | Type | Default | Description | Version |\n| --- | --- | --- | --- | --- |\n| align | `'start' \\| 'end' \\| 'center' \\| 'baseline' \\| 'stretch'` | `undefined` | Vertical arrangement. |  |\n| inline | `boolean` | `false` | Is it an inline element. |  |\n| wrap-item | `boolean` | `true` | Whether a container exists to wrap the child elements. `false` value will only work in browsers that supports flex gap. | 2.30.5 |\n| item-class | `string` | `undefined` | Node class, valid when `wrap-item` is `true` | 2.36.0 |\n| item-style | `string \\| object` | `undefined` | Node style, valid when `wrap-item` is `true` |  |\n| justify | `'start' \\| 'end' \\| 'center' \\| 'space-around' \\| 'space-between' \\| 'space-evenly'` | `'start'` | Horizontal arrangement. | `'space-evenly'` 2.28.3 |\n| reverse | `boolean` | `false` | Whether to reverse inner items. | 2.37.0 |\n| size | `'small' \\| 'medium' \\| 'large' \\| number \\| [number, number]` | `'medium'` | When it's a number, it will be used as vertical and horizontal gap, or it is `[horizontalGap, verticalGap]`. |  |\n| vertical | `boolean` | `false` | Whether to lay out vertically. |  |\n| wrap | `boolean` | `true` | Whether to exceed the line break. |  |\n\n### Space Slots\n\n| Name    | Parameters | Description      |\n| ------- | ---------- | ---------------- |\n| default | `()`       | Spacing content. |\n"
  },
  {
    "path": "src/space/demos/enUS/reverse.demo.vue",
    "content": "<markdown>\n# Reverse\n</markdown>\n\n<template>\n  <n-space reverse>\n    <n-button>1</n-button>\n    <n-button>2</n-button>\n    <n-button>3</n-button>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/space/demos/enUS/space-around.demo.vue",
    "content": "<markdown>\n# Space Around\n</markdown>\n\n<template>\n  <n-space justify=\"space-around\" size=\"large\">\n    <n-button>Oops!</n-button>\n    <n-button>Oops!</n-button>\n    <n-button>Oops!</n-button>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/space/demos/enUS/space-between.demo.vue",
    "content": "<markdown>\n# Space Between\n</markdown>\n\n<template>\n  <n-space justify=\"space-between\">\n    <n-button>Oops!</n-button>\n    <n-button>Oops!</n-button>\n    <n-button>Oops!</n-button>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/space/demos/enUS/vertical.demo.vue",
    "content": "<markdown>\n# Vertical\n</markdown>\n\n<template>\n  <n-space vertical>\n    <n-button>Oops!</n-button>\n    <n-button>Oops!</n-button>\n    <n-button>Oops!</n-button>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/space/demos/zhCN/basic.demo.vue",
    "content": "<markdown>\n# 基础用法\n</markdown>\n\n<template>\n  <n-space>\n    <n-button>Oops!</n-button>\n    <n-button>Oops!</n-button>\n    <n-button>Oops!</n-button>\n    <n-button>Long! Long! Cross the line!</n-button>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/space/demos/zhCN/center.demo.vue",
    "content": "<markdown>\n# 从中间\n</markdown>\n\n<template>\n  <n-space justify=\"center\">\n    <n-button>Oops!</n-button>\n    <n-button>Oops!</n-button>\n    <n-button>Oops!</n-button>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/space/demos/zhCN/from-end.demo.vue",
    "content": "<markdown>\n# 从尾部\n</markdown>\n\n<template>\n  <n-space justify=\"end\">\n    <n-button>Oops!</n-button>\n    <n-button>Oops!</n-button>\n    <n-button>Oops!</n-button>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/space/demos/zhCN/grid-debug.demo.vue",
    "content": "<markdown>\n# Grid Debug\n</markdown>\n\n<template>\n  <n-space vertical>\n    <div class=\"grid-list\">\n      <div class=\"item\" />\n      <div class=\"item\" />\n      <div class=\"item\" />\n    </div>\n    <div class=\"grid-list\">\n      <div class=\"item\" />\n      <div class=\"item\" />\n      <div class=\"item\" />\n    </div>\n  </n-space>\n</template>\n\n<style>\n.grid-list {\n  display: grid;\n  grid-template-columns: repeat(auto-fill, 100px);\n  gap: 20px;\n}\n.item {\n  background-color: tomato;\n  height: 100px;\n}\n</style>\n"
  },
  {
    "path": "src/space/demos/zhCN/index.demo-entry.md",
    "content": "# 间距 Space\n\n这是个伟大的发明（不是我发明的）。\n\n如果你没有对 `gap` CSS 属性的兼容性要求，建议使用 [Flex](flex)。\n\n## 演示\n\n```demo\nbasic.vue\nvertical.vue\nfrom-end.vue\nspace-between.vue\nspace-around.vue\ncenter.vue\nreverse.vue\ngrid-debug.vue\nrtl-debug.vue\n```\n\n## API\n\n### Space Props\n\n| 名称 | 类型 | 默认值 | 说明 | 版本 |\n| --- | --- | --- | --- | --- |\n| align | `'start' \\| 'end' \\| 'center' \\| 'baseline' \\| 'stretch'` | `undefined` | 垂直排列方式 |  |\n| inline | `boolean` | `false` | 是否为行内元素 |  |\n| wrap-item | `boolean` | `true` | 是否存在包裹子元素的容器，`false` 值只会对支持 flex gap 的浏览器生效 | 2.30.5 |\n| item-class | `string` | `undefined` | 节点类名，当 `wrap-item` 为 `true` 时有效 | 2.36.0 |\n| item-style | `string \\| object` | `undefined` | 节点样式，当 `wrap-item` 为 `true` 时有效 |  |\n| justify | `'start' \\| 'end' \\| 'center' \\| 'space-around' \\| 'space-between' \\| 'space-evenly'` | `'start'` | 水平排列方式 | `'space-evenly'` 2.28.3 |\n| reverse | `boolean` | `false` | 是否反向排列内部元素 | 2.37.0 |\n| size | `'small' \\| 'medium' \\| 'large' \\| number \\| [number, number]` | `'medium'` | 为数字时，是水平和垂直间距；为数组时，是 [水平间距, 垂直间距] |  |\n| vertical | `boolean` | `false` | 是否垂直布局 |  |\n| wrap | `boolean` | `true` | 是否超出换行 |  |\n\n### Space Slots\n\n| 名称    | 参数 | 说明     |\n| ------- | ---- | -------- |\n| default | `()` | 间距内容 |\n"
  },
  {
    "path": "src/space/demos/zhCN/reverse.demo.vue",
    "content": "<markdown>\n# 反向\n</markdown>\n\n<template>\n  <n-space reverse>\n    <n-button>1</n-button>\n    <n-button>2</n-button>\n    <n-button>3</n-button>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/space/demos/zhCN/rtl-debug.demo.vue",
    "content": "<markdown>\n# Rtl Debug\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { unstableSpaceRtl } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst rtlEnabled = ref(false)\nconst rtlStyles = [unstableSpaceRtl]\n</script>\n\n<template>\n  <n-space vertical>\n    <n-space><n-switch v-model:value=\"rtlEnabled\" />Rtl</n-space>\n    <n-config-provider :rtl=\"rtlEnabled ? rtlStyles : undefined\">\n      <n-space>\n        <n-button>Oops!</n-button>\n        <n-button>Oops!</n-button>\n        <n-button>Long! Long! Cross the line!</n-button>\n      </n-space>\n    </n-config-provider>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/space/demos/zhCN/space-around.demo.vue",
    "content": "<markdown>\n# 空间围绕\n</markdown>\n\n<template>\n  <n-space justify=\"space-around\" size=\"large\">\n    <n-button>Oops!</n-button>\n    <n-button>Oops!</n-button>\n    <n-button>Oops!</n-button>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/space/demos/zhCN/space-between.demo.vue",
    "content": "<markdown>\n# 间隙\n</markdown>\n\n<template>\n  <n-space justify=\"space-between\">\n    <n-button>Oops!</n-button>\n    <n-button>Oops!</n-button>\n    <n-button>Oops!</n-button>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/space/demos/zhCN/vertical.demo.vue",
    "content": "<markdown>\n# 垂直\n</markdown>\n\n<template>\n  <n-space vertical>\n    <n-button>Oops!</n-button>\n    <n-button>Oops!</n-button>\n    <n-button>Oops!</n-button>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/space/index.ts",
    "content": "export type * from './src/public-types'\nexport { default as NSpace, spaceProps } from './src/Space'\nexport type { SpaceProps } from './src/Space'\n"
  },
  {
    "path": "src/space/src/Space.tsx",
    "content": "import type { CSSProperties, PropType } from 'vue'\nimport type { ThemeProps } from '../../_mixins'\nimport type { ExtractPublicPropTypes } from '../../_utils'\nimport type { SpaceTheme } from '../styles'\nimport type { SpaceSize } from './public-types'\nimport { depx, getGap } from 'seemly'\nimport { Comment, computed, defineComponent, h } from 'vue'\nimport { useConfig, useTheme } from '../../_mixins'\nimport { useRtl } from '../../_mixins/use-rtl'\nimport { createKey, flatten, getSlot } from '../../_utils'\nimport { spaceLight } from '../styles'\nimport { ensureSupportFlexGap } from './utils'\n\ntype Align\n  = | 'stretch'\n    | 'baseline'\n    | 'start'\n    | 'end'\n    | 'center'\n    | 'flex-end'\n    | 'flex-start'\n\nexport type Justify\n  = | 'start'\n    | 'end'\n    | 'center'\n    | 'space-around'\n    | 'space-between'\n    | 'space-evenly'\n\nexport const spaceProps = {\n  ...(useTheme.props as ThemeProps<SpaceTheme>),\n  align: String as PropType<Align>,\n  justify: {\n    type: String as PropType<Justify>,\n    default: 'start'\n  },\n  inline: Boolean,\n  vertical: Boolean,\n  reverse: Boolean,\n  size: [String, Number, Array] as PropType<SpaceSize>,\n  wrapItem: {\n    type: Boolean,\n    default: true\n  },\n  itemClass: String,\n  itemStyle: [String, Object] as PropType<string | CSSProperties>,\n  wrap: {\n    type: Boolean,\n    default: true\n  },\n  // internal\n  internalUseGap: {\n    type: Boolean,\n    default: undefined\n  }\n} as const\n\nexport type SpaceProps = ExtractPublicPropTypes<typeof spaceProps>\n\nexport default defineComponent({\n  name: 'Space',\n  props: spaceProps,\n  setup(props) {\n    const { mergedClsPrefixRef, mergedRtlRef, mergedComponentPropsRef }\n      = useConfig(props)\n    const mergedSizeRef = computed<SpaceSize>(() => {\n      return (\n        props.size || mergedComponentPropsRef?.value?.Space?.size || 'medium'\n      )\n    })\n    const themeRef = useTheme(\n      'Space',\n      '-space',\n      undefined,\n      spaceLight,\n      props,\n      mergedClsPrefixRef\n    )\n    const rtlEnabledRef = useRtl('Space', mergedRtlRef, mergedClsPrefixRef)\n    return {\n      useGap: ensureSupportFlexGap(),\n      rtlEnabled: rtlEnabledRef,\n      mergedClsPrefix: mergedClsPrefixRef,\n      margin: computed<{ horizontal: number, vertical: number }>(() => {\n        const size = mergedSizeRef.value\n        if (Array.isArray(size)) {\n          return {\n            horizontal: size[0],\n            vertical: size[1]\n          }\n        }\n        if (typeof size === 'number') {\n          return {\n            horizontal: size,\n            vertical: size\n          }\n        }\n        const {\n          self: { [createKey('gap', size)]: gap }\n        } = themeRef.value\n        const { row, col } = getGap(gap)\n        return {\n          horizontal: depx(col),\n          vertical: depx(row)\n        }\n      })\n    }\n  },\n  render() {\n    const {\n      vertical,\n      reverse,\n      align,\n      inline,\n      justify,\n      itemClass,\n      itemStyle,\n      margin,\n      wrap,\n      mergedClsPrefix,\n      rtlEnabled,\n      useGap,\n      wrapItem,\n      internalUseGap\n    } = this\n    const children = flatten(getSlot(this), false)\n    if (!children.length)\n      return null\n    const horizontalMargin = `${margin.horizontal}px`\n    const semiHorizontalMargin = `${margin.horizontal / 2}px`\n    const verticalMargin = `${margin.vertical}px`\n    const semiVerticalMargin = `${margin.vertical / 2}px`\n    const lastIndex = children.length - 1\n    const isJustifySpace = justify.startsWith('space-')\n    return (\n      <div\n        role=\"none\"\n        class={[\n          `${mergedClsPrefix}-space`,\n          rtlEnabled && `${mergedClsPrefix}-space--rtl`\n        ]}\n        style={{\n          display: inline ? 'inline-flex' : 'flex',\n          flexDirection: (() => {\n            if (vertical && !reverse)\n              return 'column'\n            if (vertical && reverse)\n              return 'column-reverse'\n            if (!vertical && reverse)\n              return 'row-reverse'\n            /** (!vertical && !reverse) */ else return 'row'\n          })(),\n          justifyContent: ['start', 'end'].includes(justify)\n            ? `flex-${justify}`\n            : justify,\n          flexWrap: !wrap || vertical ? 'nowrap' : 'wrap',\n          marginTop: useGap || vertical ? '' : `-${semiVerticalMargin}`,\n          marginBottom: useGap || vertical ? '' : `-${semiVerticalMargin}`,\n          alignItems: align,\n          gap: useGap ? `${margin.vertical}px ${margin.horizontal}px` : ''\n        }}\n      >\n        {!wrapItem && (useGap || internalUseGap)\n          ? children\n          : children.map((child, index) =>\n              child.type === Comment ? (\n                child\n              ) : (\n                <div\n                  role=\"none\"\n                  class={itemClass}\n                  style={[\n                    itemStyle as any,\n                    {\n                      maxWidth: '100%'\n                    },\n                    useGap\n                      ? ''\n                      : vertical\n                        ? {\n                            marginBottom:\n                              index !== lastIndex ? verticalMargin : ''\n                          }\n                        : rtlEnabled\n                          ? {\n                              marginLeft: isJustifySpace\n                                ? justify === 'space-between'\n                                && index === lastIndex\n                                  ? ''\n                                  : semiHorizontalMargin\n                                : index !== lastIndex\n                                  ? horizontalMargin\n                                  : '',\n                              marginRight: isJustifySpace\n                                ? justify === 'space-between' && index === 0\n                                  ? ''\n                                  : semiHorizontalMargin\n                                : '',\n                              paddingTop: semiVerticalMargin,\n                              paddingBottom: semiVerticalMargin\n                            }\n                          : {\n                              marginRight: isJustifySpace\n                                ? justify === 'space-between'\n                                && index === lastIndex\n                                  ? ''\n                                  : semiHorizontalMargin\n                                : index !== lastIndex\n                                  ? horizontalMargin\n                                  : '',\n                              marginLeft: isJustifySpace\n                                ? justify === 'space-between' && index === 0\n                                  ? ''\n                                  : semiHorizontalMargin\n                                : '',\n                              paddingTop: semiVerticalMargin,\n                              paddingBottom: semiVerticalMargin\n                            }\n                  ]}\n                >\n                  {child}\n                </div>\n              )\n            )}\n      </div>\n    )\n  }\n})\n"
  },
  {
    "path": "src/space/src/public-types.ts",
    "content": "export type SpaceSize = 'small' | 'medium' | 'large' | number | [number, number]\n"
  },
  {
    "path": "src/space/src/styles/rtl.cssr.ts",
    "content": "import { cB, cM } from '../../../_utils/cssr'\n\nexport default cB('space', [\n  cM('rtl', `\n    direction: rtl;\n  `)\n])\n"
  },
  {
    "path": "src/space/src/utils.ts",
    "content": "import { isBrowser } from '../../_utils'\n\nlet supportFlexGap: boolean | undefined\n\nexport function ensureSupportFlexGap(): boolean {\n  if (!isBrowser)\n    return true\n  if (supportFlexGap === undefined) {\n    // create flex container with row-gap set\n    const flex = document.createElement('div')\n    flex.style.display = 'flex'\n    flex.style.flexDirection = 'column'\n    flex.style.rowGap = '1px'\n\n    // create two, elements inside it\n    flex.appendChild(document.createElement('div'))\n    flex.appendChild(document.createElement('div'))\n\n    // append to the DOM (needed to obtain scrollHeight)\n    document.body.appendChild(flex)\n    const isSupported = flex.scrollHeight === 1 // flex container should be 1px high from the row-gap\n    document.body.removeChild(flex)\n    return (supportFlexGap = isSupported)\n  }\n  return supportFlexGap\n}\n"
  },
  {
    "path": "src/space/styles/_common.ts",
    "content": "export default {\n  gapSmall: '4px 8px',\n  gapMedium: '8px 12px',\n  gapLarge: '12px 16px'\n}\n"
  },
  {
    "path": "src/space/styles/dark.ts",
    "content": "import type { SpaceTheme } from './light'\nimport commonVars from './_common'\n\nconst spaceDark: SpaceTheme = {\n  name: 'Space',\n  self() {\n    return commonVars\n  }\n}\n\nexport default spaceDark\n"
  },
  {
    "path": "src/space/styles/index.ts",
    "content": "export { default as spaceDark } from './dark'\nexport { default as spaceLight } from './light'\nexport type { SpaceTheme, SpaceThemeVars } from './light'\nexport { spaceRtl } from './rtl'\n"
  },
  {
    "path": "src/space/styles/light.ts",
    "content": "import type { Theme } from '../../_mixins'\nimport commonVars from './_common'\n\nfunction self() {\n  return commonVars\n}\n\nexport type SpaceThemeVars = ReturnType<typeof self>\n\nconst spaceLight: Theme<'Space', SpaceThemeVars> = {\n  name: 'Space',\n  self\n}\n\nexport default spaceLight\nexport type SpaceTheme = typeof spaceLight\n"
  },
  {
    "path": "src/space/styles/rtl.ts",
    "content": "import type { RtlItem } from '../../config-provider/src/internal-interface'\nimport rtlStyle from '../src/styles/rtl.cssr'\n\nexport const spaceRtl: RtlItem = {\n  name: 'Space',\n  style: rtlStyle\n}\n"
  },
  {
    "path": "src/space/tests/Space.spec.tsx",
    "content": "import type { VueWrapper } from '@vue/test-utils'\nimport type { Justify } from '../src/Space'\nimport { mount } from '@vue/test-utils'\nimport { createCommentVNode, Fragment, h } from 'vue'\nimport { c } from '../../_utils/cssr'\nimport { NConfigProvider } from '../../config-provider'\nimport { NSpace } from '../index'\n\nfunction getChildrenNode(wrapper: VueWrapper<any>): any[] {\n  return (\n    wrapper.findAll('div').filter((v) => {\n      return !v.classes().includes('n-space')\n    }) || []\n  )\n}\n\ndescribe('n-space', () => {\n  it('should work with import on demand', () => {\n    mount(NSpace)\n  })\n\n  it('render empty children', () => {\n    const wrapper = mount({\n      render() {\n        return <NSpace />\n      }\n    })\n    expect(wrapper.find('.n-space').exists()).toBeFalsy()\n    expect(wrapper.html()).toMatchSnapshot()\n    wrapper.unmount()\n  })\n\n  it('render space string size', () => {\n    const wrapper = mount({\n      render() {\n        return <NSpace size=\"large\">{{ default: () => 'kirby' }}</NSpace>\n      }\n    })\n    expect(wrapper.attributes('style')).toContain('margin')\n    expect(wrapper.html()).toMatchSnapshot()\n    wrapper.unmount()\n  })\n\n  it('render space number size', () => {\n    const size = 20\n    const wrapper = mount({\n      render() {\n        return <NSpace size={size}>{{ default: () => 'kirby' }}</NSpace>\n      }\n    })\n    expect(wrapper.attributes('style')).toContain(`margin-top: -${size / 2}px`)\n    expect(wrapper.html()).toMatchSnapshot()\n    wrapper.unmount()\n  })\n\n  it('render space array size', async () => {\n    const wrapper = mount(NSpace, {\n      props: {\n        size: [20, 30]\n      },\n      slots: {\n        default: () => [<div>1</div>, <div>2</div>]\n      }\n    })\n\n    const childNodes = getChildrenNode(wrapper)\n    expect(childNodes[0].attributes('style')).toContain('margin-right: 20px;')\n\n    await wrapper.setProps({ vertical: true })\n    expect(childNodes[0].attributes('style')).toContain('margin-bottom: 30px;')\n    wrapper.unmount()\n  })\n\n  it('render vertical space', () => {\n    const wrapper = mount({\n      render() {\n        return (\n          <NSpace vertical>\n            {{\n              default: () => [<div>1</div>, <div>2</div>]\n            }}\n          </NSpace>\n        )\n      }\n    })\n    expect(wrapper.attributes('style')).toContain('flex-direction: column;')\n    expect(wrapper.html()).toMatchSnapshot()\n    wrapper.unmount()\n  })\n\n  it('should work with `inline` prop', () => {\n    const wrapper = mount(NSpace, {\n      props: {\n        inline: true\n      },\n      slots: {\n        default: () => '07akioni'\n      }\n    })\n\n    expect(wrapper.attributes('style')).toContain('display: inline-flex;')\n    wrapper.unmount()\n  })\n\n  it('should render with invalidElement', () => {\n    const wrapper = mount({\n      render() {\n        return (\n          <NSpace>\n            {{\n              default: () => (\n                <>\n                  text1\n                  <span>text1</span>\n                  text1\n                </>\n              )\n            }}\n          </NSpace>\n        )\n      }\n    })\n\n    const childNodes = getChildrenNode(wrapper)\n    expect(childNodes.length).toBe(3)\n    expect(wrapper.html()).toMatchSnapshot()\n    wrapper.unmount()\n  })\n\n  it('render justify space', () => {\n    const justifyList: Justify[] = [\n      'start',\n      'end',\n      'center',\n      'space-around',\n      'space-between',\n      'space-evenly'\n    ]\n\n    justifyList.forEach((pos) => {\n      const wrapper = mount({\n        render() {\n          return (\n            <NSpace justify={pos}>\n              {{\n                default: () => [<div>1</div>, <div>2</div>]\n              }}\n            </NSpace>\n          )\n        }\n      })\n\n      expect(wrapper.attributes('style')).toContain(\n        `justify-content: ${\n          ['start', 'end'].includes(pos) ? `flex-${pos};` : pos\n        }`\n      )\n      expect(wrapper.html()).toMatchSnapshot()\n      wrapper.unmount()\n    })\n\n    justifyList.forEach((pos) => {\n      const wrapper = mount({\n        render() {\n          return (\n            <NConfigProvider rtl={[{ name: 'Space', style: c(null) }]}>\n              {{\n                default: () => {\n                  return (\n                    <NSpace justify={pos}>\n                      {{\n                        default: () => [<div>1</div>, <div>2</div>]\n                      }}\n                    </NSpace>\n                  )\n                }\n              }}\n            </NConfigProvider>\n          )\n        }\n      })\n\n      expect(wrapper.find('.n-space').attributes('style')).toContain(\n        `justify-content: ${\n          ['start', 'end'].includes(pos) ? `flex-${pos};` : pos\n        }`\n      )\n      expect(wrapper.html()).toMatchSnapshot()\n      wrapper.unmount()\n    })\n  })\n\n  it('render custom style space', () => {\n    const wrapper = mount(\n      {\n        render() {\n          return <NSpace>{{ default: () => 'div' }}</NSpace>\n        }\n      },\n      {\n        props: {\n          itemStyle: { backgroundColor: 'red', color: 'yellow' }\n        }\n      }\n    )\n    const childNodes = getChildrenNode(wrapper)\n\n    expect(childNodes[0].attributes('style')).toContain(\n      'background-color: red; color: yellow;'\n    )\n    expect(wrapper.html()).toMatchSnapshot()\n    wrapper.unmount()\n  })\n\n  it('should not render while v-if is false', () => {\n    const wrapper = mount({\n      render() {\n        return <NSpace>{{ default: () => false && 'div' }}</NSpace>\n      }\n    })\n    const childNodes = getChildrenNode(wrapper)\n    expect(childNodes.length).toEqual(0)\n    expect(wrapper.html()).toMatchSnapshot()\n  })\n\n  it('should work with `wrap` prop', async () => {\n    const wrapper = mount(NSpace, {\n      slots: { default: () => [<div>1</div>, <div>2</div>] }\n    })\n    expect(wrapper.find('.n-space').attributes('style')).toContain(\n      'flex-wrap: wrap'\n    )\n\n    await wrapper.setProps({ wrap: false })\n    expect(wrapper.find('.n-space').attributes('style')).toContain(\n      'flex-wrap: nowrap'\n    )\n    wrapper.unmount()\n  })\n\n  it('should not render while slot is Comment', () => {\n    const wrapper = mount({\n      render() {\n        return (\n          <NSpace>\n            {{\n              default: () => createCommentVNode('random comment text')\n            }}\n          </NSpace>\n        )\n      }\n    })\n    const childNodes = getChildrenNode(wrapper)\n    expect(childNodes.length).toEqual(0)\n    expect(wrapper.html()).toMatchSnapshot()\n    wrapper.unmount()\n  })\n\n  it('shound not render a container to wrap child elements', () => {\n    const wrapper = mount(\n      {\n        render() {\n          return (\n            <NSpace>\n              {{\n                default: () => [<div>1</div>, <div>2</div>]\n              }}\n            </NSpace>\n          )\n        }\n      },\n      {\n        props: {\n          wrapItem: false,\n          internalUseGap: true\n        }\n      }\n    )\n\n    expect(wrapper.html()).toMatchSnapshot()\n    wrapper.unmount()\n  })\n})\n"
  },
  {
    "path": "src/space/tests/__snapshots__/Space.spec.tsx.snap",
    "content": "// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html\n\nexports[`n-space > render custom style space 1`] = `\n\"<div role=\"none\" class=\"n-space\" style=\"display: flex; flex-direction: row; justify-content: flex-start; flex-wrap: wrap; margin-top: -4px; margin-bottom: -4px;\">\n  <div role=\"none\" style=\"background-color: red; color: yellow; max-width: 100%; padding-top: 4px; padding-bottom: 4px;\">div</div>\n</div>\"\n`;\n\nexports[`n-space > render empty children 1`] = `\"\"`;\n\nexports[`n-space > render justify space 1`] = `\n\"<div role=\"none\" class=\"n-space\" style=\"display: flex; flex-direction: row; justify-content: flex-start; flex-wrap: wrap; margin-top: -4px; margin-bottom: -4px;\">\n  <div role=\"none\" style=\"max-width: 100%; margin-right: 12px; padding-top: 4px; padding-bottom: 4px;\">\n    <div>1</div>\n  </div>\n  <div role=\"none\" style=\"max-width: 100%; padding-top: 4px; padding-bottom: 4px;\">\n    <div>2</div>\n  </div>\n</div>\"\n`;\n\nexports[`n-space > render justify space 2`] = `\n\"<div role=\"none\" class=\"n-space\" style=\"display: flex; flex-direction: row; justify-content: flex-end; flex-wrap: wrap; margin-top: -4px; margin-bottom: -4px;\">\n  <div role=\"none\" style=\"max-width: 100%; margin-right: 12px; padding-top: 4px; padding-bottom: 4px;\">\n    <div>1</div>\n  </div>\n  <div role=\"none\" style=\"max-width: 100%; padding-top: 4px; padding-bottom: 4px;\">\n    <div>2</div>\n  </div>\n</div>\"\n`;\n\nexports[`n-space > render justify space 3`] = `\n\"<div role=\"none\" class=\"n-space\" style=\"display: flex; flex-direction: row; justify-content: center; flex-wrap: wrap; margin-top: -4px; margin-bottom: -4px;\">\n  <div role=\"none\" style=\"max-width: 100%; margin-right: 12px; padding-top: 4px; padding-bottom: 4px;\">\n    <div>1</div>\n  </div>\n  <div role=\"none\" style=\"max-width: 100%; padding-top: 4px; padding-bottom: 4px;\">\n    <div>2</div>\n  </div>\n</div>\"\n`;\n\nexports[`n-space > render justify space 4`] = `\n\"<div role=\"none\" class=\"n-space\" style=\"display: flex; flex-direction: row; justify-content: space-around; flex-wrap: wrap; margin-top: -4px; margin-bottom: -4px;\">\n  <div role=\"none\" style=\"max-width: 100%; margin-right: 6px; margin-left: 6px; padding-top: 4px; padding-bottom: 4px;\">\n    <div>1</div>\n  </div>\n  <div role=\"none\" style=\"max-width: 100%; margin-right: 6px; margin-left: 6px; padding-top: 4px; padding-bottom: 4px;\">\n    <div>2</div>\n  </div>\n</div>\"\n`;\n\nexports[`n-space > render justify space 5`] = `\n\"<div role=\"none\" class=\"n-space\" style=\"display: flex; flex-direction: row; justify-content: space-between; flex-wrap: wrap; margin-top: -4px; margin-bottom: -4px;\">\n  <div role=\"none\" style=\"max-width: 100%; margin-right: 6px; padding-top: 4px; padding-bottom: 4px;\">\n    <div>1</div>\n  </div>\n  <div role=\"none\" style=\"max-width: 100%; margin-left: 6px; padding-top: 4px; padding-bottom: 4px;\">\n    <div>2</div>\n  </div>\n</div>\"\n`;\n\nexports[`n-space > render justify space 6`] = `\n\"<div role=\"none\" class=\"n-space\" style=\"display: flex; flex-direction: row; justify-content: space-evenly; flex-wrap: wrap; margin-top: -4px; margin-bottom: -4px;\">\n  <div role=\"none\" style=\"max-width: 100%; margin-right: 6px; margin-left: 6px; padding-top: 4px; padding-bottom: 4px;\">\n    <div>1</div>\n  </div>\n  <div role=\"none\" style=\"max-width: 100%; margin-right: 6px; margin-left: 6px; padding-top: 4px; padding-bottom: 4px;\">\n    <div>2</div>\n  </div>\n</div>\"\n`;\n\nexports[`n-space > render justify space 7`] = `\n\"<div class=\"n-config-provider\">\n  <div role=\"none\" class=\"n-space n-space--rtl\" style=\"display: flex; flex-direction: row; justify-content: flex-start; flex-wrap: wrap; margin-top: -4px; margin-bottom: -4px;\">\n    <div role=\"none\" style=\"max-width: 100%; margin-left: 12px; padding-top: 4px; padding-bottom: 4px;\">\n      <div>1</div>\n    </div>\n    <div role=\"none\" style=\"max-width: 100%; padding-top: 4px; padding-bottom: 4px;\">\n      <div>2</div>\n    </div>\n  </div>\n</div>\"\n`;\n\nexports[`n-space > render justify space 8`] = `\n\"<div class=\"n-config-provider\">\n  <div role=\"none\" class=\"n-space n-space--rtl\" style=\"display: flex; flex-direction: row; justify-content: flex-end; flex-wrap: wrap; margin-top: -4px; margin-bottom: -4px;\">\n    <div role=\"none\" style=\"max-width: 100%; margin-left: 12px; padding-top: 4px; padding-bottom: 4px;\">\n      <div>1</div>\n    </div>\n    <div role=\"none\" style=\"max-width: 100%; padding-top: 4px; padding-bottom: 4px;\">\n      <div>2</div>\n    </div>\n  </div>\n</div>\"\n`;\n\nexports[`n-space > render justify space 9`] = `\n\"<div class=\"n-config-provider\">\n  <div role=\"none\" class=\"n-space n-space--rtl\" style=\"display: flex; flex-direction: row; justify-content: center; flex-wrap: wrap; margin-top: -4px; margin-bottom: -4px;\">\n    <div role=\"none\" style=\"max-width: 100%; margin-left: 12px; padding-top: 4px; padding-bottom: 4px;\">\n      <div>1</div>\n    </div>\n    <div role=\"none\" style=\"max-width: 100%; padding-top: 4px; padding-bottom: 4px;\">\n      <div>2</div>\n    </div>\n  </div>\n</div>\"\n`;\n\nexports[`n-space > render justify space 10`] = `\n\"<div class=\"n-config-provider\">\n  <div role=\"none\" class=\"n-space n-space--rtl\" style=\"display: flex; flex-direction: row; justify-content: space-around; flex-wrap: wrap; margin-top: -4px; margin-bottom: -4px;\">\n    <div role=\"none\" style=\"max-width: 100%; margin-left: 6px; margin-right: 6px; padding-top: 4px; padding-bottom: 4px;\">\n      <div>1</div>\n    </div>\n    <div role=\"none\" style=\"max-width: 100%; margin-left: 6px; margin-right: 6px; padding-top: 4px; padding-bottom: 4px;\">\n      <div>2</div>\n    </div>\n  </div>\n</div>\"\n`;\n\nexports[`n-space > render justify space 11`] = `\n\"<div class=\"n-config-provider\">\n  <div role=\"none\" class=\"n-space n-space--rtl\" style=\"display: flex; flex-direction: row; justify-content: space-between; flex-wrap: wrap; margin-top: -4px; margin-bottom: -4px;\">\n    <div role=\"none\" style=\"max-width: 100%; margin-left: 6px; padding-top: 4px; padding-bottom: 4px;\">\n      <div>1</div>\n    </div>\n    <div role=\"none\" style=\"max-width: 100%; margin-right: 6px; padding-top: 4px; padding-bottom: 4px;\">\n      <div>2</div>\n    </div>\n  </div>\n</div>\"\n`;\n\nexports[`n-space > render justify space 12`] = `\n\"<div class=\"n-config-provider\">\n  <div role=\"none\" class=\"n-space n-space--rtl\" style=\"display: flex; flex-direction: row; justify-content: space-evenly; flex-wrap: wrap; margin-top: -4px; margin-bottom: -4px;\">\n    <div role=\"none\" style=\"max-width: 100%; margin-left: 6px; margin-right: 6px; padding-top: 4px; padding-bottom: 4px;\">\n      <div>1</div>\n    </div>\n    <div role=\"none\" style=\"max-width: 100%; margin-left: 6px; margin-right: 6px; padding-top: 4px; padding-bottom: 4px;\">\n      <div>2</div>\n    </div>\n  </div>\n</div>\"\n`;\n\nexports[`n-space > render space number size 1`] = `\n\"<div role=\"none\" class=\"n-space\" style=\"display: flex; flex-direction: row; justify-content: flex-start; flex-wrap: wrap; margin-top: -10px; margin-bottom: -10px;\">\n  <div role=\"none\" style=\"max-width: 100%; padding-top: 10px; padding-bottom: 10px;\">kirby</div>\n</div>\"\n`;\n\nexports[`n-space > render space string size 1`] = `\n\"<div role=\"none\" class=\"n-space\" style=\"display: flex; flex-direction: row; justify-content: flex-start; flex-wrap: wrap; margin-top: -6px; margin-bottom: -6px;\">\n  <div role=\"none\" style=\"max-width: 100%; padding-top: 6px; padding-bottom: 6px;\">kirby</div>\n</div>\"\n`;\n\nexports[`n-space > render vertical space 1`] = `\n\"<div role=\"none\" class=\"n-space\" style=\"display: flex; flex-direction: column; justify-content: flex-start; flex-wrap: nowrap;\">\n  <div role=\"none\" style=\"max-width: 100%; margin-bottom: 8px;\">\n    <div>1</div>\n  </div>\n  <div role=\"none\" style=\"max-width: 100%;\">\n    <div>2</div>\n  </div>\n</div>\"\n`;\n\nexports[`n-space > should not render while slot is Comment 1`] = `\n\"<div role=\"none\" class=\"n-space\" style=\"display: flex; flex-direction: row; justify-content: flex-start; flex-wrap: wrap; margin-top: -4px; margin-bottom: -4px;\">\n  <!--random comment text-->\n</div>\"\n`;\n\nexports[`n-space > should not render while v-if is false 1`] = `\n\"<div role=\"none\" class=\"n-space\" style=\"display: flex; flex-direction: row; justify-content: flex-start; flex-wrap: wrap; margin-top: -4px; margin-bottom: -4px;\">\n  <!---->\n</div>\"\n`;\n\nexports[`n-space > should render with invalidElement 1`] = `\n\"<div role=\"none\" class=\"n-space\" style=\"display: flex; flex-direction: row; justify-content: flex-start; flex-wrap: wrap; margin-top: -4px; margin-bottom: -4px;\">\n  <div role=\"none\" style=\"max-width: 100%; margin-right: 12px; padding-top: 4px; padding-bottom: 4px;\">text1</div>\n  <div role=\"none\" style=\"max-width: 100%; margin-right: 12px; padding-top: 4px; padding-bottom: 4px;\"><span>text1</span></div>\n  <div role=\"none\" style=\"max-width: 100%; padding-top: 4px; padding-bottom: 4px;\">text1</div>\n</div>\"\n`;\n\nexports[`n-space > shound not render a container to wrap child elements 1`] = `\n\"<div role=\"none\" class=\"n-space\" style=\"display: flex; flex-direction: row; justify-content: flex-start; flex-wrap: wrap; margin-top: -4px; margin-bottom: -4px;\">\n  <div>1</div>\n  <div>2</div>\n</div>\"\n`;\n"
  },
  {
    "path": "src/space/tests/server.spec.tsx",
    "content": "import { setup } from '@css-render/vue3-ssr'\nimport { renderToString } from '@vue/server-renderer'\n/**\n * @vitest-environment node\n */\nimport { createSSRApp, h } from 'vue'\nimport { NSpace } from '../..'\n\ndescribe('server side rendering', () => {\n  it('works', async () => {\n    const app = createSSRApp(() => <NSpace />)\n    setup(app)\n    try {\n      await renderToString(app)\n    }\n    catch (e) {\n      expect(e).not.toBeTruthy()\n    }\n  })\n})\n"
  },
  {
    "path": "src/spin/demos/enUS/basic.demo.vue",
    "content": "<markdown>\n# Basic\n\nHere are `small`, `medium` and `large` spins.\n</markdown>\n\n<template>\n  <n-space>\n    <n-spin size=\"small\" />\n    <n-spin size=\"medium\" />\n    <n-spin size=\"large\" />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/spin/demos/enUS/customize-icon.demo.vue",
    "content": "<markdown>\n# Customize icon\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { Reload } from '@vicons/ionicons5'\nimport { ref } from 'vue'\n\nconst show = ref(false)\n</script>\n\n<template>\n  <n-spin :show=\"show\">\n    <template #icon>\n      <n-icon>\n        <Reload />\n      </n-icon>\n    </template>\n  </n-spin>\n</template>\n"
  },
  {
    "path": "src/spin/demos/enUS/delay.demo.vue",
    "content": "<markdown>\n# Delay\n\nYou can specify a delay for displaying spin. If spinning ends during delay, spin won't appear.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst show = ref(false)\n</script>\n\n<template>\n  <n-space vertical>\n    <n-spin :show=\"show\" :delay=\"1000\">\n      <n-alert title=\"La La La\" type=\"success\">\n        Leave it till tomorrow to unpack my case. Honey disconnect the phone.\n      </n-alert>\n    </n-spin>\n    <n-button @click=\"show = !show\">\n      {{ show ? 'Click to stop Spin' : 'Click to Spin' }}\n    </n-button>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/spin/demos/enUS/description.demo.vue",
    "content": "<markdown>\n# Description\n\nYou can add some description under the spin.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst show = ref(false)\n</script>\n\n<template>\n  <n-space vertical>\n    <n-spin :show=\"show\">\n      <n-alert title=\"La La La\" type=\"success\">\n        Leave it till tomorrow to unpack my case. Honey disconnect the phone.\n      </n-alert>\n      <template #description>\n        You know how lucky you are.\n      </template>\n    </n-spin>\n    <n-button @click=\"show = !show\">\n      Click to Spin\n    </n-button>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/spin/demos/enUS/index.demo-entry.md",
    "content": "# Spin\n\nIt could've been called `loading`, but why is it called `spin`? Because there is another internal component with less props already named `loading`.\n\n## Demos\n\n```demo\nbasic.vue\nwrap.vue\ndescription.vue\ncustomize-icon.vue\ndelay.vue\n```\n\n## API\n\n### Spin Props\n\n| Name | Type | Default | Description | Version |\n| --- | --- | --- | --- | --- |\n| content-class | `string` | `undefined` | Content Class of the spin. | 2.36.0 |\n| content-style | `string \\| Object` | `undefined` | Content style of the spin. | 2.36.0 |\n| description | `string` | `undefined` | Description of the spin. |\n| rotate | `boolean` | `true` | Specify whether icon rotates, only working for custom icon. |\n| size | `'small' \\| 'medium' \\| 'large' \\| number` | `'medium'` | Size of the spin. |\n| show | `boolean` | `true` | Specify whether spin is active when spin has content inside. It won't work if you just use spin itself. |\n| stroke-width | `number` | `undefined` | Relative width of spin's stroke, assuming the outer radius of spin is 100. |\n| radius | `number` | `100` | Outer radius of the spin icon. | 2.44.0 |\n| scale | `number` | `1` | Scale factor of the spin icon. | 2.44.0 |\n| stroke | `string` | `undefined` | Color of the spin. |\n| delay | `number` | `undefined` | Specifies a delay in milliseconds for loading state (prevent flush). |\n\n### Spin Slots\n\n| Name        | Parameters | Description                         |\n| ----------- | ---------- | ----------------------------------- |\n| default     | `()`       | If set, spin will wrap the content. |\n| description | `()`       | Description of the spin.            |\n| icon        | `()`       | Customize the spin icon.            |\n"
  },
  {
    "path": "src/spin/demos/enUS/wrap.demo.vue",
    "content": "<markdown>\n# Wrap\n\nYou can wrap a component inside spin.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst show = ref(false)\n</script>\n\n<template>\n  <n-space vertical>\n    <n-spin :show=\"show\">\n      <n-alert title=\"La La La\" type=\"success\">\n        Leave it till tomorrow to unpack my case. Honey disconnect the phone.\n      </n-alert>\n    </n-spin>\n    <n-button @click=\"show = !show\">\n      Click to Spin\n    </n-button>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/spin/demos/zhCN/basic.demo.vue",
    "content": "<markdown>\n# 基础用法\n\n有 `small`、`medium` 和 `large` 的 Spin.\n</markdown>\n\n<template>\n  <n-space>\n    <n-spin size=\"small\" />\n    <n-spin size=\"medium\" />\n    <n-spin size=\"large\" />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/spin/demos/zhCN/blocking-debug.demo.vue",
    "content": "<markdown>\n# 阻塞性方法 Debug\n\n在调用`alert()`之类的阻塞性方法的时候，仍然可看到旋转动画，但不会有圆圈的收缩和伸展动画。\n</markdown>\n\n<script lang=\"ts\" setup>\nfunction handleClick() {\n  // eslint-disable-next-line no-alert\n  window.alert('已举办!')\n}\n</script>\n\n<template>\n  <n-space>\n    <n-button @click=\"handleClick\">\n      点此报警\n    </n-button>\n    <n-spin size=\"small\" />\n    <n-spin size=\"medium\" />\n    <n-spin size=\"large\" />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/spin/demos/zhCN/customize-icon.demo.vue",
    "content": "<markdown>\n# 自定义图标\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { Reload } from '@vicons/ionicons5'\nimport { ref } from 'vue'\n\nconst show = ref(false)\n</script>\n\n<template>\n  <n-spin :show=\"show\">\n    <template #icon>\n      <n-icon>\n        <Reload />\n      </n-icon>\n    </template>\n  </n-spin>\n</template>\n"
  },
  {
    "path": "src/spin/demos/zhCN/delay.demo.vue",
    "content": "<markdown>\n# 延迟\n\n你可以设置一个显示延迟时间。在延迟时间到达前结束，Spin 将不会显示\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst show = ref(false)\n</script>\n\n<template>\n  <n-space vertical>\n    <n-spin :show=\"show\" :delay=\"1000\">\n      <n-alert title=\"La La La\" type=\"success\">\n        明天再打开行李箱。宝贝，挂电话啦。\n      </n-alert>\n    </n-spin>\n    <n-button @click=\"show = !show\">\n      {{ show ? '不要再转啦' : '点击来转圈' }}\n    </n-button>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/spin/demos/zhCN/description.demo.vue",
    "content": "<markdown>\n# 文字信息\n\n你可以在圈圈的下面放一点文字信息。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst show = ref(false)\n</script>\n\n<template>\n  <n-space vertical>\n    <n-spin :show=\"show\">\n      <n-alert title=\"啦啦啦\" type=\"success\">\n        明天再打开行李箱。宝贝，挂电话啦。\n      </n-alert>\n      <template #description>\n        你不知道你有多幸运\n      </template>\n    </n-spin>\n    <n-button @click=\"show = !show\">\n      点击来转圈\n    </n-button>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/spin/demos/zhCN/index.demo-entry.md",
    "content": "# 加载 Spin\n\n按理说它叫做 Loading 也可以，但是为啥叫 Spin 呢？因为还有一个属性更少的内部组件叫 Loading。\n\n## 演示\n\n```demo\nbasic.vue\nwrap.vue\ndescription.vue\ncustomize-icon.vue\ndelay.vue\nblocking-debug.vue\n```\n\n## API\n\n### Spin Props\n\n| 名称 | 类型 | 默认值 | 说明 | 版本 |\n| --- | --- | --- | --- | --- |\n| content-class | `string` | `undefined` | Spin 内容的类名 | 2.36.0 |\n| content-style | `string \\| Object` | `undefined` | Spin 内容的样式 | 2.36.0 |\n| description | `string` | `undefined` | Spin 的文字信息 |\n| rotate | `boolean` | `true` | 自定义的加载图标是否有旋转动画 |\n| size | `'small' \\| 'medium' \\| 'large' \\| number` | `'medium'` | Spin 的尺寸 |\n| show | `boolean` | `true` | 在填入内容的情况下 Spin 是否激活，直接使用 Spin 时不生效 |\n| stroke-width | `number` | `undefined` | Spin 边缘的相对宽度，假定 Spin 的外侧半径是 100 |\n| radius | `number` | `100` | Spin 图标的外侧半径 | 2.44.0 |\n| scale | `number` | `1` | Spin 图标的缩放比例 | 2.44.0 |\n| stroke | `string` | `undefined` | Spin 的颜色 |\n| delay | `number` | `undefined` | 延迟显示加载效果的时间, 单位为毫秒（避免闪烁） |\n\n### Spin Slots\n\n| 名称        | 参数 | 说明                            |\n| ----------- | ---- | ------------------------------- |\n| default     | `()` | 如果填入，Spin 会包裹填入的内容 |\n| description | `()` | Spin 的文字信息                 |\n| icon        | `()` | 自定义的加载图标                |\n"
  },
  {
    "path": "src/spin/demos/zhCN/wrap.demo.vue",
    "content": "<markdown>\n# 填充内容\n\n你可以把其他内容包裹在 Spin 中。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst show = ref(false)\n</script>\n\n<template>\n  <n-space vertical>\n    <n-spin :show=\"show\">\n      <n-alert title=\"啦啦啦\" type=\"success\">\n        明天再打开行李箱。宝贝，挂电话啦。\n      </n-alert>\n    </n-spin>\n    <n-button @click=\"show = !show\">\n      点击来转圈\n    </n-button>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/spin/index.ts",
    "content": "export { default as NSpin, spinProps } from './src/Spin'\nexport type { SpinProps, SpinSlots } from './src/Spin'\n"
  },
  {
    "path": "src/spin/src/Spin.tsx",
    "content": "import type { CSSProperties, PropType, SlotsType, VNode } from 'vue'\nimport type { ThemeProps } from '../../_mixins'\nimport type { ExtractPublicPropTypes } from '../../_utils'\nimport type { SpinTheme } from '../styles'\nimport { pxfy } from 'seemly'\nimport { useCompitable } from 'vooks'\nimport { computed, defineComponent, h, ref, Transition, watchEffect } from 'vue'\nimport { NBaseLoading } from '../../_internal'\nimport { exposedLoadingProps } from '../../_internal/loading/src/Loading'\nimport { useConfig, useTheme, useThemeClass } from '../../_mixins'\nimport { createKey, warnOnce } from '../../_utils'\nimport { spinLight } from '../styles'\nimport style from './styles/index.cssr'\n\nconst STROKE_WIDTH = {\n  small: 20,\n  medium: 18,\n  large: 16\n}\n\nexport const spinProps = {\n  ...(useTheme.props as ThemeProps<SpinTheme>),\n  contentClass: String,\n  contentStyle: [Object, String] as PropType<CSSProperties | string>,\n  description: String,\n  size: {\n    type: [String, Number] as PropType<'small' | 'medium' | 'large' | number>,\n    default: 'medium'\n  },\n  show: {\n    type: Boolean,\n    default: true\n  },\n  rotate: {\n    type: Boolean,\n    default: true\n  },\n  spinning: {\n    type: Boolean,\n    validator: () => {\n      return true\n    },\n    default: undefined\n  },\n  delay: Number,\n  ...exposedLoadingProps\n}\n\nexport type SpinProps = ExtractPublicPropTypes<typeof spinProps>\n\nexport interface SpinSlots {\n  default?: () => VNode[]\n  description?: () => VNode[]\n  icon?: () => VNode[]\n}\n\nexport default defineComponent({\n  name: 'Spin',\n  props: spinProps,\n  slots: Object as SlotsType<SpinSlots>,\n  setup(props) {\n    if (__DEV__) {\n      watchEffect(() => {\n        if (props.spinning !== undefined) {\n          warnOnce(\n            'spin',\n            '`spinning` is deprecated, please use `show` instead.'\n          )\n        }\n      })\n    }\n    const { mergedClsPrefixRef, inlineThemeDisabled } = useConfig(props)\n    const themeRef = useTheme(\n      'Spin',\n      '-spin',\n      style,\n      spinLight,\n      props,\n      mergedClsPrefixRef\n    )\n    const cssVarsRef = computed(() => {\n      const { size: spinSize } = props\n      const {\n        common: { cubicBezierEaseInOut },\n        self\n      } = themeRef.value\n      const { opacitySpinning, color, textColor } = self\n      const size\n        = typeof spinSize === 'number'\n          ? pxfy(spinSize)\n          : self[createKey('size', spinSize)]\n      return {\n        '--n-bezier': cubicBezierEaseInOut,\n        '--n-opacity-spinning': opacitySpinning,\n        '--n-size': size,\n        '--n-color': color,\n        '--n-text-color': textColor\n      }\n    })\n    const themeClassHandle = inlineThemeDisabled\n      ? useThemeClass(\n          'spin',\n          computed(() => {\n            const { size } = props\n            return typeof size === 'number' ? String(size) : size[0]\n          }),\n          cssVarsRef,\n          props\n        )\n      : undefined\n\n    const compitableShow = useCompitable(props, ['spinning', 'show'])\n    const activeRef = ref(false)\n\n    watchEffect((onCleanup) => {\n      let timerId: number\n      if (compitableShow.value) {\n        const { delay } = props\n        if (delay) {\n          timerId = window.setTimeout(() => {\n            activeRef.value = true\n          }, delay)\n          onCleanup(() => {\n            clearTimeout(timerId)\n          })\n          return\n        }\n      }\n      activeRef.value = compitableShow.value\n    })\n\n    return {\n      mergedClsPrefix: mergedClsPrefixRef,\n      active: activeRef,\n      mergedStrokeWidth: computed(() => {\n        const { strokeWidth } = props\n        if (strokeWidth !== undefined)\n          return strokeWidth\n        const { size } = props\n        return STROKE_WIDTH[typeof size === 'number' ? 'medium' : size]\n      }),\n      cssVars: inlineThemeDisabled ? undefined : cssVarsRef,\n      themeClass: themeClassHandle?.themeClass,\n      onRender: themeClassHandle?.onRender\n    }\n  },\n  render() {\n    const { $slots, mergedClsPrefix, description } = this\n    const rotate = $slots.icon && this.rotate\n    const descriptionNode = (description || $slots.description) && (\n      <div class={`${mergedClsPrefix}-spin-description`}>\n        {description || $slots.description?.()}\n      </div>\n    )\n    const icon = $slots.icon ? (\n      <div class={[`${mergedClsPrefix}-spin-body`, this.themeClass]}>\n        <div\n          class={[\n            `${mergedClsPrefix}-spin`,\n            rotate && `${mergedClsPrefix}-spin--rotate`\n          ]}\n          style={$slots.default ? '' : (this.cssVars as CSSProperties)}\n        >\n          {$slots.icon()}\n        </div>\n        {descriptionNode}\n      </div>\n    ) : (\n      <div class={[`${mergedClsPrefix}-spin-body`, this.themeClass]}>\n        <NBaseLoading\n          clsPrefix={mergedClsPrefix}\n          style={$slots.default ? '' : (this.cssVars as CSSProperties)}\n          stroke={this.stroke}\n          stroke-width={this.mergedStrokeWidth}\n          radius={this.radius}\n          scale={this.scale}\n          class={`${mergedClsPrefix}-spin`}\n        />\n        {descriptionNode}\n      </div>\n    )\n    this.onRender?.()\n    return $slots.default ? (\n      <div\n        class={[`${mergedClsPrefix}-spin-container`, this.themeClass]}\n        style={this.cssVars as CSSProperties}\n      >\n        <div\n          class={[\n            `${mergedClsPrefix}-spin-content`,\n            this.active && `${mergedClsPrefix}-spin-content--spinning`,\n            this.contentClass\n          ]}\n          style={this.contentStyle}\n        >\n          {$slots}\n        </div>\n        <Transition name=\"fade-in-transition\">\n          {{\n            default: () => (this.active ? icon : null)\n          }}\n        </Transition>\n      </div>\n    ) : (\n      icon\n    )\n  }\n})\n"
  },
  {
    "path": "src/spin/src/styles/index.cssr.ts",
    "content": "import { fadeInTransition } from '../../../_styles/transitions/fade-in.cssr'\nimport { c, cB, cM } from '../../../_utils/cssr'\n\n// vars:\n// --n-bezier\n// --n-opacity-spinning\n// --n-size\n// --n-color\n// --n-text-color\n// --n-font-size\nexport default c([\n  c('@keyframes spin-rotate', `\n    from {\n      transform: rotate(0);\n    }\n    to {\n      transform: rotate(360deg);\n    }\n  `),\n  cB('spin-container', `\n    position: relative;\n  `, [\n    cB('spin-body', `\n      position: absolute;\n      top: 50%;\n      left: 50%;\n      transform: translateX(-50%) translateY(-50%);\n    `, [\n      fadeInTransition()\n    ])\n  ]),\n  cB('spin-body', `\n    display: inline-flex;\n    align-items: center;\n    justify-content: center;\n    flex-direction: column;\n  `),\n  cB('spin', `\n    display: inline-flex;\n    height: var(--n-size);\n    width: var(--n-size);\n    font-size: var(--n-size);\n    color: var(--n-color);\n  `, [\n    cM('rotate', `\n      animation: spin-rotate 2s linear infinite;\n    `)\n  ]),\n  cB('spin-description', `\n    display: inline-block;\n    font-size: var(--n-font-size);\n    color: var(--n-text-color);\n    transition: color .3s var(--n-bezier);\n    margin-top: 8px;\n  `),\n  cB('spin-content', `\n    opacity: 1;\n    transition: opacity .3s var(--n-bezier);\n    pointer-events: all;\n  `, [\n    cM('spinning', `\n      user-select: none;\n      -webkit-user-select: none;\n      pointer-events: none;\n      opacity: var(--n-opacity-spinning);\n    `)\n  ])\n])\n"
  },
  {
    "path": "src/spin/styles/dark.ts",
    "content": "import type { SpinTheme } from './light'\nimport { commonDark } from '../../_styles/common'\nimport { self } from './light'\n\nconst spinDark: SpinTheme = {\n  name: 'Spin',\n  common: commonDark,\n  self\n}\n\nexport default spinDark\n"
  },
  {
    "path": "src/spin/styles/index.ts",
    "content": "export { default as spinDark } from './dark'\nexport { default as spinLight } from './light'\nexport type { SpinTheme, SpinThemeVars } from './light'\n"
  },
  {
    "path": "src/spin/styles/light.ts",
    "content": "import type { Theme } from '../../_mixins'\nimport type { ThemeCommonVars } from '../../_styles/common'\nimport { commonLight } from '../../_styles/common'\n\nexport function self(vars: ThemeCommonVars) {\n  const {\n    opacityDisabled,\n    heightTiny,\n    heightSmall,\n    heightMedium,\n    heightLarge,\n    heightHuge,\n    primaryColor,\n    fontSize\n  } = vars\n  return {\n    fontSize,\n    textColor: primaryColor,\n    sizeTiny: heightTiny,\n    sizeSmall: heightSmall,\n    sizeMedium: heightMedium,\n    sizeLarge: heightLarge,\n    sizeHuge: heightHuge,\n    color: primaryColor,\n    opacitySpinning: opacityDisabled\n  }\n}\n\nexport type SpinThemeVars = ReturnType<typeof self>\n\nconst spinLight: Theme<'Spin', SpinThemeVars> = {\n  name: 'Spin',\n  common: commonLight,\n  self\n}\n\nexport default spinLight\nexport type SpinTheme = typeof spinLight\n"
  },
  {
    "path": "src/spin/tests/Spin.spec.ts",
    "content": "import { Reload } from '@vicons/ionicons5'\nimport { mount } from '@vue/test-utils'\nimport { sleep } from 'seemly'\nimport { h } from 'vue'\nimport { NIcon } from '../../icon'\nimport { NSpin } from '../index'\n\ndescribe('n-spin', () => {\n  it('should work with import on demand', () => {\n    mount(NSpin)\n  })\n\n  it('should work with `show` prop', async () => {\n    const wrapper = mount(NSpin, {\n      props: {\n        show: true\n      },\n      slots: {\n        default: () => 'test'\n      }\n    })\n    expect(wrapper.find('.n-spin-content').classes()).toContain(\n      'n-spin-content--spinning'\n    )\n    wrapper.unmount()\n  })\n\n  it('should work with icon slot', () => {\n    const wrapper = mount(NSpin, {\n      slots: {\n        icon: () =>\n          h(NIcon, null, {\n            default: () => h(Reload)\n          })\n      }\n    })\n\n    expect(wrapper.findComponent(NIcon).exists()).toBe(true)\n    expect(wrapper.findComponent(Reload).exists()).toBe(true)\n    wrapper.unmount()\n  })\n\n  it('rotate should work on icon slot', async () => {\n    const wrapper = mount(NSpin, {\n      slots: {\n        icon: () =>\n          h(NIcon, null, {\n            default: () => h(Reload)\n          })\n      }\n    })\n    expect(wrapper.find('.n-spin--rotate').exists()).toBe(true)\n    await wrapper.setProps({\n      rotate: false\n    })\n    expect(wrapper.find('.n-spin').classes()).not.toContain('n-spin--rotate')\n    wrapper.unmount()\n  })\n\n  it('should work with `size` prop', async () => {\n    ;(['small', 'medium', 'large', 71] as const).forEach((item) => {\n      const wrapper = mount(NSpin, {\n        props: {\n          size: item\n        }\n      })\n      expect(wrapper.find('.n-spin').attributes('style')).toMatchSnapshot()\n      wrapper.unmount()\n    })\n  })\n\n  it('should work with `default` slot', async () => {\n    const wrapper = mount(NSpin, {\n      slots: {\n        default: () => 'test'\n      }\n    })\n    expect(wrapper.find('.n-spin-container').exists()).toBe(true)\n    expect(wrapper.find('.n-spin-content').text()).toBe('test')\n    wrapper.unmount()\n  })\n\n  it('should work with `strokeWidth` prop', () => {\n    const wrapper = mount(NSpin, {\n      props: {\n        strokeWidth: 40,\n        size: 'medium'\n      }\n    })\n\n    expect(wrapper.find('circle').attributes('stroke-width')).toEqual('40')\n    wrapper.unmount()\n  })\n\n  it('should work with `delay` prop', async () => {\n    const wrapper = mount(NSpin, {\n      props: {\n        show: true,\n        delay: 1000\n      },\n      slots: {\n        default: () => 'test'\n      }\n    })\n    expect(wrapper.find('.n-spin-content').classes()).not.toContain(\n      'n-spin-content--spinning'\n    )\n    await sleep(1000)\n\n    expect(wrapper.find('.n-spin-content').classes()).toContain(\n      'n-spin-content--spinning'\n    )\n  })\n\n  it('should `delay` prop not delay close spin', async () => {\n    const wrapper = mount(NSpin, {\n      props: {\n        show: true,\n        delay: 1000\n      },\n      slots: {\n        default: () => 'test'\n      }\n    })\n    expect(wrapper.find('.n-spin-content').classes()).not.toContain(\n      'n-spin-content--spinning'\n    )\n    await sleep(1000)\n\n    expect(wrapper.find('.n-spin-content').classes()).toContain(\n      'n-spin-content--spinning'\n    )\n\n    await wrapper.setProps({\n      show: false\n    })\n    expect(wrapper.find('.n-spin-content').classes()).not.toContain(\n      'n-spin-content--spinning'\n    )\n  })\n})\n"
  },
  {
    "path": "src/spin/tests/__snapshots__/Spin.spec.ts.snap",
    "content": "// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html\n\nexports[`n-spin > should work with \\`size\\` prop 1`] = `\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-opacity-spinning: 0.5; --n-size: 28px; --n-color: #18a058; --n-text-color: #18a058;\"`;\n\nexports[`n-spin > should work with \\`size\\` prop 2`] = `\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-opacity-spinning: 0.5; --n-size: 34px; --n-color: #18a058; --n-text-color: #18a058;\"`;\n\nexports[`n-spin > should work with \\`size\\` prop 3`] = `\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-opacity-spinning: 0.5; --n-size: 40px; --n-color: #18a058; --n-text-color: #18a058;\"`;\n\nexports[`n-spin > should work with \\`size\\` prop 4`] = `\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-opacity-spinning: 0.5; --n-size: 71px; --n-color: #18a058; --n-text-color: #18a058;\"`;\n"
  },
  {
    "path": "src/spin/tests/server.spec.tsx",
    "content": "import { setup } from '@css-render/vue3-ssr'\nimport { renderToString } from '@vue/server-renderer'\n/**\n * @vitest-environment node\n */\nimport { createSSRApp, h } from 'vue'\nimport { NSpin } from '../..'\n\ndescribe('server side rendering', () => {\n  it('works', async () => {\n    const app = createSSRApp(() => <NSpin />)\n    setup(app)\n    try {\n      await renderToString(app)\n    }\n    catch (e) {\n      expect(e).not.toBeTruthy()\n    }\n  })\n})\n"
  },
  {
    "path": "src/split/demos/enUS/basic.demo.vue",
    "content": "<markdown>\n# Basic\n</markdown>\n\n<template>\n  <n-split direction=\"horizontal\" style=\"height: 200px\" :max=\"0.75\" :min=\"0.25\">\n    <template #1>\n      <div :style=\"{ height: '200px' }\">\n        Pane 1\n      </div>\n    </template>\n    <template #2>\n      <div :style=\"{ height: '200px' }\">\n        Pane 2\n      </div>\n    </template>\n  </n-split>\n</template>\n"
  },
  {
    "path": "src/split/demos/enUS/controlled.demo.vue",
    "content": "<markdown>\n# Controlled manner\n</markdown>\n\n<script setup lang=\"ts\">\nimport { NInputNumber, NSplit } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst split = ref<number>(0.8)\n</script>\n\n<template>\n  <n-flex vertical>\n    <NInputNumber\n      v-model:value=\"split\"\n      :step=\"0.1\"\n      clearable\n      :max=\"1\"\n      :min=\"0\"\n    />\n    <NSplit v-model:size=\"split\" style=\"height: 200px\">\n      <template #1>\n        <div style=\"width: 100%; background-color: black\" />\n      </template>\n      <template #2>\n        <div style=\"width: 100%; background-color: red\" />\n      </template>\n    </NSplit>\n  </n-flex>\n</template>\n"
  },
  {
    "path": "src/split/demos/enUS/event.demo.vue",
    "content": "<markdown>\n  # Event\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { useMessage } from 'naive-ui'\n\nconst message = useMessage()\nfunction handleOnDragStart() {\n  message.info('Move Start')\n}\nfunction handleOnDragMove() {\n  message.info('Moving')\n}\nfunction handleOnDragEnd() {\n  message.info('Move end')\n}\n</script>\n\n<template>\n  <n-split\n    direction=\"horizontal\"\n    style=\"height: 200px\"\n    @drag-start=\"handleOnDragStart\"\n    @drag-move=\"handleOnDragMove\"\n    @drag-end=\"handleOnDragEnd\"\n  >\n    <template #1>\n      Pane 1\n    </template>\n    <template #2>\n      Pane 2\n    </template>\n  </n-split>\n</template>\n"
  },
  {
    "path": "src/split/demos/enUS/index.demo-entry.md",
    "content": "# Split\n\nThe flexible layout tool provides the possibility of customizing the interface layout.\n\nAvailable since `2.36.0`.\n\n## Demos\n\n```demo\nbasic.vue\nvertical.vue\nnest.vue\nevent.vue\nslot.vue\ncontrolled.vue\n```\n\n## API\n\n### Split Props\n\n| Name | Type | Default | Description | Version |\n| --- | --- | --- | --- | --- |\n| default-size | `number` | `0.5` | Default split size, when it's `number` it should in 0 ~ 1, when it's `string` it should be formatted in `${number}px`. | 2.36.0, `string` 2.38.2 |\n| direction | `'horizontal' \\| 'vertical'` | `'horizontal'` | The direction of the split. | 2.36.0 |\n| disabled | `boolean` | `false` | Whether to disable the split. | 2.36.0 |\n| max | `string \\| number` | `1` | The maximum split threshold, when it's `number` it should in 0 ~ 1, when it's `string` it should be formatted in `${number}px`. | 2.36.0, `string` 2.38.2 |\n| min | `string \\| number` | `0` | The minimum threshold for splitting, when it's `number` it should in 0 ~ 1, when it's `string` it should be formatted in `${number}px`. | 2.36.0, `string` 2.38.2 |\n| pane1-class | `string` | `undefined` | The class name of the first pane. | 2.38.2 |\n| pane1-style | `Object \\| string` | `undefined` | The Style of the first pane | 2.38.2 |\n| pane2-class | `string` | `undefined` | The class name of the second pane. | 2.38.2 |\n| pane2-style | `Object \\| string` | `undefined` | The Style of the second pane | 2.38.2 |\n| resize-trigger-size | `number` | `3` | Size of the resize trigger. | 2.36.0 |\n| size | `string \\| number` | `undefined` | Split is the controlled split size, when it's `number` it should in 0 ~ 1, when it's `string` it should be formatted in `${number}px`. | 2.38.0, `string` 2.38.2 |\n| watch-props | `Array<'defaultSize'>` | `undefined` | Default prop names that needed to be watched. Components will be updated after the prop is changed. Note: the `watch-props` itself is not reactive. | 2.38.0 |\n| on-drag-start | `(e: Event) => void` | `undefined` | Callback function when drag start. | 2.36.0 |\n| on-drag-move | `(e: Event) => void` | `undefined` | Callback function when dragging. | 2.36.0 |\n| on-drag-end | `(e: Event) => void` | `undefined` | Callback function when drag end. | 2.36.0 |\n| on-update:size | `(value: string \\| number) => void` | `undefined` | Callback fired on `size` changes. If `props.value` or `props.defaultValue` is `string`, `value` is `string`. | 2.38.0, `string` 2.38.2 |\n\n### Split Slots\n\n| Name           | Parameters | Description              | Version |\n| -------------- | ---------- | ------------------------ | ------- |\n| 1              | `()`       | The first pane content.  | 2.36.0  |\n| 2              | `()`       | The Second pane content. | 2.36.0  |\n| resize-trigger | `()`       | Split bar content.       | 2.36.0  |\n"
  },
  {
    "path": "src/split/demos/enUS/nest.demo.vue",
    "content": "<markdown>\n# Nested layout\n</markdown>\n\n<template>\n  <n-split direction=\"horizontal\" style=\"height: 200px\">\n    <template #1>\n      Pane 1\n    </template>\n    <template #2>\n      <n-split direction=\"vertical\" style=\"height: 200px\">\n        <template #1>\n          Pane 2\n        </template>\n        <template #2>\n          <n-split direction=\"horizontal\" style=\"height: 100%\">\n            <template #1>\n              Pane 3\n            </template>\n            <template #2>\n              Pane 4\n            </template>\n          </n-split>\n        </template>\n      </n-split>\n    </template>\n  </n-split>\n</template>\n"
  },
  {
    "path": "src/split/demos/enUS/slot.demo.vue",
    "content": "<markdown>\n# Slot\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { SwapHorizontal as SwapHorizontalIcon } from '@vicons/ionicons5'\n</script>\n\n<template>\n  <n-split\n    direction=\"horizontal\"\n    style=\"height: 200px\"\n    :default-size=\"0.4\"\n    :resize-trigger-size=\"16\"\n    :min=\"0.25\"\n    :max=\"0.75\"\n  >\n    <template #1>\n      Pane 1\n    </template>\n    <template #2>\n      Pane 2\n    </template>\n    <template #resize-trigger>\n      <div\n        :style=\"{\n          height: '100%',\n          backgroundColor: '#409eff',\n          display: 'flex',\n          justifyContent: 'center',\n          alignItems: 'center',\n          borderRadius: '8px',\n        }\"\n      >\n        <n-icon color=\"white\" :size=\"16\">\n          <SwapHorizontalIcon />\n        </n-icon>\n      </div>\n    </template>\n  </n-split>\n</template>\n"
  },
  {
    "path": "src/split/demos/enUS/vertical.demo.vue",
    "content": "<markdown>\n# Vertical layout\n</markdown>\n\n<template>\n  <n-split direction=\"vertical\" style=\"height: 200px\">\n    <template #1>\n      <div :style=\"{ height: '100%' }\">\n        Pane 1\n      </div>\n    </template>\n    <template #2>\n      <div :style=\"{ height: '100%' }\">\n        Pane 2\n      </div>\n    </template>\n  </n-split>\n</template>\n"
  },
  {
    "path": "src/split/demos/zhCN/basic.demo.vue",
    "content": "<markdown>\n# 基础用法\n</markdown>\n\n<template>\n  <n-split direction=\"horizontal\" style=\"height: 200px\" :max=\"0.75\" :min=\"0.25\">\n    <template #1>\n      Pane 1\n    </template>\n    <template #2>\n      Pane 2\n    </template>\n  </n-split>\n</template>\n"
  },
  {
    "path": "src/split/demos/zhCN/controlled.demo.vue",
    "content": "<markdown>\n# 受控的属性值\n</markdown>\n\n<script setup lang=\"ts\">\nimport { NInputNumber, NSplit } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst split = ref<number>(0.8)\n</script>\n\n<template>\n  <n-flex vertical>\n    <NInputNumber\n      v-model:value=\"split\"\n      :step=\"0.1\"\n      clearable\n      :max=\"1\"\n      :min=\"0\"\n    />\n    <NSplit v-model:size=\"split\" style=\"height: 200px\">\n      <template #1>\n        <div style=\"width: 100%; background-color: black\" />\n      </template>\n      <template #2>\n        <div style=\"width: 100%; background-color: red\" />\n      </template>\n    </NSplit>\n  </n-flex>\n</template>\n"
  },
  {
    "path": "src/split/demos/zhCN/event.demo.vue",
    "content": "<markdown>\n  # 事件\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { useMessage } from 'naive-ui'\n\nconst message = useMessage()\nfunction handleOnDragStart() {\n  message.info('开始滚动')\n}\nfunction handleOnDragMove() {\n  message.info('滚动中')\n}\nfunction handleOnDragEnd() {\n  message.info('滚动结束')\n}\n</script>\n\n<template>\n  <n-split\n    direction=\"horizontal\"\n    style=\"height: 200px\"\n    @drag-start=\"handleOnDragStart\"\n    @drag-move=\"handleOnDragMove\"\n    @drag-end=\"handleOnDragEnd\"\n  >\n    <template #1>\n      Pane 1\n    </template>\n    <template #2>\n      Pane 2\n    </template>\n  </n-split>\n</template>\n"
  },
  {
    "path": "src/split/demos/zhCN/index.demo-entry.md",
    "content": "# 面板分割 Split\n\n灵活的布局工具，提供了用户自定义界面布局的可能性。\n\n自 `2.36.0` 开始提供。\n\n## 演示\n\n```demo\nbasic.vue\nvertical.vue\nnest.vue\nevent.vue\nslot.vue\ncontrolled.vue\npixel-value.vue\n```\n\n## API\n\n### Split Props\n\n| 名称 | 类型 | 默认值 | 说明 | 版本 |\n| --- | --- | --- | --- | --- |\n| default-size | `string \\| number` | `0.5` | Split 的默认分割大小，为 `number` 类型时应该为 0 ~ 1 之间的值，为 `string` 类型时应该为 `${number}px` 格式 | 2.36.0, `string` 2.38.2 |\n| direction | `'horizontal' \\| 'vertical'` | `'horizontal'` | Split 的分割方向 | 2.36.0 |\n| disabled | `boolean` | `false` | 是否禁用 | 2.36.0 |\n| max | `string \\| number` | `1` | Split 的分割最大阈值，为 `number` 类型时应该为 0 ~ 1 之间的值，为 `string` 类型时应该为 `${number}px` 格式 | 2.36.0, `string` 2.38.2 |\n| min | `string \\| number` | `0` | Split 的分割最小阈值，为 `number` 类型时应该为 0 ~ 1 之间的值，为 `string` 类型时应该为 `${number}px` 格式 | 2.36.0, `string` 2.38.2 |\n| pane1-class | `string` | `undefined` | 第一个面板的类名 | 2.38.2 |\n| pane1-style | `Object \\| string` | `undefined` | 第一个面板的样式 | 2.38.2 |\n| pane2-class | `string` | `undefined` | 第二个面板的类名 | 2.38.2 |\n| pane2-style | `Object \\| string` | `undefined` | 第二个面板的样式 | 2.38.2 |\n| resize-trigger-size | `number` | `3` | Split 的分隔条大小 | 2.36.0 |\n| size | `string \\| number` | `undefined` | Split 的受控分割大小，为 `number` 类型时应该为 0 ~ 1 之间的值，为 `string` 类型时应该为 `${number}px` 格式 | 2.38.0, `string` 2.38.2 |\n| watch-props | `Array<'defaultSize'>` | `undefined` | 需要检测变更的默认属性，检测后组件状态会更新。注意：`watch-props` 本身不是响应式的 | 2.38.0 |\n| on-drag-start | `(e: Event) => void` | `undefined` | 开始拖拽的回调函数 | 2.36.0 |\n| on-drag-move | `(e: Event) => void` | `undefined` | 拖拽中的回调函数 | 2.36.0 |\n| on-drag-end | `(e: Event) => void` | `undefined` | 结束拖拽的回调函数 | 2.36.0 |\n| on-update:size | `(value: string \\| number) => void` | `undefined` | 组件 `size` 属性变化时触发的回调，如果 `props.value` 或 `props.defaultValue` 是 `string`， 则 `value` 为 `string` | 2.38.0 |\n\n### Split Slots\n\n| 名称           | 参数 | 说明           | 版本   |\n| -------------- | ---- | -------------- | ------ |\n| 1              | `()` | 第一个面板内容 | 2.36.0 |\n| 2              | `()` | 第二个面板内容 | 2.36.0 |\n| resize-trigger | `()` | 分割条内容     | 2.36.0 |\n"
  },
  {
    "path": "src/split/demos/zhCN/nest.demo.vue",
    "content": "<markdown>\n# 嵌套布局\n</markdown>\n\n<template>\n  <n-split direction=\"horizontal\" style=\"height: 200px\">\n    <template #1>\n      Pane 1\n    </template>\n    <template #2>\n      <n-split direction=\"vertical\" style=\"height: 200px\">\n        <template #1>\n          Pane 2\n        </template>\n        <template #2>\n          <n-split direction=\"horizontal\" style=\"height: 100%\">\n            <template #1>\n              Pane 3\n            </template>\n            <template #2>\n              Pane 4\n            </template>\n          </n-split>\n        </template>\n      </n-split>\n    </template>\n  </n-split>\n</template>\n"
  },
  {
    "path": "src/split/demos/zhCN/pixel-value.demo.vue",
    "content": "<markdown>\n# 使用像素值控制尺寸\n\n自 `2.38.2` 开始，`min`、`max`、`size` 和 `default-size` 属性可以接受像素值。\n</markdown>\n\n<template>\n  <n-split\n    direction=\"horizontal\"\n    style=\"height: 200px\"\n    max=\"300px\"\n    min=\"100px\"\n    default-size=\"200px\"\n  >\n    <template #1>\n      Pane 1:<br>\n      min 100px<br>\n      default 200px<br>\n      max 300px\n    </template>\n    <template #2>\n      Pane 2\n    </template>\n  </n-split>\n</template>\n"
  },
  {
    "path": "src/split/demos/zhCN/slot.demo.vue",
    "content": "<markdown>\n# 插槽\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { SwapHorizontal as SwapHorizontalIcon } from '@vicons/ionicons5'\n</script>\n\n<template>\n  <n-split\n    direction=\"horizontal\"\n    style=\"height: 200px\"\n    :default-size=\"0.4\"\n    :resize-trigger-size=\"16\"\n    :min=\"0.25\"\n    :max=\"0.75\"\n  >\n    <template #1>\n      Pane 1\n    </template>\n    <template #2>\n      Pane 2\n    </template>\n    <template #resize-trigger>\n      <div\n        :style=\"{\n          height: '100%',\n          backgroundColor: '#409eff',\n          display: 'flex',\n          justifyContent: 'center',\n          alignItems: 'center',\n          borderRadius: '8px',\n        }\"\n      >\n        <n-icon color=\"white\" :size=\"16\">\n          <SwapHorizontalIcon />\n        </n-icon>\n      </div>\n    </template>\n  </n-split>\n</template>\n"
  },
  {
    "path": "src/split/demos/zhCN/vertical.demo.vue",
    "content": "<markdown>\n# 垂直布局\n</markdown>\n\n<template>\n  <n-split direction=\"vertical\" style=\"height: 200px\">\n    <template #1>\n      Pane 1\n    </template>\n    <template #2>\n      Pane 2\n    </template>\n  </n-split>\n</template>\n"
  },
  {
    "path": "src/split/index.ts",
    "content": "export { default as NSplit, splitProps } from './src/Split'\nexport type { SplitProps, SplitSlots } from './src/Split'\nexport type { SplitOnUpdateSize } from './src/types'\n"
  },
  {
    "path": "src/split/src/Split.tsx",
    "content": "import type { CSSProperties, PropType, SlotsType, VNode } from 'vue'\nimport type { ThemeProps } from '../../_mixins'\nimport type { ExtractPublicPropTypes } from '../../_utils'\nimport type { SplitTheme } from '../styles'\nimport type { SplitOnUpdateSize } from './types'\nimport { off, on } from 'evtd'\nimport { depx } from 'seemly'\nimport { useMergedState } from 'vooks'\nimport { computed, defineComponent, h, ref, toRef, watchEffect } from 'vue'\nimport { useTheme, useThemeClass } from '../../_mixins'\nimport useConfig from '../../_mixins/use-config'\nimport { call, resolveSlot } from '../../_utils'\nimport { splitLight } from '../styles'\nimport style from './styles/index.cssr'\n\nexport const splitProps = {\n  ...(useTheme.props as ThemeProps<SplitTheme>),\n  direction: {\n    type: String as PropType<'horizontal' | 'vertical'>,\n    default: 'horizontal'\n  },\n  resizeTriggerSize: {\n    type: Number,\n    default: 3\n  },\n  disabled: Boolean,\n  defaultSize: {\n    type: [String, Number] as PropType<string | number>,\n    default: 0.5\n  },\n  'onUpdate:size': [Function, Array] as PropType<\n    SplitOnUpdateSize | SplitOnUpdateSize[]\n  >,\n  onUpdateSize: [Function, Array] as PropType<\n    SplitOnUpdateSize | SplitOnUpdateSize[]\n  >,\n  size: [String, Number] as PropType<string | number>,\n  min: {\n    type: [String, Number] as PropType<string | number>,\n    default: 0\n  },\n  max: {\n    type: [String, Number] as PropType<string | number>,\n    default: 1\n  },\n  pane1Class: String,\n  pane1Style: [Object, String] as PropType<CSSProperties | string>,\n  pane2Class: String,\n  pane2Style: [Object, String] as PropType<CSSProperties | string>,\n  onDragStart: Function as PropType<(e: Event) => void>,\n  onDragMove: Function as PropType<(e: Event) => void>,\n  onDragEnd: Function as PropType<(e: Event) => void>,\n  watchProps: Array as PropType<Array<'defaultSize'>>\n} as const\n\nexport type SplitProps = ExtractPublicPropTypes<typeof splitProps>\n\nexport interface SplitSlots {\n  default?: () => VNode[]\n  1?: () => VNode[]\n  2?: () => VNode[]\n  'resize-trigger'?: () => VNode[]\n}\n\nexport default defineComponent({\n  name: 'Split',\n  props: splitProps,\n  slots: Object as SlotsType<SplitSlots>,\n  setup(props) {\n    const { mergedClsPrefixRef, inlineThemeDisabled } = useConfig(props)\n    const themeRef = useTheme(\n      'Split',\n      '-split',\n      style,\n      splitLight,\n      props,\n      mergedClsPrefixRef\n    )\n\n    const cssVarsRef = computed(() => {\n      const {\n        common: { cubicBezierEaseInOut },\n        self: { resizableTriggerColor, resizableTriggerColorHover }\n      } = themeRef.value\n      return {\n        '--n-bezier': cubicBezierEaseInOut,\n        '--n-resize-trigger-color': resizableTriggerColor,\n        '--n-resize-trigger-color-hover': resizableTriggerColorHover\n      }\n    })\n    const resizeTriggerElRef = ref<HTMLElement | null>(null)\n    const isDraggingRef = ref(false)\n    const controlledSizeRef = toRef(props, 'size')\n    const uncontrolledSizeRef = ref(props.defaultSize)\n    if (props.watchProps?.includes('defaultSize')) {\n      watchEffect(() => (uncontrolledSizeRef.value = props.defaultSize))\n    }\n    // use to update controlled or uncontrolled values\n    const doUpdateSize = (size: number | string): void => {\n      const _onUpdateSize = props['onUpdate:size']\n      if (props.onUpdateSize)\n        call(props.onUpdateSize, size as string & number)\n      if (_onUpdateSize)\n        call(_onUpdateSize, size as string & number)\n      uncontrolledSizeRef.value = size\n    }\n    const mergedSizeRef = useMergedState(controlledSizeRef, uncontrolledSizeRef)\n\n    const firstPaneStyle = computed(() => {\n      const sizeValue = mergedSizeRef.value\n      if (typeof sizeValue === 'string') {\n        return {\n          flex: `0 0 ${sizeValue}`\n        }\n      }\n      else if (typeof sizeValue === 'number') {\n        const size = sizeValue * 100\n        return {\n          flex: `0 0 calc(${size}% - ${\n            (props.resizeTriggerSize * size) / 100\n          }px)`\n        }\n      }\n    })\n\n    const resizeTriggerStyle = computed(() => {\n      return props.direction === 'horizontal'\n        ? {\n            width: `${props.resizeTriggerSize}px`,\n            height: '100%'\n          }\n        : {\n            width: '100%',\n            height: `${props.resizeTriggerSize}px`\n          }\n    })\n\n    const resizeTriggerWrapperStyle = computed(() => {\n      const horizontal = props.direction === 'horizontal'\n      return {\n        width: horizontal ? `${props.resizeTriggerSize}px` : '',\n        height: horizontal ? '' : `${props.resizeTriggerSize}px`,\n        cursor: props.direction === 'horizontal' ? 'col-resize' : 'row-resize'\n      }\n    })\n\n    let offset = 0\n    const handleMouseDown = (e: MouseEvent): void => {\n      e.preventDefault()\n      isDraggingRef.value = true\n      if (props.onDragStart)\n        props.onDragStart(e)\n      const mouseMoveEvent = 'mousemove'\n      const mouseUpEvent = 'mouseup'\n      const onMouseMove = (e: MouseEvent): void => {\n        updateSize(e)\n        if (props.onDragMove)\n          props.onDragMove(e)\n      }\n      const onMouseUp = (): void => {\n        off(mouseMoveEvent, document, onMouseMove)\n        off(mouseUpEvent, document, onMouseUp)\n        isDraggingRef.value = false\n        if (props.onDragEnd)\n          props.onDragEnd(e)\n        document.body.style.cursor = ''\n      }\n      document.body.style.cursor = resizeTriggerWrapperStyle.value.cursor\n      on(mouseMoveEvent, document, onMouseMove)\n      on(mouseUpEvent, document, onMouseUp)\n\n      const resizeTriggerEl = resizeTriggerElRef.value\n      if (resizeTriggerEl) {\n        const elRect = resizeTriggerEl.getBoundingClientRect()\n        if (props.direction === 'horizontal') {\n          offset = e.clientX - elRect.left\n        }\n        else {\n          offset = elRect.top - e.clientY\n        }\n      }\n      updateSize(e)\n    }\n\n    function updateSize(event: MouseEvent): void {\n      const containerRect\n        = resizeTriggerElRef.value?.parentElement?.getBoundingClientRect()\n      if (!containerRect)\n        return\n\n      const { direction } = props\n\n      const containerUsableWidth = containerRect.width - props.resizeTriggerSize\n      const containerUsableHeight\n        = containerRect.height - props.resizeTriggerSize\n      const containerUsableSize\n        = direction === 'horizontal'\n          ? containerUsableWidth\n          : containerUsableHeight\n\n      const newPxSize\n        = direction === 'horizontal'\n          ? event.clientX - containerRect.left - offset\n          : event.clientY - containerRect.top + offset\n\n      const { min, max } = props\n\n      const pxMin\n        = typeof min === 'string' ? depx(min) : min * containerUsableSize\n      const pxMax\n        = typeof max === 'string' ? depx(max) : max * containerUsableSize\n\n      let nextPxSize = newPxSize\n      nextPxSize = Math.max(nextPxSize, pxMin)\n      nextPxSize = Math.min(nextPxSize, pxMax, containerUsableSize)\n      // in pixel mode\n      if (typeof mergedSizeRef.value === 'string') {\n        doUpdateSize(`${nextPxSize}px`)\n      }\n      else {\n        // in percentage mode\n        doUpdateSize(nextPxSize / containerUsableSize)\n      }\n    }\n\n    const themeClassHandle = inlineThemeDisabled\n      ? useThemeClass('split', undefined, cssVarsRef, props)\n      : undefined\n\n    return {\n      themeClass: themeClassHandle?.themeClass,\n      onRender: themeClassHandle?.onRender,\n      cssVars: inlineThemeDisabled ? undefined : cssVarsRef,\n      resizeTriggerElRef,\n      isDragging: isDraggingRef,\n      mergedClsPrefix: mergedClsPrefixRef,\n      resizeTriggerWrapperStyle,\n      resizeTriggerStyle,\n      handleMouseDown,\n      firstPaneStyle\n    }\n  },\n  render() {\n    this.onRender?.()\n    return (\n      <div\n        class={[\n          `${this.mergedClsPrefix}-split`,\n          `${this.mergedClsPrefix}-split--${this.direction}`,\n          this.themeClass\n        ]}\n        style={this.cssVars as CSSProperties}\n      >\n        <div\n          class={[`${this.mergedClsPrefix}-split-pane-1`, this.pane1Class]}\n          style={[this.firstPaneStyle, this.pane1Style]}\n        >\n          {this.$slots[1]?.()}\n        </div>\n        {!this.disabled && (\n          <div\n            ref=\"resizeTriggerElRef\"\n            class={`${this.mergedClsPrefix}-split__resize-trigger-wrapper`}\n            style={this.resizeTriggerWrapperStyle}\n            onMousedown={this.handleMouseDown}\n          >\n            {resolveSlot(this.$slots['resize-trigger'], () => [\n              <div\n                style={this.resizeTriggerStyle}\n                class={[\n                  `${this.mergedClsPrefix}-split__resize-trigger`,\n                  this.isDragging\n                  && `${this.mergedClsPrefix}-split__resize-trigger--hover`\n                ]}\n              >\n              </div>\n            ])}\n          </div>\n        )}\n        <div\n          class={[`${this.mergedClsPrefix}-split-pane-2`, this.pane2Class]}\n          style={this.pane2Style}\n        >\n          {this.$slots[2]?.()}\n        </div>\n      </div>\n    )\n  }\n})\n"
  },
  {
    "path": "src/split/src/styles/index.cssr.ts",
    "content": "import { c, cB, cE, cM } from '../../../_utils/cssr'\n\n// vars:\n// --n-resize-trigger-color\n// --n-resize-trigger-color-hover\n// --n-bezier\nexport default cB('split', `\n  display: flex;\n  width: 100%;\n  height: 100%;\n`, [\n  cM('horizontal', `\n    flex-direction: row;\n  `),\n  cM('vertical', `\n    flex-direction: column;\n  `),\n  cB('split-pane-1', `\n    overflow: hidden;\n  `),\n  cB('split-pane-2', `\n    overflow: hidden;\n    flex: 1;\n  `),\n  cE('resize-trigger', `\n    background-color: var(--n-resize-trigger-color);\n    transition: background-color .3s var(--n-bezier);\n  `, [\n    cM('hover', `\n      background-color: var(--n-resize-trigger-color-hover);\n    `),\n    c('&:hover', `\n      background-color: var(--n-resize-trigger-color-hover);\n    `)\n  ])\n])\n"
  },
  {
    "path": "src/split/src/types.ts",
    "content": "export type SplitOnUpdateSize = (size: string & number) => void\n"
  },
  {
    "path": "src/split/styles/dark.ts",
    "content": "import type { SplitTheme } from './light'\nimport { commonDark } from '../../_styles/common'\n\nconst splitDark: SplitTheme = {\n  name: 'Split',\n  common: commonDark\n}\n\nexport default splitDark\n"
  },
  {
    "path": "src/split/styles/index.ts",
    "content": "export { default as splitDark } from './dark'\nexport { default as splitLight } from './light'\nexport type { SplitTheme, SplitThemeVars } from './light'\n"
  },
  {
    "path": "src/split/styles/light.ts",
    "content": "import type { Theme } from '../../_mixins'\nimport type { ThemeCommonVars } from '../../_styles/common'\nimport { commonLight } from '../../_styles/common'\n\nexport function self(vars: ThemeCommonVars) {\n  const { primaryColorHover, borderColor } = vars\n  return {\n    resizableTriggerColorHover: primaryColorHover,\n    resizableTriggerColor: borderColor\n  }\n}\n\nexport type SplitThemeVars = ReturnType<typeof self>\n\nconst themeLight: Theme<'Split', SplitThemeVars> = {\n  name: 'Split',\n  common: commonLight,\n  self\n}\n\nexport default themeLight\nexport type SplitTheme = typeof themeLight\n"
  },
  {
    "path": "src/statistic/demos/enUS/basic.demo.vue",
    "content": "<markdown>\n# Basic\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { MdSave } from '@vicons/ionicons4'\n</script>\n\n<template>\n  <n-row>\n    <n-col :span=\"12\">\n      <n-statistic label=\"Statistic\" :value=\"99\">\n        <template #prefix>\n          <n-icon>\n            <MdSave />\n          </n-icon>\n        </template>\n        <template #suffix>\n          / 100\n        </template>\n      </n-statistic>\n    </n-col>\n    <n-col :span=\"12\">\n      <n-statistic label=\"Active Users\">\n        1,234,123\n      </n-statistic>\n    </n-col>\n  </n-row>\n</template>\n"
  },
  {
    "path": "src/statistic/demos/enUS/index.demo-entry.md",
    "content": "# Statistic\n\nAs simple as it looks.\n\n## Demos\n\n```demo\nbasic.vue\n```\n\n## API\n\n### Statistic Props\n\n| Name | Type | Default | Description | Version |\n| --- | --- | --- | --- | --- |\n| label | `string` | `undefined` | Label of the statistics. |  |\n| tabular-nums | `boolean` | `false` | Whether to make numbers with same width. | 2.23.2 |\n| value | `string \\| number` | `undefined` | Statistics value. |  |\n\n### Statistic Slots\n\n| Name    | Parameters | Description   |\n| ------- | ---------- | ------------- |\n| default | `()`       | Value slot.   |\n| label   | `()`       | Label slot.   |\n| prefix  | `()`       | Value prefix. |\n| suffix  | `()`       | Value suffix. |\n"
  },
  {
    "path": "src/statistic/demos/zhCN/basic.demo.vue",
    "content": "<markdown>\n# 基础用法\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { MdSave } from '@vicons/ionicons4'\n</script>\n\n<template>\n  <n-row>\n    <n-col :span=\"12\">\n      <n-statistic label=\"统计数据\" :value=\"99\">\n        <template #prefix>\n          <n-icon>\n            <MdSave />\n          </n-icon>\n        </template>\n        <template #suffix>\n          / 100\n        </template>\n      </n-statistic>\n    </n-col>\n    <n-col :span=\"12\">\n      <n-statistic label=\"活跃用户\">\n        1,234,123\n      </n-statistic>\n    </n-col>\n  </n-row>\n</template>\n"
  },
  {
    "path": "src/statistic/demos/zhCN/index.demo-entry.md",
    "content": "# 统计数据 Statistic\n\n和它看起来一样简单。\n\n## 演示\n\n```demo\nbasic.vue\nrtl-debug.vue\n```\n\n## API\n\n### Statistic Props\n\n| 名称 | 类型 | 默认值 | 说明 | 版本 |\n| --- | --- | --- | --- | --- |\n| label | `string` | `undefined` | 展示的 `label` 信息 |  |\n| tabular-nums | `boolean` | `false` | 是否让数字等宽 | 2.23.2 |\n| value | `string \\| number` | `undefined` | 统计数据的值 |  |\n\n### Statistic Slots\n\n| 名称    | 参数 | 说明     |\n| ------- | ---- | -------- |\n| default | `()` | 值       |\n| label   | `()` | 标签     |\n| prefix  | `()` | 值的前缀 |\n| suffix  | `()` | 值的后缀 |\n"
  },
  {
    "path": "src/statistic/demos/zhCN/rtl-debug.demo.vue",
    "content": "<markdown>\n# Rtl Debug\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { MdSave } from '@vicons/ionicons4'\nimport { unstableRowRtl, unstableStatisticRtl } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst rtlEnabled = ref(false)\nconst rtlStyles = [unstableStatisticRtl, unstableRowRtl]\n</script>\n\n<template>\n  <n-space vertical>\n    <n-space><n-switch v-model:value=\"rtlEnabled\" />Rtl</n-space>\n    <n-config-provider :rtl=\"rtlEnabled ? rtlStyles : undefined\">\n      <n-row>\n        <n-col :span=\"12\">\n          <n-statistic label=\"Statistic\" :value=\"99\">\n            <template #prefix>\n              <n-icon>\n                <MdSave />\n              </n-icon>\n            </template>\n            <template #suffix>\n              / 100\n            </template>\n          </n-statistic>\n        </n-col>\n        <n-col :span=\"12\">\n          <n-statistic label=\"Active Users\">\n            1,234,123\n          </n-statistic>\n        </n-col>\n      </n-row>\n    </n-config-provider>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/statistic/index.ts",
    "content": "export { default as NStatistic, statisticProps } from './src/Statistic'\nexport type { StatisticProps, StatisticSlots } from './src/Statistic'\n"
  },
  {
    "path": "src/statistic/src/Statistic.tsx",
    "content": "import type { SlotsType, VNode } from 'vue'\nimport type { ThemeProps } from '../../_mixins'\nimport type { ExtractPublicPropTypes } from '../../_utils'\nimport type { StatisticTheme } from '../styles'\nimport { computed, defineComponent, h } from 'vue'\nimport { useConfig, useRtl, useTheme, useThemeClass } from '../../_mixins'\nimport { resolveWrappedSlot } from '../../_utils'\nimport { statisticLight } from '../styles'\nimport style from './styles/index.cssr'\n\nexport const statisticProps = {\n  ...(useTheme.props as ThemeProps<StatisticTheme>),\n  tabularNums: Boolean,\n  label: String,\n  value: [String, Number]\n}\n\nexport type StatisticProps = ExtractPublicPropTypes<typeof statisticProps>\n\nexport interface StatisticSlots {\n  default?: () => VNode[]\n  label?: () => VNode[]\n  prefix?: () => VNode[]\n  suffix?: () => VNode[]\n}\n\nexport default defineComponent({\n  name: 'Statistic',\n  props: statisticProps,\n  slots: Object as SlotsType<StatisticSlots>,\n  setup(props) {\n    const { mergedClsPrefixRef, inlineThemeDisabled, mergedRtlRef }\n      = useConfig(props)\n    const themeRef = useTheme(\n      'Statistic',\n      '-statistic',\n      style,\n      statisticLight,\n      props,\n      mergedClsPrefixRef\n    )\n    const rtlEnabledRef = useRtl('Statistic', mergedRtlRef, mergedClsPrefixRef)\n    const cssVarsRef = computed(() => {\n      const {\n        self: {\n          labelFontWeight,\n          valueFontSize,\n          valueFontWeight,\n          valuePrefixTextColor,\n          labelTextColor,\n          valueSuffixTextColor,\n          valueTextColor,\n          labelFontSize\n        },\n        common: { cubicBezierEaseInOut }\n      } = themeRef.value\n      return {\n        '--n-bezier': cubicBezierEaseInOut,\n        '--n-label-font-size': labelFontSize,\n        '--n-label-font-weight': labelFontWeight,\n        '--n-label-text-color': labelTextColor,\n        '--n-value-font-weight': valueFontWeight,\n        '--n-value-font-size': valueFontSize,\n        '--n-value-prefix-text-color': valuePrefixTextColor,\n        '--n-value-suffix-text-color': valueSuffixTextColor,\n        '--n-value-text-color': valueTextColor\n      }\n    })\n    const themeClassHandle = inlineThemeDisabled\n      ? useThemeClass('statistic', undefined, cssVarsRef, props)\n      : undefined\n    return {\n      rtlEnabled: rtlEnabledRef,\n      mergedClsPrefix: mergedClsPrefixRef,\n      cssVars: inlineThemeDisabled ? undefined : cssVarsRef,\n      themeClass: themeClassHandle?.themeClass,\n      onRender: themeClassHandle?.onRender\n    }\n  },\n  render() {\n    const {\n      mergedClsPrefix,\n      $slots: {\n        default: defaultSlot,\n        label: labelSlot,\n        prefix: prefixSlot,\n        suffix: suffixSlot\n      }\n    } = this\n    this.onRender?.()\n    return (\n      <div\n        class={[\n          `${mergedClsPrefix}-statistic`,\n          this.themeClass,\n          this.rtlEnabled && `${mergedClsPrefix}-statistic--rtl`\n        ]}\n        style={this.cssVars as any}\n      >\n        {resolveWrappedSlot(labelSlot, children => (\n          <div class={`${mergedClsPrefix}-statistic__label`}>\n            {this.label || children}\n          </div>\n        ))}\n        <div\n          class={`${mergedClsPrefix}-statistic-value`}\n          style={{\n            fontVariantNumeric: this.tabularNums ? 'tabular-nums' : ''\n          }}\n        >\n          {resolveWrappedSlot(\n            prefixSlot,\n            children =>\n              children && (\n                <span class={`${mergedClsPrefix}-statistic-value__prefix`}>\n                  {children}\n                </span>\n              )\n          )}\n          {this.value !== undefined ? (\n            <span class={`${mergedClsPrefix}-statistic-value__content`}>\n              {this.value}\n            </span>\n          ) : (\n            resolveWrappedSlot(\n              defaultSlot,\n              children =>\n                children && (\n                  <span class={`${mergedClsPrefix}-statistic-value__content`}>\n                    {children}\n                  </span>\n                )\n            )\n          )}\n          {resolveWrappedSlot(\n            suffixSlot,\n            children =>\n              children && (\n                <span class={`${mergedClsPrefix}-statistic-value__suffix`}>\n                  {children}\n                </span>\n              )\n          )}\n        </div>\n      </div>\n    )\n  }\n})\n"
  },
  {
    "path": "src/statistic/src/styles/index.cssr.ts",
    "content": "import { cB, cE } from '../../../_utils/cssr'\n\n// vars:\n// --n-bezier\n// --n-label-font-size\n// --n-label-font-weight\n// --n-label-text-color\n// --n-value-font-weight\n// --n-value-font-size\n// --n-value-prefix-text-color\n// --n-value-suffix-text-color\n// --n-value-text-color\nexport default cB('statistic', [\n  cE('label', `\n    font-weight: var(--n-label-font-weight);\n    transition: .3s color var(--n-bezier);\n    font-size: var(--n-label-font-size);\n    color: var(--n-label-text-color);\n  `),\n  cB('statistic-value', `\n    margin-top: 4px;\n    font-weight: var(--n-value-font-weight);\n  `, [\n    cE('prefix', `\n      margin: 0 4px 0 0;\n      font-size: var(--n-value-font-size);\n      transition: .3s color var(--n-bezier);\n      color: var(--n-value-prefix-text-color);\n    `, [\n      cB('icon', {\n        verticalAlign: '-0.125em'\n      })\n    ]),\n    cE('content', `\n      font-size: var(--n-value-font-size);\n      transition: .3s color var(--n-bezier);\n      color: var(--n-value-text-color);\n    `),\n    cE('suffix', `\n      margin: 0 0 0 4px;\n      font-size: var(--n-value-font-size);\n      transition: .3s color var(--n-bezier);\n      color: var(--n-value-suffix-text-color);\n    `, [\n      cB('icon', {\n        verticalAlign: '-0.125em'\n      })\n    ])\n  ])\n])\n"
  },
  {
    "path": "src/statistic/src/styles/rtl.cssr.ts",
    "content": "import { cB, cE, cM } from '../../../_utils/cssr'\n\nexport default cB('statistic', [\n  cM('rtl', `\n    direction: rtl;\n    text-align: right;\n  `, [\n    cB('statistic-value', [\n      cE('prefix', `\n        margin: 0 0 0 4px;\n      `),\n      cE('suffix', `\n        margin: 0 4px 0 0;\n      `)\n    ])\n  ])\n])\n"
  },
  {
    "path": "src/statistic/styles/dark.ts",
    "content": "import type { StatisticTheme } from './light'\nimport { commonDark } from '../../_styles/common'\nimport { self } from './light'\n\nconst statisticDark: StatisticTheme = {\n  name: 'Statistic',\n  common: commonDark,\n  self\n}\n\nexport default statisticDark\n"
  },
  {
    "path": "src/statistic/styles/index.ts",
    "content": "export { default as statisticDark } from './dark'\nexport { default as statisticLight } from './light'\nexport type { StatisticTheme, StatisticThemeVars } from './light'\nexport { statisticRtl } from './rtl'\n"
  },
  {
    "path": "src/statistic/styles/light.ts",
    "content": "import type { Theme } from '../../_mixins'\nimport type { ThemeCommonVars } from '../../_styles/common'\nimport { commonLight } from '../../_styles/common'\n\nexport function self(vars: ThemeCommonVars) {\n  const { textColor2, textColor3, fontSize, fontWeight } = vars\n  return {\n    labelFontSize: fontSize,\n    labelFontWeight: fontWeight,\n    valueFontWeight: fontWeight,\n    valueFontSize: '24px',\n    labelTextColor: textColor3,\n    valuePrefixTextColor: textColor2,\n    valueSuffixTextColor: textColor2,\n    valueTextColor: textColor2\n  }\n}\n\nexport type StatisticThemeVars = ReturnType<typeof self>\n\nconst statisticLight: Theme<'Statistic', StatisticThemeVars> = {\n  name: 'Statistic',\n  common: commonLight,\n  self\n}\n\nexport default statisticLight\nexport type StatisticTheme = typeof statisticLight\n"
  },
  {
    "path": "src/statistic/styles/rtl.ts",
    "content": "import type { RtlItem } from '../../config-provider/src/internal-interface'\nimport rtlStyle from '../src/styles/rtl.cssr'\n\nexport const statisticRtl: RtlItem = {\n  name: 'Statistic',\n  style: rtlStyle\n}\n"
  },
  {
    "path": "src/statistic/tests/Statistic.spec.ts",
    "content": "import { mount } from '@vue/test-utils'\nimport { NStatistic } from '../index'\n\ndescribe('n-statistic', () => {\n  it('should work with import on demand', () => {\n    mount(NStatistic)\n  })\n\n  it('should work with `label` prop', async () => {\n    const wrapper = mount(NStatistic, { props: { label: 'test' } })\n\n    expect(wrapper.find('.n-statistic__label').exists()).toBe(true)\n    expect(wrapper.find('.n-statistic__label').text()).toBe('test')\n    wrapper.unmount()\n  })\n\n  it('should work with `value` prop', async () => {\n    const wrapper = mount(NStatistic, { props: { value: 'test' } })\n\n    expect(wrapper.find('.n-statistic-value__content').exists()).toBe(true)\n    expect(wrapper.find('.n-statistic-value__content').text()).toBe('test')\n    wrapper.unmount()\n  })\n\n  it('should work with `tabularNums` prop', async () => {\n    const wrapper = mount(NStatistic, {\n      props: {\n        value: 10001\n      }\n    })\n\n    expect(wrapper.find('.n-statistic-value').attributes('style')).toBeFalsy()\n    await wrapper.setProps({ tabularNums: true })\n    expect(wrapper.find('.n-statistic-value').attributes('style')).toContain(\n      'font-variant-numeric: tabular-nums;'\n    )\n    wrapper.unmount()\n  })\n\n  it('should work with `default` slot', async () => {\n    const wrapper = mount(NStatistic, { slots: { default: () => 'test' } })\n\n    expect(wrapper.find('.n-statistic-value__content').exists()).toBe(true)\n    expect(wrapper.find('.n-statistic-value__content').text()).toBe('test')\n    wrapper.unmount()\n  })\n\n  it('should work with `label` slot', async () => {\n    const wrapper = mount(NStatistic, { slots: { label: () => 'test' } })\n\n    expect(wrapper.find('.n-statistic__label').exists()).toBe(true)\n    expect(wrapper.find('.n-statistic__label').text()).toBe('test')\n    wrapper.unmount()\n  })\n\n  it('should work with `prefix` slot', async () => {\n    const wrapper = mount(NStatistic, { slots: { prefix: () => 'test' } })\n\n    expect(wrapper.find('.n-statistic-value__prefix').exists()).toBe(true)\n    expect(wrapper.find('.n-statistic-value__prefix').text()).toBe('test')\n    wrapper.unmount()\n  })\n\n  it('should work with `suffix` slot', async () => {\n    const wrapper = mount(NStatistic, { slots: { suffix: () => 'test' } })\n\n    expect(wrapper.find('.n-statistic-value__suffix').exists()).toBe(true)\n    expect(wrapper.find('.n-statistic-value__suffix').text()).toBe('test')\n    wrapper.unmount()\n  })\n})\n"
  },
  {
    "path": "src/statistic/tests/server.spec.tsx",
    "content": "import { setup } from '@css-render/vue3-ssr'\nimport { renderToString } from '@vue/server-renderer'\n/**\n * @vitest-environment node\n */\nimport { createSSRApp, h } from 'vue'\nimport { NStatistic } from '../..'\n\ndescribe('server side rendering', () => {\n  it('works', async () => {\n    const app = createSSRApp(() => <NStatistic />)\n    setup(app)\n    try {\n      await renderToString(app)\n    }\n    catch (e) {\n      expect(e).not.toBeTruthy()\n    }\n  })\n})\n"
  },
  {
    "path": "src/steps/demos/enUS/basic.demo.vue",
    "content": "<markdown>\n# Basic\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { StepsProps } from 'naive-ui'\nimport { MdArrowRoundBack, MdArrowRoundForward } from '@vicons/ionicons4'\nimport { ref } from 'vue'\n\nconst currentRef = ref<number | null>(1)\nconst currentStatus = ref<StepsProps['status']>('process')\nconst current = currentRef\n\nfunction next() {\n  if (currentRef.value === null)\n    currentRef.value = 1\n  else if (currentRef.value >= 4)\n    currentRef.value = null\n  else currentRef.value++\n}\n\nfunction prev() {\n  if (currentRef.value === 0)\n    currentRef.value = null\n  else if (currentRef.value === null)\n    currentRef.value = 4\n  else currentRef.value--\n}\n</script>\n\n<template>\n  <n-space vertical>\n    <n-steps :current=\"current as number\" :status=\"currentStatus\">\n      <n-step\n        title=\"I Me Mine\"\n        description=\"All through the day, I me mine I me mine, I me mine\"\n      />\n      <n-step\n        title=\"Let It Be\"\n        description=\"When I find myself in times of trouble Mother Mary comes to me\"\n      />\n      <n-step\n        title=\"Come Together\"\n        description=\"Here come old flat top He come grooving up slowly\"\n      />\n      <n-step\n        title=\"Something\"\n        description=\"Something in the way she moves Attracts me like no other lover\"\n      />\n    </n-steps>\n    <n-space>\n      <n-button-group>\n        <n-button @click=\"prev\">\n          <template #icon>\n            <n-icon>\n              <MdArrowRoundBack />\n            </n-icon>\n          </template>\n        </n-button>\n        <n-button @click=\"next\">\n          <template #icon>\n            <n-icon>\n              <MdArrowRoundForward />\n            </n-icon>\n          </template>\n        </n-button>\n      </n-button-group>\n      <n-radio-group v-model:value=\"currentStatus\" size=\"medium\" name=\"basic\">\n        <n-radio-button value=\"error\">\n          Error\n        </n-radio-button>\n        <n-radio-button value=\"process\">\n          Process\n        </n-radio-button>\n        <n-radio-button value=\"wait\">\n          Wait\n        </n-radio-button>\n        <n-radio-button value=\"finish\">\n          Finish\n        </n-radio-button>\n      </n-radio-group>\n    </n-space>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/steps/demos/enUS/click.demo.vue",
    "content": "<markdown>\n# Click to switch\n\nIf `@update:current` is set, you can switch step by click.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst currentRef = ref<number | undefined>(1)\nconst current = currentRef\n</script>\n\n<template>\n  <n-steps v-model:current=\"current\">\n    <n-step\n      title=\"I Me Mine\"\n      description=\"All through the day, I me mine I me mine, I me mine\"\n    />\n    <n-step\n      title=\"Let It Be\"\n      description=\"When I find myself in times of trouble Mother Mary comes to me\"\n    />\n    <n-step\n      title=\"Come Together\"\n      description=\"Here come old flat top He come grooving up slowly\"\n    />\n    <n-step\n      disabled\n      title=\"Something\"\n      description=\"Something in the way she moves Attracts me like no other lover\"\n    />\n  </n-steps>\n</template>\n"
  },
  {
    "path": "src/steps/demos/enUS/content-placement.demo.vue",
    "content": "<markdown>\n# Content Placement\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { StepsProps } from 'naive-ui'\nimport { MdArrowRoundBack, MdArrowRoundForward } from '@vicons/ionicons4'\nimport { ref } from 'vue'\n\nconst currentRef = ref<number | null>(1)\nconst currentStatus = ref<StepsProps['status']>('process')\nconst contentPlacement = ref<StepsProps['contentPlacement']>('bottom')\nconst current = currentRef\n\nfunction next() {\n  if (currentRef.value === null)\n    currentRef.value = 1\n  else if (currentRef.value >= 4)\n    currentRef.value = null\n  else currentRef.value++\n}\n\nfunction prev() {\n  if (currentRef.value === 0)\n    currentRef.value = null\n  else if (currentRef.value === null)\n    currentRef.value = 4\n  else currentRef.value--\n}\n\nfunction right() {\n  contentPlacement.value = 'right'\n}\n\nfunction bottom() {\n  contentPlacement.value = 'bottom'\n}\n</script>\n\n<template>\n  <n-space vertical>\n    <n-steps\n      :content-placement=\"contentPlacement\"\n      :current=\"current as number\"\n      :status=\"currentStatus\"\n    >\n      <n-step\n        title=\"I Me Mine\"\n        description=\"All through the day, I me mine I me mine, I me mine\"\n      />\n      <n-step\n        title=\"Let It Be\"\n        description=\"When I find myself in times of trouble Mother Mary comes to me\"\n      />\n      <n-step\n        title=\"Come Together\"\n        description=\"Here come old flat top He come grooving up slowly\"\n      />\n      <n-step\n        title=\"Something\"\n        description=\"Something in the way she moves Attracts me like no other lover\"\n      />\n    </n-steps>\n    <n-space>\n      <n-radio-group v-model:value=\"contentPlacement\">\n        <n-radio-button value=\"right\" @click=\"right\">\n          Right\n        </n-radio-button>\n        <n-radio-button value=\"bottom\" @click=\"bottom\">\n          Bottom\n        </n-radio-button>\n      </n-radio-group>\n      <n-button-group>\n        <n-button @click=\"prev\">\n          <template #icon>\n            <n-icon>\n              <MdArrowRoundBack />\n            </n-icon>\n          </template>\n        </n-button>\n        <n-button @click=\"next\">\n          <template #icon>\n            <n-icon>\n              <MdArrowRoundForward />\n            </n-icon>\n          </template>\n        </n-button>\n      </n-button-group>\n      <n-radio-group v-model:value=\"currentStatus\" size=\"medium\" name=\"basic\">\n        <n-radio-button value=\"error\">\n          Error\n        </n-radio-button>\n        <n-radio-button value=\"process\">\n          Process\n        </n-radio-button>\n        <n-radio-button value=\"wait\">\n          Wait\n        </n-radio-button>\n        <n-radio-button value=\"finish\">\n          Finish\n        </n-radio-button>\n      </n-radio-group>\n    </n-space>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/steps/demos/enUS/content.demo.vue",
    "content": "<markdown>\n# Use slot in step\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { StepsProps } from 'naive-ui'\nimport { computed, ref } from 'vue'\n\nconst currentRef = ref(1)\nconst currentStatusRef = ref<StepsProps['status']>('process')\n\nconst buttonTypeRef = computed(() => {\n  switch (currentStatusRef.value) {\n    case 'error':\n      return 'error'\n    case 'finish':\n      return 'success'\n    default:\n      return 'default'\n  }\n})\n\nconst current = currentRef\nconst currentStatus = currentStatusRef\nconst buttonType = buttonTypeRef\n\nfunction handleButtonClick() {\n  currentRef.value = (currentRef.value % 4) + 1\n}\n</script>\n\n<template>\n  <n-space vertical>\n    <n-steps :current=\"current\" :status=\"currentStatus\">\n      <n-step title=\"I Me Mine\">\n        <div class=\"n-step-description\">\n          <p>Al through the day, I me mine I me mine, I me mine</p>\n          <n-button\n            v-if=\"current === 1\"\n            :type=\"buttonType\"\n            size=\"small\"\n            @click=\"handleButtonClick\"\n          >\n            Next\n          </n-button>\n        </div>\n      </n-step>\n      <n-step title=\"Let It Be\">\n        <div class=\"n-step-description\">\n          <p>When I find myself in times of trouble Mother Mary comes to me</p>\n          <n-button\n            v-if=\"current === 2\"\n            :type=\"buttonType\"\n            size=\"small\"\n            @click=\"handleButtonClick\"\n          >\n            Next\n          </n-button>\n        </div>\n      </n-step>\n      <n-step title=\"Come Together\">\n        <div class=\"n-step-description\">\n          <p>Here come old flat top He come grooving up slowly</p>\n          <n-button\n            v-if=\"current === 3\"\n            :type=\"buttonType\"\n            size=\"small\"\n            @click=\"handleButtonClick\"\n          >\n            Next\n          </n-button>\n        </div>\n      </n-step>\n      <n-step title=\"Something\">\n        <div class=\"n-step-description\">\n          <p>Something in the way she moves Attracts me like no other lover</p>\n          <n-button\n            v-if=\"current === 4\"\n            :type=\"buttonType\"\n            size=\"small\"\n            @click=\"handleButtonClick\"\n          >\n            Next\n          </n-button>\n        </div>\n      </n-step>\n    </n-steps>\n    <n-radio-group v-model:value=\"currentStatus\" size=\"medium\" name=\"basic\">\n      <n-radio-button value=\"error\">\n        Error\n      </n-radio-button>\n      <n-radio-button value=\"process\">\n        Process\n      </n-radio-button>\n      <n-radio-button value=\"wait\">\n        Wait\n      </n-radio-button>\n      <n-radio-button value=\"finish\">\n        Finish\n      </n-radio-button>\n    </n-radio-group>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/steps/demos/enUS/custom-icon.demo.vue",
    "content": "<markdown>\n# Customizing icon\n\n`'finish'` and `'error'` states icon or index icon can be customized.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { StepsProps } from 'naive-ui'\nimport {\n  MdArrowRoundBack,\n  MdArrowRoundForward,\n  MdCafe,\n  MdHappy,\n  MdSad\n} from '@vicons/ionicons4'\nimport { ref } from 'vue'\n\nconst currentRef = ref<number | null>(1)\nconst currentStatus = ref<StepsProps['status']>('finish')\nconst current = currentRef\n\nfunction next() {\n  if (currentRef.value === null)\n    currentRef.value = 1\n  else if (currentRef.value >= 4)\n    currentRef.value = null\n  else currentRef.value++\n}\n\nfunction prev() {\n  if (currentRef.value === 0)\n    currentRef.value = null\n  else if (currentRef.value === null)\n    currentRef.value = 4\n  else currentRef.value--\n}\n</script>\n\n<template>\n  <n-space vertical>\n    <n-steps :current=\"current as number\" :status=\"currentStatus\">\n      <template #finish-icon>\n        <n-icon>\n          <MdHappy />\n        </n-icon>\n      </template>\n      <template #error-icon>\n        <n-icon>\n          <MdSad />\n        </n-icon>\n      </template>\n      <n-step\n        title=\"I Me Mine\"\n        description=\"All through the day, I me mine I me mine, I me mine\"\n      />\n      <n-step\n        title=\"Let It Be\"\n        description=\"When I find myself in times of trouble Mother Mary comes to me\"\n      />\n      <n-step\n        title=\"Come Together\"\n        description=\"Here come old flat top He come grooving up slowly\"\n      />\n      <n-step\n        title=\"Something\"\n        description=\"Something in the way she moves Attracts me like no other lover\"\n      >\n        <template #icon>\n          <n-icon>\n            <MdCafe />\n          </n-icon>\n        </template>\n      </n-step>\n    </n-steps>\n    <n-space>\n      <n-button-group>\n        <n-button @click=\"prev\">\n          <template #icon>\n            <n-icon>\n              <MdArrowRoundBack />\n            </n-icon>\n          </template>\n        </n-button>\n        <n-button @click=\"next\">\n          <template #icon>\n            <n-icon>\n              <MdArrowRoundForward />\n            </n-icon>\n          </template>\n        </n-button>\n      </n-button-group>\n      <n-radio-group v-model:value=\"currentStatus\" size=\"medium\" name=\"basic\">\n        <n-radio-button value=\"error\">\n          Error\n        </n-radio-button>\n        <n-radio-button value=\"process\">\n          Process\n        </n-radio-button>\n        <n-radio-button value=\"wait\">\n          Wait\n        </n-radio-button>\n        <n-radio-button value=\"finish\">\n          Finish\n        </n-radio-button>\n      </n-radio-group>\n    </n-space>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/steps/demos/enUS/index.demo-entry.md",
    "content": "# Steps\n\n<!--single-column-->\n\n1, 2, 3... done!\n\n## Demos\n\n```demo\nbasic.vue\nsize.vue\nvertical.vue\ncontent-placement.vue\ncontent.vue\ncustom-icon.vue\nclick.vue\n```\n\n## API\n\n### Steps Props\n\n| Name | Type | Default | Description | Version |\n| --- | --- | --- | --- | --- |\n| content-placement | `'right' \\| 'bottom'` | `right` | Steps content placement, only can be used in horizontal mode. | 2.43.2 |\n| current | `number` | `undefined` | Currently active step index. |  |\n| size | `'small' \\| 'medium'` | `'medium'` | Steps size. |  |\n| status | `'process' \\| 'finish' \\| 'error' \\| 'wait'` | `'process'` | Steps status. |  |\n| vertical | `boolean` | `false` | Steps vertical. |  |\n| on-update:current | `(index: number) => void` | `undefined` | Callback on currently active step index changed. If it's set, step can be switched by click. | 2.29.1 |\n\n### Step Props\n\n| Name | Type | Default | Description | Version |\n| --- | --- | --- | --- | --- |\n| description | `string` | `undefined` | Step description. |  |\n| disabled | `boolean` | `false` | Whether it's clickable. | 2.29.1 |\n| status | `'process' \\| 'finish' \\| 'error' \\| 'wait'` | `undefined` | Step status. |  |\n| title | `string` | `undefined` | Step title. |  |\n\n### Steps Slots\n\n| Name        | Parameters | Description                      |\n| ----------- | ---------- | -------------------------------- |\n| default     | `()`       | Steps content.                   |\n| finish-icon | `()`       | `'finish'` status button deploy. |\n| error-icon  | `()`       | `'error'` status button deploy.  |\n\n### Step Slots\n\n| Name    | Parameters | Description   | Version |\n| ------- | ---------- | ------------- | ------- |\n| default | `()`       | Step content. |         |\n| icon    | `()`       | Step icon.    | 2.26.1  |\n| title   | `()`       | Step title.   |         |\n"
  },
  {
    "path": "src/steps/demos/enUS/size.demo.vue",
    "content": "<markdown>\n# Size\n\nSteps has `small`, `medium` size.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { StepsProps } from 'naive-ui'\nimport { MdArrowRoundBack, MdArrowRoundForward } from '@vicons/ionicons4'\nimport { ref } from 'vue'\n\nconst currentRef = ref<number | null>(1)\nconst currentStatus = ref<StepsProps['status']>('process')\nconst current = currentRef\n\nfunction next() {\n  if (currentRef.value === null)\n    currentRef.value = 1\n  else if (currentRef.value >= 4)\n    currentRef.value = null\n  else currentRef.value++\n}\n\nfunction prev() {\n  if (currentRef.value === 0)\n    currentRef.value = null\n  else if (currentRef.value === null)\n    currentRef.value = 4\n  else currentRef.value--\n}\n</script>\n\n<template>\n  <n-space vertical>\n    <n-steps size=\"small\" :current=\"current as number\" :status=\"currentStatus\">\n      <n-step\n        title=\"I Me Mine\"\n        description=\"All through the day, I me mine I me mine, I me mine\"\n      />\n      <n-step\n        title=\"Let It Be\"\n        description=\"When I find myself in times of trouble Mother Mary comes to me\"\n      />\n      <n-step\n        title=\"Come Together\"\n        description=\"Here come old flat top He come grooving up slowly\"\n      />\n      <n-step\n        title=\"Something\"\n        description=\"Something in the way she moves Attracts me like no other lover\"\n      />\n    </n-steps>\n    <n-space>\n      <n-button-group>\n        <n-button @click=\"prev\">\n          <template #icon>\n            <n-icon>\n              <MdArrowRoundBack />\n            </n-icon>\n          </template>\n        </n-button>\n        <n-button @click=\"next\">\n          <template #icon>\n            <n-icon>\n              <MdArrowRoundForward />\n            </n-icon>\n          </template>\n        </n-button>\n      </n-button-group>\n      <n-radio-group v-model:value=\"currentStatus\" size=\"medium\" name=\"size\">\n        <n-radio-button value=\"error\">\n          Error\n        </n-radio-button>\n        <n-radio-button value=\"process\">\n          Process\n        </n-radio-button>\n        <n-radio-button value=\"wait\">\n          Wait\n        </n-radio-button>\n        <n-radio-button value=\"finish\">\n          Finish\n        </n-radio-button>\n      </n-radio-group>\n    </n-space>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/steps/demos/enUS/vertical.demo.vue",
    "content": "<markdown>\n# Vertical\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { StepsProps } from 'naive-ui'\nimport { MdArrowRoundBack, MdArrowRoundForward } from '@vicons/ionicons4'\nimport { ref } from 'vue'\n\nconst currentRef = ref<number | null>(1)\nconst currentStatus = ref<StepsProps['status']>('process')\nconst current = currentRef\n\nfunction next() {\n  if (currentRef.value === null)\n    currentRef.value = 1\n  else if (currentRef.value >= 5)\n    currentRef.value = null\n  else currentRef.value++\n}\n\nfunction prev() {\n  if (currentRef.value === 0)\n    currentRef.value = null\n  else if (currentRef.value === null)\n    currentRef.value = 5\n  else currentRef.value--\n}\n</script>\n\n<template>\n  <n-space vertical>\n    <n-steps vertical :current=\"current as number\" :status=\"currentStatus\">\n      <n-step\n        title=\"I Me Mine\"\n        description=\"All through the day, I me mine I me mine, I me mine\"\n      />\n      <n-step\n        title=\"Let It Be\"\n        description=\"When I find myself in times of trouble Mother Mary comes to me\"\n      />\n      <n-step title=\"Break\" />\n      <n-step\n        title=\"Come Together\"\n        description=\"Here come old flat top He come grooving up slowly\"\n      />\n      <n-step\n        title=\"Something\"\n        description=\"Something in the way she moves Attracts me like no other lover\"\n      />\n    </n-steps>\n    <n-space>\n      <n-button-group>\n        <n-button @click=\"prev\">\n          <template #icon>\n            <n-icon>\n              <MdArrowRoundBack />\n            </n-icon>\n          </template>\n        </n-button>\n        <n-button @click=\"next\">\n          <template #icon>\n            <n-icon>\n              <MdArrowRoundForward />\n            </n-icon>\n          </template>\n        </n-button>\n      </n-button-group>\n      <n-radio-group\n        v-model:value=\"currentStatus\"\n        size=\"medium\"\n        name=\"vertical\"\n      >\n        <n-radio-button value=\"error\">\n          Error\n        </n-radio-button>\n        <n-radio-button value=\"process\">\n          Process\n        </n-radio-button>\n        <n-radio-button value=\"wait\">\n          Wait\n        </n-radio-button>\n        <n-radio-button value=\"finish\">\n          Finish\n        </n-radio-button>\n      </n-radio-group>\n    </n-space>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/steps/demos/zhCN/basic.demo.vue",
    "content": "<markdown>\n# 基础用法\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { StepsProps } from 'naive-ui'\nimport { MdArrowRoundBack, MdArrowRoundForward } from '@vicons/ionicons4'\nimport { ref } from 'vue'\n\nconst currentRef = ref<number | null>(1)\nconst currentStatus = ref<StepsProps['status']>('process')\nconst current = currentRef\n\nfunction next() {\n  if (currentRef.value === null)\n    currentRef.value = 1\n  else if (currentRef.value >= 4)\n    currentRef.value = null\n  else currentRef.value++\n}\n\nfunction prev() {\n  if (currentRef.value === 0)\n    currentRef.value = null\n  else if (currentRef.value === null)\n    currentRef.value = 4\n  else currentRef.value--\n}\n</script>\n\n<template>\n  <n-space vertical>\n    <n-steps :current=\"current as number\" :status=\"currentStatus\">\n      <n-step\n        title=\"I Me Mine\"\n        description=\"All through the day, I me mine I me mine, I me mine\"\n      />\n      <n-step\n        title=\"Let It Be\"\n        description=\"When I find myself in times of trouble Mother Mary comes to me\"\n      />\n      <n-step\n        title=\"Come Together\"\n        description=\"Here come old flat top He come grooving up slowly\"\n      />\n      <n-step\n        title=\"Something\"\n        description=\"Something in the way she moves Attracts me like no other lover\"\n      />\n    </n-steps>\n    <n-space>\n      <n-button-group>\n        <n-button @click=\"prev\">\n          <template #icon>\n            <n-icon>\n              <MdArrowRoundBack />\n            </n-icon>\n          </template>\n        </n-button>\n        <n-button @click=\"next\">\n          <template #icon>\n            <n-icon>\n              <MdArrowRoundForward />\n            </n-icon>\n          </template>\n        </n-button>\n      </n-button-group>\n      <n-radio-group v-model:value=\"currentStatus\" size=\"medium\" name=\"basic\">\n        <n-radio-button value=\"error\">\n          Error\n        </n-radio-button>\n        <n-radio-button value=\"process\">\n          Process\n        </n-radio-button>\n        <n-radio-button value=\"wait\">\n          Wait\n        </n-radio-button>\n        <n-radio-button value=\"finish\">\n          Finish\n        </n-radio-button>\n      </n-radio-group>\n    </n-space>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/steps/demos/zhCN/click.demo.vue",
    "content": "<markdown>\n# 点击切换\n\n当设定 `@update:current` 时，可以通过点击切换步骤。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst currentRef = ref<number | undefined>(1)\nconst current = currentRef\n</script>\n\n<template>\n  <n-steps v-model:current=\"current\">\n    <n-step\n      title=\"I Me Mine\"\n      description=\"All through the day, I me mine I me mine, I me mine\"\n    />\n    <n-step\n      title=\"Let It Be\"\n      description=\"When I find myself in times of trouble Mother Mary comes to me\"\n    />\n    <n-step\n      title=\"Come Together\"\n      description=\"Here come old flat top He come grooving up slowly\"\n    />\n    <n-step\n      disabled\n      title=\"Something\"\n      description=\"Something in the way she moves Attracts me like no other lover\"\n    />\n  </n-steps>\n</template>\n"
  },
  {
    "path": "src/steps/demos/zhCN/content-placement.demo.vue",
    "content": "<markdown>\n# 内容位置\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { StepsProps } from 'naive-ui'\nimport { MdArrowRoundBack, MdArrowRoundForward } from '@vicons/ionicons4'\nimport { ref } from 'vue'\n\nconst currentRef = ref<number | null>(1)\nconst currentStatus = ref<StepsProps['status']>('process')\nconst contentPlacement = ref<StepsProps['contentPlacement']>('bottom')\nconst current = currentRef\n\nfunction next() {\n  if (currentRef.value === null)\n    currentRef.value = 1\n  else if (currentRef.value >= 4)\n    currentRef.value = null\n  else currentRef.value++\n}\n\nfunction prev() {\n  if (currentRef.value === 0)\n    currentRef.value = null\n  else if (currentRef.value === null)\n    currentRef.value = 4\n  else currentRef.value--\n}\n\nfunction right() {\n  contentPlacement.value = 'right'\n}\n\nfunction bottom() {\n  contentPlacement.value = 'bottom'\n}\n</script>\n\n<template>\n  <n-space vertical>\n    <n-steps\n      :content-placement=\"contentPlacement\"\n      :current=\"current as number\"\n      :status=\"currentStatus\"\n    >\n      <n-step\n        title=\"I Me Mine\"\n        description=\"All through the day, I me mine I me mine, I me mine\"\n      />\n      <n-step\n        title=\"Let It Be\"\n        description=\"When I find myself in times of trouble Mother Mary comes to me\"\n      />\n      <n-step\n        title=\"Come Together\"\n        description=\"Here come old flat top He come grooving up slowly\"\n      />\n      <n-step\n        title=\"Something\"\n        description=\"Something in the way she moves Attracts me like no other lover\"\n      />\n    </n-steps>\n    <n-space>\n      <n-radio-group v-model:value=\"contentPlacement\">\n        <n-radio-button value=\"right\" @click=\"right\">\n          Right\n        </n-radio-button>\n        <n-radio-button value=\"bottom\" @click=\"bottom\">\n          Bottom\n        </n-radio-button>\n      </n-radio-group>\n      <n-button-group>\n        <n-button @click=\"prev\">\n          <template #icon>\n            <n-icon>\n              <MdArrowRoundBack />\n            </n-icon>\n          </template>\n        </n-button>\n        <n-button @click=\"next\">\n          <template #icon>\n            <n-icon>\n              <MdArrowRoundForward />\n            </n-icon>\n          </template>\n        </n-button>\n      </n-button-group>\n      <n-radio-group v-model:value=\"currentStatus\" size=\"medium\" name=\"basic\">\n        <n-radio-button value=\"error\">\n          Error\n        </n-radio-button>\n        <n-radio-button value=\"process\">\n          Process\n        </n-radio-button>\n        <n-radio-button value=\"wait\">\n          Wait\n        </n-radio-button>\n        <n-radio-button value=\"finish\">\n          Finish\n        </n-radio-button>\n      </n-radio-group>\n    </n-space>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/steps/demos/zhCN/content.demo.vue",
    "content": "<markdown>\n# 使用 Step 的 Slot\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { StepsProps } from 'naive-ui'\nimport { computed, ref } from 'vue'\n\nconst currentRef = ref(1)\nconst currentStatusRef = ref<StepsProps['status']>('process')\n\nconst buttonTypeRef = computed(() => {\n  switch (currentStatusRef.value) {\n    case 'error':\n      return 'error'\n    case 'finish':\n      return 'success'\n    default:\n      return 'default'\n  }\n})\n\nconst current = currentRef\nconst currentStatus = currentStatusRef\nconst buttonType = buttonTypeRef\n\nfunction handleButtonClick() {\n  currentRef.value = (currentRef.value % 4) + 1\n}\n</script>\n\n<template>\n  <n-space vertical>\n    <n-steps :current=\"current\" :status=\"currentStatus\">\n      <n-step title=\"I Me Mine\">\n        <div class=\"n-step-description\">\n          <p>Al through the day, I me mine I me mine, I me mine</p>\n          <n-button\n            v-if=\"current === 1\"\n            :type=\"buttonType\"\n            size=\"small\"\n            @click=\"handleButtonClick\"\n          >\n            Next\n          </n-button>\n        </div>\n      </n-step>\n      <n-step title=\"Let It Be\">\n        <div class=\"n-step-description\">\n          <p>When I find myself in times of trouble Mother Mary comes to me</p>\n          <n-button\n            v-if=\"current === 2\"\n            :type=\"buttonType\"\n            size=\"small\"\n            @click=\"handleButtonClick\"\n          >\n            Next\n          </n-button>\n        </div>\n      </n-step>\n      <n-step title=\"Come Together\">\n        <div class=\"n-step-description\">\n          <p>Here come old flat top He come grooving up slowly</p>\n          <n-button\n            v-if=\"current === 3\"\n            :type=\"buttonType\"\n            size=\"small\"\n            @click=\"handleButtonClick\"\n          >\n            Next\n          </n-button>\n        </div>\n      </n-step>\n      <n-step title=\"Something\">\n        <div class=\"n-step-description\">\n          <p>Something in the way she moves Attracts me like no other lover</p>\n          <n-button\n            v-if=\"current === 4\"\n            :type=\"buttonType\"\n            size=\"small\"\n            @click=\"handleButtonClick\"\n          >\n            Next\n          </n-button>\n        </div>\n      </n-step>\n    </n-steps>\n    <n-radio-group v-model:value=\"currentStatus\" size=\"medium\" name=\"basic\">\n      <n-radio-button value=\"error\">\n        Error\n      </n-radio-button>\n      <n-radio-button value=\"process\">\n        Process\n      </n-radio-button>\n      <n-radio-button value=\"wait\">\n        Wait\n      </n-radio-button>\n      <n-radio-button value=\"finish\">\n        Finish\n      </n-radio-button>\n    </n-radio-group>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/steps/demos/zhCN/custom-icon.demo.vue",
    "content": "<markdown>\n# 定制图标\n\n可以定制 `'finish'` 和 `'error'` 状态下的图标和每一步的图标。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { StepsProps } from 'naive-ui'\nimport {\n  MdArrowRoundBack,\n  MdArrowRoundForward,\n  MdCafe,\n  MdHappy,\n  MdSad\n} from '@vicons/ionicons4'\nimport { ref } from 'vue'\n\nconst currentRef = ref<number | null>(1)\nconst currentStatus = ref<StepsProps['status']>('finish')\nconst current = currentRef\n\nfunction next() {\n  if (currentRef.value === null)\n    currentRef.value = 1\n  else if (currentRef.value >= 4)\n    currentRef.value = null\n  else currentRef.value++\n}\n\nfunction prev() {\n  if (currentRef.value === 0)\n    currentRef.value = null\n  else if (currentRef.value === null)\n    currentRef.value = 4\n  else currentRef.value--\n}\n</script>\n\n<template>\n  <n-space vertical>\n    <n-steps :current=\"current as number\" :status=\"currentStatus\">\n      <template #finish-icon>\n        <n-icon>\n          <MdHappy />\n        </n-icon>\n      </template>\n      <template #error-icon>\n        <n-icon>\n          <MdSad />\n        </n-icon>\n      </template>\n      <n-step\n        title=\"I Me Mine\"\n        description=\"All through the day, I me mine I me mine, I me mine\"\n      />\n      <n-step\n        title=\"Let It Be\"\n        description=\"When I find myself in times of trouble Mother Mary comes to me\"\n      />\n      <n-step\n        title=\"Come Together\"\n        description=\"Here come old flat top He come grooving up slowly\"\n      />\n      <n-step\n        title=\"Something\"\n        description=\"Something in the way she moves Attracts me like no other lover\"\n      >\n        <template #icon>\n          <n-icon>\n            <MdCafe />\n          </n-icon>\n        </template>\n      </n-step>\n    </n-steps>\n    <n-space>\n      <n-button-group>\n        <n-button @click=\"prev\">\n          <template #icon>\n            <n-icon>\n              <MdArrowRoundBack />\n            </n-icon>\n          </template>\n        </n-button>\n        <n-button @click=\"next\">\n          <template #icon>\n            <n-icon>\n              <MdArrowRoundForward />\n            </n-icon>\n          </template>\n        </n-button>\n      </n-button-group>\n      <n-radio-group v-model:value=\"currentStatus\" size=\"medium\" name=\"basic\">\n        <n-radio-button value=\"error\">\n          Error\n        </n-radio-button>\n        <n-radio-button value=\"process\">\n          Process\n        </n-radio-button>\n        <n-radio-button value=\"wait\">\n          Wait\n        </n-radio-button>\n        <n-radio-button value=\"finish\">\n          Finish\n        </n-radio-button>\n      </n-radio-group>\n    </n-space>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/steps/demos/zhCN/index.demo-entry.md",
    "content": "# 步骤 Steps\n\n<!--single-column-->\n\n1、2、3...成了！\n\n## 演示\n\n```demo\nbasic.vue\nsize.vue\nvertical.vue\ncontent-placement.vue\ncontent.vue\ncustom-icon.vue\nclick.vue\nvertical-debug.vue\nrtl-debug.vue\n```\n\n## API\n\n### Steps Props\n\n| 名称 | 类型 | 默认值 | 说明 | 版本 |\n| --- | --- | --- | --- | --- |\n| content-placement | `'right' \\| 'bottom'` | `right` | 步骤条内容位置，仅在横向模式下生效 | 2.43.2 |\n| current | `number` | `undefined` | 当前选中在第几步 |  |\n| size | `'small' \\| 'medium'` | `'medium'` | 步骤条大小 |  |\n| status | `'process' \\| 'finish' \\| 'error' \\| 'wait'` | `'process'` | 步骤条状态 |  |\n| vertical | `boolean` | `false` | 步骤条方向 |  |\n| on-update:current | `(index: number) => void` | `undefined` | 更新当前第几步的回调，设定后可点击切换步骤 | 2.29.1 |\n\n### Step Props\n\n| 名称 | 类型 | 默认值 | 说明 | 版本 |\n| --- | --- | --- | --- | --- |\n| description | `string` | `undefined` | 节点描述 |  |\n| disabled | `boolean` | `false` | 是否可点击 | 2.29.1 |\n| status | `'process' \\| 'finish' \\| 'error' \\| 'wait'` | `undefined` | 节点状态 |  |\n| title | `string` | `undefined` | 节点标题 |  |\n\n### Steps Slots\n\n| 名称        | 参数 | 说明                    |\n| ----------- | ---- | ----------------------- |\n| default     | `()` | 步骤条内容              |\n| finish-icon | `()` | `'finish'` 状态按钮配置 |\n| error-icon  | `()` | `'error'` 状态按钮配置  |\n\n### Step Slots\n\n| 名称    | 参数 | 说明         | 版本   |\n| ------- | ---- | ------------ | ------ |\n| default | `()` | 步骤节点内容 |        |\n| icon    | `()` | 步骤节点图标 | 2.26.1 |\n| title   | `()` | 步骤节点标题 |        |\n"
  },
  {
    "path": "src/steps/demos/zhCN/rtl-debug.demo.vue",
    "content": "<markdown>\n# Rtl Debug\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { StepsProps } from 'naive-ui'\nimport { MdArrowRoundBack, MdArrowRoundForward } from '@vicons/ionicons4'\nimport { unstableStepsRtl } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst currentRef = ref<number | null>(1)\nconst rtlEnabled = ref(false)\nconst rtlStyles = [unstableStepsRtl]\nconst currentStatus = ref<StepsProps['status']>('process')\nconst current = currentRef\n\nfunction next() {\n  if (currentRef.value === null)\n    currentRef.value = 1\n  else if (currentRef.value >= 4)\n    currentRef.value = null\n  else currentRef.value++\n}\n\nfunction prev() {\n  if (currentRef.value === 0)\n    currentRef.value = null\n  else if (currentRef.value === null)\n    currentRef.value = 4\n  else currentRef.value--\n}\n</script>\n\n<template>\n  <n-space vertical>\n    <n-space><n-switch v-model:value=\"rtlEnabled\" />Rtl</n-space>\n    <n-config-provider :rtl=\"rtlEnabled ? rtlStyles : undefined\">\n      <n-space vertical>\n        <n-steps :current=\"current as number\" :status=\"currentStatus\">\n          <n-step\n            title=\"I Me Mine\"\n            description=\"All through the day, I me mine I me mine, I me mine\"\n          />\n          <n-step\n            title=\"Let It Be\"\n            description=\"When I find myself in times of trouble Mother Mary comes to me\"\n          />\n          <n-step\n            title=\"Come Together\"\n            description=\"Here come old flat top He come grooving up slowly\"\n          />\n          <n-step\n            title=\"Something\"\n            description=\"Something in the way she moves Attracts me like no other lover\"\n          />\n        </n-steps>\n        <n-space>\n          <n-button-group>\n            <n-button @click=\"prev\">\n              <template #icon>\n                <n-icon>\n                  <MdArrowRoundBack />\n                </n-icon>\n              </template>\n            </n-button>\n            <n-button @click=\"next\">\n              <template #icon>\n                <n-icon>\n                  <MdArrowRoundForward />\n                </n-icon>\n              </template>\n            </n-button>\n          </n-button-group>\n          <n-radio-group\n            v-model:value=\"currentStatus\"\n            size=\"medium\"\n            name=\"basic\"\n          >\n            <n-radio-button value=\"error\">\n              Error\n            </n-radio-button>\n            <n-radio-button value=\"process\">\n              Process\n            </n-radio-button>\n            <n-radio-button value=\"wait\">\n              Wait\n            </n-radio-button>\n            <n-radio-button value=\"finish\">\n              Finish\n            </n-radio-button>\n          </n-radio-group>\n        </n-space>\n      </n-space>\n    </n-config-provider>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/steps/demos/zhCN/size.demo.vue",
    "content": "<markdown>\n# 尺寸\n\n有 `small` 和 `medium` 大小。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { StepsProps } from 'naive-ui'\nimport { MdArrowRoundBack, MdArrowRoundForward } from '@vicons/ionicons4'\nimport { ref } from 'vue'\n\nconst currentRef = ref<number | null>(1)\nconst currentStatus = ref<StepsProps['status']>('process')\nconst current = currentRef\n\nfunction next() {\n  if (currentRef.value === null)\n    currentRef.value = 1\n  else if (currentRef.value >= 4)\n    currentRef.value = null\n  else currentRef.value++\n}\n\nfunction prev() {\n  if (currentRef.value === 0)\n    currentRef.value = null\n  else if (currentRef.value === null)\n    currentRef.value = 4\n  else currentRef.value--\n}\n</script>\n\n<template>\n  <n-space vertical>\n    <n-steps size=\"small\" :current=\"current as number\" :status=\"currentStatus\">\n      <n-step\n        title=\"I Me Mine\"\n        description=\"All through the day, I me mine I me mine, I me mine\"\n      />\n      <n-step\n        title=\"Let It Be\"\n        description=\"When I find myself in times of trouble Mother Mary comes to me\"\n      />\n      <n-step\n        title=\"Come Together\"\n        description=\"Here come old flat top He come grooving up slowly\"\n      />\n      <n-step\n        title=\"Something\"\n        description=\"Something in the way she moves Attracts me like no other lover\"\n      />\n    </n-steps>\n    <n-space>\n      <n-button-group>\n        <n-button @click=\"prev\">\n          <template #icon>\n            <n-icon>\n              <MdArrowRoundBack />\n            </n-icon>\n          </template>\n        </n-button>\n        <n-button @click=\"next\">\n          <template #icon>\n            <n-icon>\n              <MdArrowRoundForward />\n            </n-icon>\n          </template>\n        </n-button>\n      </n-button-group>\n      <n-radio-group v-model:value=\"currentStatus\" size=\"medium\" name=\"size\">\n        <n-radio-button value=\"error\">\n          Error\n        </n-radio-button>\n        <n-radio-button value=\"process\">\n          Process\n        </n-radio-button>\n        <n-radio-button value=\"wait\">\n          Wait\n        </n-radio-button>\n        <n-radio-button value=\"finish\">\n          Finish\n        </n-radio-button>\n      </n-radio-group>\n    </n-space>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/steps/demos/zhCN/vertical-debug.demo.vue",
    "content": "<markdown>\n# 垂直 debug\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { StepsProps } from 'naive-ui'\nimport { MdArrowRoundBack, MdArrowRoundForward } from '@vicons/ionicons4'\nimport { ref } from 'vue'\n\nconst currentRef = ref<number | null>(1)\nconst currentStatus = ref<StepsProps['status']>('process')\nconst current = currentRef\n\nfunction next() {\n  if (currentRef.value === null)\n    currentRef.value = 1\n  else if (currentRef.value >= 5)\n    currentRef.value = null\n  else currentRef.value++\n}\n\nfunction prev() {\n  if (currentRef.value === 0)\n    currentRef.value = null\n  else if (currentRef.value === null)\n    currentRef.value = 5\n  else currentRef.value--\n}\n</script>\n\n<template>\n  <n-space vertical>\n    <n-steps vertical :current=\"current as number\" :status=\"currentStatus\">\n      <n-step\n        title=\"I Me Mine\"\n        description=\"All through the day, I me mine I me mine, I me mine\"\n      >\n        <n-steps :current=\"current as number\" :status=\"currentStatus\">\n          <n-step\n            title=\"I Me Mine\"\n            description=\"All through the day, I me mine I me mine, I me mine\"\n          />\n          <n-step\n            title=\"Let It Be\"\n            description=\"When I find myself in times of trouble Mother Mary comes to me\"\n          />\n          <n-step title=\"Break\" />\n          <n-step\n            title=\"Come Together\"\n            description=\"Here come old flat top He come grooving up slowly\"\n          />\n          <n-step\n            title=\"Something\"\n            description=\"Something in the way she moves Attracts me like no other lover\"\n          />\n        </n-steps>\n      </n-step>\n      <n-step\n        title=\"Let It Be\"\n        description=\"When I find myself in times of trouble Mother Mary comes to me\"\n      />\n      <n-step title=\"Break\" />\n      <n-step\n        title=\"Come Together\"\n        description=\"Here come old flat top He come grooving up slowly\"\n      />\n      <n-step\n        title=\"Something\"\n        description=\"Something in the way she moves Attracts me like no other lover\"\n      />\n    </n-steps>\n    <n-space>\n      <n-button-group>\n        <n-button @click=\"prev\">\n          <template #icon>\n            <n-icon>\n              <MdArrowRoundBack />\n            </n-icon>\n          </template>\n        </n-button>\n        <n-button @click=\"next\">\n          <template #icon>\n            <n-icon>\n              <MdArrowRoundForward />\n            </n-icon>\n          </template>\n        </n-button>\n      </n-button-group>\n      <n-radio-group\n        v-model:value=\"currentStatus\"\n        size=\"medium\"\n        name=\"vertical\"\n      >\n        <n-radio-button value=\"error\">\n          Error\n        </n-radio-button>\n        <n-radio-button value=\"process\">\n          Process\n        </n-radio-button>\n        <n-radio-button value=\"wait\">\n          Wait\n        </n-radio-button>\n        <n-radio-button value=\"finish\">\n          Finish\n        </n-radio-button>\n      </n-radio-group>\n    </n-space>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/steps/demos/zhCN/vertical.demo.vue",
    "content": "<markdown>\n# 垂直\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { StepsProps } from 'naive-ui'\nimport { MdArrowRoundBack, MdArrowRoundForward } from '@vicons/ionicons4'\nimport { ref } from 'vue'\n\nconst currentRef = ref<number | null>(1)\nconst currentStatus = ref<StepsProps['status']>('process')\nconst current = currentRef\n\nfunction next() {\n  if (currentRef.value === null)\n    currentRef.value = 1\n  else if (currentRef.value >= 5)\n    currentRef.value = null\n  else currentRef.value++\n}\n\nfunction prev() {\n  if (currentRef.value === 0)\n    currentRef.value = null\n  else if (currentRef.value === null)\n    currentRef.value = 5\n  else currentRef.value--\n}\n</script>\n\n<template>\n  <n-space vertical>\n    <n-steps vertical :current=\"current as number\" :status=\"currentStatus\">\n      <n-step\n        title=\"I Me Mine\"\n        description=\"All through the day, I me mine I me mine, I me mine\"\n      />\n      <n-step\n        title=\"Let It Be\"\n        description=\"When I find myself in times of trouble Mother Mary comes to me\"\n      />\n      <n-step title=\"Break\" />\n      <n-step\n        title=\"Come Together\"\n        description=\"Here come old flat top He come grooving up slowly\"\n      />\n      <n-step\n        title=\"Something\"\n        description=\"Something in the way she moves Attracts me like no other lover\"\n      />\n    </n-steps>\n    <n-space>\n      <n-button-group>\n        <n-button @click=\"prev\">\n          <template #icon>\n            <n-icon>\n              <MdArrowRoundBack />\n            </n-icon>\n          </template>\n        </n-button>\n        <n-button @click=\"next\">\n          <template #icon>\n            <n-icon>\n              <MdArrowRoundForward />\n            </n-icon>\n          </template>\n        </n-button>\n      </n-button-group>\n      <n-radio-group\n        v-model:value=\"currentStatus\"\n        size=\"medium\"\n        name=\"vertical\"\n      >\n        <n-radio-button value=\"error\">\n          Error\n        </n-radio-button>\n        <n-radio-button value=\"process\">\n          Process\n        </n-radio-button>\n        <n-radio-button value=\"wait\">\n          Wait\n        </n-radio-button>\n        <n-radio-button value=\"finish\">\n          Finish\n        </n-radio-button>\n      </n-radio-group>\n    </n-space>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/steps/index.ts",
    "content": "export { default as NStep, stepProps } from './src/Step'\nexport type { StepProps, StepSlots } from './src/Step'\nexport { default as NSteps, stepsProps } from './src/Steps'\nexport type { StepsProps, StepsSlots } from './src/Steps'\n"
  },
  {
    "path": "src/steps/src/Step.tsx",
    "content": "import type { CSSProperties, PropType, SlotsType, VNode } from 'vue'\nimport type { ExtractPublicPropTypes } from '../../_utils'\nimport { computed, defineComponent, Fragment, h, inject, toRef } from 'vue'\nimport { NBaseIcon, NIconSwitchTransition } from '../../_internal'\nimport {\n  CloseIcon as ErrorIcon,\n  CheckmarkIcon as FinishedIcon\n} from '../../_internal/icons'\nimport { useConfig, useThemeClass } from '../../_mixins'\nimport {\n  call,\n  createKey,\n  resolveSlot,\n  resolveWrappedSlot,\n  throwError\n} from '../../_utils'\nimport { stepsInjectionKey } from './Steps'\n\nexport const stepProps = {\n  status: String as PropType<'process' | 'finish' | 'error' | 'wait'>,\n  title: String,\n  description: String,\n  disabled: Boolean,\n  // index will be filled by parent steps, not user\n  internalIndex: {\n    type: Number,\n    default: 0\n  }\n} as const\n\nexport type StepProps = ExtractPublicPropTypes<typeof stepProps>\n\nexport interface StepSlots {\n  default?: () => VNode[]\n  icon?: () => VNode[]\n  title?: () => VNode[]\n}\n\nexport default defineComponent({\n  name: 'Step',\n  props: stepProps,\n  slots: Object as SlotsType<StepSlots>,\n  setup(props) {\n    const NSteps = inject(stepsInjectionKey, null)\n\n    if (!NSteps)\n      throwError('step', '`n-step` must be placed inside `n-steps`.')\n\n    const { inlineThemeDisabled } = useConfig()\n\n    const {\n      props: stepsProps,\n      mergedThemeRef,\n      mergedClsPrefixRef,\n      stepsSlots\n    } = NSteps\n\n    const verticalRef = toRef(stepsProps, 'vertical')\n\n    const contentPlacementRef = toRef(stepsProps, 'contentPlacement')\n\n    const mergedStatusRef = computed<'process' | 'finish' | 'error' | 'wait'>(\n      () => {\n        const { status } = props\n        if (status) {\n          return status\n        }\n        else {\n          const { internalIndex } = props\n          const { current } = stepsProps\n          if (current === undefined)\n            return 'process'\n          if (internalIndex < current) {\n            return 'finish'\n          }\n          else if (internalIndex === current) {\n            return stepsProps.status || 'process'\n          }\n          else if (internalIndex > current) {\n            return 'wait'\n          }\n        }\n        return 'process'\n      }\n    )\n    const cssVarsRef = computed(() => {\n      const { value: status } = mergedStatusRef\n      const { size } = stepsProps\n      const {\n        common: { cubicBezierEaseInOut },\n        self: {\n          stepHeaderFontWeight,\n          [createKey('stepHeaderFontSize', size)]: stepHeaderFontSize,\n          [createKey('indicatorIndexFontSize', size)]: indicatorIndexFontSize,\n          [createKey('indicatorSize', size)]: indicatorSize,\n          [createKey('indicatorIconSize', size)]: indicatorIconSize,\n          [createKey('indicatorTextColor', status)]: indicatorTextColor,\n          [createKey('indicatorBorderColor', status)]: indicatorBorderColor,\n          [createKey('headerTextColor', status)]: headerTextColor,\n          [createKey('splitorColor', status)]: splitorColor,\n          [createKey('indicatorColor', status)]: indicatorColor,\n          [createKey('descriptionTextColor', status)]: descriptionTextColor\n        }\n      } = mergedThemeRef.value\n      return {\n        '--n-bezier': cubicBezierEaseInOut,\n        '--n-description-text-color': descriptionTextColor,\n        '--n-header-text-color': headerTextColor,\n        '--n-indicator-border-color': indicatorBorderColor,\n        '--n-indicator-color': indicatorColor,\n        '--n-indicator-icon-size': indicatorIconSize,\n        '--n-indicator-index-font-size': indicatorIndexFontSize,\n        '--n-indicator-size': indicatorSize,\n        '--n-indicator-text-color': indicatorTextColor,\n        '--n-splitor-color': splitorColor,\n        '--n-step-header-font-size': stepHeaderFontSize,\n        '--n-step-header-font-weight': stepHeaderFontWeight\n      }\n    })\n    const themeClassHandle = inlineThemeDisabled\n      ? useThemeClass(\n          'step',\n          computed(() => {\n            const { value: status } = mergedStatusRef\n            const { size } = stepsProps\n            return `${status[0]}${size[0]}`\n          }),\n          cssVarsRef,\n          stepsProps\n        )\n      : undefined\n\n    const handleStepClick = computed((): undefined | (() => void) => {\n      if (props.disabled)\n        return undefined\n      const { onUpdateCurrent, 'onUpdate:current': _onUpdateCurrent }\n        = stepsProps\n      return onUpdateCurrent || _onUpdateCurrent\n        ? () => {\n            if (onUpdateCurrent) {\n              call(onUpdateCurrent, props.internalIndex)\n            }\n            if (_onUpdateCurrent) {\n              call(_onUpdateCurrent, props.internalIndex)\n            }\n          }\n        : undefined\n    })\n    return {\n      stepsSlots,\n      mergedClsPrefix: mergedClsPrefixRef,\n      vertical: verticalRef,\n      mergedStatus: mergedStatusRef,\n      handleStepClick,\n      cssVars: inlineThemeDisabled ? undefined : cssVarsRef,\n      themeClass: themeClassHandle?.themeClass,\n      onRender: themeClassHandle?.onRender,\n      contentPlacement: contentPlacementRef\n    }\n  },\n  render() {\n    const {\n      mergedClsPrefix,\n      onRender,\n      handleStepClick,\n      disabled,\n      contentPlacement,\n      vertical\n    } = this\n    const descriptionNode = resolveWrappedSlot(\n      this.$slots.default,\n      (children) => {\n        const mergedDescription = children || this.description\n        if (mergedDescription) {\n          return (\n            <div class={`${mergedClsPrefix}-step-content__description`}>\n              {mergedDescription}\n            </div>\n          )\n        }\n        return null\n      }\n    )\n    const splitorNode = <div class={`${mergedClsPrefix}-step-splitor`} />\n\n    const indicatorNode = (\n      // We need a key here to prevent reconcile progress from affecting styling.\n      // A DOM can be reused so if it is used both for A component & B component,\n      // the styling transition bewteen two components may be incorrect.\n      <div class={`${mergedClsPrefix}-step-indicator`} key={contentPlacement}>\n        <div class={`${mergedClsPrefix}-step-indicator-slot`}>\n          <NIconSwitchTransition>\n            {{\n              default: () => {\n                return resolveWrappedSlot(this.$slots.icon, (icon) => {\n                  const { mergedStatus, stepsSlots } = this\n                  return !(\n                    mergedStatus === 'finish' || mergedStatus === 'error'\n                  ) ? (\n                        icon || (\n                          <div\n                            key={this.internalIndex}\n                            class={`${mergedClsPrefix}-step-indicator-slot__index`}\n                          >\n                            {this.internalIndex}\n                          </div>\n                        )\n                      ) : mergedStatus === 'finish' ? (\n                        <NBaseIcon clsPrefix={mergedClsPrefix} key=\"finish\">\n                          {{\n                            default: () =>\n                              resolveSlot(stepsSlots['finish-icon'], () => [\n                                <FinishedIcon />\n                              ])\n                          }}\n                        </NBaseIcon>\n                      ) : mergedStatus === 'error' ? (\n                        <NBaseIcon clsPrefix={mergedClsPrefix} key=\"error\">\n                          {{\n                            default: () =>\n                              resolveSlot(stepsSlots['error-icon'], () => [\n                                <ErrorIcon />\n                              ])\n                          }}\n                        </NBaseIcon>\n                      ) : null\n                })\n              }\n            }}\n          </NIconSwitchTransition>\n        </div>\n        {vertical ? splitorNode : null}\n      </div>\n    )\n    const contentNode = (\n      <div class={`${mergedClsPrefix}-step-content`}>\n        <div class={`${mergedClsPrefix}-step-content-header`}>\n          <div class={`${mergedClsPrefix}-step-content-header__title`}>\n            {resolveSlot(this.$slots.title, () => [this.title])}\n          </div>\n          {!vertical && contentPlacement === 'right' ? splitorNode : null}\n        </div>\n        {descriptionNode}\n      </div>\n    )\n\n    let stepNode: VNode\n    if (!vertical && contentPlacement === 'bottom') {\n      stepNode = (\n        <Fragment>\n          <div class={`${mergedClsPrefix}-step-line`}>\n            {indicatorNode}\n            {splitorNode}\n          </div>\n          {contentNode}\n        </Fragment>\n      )\n    }\n    else {\n      stepNode = (\n        <Fragment>\n          {indicatorNode}\n          {contentNode}\n        </Fragment>\n      )\n    }\n    onRender?.()\n    return (\n      <div\n        class={[\n          `${mergedClsPrefix}-step`,\n          disabled && `${mergedClsPrefix}-step--disabled`,\n          !disabled && handleStepClick && `${mergedClsPrefix}-step--clickable`,\n          this.themeClass,\n          descriptionNode && `${mergedClsPrefix}-step--show-description`,\n          `${mergedClsPrefix}-step--${this.mergedStatus}-status`\n        ]}\n        style={this.cssVars as CSSProperties}\n        onClick={handleStepClick}\n      >\n        {stepNode}\n      </div>\n    )\n  }\n})\n"
  },
  {
    "path": "src/steps/src/Steps.tsx",
    "content": "import type {\n  ExtractPropTypes,\n  PropType,\n  Ref,\n  SlotsType,\n  VNode,\n  VNodeChild\n} from 'vue'\nimport type { MergedTheme, ThemeProps } from '../../_mixins'\nimport type { ExtractPublicPropTypes, MaybeArray } from '../../_utils'\nimport type { StepsTheme } from '../styles'\nimport { defineComponent, h, provide } from 'vue'\nimport { useConfig, useRtl, useTheme } from '../../_mixins'\nimport { createInjectionKey, flatten, getSlot } from '../../_utils'\nimport { stepsLight } from '../styles'\nimport style from './styles/index.cssr'\n\nfunction stepWithIndex(step: VNodeChild, i: number): VNode | null {\n  if (typeof step !== 'object' || step === null || Array.isArray(step)) {\n    return null\n  }\n  if (!step.props)\n    step.props = {}\n  step.props.internalIndex = i + 1\n  return step\n}\n\nfunction stepsWithIndex(steps: VNodeChild[]): Array<VNode | null> {\n  return steps.map((step, i) => stepWithIndex(step, i))\n}\n\nexport const stepsProps = {\n  ...(useTheme.props as ThemeProps<StepsTheme>),\n  current: Number,\n  status: {\n    type: String as PropType<'process' | 'finish' | 'error' | 'wait'>,\n    default: 'process'\n  },\n  size: {\n    type: String as PropType<'small' | 'medium'>,\n    default: 'medium'\n  },\n  vertical: Boolean,\n  contentPlacement: {\n    type: String as PropType<'right' | 'bottom'>,\n    default: 'right'\n  },\n  'onUpdate:current': [Function, Array] as PropType<\n    MaybeArray<(current: number) => void>\n  >,\n  onUpdateCurrent: [Function, Array] as PropType<\n    MaybeArray<(current: number) => void>\n  >\n}\n\nexport interface StepsInjection {\n  props: ExtractPropTypes<typeof stepsProps>\n  mergedClsPrefixRef: Ref<string>\n  mergedThemeRef: Ref<MergedTheme<StepsTheme>>\n  stepsSlots: StepsSlots\n}\n\nexport type StepsProps = ExtractPublicPropTypes<typeof stepsProps>\n\nexport interface StepsSlots {\n  default?: () => VNode[]\n  'finish-icon'?: () => VNode[]\n  'error-icon'?: () => VNode[]\n}\n\nexport const stepsInjectionKey = createInjectionKey<StepsInjection>('n-steps')\n\nexport default defineComponent({\n  name: 'Steps',\n  props: stepsProps,\n  slots: Object as SlotsType<StepsSlots>,\n  setup(props, { slots }) {\n    const { mergedClsPrefixRef, mergedRtlRef } = useConfig(props)\n    const rtlEnabledRef = useRtl('Steps', mergedRtlRef, mergedClsPrefixRef)\n    const themeRef = useTheme(\n      'Steps',\n      '-steps',\n      style,\n      stepsLight,\n      props,\n      mergedClsPrefixRef\n    )\n    provide(stepsInjectionKey, {\n      props,\n      mergedThemeRef: themeRef,\n      mergedClsPrefixRef,\n      stepsSlots: slots\n    })\n    return {\n      mergedClsPrefix: mergedClsPrefixRef,\n      rtlEnabled: rtlEnabledRef\n    }\n  },\n  render() {\n    const { mergedClsPrefix } = this\n    return (\n      <div\n        class={[\n          `${mergedClsPrefix}-steps`,\n          this.rtlEnabled && `${mergedClsPrefix}-steps--rtl`,\n          this.vertical && `${mergedClsPrefix}-steps--vertical`,\n          this.contentPlacement === 'bottom'\n          && `${mergedClsPrefix}-steps--content-bottom`\n        ]}\n      >\n        {stepsWithIndex(flatten(getSlot(this)))}\n      </div>\n    )\n  }\n})\n"
  },
  {
    "path": "src/steps/src/styles/index.cssr.ts",
    "content": "import { iconSwitchTransition } from '../../../_styles/transitions/icon-switch.cssr'\nimport { c, cB, cE, cM, cNotM } from '../../../_utils/cssr'\n\n// vars:\n// --n-bezier\n// --n-description-text-color\n// --n-header-text-color\n// --n-indicator-border-color\n// --n-indicator-color\n// --n-indicator-icon-size\n// --n-indicator-index-font-size\n// --n-indicator-size\n// --n-indicator-text-color\n// --n-splitor-color\n// --n-step-header-font-size\n// --n-step-header-font-weight\nexport default cB('steps', `\n  width: 100%;\n  display: flex;\n`, [\n  cB('step', `\n    position: relative;\n    display: flex;\n    flex: 1;\n  `, [\n    cM('disabled', 'cursor: not-allowed'),\n    cM('clickable', `\n      cursor: pointer;\n    `),\n    c('&:last-child', [\n      cB('step-splitor', 'display: none;')\n    ])\n  ]),\n  cB('step-splitor', `\n    background-color: var(--n-splitor-color);\n    margin-top: calc(var(--n-step-header-font-size) / 2);\n    height: 1px;\n    flex: 1;\n    align-self: flex-start;\n    margin-left: 12px;\n    margin-right: 12px;\n    transition:\n      color .3s var(--n-bezier),\n      background-color .3s var(--n-bezier);\n  `),\n  cB('step-content', 'flex: 1;', [\n    cB('step-content-header', `\n      color: var(--n-header-text-color);\n      margin-top: calc(var(--n-indicator-size) / 2 - var(--n-step-header-font-size) / 2);\n      line-height: var(--n-step-header-font-size);\n      font-size: var(--n-step-header-font-size);\n      position: relative;\n      display: flex;\n      font-weight: var(--n-step-header-font-weight);\n      margin-left: 9px;\n      transition:\n        color .3s var(--n-bezier),\n        background-color .3s var(--n-bezier);\n    `, [\n      cE('title', `\n        white-space: nowrap;\n        flex: 0;\n      `)\n    ]),\n    cE('description', `\n      color: var(--n-description-text-color);\n      margin-top: 12px;\n      margin-left: 9px;\n      transition:\n        color .3s var(--n-bezier),\n        background-color .3s var(--n-bezier);\n    `)\n  ]),\n  cB('step-indicator', `\n    background-color: var(--n-indicator-color);\n    box-shadow: 0 0 0 1px var(--n-indicator-border-color);\n    height: var(--n-indicator-size);\n    width: var(--n-indicator-size);\n    border-radius: 50%;\n    display: flex;\n    align-items: center;\n    justify-content: center;\n    transition:\n      background-color .3s var(--n-bezier),\n      box-shadow .3s var(--n-bezier);\n  `, [\n    cB('step-indicator-slot', `\n      position: relative;\n      width: var(--n-indicator-icon-size);\n      height: var(--n-indicator-icon-size);\n      font-size: var(--n-indicator-icon-size);\n      line-height: var(--n-indicator-icon-size);\n    `, [\n      cE('index', `\n        display: inline-block;\n        text-align: center;\n        position: absolute;\n        left: 0;\n        top: 0;\n        white-space: nowrap;\n        font-size: var(--n-indicator-index-font-size);\n        width: var(--n-indicator-icon-size);\n        height: var(--n-indicator-icon-size);\n        line-height: var(--n-indicator-icon-size);\n        color: var(--n-indicator-text-color);\n        transition: color .3s var(--n-bezier);\n      `, [\n        iconSwitchTransition()\n      ]),\n      cB('icon', `\n        color: var(--n-indicator-text-color);\n        transition: color .3s var(--n-bezier);\n      `, [\n        iconSwitchTransition()\n      ]),\n      cB('base-icon', `\n        color: var(--n-indicator-text-color);\n        transition: color .3s var(--n-bezier);\n      `, [\n        iconSwitchTransition()\n      ])\n    ])\n  ]),\n  cM('vertical', 'flex-direction: column;', [\n    cNotM('show-description', [\n      c('>', [\n        cB('step', 'padding-bottom: 8px;')\n      ])\n    ]),\n    c('>', [\n      cB('step', 'margin-bottom: 16px;', [\n        c('&:last-child', 'margin-bottom: 0;'),\n        c('>', [\n          cB('step-indicator', [\n            c('>', [\n              cB('step-splitor', `\n                position: absolute;\n                bottom: -8px;\n                width: 1px;\n                margin: 0 !important;\n                left: calc(var(--n-indicator-size) / 2);\n                height: calc(100% - var(--n-indicator-size));\n              `)\n            ])\n          ]),\n          cB('step-content', [\n            cE('description', 'margin-top: 8px;')\n          ])\n        ])\n      ])\n    ])\n  ]),\n  cM('content-bottom', [cNotM('vertical', [\n    c('>', [\n      cB('step', 'flex-direction: column', [\n        c('>', [\n          cB('step-line', 'display: flex;', [\n            c('>', [\n              cB('step-splitor', `\n                margin-top: 0;\n                align-self: center;\n              `)\n            ]),\n          ])\n        ]),\n        c('>', [\n          cB('step-content', 'margin-top: calc(var(--n-indicator-size) / 2 - var(--n-step-header-font-size) / 2);', [\n            cB('step-content-header', `\n                margin-left: 0;\n              `),\n            cB('step-content__description', `\n                margin-left: 0;\n            `)\n          ])\n        ])\n      ])\n    ])\n  ])])\n])\n"
  },
  {
    "path": "src/steps/src/styles/rtl.cssr.ts",
    "content": "import { c, cB, cE, cM } from '../../../_utils/cssr'\n\nexport default c([\n  cB('steps', [\n    cM('rtl', `\n      direction: rtl;\n      text-align: right;\n    `, [\n      cB('step-content', [\n        cB('step-content-header', `\n          margin-left: 0;\n          margin-right: 9px;\n        `),\n        cE('description', `\n          margin-left: 0;\n          margin-right: 9px;\n        `)\n      ]),\n      cM('vertical', [\n        c('>', [\n          cB('step', [\n            c('>', [\n              cB('step-indicator', [\n                c('>', [\n                  cB('step-splitor', `\n                    left: unset;\n                    right: calc(var(--n-indicator-size) / 2);\n                  `)\n                ])\n              ])\n            ])\n          ])\n        ])\n      ])\n    ])\n  ])\n])\n"
  },
  {
    "path": "src/steps/styles/_common.ts",
    "content": "export default {\n  stepHeaderFontSizeSmall: '14px',\n  stepHeaderFontSizeMedium: '16px',\n  indicatorIndexFontSizeSmall: '14px',\n  indicatorIndexFontSizeMedium: '16px',\n  indicatorSizeSmall: '22px',\n  indicatorSizeMedium: '28px',\n  indicatorIconSizeSmall: '14px',\n  indicatorIconSizeMedium: '18px'\n}\n"
  },
  {
    "path": "src/steps/styles/dark.ts",
    "content": "import type { StepsTheme } from './light'\nimport { commonDark } from '../../_styles/common'\nimport { self } from './light'\n\nconst stepsDark: StepsTheme = {\n  name: 'Steps',\n  common: commonDark,\n  self\n}\n\nexport default stepsDark\n"
  },
  {
    "path": "src/steps/styles/index.ts",
    "content": "export { default as stepsDark } from './dark'\nexport { default as stepsLight } from './light'\nexport type { StepsTheme, StepsThemeVars } from './light'\nexport { stepsRtl } from './rtl'\n"
  },
  {
    "path": "src/steps/styles/light.ts",
    "content": "import type { Theme } from '../../_mixins'\nimport type { ThemeCommonVars } from '../../_styles/common'\nimport { commonLight } from '../../_styles/common'\nimport commonVariables from './_common'\n\nexport function self(vars: ThemeCommonVars) {\n  const {\n    fontWeightStrong,\n    baseColor,\n    textColorDisabled,\n    primaryColor,\n    errorColor,\n    textColor1,\n    textColor2\n  } = vars\n  return {\n    ...commonVariables,\n    stepHeaderFontWeight: fontWeightStrong,\n    indicatorTextColorProcess: baseColor,\n    indicatorTextColorWait: textColorDisabled,\n    indicatorTextColorFinish: primaryColor,\n    indicatorTextColorError: errorColor,\n    indicatorBorderColorProcess: primaryColor,\n    indicatorBorderColorWait: textColorDisabled,\n    indicatorBorderColorFinish: primaryColor,\n    indicatorBorderColorError: errorColor,\n    indicatorColorProcess: primaryColor,\n    indicatorColorWait: '#0000',\n    indicatorColorFinish: '#0000',\n    indicatorColorError: '#0000',\n    splitorColorProcess: textColorDisabled,\n    splitorColorWait: textColorDisabled,\n    splitorColorFinish: primaryColor,\n    splitorColorError: textColorDisabled,\n    headerTextColorProcess: textColor1,\n    headerTextColorWait: textColorDisabled,\n    headerTextColorFinish: textColorDisabled,\n    headerTextColorError: errorColor,\n    descriptionTextColorProcess: textColor2,\n    descriptionTextColorWait: textColorDisabled,\n    descriptionTextColorFinish: textColorDisabled,\n    descriptionTextColorError: errorColor\n  }\n}\n\nexport type StepsThemeVars = ReturnType<typeof self>\n\nconst stepsLight: Theme<'Steps', StepsThemeVars> = {\n  name: 'Steps',\n  common: commonLight,\n  self\n}\n\nexport default stepsLight\nexport type StepsTheme = typeof stepsLight\n"
  },
  {
    "path": "src/steps/styles/rtl.ts",
    "content": "import type { RtlItem } from '../../config-provider/src/internal-interface'\nimport rtlStyle from '../src/styles/rtl.cssr'\n\nexport const stepsRtl: RtlItem = {\n  name: 'Steps',\n  style: rtlStyle\n}\n"
  },
  {
    "path": "src/steps/tests/Steps.spec.ts",
    "content": "import { mount } from '@vue/test-utils'\nimport { h } from 'vue'\nimport { CloseIcon as ErrorIcon } from '../../_internal/icons'\nimport { NIcon } from '../../icon'\nimport { NStep, NSteps } from '../index'\n\ndescribe('n-steps', () => {\n  it('should work with import on demand', () => {\n    mount(NSteps)\n  })\n\n  it('should work with `current` prop', async () => {\n    const processStyle\n      = '--n-description-text-color: rgb(51, 54, 57); --n-header-text-color: rgb(31, 34, 37); --n-indicator-border-color: #18a058; --n-indicator-color: #18a058;'\n    const waitStyle\n      = '--n-description-text-color: rgba(194, 194, 194, 1); --n-header-text-color: rgba(194, 194, 194, 1); --n-indicator-border-color: rgba(194, 194, 194, 1); --n-indicator-color: #0000;'\n    const finishStyle\n      = ' --n-description-text-color: rgba(194, 194, 194, 1); --n-header-text-color: rgba(194, 194, 194, 1); --n-indicator-border-color: #18a058; --n-indicator-color: #0000;'\n    const wrapper = mount(NSteps, {\n      slots: {\n        default: () => [\n          h(NStep, { title: 'test1', description: 'test1', internalIndex: 1 }),\n          h(NStep, { title: 'test2', description: 'test2', internalIndex: 2 }),\n          h(NStep, { title: 'test3', description: 'test3', internalIndex: 3 })\n        ]\n      }\n    })\n\n    wrapper.findAll('.n-step').forEach((item) => {\n      expect(item.attributes('style')).toContain(processStyle)\n    })\n\n    await wrapper.setProps({ current: 1 })\n    expect(wrapper.findAll('.n-step')[0].attributes('style')).toContain(\n      processStyle\n    )\n    expect(wrapper.findAll('.n-step')[1].attributes('style')).toContain(\n      waitStyle\n    )\n    expect(wrapper.findAll('.n-step')[2].attributes('style')).toContain(\n      waitStyle\n    )\n\n    await wrapper.setProps({ current: 2 })\n    expect(wrapper.findAll('.n-step')[0].attributes('style')).toContain(\n      finishStyle\n    )\n    expect(wrapper.findAll('.n-step')[1].attributes('style')).toContain(\n      processStyle\n    )\n    expect(wrapper.findAll('.n-step')[2].attributes('style')).toContain(\n      waitStyle\n    )\n\n    await wrapper.setProps({ current: 3 })\n    expect(wrapper.findAll('.n-step')[0].attributes('style')).toContain(\n      finishStyle\n    )\n    expect(wrapper.findAll('.n-step')[1].attributes('style')).toContain(\n      finishStyle\n    )\n    expect(wrapper.findAll('.n-step')[2].attributes('style')).toContain(\n      processStyle\n    )\n  })\n\n  it('should work with `size` prop', async () => {\n    const mediumStyle\n      = '--n-indicator-icon-size: 18px; --n-indicator-index-font-size: 16px; --n-indicator-size: 28px;'\n    const smallStyle\n      = '--n-indicator-icon-size: 14px; --n-indicator-index-font-size: 14px; --n-indicator-size: 22px;'\n    const wrapper = mount(NSteps, {\n      props: {\n        current: 1\n      },\n      slots: {\n        default: () =>\n          h(NStep, { title: 'test1', description: 'test1', internalIndex: 1 })\n      }\n    })\n    expect(wrapper.find('.n-step').attributes('style')).toContain(mediumStyle)\n    await wrapper.setProps({ size: 'small' })\n    expect(wrapper.find('.n-step').attributes('style')).toContain(smallStyle)\n  })\n\n  it('should work with `vertical` prop', async () => {\n    const wrapper = mount(NSteps, {\n      props: {\n        current: 1\n      },\n      slots: {\n        default: () =>\n          h(NStep, { title: 'test1', description: 'test1', internalIndex: 1 })\n      }\n    })\n    expect(wrapper.find('.n-steps').classes()).not.toContain(\n      'n-steps--vertical'\n    )\n    await wrapper.setProps({ vertical: true })\n    expect(wrapper.find('.n-steps').classes()).toContain('n-steps--vertical')\n  })\n\n  it('should work with `content-placement` prop', async () => {\n    const wrapper = mount(NSteps, {\n      props: {\n        current: 1\n      },\n      slots: {\n        default: () =>\n          h(NStep, { title: 'test1', description: 'test1', internalIndex: 1 })\n      }\n    })\n    expect(wrapper.find('.n-steps').classes()).not.toContain(\n      'n-steps--content-bottom'\n    )\n    await wrapper.setProps({ contentPlacement: 'bottom' })\n    expect(wrapper.find('.n-steps').classes()).toContain(\n      'n-steps--content-bottom'\n    )\n  })\n\n  it('should work with `finish-icon` and `error-icon` slots', async () => {\n    const wrapper = mount(NSteps, {\n      props: {\n        status: 'finish',\n        current: 1\n      },\n      slots: {\n        'finish-icon': () =>\n          h(NIcon, null, {\n            default: () => 'finish'\n          }),\n        'error-icon': () =>\n          h(NIcon, null, {\n            default: () => 'error'\n          }),\n        default: () =>\n          h(NStep, { title: 'test', description: 'test', internalIndex: 1 })\n      }\n    })\n\n    expect(wrapper.find('.n-icon').exists()).toBe(true)\n    expect(wrapper.find('.n-icon').text()).toBe('finish')\n\n    await wrapper.setProps({ status: 'error' })\n    expect(wrapper.find('.n-icon').exists()).toBe(true)\n    expect(wrapper.find('.n-icon').text()).toBe('error')\n  })\n\n  it('should show ErrorIcon with `error` status', () => {\n    const wrapper = mount(NSteps, {\n      slots: {\n        default: () => h(NStep, { internalIndex: 1, status: 'error' })\n      }\n    })\n\n    expect(wrapper.findComponent(ErrorIcon).exists()).toBe(true)\n  })\n\n  it('step should work with `icon` slot', () => {\n    const wrapper = mount(NSteps, {\n      props: {\n        current: 1\n      },\n      slots: {\n        default: () =>\n          h(\n            NStep,\n            {\n              title: 'test',\n              description: 'test'\n            },\n            {\n              icon: () => h(NIcon, null, { default: () => 'icon' })\n            }\n          )\n      }\n    })\n\n    expect(wrapper.find('.n-icon').exists()).toBe(true)\n    expect(wrapper.find('.n-icon').text()).toBe('icon')\n  })\n})\n"
  },
  {
    "path": "src/steps/tests/server.spec.tsx",
    "content": "import { setup } from '@css-render/vue3-ssr'\nimport { renderToString } from '@vue/server-renderer'\n/**\n * @vitest-environment node\n */\nimport { createSSRApp, h } from 'vue'\nimport { NSteps } from '../..'\n\ndescribe('server side rendering', () => {\n  it('works', async () => {\n    const app = createSSRApp(() => <NSteps />)\n    setup(app)\n    try {\n      await renderToString(app)\n    }\n    catch (e) {\n      expect(e).not.toBeTruthy()\n    }\n  })\n})\n"
  },
  {
    "path": "src/styles.ts",
    "content": "// danger zone, internal styles\nexport { scrollbarDark } from './_internal/scrollbar/styles'\nexport { scrollbarRtl as unstableScrollbarRtl } from './_internal/scrollbar/styles'\nexport { internalSelectMenuDark } from './_internal/select-menu/styles'\nexport { internalSelectionDark } from './_internal/selection/styles'\nexport { commonDark, commonLight } from './_styles/common'\nexport { alertDark, alertRtl as unstableAlertRtl } from './alert/styles'\nexport { anchorDark } from './anchor/styles'\nexport { autoCompleteDark } from './auto-complete/styles'\nexport { avatarGroupRtl as unstableAvatarGroupRtl } from './avatar-group/styles'\nexport { avatarDark } from './avatar/styles'\nexport { backTopDark } from './back-top/styles'\nexport { badgeDark, badgeRtl as unstableBadgeRtl } from './badge/styles'\nexport { breadcrumbDark } from './breadcrumb/styles'\nexport {\n  buttonGroupDark,\n  buttonGroupRtl as unstableButtonGroupRtl\n} from './button-group/styles'\nexport { buttonDark, buttonRtl as unstableButtonRtl } from './button/styles'\nexport { cardDark, cardRtl as unstableCardRtl } from './card/styles'\nexport { cascaderDark } from './cascader/styles'\nexport {\n  checkboxDark,\n  checkboxRtl as unstableCheckboxRtl\n} from './checkbox/styles'\nexport { codeDark } from './code/styles'\nexport { collapseTransitionRtl as unstableCollapseTransitionRtl } from './collapse-transition/styles'\nexport {\n  collapseDark,\n  collapseRtl as unstableCollapseRtl\n} from './collapse/styles'\nexport { DataTableRtl as unstableDataTableRtl } from './data-table/styles'\nexport { dataTableDark } from './data-table/styles'\nexport { datePickerDark } from './date-picker/styles'\nexport { descriptionsDark } from './descriptions/styles'\nexport { dialogDark, dialogRtl as unstableDialogRtl } from './dialog/styles'\nexport { dividerDark } from './divider/styles'\nexport { drawerDark, drawerRtl as unstableDrawerRtl } from './drawer/styles'\nexport { dropdownDark } from './dropdown/styles'\nexport {\n  dynamicInputDark,\n  dynamicInputRtl as unstableDynamicInputRtl\n} from './dynamic-input/styles'\nexport { dynamicTagsDark } from './dynamic-tags/styles'\nexport { elementDark } from './element/styles'\nexport { emptyDark } from './empty/styles'\nexport { flexDark, flexRtl as unstableFlexRtl } from './flex/styles'\nexport { formDark } from './form/styles'\nexport { gradientTextDark } from './gradient-text/styles'\nexport { iconDark } from './icon/styles'\nexport {\n  inputNumberDark,\n  inputNumberRtl as unstableInputNumberRtl\n} from './input-number/styles'\nexport {\n  inputOtpDark,\n  inputOtpRtl as unstableInputOtpRtl\n} from './input-otp/styles'\nexport { inputDark, inputRtl as unstableInputRtl } from './input/styles'\nexport { layoutDark } from './layout/styles'\nexport { rowRtl as unstableRowRtl } from './legacy-grid/styles'\nexport { listDark, listRtl as unstableListRtl } from './list/styles'\nexport { loadingBarDark } from './loading-bar/styles'\nexport { logDark } from './log/styles'\nexport { mentionDark } from './mention/styles'\nexport { menuDark } from './menu/styles'\nexport { messageRtl as unstableMessageRtl } from './message/styles'\nexport { messageDark } from './message/styles'\nexport { modalDark } from './modal/styles'\nexport { notificationRtl as unstableNotificationRtl } from './notification/styles'\nexport { notificationDark } from './notification/styles'\nexport { pageHeaderRtl as unstablePageHeaderRtl } from './page-header/styles'\nexport {\n  paginationDark,\n  paginationRtl as unstablePaginationRtl\n} from './pagination/styles'\nexport { popconfirmDark } from './popconfirm/styles'\nexport { popoverDark, popoverRtl as unstablePopoverRtl } from './popover/styles'\nexport { popselectDark } from './popselect/styles'\nexport { progressDark } from './progress/styles'\nexport { radioDark, radioRtl as unstableRadioRtl } from './radio/styles'\nexport { rateDark } from './rate/styles'\nexport { resultDark } from './result/styles'\nexport { selectDark, selectRtl as unstableSelectRtl } from './select/styles'\nexport { sliderDark } from './slider/styles'\nexport { spaceDark, spaceRtl as unstableSpaceRtl } from './space/styles'\nexport { spinDark } from './spin/styles'\nexport {\n  statisticDark,\n  statisticRtl as unstableStatisticRtl\n} from './statistic/styles'\nexport { stepsDark, stepsRtl as unstableStepsRtl } from './steps/styles'\nexport { switchDark } from './switch/styles'\nexport { tableDark, tableRtl as unstableTableRtl } from './table/styles'\nexport { tabsDark } from './tabs/styles'\nexport { tagDark, tagRtl as unstableTagRtl } from './tag/styles'\nexport { thingDark, thingRtl as unstableThingRtl } from './thing/styles'\nexport { timePickerDark } from './time-picker/styles'\nexport { timelineDark } from './timeline/styles'\nexport { tooltipDark } from './tooltip/styles'\nexport { transferDark } from './transfer/styles'\nexport {\n  treeSelectDark,\n  treeSelectRtl as unstableTreeSelectRtl\n} from './tree-select/styles'\n\nexport { treeDark, treeRtl as unstableTreeRtl } from './tree/styles'\nexport { typographyDark } from './typography/styles'\nexport { uploadRtl as unstableUploadsRtl, uploadDark } from './upload/styles'\nexport { watermarkDark } from './watermark/styles'\n"
  },
  {
    "path": "src/switch/demos/enUS/basic.demo.vue",
    "content": "<markdown>\n# Basic\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst active = ref(false)\n</script>\n\n<template>\n  <n-space>\n    <n-switch v-model:value=\"active\" />\n    <n-switch v-model:value=\"active\" disabled />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/switch/demos/enUS/color.demo.vue",
    "content": "<markdown>\n# Customizing colors\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { CSSProperties } from 'vue'\n\nfunction railStyle({\n  focused,\n  checked\n}: {\n  focused: boolean\n  checked: boolean\n}) {\n  const style: CSSProperties = {}\n  if (checked) {\n    style.background = '#d03050'\n    if (focused) {\n      style.boxShadow = '0 0 0 2px #d0305040'\n    }\n  }\n  else {\n    style.background = '#2080f0'\n    if (focused) {\n      style.boxShadow = '0 0 0 2px #2080f040'\n    }\n  }\n  return style\n}\n</script>\n\n<template>\n  <n-switch :rail-style=\"railStyle\">\n    <template #checked>\n      Checked\n    </template>\n    <template #unchecked>\n      Unchecked\n    </template>\n  </n-switch>\n</template>\n"
  },
  {
    "path": "src/switch/demos/enUS/content.demo.vue",
    "content": "<markdown>\n# Content\n\nAdd switch content.\n</markdown>\n\n<template>\n  <n-switch>\n    <template #checked>\n      Big wheels keep on turnin'\n    </template>\n    <template #unchecked>\n      Carry me home to see my kin\n    </template>\n  </n-switch>\n</template>\n"
  },
  {
    "path": "src/switch/demos/enUS/customize-value.demo.vue",
    "content": "<markdown>\n# Customize checked value\n\nUse `checked-value` and `unchecked-value` to customize respective values.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { useMessage } from 'naive-ui'\n\nconst message = useMessage()\nfunction handleUpdateValue(value: string) {\n  message.info(value)\n}\n</script>\n\n<template>\n  <n-switch\n    checked-value=\"Foo\"\n    unchecked-value=\"Bar\"\n    @update:value=\"handleUpdateValue\"\n  />\n</template>\n"
  },
  {
    "path": "src/switch/demos/enUS/event.demo.vue",
    "content": "<markdown>\n# Event\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { useMessage } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst message = useMessage()\nconst active = ref(false)\nfunction handleChange(value: boolean) {\n  message.info(`Update value: ${value}`)\n}\n</script>\n\n<template>\n  <n-switch v-model:value=\"active\" @update:value=\"handleChange\" />\n</template>\n"
  },
  {
    "path": "src/switch/demos/enUS/icon.demo.vue",
    "content": "<markdown>\n# Customizing Icon\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ArrowBackOutline, ArrowForwardOutline } from '@vicons/ionicons5'\nimport { ref } from 'vue'\n\nconst active = ref(false)\n</script>\n\n<template>\n  <n-space>\n    <n-switch v-model:value=\"active\" size=\"medium\">\n      <template #icon>\n        🤔\n      </template>\n    </n-switch>\n    <n-switch v-model:value=\"active\" size=\"large\">\n      <template #checked-icon>\n        <n-icon :component=\"ArrowForwardOutline\" />\n      </template>\n      <template #unchecked-icon>\n        <n-icon :component=\"ArrowBackOutline\" />\n      </template>\n    </n-switch>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/switch/demos/enUS/index.demo-entry.md",
    "content": "# Switch\n\nI have a Nintendo Switch, but don't have time to play it. This reminds me of my childhood when I played NDS... a happier time.\n\n## Demos\n\n```demo\nbasic.vue\nsize.vue\ncontent.vue\nloading.vue\nevent.vue\ncustomize-value.vue\nshape.vue\ncolor.vue\nicon.vue\n```\n\n## API\n\n### Switch Props\n\n| Name | Type | Default | Description | Version |\n| --- | --- | --- | --- | --- |\n| checked-value | `string \\| boolean \\| number` | `true` | Value of checked state. |  |\n| default-value | `boolean` | `false` | Default value. |  |\n| disabled | `boolean` | `false` | Whether to disable the switch. |  |\n| loading | `boolean` | `false` | Whether to show loading state. |  |\n| rail-style | `(info: { focused: boolean, checked: boolean }) => (CSSProperties \\| string)` | `undefined` | Rail style generator. |  |\n| round | `boolean` | `true` | Whether the switch has rounded corners. |  |\n| rubber-band | `boolean` | `true` | Whether the switch button has rubber band effect. | 2.28.3 |\n| size | `'small' \\| 'medium' \\| 'large'` | `'medium'` | The size of the switch. |  |\n| spin-props | `{ strokeWidth?: number, stroke?: string, scale?: number, radius?: number }` | `undefined` | Loading icon properties. | 2.44.0 |\n| unchecked-value | `string \\| boolean \\| number` | `false` | Value of unchecked state. |  |\n| value | `string \\| number \\| boolean \\| undefined` | `undefined` | Value when being set manually. |  |\n| on-update:value | `(value: boolean) => void` | `undefined` | Callback when the component's value changes. |  |\n\n### Switch Slots\n\n| Name | Parameters | Description | Version |\n| --- | --- | --- | --- |\n| checked | `()` | Content when the switch is checked. |  |\n| checked-icon | `()` | Icon of switch button when checked. | 2.25.3 |\n| icon | `()` | Icon of switch button. | 2.25.3 |\n| unchecked | `()` | Content when the switch is unchecked. |  |\n| unchecked-icon | `()` | Icon of switch button when unchecked. | 2.25.3 |\n"
  },
  {
    "path": "src/switch/demos/enUS/loading.demo.vue",
    "content": "<markdown>\n# Loading\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst active = ref(false)\nconst loading = ref(false)\nfunction handleUpdateValue(value: boolean) {\n  loading.value = true\n  setTimeout(() => {\n    active.value = value\n    loading.value = false\n  }, 2000)\n}\n</script>\n\n<template>\n  <n-space>\n    <n-switch :rubber-band=\"false\" loading />\n    <n-switch\n      :rubber-band=\"false\"\n      :value=\"active\"\n      :loading=\"loading\"\n      @update:value=\"handleUpdateValue\"\n    />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/switch/demos/enUS/shape.demo.vue",
    "content": "<markdown>\n# Shape\n\nSwitch can have square shape.\n</markdown>\n\n<template>\n  <n-space>\n    <n-switch :round=\"false\" />\n    <n-switch />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/switch/demos/enUS/size.demo.vue",
    "content": "<markdown>\n# Size\n</markdown>\n\n<template>\n  <n-space>\n    <n-switch size=\"small\" />\n    <n-switch size=\"medium\" />\n    <n-switch size=\"large\" />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/switch/demos/zhCN/basic.demo.vue",
    "content": "<markdown>\n# 基础用法\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst active = ref(false)\n</script>\n\n<template>\n  <n-space>\n    <n-switch v-model:value=\"active\" />\n    <n-switch v-model:value=\"active\" disabled />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/switch/demos/zhCN/color.demo.vue",
    "content": "<markdown>\n# 自定义颜色\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { CSSProperties } from 'vue'\n\nfunction railStyle({\n  focused,\n  checked\n}: {\n  focused: boolean\n  checked: boolean\n}) {\n  const style: CSSProperties = {}\n  if (checked) {\n    style.background = '#d03050'\n    if (focused) {\n      style.boxShadow = '0 0 0 2px #d0305040'\n    }\n  }\n  else {\n    style.background = '#2080f0'\n    if (focused) {\n      style.boxShadow = '0 0 0 2px #2080f040'\n    }\n  }\n  return style\n}\n</script>\n\n<template>\n  <n-switch :rail-style=\"railStyle\">\n    <template #checked>\n      傍晚六点下班\n    </template>\n    <template #unchecked>\n      午夜零点下班\n    </template>\n  </n-switch>\n</template>\n"
  },
  {
    "path": "src/switch/demos/zhCN/content.demo.vue",
    "content": "<markdown>\n# 内容\n\n向开关中加入内容。\n</markdown>\n\n<template>\n  <n-switch>\n    <template #checked>\n      自然赠予你，树冠 微风 肩头的暴雨\n    </template>\n    <template #unchecked>\n      片刻后生成，平衡 忠诚 不息的身体\n    </template>\n  </n-switch>\n</template>\n"
  },
  {
    "path": "src/switch/demos/zhCN/customize-value.demo.vue",
    "content": "<markdown>\n# 自定义选中的值\n\n使用 `checked-value` 和 `unchecked-value` 制定选中的值。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { useMessage } from 'naive-ui'\n\nconst message = useMessage()\nfunction handleUpdateValue(value: string) {\n  message.info(value)\n}\n</script>\n\n<template>\n  <n-switch\n    checked-value=\"周末加班\"\n    unchecked-value=\"周末支持一下\"\n    @update:value=\"handleUpdateValue\"\n  />\n</template>\n"
  },
  {
    "path": "src/switch/demos/zhCN/event.demo.vue",
    "content": "<markdown>\n# 事件\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { useMessage } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst message = useMessage()\nconst active = ref(false)\nfunction handleChange(value: boolean) {\n  message.info(`Update value: ${value}`)\n}\n</script>\n\n<template>\n  <n-switch v-model:value=\"active\" @update:value=\"handleChange\" />\n</template>\n"
  },
  {
    "path": "src/switch/demos/zhCN/icon.demo.vue",
    "content": "<markdown>\n# 自定义图标\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ArrowBackOutline, ArrowForwardOutline } from '@vicons/ionicons5'\nimport { ref } from 'vue'\n\nconst active = ref(false)\n</script>\n\n<template>\n  <n-space>\n    <n-switch v-model:value=\"active\" size=\"medium\">\n      <template #icon>\n        🤔\n      </template>\n    </n-switch>\n    <n-switch v-model:value=\"active\" size=\"large\">\n      <template #checked-icon>\n        <n-icon :component=\"ArrowForwardOutline\" />\n      </template>\n      <template #unchecked-icon>\n        <n-icon :component=\"ArrowBackOutline\" />\n      </template>\n    </n-switch>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/switch/demos/zhCN/index.demo-entry.md",
    "content": "# 开关 Switch\n\n我有一个 Switch，不过没时间玩。每每这个时候，我都会回忆起童年玩 NDS 的快乐时光。\n\n## 演示\n\n```demo\nbasic.vue\nsize.vue\ncontent.vue\nloading.vue\nevent.vue\ncustomize-value.vue\nshape.vue\ncolor.vue\nicon.vue\n```\n\n## API\n\n### Switch Props\n\n| 名称 | 类型 | 默认值 | 说明 | 版本 |\n| --- | --- | --- | --- | --- |\n| checked-value | `string \\| boolean \\| number` | `true` | 选中时对应的值 |  |\n| default-value | `boolean` | `false` | 非受控模式下的默认值 |  |\n| disabled | `boolean` | `false` | 是否禁用 |  |\n| loading | `boolean` | `false` | 是否加载 |  |\n| rail-style | `(info: { focused: boolean, checked: boolean }) => (CSSProperties \\| string)` | `undefined` | 创建轨道样式的函数 |  |\n| round | `boolean` | `true` | 是否为圆形按钮 |  |\n| rubber-band | `boolean` | `true` | 按钮是否有橡皮筋效果 | 2.28.3 |\n| size | `'small' \\| 'medium' \\| 'large'` | `'medium'` | 开关大小 |  |\n| spin-props | `{ strokeWidth?: number, stroke?: string, scale?: number, radius?: number }` | `undefined` | 加载图标的属性 | 2.44.0 |\n| unchecked-value | `string \\| boolean \\| number` | `false` | 未选中时对应的值 |  |\n| value | `string \\| number \\| boolean \\| undefined` | `undefined` | 受控模式下的值 |  |\n| on-update:value | `(value: boolean) => void` | `undefined` | 组件值发生变化的回调 |  |\n\n### Switch Slots\n\n| 名称           | 参数 | 说明                   | 版本   |\n| -------------- | ---- | ---------------------- | ------ |\n| checked        | `()` | 开关激活时的内容       |        |\n| checked-icon   | `()` | 开关按钮选中时的图标   | 2.25.3 |\n| icon           | `()` | 开关按钮的图标         | 2.25.3 |\n| unchecked      | `()` | 开关关闭时的内容       |        |\n| unchecked-icon | `()` | 开关按钮未选中时的图标 | 2.25.3 |\n"
  },
  {
    "path": "src/switch/demos/zhCN/loading.demo.vue",
    "content": "<markdown>\n# 加载中\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst active = ref(false)\nconst loading = ref(false)\nfunction handleUpdateValue(value: boolean) {\n  loading.value = true\n  setTimeout(() => {\n    active.value = value\n    loading.value = false\n  }, 2000)\n}\n</script>\n\n<template>\n  <n-space>\n    <n-switch :rubber-band=\"false\" loading />\n    <n-switch\n      :rubber-band=\"false\"\n      :value=\"active\"\n      :loading=\"loading\"\n      @update:value=\"handleUpdateValue\"\n    />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/switch/demos/zhCN/shape.demo.vue",
    "content": "<markdown>\n# 形状\n\n开关可以设为方形。\n</markdown>\n\n<template>\n  <n-space>\n    <n-switch :round=\"false\" />\n    <n-switch />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/switch/demos/zhCN/size.demo.vue",
    "content": "<markdown>\n# 尺寸\n</markdown>\n\n<template>\n  <n-space>\n    <n-switch size=\"small\" />\n    <n-switch size=\"medium\" />\n    <n-switch size=\"large\" />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/switch/index.ts",
    "content": "export type * from './src/public-types'\nexport { default as NSwitch, switchProps } from './src/Switch'\nexport type { SwitchProps, SwitchSlots } from './src/Switch'\n"
  },
  {
    "path": "src/switch/src/Switch.tsx",
    "content": "import type { CSSProperties, PropType, SlotsType, VNode } from 'vue'\nimport type { ThemeProps } from '../../_mixins'\nimport type { ExtractPublicPropTypes, MaybeArray } from '../../_utils'\nimport type { SwitchTheme } from '../styles'\nimport type { OnUpdateValue, OnUpdateValueImpl } from './interface'\nimport type { SwitchSize, SwitchSpinProps } from './public-types'\nimport { depx, pxfy } from 'seemly'\nimport { useMergedState } from 'vooks'\nimport { computed, defineComponent, h, ref, toRef, watchEffect } from 'vue'\nimport { NBaseLoading, NIconSwitchTransition } from '../../_internal'\nimport { useConfig, useFormItem, useTheme, useThemeClass } from '../../_mixins'\nimport {\n  call,\n  createKey,\n  isSlotEmpty,\n  resolveWrappedSlot,\n  warnOnce\n} from '../../_utils'\nimport { switchLight } from '../styles'\nimport style from './styles/index.cssr'\n\nexport const switchProps = {\n  ...(useTheme.props as ThemeProps<SwitchTheme>),\n  size: String as PropType<SwitchSize>,\n  value: {\n    type: [String, Number, Boolean] as PropType<\n      string | number | boolean | undefined\n    >,\n    default: undefined\n  },\n  loading: Boolean,\n  defaultValue: {\n    type: [String, Number, Boolean] as PropType<string | number | boolean>,\n    default: false\n  },\n  disabled: {\n    type: Boolean as PropType<boolean | undefined>,\n    default: undefined\n  },\n  round: {\n    type: Boolean,\n    default: true\n  },\n  'onUpdate:value': [Function, Array] as PropType<MaybeArray<OnUpdateValue>>,\n  onUpdateValue: [Function, Array] as PropType<MaybeArray<OnUpdateValue>>,\n  checkedValue: {\n    type: [String, Number, Boolean] as PropType<string | number | boolean>,\n    default: true\n  },\n  uncheckedValue: {\n    type: [String, Number, Boolean] as PropType<string | number | boolean>,\n    default: false\n  },\n  railStyle: Function as PropType<\n    (params: { focused: boolean, checked: boolean }) => string | CSSProperties\n  >,\n  rubberBand: {\n    type: Boolean,\n    default: true\n  },\n  spinProps: Object as PropType<SwitchSpinProps>,\n  /** @deprecated */\n  onChange: [Function, Array] as PropType<MaybeArray<OnUpdateValue> | undefined>\n} as const\n\nexport type SwitchProps = ExtractPublicPropTypes<typeof switchProps>\n\nexport interface SwitchSlots {\n  checked?: () => VNode[]\n  'checked-icon'?: () => VNode[]\n  icon?: () => VNode[]\n  unchecked?: () => VNode[]\n  'unchecked-icon'?: () => VNode[]\n}\n\nlet supportCssMax: boolean | undefined\n\nexport default defineComponent({\n  name: 'Switch',\n  props: switchProps,\n  slots: Object as SlotsType<SwitchSlots>,\n  setup(props) {\n    if (__DEV__) {\n      watchEffect(() => {\n        if (props.onChange) {\n          warnOnce(\n            'switch',\n            '`on-change` is deprecated, please use `on-update:value` instead.'\n          )\n        }\n      })\n    }\n    if (supportCssMax === undefined) {\n      if (typeof CSS !== 'undefined') {\n        if (typeof CSS.supports !== 'undefined') {\n          supportCssMax = CSS.supports('width', 'max(1px)')\n        }\n        else {\n          supportCssMax = false\n        }\n      }\n      else {\n        // If you are using SSR, we assume that you are targeting browsers with\n        // recent versions\n        supportCssMax = true\n      }\n    }\n    const { mergedClsPrefixRef, inlineThemeDisabled, mergedComponentPropsRef }\n      = useConfig(props)\n    const themeRef = useTheme(\n      'Switch',\n      '-switch',\n      style,\n      switchLight,\n      props,\n      mergedClsPrefixRef\n    )\n    const formItem = useFormItem(props, {\n      mergedSize(NFormItem) {\n        if (props.size !== undefined)\n          return props.size\n        if (NFormItem) {\n          return NFormItem.mergedSize.value\n        }\n        const configSize = mergedComponentPropsRef?.value?.Switch?.size\n        if (configSize)\n          return configSize\n        return 'medium'\n      }\n    })\n    const { mergedSizeRef, mergedDisabledRef } = formItem\n    const uncontrolledValueRef = ref(props.defaultValue)\n    const controlledValueRef = toRef(props, 'value')\n    const mergedValueRef = useMergedState(\n      controlledValueRef,\n      uncontrolledValueRef\n    )\n    const checkedRef = computed(() => {\n      return mergedValueRef.value === props.checkedValue\n    })\n    const pressedRef = ref(false)\n    const focusedRef = ref(false)\n    const mergedRailStyleRef = computed(() => {\n      const { railStyle } = props\n      if (!railStyle)\n        return undefined\n      return railStyle({ focused: focusedRef.value, checked: checkedRef.value })\n    })\n    function doUpdateValue(value: string | number | boolean): void {\n      const {\n        'onUpdate:value': _onUpdateValue,\n        onChange,\n        onUpdateValue\n      } = props\n      const { nTriggerFormInput, nTriggerFormChange } = formItem\n      if (_onUpdateValue)\n        call(_onUpdateValue as OnUpdateValueImpl, value)\n      if (onUpdateValue)\n        call(onUpdateValue as OnUpdateValueImpl, value)\n      if (onChange)\n        call(onChange as OnUpdateValueImpl, value)\n      uncontrolledValueRef.value = value\n      nTriggerFormInput()\n      nTriggerFormChange()\n    }\n    function doFocus(): void {\n      const { nTriggerFormFocus } = formItem\n      nTriggerFormFocus()\n    }\n    function doBlur(): void {\n      const { nTriggerFormBlur } = formItem\n      nTriggerFormBlur()\n    }\n    function handleClick(): void {\n      if (props.loading || mergedDisabledRef.value)\n        return\n      if (mergedValueRef.value !== props.checkedValue) {\n        doUpdateValue(props.checkedValue)\n      }\n      else {\n        doUpdateValue(props.uncheckedValue)\n      }\n    }\n    function handleFocus(): void {\n      focusedRef.value = true\n      doFocus()\n    }\n    function handleBlur(): void {\n      focusedRef.value = false\n      doBlur()\n      pressedRef.value = false\n    }\n    function handleKeyup(e: KeyboardEvent): void {\n      if (props.loading || mergedDisabledRef.value)\n        return\n      if (e.key === ' ') {\n        if (mergedValueRef.value !== props.checkedValue) {\n          doUpdateValue(props.checkedValue)\n        }\n        else {\n          doUpdateValue(props.uncheckedValue)\n        }\n        pressedRef.value = false\n      }\n    }\n    function handleKeydown(e: KeyboardEvent): void {\n      if (props.loading || mergedDisabledRef.value)\n        return\n      if (e.key === ' ') {\n        e.preventDefault()\n        pressedRef.value = true\n      }\n    }\n    const cssVarsRef = computed(() => {\n      const { value: size } = mergedSizeRef\n      const {\n        self: {\n          opacityDisabled,\n          railColor,\n          railColorActive,\n          buttonBoxShadow,\n          buttonColor,\n          boxShadowFocus,\n          loadingColor,\n          textColor,\n          iconColor,\n          [createKey('buttonHeight', size)]: buttonHeight,\n          [createKey('buttonWidth', size)]: buttonWidth,\n          [createKey('buttonWidthPressed', size)]: buttonWidthPressed,\n          [createKey('railHeight', size)]: railHeight,\n          [createKey('railWidth', size)]: railWidth,\n          [createKey('railBorderRadius', size)]: railBorderRadius,\n          [createKey('buttonBorderRadius', size)]: buttonBorderRadius\n        },\n        common: { cubicBezierEaseInOut }\n      } = themeRef.value\n\n      let offset: string\n      let height: string\n      let width: string\n      if (supportCssMax) {\n        offset = `calc((${railHeight} - ${buttonHeight}) / 2)`\n        height = `max(${railHeight}, ${buttonHeight})`\n        width = `max(${railWidth}, calc(${railWidth} + ${buttonHeight} - ${railHeight}))`\n      }\n      else {\n        offset = pxfy((depx(railHeight) - depx(buttonHeight)) / 2)\n        height = pxfy(Math.max(depx(railHeight), depx(buttonHeight)))\n        width\n          = depx(railHeight) > depx(buttonHeight)\n            ? railWidth\n            : pxfy(depx(railWidth) + depx(buttonHeight) - depx(railHeight))\n      }\n      return {\n        '--n-bezier': cubicBezierEaseInOut,\n        '--n-button-border-radius': buttonBorderRadius,\n        '--n-button-box-shadow': buttonBoxShadow,\n        '--n-button-color': buttonColor,\n        '--n-button-width': buttonWidth,\n        '--n-button-width-pressed': buttonWidthPressed,\n        '--n-button-height': buttonHeight,\n        '--n-height': height,\n        '--n-offset': offset,\n        '--n-opacity-disabled': opacityDisabled,\n        '--n-rail-border-radius': railBorderRadius,\n        '--n-rail-color': railColor,\n        '--n-rail-color-active': railColorActive,\n        '--n-rail-height': railHeight,\n        '--n-rail-width': railWidth,\n        '--n-width': width,\n        '--n-box-shadow-focus': boxShadowFocus,\n        '--n-loading-color': loadingColor,\n        '--n-text-color': textColor,\n        '--n-icon-color': iconColor\n      }\n    })\n    const themeClassHandle = inlineThemeDisabled\n      ? useThemeClass(\n          'switch',\n          computed(() => {\n            return mergedSizeRef.value[0]\n          }),\n          cssVarsRef,\n          props\n        )\n      : undefined\n    return {\n      handleClick,\n      handleBlur,\n      handleFocus,\n      handleKeyup,\n      handleKeydown,\n      mergedRailStyle: mergedRailStyleRef,\n      pressed: pressedRef,\n      mergedClsPrefix: mergedClsPrefixRef,\n      mergedValue: mergedValueRef,\n      checked: checkedRef,\n      mergedDisabled: mergedDisabledRef,\n      cssVars: inlineThemeDisabled ? undefined : cssVarsRef,\n      themeClass: themeClassHandle?.themeClass,\n      onRender: themeClassHandle?.onRender\n    }\n  },\n  render() {\n    const {\n      mergedClsPrefix,\n      mergedDisabled,\n      checked,\n      mergedRailStyle,\n      onRender,\n      $slots\n    } = this\n    onRender?.()\n    const {\n      checked: checkedSlot,\n      unchecked: uncheckedSlot,\n      icon: iconSlot,\n      'checked-icon': checkedIconSlot,\n      'unchecked-icon': uncheckedIconSlot\n    } = $slots\n    const hasIcon = !(\n      isSlotEmpty(iconSlot)\n      && isSlotEmpty(checkedIconSlot)\n      && isSlotEmpty(uncheckedIconSlot)\n    )\n    return (\n      <div\n        role=\"switch\"\n        aria-checked={checked}\n        class={[\n          `${mergedClsPrefix}-switch`,\n          this.themeClass,\n          hasIcon && `${mergedClsPrefix}-switch--icon`,\n          checked && `${mergedClsPrefix}-switch--active`,\n          mergedDisabled && `${mergedClsPrefix}-switch--disabled`,\n          this.round && `${mergedClsPrefix}-switch--round`,\n          this.loading && `${mergedClsPrefix}-switch--loading`,\n          this.pressed && `${mergedClsPrefix}-switch--pressed`,\n          this.rubberBand && `${mergedClsPrefix}-switch--rubber-band`\n        ]}\n        tabindex={!this.mergedDisabled ? 0 : undefined}\n        style={this.cssVars as CSSProperties}\n        onClick={this.handleClick}\n        onFocus={this.handleFocus}\n        onBlur={this.handleBlur}\n        onKeyup={this.handleKeyup}\n        onKeydown={this.handleKeydown}\n      >\n        <div\n          class={`${mergedClsPrefix}-switch__rail`}\n          aria-hidden=\"true\"\n          style={mergedRailStyle}\n        >\n          {resolveWrappedSlot(checkedSlot, checkedSlotChildren =>\n            resolveWrappedSlot(uncheckedSlot, (uncheckedSlotChildren) => {\n              if (checkedSlotChildren || uncheckedSlotChildren) {\n                return (\n                  <div\n                    aria-hidden\n                    class={`${mergedClsPrefix}-switch__children-placeholder`}\n                  >\n                    <div class={`${mergedClsPrefix}-switch__rail-placeholder`}>\n                      <div\n                        class={`${mergedClsPrefix}-switch__button-placeholder`}\n                      />\n                      {checkedSlotChildren}\n                    </div>\n                    <div class={`${mergedClsPrefix}-switch__rail-placeholder`}>\n                      <div\n                        class={`${mergedClsPrefix}-switch__button-placeholder`}\n                      />\n                      {uncheckedSlotChildren}\n                    </div>\n                  </div>\n                )\n              }\n              return null\n            }))}\n          <div class={`${mergedClsPrefix}-switch__button`}>\n            {resolveWrappedSlot(iconSlot, icon =>\n              resolveWrappedSlot(checkedIconSlot, checkedIcon =>\n                resolveWrappedSlot(uncheckedIconSlot, (uncheckedIcon) => {\n                  return (\n                    <NIconSwitchTransition>\n                      {{\n                        default: () =>\n                          this.loading ? (\n                            <NBaseLoading\n                              key=\"loading\"\n                              clsPrefix={mergedClsPrefix}\n                              strokeWidth={20}\n                              {...this.spinProps}\n                            />\n                          ) : this.checked && (checkedIcon || icon) ? (\n                            <div\n                              class={`${mergedClsPrefix}-switch__button-icon`}\n                              key={checkedIcon ? 'checked-icon' : 'icon'}\n                            >\n                              {checkedIcon || icon}\n                            </div>\n                          ) : !this.checked && (uncheckedIcon || icon) ? (\n                            <div\n                              class={`${mergedClsPrefix}-switch__button-icon`}\n                              key={uncheckedIcon ? 'unchecked-icon' : 'icon'}\n                            >\n                              {uncheckedIcon || icon}\n                            </div>\n                          ) : null\n                      }}\n                    </NIconSwitchTransition>\n                  )\n                })))}\n            {resolveWrappedSlot(\n              checkedSlot,\n              children =>\n                children && (\n                  <div\n                    key=\"checked\"\n                    class={`${mergedClsPrefix}-switch__checked`}\n                  >\n                    {children}\n                  </div>\n                )\n            )}\n            {resolveWrappedSlot(\n              uncheckedSlot,\n              children =>\n                children && (\n                  <div\n                    key=\"unchecked\"\n                    class={`${mergedClsPrefix}-switch__unchecked`}\n                  >\n                    {children}\n                  </div>\n                )\n            )}\n          </div>\n        </div>\n      </div>\n    )\n  }\n})\n"
  },
  {
    "path": "src/switch/src/interface.ts",
    "content": "export type OnUpdateValue = (value: string & number & boolean) => void\nexport type OnUpdateValueImpl = (value: string | number | boolean) => void\n"
  },
  {
    "path": "src/switch/src/public-types.ts",
    "content": "import type { SharedSpinProps } from '../../_internal'\n\nexport type SwitchSize = 'small' | 'medium' | 'large'\nexport type SwitchSpinProps = SharedSpinProps\n"
  },
  {
    "path": "src/switch/src/styles/index.cssr.ts",
    "content": "import { iconSwitchTransition } from '../../../_styles/transitions/icon-switch.cssr'\nimport { c, cB, cE, cM, cNotM } from '../../../_utils/cssr'\n\n// vars:\n// --n-bezier\n// --n-button-border-radius\n// --n-button-box-shadow\n// --n-button-color\n// --n-button-width\n// --n-button-width-pressed\n// --n-height\n// --n-offset\n// --n-rail-border-radius\n// --n-rail-color\n// --n-rail-color-active\n// --n-rail-height\n// --n-rail-width\n// --n-width\n// --n-box-shadow-focus\n// --n-loading-color\n// --n-text-color\n// --n-icon-color\nexport default cB('switch', `\n  height: var(--n-height);\n  min-width: var(--n-width);\n  vertical-align: middle;\n  user-select: none;\n  -webkit-user-select: none;\n  display: inline-flex;\n  outline: none;\n  justify-content: center;\n  align-items: center;\n`, [\n  cE('children-placeholder', `\n    height: var(--n-rail-height);\n    display: flex;\n    flex-direction: column;\n    overflow: hidden;\n    pointer-events: none;\n    visibility: hidden;\n  `),\n  cE('rail-placeholder', `\n    display: flex;\n    flex-wrap: none;\n  `),\n  cE('button-placeholder', `\n    width: calc(1.75 * var(--n-rail-height));\n    height: var(--n-rail-height);\n  `),\n  cB('base-loading', `\n    position: absolute;\n    top: 50%;\n    left: 50%;\n    transform: translateX(-50%) translateY(-50%);\n    font-size: calc(var(--n-button-width) - 4px);\n    color: var(--n-loading-color);\n    transition: color .3s var(--n-bezier);\n  `, [\n    iconSwitchTransition({\n      left: '50%',\n      top: '50%',\n      originalTransform: 'translateX(-50%) translateY(-50%)'\n    })\n  ]),\n  cE('checked, unchecked', `\n    transition: color .3s var(--n-bezier);\n    color: var(--n-text-color);\n    box-sizing: border-box;\n    position: absolute;\n    white-space: nowrap;\n    top: 0;\n    bottom: 0;\n    display: flex;\n    align-items: center;\n    line-height: 1;\n  `),\n  cE('checked', `\n    right: 0;\n    padding-right: calc(1.25 * var(--n-rail-height) - var(--n-offset));\n  `),\n  cE('unchecked', `\n    left: 0;\n    justify-content: flex-end;\n    padding-left: calc(1.25 * var(--n-rail-height) - var(--n-offset));\n  `),\n  c('&:focus', [\n    cE('rail', `\n      box-shadow: var(--n-box-shadow-focus);\n    `)\n  ]),\n  cM('round', [\n    cE('rail', 'border-radius: calc(var(--n-rail-height) / 2);', [\n      cE('button', 'border-radius: calc(var(--n-button-height) / 2);')\n    ])\n  ]),\n  cNotM('disabled', [\n    cNotM('icon', [\n      cM('rubber-band', [\n        cM('pressed', [\n          cE('rail', [\n            cE('button', 'max-width: var(--n-button-width-pressed);')\n          ])\n        ]),\n        cE('rail', [\n          c('&:active', [\n            cE('button', 'max-width: var(--n-button-width-pressed);')\n          ])\n        ]),\n        cM('active', [\n          cM('pressed', [\n            cE('rail', [\n              cE('button', 'left: calc(100% - var(--n-offset) - var(--n-button-width-pressed));')\n            ])\n          ]),\n          cE('rail', [\n            c('&:active', [\n              cE('button', 'left: calc(100% - var(--n-offset) - var(--n-button-width-pressed));')\n            ])\n          ])\n        ])\n      ])\n    ])\n  ]),\n  cM('active', [\n    cE('rail', [\n      cE('button', 'left: calc(100% - var(--n-button-width) - var(--n-offset))')\n    ])\n  ]),\n  cE('rail', `\n    overflow: hidden;\n    height: var(--n-rail-height);\n    min-width: var(--n-rail-width);\n    border-radius: var(--n-rail-border-radius);\n    cursor: pointer;\n    position: relative;\n    transition:\n      opacity .3s var(--n-bezier),\n      background .3s var(--n-bezier),\n      box-shadow .3s var(--n-bezier);\n    background-color: var(--n-rail-color);\n  `, [\n    cE('button-icon', `\n      color: var(--n-icon-color);\n      transition: color .3s var(--n-bezier);\n      font-size: calc(var(--n-button-height) - 4px);\n      position: absolute;\n      left: 0;\n      right: 0;\n      top: 0;\n      bottom: 0;\n      display: flex;\n      justify-content: center;\n      align-items: center;\n      line-height: 1;\n    `, [\n      iconSwitchTransition()\n    ]),\n    cE('button', `\n      align-items: center;    \n      top: var(--n-offset);\n      left: var(--n-offset);\n      height: var(--n-button-height);\n      width: var(--n-button-width-pressed);\n      max-width: var(--n-button-width);\n      border-radius: var(--n-button-border-radius);\n      background-color: var(--n-button-color);\n      box-shadow: var(--n-button-box-shadow);\n      box-sizing: border-box;\n      cursor: inherit;\n      content: \"\";\n      position: absolute;\n      transition:\n        background-color .3s var(--n-bezier),\n        left .3s var(--n-bezier),\n        opacity .3s var(--n-bezier),\n        max-width .3s var(--n-bezier),\n        box-shadow .3s var(--n-bezier);\n    `)\n  ]),\n  cM('active', [\n    cE('rail', 'background-color: var(--n-rail-color-active);')\n  ]),\n  cM('loading', [\n    cE('rail', `\n      cursor: wait;\n    `)\n  ]),\n  cM('disabled', [\n    cE('rail', `\n      cursor: not-allowed;\n      opacity: .5;\n    `)\n  ])\n])\n"
  },
  {
    "path": "src/switch/styles/_common.ts",
    "content": "export default {\n  buttonHeightSmall: '14px',\n  buttonHeightMedium: '18px',\n  buttonHeightLarge: '22px',\n  buttonWidthSmall: '14px',\n  buttonWidthMedium: '18px',\n  buttonWidthLarge: '22px',\n  buttonWidthPressedSmall: '20px',\n  buttonWidthPressedMedium: '24px',\n  buttonWidthPressedLarge: '28px',\n  railHeightSmall: '18px',\n  railHeightMedium: '22px',\n  railHeightLarge: '26px',\n  railWidthSmall: '32px',\n  railWidthMedium: '40px',\n  railWidthLarge: '48px'\n}\n"
  },
  {
    "path": "src/switch/styles/dark.ts",
    "content": "import type { SwitchTheme } from './light'\nimport { changeColor } from 'seemly'\nimport { commonDark } from '../../_styles/common'\nimport commonVars from './_common'\n\nconst switchDark: SwitchTheme = {\n  name: 'Switch',\n  common: commonDark,\n  self(vars) {\n    const {\n      primaryColorSuppl,\n      opacityDisabled,\n      borderRadius,\n      primaryColor,\n      textColor2,\n      baseColor\n    } = vars\n    const railOverlayColor = 'rgba(255, 255, 255, .20)'\n    return {\n      ...commonVars,\n      iconColor: baseColor,\n      textColor: textColor2,\n      loadingColor: primaryColorSuppl,\n      opacityDisabled,\n      railColor: railOverlayColor,\n      railColorActive: primaryColorSuppl,\n      buttonBoxShadow: '0px 2px 4px 0 rgba(0, 0, 0, 0.4)',\n      buttonColor: '#FFF',\n      railBorderRadiusSmall: borderRadius,\n      railBorderRadiusMedium: borderRadius,\n      railBorderRadiusLarge: borderRadius,\n      buttonBorderRadiusSmall: borderRadius,\n      buttonBorderRadiusMedium: borderRadius,\n      buttonBorderRadiusLarge: borderRadius,\n      boxShadowFocus: `0 0 8px 0 ${changeColor(primaryColor, { alpha: 0.3 })}`\n    }\n  }\n}\n\nexport default switchDark\n"
  },
  {
    "path": "src/switch/styles/index.ts",
    "content": "export { default as switchDark } from './dark'\nexport { default as switchLight } from './light'\nexport type { SwitchTheme, SwitchThemeVars } from './light'\n"
  },
  {
    "path": "src/switch/styles/light.ts",
    "content": "import type { Theme } from '../../_mixins'\nimport type { ThemeCommonVars } from '../../_styles/common'\nimport { changeColor } from 'seemly'\nimport { commonLight } from '../../_styles/common'\nimport commonVars from './_common'\n\nfunction self(vars: ThemeCommonVars) {\n  const { primaryColor, opacityDisabled, borderRadius, textColor3 } = vars\n  const railOverlayColor = 'rgba(0, 0, 0, .14)'\n  return {\n    ...commonVars,\n    iconColor: textColor3,\n    textColor: 'white',\n    loadingColor: primaryColor,\n    opacityDisabled,\n    railColor: railOverlayColor,\n    railColorActive: primaryColor,\n    buttonBoxShadow:\n      '0 1px 4px 0 rgba(0, 0, 0, 0.3), inset 0 0 1px 0 rgba(0, 0, 0, 0.05)',\n    buttonColor: '#FFF',\n    railBorderRadiusSmall: borderRadius,\n    railBorderRadiusMedium: borderRadius,\n    railBorderRadiusLarge: borderRadius,\n    buttonBorderRadiusSmall: borderRadius,\n    buttonBorderRadiusMedium: borderRadius,\n    buttonBorderRadiusLarge: borderRadius,\n    boxShadowFocus: `0 0 0 2px ${changeColor(primaryColor, { alpha: 0.2 })}`\n  }\n}\n\nexport type SwitchThemeVars = ReturnType<typeof self>\n\nconst switchLight: Theme<'Switch', SwitchThemeVars> = {\n  name: 'Switch',\n  common: commonLight,\n  self\n}\n\nexport default switchLight\nexport type SwitchTheme = typeof switchLight\n"
  },
  {
    "path": "src/switch/tests/Switch.spec.tsx",
    "content": "import type { CSSProperties } from 'vue'\nimport { mount } from '@vue/test-utils'\nimport { Fragment, h } from 'vue'\nimport { NSwitch } from '../index'\n\ndescribe('n-switch', () => {\n  it('should work with import on demand', () => {\n    mount(NSwitch)\n  })\n\n  it('should work with `disabled` prop', async () => {\n    const wrapper = mount(NSwitch)\n    expect(wrapper.find('.n-switch--disabled').exists()).not.toBe(true)\n\n    await wrapper.setProps({ disabled: true })\n    expect(wrapper.find('.n-switch').classes()).toContain('n-switch--disabled')\n  })\n\n  it('should work with `checked-value` prop', async () => {\n    const onUpdateValue = vi.fn()\n    const wrapper = mount(NSwitch, {\n      props: {\n        checkedValue: 'fooo',\n        uncheckedValue: 'barr',\n        onUpdateValue\n      }\n    })\n    await wrapper.trigger('click')\n    expect(onUpdateValue).toHaveBeenCalledWith('fooo')\n    await wrapper.trigger('click')\n    expect(onUpdateValue).toHaveBeenCalledWith('barr')\n    await wrapper.trigger('click')\n    expect(onUpdateValue).toHaveBeenCalledWith('fooo')\n  })\n\n  it('should work with `checked-value` prop in type layer', () => {\n    const onUpdateValue1: (value: string) => void = () => {}\n    const onUpdateValue2: (value: number) => void = () => {}\n    const onUpdateValue3: (value: boolean) => void = () => {}\n    <Fragment>\n      <NSwitch onUpdateValue={onUpdateValue1} value=\"123\" defaultValue=\"123\" />\n      <NSwitch onUpdateValue={onUpdateValue2} value={123} defaultValue={123} />\n      <NSwitch\n        onUpdateValue={onUpdateValue3}\n        value={true}\n        defaultValue={false}\n      />\n    </Fragment>\n  })\n\n  it('should work with `round` prop', async () => {\n    const wrapper = mount(NSwitch)\n    expect(wrapper.find('.n-switch--round').exists()).toBe(true)\n    await wrapper.setProps({ round: false })\n    expect(wrapper.find('.n-switch--round').exists()).not.toBe(true)\n  })\n\n  it('should work with `size` prop', async () => {\n    const wrapper = mount(NSwitch)\n\n    await wrapper.setProps({ size: 'small' })\n    expect(wrapper.find('.n-switch').attributes('style')).toMatchSnapshot()\n\n    await wrapper.setProps({ size: 'medium' })\n    expect(wrapper.find('.n-switch').attributes('style')).toMatchSnapshot()\n\n    await wrapper.setProps({ size: 'large' })\n    expect(wrapper.find('.n-switch').attributes('style')).toMatchSnapshot()\n  })\n\n  it('should work with `value` prop', async () => {\n    const wrapper = mount(NSwitch, { props: { value: true } })\n    expect(wrapper.find('.n-switch--active').exists()).toBe(true)\n\n    await wrapper.setProps({ value: false })\n    expect(wrapper.find('.n-switch--active').exists()).not.toBe(true)\n  })\n\n  it('should work with `on-update:value` prop', async () => {\n    const onUpdate = vi.fn()\n    const wrapper = mount(NSwitch, { props: { 'onUpdate:value': onUpdate } })\n\n    await wrapper.trigger('click')\n    expect(onUpdate).toHaveBeenCalled()\n  })\n\n  it('should work with `loading` prop', () => {\n    const wrapper = mount(NSwitch, {\n      props: {\n        loading: true\n      }\n    })\n    expect(wrapper.find('.n-base-loading').exists()).toBe(true)\n  })\n\n  it('should work with `rail-style` prop', () => {\n    const color = 'rgb(32, 128, 240)'\n    const railStyle = ({\n      focused,\n      checked\n    }: {\n      focused: boolean\n      checked: boolean\n    }): CSSProperties | string => {\n      const style: any = {}\n      if (!checked) {\n        style.background = color\n        if (focused) {\n          style.boxShadow = '0 0 0 2px #d0305040'\n        }\n      }\n      return style\n    }\n    const wrapper = mount(NSwitch, {\n      props: {\n        railStyle\n      }\n    })\n    expect(wrapper.find('.n-switch__rail').attributes('style')).toContain(color)\n  })\n\n  it('should work with slot', () => {\n    const wrapper = mount(NSwitch, {\n      slots: {\n        checked: () => 'checked',\n        unchecked: () => 'unchecked'\n      }\n    })\n    expect(wrapper.find('.n-switch__checked').text()).toEqual('checked')\n    expect(wrapper.find('.n-switch__unchecked').text()).toEqual('unchecked')\n  })\n  it('should work with `icon` slot', () => {\n    const wrapper = mount(NSwitch, {\n      slots: {\n        icon: () => h('div', null, 'icon')\n      }\n    })\n    expect(wrapper.find('.n-switch__button').text()).toEqual('icon')\n  })\n  it('should work with `checked-icon` & `unchecked-icon` slots', async () => {\n    const wrapper = mount(NSwitch, {\n      slots: {\n        'checked-icon': () => h('div', null, 'checked-icon'),\n        'unchecked-icon': () => h('div', null, 'unchecked-icon')\n      }\n    })\n    expect(wrapper.find('.n-switch__button').text()).toEqual('unchecked-icon')\n    await wrapper.trigger('click')\n    expect(wrapper.find('.n-switch__button').text()).toEqual('checked-icon')\n  })\n})\n"
  },
  {
    "path": "src/switch/tests/__snapshots__/Switch.spec.tsx.snap",
    "content": "// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html\n\nexports[`n-switch > should work with \\`size\\` prop 1`] = `\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-button-border-radius: 3px; --n-button-box-shadow: 0 1px 4px 0 rgba(0, 0, 0, 0.3), inset 0 0 1px 0 rgba(0, 0, 0, 0.05); --n-button-color: #FFF; --n-button-width: 14px; --n-button-width-pressed: 20px; --n-button-height: 14px; --n-height: max(18px, 14px); --n-offset: calc((18px - 14px) / 2); --n-opacity-disabled: 0.5; --n-rail-border-radius: 3px; --n-rail-color: rgba(0, 0, 0, .14); --n-rail-color-active: #18a058; --n-rail-height: 18px; --n-rail-width: 32px; --n-width: max(32px, calc(32px + 14px - 18px)); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-loading-color: #18a058; --n-text-color: white; --n-icon-color: rgb(118, 124, 130);\"`;\n\nexports[`n-switch > should work with \\`size\\` prop 2`] = `\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-button-border-radius: 3px; --n-button-box-shadow: 0 1px 4px 0 rgba(0, 0, 0, 0.3), inset 0 0 1px 0 rgba(0, 0, 0, 0.05); --n-button-color: #FFF; --n-button-width: 18px; --n-button-width-pressed: 24px; --n-button-height: 18px; --n-height: max(22px, 18px); --n-offset: calc((22px - 18px) / 2); --n-opacity-disabled: 0.5; --n-rail-border-radius: 3px; --n-rail-color: rgba(0, 0, 0, .14); --n-rail-color-active: #18a058; --n-rail-height: 22px; --n-rail-width: 40px; --n-width: max(40px, calc(40px + 18px - 22px)); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-loading-color: #18a058; --n-text-color: white; --n-icon-color: rgb(118, 124, 130);\"`;\n\nexports[`n-switch > should work with \\`size\\` prop 3`] = `\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-button-border-radius: 3px; --n-button-box-shadow: 0 1px 4px 0 rgba(0, 0, 0, 0.3), inset 0 0 1px 0 rgba(0, 0, 0, 0.05); --n-button-color: #FFF; --n-button-width: 22px; --n-button-width-pressed: 28px; --n-button-height: 22px; --n-height: max(26px, 22px); --n-offset: calc((26px - 22px) / 2); --n-opacity-disabled: 0.5; --n-rail-border-radius: 3px; --n-rail-color: rgba(0, 0, 0, .14); --n-rail-color-active: #18a058; --n-rail-height: 26px; --n-rail-width: 48px; --n-width: max(48px, calc(48px + 22px - 26px)); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-loading-color: #18a058; --n-text-color: white; --n-icon-color: rgb(118, 124, 130);\"`;\n"
  },
  {
    "path": "src/switch/tests/server.spec.tsx",
    "content": "import { setup } from '@css-render/vue3-ssr'\nimport { renderToString } from '@vue/server-renderer'\n/**\n * @vitest-environment node\n */\nimport { createSSRApp, h } from 'vue'\nimport { NSwitch } from '../..'\n\ndescribe('server side rendering', () => {\n  it('works', async () => {\n    const app = createSSRApp(() => <NSwitch />)\n    setup(app)\n    try {\n      await renderToString(app)\n    }\n    catch (e) {\n      expect(e).not.toBeTruthy()\n    }\n  })\n})\n"
  },
  {
    "path": "src/table/demos/enUS/basic.demo.vue",
    "content": "<markdown>\n# Basic\n</markdown>\n\n<template>\n  <n-table :bordered=\"false\" :single-line=\"false\">\n    <thead>\n      <tr>\n        <th>Abandon</th>\n        <th>Abnormal</th>\n        <th>Abolish</th>\n        <th>...</th>\n        <th>It's hard to learn words</th>\n      </tr>\n    </thead>\n    <tbody>\n      <tr>\n        <td>放弃</td>\n        <td>反常的</td>\n        <td>彻底废除</td>\n        <td>...</td>\n        <td>Damn it! I can't remember those words.</td>\n      </tr>\n      <tr>\n        <td>...</td>\n        <td>...</td>\n        <td>...</td>\n        <td>...</td>\n        <td>...</td>\n      </tr>\n    </tbody>\n  </n-table>\n</template>\n"
  },
  {
    "path": "src/table/demos/enUS/bordered.demo.vue",
    "content": "<markdown>\n# Bordered\n</markdown>\n\n<template>\n  <n-table :single-line=\"false\">\n    <thead>\n      <tr>\n        <th>Abandon</th>\n        <th>Abnormal</th>\n        <th>Abolish</th>\n        <th>...</th>\n        <th>It's hard to learn words</th>\n      </tr>\n    </thead>\n    <tbody>\n      <tr>\n        <td>放弃</td>\n        <td>反常的</td>\n        <td>彻底废除</td>\n        <td>...</td>\n        <td>Damn it! I can't remember those words.</td>\n      </tr>\n      <tr>\n        <td>...</td>\n        <td>...</td>\n        <td>...</td>\n        <td>...</td>\n        <td>...</td>\n      </tr>\n    </tbody>\n  </n-table>\n</template>\n"
  },
  {
    "path": "src/table/demos/enUS/index.demo-entry.md",
    "content": "# Table\n\n<!--single-column-->\n\nIf you only want to render some basic tables, use it. If you want to render structured data, see [Data Table](data-table).\n\n## Demos\n\n```demo\nbasic.vue\nbordered.vue\nsize.vue\nsingle-column.vue\nsingle-line.vue\nstriped.vue\n```\n\n## Components\n\nYou can use `n-table`, `n-thead`, `n-tbody`, `n-tr`, `n-th` and `n-td`. At most time you won't need the components after `n-table`. They can be used to reduce the granularity of dependency collecting.\n\n## API\n\n### Table Props\n\n| Name | Type | Default | Description |\n| --- | --- | --- | --- |\n| bottom-bordered | `boolean` | `true` | The bottom border of the table, this prop is invalid when `bordered` is `true`. |\n| bordered | `boolean` | `true` | Whether to show table border. |\n| single-column | `boolean` | `false` | Whether rows are not divided. If the prop is `true`, table cell has no `border-bottom`. |\n| single-line | `boolean` | `true` | Whether columns are not divided. If the prop is `true`, table cell has no `border-right`. |\n| size | `'small' \\| 'medium' \\| 'large'` | `'medium'` | Table size. |\n| striped | `boolean` | `false` | Whether to show zebra stripes on rows. |\n"
  },
  {
    "path": "src/table/demos/enUS/single-column.demo.vue",
    "content": "<markdown>\n# Single column\n</markdown>\n\n<template>\n  <n-table single-column :single-line=\"false\">\n    <thead>\n      <tr>\n        <th>Abandon</th>\n        <th>Abnormal</th>\n        <th>Abolish</th>\n        <th>...</th>\n        <th>It's hard to learn words</th>\n      </tr>\n    </thead>\n    <tbody>\n      <tr>\n        <td>放弃</td>\n        <td>反常的</td>\n        <td>彻底废除</td>\n        <td>...</td>\n        <td>Damn it! I can't remember those words.</td>\n      </tr>\n      <tr>\n        <td>...</td>\n        <td>...</td>\n        <td>...</td>\n        <td>...</td>\n        <td>...</td>\n      </tr>\n    </tbody>\n  </n-table>\n</template>\n"
  },
  {
    "path": "src/table/demos/enUS/single-line.demo.vue",
    "content": "<markdown>\n# Single line\n</markdown>\n\n<template>\n  <n-table>\n    <thead>\n      <tr>\n        <th>Abandon</th>\n        <th>Abnormal</th>\n        <th>Abolish</th>\n        <th>...</th>\n        <th>It's hard to learn words</th>\n      </tr>\n    </thead>\n    <tbody>\n      <tr>\n        <td>放弃</td>\n        <td>反常的</td>\n        <td>彻底废除</td>\n        <td>...</td>\n        <td>Damn it! I can't remember those words.</td>\n      </tr>\n      <tr>\n        <td>...</td>\n        <td>...</td>\n        <td>...</td>\n        <td>...</td>\n        <td>...</td>\n      </tr>\n    </tbody>\n  </n-table>\n</template>\n"
  },
  {
    "path": "src/table/demos/enUS/size.demo.vue",
    "content": "<markdown>\n# Size\n</markdown>\n\n<template>\n  <n-space vertical>\n    <n-table :bordered=\"false\" :single-line=\"false\" size=\"small\">\n      <thead>\n        <tr>\n          <th>Abandon</th>\n          <th>Abnormal</th>\n          <th>Abolish</th>\n          <th>...</th>\n          <th>It's hard to learn words</th>\n        </tr>\n      </thead>\n      <tbody>\n        <tr>\n          <td>放弃</td>\n          <td>反常的</td>\n          <td>彻底废除</td>\n          <td>...</td>\n          <td>Damn it! I can't remember those words.</td>\n        </tr>\n        <tr>\n          <td>...</td>\n          <td>...</td>\n          <td>...</td>\n          <td>...</td>\n          <td>...</td>\n        </tr>\n      </tbody>\n    </n-table>\n    <n-table :bordered=\"false\" :single-line=\"false\" size=\"large\">\n      <thead>\n        <tr>\n          <th>Abandon</th>\n          <th>Abnormal</th>\n          <th>Abolish</th>\n          <th>...</th>\n          <th>It's hard to learn words</th>\n        </tr>\n      </thead>\n      <tbody>\n        <tr>\n          <td>放弃</td>\n          <td>反常的</td>\n          <td>彻底废除</td>\n          <td>...</td>\n          <td>Damn it! I can't remember those words.</td>\n        </tr>\n        <tr>\n          <td>...</td>\n          <td>...</td>\n          <td>...</td>\n          <td>...</td>\n          <td>...</td>\n        </tr>\n      </tbody>\n    </n-table>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/table/demos/enUS/striped.demo.vue",
    "content": "<markdown>\n# Stripe\n</markdown>\n\n<template>\n  <n-space vertical>\n    <n-table striped>\n      <thead>\n        <tr>\n          <th>Abandon</th>\n          <th>Abnormal</th>\n          <th>Abolish</th>\n          <th>...</th>\n          <th>It's hard to learn words</th>\n        </tr>\n      </thead>\n      <tbody>\n        <tr>\n          <td>放弃</td>\n          <td>反常的</td>\n          <td>彻底废除</td>\n          <td>...</td>\n          <td>Damn it! I can't remember those words.</td>\n        </tr>\n        <tr>\n          <td>...</td>\n          <td>...</td>\n          <td>...</td>\n          <td>...</td>\n          <td>...</td>\n        </tr>\n        <tr>\n          <td>...</td>\n          <td>...</td>\n          <td>...</td>\n          <td>...</td>\n          <td>...</td>\n        </tr>\n      </tbody>\n    </n-table>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/table/demos/zhCN/basic.demo.vue",
    "content": "<markdown>\n# 基础用法\n</markdown>\n\n<template>\n  <n-table :bordered=\"false\" :single-line=\"false\">\n    <thead>\n      <tr>\n        <th>Abandon</th>\n        <th>Abnormal</th>\n        <th>Abolish</th>\n        <th>...</th>\n        <th>万事开头难</th>\n      </tr>\n    </thead>\n    <tbody>\n      <tr>\n        <td>放弃</td>\n        <td>反常的</td>\n        <td>彻底废除</td>\n        <td>...</td>\n        <td>干！我刚才背的是啥</td>\n      </tr>\n      <tr>\n        <td>...</td>\n        <td>...</td>\n        <td>...</td>\n        <td>...</td>\n        <td>...</td>\n      </tr>\n    </tbody>\n  </n-table>\n</template>\n"
  },
  {
    "path": "src/table/demos/zhCN/bordered.demo.vue",
    "content": "<markdown>\n# 边框\n</markdown>\n\n<template>\n  <n-table :single-line=\"false\">\n    <thead>\n      <tr>\n        <th>Abandon</th>\n        <th>Abnormal</th>\n        <th>Abolish</th>\n        <th>...</th>\n        <th>万事开头难</th>\n      </tr>\n    </thead>\n    <tbody>\n      <tr>\n        <td>放弃</td>\n        <td>反常的</td>\n        <td>彻底废除</td>\n        <td>...</td>\n        <td>干！我刚才背的是啥</td>\n      </tr>\n      <tr>\n        <td>...</td>\n        <td>...</td>\n        <td>...</td>\n        <td>...</td>\n        <td>...</td>\n      </tr>\n    </tbody>\n  </n-table>\n</template>\n"
  },
  {
    "path": "src/table/demos/zhCN/index.demo-entry.md",
    "content": "# 表格 Table\n\n<!--single-column-->\n\n如果你只想画点简单的表格，用它。需要渲染数据请看[数据表格 Data Table](data-table)。\n\n## 演示\n\n```demo\nbasic.vue\nbordered.vue\nsize.vue\nsingle-column.vue\nsingle-line.vue\nstriped.vue\nrtl-debug.vue\n```\n\n## Components\n\n你可以使用 `n-table`、`n-thead`、`n-tbody`、`n-tr`、`n-th` 和 `n-td`。多数情况下你不需要使用后面的组件，他们可以用来减少依赖收集的粒度。\n\n## API\n\n### Table Props\n\n| 名称 | 类型 | 默认值 | 说明 |\n| --- | --- | --- | --- |\n| bottom-bordered | `boolean` | `true` | 表格底部是否有边框，在 `bordered` 为 `true` 时该参数无效 |\n| bordered | `boolean` | `true` | 是否显示边框 |\n| single-column | `boolean` | `false` | 是否不设定行的分割线，当参数为`true`时，则单元格没有下边线 |\n| single-line | `boolean` | `true` | 是否不设定列的分割线，当参数值为 `true` 时，则单元格没有右边线 |\n| size | `'small' \\| 'medium' \\| 'large'` | `'medium'` | 表格尺寸大小 |\n| striped | `boolean` | `false` | 是否使用斑马线条纹 |\n"
  },
  {
    "path": "src/table/demos/zhCN/rtl-debug.demo.vue",
    "content": "<markdown>\n# Rtl Debug\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { unstableTableRtl } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst singleColumn = ref(false)\nconst singleLine = ref(false)\nconst bordered = ref(false)\nconst rtlEnabled = ref(false)\nconst rtlStyles = [unstableTableRtl]\n</script>\n\n<template>\n  <n-space vertical>\n    <n-space><n-switch v-model:value=\"rtlEnabled\" />Rtl</n-space>\n    <n-space><n-switch v-model:value=\"singleLine\" />Single line</n-space>\n    <n-space><n-switch v-model:value=\"singleColumn\" />Single column</n-space>\n    <n-space><n-switch v-model:value=\"bordered\" />Bordered</n-space>\n    <n-config-provider :rtl=\"rtlEnabled ? rtlStyles : undefined\">\n      <n-table\n        :bordered=\"bordered\"\n        :single-column=\"singleColumn\"\n        :single-line=\"singleLine\"\n      >\n        <thead>\n          <tr>\n            <th>Abandon</th>\n            <th>Abnormal</th>\n            <th>Abolish</th>\n            <th>...</th>\n            <th>万事开头难</th>\n          </tr>\n        </thead>\n        <tbody>\n          <tr>\n            <td>放弃</td>\n            <td>反常的</td>\n            <td>彻底废除</td>\n            <td>...</td>\n            <td>干！我刚才背的是啥</td>\n          </tr>\n          <tr>\n            <td>...</td>\n            <td>...</td>\n            <td>...</td>\n            <td>...</td>\n            <td>...</td>\n          </tr>\n        </tbody>\n      </n-table>\n    </n-config-provider>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/table/demos/zhCN/single-column.demo.vue",
    "content": "<markdown>\n# 单列\n</markdown>\n\n<template>\n  <n-table single-column :single-line=\"false\">\n    <thead>\n      <tr>\n        <th>Abandon</th>\n        <th>Abnormal</th>\n        <th>Abolish</th>\n        <th>...</th>\n        <th>万事开头难</th>\n      </tr>\n    </thead>\n    <tbody>\n      <tr>\n        <td>放弃</td>\n        <td>反常的</td>\n        <td>彻底废除</td>\n        <td>...</td>\n        <td>干！我刚才背的是啥</td>\n      </tr>\n      <tr>\n        <td>...</td>\n        <td>...</td>\n        <td>...</td>\n        <td>...</td>\n        <td>...</td>\n      </tr>\n    </tbody>\n  </n-table>\n</template>\n"
  },
  {
    "path": "src/table/demos/zhCN/single-line.demo.vue",
    "content": "<markdown>\n# 单行\n</markdown>\n\n<template>\n  <n-table>\n    <thead>\n      <tr>\n        <th>Abandon</th>\n        <th>Abnormal</th>\n        <th>Abolish</th>\n        <th>...</th>\n        <th>万事开头难</th>\n      </tr>\n    </thead>\n    <tbody>\n      <tr>\n        <td>放弃</td>\n        <td>反常的</td>\n        <td>彻底废除</td>\n        <td>...</td>\n        <td>干！我刚才背的是啥</td>\n      </tr>\n      <tr>\n        <td>...</td>\n        <td>...</td>\n        <td>...</td>\n        <td>...</td>\n        <td>...</td>\n      </tr>\n    </tbody>\n  </n-table>\n</template>\n"
  },
  {
    "path": "src/table/demos/zhCN/size.demo.vue",
    "content": "<markdown>\n# 尺寸\n</markdown>\n\n<template>\n  <n-space vertical>\n    <n-table :bordered=\"false\" :single-line=\"false\" size=\"small\">\n      <thead>\n        <tr>\n          <th>Abandon</th>\n          <th>Abnormal</th>\n          <th>Abolish</th>\n          <th>...</th>\n          <th>万事开头难</th>\n        </tr>\n      </thead>\n      <tbody>\n        <tr>\n          <td>放弃</td>\n          <td>反常的</td>\n          <td>彻底废除</td>\n          <td>...</td>\n          <td>干！我刚才背的是啥</td>\n        </tr>\n        <tr>\n          <td>...</td>\n          <td>...</td>\n          <td>...</td>\n          <td>...</td>\n          <td>...</td>\n        </tr>\n      </tbody>\n    </n-table>\n    <n-table :bordered=\"false\" :single-line=\"false\" size=\"large\">\n      <thead>\n        <tr>\n          <th>Abandon</th>\n          <th>Abnormal</th>\n          <th>Abolish</th>\n          <th>...</th>\n          <th>万事开头难</th>\n        </tr>\n      </thead>\n      <tbody>\n        <tr>\n          <td>放弃</td>\n          <td>反常的</td>\n          <td>彻底废除</td>\n          <td>...</td>\n          <td>干！我刚才背的是啥</td>\n        </tr>\n        <tr>\n          <td>...</td>\n          <td>...</td>\n          <td>...</td>\n          <td>...</td>\n          <td>...</td>\n        </tr>\n      </tbody>\n    </n-table>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/table/demos/zhCN/striped.demo.vue",
    "content": "<markdown>\n# 条纹\n</markdown>\n\n<template>\n  <n-space vertical>\n    <n-table striped>\n      <thead>\n        <tr>\n          <th>Abandon</th>\n          <th>Abnormal</th>\n          <th>Abolish</th>\n          <th>...</th>\n          <th>万事开头难</th>\n        </tr>\n      </thead>\n      <tbody>\n        <tr>\n          <td>放弃</td>\n          <td>反常的</td>\n          <td>彻底废除</td>\n          <td>...</td>\n          <td>干！我刚才背的是啥</td>\n        </tr>\n        <tr>\n          <td>...</td>\n          <td>...</td>\n          <td>...</td>\n          <td>...</td>\n          <td>...</td>\n        </tr>\n        <tr>\n          <td>...</td>\n          <td>...</td>\n          <td>...</td>\n          <td>...</td>\n          <td>...</td>\n        </tr>\n      </tbody>\n    </n-table>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/table/index.ts",
    "content": "export type * from './src/public-types'\nexport { default as NTable, tableProps } from './src/Table'\nexport type { TableProps } from './src/Table'\nexport { default as NTbody } from './src/Tbody'\nexport { default as NTd } from './src/Td'\nexport { default as NTh } from './src/Th'\nexport { default as NThead } from './src/Thead'\nexport { default as NTr } from './src/Tr'\n"
  },
  {
    "path": "src/table/src/Table.tsx",
    "content": "import type { CSSProperties, PropType } from 'vue'\nimport type { ThemeProps } from '../../_mixins'\nimport type { ExtractPublicPropTypes } from '../../_utils'\nimport type { TableTheme } from '../styles'\nimport type { TableSize } from './public-types'\nimport { computed, defineComponent, h } from 'vue'\nimport { useConfig, useTheme, useThemeClass } from '../../_mixins'\nimport { useRtl } from '../../_mixins/use-rtl'\nimport { createKey } from '../../_utils'\nimport { tableLight } from '../styles'\nimport style from './styles/index.cssr'\n\nexport const tableProps = {\n  ...(useTheme.props as ThemeProps<TableTheme>),\n  bordered: {\n    type: Boolean,\n    default: true\n  },\n  bottomBordered: {\n    type: Boolean,\n    default: true\n  },\n  singleLine: {\n    type: Boolean,\n    default: true\n  },\n  striped: Boolean,\n  singleColumn: Boolean,\n  size: String as PropType<TableSize>\n}\n\nexport type TableProps = ExtractPublicPropTypes<typeof tableProps>\n\nexport default defineComponent({\n  name: 'Table',\n  props: tableProps,\n  setup(props) {\n    const {\n      mergedClsPrefixRef,\n      inlineThemeDisabled,\n      mergedRtlRef,\n      mergedComponentPropsRef\n    } = useConfig(props)\n    const mergedSizeRef = computed(() => {\n      return (\n        props.size || mergedComponentPropsRef?.value?.Table?.size || 'medium'\n      )\n    })\n    const themeRef = useTheme(\n      'Table',\n      '-table',\n      style,\n      tableLight,\n      props,\n      mergedClsPrefixRef\n    )\n    const rtlEnabledRef = useRtl('Table', mergedRtlRef, mergedClsPrefixRef)\n    const cssVarsRef = computed(() => {\n      const size = mergedSizeRef.value\n      const {\n        self: {\n          borderColor,\n          tdColor,\n          tdColorModal,\n          tdColorPopover,\n          thColor,\n          thColorModal,\n          thColorPopover,\n          thTextColor,\n          tdTextColor,\n          borderRadius,\n          thFontWeight,\n          lineHeight,\n          borderColorModal,\n          borderColorPopover,\n          tdColorStriped,\n          tdColorStripedModal,\n          tdColorStripedPopover,\n          [createKey('fontSize', size)]: fontSize,\n          [createKey('tdPadding', size)]: tdPadding,\n          [createKey('thPadding', size)]: thPadding\n        },\n        common: { cubicBezierEaseInOut }\n      } = themeRef.value\n      return {\n        '--n-bezier': cubicBezierEaseInOut,\n        '--n-td-color': tdColor,\n        '--n-td-color-modal': tdColorModal,\n        '--n-td-color-popover': tdColorPopover,\n        '--n-td-text-color': tdTextColor,\n        '--n-border-color': borderColor,\n        '--n-border-color-modal': borderColorModal,\n        '--n-border-color-popover': borderColorPopover,\n        '--n-border-radius': borderRadius,\n        '--n-font-size': fontSize,\n        '--n-th-color': thColor,\n        '--n-th-color-modal': thColorModal,\n        '--n-th-color-popover': thColorPopover,\n        '--n-th-font-weight': thFontWeight,\n        '--n-th-text-color': thTextColor,\n        '--n-line-height': lineHeight,\n        '--n-td-padding': tdPadding,\n        '--n-th-padding': thPadding,\n        '--n-td-color-striped': tdColorStriped,\n        '--n-td-color-striped-modal': tdColorStripedModal,\n        '--n-td-color-striped-popover': tdColorStripedPopover\n      }\n    })\n    const themeClassHandle = inlineThemeDisabled\n      ? useThemeClass(\n          'table',\n          computed(() => {\n            return mergedSizeRef.value[0]\n          }),\n          cssVarsRef,\n          props\n        )\n      : undefined\n    return {\n      rtlEnabled: rtlEnabledRef,\n      mergedClsPrefix: mergedClsPrefixRef,\n      cssVars: inlineThemeDisabled ? undefined : cssVarsRef,\n      themeClass: themeClassHandle?.themeClass,\n      onRender: themeClassHandle?.onRender\n    }\n  },\n  render() {\n    const { mergedClsPrefix } = this\n    this.onRender?.()\n    return (\n      <table\n        class={[\n          `${mergedClsPrefix}-table`,\n          this.themeClass,\n          {\n            [`${mergedClsPrefix}-table--rtl`]: this.rtlEnabled,\n            [`${mergedClsPrefix}-table--bottom-bordered`]: this.bottomBordered,\n            [`${mergedClsPrefix}-table--bordered`]: this.bordered,\n            [`${mergedClsPrefix}-table--single-line`]: this.singleLine,\n            [`${mergedClsPrefix}-table--single-column`]: this.singleColumn,\n            [`${mergedClsPrefix}-table--striped`]: this.striped\n          }\n        ]}\n        style={this.cssVars as CSSProperties}\n      >\n        {this.$slots}\n      </table>\n    )\n  }\n})\n"
  },
  {
    "path": "src/table/src/Tbody.tsx",
    "content": "import { defineComponent, h } from 'vue'\n\nexport default defineComponent({\n  name: 'Tbody',\n  render() {\n    return <tbody>{this.$slots}</tbody>\n  }\n})\n"
  },
  {
    "path": "src/table/src/Td.tsx",
    "content": "import { defineComponent, h } from 'vue'\n\nexport default defineComponent({\n  name: 'Td',\n  render() {\n    return <td>{this.$slots}</td>\n  }\n})\n"
  },
  {
    "path": "src/table/src/Th.tsx",
    "content": "import { defineComponent, h } from 'vue'\n\nexport default defineComponent({\n  name: 'Th',\n  render() {\n    return <th>{this.$slots}</th>\n  }\n})\n"
  },
  {
    "path": "src/table/src/Thead.tsx",
    "content": "import { defineComponent, h } from 'vue'\n\nexport default defineComponent({\n  name: 'Thead',\n  render() {\n    return <thead>{this.$slots}</thead>\n  }\n})\n"
  },
  {
    "path": "src/table/src/Tr.tsx",
    "content": "import { defineComponent, h } from 'vue'\n\nexport default defineComponent({\n  name: 'Tr',\n  render() {\n    return <tr>{this.$slots}</tr>\n  }\n})\n"
  },
  {
    "path": "src/table/src/public-types.ts",
    "content": "export type TableSize = 'small' | 'medium' | 'large'\n"
  },
  {
    "path": "src/table/src/styles/index.cssr.ts",
    "content": "import { c, cB, cM, cNotM, insideModal, insidePopover } from '../../../_utils/cssr'\n\n// vars:\n// --n-bezier\n// --n-td-color\n// --n-td-color-modal\n// --n-td-color-popover\n// --n-td-text-color\n// --n-border-color\n// --n-border-color-modal\n// --n-border-color-popover\n// --n-border-radius\n// --n-font-size\n// --n-th-color\n// --n-th-color-modal\n// --n-th-color-popover\n// --n-th-font-weight\n// --n-th-text-color\n// --n-line-height\n// --n-td-padding\n// --n-th-padding\nexport default c([\n  cB('table', `\n    font-size: var(--n-font-size);\n    font-variant-numeric: tabular-nums;\n    line-height: var(--n-line-height);\n    width: 100%;\n    border-radius: var(--n-border-radius) var(--n-border-radius) 0 0;\n    text-align: left;\n    border-collapse: separate;\n    border-spacing: 0;\n    overflow: hidden;\n    background-color: var(--n-td-color);\n    border-color: var(--n-merged-border-color);\n    transition:\n      background-color .3s var(--n-bezier),\n      border-color .3s var(--n-bezier),\n      color .3s var(--n-bezier);\n    --n-merged-border-color: var(--n-border-color);\n  `, [\n    c('th', `\n      white-space: nowrap;\n      transition:\n        background-color .3s var(--n-bezier),\n        border-color .3s var(--n-bezier),\n        color .3s var(--n-bezier);\n      text-align: inherit;\n      padding: var(--n-th-padding);\n      vertical-align: inherit;\n      text-transform: none;\n      border: 0px solid var(--n-merged-border-color);\n      font-weight: var(--n-th-font-weight);\n      color: var(--n-th-text-color);\n      background-color: var(--n-th-color);\n      border-bottom: 1px solid var(--n-merged-border-color);\n      border-right: 1px solid var(--n-merged-border-color);\n    `, [\n      c('&:last-child', `\n        border-right: 0px solid var(--n-merged-border-color);\n      `)\n    ]),\n    c('td', `\n      transition:\n        background-color .3s var(--n-bezier),\n        border-color .3s var(--n-bezier),\n        color .3s var(--n-bezier);\n      padding: var(--n-td-padding);\n      color: var(--n-td-text-color);\n      background-color: var(--n-td-color);\n      border: 0px solid var(--n-merged-border-color);\n      border-right: 1px solid var(--n-merged-border-color);\n      border-bottom: 1px solid var(--n-merged-border-color);\n    `, [\n      c('&:last-child', `\n        border-right: 0px solid var(--n-merged-border-color);\n      `)\n    ]),\n    cM('bordered', `\n      border: 1px solid var(--n-merged-border-color);\n      border-radius: var(--n-border-radius);\n    `, [\n      c('tr', [\n        c('&:last-child', [\n          c('td', `\n            border-bottom: 0 solid var(--n-merged-border-color);\n          `)\n        ])\n      ])\n    ]),\n    cM('single-line', [\n      c('th', `\n        border-right: 0px solid var(--n-merged-border-color);\n      `),\n      c('td', `\n        border-right: 0px solid var(--n-merged-border-color);\n      `)\n    ]),\n    cM('single-column', [\n      c('tr', [\n        c('&:not(:last-child)', [\n          c('td', `\n            border-bottom: 0px solid var(--n-merged-border-color);\n          `)\n        ])\n      ])\n    ]),\n    cM('striped', [\n      c('tr:nth-of-type(even)', [c('td', 'background-color: var(--n-td-color-striped)')])\n    ]),\n    cNotM('bottom-bordered', [\n      c('tr', [\n        c('&:last-child', [\n          c('td', `\n            border-bottom: 0px solid var(--n-merged-border-color);\n          `)\n        ])\n      ])\n    ])\n  ]),\n  insideModal(\n    cB('table', `\n      background-color: var(--n-td-color-modal);\n      --n-merged-border-color: var(--n-border-color-modal);\n    `, [\n      c('th', `\n        background-color: var(--n-th-color-modal);\n      `),\n      c('td', `\n        background-color: var(--n-td-color-modal);\n      `)\n    ])\n  ),\n  insidePopover(\n    cB('table', `\n      background-color: var(--n-td-color-popover);\n      --n-merged-border-color: var(--n-border-color-popover);\n    `, [\n      c('th', `\n        background-color: var(--n-th-color-popover);\n      `),\n      c('td', `\n        background-color: var(--n-td-color-popover);\n      `)\n    ])\n  )\n])\n"
  },
  {
    "path": "src/table/src/styles/rtl.cssr.ts",
    "content": "import { c, cB, cM } from '../../../_utils/cssr'\n\nexport default c([\n  cB('table', [\n    cM('rtl', `\n      direction: rtl;\n      text-align: right;\n    `, [\n      c('th, td', `\n        border-right: 0px solid var(--n-merged-border-color);\n        border-left: 1px solid var(--n-merged-border-color);\n      `, [\n        c('&:last-child', `\n          border-left: none;\n          border-right: inherit;\n        `)\n      ]),\n      cM('single-line', [\n        c('th, td', `\n          border-left: 0px solid var(--n-merged-border-color);\n        `)\n      ])\n    ])\n  ])\n])\n"
  },
  {
    "path": "src/table/styles/_common.ts",
    "content": "export default {\n  thPaddingSmall: '6px',\n  thPaddingMedium: '12px',\n  thPaddingLarge: '12px',\n  tdPaddingSmall: '6px',\n  tdPaddingMedium: '12px',\n  tdPaddingLarge: '12px'\n}\n"
  },
  {
    "path": "src/table/styles/dark.ts",
    "content": "import type { TableTheme } from './light'\nimport { commonDark } from '../../_styles/common'\nimport { self } from './light'\n\nconst tableDark: TableTheme = {\n  name: 'Table',\n  common: commonDark,\n  self\n}\n\nexport default tableDark\n"
  },
  {
    "path": "src/table/styles/index.ts",
    "content": "export { default as tableDark } from './dark'\nexport { default as tableLight } from './light'\nexport type { TableTheme, TableThemeVars } from './light'\nexport { tableRtl } from './rtl'\n"
  },
  {
    "path": "src/table/styles/light.ts",
    "content": "import type { Theme } from '../../_mixins'\nimport type { ThemeCommonVars } from '../../_styles/common'\nimport { composite } from 'seemly'\nimport { commonLight } from '../../_styles/common'\nimport sizeVariables from './_common'\n\nexport function self(vars: ThemeCommonVars) {\n  const {\n    dividerColor,\n    cardColor,\n    modalColor,\n    popoverColor,\n    tableHeaderColor,\n    tableColorStriped,\n    textColor1,\n    textColor2,\n    borderRadius,\n    fontWeightStrong,\n    lineHeight,\n    fontSizeSmall,\n    fontSizeMedium,\n    fontSizeLarge\n  } = vars\n  return {\n    ...sizeVariables,\n    fontSizeSmall,\n    fontSizeMedium,\n    fontSizeLarge,\n    lineHeight,\n    borderRadius,\n    borderColor: composite(cardColor, dividerColor),\n    borderColorModal: composite(modalColor, dividerColor),\n    borderColorPopover: composite(popoverColor, dividerColor),\n    tdColor: cardColor,\n    tdColorModal: modalColor,\n    tdColorPopover: popoverColor,\n    tdColorStriped: composite(cardColor, tableColorStriped),\n    tdColorStripedModal: composite(modalColor, tableColorStriped),\n    tdColorStripedPopover: composite(popoverColor, tableColorStriped),\n    thColor: composite(cardColor, tableHeaderColor),\n    thColorModal: composite(modalColor, tableHeaderColor),\n    thColorPopover: composite(popoverColor, tableHeaderColor),\n    thTextColor: textColor1,\n    tdTextColor: textColor2,\n    thFontWeight: fontWeightStrong\n  }\n}\n\nexport type TableThemeVars = ReturnType<typeof self>\n\nconst tableLight: Theme<'Table', TableThemeVars> = {\n  name: 'Table',\n  common: commonLight,\n  self\n}\n\nexport default tableLight\nexport type TableTheme = typeof tableLight\n"
  },
  {
    "path": "src/table/styles/rtl.ts",
    "content": "import type { RtlItem } from '../../config-provider/src/internal-interface'\nimport rtlStyle from '../src/styles/rtl.cssr'\n\nexport const tableRtl: RtlItem = {\n  name: 'Table',\n  style: rtlStyle\n}\n"
  },
  {
    "path": "src/table/tests/Table.spec.ts",
    "content": "import { mount } from '@vue/test-utils'\nimport { NTable, NTbody, NTd, NTh, NThead, NTr } from '../index'\n\ndescribe('n-table', () => {\n  it('should work with import on demand', () => {\n    mount(NTable)\n  })\n\n  it('should work with `bottom-bordered` prop', async () => {\n    const wrapper = mount(NTable)\n    expect(wrapper.find('.n-table').classes()).toContain(\n      'n-table--bottom-bordered'\n    )\n\n    await wrapper.setProps({ bottomBordered: false })\n    expect(wrapper.find('.n-table').classes()).not.toContain(\n      'n-table--bottom-bordered'\n    )\n  })\n\n  it('should work with `bordered` prop', async () => {\n    const wrapper = mount(NTable)\n    expect(wrapper.find('.n-table').classes()).toContain('n-table--bordered')\n\n    await wrapper.setProps({ bordered: false })\n    expect(wrapper.find('.n-table').classes()).not.toContain(\n      'n-table--bordered'\n    )\n  })\n\n  it('should work with `single-column` prop', async () => {\n    const wrapper = mount(NTable)\n    expect(wrapper.find('.n-table').classes()).not.toContain(\n      'n-table--single-column'\n    )\n\n    await wrapper.setProps({ singleColumn: true })\n    expect(wrapper.find('.n-table').classes()).toContain(\n      'n-table--single-column'\n    )\n  })\n\n  it('should work with `single-line` prop', async () => {\n    const wrapper = mount(NTable)\n    expect(wrapper.find('.n-table').classes()).toContain('n-table--single-line')\n\n    await wrapper.setProps({ singleLine: false })\n    expect(wrapper.find('.n-table').classes()).not.toContain(\n      'n-table--single-line'\n    )\n  })\n\n  it('should work with `size` prop', async () => {\n    ;(['small', 'medium', 'large'] as const).forEach((size) => {\n      const wrapper = mount(NTable, { props: { size } })\n      expect(wrapper.find('.n-table').attributes('style')).toMatchSnapshot()\n    })\n  })\n\n  it('should work with `striped` prop', async () => {\n    const wrapper = mount(NTable)\n    expect(wrapper.find('.n-table').classes()).not.toContain('n-table--striped')\n\n    await wrapper.setProps({ striped: true })\n    expect(wrapper.find('.n-table').classes()).toContain('n-table--striped')\n  })\n})\n\ndescribe('n-table-body', () => {\n  it('should work with import on demand', () => {\n    mount(NTbody)\n  })\n})\n\ndescribe('n-table-head', () => {\n  it('should work with import on demand', () => {\n    mount(NThead)\n  })\n})\n\ndescribe('n-table-td', () => {\n  it('should work with import on demand', () => {\n    mount(NTd)\n  })\n})\n\ndescribe('n-table-th', () => {\n  it('should work with import on demand', () => {\n    mount(NTh)\n  })\n})\n\ndescribe('n-table-tr', () => {\n  it('should work with import on demand', () => {\n    mount(NTr)\n  })\n})\n"
  },
  {
    "path": "src/table/tests/__snapshots__/Table.spec.ts.snap",
    "content": "// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html\n\nexports[`n-table > should work with \\`size\\` prop 1`] = `\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-td-color: #fff; --n-td-color-modal: #fff; --n-td-color-popover: #fff; --n-td-text-color: rgb(51, 54, 57); --n-border-color: rgba(239, 239, 245, 1); --n-border-color-modal: rgba(239, 239, 245, 1); --n-border-color-popover: rgba(239, 239, 245, 1); --n-border-radius: 3px; --n-font-size: 14px; --n-th-color: rgba(250, 250, 252, 1); --n-th-color-modal: rgba(250, 250, 252, 1); --n-th-color-popover: rgba(250, 250, 252, 1); --n-th-font-weight: 500; --n-th-text-color: rgb(31, 34, 37); --n-line-height: 1.6; --n-td-padding: 6px; --n-th-padding: 6px; --n-td-color-striped: rgba(250, 250, 252, 1); --n-td-color-striped-modal: rgba(250, 250, 252, 1); --n-td-color-striped-popover: rgba(250, 250, 252, 1);\"`;\n\nexports[`n-table > should work with \\`size\\` prop 2`] = `\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-td-color: #fff; --n-td-color-modal: #fff; --n-td-color-popover: #fff; --n-td-text-color: rgb(51, 54, 57); --n-border-color: rgba(239, 239, 245, 1); --n-border-color-modal: rgba(239, 239, 245, 1); --n-border-color-popover: rgba(239, 239, 245, 1); --n-border-radius: 3px; --n-font-size: 14px; --n-th-color: rgba(250, 250, 252, 1); --n-th-color-modal: rgba(250, 250, 252, 1); --n-th-color-popover: rgba(250, 250, 252, 1); --n-th-font-weight: 500; --n-th-text-color: rgb(31, 34, 37); --n-line-height: 1.6; --n-td-padding: 12px; --n-th-padding: 12px; --n-td-color-striped: rgba(250, 250, 252, 1); --n-td-color-striped-modal: rgba(250, 250, 252, 1); --n-td-color-striped-popover: rgba(250, 250, 252, 1);\"`;\n\nexports[`n-table > should work with \\`size\\` prop 3`] = `\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-td-color: #fff; --n-td-color-modal: #fff; --n-td-color-popover: #fff; --n-td-text-color: rgb(51, 54, 57); --n-border-color: rgba(239, 239, 245, 1); --n-border-color-modal: rgba(239, 239, 245, 1); --n-border-color-popover: rgba(239, 239, 245, 1); --n-border-radius: 3px; --n-font-size: 15px; --n-th-color: rgba(250, 250, 252, 1); --n-th-color-modal: rgba(250, 250, 252, 1); --n-th-color-popover: rgba(250, 250, 252, 1); --n-th-font-weight: 500; --n-th-text-color: rgb(31, 34, 37); --n-line-height: 1.6; --n-td-padding: 12px; --n-th-padding: 12px; --n-td-color-striped: rgba(250, 250, 252, 1); --n-td-color-striped-modal: rgba(250, 250, 252, 1); --n-td-color-striped-popover: rgba(250, 250, 252, 1);\"`;\n"
  },
  {
    "path": "src/table/tests/server.spec.tsx",
    "content": "import { setup } from '@css-render/vue3-ssr'\nimport { renderToString } from '@vue/server-renderer'\n/**\n * @vitest-environment node\n */\nimport { createSSRApp, h } from 'vue'\nimport { NTable } from '../..'\n\ndescribe('server side rendering', () => {\n  it('works', async () => {\n    const app = createSSRApp(() => <NTable />)\n    setup(app)\n    try {\n      await renderToString(app)\n    }\n    catch (e) {\n      expect(e).not.toBeTruthy()\n    }\n  })\n})\n"
  },
  {
    "path": "src/tabs/demos/enUS/addable.demo.vue",
    "content": "<markdown>\n# Addable\n\nAdd some tabs. Only work with `'card'` type.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { computed, ref } from 'vue'\n\nconst valueRef = ref(1)\nconst panelsRef = ref([1, 2, 3, 4, 5])\nconst addableRef = computed(() => {\n  return {\n    disabled: panelsRef.value.length >= 10\n  }\n})\nconst closableRef = computed(() => {\n  return panelsRef.value.length > 1\n})\n\nconst value = valueRef\nconst panels = panelsRef\nconst addable = addableRef\nconst closable = closableRef\n\nfunction handleAdd() {\n  const newValue = Math.max(...panelsRef.value) + 1\n  panelsRef.value.push(newValue)\n  valueRef.value = newValue\n}\n\nfunction handleClose(name: number) {\n  const { value: panels } = panelsRef\n  const nameIndex = panels.findIndex(panelName => panelName === name)\n  if (!~nameIndex)\n    return\n  panels.splice(nameIndex, 1)\n  if (name === valueRef.value) {\n    valueRef.value = panels[Math.min(nameIndex, panels.length - 1)]\n  }\n}\n</script>\n\n<template>\n  <n-tabs\n    v-model:value=\"value\"\n    type=\"card\"\n    :addable=\"addable\"\n    :closable=\"closable\"\n    tab-style=\"min-width: 80px;\"\n    @close=\"handleClose\"\n    @add=\"handleAdd\"\n  >\n    <n-tab-pane v-for=\"panel in panels\" :key=\"panel\" :name=\"panel\">\n      {{ panel }}\n    </n-tab-pane>\n    <template #prefix>\n      Prefix\n    </template>\n    <template #suffix>\n      Suffix\n    </template>\n  </n-tabs>\n</template>\n"
  },
  {
    "path": "src/tabs/demos/enUS/bar-width.demo.vue",
    "content": "<markdown>\n# Set the width of the bar\n\nDo whatever you want.\n</markdown>\n\n<template>\n  <n-tabs :bar-width=\"28\" type=\"line\">\n    <n-tab-pane name=\"oasis\" tab=\"Oasis\">\n      Wonderwall\n    </n-tab-pane>\n    <n-tab-pane name=\"the beatles\" tab=\"the Beatles\">\n      Hey Jude\n    </n-tab-pane>\n    <n-tab-pane name=\"jay chou\" tab=\"Jay Chou\">\n      Qilixiang\n    </n-tab-pane>\n  </n-tabs>\n</template>\n\n<style>\n.custom-tabs .n-tabs-bar {\n  background-color: transparent !important;\n}\n\n.custom-tabs .n-tabs-bar::after {\n  position: absolute;\n  content: '';\n  left: 0;\n  right: 0;\n  top: 0;\n  bottom: -2px;\n  border-radius: 2px;\n  background-color: var(--bar-color);\n}\n</style>\n"
  },
  {
    "path": "src/tabs/demos/enUS/basic.demo.vue",
    "content": "<markdown>\n# Basic\n</markdown>\n\n<template>\n  <n-card title=\"Song of\" style=\"margin-bottom: 16px\">\n    <n-tabs type=\"line\" animated>\n      <n-tab-pane name=\"oasis\" tab=\"Oasis\">\n        Wonderwall\n      </n-tab-pane>\n      <n-tab-pane name=\"the beatles\" tab=\"the Beatles\">\n        Hey Jude\n      </n-tab-pane>\n      <n-tab-pane name=\"jay chou\" tab=\"Jay Chou\">\n        Qilixiang\n      </n-tab-pane>\n    </n-tabs>\n  </n-card>\n  <n-card>\n    <n-tabs\n      class=\"card-tabs\"\n      default-value=\"signin\"\n      size=\"large\"\n      animated\n      pane-wrapper-style=\"margin: 0 -4px\"\n      pane-style=\"padding-left: 4px; padding-right: 4px; box-sizing: border-box;\"\n    >\n      <n-tab-pane name=\"signin\" tab=\"Sign in\">\n        <n-form>\n          <n-form-item-row label=\"Username\">\n            <n-input />\n          </n-form-item-row>\n          <n-form-item-row label=\"Password\">\n            <n-input />\n          </n-form-item-row>\n        </n-form>\n        <n-button type=\"primary\" block secondary strong>\n          Sign In\n        </n-button>\n      </n-tab-pane>\n      <n-tab-pane name=\"signup\" tab=\"Sign up\">\n        <n-form>\n          <n-form-item-row label=\"Username\">\n            <n-input />\n          </n-form-item-row>\n          <n-form-item-row label=\"Password\">\n            <n-input />\n          </n-form-item-row>\n          <n-form-item-row label=\"Reenter Password\">\n            <n-input />\n          </n-form-item-row>\n        </n-form>\n        <n-button type=\"primary\" block secondary strong>\n          Sign up\n        </n-button>\n      </n-tab-pane>\n    </n-tabs>\n  </n-card>\n</template>\n\n<style>\n.card-tabs .n-tabs-nav--bar-type {\n  padding-left: 4px;\n}\n</style>\n"
  },
  {
    "path": "src/tabs/demos/enUS/before-leave.demo.vue",
    "content": "<markdown>\n# Hook before tab switching\n\nYou can prevent or postpone tab switching.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { useMessage } from 'naive-ui'\n\nconst message = useMessage()\n\nfunction handleBeforeLeave(tabName: string) {\n  switch (tabName) {\n    case 'not-allowed':\n      message.error('Not allowed')\n      return false\n    case 'wait':\n      return new Promise<boolean>((resolve) => {\n        const messageInstance = message.loading('Wait for 1s')\n        setTimeout(() => {\n          messageInstance.destroy()\n          resolve(true)\n        }, 1000)\n      })\n    default:\n      return true\n  }\n}\n\nfunction handleUpdateValue(value: string) {\n  message.info(value)\n}\n</script>\n\n<template>\n  <n-tabs\n    type=\"line\"\n    default-value=\"okay\"\n    @before-leave=\"handleBeforeLeave\"\n    @update:value=\"handleUpdateValue\"\n  >\n    <n-tab-pane name=\"wait\" tab=\"Wait for 1s\">\n      +1s\n    </n-tab-pane>\n    <n-tab-pane name=\"not-allowed\" tab=\"Not allowed\">\n      ???\n    </n-tab-pane>\n    <n-tab-pane name=\"okay\" tab=\"Okay\">\n      Just so so\n    </n-tab-pane>\n  </n-tabs>\n</template>\n"
  },
  {
    "path": "src/tabs/demos/enUS/card.demo.vue",
    "content": "<markdown>\n# Card type\n\nSet `type='card'`.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { useMessage } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst nameRef = ref(1)\nconst message = useMessage()\nconst panelsRef = ref([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15])\n\nfunction handleClose(name: number) {\n  const { value: panels } = panelsRef\n  if (panels.length === 1) {\n    message.error('The last one!')\n    return\n  }\n  message.info(`Close ${name}`)\n  const index = panels.findIndex(v => name === v)\n  panels.splice(index, 1)\n  if (nameRef.value === name) {\n    nameRef.value = panels[index]\n  }\n}\n\nconst name = nameRef\nconst panels = panelsRef\n</script>\n\n<template>\n  <n-tabs\n    v-model:value=\"name\"\n    type=\"card\"\n    closable\n    tab-style=\"min-width: 80px;\"\n    @close=\"handleClose\"\n  >\n    <n-tab-pane\n      v-for=\"panel in panels\"\n      :key=\"panel\"\n      :tab=\"panel.toString()\"\n      :name=\"panel\"\n    >\n      {{ panel }}\n    </n-tab-pane>\n  </n-tabs>\n</template>\n"
  },
  {
    "path": "src/tabs/demos/enUS/display-directive.demo.vue",
    "content": "<markdown>\n# Display directive\n\nYou can set tab-panel's display directive to `if` or `show`. When use `show`, the tab-panel's content won't be reset after tab changes. When use `show:lazy`, the display effect is the same as `show`, but the content will be lazily loaded.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { NInput } from 'naive-ui'\nimport { defineComponent, h } from 'vue'\n\nconst showInput = defineComponent({\n  render() {\n    return h(NInput, {\n      placeholder: 'My content won\\'t be reset'\n    })\n  }\n})\n\nconst ifInput = defineComponent({\n  render() {\n    return h(NInput, {\n      placeholder: 'My content will be reset'\n    })\n  }\n})\n\nconst showLazyInput = defineComponent({\n  render() {\n    return h(NInput, {\n      placeholder:\n        'I will delay loading, and my content will not be reset afterwards'\n    })\n  }\n})\n\nconst ShowInput = showInput\nconst IfInput = ifInput\nconst ShowLazyInput = showLazyInput\n</script>\n\n<template>\n  <n-tabs default-value=\"show\">\n    <n-tab-pane name=\"show\" display-directive=\"show\" tab=\"show\">\n      <ShowInput />\n    </n-tab-pane>\n    <n-tab-pane name=\"if\" display-directive=\"if\" tab=\"if\">\n      <IfInput />\n    </n-tab-pane>\n    <n-tab-pane name=\"show:lazy\" display-directive=\"show:lazy\" tab=\"show:lazy\">\n      <ShowLazyInput />\n    </n-tab-pane>\n  </n-tabs>\n</template>\n"
  },
  {
    "path": "src/tabs/demos/enUS/flex-label.demo.vue",
    "content": "<markdown>\n# Flex tabs\n\nOnly works with `'line'` or `'bar'` typed tabs.\n</markdown>\n\n<template>\n  <n-card title=\"Song of\" style=\"margin-bottom: 16px\">\n    <n-tabs default-value=\"oasis\" justify-content=\"space-evenly\" type=\"line\">\n      <n-tab-pane name=\"oasis\" tab=\"Oasis\">\n        Wonderwall\n      </n-tab-pane>\n      <n-tab-pane name=\"the beatles\" tab=\"the Beatles\">\n        Hey Jude\n      </n-tab-pane>\n      <n-tab-pane name=\"jay chou\" tab=\"Jay Chou\">\n        Qilixiang\n      </n-tab-pane>\n    </n-tabs>\n  </n-card>\n  <n-card title=\"Too Simple\">\n    <n-tabs default-value=\"signin\" size=\"large\" justify-content=\"space-evenly\">\n      <n-tab-pane name=\"signin\" tab=\"Sign in\">\n        <n-form>\n          <n-form-item-row label=\"Username\">\n            <n-input />\n          </n-form-item-row>\n          <n-form-item-row label=\"Password\">\n            <n-input />\n          </n-form-item-row>\n        </n-form>\n        <n-button type=\"primary\" block secondary strong>\n          Sign In\n        </n-button>\n      </n-tab-pane>\n      <n-tab-pane name=\"signup\" tab=\"Sign up\">\n        <n-form>\n          <n-form-item-row label=\"Username\">\n            <n-input />\n          </n-form-item-row>\n          <n-form-item-row label=\"Password\">\n            <n-input />\n          </n-form-item-row>\n          <n-form-item-row label=\"Reenter Password\">\n            <n-input />\n          </n-form-item-row>\n        </n-form>\n        <n-button type=\"primary\" block secondary strong>\n          Sign up\n        </n-button>\n      </n-tab-pane>\n    </n-tabs>\n  </n-card>\n</template>\n"
  },
  {
    "path": "src/tabs/demos/enUS/index.demo-entry.md",
    "content": "# Tabs\n\nSwitch contents in same area.\n\n<n-alert type=\"warning\" title=\"Note\" :bordered=\"false\">\n  <n-text code>n-tabs</n-text> will extract default tab value from default slot, so there would be a vue slot warning. If you don't want to see the warning, you should give component a  <n-text code>default-value</n-text>.\n</n-alert>\n\n## Demos\n\n```demo\nbasic.vue\nsegment.vue\ncard.vue\nflex-label.vue\nprefix.vue\nsize.vue\ndisplay-directive.vue\naddable.vue\nbefore-leave.vue\nno-pane.vue\nupdate-bar-manually.vue\nbar-width.vue\ntrigger.vue\nplacement.vue\n```\n\n## API\n\n### Tabs Props\n\n| Name | Type | Default | Description | Version |\n| --- | --- | --- | --- | --- |\n| addable | `boolean \\| { disabled?: boolean }` | `false` | Whether to allow adding a tag. Only works when the tag's `type` is `card`. |  |\n| add-tab-class | `string` | `undefined` | Class of the add tab. | 2.37.0 |\n| add-tab-style | `string \\| object` | `undefined` | Style of the add tab. | 2.37.0 |\n| animated | `boolean` | `false` | Whether to activate tab switching animation. It has no effect if `placement` is `'left'` or `'right'`. | 2.27.0 |\n| bar-width | `number` | `undefined` | The width of the tab bar. | 2.25.0 |\n| closable | `boolean` | `false` | Whether to allow the tag to be closed. Only works when the tag's `type` is `card`. |  |\n| default-value | `string \\| number` | `undefined` | Default value in uncontrolled mode. |  |\n| justify-content | `'space-between' \\| 'space-around' \\| 'space-evenly' \\| 'start' \\| 'center' \\| 'end'` | `undefined` | Justify-content value of `flex` layout. Only works with `'line'` or `'bar'` typed tabs. | `space-*` 2.29.1 |\n| size | `'small' \\| 'medium' \\| 'large'` | `'medium'` | Size of tabs. |  |\n| pane-class | `string` | `undefined` | Class of the pane. |  |\n| pane-style | `string \\| object` | `undefined` | Style of the pane. |  |\n| pane-wrapper-class | `string` | `undefined` | Class of the pane wrapper. | 2.34.4 |\n| pane-wrapper-style | `string \\| object` | `undefined` | Style of the pane wrapper. | 2.34.4 |\n| placement | `'left' \\| 'right' \\| 'top' \\| 'bottom'` | `'top'` | Placement of tabs. It won't work with `n-tabs` whose `type` is `'segment'`. | 2.34.4 |\n| tab-class | `string` | `undefined` | Class of the tab. | 2.37.0 |\n| tab-style | `string \\| object` | `undefined` | Style of the tab. |  |\n| tabs-padding | `number` | `0` | Left & right `padding` of the group of tabs. |  |\n| trigger | `'click' \\| 'hover'` | `'click'` | Trigger of activating a tab | 2.27.0 |\n| type | `'bar' \\| 'line' \\| 'card' \\| 'segment'` | `'bar'` | Tabs type. |  |\n| value | `string \\| number` | `undefined` | Value in controlled mode. |  |\n| on-add | `() => void` | `undefined` | Callback function triggered when adding tag. |  |\n| on-before-leave | `(activeName: string \\| number, oldActiveName: string \\| number \\| null) => boolean \\| Promise<boolean>` | `undefined` | Hook function executed before switching tabs. Returning `false` or promise resolving `false` or promise rejection will prevent tab switching. |  |\n| on-close | `(name: string \\| number) => void` | `undefined` | Callback function triggered when closing a tag. |  |\n| on-update:value | `(value: string \\| number) => void` | `undefined` | Callback function triggered when the value changes. |  |\n\n### TabPane Props\n\n| Name | Type | Default | Description | Version |\n| --- | --- | --- | --- | --- |\n| closable | `boolean` | `false` | Whether to allow the tag to be closed. Only works when the tag's `type` is `card`. |  |\n| disabled | `boolean` | `false` | Whether to disable the tab. |  |\n| display-directive | `'if' \\| 'show' \\| 'show:lazy'` | `'if'` | The directive to use in conditionally rendering. `if` will use `v-if` and `show` will use `v-show`. When using the `show` directive, the status of tab won't be reset after tab changes. When use `show:lazy`, the display effect is the same as `show`, but the content will be lazily loaded. |  |\n| name | `string \\| number` | `undefined` | Required, the name of the tab. |  |\n| tab | `string \\| VNode \\| () => VNodeChild` | `undefined` | Tab label. |  |\n| tab-props | `Object` | `undefined` | DOM attributes of tab label. | 2.24.2 |\n\n### Tab Props\n\n| Name | Type | Default | Description |\n| --- | --- | --- | --- |\n| closable | `boolean` | `false` | Whether to allow the tag to be closed. Only works when the tag's `type` is `card`. |\n| disabled | `boolean` | `false` | Whether to disable. |\n| name | `string \\| number` | `undefined` | Required, the name of the tab. |\n\n### Tabs Slots\n\n| Name    | Parameters | Description   |\n| ------- | ---------- | ------------- |\n| default | `()`       | Tabs content. |\n| prefix  | `()`       | Tabs prefix.  |\n| suffix  | `()`       | Tabs suffix.  |\n\n### TabPane Slots\n\n| Name    | Parameters | Description        |\n| ------- | ---------- | ------------------ |\n| default | `()`       | Tab pane content.  |\n| tab     | `()`       | Tab label content. |\n\n### Tab Slots\n\n| Name    | Parameters | Description  |\n| ------- | ---------- | ------------ |\n| default | `()`       | Tab content. |\n\n### Tabs Methods\n\n| Name            | Type         | Description              | Version |\n| --------------- | ------------ | ------------------------ | ------- |\n| syncBarPosition | `() => void` | Sync tab bar's position. | 2.24.0  |\n"
  },
  {
    "path": "src/tabs/demos/enUS/no-pane.demo.vue",
    "content": "<markdown>\n# No pane\n\n`n-tabs` always display a pane. If you only want to show tab, use `n-tab` instead of `n-tab-pane`.\n</markdown>\n\n<template>\n  <n-tabs type=\"line\">\n    <n-tab name=\"Riders On the Storm\">\n      Riders On the Storm\n    </n-tab>\n    <n-tab name=\"Light My Fire\">\n      Light My Fire\n    </n-tab>\n    <n-tab name=\"Berak On Through\">\n      Berak On Through\n    </n-tab>\n  </n-tabs>\n</template>\n"
  },
  {
    "path": "src/tabs/demos/enUS/placement.demo.vue",
    "content": "<markdown>\n# Tabs placement\n</markdown>\n\n<script setup lang=\"ts\">\nimport type { TabsProps } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst placement = ref<NonNullable<TabsProps['placement']>>('left')\nconst type = ref<TabsProps['type']>('card')\n</script>\n\n<template>\n  <n-space vertical>\n    <n-radio-group v-model:value=\"placement\">\n      <n-radio label=\"top\" value=\"top\" />\n      <n-radio label=\"bottom\" value=\"bottom\" />\n      <n-radio label=\"left\" value=\"left\" />\n      <n-radio label=\"right\" value=\"right\" />\n    </n-radio-group>\n    <n-radio-group v-model:value=\"type\">\n      <n-radio label=\"card\" value=\"card\" />\n      <n-radio label=\"bar\" value=\"bar\" />\n      <n-radio label=\"line\" value=\"line\" />\n    </n-radio-group>\n    <n-tabs\n      :key=\"type + placement\"\n      :type=\"type\"\n      animated\n      :placement=\"placement\"\n      :style=\"\n        placement === 'left' || placement === 'right'\n          ? { height: '240px' }\n          : undefined\n      \"\n    >\n      <n-tab-pane name=\"oasis\" tab=\"Oasis\">\n        Wonderwall\n      </n-tab-pane>\n      <n-tab-pane name=\"the beatles\" tab=\"the Beatles\">\n        Hey Jude\n      </n-tab-pane>\n      <n-tab-pane name=\"jay chou\" tab=\"Jay Chou\">\n        Qilixiang\n      </n-tab-pane>\n      <n-tab-pane name=\"oasis1\" tab=\"Oasis1\">\n        Wonderwall\n      </n-tab-pane>\n      <n-tab-pane name=\"the beatles1\" tab=\"the Beatles1\">\n        Hey Jude\n      </n-tab-pane>\n      <n-tab-pane name=\"jay chou1\" tab=\"Jay Chou1\">\n        Qilixiang\n      </n-tab-pane>\n      <n-tab-pane name=\"oasis2\" tab=\"Oasis2\">\n        Wonderwall\n      </n-tab-pane>\n      <n-tab-pane name=\"the beatles2\" tab=\"the Beatles2\">\n        Hey Jude\n      </n-tab-pane>\n      <n-tab-pane name=\"jay chou2\" tab=\"Jay Chou2\">\n        Qilixiang\n      </n-tab-pane>\n      <n-tab-pane name=\"oasis3\" tab=\"Oasis3\">\n        Wonderwall\n      </n-tab-pane>\n      <n-tab-pane name=\"the beatles3\" tab=\"the Beatles3\">\n        Hey Jude\n      </n-tab-pane>\n      <n-tab-pane name=\"jay chou3\" tab=\"Jay Chou3\">\n        Qilixiang\n      </n-tab-pane>\n      <n-tab-pane name=\"oasis4\" tab=\"Oasis4\">\n        Wonderwall\n      </n-tab-pane>\n      <n-tab-pane name=\"the beatles4\" tab=\"the Beatles4\">\n        Hey Jude\n      </n-tab-pane>\n      <n-tab-pane name=\"jay chou4\" tab=\"Jay Chou4\">\n        Qilixiang\n      </n-tab-pane>\n      <n-tab-pane name=\"oasis5\" tab=\"Oasis5\">\n        Wonderwall\n      </n-tab-pane>\n      <n-tab-pane name=\"the beatles5\" tab=\"the Beatles5\">\n        Hey Jude\n      </n-tab-pane>\n      <n-tab-pane name=\"jay chou5\" tab=\"Jay Chou5\">\n        Qilixiang\n      </n-tab-pane>\n    </n-tabs>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/tabs/demos/enUS/prefix.demo.vue",
    "content": "<markdown>\n# Prefix & suffix\n\nUse `prefix` & `suffix` slot to add prefix & suffix.\n</markdown>\n\n<template>\n  <n-tabs default-value=\"oasis\">\n    <template #prefix>\n      Prefix\n    </template>\n    <n-tab-pane name=\"oasis\" tab=\"Oasis\">\n      Wonderwall\n    </n-tab-pane>\n    <n-tab-pane name=\"the beatles\" tab=\"the Beatles\">\n      Hey Jude\n    </n-tab-pane>\n    <n-tab-pane name=\"jay chou\" tab=\"Jay Chou\">\n      Qilixiang\n    </n-tab-pane>\n    <template #suffix>\n      Suffix\n    </template>\n  </n-tabs>\n</template>\n"
  },
  {
    "path": "src/tabs/demos/enUS/segment.demo.vue",
    "content": "<markdown>\n# Segment\n\nTabs of segment type.\n</markdown>\n\n<template>\n  <n-tabs type=\"segment\" animated>\n    <n-tab-pane name=\"oasis\" tab=\"Oasis\">\n      Wonderwall\n    </n-tab-pane>\n    <n-tab-pane name=\"the beatles\" tab=\"the Beatles\">\n      Hey Jude\n    </n-tab-pane>\n    <n-tab-pane name=\"jay chou\" tab=\"Jay Chou\">\n      Qilixiang\n    </n-tab-pane>\n  </n-tabs>\n</template>\n"
  },
  {
    "path": "src/tabs/demos/enUS/size.demo.vue",
    "content": "<markdown>\n# Size\n\nTabs may have different sizes.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst size = ref<'small' | 'medium' | 'large'>('medium')\n</script>\n\n<template>\n  <n-space vertical>\n    <n-radio-group v-model:value=\"size\">\n      <n-space>\n        <n-radio value=\"small\">\n          Small\n        </n-radio>\n        <n-radio value=\"medium\">\n          Not Small\n        </n-radio>\n        <n-radio value=\"large\">\n          Not Not Small\n        </n-radio>\n      </n-space>\n    </n-radio-group>\n    <n-tabs type=\"bar\" :size=\"size\">\n      <n-tab-pane name=\"oasis\" tab=\"Oasis\">\n        Wonderwall\n      </n-tab-pane>\n      <n-tab-pane name=\"the beatles\" tab=\"the Beatles\">\n        Hey Jude\n      </n-tab-pane>\n      <n-tab-pane name=\"jay chou\" tab=\"Jay Chou\">\n        Qilixiang\n      </n-tab-pane>\n    </n-tabs>\n    <n-tabs type=\"line\" :size=\"size\">\n      <n-tab-pane name=\"oasis\" tab=\"Oasis\">\n        Wonderwall\n      </n-tab-pane>\n      <n-tab-pane name=\"the beatles\" tab=\"the Beatles\">\n        Hey Jude\n      </n-tab-pane>\n      <n-tab-pane name=\"jay chou\" tab=\"Jay Chou\">\n        Qilixiang\n      </n-tab-pane>\n    </n-tabs>\n    <n-tabs type=\"card\" :size=\"size\" closable>\n      <n-tab-pane name=\"oasis\" tab=\"Oasis\">\n        Wonderwall\n      </n-tab-pane>\n      <n-tab-pane name=\"the beatles\" tab=\"the Beatles\">\n        Hey Jude\n      </n-tab-pane>\n      <n-tab-pane name=\"jay chou\" tab=\"Jay Chou\">\n        Qilixiang\n      </n-tab-pane>\n    </n-tabs>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/tabs/demos/enUS/trigger.demo.vue",
    "content": "<markdown>\n# Trigger\n\nYou can use `trigger='hover'` to trigger activated tab.\n</markdown>\n\n<template>\n  <n-tabs type=\"line\" trigger=\"hover\">\n    <n-tab-pane name=\"oasis\" tab=\"Oasis\">\n      Wonderwall\n    </n-tab-pane>\n    <n-tab-pane name=\"the beatles\" tab=\"the Beatles\">\n      Hey Jude\n    </n-tab-pane>\n    <n-tab-pane name=\"jay chou\" tab=\"Jay Chou\">\n      Qilixiang\n    </n-tab-pane>\n  </n-tabs>\n</template>\n"
  },
  {
    "path": "src/tabs/demos/enUS/update-bar-manually.demo.vue",
    "content": "<markdown>\n  # Update bar manually\n\n  Since `n-tabs` renders children directly, it can't understand your intention to update active tab. In some edge cases, you need to update bar position manually.\n  </markdown>\n\n<script lang=\"ts\" setup>\nimport type { TabsInst } from 'naive-ui'\nimport { nextTick, ref } from 'vue'\n\nconst tabsInstRef = ref<TabsInst | null>(null)\nconst tabsRef = ref(['a', 'b'])\nconst valueRef = ref('a')\n\nfunction handleClick() {\n  tabsRef.value.reverse()\n  valueRef.value = 'a'\n  nextTick(() => tabsInstRef.value?.syncBarPosition())\n}\n\nconst tabs = tabsRef\nconst value = valueRef\n</script>\n\n<template>\n  <n-space vertical>\n    <n-button @click=\"handleClick\">\n      Useless change\n    </n-button>\n    <n-tabs ref=\"tabsInstRef\" v-model:value=\"value\">\n      <n-tab v-for=\"tab in tabs\" :key=\"tab\" :name=\"tab\">\n        I'm {{ tab }}\n      </n-tab>\n    </n-tabs>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/tabs/demos/zhCN/addable-debug.demo.vue",
    "content": "<markdown>\n# Addable debug\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { NTab, NTabs } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst itemsRef = ref<{ id: string, name: string }[]>([])\nlet i = 0\n\nfunction handleAdd() {\n  i += 1\n  itemsRef.value.push({\n    id: `${i}`,\n    name: `name-${i}`\n  })\n}\n\nconst items = itemsRef.value\n</script>\n\n<template>\n  <NTabs type=\"card\" addable @add=\"handleAdd\">\n    <NTab\n      v-for=\"item in items\"\n      :key=\"item.id\"\n      :name=\"item.name\"\n      :tab=\"item.name\"\n    />\n  </NTabs>\n</template>\n"
  },
  {
    "path": "src/tabs/demos/zhCN/addable.demo.vue",
    "content": "<markdown>\n# 可增加\n\n增加一些标签页。只对 `'card'` 类型生效。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { computed, ref } from 'vue'\n\nconst valueRef = ref(1)\nconst panelsRef = ref([1, 2, 3, 4, 5])\nconst addableRef = computed(() => {\n  return {\n    disabled: panelsRef.value.length >= 10\n  }\n})\nconst closableRef = computed(() => {\n  return panelsRef.value.length > 1\n})\n\nconst value = valueRef\nconst panels = panelsRef\nconst addable = addableRef\nconst closable = closableRef\n\nfunction handleAdd() {\n  const newValue = Math.max(...panelsRef.value) + 1\n  panelsRef.value.push(newValue)\n  valueRef.value = newValue\n}\n\nfunction handleClose(name: number) {\n  const { value: panels } = panelsRef\n  const nameIndex = panels.findIndex(panelName => panelName === name)\n  if (!~nameIndex)\n    return\n  panels.splice(nameIndex, 1)\n  if (name === valueRef.value) {\n    valueRef.value = panels[Math.min(nameIndex, panels.length - 1)]\n  }\n}\n</script>\n\n<template>\n  <n-tabs\n    v-model:value=\"value\"\n    type=\"card\"\n    :addable=\"addable\"\n    :closable=\"closable\"\n    tab-style=\"min-width: 80px;\"\n    @close=\"handleClose\"\n    @add=\"handleAdd\"\n  >\n    <n-tab-pane v-for=\"panel in panels\" :key=\"panel\" :name=\"panel\">\n      {{ panel }}\n    </n-tab-pane>\n    <template #prefix>\n      Prefix\n    </template>\n    <template #suffix>\n      Suffix\n    </template>\n  </n-tabs>\n</template>\n"
  },
  {
    "path": "src/tabs/demos/zhCN/animation-debug.demo.vue",
    "content": "<markdown>\n# Animation debug\n</markdown>\n\n<template>\n  <n-card title=\"歌曲\" style=\"margin-bottom: 16px\">\n    <n-tabs type=\"card\">\n      <n-tab-pane name=\"oasis\" tab=\"Oasis\" display-directive=\"show:lazy\">\n        <n-card>\n          <n-tabs\n            class=\"card-tabs\"\n            default-value=\"signin\"\n            size=\"large\"\n            animated\n            style=\"margin: 0 -4px\"\n            pane-style=\"padding-left: 4px; padding-right: 4px; box-sizing: border-box;\"\n          >\n            <n-tab-pane name=\"signin\" tab=\"登录\">\n              <n-form>\n                <n-form-item-row label=\"用户名\">\n                  <n-input />\n                </n-form-item-row>\n                <n-form-item-row label=\"密码\">\n                  <n-input />\n                </n-form-item-row>\n              </n-form>\n              <n-button type=\"primary\" block secondary strong>\n                登录\n              </n-button>\n            </n-tab-pane>\n            <n-tab-pane name=\"signup\" tab=\"注册\">\n              <n-form>\n                <n-form-item-row label=\"用户名\">\n                  <n-input />\n                </n-form-item-row>\n                <n-form-item-row label=\"密码\">\n                  <n-input />\n                </n-form-item-row>\n                <n-form-item-row label=\"重复密码\">\n                  <n-input />\n                </n-form-item-row>\n              </n-form>\n              <n-button type=\"primary\" block secondary strong>\n                注册\n              </n-button>\n            </n-tab-pane>\n          </n-tabs>\n        </n-card>\n      </n-tab-pane>\n      <n-tab-pane\n        name=\"the beatles\"\n        tab=\"the Beatles\"\n        display-directive=\"show:lazy\"\n      >\n        Hey Jude\n      </n-tab-pane>\n      <n-tab-pane name=\"jay chou\" tab=\"周杰伦\" display-directive=\"show:lazy\">\n        七里香\n      </n-tab-pane>\n    </n-tabs>\n  </n-card>\n</template>\n\n<style>\n.card-tabs .n-tabs-nav--bar-type {\n  padding-left: 4px;\n}\n</style>\n"
  },
  {
    "path": "src/tabs/demos/zhCN/animationx-debug.demo.vue",
    "content": "<markdown>\n# Animationx debug\n</markdown>\n\n<template>\n  <n-card title=\"歌曲\" style=\"margin-bottom: 16px\">\n    <n-tabs type=\"line\" animated>\n      <n-tab-pane name=\"oasis\" tab=\"Oasis\" display-directive=\"show\">\n        Wonderwall<br>\n        Wonderwall<br>\n        Wonderwall<br>\n        Wonderwall<br>\n        Wonderwall<br>\n        Wonderwall<br>\n        Wonderwall<br>\n        Wonderwall<br>\n        Wonderwall<br>\n      </n-tab-pane>\n      <n-tab-pane name=\"jay chou\" tab=\"周杰伦\" display-directive=\"show\">\n        七里香\n      </n-tab-pane>\n      <n-tab-pane name=\"the beatles\" tab=\"the Beatles\" display-directive=\"show\">\n        Hey Jude<br>\n        Hey Jude<br>\n        Hey Jude<br>\n        Hey Jude<br>\n        Hey Jude<br>\n      </n-tab-pane>\n    </n-tabs>\n  </n-card>\n</template>\n\n<style>\n.card-tabs .n-tabs-nav--bar-type {\n  padding-left: 4px;\n}\n</style>\n"
  },
  {
    "path": "src/tabs/demos/zhCN/bar-width.demo.vue",
    "content": "<markdown>\n# 设置 Tab 条的长度\n\n想怎么搞就怎么搞。\n</markdown>\n\n<template>\n  <n-tabs :bar-width=\"28\" type=\"line\" class=\"custom-tabs\">\n    <n-tab-pane name=\"oasis\" tab=\"Oasis\">\n      Wonderwall\n    </n-tab-pane>\n    <n-tab-pane name=\"the beatles\" tab=\"the Beatles\">\n      Hey Jude\n    </n-tab-pane>\n    <n-tab-pane name=\"jay chou\" tab=\"周杰伦\">\n      七里香\n    </n-tab-pane>\n  </n-tabs>\n</template>\n\n<style>\n.custom-tabs .n-tabs-bar {\n  background-color: transparent !important;\n}\n\n.custom-tabs .n-tabs-bar::after {\n  position: absolute;\n  content: '';\n  left: 0;\n  right: 0;\n  top: 0;\n  bottom: -2px;\n  border-radius: 2px;\n  background-color: var(--bar-color);\n}\n</style>\n"
  },
  {
    "path": "src/tabs/demos/zhCN/basic.demo.vue",
    "content": "<markdown>\n# 基础用法\n</markdown>\n\n<template>\n  <n-card title=\"歌曲\" style=\"margin-bottom: 16px\">\n    <n-tabs type=\"line\" animated>\n      <n-tab-pane name=\"oasis\" tab=\"Oasis\">\n        Wonderwall\n      </n-tab-pane>\n      <n-tab-pane name=\"the beatles\" tab=\"the Beatles\">\n        Hey Jude\n      </n-tab-pane>\n      <n-tab-pane name=\"jay chou\" tab=\"周杰伦\">\n        七里香\n      </n-tab-pane>\n    </n-tabs>\n  </n-card>\n  <n-card>\n    <n-tabs\n      class=\"card-tabs\"\n      default-value=\"signin\"\n      size=\"large\"\n      animated\n      pane-wrapper-style=\"margin: 0 -4px\"\n      pane-style=\"padding-left: 4px; padding-right: 4px; box-sizing: border-box;\"\n    >\n      <n-tab-pane name=\"signin\" tab=\"登录\">\n        <n-form>\n          <n-form-item-row label=\"用户名\">\n            <n-input />\n          </n-form-item-row>\n          <n-form-item-row label=\"密码\">\n            <n-input />\n          </n-form-item-row>\n        </n-form>\n        <n-button type=\"primary\" block secondary strong>\n          登录\n        </n-button>\n      </n-tab-pane>\n      <n-tab-pane name=\"signup\" tab=\"注册\">\n        <n-form>\n          <n-form-item-row label=\"用户名\">\n            <n-input />\n          </n-form-item-row>\n          <n-form-item-row label=\"密码\">\n            <n-input />\n          </n-form-item-row>\n          <n-form-item-row label=\"重复密码\">\n            <n-input />\n          </n-form-item-row>\n        </n-form>\n        <n-button type=\"primary\" block secondary strong>\n          注册\n        </n-button>\n      </n-tab-pane>\n    </n-tabs>\n  </n-card>\n</template>\n\n<style>\n.card-tabs .n-tabs-nav--bar-type {\n  padding-left: 4px;\n}\n</style>\n"
  },
  {
    "path": "src/tabs/demos/zhCN/before-leave.demo.vue",
    "content": "<markdown>\n# 切换 Tab 前的回调\n\n你可以延迟或阻止 Tab 切换。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { useMessage } from 'naive-ui'\n\nconst message = useMessage()\n\nfunction handleBeforeLeave(tabName: string) {\n  switch (tabName) {\n    case 'not-allowed':\n      message.error('不许进来')\n      return false\n    case 'wait':\n      return new Promise<boolean>((resolve) => {\n        const messageInstance = message.loading('Wait for 1s')\n        setTimeout(() => {\n          messageInstance.destroy()\n          resolve(true)\n        }, 1000)\n      })\n    default:\n      return true\n  }\n}\n\nfunction handleUpdateValue(value: string) {\n  message.info(value)\n}\n</script>\n\n<template>\n  <n-tabs\n    type=\"line\"\n    default-value=\"okay\"\n    @before-leave=\"handleBeforeLeave\"\n    @update:value=\"handleUpdateValue\"\n  >\n    <n-tab-pane name=\"wait\" tab=\"等 1 秒\">\n      +1s\n    </n-tab-pane>\n    <n-tab-pane name=\"not-allowed\" tab=\"不许进来\">\n      ???\n    </n-tab-pane>\n    <n-tab-pane name=\"okay\" tab=\"可以\">\n      就那么回事吧\n    </n-tab-pane>\n  </n-tabs>\n</template>\n"
  },
  {
    "path": "src/tabs/demos/zhCN/card.demo.vue",
    "content": "<markdown>\n# 卡片类型\n\n设定 `type='card'`。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { useMessage } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst nameRef = ref(1)\nconst message = useMessage()\nconst panelsRef = ref([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15])\n\nfunction handleClose(name: number) {\n  const { value: panels } = panelsRef\n  if (panels.length === 1) {\n    message.error('最后一个了')\n    return\n  }\n  message.info(`关掉 ${name}`)\n  const index = panels.findIndex(v => name === v)\n  panels.splice(index, 1)\n  if (nameRef.value === name) {\n    nameRef.value = panels[index]\n  }\n}\n\nconst name = nameRef\nconst panels = panelsRef\n</script>\n\n<template>\n  <n-tabs\n    v-model:value=\"name\"\n    type=\"card\"\n    closable\n    tab-style=\"min-width: 80px;\"\n    @close=\"handleClose\"\n  >\n    <n-tab-pane\n      v-for=\"panel in panels\"\n      :key=\"panel\"\n      :tab=\"panel.toString()\"\n      :name=\"panel\"\n    >\n      {{ panel }}\n    </n-tab-pane>\n  </n-tabs>\n</template>\n"
  },
  {
    "path": "src/tabs/demos/zhCN/display-directive.demo.vue",
    "content": "<markdown>\n# 展示指令\n\n可以制定标签页展示的指令为 `if` 、 `show` 或者 `show:lazy` 。使用 `show` 的时候标签页内容不会随着切换重置。使用 `show:lazy` 的时候显示效果跟 `show` 一致，不过内容会进行延迟加载。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { NInput } from 'naive-ui'\nimport { defineComponent, h } from 'vue'\n\nconst showInput = defineComponent({\n  render() {\n    return h(NInput, {\n      placeholder: '我的内容不会被重置'\n    })\n  }\n})\n\nconst ifInput = defineComponent({\n  render() {\n    return h(NInput, {\n      placeholder: '我的内容会被重置'\n    })\n  }\n})\n\nconst showLazyInput = defineComponent({\n  render() {\n    return h(NInput, {\n      placeholder: '我会延迟加载，并且之后我的内容不会被重置'\n    })\n  }\n})\n\nconst ShowInput = showInput\nconst IfInput = ifInput\nconst ShowLazyInput = showLazyInput\n</script>\n\n<template>\n  <n-tabs default-value=\"show\">\n    <n-tab-pane name=\"show\" display-directive=\"show\" tab=\"show\">\n      <ShowInput />\n    </n-tab-pane>\n    <n-tab-pane name=\"if\" display-directive=\"if\" tab=\"if\">\n      <IfInput />\n    </n-tab-pane>\n    <n-tab-pane name=\"show:lazy\" display-directive=\"show:lazy\" tab=\"show:lazy\">\n      <ShowLazyInput />\n    </n-tab-pane>\n  </n-tabs>\n</template>\n"
  },
  {
    "path": "src/tabs/demos/zhCN/flex-label.demo.vue",
    "content": "<markdown>\n# Flex 布局的标签\n\n只对 `'line'` 和 `'bar'` 类型的 Tabs 生效。\n</markdown>\n\n<template>\n  <n-card title=\"歌曲\" style=\"margin-bottom: 16px\">\n    <n-tabs default-value=\"oasis\" justify-content=\"space-evenly\" type=\"line\">\n      <n-tab-pane name=\"oasis\" tab=\"Oasis\">\n        Wonderwall\n      </n-tab-pane>\n      <n-tab-pane name=\"the beatles\" tab=\"the Beatles\">\n        Hey Jude\n      </n-tab-pane>\n      <n-tab-pane name=\"jay chou\" tab=\"周杰伦\">\n        七里香\n      </n-tab-pane>\n    </n-tabs>\n  </n-card>\n  <n-card title=\"Too Simple\">\n    <n-tabs default-value=\"signin\" size=\"large\" justify-content=\"space-evenly\">\n      <n-tab-pane name=\"signin\" tab=\"登录\">\n        <n-form>\n          <n-form-item-row label=\"用户名\">\n            <n-input />\n          </n-form-item-row>\n          <n-form-item-row label=\"密码\">\n            <n-input />\n          </n-form-item-row>\n        </n-form>\n        <n-button type=\"primary\" block secondary strong>\n          登录\n        </n-button>\n      </n-tab-pane>\n      <n-tab-pane name=\"signup\" tab=\"注册\">\n        <n-form>\n          <n-form-item-row label=\"用户名\">\n            <n-input />\n          </n-form-item-row>\n          <n-form-item-row label=\"密码\">\n            <n-input />\n          </n-form-item-row>\n          <n-form-item-row label=\"重复密码\">\n            <n-input />\n          </n-form-item-row>\n        </n-form>\n        <n-button type=\"primary\" block secondary strong>\n          注册\n        </n-button>\n      </n-tab-pane>\n    </n-tabs>\n  </n-card>\n</template>\n"
  },
  {
    "path": "src/tabs/demos/zhCN/index.demo-entry.md",
    "content": "# 标签页 Tabs\n\n在同一块区域切换内容。\n\n<n-alert type=\"warning\" title=\"注意\" :bordered=\"false\">\n  <n-text code>n-tabs</n-text> 默认情况下会从 slot 获取默认展示的 tab 值，因此会产生一个 vue slot 的 warning。如果你不想看到这个 warning，请设定一个 <n-text code>default-value</n-text>。\n</n-alert>\n\n## 演示\n\n```demo\nbasic.vue\nsegment.vue\ncard.vue\nflex-label.vue\nprefix.vue\nsize.vue\ndisplay-directive.vue\naddable.vue\nbefore-leave.vue\nno-pane.vue\nupdate-bar-manually.vue\nbar-width.vue\ntrigger.vue\nplacement.vue\nline-debug.vue\nstyle-inherit-debug.vue\nshadow-debug.vue\nunkeyed-debug.vue\naddable-debug.vue\nanimation-debug.vue\nanimationx-debug.vue\nnone-debug.vue\nmodal-debug.vue\n```\n\n## API\n\n### Tabs Props\n\n| 名称 | 类型 | 默认值 | 说明 | 版本 |\n| --- | --- | --- | --- | --- |\n| addable | `boolean \\| { disabled?: boolean }` | `false` | 是否允许添加标签，只在标签的 `type` 为 `card` 时生效 |  |\n| add-tab-class | `string` | `undefined` | 添加标签标签的类名 | 2.37.0 |\n| add-tab-style | `string \\| object` | `undefined` | 添加标签标签的样式 | 2.37.0 |\n| animated | `boolean` | `false` | 标签页切换是否使用动画，当 `placement` 为 `'left'` 或 `'right'` 时不生效 | 2.27.0 |\n| bar-width | `number` | `undefined` | 标签条的宽度 | 2.25.0 |\n| closable | `boolean` | `false` | 是否允许关闭标签，只在标签的 `type` 为 `card` 时生效 |  |\n| default-value | `string \\| number` | `undefined` | 非受控模式下的默认值 |  |\n| justify-content | `'space-between' \\| 'space-around' \\| 'space-evenly' \\| 'start' \\| 'center' \\| 'end'` | `undefined` | `flex` 布局下主轴的排列方式，只对 `'line'` 和 `'bar'` 类型生效 | `space-*` 2.29.1 |\n| size | `'small' \\| 'medium' \\| 'large'` | `'medium'` | 标签页的尺寸 |  |\n| pane-class | `string` | `undefined` | 面板的类名 |  |\n| pane-style | `string \\| object` | `undefined` | 面板的样式 |  |\n| pane-wrapper-class | `string` | `undefined` | 面板容器的类名 | 2.34.4 |\n| pane-wrapper-style | `string \\| object` | `undefined` | 面板容器的样式 | 2.34.4 |\n| placement | `'left' \\| 'right' \\| 'top' \\| 'bottom'` | `'top'` | 标签的位置，对于 `'segment'` 类型的 `n-tabs` 不生效 | 2.34.4 |\n| tab-class | `string` | `undefined` | 标签的类名 | 2.37.0 |\n| tab-style | `string \\| object` | `undefined` | 标签的样式 |  |\n| tabs-padding | `number` | `0` | 全部标签最左和最右的 `padding` |  |\n| trigger | `'click' \\| 'hover'` | `'click'` | 触发 tab 的方式 | 2.27.0 |\n| type | `'bar' \\| 'line' \\| 'card' \\| 'segment'` | `'bar'` | 标签类型 |  |\n| value | `string \\| number` | `undefined` | 受控模式下的值 |  |\n| on-add | `() => void` | `undefined` | 添加标签的回调函数 |  |\n| on-before-leave | `(name: string \\| number, oldName: string \\| number \\| null) => boolean \\| Promise<boolean>` | `undefined` | 切换标签之前的钩子函数，返回 `false` 或 promise resolve `false` 或 promise reject 会阻止切换 |  |\n| on-close | `(name: string \\| number) => void` | `undefined` | 关闭标签的回调函数 |  |\n| on-update:value | `(value: string \\| number) => void` | `undefined` | 选中发生改变时的回调函数 |  |\n\n### TabPane Props\n\n| 名称 | 类型 | 默认值 | 说明 | 版本 |\n| --- | --- | --- | --- | --- |\n| closable | `boolean` | `false` | 是否允许关闭标签，只在标签的 `type` 为 `card` 时生效 |  |\n| disabled | `boolean` | `false` | 是否禁用 |  |\n| display-directive | `'if' \\| 'show' \\| 'show:lazy'` | `'if'` | 选择性渲染使用的指令，`if` 对应 `v-if`，`show` 对应 `v-show`，使用 `show` 的时候标签页状态切换后不会被重置，使用 `show:lazy` 的时候显示效果跟 `show` 一致，不过内容会进行延迟加载 |  |\n| name | `string \\| number` | `undefined` | 必填，标签的名称 |  |\n| tab | `string \\| VNode \\| () => VNodeChild` | `undefined` | 标签的 `tab` |  |\n| tab-props | `Object` | `undefined` | 标签 `tab` 的 DOM 属性 | 2.24.2 |\n\n### Tab Props\n\n| 名称 | 类型 | 默认值 | 说明 |\n| --- | --- | --- | --- |\n| closable | `boolean` | `false` | 是否允许关闭标签，只在标签的 `type` 为 `card` 时生效 |\n| disabled | `boolean` | `false` | 是否禁用 |\n| name | `string \\| number` | `undefined` | 必填，标签的名称 |\n\n### Tabs Slots\n\n| 名称    | 参数 | 说明       |\n| ------- | ---- | ---------- |\n| default | `()` | 标签的内容 |\n| prefix  | `()` | 标签的前缀 |\n| suffix  | `()` | 标签的后缀 |\n\n### TabPane Slots\n\n| 名称    | 参数 | 说明                |\n| ------- | ---- | ------------------- |\n| default | `()` | 标签项的内容        |\n| tab     | `()` | 标签项 `tab` 的内容 |\n\n### Tab Slots\n\n| 名称    | 参数 | 说明       |\n| ------- | ---- | ---------- |\n| default | `()` | tab 的内容 |\n\n### Tabs Methods\n\n| 名称            | 类型         | 说明             | 版本   |\n| --------------- | ------------ | ---------------- | ------ |\n| syncBarPosition | `() => void` | 更新指示条的位置 | 2.24.0 |\n"
  },
  {
    "path": "src/tabs/demos/zhCN/line-debug.demo.vue",
    "content": "<markdown>\n# 调试\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst name = ref('oasis')\n</script>\n\n<template>\n  <n-button @click=\"name = 'the beatles'\">\n    将名称设置为披头士乐队\n  </n-button>\n\n  <n-card title=\"歌曲\" style=\"margin-bottom: 16px\">\n    <n-tabs v-model:value=\"name\">\n      <n-tab-pane name=\"oasis\" tab=\"绿洲乐队\">\n        Wonderwall\n      </n-tab-pane>\n      <n-tab-pane name=\"the beatles\" tab=\"披头士乐队\">\n        Hey Jude\n      </n-tab-pane>\n      <n-tab-pane name=\"jay chou\" tab=\"周杰伦\">\n        七里香\n      </n-tab-pane>\n    </n-tabs>\n  </n-card>\n\n  <n-card content-style=\"padding: 0;\">\n    <n-tabs\n      type=\"line\"\n      size=\"large\"\n      :tabs-padding=\"20\"\n      pane-style=\"padding: 20px;\"\n    >\n      <n-tab-pane v-for=\"item in 50\" :key=\"item\" :name=\"`item${item}`\">\n        PARKLIFE\n      </n-tab-pane>\n    </n-tabs>\n  </n-card>\n</template>\n\n<style>\n.n-button {\n  margin-top: 12px;\n}\n</style>\n"
  },
  {
    "path": "src/tabs/demos/zhCN/modal-debug.demo.vue",
    "content": "<markdown>\n# Modal debug\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst showRef = ref(false)\nconst tabs = ['ccccc', 'dddddd']\nconst show = showRef\n</script>\n\n<template>\n  <n-button @click=\"show = true\">\n    Show modal\n  </n-button>\n  <n-modal v-model:show=\"show\" preset=\"card\">\n    <n-tabs type=\"segment\">\n      <n-tab v-for=\"tab in tabs\" :key=\"tab\" :name=\"tab\">\n        I'm {{ tab }}\n      </n-tab>\n    </n-tabs>\n  </n-modal>\n</template>\n"
  },
  {
    "path": "src/tabs/demos/zhCN/no-pane.demo.vue",
    "content": "<markdown>\n# 不使用面板\n\n`n-tabs` 自带面板的显示，如果你只想要显示 tab 的部分，可以使用 `n-tab` 代替 `n-tab-pane`。\n</markdown>\n\n<template>\n  <n-tabs type=\"line\">\n    <n-tab name=\"幸福\">\n      寂寞围绕着电视\n    </n-tab>\n    <n-tab name=\"的\">\n      垂死坚持\n    </n-tab>\n    <n-tab name=\"旁边\">\n      在两点半消失\n    </n-tab>\n  </n-tabs>\n</template>\n"
  },
  {
    "path": "src/tabs/demos/zhCN/none-debug.demo.vue",
    "content": "<markdown>\n# None debug\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst valueRef = ref('a')\nconst tabs = ['c', 'd']\nconst value = valueRef\n\nfunction switchTabs() {\n  if (valueRef.value === 'a') {\n    valueRef.value = 'c'\n  }\n  else {\n    valueRef.value = 'a'\n  }\n}\n</script>\n\n<template>\n  <n-button @click=\"switchTabs\">\n    Switch tabs\n  </n-button>\n  <n-tabs v-model:value=\"value\">\n    <n-tab v-for=\"tab in tabs\" :key=\"tab\" :name=\"tab\">\n      I'm {{ tab }}\n    </n-tab>\n  </n-tabs>\n</template>\n"
  },
  {
    "path": "src/tabs/demos/zhCN/placement.demo.vue",
    "content": "<markdown>\n# 标签页的位置\n</markdown>\n\n<script setup lang=\"ts\">\nimport type { TabsProps } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst placement = ref<NonNullable<TabsProps['placement']>>('left')\nconst type = ref<TabsProps['type']>('card')\n</script>\n\n<template>\n  <n-space vertical>\n    <n-radio-group v-model:value=\"placement\">\n      <n-radio label=\"top\" value=\"top\" />\n      <n-radio label=\"bottom\" value=\"bottom\" />\n      <n-radio label=\"left\" value=\"left\" />\n      <n-radio label=\"right\" value=\"right\" />\n    </n-radio-group>\n    <n-radio-group v-model:value=\"type\">\n      <n-radio label=\"card\" value=\"card\" />\n      <n-radio label=\"bar\" value=\"bar\" />\n      <n-radio label=\"line\" value=\"line\" />\n    </n-radio-group>\n    <n-tabs\n      :key=\"type + placement\"\n      addable\n      :type=\"type\"\n      animated\n      :placement=\"placement\"\n      :style=\"\n        placement === 'left' || placement === 'right'\n          ? { height: '240px' }\n          : undefined\n      \"\n    >\n      <template #prefix>\n        Prefix\n      </template>\n      <template #suffix>\n        Suffix\n      </template>\n      <n-tab-pane name=\"oasis\" tab=\"Oasis\">\n        Wonderwall\n      </n-tab-pane>\n      <n-tab-pane name=\"the beatles\" tab=\"the Beatles\">\n        Hey Jude\n      </n-tab-pane>\n      <n-tab-pane name=\"jay chou\" tab=\"Jay Chou\">\n        Qilixiang\n      </n-tab-pane>\n      <n-tab-pane name=\"oasis1\" tab=\"Oasis1\">\n        Wonderwall\n      </n-tab-pane>\n      <n-tab-pane name=\"the beatles1\" tab=\"the Beatles1\">\n        Hey Jude\n      </n-tab-pane>\n      <n-tab-pane name=\"jay chou1\" tab=\"Jay Chou1\">\n        Qilixiang\n      </n-tab-pane>\n      <n-tab-pane name=\"oasis2\" tab=\"Oasis2\">\n        Wonderwall\n      </n-tab-pane>\n      <n-tab-pane name=\"the beatles2\" tab=\"the Beatles2\">\n        Hey Jude\n      </n-tab-pane>\n      <n-tab-pane name=\"jay chou2\" tab=\"Jay Chou2\">\n        Qilixiang\n      </n-tab-pane>\n      <n-tab-pane name=\"oasis3\" tab=\"Oasis3\">\n        Wonderwall\n      </n-tab-pane>\n      <n-tab-pane name=\"the beatles3\" tab=\"the Beatles3\">\n        Hey Jude\n      </n-tab-pane>\n      <n-tab-pane name=\"jay chou3\" tab=\"Jay Chou3\">\n        Qilixiang\n      </n-tab-pane>\n      <n-tab-pane name=\"oasis4\" tab=\"Oasis4\">\n        Wonderwall\n      </n-tab-pane>\n      <n-tab-pane name=\"the beatles4\" tab=\"the Beatles4\">\n        Hey Jude\n      </n-tab-pane>\n      <n-tab-pane name=\"jay chou4\" tab=\"Jay Chou4\">\n        Qilixiang\n      </n-tab-pane>\n      <n-tab-pane name=\"oasis5\" tab=\"Oasis5\">\n        Wonderwall\n      </n-tab-pane>\n      <n-tab-pane name=\"the beatles5\" tab=\"the Beatles5\">\n        Hey Jude\n      </n-tab-pane>\n      <n-tab-pane name=\"jay chou5\" tab=\"Jay Chou5\">\n        Qilixiang\n      </n-tab-pane>\n    </n-tabs>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/tabs/demos/zhCN/prefix.demo.vue",
    "content": "<markdown>\n# 前缀 & 后缀\n\n使用 `prefix`、`suffix` slot 来添加前后缀。\n</markdown>\n\n<template>\n  <n-tabs default-value=\"oasis\">\n    <template #prefix>\n      Prefix\n    </template>\n    <n-tab-pane name=\"oasis\" tab=\"Oasis\">\n      Wonderwall\n    </n-tab-pane>\n    <n-tab-pane name=\"the beatles\" tab=\"the Beatles\">\n      Hey Jude\n    </n-tab-pane>\n    <n-tab-pane name=\"jay chou\" tab=\"周杰伦\">\n      七里香\n    </n-tab-pane>\n    <template #suffix>\n      Suffix\n    </template>\n  </n-tabs>\n</template>\n"
  },
  {
    "path": "src/tabs/demos/zhCN/segment.demo.vue",
    "content": "<markdown>\n# 分段\n\n分段类型的标签页。\n</markdown>\n\n<template>\n  <n-divider />\n  <n-h3 style=\"text-align: center\">\n    五美金的礼品卡\n  </n-h3>\n  <n-tabs type=\"segment\" animated>\n    <n-tab-pane name=\"chap1\" tab=\"第一章\">\n      我这辈子最疯狂的事，发生在我在 Amazon\n      当软件工程师的时候，故事是这样的：<br><br>\n      那时我和女朋友住在一起，正在家里远程工作。忽然同事给我发来了紧急消息：”我们的服务出现了\n      SEV 2 级别的故障！需要所有的人马上协助！“我们组的应用全挂掉了。<br><br>\n      当我还在费力的寻找修复方法的时候，忽然闻到隔壁房间的的焦味，防火报警器开始鸣叫。\n    </n-tab-pane>\n    <n-tab-pane name=\"chap2\" tab=\"第二章\">\n      “威尔！着火了！快来帮忙！”我听到女朋友大喊。现在一个难题在我面前——是恢复一个重要的\n      Amazon 服务，还是救公寓的火。<br><br>\n      我的脑海中忽然出现了 Amazon\n      著名的领导力准则”客户至上“，有很多的客户还依赖我们的服务，我不能让他们失望！所以着火也不管了，女朋友喊我也无所谓，我开始\n      debug 这个线上问题。\n    </n-tab-pane>\n    <n-tab-pane name=\"chap3\" tab=\"第三章\">\n      但是忽然，公寓的烟味消失，火警也停了。我的女朋友走进了房间，让我震惊的是，她摘下了自己的假发，她是\n      Jeff Bezos（Amazon 老板）假扮的！<br><br>\n      “我对你坚持顾客至上的原则感到十分骄傲”，说完，他递给我一张五美金的亚马逊礼品卡，从我家窗户翻了出去，跳上了一辆\n      Amazon 会员服务的小货车，一溜烟离开了。<br><br>虽然现在我已不在 Amazon\n      工作，但我还是非常感激在哪里学的到的经验，这些经验我终身难忘。你们同意么？\n    </n-tab-pane>\n  </n-tabs>\n</template>\n"
  },
  {
    "path": "src/tabs/demos/zhCN/shadow-debug.demo.vue",
    "content": "<markdown>\n# Shadow Debug\n\n`#1224`\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst valueRef = ref(1)\nconst panelsRef = ref([1, 2, 3])\n\nconst value = valueRef\nconst panels = panelsRef\nconst getClass = ref('half')\n</script>\n\n<template>\n  <div :class=\"getClass\">\n    <n-button @click=\"() => (getClass = 'half')\">\n      half\n    </n-button>\n    <n-button @click=\"() => (getClass = 'full')\">\n      full\n    </n-button>\n    <n-tabs v-model:value=\"value\" type=\"card\" tab-style=\"min-width: 100px;\">\n      <n-tab-pane v-for=\"panel in panels\" :key=\"panel\" :name=\"panel\">\n        {{ panel }}\n      </n-tab-pane>\n      <template #prefix>\n        Prefix\n      </template>\n      <template #suffix>\n        Suffix\n      </template>\n    </n-tabs>\n  </div>\n</template>\n\n<style>\n.half {\n  width: 50%;\n}\n</style>\n"
  },
  {
    "path": "src/tabs/demos/zhCN/size.demo.vue",
    "content": "<markdown>\n# 尺寸\n\nTabs 可以有不同的尺寸。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst size = ref<'small' | 'medium' | 'large'>('medium')\n</script>\n\n<template>\n  <n-space vertical>\n    <n-radio-group v-model:value=\"size\">\n      <n-space>\n        <n-radio value=\"small\">\n          小\n        </n-radio>\n        <n-radio value=\"medium\">\n          不小\n        </n-radio>\n        <n-radio value=\"large\">\n          不不小\n        </n-radio>\n      </n-space>\n    </n-radio-group>\n    <n-tabs type=\"bar\" :size=\"size\">\n      <n-tab-pane name=\"oasis\" tab=\"Oasis\">\n        Wonderwall\n      </n-tab-pane>\n      <n-tab-pane name=\"the beatles\" tab=\"the Beatles\">\n        Hey Jude\n      </n-tab-pane>\n      <n-tab-pane name=\"jay chou\" tab=\"周杰伦\">\n        七里香\n      </n-tab-pane>\n    </n-tabs>\n    <n-tabs type=\"line\" :size=\"size\">\n      <n-tab-pane name=\"oasis\" tab=\"Oasis\">\n        Wonderwall\n      </n-tab-pane>\n      <n-tab-pane name=\"the beatles\" tab=\"the Beatles\">\n        Hey Jude\n      </n-tab-pane>\n      <n-tab-pane name=\"jay chou\" tab=\"周杰伦\">\n        七里香\n      </n-tab-pane>\n    </n-tabs>\n    <n-tabs type=\"card\" :size=\"size\" closable>\n      <n-tab-pane name=\"oasis\" tab=\"Oasis\">\n        Wonderwall\n      </n-tab-pane>\n      <n-tab-pane name=\"the beatles\" tab=\"the Beatles\">\n        Hey Jude\n      </n-tab-pane>\n      <n-tab-pane name=\"jay chou\" tab=\"周杰伦\">\n        七里香\n      </n-tab-pane>\n    </n-tabs>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/tabs/demos/zhCN/style-inherit-debug.demo.vue",
    "content": "<markdown>\n# Style Inherit Debug\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { NTabPane, NTabs } from 'naive-ui'\n</script>\n\n<template>\n  <div id=\"app\">\n    <h2>one tab</h2>\n    <NTabs type=\"line\">\n      <NTabPane name=\"One\">\n        1111\n      </NTabPane>\n      <NTabPane name=\"Two\">\n        1111\n      </NTabPane>\n    </NTabs>\n\n    <h2>one tabs Parent/Child</h2>\n    <NTabs type=\"card\">\n      <NTabPane name=\"POne\">\n        <NTabs type=\"line\">\n          <NTabPane name=\"COne\">\n            1111\n          </NTabPane>\n          <NTabPane name=\"CTwo\">\n            1111\n          </NTabPane>\n        </NTabs>\n      </NTabPane>\n      <NTabPane name=\"PTwo\">\n        1111\n      </NTabPane>\n    </NTabs>\n  </div>\n</template>\n"
  },
  {
    "path": "src/tabs/demos/zhCN/trigger.demo.vue",
    "content": "<markdown>\n# 触发方式\n\n可以使用 `trigger='hover'` 触发标签页的改变。\n</markdown>\n\n<template>\n  <n-tabs type=\"line\" trigger=\"hover\">\n    <n-tab-pane name=\"oasis\" tab=\"Oasis\">\n      Wonderwall\n    </n-tab-pane>\n    <n-tab-pane name=\"the beatles\" tab=\"the Beatles\">\n      Hey Jude\n    </n-tab-pane>\n    <n-tab-pane name=\"jay chou\" tab=\"周杰伦\">\n      七里香\n    </n-tab-pane>\n  </n-tabs>\n</template>\n"
  },
  {
    "path": "src/tabs/demos/zhCN/unkeyed-debug.demo.vue",
    "content": "<markdown>\n# Unkeyed\n</markdown>\n\n<script lang=\"ts\" setup>\nconst list = [\n  {\n    a: '1a',\n    b: '1b'\n  },\n  {\n    a: '2a',\n    b: '2b'\n  },\n  {\n    a: '3a',\n    b: '3b'\n  }\n]\n</script>\n\n<template>\n  <n-tabs type=\"line\" :default-value=\"list[0].a\">\n    <!-- eslint-disable vue/valid-v-for -->\n    <n-tab-pane v-for=\"i in list\" :name=\"i.a\" :tab=\"i.b\">\n      <div>{{ i.a }} {{ i.b }}</div>\n    </n-tab-pane>\n  </n-tabs>\n</template>\n"
  },
  {
    "path": "src/tabs/demos/zhCN/update-bar-manually.demo.vue",
    "content": "<markdown>\n# 手动更新指示条\n\n因为 `n-tabs` 直接读取 children 渲染，所以它无法理解你的更新意图，在某些极端情况下，需要你手动的更新条的位置。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { TabsInst } from 'naive-ui'\nimport { nextTick, ref } from 'vue'\n\nconst tabsInstRef = ref<TabsInst | null>(null)\nconst tabsRef = ref(['a', 'b'])\nconst valueRef = ref('a')\n\nfunction handleClick() {\n  tabsRef.value.reverse()\n  valueRef.value = 'a'\n  nextTick(() => tabsInstRef.value?.syncBarPosition())\n}\n\nconst tabs = tabsRef\nconst value = valueRef\n</script>\n\n<template>\n  <n-space vertical>\n    <n-button @click=\"handleClick\">\n      没有任何意义的改动\n    </n-button>\n    <n-tabs ref=\"tabsInstRef\" v-model:value=\"value\">\n      <n-tab v-for=\"tab in tabs\" :key=\"tab\" :name=\"tab\">\n        我是 {{ tab }}\n      </n-tab>\n    </n-tabs>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/tabs/index.ts",
    "content": "export type { TabsInst } from './src/interface'\nexport type * from './src/public-types'\nexport { default as NTab, tabProps } from './src/Tab'\nexport type { TabProps } from './src/Tab'\nexport { default as NTabPane, tabPaneProps } from './src/TabPane'\nexport type { TabPaneProps, TabPaneSlots } from './src/TabPane'\nexport { default as NTabs, tabsProps } from './src/Tabs'\nexport type { TabsProps, TabsSlots } from './src/Tabs'\n"
  },
  {
    "path": "src/tabs/src/Tab.tsx",
    "content": "import type { ExtractPublicPropTypes } from '../../_utils'\nimport type { OnBeforeLeaveImpl } from './interface'\nimport { computed, defineComponent, Fragment, h, inject, mergeProps } from 'vue'\nimport { NBaseClose, NBaseIcon } from '../../_internal'\nimport { AddIcon } from '../../_internal/icons'\nimport { omit, render } from '../../_utils'\nimport { tabsInjectionKey } from './interface'\nimport { tabPaneProps } from './TabPane'\n\nexport const tabProps = {\n  internalLeftPadded: Boolean,\n  internalAddable: Boolean,\n  internalCreatedByPane: Boolean,\n  ...omit(tabPaneProps, ['displayDirective'])\n} as const\n\nexport type TabProps = ExtractPublicPropTypes<typeof tabProps>\n\nexport default defineComponent({\n  __TAB__: true,\n  inheritAttrs: false,\n  name: 'Tab',\n  props: tabProps,\n  setup(props) {\n    const {\n      mergedClsPrefixRef,\n      valueRef,\n      typeRef,\n      closableRef,\n      tabStyleRef,\n      addTabStyleRef,\n      tabClassRef,\n      addTabClassRef,\n      tabChangeIdRef,\n      onBeforeLeaveRef,\n      triggerRef,\n      handleAdd,\n      activateTab,\n      handleClose\n    } = inject(tabsInjectionKey)!\n    return {\n      trigger: triggerRef,\n      mergedClosable: computed(() => {\n        if (props.internalAddable)\n          return false\n        const { closable } = props\n        if (closable === undefined)\n          return closableRef.value\n        return closable\n      }),\n      style: tabStyleRef,\n      addStyle: addTabStyleRef,\n      tabClass: tabClassRef,\n      addTabClass: addTabClassRef,\n      clsPrefix: mergedClsPrefixRef,\n      value: valueRef,\n      type: typeRef,\n      handleClose(e: MouseEvent) {\n        e.stopPropagation()\n        if (props.disabled)\n          return\n        handleClose(props.name)\n      },\n      activateTab() {\n        if (props.disabled)\n          return\n        if (props.internalAddable) {\n          handleAdd()\n          return\n        }\n        const { name: nameProp } = props\n        const id = ++tabChangeIdRef.id\n        if (nameProp !== valueRef.value) {\n          const { value: onBeforeLeave } = onBeforeLeaveRef\n          if (!onBeforeLeave) {\n            activateTab(nameProp)\n          }\n          else {\n            void Promise.resolve(\n              (onBeforeLeave as OnBeforeLeaveImpl)(props.name, valueRef.value)\n            ).then((allowLeave) => {\n              if (allowLeave && tabChangeIdRef.id === id) {\n                activateTab(nameProp)\n              }\n            })\n          }\n        }\n      }\n    }\n  },\n  render() {\n    const {\n      internalAddable,\n      clsPrefix,\n      name,\n      disabled,\n      label,\n      tab,\n      value,\n      mergedClosable,\n      trigger,\n      $slots: { default: defaultSlot }\n    } = this\n    const mergedTab = label ?? tab\n    return (\n      <div class={`${clsPrefix}-tabs-tab-wrapper`}>\n        {this.internalLeftPadded ? (\n          <div class={`${clsPrefix}-tabs-tab-pad`} />\n        ) : null}\n        <div\n          key={name}\n          data-name={name}\n          data-disabled={disabled ? true : undefined}\n          {...mergeProps(\n            {\n              class: [\n                `${clsPrefix}-tabs-tab`,\n                value === name && `${clsPrefix}-tabs-tab--active`,\n                disabled && `${clsPrefix}-tabs-tab--disabled`,\n                mergedClosable && `${clsPrefix}-tabs-tab--closable`,\n                internalAddable && `${clsPrefix}-tabs-tab--addable`,\n                internalAddable ? this.addTabClass : this.tabClass\n              ],\n              onClick: trigger === 'click' ? this.activateTab : undefined,\n              onMouseenter: trigger === 'hover' ? this.activateTab : undefined,\n              style: internalAddable ? this.addStyle : this.style\n            },\n            this.internalCreatedByPane\n              ? ((this.tabProps || {}) as any)\n              : this.$attrs\n          )}\n        >\n          <span class={`${clsPrefix}-tabs-tab__label`}>\n            {internalAddable ? (\n              <>\n                <div class={`${clsPrefix}-tabs-tab__height-placeholder`}>\n                  &nbsp;\n                </div>\n                <NBaseIcon clsPrefix={clsPrefix}>\n                  {{\n                    default: () => <AddIcon />\n                  }}\n                </NBaseIcon>\n              </>\n            ) : defaultSlot ? (\n              defaultSlot()\n            ) : typeof mergedTab === 'object' ? (\n              mergedTab // VNode\n            ) : (\n              render(mergedTab ?? name)\n            )}\n          </span>\n          {mergedClosable && this.type === 'card' ? (\n            <NBaseClose\n              clsPrefix={clsPrefix}\n              class={`${clsPrefix}-tabs-tab__close`}\n              onClick={this.handleClose}\n              disabled={disabled}\n            />\n          ) : null}\n        </div>\n      </div>\n    )\n  }\n})\n"
  },
  {
    "path": "src/tabs/src/TabPane.tsx",
    "content": "import type {\n  HTMLAttributes,\n  PropType,\n  SlotsType,\n  VNode,\n  VNodeChild\n} from 'vue'\nimport type { ExtractPublicPropTypes } from '../../_utils'\nimport { defineComponent, h, inject, watchEffect } from 'vue'\nimport { throwError, warnOnce } from '../../_utils'\nimport { tabsInjectionKey } from './interface'\n\nexport const tabPaneProps = {\n  tab: [String, Number, Object, Function] as PropType<\n    string | number | VNode | (() => VNodeChild)\n  >,\n  name: {\n    type: [String, Number] as PropType<string | number>,\n    required: true\n  },\n  disabled: Boolean,\n  displayDirective: {\n    type: String as PropType<'if' | 'show' | 'show:lazy'>,\n    default: 'if'\n  },\n  closable: {\n    type: Boolean as PropType<boolean | undefined>,\n    default: undefined\n  },\n  tabProps: Object as PropType<HTMLAttributes>,\n  /** @deprecated */\n  label: [String, Number, Object, Function] as PropType<\n    string | number | VNode | (() => VNodeChild)\n  >\n} as const\n\nexport type TabPaneProps = ExtractPublicPropTypes<typeof tabPaneProps>\n\nexport interface TabPaneSlots {\n  default?: () => VNode[]\n  tab?: () => VNode[]\n  prefix?: () => VNode[]\n  suffix?: () => VNode[]\n}\n\nexport default defineComponent({\n  __TAB_PANE__: true,\n  name: 'TabPane',\n  alias: ['TabPanel'],\n  props: tabPaneProps,\n  slots: Object as SlotsType<TabPaneSlots>,\n  setup(props) {\n    if (__DEV__) {\n      watchEffect(() => {\n        if (props.label !== undefined) {\n          warnOnce(\n            'tab-pane',\n            '`label` is deprecated, please use `tab` instead.'\n          )\n        }\n      })\n    }\n    const NTab = inject(tabsInjectionKey, null)\n    if (!NTab) {\n      throwError('tab-pane', '`n-tab-pane` must be placed inside `n-tabs`.')\n    }\n    return {\n      style: NTab.paneStyleRef,\n      class: NTab.paneClassRef,\n      mergedClsPrefix: NTab.mergedClsPrefixRef\n    }\n  },\n  render() {\n    return (\n      <div\n        class={[`${this.mergedClsPrefix}-tab-pane`, this.class]}\n        style={this.style}\n      >\n        {this.$slots}\n      </div>\n    )\n  }\n})\n"
  },
  {
    "path": "src/tabs/src/Tabs.tsx",
    "content": "import type {\n  ComponentPublicInstance,\n  CSSProperties,\n  ExtractPropTypes,\n  PropType,\n  SlotsType,\n  VNode,\n  VNodeChild\n} from 'vue'\nimport type { VXScrollInst } from 'vueuc'\nimport type { ThemeProps } from '../../_mixins'\nimport type { ExtractPublicPropTypes, MaybeArray } from '../../_utils'\nimport type { TabsTheme } from '../styles'\nimport type {\n  Addable,\n  OnBeforeLeave,\n  OnClose,\n  OnCloseImpl,\n  OnUpdateValue,\n  OnUpdateValueImpl,\n  TabsInst,\n  TabsType\n} from './interface'\nimport type { TabsSize } from './public-types'\nimport type { tabPaneProps } from './TabPane'\nimport { throttle as _throttle } from 'lodash-es'\nimport { depx, getPadding } from 'seemly'\nimport { onFontsReady, useCompitable, useMergedState } from 'vooks'\nimport {\n  cloneVNode,\n  computed,\n  defineComponent,\n  h,\n  nextTick,\n  onMounted,\n  provide,\n  ref,\n  toRef,\n  TransitionGroup,\n  vShow,\n  watch,\n  watchEffect,\n  withDirectives\n} from 'vue'\nimport { VResizeObserver, VXScroll } from 'vueuc'\nimport { useConfig, useTheme, useThemeClass } from '../../_mixins'\nimport {\n  call,\n  createKey,\n  flatten,\n  resolveWrappedSlot,\n  warnOnce\n} from '../../_utils'\nimport { tabsLight } from '../styles'\nimport { tabsInjectionKey } from './interface'\nimport style from './styles/index.cssr'\nimport Tab from './Tab'\n\n// Fix vue-tsc error\nconst throttle: <T>(f: T, t: number) => T = _throttle\n\ntype TabPaneProps = ExtractPropTypes<typeof tabPaneProps> & {\n  'display-directive': 'if' | 'show' | 'show:lazy'\n}\n\nexport const tabsProps = {\n  ...(useTheme.props as ThemeProps<TabsTheme>),\n  value: [String, Number] as PropType<string | number>,\n  defaultValue: [String, Number] as PropType<string | number>,\n  trigger: {\n    type: String as PropType<'click' | 'hover'>,\n    default: 'click'\n  },\n  type: {\n    type: String as PropType<TabsType>,\n    default: 'bar'\n  },\n  closable: Boolean,\n  justifyContent: String as PropType<\n    | 'space-between'\n    | 'space-around'\n    | 'space-evenly'\n    | 'center'\n    | 'start'\n    | 'end'\n  >,\n  size: String as PropType<TabsSize>,\n  placement: {\n    type: String as PropType<'top' | 'left' | 'right' | 'bottom'>,\n    default: 'top'\n  },\n  tabStyle: [String, Object] as PropType<string | CSSProperties>,\n  tabClass: String,\n  addTabStyle: [String, Object] as PropType<string | CSSProperties>,\n  addTabClass: String,\n  barWidth: Number,\n  paneClass: String,\n  paneStyle: [String, Object] as PropType<string | CSSProperties>,\n  paneWrapperClass: String,\n  paneWrapperStyle: [String, Object] as PropType<string | CSSProperties>,\n  addable: [Boolean, Object] as PropType<Addable>,\n  tabsPadding: {\n    type: Number,\n    default: 0\n  },\n  animated: Boolean,\n  onBeforeLeave: Function as PropType<OnBeforeLeave>,\n  onAdd: Function as PropType<() => void>,\n  'onUpdate:value': [Function, Array] as PropType<MaybeArray<OnUpdateValue>>,\n  onUpdateValue: [Function, Array] as PropType<MaybeArray<OnUpdateValue>>,\n  onClose: [Function, Array] as PropType<MaybeArray<OnClose>>,\n  // deprecated\n  labelSize: String as PropType<TabsSize>,\n  activeName: [String, Number] as PropType<string | number>,\n  onActiveNameChange: [Function, Array] as PropType<\n    MaybeArray<(value: string & number) => void>\n  >\n} as const\n\nexport type TabsProps = ExtractPublicPropTypes<typeof tabsProps>\n\nexport interface TabsSlots {\n  default?: () => VNode[]\n  prefix?: () => VNode[]\n  suffix?: () => VNode[]\n}\n\nexport default defineComponent({\n  name: 'Tabs',\n  props: tabsProps,\n  slots: Object as SlotsType<TabsSlots>,\n  setup(props, { slots }) {\n    if (__DEV__) {\n      watchEffect(() => {\n        if (props.labelSize !== undefined) {\n          warnOnce(\n            'tabs',\n            '`label-size` is deprecated, please use `size` instead.'\n          )\n        }\n        if (props.activeName !== undefined) {\n          warnOnce(\n            'tabs',\n            '`active-name` is deprecated, please use `value` instead.'\n          )\n        }\n        if (props.onActiveNameChange !== undefined) {\n          warnOnce(\n            'tabs',\n            '`on-active-name-change` is deprecated, please use `on-update:value` instead.'\n          )\n        }\n      })\n    }\n\n    const { mergedClsPrefixRef, inlineThemeDisabled, mergedComponentPropsRef }\n      = useConfig(props)\n    const themeRef = useTheme(\n      'Tabs',\n      '-tabs',\n      style,\n      tabsLight,\n      props,\n      mergedClsPrefixRef\n    )\n\n    const tabsElRef = ref<HTMLElement | null>(null)\n    const barElRef = ref<HTMLElement | null>(null)\n    const scrollWrapperElRef = ref<HTMLElement | null>(null)\n    const addTabInstRef = ref<ComponentPublicInstance | null>(null)\n    const xScrollInstRef = ref<(VXScrollInst & ComponentPublicInstance) | null>(\n      null\n    )\n    const yScrollElRef = ref<HTMLElement | null>(null)\n\n    const startReachedRef = ref(true)\n    const endReachedRef = ref(true)\n\n    const compitableSizeRef = useCompitable(props, ['labelSize', 'size'])\n    const mergedSizeRef = computed(() => {\n      if (compitableSizeRef.value)\n        return compitableSizeRef.value\n\n      const configSize = mergedComponentPropsRef?.value?.Tabs?.size\n      if (configSize)\n        return configSize\n\n      return 'medium'\n    })\n    const compitableValueRef = useCompitable(props, ['activeName', 'value'])\n    const uncontrolledValueRef = ref(\n      compitableValueRef.value\n      ?? props.defaultValue\n      ?? (slots.default\n        ? ((flatten((slots as any).default() as VNodeChild[])[0] as any)\n            ?.props\n            ?.name as string | number)\n        : null)\n    )\n    const mergedValueRef = useMergedState(\n      compitableValueRef,\n      uncontrolledValueRef\n    )\n\n    const tabChangeIdRef = { id: 0 }\n\n    const tabWrapperStyleRef = computed(() => {\n      if (!props.justifyContent || props.type === 'card')\n        return undefined\n      return {\n        display: 'flex',\n        justifyContent: props.justifyContent\n      }\n    })\n\n    watch(mergedValueRef, () => {\n      tabChangeIdRef.id = 0\n      updateCurrentBarStyle()\n      updateCurrentScrollPosition()\n    })\n\n    function getCurrentEl(): HTMLElement | null {\n      const { value } = mergedValueRef\n      if (value === null)\n        return null\n      const tabEl = tabsElRef.value?.querySelector(`[data-name=\"${value}\"]`)\n      return tabEl as HTMLElement | null\n    }\n    function updateBarStyle(tabEl: HTMLElement): void {\n      if (props.type === 'card')\n        return\n      const { value: barEl } = barElRef\n      if (!barEl)\n        return\n      const barIsHide = barEl.style.opacity === '0'\n      if (tabEl) {\n        const disabledClassName = `${mergedClsPrefixRef.value}-tabs-bar--disabled`\n        const { barWidth, placement } = props\n        if (tabEl.dataset.disabled === 'true') {\n          barEl.classList.add(disabledClassName)\n        }\n        else {\n          barEl.classList.remove(disabledClassName)\n        }\n        if (['top', 'bottom'].includes(placement)) {\n          clearBarStyle(['top', 'maxHeight', 'height'])\n          if (typeof barWidth === 'number' && tabEl.offsetWidth >= barWidth) {\n            const offsetDiffLeft\n              = Math.floor((tabEl.offsetWidth - barWidth) / 2) + tabEl.offsetLeft\n            barEl.style.left = `${offsetDiffLeft}px`\n            barEl.style.maxWidth = `${barWidth}px`\n          }\n          else {\n            barEl.style.left = `${tabEl.offsetLeft}px`\n            barEl.style.maxWidth = `${tabEl.offsetWidth}px`\n          }\n          barEl.style.width = '8192px'\n          if (barIsHide) {\n            barEl.style.transition = 'none'\n          }\n          void barEl.offsetWidth\n          if (barIsHide) {\n            barEl.style.transition = ''\n            barEl.style.opacity = '1'\n          }\n        }\n        else {\n          clearBarStyle(['left', 'maxWidth', 'width'])\n          if (typeof barWidth === 'number' && tabEl.offsetHeight >= barWidth) {\n            const offsetDiffTop\n              = Math.floor((tabEl.offsetHeight - barWidth) / 2) + tabEl.offsetTop\n            barEl.style.top = `${offsetDiffTop}px`\n            barEl.style.maxHeight = `${barWidth}px`\n          }\n          else {\n            barEl.style.top = `${tabEl.offsetTop}px`\n            barEl.style.maxHeight = `${tabEl.offsetHeight}px`\n          }\n          barEl.style.height = '8192px'\n          if (barIsHide) {\n            barEl.style.transition = 'none'\n          }\n          void barEl.offsetHeight\n          if (barIsHide) {\n            barEl.style.transition = ''\n            barEl.style.opacity = '1'\n          }\n        }\n      }\n    }\n    function hideBarStyle(): void {\n      if (props.type === 'card')\n        return\n      const { value: barEl } = barElRef\n      if (!barEl)\n        return\n      barEl.style.opacity = '0'\n    }\n    function clearBarStyle(styleProps: string[]): void {\n      const { value: barEl } = barElRef\n      if (!barEl)\n        return\n      for (const prop of styleProps) {\n        barEl.style[prop as any] = ''\n      }\n    }\n    function updateCurrentBarStyle(): void {\n      if (props.type === 'card')\n        return\n      const tabEl = getCurrentEl()\n      if (tabEl) {\n        updateBarStyle(tabEl)\n      }\n      else {\n        hideBarStyle()\n      }\n    }\n    function updateCurrentScrollPosition(): void {\n      const scrollWrapperEl: HTMLElement | undefined = xScrollInstRef.value?.$el\n      if (!scrollWrapperEl)\n        return\n      const tabEl = getCurrentEl()\n      if (!tabEl)\n        return\n      const {\n        scrollLeft: scrollWrapperElScrollLeft,\n        offsetWidth: scrollWrapperElOffsetWidth\n      } = scrollWrapperEl\n      const { offsetLeft: tabElOffsetLeft, offsetWidth: tabElOffsetWidth }\n        = tabEl\n      if (scrollWrapperElScrollLeft > tabElOffsetLeft) {\n        scrollWrapperEl.scrollTo({\n          top: 0,\n          left: tabElOffsetLeft,\n          behavior: 'smooth'\n        })\n      }\n      else if (\n        tabElOffsetLeft + tabElOffsetWidth\n        > scrollWrapperElScrollLeft + scrollWrapperElOffsetWidth\n      ) {\n        scrollWrapperEl.scrollTo({\n          top: 0,\n          left: tabElOffsetLeft + tabElOffsetWidth - scrollWrapperElOffsetWidth,\n          behavior: 'smooth'\n        })\n      }\n    }\n\n    const tabsPaneWrapperRef = ref<HTMLElement | null>(null)\n    let fromHeight = 0\n    let hangingTransition: (() => void) | null = null\n    function onAnimationBeforeLeave(el: HTMLElement): void {\n      const tabsPaneWrapperEl = tabsPaneWrapperRef.value\n      if (tabsPaneWrapperEl) {\n        fromHeight = el.getBoundingClientRect().height\n        const fromHeightPx = `${fromHeight}px`\n        const applyFromStyle = (): void => {\n          tabsPaneWrapperEl.style.height = fromHeightPx\n          tabsPaneWrapperEl.style.maxHeight = fromHeightPx\n        }\n        if (!hangingTransition) {\n          hangingTransition = applyFromStyle\n        }\n        else {\n          applyFromStyle()\n          hangingTransition()\n          hangingTransition = null\n        }\n      }\n    }\n    function onAnimationEnter(el: HTMLElement): void {\n      const tabsPaneWrapperEl = tabsPaneWrapperRef.value\n      if (tabsPaneWrapperEl) {\n        const targetHeight = el.getBoundingClientRect().height\n        const applyTargetStyle = (): void => {\n          void document.body.offsetHeight\n          tabsPaneWrapperEl.style.maxHeight = `${targetHeight}px`\n          tabsPaneWrapperEl.style.height = `${Math.max(\n            fromHeight,\n            targetHeight\n          )}px`\n        }\n        if (!hangingTransition) {\n          hangingTransition = applyTargetStyle\n        }\n        else {\n          hangingTransition()\n          hangingTransition = null\n          applyTargetStyle()\n        }\n      }\n    }\n    function onAnimationAfterEnter(): void {\n      const tabsPaneWrapperEl = tabsPaneWrapperRef.value\n      if (tabsPaneWrapperEl) {\n        tabsPaneWrapperEl.style.maxHeight = ''\n        tabsPaneWrapperEl.style.height = ''\n        const { paneWrapperStyle } = props\n        if (typeof paneWrapperStyle === 'string') {\n          tabsPaneWrapperEl.style.cssText = paneWrapperStyle\n        }\n        else if (paneWrapperStyle) {\n          const { maxHeight, height } = paneWrapperStyle\n          if (maxHeight !== undefined) {\n            tabsPaneWrapperEl.style.maxHeight = maxHeight as string\n          }\n          if (height !== undefined) {\n            tabsPaneWrapperEl.style.height = height as string\n          }\n        }\n      }\n    }\n\n    const renderNameListRef: { value: Array<string | number> } = { value: [] }\n    const animationDirectionRef = ref<'next' | 'prev'>('next')\n    function activateTab(panelName: string | number): void {\n      const currentValue = mergedValueRef.value\n      let dir: 'next' | 'prev' = 'next'\n      for (const name of renderNameListRef.value) {\n        if (name === currentValue) {\n          break\n        }\n        if (name === panelName) {\n          dir = 'prev'\n          break\n        }\n      }\n      animationDirectionRef.value = dir\n      doUpdateValue(panelName)\n    }\n    function doUpdateValue(panelName: string | number): void {\n      const {\n        onActiveNameChange,\n        onUpdateValue,\n        'onUpdate:value': _onUpdateValue\n      } = props\n      if (onActiveNameChange) {\n        call(onActiveNameChange as OnUpdateValueImpl, panelName)\n      }\n      if (onUpdateValue)\n        call(onUpdateValue as OnUpdateValueImpl, panelName)\n      if (_onUpdateValue)\n        call(_onUpdateValue as OnUpdateValueImpl, panelName)\n      uncontrolledValueRef.value = panelName\n    }\n    function handleClose(panelName: string | number): void {\n      const { onClose } = props\n      if (onClose)\n        call(onClose as OnCloseImpl, panelName)\n    }\n\n    let firstTimeUpdatePosition = true\n    function updateBarPositionInstantly(): void {\n      const { value: barEl } = barElRef\n      if (!barEl)\n        return\n      if (!firstTimeUpdatePosition)\n        firstTimeUpdatePosition = false\n      const disableTransitionClassName = 'transition-disabled'\n      barEl.classList.add(disableTransitionClassName)\n      updateCurrentBarStyle()\n      // here we don't need to force layout after update bar style\n      // since deriveScrollShadow will force layout\n      barEl.classList.remove(disableTransitionClassName)\n    }\n\n    const segmentCapsuleElRef = ref<HTMLElement | null>(null)\n\n    function updateSegmentPosition({\n      transitionDisabled\n    }: {\n      transitionDisabled: boolean\n    }): void {\n      const tabsEl = tabsElRef.value\n      if (!tabsEl)\n        return\n      if (transitionDisabled)\n        tabsEl.classList.add('transition-disabled')\n      const activeTabEl = getCurrentEl()\n      if (activeTabEl && segmentCapsuleElRef.value) {\n        // move segment capsule to match the position of the active tab\n        segmentCapsuleElRef.value.style.width = `${activeTabEl.offsetWidth}px`\n        segmentCapsuleElRef.value.style.height = `${activeTabEl.offsetHeight}px`\n        segmentCapsuleElRef.value.style.transform = `translateX(${\n          activeTabEl.offsetLeft - depx(getComputedStyle(tabsEl).paddingLeft)\n        }px)`\n        if (transitionDisabled) {\n          void segmentCapsuleElRef.value.offsetWidth\n        }\n      }\n      if (transitionDisabled) {\n        tabsEl.classList.remove('transition-disabled')\n      }\n    }\n\n    watch([mergedValueRef], () => {\n      if (props.type === 'segment') {\n        void nextTick(() => {\n          updateSegmentPosition({\n            transitionDisabled: false\n          })\n        })\n      }\n    })\n\n    onMounted(() => {\n      if (props.type === 'segment') {\n        updateSegmentPosition({\n          transitionDisabled: true\n        })\n      }\n    })\n\n    let memorizedWidth = 0\n    function _handleNavResize(entry: ResizeObserverEntry): void {\n      if (entry.contentRect.width === 0 && entry.contentRect.height === 0) {\n        return\n      }\n      if (memorizedWidth === entry.contentRect.width) {\n        return\n      }\n      memorizedWidth = entry.contentRect.width\n      const { type } = props\n      if (type === 'line' || type === 'bar') {\n        if (\n          firstTimeUpdatePosition\n          || props.justifyContent?.startsWith('space')\n        ) {\n          updateBarPositionInstantly()\n        }\n      }\n      if (type !== 'segment') {\n        const { placement } = props\n        deriveScrollShadow(\n          (placement === 'top' || placement === 'bottom'\n            ? (xScrollInstRef.value?.$el as undefined | HTMLElement)\n            : yScrollElRef.value) || null\n        )\n      }\n    }\n    const handleNavResize: (entry: ResizeObserverEntry) => void = throttle(\n      _handleNavResize,\n      64\n    )\n    watch([() => props.justifyContent, () => props.size], () => {\n      void nextTick(() => {\n        const { type } = props\n        if (type === 'line' || type === 'bar') {\n          updateBarPositionInstantly()\n        }\n      })\n    })\n\n    const addTabFixedRef = ref(false)\n    function _handleTabsResize(entry: ResizeObserverEntry): void {\n      const {\n        target,\n        contentRect: { width, height }\n      } = entry\n      const containerWidth = target.parentElement!.parentElement!.offsetWidth\n      const containerHeight = target.parentElement!.parentElement!.offsetHeight\n      const { placement } = props\n      if (!addTabFixedRef.value) {\n        if (placement === 'top' || placement === 'bottom') {\n          if (containerWidth < width) {\n            addTabFixedRef.value = true\n          }\n        }\n        else {\n          if (containerHeight < height) {\n            addTabFixedRef.value = true\n          }\n        }\n      }\n      else {\n        const { value: addTabInst } = addTabInstRef\n        if (!addTabInst)\n          return\n        if (placement === 'top' || placement === 'bottom') {\n          if (\n            containerWidth - width\n            > (addTabInst.$el as HTMLElement).offsetWidth\n          ) {\n            addTabFixedRef.value = false\n          }\n        }\n        else {\n          if (\n            containerHeight - height\n            > (addTabInst.$el as HTMLElement).offsetHeight\n          ) {\n            addTabFixedRef.value = false\n          }\n        }\n      }\n      deriveScrollShadow(\n        (xScrollInstRef.value?.$el as undefined | HTMLElement) || null\n      )\n    }\n    const handleTabsResize: (entry: ResizeObserverEntry) => void = throttle(\n      _handleTabsResize,\n      64\n    )\n\n    function handleAdd(): void {\n      const { onAdd } = props\n      if (onAdd)\n        onAdd()\n      void nextTick(() => {\n        const currentEl = getCurrentEl()\n        const { value: xScrollInst } = xScrollInstRef\n        if (!currentEl || !xScrollInst)\n          return\n        xScrollInst.scrollTo({\n          left: currentEl.offsetLeft,\n          top: 0,\n          behavior: 'smooth'\n        })\n      })\n    }\n\n    function deriveScrollShadow(el: HTMLElement | null): void {\n      if (!el)\n        return\n      const { placement } = props\n      if (placement === 'top' || placement === 'bottom') {\n        const { scrollLeft, scrollWidth, offsetWidth } = el\n        startReachedRef.value = scrollLeft <= 0\n        endReachedRef.value = scrollLeft + offsetWidth >= scrollWidth\n      }\n      else {\n        const { scrollTop, scrollHeight, offsetHeight } = el\n        startReachedRef.value = scrollTop <= 0\n        endReachedRef.value = scrollTop + offsetHeight >= scrollHeight\n      }\n    }\n\n    const handleScroll: (e: Event) => void = throttle((e: Event) => {\n      deriveScrollShadow(e.target as HTMLElement)\n    }, 64)\n    provide(tabsInjectionKey, {\n      triggerRef: toRef(props, 'trigger'),\n      tabStyleRef: toRef(props, 'tabStyle'),\n      tabClassRef: toRef(props, 'tabClass'),\n      addTabStyleRef: toRef(props, 'addTabStyle'),\n      addTabClassRef: toRef(props, 'addTabClass'),\n      paneClassRef: toRef(props, 'paneClass'),\n      paneStyleRef: toRef(props, 'paneStyle'),\n      mergedClsPrefixRef,\n      typeRef: toRef(props, 'type'),\n      closableRef: toRef(props, 'closable'),\n      valueRef: mergedValueRef,\n      tabChangeIdRef,\n      onBeforeLeaveRef: toRef(props, 'onBeforeLeave'),\n      activateTab,\n      handleClose,\n      handleAdd\n    })\n    onFontsReady(() => {\n      updateCurrentBarStyle()\n      updateCurrentScrollPosition()\n    })\n\n    // avoid useless rerender\n    watchEffect(() => {\n      const { value: el } = scrollWrapperElRef\n      if (!el)\n        return\n      const { value: clsPrefix } = mergedClsPrefixRef\n      const shadowStartClass = `${clsPrefix}-tabs-nav-scroll-wrapper--shadow-start`\n      const shadowEndClass = `${clsPrefix}-tabs-nav-scroll-wrapper--shadow-end`\n      if (startReachedRef.value) {\n        el.classList.remove(shadowStartClass)\n      }\n      else {\n        el.classList.add(shadowStartClass)\n      }\n      if (endReachedRef.value) {\n        el.classList.remove(shadowEndClass)\n      }\n      else {\n        el.classList.add(shadowEndClass)\n      }\n    })\n\n    const exposedMethods: TabsInst = {\n      syncBarPosition: () => {\n        updateCurrentBarStyle()\n      }\n    }\n\n    const handleSegmentResize = (): void => {\n      updateSegmentPosition({\n        transitionDisabled: true\n      })\n    }\n\n    const cssVarsRef = computed(() => {\n      const { value: size } = mergedSizeRef\n      const { type } = props\n      const typeSuffix = (\n        {\n          card: 'Card',\n          bar: 'Bar',\n          line: 'Line',\n          segment: 'Segment'\n        } as const\n      )[type]\n      const sizeType = `${size}${typeSuffix}` as const\n      const {\n        self: {\n          barColor,\n          closeIconColor,\n          closeIconColorHover,\n          closeIconColorPressed,\n          tabColor,\n          tabBorderColor,\n          paneTextColor,\n          tabFontWeight,\n          tabBorderRadius,\n          tabFontWeightActive,\n          colorSegment,\n          fontWeightStrong,\n          tabColorSegment,\n          closeSize,\n          closeIconSize,\n          closeColorHover,\n          closeColorPressed,\n          closeBorderRadius,\n          [createKey('panePadding', size)]: panePadding,\n          [createKey('tabPadding', sizeType)]: tabPadding,\n          [createKey('tabPaddingVertical', sizeType)]: tabPaddingVertical,\n          [createKey('tabGap', sizeType)]: tabGap,\n          [createKey('tabGap', `${sizeType}Vertical`)]: tabGapVertical,\n          [createKey('tabTextColor', type)]: tabTextColor,\n          [createKey('tabTextColorActive', type)]: tabTextColorActive,\n          [createKey('tabTextColorHover', type)]: tabTextColorHover,\n          [createKey('tabTextColorDisabled', type)]: tabTextColorDisabled,\n          [createKey('tabFontSize', size)]: tabFontSize\n        },\n        common: { cubicBezierEaseInOut }\n      } = themeRef.value\n      return {\n        '--n-bezier': cubicBezierEaseInOut,\n        '--n-color-segment': colorSegment,\n        '--n-bar-color': barColor,\n        '--n-tab-font-size': tabFontSize,\n        '--n-tab-text-color': tabTextColor,\n        '--n-tab-text-color-active': tabTextColorActive,\n        '--n-tab-text-color-disabled': tabTextColorDisabled,\n        '--n-tab-text-color-hover': tabTextColorHover,\n        '--n-pane-text-color': paneTextColor,\n        '--n-tab-border-color': tabBorderColor,\n        '--n-tab-border-radius': tabBorderRadius,\n        '--n-close-size': closeSize,\n        '--n-close-icon-size': closeIconSize,\n        '--n-close-color-hover': closeColorHover,\n        '--n-close-color-pressed': closeColorPressed,\n        '--n-close-border-radius': closeBorderRadius,\n        '--n-close-icon-color': closeIconColor,\n        '--n-close-icon-color-hover': closeIconColorHover,\n        '--n-close-icon-color-pressed': closeIconColorPressed,\n        '--n-tab-color': tabColor,\n        '--n-tab-font-weight': tabFontWeight,\n        '--n-tab-font-weight-active': tabFontWeightActive,\n        '--n-tab-padding': tabPadding,\n        '--n-tab-padding-vertical': tabPaddingVertical,\n        '--n-tab-gap': tabGap,\n        '--n-tab-gap-vertical': tabGapVertical,\n        '--n-pane-padding-left': getPadding(panePadding, 'left'),\n        '--n-pane-padding-right': getPadding(panePadding, 'right'),\n        '--n-pane-padding-top': getPadding(panePadding, 'top'),\n        '--n-pane-padding-bottom': getPadding(panePadding, 'bottom'),\n        '--n-font-weight-strong': fontWeightStrong,\n        '--n-tab-color-segment': tabColorSegment\n      }\n    })\n\n    const themeClassHandle = inlineThemeDisabled\n      ? useThemeClass(\n          'tabs',\n          computed(() => {\n            return `${mergedSizeRef.value[0]}${props.type[0]}`\n          }),\n          cssVarsRef,\n          props\n        )\n      : undefined\n\n    return {\n      mergedClsPrefix: mergedClsPrefixRef,\n      mergedValue: mergedValueRef,\n      renderedNames: new Set<NonNullable<TabPaneProps['name']>>(),\n      segmentCapsuleElRef,\n      tabsPaneWrapperRef,\n      tabsElRef,\n      barElRef,\n      addTabInstRef,\n      xScrollInstRef,\n      scrollWrapperElRef,\n      addTabFixed: addTabFixedRef,\n      tabWrapperStyle: tabWrapperStyleRef,\n      handleNavResize,\n      mergedSize: mergedSizeRef,\n      handleScroll,\n      handleTabsResize,\n      cssVars: inlineThemeDisabled ? undefined : cssVarsRef,\n      themeClass: themeClassHandle?.themeClass,\n      animationDirection: animationDirectionRef,\n      renderNameListRef,\n      yScrollElRef,\n      handleSegmentResize,\n      onAnimationBeforeLeave,\n      onAnimationEnter,\n      onAnimationAfterEnter,\n      onRender: themeClassHandle?.onRender,\n      ...exposedMethods\n    }\n  },\n  render() {\n    const {\n      mergedClsPrefix,\n      type,\n      placement,\n      addTabFixed,\n      addable,\n      mergedSize,\n      renderNameListRef,\n      onRender,\n      paneWrapperClass,\n      paneWrapperStyle,\n      $slots: { default: defaultSlot, prefix: prefixSlot, suffix: suffixSlot }\n    } = this\n\n    onRender?.()\n\n    const tabPaneChildren = defaultSlot\n      ? flatten(defaultSlot()).filter((v) => {\n          return (v.type as any).__TAB_PANE__ === true\n        })\n      : []\n    const tabChildren = defaultSlot\n      ? flatten(defaultSlot()).filter((v) => {\n          return (v.type as any).__TAB__ === true\n        })\n      : []\n    const showPane = !tabChildren.length\n    const isCard = type === 'card'\n    const isSegment = type === 'segment'\n    const mergedJustifyContent = !isCard && !isSegment && this.justifyContent\n    renderNameListRef.value = []\n    const scrollContent = (): JSX.Element => {\n      const tabs = (\n        <div\n          style={this.tabWrapperStyle}\n          class={`${mergedClsPrefix}-tabs-wrapper`}\n        >\n          {mergedJustifyContent ? null : (\n            <div\n              class={`${mergedClsPrefix}-tabs-scroll-padding`}\n              style={\n                placement === 'top' || placement === 'bottom'\n                  ? { width: `${this.tabsPadding}px` }\n                  : { height: `${this.tabsPadding}px` }\n              }\n            />\n          )}\n          {showPane\n            ? tabPaneChildren.map((tabPaneVNode: any, index: number) => {\n                renderNameListRef.value.push(\n                  tabPaneVNode.props.name as string | number\n                )\n                return justifyTabDynamicProps(\n                  <Tab\n                    {...tabPaneVNode.props}\n                    internalCreatedByPane={true}\n                    internalLeftPadded={\n                      index !== 0\n                      && (!mergedJustifyContent\n                        || mergedJustifyContent === 'center'\n                        || mergedJustifyContent === 'start'\n                        || mergedJustifyContent === 'end')\n                    }\n                  >\n                    {tabPaneVNode.children\n                      ? {\n                          default: tabPaneVNode.children.tab\n                        }\n                      : undefined}\n                  </Tab>\n                )\n              })\n            : tabChildren.map((tabVNode: any, index: number) => {\n                renderNameListRef.value.push(\n                  tabVNode.props.name as string | number\n                )\n                if (index !== 0 && !mergedJustifyContent) {\n                  return justifyTabDynamicProps(\n                    createLeftPaddedTabVNode(tabVNode as VNode)\n                  )\n                }\n                else {\n                  return justifyTabDynamicProps(tabVNode as VNode)\n                }\n              })}\n          {!addTabFixed && addable && isCard\n            ? createAddTag(\n                addable,\n                (showPane ? tabPaneChildren.length : tabChildren.length) !== 0\n              )\n            : null}\n          {mergedJustifyContent ? null : (\n            <div\n              class={`${mergedClsPrefix}-tabs-scroll-padding`}\n              style={{ width: `${this.tabsPadding}px` }}\n            />\n          )}\n        </div>\n      )\n      return (\n        <div\n          ref=\"tabsElRef\"\n          class={`${mergedClsPrefix}-tabs-nav-scroll-content`}\n        >\n          {isCard && addable ? (\n            <VResizeObserver onResize={this.handleTabsResize}>\n              {{\n                default: () => tabs\n              }}\n            </VResizeObserver>\n          ) : (\n            tabs\n          )}\n          {isCard ? <div class={`${mergedClsPrefix}-tabs-pad`} /> : null}\n          {isCard ? null : (\n            <div ref=\"barElRef\" class={`${mergedClsPrefix}-tabs-bar`} />\n          )}\n        </div>\n      )\n    }\n    const resolvedPlacement = isSegment ? 'top' : placement\n    return (\n      <div\n        class={[\n          `${mergedClsPrefix}-tabs`,\n          this.themeClass,\n          `${mergedClsPrefix}-tabs--${type}-type`,\n          `${mergedClsPrefix}-tabs--${mergedSize}-size`,\n          mergedJustifyContent && `${mergedClsPrefix}-tabs--flex`,\n          `${mergedClsPrefix}-tabs--${resolvedPlacement}`\n        ]}\n        style={this.cssVars as CSSProperties}\n      >\n        <div\n          class={[\n            // the class should be applied here since it's possible\n            // to make tabs nested in tabs, style may influence each\n            // other. adding a class will make it easy to write the\n            // style.\n            `${mergedClsPrefix}-tabs-nav--${type}-type`,\n            `${mergedClsPrefix}-tabs-nav--${resolvedPlacement}`,\n            `${mergedClsPrefix}-tabs-nav`\n          ]}\n        >\n          {resolveWrappedSlot(\n            prefixSlot,\n            children =>\n              children && (\n                <div class={`${mergedClsPrefix}-tabs-nav__prefix`}>\n                  {children}\n                </div>\n              )\n          )}\n          {isSegment ? (\n            <VResizeObserver onResize={this.handleSegmentResize}>\n              {{\n                default: () => (\n                  <div class={`${mergedClsPrefix}-tabs-rail`} ref=\"tabsElRef\">\n                    <div\n                      class={`${mergedClsPrefix}-tabs-capsule`}\n                      ref=\"segmentCapsuleElRef\"\n                    >\n                      <div class={`${mergedClsPrefix}-tabs-wrapper`}>\n                        <div class={`${mergedClsPrefix}-tabs-tab`} />\n                      </div>\n                    </div>\n                    {showPane\n                      ? tabPaneChildren.map(\n                          (tabPaneVNode: any, index: number) => {\n                            renderNameListRef.value.push(\n                              tabPaneVNode.props.name as string | number\n                            )\n                            return (\n                              <Tab\n                                {...tabPaneVNode.props}\n                                internalCreatedByPane={true}\n                                internalLeftPadded={index !== 0}\n                              >\n                                {tabPaneVNode.children\n                                  ? {\n                                      default: tabPaneVNode.children.tab\n                                    }\n                                  : undefined}\n                              </Tab>\n                            )\n                          }\n                        )\n                      : tabChildren.map((tabVNode: any, index: number) => {\n                          renderNameListRef.value.push(\n                            tabVNode.props.name as string | number\n                          )\n                          if (index === 0) {\n                            return tabVNode\n                          }\n                          else {\n                            return createLeftPaddedTabVNode(tabVNode as VNode)\n                          }\n                        })}\n                  </div>\n                )\n              }}\n            </VResizeObserver>\n          ) : (\n            <VResizeObserver onResize={this.handleNavResize}>\n              {{\n                default: () => (\n                  <div\n                    class={`${mergedClsPrefix}-tabs-nav-scroll-wrapper`}\n                    ref=\"scrollWrapperElRef\"\n                  >\n                    {['top', 'bottom'].includes(resolvedPlacement) ? (\n                      <VXScroll\n                        ref=\"xScrollInstRef\"\n                        onScroll={this.handleScroll}\n                      >\n                        {{\n                          default: scrollContent\n                        }}\n                      </VXScroll>\n                    ) : (\n                      <div\n                        class={`${mergedClsPrefix}-tabs-nav-y-scroll`}\n                        onScroll={this.handleScroll}\n                        ref=\"yScrollElRef\"\n                      >\n                        {scrollContent()}\n                      </div>\n                    )}\n                  </div>\n                )\n              }}\n            </VResizeObserver>\n          )}\n          {addTabFixed && addable && isCard\n            ? createAddTag(addable, true)\n            : null}\n          {resolveWrappedSlot(\n            suffixSlot,\n            children =>\n              children && (\n                <div class={`${mergedClsPrefix}-tabs-nav__suffix`}>\n                  {children}\n                </div>\n              )\n          )}\n        </div>\n        {showPane\n          && (this.animated\n            && (resolvedPlacement === 'top' || resolvedPlacement === 'bottom') ? (\n                <div\n                  ref=\"tabsPaneWrapperRef\"\n                  style={paneWrapperStyle}\n                  class={[`${mergedClsPrefix}-tabs-pane-wrapper`, paneWrapperClass]}\n                >\n                  {filterMapTabPanes(\n                    tabPaneChildren,\n                    this.mergedValue,\n                    this.renderedNames,\n                    this.onAnimationBeforeLeave,\n                    this.onAnimationEnter,\n                    this.onAnimationAfterEnter,\n                    this.animationDirection\n                  )}\n                </div>\n              ) : (\n                filterMapTabPanes(\n                  tabPaneChildren,\n                  this.mergedValue,\n                  this.renderedNames\n                )\n              ))}\n      </div>\n    )\n  }\n})\n\nfunction filterMapTabPanes(\n  tabPaneVNodes: VNode[],\n  value: string | number | null,\n  renderedNames: Set<string | number>,\n  onBeforeLeave?: (el: HTMLElement) => void,\n  onEnter?: (el: HTMLElement) => void,\n  onAfterEnter?: () => void,\n  animationDirection?: 'next' | 'prev'\n): VNode | VNode[] {\n  const children: VNode[] = []\n  tabPaneVNodes.forEach((vNode) => {\n    const {\n      name,\n      displayDirective,\n      'display-directive': _displayDirective\n    } = vNode.props as TabPaneProps\n    const matchDisplayDirective = (\n      directive: TabPaneProps['displayDirective']\n    ): boolean =>\n      displayDirective === directive || _displayDirective === directive\n    const show = value === name\n    if (vNode.key !== undefined) {\n      vNode.key = name\n    }\n    if (\n      show\n      || matchDisplayDirective('show')\n      || (matchDisplayDirective('show:lazy') && renderedNames.has(name))\n    ) {\n      if (!renderedNames.has(name)) {\n        renderedNames.add(name)\n      }\n      const useVShow = !matchDisplayDirective('if')\n      children.push(useVShow ? withDirectives(vNode, [[vShow, show]]) : vNode)\n    }\n  })\n  if (!animationDirection) {\n    return children\n  }\n  return (\n    <TransitionGroup\n      name={`${animationDirection}-transition`}\n      onBeforeLeave={onBeforeLeave as (el: Element) => void}\n      onEnter={onEnter as (el: Element) => void}\n      onAfterEnter={onAfterEnter}\n    >\n      {{ default: () => children }}\n    </TransitionGroup>\n  )\n}\n\nfunction createAddTag(addable: Addable, internalLeftPadded: boolean): VNode {\n  return (\n    <Tab\n      ref=\"addTabInstRef\"\n      key=\"__addable\"\n      name=\"__addable\"\n      internalCreatedByPane\n      internalAddable\n      internalLeftPadded={internalLeftPadded}\n      disabled={typeof addable === 'object' && addable.disabled}\n    />\n  )\n}\n\nfunction createLeftPaddedTabVNode(tabVNode: VNode): VNode {\n  const modifiedVNode = cloneVNode(tabVNode)\n  if (modifiedVNode.props) {\n    modifiedVNode.props.internalLeftPadded = true\n  }\n  else {\n    modifiedVNode.props = {\n      internalLeftPadded: true\n    }\n  }\n  return modifiedVNode\n}\n\nfunction justifyTabDynamicProps(\n  tabVNode: {\n    dynamicProps?: string[]\n  } & VNode\n): VNode {\n  if (Array.isArray(tabVNode.dynamicProps)) {\n    if (!tabVNode.dynamicProps.includes('internalLeftPadded')) {\n      tabVNode.dynamicProps.push('internalLeftPadded')\n    }\n  }\n  else {\n    tabVNode.dynamicProps = ['internalLeftPadded']\n  }\n  return tabVNode\n}\n"
  },
  {
    "path": "src/tabs/src/interface.ts",
    "content": "import type { CSSProperties, Ref } from 'vue'\nimport { createInjectionKey } from '../../_utils'\n\nexport type TabsType = 'line' | 'card' | 'bar' | 'segment'\n\nexport type OnUpdateValue = (value: string & number) => void\nexport type OnUpdateValueImpl = (value: string | number) => void\n\nexport type OnClose = (name: string & number) => void\nexport type OnCloseImpl = (name: string | number) => void\n\nexport type OnBeforeLeave = (\n  name: string & number,\n  oldName: string & number & null\n) => boolean | Promise<boolean>\nexport type OnBeforeLeaveImpl = (\n  name: string | number,\n  oldName: string | number | null\n) => boolean | Promise<boolean>\n\nexport interface TabsInjection {\n  mergedClsPrefixRef: Ref<string>\n  valueRef: Ref<string | number | null>\n  typeRef: Ref<TabsType>\n  closableRef: Ref<boolean>\n  tabStyleRef: Ref<string | CSSProperties | undefined>\n  tabClassRef: Ref<string | undefined>\n  addTabClassRef: Ref<string | undefined>\n  addTabStyleRef: Ref<string | CSSProperties | undefined>\n  paneClassRef: Ref<string | undefined>\n  paneStyleRef: Ref<string | CSSProperties | undefined>\n  tabChangeIdRef: { id: number }\n  onBeforeLeaveRef: Ref<OnBeforeLeave | undefined>\n  triggerRef: Ref<'click' | 'hover'>\n  activateTab: (panelName: string | number) => void\n  handleClose: (panelName: string | number) => void\n  handleAdd: () => void\n}\n\nexport type Addable\n  = | boolean\n    | {\n      disabled?: boolean\n    }\n\nexport const tabsInjectionKey = createInjectionKey<TabsInjection>('n-tabs')\n\nexport interface TabsInst {\n  syncBarPosition: () => void\n}\n"
  },
  {
    "path": "src/tabs/src/public-types.ts",
    "content": "export type TabsSize = 'small' | 'medium' | 'large'\n"
  },
  {
    "path": "src/tabs/src/styles/index.cssr.ts",
    "content": "import { c, cB, cE, cM, cNotM } from '../../../_utils/cssr'\n\n// vars:\n// --n-bezier\n// --n-close-size\n// --n-close-color-hover\n// --n-close-color-pressed\n// --n-close-icon-size\n// --n-close-icon-color\n// --n-close-icon-color-hover\n// --n-close-icon-color-pressed\n// --n-bar-color\n// --n-tab-font-size\n// --n-tab-text-color\n// --n-tab-text-color-active\n// --n-tab-text-color-disabled\n// --n-tab-text-color-hover\n// --n-pane-text-color\n// --n-tab-border-color\n// --n-tab-border-radius\n// --n-tab-color\n// --n-tab-font-weight\n// --n-tab-font-weight-active\n// --n-tab-gap\n// --n-tab-gap-vertical\n// --n-tab-padding\n// --n-pane-padding-left\n// --n-pane-padding-right\n// --n-pane-padding-top\n// --n-pane-padding-bottom\n// --n-color-segment\n// --n-font-weight-strong\n// --n-tab-color-segment\nexport default cB('tabs', `\n  box-sizing: border-box;\n  width: 100%;\n  display: flex;\n  flex-direction: column;\n  transition:\n    background-color .3s var(--n-bezier),\n    border-color .3s var(--n-bezier);\n`, [\n  cM('segment-type', [\n    cB('tabs-rail', [\n      c('&.transition-disabled', [\n        cB('tabs-capsule', `\n          transition: none;\n        `)\n      ])\n    ])\n  ]),\n  cM('top', [\n    cB('tab-pane', `\n      padding: var(--n-pane-padding-top) var(--n-pane-padding-right) var(--n-pane-padding-bottom) var(--n-pane-padding-left);\n    `)\n  ]),\n  cM('left', [\n    cB('tab-pane', `\n      padding: var(--n-pane-padding-right) var(--n-pane-padding-bottom) var(--n-pane-padding-left) var(--n-pane-padding-top);\n    `)\n  ]),\n  cM('left, right', `\n    flex-direction: row;\n  `, [\n    cB('tabs-bar', `\n      width: 2px;\n      right: 0;\n      transition:\n        top .2s var(--n-bezier),\n        max-height .2s var(--n-bezier),\n        background-color .3s var(--n-bezier);\n    `),\n    cB('tabs-tab', `\n      padding: var(--n-tab-padding-vertical); \n    `)\n  ]),\n  cM('right', `\n    flex-direction: row-reverse;\n  `, [\n    cB('tab-pane', `\n      padding: var(--n-pane-padding-left) var(--n-pane-padding-top) var(--n-pane-padding-right) var(--n-pane-padding-bottom);\n    `),\n    cB('tabs-bar', `\n      left: 0;\n    `)\n  ]),\n  cM('bottom', `\n    flex-direction: column-reverse;\n    justify-content: flex-end;\n  `, [\n    cB('tab-pane', `\n      padding: var(--n-pane-padding-bottom) var(--n-pane-padding-right) var(--n-pane-padding-top) var(--n-pane-padding-left);\n    `),\n    cB('tabs-bar', `\n      top: 0;\n    `)\n  ]),\n  cB('tabs-rail', `\n    position: relative;\n    padding: 3px;\n    border-radius: var(--n-tab-border-radius);\n    width: 100%;\n    background-color: var(--n-color-segment);\n    transition: background-color .3s var(--n-bezier);\n    display: flex;\n    align-items: center;\n  `, [\n    cB('tabs-capsule', `\n      border-radius: var(--n-tab-border-radius);\n      position: absolute;\n      pointer-events: none;\n      background-color: var(--n-tab-color-segment);\n      box-shadow: 0 1px 3px 0 rgba(0, 0, 0, .08);\n      transition: transform 0.3s var(--n-bezier);\n    `),\n    cB('tabs-tab-wrapper', `\n      flex-basis: 0;\n      flex-grow: 1;\n      display: flex;\n      align-items: center;\n      justify-content: center;\n    `, [\n      cB('tabs-tab', `\n        overflow: hidden;\n        border-radius: var(--n-tab-border-radius);\n        width: 100%;\n        display: flex;\n        align-items: center;\n        justify-content: center;\n      `, [\n        cM('active', `\n          font-weight: var(--n-font-weight-strong);\n          color: var(--n-tab-text-color-active);\n        `),\n        c('&:hover', `\n          color: var(--n-tab-text-color-hover);\n        `)\n      ])\n    ])\n  ]),\n  cM('flex', [\n    cB('tabs-nav', `\n      width: 100%;\n      position: relative;\n    `, [\n      cB('tabs-wrapper', `\n        width: 100%;\n      `, [\n        cB('tabs-tab', `\n          margin-right: 0;\n        `)\n      ])\n    ])\n  ]),\n  cB('tabs-nav', `\n    box-sizing: border-box;\n    line-height: 1.5;\n    display: flex;\n    transition: border-color .3s var(--n-bezier);\n  `, [\n    cE('prefix, suffix', `\n      display: flex;\n      align-items: center;\n    `),\n    cE('prefix', 'padding-right: 16px;'),\n    cE('suffix', 'padding-left: 16px;')\n  ]),\n  cM('top, bottom', [\n    c('>', [\n      cB('tabs-nav', [\n        cB('tabs-nav-scroll-wrapper', [\n          c('&::before', `\n            top: 0;\n            bottom: 0;\n            left: 0;\n            width: 20px;\n          `),\n          c('&::after', `\n            top: 0;\n            bottom: 0;\n            right: 0;\n            width: 20px;\n          `),\n          cM('shadow-start', [\n            c('&::before', `\n              box-shadow: inset 10px 0 8px -8px rgba(0, 0, 0, .12);\n            `)\n          ]),\n          cM('shadow-end', [\n            c('&::after', `\n              box-shadow: inset -10px 0 8px -8px rgba(0, 0, 0, .12);\n            `)\n          ])\n        ])\n      ])\n    ])\n  ]),\n  cM('left, right', [\n    cB('tabs-nav-scroll-content', `\n      flex-direction: column;\n    `),\n    c('>', [\n      cB('tabs-nav', [\n        cB('tabs-nav-scroll-wrapper', [\n          c('&::before', `\n            top: 0;\n            left: 0;\n            right: 0;\n            height: 20px;\n          `),\n          c('&::after', `\n            bottom: 0;\n            left: 0;\n            right: 0;\n            height: 20px;\n          `),\n          cM('shadow-start', [\n            c('&::before', `\n              box-shadow: inset 0 10px 8px -8px rgba(0, 0, 0, .12);\n            `)\n          ]),\n          cM('shadow-end', [\n            c('&::after', `\n              box-shadow: inset 0 -10px 8px -8px rgba(0, 0, 0, .12);\n            `)\n          ])\n        ])\n      ])\n    ])\n  ]),\n  cB('tabs-nav-scroll-wrapper', `\n    flex: 1;\n    position: relative;\n    overflow: hidden;\n  `, [\n    cB('tabs-nav-y-scroll', `\n      height: 100%;\n      width: 100%;\n      overflow-y: auto; \n      scrollbar-width: none;\n    `, [\n      c('&::-webkit-scrollbar, &::-webkit-scrollbar-track-piece, &::-webkit-scrollbar-thumb', `\n        width: 0;\n        height: 0;\n        display: none;\n      `)\n    ]),\n    c('&::before, &::after', `\n      transition: box-shadow .3s var(--n-bezier);\n      pointer-events: none;\n      content: \"\";\n      position: absolute;\n      z-index: 1;\n    `)\n  ]),\n  cB('tabs-nav-scroll-content', `\n    display: flex;\n    position: relative;\n    min-width: 100%;\n    min-height: 100%;\n    width: fit-content;\n    box-sizing: border-box;\n  `),\n  cB('tabs-wrapper', `\n    display: inline-flex;\n    flex-wrap: nowrap;\n    position: relative;\n  `),\n  cB('tabs-tab-wrapper', `\n    display: flex;\n    flex-wrap: nowrap;\n    flex-shrink: 0;\n    flex-grow: 0;\n  `),\n  cB('tabs-tab', `\n    cursor: pointer;\n    white-space: nowrap;\n    flex-wrap: nowrap;\n    display: inline-flex;\n    align-items: center;\n    color: var(--n-tab-text-color);\n    font-size: var(--n-tab-font-size);\n    background-clip: padding-box;\n    padding: var(--n-tab-padding);\n    transition:\n      box-shadow .3s var(--n-bezier),\n      color .3s var(--n-bezier),\n      background-color .3s var(--n-bezier),\n      border-color .3s var(--n-bezier);\n  `, [\n    cM('disabled', {\n      cursor: 'not-allowed'\n    }),\n    cE('close', `\n      margin-left: 6px;\n      transition:\n        background-color .3s var(--n-bezier),\n        color .3s var(--n-bezier);\n    `),\n    cE('label', `\n      display: flex;\n      align-items: center;\n      z-index: 1;\n    `)\n  ]),\n  cB('tabs-bar', `\n    position: absolute;\n    bottom: 0;\n    height: 2px;\n    border-radius: 1px;\n    background-color: var(--n-bar-color);\n    transition:\n      left .2s var(--n-bezier),\n      max-width .2s var(--n-bezier),\n      opacity .3s var(--n-bezier),\n      background-color .3s var(--n-bezier);\n  `, [\n    c('&.transition-disabled', `\n      transition: none;\n    `),\n    cM('disabled', `\n      background-color: var(--n-tab-text-color-disabled)\n    `)\n  ]),\n  cB('tabs-pane-wrapper', `\n    position: relative;\n    overflow: hidden;\n    transition: max-height .2s var(--n-bezier);\n  `),\n  cB('tab-pane', `\n    color: var(--n-pane-text-color);\n    width: 100%;\n    transition:\n      color .3s var(--n-bezier),\n      background-color .3s var(--n-bezier),\n      opacity .2s var(--n-bezier);\n    left: 0;\n    right: 0;\n    top: 0;\n  `, [\n    c('&.next-transition-leave-active, &.prev-transition-leave-active, &.next-transition-enter-active, &.prev-transition-enter-active', `\n      transition:\n      color .3s var(--n-bezier),\n      background-color .3s var(--n-bezier),\n      transform .2s var(--n-bezier),\n      opacity .2s var(--n-bezier);\n    `),\n    c('&.next-transition-leave-active, &.prev-transition-leave-active', `\n      position: absolute;\n    `),\n    c('&.next-transition-enter-from, &.prev-transition-leave-to', `\n      transform: translateX(32px);\n      opacity: 0;\n    `),\n    c('&.next-transition-leave-to, &.prev-transition-enter-from', `\n      transform: translateX(-32px);\n      opacity: 0;\n    `),\n    c('&.next-transition-leave-from, &.next-transition-enter-to, &.prev-transition-leave-from, &.prev-transition-enter-to', `\n      transform: translateX(0);\n      opacity: 1;\n    `)\n  ]),\n  cB('tabs-tab-pad', `\n    box-sizing: border-box;\n    width: var(--n-tab-gap);\n    flex-grow: 0;\n    flex-shrink: 0;\n  `),\n  cM('line-type, bar-type', [\n    cB('tabs-tab', `\n      font-weight: var(--n-tab-font-weight);\n      box-sizing: border-box;\n      vertical-align: bottom;\n    `, [\n      c('&:hover', {\n        color: 'var(--n-tab-text-color-hover)'\n      }),\n      cM('active', `\n        color: var(--n-tab-text-color-active);\n        font-weight: var(--n-tab-font-weight-active);\n      `),\n      cM('disabled', {\n        color: 'var(--n-tab-text-color-disabled)'\n      })\n    ])\n  ]),\n  cB('tabs-nav', [\n    cM('line-type', [\n      cM('top', [\n        cE('prefix, suffix', `\n          border-bottom: 1px solid var(--n-tab-border-color);\n        `),\n        cB('tabs-nav-scroll-content', `\n          border-bottom: 1px solid var(--n-tab-border-color);\n        `),\n        cB('tabs-bar', `\n          bottom: -1px;\n        `)\n      ]),\n      cM('left', [\n        cE('prefix, suffix', `\n          border-right: 1px solid var(--n-tab-border-color);\n        `),\n        cB('tabs-nav-scroll-content', `\n          border-right: 1px solid var(--n-tab-border-color);\n        `),\n        cB('tabs-bar', `\n          right: -1px;\n        `)\n      ]),\n      cM('right', [\n        cE('prefix, suffix', `\n          border-left: 1px solid var(--n-tab-border-color);\n        `),\n        cB('tabs-nav-scroll-content', `\n          border-left: 1px solid var(--n-tab-border-color);\n        `),\n        cB('tabs-bar', `\n          left: -1px;\n        `)\n      ]),\n      cM('bottom', [\n        cE('prefix, suffix', `\n          border-top: 1px solid var(--n-tab-border-color);\n        `),\n        cB('tabs-nav-scroll-content', `\n          border-top: 1px solid var(--n-tab-border-color);\n        `),\n        cB('tabs-bar', `\n          top: -1px;\n        `)\n      ]),\n      cE('prefix, suffix', `\n        transition: border-color .3s var(--n-bezier);\n      `),\n      cB('tabs-nav-scroll-content', `\n        transition: border-color .3s var(--n-bezier);\n      `),\n      cB('tabs-bar', `\n        border-radius: 0;\n      `)\n    ]),\n    cM('card-type', [\n      cE('prefix, suffix', `\n        transition: border-color .3s var(--n-bezier);\n      `),\n      cB('tabs-pad', `\n        flex-grow: 1;\n        transition: border-color .3s var(--n-bezier);\n      `),\n      cB('tabs-tab-pad', `\n        transition: border-color .3s var(--n-bezier);\n      `),\n      cB('tabs-tab', `\n        font-weight: var(--n-tab-font-weight);\n        border: 1px solid var(--n-tab-border-color);\n        background-color: var(--n-tab-color);\n        box-sizing: border-box;\n        position: relative;\n        vertical-align: bottom;\n        display: flex;\n        justify-content: space-between;\n        font-size: var(--n-tab-font-size);\n        color: var(--n-tab-text-color);\n      `, [\n        cM('addable', `\n          padding-left: 8px;\n          padding-right: 8px;\n          font-size: 16px;\n          justify-content: center;\n        `, [\n          cE('height-placeholder', `\n            width: 0;\n            font-size: var(--n-tab-font-size);\n          `),\n          cNotM('disabled', [\n            c('&:hover', `\n              color: var(--n-tab-text-color-hover);\n            `)\n          ])\n        ]),\n        cM('closable', 'padding-right: 8px;'),\n        cM('active', `\n          background-color: #0000;\n          font-weight: var(--n-tab-font-weight-active);\n          color: var(--n-tab-text-color-active);\n        `),\n        cM('disabled', 'color: var(--n-tab-text-color-disabled);')\n      ]),\n    ]),\n    cM('left, right', `\n      flex-direction: column;  \n    `, [\n      cE('prefix, suffix', `\n        padding: var(--n-tab-padding-vertical);\n      `),\n      cB('tabs-wrapper', `\n        flex-direction: column;\n      `),\n      cB('tabs-tab-wrapper', `\n        flex-direction: column;\n      `, [\n        cB('tabs-tab-pad', `\n          height: var(--n-tab-gap-vertical);\n          width: 100%;\n        `)\n      ])\n    ]),\n    cM('top', [\n      cM('card-type', [\n        cB('tabs-scroll-padding', 'border-bottom: 1px solid var(--n-tab-border-color);'),\n        cE('prefix, suffix', `\n          border-bottom: 1px solid var(--n-tab-border-color);\n        `),\n        cB('tabs-tab', `\n          border-top-left-radius: var(--n-tab-border-radius);\n          border-top-right-radius: var(--n-tab-border-radius);\n        `, [\n          cM('active', `\n            border-bottom: 1px solid #0000;\n          `)\n        ]),\n        cB('tabs-tab-pad', `\n          border-bottom: 1px solid var(--n-tab-border-color);\n        `),\n        cB('tabs-pad', `\n          border-bottom: 1px solid var(--n-tab-border-color);\n        `)\n      ])\n    ]),\n    cM('left', [\n      cM('card-type', [\n        cB('tabs-scroll-padding', 'border-right: 1px solid var(--n-tab-border-color);'),\n        cE('prefix, suffix', `\n          border-right: 1px solid var(--n-tab-border-color);\n        `),\n        cB('tabs-tab', `\n          border-top-left-radius: var(--n-tab-border-radius);\n          border-bottom-left-radius: var(--n-tab-border-radius);\n        `, [\n          cM('active', `\n            border-right: 1px solid #0000;\n          `)\n        ]),\n        cB('tabs-tab-pad', `\n          border-right: 1px solid var(--n-tab-border-color);\n        `),\n        cB('tabs-pad', `\n          border-right: 1px solid var(--n-tab-border-color);\n        `)\n      ])\n    ]),\n    cM('right', [\n      cM('card-type', [\n        cB('tabs-scroll-padding', 'border-left: 1px solid var(--n-tab-border-color);'),\n        cE('prefix, suffix', `\n          border-left: 1px solid var(--n-tab-border-color);\n        `),\n        cB('tabs-tab', `\n          border-top-right-radius: var(--n-tab-border-radius);\n          border-bottom-right-radius: var(--n-tab-border-radius);\n        `, [\n          cM('active', `\n            border-left: 1px solid #0000;\n          `)\n        ]),\n        cB('tabs-tab-pad', `\n          border-left: 1px solid var(--n-tab-border-color);\n        `),\n        cB('tabs-pad', `\n          border-left: 1px solid var(--n-tab-border-color);\n        `)\n      ])\n    ]),\n    cM('bottom', [\n      cM('card-type', [\n        cB('tabs-scroll-padding', 'border-top: 1px solid var(--n-tab-border-color);'),\n        cE('prefix, suffix', `\n          border-top: 1px solid var(--n-tab-border-color);\n        `),\n        cB('tabs-tab', `\n          border-bottom-left-radius: var(--n-tab-border-radius);\n          border-bottom-right-radius: var(--n-tab-border-radius);\n        `, [\n          cM('active', `\n            border-top: 1px solid #0000;\n          `)\n        ]),\n        cB('tabs-tab-pad', `\n          border-top: 1px solid var(--n-tab-border-color);\n        `),\n        cB('tabs-pad', `\n          border-top: 1px solid var(--n-tab-border-color);\n        `)\n      ])\n    ])\n  ])\n])\n"
  },
  {
    "path": "src/tabs/styles/_common.ts",
    "content": "export default {\n  tabFontSizeSmall: '14px',\n  tabFontSizeMedium: '14px',\n  tabFontSizeLarge: '16px',\n  tabGapSmallLine: '36px',\n  tabGapMediumLine: '36px',\n  tabGapLargeLine: '36px',\n  tabGapSmallLineVertical: '8px',\n  tabGapMediumLineVertical: '8px',\n  tabGapLargeLineVertical: '8px',\n  tabPaddingSmallLine: '6px 0',\n  tabPaddingMediumLine: '10px 0',\n  tabPaddingLargeLine: '14px 0',\n  tabPaddingVerticalSmallLine: '6px 12px',\n  tabPaddingVerticalMediumLine: '8px 16px',\n  tabPaddingVerticalLargeLine: '10px 20px',\n  tabGapSmallBar: '36px',\n  tabGapMediumBar: '36px',\n  tabGapLargeBar: '36px',\n  tabGapSmallBarVertical: '8px',\n  tabGapMediumBarVertical: '8px',\n  tabGapLargeBarVertical: '8px',\n  tabPaddingSmallBar: '4px 0',\n  tabPaddingMediumBar: '6px 0',\n  tabPaddingLargeBar: '10px 0',\n  tabPaddingVerticalSmallBar: '6px 12px',\n  tabPaddingVerticalMediumBar: '8px 16px',\n  tabPaddingVerticalLargeBar: '10px 20px',\n  tabGapSmallCard: '4px',\n  tabGapMediumCard: '4px',\n  tabGapLargeCard: '4px',\n  tabGapSmallCardVertical: '4px',\n  tabGapMediumCardVertical: '4px',\n  tabGapLargeCardVertical: '4px',\n  tabPaddingSmallCard: '8px 16px',\n  tabPaddingMediumCard: '10px 20px',\n  tabPaddingLargeCard: '12px 24px',\n  tabPaddingSmallSegment: '4px 0',\n  tabPaddingMediumSegment: '6px 0',\n  tabPaddingLargeSegment: '8px 0',\n  tabPaddingVerticalLargeSegment: '0 8px',\n  tabPaddingVerticalSmallCard: '8px 12px',\n  tabPaddingVerticalMediumCard: '10px 16px',\n  tabPaddingVerticalLargeCard: '12px 20px',\n  tabPaddingVerticalSmallSegment: '0 4px',\n  tabPaddingVerticalMediumSegment: '0 6px',\n  tabGapSmallSegment: '0',\n  tabGapMediumSegment: '0',\n  tabGapLargeSegment: '0',\n  tabGapSmallSegmentVertical: '0',\n  tabGapMediumSegmentVertical: '0',\n  tabGapLargeSegmentVertical: '0',\n  panePaddingSmall: '8px 0 0 0',\n  panePaddingMedium: '12px 0 0 0',\n  panePaddingLarge: '16px 0 0 0',\n  closeSize: '18px',\n  closeIconSize: '14px'\n}\n"
  },
  {
    "path": "src/tabs/styles/dark.ts",
    "content": "import type { TabsTheme } from './light'\nimport { commonDark } from '../../_styles/common'\nimport { self } from './light'\n\nconst tabsDark: TabsTheme = {\n  name: 'Tabs',\n  common: commonDark,\n  self(vars) {\n    const commonSelf = self(vars)\n    const { inputColor } = vars\n    commonSelf.colorSegment = inputColor\n    commonSelf.tabColorSegment = inputColor\n    return commonSelf\n  }\n}\n\nexport default tabsDark\n"
  },
  {
    "path": "src/tabs/styles/index.ts",
    "content": "export { default as tabsDark } from './dark'\nexport { default as tabsLight } from './light'\nexport type { TabsTheme, TabsThemeVars } from './light'\n"
  },
  {
    "path": "src/tabs/styles/light.ts",
    "content": "import type { Theme } from '../../_mixins'\nimport type { ThemeCommonVars } from '../../_styles/common'\nimport { commonLight } from '../../_styles/common'\nimport sizeVariables from './_common'\n\nexport function self(vars: ThemeCommonVars) {\n  const {\n    textColor2,\n    primaryColor,\n    textColorDisabled,\n    closeIconColor,\n    closeIconColorHover,\n    closeIconColorPressed,\n    closeColorHover,\n    closeColorPressed,\n    tabColor,\n    baseColor,\n    dividerColor,\n    fontWeight,\n    textColor1,\n    borderRadius,\n    fontSize,\n    fontWeightStrong\n  } = vars\n  return {\n    ...sizeVariables,\n    colorSegment: tabColor,\n    tabFontSizeCard: fontSize,\n    tabTextColorLine: textColor1,\n    tabTextColorActiveLine: primaryColor,\n    tabTextColorHoverLine: primaryColor,\n    tabTextColorDisabledLine: textColorDisabled,\n    tabTextColorSegment: textColor1,\n    tabTextColorActiveSegment: textColor2,\n    tabTextColorHoverSegment: textColor2,\n    tabTextColorDisabledSegment: textColorDisabled,\n    tabTextColorBar: textColor1,\n    tabTextColorActiveBar: primaryColor,\n    tabTextColorHoverBar: primaryColor,\n    tabTextColorDisabledBar: textColorDisabled,\n    tabTextColorCard: textColor1,\n    tabTextColorHoverCard: textColor1,\n    tabTextColorActiveCard: primaryColor,\n    tabTextColorDisabledCard: textColorDisabled,\n    barColor: primaryColor,\n    closeIconColor,\n    closeIconColorHover,\n    closeIconColorPressed,\n    closeColorHover,\n    closeColorPressed,\n    closeBorderRadius: borderRadius,\n    tabColor,\n    tabColorSegment: baseColor,\n    tabBorderColor: dividerColor,\n    tabFontWeightActive: fontWeight,\n    tabFontWeight: fontWeight,\n    tabBorderRadius: borderRadius,\n    paneTextColor: textColor2,\n    fontWeightStrong\n  }\n}\n\nexport type TabsThemeVars = ReturnType<typeof self>\n\nconst tabsLight: Theme<'Tabs', TabsThemeVars> = {\n  name: 'Tabs',\n  common: commonLight,\n  self\n}\n\nexport default tabsLight\nexport type TabsTheme = typeof tabsLight\n"
  },
  {
    "path": "src/tabs/tests/Tabs.spec.tsx",
    "content": "/* eslint-disable unused-imports/no-unused-vars */\nimport { mount } from '@vue/test-utils'\nimport { sleep } from 'seemly'\nimport { h } from 'vue'\nimport { AddIcon } from '../../_internal/icons'\nimport { NTabPane, NTabs } from '../index'\n\ndescribe('n-tabs', () => {\n  it('should work with import on demand', () => {\n    mount(NTabs)\n  })\n\n  it('should work with callback types', () => {\n    function onUpdateValue1(name: number): void {}\n    function onUpdateValue2(name: string): void {}\n    function onUpdateValue3(name: number | string): void {}\n    mount(NTabs, {\n      props: {\n        onUpdateValue: onUpdateValue1\n      }\n    })\n    mount(NTabs, {\n      props: {\n        onUpdateValue: onUpdateValue2\n      }\n    })\n    mount(NTabs, {\n      props: {\n        onUpdateValue: onUpdateValue3\n      }\n    })\n  })\n\n  it('should work with empty tab-pane', () => {\n    mount(NTabs, {\n      props: {\n        defaultValue: 'a'\n      },\n      slots: {\n        default: () =>\n          h(NTabPane, {\n            tab: 'a',\n            name: 'a'\n          })\n      }\n    })\n  })\n\n  it('should show AddIcon with `addable` `on-add` prop', async () => {\n    const onAdd = vi.fn()\n    const wrapper = mount(NTabs, {\n      props: {\n        type: 'card',\n        addable: true,\n        onAdd\n      }\n    })\n\n    expect(wrapper.findComponent(AddIcon).exists()).toBe(true)\n    const addIcon = wrapper.find('.n-tabs-tab--addable')\n    await addIcon.trigger('click')\n    expect(onAdd).toHaveBeenCalled()\n  })\n\n  it('should work with `justify-content` prop', async () => {\n    const wrapper = mount(NTabs)\n\n    await wrapper.setProps({ justifyContent: 'space-between' })\n    expect(wrapper.find('.n-tabs-wrapper').attributes('style')).toContain(\n      'justify-content: space-between;'\n    )\n\n    await wrapper.setProps({ justifyContent: 'space-around' })\n    expect(wrapper.find('.n-tabs-wrapper').attributes('style')).toContain(\n      'justify-content: space-around;'\n    )\n\n    await wrapper.setProps({ justifyContent: 'space-evenly' })\n    expect(wrapper.find('.n-tabs-wrapper').attributes('style')).toContain(\n      'justify-content: space-evenly;'\n    )\n  })\n\n  it('should work with `closable` prop', async () => {\n    const wrapper = mount(NTabs, {\n      props: {\n        type: 'card',\n        defaultValue: '1'\n      },\n      slots: {\n        default: () => [\n          h(NTabPane, {\n            tab: '1',\n            name: '1'\n          })\n        ]\n      }\n    })\n    expect(wrapper.find('.n-base-close').exists()).toBe(false)\n\n    await wrapper.setProps({ closable: true })\n    expect(wrapper.find('.n-base-close').exists()).toBe(true)\n  })\n\n  it('should work with `size` prop', async () => {\n    const wrapper = mount(NTabs)\n\n    await wrapper.setProps({ size: 'small' })\n    expect(wrapper.find('.n-tabs').attributes('style')).toMatchSnapshot()\n\n    await wrapper.setProps({ size: 'medium' })\n    expect(wrapper.find('.n-tabs').attributes('style')).toMatchSnapshot()\n\n    await wrapper.setProps({ size: 'large' })\n    expect(wrapper.find('.n-tabs').attributes('style')).toMatchSnapshot()\n  })\n\n  it('should work with `tabs-padding` prop', async () => {\n    const wrapper = mount(NTabs)\n\n    expect(\n      wrapper.find('.n-tabs-scroll-padding').attributes('style')\n    ).toContain('width: 0px;')\n\n    await wrapper.setProps({ tabsPadding: 100 })\n    expect(\n      wrapper.find('.n-tabs-scroll-padding').attributes('style')\n    ).toContain('width: 100px;')\n  })\n\n  it('should work with `display-directive` prop', async () => {\n    const displayDirectives: Array<'show' | 'if' | 'show:lazy'> = [\n      'show',\n      'if',\n      'show:lazy'\n    ]\n    const wrapper = mount(NTabs, {\n      props: { value: 'show' },\n      slots: {\n        default: () =>\n          displayDirectives.map(directive => (\n            <NTabPane\n              displayDirective={directive}\n              tab={directive}\n              name={directive}\n            >\n              {{\n                default: () => (\n                  <span class={`test-${directive.replace(':', '-')}`} />\n                )\n              }}\n            </NTabPane>\n          ))\n      }\n    })\n    await wrapper.setProps({ value: 'if' })\n    expect(wrapper.find('.test-show').exists()).toEqual(true)\n    expect(wrapper.find('.test-if').exists()).toEqual(true)\n    expect(wrapper.find('.test-show-lazy').exists()).toEqual(false)\n    await wrapper.setProps({ value: 'show:lazy' })\n    expect(wrapper.find('.test-show').exists()).toEqual(true)\n    expect(wrapper.find('.test-if').exists()).toEqual(false)\n    expect(wrapper.find('.test-show-lazy').exists()).toEqual(true)\n    await wrapper.setProps({ value: 'show' })\n    expect(wrapper.find('.test-show').exists()).toEqual(true)\n    expect(wrapper.find('.test-if').exists()).toEqual(false)\n    expect(wrapper.find('.test-show-lazy').exists()).toEqual(true)\n  })\n\n  it('should work with `on-before-leave` prop', async () => {\n    const wrapper = mount(NTabs, {\n      props: {\n        type: 'card',\n        defaultValue: '3',\n        onBeforeLeave: async (name: string) => {\n          switch (name) {\n            case '1':\n              return false\n            case '2':\n              return await new Promise<boolean>((resolve) => {\n                setTimeout(() => {\n                  resolve(true)\n                }, 1000)\n              })\n            default:\n              return true\n          }\n        }\n      },\n      slots: {\n        default: () => [\n          h(NTabPane, {\n            tab: '1',\n            name: '1'\n          }),\n          h(NTabPane, {\n            tab: '2',\n            name: '2'\n          }),\n          h(NTabPane, {\n            tab: '3',\n            name: '3'\n          })\n        ]\n      }\n    })\n    const tabs = wrapper.findAll('.n-tabs-tab')\n    expect(tabs[2].classes()).toContain('n-tabs-tab--active')\n    await tabs[0].trigger('click')\n    expect(tabs[2].classes()).toContain('n-tabs-tab--active')\n    await tabs[1].trigger('click')\n    expect(tabs[2].classes()).toContain('n-tabs-tab--active')\n    await sleep(1000)\n    expect(tabs[1].classes()).toContain('n-tabs-tab--active')\n  })\n\n  it('should work with `pane-class` prop', () => {\n    const wrapper = mount(NTabs, {\n      props: {\n        paneClass: 'test'\n      },\n      slots: {\n        default: () =>\n          h(\n            NTabPane,\n            {\n              tab: 'Oasis',\n              name: 'oasis'\n            },\n            'Wonderwall'\n          )\n      }\n    })\n\n    expect(wrapper.find('.n-tab-pane').classes('test')).toBe(true)\n  })\n\n  it('should work with `pane-style` prop', () => {\n    const wrapper = mount(NTabs, {\n      props: {\n        paneStyle: {\n          color: 'red'\n        }\n      },\n      slots: {\n        default: () =>\n          h(\n            NTabPane,\n            {\n              tab: 'Oasis',\n              name: 'oasis'\n            },\n            'Wonderwall'\n          )\n      }\n    })\n\n    expect(wrapper.find('.n-tab-pane').attributes('style')).toBe('color: red;')\n  })\n\n  it('should work with `tab-style` prop', () => {\n    const wrapper = mount(NTabs, {\n      props: {\n        tabStyle: {\n          color: 'red'\n        }\n      },\n      slots: {\n        default: () =>\n          h(\n            NTabPane,\n            {\n              tab: 'Oasis',\n              name: 'oasis'\n            },\n            'Wonderwall'\n          )\n      }\n    })\n\n    expect(wrapper.find('.n-tabs-tab').attributes('style')).toBe('color: red;')\n  })\n\n  it('should work with `type` prop', () => {\n    ;(['bar', 'line', 'card', 'segment'] as const).forEach((type) => {\n      const wrapper = mount(NTabs, {\n        props: {\n          type\n        },\n        slots: {\n          default: () =>\n            h(\n              NTabPane,\n              {\n                tab: 'Oasis',\n                name: 'oasis'\n              },\n              { default: () => 'Wonderwall' }\n            )\n        }\n      })\n\n      expect(wrapper.find('.n-tabs').classes()).toContain(\n        `n-tabs--${type}-type`\n      )\n      wrapper.unmount()\n    })\n  })\n\n  it('should work with `on-close` prop', async () => {\n    const onClose = vi.fn()\n    const wrapper = mount(NTabs, {\n      props: {\n        type: 'card',\n        defaultValue: '1',\n        closable: true,\n        onClose\n      },\n      slots: {\n        default: () => [\n          h(NTabPane, {\n            tab: '1',\n            name: '1'\n          })\n        ]\n      }\n    })\n\n    const addIcon = wrapper.find('.n-base-close')\n    await addIcon.trigger('click')\n    expect(onClose).toHaveBeenCalled()\n  })\n\n  it('should work with `prefix` `suffix` slots', async () => {\n    const wrapper = mount(NTabs, {\n      props: {\n        defaultValue: '1'\n      },\n      slots: {\n        default: () => [\n          h(NTabPane, {\n            tab: '1',\n            name: '1'\n          })\n        ],\n        prefix: () => 'test-prefix',\n        suffix: () => 'test-suffix'\n      }\n    })\n\n    expect(wrapper.find('.n-tabs-nav__prefix').exists()).toBe(true)\n    expect(wrapper.find('.n-tabs-nav__prefix').text()).toBe('test-prefix')\n    expect(wrapper.find('.n-tabs-nav__suffix').exists()).toBe(true)\n    expect(wrapper.find('.n-tabs-nav__suffix').text()).toBe('test-suffix')\n  })\n\n  it('should work with `tab-class` prop', () => {\n    const wrapper = mount(NTabs, {\n      props: {\n        defaultValue: '1',\n        tabClass: 'foo'\n      },\n      slots: {\n        default: () => [\n          h(NTabPane, {\n            tab: '1',\n            name: '1'\n          })\n        ]\n      }\n    })\n    expect(wrapper.find('.n-tabs-tab').classes()).toContain('foo')\n  })\n\n  it('should work with `add-tab-class` prop', () => {\n    const wrapper = mount(NTabs, {\n      props: {\n        defaultValue: '1',\n        type: 'card',\n        addTabClass: 'foo',\n        addable: true\n      },\n      slots: {\n        default: () => [\n          h(NTabPane, {\n            tab: '1',\n            name: '1'\n          })\n        ]\n      }\n    })\n    expect(wrapper.find('.n-tabs-tab.n-tabs-tab--addable').classes()).toContain(\n      'foo'\n    )\n    expect(\n      wrapper.find('.n-tabs-tab:not(.n-tabs-tab--addable)').classes()\n    ).not.toContain('foo')\n  })\n\n  it('should work with `add-tab-style` prop', () => {\n    const wrapper = mount(NTabs, {\n      props: {\n        defaultValue: '1',\n        type: 'card',\n        addTabStyle: {\n          fontSize: '64px'\n        },\n        addable: true\n      },\n      slots: {\n        default: () => [\n          h(NTabPane, {\n            tab: '1',\n            name: '1'\n          })\n        ]\n      }\n    })\n    expect(\n      wrapper.find('.n-tabs-tab.n-tabs-tab--addable').attributes('style')\n    ).toContain('64px')\n    expect(\n      wrapper.find('.n-tabs-tab:not(.n-tabs-tab--addable)').attributes('style')\n    ).toBe(undefined)\n  })\n})\n"
  },
  {
    "path": "src/tabs/tests/__snapshots__/Tabs.spec.tsx.snap",
    "content": "// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html\n\nexports[`n-tabs > should work with \\`size\\` prop 1`] = `\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-color-segment: rgb(247, 247, 250); --n-bar-color: #18a058; --n-tab-font-size: 14px; --n-tab-text-color: rgb(31, 34, 37); --n-tab-text-color-active: #18a058; --n-tab-text-color-disabled: rgba(194, 194, 194, 1); --n-tab-text-color-hover: #18a058; --n-pane-text-color: rgb(51, 54, 57); --n-tab-border-color: rgb(239, 239, 245); --n-tab-border-radius: 3px; --n-close-size: 18px; --n-close-icon-size: 14px; --n-close-color-hover: rgba(0, 0, 0, .09); --n-close-color-pressed: rgba(0, 0, 0, .13); --n-close-border-radius: 3px; --n-close-icon-color: rgba(102, 102, 102, 1); --n-close-icon-color-hover: rgba(102, 102, 102, 1); --n-close-icon-color-pressed: rgba(102, 102, 102, 1); --n-tab-color: rgb(247, 247, 250); --n-tab-font-weight: 400; --n-tab-font-weight-active: 400; --n-tab-padding: 4px 0; --n-tab-padding-vertical: 6px 12px; --n-tab-gap: 36px; --n-tab-gap-vertical: 8px; --n-pane-padding-left: 0; --n-pane-padding-right: 0; --n-pane-padding-top: 8px; --n-pane-padding-bottom: 0; --n-font-weight-strong: 500; --n-tab-color-segment: #FFF;\"`;\n\nexports[`n-tabs > should work with \\`size\\` prop 2`] = `\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-color-segment: rgb(247, 247, 250); --n-bar-color: #18a058; --n-tab-font-size: 14px; --n-tab-text-color: rgb(31, 34, 37); --n-tab-text-color-active: #18a058; --n-tab-text-color-disabled: rgba(194, 194, 194, 1); --n-tab-text-color-hover: #18a058; --n-pane-text-color: rgb(51, 54, 57); --n-tab-border-color: rgb(239, 239, 245); --n-tab-border-radius: 3px; --n-close-size: 18px; --n-close-icon-size: 14px; --n-close-color-hover: rgba(0, 0, 0, .09); --n-close-color-pressed: rgba(0, 0, 0, .13); --n-close-border-radius: 3px; --n-close-icon-color: rgba(102, 102, 102, 1); --n-close-icon-color-hover: rgba(102, 102, 102, 1); --n-close-icon-color-pressed: rgba(102, 102, 102, 1); --n-tab-color: rgb(247, 247, 250); --n-tab-font-weight: 400; --n-tab-font-weight-active: 400; --n-tab-padding: 6px 0; --n-tab-padding-vertical: 8px 16px; --n-tab-gap: 36px; --n-tab-gap-vertical: 8px; --n-pane-padding-left: 0; --n-pane-padding-right: 0; --n-pane-padding-top: 12px; --n-pane-padding-bottom: 0; --n-font-weight-strong: 500; --n-tab-color-segment: #FFF;\"`;\n\nexports[`n-tabs > should work with \\`size\\` prop 3`] = `\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-color-segment: rgb(247, 247, 250); --n-bar-color: #18a058; --n-tab-font-size: 16px; --n-tab-text-color: rgb(31, 34, 37); --n-tab-text-color-active: #18a058; --n-tab-text-color-disabled: rgba(194, 194, 194, 1); --n-tab-text-color-hover: #18a058; --n-pane-text-color: rgb(51, 54, 57); --n-tab-border-color: rgb(239, 239, 245); --n-tab-border-radius: 3px; --n-close-size: 18px; --n-close-icon-size: 14px; --n-close-color-hover: rgba(0, 0, 0, .09); --n-close-color-pressed: rgba(0, 0, 0, .13); --n-close-border-radius: 3px; --n-close-icon-color: rgba(102, 102, 102, 1); --n-close-icon-color-hover: rgba(102, 102, 102, 1); --n-close-icon-color-pressed: rgba(102, 102, 102, 1); --n-tab-color: rgb(247, 247, 250); --n-tab-font-weight: 400; --n-tab-font-weight-active: 400; --n-tab-padding: 10px 0; --n-tab-padding-vertical: 10px 20px; --n-tab-gap: 36px; --n-tab-gap-vertical: 8px; --n-pane-padding-left: 0; --n-pane-padding-right: 0; --n-pane-padding-top: 16px; --n-pane-padding-bottom: 0; --n-font-weight-strong: 500; --n-tab-color-segment: #FFF;\"`;\n"
  },
  {
    "path": "src/tabs/tests/server.spec.tsx",
    "content": "import { setup } from '@css-render/vue3-ssr'\nimport { renderToString } from '@vue/server-renderer'\n/**\n * @vitest-environment node\n */\nimport { createSSRApp, h } from 'vue'\nimport { NTabs } from '../..'\n\ndescribe('server side rendering', () => {\n  it('works', async () => {\n    const app = createSSRApp(() => <NTabs />)\n    setup(app)\n    try {\n      await renderToString(app)\n    }\n    catch (e) {\n      expect(e).not.toBeTruthy()\n    }\n  })\n})\n"
  },
  {
    "path": "src/tag/demos/enUS/avatar.demo.vue",
    "content": "<markdown>\n# Avatar\n\nPut avatar in tag.\n</markdown>\n\n<template>\n  <n-space>\n    <n-tag>\n      Anyway.FM\n      <template #avatar>\n        <n-avatar\n          src=\"https://cdnimg103.lizhi.fm/user/2017/02/04/2583325032200238082_160x160.jpg\"\n        />\n      </template>\n    </n-tag>\n    <n-tag round :bordered=\"false\">\n      Anyway.FM\n      <template #avatar>\n        <n-avatar\n          src=\"https://cdnimg103.lizhi.fm/user/2017/02/04/2583325032200238082_160x160.jpg\"\n        />\n      </template>\n    </n-tag>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/tag/demos/enUS/basic.demo.vue",
    "content": "<markdown>\n# Type\n\nIt has some types.\n</markdown>\n\n<template>\n  <n-space>\n    <n-tag>Real Love</n-tag>\n    <n-tag type=\"success\">\n      Yes It Is\n    </n-tag>\n    <n-tag type=\"warning\">\n      I'm Down\n    </n-tag>\n    <n-tag type=\"error\">\n      Yesterday\n    </n-tag>\n    <n-tag type=\"info\">\n      I'm Looking Through You\n    </n-tag>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/tag/demos/enUS/bordered.demo.vue",
    "content": "<markdown>\n# Borderless\n</markdown>\n\n<template>\n  <n-space>\n    <n-tag :bordered=\"false\">\n      Real Love\n    </n-tag>\n    <n-tag :bordered=\"false\" type=\"success\">\n      Yes It Is\n    </n-tag>\n    <n-tag :bordered=\"false\" type=\"warning\">\n      I'm Down\n    </n-tag>\n    <n-tag :bordered=\"false\" type=\"error\">\n      Yesterday\n    </n-tag>\n    <n-tag :bordered=\"false\" type=\"info\">\n      I'm Looking Through You\n    </n-tag>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/tag/demos/enUS/checkable.demo.vue",
    "content": "<markdown>\n# Checkable\n\nIt can be checkable.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst checked = ref(false)\n</script>\n\n<template>\n  <n-space>\n    <n-tag v-model:checked=\"checked\" checkable disabled>\n      Real Love\n    </n-tag>\n    <n-tag v-model:checked=\"checked\" checkable>\n      Yes It Is\n    </n-tag>\n    <n-tag v-model:checked=\"checked\" checkable>\n      I'm Down\n    </n-tag>\n    <n-tag v-model:checked=\"checked\" checkable>\n      Yesterday\n    </n-tag>\n    <n-tag v-model:checked=\"checked\" checkable>\n      I'm Looking Through You\n    </n-tag>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/tag/demos/enUS/closable.demo.vue",
    "content": "<markdown>\n# Closable\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { useMessage } from 'naive-ui'\n\nconst message = useMessage()\nfunction handleClose() {\n  message.info('tag close')\n}\nfunction handleClick() {\n  message.info('tag click')\n}\n</script>\n\n<template>\n  <n-space>\n    <n-tag closable @close=\"handleClose\">\n      Real Love\n    </n-tag>\n    <n-tag type=\"success\" closable @close=\"handleClose\">\n      Yes It Is\n    </n-tag>\n    <n-tag type=\"warning\" closable @close=\"handleClose\">\n      I'm Down\n    </n-tag>\n    <n-tag type=\"error\" closable @close=\"handleClose\">\n      Yesterday\n    </n-tag>\n    <n-tag\n      type=\"info\"\n      closable\n      :trigger-click-on-close=\"false\"\n      @click=\"handleClick\"\n      @close=\"handleClose\"\n    >\n      I'm Looking Through You\n    </n-tag>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/tag/demos/enUS/color.demo.vue",
    "content": "<markdown>\n# Color\n\nUse a color object to customize color.\n</markdown>\n\n<template>\n  <n-tag :color=\"{ color: '#BBB', textColor: '#555', borderColor: '#555' }\">\n    Farewell to the night, waiting for dawn\n  </n-tag>\n</template>\n"
  },
  {
    "path": "src/tag/demos/enUS/disabled.demo.vue",
    "content": "<markdown>\n# Disabled\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { useMessage } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst message = useMessage()\nconst disabled = ref(true)\nfunction handleClose() {\n  message.info('tag close')\n}\n</script>\n\n<template>\n  <n-space align=\"center\" item-style=\"display: flex;\">\n    <n-tag closable :disabled=\"disabled\" @close=\"handleClose\">\n      Real Love\n    </n-tag>\n    <n-tag type=\"success\" closable :disabled=\"disabled\" @close=\"handleClose\">\n      Yes It Is\n    </n-tag>\n    <n-tag type=\"warning\" closable :disabled=\"disabled\" @close=\"handleClose\">\n      I'm Down\n    </n-tag>\n    <n-tag type=\"error\" closable :disabled=\"disabled\" @close=\"handleClose\">\n      Yesterday\n    </n-tag>\n    <n-tag type=\"info\" closable :disabled=\"disabled\" @close=\"handleClose\">\n      I'm Looking Through You\n    </n-tag>\n    <n-switch v-model:value=\"disabled\" />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/tag/demos/enUS/icon.demo.vue",
    "content": "<markdown>\n# Icon\n\nUse icon in tag.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { CheckmarkCircle } from '@vicons/ionicons5'\n</script>\n\n<template>\n  <n-space>\n    <n-tag type=\"success\">\n      Checked\n      <template #icon>\n        <n-icon :component=\"CheckmarkCircle\" />\n      </template>\n    </n-tag>\n    <n-tag round :bordered=\"false\" type=\"success\">\n      Checked\n      <template #icon>\n        <n-icon :component=\"CheckmarkCircle\" />\n      </template>\n    </n-tag>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/tag/demos/enUS/index.demo-entry.md",
    "content": "# Tag\n\nTags are great for showing attributes; and sometimes toggle options.\n\n## Demos\n\n```demo\nbasic.vue\nbordered.vue\nclosable.vue\ndisabled.vue\nsize.vue\ncheckable.vue\nshape.vue\ncolor.vue\navatar.vue\nicon.vue\n```\n\n## API\n\n### Tag Props\n\n| Name | Type | Default | Description | Version |\n| --- | --- | --- | --- | --- |\n| bordered | `boolean` | `true` | Whether the tag has border. |  |\n| checkable | `boolean` | `false` | Whether the tag is checkable. Note: this nullifies the type property. |  |\n| checked | `boolean` | `false` | Whether the tag is checked. Note: used with `checkable`. |  |\n| closable | `boolean` | `false` | Whether the tag shows a close button. |  |\n| color | `{ color?: string, borderColor?: string, textColor?: string }` | `undefined` | Color of the tag. Note: this will override the type property's color. |  |\n| disabled | `boolean` | `false` | Whether the tag is disabled. |  |\n| round | `boolean` | `false` | Whether the tag has rounded corners. |  |\n| size | `'tiny' \\| 'small' \\| 'medium' \\| 'large'` | `'medium'` | Size of the tag. |  |\n| strong | `boolean` | `false` | Whether to use strong text | 2.30.0 |\n| trigger-click-on-close | `boolean` | `false` | Whether the tag triggers click on close. | 2.32.2 |\n| type | `'default' \\| 'primary' \\| 'info' \\| 'success' \\| 'warning' \\| 'error'` | `'default'` | Type of the tag. |  |\n| on-close | `(e: MouseEvent) => void` | `undefined` | Close clicked callback. |  |\n| on-update:checked | `(value: boolean) => void` | `undefined` | Checked status change callback. |  |\n\n### Tag Slots\n\n| Name    | Parameters | Description    | Version |\n| ------- | ---------- | -------------- | ------- |\n| avatar  | `()`       | Tag'a avatar.  |         |\n| default | `()`       | Tag's content. |         |\n| icon    | `()`       | Tag'a icon.    | 2.30.0  |\n"
  },
  {
    "path": "src/tag/demos/enUS/shape.demo.vue",
    "content": "<markdown>\n# Shape\n\nRound tag looks like a capsule.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { useMessage } from 'naive-ui'\n\nconst message = useMessage()\nfunction handleClose() {\n  message.info('tag close')\n}\n</script>\n\n<template>\n  <n-space>\n    <n-tag closable size=\"small\" round @close=\"handleClose\">\n      Real Love\n    </n-tag>\n    <n-tag type=\"success\" size=\"large\" round closable @close=\"handleClose\">\n      Yes It Is\n    </n-tag>\n    <n-tag type=\"warning\" closable round @close=\"handleClose\">\n      I'm Down\n    </n-tag>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/tag/demos/enUS/size.demo.vue",
    "content": "<markdown>\n# Size\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { useMessage } from 'naive-ui'\n\nconst message = useMessage()\nfunction handleClose() {\n  message.info('tag close')\n}\n</script>\n\n<template>\n  <n-space>\n    <n-tag size=\"tiny\" closable @close=\"handleClose\">\n      Real Love\n    </n-tag>\n    <n-tag type=\"success\" size=\"small\" closable @close=\"handleClose\">\n      Yes It Is\n    </n-tag>\n    <n-tag type=\"warning\" closable @close=\"handleClose\">\n      I'm Down\n    </n-tag>\n    <n-tag type=\"error\" size=\"large\" closable @close=\"handleClose\">\n      Yesterday\n    </n-tag>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/tag/demos/zhCN/avatar.demo.vue",
    "content": "<markdown>\n# 头像\n\n在标签中使用头像。\n</markdown>\n\n<template>\n  <n-space>\n    <n-tag>\n      Anyway.FM\n      <template #avatar>\n        <n-avatar\n          src=\"https://cdnimg103.lizhi.fm/user/2017/02/04/2583325032200238082_160x160.jpg\"\n        />\n      </template>\n    </n-tag>\n    <n-tag round :bordered=\"false\">\n      Anyway.FM\n      <template #avatar>\n        <n-avatar\n          src=\"https://cdnimg103.lizhi.fm/user/2017/02/04/2583325032200238082_160x160.jpg\"\n        />\n      </template>\n    </n-tag>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/tag/demos/zhCN/basic.demo.vue",
    "content": "<markdown>\n# 基础\n\n它有不同的类型。\n</markdown>\n\n<template>\n  <n-space>\n    <n-tag> 爱在西元前 </n-tag>\n    <n-tag type=\"success\">\n      不该\n    </n-tag>\n    <n-tag type=\"warning\">\n      超人不会飞\n    </n-tag>\n    <n-tag type=\"error\">\n      手写的从前\n    </n-tag>\n    <n-tag type=\"info\">\n      哪里都是你\n    </n-tag>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/tag/demos/zhCN/bordered.demo.vue",
    "content": "<markdown>\n# 无边框\n</markdown>\n\n<template>\n  <n-space>\n    <n-tag :bordered=\"false\">\n      爱在西元前\n    </n-tag>\n    <n-tag :bordered=\"false\" type=\"success\">\n      不该\n    </n-tag>\n    <n-tag :bordered=\"false\" type=\"warning\">\n      超人不会飞\n    </n-tag>\n    <n-tag :bordered=\"false\" type=\"error\">\n      手写的从前\n    </n-tag>\n    <n-tag :bordered=\"false\" type=\"info\">\n      哪里都是你\n    </n-tag>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/tag/demos/zhCN/checkable.demo.vue",
    "content": "<markdown>\n# 可选择\n\n它可以变成可选择的。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst checked = ref(false)\n</script>\n\n<template>\n  <n-space>\n    <n-tag v-model:checked=\"checked\" checkable disabled>\n      爱在西元前\n    </n-tag>\n    <n-tag v-model:checked=\"checked\" checkable>\n      不该\n    </n-tag>\n    <n-tag v-model:checked=\"checked\" checkable>\n      超人不会飞\n    </n-tag>\n    <n-tag v-model:checked=\"checked\" checkable>\n      手写的从前\n    </n-tag>\n    <n-tag v-model:checked=\"checked\" checkable>\n      哪里都是你\n    </n-tag>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/tag/demos/zhCN/closable.demo.vue",
    "content": "<markdown>\n# 可关闭\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { useMessage } from 'naive-ui'\n\nconst message = useMessage()\nfunction handleClose() {\n  message.info('tag close')\n}\nfunction handleClick() {\n  message.info('tag click')\n}\n</script>\n\n<template>\n  <n-space>\n    <n-tag closable @close=\"handleClose\">\n      爱在西元前\n    </n-tag>\n    <n-tag type=\"success\" closable @close=\"handleClose\">\n      不该\n    </n-tag>\n    <n-tag type=\"warning\" closable @close=\"handleClose\">\n      超人不会飞\n    </n-tag>\n    <n-tag type=\"error\" closable @close=\"handleClose\">\n      手写的从前\n    </n-tag>\n    <n-tag type=\"info\" closable @click=\"handleClick\" @close=\"handleClose\">\n      哪里都是你\n    </n-tag>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/tag/demos/zhCN/color.demo.vue",
    "content": "<markdown>\n# 颜色\n\n使用一个颜色对象定制标签的颜色。\n</markdown>\n\n<template>\n  <n-tag :color=\"{ color: '#BBB', textColor: '#555', borderColor: '#555' }\">\n    告别夜晚 等待天亮\n  </n-tag>\n</template>\n"
  },
  {
    "path": "src/tag/demos/zhCN/disabled.demo.vue",
    "content": "<markdown>\n# 禁用\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { useMessage } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst message = useMessage()\nconst disabled = ref(true)\nfunction handleClose() {\n  message.info('tag close')\n}\n</script>\n\n<template>\n  <n-space align=\"center\" item-style=\"display: flex;\">\n    <n-tag closable :disabled=\"disabled\" @close=\"handleClose\">\n      爱在西元前\n    </n-tag>\n    <n-tag type=\"success\" closable :disabled=\"disabled\" @close=\"handleClose\">\n      不该\n    </n-tag>\n    <n-tag type=\"warning\" closable :disabled=\"disabled\" @close=\"handleClose\">\n      超人不会飞\n    </n-tag>\n    <n-tag type=\"error\" closable :disabled=\"disabled\" @close=\"handleClose\">\n      手写的从前\n    </n-tag>\n    <n-tag type=\"info\" closable :disabled=\"disabled\" @close=\"handleClose\">\n      哪里都是你\n    </n-tag>\n    <n-switch v-model:value=\"disabled\" />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/tag/demos/zhCN/icon.demo.vue",
    "content": "<markdown>\n# 图标\n\n在标签中使用图标。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { CheckmarkCircle } from '@vicons/ionicons5'\n</script>\n\n<template>\n  <n-space>\n    <n-tag type=\"success\">\n      Checked\n      <template #icon>\n        <n-icon :component=\"CheckmarkCircle\" />\n      </template>\n    </n-tag>\n    <n-tag round :bordered=\"false\" type=\"success\">\n      Checked\n      <template #icon>\n        <n-icon :component=\"CheckmarkCircle\" />\n      </template>\n    </n-tag>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/tag/demos/zhCN/index.demo-entry.md",
    "content": "# 标签 Tag\n\n通常用来展示一些属性，偶尔也用来当一些备选的属性。\n\n## 演示\n\n```demo\nbasic.vue\nbordered.vue\nclosable.vue\ndisabled.vue\nsize.vue\ncheckable.vue\nshape.vue\ncolor.vue\navatar.vue\nicon.vue\nrtl-debug.vue\n```\n\n## API\n\n### Tag Props\n\n| 名称 | 类型 | 默认值 | 说明 | 版本 |\n| --- | --- | --- | --- | --- |\n| bordered | `boolean` | `true` | 是否有边框 |  |\n| checkable | `boolean` | `false` | 是否可以选择，使用后 type 将不生效 |  |\n| checked | `boolean` | `false` | 是否被选中，配合 checkable 一起使用 |  |\n| closable | `boolean` | `false` | 是否可关闭 |  |\n| color | `{ color?: string, borderColor?: string, textColor?: string }` | `undefined` | 标签颜色，设置该项后 `type` 无效 |  |\n| disabled | `boolean` | `false` | 是否禁用 |  |\n| round | `boolean` | `false` | 是否圆角 |  |\n| size | `'tiny' \\| 'small' \\| 'medium' \\| 'large'` | `'medium'` | 尺寸 |  |\n| strong | `boolean` | `false` | 文字是否加粗 | 2.30.0 |\n| trigger-click-on-close | `boolean` | `false` | 关闭时是否触发点击事件 | 2.32.2 |\n| type | `'default' \\| 'primary' \\| 'info' \\| 'success' \\| 'warning' \\| 'error'` | `'default'` | 类型 |\n| on-close | `(e: MouseEvent) => void` | `undefined` | 点击关闭时的回调 |\n| on-update:checked | `(value: boolean) => void` | `undefined` | 选择状态更改时的回调 |\n\n### Tag Slots\n\n| 名称    | 参数 | 说明         | 版本   |\n| ------- | ---- | ------------ | ------ |\n| avatar  | `()` | 标签中的头像 |        |\n| default | `()` | 标签内容     |        |\n| icon    | `()` | 标签中的图标 | 2.30.0 |\n"
  },
  {
    "path": "src/tag/demos/zhCN/rtl-debug.demo.vue",
    "content": "<markdown>\n# Rtl Debug\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { unstableTagRtl, useMessage } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst message = useMessage()\nconst rtlEnabled = ref(false)\nconst rtlStyles = [unstableTagRtl]\nfunction handleClose() {\n  message.info('tag close')\n}\n</script>\n\n<template>\n  <n-space vertical>\n    <n-space><n-switch v-model:value=\"rtlEnabled\" />Rtl</n-space>\n    <n-config-provider :rtl=\"rtlEnabled ? rtlStyles : undefined\">\n      <n-space>\n        <n-tag>\n          我不配\n          <template #avatar>\n            <n-avatar\n              src=\"https://cdnimg103.lizhi.fm/user/2017/02/04/2583325032200238082_160x160.jpg\"\n            />\n          </template>\n        </n-tag>\n        <n-tag type=\"success\" size=\"small\" round closable @close=\"handleClose\">\n          梯田\n        </n-tag>\n        <n-tag type=\"error\" closable round @close=\"handleClose\">\n          说好不哭\n          <template #avatar>\n            <n-avatar\n              round\n              src=\"https://cdnimg103.lizhi.fm/user/2017/02/04/2583325032200238082_160x160.jpg\"\n            />\n          </template>\n        </n-tag>\n        <n-tag type=\"error\" closable size=\"large\" round @close=\"handleClose\">\n          一路向北\n        </n-tag>\n      </n-space>\n    </n-config-provider>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/tag/demos/zhCN/shape.demo.vue",
    "content": "<markdown>\n# 形状\n\n圆的 Tag 长得像个胶囊。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { useMessage } from 'naive-ui'\n\nconst message = useMessage()\nfunction handleClose() {\n  message.info('tag close')\n}\n</script>\n\n<template>\n  <n-space>\n    <n-tag type=\"success\" size=\"small\" round closable @close=\"handleClose\">\n      不该\n    </n-tag>\n    <n-tag type=\"error\" closable round @close=\"handleClose\">\n      手写的从前\n    </n-tag>\n    <n-tag type=\"error\" closable size=\"large\" round @close=\"handleClose\">\n      手写的从前\n    </n-tag>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/tag/demos/zhCN/size.demo.vue",
    "content": "<markdown>\n# 尺寸\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { useMessage } from 'naive-ui'\n\nconst message = useMessage()\nfunction handleClose() {\n  message.info('tag close')\n}\n</script>\n\n<template>\n  <n-space>\n    <n-tag closable size=\"tiny\" @close=\"handleClose\">\n      爱在西元前\n    </n-tag>\n    <n-tag type=\"success\" closable size=\"small\" @close=\"handleClose\">\n      不该\n    </n-tag>\n    <n-tag type=\"warning\" closable @close=\"handleClose\">\n      超人不会飞\n    </n-tag>\n    <n-tag type=\"error\" closable size=\"large\" @close=\"handleClose\">\n      手写的从前\n    </n-tag>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/tag/index.ts",
    "content": "export type * from './src/public-types'\nexport { default as NTag, tagProps } from './src/Tag'\nexport type { TagProps, TagSlots } from './src/Tag'\n"
  },
  {
    "path": "src/tag/src/Tag.tsx",
    "content": "import type { CSSProperties, PropType, Ref, SlotsType, VNode } from 'vue'\nimport type { ThemeProps } from '../../_mixins'\nimport type { ExtractPublicPropTypes, MaybeArray } from '../../_utils'\nimport type { TagTheme } from '../styles'\nimport { getMargin } from 'seemly'\nimport {\n  computed,\n  defineComponent,\n  h,\n  provide,\n  ref,\n  toRef,\n  watchEffect\n} from 'vue'\nimport { NBaseClose } from '../../_internal/close'\nimport { useConfig, useTheme, useThemeClass } from '../../_mixins'\nimport { useRtl } from '../../_mixins/use-rtl'\nimport {\n  call,\n  color2Class,\n  createInjectionKey,\n  createKey,\n  resolveWrappedSlot,\n  warnOnce\n} from '../../_utils'\nimport { tagLight } from '../styles'\nimport commonProps from './common-props'\nimport style from './styles/index.cssr'\n\nexport interface TagPublicMethods {\n  setTextContent: (textContent: string) => void\n}\nexport interface TagRef extends TagPublicMethods {\n  $el: HTMLElement\n}\n\nexport const tagProps = {\n  ...(useTheme.props as ThemeProps<TagTheme>),\n  ...commonProps,\n  bordered: {\n    type: Boolean as PropType<boolean | undefined>,\n    default: undefined\n  },\n  checked: Boolean,\n  checkable: Boolean,\n  strong: Boolean,\n  triggerClickOnClose: Boolean,\n  onClose: [Array, Function] as PropType<MaybeArray<(e: MouseEvent) => void>>,\n  onMouseenter: Function as PropType<(e: MouseEvent) => void>,\n  onMouseleave: Function as PropType<(e: MouseEvent) => void>,\n  'onUpdate:checked': Function as PropType<(checked: boolean) => void>,\n  onUpdateChecked: Function as PropType<(checked: boolean) => void>,\n  // private\n  internalCloseFocusable: {\n    type: Boolean,\n    default: true\n  },\n  internalCloseIsButtonTag: {\n    type: Boolean,\n    default: true\n  },\n  // deprecated\n  onCheckedChange: Function as PropType<(checked: boolean) => void>\n}\n\ninterface TagInjection {\n  roundRef: Ref<boolean>\n}\n\nexport const tagInjectionKey = createInjectionKey<TagInjection>('n-tag')\n\nexport type TagProps = ExtractPublicPropTypes<typeof tagProps>\n\nexport interface TagSlots {\n  default?: () => VNode[]\n  avatar?: () => VNode[]\n  icon?: () => VNode[]\n}\n\nexport default defineComponent({\n  name: 'Tag',\n  props: tagProps,\n  slots: Object as SlotsType<TagSlots>,\n  setup(props) {\n    if (__DEV__) {\n      watchEffect(() => {\n        if (props.onCheckedChange !== undefined) {\n          warnOnce(\n            'tag',\n            '`on-checked-change` is deprecated, please use `on-update:checked` instead'\n          )\n        }\n      })\n    }\n    const contentRef = ref<HTMLElement | null>(null)\n    const {\n      mergedBorderedRef,\n      mergedClsPrefixRef,\n      inlineThemeDisabled,\n      mergedRtlRef,\n      mergedComponentPropsRef\n    } = useConfig(props)\n    const mergedSizeRef = computed(() => {\n      return props.size || mergedComponentPropsRef?.value?.Tag?.size || 'medium'\n    })\n    const themeRef = useTheme(\n      'Tag',\n      '-tag',\n      style,\n      tagLight,\n      props,\n      mergedClsPrefixRef\n    )\n    provide(tagInjectionKey, {\n      roundRef: toRef(props, 'round')\n    })\n    function handleClick(): void {\n      if (!props.disabled) {\n        if (props.checkable) {\n          const {\n            checked,\n            onCheckedChange,\n            onUpdateChecked,\n            'onUpdate:checked': _onUpdateChecked\n          } = props\n          if (onUpdateChecked)\n            onUpdateChecked(!checked)\n          if (_onUpdateChecked)\n            _onUpdateChecked(!checked)\n          // deprecated\n          if (onCheckedChange)\n            onCheckedChange(!checked)\n        }\n      }\n    }\n    function handleCloseClick(e: MouseEvent): void {\n      if (!props.triggerClickOnClose) {\n        e.stopPropagation()\n      }\n      if (!props.disabled) {\n        const { onClose } = props\n        if (onClose)\n          call(onClose, e)\n      }\n    }\n    const tagPublicMethods: TagPublicMethods = {\n      setTextContent(textContent: string) {\n        const { value } = contentRef\n        if (value)\n          value.textContent = textContent\n      }\n    }\n    const rtlEnabledRef = useRtl('Tag', mergedRtlRef, mergedClsPrefixRef)\n    const cssVarsRef = computed(() => {\n      const { type, color: { color, textColor } = {} } = props\n      const size = mergedSizeRef.value\n      const {\n        common: { cubicBezierEaseInOut },\n        self: {\n          padding,\n          closeMargin,\n          borderRadius,\n          opacityDisabled,\n          textColorCheckable,\n          textColorHoverCheckable,\n          textColorPressedCheckable,\n          textColorChecked,\n          colorCheckable,\n          colorHoverCheckable,\n          colorPressedCheckable,\n          colorChecked,\n          colorCheckedHover,\n          colorCheckedPressed,\n          closeBorderRadius,\n          fontWeightStrong,\n          [createKey('colorBordered', type)]: colorBordered,\n          [createKey('closeSize', size)]: closeSize,\n          [createKey('closeIconSize', size)]: closeIconSize,\n          [createKey('fontSize', size)]: fontSize,\n          [createKey('height', size)]: height,\n          [createKey('color', type)]: typedColor,\n          [createKey('textColor', type)]: typeTextColor,\n          [createKey('border', type)]: border,\n          [createKey('closeIconColor', type)]: closeIconColor,\n          [createKey('closeIconColorHover', type)]: closeIconColorHover,\n          [createKey('closeIconColorPressed', type)]: closeIconColorPressed,\n          [createKey('closeColorHover', type)]: closeColorHover,\n          [createKey('closeColorPressed', type)]: closeColorPressed\n        }\n      } = themeRef.value\n      const closeMarginDiscrete = getMargin(closeMargin)\n      return {\n        '--n-font-weight-strong': fontWeightStrong,\n        '--n-avatar-size-override': `calc(${height} - 8px)`,\n        '--n-bezier': cubicBezierEaseInOut,\n        '--n-border-radius': borderRadius,\n        '--n-border': border,\n        '--n-close-icon-size': closeIconSize,\n        '--n-close-color-pressed': closeColorPressed,\n        '--n-close-color-hover': closeColorHover,\n        '--n-close-border-radius': closeBorderRadius,\n        '--n-close-icon-color': closeIconColor,\n        '--n-close-icon-color-hover': closeIconColorHover,\n        '--n-close-icon-color-pressed': closeIconColorPressed,\n        '--n-close-icon-color-disabled': closeIconColor,\n        '--n-close-margin-top': closeMarginDiscrete.top,\n        '--n-close-margin-right': closeMarginDiscrete.right,\n        '--n-close-margin-bottom': closeMarginDiscrete.bottom,\n        '--n-close-margin-left': closeMarginDiscrete.left,\n        '--n-close-size': closeSize,\n        '--n-color':\n          color || (mergedBorderedRef.value ? colorBordered : typedColor),\n        '--n-color-checkable': colorCheckable,\n        '--n-color-checked': colorChecked,\n        '--n-color-checked-hover': colorCheckedHover,\n        '--n-color-checked-pressed': colorCheckedPressed,\n        '--n-color-hover-checkable': colorHoverCheckable,\n        '--n-color-pressed-checkable': colorPressedCheckable,\n        '--n-font-size': fontSize,\n        '--n-height': height,\n        '--n-opacity-disabled': opacityDisabled,\n        '--n-padding': padding,\n        '--n-text-color': textColor || typeTextColor,\n        '--n-text-color-checkable': textColorCheckable,\n        '--n-text-color-checked': textColorChecked,\n        '--n-text-color-hover-checkable': textColorHoverCheckable,\n        '--n-text-color-pressed-checkable': textColorPressedCheckable\n      }\n    })\n    const themeClassHandle = inlineThemeDisabled\n      ? useThemeClass(\n          'tag',\n          computed(() => {\n            let hash = ''\n            const { type, color: { color, textColor } = {} } = props\n            hash += type[0]\n            hash += mergedSizeRef.value[0]\n            if (color) {\n              hash += `a${color2Class(color)}`\n            }\n            if (textColor) {\n              hash += `b${color2Class(textColor)}`\n            }\n            if (mergedBorderedRef.value) {\n              hash += 'c'\n            }\n            return hash\n          }),\n          cssVarsRef,\n          props\n        )\n      : undefined\n    return {\n      ...tagPublicMethods,\n      rtlEnabled: rtlEnabledRef,\n      mergedClsPrefix: mergedClsPrefixRef,\n      contentRef,\n      mergedBordered: mergedBorderedRef,\n      handleClick,\n      handleCloseClick,\n      cssVars: inlineThemeDisabled ? undefined : cssVarsRef,\n      themeClass: themeClassHandle?.themeClass,\n      onRender: themeClassHandle?.onRender\n    }\n  },\n  render() {\n    const {\n      mergedClsPrefix,\n      rtlEnabled,\n      closable,\n      color: { borderColor } = {},\n      round,\n      onRender,\n      $slots\n    } = this\n    onRender?.()\n    const avatarNode = resolveWrappedSlot(\n      $slots.avatar,\n      children =>\n        children && (\n          <div class={`${mergedClsPrefix}-tag__avatar`}>{children}</div>\n        )\n    )\n    const iconNode = resolveWrappedSlot(\n      $slots.icon,\n      children =>\n        children && <div class={`${mergedClsPrefix}-tag__icon`}>{children}</div>\n    )\n    return (\n      <div\n        class={[\n          `${mergedClsPrefix}-tag`,\n          this.themeClass,\n          {\n            [`${mergedClsPrefix}-tag--rtl`]: rtlEnabled,\n            [`${mergedClsPrefix}-tag--strong`]: this.strong,\n            [`${mergedClsPrefix}-tag--disabled`]: this.disabled,\n            [`${mergedClsPrefix}-tag--checkable`]: this.checkable,\n            [`${mergedClsPrefix}-tag--checked`]: this.checkable && this.checked,\n            [`${mergedClsPrefix}-tag--round`]: round,\n            [`${mergedClsPrefix}-tag--avatar`]: avatarNode,\n            [`${mergedClsPrefix}-tag--icon`]: iconNode,\n            [`${mergedClsPrefix}-tag--closable`]: closable\n          }\n        ]}\n        style={this.cssVars as CSSProperties}\n        onClick={this.handleClick}\n        onMouseenter={this.onMouseenter}\n        onMouseleave={this.onMouseleave}\n      >\n        {iconNode || avatarNode}\n        <span class={`${mergedClsPrefix}-tag__content`} ref=\"contentRef\">\n          {this.$slots.default?.()}\n        </span>\n        {!this.checkable && closable ? (\n          <NBaseClose\n            clsPrefix={mergedClsPrefix}\n            class={`${mergedClsPrefix}-tag__close`}\n            disabled={this.disabled}\n            onClick={this.handleCloseClick}\n            focusable={this.internalCloseFocusable}\n            round={round}\n            isButtonTag={this.internalCloseIsButtonTag}\n            absolute\n          />\n        ) : null}\n        {!this.checkable && this.mergedBordered ? (\n          <div\n            class={`${mergedClsPrefix}-tag__border`}\n            style={{ borderColor }}\n          />\n        ) : null}\n      </div>\n    )\n  }\n})\n"
  },
  {
    "path": "src/tag/src/common-props.ts",
    "content": "import type { PropType } from 'vue'\nimport type { TagSize } from './public-types'\n\nexport interface TagColor {\n  color?: string\n  borderColor?: string\n  textColor?: string\n}\n\nexport default {\n  color: Object as PropType<TagColor>,\n  type: {\n    type: String as PropType<\n      'default' | 'primary' | 'success' | 'info' | 'warning' | 'error'\n    >,\n    default: 'default'\n  },\n  round: Boolean,\n  size: String as PropType<TagSize>,\n  closable: Boolean,\n  disabled: {\n    type: Boolean as PropType<boolean | undefined>,\n    default: undefined\n  }\n} as const\n"
  },
  {
    "path": "src/tag/src/public-types.ts",
    "content": "export type TagSize = 'tiny' | 'small' | 'medium' | 'large'\n"
  },
  {
    "path": "src/tag/src/styles/index.cssr.ts",
    "content": "import { c, cB, cE, cM, cNotM } from '../../../_utils/cssr'\n\n// vars:\n// --n-bezier\n// --n-border-radius\n// --n-border\n// --n-close-icon-color\n// --n-close-icon-color-hover\n// --n-close-icon-color-pressed\n// --n-close-margin\n// --n-close-size\n// --n-color\n// --n-color-checkable\n// --n-color-checked\n// --n-color-checked-hover\n// --n-color-checked-pressed\n// --n-color-hover-checkable\n// --n-color-pressed-checkable\n// --n-font-size\n// --n-height\n// --n-opacity-disabled\n// --n-padding\n// --n-text-color\n// --n-text-color-checkable\n// --n-text-color-checked\n// --n-text-color-hover-checkable\n// --n-text-color-pressed-checkable\n// --n-font-weight-strong\nexport default cB('tag', `\n  --n-close-margin: var(--n-close-margin-top) var(--n-close-margin-right) var(--n-close-margin-bottom) var(--n-close-margin-left);\n  white-space: nowrap;\n  position: relative;\n  box-sizing: border-box;\n  cursor: default;\n  display: inline-flex;\n  align-items: center;\n  flex-wrap: nowrap;\n  padding: var(--n-padding);\n  border-radius: var(--n-border-radius);\n  color: var(--n-text-color);\n  background-color: var(--n-color);\n  transition: \n    border-color .3s var(--n-bezier),\n    background-color .3s var(--n-bezier),\n    color .3s var(--n-bezier),\n    box-shadow .3s var(--n-bezier),\n    opacity .3s var(--n-bezier);\n  line-height: 1;\n  height: var(--n-height);\n  font-size: var(--n-font-size);\n`, [\n  cM('strong', `\n    font-weight: var(--n-font-weight-strong);\n  `),\n  cE('border', `\n    pointer-events: none;\n    position: absolute;\n    left: 0;\n    right: 0;\n    top: 0;\n    bottom: 0;\n    border-radius: inherit;\n    border: var(--n-border);\n    transition: border-color .3s var(--n-bezier);\n  `),\n  cE('icon', `\n    display: flex;\n    margin: 0 4px 0 0;\n    color: var(--n-text-color);\n    transition: color .3s var(--n-bezier);\n    font-size: var(--n-avatar-size-override);\n  `),\n  cE('avatar', `\n    display: flex;\n    margin: 0 6px 0 0;\n  `),\n  cE('close', `\n    margin: var(--n-close-margin);\n    transition:\n      background-color .3s var(--n-bezier),\n      color .3s var(--n-bezier);\n  `),\n  cM('round', `\n    padding: 0 calc(var(--n-height) / 3);\n    border-radius: calc(var(--n-height) / 2);\n  `, [\n    cE('icon', `\n      margin: 0 4px 0 calc((var(--n-height) - 8px) / -2);\n    `),\n    cE('avatar', `\n      margin: 0 6px 0 calc((var(--n-height) - 8px) / -2);\n    `),\n    cM('closable', `\n      padding: 0 calc(var(--n-height) / 4) 0 calc(var(--n-height) / 3);\n    `)\n  ]),\n  cM('icon, avatar', [\n    cM('round', `\n      padding: 0 calc(var(--n-height) / 3) 0 calc(var(--n-height) / 2);\n    `)\n  ]),\n  cM('disabled', `\n    cursor: not-allowed !important;\n    opacity: var(--n-opacity-disabled);\n  `),\n  cM('checkable', `\n    cursor: pointer;\n    box-shadow: none;\n    color: var(--n-text-color-checkable);\n    background-color: var(--n-color-checkable);\n  `, [\n    cNotM('disabled', [\n      c('&:hover', 'background-color: var(--n-color-hover-checkable);', [\n        cNotM('checked', 'color: var(--n-text-color-hover-checkable);')\n      ]),\n      c('&:active', 'background-color: var(--n-color-pressed-checkable);', [\n        cNotM('checked', 'color: var(--n-text-color-pressed-checkable);')\n      ])\n    ]),\n    cM('checked', `\n      color: var(--n-text-color-checked);\n      background-color: var(--n-color-checked);\n    `, [\n      cNotM('disabled', [\n        c('&:hover', 'background-color: var(--n-color-checked-hover);'),\n        c('&:active', 'background-color: var(--n-color-checked-pressed);')\n      ])\n    ])\n  ])\n])\n"
  },
  {
    "path": "src/tag/src/styles/rtl.cssr.ts",
    "content": "import { cB, cE, cM } from '../../../_utils/cssr'\n\nexport default cB('tag', [\n  cM('rtl', `\n    direction: rtl;\n    --n-close-margin: var(--n-close-margin-top) var(--n-close-margin-left) var(--n-close-margin-bottom) var(--n-close-margin-right);\n  `, [\n    cE('icon', `\n      margin: 0 0 0 4px;\n    `),\n    cE('avatar', `\n      margin: 0 0 0 6px;\n    `),\n    cM('round', [\n      cE('icon', `\n        margin: 0 calc((var(--n-height) - 8px) / -2) 0 4px;\n      `),\n      cE('avatar', `\n        margin: 0 calc((var(--n-height) - 8px) / -2) 0 6px;\n      `),\n      cM('closable', `\n        padding: 0 calc(var(--n-height) / 3) 0 calc(var(--n-height) / 4);\n      `)\n    ]),\n    cM('icon, avatar', [\n      cM('round', `\n        padding: 0 calc(var(--n-height) / 2) 0 calc(var(--n-height) / 3);\n      `)\n    ])\n  ])\n])\n"
  },
  {
    "path": "src/tag/styles/_common.ts",
    "content": "export default {\n  closeIconSizeTiny: '12px',\n  closeIconSizeSmall: '12px',\n  closeIconSizeMedium: '14px',\n  closeIconSizeLarge: '14px',\n  closeSizeTiny: '16px',\n  closeSizeSmall: '16px',\n  closeSizeMedium: '18px',\n  closeSizeLarge: '18px',\n  padding: '0 7px',\n  closeMargin: '0 0 0 4px'\n}\n"
  },
  {
    "path": "src/tag/styles/dark.ts",
    "content": "import type { TagTheme } from './light'\nimport { changeColor, scaleColor } from 'seemly'\nimport { commonDark } from '../../_styles/common'\nimport commonVariables from './_common'\n\nconst tagDark: TagTheme = {\n  name: 'Tag',\n  common: commonDark,\n  self(vars) {\n    const {\n      textColor2,\n      primaryColorHover,\n      primaryColorPressed,\n      primaryColor,\n      infoColor,\n      successColor,\n      warningColor,\n      errorColor,\n      baseColor,\n      borderColor,\n      tagColor,\n      opacityDisabled,\n      closeIconColor,\n      closeIconColorHover,\n      closeIconColorPressed,\n      closeColorHover,\n      closeColorPressed,\n      borderRadiusSmall: borderRadius,\n      fontSizeMini,\n      fontSizeTiny,\n      fontSizeSmall,\n      fontSizeMedium,\n      heightMini,\n      heightTiny,\n      heightSmall,\n      heightMedium,\n      buttonColor2Hover,\n      buttonColor2Pressed,\n      fontWeightStrong\n    } = vars\n    return {\n      ...commonVariables,\n      closeBorderRadius: borderRadius,\n      heightTiny: heightMini,\n      heightSmall: heightTiny,\n      heightMedium: heightSmall,\n      heightLarge: heightMedium,\n      borderRadius,\n      opacityDisabled,\n      fontSizeTiny: fontSizeMini,\n      fontSizeSmall: fontSizeTiny,\n      fontSizeMedium: fontSizeSmall,\n      fontSizeLarge: fontSizeMedium,\n      fontWeightStrong,\n      // checked\n      textColorCheckable: textColor2,\n      textColorHoverCheckable: textColor2,\n      textColorPressedCheckable: textColor2,\n      textColorChecked: baseColor,\n      colorCheckable: '#0000',\n      colorHoverCheckable: buttonColor2Hover,\n      colorPressedCheckable: buttonColor2Pressed,\n      colorChecked: primaryColor,\n      colorCheckedHover: primaryColorHover,\n      colorCheckedPressed: primaryColorPressed,\n      // default\n      border: `1px solid ${borderColor}`,\n      textColor: textColor2,\n      color: tagColor,\n      colorBordered: '#0000',\n      closeIconColor,\n      closeIconColorHover,\n      closeIconColorPressed,\n      closeColorHover,\n      closeColorPressed,\n      borderPrimary: `1px solid ${changeColor(primaryColor, { alpha: 0.3 })}`,\n      textColorPrimary: primaryColor,\n      colorPrimary: changeColor(primaryColor, { alpha: 0.16 }),\n      colorBorderedPrimary: '#0000',\n      closeIconColorPrimary: scaleColor(primaryColor, { lightness: 0.7 }),\n      closeIconColorHoverPrimary: scaleColor(primaryColor, { lightness: 0.7 }),\n      closeIconColorPressedPrimary: scaleColor(primaryColor, {\n        lightness: 0.7\n      }),\n      closeColorHoverPrimary: changeColor(primaryColor, { alpha: 0.16 }),\n      closeColorPressedPrimary: changeColor(primaryColor, { alpha: 0.12 }),\n      borderInfo: `1px solid ${changeColor(infoColor, { alpha: 0.3 })}`,\n      textColorInfo: infoColor,\n      colorInfo: changeColor(infoColor, { alpha: 0.16 }),\n      colorBorderedInfo: '#0000',\n      closeIconColorInfo: scaleColor(infoColor, { alpha: 0.7 }),\n      closeIconColorHoverInfo: scaleColor(infoColor, { alpha: 0.7 }),\n      closeIconColorPressedInfo: scaleColor(infoColor, { alpha: 0.7 }),\n      closeColorHoverInfo: changeColor(infoColor, { alpha: 0.16 }),\n      closeColorPressedInfo: changeColor(infoColor, { alpha: 0.12 }),\n      borderSuccess: `1px solid ${changeColor(successColor, { alpha: 0.3 })}`,\n      textColorSuccess: successColor,\n      colorSuccess: changeColor(successColor, { alpha: 0.16 }),\n      colorBorderedSuccess: '#0000',\n      closeIconColorSuccess: scaleColor(successColor, { alpha: 0.7 }),\n      closeIconColorHoverSuccess: scaleColor(successColor, { alpha: 0.7 }),\n      closeIconColorPressedSuccess: scaleColor(successColor, { alpha: 0.7 }),\n      closeColorHoverSuccess: changeColor(successColor, { alpha: 0.16 }),\n      closeColorPressedSuccess: changeColor(successColor, { alpha: 0.12 }),\n      borderWarning: `1px solid ${changeColor(warningColor, { alpha: 0.3 })}`,\n      textColorWarning: warningColor,\n      colorWarning: changeColor(warningColor, { alpha: 0.16 }),\n      colorBorderedWarning: '#0000',\n      closeIconColorWarning: scaleColor(warningColor, { alpha: 0.7 }),\n      closeIconColorHoverWarning: scaleColor(warningColor, { alpha: 0.7 }),\n      closeIconColorPressedWarning: scaleColor(warningColor, { alpha: 0.7 }),\n      closeColorHoverWarning: changeColor(warningColor, { alpha: 0.16 }),\n      closeColorPressedWarning: changeColor(warningColor, { alpha: 0.11 }),\n      borderError: `1px solid ${changeColor(errorColor, { alpha: 0.3 })}`,\n      textColorError: errorColor,\n      colorError: changeColor(errorColor, { alpha: 0.16 }),\n      colorBorderedError: '#0000',\n      closeIconColorError: scaleColor(errorColor, { alpha: 0.7 }),\n      closeIconColorHoverError: scaleColor(errorColor, { alpha: 0.7 }),\n      closeIconColorPressedError: scaleColor(errorColor, { alpha: 0.7 }),\n      closeColorHoverError: changeColor(errorColor, { alpha: 0.16 }),\n      closeColorPressedError: changeColor(errorColor, { alpha: 0.12 })\n    }\n  }\n}\n\nexport default tagDark\n"
  },
  {
    "path": "src/tag/styles/index.ts",
    "content": "export { default as tagDark } from './dark'\nexport { default as tagLight } from './light'\nexport type { TagTheme, TagThemeVars } from './light'\nexport { tagRtl } from './rtl'\n"
  },
  {
    "path": "src/tag/styles/light.ts",
    "content": "import type { Theme } from '../../_mixins'\nimport type { ThemeCommonVars } from '../../_styles/common'\nimport { changeColor } from 'seemly'\nimport { commonLight } from '../../_styles/common'\nimport commonVariables from './_common'\n\nfunction self(vars: ThemeCommonVars) {\n  const {\n    textColor2,\n    primaryColorHover,\n    primaryColorPressed,\n    primaryColor,\n    infoColor,\n    successColor,\n    warningColor,\n    errorColor,\n    baseColor,\n    borderColor,\n    opacityDisabled,\n    tagColor,\n    closeIconColor,\n    closeIconColorHover,\n    closeIconColorPressed,\n    borderRadiusSmall: borderRadius,\n    fontSizeMini,\n    fontSizeTiny,\n    fontSizeSmall,\n    fontSizeMedium,\n    heightMini,\n    heightTiny,\n    heightSmall,\n    heightMedium,\n    closeColorHover,\n    closeColorPressed,\n    buttonColor2Hover,\n    buttonColor2Pressed,\n    fontWeightStrong\n  } = vars\n  return {\n    ...commonVariables,\n    closeBorderRadius: borderRadius,\n    heightTiny: heightMini,\n    heightSmall: heightTiny,\n    heightMedium: heightSmall,\n    heightLarge: heightMedium,\n    borderRadius,\n    opacityDisabled,\n    fontSizeTiny: fontSizeMini,\n    fontSizeSmall: fontSizeTiny,\n    fontSizeMedium: fontSizeSmall,\n    fontSizeLarge: fontSizeMedium,\n    fontWeightStrong,\n    // checked\n    textColorCheckable: textColor2,\n    textColorHoverCheckable: textColor2,\n    textColorPressedCheckable: textColor2,\n    textColorChecked: baseColor,\n    colorCheckable: '#0000',\n    colorHoverCheckable: buttonColor2Hover,\n    colorPressedCheckable: buttonColor2Pressed,\n    colorChecked: primaryColor,\n    colorCheckedHover: primaryColorHover,\n    colorCheckedPressed: primaryColorPressed,\n    // default\n    border: `1px solid ${borderColor}`,\n    textColor: textColor2,\n    color: tagColor,\n    colorBordered: 'rgb(250, 250, 252)',\n    closeIconColor,\n    closeIconColorHover,\n    closeIconColorPressed,\n    closeColorHover,\n    closeColorPressed,\n    borderPrimary: `1px solid ${changeColor(primaryColor, { alpha: 0.3 })}`,\n    textColorPrimary: primaryColor,\n    colorPrimary: changeColor(primaryColor, { alpha: 0.12 }),\n    colorBorderedPrimary: changeColor(primaryColor, { alpha: 0.1 }),\n    closeIconColorPrimary: primaryColor,\n    closeIconColorHoverPrimary: primaryColor,\n    closeIconColorPressedPrimary: primaryColor,\n    closeColorHoverPrimary: changeColor(primaryColor, { alpha: 0.12 }),\n    closeColorPressedPrimary: changeColor(primaryColor, { alpha: 0.18 }),\n    borderInfo: `1px solid ${changeColor(infoColor, { alpha: 0.3 })}`,\n    textColorInfo: infoColor,\n    colorInfo: changeColor(infoColor, { alpha: 0.12 }),\n    colorBorderedInfo: changeColor(infoColor, { alpha: 0.1 }),\n    closeIconColorInfo: infoColor,\n    closeIconColorHoverInfo: infoColor,\n    closeIconColorPressedInfo: infoColor,\n    closeColorHoverInfo: changeColor(infoColor, { alpha: 0.12 }),\n    closeColorPressedInfo: changeColor(infoColor, { alpha: 0.18 }),\n    borderSuccess: `1px solid ${changeColor(successColor, { alpha: 0.3 })}`,\n    textColorSuccess: successColor,\n    colorSuccess: changeColor(successColor, { alpha: 0.12 }),\n    colorBorderedSuccess: changeColor(successColor, { alpha: 0.1 }),\n    closeIconColorSuccess: successColor,\n    closeIconColorHoverSuccess: successColor,\n    closeIconColorPressedSuccess: successColor,\n    closeColorHoverSuccess: changeColor(successColor, { alpha: 0.12 }),\n    closeColorPressedSuccess: changeColor(successColor, { alpha: 0.18 }),\n    borderWarning: `1px solid ${changeColor(warningColor, { alpha: 0.35 })}`,\n    textColorWarning: warningColor,\n    colorWarning: changeColor(warningColor, { alpha: 0.15 }),\n    colorBorderedWarning: changeColor(warningColor, { alpha: 0.12 }),\n    closeIconColorWarning: warningColor,\n    closeIconColorHoverWarning: warningColor,\n    closeIconColorPressedWarning: warningColor,\n    closeColorHoverWarning: changeColor(warningColor, { alpha: 0.12 }),\n    closeColorPressedWarning: changeColor(warningColor, { alpha: 0.18 }),\n    borderError: `1px solid ${changeColor(errorColor, { alpha: 0.23 })}`,\n    textColorError: errorColor,\n    colorError: changeColor(errorColor, { alpha: 0.1 }),\n    colorBorderedError: changeColor(errorColor, { alpha: 0.08 }),\n    closeIconColorError: errorColor,\n    closeIconColorHoverError: errorColor,\n    closeIconColorPressedError: errorColor,\n    closeColorHoverError: changeColor(errorColor, { alpha: 0.12 }),\n    closeColorPressedError: changeColor(errorColor, { alpha: 0.18 })\n  }\n}\n\nexport type TagThemeVars = ReturnType<typeof self>\n\nconst tagLight: Theme<'Tag', TagThemeVars> = {\n  name: 'Tag',\n  common: commonLight,\n  self\n}\n\nexport default tagLight\nexport type TagTheme = typeof tagLight\n"
  },
  {
    "path": "src/tag/styles/rtl.ts",
    "content": "import type { RtlItem } from '../../config-provider/src/internal-interface'\nimport rtlStyle from '../src/styles/rtl.cssr'\n\nexport const tagRtl: RtlItem = {\n  name: 'Tag',\n  style: rtlStyle\n}\n"
  },
  {
    "path": "src/tag/tests/Tag.spec.ts",
    "content": "import { mount } from '@vue/test-utils'\nimport { h } from 'vue'\nimport { NAvatar } from '../../avatar'\nimport { NTag } from '../index'\n\ndescribe('n-tag', () => {\n  it('should work with import on demand', () => {\n    mount(NTag)\n  })\n\n  it('should work with `bordered` prop', () => {\n    const wrapper = mount(NTag, {\n      props: {\n        bordered: true\n      }\n    })\n\n    expect(wrapper.find('.n-tag__border').exists()).toBe(true)\n  })\n\n  it('should be clickable', () => {\n    const onClick = vi.fn()\n    const wrapper = mount(NTag, {\n      props: {\n        onClick\n      }\n    })\n\n    wrapper.trigger('click')\n    expect(onClick).toHaveBeenCalled()\n  })\n\n  it('should be `checkable` prop', async () => {\n    const wrapper = mount(NTag, {\n      props: {\n        checkable: true\n      }\n    })\n\n    await wrapper.setProps({ checked: true })\n    expect(wrapper.find('.n-tag').classes()).toContain('n-tag--checkable')\n\n    await wrapper.setProps({ checked: false })\n    expect(wrapper.find('.n-tag').classes()).not.toContain('n-tag--checked')\n  })\n\n  it('should work with `on-update:checked` prop', () => {\n    const onChecked = vi.fn()\n    const wrapper = mount(NTag, {\n      props: {\n        checkable: true,\n        'onUpdate:checked': onChecked,\n        onUpdateChecked: onChecked\n      }\n    })\n\n    wrapper.trigger('click')\n    expect(onChecked).toHaveBeenCalled()\n    expect(onChecked).toHaveBeenCalledTimes(2)\n  })\n\n  it('should work with `closable` `on-close` prop', () => {\n    const onClose = vi.fn()\n    const wrapper = mount(NTag, {\n      props: {\n        closable: true,\n        onClose\n      }\n    })\n\n    expect(wrapper.find('.n-tag__close').exists()).toBe(true)\n    wrapper.find('.n-tag__close').trigger('click')\n    expect(onClose).toHaveBeenCalled()\n  })\n\n  it('should work with `disabled` prop', async () => {\n    const onClose = vi.fn()\n    const wrapper = mount(NTag, {\n      props: {\n        disabled: true,\n        closable: true,\n        onClose\n      }\n    })\n\n    expect(wrapper.find('.n-tag').classes()).toContain('n-tag--disabled')\n    wrapper.find('.n-tag__close').trigger('click')\n    expect(onClose).not.toHaveBeenCalled()\n  })\n\n  it('should work with `round` prop', () => {\n    const wrapper = mount(NTag, {\n      props: {\n        round: true\n      }\n    })\n\n    expect(wrapper.find('.n-tag').classes()).toContain('n-tag--round')\n  })\n\n  it('should work with `size` prop', () => {\n    ;(['small', 'medium', 'large'] as const).forEach((size) => {\n      const wrapper = mount(NTag)\n      wrapper.setProps({ size })\n      expect(wrapper.find('.n-tag').attributes('style')).toMatchSnapshot()\n      wrapper.unmount()\n    })\n  })\n\n  it('should work with `type` prop', () => {\n    ;(['default', 'info', 'success', 'warning', 'error'] as const).forEach(\n      (type) => {\n        const wrapper = mount(NTag)\n        wrapper.setProps({ type })\n        expect(wrapper.find('.n-tag').attributes('style')).toMatchSnapshot()\n        wrapper.unmount()\n      }\n    )\n  })\n\n  it('should work with default slot', () => {\n    const wrapper = mount(NTag, {\n      slots: {\n        default: () => 'default'\n      }\n    })\n\n    expect(wrapper.find('.n-tag__content').exists()).toBe(true)\n    expect(wrapper.find('.n-tag__content').element.textContent).toBe('default')\n    expect(wrapper.find('.n-tag__content').html()).toMatchSnapshot()\n  })\n\n  it('should work with `color` prop', () => {\n    const wrapper = mount(NTag, {\n      props: {\n        color: {\n          color: '#ccc',\n          textColor: '#555',\n          borderColor: 'rgb(85, 85, 85)'\n        }\n      }\n    })\n    expect(wrapper.find('.n-tag').attributes('style')).toContain(\n      '--n-color: #ccc;'\n    )\n    expect(wrapper.find('.n-tag').attributes('style')).toContain(\n      '--n-text-color: #555;'\n    )\n    expect(wrapper.find('.n-tag__border').attributes('style')).toContain(\n      'border-color: rgb(85, 85, 85);'\n    )\n  })\n\n  it('should work with `avatar` slot', () => {\n    const wrapper = mount(NTag, {\n      slots: {\n        avatar: () =>\n          h(NAvatar, {\n            src: 'https://cdnimg103.lizhi.fm/user/2017/02/04/2583325032200238082_160x160.jpg'\n          })\n      }\n    })\n\n    expect(wrapper.find('.n-tag__avatar').exists()).toBe(true)\n    expect(wrapper.find('.n-avatar').attributes('style')).toContain(\n      '--n-merged-size: var(--n-avatar-size-override, 34px);'\n    )\n  })\n})\n"
  },
  {
    "path": "src/tag/tests/__snapshots__/Tag.spec.ts.snap",
    "content": "// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html\n\nexports[`n-tag > should work with \\`size\\` prop 1`] = `\"--n-font-weight-strong: 500; --n-avatar-size-override: calc(28px - 8px); --n-bezier: cubic-bezier(.4, 0, .2, 1); --n-border-radius: 2px; --n-border: 1px solid rgb(224, 224, 230); --n-close-icon-size: 14px; --n-close-color-pressed: rgba(0, 0, 0, .13); --n-close-color-hover: rgba(0, 0, 0, .09); --n-close-border-radius: 2px; --n-close-icon-color: rgba(102, 102, 102, 1); --n-close-icon-color-hover: rgba(102, 102, 102, 1); --n-close-icon-color-pressed: rgba(102, 102, 102, 1); --n-close-icon-color-disabled: rgba(102, 102, 102, 1); --n-close-margin-top: 0; --n-close-margin-right: 0; --n-close-margin-bottom: 0; --n-close-margin-left: 4px; --n-close-size: 18px; --n-color: rgb(250, 250, 252); --n-color-checkable: #0000; --n-color-checked: #18a058; --n-color-checked-hover: #36ad6a; --n-color-checked-pressed: #0c7a43; --n-color-hover-checkable: rgba(46, 51, 56, .09); --n-color-pressed-checkable: rgba(46, 51, 56, .13); --n-font-size: 14px; --n-height: 28px; --n-opacity-disabled: 0.5; --n-padding: 0 7px; --n-text-color: rgb(51, 54, 57); --n-text-color-checkable: rgb(51, 54, 57); --n-text-color-checked: #FFF; --n-text-color-hover-checkable: rgb(51, 54, 57); --n-text-color-pressed-checkable: rgb(51, 54, 57);\"`;\n\nexports[`n-tag > should work with \\`size\\` prop 2`] = `\"--n-font-weight-strong: 500; --n-avatar-size-override: calc(28px - 8px); --n-bezier: cubic-bezier(.4, 0, .2, 1); --n-border-radius: 2px; --n-border: 1px solid rgb(224, 224, 230); --n-close-icon-size: 14px; --n-close-color-pressed: rgba(0, 0, 0, .13); --n-close-color-hover: rgba(0, 0, 0, .09); --n-close-border-radius: 2px; --n-close-icon-color: rgba(102, 102, 102, 1); --n-close-icon-color-hover: rgba(102, 102, 102, 1); --n-close-icon-color-pressed: rgba(102, 102, 102, 1); --n-close-icon-color-disabled: rgba(102, 102, 102, 1); --n-close-margin-top: 0; --n-close-margin-right: 0; --n-close-margin-bottom: 0; --n-close-margin-left: 4px; --n-close-size: 18px; --n-color: rgb(250, 250, 252); --n-color-checkable: #0000; --n-color-checked: #18a058; --n-color-checked-hover: #36ad6a; --n-color-checked-pressed: #0c7a43; --n-color-hover-checkable: rgba(46, 51, 56, .09); --n-color-pressed-checkable: rgba(46, 51, 56, .13); --n-font-size: 14px; --n-height: 28px; --n-opacity-disabled: 0.5; --n-padding: 0 7px; --n-text-color: rgb(51, 54, 57); --n-text-color-checkable: rgb(51, 54, 57); --n-text-color-checked: #FFF; --n-text-color-hover-checkable: rgb(51, 54, 57); --n-text-color-pressed-checkable: rgb(51, 54, 57);\"`;\n\nexports[`n-tag > should work with \\`size\\` prop 3`] = `\"--n-font-weight-strong: 500; --n-avatar-size-override: calc(28px - 8px); --n-bezier: cubic-bezier(.4, 0, .2, 1); --n-border-radius: 2px; --n-border: 1px solid rgb(224, 224, 230); --n-close-icon-size: 14px; --n-close-color-pressed: rgba(0, 0, 0, .13); --n-close-color-hover: rgba(0, 0, 0, .09); --n-close-border-radius: 2px; --n-close-icon-color: rgba(102, 102, 102, 1); --n-close-icon-color-hover: rgba(102, 102, 102, 1); --n-close-icon-color-pressed: rgba(102, 102, 102, 1); --n-close-icon-color-disabled: rgba(102, 102, 102, 1); --n-close-margin-top: 0; --n-close-margin-right: 0; --n-close-margin-bottom: 0; --n-close-margin-left: 4px; --n-close-size: 18px; --n-color: rgb(250, 250, 252); --n-color-checkable: #0000; --n-color-checked: #18a058; --n-color-checked-hover: #36ad6a; --n-color-checked-pressed: #0c7a43; --n-color-hover-checkable: rgba(46, 51, 56, .09); --n-color-pressed-checkable: rgba(46, 51, 56, .13); --n-font-size: 14px; --n-height: 28px; --n-opacity-disabled: 0.5; --n-padding: 0 7px; --n-text-color: rgb(51, 54, 57); --n-text-color-checkable: rgb(51, 54, 57); --n-text-color-checked: #FFF; --n-text-color-hover-checkable: rgb(51, 54, 57); --n-text-color-pressed-checkable: rgb(51, 54, 57);\"`;\n\nexports[`n-tag > should work with \\`type\\` prop 1`] = `\"--n-font-weight-strong: 500; --n-avatar-size-override: calc(28px - 8px); --n-bezier: cubic-bezier(.4, 0, .2, 1); --n-border-radius: 2px; --n-border: 1px solid rgb(224, 224, 230); --n-close-icon-size: 14px; --n-close-color-pressed: rgba(0, 0, 0, .13); --n-close-color-hover: rgba(0, 0, 0, .09); --n-close-border-radius: 2px; --n-close-icon-color: rgba(102, 102, 102, 1); --n-close-icon-color-hover: rgba(102, 102, 102, 1); --n-close-icon-color-pressed: rgba(102, 102, 102, 1); --n-close-icon-color-disabled: rgba(102, 102, 102, 1); --n-close-margin-top: 0; --n-close-margin-right: 0; --n-close-margin-bottom: 0; --n-close-margin-left: 4px; --n-close-size: 18px; --n-color: rgb(250, 250, 252); --n-color-checkable: #0000; --n-color-checked: #18a058; --n-color-checked-hover: #36ad6a; --n-color-checked-pressed: #0c7a43; --n-color-hover-checkable: rgba(46, 51, 56, .09); --n-color-pressed-checkable: rgba(46, 51, 56, .13); --n-font-size: 14px; --n-height: 28px; --n-opacity-disabled: 0.5; --n-padding: 0 7px; --n-text-color: rgb(51, 54, 57); --n-text-color-checkable: rgb(51, 54, 57); --n-text-color-checked: #FFF; --n-text-color-hover-checkable: rgb(51, 54, 57); --n-text-color-pressed-checkable: rgb(51, 54, 57);\"`;\n\nexports[`n-tag > should work with \\`type\\` prop 2`] = `\"--n-font-weight-strong: 500; --n-avatar-size-override: calc(28px - 8px); --n-bezier: cubic-bezier(.4, 0, .2, 1); --n-border-radius: 2px; --n-border: 1px solid rgb(224, 224, 230); --n-close-icon-size: 14px; --n-close-color-pressed: rgba(0, 0, 0, .13); --n-close-color-hover: rgba(0, 0, 0, .09); --n-close-border-radius: 2px; --n-close-icon-color: rgba(102, 102, 102, 1); --n-close-icon-color-hover: rgba(102, 102, 102, 1); --n-close-icon-color-pressed: rgba(102, 102, 102, 1); --n-close-icon-color-disabled: rgba(102, 102, 102, 1); --n-close-margin-top: 0; --n-close-margin-right: 0; --n-close-margin-bottom: 0; --n-close-margin-left: 4px; --n-close-size: 18px; --n-color: rgb(250, 250, 252); --n-color-checkable: #0000; --n-color-checked: #18a058; --n-color-checked-hover: #36ad6a; --n-color-checked-pressed: #0c7a43; --n-color-hover-checkable: rgba(46, 51, 56, .09); --n-color-pressed-checkable: rgba(46, 51, 56, .13); --n-font-size: 14px; --n-height: 28px; --n-opacity-disabled: 0.5; --n-padding: 0 7px; --n-text-color: rgb(51, 54, 57); --n-text-color-checkable: rgb(51, 54, 57); --n-text-color-checked: #FFF; --n-text-color-hover-checkable: rgb(51, 54, 57); --n-text-color-pressed-checkable: rgb(51, 54, 57);\"`;\n\nexports[`n-tag > should work with \\`type\\` prop 3`] = `\"--n-font-weight-strong: 500; --n-avatar-size-override: calc(28px - 8px); --n-bezier: cubic-bezier(.4, 0, .2, 1); --n-border-radius: 2px; --n-border: 1px solid rgb(224, 224, 230); --n-close-icon-size: 14px; --n-close-color-pressed: rgba(0, 0, 0, .13); --n-close-color-hover: rgba(0, 0, 0, .09); --n-close-border-radius: 2px; --n-close-icon-color: rgba(102, 102, 102, 1); --n-close-icon-color-hover: rgba(102, 102, 102, 1); --n-close-icon-color-pressed: rgba(102, 102, 102, 1); --n-close-icon-color-disabled: rgba(102, 102, 102, 1); --n-close-margin-top: 0; --n-close-margin-right: 0; --n-close-margin-bottom: 0; --n-close-margin-left: 4px; --n-close-size: 18px; --n-color: rgb(250, 250, 252); --n-color-checkable: #0000; --n-color-checked: #18a058; --n-color-checked-hover: #36ad6a; --n-color-checked-pressed: #0c7a43; --n-color-hover-checkable: rgba(46, 51, 56, .09); --n-color-pressed-checkable: rgba(46, 51, 56, .13); --n-font-size: 14px; --n-height: 28px; --n-opacity-disabled: 0.5; --n-padding: 0 7px; --n-text-color: rgb(51, 54, 57); --n-text-color-checkable: rgb(51, 54, 57); --n-text-color-checked: #FFF; --n-text-color-hover-checkable: rgb(51, 54, 57); --n-text-color-pressed-checkable: rgb(51, 54, 57);\"`;\n\nexports[`n-tag > should work with \\`type\\` prop 4`] = `\"--n-font-weight-strong: 500; --n-avatar-size-override: calc(28px - 8px); --n-bezier: cubic-bezier(.4, 0, .2, 1); --n-border-radius: 2px; --n-border: 1px solid rgb(224, 224, 230); --n-close-icon-size: 14px; --n-close-color-pressed: rgba(0, 0, 0, .13); --n-close-color-hover: rgba(0, 0, 0, .09); --n-close-border-radius: 2px; --n-close-icon-color: rgba(102, 102, 102, 1); --n-close-icon-color-hover: rgba(102, 102, 102, 1); --n-close-icon-color-pressed: rgba(102, 102, 102, 1); --n-close-icon-color-disabled: rgba(102, 102, 102, 1); --n-close-margin-top: 0; --n-close-margin-right: 0; --n-close-margin-bottom: 0; --n-close-margin-left: 4px; --n-close-size: 18px; --n-color: rgb(250, 250, 252); --n-color-checkable: #0000; --n-color-checked: #18a058; --n-color-checked-hover: #36ad6a; --n-color-checked-pressed: #0c7a43; --n-color-hover-checkable: rgba(46, 51, 56, .09); --n-color-pressed-checkable: rgba(46, 51, 56, .13); --n-font-size: 14px; --n-height: 28px; --n-opacity-disabled: 0.5; --n-padding: 0 7px; --n-text-color: rgb(51, 54, 57); --n-text-color-checkable: rgb(51, 54, 57); --n-text-color-checked: #FFF; --n-text-color-hover-checkable: rgb(51, 54, 57); --n-text-color-pressed-checkable: rgb(51, 54, 57);\"`;\n\nexports[`n-tag > should work with \\`type\\` prop 5`] = `\"--n-font-weight-strong: 500; --n-avatar-size-override: calc(28px - 8px); --n-bezier: cubic-bezier(.4, 0, .2, 1); --n-border-radius: 2px; --n-border: 1px solid rgb(224, 224, 230); --n-close-icon-size: 14px; --n-close-color-pressed: rgba(0, 0, 0, .13); --n-close-color-hover: rgba(0, 0, 0, .09); --n-close-border-radius: 2px; --n-close-icon-color: rgba(102, 102, 102, 1); --n-close-icon-color-hover: rgba(102, 102, 102, 1); --n-close-icon-color-pressed: rgba(102, 102, 102, 1); --n-close-icon-color-disabled: rgba(102, 102, 102, 1); --n-close-margin-top: 0; --n-close-margin-right: 0; --n-close-margin-bottom: 0; --n-close-margin-left: 4px; --n-close-size: 18px; --n-color: rgb(250, 250, 252); --n-color-checkable: #0000; --n-color-checked: #18a058; --n-color-checked-hover: #36ad6a; --n-color-checked-pressed: #0c7a43; --n-color-hover-checkable: rgba(46, 51, 56, .09); --n-color-pressed-checkable: rgba(46, 51, 56, .13); --n-font-size: 14px; --n-height: 28px; --n-opacity-disabled: 0.5; --n-padding: 0 7px; --n-text-color: rgb(51, 54, 57); --n-text-color-checkable: rgb(51, 54, 57); --n-text-color-checked: #FFF; --n-text-color-hover-checkable: rgb(51, 54, 57); --n-text-color-pressed-checkable: rgb(51, 54, 57);\"`;\n\nexports[`n-tag > should work with default slot 1`] = `\"<span class=\"n-tag__content\">default</span>\"`;\n"
  },
  {
    "path": "src/tag/tests/server.spec.tsx",
    "content": "import { setup } from '@css-render/vue3-ssr'\nimport { renderToString } from '@vue/server-renderer'\n/**\n * @vitest-environment node\n */\nimport { createSSRApp, h } from 'vue'\nimport { NTag } from '../..'\n\ndescribe('server side rendering', () => {\n  it('works', async () => {\n    const app = createSSRApp(() => <NTag />)\n    setup(app)\n    try {\n      await renderToString(app)\n    }\n    catch (e) {\n      expect(e).not.toBeTruthy()\n    }\n  })\n})\n"
  },
  {
    "path": "src/theme-editor/index.ts",
    "content": "export { default as NThemeEditor } from './src/ThemeEditor'\n"
  },
  {
    "path": "src/theme-editor/src/MaximizeIcon.tsx",
    "content": "import { defineComponent, h } from 'vue'\n\nexport const MaximizeIcon = defineComponent({\n  render() {\n    return (\n      <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 16 16\">\n        <g fill=\"none\">\n          <path\n            d=\"M8.5 2a.5.5 0 0 0 0 1h3.793L3 12.293V8.5a.5.5 0 0 0-1 0v4.9a.6.6 0 0 0 .6.6h4.9a.5.5 0 0 0 0-1H3.707L13 3.707V7.5a.5.5 0 0 0 1 0V2.6a.6.6 0 0 0-.6-.6H8.5z\"\n            fill=\"currentColor\"\n          >\n          </path>\n        </g>\n      </svg>\n    )\n  }\n})\n"
  },
  {
    "path": "src/theme-editor/src/MinimizeIcon.tsx",
    "content": "import { defineComponent, h } from 'vue'\n\nexport const MinimizeIcon = defineComponent({\n  render() {\n    return (\n      <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 32 32\">\n        <path\n          d=\"M4 18v2h6.586L2 28.582L3.414 30L12 21.414V28h2V18H4z\"\n          fill=\"currentColor\"\n        >\n        </path>\n        <path\n          d=\"M30 3.416L28.592 2L20 10.586V4h-2v10h10v-2h-6.586L30 3.416z\"\n          fill=\"currentColor\"\n        >\n        </path>\n      </svg>\n    )\n  }\n})\n"
  },
  {
    "path": "src/theme-editor/src/ThemeEditor.tsx",
    "content": "import type { GlobalTheme, GlobalThemeOverrides } from '../../config-provider'\nimport { cloneDeep, merge } from 'lodash-es'\nimport {\n  computed,\n  defineComponent,\n  Fragment,\n  h,\n  inject,\n  ref,\n  toRaw,\n  watch\n} from 'vue'\nimport { useLocale } from '../../_mixins'\nimport { download, lockHtmlScrollRightCompensationRef } from '../../_utils'\nimport { NButton } from '../../button'\nimport { NCollapse, NCollapseItem } from '../../collapse'\nimport { NColorPicker } from '../../color-picker'\nimport { NConfigProvider } from '../../config-provider'\nimport { configProviderInjectionKey } from '../../config-provider/src/context'\nimport { NDivider } from '../../divider'\nimport { NElement } from '../../element'\nimport { NEmpty } from '../../empty'\nimport { NGi, NGrid } from '../../grid'\nimport { NIcon } from '../../icon'\nimport { NInput } from '../../input'\nimport { NPopover } from '../../popover'\nimport { NSpace } from '../../space'\nimport { lightTheme } from '../../themes/light'\nimport { MaximizeIcon } from './MaximizeIcon'\nimport { MinimizeIcon } from './MinimizeIcon'\n\nfunction renderColorWandIcon() {\n  return (\n    <svg\n      viewBox=\"0 0 16 16\"\n      fill=\"none\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n      style={{ width: '1em', height: '1em', color: 'currentColor' }}\n    >\n      <path\n        d=\"M13.5 1C13.7761 1 14 1.22386 14 1.5V2H14.5C14.7761 2 15 2.22386 15 2.5C15 2.77614 14.7761 3 14.5 3H14V3.5C14 3.77614 13.7761 4 13.5 4C13.2239 4 13 3.77614 13 3.5V3H12.5C12.2239 3 12 2.77614 12 2.5C12 2.22386 12.2239 2 12.5 2H13V1.5C13 1.22386 13.2239 1 13.5 1Z\"\n        fill=\"currentColor\"\n      >\n      </path>\n      <path\n        d=\"M3.5 3C3.77615 3 4 3.22386 4 3.5V4H4.5C4.77615 4 5 4.22386 5 4.5C5 4.77614 4.77615 5 4.5 5H4V5.5C4 5.77614 3.77615 6 3.5 6C3.22386 6 3 5.77614 3 5.5V5H2.5C2.22386 5 2 4.77614 2 4.5C2 4.22386 2.22386 4 2.5 4H3V3.5C3 3.22386 3.22386 3 3.5 3Z\"\n        fill=\"currentColor\"\n      >\n      </path>\n      <path\n        d=\"M12.5 12C12.7761 12 13 11.7761 13 11.5C13 11.2239 12.7761 11 12.5 11H12V10.5C12 10.2239 11.7761 10 11.5 10C11.2239 10 11 10.2239 11 10.5V11H10.5C10.2239 11 10 11.2239 10 11.5C10 11.7761 10.2239 12 10.5 12H11V12.5C11 12.7761 11.2239 13 11.5 13C11.7761 13 12 12.7761 12 12.5V12H12.5Z\"\n        fill=\"currentColor\"\n      >\n      </path>\n      <path\n        d=\"M8.72956 4.56346C9.4771 3.81592 10.6891 3.81592 11.4367 4.56347C12.1842 5.31102 12.1842 6.52303 11.4367 7.27058L4.26679 14.4404C3.51924 15.1879 2.30723 15.1879 1.55968 14.4404C0.812134 13.6928 0.812138 12.4808 1.55969 11.7333L8.72956 4.56346ZM8.25002 6.4572L2.26679 12.4404C1.90977 12.7974 1.90977 13.3763 2.26679 13.7333C2.62381 14.0903 3.20266 14.0903 3.55968 13.7333L9.54292 7.75009L8.25002 6.4572ZM10.25 7.04299L10.7295 6.56347C11.0866 6.20645 11.0866 5.6276 10.7296 5.27057C10.3725 4.91355 9.79368 4.91355 9.43666 5.27057L8.95713 5.7501L10.25 7.04299Z\"\n        fill=\"currentColor\"\n      >\n      </path>\n    </svg>\n  )\n}\n\n// button colorOpacitySecondary var is not color\nfunction showColorPicker(key: string): boolean {\n  if (key.includes('pacity'))\n    return false\n  if (key.includes('color') || key.includes('Color'))\n    return true\n  return false\n}\n\nexport default defineComponent({\n  name: 'ThemeEditor',\n  inheritAttrs: false,\n  setup() {\n    const isMaximized = ref<boolean>(false)\n    const fileInputRef = ref<HTMLInputElement | null>(null)\n    const NConfigProvider = inject(configProviderInjectionKey, null)\n    const overridesRef = ref<any>(\n      JSON.parse((localStorage['naive-ui-theme-overrides'] as string) || '{}')\n    )\n    const theme = computed(() => {\n      const mergedTheme: GlobalTheme\n        = NConfigProvider?.mergedThemeRef.value || lightTheme\n      const mergedThemeOverrides\n        = NConfigProvider?.mergedThemeOverridesRef.value\n      const common = merge(\n        {},\n        mergedTheme.common || lightTheme.common,\n        mergedThemeOverrides?.common,\n        overridesRef.value.common || {}\n      ) as NonNullable<GlobalTheme['common']>\n      const overrides: GlobalThemeOverrides = {\n        common\n      }\n      for (const key of Object.keys(lightTheme) as Array<\n        Exclude<keyof typeof lightTheme, 'name'>\n      >) {\n        if (key === 'common') {\n          continue\n        }\n        ;(overrides as any)[key] = (mergedTheme[key]?.self?.(common)\n          || lightTheme[key].self?.(common)) as any\n        // There (last line) we must use as any, nor ts 2590 will be raised since the union\n        // is too complex\n        if (mergedThemeOverrides && (overrides as any)[key]) {\n          merge((overrides as any)[key], mergedThemeOverrides[key])\n        }\n      }\n      return overrides\n    })\n    const themeCommonDefaultRef = computed(() => {\n      return NConfigProvider?.mergedThemeRef.value?.common || lightTheme.common\n    })\n    const showPanelRef = ref(false)\n    const tempOverridesRef = ref<any>(\n      JSON.parse((localStorage['naive-ui-theme-overrides'] as string) || '{}')\n    )\n    const varNamePatternRef = ref('')\n    const compNamePatternRef = ref('')\n    const tempVarNamePatternRef = ref('')\n    const tempCompNamePatternRef = ref('')\n    function applyTempOverrides(): void {\n      overridesRef.value = cloneDeep(toRaw(tempOverridesRef.value))\n    }\n    function setTempOverrides(\n      compName: string,\n      varName: string,\n      value: string\n    ): void {\n      const { value: tempOverrides } = tempOverridesRef\n      if (!(compName in tempOverrides))\n        tempOverrides[compName] = {}\n      const compOverrides = tempOverrides[compName]\n      if (value) {\n        compOverrides[varName] = value\n      }\n      else {\n        delete compOverrides[varName]\n      }\n    }\n    function handleClearAllClick(): void {\n      tempOverridesRef.value = {}\n      overridesRef.value = {}\n    }\n    function handleImportClick(): void {\n      const { value: fileInput } = fileInputRef\n      if (!fileInput)\n        return\n      fileInput.click()\n    }\n    function toggleMaximized(): void {\n      isMaximized.value = !isMaximized.value\n    }\n    function handleInputFileChange(): void {\n      const { value: fileInput } = fileInputRef\n      if (!fileInput)\n        return\n      const fileList = fileInput.files\n      const file = fileList?.[0]\n      if (!file)\n        return\n      file\n        .text()\n        .then((value) => {\n          overridesRef.value = JSON.parse(value)\n          tempOverridesRef.value = JSON.parse(value)\n        })\n        .catch((e) => {\n          // eslint-disable-next-line no-alert\n          alert('Imported File is Invalid')\n          console.error(e)\n        })\n        .finally(() => {\n          fileInput.value = ''\n        })\n    }\n    function handleExportClick(): void {\n      const url = URL.createObjectURL(\n        new Blob([JSON.stringify(overridesRef.value, undefined, 2)])\n      )\n      download(url, 'naive-ui-theme-overrides.json')\n      URL.revokeObjectURL(url)\n    }\n    watch(overridesRef, (value) => {\n      localStorage['naive-ui-theme-overrides'] = JSON.stringify(value)\n    })\n    return {\n      locale: useLocale('ThemeEditor').localeRef,\n      themeCommonDefault: themeCommonDefaultRef,\n      theme,\n      showPanel: showPanelRef,\n      tempOverrides: tempOverridesRef,\n      overrides: overridesRef,\n      compNamePattern: compNamePatternRef,\n      tempCompNamePattern: tempCompNamePatternRef,\n      varNamePattern: varNamePatternRef,\n      tempVarNamePattern: tempVarNamePatternRef,\n      fileInputRef,\n      applyTempOverrides,\n      setTempOverrides,\n      handleClearAllClick,\n      handleExportClick,\n      handleImportClick,\n      handleInputFileChange,\n      toggleMaximized,\n      isMaximized\n    }\n  },\n  render() {\n    return (\n      <NConfigProvider themeOverrides={this.overrides}>\n        {{\n          default: () => [\n            <NPopover\n              scrollable\n              arrowPointToCenter\n              trigger=\"manual\"\n              show={this.showPanel}\n              displayDirective=\"show\"\n              placement=\"top-end\"\n              style={{\n                width: this.isMaximized ? 'calc(100vw - 80px)' : '288px',\n                height: 'calc(100vh - 200px)',\n                padding: 0\n              }}\n            >\n              {{\n                trigger: () => (\n                  <NElement\n                    style={[\n                      {\n                        position: 'fixed',\n                        zIndex: 10,\n                        bottom: '40px',\n                        right: `calc(40px + ${lockHtmlScrollRightCompensationRef.value})`,\n                        width: '44px',\n                        height: '44px',\n                        fontSize: '26px',\n                        display: 'flex',\n                        alignItems: 'center',\n                        justifyContent: 'center',\n                        borderRadius: '50%',\n                        backgroundColor: 'var(--popover-color)',\n                        color: 'var(--text-color-2)',\n                        transition:\n                          'color .3s var(--cubic-bezier-ease-in-out), background-color .3s var(--cubic-bezier-ease-in-out), box-shadow .3s var(--cubic-bezier-ease-in-out)',\n                        boxShadow: '0 2px 8px 0px rgba(0, 0, 0, .12)',\n                        cursor: 'pointer'\n                      },\n                      this.$attrs.style\n                    ]}\n                    // @ts-expect-error We use ts-ignore for vue-tsc, since it\n                    // seems to patch native event for vue components\n                    onClick={() => {\n                      this.showPanel = !this.showPanel\n                    }}\n                  >\n                    {{ default: renderColorWandIcon }}\n                  </NElement>\n                ),\n                default: () => (\n                  <>\n                    <input\n                      type=\"file\"\n                      ref=\"fileInputRef\"\n                      style={{\n                        display: 'block',\n                        width: 0,\n                        height: 0,\n                        visibility: 'hidden'\n                      }}\n                      onChange={this.handleInputFileChange}\n                    />\n                    <NSpace vertical>\n                      {{\n                        default: () => [\n                          <NSpace\n                            align=\"center\"\n                            justify=\"space-between\"\n                            style={{\n                              marginBottom: '8px',\n                              fontSize: '18px',\n                              fontWeight: 500\n                            }}\n                          >\n                            {{\n                              default: () => (\n                                <>\n                                  <span>{this.locale.title}</span>\n                                  <NButton\n                                    onClick={this.toggleMaximized}\n                                    secondary\n                                    circle\n                                    size=\"tiny\"\n                                  >\n                                    {{\n                                      icon: () => (\n                                        <NIcon\n                                          component={\n                                            this.isMaximized\n                                              ? MinimizeIcon\n                                              : MaximizeIcon\n                                          }\n                                        />\n                                      )\n                                    }}\n                                  </NButton>\n                                </>\n                              )\n                            }}\n                          </NSpace>,\n                          this.locale.filterCompName,\n                          <NInput\n                            onChange={() => {\n                              this.compNamePattern = this.tempCompNamePattern\n                            }}\n                            onInput={(value: string) => {\n                              this.tempCompNamePattern = value\n                            }}\n                            value={this.tempCompNamePattern}\n                            placeholder={this.locale.filterCompName}\n                          />,\n                          this.locale.filterVarName,\n                          <NInput\n                            onChange={(value: string) => {\n                              this.varNamePattern = value\n                            }}\n                            onInput={(value: string) => {\n                              this.tempVarNamePattern = value\n                            }}\n                            value={this.tempVarNamePattern}\n                            placeholder={this.locale.filterVarName}\n                          />,\n                          <NButton\n                            size=\"small\"\n                            onClick={() => {\n                              this.compNamePattern = ''\n                              this.varNamePattern = ''\n                              this.tempCompNamePattern = ''\n                              this.tempVarNamePattern = ''\n                            }}\n                            block\n                          >\n                            {{ default: () => this.locale.clearSearch }}\n                          </NButton>,\n                          <NButton\n                            size=\"small\"\n                            onClick={this.handleClearAllClick}\n                            block\n                          >\n                            {{\n                              default: () => this.locale.clearAllVars\n                            }}\n                          </NButton>,\n                          <NSpace itemStyle={{ flex: 1 }}>\n                            {{\n                              default: () => (\n                                <>\n                                  <NButton\n                                    block\n                                    size=\"small\"\n                                    onClick={this.handleImportClick}\n                                  >\n                                    {{\n                                      default: () => this.locale.import\n                                    }}\n                                  </NButton>\n                                  <NButton\n                                    block\n                                    size=\"small\"\n                                    onClick={this.handleExportClick}\n                                  >\n                                    {{\n                                      default: () => this.locale.export\n                                    }}\n                                  </NButton>\n                                </>\n                              )\n                            }}\n                          </NSpace>\n                        ]\n                      }}\n                    </NSpace>\n                    <NDivider />\n                    <NCollapse>\n                      {{\n                        default: () => {\n                          const { theme, compNamePattern, varNamePattern }\n                            = this\n                          const themeKeys = Object.keys(theme)\n                          const compNamePatternLower\n                            = compNamePattern.toLowerCase()\n                          const varNamePatternLower\n                            = varNamePattern.toLowerCase()\n                          let filteredItemsCount = 0\n                          const collapsedItems = themeKeys\n                            .filter((themeKey) => {\n                              return themeKey\n                                .toLowerCase()\n                                .includes(compNamePatternLower)\n                            })\n                            .map((themeKey) => {\n                              const componentTheme:\n                                | Record<string, string>\n                                | undefined\n                                  = themeKey === 'common'\n                                    ? this.themeCommonDefault\n                                    : (theme as any)[themeKey]\n                              if (componentTheme === undefined) {\n                                return null\n                              }\n                              const varKeys = Object.keys(\n                                componentTheme\n                              ).filter((key) => {\n                                return (\n                                  key !== 'name'\n                                  && key\n                                    .toLowerCase()\n                                    .includes(varNamePatternLower)\n                                )\n                              })\n                              if (!varKeys.length) {\n                                return null\n                              }\n                              filteredItemsCount += 1\n                              return (\n                                <NCollapseItem title={themeKey} name={themeKey}>\n                                  {{\n                                    default: () => (\n                                      <NGrid\n                                        xGap={32}\n                                        yGap={16}\n                                        responsive=\"screen\"\n                                        cols={\n                                          this.isMaximized\n                                            ? '1 xs:1 s:2 m:3 l:4'\n                                            : 1\n                                        }\n                                      >\n                                        {{\n                                          default: () =>\n                                            varKeys.map(varKey => (\n                                              <NGi>\n                                                {{\n                                                  default: () => (\n                                                    <>\n                                                      <div\n                                                        key={`${varKey}Label`}\n                                                        style={{\n                                                          wordBreak:\n                                                            'break-word'\n                                                        }}\n                                                      >\n                                                        {varKey}\n                                                      </div>\n                                                      {showColorPicker(\n                                                        varKey\n                                                      ) ? (\n                                                            <NColorPicker\n                                                              key={varKey}\n                                                              modes={['rgb', 'hex']}\n                                                              value={\n                                                                this\n                                                                  .tempOverrides?.[\n                                                                    themeKey\n                                                                  ]?.[varKey]\n                                                                  || componentTheme[\n                                                                    varKey\n                                                                  ]\n                                                              }\n                                                              onComplete={\n                                                                this\n                                                                  .applyTempOverrides\n                                                              }\n                                                              onUpdateValue={(\n                                                                value: string\n                                                              ) => {\n                                                                this.setTempOverrides(\n                                                                  themeKey,\n                                                                  varKey,\n                                                                  value\n                                                                )\n                                                              }}\n                                                            >\n                                                              {{\n                                                                action: () => (\n                                                                  <NButton\n                                                                    size=\"small\"\n                                                                    disabled={\n                                                                      componentTheme[\n                                                                        varKey\n                                                                      ]\n                                                                      === this\n                                                                        .tempOverrides?.[\n                                                                          themeKey\n                                                                        ]?.[varKey]\n                                                                    }\n                                                                    onClick={() => {\n                                                                      this.setTempOverrides(\n                                                                        themeKey,\n                                                                        varKey,\n                                                                        componentTheme[\n                                                                          varKey\n                                                                        ]\n                                                                      )\n                                                                      this.applyTempOverrides()\n                                                                    }}\n                                                                  >\n                                                                    {{\n                                                                      default: () =>\n                                                                        this.locale\n                                                                          .restore\n                                                                    }}\n                                                                  </NButton>\n                                                                )\n                                                              }}\n                                                            </NColorPicker>\n                                                          ) : (\n                                                            <NInput\n                                                              key={varKey}\n                                                              onChange={\n                                                                this\n                                                                  .applyTempOverrides\n                                                              }\n                                                              onUpdateValue={(\n                                                                value: string\n                                                              ) => {\n                                                                this.setTempOverrides(\n                                                                  themeKey,\n                                                                  varKey,\n                                                                  value\n                                                                )\n                                                              }}\n                                                              value={\n                                                                this\n                                                                  .tempOverrides?.[\n                                                                    themeKey\n                                                                  ]?.[varKey] || ''\n                                                              }\n                                                              placeholder={\n                                                                componentTheme[\n                                                                  varKey\n                                                                ]\n                                                              }\n                                                            />\n                                                          )}\n                                                    </>\n                                                  )\n                                                }}\n                                              </NGi>\n                                            ))\n                                        }}\n                                      </NGrid>\n                                    )\n                                  }}\n                                </NCollapseItem>\n                              )\n                            })\n                          if (!filteredItemsCount)\n                            return <NEmpty />\n                          return collapsedItems\n                        }\n                      }}\n                    </NCollapse>\n                  </>\n                )\n              }}\n            </NPopover>,\n            this.$slots.default?.()\n          ]\n        }}\n      </NConfigProvider>\n    )\n  }\n})\n"
  },
  {
    "path": "src/themes/dark.ts",
    "content": "import type { BuiltInGlobalTheme } from './interface'\nimport { scrollbarDark } from '../_internal/scrollbar/styles'\nimport { commonDark } from '../_styles/common'\nimport { alertDark } from '../alert/styles'\nimport { anchorDark } from '../anchor/styles'\nimport { autoCompleteDark } from '../auto-complete/styles'\nimport { avatarGroupDark } from '../avatar-group/styles'\nimport { avatarDark } from '../avatar/styles'\nimport { backTopDark } from '../back-top/styles'\nimport { badgeDark } from '../badge/styles'\nimport { breadcrumbDark } from '../breadcrumb/styles'\nimport { buttonGroupDark } from '../button-group/styles'\nimport { buttonDark } from '../button/styles'\nimport { calendarDark } from '../calendar/styles'\nimport { cardDark } from '../card/styles'\nimport { carouselDark } from '../carousel/styles'\nimport { cascaderDark } from '../cascader/styles'\nimport { checkboxDark } from '../checkbox/styles'\nimport { codeDark } from '../code/styles'\nimport { collapseTransitionDark } from '../collapse-transition/styles'\nimport { collapseDark } from '../collapse/styles'\nimport { colorPickerDark } from '../color-picker/styles'\nimport { dataTableDark } from '../data-table/styles'\nimport { datePickerDark } from '../date-picker/styles'\nimport { descriptionsDark } from '../descriptions/styles'\nimport { dialogDark } from '../dialog/styles'\nimport { dividerDark } from '../divider/styles'\nimport { drawerDark } from '../drawer/styles'\nimport { dropdownDark } from '../dropdown/styles'\nimport { dynamicInputDark } from '../dynamic-input/styles'\nimport { dynamicTagsDark } from '../dynamic-tags/styles'\nimport { elementDark } from '../element/styles'\nimport { ellipsisDark } from '../ellipsis/styles'\nimport { emptyDark } from '../empty/styles'\nimport { equationDark } from '../equation/styles'\nimport { floatButtonGroupDark } from '../float-button-group/styles'\nimport { floatButtonDark } from '../float-button/styles'\nimport { formDark } from '../form/styles'\nimport { gradientTextDark } from '../gradient-text/styles'\nimport { heatmapDark } from '../heatmap/styles'\nimport { iconWrapperDark } from '../icon-wrapper/styles'\nimport { iconDark } from '../icon/styles'\nimport { imageDark } from '../image/styles'\nimport { inputNumberDark } from '../input-number/styles'\nimport { inputDark } from '../input/styles'\nimport { layoutDark } from '../layout/styles'\nimport { rowDark } from '../legacy-grid/styles'\nimport { legacyTransferDark } from '../legacy-transfer/styles'\nimport { listDark } from '../list/styles'\nimport { loadingBarDark } from '../loading-bar/styles'\nimport { logDark } from '../log/styles'\nimport { marqueeDark } from '../marquee/styles'\nimport { mentionDark } from '../mention/styles'\nimport { menuDark } from '../menu/styles'\nimport { messageDark } from '../message/styles'\nimport { modalDark } from '../modal/styles'\nimport { notificationDark } from '../notification/styles'\nimport { pageHeaderDark } from '../page-header/styles'\nimport { paginationDark } from '../pagination/styles'\nimport { popconfirmDark } from '../popconfirm/styles'\nimport { popoverDark } from '../popover/styles'\nimport { popselectDark } from '../popselect/styles'\nimport { progressDark } from '../progress/styles'\nimport { qrcodeDark } from '../qr-code/styles'\nimport { radioDark } from '../radio/styles'\nimport { rateDark } from '../rate/styles'\nimport { resultDark } from '../result/styles'\nimport { selectDark } from '../select/styles'\nimport { skeletonDark } from '../skeleton/styles'\nimport { sliderDark } from '../slider/styles'\nimport { spaceDark } from '../space/styles'\nimport { spinDark } from '../spin/styles'\nimport { splitDark } from '../split/styles'\nimport { statisticDark } from '../statistic/styles'\nimport { stepsDark } from '../steps/styles'\nimport { flexDark, inputOtpDark } from '../styles'\nimport { switchDark } from '../switch/styles'\nimport { tableDark } from '../table/styles'\nimport { tabsDark } from '../tabs/styles'\nimport { tagDark } from '../tag/styles'\nimport { thingDark } from '../thing/styles'\nimport { timePickerDark } from '../time-picker/styles'\nimport { timelineDark } from '../timeline/styles'\nimport { tooltipDark } from '../tooltip/styles'\nimport { transferDark } from '../transfer/styles'\nimport { treeSelectDark } from '../tree-select/styles'\nimport { treeDark } from '../tree/styles'\nimport { typographyDark } from '../typography/styles'\nimport { uploadDark } from '../upload/styles'\nimport { watermarkDark } from '../watermark/styles'\n\nexport const darkTheme: BuiltInGlobalTheme = {\n  name: 'dark',\n  common: commonDark,\n  Alert: alertDark,\n  Anchor: anchorDark,\n  AutoComplete: autoCompleteDark,\n  Avatar: avatarDark,\n  AvatarGroup: avatarGroupDark,\n  BackTop: backTopDark,\n  Badge: badgeDark,\n  Breadcrumb: breadcrumbDark,\n  Button: buttonDark,\n  ButtonGroup: buttonGroupDark,\n  Calendar: calendarDark,\n  Card: cardDark,\n  Carousel: carouselDark,\n  Cascader: cascaderDark,\n  Checkbox: checkboxDark,\n  Code: codeDark,\n  Collapse: collapseDark,\n  CollapseTransition: collapseTransitionDark,\n  ColorPicker: colorPickerDark,\n  DataTable: dataTableDark,\n  DatePicker: datePickerDark,\n  Descriptions: descriptionsDark,\n  Dialog: dialogDark,\n  Divider: dividerDark,\n  Drawer: drawerDark,\n  Dropdown: dropdownDark,\n  DynamicInput: dynamicInputDark,\n  DynamicTags: dynamicTagsDark,\n  Element: elementDark,\n  Empty: emptyDark,\n  Ellipsis: ellipsisDark,\n  Equation: equationDark,\n  Flex: flexDark,\n  Form: formDark,\n  GradientText: gradientTextDark,\n  Heatmap: heatmapDark,\n  Icon: iconDark,\n  IconWrapper: iconWrapperDark,\n  Image: imageDark,\n  Input: inputDark,\n  InputNumber: inputNumberDark,\n  InputOtp: inputOtpDark,\n  LegacyTransfer: legacyTransferDark,\n  Layout: layoutDark,\n  List: listDark,\n  LoadingBar: loadingBarDark,\n  Log: logDark,\n  Menu: menuDark,\n  Mention: mentionDark,\n  Message: messageDark,\n  Modal: modalDark,\n  Notification: notificationDark,\n  PageHeader: pageHeaderDark,\n  Pagination: paginationDark,\n  Popconfirm: popconfirmDark,\n  Popover: popoverDark,\n  Popselect: popselectDark,\n  Progress: progressDark,\n  QrCode: qrcodeDark,\n  Radio: radioDark,\n  Rate: rateDark,\n  Result: resultDark,\n  Row: rowDark,\n  Scrollbar: scrollbarDark,\n  Select: selectDark,\n  Skeleton: skeletonDark,\n  Slider: sliderDark,\n  Space: spaceDark,\n  Spin: spinDark,\n  Statistic: statisticDark,\n  Steps: stepsDark,\n  Switch: switchDark,\n  Table: tableDark,\n  Tabs: tabsDark,\n  Tag: tagDark,\n  Thing: thingDark,\n  TimePicker: timePickerDark,\n  Timeline: timelineDark,\n  Tooltip: tooltipDark,\n  Transfer: transferDark,\n  Tree: treeDark,\n  TreeSelect: treeSelectDark,\n  Typography: typographyDark,\n  Upload: uploadDark,\n  Watermark: watermarkDark,\n  Split: splitDark,\n  FloatButton: floatButtonDark,\n  FloatButtonGroup: floatButtonGroupDark,\n  Marquee: marqueeDark\n}\n"
  },
  {
    "path": "src/themes/index.ts",
    "content": "export { darkTheme } from './dark'\nexport { lightTheme } from './light'\nexport { createTheme } from './utils'\n"
  },
  {
    "path": "src/themes/interface.ts",
    "content": "import type { GlobalTheme } from '../config-provider'\n\nexport type BuiltInGlobalTheme = Omit<\n  Required<GlobalTheme>,\n  'InternalSelectMenu' | 'InternalSelection'\n>\n"
  },
  {
    "path": "src/themes/light.ts",
    "content": "import type { BuiltInGlobalTheme } from './interface'\nimport { scrollbarLight } from '../_internal/scrollbar/styles'\n// The file is for internal usage, do not export it, since all the components\n// have default light theme.\nimport { commonLight } from '../_styles/common'\nimport { alertLight } from '../alert/styles'\nimport { anchorLight } from '../anchor/styles'\nimport { autoCompleteLight } from '../auto-complete/styles'\nimport { avatarGroupLight } from '../avatar-group/styles'\nimport { avatarLight } from '../avatar/styles'\nimport { backTopLight } from '../back-top/styles'\nimport { badgeLight } from '../badge/styles'\nimport { breadcrumbLight } from '../breadcrumb/styles'\nimport { buttonGroupLight } from '../button-group/styles'\nimport { buttonLight } from '../button/styles'\nimport { calendarLight } from '../calendar/styles'\nimport { cardLight } from '../card/styles'\nimport { carouselLight } from '../carousel/styles'\nimport { cascaderLight } from '../cascader/styles'\nimport { checkboxLight } from '../checkbox/styles'\nimport { codeLight } from '../code/styles'\nimport { collapseTransitionLight } from '../collapse-transition/styles'\nimport { collapseLight } from '../collapse/styles'\nimport { colorPickerLight } from '../color-picker/styles'\nimport { dataTableLight } from '../data-table/styles'\nimport { datePickerLight } from '../date-picker/styles'\nimport { descriptionsLight } from '../descriptions/styles'\nimport { dialogLight } from '../dialog/styles'\nimport { dividerLight } from '../divider/styles'\nimport { drawerLight } from '../drawer/styles'\nimport { dropdownLight } from '../dropdown/styles'\nimport { dynamicInputLight } from '../dynamic-input/styles'\nimport { dynamicTagsLight } from '../dynamic-tags/styles'\nimport { elementLight } from '../element/styles'\nimport { ellipsisLight } from '../ellipsis/styles'\nimport { emptyLight } from '../empty/styles'\nimport { equationLight } from '../equation/styles'\nimport { flexLight } from '../flex/styles'\nimport { floatButtonGroupLight } from '../float-button-group/styles'\nimport { floatButtonLight } from '../float-button/styles'\nimport { formLight } from '../form/styles'\nimport { gradientTextLight } from '../gradient-text/styles'\nimport { heatmapLight } from '../heatmap/styles'\nimport { iconWrapperLight } from '../icon-wrapper/styles'\nimport { iconLight } from '../icon/styles'\nimport { imageLight } from '../image/styles'\nimport { inputNumberLight } from '../input-number/styles'\nimport { inputOtpLight } from '../input-otp/styles'\nimport { inputLight } from '../input/styles'\nimport { layoutLight } from '../layout/styles'\nimport { rowLight } from '../legacy-grid/styles'\nimport { legacyTransferLight } from '../legacy-transfer/styles'\nimport { listLight } from '../list/styles'\nimport { loadingBarLight } from '../loading-bar/styles'\nimport { logLight } from '../log/styles'\nimport { marqueeLight } from '../marquee/styles'\nimport { mentionLight } from '../mention/styles'\nimport { menuLight } from '../menu/styles'\nimport { messageLight } from '../message/styles'\nimport { modalLight } from '../modal/styles'\nimport { notificationLight } from '../notification/styles'\nimport { pageHeaderLight } from '../page-header/styles'\nimport { paginationLight } from '../pagination/styles'\nimport { popconfirmLight } from '../popconfirm/styles'\nimport { popoverLight } from '../popover/styles'\nimport { popselectLight } from '../popselect/styles'\nimport { progressLight } from '../progress/styles'\nimport { qrcodeLight } from '../qr-code/styles'\nimport { radioLight } from '../radio/styles'\nimport { rateLight } from '../rate/styles'\nimport { resultLight } from '../result/styles'\nimport { selectLight } from '../select/styles'\nimport { skeletonLight } from '../skeleton/styles'\nimport { sliderLight } from '../slider/styles'\nimport { spaceLight } from '../space/styles'\nimport { spinLight } from '../spin/styles'\nimport { splitLight } from '../split/styles'\nimport { statisticLight } from '../statistic/styles'\nimport { stepsLight } from '../steps/styles'\nimport { switchLight } from '../switch/styles'\nimport { tableLight } from '../table/styles'\nimport { tabsLight } from '../tabs/styles'\nimport { tagLight } from '../tag/styles'\nimport { thingLight } from '../thing/styles'\nimport { timePickerLight } from '../time-picker/styles'\nimport { timelineLight } from '../timeline/styles'\nimport { tooltipLight } from '../tooltip/styles'\nimport { transferLight } from '../transfer/styles'\nimport { treeSelectLight } from '../tree-select/styles'\nimport { treeLight } from '../tree/styles'\nimport { typographyLight } from '../typography/styles'\nimport { uploadLight } from '../upload/styles'\nimport { watermarkLight } from '../watermark/styles'\n\nexport const lightTheme: BuiltInGlobalTheme = {\n  name: 'light',\n  common: commonLight,\n  Alert: alertLight,\n  Anchor: anchorLight,\n  AutoComplete: autoCompleteLight,\n  Avatar: avatarLight,\n  AvatarGroup: avatarGroupLight,\n  BackTop: backTopLight,\n  Badge: badgeLight,\n  Breadcrumb: breadcrumbLight,\n  Button: buttonLight,\n  ButtonGroup: buttonGroupLight,\n  Calendar: calendarLight,\n  Card: cardLight,\n  Carousel: carouselLight,\n  Cascader: cascaderLight,\n  Checkbox: checkboxLight,\n  Code: codeLight,\n  Collapse: collapseLight,\n  CollapseTransition: collapseTransitionLight,\n  ColorPicker: colorPickerLight,\n  DataTable: dataTableLight,\n  DatePicker: datePickerLight,\n  Descriptions: descriptionsLight,\n  Dialog: dialogLight,\n  Divider: dividerLight,\n  Drawer: drawerLight,\n  Dropdown: dropdownLight,\n  DynamicInput: dynamicInputLight,\n  DynamicTags: dynamicTagsLight,\n  Element: elementLight,\n  Empty: emptyLight,\n  Equation: equationLight,\n  Ellipsis: ellipsisLight,\n  Flex: flexLight,\n  Form: formLight,\n  GradientText: gradientTextLight,\n  Heatmap: heatmapLight,\n  Icon: iconLight,\n  IconWrapper: iconWrapperLight,\n  Image: imageLight,\n  Input: inputLight,\n  InputNumber: inputNumberLight,\n  InputOtp: inputOtpLight,\n  Layout: layoutLight,\n  LegacyTransfer: legacyTransferLight,\n  List: listLight,\n  LoadingBar: loadingBarLight,\n  Log: logLight,\n  Menu: menuLight,\n  Mention: mentionLight,\n  Message: messageLight,\n  Modal: modalLight,\n  Notification: notificationLight,\n  PageHeader: pageHeaderLight,\n  Pagination: paginationLight,\n  Popconfirm: popconfirmLight,\n  Popover: popoverLight,\n  Popselect: popselectLight,\n  Progress: progressLight,\n  QrCode: qrcodeLight,\n  Radio: radioLight,\n  Rate: rateLight,\n  Row: rowLight,\n  Result: resultLight,\n  Scrollbar: scrollbarLight,\n  Skeleton: skeletonLight,\n  Select: selectLight,\n  Slider: sliderLight,\n  Space: spaceLight,\n  Spin: spinLight,\n  Statistic: statisticLight,\n  Steps: stepsLight,\n  Switch: switchLight,\n  Table: tableLight,\n  Tabs: tabsLight,\n  Tag: tagLight,\n  Thing: thingLight,\n  TimePicker: timePickerLight,\n  Timeline: timelineLight,\n  Tooltip: tooltipLight,\n  Transfer: transferLight,\n  Tree: treeLight,\n  TreeSelect: treeSelectLight,\n  Typography: typographyLight,\n  Upload: uploadLight,\n  Watermark: watermarkLight,\n  Split: splitLight,\n  FloatButton: floatButtonLight,\n  FloatButtonGroup: floatButtonGroupLight,\n  Marquee: marqueeLight\n}\n"
  },
  {
    "path": "src/themes/utils.ts",
    "content": "import type { GlobalTheme } from '../config-provider'\n\ntype ComponentKey = Exclude<keyof GlobalTheme, 'name'>\ntype ComponentThemes = Array<Exclude<GlobalTheme[ComponentKey], undefined>>\n\nexport function createTheme(\n  name: string,\n  componentThemes: ComponentThemes\n): GlobalTheme\nexport function createTheme(componentThemes: ComponentThemes): GlobalTheme\nexport function createTheme(\n  name: string | ComponentThemes,\n  componentThemes?: ComponentThemes\n): GlobalTheme {\n  const nameIsString = typeof name === 'string'\n  const theme: GlobalTheme = {\n    name: nameIsString ? name : 'customized-theme'\n  }\n  if (nameIsString) {\n    if (componentThemes) {\n      for (const cTheme of componentThemes) {\n        theme[cTheme.name] = cTheme as any\n      }\n    }\n  }\n  else {\n    for (const cTheme of name) {\n      theme[cTheme.name] = cTheme as any\n    }\n  }\n  return theme\n}\n"
  },
  {
    "path": "src/thing/demos/enUS/basic.demo.vue",
    "content": "<markdown>\n# Basic\n\nThing provides many slots to custom.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { CashOutline as CashIcon } from '@vicons/ionicons5'\nimport { ref } from 'vue'\n\nconst avatar = ref(true)\nconst header = ref(true)\nconst headerExtra = ref(true)\nconst description = ref(true)\nconst footer = ref(true)\nconst action = ref(true)\n</script>\n\n<template>\n  <n-row>\n    <n-col :span=\"12\">\n      <n-checkbox v-model:checked=\"avatar\">\n        Avatar\n      </n-checkbox>\n    </n-col>\n    <n-col :span=\"12\">\n      <n-checkbox v-model:checked=\"action\">\n        Action\n      </n-checkbox>\n    </n-col>\n  </n-row>\n  <n-row>\n    <n-col :span=\"12\">\n      <n-checkbox v-model:checked=\"header\">\n        Header\n      </n-checkbox>\n    </n-col>\n    <n-col :span=\"12\">\n      <n-checkbox v-model:checked=\"headerExtra\">\n        Header Extra\n      </n-checkbox>\n    </n-col>\n  </n-row>\n  <n-row>\n    <n-col :span=\"12\">\n      <n-checkbox v-model:checked=\"description\">\n        Description\n      </n-checkbox>\n    </n-col>\n    <n-col :span=\"12\">\n      <n-checkbox v-model:checked=\"footer\">\n        Footer\n      </n-checkbox>\n    </n-col>\n  </n-row>\n  <n-divider />\n  <n-thing>\n    <template v-if=\"avatar\" #avatar>\n      <n-avatar>\n        <n-icon>\n          <CashIcon />\n        </n-icon>\n      </n-avatar>\n    </template>\n    <template v-if=\"header\" #header>\n      Money\n    </template>\n    <template v-if=\"headerExtra\" #header-extra>\n      <n-button circle size=\"small\">\n        <template #icon>\n          <CashIcon />\n        </template>\n      </n-button>\n    </template>\n    <template v-if=\"description\" #description>\n      Description\n    </template>\n    Money is any item or verifiable record that is generally accepted as payment\n    for goods and services and repayment of debts, such as taxes, in a\n    particular country or socio-economic context.\n    <template v-if=\"footer\" #footer>\n      Footer\n    </template>\n    <template v-if=\"action\" #action>\n      <n-space>\n        <n-button size=\"small\">\n          <template #icon>\n            <n-icon>\n              <CashIcon />\n            </n-icon>\n          </template>\n          1$\n        </n-button>\n        <n-button size=\"small\">\n          <template #icon>\n            <n-icon>\n              <CashIcon />\n            </n-icon>\n          </template>\n          10$\n        </n-button>\n        <n-button size=\"small\">\n          <template #icon>\n            <n-icon>\n              <CashIcon />\n            </n-icon>\n          </template>\n          100$\n        </n-button>\n      </n-space>\n    </template>\n  </n-thing>\n</template>\n"
  },
  {
    "path": "src/thing/demos/enUS/indent.demo.vue",
    "content": "<markdown>\n# Content indented\n\nContent can be indented after avatar.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { CashOutline as CashIcon } from '@vicons/ionicons5'\nimport { ref } from 'vue'\n\nconst avatar = ref(true)\nconst header = ref(true)\nconst headerExtra = ref(true)\nconst description = ref(true)\nconst footer = ref(true)\nconst action = ref(true)\n</script>\n\n<template>\n  <n-row>\n    <n-col :span=\"12\">\n      <n-checkbox v-model:checked=\"avatar\">\n        Avatar\n      </n-checkbox>\n    </n-col>\n    <n-col :span=\"12\">\n      <n-checkbox v-model:checked=\"action\">\n        Action\n      </n-checkbox>\n    </n-col>\n  </n-row>\n  <n-row>\n    <n-col :span=\"12\">\n      <n-checkbox v-model:checked=\"header\">\n        Header\n      </n-checkbox>\n    </n-col>\n    <n-col :span=\"12\">\n      <n-checkbox v-model:checked=\"headerExtra\">\n        Header Extra\n      </n-checkbox>\n    </n-col>\n  </n-row>\n  <n-row>\n    <n-col :span=\"12\">\n      <n-checkbox v-model:checked=\"description\">\n        Description\n      </n-checkbox>\n    </n-col>\n    <n-col :span=\"12\">\n      <n-checkbox v-model:checked=\"footer\">\n        Footer\n      </n-checkbox>\n    </n-col>\n  </n-row>\n  <n-divider />\n  <n-thing content-indented>\n    <template v-if=\"avatar\" #avatar>\n      <n-avatar>\n        <n-icon>\n          <CashIcon />\n        </n-icon>\n      </n-avatar>\n    </template>\n    <template v-if=\"header\" #header>\n      Money\n    </template>\n    <template v-if=\"headerExtra\" #header-extra>\n      <n-button circle size=\"small\">\n        <template #icon>\n          <CashIcon />\n        </template>\n      </n-button>\n    </template>\n    <template v-if=\"description\" #description>\n      Description\n    </template>\n    Money is any item or verifiable record that is generally accepted as payment\n    for goods and services and repayment of debts, such as taxes, in a\n    particular country or socio-economic context.\n    <template v-if=\"footer\" #footer>\n      Footer\n    </template>\n    <template v-if=\"action\" #action>\n      <n-space>\n        <n-button size=\"small\">\n          <template #icon>\n            <n-icon>\n              <CashIcon />\n            </n-icon>\n          </template>\n          1$\n        </n-button>\n        <n-button size=\"small\">\n          <template #icon>\n            <n-icon>\n              <CashIcon />\n            </n-icon>\n          </template>\n          10$\n        </n-button>\n        <n-button size=\"small\">\n          <template #icon>\n            <n-icon>\n              <CashIcon />\n            </n-icon>\n          </template>\n          100$\n        </n-button>\n      </n-space>\n    </template>\n  </n-thing>\n</template>\n"
  },
  {
    "path": "src/thing/demos/enUS/index.demo-entry.md",
    "content": "# Thing\n\nWhen you want to describe a thing, use thing. If you find it doesn't fit you demand, write one by yourself.\n\nI wish there is a way to build all kinds of frequently used layout inside a component. It takes me some time to figure out that the component already exist, the brower itself.\n\n## Demos\n\n```demo\nbasic.vue\nindent.vue\n```\n\n## API\n\n### Thing Props\n\n| Name | Type | Default | Description | Version |\n| --- | --- | --- | --- | --- |\n| content-indented | `boolean` | `false` | Whether to enable content indentation. |\n| content | `string` | `undefined` | Content area. |\n| content-class | `string` | `undefined` | Content area class. | 2.36.0 |\n| content-style | `string \\| Object` | `undefined` | Content area style. | 2.32.2 |\n| description | `string` | `undefined` | Description information. |\n| description-class | `string` | `undefined` | Description area class. | 2.36.0 |\n| description-style | `string \\| Object` | `undefined` | Description area style. | 2.32.2 |\n| title-extra | `string` | `undefined` | Additional information for the title. |\n| title | `string` | `undefined` | Title information. |\n\n### Thing Slots\n\n| Name         | Parameters | Description          |\n| ------------ | ---------- | -------------------- |\n| action       | `()`       | Action's slot.       |\n| avatar       | `()`       | Avatar's slot.       |\n| default      | `()`       | Content's slot.      |\n| description  | `()`       | Description's slot.  |\n| footer       | `()`       | Footer's slot.       |\n| header-extra | `()`       | Header extra's slot. |\n| header       | `()`       | Header's slot.       |\n"
  },
  {
    "path": "src/thing/demos/zhCN/basic.demo.vue",
    "content": "<markdown>\n# 基础用法\n\nThing 提供了很多 slot 来定制。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { CashOutline as CashIcon } from '@vicons/ionicons5'\nimport { ref } from 'vue'\n\nconst avatar = ref(true)\nconst header = ref(true)\nconst headerExtra = ref(true)\nconst description = ref(true)\nconst footer = ref(true)\nconst action = ref(true)\n</script>\n\n<template>\n  <n-row>\n    <n-col :span=\"12\">\n      <n-checkbox v-model:checked=\"avatar\">\n        头像\n      </n-checkbox>\n    </n-col>\n    <n-col :span=\"12\">\n      <n-checkbox v-model:checked=\"action\">\n        操作\n      </n-checkbox>\n    </n-col>\n  </n-row>\n  <n-row>\n    <n-col :span=\"12\">\n      <n-checkbox v-model:checked=\"header\">\n        标题\n      </n-checkbox>\n    </n-col>\n    <n-col :span=\"12\">\n      <n-checkbox v-model:checked=\"headerExtra\">\n        标题附加信息\n      </n-checkbox>\n    </n-col>\n  </n-row>\n  <n-row>\n    <n-col :span=\"12\">\n      <n-checkbox v-model:checked=\"description\">\n        描述\n      </n-checkbox>\n    </n-col>\n    <n-col :span=\"12\">\n      <n-checkbox v-model:checked=\"footer\">\n        底部\n      </n-checkbox>\n    </n-col>\n  </n-row>\n  <n-divider />\n  <n-thing>\n    <template v-if=\"avatar\" #avatar>\n      <n-avatar>\n        <n-icon>\n          <CashIcon />\n        </n-icon>\n      </n-avatar>\n    </template>\n    <template v-if=\"header\" #header>\n      货币\n    </template>\n    <template v-if=\"headerExtra\" #header-extra>\n      <n-button circle size=\"small\">\n        <template #icon>\n          <CashIcon />\n        </template>\n      </n-button>\n    </template>\n    <template v-if=\"description\" #description>\n      描述\n    </template>\n    货币是为了提高交易效率而用于交换的中介商品。货币有多种形式，如贝壳粮食等自然物、金属纸张等加工品、银行卡信用卡等磁条卡、移动支付加密货币等APP。\n    <template v-if=\"footer\" #footer>\n      尾部\n    </template>\n    <template v-if=\"action\" #action>\n      <n-space>\n        <n-button size=\"small\">\n          <template #icon>\n            <n-icon>\n              <CashIcon />\n            </n-icon>\n          </template>\n          1 块钱\n        </n-button>\n        <n-button size=\"small\">\n          <template #icon>\n            <n-icon>\n              <CashIcon />\n            </n-icon>\n          </template>\n          10 块钱\n        </n-button>\n        <n-button size=\"small\">\n          <template #icon>\n            <n-icon>\n              <CashIcon />\n            </n-icon>\n          </template>\n          100 块钱\n        </n-button>\n      </n-space>\n    </template>\n  </n-thing>\n</template>\n"
  },
  {
    "path": "src/thing/demos/zhCN/indent.demo.vue",
    "content": "<markdown>\n# 内容缩进\n\n内容可以缩进到头像旁边。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { CashOutline as CashIcon } from '@vicons/ionicons5'\nimport { ref } from 'vue'\n\nconst avatar = ref(true)\nconst header = ref(true)\nconst headerExtra = ref(true)\nconst description = ref(true)\nconst footer = ref(true)\nconst action = ref(true)\n</script>\n\n<template>\n  <n-row>\n    <n-col :span=\"12\">\n      <n-checkbox v-model:checked=\"avatar\">\n        头像\n      </n-checkbox>\n    </n-col>\n    <n-col :span=\"12\">\n      <n-checkbox v-model:checked=\"action\">\n        操作\n      </n-checkbox>\n    </n-col>\n  </n-row>\n  <n-row>\n    <n-col :span=\"12\">\n      <n-checkbox v-model:checked=\"header\">\n        标题\n      </n-checkbox>\n    </n-col>\n    <n-col :span=\"12\">\n      <n-checkbox v-model:checked=\"headerExtra\">\n        标题附加信息\n      </n-checkbox>\n    </n-col>\n  </n-row>\n  <n-row>\n    <n-col :span=\"12\">\n      <n-checkbox v-model:checked=\"description\">\n        描述\n      </n-checkbox>\n    </n-col>\n    <n-col :span=\"12\">\n      <n-checkbox v-model:checked=\"footer\">\n        底部\n      </n-checkbox>\n    </n-col>\n  </n-row>\n  <n-divider />\n  <n-thing content-indented>\n    <template v-if=\"avatar\" #avatar>\n      <n-avatar>\n        <n-icon>\n          <CashIcon />\n        </n-icon>\n      </n-avatar>\n    </template>\n    <template v-if=\"header\" #header>\n      货币\n    </template>\n    <template v-if=\"headerExtra\" #header-extra>\n      <n-button circle size=\"small\">\n        <template #icon>\n          <CashIcon />\n        </template>\n      </n-button>\n    </template>\n    <template v-if=\"description\" #description>\n      描述\n    </template>\n    货币是为了提高交易效率而用于交换的中介商品。货币有多种形式，如贝壳粮食等自然物、金属纸张等加工品、银行卡信用卡等磁条卡、移动支付加密货币等APP。\n    <template v-if=\"footer\" #footer>\n      尾部\n    </template>\n    <template v-if=\"action\" #action>\n      <n-space>\n        <n-button size=\"small\">\n          <template #icon>\n            <n-icon>\n              <CashIcon />\n            </n-icon>\n          </template>\n          1 块钱\n        </n-button>\n        <n-button size=\"small\">\n          <template #icon>\n            <n-icon>\n              <CashIcon />\n            </n-icon>\n          </template>\n          10 块钱\n        </n-button>\n        <n-button size=\"small\">\n          <template #icon>\n            <n-icon>\n              <CashIcon />\n            </n-icon>\n          </template>\n          100 块钱\n        </n-button>\n      </n-space>\n    </template>\n  </n-thing>\n</template>\n"
  },
  {
    "path": "src/thing/demos/zhCN/index.demo-entry.md",
    "content": "# 东西 Thing\n\n当你想要描述一个东西，使用 Thing。如果你觉得这个组件不能满足你的需求，可以自己写一个。\n\n我其实很想把所有常用的布局都装到一个组件里，我想了很久，感觉这个组件确实已经存在了，那就是浏览器本身。\n\n## 演示\n\n```demo\nbasic.vue\nindent.vue\nrtl-debug.vue\n```\n\n## API\n\n### Thing Props\n\n| 名称 | 类型 | 默认值 | 说明 | 版本 |\n| --- | --- | --- | --- | --- |\n| content-indented | `boolean` | `false` | 是否启用内容缩进 |  |\n| content | `string` | `undefined` | 内容区域 |  |\n| content-class | `string` | `undefined` | 内容区域类名 | 2.36.0 |\n| content-style | `string \\| Object` | `undefined` | 内容区域样式 | 2.32.2 |\n| description | `string` | `undefined` | 描述信息 |  |\n| description-class | `string` | `undefined` | 描述信息区域类名 | 2.36.0 |\n| description-style | `string \\| Object` | `undefined` | 描述信息区域样式 | 2.32.2 |\n| title-extra | `string` | `undefined` | 标题的附加信息 |  |\n| title | `string` | `undefined` | 标题 |  |\n\n### Thing Slots\n\n| 名称         | 参数 | 说明             |\n| ------------ | ---- | ---------------- |\n| action       | `()` | 操作区域插槽     |\n| avatar       | `()` | 头像区域插槽     |\n| default      | `()` | 内容区域插槽     |\n| description  | `()` | 描述区域插槽     |\n| footer       | `()` | 尾部区域插槽     |\n| header-extra | `()` | 头部附加区域插槽 |\n| header       | `()` | 头部区域插槽     |\n"
  },
  {
    "path": "src/thing/demos/zhCN/rtl-debug.demo.vue",
    "content": "<markdown>\n# Rtl Debug\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { CashOutline as CashIcon } from '@vicons/ionicons5'\nimport { unstableRowRtl, unstableThingRtl } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst rtlEnabled = ref(false)\nconst rtlStyles = [unstableThingRtl, unstableRowRtl]\nconst avatar = ref(true)\nconst header = ref(true)\nconst headerExtra = ref(true)\nconst description = ref(true)\nconst footer = ref(true)\nconst action = ref(true)\n</script>\n\n<template>\n  <n-space vertical>\n    <n-space><n-switch v-model:value=\"rtlEnabled\" />Rtl</n-space>\n    <n-config-provider :rtl=\"rtlEnabled ? rtlStyles : undefined\">\n      <n-row>\n        <n-col :span=\"12\">\n          <n-checkbox v-model:checked=\"avatar\">\n            Avatar\n          </n-checkbox>\n        </n-col>\n        <n-col :span=\"12\">\n          <n-checkbox v-model:checked=\"action\">\n            Action\n          </n-checkbox>\n        </n-col>\n      </n-row>\n      <n-row>\n        <n-col :span=\"12\">\n          <n-checkbox v-model:checked=\"header\">\n            Header\n          </n-checkbox>\n        </n-col>\n        <n-col :span=\"12\">\n          <n-checkbox v-model:checked=\"headerExtra\">\n            Header Extra\n          </n-checkbox>\n        </n-col>\n      </n-row>\n      <n-row>\n        <n-col :span=\"12\">\n          <n-checkbox v-model:checked=\"description\">\n            Description\n          </n-checkbox>\n        </n-col>\n        <n-col :span=\"12\">\n          <n-checkbox v-model:checked=\"footer\">\n            Footer\n          </n-checkbox>\n        </n-col>\n      </n-row>\n      <n-divider />\n      <n-thing>\n        <template v-if=\"avatar\" #avatar>\n          <n-avatar>\n            <n-icon>\n              <CashIcon />\n            </n-icon>\n          </n-avatar>\n        </template>\n        <template v-if=\"header\" #header>\n          货币\n        </template>\n        <template v-if=\"headerExtra\" #header-extra>\n          <n-button circle size=\"small\">\n            <template #icon>\n              <CashIcon />\n            </template>\n          </n-button>\n        </template>\n        <template v-if=\"description\" #description>\n          描述\n        </template>\n        货币是为了提高交易效率而用于交换的中介商品。货币有多种形式，如贝壳粮食等自然物、金属纸张等加工品、银行卡信用卡等磁条卡、移动支付加密货币等APP。\n        <template v-if=\"footer\" #footer>\n          尾部\n        </template>\n        <template v-if=\"action\" #action>\n          <n-space>\n            <n-button size=\"small\">\n              <template #icon>\n                <n-icon>\n                  <CashIcon />\n                </n-icon>\n              </template>\n              1 块钱\n            </n-button>\n            <n-button size=\"small\">\n              <template #icon>\n                <n-icon>\n                  <CashIcon />\n                </n-icon>\n              </template>\n              10 块钱\n            </n-button>\n            <n-button size=\"small\">\n              <template #icon>\n                <n-icon>\n                  <CashIcon />\n                </n-icon>\n              </template>\n              100 块钱\n            </n-button>\n          </n-space>\n        </template>\n      </n-thing>\n    </n-config-provider>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/thing/index.ts",
    "content": "export { default as NThing, thingProps } from './src/Thing'\nexport type { ThingProps, ThingSlots } from './src/Thing'\n"
  },
  {
    "path": "src/thing/src/Thing.tsx",
    "content": "import type { CSSProperties, PropType, SlotsType, VNode } from 'vue'\nimport type { ThemeProps } from '../../_mixins'\nimport type { ExtractPublicPropTypes } from '../../_utils'\nimport type { ThingTheme } from '../styles'\nimport { computed, defineComponent, Fragment, h } from 'vue'\nimport { useConfig, useRtl, useTheme, useThemeClass } from '../../_mixins'\nimport { thingLight } from '../styles'\nimport style from './styles/index.cssr'\n\nexport const thingProps = {\n  ...(useTheme.props as ThemeProps<ThingTheme>),\n  title: String,\n  titleExtra: String,\n  description: String,\n  descriptionClass: String,\n  descriptionStyle: [String, Object] as PropType<string | CSSProperties>,\n  content: String,\n  contentClass: String,\n  contentStyle: [String, Object] as PropType<string | CSSProperties>,\n  contentIndented: Boolean\n}\n\nexport type ThingProps = ExtractPublicPropTypes<typeof thingProps>\n\nexport interface ThingSlots {\n  action?: () => VNode[]\n  avatar?: () => VNode[]\n  default?: () => VNode[]\n  description?: () => VNode[]\n  footer?: () => VNode[]\n  'header-extra'?: () => VNode[]\n  header?: () => VNode[]\n}\n\nexport default defineComponent({\n  name: 'Thing',\n  props: thingProps,\n  slots: Object as SlotsType<ThingSlots>,\n  setup(props, { slots }) {\n    const { mergedClsPrefixRef, inlineThemeDisabled, mergedRtlRef }\n      = useConfig(props)\n    const themeRef = useTheme(\n      'Thing',\n      '-thing',\n      style,\n      thingLight,\n      props,\n      mergedClsPrefixRef\n    )\n    const rtlEnabledRef = useRtl('Thing', mergedRtlRef, mergedClsPrefixRef)\n    const cssVarsRef = computed(() => {\n      const {\n        self: { titleTextColor, textColor, titleFontWeight, fontSize },\n        common: { cubicBezierEaseInOut }\n      } = themeRef.value\n      return {\n        '--n-bezier': cubicBezierEaseInOut,\n        '--n-font-size': fontSize,\n        '--n-text-color': textColor,\n        '--n-title-font-weight': titleFontWeight,\n        '--n-title-text-color': titleTextColor\n      }\n    })\n    const themeClassHandle = inlineThemeDisabled\n      ? useThemeClass('thing', undefined, cssVarsRef, props)\n      : undefined\n\n    return () => {\n      const { value: mergedClsPrefix } = mergedClsPrefixRef\n      const rtlEnabled = rtlEnabledRef ? rtlEnabledRef.value : false\n      themeClassHandle?.onRender?.()\n      return (\n        <div\n          class={[\n            `${mergedClsPrefix}-thing`,\n            themeClassHandle?.themeClass,\n            rtlEnabled && `${mergedClsPrefix}-thing--rtl`\n          ]}\n          style={\n            inlineThemeDisabled\n              ? undefined\n              : (cssVarsRef.value as CSSProperties)\n          }\n        >\n          {slots.avatar && props.contentIndented ? (\n            <div class={`${mergedClsPrefix}-thing-avatar`}>\n              {slots.avatar()}\n            </div>\n          ) : null}\n          <div class={`${mergedClsPrefix}-thing-main`}>\n            {!props.contentIndented\n              && (slots.header\n                || props.title\n                || slots['header-extra']\n                || props.titleExtra\n                || slots.avatar) ? (\n                  <div class={`${mergedClsPrefix}-thing-avatar-header-wrapper`}>\n                    {slots.avatar ? (\n                      <div class={`${mergedClsPrefix}-thing-avatar`}>\n                        {slots.avatar()}\n                      </div>\n                    ) : null}\n                    {slots.header\n                      || props.title\n                      || slots['header-extra']\n                      || props.titleExtra ? (\n                          <div class={`${mergedClsPrefix}-thing-header-wrapper`}>\n                            <div class={`${mergedClsPrefix}-thing-header`}>\n                              {slots.header || props.title ? (\n                                <div class={`${mergedClsPrefix}-thing-header__title`}>\n                                  {slots.header ? slots.header() : props.title}\n                                </div>\n                              ) : null}\n                              {slots['header-extra'] || props.titleExtra ? (\n                                <div class={`${mergedClsPrefix}-thing-header__extra`}>\n                                  {slots['header-extra']\n                                    ? slots['header-extra']()\n                                    : props.titleExtra}\n                                </div>\n                              ) : null}\n                            </div>\n                            {slots.description || props.description ? (\n                              <div\n                                class={[\n                                  `${mergedClsPrefix}-thing-main__description`,\n                                  props.descriptionClass\n                                ]}\n                                style={props.descriptionStyle}\n                              >\n                                {slots.description\n                                  ? slots.description()\n                                  : props.description}\n                              </div>\n                            ) : null}\n                          </div>\n                        ) : null}\n                  </div>\n                ) : (\n                  <>\n                    {slots.header\n                      || props.title\n                      || slots['header-extra']\n                      || props.titleExtra ? (\n                          <div class={`${mergedClsPrefix}-thing-header`}>\n                            {slots.header || props.title ? (\n                              <div class={`${mergedClsPrefix}-thing-header__title`}>\n                                {slots.header ? slots.header() : props.title}\n                              </div>\n                            ) : null}\n                            {slots['header-extra'] || props.titleExtra ? (\n                              <div class={`${mergedClsPrefix}-thing-header__extra`}>\n                                {slots['header-extra']\n                                  ? slots['header-extra']()\n                                  : props.titleExtra}\n                              </div>\n                            ) : null}\n                          </div>\n                        ) : null}\n                    {slots.description || props.description ? (\n                      <div\n                        class={[\n                          `${mergedClsPrefix}-thing-main__description`,\n                          props.descriptionClass\n                        ]}\n                        style={props.descriptionStyle}\n                      >\n                        {slots.description\n                          ? slots.description()\n                          : props.description}\n                      </div>\n                    ) : null}\n                  </>\n                )}\n            {slots.default || props.content ? (\n              <div\n                class={[\n                  `${mergedClsPrefix}-thing-main__content`,\n                  props.contentClass\n                ]}\n                style={props.contentStyle}\n              >\n                {slots.default ? slots.default() : props.content}\n              </div>\n            ) : null}\n            {slots.footer ? (\n              <div class={`${mergedClsPrefix}-thing-main__footer`}>\n                {slots.footer()}\n              </div>\n            ) : null}\n            {slots.action ? (\n              <div class={`${mergedClsPrefix}-thing-main__action`}>\n                {slots.action()}\n              </div>\n            ) : null}\n          </div>\n        </div>\n      )\n    }\n  }\n})\n"
  },
  {
    "path": "src/thing/src/styles/index.cssr.ts",
    "content": "import { c, cB, cE } from '../../../_utils/cssr'\n\n// vars:\n// --n-bezier\n// --n-font-size\n// --n-text-color\n// --n-title-font-weight\n// --n-title-text-color\nexport default cB('thing', `\n  display: flex;\n  transition: color .3s var(--n-bezier);\n  font-size: var(--n-font-size);\n  color: var(--n-text-color);\n`, [\n  cB('thing-avatar', `\n    margin-right: 12px;\n    margin-top: 2px;\n  `),\n  cB('thing-avatar-header-wrapper', `\n    display: flex;\n    flex-wrap: nowrap;\n  `, [\n    cB('thing-header-wrapper', `\n      flex: 1;\n    `)\n  ]),\n  cB('thing-main', `\n    flex-grow: 1;\n  `, [\n    cB('thing-header', `\n      display: flex;\n      margin-bottom: 4px;\n      justify-content: space-between;\n      align-items: center;\n    `, [\n      cE('title', `\n        font-size: 16px;\n        font-weight: var(--n-title-font-weight);\n        transition: color .3s var(--n-bezier);\n        color: var(--n-title-text-color);\n      `)\n    ]),\n    cE('description', [\n      c('&:not(:last-child)', `\n        margin-bottom: 4px;\n      `)\n    ]),\n    cE('content', [\n      c('&:not(:first-child)', `\n        margin-top: 12px;\n      `)\n    ]),\n    cE('footer', [\n      c('&:not(:first-child)', `\n        margin-top: 12px;\n      `)\n    ]),\n    cE('action', [\n      c('&:not(:first-child)', `\n        margin-top: 12px;\n      `)\n    ])\n  ])\n])\n"
  },
  {
    "path": "src/thing/src/styles/rtl.cssr.ts",
    "content": "import { cB, cM } from '../../../_utils/cssr'\n\nexport default cB('thing', [\n  cM('rtl', `\n    direction: rtl;\n    text-align: right;\n  `, [\n    cB('thing-avatar', `\n      margin-left: 12px;\n      margin-right: 0;\n    `)\n  ])\n])\n"
  },
  {
    "path": "src/thing/styles/dark.ts",
    "content": "import type { ThingTheme } from './light'\nimport { commonDark } from '../../_styles/common'\nimport { self } from './light'\n\nconst thingDark: ThingTheme = {\n  name: 'Thing',\n  common: commonDark,\n  self\n}\n\nexport default thingDark\n"
  },
  {
    "path": "src/thing/styles/index.ts",
    "content": "export { default as thingDark } from './dark'\nexport { default as thingLight } from './light'\nexport type { ThingTheme, ThingThemeVars } from './light'\nexport { thingRtl } from './rtl'\n"
  },
  {
    "path": "src/thing/styles/light.ts",
    "content": "import type { Theme } from '../../_mixins'\nimport type { ThemeCommonVars } from '../../_styles/common'\nimport { commonLight } from '../../_styles/common'\n\nexport function self(vars: ThemeCommonVars) {\n  const { textColor1, textColor2, fontWeightStrong, fontSize } = vars\n  return {\n    fontSize,\n    titleTextColor: textColor1,\n    textColor: textColor2,\n    titleFontWeight: fontWeightStrong\n  }\n}\n\nexport type ThingThemeVars = ReturnType<typeof self>\n\nconst thingLight: Theme<'Thing', ThingThemeVars> = {\n  name: 'Thing',\n  common: commonLight,\n  self\n}\n\nexport default thingLight\nexport type ThingTheme = typeof thingLight\n"
  },
  {
    "path": "src/thing/styles/rtl.ts",
    "content": "import type { RtlItem } from '../../config-provider/src/internal-interface'\nimport { buttonRtl } from '../../button/styles/rtl'\nimport { spaceRtl } from '../../space/styles/rtl'\nimport rtlStyle from '../src/styles/rtl.cssr'\n\nexport const thingRtl: RtlItem = {\n  name: 'Thing',\n  style: rtlStyle,\n  peers: [buttonRtl, spaceRtl]\n}\n"
  },
  {
    "path": "src/thing/tests/Thing.spec.ts",
    "content": "import { mount } from '@vue/test-utils'\nimport { NThing } from '../index'\n\ndescribe('n-thing', () => {\n  it('should work with import on demand', () => {\n    mount(NThing)\n  })\n\n  it('should work with `content`, `description`, `title-extra`, `title` props', async () => {\n    const wrapper = mount(NThing, {\n      props: {\n        content: 'test-content',\n        description: 'test-description',\n        'title-extra': 'test-title-extra',\n        title: 'test-title'\n      }\n    })\n\n    expect(wrapper.find('.n-thing-main__content').exists()).toBe(true)\n    expect(wrapper.find('.n-thing-main__content').text()).toBe('test-content')\n    expect(wrapper.find('.n-thing-main__description').exists()).toBe(true)\n    expect(wrapper.find('.n-thing-main__description').text()).toBe(\n      'test-description'\n    )\n    expect(wrapper.find('.n-thing-header__title').exists()).toBe(true)\n    expect(wrapper.find('.n-thing-header__title').text()).toBe('test-title')\n    expect(wrapper.find('.n-thing-header__extra').exists()).toBe(true)\n    expect(wrapper.find('.n-thing-header__extra').text()).toBe(\n      'test-title-extra'\n    )\n  })\n\n  it('should work with `content-indented` prop', async () => {\n    const wrapper = mount(NThing, {\n      props: {\n        content: 'test-content',\n        description: 'test-description',\n        'title-extra': 'test-title-extra',\n        title: 'test-title'\n      },\n      slots: { avatar: () => 'test-avatar' }\n    })\n    expect(wrapper.find('.n-thing').element.children.length).toBe(1)\n    expect(\n      wrapper.find('.n-thing').element.children[0].getAttribute('class')\n    ).toContain('n-thing-main')\n\n    await wrapper.setProps({ contentIndented: true })\n    expect(wrapper.find('.n-thing').element.children.length).toBe(2)\n    expect(\n      wrapper.find('.n-thing').element.children[0].getAttribute('class')\n    ).toContain('n-thing-avatar')\n    expect(\n      wrapper.find('.n-thing').element.children[1].getAttribute('class')\n    ).toContain('n-thing-main')\n  })\n\n  it('should work with `avatar` `action` `default` `description` `header-extra` `header` `footer` Slots', async () => {\n    const wrapper = mount(NThing, {\n      slots: {\n        avatar: () => 'test-avatar',\n        action: () => 'test-action',\n        default: () => 'test-default',\n        description: () => 'test-description',\n        'header-extra': () => 'test-header-extra',\n        header: () => 'test-header',\n        footer: () => 'test-footer'\n      }\n    })\n\n    expect(wrapper.find('.n-thing-avatar').exists()).toBe(true)\n    expect(wrapper.find('.n-thing-avatar').text()).toBe('test-avatar')\n    expect(wrapper.find('.n-thing-main__action').exists()).toBe(true)\n    expect(wrapper.find('.n-thing-main__action').text()).toBe('test-action')\n    expect(wrapper.find('.n-thing-main__content').exists()).toBe(true)\n    expect(wrapper.find('.n-thing-main__content').text()).toBe('test-default')\n    expect(wrapper.find('.n-thing-main__description').exists()).toBe(true)\n    expect(wrapper.find('.n-thing-main__description').text()).toBe(\n      'test-description'\n    )\n    expect(wrapper.find('.n-thing-header__extra').exists()).toBe(true)\n    expect(wrapper.find('.n-thing-header__extra').text()).toBe(\n      'test-header-extra'\n    )\n    expect(wrapper.find('.n-thing-header__title').exists()).toBe(true)\n    expect(wrapper.find('.n-thing-header__title').text()).toBe('test-header')\n    expect(wrapper.find('.n-thing-main__footer').exists()).toBe(true)\n    expect(wrapper.find('.n-thing-main__footer').text()).toBe('test-footer')\n  })\n})\n"
  },
  {
    "path": "src/thing/tests/server.spec.tsx",
    "content": "import { setup } from '@css-render/vue3-ssr'\nimport { renderToString } from '@vue/server-renderer'\n/**\n * @vitest-environment node\n */\nimport { createSSRApp, h } from 'vue'\nimport { NThing } from '../..'\n\ndescribe('server side rendering', () => {\n  it('works', async () => {\n    const app = createSSRApp(() => <NThing />)\n    setup(app)\n    try {\n      await renderToString(app)\n    }\n    catch (e) {\n      expect(e).not.toBeTruthy()\n    }\n  })\n})\n"
  },
  {
    "path": "src/time/demos/enUS/basic.demo.vue",
    "content": "<markdown>\n# Basic\n</markdown>\n\n<script lang=\"ts\" setup>\nconst time = new Date(0)\n</script>\n\n<template>\n  <n-time :time=\"0\" />\n  <br>\n  <n-time :time=\"time\" />\n</template>\n"
  },
  {
    "path": "src/time/demos/enUS/format.demo.vue",
    "content": "<markdown>\n# Format\n\nFormat time. Specs see <n-a href=\"https://date-fns.org/v2.6.0/docs/format\" target=\"_blank\">date-fns format</n-a>.\n</markdown>\n\n<template>\n  <n-time :time=\"0\" format=\"yyyy-MM-dd\" />\n  <br>\n  <n-time :time=\"0\" format=\"yyyy-MM-dd hh:mm\" />\n  <br>\n  <n-time :time=\"0\" format=\"yyyy-MM-dd hh:mm:ss\" />\n</template>\n"
  },
  {
    "path": "src/time/demos/enUS/index.demo-entry.md",
    "content": "# Time\n\nTime provide some basic formation for time.\n\n## Demos\n\n```demo\nbasic.vue\ntype.vue\nformat.vue\nrelative.vue\nunix.vue\ntimezone.vue\n```\n\n## API\n\n### Time Props\n\n| Name | Type | Default | Description | Version |\n| --- | --- | --- | --- | --- |\n| format | `string` | `undefined` | Time format. For detail please see [format](https://date-fns.org/v2.23.0/docs/format). |  |\n| time | `number \\| Date` | `Date.now()` | Time. |  |\n| time-zone | `string` | `undefined` | Time zone to be used to format the value. It follows [iana time zones](https://www.iana.org/time-zones). You can use `Intl.supportedValuesOf('timeZone')` to check supported values. | 2.30.0 |\n| to | `number \\| Date` | `Date.now()` | Target time. |  |\n| type | `'relative' \\| 'date' \\| 'datetime'` | `'datetime'` | Time type. |  |\n| unix | `boolean` | `false` | `unix` timestamp. |  |\n"
  },
  {
    "path": "src/time/demos/enUS/relative.demo.vue",
    "content": "<markdown>\n# Relative\n\n`n-time` uses `date-fns`'s [`formatDistanceStrict`](https://date-fns.org/v2.28.0/docs/formatDistanceStrict) to format relative time.\n\nIf you don't need much customization, this is enough.\n</markdown>\n\n<template>\n  <n-time :time=\"0\" :to=\"86400000\" type=\"relative\" />\n  <br>\n  <n-time :time=\"0\" :to=\"864000000\" type=\"relative\" />\n  <br>\n  <n-time :time=\"0\" :to=\"8640000000\" type=\"relative\" />\n</template>\n"
  },
  {
    "path": "src/time/demos/enUS/timezone.demo.vue",
    "content": "<markdown>\n# Time zone\n</markdown>\n\n<template>\n  Shanghai <n-time time-zone=\"Asia/Shanghai\" /><br>Pittsburgh\n  <n-time time-zone=\"America/New_York\" /><br>UTC <n-time time-zone=\"UTC\" />\n</template>\n"
  },
  {
    "path": "src/time/demos/enUS/type.demo.vue",
    "content": "<markdown>\n# Type\n\n`date`, `datetime` or `relative`.\n</markdown>\n\n<script lang=\"ts\" setup>\nconst time = new Date(0)\n</script>\n\n<template>\n  <n-time :time=\"0\" type=\"date\" />\n  <br>\n  <n-time :time=\"time\" type=\"datetime\" />\n</template>\n"
  },
  {
    "path": "src/time/demos/enUS/unix.demo.vue",
    "content": "<markdown>\n# Unix timestamp\n\nUse Unix timestamp as time.\n</markdown>\n\n<template>\n  <n-time :time=\"4320000000\" :to=\"8640000000\" />\n  <br>\n  <n-time :time=\"4320000\" :to=\"8640000\" unix />\n  <br>\n  <n-time :time=\"4320000000\" format=\"yyyy-MM-dd hh:mm:ss\" />\n  <br>\n  <n-time :time=\"4320000\" format=\"yyyy-MM-dd hh:mm:ss\" unix />\n</template>\n"
  },
  {
    "path": "src/time/demos/zhCN/basic.demo.vue",
    "content": "<markdown>\n# 基础用法\n</markdown>\n\n<script lang=\"ts\" setup>\nconst time = new Date(0)\n</script>\n\n<template>\n  <n-time :time=\"0\" />\n  <br>\n  <n-time :time=\"time\" />\n</template>\n"
  },
  {
    "path": "src/time/demos/zhCN/format.demo.vue",
    "content": "<markdown>\n# 格式化\n\n格式化时间， 详尽文档请查看 <n-a href=\"https://date-fns.org/v2.6.0/docs/format\" target=\"_blank\">date-fns format</n-a>。\n</markdown>\n\n<template>\n  <n-time :time=\"0\" format=\"yyyy-MM-dd\" />\n  <br>\n  <n-time :time=\"0\" format=\"yyyy-MM-dd hh:mm\" />\n  <br>\n  <n-time :time=\"0\" format=\"yyyy-MM-dd hh:mm:ss\" />\n</template>\n"
  },
  {
    "path": "src/time/demos/zhCN/index.demo-entry.md",
    "content": "# 时间 Time\n\nTime 提供一些基本的时间格式化功能。\n\n## 演示\n\n```demo\nbasic.vue\ntype.vue\nformat.vue\nrelative.vue\nunix.vue\ntimezone.vue\ntimezone-debug.vue\n```\n\n## API\n\n### Time Props\n\n| 名称 | 类型 | 默认值 | 说明 | 版本 |\n| --- | --- | --- | --- | --- |\n| format | `string` | `undefined` | 时间格式化字符串，详情见 [format](https://date-fns.org/v2.23.0/docs/format) |  |\n| time | `number \\| Date` | `Date.now()` | 时间 |  |\n| time-zone | `string` | `undefined` | 格式化值时使用的时区，遵循 [iana time zones](https://www.iana.org/time-zones) 格式。你可以使用 `Intl.supportedValuesOf('timeZone')` 来查看支持的时区 | 2.30.0 |\n| to | `number \\| Date` | `Date.now()` | 目标时间 |  |\n| type | `'relative' \\| 'date' \\| 'datetime'` | `'datetime'` | 时间类型 |  |\n| unix | `boolean` | `false` | `unix` 时间戳 |  |\n"
  },
  {
    "path": "src/time/demos/zhCN/relative.demo.vue",
    "content": "<markdown>\n# 相对时间\n\n时间组件使用 `date-fns` 的 [`formatDistanceStrict`](https://date-fns.org/v2.28.0/docs/formatDistanceStrict) 格式化相对时间。\n\n如果你对于显示没有很多定制化的要求，这个一般够用了。\n</markdown>\n\n<template>\n  <n-time :time=\"0\" :to=\"86400000\" type=\"relative\" />\n  <br>\n  <n-time :time=\"0\" :to=\"864000000\" type=\"relative\" />\n  <br>\n  <n-time :time=\"0\" :to=\"8640000000\" type=\"relative\" />\n</template>\n"
  },
  {
    "path": "src/time/demos/zhCN/timezone-debug.demo.vue",
    "content": "<markdown>\n# Timezone debug\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst tz = ref('Asia/Shanghai')\nfunction toggle() {\n  if (tz.value === 'Asia/Shanghai') {\n    tz.value = 'America/New_York'\n  }\n  else {\n    tz.value = 'Asia/Shanghai'\n  }\n}\n</script>\n\n<template>\n  <button @click=\"toggle\">\n    toggle\n  </button>\n  {{ tz }} <n-time :time-zone=\"tz\" />\n</template>\n"
  },
  {
    "path": "src/time/demos/zhCN/timezone.demo.vue",
    "content": "<markdown>\n# 时区\n</markdown>\n\n<template>\n  上海 <n-time time-zone=\"Asia/Shanghai\" /><br>匹兹堡\n  <n-time time-zone=\"America/New_York\" /><br>UTC <n-time time-zone=\"UTC\" />\n</template>\n"
  },
  {
    "path": "src/time/demos/zhCN/type.demo.vue",
    "content": "<markdown>\n# 类型\n\n`date`、`datetime` 或者 `relative`。\n</markdown>\n\n<script lang=\"ts\" setup>\nconst time = new Date(0)\n</script>\n\n<template>\n  <n-time :time=\"0\" type=\"date\" />\n  <br>\n  <n-time :time=\"time\" type=\"datetime\" />\n</template>\n"
  },
  {
    "path": "src/time/demos/zhCN/unix.demo.vue",
    "content": "<markdown>\n# Unix 时间戳\n\n使用 Unix 时间戳作为时间。\n</markdown>\n\n<template>\n  <n-time :time=\"4320000000\" :to=\"8640000000\" />\n  <br>\n  <n-time :time=\"4320000\" :to=\"8640000\" unix />\n  <br>\n  <n-time :time=\"4320000000\" format=\"yyyy-MM-dd hh:mm:ss\" />\n  <br>\n  <n-time :time=\"4320000\" format=\"yyyy-MM-dd hh:mm:ss\" unix />\n</template>\n"
  },
  {
    "path": "src/time/index.ts",
    "content": "export { default as NTime, timeProps } from './src/Time'\nexport type { TimeProps } from './src/Time'\n"
  },
  {
    "path": "src/time/src/Time.ts",
    "content": "import type { Locale } from 'date-fns'\nimport type { PropType } from 'vue'\nimport type { ExtractPublicPropTypes } from '../../_utils'\nimport { format, formatDistanceStrict, fromUnixTime } from 'date-fns'\nimport { formatInTimeZone } from 'date-fns-tz'\nimport { computed, createTextVNode, defineComponent, h } from 'vue'\nimport { useLocale } from '../../_mixins'\n\nexport const timeProps = {\n  time: {\n    type: [Number, Date] as PropType<number | Date>,\n    default: undefined // For unix or non unix mode, it should be different default value\n  },\n  type: {\n    type: String as PropType<'relative' | 'date' | 'datetime'>,\n    default: 'datetime'\n  },\n  to: {\n    type: [Number, Date] as PropType<number | Date>,\n    default: undefined // the same as `time` prop\n  },\n  unix: Boolean,\n  format: String,\n  text: Boolean,\n  timeZone: String\n} as const\n\nexport type TimeProps = ExtractPublicPropTypes<typeof timeProps>\n\nexport default defineComponent({\n  name: 'Time',\n  props: timeProps,\n  setup(props) {\n    const now = Date.now()\n    const { localeRef, dateLocaleRef } = useLocale('Time')\n    const mergedFormatRef = computed(() => {\n      const { timeZone } = props\n      if (timeZone) {\n        return (\n          time: number | Date,\n          _format: string,\n          options: { locale: Locale }\n        ) => {\n          return formatInTimeZone(time, timeZone, _format, options)\n        }\n      }\n      return format\n    })\n    const dateFnsOptionsRef = computed(() => {\n      return {\n        locale: dateLocaleRef.value.locale\n      }\n    })\n    const mergedTimeRef = computed(() => {\n      const { time } = props\n      if (props.unix) {\n        if (time === undefined)\n          return now\n        return fromUnixTime(typeof time === 'number' ? time : time.valueOf())\n      }\n      return time ?? now\n    })\n    const mergedToRef = computed(() => {\n      const { to } = props\n      if (props.unix) {\n        if (to === undefined)\n          return now\n        return fromUnixTime(typeof to === 'number' ? to : to.valueOf())\n      }\n      return to ?? now\n    })\n    const renderedTimeRef = computed(() => {\n      if (props.format) {\n        return mergedFormatRef.value(\n          mergedTimeRef.value,\n          props.format,\n          dateFnsOptionsRef.value\n        )\n      }\n      else if (props.type === 'date') {\n        return mergedFormatRef.value(\n          mergedTimeRef.value,\n          localeRef.value.dateFormat,\n          dateFnsOptionsRef.value\n        )\n      }\n      else if (props.type === 'datetime') {\n        return mergedFormatRef.value(\n          mergedTimeRef.value,\n          localeRef.value.dateTimeFormat,\n          dateFnsOptionsRef.value\n        )\n      }\n      else {\n        return formatDistanceStrict(mergedTimeRef.value, mergedToRef.value, {\n          addSuffix: true,\n          locale: dateLocaleRef.value.locale\n        })\n      }\n    })\n    return {\n      renderedTime: renderedTimeRef\n    }\n  },\n  render() {\n    return this.text\n      ? createTextVNode(this.renderedTime)\n      : h('time', [this.renderedTime])\n  }\n})\n"
  },
  {
    "path": "src/time/tests/Time.spec.ts",
    "content": "import { mount } from '@vue/test-utils'\nimport { NTime } from '../index'\n\ndescribe('n-time', () => {\n  const date = new Date('1970-01-01 00:00:00 UTC').getTime()\n\n  const mockedNow = new Date('2020-01-01 00:00:01 UTC').getTime()\n\n  const cachedDateNow = Date.now\n\n  it('should work with import on demand', () => {\n    mount(NTime)\n  })\n\n  it('should work with `unix` prop', async () => {\n    const wrapper = mount(NTime, {\n      props: { time: 3600, unix: true, timeZone: 'Asia/Shanghai' }\n    })\n    expect(wrapper.find('time').text()).toContain('1970-01-01 09:00:00')\n    await wrapper.setProps({ time: date })\n  })\n\n  it('should work with `format` prop with timezone', async () => {\n    // 上海 2022-06-06 02:09:12\n    // 匹兹堡 2022-06-05 14:09:12\n    // UTC 2022-06-05 18:09:12\n    const wrapper = mount(NTime, {\n      props: {\n        time: 1654452568216,\n        format: 'yyyy/MM/dd',\n        timeZone: 'Asia/Shanghai'\n      }\n    })\n    expect(wrapper.find('time').text()).toContain('2022/06/06')\n    await wrapper.setProps({\n      timeZone: 'America/New_York'\n    })\n    expect(wrapper.find('time').text()).toContain('2022/06/05')\n  })\n\n  it('should work with `type` `to` prop', async () => {\n    Date.now = () => mockedNow\n\n    const wrapper = mount(NTime, {\n      props: { time: date, type: 'date', timeZone: 'Asia/Shanghai' }\n    })\n    expect(wrapper.find('time').text()).toContain('1970-01-01')\n    // eslint-disable-next-line no-console\n    console.log(\n      'github ci time zone',\n      Intl.DateTimeFormat().resolvedOptions().timeZone\n    )\n    await wrapper.setProps({ time: date, type: 'datetime' })\n    expect(wrapper.find('time').text().length).toBe(19)\n    await wrapper.setProps({ time: date, type: 'relative' })\n    expect(wrapper.find('time').text()).toContain('50 years ago')\n    Date.now = () => new Date('1972-01-01 00:00:00 UTC').getTime()\n    const wrapper2 = mount(NTime, {\n      props: { to: 0, type: 'relative', unix: true }\n    })\n    expect(wrapper2.find('time').text()).toContain('in 2 years')\n\n    Date.now = cachedDateNow\n  })\n\n  it('should work with `text` prop', () => {\n    const wrapper = mount(NTime, { props: { time: date, text: true } })\n    expect(wrapper.find('time').exists()).toEqual(false)\n  })\n})\n"
  },
  {
    "path": "src/time/tests/server.spec.tsx",
    "content": "import { setup } from '@css-render/vue3-ssr'\nimport { renderToString } from '@vue/server-renderer'\n/**\n * @vitest-environment node\n */\nimport { createSSRApp, h } from 'vue'\nimport { NTime } from '../..'\n\ndescribe('server side rendering', () => {\n  it('works', async () => {\n    const app = createSSRApp(() => <NTime />)\n    setup(app)\n    try {\n      await renderToString(app)\n    }\n    catch (e) {\n      expect(e).not.toBeTruthy()\n    }\n  })\n})\n"
  },
  {
    "path": "src/time-picker/demos/enUS/actions.demo.vue",
    "content": "<markdown>\n# Actions\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst ts1 = ref(null)\nconst ts2 = ref(861333934000)\n</script>\n\n<template>\n  <n-space vertical>\n    <n-time-picker v-model:value=\"ts1\" :actions=\"['now', 'clear']\" />\n    <n-time-picker v-model:value=\"ts2\" :actions=\"null\" />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/time-picker/demos/enUS/basic.demo.vue",
    "content": "<markdown>\n# Basic\n</markdown>\n\n<template>\n  <n-space>\n    <n-time-picker default-formatted-value=\"00:12:13\" />\n    <n-time-picker :default-value=\"1183135260000\" />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/time-picker/demos/enUS/confirm.demo.vue",
    "content": "<markdown>\n# Confirm\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { useMessage } from 'naive-ui'\n\nconst message = useMessage()\nfunction handleConfirm(value: number | null) {\n  message.success(`Confirm${value}`)\n}\n</script>\n\n<template>\n  <n-space>\n    <n-time-picker\n      default-formatted-value=\"00:12:13\"\n      @confirm=\"handleConfirm\"\n    />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/time-picker/demos/enUS/disabled-time.demo.vue",
    "content": "<markdown>\n# Disable time\n\nIf you can't stop time, at least disable it.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst time0 = ref(null)\n\nfunction isHourDisabled(hour: number) {\n  return hour % 2 === 0\n}\n\nfunction isMinuteDisabled(minute: number, selectedHour: number | null) {\n  if (selectedHour === null)\n    return false\n  if (Number(selectedHour) < 12) {\n    return minute < 30\n  }\n  else {\n    return false\n  }\n}\n\nfunction isSecondDisabled(\n  second: number,\n  selectedMinute: number | null,\n  selectedHour: number | null\n) {\n  if (selectedHour === null || selectedMinute === null)\n    return false\n  if (Number(selectedHour) > 20 && Number(selectedMinute) < 30) {\n    return second < 40\n  }\n  else {\n    return false\n  }\n}\n</script>\n\n<template>\n  <n-time-picker\n    v-model:value=\"time0\"\n    :is-hour-disabled=\"isHourDisabled\"\n    :is-minute-disabled=\"isMinuteDisabled\"\n    :is-second-disabled=\"isSecondDisabled\"\n  />\n</template>\n"
  },
  {
    "path": "src/time-picker/demos/enUS/focus.demo.vue",
    "content": "<markdown>\n# Focus & blur manually\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { TimePickerInst } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst timePickerInstRef = ref<TimePickerInst | null>(null)\n\nfunction handleClick() {\n  timePickerInstRef.value?.focus()\n  setTimeout(() => {\n    timePickerInstRef.value?.blur()\n  }, 1000)\n}\n</script>\n\n<template>\n  <n-space item-style=\"display: flex; align-item: center;\">\n    <n-button @click=\"handleClick\">\n      Focus then blur in 1 second\n    </n-button>\n    <n-time-picker ref=\"timePickerInstRef\" />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/time-picker/demos/enUS/format.demo.vue",
    "content": "<markdown>\n# Format\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst time = ref(null)\n</script>\n\n<template>\n  <n-time-picker v-model:value=\"time\" format=\"h:mm a\" />\n</template>\n"
  },
  {
    "path": "src/time-picker/demos/enUS/formatted.demo.vue",
    "content": "<markdown>\n# Use formatted value\n\nUse `formatted-value` to control formatted value.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst formattedValue = ref('4~1~8')\n</script>\n\n<template>\n  <pre>{{ formattedValue }}</pre>\n  <n-time-picker\n    v-model:formatted-value=\"formattedValue\"\n    value-format=\"H~m~s\"\n  />\n</template>\n"
  },
  {
    "path": "src/time-picker/demos/enUS/hours12.demo.vue",
    "content": "<markdown>\n# 12 hours\n</markdown>\n\n<template>\n  <n-space>\n    <n-time-picker use-12-hours />\n    <n-time-picker use-12-hours :default-value=\"1183135260000\" />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/time-picker/demos/enUS/index.demo-entry.md",
    "content": "# Time Picker\n\nLike a digital clock.\n\n## Demos\n\n```demo\nbasic.vue\nconfirm.vue\nsize.vue\ndisabled-time.vue\nstep-time.vue\nformat.vue\nactions.vue\nhours12.vue\nformatted.vue\nfocus.vue\nstatus.vue\ntimezone.vue\n```\n\n## API\n\n### TimePicker Props\n\n| Name | Type | Default | Description | Version |\n| --- | --- | --- | --- | --- |\n| actions | `Array<'clear' \\| 'now' \\| 'confirm'> \\| null` | `['now', 'confirm']` | Operations supported by the Time Picker. | `'clear'` 2.37.0 |\n| clearable | `boolean` | `false` | Whether the value is clearable. |  |\n| default-value | `number \\| null` | `null` | Default value. |  |\n| default-formatted-value | `number \\| null` | `undefined` | Default formatted value. | 2.24.0 |\n| disabled | `boolean` | `false` | Disabled state. |  |\n| format | `string` | `'HH:mm:ss'` | Time format. For possible formats see [date-fns.org](https://date-fns.org/v2.23.0/docs/format). |  |\n| formatted-value | `string \\| null` | `undefined` | Formatted value. | 2.24.0 |\n| hours | `number \\| number[]` | `undefined` | The array of hours that can be selected. If a number, it'll be converted into an array of numbers using that increment. |  |\n| minutes | `number \\| number[]` | `undefined` | The array of minutes that can be selected. If a number, it'll be converted into an array of numbers using that increment. |  |\n| seconds | `number \\| number[]` | `undefined` | The array of seconds that can be selected. If a number, it'll be converted into an array of numbers using that increment. |  |\n| input-readonly | `boolean` | `false` | Readonly state (does not apply to touch devices). |  |\n| is-hour-disabled | `(hour: number) => boolean` | `() => false` | Callback function for disabling hours. |  |\n| is-minute-disabled | `(minute: number, hour: number \\| null) => boolean` | `() => false` | Callback function for disabling minutes. When value is empty, `hour` is `null`. |  |\n| is-second-disabled | `(second: number, minute: number \\| null, hour: number \\| null) => boolean` | `() => false` | Callback function for disabling seconds. When value is empty, `hour` and `minute` are `null`. |  |\n| placeholder | `string` | `'Select Time'` | Placeholder. |  |\n| placement | `'top-start' \\| 'top' \\| 'top-end' \\| 'right-start' \\| 'right' \\| 'right-end' \\| 'bottom-start' \\| 'bottom' \\| 'bottom-end' \\| 'left-start' \\| 'left' \\| 'left-end'` | `'bottom-start'` | Time picker panel's placement. | 2.25.0 |\n| show | `boolean` | `undefined` | Whether to show panel | 2.28.3 |\n| size | `'small' \\| 'medium' \\| 'large'` | `'medium'` | Size. |  |\n| status | `'success' \\| 'warning' \\| 'error'` | `undefined` | Validation status. | 2.27.0 |\n| time-zone | `string` | `undefined` | Time zone to be used to format the value. It follows [iana time zones](https://www.iana.org/time-zones). You can use `Intl.supportedValuesOf('timeZone')` to check supported values. | 2.30.0 |\n| to | `string \\| HTMLElement \\| false` | `body` | Container node of the menu. `false` will keep it not detached. |  |\n| use-12-hours | `boolean` | `false` | Whether to use a 12-hour clock panel. |  |\n| value | `number \\| null` | `undefined` | Value when being set manually. |  |\n| value-format | `string` | follows `format` | Format of formatted value. | 2.24.0 |\n| on-blur | `() => void` | `undefined` | Callback when the selection box loses focus. |  |\n| on-clear | `() => void` | `undefined` | Callback when value is cleared. | 2.28.3 |\n| on-confirm | `(value: number \\| null, formattedValue: string \\| null) => void` | `undefined` | Callback when the click confirm button. | 2.28.3 |\n| on-focus | `() => void` | `undefined` | Callback when the selection box gets focus. |  |\n| on-update:formatted-value | `(value: number \\| null, timestampValue: number \\| null) => void` | `undefined` | Callback when formatted value changes. | 2.24.0 |\n| on-update:show | `(show: boolean) => void` | `undefined` | Callback when panel shows & hides. | 2.28.3 |\n| on-update:value | `(value: number \\| null, formattedValue: string \\| null) => void` | `undefined` | Callback when the value changes. | `formattedValue` 2.24.0 |\n\n### TimePicker Slots\n\n| Name | Parameters | Description |\n| ---- | ---------- | ----------- |\n| icon | `()`       | Custom icon |\n\n### TimePicker Methods\n\n| Name  | Type         | Description | Version |\n| ----- | ------------ | ----------- | ------- |\n| focus | `() => void` | Focus.      | 2.24.2  |\n| blur  | `() => void` | Blur.       | 2.24.2  |\n"
  },
  {
    "path": "src/time-picker/demos/enUS/size.demo.vue",
    "content": "<markdown>\n# Size\n\nThe Time Picker can be a `small`, `medium` or `large` size.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst timestamp = ref(null)\n</script>\n\n<template>\n  <n-space vertical>\n    <n-time-picker v-model:value=\"timestamp\" size=\"small\" />\n    <n-time-picker v-model:value=\"timestamp\" size=\"medium\" />\n    <n-time-picker v-model:value=\"timestamp\" size=\"large\" />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/time-picker/demos/enUS/status.demo.vue",
    "content": "<markdown>\n# Validation status\n\nValidation status can be applied outside form.\n</markdown>\n\n<template>\n  <n-space vertical>\n    <n-time-picker status=\"warning\" placeholder=\"\" />\n    <n-time-picker status=\"error\" placeholder=\"\" />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/time-picker/demos/enUS/step-time.demo.vue",
    "content": "<markdown>\n# Step time\n\nPass a number as an incremental step, or use an array to specify the values you want to show. If inputs do not adhere to these parameters, an invalid status will be shown (strikethrough text).\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst time = ref(1183135260000)\n</script>\n\n<template>\n  <n-time-picker\n    v-model:value=\"time\"\n    :hours=\"[8, 18]\"\n    :minutes=\"8\"\n    :seconds=\"[0]\"\n  />\n</template>\n"
  },
  {
    "path": "src/time-picker/demos/enUS/timezone.demo.vue",
    "content": "<markdown>\n# Time zone\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst value = ref(Date.now())\n</script>\n\n<template>\n  <n-grid :cols=\"2\" :x-gap=\"12\" :y-gap=\"12\">\n    <n-grid-item>\n      <n-form-item label=\"Shanghai\" :show-feedback=\"false\">\n        <n-time-picker\n          v-model:value=\"value\"\n          style=\"width: 100%\"\n          time-zone=\"Asia/Shanghai\"\n        />\n      </n-form-item>\n    </n-grid-item>\n    <n-grid-item>\n      <n-form-item label=\"Pittsburgh\" :show-feedback=\"false\">\n        <n-time-picker\n          v-model:value=\"value\"\n          style=\"width: 100%\"\n          time-zone=\"America/New_York\"\n        />\n      </n-form-item>\n    </n-grid-item>\n    <n-grid-item>\n      <n-form-item label=\"UTC\" :show-feedback=\"false\">\n        <n-time-picker\n          v-model:value=\"value\"\n          style=\"width: 100%\"\n          time-zone=\"UTC\"\n        />\n      </n-form-item>\n    </n-grid-item>\n  </n-grid>\n</template>\n"
  },
  {
    "path": "src/time-picker/demos/zhCN/actions.demo.vue",
    "content": "<markdown>\n# 操作\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst ts1 = ref(null)\nconst ts2 = ref(861333934000)\n</script>\n\n<template>\n  <n-space vertical>\n    <n-time-picker v-model:value=\"ts1\" :actions=\"['now', 'clear']\" />\n    <n-time-picker v-model:value=\"ts2\" :actions=\"null\" />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/time-picker/demos/zhCN/basic.demo.vue",
    "content": "<markdown>\n# 基础用法\n</markdown>\n\n<template>\n  <n-space>\n    <n-time-picker default-formatted-value=\"00:12:13\" />\n    <n-time-picker :default-value=\"1183135260000\" />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/time-picker/demos/zhCN/confirm.demo.vue",
    "content": "<markdown>\n# 确认\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { useMessage } from 'naive-ui'\n\nconst message = useMessage()\nfunction handleConfirm(value: number | null) {\n  message.success(`确认${value}`)\n}\n</script>\n\n<template>\n  <n-space>\n    <n-time-picker\n      default-formatted-value=\"00:12:13\"\n      @confirm=\"handleConfirm\"\n    />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/time-picker/demos/zhCN/disabled-time.demo.vue",
    "content": "<markdown>\n# 禁用某些时间\n\n你可以禁用某些时间。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst time0 = ref(null)\n\nfunction isHourDisabled(hour: number) {\n  return hour % 2 === 0\n}\n\nfunction isMinuteDisabled(minute: number, selectedHour: number | null) {\n  if (selectedHour === null)\n    return false\n  if (Number(selectedHour) < 12) {\n    return minute < 30\n  }\n  else {\n    return false\n  }\n}\n\nfunction isSecondDisabled(\n  second: number,\n  selectedMinute: number | null,\n  selectedHour: number | null\n) {\n  if (selectedHour === null || selectedMinute === null)\n    return false\n  if (Number(selectedHour) > 20 && Number(selectedMinute) < 30) {\n    return second < 40\n  }\n  else {\n    return false\n  }\n}\n</script>\n\n<template>\n  <n-time-picker\n    v-model:value=\"time0\"\n    :is-hour-disabled=\"isHourDisabled\"\n    :is-minute-disabled=\"isMinuteDisabled\"\n    :is-second-disabled=\"isSecondDisabled\"\n  />\n</template>\n"
  },
  {
    "path": "src/time-picker/demos/zhCN/focus.demo.vue",
    "content": "<markdown>\n# 手动 focus & blur\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { TimePickerInst } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst timePickerInstRef = ref<TimePickerInst | null>(null)\n\nfunction handleClick() {\n  timePickerInstRef.value?.focus()\n  setTimeout(() => {\n    timePickerInstRef.value?.blur()\n  }, 1000)\n}\n</script>\n\n<template>\n  <n-space item-style=\"display: flex; align-item: center;\">\n    <n-button @click=\"handleClick\">\n      聚焦，一秒后失效\n    </n-button>\n    <n-time-picker ref=\"timePickerInstRef\" />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/time-picker/demos/zhCN/format.demo.vue",
    "content": "<markdown>\n# 格式化\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst time = ref(null)\n</script>\n\n<template>\n  <n-time-picker v-model:value=\"time\" format=\"h:mm a\" />\n</template>\n"
  },
  {
    "path": "src/time-picker/demos/zhCN/formatted.demo.vue",
    "content": "<markdown>\n# 使用格式化后的值\n\n你可以使用 `formatted-value` 控制格式化后的值。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst formattedValue = ref('4~1~8')\n</script>\n\n<template>\n  <pre>{{ formattedValue }}</pre>\n  <n-time-picker\n    v-model:formatted-value=\"formattedValue\"\n    value-format=\"H~m~s\"\n  />\n</template>\n"
  },
  {
    "path": "src/time-picker/demos/zhCN/hours12.demo.vue",
    "content": "<markdown>\n# 12 小时\n</markdown>\n\n<template>\n  <n-space>\n    <n-time-picker use-12-hours />\n    <n-time-picker use-12-hours :default-value=\"1183135260000\" />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/time-picker/demos/zhCN/index.demo-entry.md",
    "content": "# 时间选择器 Time Picker\n\n就像一块数码表。\n\n## 演示\n\n```demo\nbasic.vue\nconfirm.vue\nsize.vue\ndisabled-time.vue\nstep-time.vue\nformat.vue\nactions.vue\nhours12.vue\nformatted.vue\nfocus.vue\nstatus.vue\ntimezone.vue\ntimezone-debug.vue\n```\n\n## API\n\n### TimePicker Props\n\n| 名称 | 类型 | 默认值 | 说明 | 版本 |\n| --- | --- | --- | --- | --- |\n| actions | `Array<'clear' \\| 'now' \\| 'confirm'> \\| null` | `['now', 'confirm']` | Time Picker 中支持的操作 | `'clear'` 2.37.0 |\n| clearable | `boolean` | `false` | 是否可清空 |  |\n| default-value | `number \\| null` | `null` | 非受控模式下的默认值 |  |\n| default-formatted-value | `string \\| null` | `undefined` | 非受控模式下的默认格式化后的值 | 2.24.0 |\n| disabled | `boolean` | `false` | 是否禁用 |  |\n| format | `string` | `'HH:mm:ss'` | 时间格式化字符串，详情见 [format](https://date-fns.org/v2.23.0/docs/format) |  |\n| formatted-value | `string \\| null` | `undefined` | 格式化后的值 | 2.24.0 |\n| hours | `number \\| number[]` | `undefined` | 通过数组指定显示的小时。当值为 `number` 时，将被当做时间步进处理 |  |\n| minutes | `number \\| number[]` | `undefined` | 通过数组指定显示的分钟。当值为 `number` 时，将被当做时间步进处理 |  |\n| seconds | `number \\| number[]` | `undefined` | 通过数组指定显示的秒。当值为 `number` 时，将被当做时间步进处理 |  |\n| input-readonly | `boolean` | `false` | 设置输入框为只读（避免在移动设备上打开虚拟键盘） |  |\n| is-hour-disabled | `(hour: number) => boolean` | `() => false` | 用于禁用小时的回调函数 |  |\n| is-minute-disabled | `(minute: number, hour: number \\| null) => boolean` | `() => false` | 用于禁用分钟的回调函数，在没有选中值时，`hour` 是 `null` |  |\n| is-second-disabled | `(second: number, minute: number \\| null, hour: number \\| null) => boolean` | `() => false` | 用于禁用秒钟的回调函数，在没有选中值时，`minute` 和 `hour` 是 `null` |  |\n| placeholder | `string` | `'请选择时间'` | 选择框的占位符 |  |\n| placement | `'top-start' \\| 'top' \\| 'top-end' \\| 'right-start' \\| 'right' \\| 'right-end' \\| 'bottom-start' \\| 'bottom' \\| 'bottom-end' \\| 'left-start' \\| 'left' \\| 'left-end'` | `'bottom-start'` | 时间选择器的面板的弹出位置 | 2.25.0 |\n| show | `boolean` | `undefined` | 是否展示面板 | 2.28.3 |\n| size | `'small' \\| 'medium' \\| 'large'` | `'medium'` | 选择框的尺寸 |  |\n| status | `'success' \\| 'warning' \\| 'error'` | `undefined` | 验证状态 | 2.27.0 |\n| time-zone | `string` | `undefined` | 格式化值时使用的时区，遵循 [iana time zones](https://www.iana.org/time-zones) 格式。你可以使用 `Intl.supportedValuesOf('timeZone')` 来查看支持的时区 | 2.30.0 |\n| to | `string \\| HTMLElement \\| false` | `body` | 菜单的容器节点，`false` 会待在原地 |  |\n| use-12-hours | `boolean` | `false` | 是否使用 12 小时制的面板 |  |\n| value | `number \\| null` | `undefined` | 受控模式下的值 |  |\n| value-format | `string` | 跟随 `format` | 格式化后值的格式 | 2.24.0 |\n| on-blur | `() => void` | `undefined` | 选择框失去焦点时的回调 |  |\n| on-clear | `() => void` | `undefined` | 清除值时的回调 | 2.28.3 |\n| on-confirm | `(value: number \\| null, formattedValue: string \\| null) => void` | `undefined` | 点击确认按钮时的回调 | 2.28.3 |\n| on-focus | `() => void` | `undefined` | 选择框获得焦点时的回调 |  |\n| on-update:formatted-value | `(value: number \\| null, timestampValue: number \\| null) => void` | `undefined` | 格式化的值发生改变时的回调 | 2.24.0 |\n| on-update:show | `(show: boolean) => void` | `undefined` | 面板打开、关闭时的回调 | 2.28.3 |\n| on-update:value | `(value: number \\| null, formattedValue: string \\| null) => void` | `undefined` | 值发生改变时的回调 | `formattedValue` 2.24.0 |\n\n### TimePicker Slots\n\n| 名称 | 参数 | 说明       |\n| ---- | ---- | ---------- |\n| icon | `()` | 自定义图标 |\n\n### TimePicker Methods\n\n| 名称  | 类型         | 说明 | 版本   |\n| ----- | ------------ | ---- | ------ |\n| focus | `() => void` | 聚焦 | 2.24.2 |\n| blur  | `() => void` | 失焦 | 2.24.2 |\n"
  },
  {
    "path": "src/time-picker/demos/zhCN/size.demo.vue",
    "content": "<markdown>\n# 尺寸\n\n可以是 `small`、`medium` 或 `large` 尺寸。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst timestamp = ref(null)\n</script>\n\n<template>\n  <n-space vertical>\n    <n-time-picker v-model:value=\"timestamp\" size=\"small\" />\n    <n-time-picker v-model:value=\"timestamp\" size=\"medium\" />\n    <n-time-picker v-model:value=\"timestamp\" size=\"large\" />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/time-picker/demos/zhCN/status.demo.vue",
    "content": "<markdown>\n# 验证状态\n\n输入的验证状态可以脱离表单使用。\n</markdown>\n\n<template>\n  <n-space vertical>\n    <n-time-picker status=\"warning\" placeholder=\"\" />\n    <n-time-picker status=\"error\" placeholder=\"\" />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/time-picker/demos/zhCN/step-time.demo.vue",
    "content": "<markdown>\n# 展示某些时间\n\n传递单独的数字来定义时间步进或用数组指定你需要显示的内容，输入超出设定范围的值将将显示无效样式。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst time = ref(1183135260000)\n</script>\n\n<template>\n  <n-time-picker\n    v-model:value=\"time\"\n    :hours=\"[8, 18]\"\n    :minutes=\"8\"\n    :seconds=\"[0]\"\n  />\n</template>\n"
  },
  {
    "path": "src/time-picker/demos/zhCN/timezone-debug.demo.vue",
    "content": "<markdown>\n# Timezone debug\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst tz = ref('Asia/Shanghai')\n\nfunction toggle() {\n  if (tz.value === 'Asia/Shanghai') {\n    tz.value = 'America/New_York'\n  }\n  else {\n    tz.value = 'Asia/Shanghai'\n  }\n}\n</script>\n\n<template>\n  <button @click=\"toggle\">\n    toggle\n  </button>\n  {{ tz }} <n-time-picker :time-zone=\"tz\" />\n</template>\n"
  },
  {
    "path": "src/time-picker/demos/zhCN/timezone.demo.vue",
    "content": "<markdown>\n# 时区\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst value = ref(Date.now())\n</script>\n\n<template>\n  <n-grid :cols=\"2\" :x-gap=\"12\" :y-gap=\"12\">\n    <n-grid-item>\n      <n-form-item label=\"上海\" :show-feedback=\"false\">\n        <n-time-picker\n          v-model:value=\"value\"\n          style=\"width: 100%\"\n          time-zone=\"Asia/Shanghai\"\n        />\n      </n-form-item>\n    </n-grid-item>\n    <n-grid-item>\n      <n-form-item label=\"匹兹堡\" :show-feedback=\"false\">\n        <n-time-picker\n          v-model:value=\"value\"\n          style=\"width: 100%\"\n          time-zone=\"America/New_York\"\n        />\n      </n-form-item>\n    </n-grid-item>\n    <n-grid-item>\n      <n-form-item label=\"UTC\" :show-feedback=\"false\">\n        <n-time-picker\n          v-model:value=\"value\"\n          style=\"width: 100%\"\n          time-zone=\"UTC\"\n        />\n      </n-form-item>\n    </n-grid-item>\n  </n-grid>\n</template>\n"
  },
  {
    "path": "src/time-picker/index.ts",
    "content": "export type { TimePickerInst } from './src/interface'\nexport type * from './src/public-types'\nexport { default as NTimePicker, timePickerProps } from './src/TimePicker'\nexport type { TimePickerProps, TimePickerSlots } from './src/TimePicker'\n"
  },
  {
    "path": "src/time-picker/src/Panel.tsx",
    "content": "import type { PropType } from 'vue'\nimport type { MaybeArray } from '../../_utils'\nimport type {\n  IsHourDisabled,\n  IsMinuteDisabled,\n  IsSecondDisabled,\n  Item,\n  ItemValue\n} from './interface'\nimport { computed, defineComponent, h, inject, ref } from 'vue'\nimport { NBaseFocusDetector, NScrollbar } from '../../_internal'\nimport { NButton } from '../../button'\nimport { timePickerInjectionKey } from './interface'\nimport PanelCol from './PanelCol'\nimport { getAmPm, getTimeUnits, time } from './utils'\n\nconst timePickerPanelProps = {\n  actions: {\n    type: Array as PropType<Array<'clear' | 'now' | 'confirm'> | null>,\n    default: () => ['now', 'confirm']\n  },\n  showHour: {\n    type: Boolean,\n    default: true\n  },\n  showMinute: {\n    type: Boolean,\n    default: true\n  },\n  showSecond: {\n    type: Boolean,\n    default: true\n  },\n  showPeriod: {\n    type: Boolean,\n    default: true\n  },\n  isHourInvalid: Boolean,\n  isMinuteInvalid: Boolean,\n  isSecondInvalid: Boolean,\n  isAmPmInvalid: Boolean,\n  isValueInvalid: Boolean,\n  hourValue: {\n    type: Number as PropType<number | null>,\n    default: null\n  },\n  minuteValue: {\n    type: Number as PropType<number | null>,\n    default: null\n  },\n  secondValue: {\n    type: Number as PropType<number | null>,\n    default: null\n  },\n  amPmValue: {\n    type: String as PropType<'am' | 'pm' | null>,\n    default: null\n  },\n  isHourDisabled: Function as PropType<IsHourDisabled>,\n  isMinuteDisabled: Function as PropType<IsMinuteDisabled>,\n  isSecondDisabled: Function as PropType<IsSecondDisabled>,\n  onHourClick: {\n    type: Function as PropType<(value: ItemValue) => void>,\n    required: true\n  },\n  onMinuteClick: {\n    type: Function as PropType<(value: ItemValue) => void>,\n    required: true\n  },\n  onSecondClick: {\n    type: Function as PropType<(value: ItemValue) => void>,\n    required: true\n  },\n  onAmPmClick: {\n    type: Function as PropType<(value: ItemValue) => void>,\n    required: true\n  },\n  onNowClick: Function as PropType<() => void>,\n  clearText: String,\n  nowText: String,\n  confirmText: String,\n  transitionDisabled: Boolean,\n  onClearClick: Function as PropType<() => void>,\n  onConfirmClick: Function as PropType<() => void>,\n  onFocusin: Function as PropType<(e: FocusEvent) => void>,\n  onFocusout: Function as PropType<(e: FocusEvent) => void>,\n  onFocusDetectorFocus: Function as PropType<() => void>,\n  onKeydown: Function as PropType<(e: KeyboardEvent) => void>,\n  hours: [Number, Array] as PropType<MaybeArray<number>>,\n  minutes: [Number, Array] as PropType<MaybeArray<number>>,\n  seconds: [Number, Array] as PropType<MaybeArray<number>>,\n  use12Hours: Boolean\n}\n\nexport default defineComponent({\n  name: 'TimePickerPanel',\n  props: timePickerPanelProps,\n  setup(props) {\n    const { mergedThemeRef, mergedClsPrefixRef } = inject(\n      timePickerInjectionKey\n    )!\n\n    const hoursRef = computed<Item[]>(() => {\n      const { isHourDisabled, hours, use12Hours, amPmValue } = props\n      if (!use12Hours) {\n        return getTimeUnits(time.hours, hours).map((hour) => {\n          return {\n            label: hour,\n            value: Number(hour),\n            disabled: isHourDisabled ? isHourDisabled(Number(hour)) : false\n          }\n        })\n      }\n      else {\n        const mergedAmPmValue = amPmValue ?? getAmPm(Date.now())\n        return getTimeUnits(time.hours, hours, mergedAmPmValue).map((hour) => {\n          const hourAs12FormattedNumber = Number(hour)\n          const hourAs24FormattedNumber\n            = mergedAmPmValue === 'pm' && hourAs12FormattedNumber !== 12\n              ? hourAs12FormattedNumber + 12\n              : hourAs12FormattedNumber\n          return {\n            label: hour,\n            value: hourAs24FormattedNumber,\n            disabled: isHourDisabled\n              ? isHourDisabled(hourAs24FormattedNumber)\n              : false\n          }\n        })\n      }\n    })\n    const minutesRef = computed<Item[]>(() => {\n      const { isMinuteDisabled, minutes } = props\n      return getTimeUnits(time.minutes, minutes).map((minute) => {\n        return {\n          label: minute,\n          value: Number(minute),\n          disabled: isMinuteDisabled\n            ? isMinuteDisabled(Number(minute), props.hourValue)\n            : false\n        }\n      })\n    })\n    const secondsRef = computed<Item[]>(() => {\n      const { isSecondDisabled, seconds } = props\n      return getTimeUnits(time.seconds, seconds).map((second) => {\n        return {\n          label: second,\n          value: Number(second),\n          disabled: isSecondDisabled\n            ? isSecondDisabled(\n                Number(second),\n                props.minuteValue,\n                props.hourValue\n              )\n            : false\n        }\n      })\n    })\n    const amPmRef = computed<Item[]>(() => {\n      const { isHourDisabled } = props\n      let amDisabled = true\n      let pmDisabled = true\n      for (let i = 0; i < 12; ++i) {\n        if (!isHourDisabled?.(i)) {\n          amDisabled = false\n          break\n        }\n      }\n      for (let i = 12; i < 24; ++i) {\n        if (!isHourDisabled?.(i)) {\n          pmDisabled = false\n          break\n        }\n      }\n      return [\n        {\n          label: 'AM',\n          value: 'am',\n          disabled: amDisabled\n        },\n        {\n          label: 'PM',\n          value: 'pm',\n          disabled: pmDisabled\n        }\n      ]\n    })\n    return {\n      mergedTheme: mergedThemeRef,\n      mergedClsPrefix: mergedClsPrefixRef,\n      hours: hoursRef,\n      minutes: minutesRef,\n      seconds: secondsRef,\n      amPm: amPmRef,\n      hourScrollRef: ref(null),\n      minuteScrollRef: ref(null),\n      secondScrollRef: ref(null),\n      amPmScrollRef: ref(null)\n    }\n  },\n  render() {\n    const { mergedClsPrefix, mergedTheme } = this\n    return (\n      <div\n        tabindex={0}\n        class={`${mergedClsPrefix}-time-picker-panel`}\n        onFocusin={this.onFocusin}\n        onFocusout={this.onFocusout}\n        onKeydown={this.onKeydown}\n      >\n        <div class={`${mergedClsPrefix}-time-picker-cols`}>\n          {this.showHour ? (\n            <div\n              class={[\n                `${mergedClsPrefix}-time-picker-col`,\n                this.isHourInvalid\n                && `${mergedClsPrefix}-time-picker-col--invalid`,\n                this.transitionDisabled\n                && `${mergedClsPrefix}-time-picker-col--transition-disabled`\n              ]}\n            >\n              <NScrollbar\n                ref=\"hourScrollRef\"\n                theme={mergedTheme.peers.Scrollbar}\n                themeOverrides={mergedTheme.peerOverrides.Scrollbar}\n              >\n                {{\n                  default: () => [\n                    <PanelCol\n                      clsPrefix={mergedClsPrefix}\n                      data={this.hours}\n                      activeValue={this.hourValue}\n                      onItemClick={this.onHourClick}\n                    />,\n                    <div\n                      class={`${mergedClsPrefix}-time-picker-col__padding`}\n                    />\n                  ]\n                }}\n              </NScrollbar>\n            </div>\n          ) : null}\n          {this.showMinute ? (\n            <div\n              class={[\n                `${mergedClsPrefix}-time-picker-col`,\n                this.transitionDisabled\n                && `${mergedClsPrefix}-time-picker-col--transition-disabled`,\n                this.isMinuteInvalid\n                && `${mergedClsPrefix}-time-picker-col--invalid`\n              ]}\n            >\n              <NScrollbar\n                ref=\"minuteScrollRef\"\n                theme={mergedTheme.peers.Scrollbar}\n                themeOverrides={mergedTheme.peerOverrides.Scrollbar}\n              >\n                {{\n                  default: () => [\n                    <PanelCol\n                      clsPrefix={mergedClsPrefix}\n                      data={this.minutes}\n                      activeValue={this.minuteValue}\n                      onItemClick={this.onMinuteClick}\n                    />,\n                    <div\n                      class={`${mergedClsPrefix}-time-picker-col__padding`}\n                    />\n                  ]\n                }}\n              </NScrollbar>\n            </div>\n          ) : null}\n          {this.showSecond ? (\n            <div\n              class={[\n                `${mergedClsPrefix}-time-picker-col`,\n                this.isSecondInvalid\n                && `${mergedClsPrefix}-time-picker-col--invalid`,\n                this.transitionDisabled\n                && `${mergedClsPrefix}-time-picker-col--transition-disabled`\n              ]}\n            >\n              <NScrollbar\n                ref=\"secondScrollRef\"\n                theme={mergedTheme.peers.Scrollbar}\n                themeOverrides={mergedTheme.peerOverrides.Scrollbar}\n              >\n                {{\n                  default: () => [\n                    <PanelCol\n                      clsPrefix={mergedClsPrefix}\n                      data={this.seconds}\n                      activeValue={this.secondValue}\n                      onItemClick={this.onSecondClick}\n                    />,\n                    <div\n                      class={`${mergedClsPrefix}-time-picker-col__padding`}\n                    />\n                  ]\n                }}\n              </NScrollbar>\n            </div>\n          ) : null}\n          {this.use12Hours ? (\n            <div\n              class={[\n                `${mergedClsPrefix}-time-picker-col`,\n                this.isAmPmInvalid\n                && `${mergedClsPrefix}-time-picker-col--invalid`,\n                this.transitionDisabled\n                && `${mergedClsPrefix}-time-picker-col--transition-disabled`\n              ]}\n            >\n              <NScrollbar\n                ref=\"amPmScrollRef\"\n                theme={mergedTheme.peers.Scrollbar}\n                themeOverrides={mergedTheme.peerOverrides.Scrollbar}\n              >\n                {{\n                  default: () => [\n                    <PanelCol\n                      clsPrefix={mergedClsPrefix}\n                      data={this.amPm}\n                      activeValue={this.amPmValue}\n                      onItemClick={this.onAmPmClick}\n                    />,\n                    <div\n                      class={`${mergedClsPrefix}-time-picker-col__padding`}\n                    />\n                  ]\n                }}\n              </NScrollbar>\n            </div>\n          ) : null}\n        </div>\n        {this.actions?.length ? (\n          <div class={`${mergedClsPrefix}-time-picker-actions`}>\n            {this.actions?.includes('clear') ? (\n              <NButton\n                theme={mergedTheme.peers.Button}\n                themeOverrides={mergedTheme.peerOverrides.Button}\n                size=\"tiny\"\n                onClick={this.onClearClick}\n              >\n                {{ default: () => this.clearText }}\n              </NButton>\n            ) : null}\n            {this.actions?.includes('now') ? (\n              <NButton\n                size=\"tiny\"\n                theme={mergedTheme.peers.Button}\n                themeOverrides={mergedTheme.peerOverrides.Button}\n                onClick={this.onNowClick}\n              >\n                {{ default: () => this.nowText }}\n              </NButton>\n            ) : null}\n            {this.actions?.includes('confirm') ? (\n              <NButton\n                size=\"tiny\"\n                type=\"primary\"\n                class={`${mergedClsPrefix}-time-picker-actions__confirm`}\n                theme={mergedTheme.peers.Button}\n                themeOverrides={mergedTheme.peerOverrides.Button}\n                disabled={this.isValueInvalid}\n                onClick={this.onConfirmClick}\n              >\n                {{ default: () => this.confirmText }}\n              </NButton>\n            ) : null}\n          </div>\n        ) : null}\n        <NBaseFocusDetector onFocus={this.onFocusDetectorFocus} />\n      </div>\n    )\n  }\n})\n"
  },
  {
    "path": "src/time-picker/src/PanelCol.tsx",
    "content": "import type { PropType } from 'vue'\nimport type { Item } from './interface'\nimport { defineComponent, h } from 'vue'\n\nexport default defineComponent({\n  name: 'TimePickerPanelCol',\n  props: {\n    clsPrefix: {\n      type: String,\n      required: true\n    },\n    data: {\n      type: Array as PropType<Item[]>,\n      required: true\n    },\n    activeValue: {\n      type: [Number, String] as PropType<number | null | 'am' | 'pm'>,\n      default: null\n    },\n    // It should be required but vue's type seems to have bugs\n    onItemClick: Function as PropType<(value: number | 'am' | 'pm') => void>\n  },\n  render() {\n    const { activeValue, onItemClick, clsPrefix } = this\n    return this.data.map((item) => {\n      const { label, disabled, value } = item\n      const active = activeValue === value\n      return (\n        <div\n          key={label}\n          data-active={active ? '' : null}\n          class={[\n            `${clsPrefix}-time-picker-col__item`,\n            active && `${clsPrefix}-time-picker-col__item--active`,\n            disabled && `${clsPrefix}-time-picker-col__item--disabled`\n          ]}\n          onClick={\n            onItemClick && !disabled\n              ? () => {\n                  onItemClick(value)\n                }\n              : undefined\n          }\n        >\n          {label}\n        </div>\n      )\n    })\n  }\n})\n"
  },
  {
    "path": "src/time-picker/src/TimePicker.tsx",
    "content": "import type { Locale } from 'date-fns'\nimport type { CSSProperties, PropType, VNode } from 'vue'\nimport type { FollowerPlacement } from 'vueuc'\nimport type { ThemeProps } from '../../_mixins'\nimport type { ExtractPublicPropTypes, MaybeArray } from '../../_utils'\nimport type { FormValidationStatus } from '../../form/src/public-types'\nimport type { InputInst } from '../../input'\nimport type { TimePickerTheme } from '../styles'\nimport type {\n  IsHourDisabled,\n  IsMinuteDisabled,\n  IsSecondDisabled,\n  ItemValue,\n  OnUpdateFormattedValue,\n  OnUpdateFormattedValueImpl,\n  OnUpdateValue,\n  OnUpdateValueImpl,\n  PanelRef,\n  TimePickerInst\n} from './interface'\nimport type { TimePickerSize } from './public-types'\nimport {\n  format,\n  getHours,\n  getMilliseconds,\n  getMinutes,\n  getSeconds,\n  getTime,\n  isValid,\n  set,\n  setHours,\n  setMinutes,\n  setSeconds,\n  startOfHour,\n  startOfMinute,\n  startOfSecond\n} from 'date-fns'\nimport { formatInTimeZone } from 'date-fns-tz'\nimport { getPreciseEventTarget, happensIn } from 'seemly'\nimport { clickoutside } from 'vdirs'\nimport { useIsMounted, useKeyboard, useMergedState } from 'vooks'\nimport {\n  computed,\n  defineComponent,\n  h,\n  nextTick,\n  provide,\n  ref,\n  toRef,\n  Transition,\n  watch,\n  watchEffect,\n  withDirectives\n} from 'vue'\nimport { VBinder, VFollower, VTarget } from 'vueuc'\nimport { NBaseIcon } from '../../_internal'\nimport { TimeIcon } from '../../_internal/icons'\nimport {\n  useConfig,\n  useFormItem,\n  useLocale,\n  useTheme,\n  useThemeClass\n} from '../../_mixins'\nimport {\n  call,\n  markEventEffectPerformed,\n  useAdjustedTo,\n  warnOnce\n} from '../../_utils'\nimport { strictParse } from '../../date-picker/src/utils'\nimport { NInput } from '../../input'\nimport { timePickerLight } from '../styles'\nimport { timePickerInjectionKey } from './interface'\nimport Panel from './Panel'\nimport style from './styles/index.cssr'\nimport { findSimilarTime, isTimeInStep } from './utils'\n\n// validate hours, minutes, seconds prop\nfunction validateUnits(value: MaybeArray<number>, max: number): boolean {\n  if (value === undefined) {\n    return true\n  }\n  if (Array.isArray(value)) {\n    return value.every(v => v >= 0 && v <= max)\n  }\n  else {\n    return value >= 0 && value <= max\n  }\n}\n\nexport const timePickerProps = {\n  ...(useTheme.props as ThemeProps<TimePickerTheme>),\n  to: useAdjustedTo.propTo,\n  bordered: {\n    type: Boolean as PropType<boolean | undefined>,\n    default: undefined\n  },\n  actions: Array as PropType<Array<'clear' | 'now' | 'confirm'> | null>,\n  defaultValue: {\n    type: Number as PropType<number | null>,\n    default: null\n  },\n  defaultFormattedValue: String,\n  placeholder: String,\n  placement: {\n    type: String as PropType<FollowerPlacement>,\n    default: 'bottom-start'\n  },\n  value: Number as PropType<number | null>,\n  format: {\n    type: String,\n    default: 'HH:mm:ss'\n  },\n  valueFormat: String,\n  formattedValue: String as PropType<string | null>,\n  isHourDisabled: Function as PropType<IsHourDisabled>,\n  size: String as PropType<TimePickerSize>,\n  isMinuteDisabled: Function as PropType<IsMinuteDisabled>,\n  isSecondDisabled: Function as PropType<IsSecondDisabled>,\n  inputReadonly: Boolean,\n  clearable: Boolean,\n  status: String as PropType<FormValidationStatus>,\n  'onUpdate:value': [Function, Array] as PropType<MaybeArray<OnUpdateValue>>,\n  onUpdateValue: [Function, Array] as PropType<MaybeArray<OnUpdateValue>>,\n  'onUpdate:show': [Function, Array] as PropType<\n    MaybeArray<(show: boolean) => void>\n  >,\n  onUpdateShow: [Function, Array] as PropType<\n    MaybeArray<(show: boolean) => void>\n  >,\n  onUpdateFormattedValue: [Function, Array] as PropType<\n    MaybeArray<OnUpdateFormattedValue>\n  >,\n  'onUpdate:formattedValue': [Function, Array] as PropType<\n    MaybeArray<OnUpdateFormattedValue>\n  >,\n  onBlur: [Function, Array] as PropType<MaybeArray<(e: FocusEvent) => void>>,\n  onConfirm: [Function, Array] as PropType<\n    MaybeArray<(value: number & null, formattedValue: string & null) => void>\n  >,\n  onClear: Function as PropType<() => void>,\n  onFocus: [Function, Array] as PropType<MaybeArray<(e: FocusEvent) => void>>,\n  // https://www.iana.org/time-zones\n  timeZone: String,\n  showIcon: {\n    type: Boolean,\n    default: true\n  },\n  disabled: {\n    type: Boolean as PropType<boolean | undefined>,\n    default: undefined\n  },\n  show: {\n    type: Boolean as PropType<boolean | undefined>,\n    default: undefined\n  },\n  hours: {\n    type: [Number, Array] as PropType<MaybeArray<number>>,\n    validator: (value: MaybeArray<number>) => validateUnits(value, 23)\n  },\n  minutes: {\n    type: [Number, Array] as PropType<MaybeArray<number>>,\n    validator: (value: MaybeArray<number>) => validateUnits(value, 59)\n  },\n  seconds: {\n    type: [Number, Array] as PropType<MaybeArray<number>>,\n    validator: (value: MaybeArray<number>) => validateUnits(value, 59)\n  },\n  use12Hours: Boolean,\n  // private\n  stateful: {\n    type: Boolean,\n    default: true\n  },\n  // deprecated\n  onChange: [Function, Array] as PropType<MaybeArray<OnUpdateValue> | undefined>\n}\n\nexport type TimePickerProps = ExtractPublicPropTypes<typeof timePickerProps>\n\nexport interface TimePickerSlots {\n  default?: () => VNode[]\n  icon?: () => VNode[]\n}\n\nexport default defineComponent({\n  name: 'TimePicker',\n  props: timePickerProps,\n  setup(props) {\n    if (__DEV__) {\n      watchEffect(() => {\n        if (props.onChange !== undefined) {\n          warnOnce(\n            'time-picker',\n            '`on-change` is deprecated, please use `on-update:value` instead.'\n          )\n        }\n      })\n    }\n\n    const {\n      mergedBorderedRef,\n      mergedClsPrefixRef,\n      namespaceRef,\n      inlineThemeDisabled,\n      mergedComponentPropsRef\n    } = useConfig(props)\n    const { localeRef, dateLocaleRef } = useLocale('TimePicker')\n    const formItem = useFormItem(props, {\n      mergedSize: (NFormItem) => {\n        const { size } = props\n        if (size)\n          return size\n        const { mergedSize: formItemSize } = NFormItem || {}\n        if (formItemSize?.value)\n          return formItemSize.value as TimePickerSize\n        const configSize = mergedComponentPropsRef?.value?.TimePicker?.size\n        if (configSize)\n          return configSize\n        return 'medium'\n      }\n    })\n    const { mergedSizeRef, mergedDisabledRef, mergedStatusRef } = formItem\n    const themeRef = useTheme(\n      'TimePicker',\n      '-time-picker',\n      style,\n      timePickerLight,\n      props,\n      mergedClsPrefixRef\n    )\n\n    const keyboardState = useKeyboard()\n\n    const inputInstRef = ref<InputInst | null>(null)\n    const panelInstRef = ref<PanelRef | null>(null)\n\n    const dateFnsOptionsRef = computed(() => {\n      return {\n        locale: dateLocaleRef.value.locale\n      }\n    })\n\n    function getTimestampFromFormattedValue(\n      value: string | null\n    ): number | null {\n      if (value === null)\n        return null\n      return strictParse(\n        value,\n        props.valueFormat || props.format,\n        new Date(),\n        dateFnsOptionsRef.value\n      ).getTime()\n    }\n\n    const { defaultValue, defaultFormattedValue } = props\n\n    const uncontrolledValueRef = ref(\n      defaultFormattedValue !== undefined\n        ? getTimestampFromFormattedValue(defaultFormattedValue)\n        : defaultValue\n    )\n    const mergedValueRef = computed(() => {\n      const { formattedValue } = props\n      if (formattedValue !== undefined) {\n        return getTimestampFromFormattedValue(formattedValue)\n      }\n      const { value } = props\n      if (value !== undefined) {\n        return value\n      }\n      return uncontrolledValueRef.value\n    })\n\n    const mergedFormatRef = computed(() => {\n      const { timeZone } = props\n      if (timeZone) {\n        return (\n          date: Date | number,\n          format: string,\n          options?: {\n            locale?: Locale\n          }\n        ) => {\n          return formatInTimeZone(date, timeZone, format, options)\n        }\n      }\n      else {\n        return (\n          date: Date | number,\n          _format: string,\n          options?: {\n            locale?: Locale\n          }\n        ) => {\n          return format(date, _format, options)\n        }\n      }\n    })\n\n    const displayTimeStringRef = ref('')\n    watch(\n      () => props.timeZone,\n      () => {\n        const mergedValue = mergedValueRef.value\n        displayTimeStringRef.value\n          = mergedValue === null\n            ? ''\n            : mergedFormatRef.value(\n                mergedValue,\n                props.format,\n                dateFnsOptionsRef.value\n              )\n      },\n      {\n        immediate: true\n      }\n    )\n    const uncontrolledShowRef = ref(false)\n    const controlledShowRef = toRef(props, 'show')\n    const mergedShowRef = useMergedState(controlledShowRef, uncontrolledShowRef)\n    const memorizedValueRef = ref(mergedValueRef.value)\n    const transitionDisabledRef = ref(false)\n\n    const localizedClearRef = computed(() => {\n      return localeRef.value.clear\n    })\n    const localizedNowRef = computed(() => {\n      return localeRef.value.now\n    })\n    const localizedPlaceholderRef = computed(() => {\n      if (props.placeholder !== undefined)\n        return props.placeholder\n      return localeRef.value.placeholder\n    })\n    const localizedNegativeTextRef = computed(() => {\n      return localeRef.value.negativeText\n    })\n    const localizedPositiveTextRef = computed(() => {\n      return localeRef.value.positiveText\n    })\n    const hourInFormatRef = computed(() => {\n      return /H|h|K|k/.test(props.format)\n    })\n    const minuteInFormatRef = computed(() => {\n      return props.format.includes('m')\n    })\n    const secondInFormatRef = computed(() => {\n      return props.format.includes('s')\n    })\n    const hourValueRef = computed(() => {\n      const { value } = mergedValueRef\n      if (value === null)\n        return null\n      return Number(mergedFormatRef.value(value, 'HH', dateFnsOptionsRef.value))\n    })\n    const minuteValueRef = computed(() => {\n      const { value } = mergedValueRef\n      if (value === null)\n        return null\n      return Number(mergedFormatRef.value(value, 'mm', dateFnsOptionsRef.value))\n    })\n    const secondValueRef = computed(() => {\n      const { value } = mergedValueRef\n      if (value === null)\n        return null\n      return Number(mergedFormatRef.value(value, 'ss', dateFnsOptionsRef.value))\n    })\n    const isHourInvalidRef = computed(() => {\n      const { isHourDisabled } = props\n      if (hourValueRef.value === null)\n        return false\n      if (!isTimeInStep(hourValueRef.value, 'hours', props.hours))\n        return true\n      if (!isHourDisabled)\n        return false\n      return isHourDisabled(hourValueRef.value)\n    })\n    const isMinuteInvalidRef = computed(() => {\n      const { value: minuteValue } = minuteValueRef\n      const { value: hourValue } = hourValueRef\n      if (minuteValue === null || hourValue === null)\n        return false\n      if (!isTimeInStep(minuteValue, 'minutes', props.minutes))\n        return true\n      const { isMinuteDisabled } = props\n      if (!isMinuteDisabled)\n        return false\n      return isMinuteDisabled(minuteValue, hourValue)\n    })\n    const isSecondInvalidRef = computed(() => {\n      const { value: minuteValue } = minuteValueRef\n      const { value: hourValue } = hourValueRef\n      const { value: secondValue } = secondValueRef\n      if (secondValue === null || minuteValue === null || hourValue === null) {\n        return false\n      }\n      if (!isTimeInStep(secondValue, 'seconds', props.seconds))\n        return true\n      const { isSecondDisabled } = props\n      if (!isSecondDisabled)\n        return false\n      return isSecondDisabled(secondValue, minuteValue, hourValue)\n    })\n    const isValueInvalidRef = computed(() => {\n      return (\n        isHourInvalidRef.value\n        || isMinuteInvalidRef.value\n        || isSecondInvalidRef.value\n      )\n    })\n    const mergedAttrSizeRef = computed(() => {\n      return props.format.length + 4\n    })\n    const amPmValueRef = computed(() => {\n      const { value } = mergedValueRef\n      if (value === null)\n        return null\n      return getHours(value) < 12 ? 'am' : 'pm'\n    })\n    function doUpdateFormattedValue(\n      value: string | null,\n      timestampValue: number | null\n    ): void {\n      const {\n        onUpdateFormattedValue,\n        'onUpdate:formattedValue': _onUpdateFormattedValue\n      } = props\n      if (onUpdateFormattedValue) {\n        call(\n          onUpdateFormattedValue as OnUpdateFormattedValueImpl,\n          value,\n          timestampValue\n        )\n      }\n      if (_onUpdateFormattedValue) {\n        call(\n          _onUpdateFormattedValue as OnUpdateFormattedValueImpl,\n          value,\n          timestampValue\n        )\n      }\n    }\n    function createFormattedValue(value: number | null): string | null {\n      return value === null\n        ? null\n        : mergedFormatRef.value(value, props.valueFormat || props.format)\n    }\n    function doUpdateValue(value: number | null): void {\n      const {\n        onUpdateValue,\n        'onUpdate:value': _onUpdateValue,\n        onChange\n      } = props\n      const { nTriggerFormChange, nTriggerFormInput } = formItem\n      const formattedValue = createFormattedValue(value)\n      if (onUpdateValue) {\n        call(onUpdateValue as OnUpdateValueImpl, value, formattedValue)\n      }\n      if (_onUpdateValue) {\n        call(_onUpdateValue as OnUpdateValueImpl, value, formattedValue)\n      }\n      if (onChange)\n        call(onChange as OnUpdateValueImpl, value, formattedValue)\n      doUpdateFormattedValue(formattedValue, value)\n      uncontrolledValueRef.value = value\n      nTriggerFormChange()\n      nTriggerFormInput()\n    }\n    function doFocus(e: FocusEvent): void {\n      const { onFocus } = props\n      const { nTriggerFormFocus } = formItem\n      if (onFocus)\n        call(onFocus, e)\n      nTriggerFormFocus()\n    }\n    function doBlur(e: FocusEvent): void {\n      const { onBlur } = props\n      const { nTriggerFormBlur } = formItem\n      if (onBlur)\n        call(onBlur, e)\n      nTriggerFormBlur()\n    }\n    function doConfirm(): void {\n      const { onConfirm } = props\n      if (onConfirm) {\n        call(\n          onConfirm,\n          mergedValueRef.value as number & null,\n          createFormattedValue(mergedValueRef.value) as string & null\n        )\n      }\n    }\n    function handleTimeInputClear(e: MouseEvent): void {\n      e.stopPropagation()\n      doUpdateValue(null)\n      deriveInputValue(null)\n      props.onClear?.()\n    }\n    function handleFocusDetectorFocus(): void {\n      closePanel({\n        returnFocus: true\n      })\n    }\n    // clear selected time\n    function clearSelectedValue(): void {\n      doUpdateValue(null)\n      deriveInputValue(null)\n      closePanel({\n        returnFocus: true\n      })\n    }\n    function handleInputKeydown(e: KeyboardEvent): void {\n      if (e.key === 'Escape' && mergedShowRef.value) {\n        markEventEffectPerformed(e)\n        // closePanel will be called in onDeactivated\n      }\n    }\n    function handleMenuKeydown(e: KeyboardEvent): void {\n      switch (e.key) {\n        case 'Escape':\n          if (mergedShowRef.value) {\n            markEventEffectPerformed(e)\n            closePanel({\n              returnFocus: true\n            })\n          }\n          break\n        case 'Tab':\n          if (keyboardState.shift && e.target === panelInstRef.value?.$el) {\n            e.preventDefault()\n            closePanel({\n              returnFocus: true\n            })\n          }\n          break\n      }\n    }\n    function disableTransitionOneTick(): void {\n      transitionDisabledRef.value = true\n      void nextTick(() => {\n        transitionDisabledRef.value = false\n      })\n    }\n    function handleTriggerClick(e: MouseEvent): void {\n      if (mergedDisabledRef.value || happensIn(e, 'clear'))\n        return\n      if (!mergedShowRef.value) {\n        openPanel()\n      }\n    }\n    function handleHourClick(hour: ItemValue): void {\n      if (typeof hour === 'string')\n        return\n      if (mergedValueRef.value === null) {\n        doUpdateValue(getTime(setHours(startOfHour(new Date()), hour)))\n      }\n      else {\n        doUpdateValue(getTime(setHours(mergedValueRef.value, hour)))\n      }\n    }\n    function handleMinuteClick(minute: ItemValue): void {\n      if (typeof minute === 'string')\n        return\n      if (mergedValueRef.value === null) {\n        doUpdateValue(getTime(setMinutes(startOfMinute(new Date()), minute)))\n      }\n      else {\n        doUpdateValue(getTime(setMinutes(mergedValueRef.value, minute)))\n      }\n    }\n    function handleSecondClick(second: ItemValue): void {\n      if (typeof second === 'string')\n        return\n      if (mergedValueRef.value === null) {\n        doUpdateValue(getTime(setSeconds(startOfSecond(new Date()), second)))\n      }\n      else {\n        doUpdateValue(getTime(setSeconds(mergedValueRef.value, second)))\n      }\n    }\n    function handleAmPmClick(amPm: ItemValue): void {\n      const { value: mergedValue } = mergedValueRef\n      if (mergedValue === null) {\n        const now = new Date()\n        const hours = getHours(now)\n        if (amPm === 'pm' && hours < 12) {\n          doUpdateValue(getTime(setHours(now, hours + 12)))\n        }\n        else if (amPm === 'am' && hours >= 12) {\n          doUpdateValue(getTime(setHours(now, hours - 12)))\n        }\n        doUpdateValue(getTime(now))\n      }\n      else {\n        const hours = getHours(mergedValue)\n        if (amPm === 'pm' && hours < 12) {\n          doUpdateValue(getTime(setHours(mergedValue, hours + 12)))\n        }\n        else if (amPm === 'am' && hours >= 12) {\n          doUpdateValue(getTime(setHours(mergedValue, hours - 12)))\n        }\n      }\n    }\n    function deriveInputValue(time?: null | number): void {\n      if (time === undefined)\n        time = mergedValueRef.value\n      if (time === null) {\n        displayTimeStringRef.value = ''\n      }\n      else {\n        displayTimeStringRef.value = mergedFormatRef.value(\n          time,\n          props.format,\n          dateFnsOptionsRef.value\n        )\n      }\n    }\n    function handleTimeInputFocus(e: FocusEvent): void {\n      if (isInternalFocusSwitch(e))\n        return\n      doFocus(e)\n    }\n    function handleTimeInputBlur(e: FocusEvent): void {\n      if (isInternalFocusSwitch(e))\n        return\n      if (mergedShowRef.value) {\n        const panelEl = panelInstRef.value?.$el\n        if (!panelEl?.contains(e.relatedTarget as Node)) {\n          deriveInputValue()\n          doBlur(e)\n          closePanel({\n            returnFocus: false\n          })\n        }\n      }\n      else {\n        deriveInputValue()\n        doBlur(e)\n      }\n    }\n\n    function handleTimeInputActivate(): void {\n      if (mergedDisabledRef.value)\n        return\n      if (!mergedShowRef.value) {\n        openPanel()\n      }\n    }\n    function handleTimeInputDeactivate(): void {\n      if (mergedDisabledRef.value)\n        return\n      deriveInputValue()\n      closePanel({\n        returnFocus: false\n      })\n    }\n    function scrollTimer(): void {\n      if (!panelInstRef.value)\n        return\n      const { hourScrollRef, minuteScrollRef, secondScrollRef, amPmScrollRef }\n        = panelInstRef.value\n      ;[hourScrollRef, minuteScrollRef, secondScrollRef, amPmScrollRef].forEach(\n        (itemScrollRef) => {\n          if (!itemScrollRef)\n            return\n          const activeItemEl\n            = itemScrollRef.contentRef?.querySelector('[data-active]')\n          if (activeItemEl) {\n            itemScrollRef.scrollTo({\n              top: (activeItemEl as HTMLElement).offsetTop\n            })\n          }\n        }\n      )\n    }\n    function doUpdateShow(value: boolean): void {\n      uncontrolledShowRef.value = value\n      const { onUpdateShow, 'onUpdate:show': _onUpdateShow } = props\n      if (onUpdateShow)\n        call(onUpdateShow, value)\n      if (_onUpdateShow)\n        call(_onUpdateShow, value)\n    }\n    function isInternalFocusSwitch(e: FocusEvent): boolean {\n      return !!(\n        inputInstRef.value?.wrapperElRef?.contains(e.relatedTarget as Node)\n        || panelInstRef.value?.$el.contains(e.relatedTarget as Node)\n      )\n    }\n    function openPanel(): void {\n      memorizedValueRef.value = mergedValueRef.value\n      doUpdateShow(true)\n      void nextTick(scrollTimer)\n    }\n    function handleClickOutside(e: MouseEvent): void {\n      if (\n        mergedShowRef.value\n        && !inputInstRef.value?.wrapperElRef?.contains(\n          getPreciseEventTarget(e) as Node | null\n        )\n      ) {\n        closePanel({\n          returnFocus: false\n        })\n      }\n    }\n    function closePanel({ returnFocus }: { returnFocus: boolean }): void {\n      if (mergedShowRef.value) {\n        doUpdateShow(false)\n        if (returnFocus) {\n          inputInstRef.value?.focus()\n        }\n      }\n    }\n    function handleTimeInputUpdateValue(v: string): void {\n      if (v === '') {\n        doUpdateValue(null)\n        return\n      }\n      const time = strictParse(\n        v,\n        props.format,\n        new Date(),\n        dateFnsOptionsRef.value\n      )\n      displayTimeStringRef.value = v\n      if (isValid(time)) {\n        const { value: mergedValue } = mergedValueRef\n        if (mergedValue !== null) {\n          const newTime = set(mergedValue, {\n            hours: getHours(time),\n            minutes: getMinutes(time),\n            seconds: getSeconds(time),\n            milliseconds: getMilliseconds(time)\n          })\n          doUpdateValue(getTime(newTime))\n        }\n        else {\n          doUpdateValue(getTime(time))\n        }\n      }\n    }\n    function handleCancelClick(): void {\n      doUpdateValue(memorizedValueRef.value)\n      doUpdateShow(false)\n    }\n    function handleNowClick(): void {\n      const now = new Date()\n      const getNowTime = {\n        hours: getHours,\n        minutes: getMinutes,\n        seconds: getSeconds\n      }\n      const [mergeHours, mergeMinutes, mergeSeconds] = (\n        ['hours', 'minutes', 'seconds'] as const\n      ).map(i =>\n        !props[i] || isTimeInStep(getNowTime[i](now), i, props[i])\n          ? getNowTime[i](now)\n          : findSimilarTime(getNowTime[i](now), i, props[i])\n      )\n      const newValue = setSeconds(\n        setMinutes(\n          setHours(\n            mergedValueRef.value ? mergedValueRef.value : getTime(now),\n            mergeHours\n          ),\n          mergeMinutes\n        ),\n        mergeSeconds\n      )\n      doUpdateValue(getTime(newValue))\n    }\n    function handleConfirmClick(): void {\n      deriveInputValue()\n      doConfirm()\n      closePanel({\n        returnFocus: true\n      })\n    }\n    function handleMenuFocusOut(e: FocusEvent): void {\n      if (isInternalFocusSwitch(e))\n        return\n      deriveInputValue()\n      doBlur(e)\n      closePanel({\n        returnFocus: false\n      })\n    }\n    watch(mergedValueRef, (value) => {\n      deriveInputValue(value)\n      disableTransitionOneTick()\n      void nextTick(scrollTimer)\n    })\n    watch(mergedShowRef, () => {\n      if (isValueInvalidRef.value) {\n        doUpdateValue(memorizedValueRef.value)\n      }\n    })\n    provide(timePickerInjectionKey, {\n      mergedThemeRef: themeRef,\n      mergedClsPrefixRef\n    })\n    const exposedMethods: TimePickerInst = {\n      focus: () => {\n        inputInstRef.value?.focus()\n      },\n      blur: () => {\n        inputInstRef.value?.blur()\n      }\n    }\n    const triggerCssVarsRef = computed(() => {\n      const {\n        common: { cubicBezierEaseInOut },\n        self: { iconColor, iconColorDisabled }\n      } = themeRef.value\n      return {\n        '--n-icon-color-override': iconColor,\n        '--n-icon-color-disabled-override': iconColorDisabled,\n        '--n-bezier': cubicBezierEaseInOut\n      }\n    })\n    const triggerThemeClassHandle = inlineThemeDisabled\n      ? useThemeClass(\n          'time-picker-trigger',\n          undefined,\n          triggerCssVarsRef,\n          props\n        )\n      : undefined\n    const cssVarsRef = computed(() => {\n      const {\n        self: {\n          panelColor,\n          itemTextColor,\n          itemTextColorActive,\n          itemColorHover,\n          panelDividerColor,\n          panelBoxShadow,\n          itemOpacityDisabled,\n          borderRadius,\n          itemFontSize,\n          itemWidth,\n          itemHeight,\n          panelActionPadding,\n          itemBorderRadius\n        },\n        common: { cubicBezierEaseInOut }\n      } = themeRef.value\n      return {\n        '--n-bezier': cubicBezierEaseInOut,\n        '--n-border-radius': borderRadius,\n        '--n-item-color-hover': itemColorHover,\n        '--n-item-font-size': itemFontSize,\n        '--n-item-height': itemHeight,\n        '--n-item-opacity-disabled': itemOpacityDisabled,\n        '--n-item-text-color': itemTextColor,\n        '--n-item-text-color-active': itemTextColorActive,\n        '--n-item-width': itemWidth,\n        '--n-panel-action-padding': panelActionPadding,\n        '--n-panel-box-shadow': panelBoxShadow,\n        '--n-panel-color': panelColor,\n        '--n-panel-divider-color': panelDividerColor,\n        '--n-item-border-radius': itemBorderRadius\n      }\n    })\n    const themeClassHandle = inlineThemeDisabled\n      ? useThemeClass('time-picker', undefined, cssVarsRef, props)\n      : undefined\n    return {\n      focus: exposedMethods.focus,\n      blur: exposedMethods.blur,\n      mergedStatus: mergedStatusRef,\n      mergedBordered: mergedBorderedRef,\n      mergedClsPrefix: mergedClsPrefixRef,\n      namespace: namespaceRef,\n      uncontrolledValue: uncontrolledValueRef,\n      mergedValue: mergedValueRef,\n      isMounted: useIsMounted(),\n      inputInstRef,\n      panelInstRef,\n      adjustedTo: useAdjustedTo(props),\n      mergedShow: mergedShowRef,\n      localizedClear: localizedClearRef,\n      localizedNow: localizedNowRef,\n      localizedPlaceholder: localizedPlaceholderRef,\n      localizedNegativeText: localizedNegativeTextRef,\n      localizedPositiveText: localizedPositiveTextRef,\n      hourInFormat: hourInFormatRef,\n      minuteInFormat: minuteInFormatRef,\n      secondInFormat: secondInFormatRef,\n      mergedAttrSize: mergedAttrSizeRef,\n      displayTimeString: displayTimeStringRef,\n      mergedSize: mergedSizeRef,\n      mergedDisabled: mergedDisabledRef,\n      isValueInvalid: isValueInvalidRef,\n      isHourInvalid: isHourInvalidRef,\n      isMinuteInvalid: isMinuteInvalidRef,\n      isSecondInvalid: isSecondInvalidRef,\n      transitionDisabled: transitionDisabledRef,\n      hourValue: hourValueRef,\n      minuteValue: minuteValueRef,\n      secondValue: secondValueRef,\n      amPmValue: amPmValueRef,\n      handleInputKeydown,\n      handleTimeInputFocus,\n      handleTimeInputBlur,\n      handleNowClick,\n      handleConfirmClick,\n      handleTimeInputUpdateValue,\n      handleMenuFocusOut,\n      handleCancelClick,\n      handleClickOutside,\n      handleTimeInputActivate,\n      handleTimeInputDeactivate,\n      handleHourClick,\n      handleMinuteClick,\n      handleSecondClick,\n      handleAmPmClick,\n      handleTimeInputClear,\n      handleFocusDetectorFocus,\n      handleMenuKeydown,\n      handleTriggerClick,\n      mergedTheme: themeRef,\n      triggerCssVars: inlineThemeDisabled ? undefined : triggerCssVarsRef,\n      triggerThemeClass: triggerThemeClassHandle?.themeClass,\n      triggerOnRender: triggerThemeClassHandle?.onRender,\n      cssVars: inlineThemeDisabled ? undefined : cssVarsRef,\n      themeClass: themeClassHandle?.themeClass,\n      onRender: themeClassHandle?.onRender,\n      clearSelectedValue\n    }\n  },\n  render() {\n    const { mergedClsPrefix, $slots, triggerOnRender } = this\n    triggerOnRender?.()\n    return (\n      <div\n        class={[`${mergedClsPrefix}-time-picker`, this.triggerThemeClass]}\n        style={this.triggerCssVars as CSSProperties}\n      >\n        <VBinder>\n          {{\n            default: () => [\n              <VTarget>\n                {{\n                  default: () => (\n                    <NInput\n                      ref=\"inputInstRef\"\n                      status={this.mergedStatus}\n                      value={this.displayTimeString}\n                      bordered={this.mergedBordered}\n                      passivelyActivated\n                      attrSize={this.mergedAttrSize}\n                      theme={this.mergedTheme.peers.Input}\n                      themeOverrides={this.mergedTheme.peerOverrides.Input}\n                      stateful={this.stateful}\n                      size={this.mergedSize}\n                      placeholder={this.localizedPlaceholder}\n                      clearable={this.clearable}\n                      disabled={this.mergedDisabled}\n                      textDecoration={\n                        this.isValueInvalid ? 'line-through' : undefined\n                      }\n                      onFocus={this.handleTimeInputFocus}\n                      onBlur={this.handleTimeInputBlur}\n                      onActivate={this.handleTimeInputActivate}\n                      onDeactivate={this.handleTimeInputDeactivate}\n                      onUpdateValue={this.handleTimeInputUpdateValue}\n                      onClear={this.handleTimeInputClear}\n                      internalDeactivateOnEnter\n                      internalForceFocus={this.mergedShow}\n                      readonly={this.inputReadonly || this.mergedDisabled}\n                      onClick={this.handleTriggerClick}\n                      onKeydown={this.handleInputKeydown}\n                    >\n                      {this.showIcon\n                        ? {\n                            [this.clearable\n                              ? 'clear-icon-placeholder'\n                              : 'suffix']: () => (\n                              <NBaseIcon\n                                clsPrefix={mergedClsPrefix}\n                                class={`${mergedClsPrefix}-time-picker-icon`}\n                              >\n                                {{\n                                  default: () =>\n                                    $slots.icon ? $slots.icon() : <TimeIcon />\n                                }}\n                              </NBaseIcon>\n                            )\n                          }\n                        : null}\n                    </NInput>\n                  )\n                }}\n              </VTarget>,\n              <VFollower\n                teleportDisabled={this.adjustedTo === useAdjustedTo.tdkey}\n                show={this.mergedShow}\n                to={this.adjustedTo}\n                containerClass={this.namespace}\n                placement={this.placement}\n              >\n                {{\n                  default: () => (\n                    <Transition\n                      name=\"fade-in-scale-up-transition\"\n                      appear={this.isMounted}\n                    >\n                      {{\n                        default: () => {\n                          if (this.mergedShow) {\n                            this.onRender?.()\n                            return withDirectives(\n                              <Panel\n                                ref=\"panelInstRef\"\n                                actions={this.actions}\n                                class={this.themeClass}\n                                style={this.cssVars as CSSProperties}\n                                seconds={this.seconds}\n                                minutes={this.minutes}\n                                hours={this.hours}\n                                transitionDisabled={this.transitionDisabled}\n                                hourValue={this.hourValue}\n                                showHour={this.hourInFormat}\n                                isHourInvalid={this.isHourInvalid}\n                                isHourDisabled={this.isHourDisabled}\n                                minuteValue={this.minuteValue}\n                                showMinute={this.minuteInFormat}\n                                isMinuteInvalid={this.isMinuteInvalid}\n                                isMinuteDisabled={this.isMinuteDisabled}\n                                secondValue={this.secondValue}\n                                amPmValue={this.amPmValue}\n                                showSecond={this.secondInFormat}\n                                isSecondInvalid={this.isSecondInvalid}\n                                isSecondDisabled={this.isSecondDisabled}\n                                isValueInvalid={this.isValueInvalid}\n                                clearText={this.localizedClear}\n                                nowText={this.localizedNow}\n                                confirmText={this.localizedPositiveText}\n                                use12Hours={this.use12Hours}\n                                onFocusout={this.handleMenuFocusOut}\n                                onKeydown={this.handleMenuKeydown}\n                                onHourClick={this.handleHourClick}\n                                onMinuteClick={this.handleMinuteClick}\n                                onSecondClick={this.handleSecondClick}\n                                onAmPmClick={this.handleAmPmClick}\n                                onNowClick={this.handleNowClick}\n                                onConfirmClick={this.handleConfirmClick}\n                                onClearClick={this.clearSelectedValue}\n                                onFocusDetectorFocus={\n                                  this.handleFocusDetectorFocus\n                                }\n                              />,\n                              [\n                                [\n                                  clickoutside,\n                                  this.handleClickOutside,\n                                  undefined as unknown as string,\n                                  { capture: true }\n                                ]\n                              ]\n                            )\n                          }\n                          return null\n                        }\n                      }}\n                    </Transition>\n                  )\n                }}\n              </VFollower>\n            ]\n          }}\n        </VBinder>\n      </div>\n    )\n  }\n})\n"
  },
  {
    "path": "src/time-picker/src/interface.ts",
    "content": "import type { Ref } from 'vue'\nimport type { ScrollbarInst } from '../../_internal'\nimport type { MergedTheme } from '../../_mixins'\nimport type { TimePickerTheme } from '../styles'\nimport { createInjectionKey } from '../../_utils'\n\nexport type ItemValue = number | 'am' | 'pm'\n\nexport interface Item {\n  label: string\n  value: ItemValue\n  disabled: boolean\n}\n\nexport interface TimePickerInjection {\n  mergedThemeRef: Ref<MergedTheme<TimePickerTheme>>\n  mergedClsPrefixRef: Ref<string>\n}\n\nexport const timePickerInjectionKey\n  = createInjectionKey<TimePickerInjection>('n-time-picker')\n\nexport interface PanelRef {\n  $el: HTMLElement\n  hourScrollRef?: ScrollbarInst\n  minuteScrollRef?: ScrollbarInst\n  secondScrollRef?: ScrollbarInst\n  amPmScrollRef?: ScrollbarInst\n}\n\nexport type OnUpdateValue = ((value: number, formattedValue: string) => void)\n  & ((value: number | null, formattedValue: string | null) => void)\nexport type OnUpdateValueImpl = (\n  value: number | null,\n  formattedValue: string | null\n) => void\n\nexport type OnUpdateFormattedValue = ((\n  value: string,\n  timestampValue: number\n) => void)\n& ((value: string | null, timestampValue: number | null) => void)\nexport type OnUpdateFormattedValueImpl = (\n  value: string | null,\n  timestampValue: number | null\n) => void\n\nexport type IsHourDisabled = (hour: number) => boolean\nexport type IsMinuteDisabled = (minute: number, hour: number | null) => boolean\nexport type IsSecondDisabled = (\n  second: number,\n  minute: number | null,\n  hour: number | null\n) => boolean\n\nexport interface TimePickerInst {\n  focus: () => void\n  blur: () => void\n}\n"
  },
  {
    "path": "src/time-picker/src/public-types.ts",
    "content": "export type TimePickerSize = 'small' | 'medium' | 'large'\n"
  },
  {
    "path": "src/time-picker/src/styles/index.cssr.ts",
    "content": "import { fadeInScaleUpTransition } from '../../../_styles/transitions/fade-in-scale-up.cssr'\nimport { c, cB, cE, cM, cNotM } from '../../../_utils/cssr'\n\n// vars:\n// --n-icon-color-override\n// --n-icon-color-disabled-override\n// --n-bezier\n// --n-border-radius\n// --n-item-color-hover\n// --n-item-font-size\n// --n-item-height\n// --n-item-opacity-disabled\n// --n-item-text-color\n// --n-item-text-color-active\n// --n-item-width\n// --n-panel-action-padding\n// --n-panel-box-shadow\n// --n-panel-color\n// --n-panel-divider-color\n// --n-item-border-radius\nexport default c([\n  cB('time-picker', `\n    z-index: auto;\n    position: relative;\n  `, [\n    cB('time-picker-icon', `\n      color: var(--n-icon-color-override);\n      transition: color .3s var(--n-bezier);\n    `),\n    cM('disabled', [\n      cB('time-picker-icon', `\n        color: var(--n-icon-color-disabled-override);\n      `)\n    ])\n  ]),\n  cB('time-picker-panel', `\n    transition:\n      box-shadow .3s var(--n-bezier),\n      background-color .3s var(--n-bezier);\n    outline: none;\n    font-size: var(--n-item-font-size);\n    border-radius: var(--n-border-radius);\n    margin: 4px 0;\n    min-width: 104px;\n    overflow: hidden;\n    background-color: var(--n-panel-color);\n    box-shadow: var(--n-panel-box-shadow);\n  `, [\n    fadeInScaleUpTransition(),\n    cB('time-picker-actions', `\n      padding: var(--n-panel-action-padding);\n      align-items: center;\n      display: flex;\n      justify-content: space-evenly;\n    `),\n    cB('time-picker-cols', `\n      height: calc(var(--n-item-height) * 6);\n      display: flex;\n      position: relative;\n      transition: border-color .3s var(--n-bezier);\n      border-bottom: 1px solid var(--n-panel-divider-color);\n    `),\n    cB('time-picker-col', `\n      flex-grow: 1;\n      min-width: var(--n-item-width);\n      height: calc(var(--n-item-height) * 6);\n      flex-direction: column;\n      transition: box-shadow .3s var(--n-bezier);\n    `, [\n      cM('transition-disabled', [\n        cE('item', 'transition: none;', [\n          c('&::before', 'transition: none;')\n        ])\n      ]),\n      cE('padding', `\n        height: calc(var(--n-item-height) * 5);\n      `),\n      c('&:first-child', 'min-width: calc(var(--n-item-width) + 4px);', [\n        cE('item', [\n          c('&::before', 'left: 4px;')\n        ])\n      ]),\n      cE('item', `\n        cursor: pointer;\n        height: var(--n-item-height);\n        display: flex;\n        align-items: center;\n        justify-content: center;\n        transition: \n          color .3s var(--n-bezier),\n          background-color .3s var(--n-bezier),\n          opacity .3s var(--n-bezier),\n          text-decoration-color .3s var(--n-bezier);\n        background: #0000;\n        text-decoration-color: #0000;\n        color: var(--n-item-text-color);\n        z-index: 0;\n        box-sizing: border-box;\n        padding-top: 4px;\n        position: relative;\n      `, [\n        c('&::before', `\n          content: \"\";\n          transition: background-color .3s var(--n-bezier);\n          z-index: -1;\n          position: absolute;\n          left: 0;\n          right: 4px;\n          top: 4px;\n          bottom: 0;\n          border-radius: var(--n-item-border-radius);\n        `),\n        cNotM('disabled', [\n          c('&:hover::before', `\n            background-color: var(--n-item-color-hover);\n          `)\n        ]),\n        cM('active', `\n          color: var(--n-item-text-color-active);\n        `, [\n          c('&::before', `\n            background-color: var(--n-item-color-hover);\n          `)\n        ]),\n        cM('disabled', `\n          opacity: var(--n-item-opacity-disabled);\n          cursor: not-allowed;\n        `)\n      ]),\n      cM('invalid', [\n        cE('item', [\n          cM('active', `\n            text-decoration: line-through;\n            text-decoration-color: var(--n-item-text-color-active);\n          `)\n        ])\n      ])\n    ])\n  ])\n])\n"
  },
  {
    "path": "src/time-picker/src/utils.ts",
    "content": "import type { MaybeArray } from '../../_utils'\nimport { getHours } from 'date-fns'\nimport { throwError } from '../../_utils'\n\nexport const time = {\n  amHours: [\n    '00',\n    '01',\n    '02',\n    '03',\n    '04',\n    '05',\n    '06',\n    '07',\n    '08',\n    '09',\n    '10',\n    '11'\n  ],\n  pmHours: [\n    '12',\n    '01',\n    '02',\n    '03',\n    '04',\n    '05',\n    '06',\n    '07',\n    '08',\n    '09',\n    '10',\n    '11'\n  ],\n  hours: [\n    '00',\n    '01',\n    '02',\n    '03',\n    '04',\n    '05',\n    '06',\n    '07',\n    '08',\n    '09',\n    '10',\n    '11',\n    '12',\n    '13',\n    '14',\n    '15',\n    '16',\n    '17',\n    '18',\n    '19',\n    '20',\n    '21',\n    '22',\n    '23'\n  ],\n  minutes: [\n    '00',\n    '01',\n    '02',\n    '03',\n    '04',\n    '05',\n    '06',\n    '07',\n    '08',\n    '09',\n    '10',\n    '11',\n    '12',\n    '13',\n    '14',\n    '15',\n    '16',\n    '17',\n    '18',\n    '19',\n    '20',\n    '21',\n    '22',\n    '23',\n    '24',\n    '25',\n    '26',\n    '27',\n    '28',\n    '29',\n    '30',\n    '31',\n    '32',\n    '33',\n    '34',\n    '35',\n    '36',\n    '37',\n    '38',\n    '39',\n    '40',\n    '41',\n    '42',\n    '43',\n    '44',\n    '45',\n    '46',\n    '47',\n    '48',\n    '49',\n    '50',\n    '51',\n    '52',\n    '53',\n    '54',\n    '55',\n    '56',\n    '57',\n    '58',\n    '59'\n  ],\n  seconds: [\n    '00',\n    '01',\n    '02',\n    '03',\n    '04',\n    '05',\n    '06',\n    '07',\n    '08',\n    '09',\n    '10',\n    '11',\n    '12',\n    '13',\n    '14',\n    '15',\n    '16',\n    '17',\n    '18',\n    '19',\n    '20',\n    '21',\n    '22',\n    '23',\n    '24',\n    '25',\n    '26',\n    '27',\n    '28',\n    '29',\n    '30',\n    '31',\n    '32',\n    '33',\n    '34',\n    '35',\n    '36',\n    '37',\n    '38',\n    '39',\n    '40',\n    '41',\n    '42',\n    '43',\n    '44',\n    '45',\n    '46',\n    '47',\n    '48',\n    '49',\n    '50',\n    '51',\n    '52',\n    '53',\n    '54',\n    '55',\n    '56',\n    '57',\n    '58',\n    '59'\n  ],\n  period: ['AM', 'PM']\n}\n\nexport function getFixValue(value: number): string {\n  return `00${value}`.slice(-2)\n}\n\n// TODO: refactor the logic, it's somehow a patch logic\nexport function getTimeUnits(\n  defaultValue: string[],\n  stepOrList: MaybeArray<number> | undefined,\n  isHourWithAmPm?: 'am' | 'pm'\n): string[] {\n  if (Array.isArray(stepOrList)) {\n    return (\n      isHourWithAmPm === 'am'\n        ? stepOrList.filter(v => v < 12)\n        : isHourWithAmPm === 'pm'\n          ? stepOrList\n              .filter(v => v >= 12)\n              .map(v => (v === 12 ? 12 : v - 12))\n          : stepOrList\n    ).map(v => getFixValue(v))\n  }\n  else if (typeof stepOrList === 'number') {\n    if (isHourWithAmPm === 'am') {\n      return defaultValue.filter((hour) => {\n        const hourAsNumber = Number(hour)\n        return hourAsNumber < 12 && hourAsNumber % stepOrList === 0\n      })\n    }\n    else if (isHourWithAmPm === 'pm') {\n      return defaultValue\n        .filter((hour) => {\n          const hourAsNumber = Number(hour)\n          return hourAsNumber >= 12 && hourAsNumber % stepOrList === 0\n        })\n        .map((hour) => {\n          const hourAsNumber = Number(hour)\n          return getFixValue(hourAsNumber === 12 ? 12 : hourAsNumber - 12)\n        })\n    }\n    return defaultValue.filter((hour) => {\n      return Number(hour) % stepOrList === 0\n    })\n  }\n  else {\n    return isHourWithAmPm === 'am'\n      ? defaultValue.filter(hour => Number(hour) < 12)\n      : isHourWithAmPm === 'pm'\n        ? defaultValue\n            .map(hour => Number(hour))\n            .filter(hour => Number(hour) >= 12)\n            .map(v => getFixValue(v === 12 ? 12 : v - 12))\n        : defaultValue\n  }\n}\n\nexport function isTimeInStep(\n  value: number,\n  type: 'hours' | 'minutes' | 'seconds',\n  stepOrList: MaybeArray<number> | undefined\n): boolean {\n  if (!stepOrList) {\n    return true\n  }\n  else if (typeof stepOrList === 'number') {\n    return value % stepOrList === 0\n  }\n  else {\n    return stepOrList.includes(value)\n  }\n}\n\nexport function findSimilarTime(\n  value: number,\n  type: 'hours' | 'minutes' | 'seconds',\n  stepOrList: MaybeArray<number> | undefined\n): number {\n  const list = getTimeUnits(time[type], stepOrList).map(Number)\n  let lowerBound, upperBound\n  for (let i = 0; i < list.length; ++i) {\n    const v = list[i]\n    if (v === value) {\n      return v\n    }\n    else if (v > value) {\n      upperBound = v\n      break\n    }\n    lowerBound = v\n  }\n  if (lowerBound === undefined) {\n    if (!upperBound) {\n      throwError(\n        'time-picker',\n        'Please set \\'hours\\' or \\'minutes\\' or \\'seconds\\' props'\n      )\n    }\n    return upperBound\n  }\n  if (upperBound === undefined) {\n    return lowerBound\n  }\n  return upperBound - value > value - lowerBound ? lowerBound : upperBound\n}\n\nexport function getAmPm(value: number): 'am' | 'pm' {\n  return getHours(value) < 12 ? 'am' : 'pm'\n}\n"
  },
  {
    "path": "src/time-picker/styles/_common.ts",
    "content": "export default {\n  itemFontSize: '12px',\n  itemHeight: '36px',\n  itemWidth: '52px',\n  panelActionPadding: '8px 0'\n}\n"
  },
  {
    "path": "src/time-picker/styles/dark.ts",
    "content": "import type { TimePickerTheme } from './light'\nimport { scrollbarDark } from '../../_internal/scrollbar/styles'\nimport { commonDark } from '../../_styles/common'\nimport { buttonDark } from '../../button/styles'\nimport { inputDark } from '../../input/styles'\nimport { self } from './light'\n\nconst timePickerDark: TimePickerTheme = {\n  name: 'TimePicker',\n  common: commonDark,\n  peers: {\n    Scrollbar: scrollbarDark,\n    Button: buttonDark,\n    Input: inputDark\n  },\n  self\n}\n\nexport default timePickerDark\n"
  },
  {
    "path": "src/time-picker/styles/index.ts",
    "content": "export { default as timePickerDark } from './dark'\nexport { default as timePickerLight } from './light'\nexport type { TimePickerTheme, TimePickerThemeVars } from './light'\n"
  },
  {
    "path": "src/time-picker/styles/light.ts",
    "content": "import type { ThemeCommonVars } from '../../_styles/common'\nimport { scrollbarLight } from '../../_internal/scrollbar/styles'\nimport { createTheme } from '../../_mixins'\nimport { commonLight } from '../../_styles/common'\nimport { buttonLight } from '../../button/styles'\nimport { inputLight } from '../../input/styles'\nimport commonVars from './_common'\n\nexport function self(vars: ThemeCommonVars) {\n  const {\n    popoverColor,\n    textColor2,\n    primaryColor,\n    hoverColor,\n    dividerColor,\n    opacityDisabled,\n    boxShadow2,\n    borderRadius,\n    iconColor,\n    iconColorDisabled\n  } = vars\n  return {\n    ...commonVars,\n    panelColor: popoverColor,\n    panelBoxShadow: boxShadow2,\n    panelDividerColor: dividerColor,\n    itemTextColor: textColor2,\n    itemTextColorActive: primaryColor,\n    itemColorHover: hoverColor,\n    itemOpacityDisabled: opacityDisabled,\n    itemBorderRadius: borderRadius,\n    borderRadius,\n    iconColor,\n    iconColorDisabled\n  }\n}\n\nexport type TimePickerThemeVars = ReturnType<typeof self>\n\nconst timePickerLight = createTheme({\n  name: 'TimePicker',\n  common: commonLight,\n  peers: {\n    Scrollbar: scrollbarLight,\n    Button: buttonLight,\n    Input: inputLight\n  },\n  self\n})\n\nexport default timePickerLight\nexport type TimePickerTheme = typeof timePickerLight\n"
  },
  {
    "path": "src/time-picker/tests/TimePicker.spec.ts",
    "content": "import { mount } from '@vue/test-utils'\nimport { h } from 'vue'\nimport { NInput } from '../../input'\nimport { NTimePicker } from '../index'\n\ndescribe('n-time-picker', () => {\n  it('should work with import on demand', () => {\n    mount(NTimePicker)\n  })\n\n  it('should work with `actions` prop', async () => {\n    const wrapper = mount(NTimePicker, {\n      attachTo: document.body\n    })\n    await wrapper.find('.n-input').trigger('click')\n    expect(document.querySelectorAll('button').length).toBe(2)\n    expect(document.querySelectorAll('button')[0].textContent).toBe('Now')\n    expect(document.querySelectorAll('button')[1].textContent).toBe('OK')\n    await wrapper.setProps({\n      actions: ['now']\n    })\n    expect(document.querySelectorAll('button').length).toBe(1)\n    expect(document.querySelectorAll('button')[0].textContent).toBe('Now')\n    await wrapper.setProps({\n      actions: ['confirm']\n    })\n    expect(document.querySelectorAll('button').length).toBe(1)\n    expect(document.querySelectorAll('button')[0].textContent).toBe('OK')\n    await wrapper.setProps({\n      actions: []\n    })\n    expect(document.querySelectorAll('button').length).toBe(0)\n    wrapper.unmount()\n  })\n\n  it('should work with `clearable` prop', async () => {\n    const wrapper = mount(NTimePicker)\n    expect(wrapper.find('.n-base-clear').exists()).not.toBe(true)\n    await wrapper.setProps({\n      clearable: true\n    })\n    expect(wrapper.find('.n-base-clear').exists()).toBe(true)\n    wrapper.unmount()\n  })\n\n  it('should work with `disabled` prop', async () => {\n    const wrapper = mount(NTimePicker)\n    expect(wrapper.find('.n-input').attributes('class')).not.toContain(\n      'n-input--disabled'\n    )\n    await wrapper.setProps({\n      disabled: true\n    })\n    expect(wrapper.find('.n-input').attributes('class')).toContain(\n      'n-input--disabled'\n    )\n    wrapper.unmount()\n  })\n\n  it('should work with `format` prop', async () => {\n    const wrapper = mount(NTimePicker, {\n      props: { value: 1642183200000, format: 'h:mm' }\n    })\n    expect(wrapper.find('input').element.value.length).toBe(4)\n    wrapper.unmount()\n  })\n\n  it('should work with `formatted-value` `value-format` prop', async () => {\n    const wrapper = mount(NTimePicker, {\n      props: { formattedValue: '8~30~30', valueFormat: 'H~m~s' }\n    })\n    expect(wrapper.find('input').element.value).toBe('08:30:30')\n    wrapper.unmount()\n  })\n\n  it('should work with `inputReadonly` prop', async () => {\n    const wrapper = mount(NTimePicker)\n    expect(wrapper.find('input').attributes('readonly')).not.toBe('')\n    await wrapper.setProps({\n      inputReadonly: true\n    })\n    expect(wrapper.find('input').attributes('readonly')).toBe('')\n    wrapper.unmount()\n  })\n\n  it('should work with `placeholder` prop', async () => {\n    const wrapper = mount(NTimePicker)\n    expect(wrapper.find('input').attributes('placeholder')).toBe('Select Time')\n    await wrapper.setProps({\n      placeholder: 'test-placeholder'\n    })\n    expect(wrapper.find('input').attributes('placeholder')).toBe(\n      'test-placeholder'\n    )\n    wrapper.unmount()\n  })\n\n  it('should work with `size` prop', async () => {\n    ;(['small', 'medium', 'large'] as const).forEach((item) => {\n      const wrapper = mount(NTimePicker, { props: { size: item } })\n      expect(wrapper.find('.n-input').attributes('style')).toMatchSnapshot()\n      wrapper.unmount()\n    })\n  })\n\n  it('should work with `on-blur` prop', async () => {\n    const onBlur = vi.fn()\n    const wrapper = mount(NTimePicker, {\n      props: { onBlur }\n    })\n    await wrapper.find('input').trigger('focus')\n    await wrapper.find('input').trigger('blur')\n    expect(onBlur).toHaveBeenCalled()\n    wrapper.unmount()\n  })\n  it('should work with `on-blur` prop when use `ok` button', async () => {\n    const onBlur = vi.fn()\n    const Render = () => {\n      return h('div', null, [\n        h(NTimePicker, {\n          onBlur,\n          actions: ['confirm']\n        }),\n        h(NInput, {\n          inputProps: {\n            id: 'input'\n          }\n        })\n      ])\n    }\n    const wrapper = mount(Render, {\n      attachTo: document.body\n    })\n    await wrapper.find('input').trigger('click')\n    const button: HTMLElement = document.querySelector(\n      '.n-button'\n    ) as HTMLElement\n    button.click()\n\n    const input = document.querySelector('#input') as HTMLElement\n    input.focus()\n\n    expect(onBlur).toHaveBeenCalled()\n    wrapper.unmount()\n  })\n\n  it('should work with `on-focus` prop', async () => {\n    const onFocus = vi.fn()\n    const wrapper = mount(NTimePicker, {\n      props: { onFocus }\n    })\n    await wrapper.find('input').trigger('focus')\n    expect(onFocus).toHaveBeenCalled()\n    wrapper.unmount()\n  })\n})\n"
  },
  {
    "path": "src/time-picker/tests/__snapshots__/TimePicker.spec.ts.snap",
    "content": "// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html\n\nexports[`n-time-picker > should work with \\`size\\` prop 1`] = `\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-count-text-color: rgb(118, 124, 130); --n-count-text-color-disabled: rgba(194, 194, 194, 1); --n-color: rgba(255, 255, 255, 1); --n-font-size: 14px; --n-font-weight: 400; --n-border-radius: 3px; --n-height: 28px; --n-padding-left: 10px; --n-padding-right: 10px; --n-text-color: rgb(51, 54, 57); --n-caret-color: #18a058; --n-text-decoration-color: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-focus: 1px solid #36ad6a; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-icon-size: 16px; --n-line-height-textarea: 1.6; --n-color-disabled: rgb(250, 250, 252); --n-color-focus: rgba(255, 255, 255, 1); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-loading-color: #18a058; --n-caret-color-warning: #f0a020; --n-color-focus-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-loading-color-warning: #f0a020; --n-caret-color-error: #d03050; --n-color-focus-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-loading-color-error: #d03050; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-size: 16px; --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-icon-color-hover: rgba(146, 146, 146, 1); --n-icon-color-pressed: rgba(175, 175, 175, 1); --n-icon-color-disabled: rgba(209, 209, 209, 1); --n-suffix-text-color: rgb(51, 54, 57);\"`;\n\nexports[`n-time-picker > should work with \\`size\\` prop 2`] = `\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-count-text-color: rgb(118, 124, 130); --n-count-text-color-disabled: rgba(194, 194, 194, 1); --n-color: rgba(255, 255, 255, 1); --n-font-size: 14px; --n-font-weight: 400; --n-border-radius: 3px; --n-height: 34px; --n-padding-left: 12px; --n-padding-right: 12px; --n-text-color: rgb(51, 54, 57); --n-caret-color: #18a058; --n-text-decoration-color: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-focus: 1px solid #36ad6a; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-icon-size: 16px; --n-line-height-textarea: 1.6; --n-color-disabled: rgb(250, 250, 252); --n-color-focus: rgba(255, 255, 255, 1); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-loading-color: #18a058; --n-caret-color-warning: #f0a020; --n-color-focus-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-loading-color-warning: #f0a020; --n-caret-color-error: #d03050; --n-color-focus-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-loading-color-error: #d03050; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-size: 16px; --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-icon-color-hover: rgba(146, 146, 146, 1); --n-icon-color-pressed: rgba(175, 175, 175, 1); --n-icon-color-disabled: rgba(209, 209, 209, 1); --n-suffix-text-color: rgb(51, 54, 57);\"`;\n\nexports[`n-time-picker > should work with \\`size\\` prop 3`] = `\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-count-text-color: rgb(118, 124, 130); --n-count-text-color-disabled: rgba(194, 194, 194, 1); --n-color: rgba(255, 255, 255, 1); --n-font-size: 15px; --n-font-weight: 400; --n-border-radius: 3px; --n-height: 40px; --n-padding-left: 14px; --n-padding-right: 14px; --n-text-color: rgb(51, 54, 57); --n-caret-color: #18a058; --n-text-decoration-color: rgb(51, 54, 57); --n-border: 1px solid rgb(224, 224, 230); --n-border-disabled: 1px solid rgb(224, 224, 230); --n-border-hover: 1px solid #36ad6a; --n-border-focus: 1px solid #36ad6a; --n-placeholder-color: rgba(194, 194, 194, 1); --n-placeholder-color-disabled: rgba(209, 209, 209, 1); --n-icon-size: 16px; --n-line-height-textarea: 1.6; --n-color-disabled: rgb(250, 250, 252); --n-color-focus: rgba(255, 255, 255, 1); --n-text-color-disabled: rgba(194, 194, 194, 1); --n-box-shadow-focus: 0 0 0 2px rgba(24, 160, 88, 0.2); --n-loading-color: #18a058; --n-caret-color-warning: #f0a020; --n-color-focus-warning: rgba(255, 255, 255, 1); --n-box-shadow-focus-warning: 0 0 0 2px rgba(240, 160, 32, 0.2); --n-border-warning: 1px solid #f0a020; --n-border-focus-warning: 1px solid #fcb040; --n-border-hover-warning: 1px solid #fcb040; --n-loading-color-warning: #f0a020; --n-caret-color-error: #d03050; --n-color-focus-error: rgba(255, 255, 255, 1); --n-box-shadow-focus-error: 0 0 0 2px rgba(208, 48, 80, 0.2); --n-border-error: 1px solid #d03050; --n-border-focus-error: 1px solid #de576d; --n-border-hover-error: 1px solid #de576d; --n-loading-color-error: #d03050; --n-clear-color: rgba(194, 194, 194, 1); --n-clear-size: 16px; --n-clear-color-hover: rgba(146, 146, 146, 1); --n-clear-color-pressed: rgba(175, 175, 175, 1); --n-icon-color: rgba(194, 194, 194, 1); --n-icon-color-hover: rgba(146, 146, 146, 1); --n-icon-color-pressed: rgba(175, 175, 175, 1); --n-icon-color-disabled: rgba(209, 209, 209, 1); --n-suffix-text-color: rgb(51, 54, 57);\"`;\n"
  },
  {
    "path": "src/time-picker/tests/server.spec.tsx",
    "content": "import { setup } from '@css-render/vue3-ssr'\nimport { renderToString } from '@vue/server-renderer'\n/**\n * @vitest-environment node\n */\nimport { createSSRApp, h } from 'vue'\nimport { NTimePicker } from '../..'\n\ndescribe('server side rendering', () => {\n  it('works', async () => {\n    const app = createSSRApp(() => <NTimePicker />)\n    setup(app)\n    try {\n      await renderToString(app)\n    }\n    catch (e) {\n      expect(e).not.toBeTruthy()\n    }\n  })\n})\n"
  },
  {
    "path": "src/timeline/demos/enUS/basic.demo.vue",
    "content": "<markdown>\n# Basic\n</markdown>\n\n<template>\n  <n-timeline>\n    <n-timeline-item content=\"Oops\" />\n    <n-timeline-item\n      type=\"success\"\n      title=\"Success\"\n      content=\"success content\"\n      time=\"2018-04-03 20:46\"\n    />\n    <n-timeline-item\n      type=\"error\"\n      content=\"Error content\"\n      time=\"2018-04-03 20:46\"\n    />\n    <n-timeline-item\n      type=\"warning\"\n      title=\"Warning\"\n      content=\"warning content\"\n      time=\"2018-04-03 20:46\"\n    />\n    <n-timeline-item\n      type=\"info\"\n      title=\"Info\"\n      content=\"info content\"\n      time=\"2018-04-03 20:46\"\n      line-type=\"dashed\"\n    />\n    <n-timeline-item content=\"Oops\" />\n  </n-timeline>\n</template>\n"
  },
  {
    "path": "src/timeline/demos/enUS/customize-icon.demo.vue",
    "content": "<markdown>\n# Customize icon\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { CashOutline as CashIcon } from '@vicons/ionicons5'\n</script>\n\n<template>\n  <n-timeline>\n    <n-timeline-item color=\"grey\" content=\"Oops\">\n      <template #icon>\n        <n-icon>\n          <CashIcon />\n        </n-icon>\n      </template>\n    </n-timeline-item>\n    <n-timeline-item\n      type=\"success\"\n      title=\"Success\"\n      content=\"success content\"\n      time=\"2018-04-03 20:46\"\n    >\n      <template #icon>\n        <n-icon>\n          <CashIcon />\n        </n-icon>\n      </template>\n    </n-timeline-item>\n    <n-timeline-item\n      type=\"error\"\n      content=\"error content\"\n      time=\"2018-04-03 20:46\"\n    >\n      <template #icon>\n        <n-icon>\n          <CashIcon />\n        </n-icon>\n      </template>\n    </n-timeline-item>\n    <n-timeline-item\n      type=\"warning\"\n      title=\"Warning\"\n      content=\"warning content\"\n      time=\"2018-04-03 20:46\"\n    >\n      <template #icon>\n        <n-icon>\n          <CashIcon />\n        </n-icon>\n      </template>\n    </n-timeline-item>\n    <n-timeline-item\n      type=\"info\"\n      title=\"Info\"\n      content=\"info content\"\n      time=\"2018-04-03 20:46\"\n    >\n      <template #icon>\n        <n-icon>\n          <CashIcon />\n        </n-icon>\n      </template>\n    </n-timeline-item>\n  </n-timeline>\n</template>\n"
  },
  {
    "path": "src/timeline/demos/enUS/horizontal.demo.vue",
    "content": "<markdown>\n# Horizontal\n</markdown>\n\n<template>\n  <div style=\"overflow: auto\">\n    <n-timeline horizontal>\n      <n-timeline-item content=\"Oops\" />\n      <n-timeline-item\n        type=\"success\"\n        title=\"Success\"\n        content=\"Success content\"\n        time=\"2018-04-03 20:46\"\n      />\n      <n-timeline-item\n        type=\"error\"\n        content=\"Error content\"\n        time=\"2018-04-03 20:46\"\n      />\n      <n-timeline-item\n        type=\"warning\"\n        title=\"Warning\"\n        content=\"Warning content\"\n        time=\"2018-04-03 20:46\"\n      />\n      <n-timeline-item\n        type=\"info\"\n        title=\"Info\"\n        content=\"Info content\"\n        time=\"2018-04-03 20:46\"\n      />\n    </n-timeline>\n  </div>\n</template>\n"
  },
  {
    "path": "src/timeline/demos/enUS/index.demo-entry.md",
    "content": "# Timeline\n\nThe world is 2 dimensioned. One of them is time. The Other is event.\n\n## Demos\n\n```demo\nbasic.vue\nsize.vue\nitem-placement.vue\nhorizontal.vue\ncustomize-icon.vue\n```\n\n## API\n\n### Timeline Props\n\n| Name           | Type                  | Default     | Description        |\n| -------------- | --------------------- | ----------- | ------------------ |\n| horizontal     | `boolean`             | `'false'`   | Horizontal         |\n| icon-size      | `number`              | `undefined` | Size of icon part. |\n| item-placement | `'left' \\| 'right'`   | `'left'`    | Direction.         |\n| size           | `'medium' \\| 'large'` | `'medium'`  | Size.              |\n\n### TimelineItem Props\n\n| Name | Type | Default | Description | Version |\n| --- | --- | --- | --- | --- |\n| color | `string` | `undefined` | Item color. |  |\n| content | `string` | `undefined` | Item content. |  |\n| line-type | `'default' \\| 'dashed'` | `'default'` | Line type. | 2.26.1 |\n| time | `string` | `undefined` | Item time. |  |\n| title | `string` | `undefined` | Item title. |  |\n| type | `'default' \\| 'success' \\| 'info' \\| 'warning' \\| 'error'` | `'default'` | Item type. |  |\n\n### Timeline Slots\n\n| Name    | Parameters | Description       |\n| ------- | ---------- | ----------------- |\n| default | `()`       | Timeline Content. |\n\n### TimelineItem Slots\n\n| Name    | Parameters | Description                                    |\n| ------- | ---------- | ---------------------------------------------- |\n| default | `()`       | Timeline item content.                         |\n| icon    | `()`       | Timeline item customize timeline icon.         |\n| footer  | `()`       | Content at the bottom of the timeline options. |\n| header  | `()`       | Content at the top of the timeline options.    |\n"
  },
  {
    "path": "src/timeline/demos/enUS/item-placement.demo.vue",
    "content": "<markdown>\n# Item placement\n\nLeft. .thgiR\n</markdown>\n\n<template>\n  <n-timeline item-placement=\"right\">\n    <n-timeline-item content=\"Oops\" />\n    <n-timeline-item\n      type=\"success\"\n      title=\"Success\"\n      content=\"success content\"\n      time=\"2018-04-03 20:46\"\n    />\n    <n-timeline-item\n      type=\"error\"\n      content=\"Error content\"\n      time=\"2018-04-03 20:46\"\n    />\n    <n-timeline-item\n      type=\"warning\"\n      title=\"Warning\"\n      content=\"warning content\"\n      time=\"2018-04-03 20:46\"\n    />\n    <n-timeline-item\n      type=\"info\"\n      title=\"Info\"\n      content=\"info content\"\n      time=\"2018-04-03 20:46\"\n    />\n  </n-timeline>\n</template>\n"
  },
  {
    "path": "src/timeline/demos/enUS/size.demo.vue",
    "content": "<markdown>\n# Size\n</markdown>\n\n<template>\n  <n-timeline size=\"large\">\n    <n-timeline-item content=\"Oops\" />\n    <n-timeline-item\n      type=\"success\"\n      title=\"Success\"\n      content=\"success content\"\n      time=\"2018-04-03 20:46\"\n    />\n    <n-timeline-item\n      type=\"error\"\n      content=\"Error content\"\n      time=\"2018-04-03 20:46\"\n    />\n    <n-timeline-item\n      type=\"warning\"\n      title=\"Warning\"\n      content=\"warning content\"\n      time=\"2018-04-03 20:46\"\n    />\n    <n-timeline-item\n      type=\"info\"\n      title=\"Info\"\n      content=\"info content\"\n      time=\"2018-04-03 20:46\"\n    />\n  </n-timeline>\n</template>\n"
  },
  {
    "path": "src/timeline/demos/zhCN/basic.demo.vue",
    "content": "<markdown>\n# 基础用法\n</markdown>\n\n<template>\n  <n-timeline>\n    <n-timeline-item content=\"啊\" />\n    <n-timeline-item\n      type=\"success\"\n      title=\"成功\"\n      content=\"哪里成功\"\n      time=\"2018-04-03 20:46\"\n    />\n    <n-timeline-item type=\"error\" content=\"哪里错误\" time=\"2018-04-03 20:46\" />\n    <n-timeline-item\n      type=\"warning\"\n      title=\"警告\"\n      content=\"哪里警告\"\n      time=\"2018-04-03 20:46\"\n    />\n    <n-timeline-item\n      type=\"info\"\n      title=\"信息\"\n      content=\"是的\"\n      time=\"2018-04-03 20:46\"\n      line-type=\"dashed\"\n    />\n    <n-timeline-item content=\"啊\" />\n  </n-timeline>\n</template>\n"
  },
  {
    "path": "src/timeline/demos/zhCN/customize-icon.demo.vue",
    "content": "<markdown>\n# 自定义图标\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { CashOutline as CashIcon } from '@vicons/ionicons5'\n</script>\n\n<template>\n  <n-timeline :icon-size=\"20\">\n    <n-timeline-item color=\"grey\" content=\"啊\">\n      <template #icon>\n        <n-icon>\n          <CashIcon />\n        </n-icon>\n      </template>\n    </n-timeline-item>\n    <n-timeline-item\n      type=\"success\"\n      title=\"成功\"\n      content=\"哪里成功\"\n      time=\"2018-04-03 20:46\"\n    >\n      <template #icon>\n        <n-icon>\n          <CashIcon />\n        </n-icon>\n      </template>\n    </n-timeline-item>\n    <n-timeline-item type=\"error\" content=\"哪里错误\" time=\"2018-04-03 20:46\">\n      <template #icon>\n        <n-icon>\n          <CashIcon />\n        </n-icon>\n      </template>\n    </n-timeline-item>\n    <n-timeline-item\n      type=\"warning\"\n      title=\"警告\"\n      content=\"哪里警告\"\n      time=\"2018-04-03 20:46\"\n    >\n      <template #icon>\n        <n-icon>\n          <CashIcon />\n        </n-icon>\n      </template>\n    </n-timeline-item>\n    <n-timeline-item\n      type=\"info\"\n      title=\"信息\"\n      content=\"是的\"\n      time=\"2018-04-03 20:46\"\n    >\n      <template #icon>\n        <n-icon>\n          <CashIcon />\n        </n-icon>\n      </template>\n    </n-timeline-item>\n  </n-timeline>\n</template>\n"
  },
  {
    "path": "src/timeline/demos/zhCN/horizontal.demo.vue",
    "content": "<markdown>\n# 水平\n</markdown>\n\n<template>\n  <div style=\"overflow: auto\">\n    <n-timeline horizontal>\n      <n-timeline-item content=\"啊\" />\n      <n-timeline-item\n        type=\"success\"\n        title=\"成功\"\n        content=\"哪里成功\"\n        time=\"2018-04-03 20:46\"\n      />\n      <n-timeline-item\n        type=\"error\"\n        content=\"哪里失败\"\n        time=\"2018-04-03 20:46\"\n      />\n      <n-timeline-item\n        type=\"warning\"\n        title=\"警告\"\n        content=\"哪里警告\"\n        time=\"2018-04-03 20:46\"\n      />\n      <n-timeline-item\n        type=\"info\"\n        title=\"信息\"\n        content=\"是的\"\n        time=\"2018-04-03 20:46\"\n      />\n    </n-timeline>\n  </div>\n</template>\n"
  },
  {
    "path": "src/timeline/demos/zhCN/index.demo-entry.md",
    "content": "# 时间线 Timeline\n\n这个世界有两个纬度：时间、事件。\n\n## 演示\n\n```demo\nbasic.vue\nsize.vue\nitem-placement.vue\nhorizontal.vue\ncustomize-icon.vue\nnested-debug.vue\n```\n\n## API\n\n### Timeline Props\n\n| 名称           | 类型                  | 默认值      | 说明     |\n| -------------- | --------------------- | ----------- | -------- |\n| horizontal     | `boolean`             | `'false'`   | 水平的   |\n| icon-size      | `number`              | `undefined` | 图标大小 |\n| item-placement | `'left' \\| 'right'`   | `'left'`    | 方向     |\n| size           | `'medium' \\| 'large'` | `'medium'`  | 大小     |\n\n### TimelineItem Props\n\n| 名称 | 类型 | 默认值 | 说明 | 版本 |\n| --- | --- | --- | --- | --- |\n| color | `string` | `undefined` | 选项的颜色 |  |\n| content | `string` | `undefined` | 选项内容 |  |\n| line-type | `'default' \\| 'dashed'` | `'default'` | 线的类型 | 2.26.1 |\n| time | `string` | `undefined` | 选项时间 |  |\n| title | `string` | `undefined` | 选项标题 |  |\n| type | `'default' \\| 'success' \\| 'info' \\| 'warning' \\| 'error'` | `'default'` | 选项类型 |  |\n\n### Timeline Slots\n\n| 名称    | 参数 | 说明       |\n| ------- | ---- | ---------- |\n| default | `()` | 时间线内容 |\n\n### TimelineItem Slots\n\n| 名称    | 参数 | 说明                 |\n| ------- | ---- | -------------------- |\n| default | `()` | 时间线选项内容       |\n| icon    | `()` | 时间线选项自定义图标 |\n| footer  | `()` | 时间线选项底部内容   |\n| header  | `()` | 时间线选项头部内容   |\n"
  },
  {
    "path": "src/timeline/demos/zhCN/item-placement.demo.vue",
    "content": "<markdown>\n# 方向\n\n左，<span style=\"display: inline-block; transform: scaleX(-1);\">右</span>\n</markdown>\n\n<template>\n  <n-timeline item-placement=\"right\">\n    <n-timeline-item content=\"啊\" />\n    <n-timeline-item\n      type=\"success\"\n      title=\"成功\"\n      content=\"哪里成功\"\n      time=\"2018-04-03 20:46\"\n    />\n    <n-timeline-item type=\"error\" content=\"哪里失败\" time=\"2018-04-03 20:46\" />\n    <n-timeline-item\n      type=\"warning\"\n      title=\"警告\"\n      content=\"哪里警告\"\n      time=\"2018-04-03 20:46\"\n    />\n    <n-timeline-item\n      type=\"info\"\n      title=\"信息\"\n      content=\"是的\"\n      time=\"2018-04-03 20:46\"\n    />\n  </n-timeline>\n</template>\n"
  },
  {
    "path": "src/timeline/demos/zhCN/nested-debug.demo.vue",
    "content": "<markdown>\n# Nested debug\n</markdown>\n\n<template>\n  <n-timeline horizontal>\n    <n-timeline-item content=\"啊\" />\n    <n-timeline-item\n      type=\"success\"\n      title=\"成功\"\n      content=\"哪里成功\"\n      time=\"2018-04-03 20:46\"\n    >\n      <n-timeline>\n        <n-timeline-item content=\"啊\" />\n        <n-timeline-item\n          type=\"success\"\n          title=\"成功\"\n          content=\"哪里成功\"\n          time=\"2018-04-03 20:46\"\n        />\n        <n-timeline-item\n          type=\"error\"\n          content=\"哪里错误\"\n          time=\"2018-04-03 20:46\"\n        />\n        <n-timeline-item\n          type=\"warning\"\n          title=\"警告\"\n          content=\"哪里警告\"\n          time=\"2018-04-03 20:46\"\n        />\n        <n-timeline-item\n          type=\"info\"\n          title=\"信息\"\n          content=\"是的\"\n          time=\"2018-04-03 20:46\"\n        />\n      </n-timeline>\n    </n-timeline-item>\n    <n-timeline-item type=\"error\" content=\"哪里错误\" time=\"2018-04-03 20:46\" />\n    <n-timeline-item\n      type=\"warning\"\n      title=\"警告\"\n      content=\"哪里警告\"\n      time=\"2018-04-03 20:46\"\n    />\n    <n-timeline-item\n      type=\"info\"\n      title=\"信息\"\n      content=\"是的\"\n      time=\"2018-04-03 20:46\"\n    />\n  </n-timeline>\n</template>\n"
  },
  {
    "path": "src/timeline/demos/zhCN/size.demo.vue",
    "content": "<markdown>\n# 大小\n\n有 `medium`、`large` 大小\n</markdown>\n\n<template>\n  <n-timeline size=\"large\">\n    <n-timeline-item content=\"啊\" />\n    <n-timeline-item\n      type=\"success\"\n      title=\"成功\"\n      content=\"哪里成功\"\n      time=\"2018-04-03 20:46\"\n    />\n    <n-timeline-item type=\"error\" content=\"哪里错误\" time=\"2018-04-03 20:46\" />\n    <n-timeline-item\n      type=\"warning\"\n      title=\"警告\"\n      content=\"哪里警告\"\n      time=\"2018-04-03 20:46\"\n    />\n    <n-timeline-item\n      type=\"info\"\n      title=\"信息\"\n      content=\"是的\"\n      time=\"2018-04-03 20:46\"\n    />\n  </n-timeline>\n</template>\n"
  },
  {
    "path": "src/timeline/index.ts",
    "content": "export { default as NTimeline, timelineProps } from './src/Timeline'\nexport type { TimelineProps } from './src/Timeline'\nexport { default as NTimelineItem, timelineItemProps } from './src/TimelineItem'\nexport type { TimelineItemProps, TimelineItemSlots } from './src/TimelineItem'\n"
  },
  {
    "path": "src/timeline/src/Timeline.tsx",
    "content": "import type { ExtractPropTypes, PropType, Ref } from 'vue'\nimport type { MergedTheme, ThemeProps } from '../../_mixins'\nimport type { ExtractPublicPropTypes } from '../../_utils'\nimport type { TimelineTheme } from '../styles'\nimport { defineComponent, h, provide } from 'vue'\nimport { useConfig, useTheme } from '../../_mixins'\nimport { createInjectionKey } from '../../_utils'\nimport { timelineLight } from '../styles'\nimport style from './styles/index.cssr'\n\nexport const timelineProps = {\n  ...(useTheme.props as ThemeProps<TimelineTheme>),\n  horizontal: Boolean,\n  itemPlacement: {\n    type: String as PropType<'left' | 'right'>,\n    default: 'left'\n  },\n  size: {\n    type: String as PropType<'medium' | 'large'>,\n    default: 'medium'\n  },\n  iconSize: Number\n} as const\n\nexport interface TimelineInjection {\n  props: ExtractPropTypes<typeof timelineProps>\n  mergedThemeRef: Ref<MergedTheme<TimelineTheme>>\n  mergedClsPrefixRef: Ref<string>\n}\nexport const timelineInjectionKey\n  = createInjectionKey<TimelineInjection>('n-timeline')\n\nexport type TimelineProps = ExtractPublicPropTypes<typeof timelineProps>\n\nexport default defineComponent({\n  name: 'Timeline',\n  props: timelineProps,\n  setup(props, { slots }) {\n    const { mergedClsPrefixRef } = useConfig(props)\n    const themeRef = useTheme(\n      'Timeline',\n      '-timeline',\n      style,\n      timelineLight,\n      props,\n      mergedClsPrefixRef\n    )\n    provide(timelineInjectionKey, {\n      props,\n      mergedThemeRef: themeRef,\n      mergedClsPrefixRef\n    })\n    return () => {\n      const { value: mergedClsPrefix } = mergedClsPrefixRef\n      return (\n        <div\n          class={[\n            `${mergedClsPrefix}-timeline`,\n            props.horizontal && `${mergedClsPrefix}-timeline--horizontal`,\n            `${mergedClsPrefix}-timeline--${props.size}-size`,\n            !props.horizontal\n            && `${mergedClsPrefix}-timeline--${props.itemPlacement}-placement`\n          ]}\n        >\n          {slots}\n        </div>\n      )\n    }\n  }\n})\n"
  },
  {
    "path": "src/timeline/src/TimelineItem.tsx",
    "content": "import type { CSSProperties, PropType, SlotsType, VNode } from 'vue'\nimport type { ExtractPublicPropTypes } from '../../_utils'\nimport { computed, defineComponent, h, inject } from 'vue'\nimport { useConfig, useThemeClass } from '../../_mixins'\nimport {\n  createKey,\n  formatLength,\n  resolveSlot,\n  resolveWrappedSlot,\n  throwError,\n  useHoudini\n} from '../../_utils'\nimport { timelineInjectionKey } from './Timeline'\n\nexport const timelineItemProps = {\n  time: [String, Number] as PropType<string | number>,\n  title: String,\n  content: String,\n  color: String,\n  lineType: {\n    type: String as PropType<'default' | 'dashed'>,\n    default: 'default'\n  },\n  type: {\n    type: String as PropType<\n      'default' | 'success' | 'error' | 'warning' | 'info'\n    >,\n    default: 'default'\n  }\n}\n\nexport type TimelineItemProps = ExtractPublicPropTypes<typeof timelineItemProps>\n\nexport interface TimelineItemSlots {\n  default?: () => VNode[]\n  icon?: () => VNode[]\n  footer?: () => VNode[]\n  header?: () => VNode[]\n}\n\nexport default defineComponent({\n  name: 'TimelineItem',\n  props: timelineItemProps,\n  slots: Object as SlotsType<TimelineItemSlots>,\n  setup(props) {\n    const NTimeline = inject(timelineInjectionKey)\n    if (!NTimeline) {\n      throwError(\n        'timeline-item',\n        '`n-timeline-item` must be placed inside `n-timeline`.'\n      )\n    }\n    useHoudini()\n    const { inlineThemeDisabled } = useConfig()\n    const cssVarsRef = computed(() => {\n      const {\n        props: { size, iconSize: iconSizeProp },\n        mergedThemeRef\n      } = NTimeline\n      const { type } = props\n      const {\n        self: {\n          titleTextColor,\n          contentTextColor,\n          metaTextColor,\n          lineColor,\n          titleFontWeight,\n          contentFontSize,\n          [createKey('iconSize', size)]: iconSize,\n          [createKey('titleMargin', size)]: titleMargin,\n          [createKey('titleFontSize', size)]: titleFontSize,\n          [createKey('circleBorder', type)]: circleBorder,\n          [createKey('iconColor', type)]: iconColor\n        },\n        common: { cubicBezierEaseInOut }\n      } = mergedThemeRef.value\n      return {\n        '--n-bezier': cubicBezierEaseInOut,\n        '--n-circle-border': circleBorder,\n        '--n-icon-color': iconColor,\n        '--n-content-font-size': contentFontSize,\n        '--n-content-text-color': contentTextColor,\n        '--n-line-color': lineColor,\n        '--n-meta-text-color': metaTextColor,\n        '--n-title-font-size': titleFontSize,\n        '--n-title-font-weight': titleFontWeight,\n        '--n-title-margin': titleMargin,\n        '--n-title-text-color': titleTextColor,\n        '--n-icon-size': formatLength(iconSizeProp) || iconSize\n      }\n    })\n    const themeClassHandle = inlineThemeDisabled\n      ? useThemeClass(\n          'timeline-item',\n          computed(() => {\n            const {\n              props: { size, iconSize: iconSizeProp }\n            } = NTimeline\n            const { type } = props\n            return `${size[0]}${iconSizeProp || 'a'}${type[0]}`\n          }),\n          cssVarsRef,\n          NTimeline.props\n        )\n      : undefined\n    return {\n      mergedClsPrefix: NTimeline.mergedClsPrefixRef,\n      cssVars: inlineThemeDisabled ? undefined : cssVarsRef,\n      themeClass: themeClassHandle?.themeClass,\n      onRender: themeClassHandle?.onRender\n    }\n  },\n  render() {\n    const { mergedClsPrefix, color, onRender, $slots } = this\n    onRender?.()\n    return (\n      <div\n        class={[\n          `${mergedClsPrefix}-timeline-item`,\n          this.themeClass,\n          `${mergedClsPrefix}-timeline-item--${this.type}-type`,\n          `${mergedClsPrefix}-timeline-item--${this.lineType}-line-type`\n        ]}\n        style={this.cssVars as CSSProperties}\n      >\n        <div class={`${mergedClsPrefix}-timeline-item-timeline`}>\n          <div class={`${mergedClsPrefix}-timeline-item-timeline__line`} />\n          {resolveWrappedSlot($slots.icon, (children) => {\n            return children ? (\n              <div\n                class={`${mergedClsPrefix}-timeline-item-timeline__icon`}\n                style={{ color }}\n              >\n                {children}\n              </div>\n            ) : (\n              <div\n                class={`${mergedClsPrefix}-timeline-item-timeline__circle`}\n                style={{ borderColor: color }}\n              />\n            )\n          })}\n        </div>\n        <div class={`${mergedClsPrefix}-timeline-item-content`}>\n          {resolveWrappedSlot($slots.header, (children) => {\n            const mergedChildren = children || this.title\n            if (mergedChildren) {\n              return (\n                <div class={`${mergedClsPrefix}-timeline-item-content__title`}>\n                  {children || this.title}\n                </div>\n              )\n            }\n            return null\n          })}\n          <div class={`${mergedClsPrefix}-timeline-item-content__content`}>\n            {resolveSlot($slots.default, () => [this.content])}\n          </div>\n          <div class={`${mergedClsPrefix}-timeline-item-content__meta`}>\n            {resolveSlot($slots.footer, () => [this.time])}\n          </div>\n        </div>\n      </div>\n    )\n  }\n})\n"
  },
  {
    "path": "src/timeline/src/styles/index.cssr.ts",
    "content": "import { c, cB, cE, cM } from '../../../_utils/cssr'\n\nconst lineHeight = 1.25\n\n// vars:\n// --n-bezier\n// --n-circle-border\n// --n-content-font-size\n// --n-content-text-color\n// --n-line-color\n// --n-meta-text-color\n// --n-title-font-size\n// --n-title-font-weight\n// --n-title-margin\n// --n-title-text-color\n// --n-icon-size\nexport default cB('timeline', `\n  position: relative;\n  width: 100%;\n  display: flex;\n  flex-direction: column;\n  line-height: ${lineHeight};\n`, [\n  cM('horizontal', `\n    flex-direction: row;\n  `, [\n    c('>', [\n      cB('timeline-item', `\n        flex-shrink: 0;\n        padding-right: 40px;\n      `, [\n        cM('dashed-line-type', [\n          c('>', [\n            cB('timeline-item-timeline', [\n              cE('line', `\n                background-image: linear-gradient(90deg, var(--n-color-start), var(--n-color-start) 50%, transparent 50%, transparent 100%);\n                background-size: 10px 1px;\n              `)\n            ])\n          ])\n        ]),\n        c('>', [\n          cB('timeline-item-content', `\n          margin-top: calc(var(--n-icon-size) + 12px);\n          `, [\n            c('>', [\n              cE('meta', `\n                margin-top: 6px;\n                margin-bottom: unset;\n              `)\n            ])\n          ]),\n          cB('timeline-item-timeline', `\n            width: 100%;\n            height: calc(var(--n-icon-size) + 12px);\n          `, [\n            cE('line', `\n              left: var(--n-icon-size);\n              top: calc(var(--n-icon-size) / 2 - 1px);\n              right: 0px;\n              width: unset;\n              height: 2px;\n            `)\n          ])\n        ])\n      ])\n    ])\n  ]),\n  cM('right-placement', [\n    cB('timeline-item', [\n      cB('timeline-item-content', `\n        text-align: right;\n        margin-right: calc(var(--n-icon-size) + 12px);\n      `),\n      cB('timeline-item-timeline', `\n        width: var(--n-icon-size);\n        right: 0;\n      `)\n    ])\n  ]),\n  cM('left-placement', [\n    cB('timeline-item', [\n      cB('timeline-item-content', `\n        margin-left: calc(var(--n-icon-size) + 12px);\n      `),\n      cB('timeline-item-timeline', `\n        left: 0;\n      `)\n    ])\n  ]),\n  cB('timeline-item', `\n    position: relative;\n  `, [\n    c('&:last-child', [\n      cB('timeline-item-timeline', [\n        cE('line', `\n          display: none;\n        `)\n      ]),\n      cB('timeline-item-content', [\n        cE('meta', `\n          margin-bottom: 0;\n        `)\n      ])\n    ]),\n    cB('timeline-item-content', [\n      cE('title', `\n        margin: var(--n-title-margin);\n        font-size: var(--n-title-font-size);\n        transition: color .3s var(--n-bezier);\n        font-weight: var(--n-title-font-weight);\n        color: var(--n-title-text-color);\n      `),\n      cE('content', `\n        transition: color .3s var(--n-bezier);\n        font-size: var(--n-content-font-size);\n        color: var(--n-content-text-color);\n      `),\n      cE('meta', `\n        transition: color .3s var(--n-bezier);\n        font-size: 12px;\n        margin-top: 6px;\n        margin-bottom: 20px;\n        color: var(--n-meta-text-color);\n      `)\n    ]),\n    cM('dashed-line-type', [\n      cB('timeline-item-timeline', [\n        cE('line', `\n          --n-color-start: var(--n-line-color);\n          transition: --n-color-start .3s var(--n-bezier);\n          background-color: transparent;\n          background-image: linear-gradient(180deg, var(--n-color-start), var(--n-color-start) 50%, transparent 50%, transparent 100%);\n          background-size: 1px 10px;\n        `)\n      ])\n    ]),\n    cB('timeline-item-timeline', `\n      width: calc(var(--n-icon-size) + 12px);\n      position: absolute;\n      top: calc(var(--n-title-font-size) * ${lineHeight} / 2 - var(--n-icon-size) / 2);\n      height: 100%;\n    `, [\n      cE('circle', `\n        border: var(--n-circle-border);\n        transition:\n          background-color .3s var(--n-bezier),\n          border-color .3s var(--n-bezier);\n        width: var(--n-icon-size);\n        height: var(--n-icon-size);\n        border-radius: var(--n-icon-size);\n        box-sizing: border-box;\n      `),\n      cE('icon', `\n        color: var(--n-icon-color);\n        font-size: var(--n-icon-size);\n        height: var(--n-icon-size);\n        width: var(--n-icon-size);\n        display: flex;\n        align-items: center;\n        justify-content: center;\n      `),\n      cE('line', `\n        transition: background-color .3s var(--n-bezier);\n        position: absolute;\n        top: var(--n-icon-size);\n        left: calc(var(--n-icon-size) / 2 - 1px);\n        bottom: 0px;\n        width: 2px;\n        background-color: var(--n-line-color);\n      `)\n    ])\n  ])\n])\n"
  },
  {
    "path": "src/timeline/styles/_common.ts",
    "content": "export default {\n  titleMarginMedium: '0 0 6px 0',\n  titleMarginLarge: '-2px 0 6px 0',\n  titleFontSizeMedium: '14px',\n  titleFontSizeLarge: '16px',\n  iconSizeMedium: '14px',\n  iconSizeLarge: '14px'\n}\n"
  },
  {
    "path": "src/timeline/styles/dark.ts",
    "content": "import type { TimelineTheme } from './light'\nimport { commonDark } from '../../_styles/common'\nimport sizeVariables from './_common'\n\nconst timelineDark: TimelineTheme = {\n  name: 'Timeline',\n  common: commonDark,\n  self(vars) {\n    const {\n      textColor3,\n      infoColorSuppl,\n      errorColorSuppl,\n      successColorSuppl,\n      warningColorSuppl,\n      textColor1,\n      textColor2,\n      railColor,\n      fontWeightStrong,\n      fontSize\n    } = vars\n    return {\n      ...sizeVariables,\n      contentFontSize: fontSize,\n      titleFontWeight: fontWeightStrong,\n      circleBorder: `2px solid ${textColor3}`,\n      circleBorderInfo: `2px solid ${infoColorSuppl}`,\n      circleBorderError: `2px solid ${errorColorSuppl}`,\n      circleBorderSuccess: `2px solid ${successColorSuppl}`,\n      circleBorderWarning: `2px solid ${warningColorSuppl}`,\n      iconColor: textColor3,\n      iconColorInfo: infoColorSuppl,\n      iconColorError: errorColorSuppl,\n      iconColorSuccess: successColorSuppl,\n      iconColorWarning: warningColorSuppl,\n      titleTextColor: textColor1,\n      contentTextColor: textColor2,\n      metaTextColor: textColor3,\n      lineColor: railColor\n    }\n  }\n}\n\nexport default timelineDark\n"
  },
  {
    "path": "src/timeline/styles/index.ts",
    "content": "export { default as timelineDark } from './dark'\nexport { default as timelineLight } from './light'\nexport type { TimelineTheme, TimelineThemeVars } from './light'\n"
  },
  {
    "path": "src/timeline/styles/light.ts",
    "content": "import type { Theme } from '../../_mixins'\nimport type { ThemeCommonVars } from '../../_styles/common'\nimport { commonLight } from '../../_styles/common'\nimport sizeVariables from './_common'\n\nfunction self(vars: ThemeCommonVars) {\n  const {\n    textColor3,\n    infoColor,\n    errorColor,\n    successColor,\n    warningColor,\n    textColor1,\n    textColor2,\n    railColor,\n    fontWeightStrong,\n    fontSize\n  } = vars\n  return {\n    ...sizeVariables,\n    contentFontSize: fontSize,\n    titleFontWeight: fontWeightStrong,\n    circleBorder: `2px solid ${textColor3}`,\n    circleBorderInfo: `2px solid ${infoColor}`,\n    circleBorderError: `2px solid ${errorColor}`,\n    circleBorderSuccess: `2px solid ${successColor}`,\n    circleBorderWarning: `2px solid ${warningColor}`,\n    iconColor: textColor3,\n    iconColorInfo: infoColor,\n    iconColorError: errorColor,\n    iconColorSuccess: successColor,\n    iconColorWarning: warningColor,\n    titleTextColor: textColor1,\n    contentTextColor: textColor2,\n    metaTextColor: textColor3,\n    lineColor: railColor\n  }\n}\n\nexport type TimelineThemeVars = ReturnType<typeof self>\n\nconst timelineLight: Theme<'Timeline', TimelineThemeVars> = {\n  name: 'Timeline',\n  common: commonLight,\n  self\n}\n\nexport default timelineLight\nexport type TimelineTheme = typeof timelineLight\n"
  },
  {
    "path": "src/timeline/tests/Timeline.spec.ts",
    "content": "import { mount } from '@vue/test-utils'\nimport { h } from 'vue'\nimport { NTimeline, NTimelineItem } from '../index'\n\ndescribe('n-timeline', () => {\n  it('should work with import on demand', () => {\n    mount(NTimeline)\n  })\n\n  it('should work with `item-placement` prop', async () => {\n    const wrapper = mount(NTimeline)\n    expect(wrapper.find('.n-timeline').classes()).toContain(\n      'n-timeline--left-placement'\n    )\n    await wrapper.setProps({ itemPlacement: 'right' })\n    expect(wrapper.find('.n-timeline').classes()).toContain(\n      'n-timeline--right-placement'\n    )\n  })\n\n  it('should work with `icon-size` prop', async () => {\n    const iconSize = 50\n    const wrapper = mount(NTimeline, {\n      props: { iconSize },\n      slots: { default: () => h(NTimelineItem) }\n    })\n    expect(wrapper.find('.n-timeline-item').attributes('style')).toContain(\n      `--n-icon-size: ${iconSize}px`\n    )\n  })\n\n  it('should work with `size` prop', async () => {\n    const wrapper = mount(NTimeline)\n    expect(wrapper.find('.n-timeline').classes()).toContain(\n      'n-timeline--medium-size'\n    )\n    await wrapper.setProps({ size: 'large' })\n    expect(wrapper.find('.n-timeline').classes()).toContain(\n      'n-timeline--large-size'\n    )\n  })\n\n  it('should work with `default` slot', async () => {\n    const wrapper = mount(NTimeline, {\n      slots: {\n        default: () => h(NTimelineItem)\n      }\n    })\n    expect(wrapper.find('.n-timeline').element.children.length).toBe(1)\n    expect(\n      wrapper.find('.n-timeline').element.children[0].getAttribute('class')\n    ).toContain('n-timeline-item')\n  })\n\n  it('should work with `horizontal` prop', async () => {\n    const wrapper = mount(NTimeline, {\n      props: {\n        horizontal: true\n      }\n    })\n    expect(wrapper.find('.n-timeline').classes()).toContain(\n      'n-timeline--horizontal'\n    )\n    expect(wrapper.find('.n-timeline').classes()).not.toContain(\n      'n-timeline--left-placement'\n    )\n    expect(wrapper.find('.n-timeline').classes()).not.toContain(\n      'n-timeline--right-placement'\n    )\n  })\n})\n\ndescribe('n-timeline-item', () => {\n  it('should work with `color` prop', async () => {\n    let wrapper = mount(NTimeline, {\n      slots: {\n        default: () =>\n          h(NTimelineItem, { title: 'test-title' }, { icon: () => 'icon' })\n      }\n    })\n    expect(\n      wrapper.find('.n-timeline-item-timeline__icon').attributes('style')\n    ).toBe(undefined)\n\n    wrapper = mount(NTimeline, {\n      slots: {\n        default: () =>\n          h(\n            NTimelineItem,\n            { title: 'test-title', color: 'grey' },\n            { icon: () => 'icon' }\n          )\n      }\n    })\n    expect(\n      wrapper.find('.n-timeline-item-timeline__icon').attributes('style')\n    ).toContain('color: grey')\n\n    wrapper.unmount()\n  })\n\n  it('should work with `content`, `time`, `title` props', async () => {\n    const wrapper = mount(NTimeline, {\n      slots: {\n        default: () =>\n          h(NTimelineItem, {\n            title: 'test-title',\n            content: 'test-content',\n            time: '2021-07-28'\n          })\n      }\n    })\n    expect(wrapper.find('.n-timeline-item-content__title').exists()).toBe(true)\n    expect(wrapper.find('.n-timeline-item-content__title').text()).toBe(\n      'test-title'\n    )\n    expect(wrapper.find('.n-timeline-item-content__content').exists()).toBe(\n      true\n    )\n    expect(wrapper.find('.n-timeline-item-content__content').text()).toBe(\n      'test-content'\n    )\n    expect(wrapper.find('.n-timeline-item-content__meta').exists()).toBe(true)\n    expect(wrapper.find('.n-timeline-item-content__meta').text()).toBe(\n      '2021-07-28'\n    )\n  })\n\n  it('should work with `type` prop', async () => {\n    ;(['default', 'success', 'info', 'warning', 'error'] as const).forEach(\n      (item) => {\n        const wrapper = mount(NTimeline, {\n          slots: {\n            default: () => h(NTimelineItem, { title: 'test-title', type: item })\n          }\n        })\n        expect(wrapper.find('.n-timeline-item').classes()).toContain(\n          `n-timeline-item--${item}-type`\n        )\n      }\n    )\n  })\n\n  it('should work with `line-type` prop', () => {\n    ;(['default', 'dashed'] as const).forEach((lineType) => {\n      const wrapper = mount(NTimeline, {\n        slots: {\n          default: () => h(NTimelineItem, { title: 'test-title', lineType })\n        }\n      })\n\n      expect(wrapper.find('.n-timeline-item').classes()).toContain(\n        `n-timeline-item--${lineType}-line-type`\n      )\n    })\n  })\n\n  it('should work with `default`, `footer`, `header` slots', async () => {\n    const wrapper = mount(NTimeline, {\n      slots: {\n        default: () =>\n          h(NTimelineItem, null, {\n            header: () => 'test-header',\n            icon: () => 'icon',\n            default: () => 'test-default',\n            footer: () => 'test-footer'\n          })\n      }\n    })\n    expect(wrapper.find('.n-timeline-item-content__title').exists()).toBe(true)\n    expect(wrapper.find('.n-timeline-item-content__title').text()).toBe(\n      'test-header'\n    )\n    expect(wrapper.find('.n-timeline-item-timeline__icon').exists()).toBe(true)\n    expect(wrapper.find('.n-timeline-item-timeline__icon').text()).toBe('icon')\n    expect(wrapper.find('.n-timeline-item-content__content').exists()).toBe(\n      true\n    )\n    expect(wrapper.find('.n-timeline-item-content__content').text()).toBe(\n      'test-default'\n    )\n    expect(wrapper.find('.n-timeline-item-content__meta').exists()).toBe(true)\n    expect(wrapper.find('.n-timeline-item-content__meta').text()).toBe(\n      'test-footer'\n    )\n  })\n})\n"
  },
  {
    "path": "src/timeline/tests/server.spec.tsx",
    "content": "import { setup } from '@css-render/vue3-ssr'\nimport { renderToString } from '@vue/server-renderer'\n/**\n * @vitest-environment node\n */\nimport { createSSRApp, h } from 'vue'\nimport { NTimeline } from '../..'\n\ndescribe('server side rendering', () => {\n  it('works', async () => {\n    const app = createSSRApp(() => <NTimeline />)\n    setup(app)\n    try {\n      await renderToString(app)\n    }\n    catch (e) {\n      expect(e).not.toBeTruthy()\n    }\n  })\n})\n"
  },
  {
    "path": "src/tooltip/demos/enUS/arrow.demo.vue",
    "content": "<markdown>\n# No arrow\n</markdown>\n\n<template>\n  <n-tooltip trigger=\"hover\" :show-arrow=\"false\">\n    <template #trigger>\n      <n-button>Show arrow by default</n-button>\n    </template>\n    The same as popover\n  </n-tooltip>\n</template>\n"
  },
  {
    "path": "src/tooltip/demos/enUS/basic.demo.vue",
    "content": "<markdown>\n# Basic\n</markdown>\n\n<template>\n  <n-tooltip trigger=\"hover\">\n    <template #trigger>\n      <n-button> Duck </n-button>\n    </template>\n    If it looks like a duck, walks like a duck, and quacks like a duck...it must\n    be a duck.\n  </n-tooltip>\n</template>\n"
  },
  {
    "path": "src/tooltip/demos/enUS/body-style.demo.vue",
    "content": "<markdown>\n# Body style\n\nSetting style is sometimes useful.\n</markdown>\n\n<template>\n  <n-space>\n    <n-tooltip :style=\"{ maxWidth: '400px' }\" trigger=\"click\">\n      <template #trigger>\n        <n-button> California Girls </n-button>\n      </template>\n      I wish they all could be California girls. I wish they all could be\n      California girls. I wish they all could be California girls.\n    </n-tooltip>\n    <n-tooltip :style=\"{ maxWidth: '400px' }\" trigger=\"click\">\n      <template #trigger>\n        <n-button> California Girls </n-button>\n      </template>\n      I wish ...\n    </n-tooltip>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/tooltip/demos/enUS/event.demo.vue",
    "content": "<markdown>\n# Event\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { useMessage } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst message = useMessage()\nconst showPopover = ref(false)\n\nfunction handleUpdateShow(show: boolean) {\n  message.success(`${show}`)\n}\n</script>\n\n<template>\n  <n-space>\n    <n-tooltip\n      placement=\"bottom\"\n      trigger=\"hover\"\n      @update:show=\"handleUpdateShow\"\n    >\n      <template #trigger>\n        <n-button> Hover </n-button>\n      </template>\n      <span> I wish they all could be California girls </span>\n    </n-tooltip>\n    <n-tooltip\n      placement=\"bottom\"\n      trigger=\"click\"\n      @update:show=\"handleUpdateShow\"\n    >\n      <template #trigger>\n        <n-button> Click </n-button>\n      </template>\n      <span> I wish they all could be California girls </span>\n    </n-tooltip>\n    <n-tooltip :show=\"showPopover\" trigger=\"manual\" placement=\"bottom\">\n      <template #trigger>\n        <n-button @click=\"showPopover = !showPopover\">\n          Manual (No event will be emitted)\n        </n-button>\n      </template>\n      <span> I wish they all could be California girls </span>\n    </n-tooltip>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/tooltip/demos/enUS/index.demo-entry.md",
    "content": "# Tooltip\n\nIt walks like a popover, quacks like a popover but looks a bit different from popover.\n\n## Demos\n\n```demo\nbasic.vue\ntrigger.vue\nevent.vue\nplacement.vue\nbody-style.vue\narrow.vue\n```\n\n## API\n\n### Tooltip Props\n\nSee [Popover Props](popover#Popover-Props)\n\n### Tooltip Slots\n\nSee [Popover Slots](popover#Popover-Slots)\n"
  },
  {
    "path": "src/tooltip/demos/enUS/placement.demo.vue",
    "content": "<markdown>\n# Placement\n</markdown>\n\n<template>\n  <n-tooltip placement=\"top-start\" trigger=\"hover\">\n    <template #trigger>\n      <n-button> Top Start </n-button>\n    </template>\n    Woo, awesome!\n  </n-tooltip>\n</template>\n"
  },
  {
    "path": "src/tooltip/demos/enUS/trigger.demo.vue",
    "content": "<markdown>\n# Trigger\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst showPopover = ref(false)\n</script>\n\n<template>\n  <n-space>\n    <n-tooltip placement=\"bottom\" trigger=\"hover\">\n      <template #trigger>\n        <n-button> Hover </n-button>\n      </template>\n      <span> I wish they all could be California girls </span>\n    </n-tooltip>\n    <n-tooltip placement=\"bottom\" trigger=\"click\">\n      <template #trigger>\n        <n-button> Click </n-button>\n      </template>\n      <span> I wish they all could be California girls </span>\n    </n-tooltip>\n    <n-tooltip :show=\"showPopover\" placement=\"bottom\">\n      <template #trigger>\n        <n-button @click=\"showPopover = !showPopover\">\n          Manual\n        </n-button>\n      </template>\n      <span> I wish they all could be California girls </span>\n    </n-tooltip>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/tooltip/demos/zhCN/arrow.demo.vue",
    "content": "<markdown>\n# 不要箭头\n</markdown>\n\n<template>\n  <n-tooltip :show-arrow=\"false\" trigger=\"hover\">\n    <template #trigger>\n      <n-button>默认有箭头</n-button>\n    </template>\n    和 Popover 一样\n  </n-tooltip>\n</template>\n"
  },
  {
    "path": "src/tooltip/demos/zhCN/basic.demo.vue",
    "content": "<markdown>\n# 基础用法\n</markdown>\n\n<template>\n  <n-tooltip trigger=\"hover\">\n    <template #trigger>\n      <n-button> 鸭子 </n-button>\n    </template>\n    如果它长得像鸭子，走起来像鸭子，叫起来也像鸭子，那它一定是个鸭子。\n  </n-tooltip>\n</template>\n"
  },
  {
    "path": "src/tooltip/demos/zhCN/body-style.demo.vue",
    "content": "<markdown>\n# 主体样式\n\n有时候设定主体样式还是挺有用的。\n</markdown>\n\n<template>\n  <n-space>\n    <n-tooltip :style=\"{ maxWidth: '400px' }\" trigger=\"click\">\n      <template #trigger>\n        <n-button> 加州女孩 </n-button>\n      </template>\n      我希望她们都是加州女孩，我希望她们都是加州女孩，我希望她们都是加州女孩\n    </n-tooltip>\n    <n-tooltip :style=\"{ maxWidth: '400px' }\" trigger=\"click\">\n      <template #trigger>\n        <n-button> 加州女孩 </n-button>\n      </template>\n      我希望...\n    </n-tooltip>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/tooltip/demos/zhCN/event.demo.vue",
    "content": "<markdown>\n# 事件\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { useMessage } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst message = useMessage()\nconst showPopover = ref(false)\n\nfunction handleUpdateShow(show: boolean) {\n  message.success(`${show}`)\n}\n</script>\n\n<template>\n  <n-space>\n    <n-tooltip\n      placement=\"bottom\"\n      trigger=\"hover\"\n      @update:show=\"handleUpdateShow\"\n    >\n      <template #trigger>\n        <n-button> 悬浮 </n-button>\n      </template>\n      <span> I wish they all could be California girls </span>\n    </n-tooltip>\n    <n-tooltip\n      placement=\"bottom\"\n      trigger=\"click\"\n      @update:show=\"handleUpdateShow\"\n    >\n      <template #trigger>\n        <n-button> 点击 </n-button>\n      </template>\n      <span> I wish they all could be California girls </span>\n    </n-tooltip>\n    <n-tooltip :show=\"showPopover\" trigger=\"manual\" placement=\"bottom\">\n      <template #trigger>\n        <n-button @click=\"showPopover = !showPopover\">\n          手动（不会有事件发出来）\n        </n-button>\n      </template>\n      <span> I wish they all could be California girls </span>\n    </n-tooltip>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/tooltip/demos/zhCN/index.demo-entry.md",
    "content": "# 弹出提示 Tooltip\n\n它走起来像一个 Popover，叫起来像一个 Popover，但是长得有点区别。\n\n## 演示\n\n```demo\nbasic.vue\ntrigger.vue\nevent.vue\nplacement.vue\nbody-style.vue\narrow.vue\nrtl-debug.vue\n```\n\n## API\n\n### Tooltip Props\n\n参考 [Popover Props](popover#Popover-Props)\n\n### Tooltip Slots\n\n参考 [Popover Slots](popover#Popover-Slots)\n"
  },
  {
    "path": "src/tooltip/demos/zhCN/placement.demo.vue",
    "content": "<markdown>\n# 位置\n</markdown>\n\n<template>\n  <n-tooltip placement=\"top-start\" trigger=\"hover\">\n    <template #trigger>\n      <n-button> 上边一开始 </n-button>\n    </template>\n    哇哦，Awesome！\n  </n-tooltip>\n</template>\n"
  },
  {
    "path": "src/tooltip/demos/zhCN/rtl-debug.demo.vue",
    "content": "<markdown>\n# Rtl Debug\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { unstablePopoverRtl } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst rtlEnabled = ref(false)\nconst rtlStyles = [unstablePopoverRtl]\n</script>\n\n<template>\n  <n-space vertical>\n    <n-space><n-switch v-model:value=\"rtlEnabled\" />Rtl</n-space>\n    <n-config-provider :rtl=\"rtlEnabled ? rtlStyles : undefined\">\n      <n-tooltip trigger=\"click\">\n        <template #trigger>\n          <n-button>悬浮</n-button>\n        </template>\n        <template #header>\n          <span>header</span>\n        </template>\n        <template #footer>\n          <span>footer</span>\n        </template>\n        <span>或许不想知道你的花园长得咋样</span>\n      </n-tooltip>\n    </n-config-provider>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/tooltip/demos/zhCN/trigger.demo.vue",
    "content": "<markdown>\n# 触发方式\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst showPopover = ref(false)\n</script>\n\n<template>\n  <n-space>\n    <n-tooltip placement=\"bottom\" trigger=\"hover\">\n      <template #trigger>\n        <n-button> 悬浮 </n-button>\n      </template>\n      <span> I wish they all could be California girls </span>\n    </n-tooltip>\n    <n-tooltip placement=\"bottom\" trigger=\"click\">\n      <template #trigger>\n        <n-button> 点击 </n-button>\n      </template>\n      <span> I wish they all could be California girls </span>\n    </n-tooltip>\n    <n-tooltip :show=\"showPopover\" placement=\"bottom\">\n      <template #trigger>\n        <n-button @click=\"showPopover = !showPopover\">\n          手动\n        </n-button>\n      </template>\n      <span> I wish they all could be California girls </span>\n    </n-tooltip>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/tooltip/index.ts",
    "content": "export { default as NTooltip, tooltipProps } from './src/Tooltip'\nexport type { TooltipInst, TooltipProps, TooltipSlots } from './src/Tooltip'\n"
  },
  {
    "path": "src/tooltip/src/Tooltip.ts",
    "content": "import type { SlotsType } from 'vue'\nimport type { ThemeProps } from '../../_mixins'\nimport type { ExtractPublicPropTypes } from '../../_utils'\nimport type { PopoverInst, PopoverSlots } from '../../popover'\nimport type { TooltipTheme } from '../styles'\n// Tooltip: popover wearing waistcoat\nimport { computed, defineComponent, h, ref } from 'vue'\nimport { useConfig, useTheme } from '../../_mixins'\nimport { NPopover } from '../../popover'\nimport { popoverBaseProps } from '../../popover/src/Popover'\nimport { tooltipLight } from '../styles'\n\nexport type TooltipInst = PopoverInst\n\nexport const tooltipProps = {\n  ...popoverBaseProps,\n  ...(useTheme.props as ThemeProps<TooltipTheme>)\n}\n\nexport type TooltipProps = ExtractPublicPropTypes<typeof tooltipProps>\n\nexport interface TooltipSlots extends PopoverSlots {}\n\nexport default defineComponent({\n  name: 'Tooltip',\n  props: tooltipProps,\n  slots: Object as SlotsType<TooltipSlots>,\n  __popover__: true,\n  setup(props) {\n    const { mergedClsPrefixRef } = useConfig(props)\n    const themeRef = useTheme(\n      'Tooltip',\n      '-tooltip',\n      undefined,\n      tooltipLight,\n      props,\n      mergedClsPrefixRef\n    )\n    const popoverRef = ref<PopoverInst | null>(null)\n    const tooltipExposedMethod: TooltipInst = {\n      syncPosition() {\n        popoverRef.value!.syncPosition()\n      },\n      setShow(show: boolean) {\n        popoverRef.value!.setShow(show)\n      }\n    }\n    return {\n      ...tooltipExposedMethod,\n      popoverRef,\n      mergedTheme: themeRef,\n      popoverThemeOverrides: computed(() => {\n        return themeRef.value.self\n      })\n    }\n  },\n  render() {\n    const { mergedTheme, internalExtraClass } = this\n    return h(\n      NPopover,\n      {\n        ...this.$props,\n        theme: mergedTheme.peers.Popover,\n        themeOverrides: mergedTheme.peerOverrides.Popover,\n        builtinThemeOverrides: this.popoverThemeOverrides,\n        internalExtraClass: internalExtraClass.concat('tooltip'),\n        ref: 'popoverRef'\n      },\n      this.$slots\n    )\n  }\n})\n"
  },
  {
    "path": "src/tooltip/styles/_common.ts",
    "content": "export default {\n  padding: '8px 14px'\n}\n"
  },
  {
    "path": "src/tooltip/styles/dark.ts",
    "content": "import type { TooltipTheme } from './light'\nimport { commonDark } from '../../_styles/common'\nimport { popoverDark } from '../../popover/styles'\nimport commonVars from './_common'\n\nconst tooltipDark: TooltipTheme = {\n  name: 'Tooltip',\n  common: commonDark,\n  peers: {\n    Popover: popoverDark\n  },\n  self(vars) {\n    const { borderRadius, boxShadow2, popoverColor, textColor2 } = vars\n    return {\n      ...commonVars,\n      borderRadius,\n      boxShadow: boxShadow2,\n      color: popoverColor,\n      textColor: textColor2\n    }\n  }\n}\n\nexport default tooltipDark\n"
  },
  {
    "path": "src/tooltip/styles/index.ts",
    "content": "export { default as tooltipDark } from './dark'\nexport { default as tooltipLight } from './light'\nexport type { TooltipTheme, TooltipThemeVars } from './light'\n"
  },
  {
    "path": "src/tooltip/styles/light.ts",
    "content": "import type { ThemeCommonVars } from '../../_styles/common'\nimport { composite } from 'seemly'\nimport { createTheme } from '../../_mixins/use-theme'\nimport { commonLight } from '../../_styles/common'\nimport { popoverLight } from '../../popover/styles'\nimport commonVars from './_common'\n\nfunction self(vars: ThemeCommonVars) {\n  const { borderRadius, boxShadow2, baseColor } = vars\n  return {\n    ...commonVars,\n    borderRadius,\n    boxShadow: boxShadow2,\n    color: composite(baseColor, 'rgba(0, 0, 0, .85)'),\n    textColor: baseColor\n  }\n}\n\nexport type TooltipThemeVars = ReturnType<typeof self>\n\nconst tooltipLight = createTheme({\n  name: 'Tooltip',\n  common: commonLight,\n  peers: {\n    Popover: popoverLight\n  },\n  self\n})\n\nexport default tooltipLight\nexport type TooltipTheme = typeof tooltipLight\n"
  },
  {
    "path": "src/tooltip/tests/Tooltip.spec.ts",
    "content": "import { mount } from '@vue/test-utils'\nimport { NTooltip } from '../index'\n\ndescribe('n-tooltip', () => {\n  it('should work with import on demand', () => {\n    mount(NTooltip, {\n      slots: {\n        trigger: () => '07akioni'\n      }\n    })\n  })\n\n  it('should work with `show` props', async () => {\n    const wrapper = mount(NTooltip, {\n      slots: {\n        default: () => 'test-default',\n        trigger: () => 'test-trigger'\n      },\n      attachTo: document.body\n    })\n    expect(document.querySelector('.n-tooltip')).toEqual(null)\n\n    await wrapper.setProps({ show: true })\n    expect(document.querySelector('.n-tooltip')).not.toEqual(null)\n    wrapper.unmount()\n  })\n})\n"
  },
  {
    "path": "src/tooltip/tests/server.spec.tsx",
    "content": "import { setup } from '@css-render/vue3-ssr'\nimport { renderToString } from '@vue/server-renderer'\n/**\n * @vitest-environment node\n */\nimport { createSSRApp, h } from 'vue'\nimport { NTooltip } from '../..'\n\ndescribe('server side rendering', () => {\n  it('works', async () => {\n    const app = createSSRApp(() => (\n      <NTooltip>\n        {{\n          trigger: () => 'kirby'\n        }}\n      </NTooltip>\n    ))\n    setup(app)\n    try {\n      await renderToString(app)\n    }\n    catch (e) {\n      expect(e).not.toBeTruthy()\n    }\n  })\n})\n"
  },
  {
    "path": "src/transfer/demos/enUS/basic.demo.vue",
    "content": "<markdown>\n# Basic\n\nBasic example of the Transfer component. If you have tons of data, see below for virtualized list.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nfunction createOptions() {\n  return Array.from({ length: 100 }).map((v, i) => ({\n    label: `Option ${i}`,\n    value: i,\n    disabled: i % 5 === 0\n  }))\n}\n\nconst options = createOptions()\nconst value = ref([])\n</script>\n\n<template>\n  <n-transfer v-model:value=\"value\" :options=\"options\" />\n</template>\n"
  },
  {
    "path": "src/transfer/demos/enUS/filterable.demo.vue",
    "content": "<markdown>\n# Filterable\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nfunction createOptions() {\n  return Array.from({ length: 100 }).map((v, i) => ({\n    label: `Option ${i}`,\n    value: i,\n    disabled: i % 5 === 0\n  }))\n}\n\nfunction createValues() {\n  return Array.from({ length: 50 }).map((v, i) => i)\n}\n\nconst options1 = createOptions()\nconst value1 = ref(createValues())\nconst options2 = createOptions()\nconst value2 = ref(createValues())\n</script>\n\n<template>\n  <n-space vertical>\n    <n-transfer\n      v-model:value=\"value1\"\n      virtual-scroll\n      :options=\"options1\"\n      source-filterable\n    />\n    <n-transfer\n      v-model:value=\"value2\"\n      virtual-scroll\n      :options=\"options2\"\n      target-filterable\n    />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/transfer/demos/enUS/index.demo-entry.md",
    "content": "# Transfer\n\nA more efficient transfer.\n\nIf you want to use original transfer, please refer to [Legacy Transfer](legacy-transfer). Please note that the legacy transfer will be removed in the next major version. It's not recommended to to use it.\n\n## Demos\n\n```demo\nbasic.vue\nlarge-data.vue\nfilterable.vue\nrender-label.vue\nrender-source-list.vue\n```\n\n## API\n\n### Transfer Props\n\n| Name | Type | Default | Description | Version |\n| --- | --- | --- | --- | --- |\n| clear-text | `string` | `undefined` | Text of clear button. | 2.35.0 |\n| default-value | `Array<string \\| number> \\| null` | `null` | Default value. | 2.32.0 |\n| disabled | `boolean` | `true` | Disabled state. | 2.32.0 |\n| filter | `(pattern: string, option: TransferOption, from: 'source' \\| 'target') => boolean` | A basic label string match function. | 2.32.0, `from` 2.32.2 |\n| options | `TransferOption[]` | `[]` | For configuration options, see the TransferOption Type below. | 2.32.0 |\n| render-source-label | `(props: { option: TransferOption }) => VNodeChild` | `undefined` | Customize source label rendering. | 2.32.0 |\n| render-target-label | `(props: { option: TransferOption }) => VNodeChild` | `undefined` | Customize target label rendering. | 2.32.0 |\n| render-source-list | `(props: { onCheck: (checkedValueList: Array<string \\| number>) => void, checkedOptions: TransferOption[], pattern: string }) => VNodeChild` | `undefined` | Customize source list rendering. | 2.32.0 |\n| render-target-list | `(props: { onCheck: (checkedValueList: Array<string \\| number>) => void, checkedOptions: TransferOption[], pattern: string }) => VNodeChild` | `undefined` | Customize target list rendering. | 2.33.4 |\n| select-all-text | `string` | `undefined` | Text of select all button. | 2.35.0 |\n| show-selected | `boolean` | `true` | Whether to show selected options in the source list. | 2.34.0 |\n| size | `'small' \\| 'medium' \\| 'large'` | `'medium'` | Size. | 2.32.0 |\n| source-filterable | `boolean` | `false` | The source filterable state. | 2.32.2 |\n| source-filter-placeholder | `string` | `undefined` | Placeholder for the source items search box. | 2.32.0 |\n| source-title | `string \\| (() => VNodeChild)` | `undefined` | Source items title. | 2.32.0, Render function since 2.40.0 |\n| target-filterable | `boolean` | `false` | The target filterable state. | 2.32.2 |\n| target-filter-placeholder | `string` | `undefined` | Placeholder for the target items search box. | 2.32.0 |\n| target-title | `string \\| (() => VNodeChild)` | `undefined` | Target items title. | 2.32.0, Render function since 2.40.0 |\n| value | `Array<string \\| number> \\| null` | `undefined` | Value when being set manually. | 2.32.0 |\n| on-update:value | `(value: Array<string \\| number>) => void` | `undefined` | Callback when the value changes. | 2.32.0 |\n| virtual-scroll | `boolean` | `false` | Enable virtual scrolling. | 2.32.0 |\n\n#### TransferOption Type\n\n| Property | Type               | Description                    |\n| -------- | ------------------ | ------------------------------ |\n| label    | `string`           | The option's label to display. |\n| value    | `string \\| number` | The option's unique value.     |\n| disabled | `boolean`          | The option's disabled state.   |\n"
  },
  {
    "path": "src/transfer/demos/enUS/large-data.demo.vue",
    "content": "<markdown>\n# Large data\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nfunction createOptions() {\n  return Array.from({ length: 42000 }).map((v, i) => ({\n    label: `Option${i}`,\n    value: i,\n    disabled: i % 5 === 0\n  }))\n}\n\nfunction createValues() {\n  return Array.from({ length: 50 }).map((v, i) => i)\n}\n\nconst options = createOptions()\nconst value = ref(createValues())\n</script>\n\n<template>\n  <n-transfer v-model:value=\"value\" :options=\"options\" virtual-scroll />\n</template>\n"
  },
  {
    "path": "src/transfer/demos/enUS/render-label.demo.vue",
    "content": "<markdown>\n# Custom label\n\nTransfer can be applied for many scenarios.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { TransferRenderTargetLabel } from 'naive-ui'\nimport { NAvatar } from 'naive-ui'\nimport { h, ref } from 'vue'\n\nconst options = [\n  {\n    label: '07akioni',\n    value: 'https://avatars.githubusercontent.com/u/18677354?s=60&v=4'\n  },\n  {\n    label: 'amadeus711',\n    value: 'https://avatars.githubusercontent.com/u/46394163?s=60&v=4'\n  },\n  {\n    label: 'Talljack',\n    value: 'https://avatars.githubusercontent.com/u/34439652?s=60&v=4'\n  },\n  {\n    label: 'JiwenBai',\n    value: 'https://avatars.githubusercontent.com/u/43430022?s=60&v=4'\n  },\n  {\n    label: 'songjianet',\n    value: 'https://avatars.githubusercontent.com/u/19239641?s=60&v=4'\n  }\n]\n\nconst renderLabel: TransferRenderTargetLabel = function ({ option }) {\n  return h(\n    'div',\n    {\n      style: {\n        display: 'flex',\n        margin: '6px 0'\n      }\n    },\n    {\n      default: () => [\n        h(NAvatar, {\n          round: true,\n          src: option.value as string,\n          size: 'small',\n          fallbackSrc:\n            'https://07akioni.oss-cn-beijing.aliyuncs.com/07akioni.jpeg'\n        }),\n        h(\n          'div',\n          {\n            style: {\n              display: 'flex',\n              marginLeft: '6px',\n              alignSelf: 'center'\n            }\n          },\n          { default: () => option.label }\n        )\n      ]\n    }\n  )\n}\n\nconst value = ref([options[0].value])\n</script>\n\n<template>\n  <n-transfer\n    v-model:value=\"value\"\n    :options=\"options\"\n    :render-target-label=\"renderLabel\"\n  />\n</template>\n"
  },
  {
    "path": "src/transfer/demos/enUS/render-source-list.demo.vue",
    "content": "<markdown>\n# Custom source list\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { TransferRenderSourceList, TreeOption } from 'naive-ui'\nimport { NTree } from 'naive-ui'\nimport { repeat } from 'seemly'\nimport { h, ref } from 'vue'\n\nfunction createLabel(level: number): string {\n  if (level === 4)\n    return 'Foo'\n  if (level === 3)\n    return 'Bar'\n  if (level === 2)\n    return 'Baz'\n  if (level === 1)\n    return '???'\n  return ''\n}\n\ninterface Option {\n  label: string\n  value: string\n  children?: Option[]\n}\n\nfunction createData(level = 4, baseKey = ''): Option[] | undefined {\n  if (!level)\n    return undefined\n  return repeat(6 - level, undefined).map((_, index) => {\n    const value = `${baseKey}${level}${index}`\n    return {\n      label: createLabel(level),\n      value,\n      children: createData(level - 1, value)\n    }\n  })\n}\n\nfunction flattenTree(list: undefined | Option[]): Option[] {\n  const result: Option[] = []\n  function flatten(_list: Option[] = []) {\n    _list.forEach((item) => {\n      result.push(item)\n      flatten(item.children)\n    })\n  }\n  flatten(list)\n  return result\n}\n\nconst treeData = createData()\nconst value = ref<Array<string | number>>([])\nconst renderSourceList: TransferRenderSourceList = function ({\n  onCheck,\n  pattern\n}) {\n  return h(NTree, {\n    style: 'margin: 0 4px;',\n    keyField: 'value',\n    checkable: true,\n    selectable: false,\n    blockLine: true,\n    checkOnClick: true,\n    data: treeData as unknown as TreeOption[],\n    pattern,\n    checkedKeys: value.value,\n    onUpdateCheckedKeys: (checkedKeys: Array<string | number>) => {\n      onCheck(checkedKeys)\n    }\n  })\n}\n\nconst options = flattenTree(createData())\n</script>\n\n<template>\n  <n-transfer\n    v-model:value=\"value\"\n    :options=\"options\"\n    :render-source-list=\"renderSourceList\"\n    source-filterable\n  />\n</template>\n"
  },
  {
    "path": "src/transfer/demos/enUS/size.demo.vue",
    "content": "<markdown>\n# Size\n\nMixing sizes does not look harmonious.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nfunction createOptions() {\n  return Array.from({ length: 100 }).map((v, i) => ({\n    label: `Option ${i}`,\n    value: i,\n    disabled: i % 5 === 0\n  }))\n}\n\nfunction createValues() {\n  return Array.from({ length: 50 }).map((v, i) => i)\n}\n\nconst options = createOptions()\nconst value = ref(createValues())\n</script>\n\n<template>\n  <n-space vertical>\n    <n-transfer v-model:value=\"value\" :options=\"options\" size=\"small\" />\n    <n-transfer v-model:value=\"value\" :options=\"options\" size=\"large\" />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/transfer/demos/zhCN/asynchronous-options-debug.demo.vue",
    "content": "<markdown>\n# 异步options报错debug\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { TransferOption } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst values = ref([1])\nconst options = ref<TransferOption[]>([])\nfunction getOptions() {\n  setTimeout(() => {\n    options.value = [\n      {\n        label: 'Option1',\n        value: 1\n      },\n      {\n        label: 'Option2',\n        value: 2\n      },\n      {\n        label: 'Option3',\n        value: 3\n      }\n    ]\n  }, 1000)\n}\ngetOptions()\n</script>\n\n<template>\n  <NTransfer v-model:value=\"values\" :options=\"options\" source-filterable />\n</template>\n"
  },
  {
    "path": "src/transfer/demos/zhCN/basic.demo.vue",
    "content": "<markdown>\n# 基础用法\n\n穿梭框的基础用法。如果你有一大堆数据，看下一个例子。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nfunction createOptions() {\n  return Array.from({ length: 100 }).map((v, i) => ({\n    label: `Option ${i}`,\n    value: i,\n    disabled: i % 5 === 0\n  }))\n}\n\nconst options = createOptions()\nconst value = ref([])\n</script>\n\n<template>\n  <n-transfer v-model:value=\"value\" :options=\"options\" />\n</template>\n"
  },
  {
    "path": "src/transfer/demos/zhCN/filterable.demo.vue",
    "content": "<markdown>\n# 可过滤\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nfunction createOptions() {\n  return Array.from({ length: 100 }).map((v, i) => ({\n    label: `Option ${i}`,\n    value: i,\n    disabled: i % 5 === 0\n  }))\n}\n\nfunction createValues() {\n  return Array.from({ length: 50 }).map((v, i) => i)\n}\n\nconst options1 = createOptions()\nconst value1 = ref(createValues())\nconst options2 = createOptions()\nconst value2 = ref(createValues())\n</script>\n\n<template>\n  <n-space vertical>\n    <n-transfer\n      v-model:value=\"value1\"\n      virtual-scroll\n      :options=\"options1\"\n      source-filterable\n    />\n    <n-transfer\n      v-model:value=\"value2\"\n      virtual-scroll\n      :options=\"options2\"\n      target-filterable\n    />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/transfer/demos/zhCN/index.demo-entry.md",
    "content": "# 穿梭框 Transfer\n\n一个更高效的穿梭框。\n\n如果你需要使用原有的穿梭框，请参考 [旧版穿梭框](legacy-transfer)，需要注意旧版的穿梭框会在下一个主版本被移除，不建议使用。\n\n## 演示\n\n```demo\nbasic.vue\nlarge-data.vue\nfilterable.vue\nrender-label.vue\nrender-source-list.vue\nasynchronous-options-debug.vue\nvalue-debug.vue\n```\n\n## API\n\n### Transfer Props\n\n| 名称 | 类型 | 默认值 | 说明 | 版本 |\n| --- | --- | --- | --- | --- |\n| clear-text | `string` | `undefined` | 清除按钮的文本 | 2.35.0 |\n| default-value | `Array<string \\| number> \\| null` | `null` | 非受控模式下的默认值 | 2.32.0 |\n| disabled | `boolean` | `true` | 是否禁用 | 2.32.0 |\n| filter | `(pattern: string, option: TransferOption, from: 'source' \\| 'target') => boolean` | 一个简单的标签字符串匹配函数 | 搜索时使用的过滤函数 | 2.32.0，`from` 2.32.2 |\n| options | `TransferOption[]` | `[]` | 配置选项内容，详情见 TransferOption Type | 2.32.0 |\n| render-source-label | `(props: { option: TransferOption }) => VNodeChild` | `undefined` | 自定义源标签 | 2.32.0 |\n| render-target-label | `(props: { option: TransferOption }) => VNodeChild` | `undefined` | 自定义目标标签 | 2.32.0 |\n| render-source-list | `(props: { onCheck: (checkedValueList: Array<string \\| number>) => void, checkedOptions: TransferOption[], pattern: string }) => VNodeChild` | `undefined` | 自定义源列表 | 2.32.0 |\n| render-target-list | `(props: { onCheck: (checkedValueList: Array<string \\| number>) => void, checkedOptions: TransferOption[], pattern: string }) => VNodeChild` | `undefined` | 自定义目标列表 | 2.33.4 |\n| select-all-text | `string` | `undefined` | 全选按钮的文本 | 2.35.0 |\n| show-selected | `boolean` | `true` | 是否显示源列表中选中的项 | 2.34.0 |\n| size | `'small' \\| 'medium' \\| 'large'` | `'medium'` | 尺寸 | 2.32.0 |\n| source-filterable | `boolean` | `false` | 源项是否可过滤 | 2.32.2 |\n| source-filter-placeholder | `string` | `undefined` | 源项搜索框中的占位符 | 2.32.0 |\n| source-title | `string \\| (() => VNodeChild)` | `undefined` | 源项标题 | 2.32.0，2.40.0 支持 render 函数 |\n| target-filterable | `boolean` | `false` | 目标项是否可过滤 | 2.32.2 |\n| target-filter-placeholder | `string` | `undefined` | 目标项搜索框中的占位符 | 2.32.0 |\n| target-title | `string \\| (() => VNodeChild)` | `undefined` | 目标项标题 | 2.32.0，2.40.0 支持 render 函数 |\n| value | `Array<string \\| number> \\| null` | `undefined` | 受控模式下的值 | 2.32.0 |\n| on-update:value | `(value: Array<string \\| number>) => void` | `undefined` | 值发生改变时的回调 | 2.32.0 |\n| virtual-scroll | `boolean` | `false` | 是否启用虚拟滚动 | 2.32.0 |\n\n#### TransferOption Type\n\n| 属性     | 类型               | 说明                     |\n| -------- | ------------------ | ------------------------ |\n| label    | `string`           | 选项中用以页面显示的名称 |\n| value    | `string \\| number` | 所有选项中唯一的 `value` |\n| disabled | `boolean`          | 是否禁用这个选项         |\n"
  },
  {
    "path": "src/transfer/demos/zhCN/large-data.demo.vue",
    "content": "<markdown>\n# 一大堆数据\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nfunction createOptions() {\n  return Array.from({ length: 42000 }).map((v, i) => ({\n    label: `Option ${i}`,\n    value: i,\n    disabled: i % 5 === 0\n  }))\n}\n\nfunction createValues() {\n  return Array.from({ length: 50 }).map((v, i) => i)\n}\n\nconst options = createOptions()\nconst value = ref(createValues())\n</script>\n\n<template>\n  <n-transfer v-model:value=\"value\" :options=\"options\" virtual-scroll />\n</template>\n"
  },
  {
    "path": "src/transfer/demos/zhCN/render-label.demo.vue",
    "content": "<markdown>\n# 自定义标签\n\n可以变成通讯录、菜单等，应用场景挺多。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { TransferRenderTargetLabel } from 'naive-ui'\nimport { NAvatar } from 'naive-ui'\nimport { h, ref } from 'vue'\n\nconst options = [\n  {\n    label: '07akioni',\n    value: 'https://avatars.githubusercontent.com/u/18677354?s=60&v=4'\n  },\n  {\n    label: 'amadeus711',\n    value: 'https://avatars.githubusercontent.com/u/46394163?s=60&v=4'\n  },\n  {\n    label: 'Talljack',\n    value: 'https://avatars.githubusercontent.com/u/34439652?s=60&v=4'\n  },\n  {\n    label: 'JiwenBai',\n    value: 'https://avatars.githubusercontent.com/u/43430022?s=60&v=4'\n  },\n  {\n    label: 'songjianet',\n    value: 'https://avatars.githubusercontent.com/u/19239641?s=60&v=4'\n  }\n]\n\nconst renderLabel: TransferRenderTargetLabel = function ({ option }) {\n  return h(\n    'div',\n    {\n      style: {\n        display: 'flex',\n        margin: '6px 0'\n      }\n    },\n    {\n      default: () => [\n        h(NAvatar, {\n          round: true,\n          src: option.value as string,\n          size: 'small',\n          fallbackSrc:\n            'https://07akioni.oss-cn-beijing.aliyuncs.com/07akioni.jpeg'\n        }),\n        h(\n          'div',\n          {\n            style: {\n              display: 'flex',\n              marginLeft: '6px',\n              alignSelf: 'center'\n            }\n          },\n          { default: () => option.label }\n        )\n      ]\n    }\n  )\n}\n\nconst value = ref([options[0].value])\n</script>\n\n<template>\n  <n-transfer\n    v-model:value=\"value\"\n    :options=\"options\"\n    :render-target-label=\"renderLabel\"\n  />\n</template>\n"
  },
  {
    "path": "src/transfer/demos/zhCN/render-source-list.demo.vue",
    "content": "<markdown>\n# 自定义列表\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { TransferRenderSourceList, TreeOption } from 'naive-ui'\nimport { NTree } from 'naive-ui'\nimport { repeat } from 'seemly'\nimport { h, ref } from 'vue'\n\nfunction createLabel(level: number): string {\n  if (level === 4)\n    return '道生一'\n  if (level === 3)\n    return '一生二'\n  if (level === 2)\n    return '二生三'\n  if (level === 1)\n    return '三生万物'\n  return ''\n}\n\ninterface Option {\n  label: string\n  value: string\n  children?: Option[]\n}\n\nfunction createData(level = 4, baseKey = ''): Option[] | undefined {\n  if (!level)\n    return undefined\n  return repeat(6 - level, undefined).map((_, index) => {\n    const value = `${baseKey}${level}${index}`\n    return {\n      label: createLabel(level),\n      value,\n      children: createData(level - 1, value)\n    }\n  })\n}\n\nfunction flattenTree(list: undefined | Option[]): Option[] {\n  const result: Option[] = []\n  function flatten(_list: Option[] = []) {\n    _list.forEach((item) => {\n      result.push(item)\n      flatten(item.children)\n    })\n  }\n  flatten(list)\n  return result\n}\n\nconst treeData = createData()\nconst value = ref<Array<string | number>>([])\nconst renderSourceList: TransferRenderSourceList = function ({\n  onCheck,\n  pattern\n}) {\n  return h(NTree, {\n    style: 'margin: 0 4px;',\n    keyField: 'value',\n    checkable: true,\n    selectable: false,\n    blockLine: true,\n    checkOnClick: true,\n    data: treeData as unknown as TreeOption[],\n    pattern,\n    checkedKeys: value.value,\n    onUpdateCheckedKeys: (checkedKeys: Array<string | number>) => {\n      onCheck(checkedKeys)\n    }\n  })\n}\n\nconst options = flattenTree(createData())\n</script>\n\n<template>\n  <n-transfer\n    v-model:value=\"value\"\n    :options=\"options\"\n    :render-source-list=\"renderSourceList\"\n    source-filterable\n  />\n</template>\n"
  },
  {
    "path": "src/transfer/demos/zhCN/size.demo.vue",
    "content": "<markdown>\n# 尺寸\n\n太小太大好像都不怎么好看。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nfunction createOptions() {\n  return Array.from({ length: 100 }).map((v, i) => ({\n    label: `Option ${i}`,\n    value: i,\n    disabled: i % 5 === 0\n  }))\n}\n\nfunction createValues() {\n  return Array.from({ length: 50 }).map((v, i) => i)\n}\n\nconst options = createOptions()\nconst value = ref(createValues())\n</script>\n\n<template>\n  <n-space vertical>\n    <n-transfer v-model:value=\"value\" :options=\"options\" size=\"small\" />\n    <n-transfer v-model:value=\"value\" :options=\"options\" size=\"large\" />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/transfer/demos/zhCN/value-debug.demo.vue",
    "content": "<markdown>\n# Value debug\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nfunction createOptions() {\n  return Array.from({ length: 100 }).map((v, i) => ({\n    label: `Option ${i}`,\n    value: i,\n    disabled: i % 5 === 0\n  }))\n}\n\nconst options = createOptions()\nconst value = ref([9999, 9998, 9997])\n</script>\n\n<template>\n  {{ JSON.stringify(value) }}\n  <n-transfer v-model:value=\"value\" :options=\"options\" />\n</template>\n"
  },
  {
    "path": "src/transfer/index.ts",
    "content": "export type {\n  Option as TransferOption,\n  TransferRenderSourceLabel,\n  TransferRenderSourceList,\n  TransferRenderTargetLabel\n} from './src/interface'\nexport type * from './src/public-types'\nexport { default as NTransfer, transferProps } from './src/Transfer'\nexport type { TransferProps } from './src/Transfer'\n"
  },
  {
    "path": "src/transfer/src/Transfer.tsx",
    "content": "import type { CSSProperties, PropType, VNodeChild } from 'vue'\nimport type { ThemeProps } from '../../_mixins'\nimport type { ExtractPublicPropTypes, MaybeArray } from '../../_utils'\nimport type { TransferTheme } from '../styles'\nimport type {\n  Filter,\n  OnUpdateValue,\n  Option,\n  OptionValue,\n  TransferRenderSourceLabel,\n  TransferRenderSourceList,\n  TransferRenderTargetLabel\n} from './interface'\nimport type { TransferSize } from './public-types'\nimport { depx } from 'seemly'\nimport { useIsMounted } from 'vooks'\nimport { computed, defineComponent, h, provide, toRef, watchEffect } from 'vue'\nimport { NScrollbar } from '../../_internal'\nimport { useConfig, useFormItem, useTheme } from '../../_mixins'\nimport { call, warnOnce } from '../../_utils'\nimport { createKey } from '../../_utils/cssr'\nimport { transferLight } from '../styles'\nimport { transferInjectionKey } from './interface'\nimport style from './styles/index.cssr'\nimport NTransferFilter from './TransferFilter'\nimport NTransferHeader from './TransferHeader'\nimport NTransferList from './TransferList'\nimport { useTransferData } from './use-transfer-data'\n\nexport const transferProps = {\n  ...(useTheme.props as ThemeProps<TransferTheme>),\n  value: Array as PropType<OptionValue[] | null>,\n  defaultValue: {\n    type: Array as PropType<OptionValue[] | null>,\n    default: null\n  },\n  options: {\n    type: Array as PropType<Option[]>,\n    default: () => []\n  },\n  disabled: {\n    type: Boolean as PropType<boolean | undefined>,\n    default: undefined\n  },\n  virtualScroll: Boolean,\n  sourceTitle: [String, Function] as PropType<string | (() => VNodeChild)>,\n  selectAllText: String,\n  clearText: String,\n  targetTitle: [String, Function] as PropType<string | (() => VNodeChild)>,\n  filterable: {\n    type: Boolean,\n    default: undefined\n  },\n  sourceFilterable: Boolean,\n  targetFilterable: Boolean,\n  showSelected: {\n    type: Boolean,\n    default: true\n  },\n  sourceFilterPlaceholder: String,\n  targetFilterPlaceholder: String,\n  filter: {\n    type: Function as PropType<Filter>,\n    default: (pattern: string, option: Option) => {\n      if (!pattern)\n        return true\n      return ~`${option.label}`\n        .toLowerCase()\n        .indexOf(`${pattern}`.toLowerCase())\n    }\n  },\n  size: String as PropType<TransferSize>,\n  renderSourceLabel: Function as PropType<TransferRenderSourceLabel>,\n  renderTargetLabel: Function as PropType<TransferRenderTargetLabel>,\n  renderSourceList: Function as PropType<TransferRenderSourceList>,\n  renderTargetList: Function as PropType<TransferRenderSourceList>,\n  'onUpdate:value': [Function, Array] as PropType<MaybeArray<OnUpdateValue>>,\n  onUpdateValue: [Function, Array] as PropType<MaybeArray<OnUpdateValue>>,\n  onChange: [Function, Array] as PropType<MaybeArray<OnUpdateValue>>\n} as const\n\nexport type TransferProps = ExtractPublicPropTypes<typeof transferProps>\n\nexport default defineComponent({\n  name: 'Transfer',\n  props: transferProps,\n  setup(props) {\n    if (__DEV__) {\n      watchEffect(() => {\n        if (props.onChange !== undefined) {\n          warnOnce(\n            'transfer',\n            '`on-change` is deprecated, please use `on-update:value` instead.'\n          )\n        }\n        if (props.filterable !== undefined) {\n          warnOnce(\n            'transfer',\n            '`filterable` is deprecated, please use `source-filterable` or `target-filterable` instead.'\n          )\n        }\n      })\n    }\n    const { mergedClsPrefixRef, mergedComponentPropsRef } = useConfig(props)\n    const themeRef = useTheme(\n      'Transfer',\n      '-transfer',\n      style,\n      transferLight,\n      props,\n      mergedClsPrefixRef\n    )\n    const formItem = useFormItem(props, {\n      mergedSize: (NFormItem) => {\n        const { size } = props\n        if (size)\n          return size\n        const { mergedSize: formItemSize } = NFormItem || {}\n        if (formItemSize?.value)\n          return formItemSize.value as TransferSize\n        const configSize = mergedComponentPropsRef?.value?.Transfer?.size\n        if (configSize)\n          return configSize\n        return 'medium'\n      }\n    })\n    const { mergedSizeRef, mergedDisabledRef } = formItem\n    const itemSizeRef = computed(() => {\n      const { value: size } = mergedSizeRef\n      const {\n        self: { [createKey('itemHeight', size)]: itemSize }\n      } = themeRef.value\n      return depx(itemSize)\n    })\n    const {\n      uncontrolledValueRef,\n      mergedValueRef,\n      targetValueSetRef,\n      valueSetForCheckAllRef,\n      valueSetForUncheckAllRef,\n      valueSetForClearRef,\n      filteredTgtOptionsRef,\n      filteredSrcOptionsRef,\n      targetOptionsRef,\n      canNotSelectAnythingRef,\n      canBeClearedRef,\n      allCheckedRef,\n      srcPatternRef,\n      tgtPatternRef,\n      mergedSrcFilterableRef,\n      handleSrcFilterUpdateValue,\n      handleTgtFilterUpdateValue\n    } = useTransferData(props)\n    function doUpdateValue(value: OptionValue[]): void {\n      const {\n        onUpdateValue,\n        'onUpdate:value': _onUpdateValue,\n        onChange\n      } = props\n      const { nTriggerFormInput, nTriggerFormChange } = formItem\n      if (onUpdateValue)\n        call(onUpdateValue, value)\n      if (_onUpdateValue)\n        call(_onUpdateValue, value)\n      if (onChange)\n        call(onChange, value)\n      uncontrolledValueRef.value = value\n      nTriggerFormInput()\n      nTriggerFormChange()\n    }\n\n    function handleSourceCheckAll(): void {\n      doUpdateValue([...valueSetForCheckAllRef.value])\n    }\n\n    function handleSourceUncheckAll(): void {\n      doUpdateValue([...valueSetForUncheckAllRef.value])\n    }\n\n    function handleTargetClearAll(): void {\n      doUpdateValue([...valueSetForClearRef.value])\n    }\n\n    function handleItemCheck(checked: boolean, optionValue: OptionValue): void {\n      if (checked) {\n        doUpdateValue((mergedValueRef.value || []).concat(optionValue))\n      }\n      else {\n        doUpdateValue(\n          (mergedValueRef.value || []).filter(v => v !== optionValue)\n        )\n      }\n    }\n\n    function handleChecked(optionValueList: OptionValue[]): void {\n      doUpdateValue(optionValueList)\n    }\n\n    provide(transferInjectionKey, {\n      targetValueSetRef,\n      mergedClsPrefixRef,\n      disabledRef: mergedDisabledRef,\n      mergedThemeRef: themeRef,\n      targetOptionsRef,\n      canNotSelectAnythingRef,\n      canBeClearedRef,\n      allCheckedRef,\n      srcOptionsLengthRef: computed(() => props.options.length),\n      handleItemCheck,\n      renderSourceLabelRef: toRef(props, 'renderSourceLabel'),\n      renderTargetLabelRef: toRef(props, 'renderTargetLabel'),\n      showSelectedRef: toRef(props, 'showSelected')\n    })\n    return {\n      mergedClsPrefix: mergedClsPrefixRef,\n      mergedDisabled: mergedDisabledRef,\n      itemSize: itemSizeRef,\n      isMounted: useIsMounted(),\n      mergedTheme: themeRef,\n      filteredSrcOpts: filteredSrcOptionsRef,\n      filteredTgtOpts: filteredTgtOptionsRef,\n      srcPattern: srcPatternRef,\n      tgtPattern: tgtPatternRef,\n      mergedSize: mergedSizeRef,\n      mergedSrcFilterable: mergedSrcFilterableRef,\n      handleSrcFilterUpdateValue,\n      handleTgtFilterUpdateValue,\n      handleSourceCheckAll,\n      handleSourceUncheckAll,\n      handleTargetClearAll,\n      handleItemCheck,\n      handleChecked,\n      cssVars: computed(() => {\n        const { value: size } = mergedSizeRef\n        const {\n          common: { cubicBezierEaseInOut },\n          self: {\n            borderRadius,\n            borderColor,\n            listColor,\n            titleTextColor,\n            titleTextColorDisabled,\n            extraTextColor,\n            itemTextColor,\n            itemColorPending,\n            itemTextColorDisabled,\n            titleFontWeight,\n            closeColorHover,\n            closeColorPressed,\n            closeIconColor,\n            closeIconColorHover,\n            closeIconColorPressed,\n            closeIconSize,\n            closeSize,\n            dividerColor,\n            extraTextColorDisabled,\n            [createKey('extraFontSize', size)]: extraFontSize,\n            [createKey('fontSize', size)]: fontSize,\n            [createKey('titleFontSize', size)]: titleFontSize,\n            [createKey('itemHeight', size)]: itemHeight,\n            [createKey('headerHeight', size)]: headerHeight\n          }\n        } = themeRef.value\n        return {\n          '--n-bezier': cubicBezierEaseInOut,\n          '--n-border-color': borderColor,\n          '--n-border-radius': borderRadius,\n          '--n-extra-font-size': extraFontSize,\n          '--n-font-size': fontSize,\n          '--n-header-font-size': titleFontSize,\n          '--n-header-extra-text-color': extraTextColor,\n          '--n-header-extra-text-color-disabled': extraTextColorDisabled,\n          '--n-header-font-weight': titleFontWeight,\n          '--n-header-text-color': titleTextColor,\n          '--n-header-text-color-disabled': titleTextColorDisabled,\n          '--n-item-color-pending': itemColorPending,\n          '--n-item-height': itemHeight,\n          '--n-item-text-color': itemTextColor,\n          '--n-item-text-color-disabled': itemTextColorDisabled,\n          '--n-list-color': listColor,\n          '--n-header-height': headerHeight,\n          '--n-close-size': closeSize,\n          '--n-close-icon-size': closeIconSize,\n          '--n-close-color-hover': closeColorHover,\n          '--n-close-color-pressed': closeColorPressed,\n          '--n-close-icon-color': closeIconColor,\n          '--n-close-icon-color-hover': closeIconColorHover,\n          '--n-close-icon-color-pressed': closeIconColorPressed,\n          '--n-divider-color': dividerColor\n        }\n      })\n    }\n  },\n  render() {\n    const {\n      mergedClsPrefix,\n      renderSourceList,\n      renderTargetList,\n      mergedTheme,\n      mergedSrcFilterable,\n      targetFilterable\n    } = this\n    return (\n      <div\n        class={[\n          `${mergedClsPrefix}-transfer`,\n          this.mergedDisabled && `${mergedClsPrefix}-transfer--disabled`\n        ]}\n        style={this.cssVars as CSSProperties}\n      >\n        <div\n          class={`${mergedClsPrefix}-transfer-list ${mergedClsPrefix}-transfer-list--source`}\n        >\n          <NTransferHeader\n            source\n            selectAllText={this.selectAllText}\n            clearText={this.clearText}\n            title={this.sourceTitle}\n            onCheckedAll={this.handleSourceCheckAll}\n            onClearAll={this.handleSourceUncheckAll}\n            size={this.mergedSize}\n          />\n          <div class={`${mergedClsPrefix}-transfer-list-body`}>\n            {mergedSrcFilterable ? (\n              <NTransferFilter\n                onUpdateValue={this.handleSrcFilterUpdateValue}\n                value={this.srcPattern}\n                disabled={this.mergedDisabled}\n                placeholder={this.sourceFilterPlaceholder}\n              />\n            ) : null}\n            <div class={`${mergedClsPrefix}-transfer-list-flex-container`}>\n              {renderSourceList ? (\n                <NScrollbar\n                  theme={mergedTheme.peers.Scrollbar}\n                  themeOverrides={mergedTheme.peerOverrides.Scrollbar}\n                >\n                  {{\n                    default: () =>\n                      renderSourceList({\n                        onCheck: this.handleChecked,\n                        checkedOptions: this.filteredTgtOpts,\n                        pattern: this.srcPattern\n                      })\n                  }}\n                </NScrollbar>\n              ) : (\n                <NTransferList\n                  source\n                  options={this.filteredSrcOpts}\n                  disabled={this.mergedDisabled}\n                  virtualScroll={this.virtualScroll}\n                  itemSize={this.itemSize}\n                />\n              )}\n            </div>\n          </div>\n          <div class={`${mergedClsPrefix}-transfer-list__border`} />\n        </div>\n        <div\n          class={`${mergedClsPrefix}-transfer-list ${mergedClsPrefix}-transfer-list--target`}\n        >\n          <NTransferHeader\n            onClearAll={this.handleTargetClearAll}\n            size={this.mergedSize}\n            title={this.targetTitle}\n          />\n          <div class={`${mergedClsPrefix}-transfer-list-body`}>\n            {targetFilterable ? (\n              <NTransferFilter\n                onUpdateValue={this.handleTgtFilterUpdateValue}\n                value={this.tgtPattern}\n                disabled={this.mergedDisabled}\n                placeholder={this.sourceFilterPlaceholder}\n              />\n            ) : null}\n            <div class={`${mergedClsPrefix}-transfer-list-flex-container`}>\n              {renderTargetList ? (\n                <NScrollbar\n                  theme={mergedTheme.peers.Scrollbar}\n                  themeOverrides={mergedTheme.peerOverrides.Scrollbar}\n                >\n                  {{\n                    default: () =>\n                      renderTargetList({\n                        onCheck: this.handleChecked,\n                        checkedOptions: this.filteredTgtOpts,\n                        pattern: this.tgtPattern\n                      })\n                  }}\n                </NScrollbar>\n              ) : (\n                <NTransferList\n                  options={this.filteredTgtOpts}\n                  disabled={this.mergedDisabled}\n                  virtualScroll={this.virtualScroll}\n                  itemSize={this.itemSize}\n                />\n              )}\n            </div>\n          </div>\n          <div class={`${mergedClsPrefix}-transfer-list__border`} />\n        </div>\n      </div>\n    )\n  }\n})\n"
  },
  {
    "path": "src/transfer/src/TransferFilter.tsx",
    "content": "import type { PropType } from 'vue'\nimport { defineComponent, h, inject } from 'vue'\nimport { NBaseIcon } from '../../_internal'\nimport { SearchIcon } from '../../_internal/icons'\nimport { NInput } from '../../input'\nimport { transferInjectionKey } from './interface'\n\nexport default defineComponent({\n  name: 'TransferFilter',\n  props: {\n    value: String,\n    placeholder: String,\n    disabled: Boolean,\n    onUpdateValue: {\n      type: Function as PropType<(value: string | null) => void>,\n      required: true\n    }\n  },\n  setup() {\n    const { mergedThemeRef, mergedClsPrefixRef } = inject(transferInjectionKey)!\n    return {\n      mergedClsPrefix: mergedClsPrefixRef,\n      mergedTheme: mergedThemeRef\n    }\n  },\n  render() {\n    const { mergedTheme, mergedClsPrefix } = this\n    return (\n      <div class={`${mergedClsPrefix}-transfer-filter`}>\n        <NInput\n          value={this.value}\n          onUpdateValue={this.onUpdateValue}\n          disabled={this.disabled}\n          placeholder={this.placeholder}\n          theme={mergedTheme.peers.Input}\n          themeOverrides={mergedTheme.peerOverrides.Input}\n          clearable\n          size=\"small\"\n        >\n          {{\n            'clear-icon-placeholder': () => (\n              <NBaseIcon clsPrefix={mergedClsPrefix}>\n                {{ default: () => <SearchIcon /> }}\n              </NBaseIcon>\n            )\n          }}\n        </NInput>\n      </div>\n    )\n  }\n})\n"
  },
  {
    "path": "src/transfer/src/TransferHeader.tsx",
    "content": "import type { PropType, VNodeChild } from 'vue'\nimport { defineComponent, h, inject } from 'vue'\nimport { useLocale } from '../../_mixins'\nimport { NButton } from '../../button'\nimport { transferInjectionKey } from './interface'\n\nexport default defineComponent({\n  name: 'TransferHeader',\n  props: {\n    size: {\n      type: String as PropType<'small' | 'medium' | 'large'>,\n      required: true\n    },\n    selectAllText: String,\n    clearText: String,\n    source: Boolean,\n    onCheckedAll: Function as PropType<() => void>,\n    onClearAll: Function as PropType<() => void>,\n    title: [String, Function] as PropType<string | (() => VNodeChild)>\n  },\n  setup(props) {\n    const {\n      targetOptionsRef,\n      canNotSelectAnythingRef,\n      canBeClearedRef,\n      allCheckedRef,\n      mergedThemeRef,\n      disabledRef,\n      mergedClsPrefixRef,\n      srcOptionsLengthRef\n    } = inject(transferInjectionKey)!\n    const { localeRef } = useLocale('Transfer')\n    return () => {\n      const { source, onClearAll, onCheckedAll, selectAllText, clearText }\n        = props\n      const { value: mergedTheme } = mergedThemeRef\n      const { value: mergedClsPrefix } = mergedClsPrefixRef\n      const { value: locale } = localeRef\n      const buttonSize = props.size === 'large' ? 'small' : 'tiny'\n      const { title } = props\n      return (\n        <div class={`${mergedClsPrefix}-transfer-list-header`}>\n          {title && (\n            <div class={`${mergedClsPrefix}-transfer-list-header__title`}>\n              {typeof title === 'function' ? title() : title}\n            </div>\n          )}\n          {source && (\n            <NButton\n              class={`${mergedClsPrefix}-transfer-list-header__button`}\n              theme={mergedTheme.peers.Button}\n              themeOverrides={mergedTheme.peerOverrides.Button}\n              size={buttonSize}\n              tertiary\n              onClick={allCheckedRef.value ? onClearAll : onCheckedAll}\n              disabled={canNotSelectAnythingRef.value || disabledRef.value}\n            >\n              {{\n                default: () =>\n                  allCheckedRef.value\n                    ? clearText || locale.unselectAll\n                    : selectAllText || locale.selectAll\n              }}\n            </NButton>\n          )}\n          {!source && canBeClearedRef.value && (\n            <NButton\n              class={`${mergedClsPrefix}-transfer-list-header__button`}\n              theme={mergedTheme.peers.Button}\n              themeOverrides={mergedTheme.peerOverrides.Button}\n              size={buttonSize}\n              tertiary\n              onClick={onClearAll}\n              disabled={disabledRef.value}\n            >\n              {{\n                default: () => locale.clearAll\n              }}\n            </NButton>\n          )}\n          <div class={`${mergedClsPrefix}-transfer-list-header__extra`}>\n            {source\n              ? locale.total(srcOptionsLengthRef.value)\n              : locale.selected(targetOptionsRef.value.length)}\n          </div>\n        </div>\n      )\n    }\n  }\n})\n"
  },
  {
    "path": "src/transfer/src/TransferList.tsx",
    "content": "import type { PropType } from 'vue'\nimport type { VirtualListInst } from 'vueuc'\nimport type { ScrollbarInst } from '../../_internal'\nimport type { Option } from './interface'\nimport { computed, defineComponent, h, inject, ref } from 'vue'\nimport { VirtualList } from 'vueuc'\nimport { NScrollbar } from '../../_internal'\nimport { useConfig } from '../../_mixins'\nimport { NEmpty } from '../../empty'\nimport { transferInjectionKey } from './interface'\nimport NTransferListItem from './TransferListItem'\n\nexport default defineComponent({\n  name: 'TransferList',\n  props: {\n    virtualScroll: {\n      type: Boolean,\n      required: true\n    },\n    itemSize: {\n      type: Number,\n      required: true\n    },\n    options: {\n      type: Array as PropType<Option[]>,\n      required: true\n    },\n    disabled: {\n      type: Boolean,\n      required: true\n    },\n    source: Boolean\n  },\n  setup() {\n    const { mergedThemeRef, mergedClsPrefixRef } = inject(transferInjectionKey)!\n    const { mergedComponentPropsRef } = useConfig()\n    const scrollerInstRef = ref<ScrollbarInst | null>(null)\n    const vlInstRef = ref<VirtualListInst | null>(null)\n    const mergedRenderEmptyRef = computed(() => {\n      return mergedComponentPropsRef?.value?.Transfer?.renderEmpty\n    })\n    function syncVLScroller(): void {\n      scrollerInstRef.value?.sync()\n    }\n    function scrollContainer(): HTMLElement | null {\n      const { value } = vlInstRef\n      if (!value)\n        return null\n      const { listElRef } = value\n      return listElRef\n    }\n    function scrollContent(): HTMLElement | null {\n      const { value } = vlInstRef\n      if (!value)\n        return null\n      const { itemsElRef } = value\n      return itemsElRef\n    }\n    return {\n      mergedTheme: mergedThemeRef,\n      mergedClsPrefix: mergedClsPrefixRef,\n      mergedRenderEmpty: mergedRenderEmptyRef,\n      scrollerInstRef,\n      vlInstRef,\n      syncVLScroller,\n      scrollContainer,\n      scrollContent\n    }\n  },\n  render() {\n    const { mergedTheme, options } = this\n    if (options.length === 0) {\n      return (\n        this.mergedRenderEmpty?.() || (\n          <NEmpty\n            theme={mergedTheme.peers.Empty}\n            themeOverrides={mergedTheme.peerOverrides.Empty}\n          />\n        )\n      )\n    }\n    const { mergedClsPrefix, virtualScroll, source, disabled, syncVLScroller }\n      = this\n    return (\n      <NScrollbar\n        ref=\"scrollerInstRef\"\n        theme={mergedTheme.peers.Scrollbar}\n        themeOverrides={mergedTheme.peerOverrides.Scrollbar}\n        container={virtualScroll ? this.scrollContainer : undefined}\n        content={virtualScroll ? this.scrollContent : undefined}\n      >\n        {{\n          default: () =>\n            virtualScroll ? (\n              <VirtualList\n                ref=\"vlInstRef\"\n                style={{ height: '100%' }}\n                class={`${mergedClsPrefix}-transfer-list-content`}\n                items={this.options}\n                itemSize={this.itemSize}\n                showScrollbar={false}\n                onResize={syncVLScroller}\n                onScroll={syncVLScroller}\n                keyField=\"value\"\n              >\n                {{\n                  default: ({ item }: { item: Option }) => {\n                    const { source, disabled } = this\n                    return (\n                      <NTransferListItem\n                        source={source}\n                        key={item.value}\n                        value={item.value}\n                        disabled={item.disabled || disabled}\n                        label={item.label}\n                        option={item}\n                      />\n                    )\n                  }\n                }}\n              </VirtualList>\n            ) : (\n              <div class={`${mergedClsPrefix}-transfer-list-content`}>\n                {options.map(option => (\n                  <NTransferListItem\n                    source={source}\n                    key={option.value}\n                    value={option.value}\n                    disabled={option.disabled || disabled}\n                    label={option.label}\n                    option={option}\n                  />\n                ))}\n              </div>\n            )\n        }}\n      </NScrollbar>\n    )\n  }\n})\n"
  },
  {
    "path": "src/transfer/src/TransferListItem.tsx",
    "content": "import type { PropType } from 'vue'\nimport type { Option } from './interface'\nimport { useMemo } from 'vooks'\nimport { defineComponent, h, inject } from 'vue'\nimport { NBaseClose } from '../../_internal'\nimport { getTitleAttribute } from '../../_utils'\nimport { NCheckbox } from '../../checkbox'\nimport { transferInjectionKey } from './interface'\n\nexport default defineComponent({\n  name: 'NTransferListItem',\n  props: {\n    source: Boolean,\n    label: {\n      type: String,\n      required: true\n    },\n    value: {\n      type: [String, Number],\n      required: true\n    },\n    disabled: Boolean,\n    option: {\n      type: Object as PropType<Option>,\n      required: true\n    }\n  },\n  setup(props) {\n    const {\n      targetValueSetRef,\n      mergedClsPrefixRef,\n      mergedThemeRef,\n      handleItemCheck,\n      renderSourceLabelRef,\n      renderTargetLabelRef,\n      showSelectedRef\n    } = inject(transferInjectionKey)!\n    const checkedRef = useMemo(() => targetValueSetRef.value.has(props.value))\n    function handleClick(): void {\n      if (!props.disabled) {\n        handleItemCheck(!checkedRef.value, props.value)\n      }\n    }\n    return {\n      mergedClsPrefix: mergedClsPrefixRef,\n      mergedTheme: mergedThemeRef,\n      checked: checkedRef,\n      showSelected: showSelectedRef,\n      renderSourceLabel: renderSourceLabelRef,\n      renderTargetLabel: renderTargetLabelRef,\n      handleClick\n    }\n  },\n  render() {\n    const {\n      disabled,\n      mergedTheme,\n      mergedClsPrefix,\n      label,\n      checked,\n      source,\n      renderSourceLabel,\n      renderTargetLabel\n    } = this\n    return (\n      <div\n        class={[\n          `${mergedClsPrefix}-transfer-list-item`,\n          disabled && `${mergedClsPrefix}-transfer-list-item--disabled`,\n          source\n            ? `${mergedClsPrefix}-transfer-list-item--source`\n            : `${mergedClsPrefix}-transfer-list-item--target`\n        ]}\n        onClick={source ? this.handleClick : undefined}\n      >\n        <div class={`${mergedClsPrefix}-transfer-list-item__background`} />\n        {source && this.showSelected && (\n          <div class={`${mergedClsPrefix}-transfer-list-item__checkbox`}>\n            <NCheckbox\n              theme={mergedTheme.peers.Checkbox}\n              themeOverrides={mergedTheme.peerOverrides.Checkbox}\n              disabled={disabled}\n              checked={checked}\n            />\n          </div>\n        )}\n        <div\n          class={`${mergedClsPrefix}-transfer-list-item__label`}\n          title={getTitleAttribute(label)}\n        >\n          {source\n            ? renderSourceLabel\n              ? renderSourceLabel({\n                  option: this.option\n                })\n              : label\n            : renderTargetLabel\n              ? renderTargetLabel({\n                  option: this.option\n                })\n              : label}\n        </div>\n        {!source && !disabled && (\n          <NBaseClose\n            focusable={false}\n            class={`${mergedClsPrefix}-transfer-list-item__close`}\n            clsPrefix={mergedClsPrefix}\n            onClick={this.handleClick}\n          />\n        )}\n      </div>\n    )\n  }\n})\n"
  },
  {
    "path": "src/transfer/src/interface.ts",
    "content": "import type { Ref, VNodeChild } from 'vue'\nimport type { MergedTheme } from '../../_mixins'\nimport type { TransferTheme } from '../styles'\nimport { createInjectionKey } from '../../_utils'\n\nexport type OptionValue = string | number\nexport interface Option {\n  label: string\n  value: OptionValue\n  disabled?: boolean\n}\n\nexport type Filter = (\n  pattern: string,\n  option: Option,\n  from: 'source' | 'target'\n) => boolean\n\nexport interface RenderLabelProps {\n  option: Option\n}\n\nexport type TransferRenderTargetLabel = (props: RenderLabelProps) => VNodeChild\nexport type TransferRenderSourceLabel = (props: RenderLabelProps) => VNodeChild\n\nexport interface RenderListProps {\n  onCheck: (checkedValueList: OptionValue[]) => void\n  checkedOptions: Option[]\n  pattern: string\n}\n\nexport type TransferRenderSourceList = (props: RenderListProps) => VNodeChild\n\nexport interface TransferInjection {\n  targetValueSetRef: Ref<Set<OptionValue>>\n  mergedClsPrefixRef: Ref<string>\n  disabledRef: Ref<boolean>\n  mergedThemeRef: Ref<MergedTheme<TransferTheme>>\n  targetOptionsRef: Ref<Option[]>\n  canNotSelectAnythingRef: Ref<boolean>\n  canBeClearedRef: Ref<boolean>\n  allCheckedRef: Ref<boolean>\n  srcOptionsLengthRef: Ref<number>\n  handleItemCheck: (checked: boolean, value: OptionValue) => void\n  renderSourceLabelRef: Ref<TransferRenderSourceLabel | undefined>\n  renderTargetLabelRef: Ref<TransferRenderTargetLabel | undefined>\n  showSelectedRef: Ref<boolean>\n}\n\nexport const transferInjectionKey\n  = createInjectionKey<TransferInjection>('n-transfer')\n\nexport type OnUpdateValue = (value: OptionValue[]) => void\n"
  },
  {
    "path": "src/transfer/src/public-types.ts",
    "content": "export type TransferSize = 'small' | 'medium' | 'large'\n"
  },
  {
    "path": "src/transfer/src/styles/index.cssr.ts",
    "content": "import { c, cB, cE, cM, cNotM } from '../../../_utils/cssr'\n\n// --n-close-size\n// --n-close-icon-size\n// --n-close-color-hover\n// --n-close-color-pressed\n// --n-close-icon-color\n// --n-close-icon-color-hover\n// --n-close-icon-color-pressed\nexport default cB('transfer', `\n  width: 100%;\n  font-size: var(--n-font-size);\n  height: 300px;\n  display: flex;\n  flex-wrap: nowrap;\n  word-break: break-word;\n`, [\n  cM('disabled', [\n    cB('transfer-list', [\n      cB('transfer-list-header', [\n        cE('title', `\n          color: var(--n-header-text-color-disabled);\n        `),\n        cE('extra', `\n          color: var(--n-header-extra-text-color-disabled);\n        `)\n      ])\n    ])\n  ]),\n  cB('transfer-list', `\n    flex: 1;\n    min-width: 0;\n    height: inherit;\n    display: flex;\n    flex-direction: column;\n    background-clip: padding-box;\n    position: relative;\n    transition: background-color .3s var(--n-bezier);\n    background-color: var(--n-list-color);\n  `, [\n    cM('source', `\n      border-top-left-radius: var(--n-border-radius);\n      border-bottom-left-radius: var(--n-border-radius);\n    `, [\n      cE('border', 'border-right: 1px solid var(--n-divider-color);')\n    ]),\n    cM('target', `\n      border-top-right-radius: var(--n-border-radius);\n      border-bottom-right-radius: var(--n-border-radius);\n    `, [\n      cE('border', 'border-left: none;')\n    ]),\n    cE('border', `\n      padding: 0 12px;\n      border: 1px solid var(--n-border-color);\n      transition: border-color .3s var(--n-bezier);\n      pointer-events: none;\n      border-radius: inherit;\n      position: absolute;\n      left: 0;\n      right: 0;\n      top: 0;\n      bottom: 0;\n    `),\n    cB('transfer-list-header', `\n      min-height: var(--n-header-height);\n      box-sizing: border-box;\n      display: flex;\n      padding: 12px 12px 10px 12px;\n      align-items: center;\n      background-clip: padding-box;\n      border-radius: inherit;\n      border-bottom-left-radius: 0;\n      border-bottom-right-radius: 0;\n      line-height: 1.5;\n      transition:\n        border-color .3s var(--n-bezier),\n        background-color .3s var(--n-bezier);\n    `, [\n      c('> *:not(:first-child)', `\n        margin-left: 8px;\n      `),\n      cE('title', `\n        flex: 1;\n        min-width: 0;\n        line-height: 1.5;\n        font-size: var(--n-header-font-size);\n        font-weight: var(--n-header-font-weight);\n        transition: color .3s var(--n-bezier);\n        color: var(--n-header-text-color);\n      `),\n      cE('button', `\n        position: relative;\n      `),\n      cE('extra', `\n        transition: color .3s var(--n-bezier);\n        font-size: var(--n-extra-font-size);\n        margin-right: 0;\n        white-space: nowrap;\n        color: var(--n-header-extra-text-color);\n      `)\n    ]),\n    cB('transfer-list-body', `\n      flex-basis: 0;\n      flex-grow: 1;\n      box-sizing: border-box;\n      position: relative;\n      display: flex;\n      flex-direction: column;\n      border-radius: inherit;\n      border-top-left-radius: 0;\n      border-top-right-radius: 0;\n    `, [\n      cB('transfer-filter', `\n        padding: 4px 12px 8px 12px;\n        box-sizing: border-box;\n        transition:\n          border-color .3s var(--n-bezier),\n          background-color .3s var(--n-bezier);\n      `),\n      cB('transfer-list-flex-container', `\n        flex: 1;\n        position: relative;\n      `, [\n        cB('scrollbar', `\n          position: absolute;\n          left: 0;\n          right: 0;\n          top: 0;\n          bottom: 0;\n          height: unset;\n        `),\n        cB('empty', `\n          position: absolute;\n          left: 50%;\n          top: 50%;\n          transform: translateY(-50%) translateX(-50%);\n        `),\n        cB('transfer-list-content', `\n          padding: 0;\n          margin: 0;\n          position: relative;\n        `, [\n          cB('transfer-list-item', `\n            padding: 0 12px;\n            min-height: var(--n-item-height);\n            display: flex;\n            align-items: center;\n            color: var(--n-item-text-color);\n            position: relative;\n            transition: color .3s var(--n-bezier);\n          `, [\n            cE('background', `\n              position: absolute;\n              left: 4px;\n              right: 4px;\n              top: 0;\n              bottom: 0;\n              border-radius: var(--n-border-radius);\n              transition: background-color .3s var(--n-bezier);\n            `),\n            cE('checkbox', `\n              position: relative;\n              margin-right: 8px;\n            `),\n            cE('close', `\n              opacity: 0;\n              pointer-events: none;\n              position: relative;\n              transition:\n                opacity .3s var(--n-bezier),\n                background-color .3s var(--n-bezier),\n                color .3s var(--n-bezier);\n            `),\n            cE('label', `\n              position: relative;\n              min-width: 0;\n              flex-grow: 1;\n            `),\n            cM('source', 'cursor: pointer;'),\n            cM('disabled', `\n              cursor: not-allowed;\n              color: var(--n-item-text-color-disabled);\n            `),\n            cNotM('disabled', [\n              c('&:hover', [\n                cE('background', 'background-color: var(--n-item-color-pending);'),\n                cE('close', `\n                  opacity: 1;\n                  pointer-events: all;\n                `)\n              ])\n            ])\n          ])\n        ])\n      ])\n    ])\n  ])\n])\n"
  },
  {
    "path": "src/transfer/src/use-transfer-data.ts",
    "content": "import type { Filter, Option, OptionValue } from './interface'\nimport { useMergedState } from 'vooks'\nimport { computed, ref, toRef } from 'vue'\n\ninterface UseTransferDataProps {\n  defaultValue: OptionValue[] | null\n  value?: OptionValue[] | null\n  options: Option[]\n  filterable: boolean | undefined\n  sourceFilterable: boolean\n  targetFilterable: boolean\n  showSelected: boolean\n  filter: Filter\n}\n\nexport function useTransferData(props: UseTransferDataProps) {\n  const uncontrolledValueRef = ref(props.defaultValue)\n  const mergedValueRef = useMergedState(\n    toRef(props, 'value'),\n    uncontrolledValueRef\n  )\n\n  const optionsMapRef = computed(() => {\n    const map = new Map()\n    ;(props.options || []).forEach(opt => map.set(opt.value, opt))\n    return map as Map<OptionValue, Option>\n  })\n\n  const targetValueSetRef = computed(() => new Set(mergedValueRef.value || []))\n\n  const targetOptionsRef = computed(() => {\n    const optionMap = optionsMapRef.value\n    const targetOptions: Option[] = []\n    ;(mergedValueRef.value || []).forEach((v) => {\n      const option = optionMap.get(v)\n      if (option) {\n        targetOptions.push(option)\n      }\n    })\n    return targetOptions\n  })\n\n  const srcPatternRef = ref('')\n  const tgtPatternRef = ref('')\n\n  const mergedSrcFilterableRef = computed(() => {\n    return props.sourceFilterable || !!props.filterable\n  })\n\n  const filteredSrcOptionsRef = computed(() => {\n    const { showSelected, options, filter } = props\n    if (!mergedSrcFilterableRef.value) {\n      if (showSelected) {\n        return options\n      }\n      else {\n        return options.filter(\n          option => !targetValueSetRef.value.has(option.value)\n        )\n      }\n    }\n    return options.filter((option) => {\n      return (\n        filter(srcPatternRef.value, option, 'source')\n        && (showSelected || !targetValueSetRef.value.has(option.value))\n      )\n    })\n  })\n\n  const filteredTgtOptionsRef = computed(() => {\n    if (!props.targetFilterable)\n      return targetOptionsRef.value\n    const { filter } = props\n    return targetOptionsRef.value.filter(opt =>\n      filter(tgtPatternRef.value, opt, 'target')\n    )\n  })\n\n  const mergedValueSetRef = computed<Set<string | number>>(() => {\n    const { value } = mergedValueRef\n    if (value === null)\n      return new Set()\n    return new Set(value)\n  })\n\n  const valueSetForCheckAllRef = computed(() => {\n    const values = new Set<string | number>(mergedValueSetRef.value)\n    filteredSrcOptionsRef.value.forEach((option) => {\n      if (!option.disabled && !values.has(option.value)) {\n        values.add(option.value)\n      }\n    })\n    return values\n  })\n\n  const valueSetForUncheckAllRef = computed(() => {\n    const values = new Set<string | number>(mergedValueSetRef.value)\n    filteredSrcOptionsRef.value.forEach((option) => {\n      if (!option.disabled && values.has(option.value)) {\n        values.delete(option.value)\n      }\n    })\n    return values\n  })\n\n  const valueSetForClearRef = computed(() => {\n    const values = new Set<string | number>(mergedValueSetRef.value)\n    filteredTgtOptionsRef.value.forEach((option) => {\n      if (!option.disabled) {\n        values.delete(option.value)\n      }\n    })\n    return values\n  })\n\n  const canNotSelectAnythingRef = computed(() => {\n    return filteredSrcOptionsRef.value.every(option => option.disabled)\n  })\n\n  const allCheckedRef = computed(() => {\n    if (!filteredSrcOptionsRef.value.length) {\n      return false\n    }\n    const mergedValueSet = mergedValueSetRef.value\n    return filteredSrcOptionsRef.value.every(\n      option => option.disabled || mergedValueSet.has(option.value)\n    )\n  })\n\n  const canBeClearedRef = computed(() => {\n    return filteredTgtOptionsRef.value.some(option => !option.disabled)\n  })\n\n  function handleSrcFilterUpdateValue(value: string | null): void {\n    srcPatternRef.value = value ?? ''\n  }\n\n  function handleTgtFilterUpdateValue(value: string | null): void {\n    tgtPatternRef.value = value ?? ''\n  }\n\n  return {\n    uncontrolledValueRef,\n    mergedValueRef,\n    targetValueSetRef,\n    valueSetForCheckAllRef,\n    valueSetForUncheckAllRef,\n    valueSetForClearRef,\n    filteredTgtOptionsRef,\n    filteredSrcOptionsRef,\n    targetOptionsRef,\n    canNotSelectAnythingRef,\n    canBeClearedRef,\n    allCheckedRef,\n    srcPatternRef,\n    tgtPatternRef,\n    mergedSrcFilterableRef,\n    handleSrcFilterUpdateValue,\n    handleTgtFilterUpdateValue\n  }\n}\n"
  },
  {
    "path": "src/transfer/styles/_common.ts",
    "content": "export default {\n  extraFontSizeSmall: '12px',\n  extraFontSizeMedium: '12px',\n  extraFontSizeLarge: '14px',\n  titleFontSizeSmall: '14px',\n  titleFontSizeMedium: '16px',\n  titleFontSizeLarge: '16px',\n  closeSize: '20px',\n  closeIconSize: '16px',\n  headerHeightSmall: '44px',\n  headerHeightMedium: '44px',\n  headerHeightLarge: '50px'\n}\n"
  },
  {
    "path": "src/transfer/styles/dark.ts",
    "content": "import type { TransferTheme } from './light'\nimport { scrollbarDark } from '../../_internal/scrollbar/styles'\nimport { commonDark } from '../../_styles/common'\nimport { buttonDark } from '../../button/styles'\nimport { checkboxDark } from '../../checkbox/styles'\nimport { emptyDark } from '../../empty/styles'\nimport { inputDark } from '../../input/styles'\nimport commonVariables from './_common'\n\nconst transferDark: TransferTheme = {\n  name: 'Transfer',\n  common: commonDark,\n  peers: {\n    Checkbox: checkboxDark,\n    Scrollbar: scrollbarDark,\n    Input: inputDark,\n    Empty: emptyDark,\n    Button: buttonDark\n  },\n  self(vars) {\n    const {\n      fontWeight,\n      fontSizeLarge,\n      fontSizeMedium,\n      fontSizeSmall,\n      heightLarge,\n      heightMedium,\n      borderRadius,\n      inputColor,\n      tableHeaderColor,\n      textColor1,\n      textColorDisabled,\n      textColor2,\n      textColor3,\n      hoverColor,\n      closeColorHover,\n      closeColorPressed,\n      closeIconColor,\n      closeIconColorHover,\n      closeIconColorPressed,\n      dividerColor\n    } = vars\n    return {\n      ...commonVariables,\n      itemHeightSmall: heightMedium,\n      itemHeightMedium: heightMedium,\n      itemHeightLarge: heightLarge,\n      fontSizeSmall,\n      fontSizeMedium,\n      fontSizeLarge,\n      borderRadius,\n      dividerColor,\n      borderColor: '#0000',\n      listColor: inputColor,\n      headerColor: tableHeaderColor,\n      titleTextColor: textColor1,\n      titleTextColorDisabled: textColorDisabled,\n      extraTextColor: textColor3,\n      extraTextColorDisabled: textColorDisabled,\n      itemTextColor: textColor2,\n      itemTextColorDisabled: textColorDisabled,\n      itemColorPending: hoverColor,\n      titleFontWeight: fontWeight,\n      closeColorHover,\n      closeColorPressed,\n      closeIconColor,\n      closeIconColorHover,\n      closeIconColorPressed\n    }\n  }\n}\n\nexport default transferDark\n"
  },
  {
    "path": "src/transfer/styles/index.ts",
    "content": "export { default as transferDark } from './dark'\nexport { default as transferLight } from './light'\nexport type { TransferTheme, TransferThemeVars } from './light'\n"
  },
  {
    "path": "src/transfer/styles/light.ts",
    "content": "import type { ThemeCommonVars } from '../../_styles/common'\nimport { composite } from 'seemly'\nimport { scrollbarLight } from '../../_internal/scrollbar/styles'\nimport { createTheme } from '../../_mixins'\nimport { commonLight } from '../../_styles/common'\nimport { buttonLight } from '../../button/styles'\nimport { checkboxLight } from '../../checkbox/styles'\nimport { emptyLight } from '../../empty/styles'\nimport { inputLight } from '../../input/styles'\nimport commonVariables from './_common'\n\nfunction self(vars: ThemeCommonVars) {\n  const {\n    fontWeight,\n    fontSizeLarge,\n    fontSizeMedium,\n    fontSizeSmall,\n    heightLarge,\n    heightMedium,\n    borderRadius,\n    cardColor,\n    tableHeaderColor,\n    textColor1,\n    textColorDisabled,\n    textColor2,\n    textColor3,\n    borderColor,\n    hoverColor,\n    closeColorHover,\n    closeColorPressed,\n    closeIconColor,\n    closeIconColorHover,\n    closeIconColorPressed\n  } = vars\n  return {\n    ...commonVariables,\n    itemHeightSmall: heightMedium,\n    itemHeightMedium: heightMedium,\n    itemHeightLarge: heightLarge,\n    fontSizeSmall,\n    fontSizeMedium,\n    fontSizeLarge,\n    borderRadius,\n    dividerColor: borderColor,\n    borderColor,\n    listColor: cardColor,\n    headerColor: composite(cardColor, tableHeaderColor),\n    titleTextColor: textColor1,\n    titleTextColorDisabled: textColorDisabled,\n    extraTextColor: textColor3,\n    extraTextColorDisabled: textColorDisabled,\n    itemTextColor: textColor2,\n    itemTextColorDisabled: textColorDisabled,\n    itemColorPending: hoverColor,\n    titleFontWeight: fontWeight,\n    closeColorHover,\n    closeColorPressed,\n    closeIconColor,\n    closeIconColorHover,\n    closeIconColorPressed\n  }\n}\n\nexport type TransferThemeVars = ReturnType<typeof self>\n\nconst transferLight = createTheme({\n  name: 'Transfer',\n  common: commonLight,\n  peers: {\n    Checkbox: checkboxLight,\n    Scrollbar: scrollbarLight,\n    Input: inputLight,\n    Empty: emptyLight,\n    Button: buttonLight\n  },\n  self\n})\n\nexport default transferLight\nexport type TransferTheme = typeof transferLight\n"
  },
  {
    "path": "src/transfer/tests/Transfer.spec.ts",
    "content": "import { mount } from '@vue/test-utils'\nimport { sleep } from 'seemly'\nimport { NTransfer } from '../index'\n\ndescribe('n-transfer', () => {\n  it('should work with import on demand', () => {\n    mount(NTransfer)\n  })\n\n  it('should work with `disabled` prop', () => {\n    const wrapper = mount(NTransfer, { props: { disabled: true } })\n    expect(wrapper.find('.n-transfer').attributes('class')).toContain(\n      'n-transfer--disabled'\n    )\n  })\n\n  it('should work with `source-filterable` prop', async () => {\n    const wrapper = mount(NTransfer, {\n      props: { sourceFilterable: true }\n    })\n    expect(\n      wrapper.find('.n-transfer-list--source .n-transfer-filter').exists()\n    ).toBe(true)\n  })\n\n  it('should work with `filter` prop', async () => {\n    const options = [\n      {\n        label: 'test1',\n        value: 'test1'\n      }\n    ]\n    const onFilter = vi.fn()\n    const wrapper = mount(NTransfer, {\n      props: { sourceFilterable: true, filter: onFilter, options }\n    })\n    await wrapper.find('input').setValue('1')\n    await sleep(300)\n    expect(onFilter).toHaveBeenCalled()\n  })\n\n  it('should work with `size` prop', async () => {\n    ;(['small', 'medium', 'large'] as const).forEach((i) => {\n      const wrapper = mount(NTransfer, {\n        props: { size: i }\n      })\n      expect(wrapper.find('.n-transfer').attributes('style')).toMatchSnapshot()\n    })\n  })\n\n  it('should work with `source-title` prop', async () => {\n    const test = 'source-title-test'\n    const wrapper = mount(NTransfer, { props: { sourceTitle: test } })\n    expect(wrapper.find('.n-transfer-list-header__title').text()).toBe(test)\n  })\n\n  it('should work with `target-title` prop', async () => {\n    const test = 'target-title-test'\n    const wrapper = mount(NTransfer, { props: { targetTitle: test } })\n    expect(wrapper.find('.n-transfer-list-header__title').text()).toBe(test)\n  })\n\n  it('should work with `source-filter-placeholder` prop', async () => {\n    const test = 'source-filter-placeholder-test'\n    const wrapper = mount(NTransfer, {\n      props: { sourceFilterable: true, sourceFilterPlaceholder: test }\n    })\n    expect(wrapper.find('.n-input__placeholder').text()).toBe(test)\n  })\n})\n"
  },
  {
    "path": "src/transfer/tests/__snapshots__/Transfer.spec.ts.snap",
    "content": "// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html\n\nexports[`n-transfer > should work with \\`size\\` prop 1`] = `\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-border-color: rgb(224, 224, 230); --n-border-radius: 3px; --n-extra-font-size: 12px; --n-font-size: 14px; --n-header-font-size: 14px; --n-header-extra-text-color: rgb(118, 124, 130); --n-header-extra-text-color-disabled: rgba(194, 194, 194, 1); --n-header-font-weight: 400; --n-header-text-color: rgb(31, 34, 37); --n-header-text-color-disabled: rgba(194, 194, 194, 1); --n-item-color-pending: rgb(243, 243, 245); --n-item-height: 34px; --n-item-text-color: rgb(51, 54, 57); --n-item-text-color-disabled: rgba(194, 194, 194, 1); --n-list-color: #fff; --n-header-height: 44px; --n-close-size: 20px; --n-close-icon-size: 16px; --n-close-color-hover: rgba(0, 0, 0, .09); --n-close-color-pressed: rgba(0, 0, 0, .13); --n-close-icon-color: rgba(102, 102, 102, 1); --n-close-icon-color-hover: rgba(102, 102, 102, 1); --n-close-icon-color-pressed: rgba(102, 102, 102, 1); --n-divider-color: rgb(224, 224, 230);\"`;\n\nexports[`n-transfer > should work with \\`size\\` prop 2`] = `\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-border-color: rgb(224, 224, 230); --n-border-radius: 3px; --n-extra-font-size: 12px; --n-font-size: 14px; --n-header-font-size: 16px; --n-header-extra-text-color: rgb(118, 124, 130); --n-header-extra-text-color-disabled: rgba(194, 194, 194, 1); --n-header-font-weight: 400; --n-header-text-color: rgb(31, 34, 37); --n-header-text-color-disabled: rgba(194, 194, 194, 1); --n-item-color-pending: rgb(243, 243, 245); --n-item-height: 34px; --n-item-text-color: rgb(51, 54, 57); --n-item-text-color-disabled: rgba(194, 194, 194, 1); --n-list-color: #fff; --n-header-height: 44px; --n-close-size: 20px; --n-close-icon-size: 16px; --n-close-color-hover: rgba(0, 0, 0, .09); --n-close-color-pressed: rgba(0, 0, 0, .13); --n-close-icon-color: rgba(102, 102, 102, 1); --n-close-icon-color-hover: rgba(102, 102, 102, 1); --n-close-icon-color-pressed: rgba(102, 102, 102, 1); --n-divider-color: rgb(224, 224, 230);\"`;\n\nexports[`n-transfer > should work with \\`size\\` prop 3`] = `\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-border-color: rgb(224, 224, 230); --n-border-radius: 3px; --n-extra-font-size: 14px; --n-font-size: 15px; --n-header-font-size: 16px; --n-header-extra-text-color: rgb(118, 124, 130); --n-header-extra-text-color-disabled: rgba(194, 194, 194, 1); --n-header-font-weight: 400; --n-header-text-color: rgb(31, 34, 37); --n-header-text-color-disabled: rgba(194, 194, 194, 1); --n-item-color-pending: rgb(243, 243, 245); --n-item-height: 40px; --n-item-text-color: rgb(51, 54, 57); --n-item-text-color-disabled: rgba(194, 194, 194, 1); --n-list-color: #fff; --n-header-height: 50px; --n-close-size: 20px; --n-close-icon-size: 16px; --n-close-color-hover: rgba(0, 0, 0, .09); --n-close-color-pressed: rgba(0, 0, 0, .13); --n-close-icon-color: rgba(102, 102, 102, 1); --n-close-icon-color-hover: rgba(102, 102, 102, 1); --n-close-icon-color-pressed: rgba(102, 102, 102, 1); --n-divider-color: rgb(224, 224, 230);\"`;\n"
  },
  {
    "path": "src/transfer/tests/server.spec.tsx",
    "content": "import { setup } from '@css-render/vue3-ssr'\nimport { renderToString } from '@vue/server-renderer'\n/**\n * @vitest-environment node\n */\nimport { createSSRApp, h } from 'vue'\nimport { NTransfer } from '../..'\n\ndescribe('server side rendering', () => {\n  it('works', async () => {\n    const app = createSSRApp(() => <NTransfer />)\n    setup(app)\n    try {\n      await renderToString(app)\n    }\n    catch (e) {\n      expect(e).not.toBeTruthy()\n    }\n  })\n})\n"
  },
  {
    "path": "src/tree/demos/enUS/async.demo.vue",
    "content": "<markdown>\n# Async loading\n\nUse `on-load` callback to load data. When loading async, all nodes with `isLeaf` set to `false` and `chilren`'s type is not `Array` will be reckon as unloaded nodes.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { TreeDropInfo, TreeOption } from 'naive-ui'\nimport { ref } from 'vue'\n\nfunction createData() {\n  return [\n    {\n      label: nextLabel(),\n      key: 1,\n      isLeaf: false\n    },\n    {\n      label: nextLabel(),\n      key: 2,\n      isLeaf: false\n    }\n  ]\n}\n\nfunction nextLabel(currentLabel?: string): string {\n  if (!currentLabel)\n    return 'Out of Tao, One is born'\n  if (currentLabel === 'Out of Tao, One is born')\n    return 'Out of One, Two'\n  if (currentLabel === 'Out of One, Two')\n    return 'Out of Two, Three'\n  if (currentLabel === 'Out of Two, Three') {\n    return 'Out of Three, the created universe'\n  }\n  if (currentLabel === 'Out of Three, the created universe') {\n    return 'Out of Tao, One is born'\n  }\n  return ''\n}\n\nfunction findSiblingsAndIndex(\n  node: TreeOption,\n  nodes?: TreeOption[]\n): [TreeOption[], number] | [null, null] {\n  if (!nodes)\n    return [null, null]\n  for (let i = 0; i < nodes.length; ++i) {\n    const siblingNode = nodes[i]\n    if (siblingNode.key === node.key)\n      return [nodes, i]\n    const [siblings, index] = findSiblingsAndIndex(node, siblingNode.children)\n    if (siblings && index !== null)\n      return [siblings, index]\n  }\n  return [null, null]\n}\n\nconst checkStrategy = ref<'all' | 'parent' | 'child'>('all')\nconst cascade = ref(true)\nconst expandedKeysRef = ref<string[]>([])\nconst checkedKeysRef = ref<string[]>([])\nconst dataRef = ref(createData())\n\nfunction handleExpandedKeysChange(expandedKeys: string[]) {\n  expandedKeysRef.value = expandedKeys\n}\n\nfunction handleCheckedKeysChange(checkedKeys: string[]) {\n  checkedKeysRef.value = checkedKeys\n}\n\nfunction handleDrop({ node, dragNode, dropPosition }: TreeDropInfo) {\n  const [dragNodeSiblings, dragNodeIndex] = findSiblingsAndIndex(\n    dragNode,\n    dataRef.value\n  )\n  if (dragNodeSiblings === null || dragNodeIndex === null)\n    return\n  dragNodeSiblings.splice(dragNodeIndex, 1)\n  if (dropPosition === 'inside') {\n    if (node.children) {\n      node.children.unshift(dragNode)\n    }\n    else {\n      node.children = [dragNode]\n    }\n  }\n  else if (dropPosition === 'before') {\n    const [nodeSiblings, nodeIndex] = findSiblingsAndIndex(node, dataRef.value)\n    if (nodeSiblings === null || nodeIndex === null)\n      return\n    nodeSiblings.splice(nodeIndex, 0, dragNode)\n  }\n  else if (dropPosition === 'after') {\n    const [nodeSiblings, nodeIndex] = findSiblingsAndIndex(node, dataRef.value)\n    if (nodeSiblings === null || nodeIndex === null)\n      return\n    nodeSiblings.splice(nodeIndex + 1, 0, dragNode)\n  }\n\n  dataRef.value = Array.from(dataRef.value)\n}\n\nfunction handleLoad(node: TreeOption) {\n  return new Promise<void>((resolve) => {\n    setTimeout(() => {\n      node.children = [\n        {\n          label: nextLabel(node.label),\n          key: node.key + nextLabel(node.label),\n          isLeaf: false\n        }\n      ]\n      resolve()\n    }, 1000)\n  })\n}\n</script>\n\n<template>\n  <n-space vertical>\n    <n-space align=\"center\">\n      <n-radio-group v-model:value=\"checkStrategy\">\n        <n-radio-button value=\"all\">\n          All\n        </n-radio-button>\n        <n-radio-button value=\"parent\">\n          Parent\n        </n-radio-button>\n        <n-radio-button value=\"child\">\n          Child\n        </n-radio-button>\n      </n-radio-group>\n      <n-space><n-switch v-model:value=\"cascade\" />Cascade</n-space>\n    </n-space>\n    <n-tree\n      block-line\n      checkable\n      draggable\n      :data=\"dataRef\"\n      :checked-keys=\"checkedKeysRef\"\n      :on-load=\"handleLoad\"\n      :expanded-keys=\"expandedKeysRef\"\n      :check-strategy=\"checkStrategy\"\n      :allow-checking-not-loaded=\"cascade\"\n      :cascade=\"cascade\"\n      @drop=\"handleDrop\"\n      @update:checked-keys=\"handleCheckedKeysChange\"\n      @update:expanded-keys=\"handleExpandedKeysChange\"\n    />\n    {{ JSON.stringify(checkedKeysRef) }}\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/tree/demos/enUS/basic.demo.vue",
    "content": "<markdown>\n# Basic\n\nFortunately, the tree is now alive and it's not balanced.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { TreeOption } from 'naive-ui'\nimport { repeat } from 'seemly'\nimport { ref } from 'vue'\n\nfunction createData(level = 4, baseKey = ''): TreeOption[] | undefined {\n  if (!level)\n    return undefined\n  return repeat(6 - level, undefined).map((_, index) => {\n    const key = `${baseKey}${level}${index}`\n    return {\n      label: createLabel(level),\n      key,\n      children: createData(level - 1, key)\n    }\n  })\n}\n\nfunction createLabel(level: number): string {\n  if (level === 4)\n    return 'Out of Tao, One is born'\n  if (level === 3)\n    return 'Out of One, Two'\n  if (level === 2)\n    return 'Out of Two, Three'\n  if (level === 1)\n    return 'Out of Three, the created universe'\n  return ''\n}\n\nconst data = createData()\nconst defaultExpandedKeys = ref(['40', '41'])\n</script>\n\n<template>\n  <n-tree\n    block-line\n    :data=\"data\"\n    :default-expanded-keys=\"defaultExpandedKeys\"\n    expand-on-click\n    checkable\n  />\n</template>\n"
  },
  {
    "path": "src/tree/demos/enUS/batch-render.demo.vue",
    "content": "<markdown>\n# Batch rendering\n\nAs you can see, prefix, label, and suffix all have render functions.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { TreeOption } from 'naive-ui'\nimport { NButton } from 'naive-ui'\nimport { repeat } from 'seemly'\nimport { h, ref } from 'vue'\n\nfunction createData(level = 4, baseKey = ''): TreeOption[] | undefined {\n  if (!level)\n    return undefined\n  return repeat(6 - level, undefined).map((_, index) => {\n    const key = `${baseKey}${level}${index}`\n    return {\n      label: createLabel(level),\n      key,\n      children: createData(level - 1, key),\n      level\n    }\n  })\n}\n\nfunction createLabel(level: number): string {\n  if (level === 4)\n    return 'Out of Tao, One is born'\n  if (level === 3)\n    return 'Out of One, Two'\n  if (level === 2)\n    return 'Out of Two, Three'\n  if (level === 1)\n    return 'Out of Three, the created universe'\n  return ''\n}\n\nfunction renderPrefix({ option }: { option: TreeOption }) {\n  return h(\n    NButton,\n    { text: true, type: 'primary' },\n    { default: () => `Prefix-${option.level}` }\n  )\n}\n\nfunction renderLabel({ option }: { option: TreeOption }) {\n  return `${option.label} :)`\n}\n\nfunction renderSuffix({ option }: { option: TreeOption }) {\n  return h(\n    NButton,\n    { text: true, type: 'primary' },\n    { default: () => `Suffix-${option.level}` }\n  )\n}\n\nconst data = createData()\nconst defaultExpandedKeys = ref(['40', '41'])\n</script>\n\n<template>\n  <n-tree\n    block-line\n    :data=\"data\"\n    :default-expanded-keys=\"defaultExpandedKeys\"\n    :render-prefix=\"renderPrefix\"\n    :render-label=\"renderLabel\"\n    :render-suffix=\"renderSuffix\"\n    :selectable=\"false\"\n  />\n</template>\n"
  },
  {
    "path": "src/tree/demos/enUS/cascade.demo.vue",
    "content": "<markdown>\n# Cascade checking\n\nSet `cascade` to use cascade check.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { TreeOption } from 'naive-ui'\nimport { repeat } from 'seemly'\nimport { ref } from 'vue'\n\nfunction createData(level = 4, baseKey = ''): TreeOption[] | undefined {\n  if (!level)\n    return undefined\n  return repeat(6 - level, undefined).map((_, index) => {\n    const key = `${baseKey}${level}${index}`\n    return {\n      label: createLabel(level),\n      key,\n      children: createData(level - 1, key)\n    }\n  })\n}\n\nfunction createLabel(level: number): string {\n  if (level === 4)\n    return 'Out of Tao, One is born'\n  if (level === 3)\n    return 'Out of One, Two'\n  if (level === 2)\n    return 'Out of Two, Three'\n  if (level === 1)\n    return 'Out of Three, the created universe'\n  return ''\n}\n\nconst data = createData()\nconst defaultExpandedKeys = ref(['40', '4030', '403020'])\nconst defaultCheckedKeys = ref(['40302010'])\n\nfunction updateCheckedKeys(\n  keys: Array<string | number>,\n  options: Array<TreeOption | null>,\n  meta: {\n    node: TreeOption | null\n    action: 'check' | 'uncheck'\n  }\n) {\n  console.log('updateCheckedKeys', keys, options, meta)\n}\n</script>\n\n<template>\n  <n-tree\n    block-line\n    cascade\n    checkable\n    :data=\"data\"\n    :default-expanded-keys=\"defaultExpandedKeys\"\n    :default-checked-keys=\"defaultCheckedKeys\"\n    @update:checked-keys=\"updateCheckedKeys\"\n  />\n</template>\n"
  },
  {
    "path": "src/tree/demos/enUS/checkbox-placement.demo.vue",
    "content": "<markdown>\n# Checkbox Placement\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { TreeOption } from 'naive-ui'\nimport { repeat } from 'seemly'\nimport { ref } from 'vue'\n\nfunction createData(level = 4, baseKey = ''): TreeOption[] | undefined {\n  if (!level)\n    return undefined\n  return repeat(6 - level, undefined).map((_, index) => {\n    const key = `${baseKey}${level}${index}`\n    return {\n      label: createLabel(level),\n      key,\n      children: createData(level - 1, key)\n    }\n  })\n}\n\nfunction createLabel(level: number): string {\n  if (level === 4)\n    return 'Out of Tao, One is born'\n  if (level === 3)\n    return 'Out of One, Two'\n  if (level === 2)\n    return 'Out of Two, Three'\n  if (level === 1)\n    return 'Out of Three, the created universe'\n  return ''\n}\n\nconst data = createData()\nconst defaultExpandedKeys = ref(['40', '4030', '403020'])\nconst defaultCheckedKeys = ref(['40302010'])\n\nfunction updateCheckedKeys(v: string[]) {\n  console.log('updateCheckedKeys', v)\n}\n</script>\n\n<template>\n  <n-tree\n    checkable\n    block-line\n    checkbox-placement=\"right\"\n    :data=\"data\"\n    :default-expanded-keys=\"defaultExpandedKeys\"\n    :default-checked-keys=\"defaultCheckedKeys\"\n    @update:checked-keys=\"updateCheckedKeys\"\n  />\n</template>\n"
  },
  {
    "path": "src/tree/demos/enUS/custom-field.demo.vue",
    "content": "<markdown>\n# Customize key and label field\n\nVarious data would come from backend.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { TreeOption } from 'naive-ui'\nimport { repeat } from 'seemly'\nimport { ref } from 'vue'\n\nfunction createData(level = 4, baseKey = ''): TreeOption[] | undefined {\n  if (!level)\n    return undefined\n  return repeat(6 - level, undefined).map((_, index) => {\n    const key = `${baseKey}${level}${index}`\n    return {\n      whateverLabel: createLabel(level),\n      whateverKey: key,\n      whateverChildren: createData(level - 1, key)\n    }\n  })\n}\n\nfunction createLabel(level: number): string {\n  if (level === 4)\n    return 'Out of Tao, One is born'\n  if (level === 3)\n    return 'Out of One, Two'\n  if (level === 2)\n    return 'Out of Two, Three'\n  if (level === 1)\n    return 'Out of Three, the created universe'\n  return ''\n}\n\nconst data = createData()\nconst defaultExpandedKeys = ref(['40', '41'])\n</script>\n\n<template>\n  <n-tree\n    block-line\n    :data=\"data\"\n    :default-expanded-keys=\"defaultExpandedKeys\"\n    key-field=\"whateverKey\"\n    label-field=\"whateverLabel\"\n    children-field=\"whateverChildren\"\n    selectable\n  />\n</template>\n"
  },
  {
    "path": "src/tree/demos/enUS/disabled.demo.vue",
    "content": "<markdown>\n# Disabled nodes\n</markdown>\n\n<script lang=\"ts\" setup>\nconst data = [\n  {\n    key: '0',\n    label: '0',\n    children: [\n      {\n        key: '0-0',\n        label: '0-0'\n      },\n      {\n        disabled: true,\n        key: '0-1',\n        label: '0-1',\n        children: [\n          {\n            label: '0-1-0',\n            key: '0-1-0'\n          },\n          {\n            label: '0-1-1',\n            key: '0-1-1'\n          }\n        ]\n      }\n    ]\n  },\n  {\n    key: '1',\n    label: '1',\n    children: [\n      {\n        key: '1-0',\n        label: '1-0'\n      },\n      {\n        checkboxDisabled: true,\n        key: '1-1',\n        label: '1-1',\n        children: [\n          {\n            label: '1-1-0',\n            key: '1-1-0'\n          },\n          {\n            label: '1-1-1',\n            key: '1-1-1'\n          }\n        ]\n      }\n    ]\n  }\n]\n</script>\n\n<template>\n  <n-tree\n    :data=\"data\"\n    block-line\n    checkable\n    default-expand-all\n    cascade\n    :default-checked-keys=\"['1-1']\"\n  />\n</template>\n"
  },
  {
    "path": "src/tree/demos/enUS/drag-drop.demo.vue",
    "content": "<markdown>\n# Drag & drop\n\nSet `draggable` and write bunch of codes to make drag & drop work.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { TreeDropInfo, TreeOption } from 'naive-ui'\nimport { repeat } from 'seemly'\nimport { ref } from 'vue'\n\nfunction createData(level = 4, baseKey = ''): TreeOption[] | undefined {\n  if (!level)\n    return undefined\n  return repeat(6 - level, undefined).map((_, index) => {\n    const key = `${baseKey}${level}${index}`\n    return {\n      label: createLabel(level),\n      key,\n      children: createData(level - 1, key)\n    }\n  })\n}\n\nfunction createLabel(level: number): string {\n  if (level === 4)\n    return 'Out of Tao, One is born'\n  if (level === 3)\n    return 'Out of One, Two'\n  if (level === 2)\n    return 'Out of Two, Three'\n  if (level === 1)\n    return 'Out of Three, the created universe'\n  return ''\n}\n\nfunction findSiblingsAndIndex(\n  node: TreeOption,\n  nodes?: TreeOption[]\n): [TreeOption[], number] | [null, null] {\n  if (!nodes)\n    return [null, null]\n  for (let i = 0; i < nodes.length; ++i) {\n    const siblingNode = nodes[i]\n    if (siblingNode.key === node.key)\n      return [nodes, i]\n    const [siblings, index] = findSiblingsAndIndex(node, siblingNode.children)\n    if (siblings && index !== null)\n      return [siblings, index]\n  }\n  return [null, null]\n}\n\n/**\n * The time complexity of the demo can be optimized,\n * but I'm too lazy to optimize it.\n */\nconst expandedKeysRef = ref<string[]>([])\nconst checkedKeysRef = ref<string[]>([])\nconst dataRef = ref(createData() || [])\n\nfunction handleExpandedKeysChange(expandedKeys: string[]) {\n  expandedKeysRef.value = expandedKeys\n}\n\nfunction handleCheckedKeysChange(checkedKeys: string[]) {\n  checkedKeysRef.value = checkedKeys\n}\n\nfunction handleDrop({ node, dragNode, dropPosition }: TreeDropInfo) {\n  const [dragNodeSiblings, dragNodeIndex] = findSiblingsAndIndex(\n    dragNode,\n    dataRef.value\n  )\n  if (dragNodeSiblings === null || dragNodeIndex === null)\n    return\n  dragNodeSiblings.splice(dragNodeIndex, 1)\n  if (dropPosition === 'inside') {\n    if (node.children) {\n      node.children.unshift(dragNode)\n    }\n    else {\n      node.children = [dragNode]\n    }\n  }\n  else if (dropPosition === 'before') {\n    const [nodeSiblings, nodeIndex] = findSiblingsAndIndex(node, dataRef.value)\n    if (nodeSiblings === null || nodeIndex === null)\n      return\n    nodeSiblings.splice(nodeIndex, 0, dragNode)\n  }\n  else if (dropPosition === 'after') {\n    const [nodeSiblings, nodeIndex] = findSiblingsAndIndex(node, dataRef.value)\n    if (nodeSiblings === null || nodeIndex === null)\n      return\n    nodeSiblings.splice(nodeIndex + 1, 0, dragNode)\n  }\n  dataRef.value = Array.from(dataRef.value)\n}\n</script>\n\n<template>\n  <n-tree\n    block-line\n    checkable\n    draggable\n    :data=\"dataRef\"\n    :checked-keys=\"checkedKeysRef\"\n    :expanded-keys=\"expandedKeysRef\"\n    @drop=\"handleDrop\"\n    @update:checked-keys=\"handleCheckedKeysChange\"\n    @update:expanded-keys=\"handleExpandedKeysChange\"\n  />\n</template>\n"
  },
  {
    "path": "src/tree/demos/enUS/file-tree.demo.vue",
    "content": "<markdown>\n# File Tree\n\nUse `on-update:expanded-keys` to change the prefix icon style of the node in different states.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { TreeOption } from 'naive-ui'\nimport {\n  FileTrayFullOutline,\n  Folder,\n  FolderOpenOutline\n} from '@vicons/ionicons5'\nimport { NIcon, useMessage } from 'naive-ui'\nimport { h } from 'vue'\n\nconst message = useMessage()\n\nfunction updatePrefixWithExpaned(\n  _keys: Array<string | number>,\n  _option: Array<TreeOption | null>,\n  meta: {\n    node: TreeOption | null\n    action: 'expand' | 'collapse' | 'filter'\n  }\n) {\n  if (!meta.node)\n    return\n  switch (meta.action) {\n    case 'expand':\n      meta.node.prefix = () =>\n        h(NIcon, null, {\n          default: () => h(FolderOpenOutline)\n        })\n      break\n    case 'collapse':\n      meta.node.prefix = () =>\n        h(NIcon, null, {\n          default: () => h(Folder)\n        })\n      break\n  }\n}\n\nfunction nodeProps({ option }: { option: TreeOption }) {\n  return {\n    onClick() {\n      if (!option.children && !option.disabled) {\n        message.info(`[Click] ${option.label}`)\n      }\n    }\n  }\n}\n\nconst data = [\n  {\n    key: 'Folder',\n    label: 'Folder',\n    prefix: () =>\n      h(NIcon, null, {\n        default: () => h(Folder)\n      }),\n    children: [\n      {\n        key: 'Empty',\n        label: 'Empty',\n        disabled: true,\n        prefix: () =>\n          h(NIcon, null, {\n            default: () => h(Folder)\n          })\n      },\n      {\n        key: 'MyFiles',\n        label: 'MyFiles',\n        prefix: () =>\n          h(NIcon, null, {\n            default: () => h(Folder)\n          }),\n        children: [\n          {\n            label: 'template.txt',\n            key: 'template.txt',\n            prefix: () =>\n              h(NIcon, null, {\n                default: () => h(FileTrayFullOutline)\n              })\n          }\n        ]\n      }\n    ]\n  }\n]\n</script>\n\n<template>\n  <n-tree\n    block-line\n    expand-on-click\n    :data=\"data\"\n    :node-props=\"nodeProps\"\n    :on-update:expanded-keys=\"updatePrefixWithExpaned\"\n  />\n</template>\n"
  },
  {
    "path": "src/tree/demos/enUS/filter.demo.vue",
    "content": "<markdown>\n# Search\n\nTree accept `pattern` and `filter` to do searching.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { TreeOption } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst data: TreeOption[] = [\n  {\n    label: '0',\n    key: '0',\n    children: [\n      {\n        label: '0-0',\n        key: '0-0',\n        children: [\n          { label: '0-0-0', key: '0-0-0' },\n          { label: '0-0-1', key: '0-0-1' }\n        ]\n      },\n      {\n        label: '0-1',\n        key: '0-1',\n        children: [\n          { label: '0-1-0', key: '0-1-0' },\n          { label: '0-1-1', key: '0-1-1' }\n        ]\n      }\n    ]\n  },\n  {\n    label: '1',\n    key: '1',\n    children: [\n      {\n        label: '1-0',\n        key: '1-0',\n        children: [\n          { label: '1-0-0', key: '1-0-0' },\n          { label: '1-0-1', key: '1-0-1' }\n        ]\n      },\n      {\n        label: '1-1',\n        key: '1-1',\n        children: [\n          { label: '1-1-0', key: '1-1-0' },\n          { label: '1-1-1', key: '1-1-1' }\n        ]\n      }\n    ]\n  }\n]\n\nconst pattern = ref('')\nconst showIrrelevantNodes = ref(false)\n</script>\n\n<template>\n  <n-space vertical :size=\"12\">\n    <n-input v-model:value=\"pattern\" placeholder=\"Search\" />\n    <n-switch v-model:value=\"showIrrelevantNodes\">\n      <template #checked>\n        Show irrelevant nodes\n      </template>\n      <template #unchecked>\n        Hide irrelevant nodes\n      </template>\n    </n-switch>\n    <n-tree\n      :show-irrelevant-nodes=\"showIrrelevantNodes\"\n      :pattern=\"pattern\"\n      :data=\"data\"\n      block-line\n    />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/tree/demos/enUS/index.demo-entry.md",
    "content": "# Tree\n\nTo be honest, I'm not good at biology. I can figure out few kinds of trees.\n\nWhat's more, not only biology, I forget balanced tree everytime after I revise it shortly.\n\n## Demos\n\n```demo\nbasic.vue\ncustom-field.vue\nmultiple.vue\ncascade.vue\nfilter.vue\ndrag-drop.vue\nvirtual.vue\nasync.vue\ndisabled.vue\nprefix-and-suffix.vue\nbatch-render.vue\nswitcher-icon.vue\nfile-tree.vue\nnode-props.vue\nshow-line.vue\ncheckbox-placement.vue\noverride-click-behavior.vue\n```\n\n## API\n\n### Tree Props\n\n| Name | Type | default | Description | Version |\n| --- | --- | --- | --- | --- |\n| accordion | `boolean` | `false` | Whether to use accrodion expand mode. | 2.31.0 |\n| allow-checking-not-loaded | `boolean` | `false` | Whether to allow cascade checking on not loaded nodes. If you want to use this, you should know the `check-keys` may be incomplete. Also, you should aware about the consistency bewteen naive's checking logic and your backend's checking logic, especially when there are disabled nodes. | 2.28.1 |\n| allow-drop | `(info: { dropPosition: DropPosition, node: TreeOption, phase: 'drag' \\| 'drop' }) => boolean` | A function that prohibit dropping inside leaf node. | Whether to allow dropping. |  |\n| animated | `boolean` | `true` | Whether to show expand animation. | 2.33.4 |\n| block-line | `boolean` | `false` | Nodes spread out the whole row. |  |\n| block-node | `boolean` | `false` | The node name is spread out in the whole row. |  |\n| cancelable | `boolean` | `true` | Whether node's select status can be cancelled. |  |\n| cascade | `boolean` | `false` | Whether to cascade checkboxes. |  |\n| check-strategy | `string` | `'all'` | The strategy of setting checked callback's keys argument. `all` means setting all checked node. `parent` means setting all checked parent node of whom all child node are checked. `child` means setting all child node. |  |\n| checkable | `boolean` | `false` | Whether to display the selection box. |  |\n| checkbox-placement | `'left' \\| 'right'` | `'left'` | Checkbox's placement. | 2.28.3 |\n| children-field | `string` | `'children'` | The children field in `TreeOption`. |  |\n| checked-keys | `Array<string \\| number>` | `undefined` | Checked keys of the tree. |  |\n| check-on-click | `boolean \\| ((node: TreeOption) => boolean)` | `false` | Allow node clicking to trigger check when `checkable` is `true`. | 2.31.0 |\n| data | `Array<TreeOption>` | `[]` | The node data of the tree. Reset `data` will cause clearing of some uncontrolled status. If you need to modify data, you'd better make tree work in a controlled manner. |  |\n| default-checked-keys | `Array<string \\| number>` | `[]` | Multiple options selected by default. |  |\n| default-expand-all | `boolean` | `false` | Expand all options. |  |\n| default-expanded-keys | `Array<string \\| number>` | `[]` | Expanded items by default. |  |\n| default-selected-keys | `Array<string \\| number>` | `[]` | Nodes selected by default. |  |\n| draggable | `boolean` | `false` | Whether it can be dragged. |  |\n| expand-on-dragenter | `boolean` | `true` | Whether to expand nodes after dragenter. |  |\n| expand-on-click | `boolean` | `false` | Whether to expand or collapse nodes after click. | 2.29.1 |\n| expanded-keys | `Array<string \\| number>` | `undefined` | If set, expanded status will work in controlled manner. |  |\n| ellipsis | `boolean` | `false` | Whether to ellipsis the text that exceeds the width. | 2.43.0 |\n| filter | `(pattern: string, node: TreeOption) => boolean` | A simple string based filter. | The function that filter tree nodes based on pattern. |  |\n| get-children | `(option: any) => unknown` | `undefined` | Get children of the option. | 2.34.3 |\n| indent | `number` | `24` | Indent of per level of the tree. | 2.9.0 |\n| indeterminate-keys | `Array<string \\| number>` | `undefined` | Indeterminate keys of the tree. |  |\n| keyboard | `boolean` | `true` | Whether to support keyboard operation. | 2.32.2 |\n| key-field | `string` | `'key'` | The key field in `TreeOption`. |  |\n| label-field | `string` | `'label'` | The label field in `TreeOption`. |  |\n| disabled-field | `string` | `'disabled'` | The disabled field in `TreeOption`. | 2.32.2 |\n| node-props | `(info: { option: TreeOption }) => HTMLAttributes` | `undefined` | HTML attributes of node. | 2.25.0 |\n| multiple | `boolean` | `false` | Whether to allow multiple selection of nodes. |  |\n| on-load | `(node: TreeOption) => Promise<void>` | `undefined` | Callback function for asynchronously loading data. If not data is loaded, you should make promise resolve `false` or be rejected, nor the loading animation won't end. | Non void Promise 2.34.3 |\n| override-default-node-click-behavior | `(info: { option: TreeSelectOption }) => 'toggleExpand' \\| 'toggleSelect' \\| 'toggleCheck' \\| 'default' \\| 'none'` | `undefined` | Override default node click behavior. | 2.37.0 |\n| pattern | `string` | `''` | What to search by default. |  |\n| render-label | `(info: { option: TreeOption, checked: boolean, selected: boolean }) => VNodeChild` | `undefined` | Render function of all the options' label. |  |\n| render-prefix | `(info: { option: TreeOption, checked: boolean, selected: boolean }) => VNodeChild` | `undefined` | Render function of all the options' prefix. |  |\n| render-suffix | `(info: { option: TreeOption, checked: boolean, selected: boolean }) => VNodeChild` | `undefined` | Render function of all the options' suffix. |  |\n| render-switcher-icon | `(props: { option: TreeOption, expanded: boolean, selected: boolean }) => VNodeChild` | `undefined` | Render function of option switcher icon. | 2.24.0, `props` 2.34.0 |\n| scrollbar-props | `ScrollbarProps` | `undefined` | See [Scrollbar props](scrollbar#Scrollbar-Props). |  |\n| selectable | `boolean` | `true` | Whether the node can be selected. |  |\n| selected-keys | `Array<string \\| number>` | `undefined` | If set, selected status will work in controlled manner. |  |\n| show-irrelevant-nodes | `boolean` | `true` | Whether to filter unmached nodes when tree is in filter mode. | 2.28.1 |\n| show-line | `boolean` | `false` | Whether to display the connection line. | 2.35.0 |\n| spin-props | `{ strokeWidth?: number, stroke?: string, scale?: number, radius?: number }` | `undefined` | Loading icon properties. | 2.44.0 |\n| virtual-scroll | `boolean` | `false` | Whether to enable virtual scroll. You need to set proper style height of the tree in advance. |  |\n| watch-props | `Array<'defaultCheckedKeys' \\| 'defaultSelectedKeys' \\|'defaultExpandedKeys'>` | `undefined` | Default prop names that needed to be watched. Components will be updated after the prop is changed. Note: the `watch-props` itself is not reactive. |  |\n| on-dragend | `(data: { node: TreeOption, event: DragEvent }) => void` | `undefined` | The callback function after the node completes the dragging action. |  |\n| on-dragenter | `(data: { node: TreeOption, event: DragEvent }) => void` | `undefined` | Callback function in node drag and drop. |  |\n| on-dragleave | `(data: { node: TreeOption, event: DragEvent }) => void` | `undefined` | Drag a node, the callback function after the node leaves other nodes. |  |\n| on-dragstart | `(data: { node: TreeOption, event: DragEvent }) => void` | `undefined` | Callback function to start dragging a certain node. |  |\n| on-drop | `(data: { node: TreeOption, dragNode: TreeOption, dropPosition: 'before' \\| 'inside' \\| 'after', event: DragEvent }) => void` | `undefined` | The callback function after the node completes the dragging action. |  |\n| on-update:checked-keys | `(keys: Array<string \\| number>, option: Array<TreeOption \\| null>), meta: { node: TreeOption \\| null, action: 'check' \\| 'uncheck' }) => void` | `undefined` | Callback function when node checked options change. | `meta` 2.34.0 |\n| on-update:indeterminate-keys | `(keys: Array<string \\| number>, option: Array<TreeOption \\| null>) => void` | `undefined` | Callback function when node indeterminate options change. |  |\n| on-update:expanded-keys | `(keys: Array<string \\| number>, option: Array<TreeOption \\| null>), meta: { node: TreeOption \\| null, action: 'expand' \\| 'collapse' \\| 'filter' }) => void` | `undefined` | The callback function when the node expansion item changes. | `meta` 2.34.0 |\n| on-update:selected-keys | `(keys: Array<string \\| number>, option: Array<TreeOption \\| null>), meta: { node: TreeOption \\| null, action: 'select' \\| 'unselect' }) => void` | `undefined` | The callback function when the selected item of the node changes. | `meta` 2.34.0 |\n\n### TreeOption Properties\n\n| Name | Type | Description |\n| --- | --- | --- |\n| key | `string \\| number` | Key of the node, should be unique. You can use `key-field` to customize the field name. |\n| label | `string` | Label of the node. You can use `label-field` to customize the field name. |\n| checkboxDisabled? | `boolean` | Whether the checkbox is disabled. |\n| children? | `TreeOption[]` | Child nodes of the node. |\n| disabled? | `boolean` | Whether the node is disabled. |\n| isLeaf? | `boolean` | Whether the node is leaf. Required in async expanding mode. |\n| prefix? | `string \\| (() => VNodeChild)` | Prefix of the node. |\n| suffix? | `string \\| (() => VNodeChild)` | Suffix of the node. |\n\n### Tree Slots\n\n| Name  | Parameters | Description                    | Version |\n| ----- | ---------- | ------------------------------ | ------- |\n| empty | `()`       | Empty state slot for the tree. |         |\n\n## Methods\n\n### Tree Methods\n\n| Name | Paramaters | Description | Version |\n| --- | --- | --- | --- |\n| scrollTo | `ScrollTo` | Scroll to some node in virtual scroll mode. | 2.32.2, `ScrollTo` 2.37.0 |\n| getCheckedData | `() => { keys: Array<string \\| number>, options: Array<TreeOption \\| null> }` | Get checked data. | 2.34.1 |\n| getIndeterminateData | `() => { keys: Array<string \\| number>, options: Array<TreeOption \\| null> }` | Get indeterminate data. | 2.34.1 |\n\n#### ScrollTo Type\n\n```ts\ninterface ScrollTo {\n  (x: number, y: number): void\n  (options: { left?: number, top?: number, debounce?: boolean }): void\n  (options: { index: number, debounce?: boolean }): void\n  (options: { key: string | number, debounce?: boolean }): void\n  (options: { position: 'top' | 'bottom', debounce?: boolean }): void\n}\n```\n\n### Others\n\n1. `treeGetClickTarget: (e: MouseEvent) => ('checkbox' | 'switcher' | 'node')`: Get click target of a node click event. It can be used in `nodeProps.onClick`. You can import it from `naive-ui` package directly.\n"
  },
  {
    "path": "src/tree/demos/enUS/multiple.demo.vue",
    "content": "<markdown>\n# Select multiple nodes\n\nSet `multiple` to select multiple nodes.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { TreeOption } from 'naive-ui'\nimport { repeat } from 'seemly'\nimport { ref } from 'vue'\n\nfunction createData(level = 4, baseKey = ''): TreeOption[] | undefined {\n  if (!level)\n    return undefined\n  return repeat(6 - level, undefined).map((_, index) => {\n    const key = `${baseKey}${level}${index}`\n    return {\n      label: createLabel(level),\n      key,\n      children: createData(level - 1, key)\n    }\n  })\n}\n\nfunction createLabel(level: number): string {\n  if (level === 4)\n    return 'Out of Tao, One is born'\n  if (level === 3)\n    return 'Out of One, Two'\n  if (level === 2)\n    return 'Out of Two, Three'\n  if (level === 1)\n    return 'Out of Three, the created universe'\n  return ''\n}\n\nconst data = createData()\nconst value = ref([])\n</script>\n\n<template>\n  <n-tree multiple block-line :data=\"data\" />\n  <n-divider />\n  <n-tree v-model=\"value\" multiple block-line :data=\"data\" />\n</template>\n"
  },
  {
    "path": "src/tree/demos/enUS/node-props.demo.vue",
    "content": "<markdown>\n# Node events\n\nUse `node-props` to bind HTML attributes to node. For example click or contextmenu event listener.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { DropdownOption, TreeOption } from 'naive-ui'\nimport { useMessage } from 'naive-ui'\nimport { repeat } from 'seemly'\nimport { ref } from 'vue'\n\nfunction createData(level = 4, baseKey = ''): TreeOption[] | undefined {\n  if (!level)\n    return undefined\n  return repeat(6 - level, undefined).map((_, index) => {\n    const key = `${baseKey}${level}${index}`\n    return {\n      label: createLabel(level),\n      key,\n      children: createData(level - 1, key)\n    }\n  })\n}\n\nfunction createLabel(level: number): string {\n  if (level === 4)\n    return 'Out of Tao, One is born'\n  if (level === 3)\n    return 'Out of One, Two'\n  if (level === 2)\n    return 'Out of Two, Three'\n  if (level === 1)\n    return 'Out of Three, the created universe'\n  return ''\n}\n\nconst message = useMessage()\nconst showDropdownRef = ref(false)\nconst optionsRef = ref<DropdownOption[]>([])\nconst xRef = ref(0)\nconst yRef = ref(0)\nconst data = createData()\nconst defaultExpandedKeys = ref(['40', '41'])\n\nfunction handleSelect() {\n  showDropdownRef.value = false\n}\n\nfunction handleClickoutside() {\n  showDropdownRef.value = false\n}\n\nfunction nodeProps({ option }: { option: TreeOption }) {\n  return {\n    onClick() {\n      message.info(`[Click] ${option.label}`)\n    },\n    onContextmenu(e: MouseEvent): void {\n      optionsRef.value = [option]\n      showDropdownRef.value = true\n      xRef.value = e.clientX\n      yRef.value = e.clientY\n      console.log(e.clientX, e.clientY)\n      e.preventDefault()\n    }\n  }\n}\n</script>\n\n<template>\n  <n-tree\n    block-line\n    :data=\"data\"\n    :default-expanded-keys=\"defaultExpandedKeys\"\n    :node-props=\"nodeProps\"\n  />\n  <n-dropdown\n    trigger=\"manual\"\n    placement=\"bottom-start\"\n    :show=\"showDropdownRef\"\n    :options=\"optionsRef as any\"\n    :x=\"xRef\"\n    :y=\"yRef\"\n    @select=\"handleSelect\"\n    @clickoutside=\"handleClickoutside\"\n  />\n</template>\n"
  },
  {
    "path": "src/tree/demos/enUS/override-click-behavior.demo.vue",
    "content": "<markdown>\n# Custom node click behavior\n\nYou can use `override-default-node-click-behavior` prop to override default node click behavior.\n\nFor example, you can change non-leaf key's default behavior to `'toggleExpand'` to simulate a file selector.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { TreeOverrideNodeClickBehavior } from 'naive-ui'\n\nconst override: TreeOverrideNodeClickBehavior = ({ option }) => {\n  if (option.children) {\n    return 'toggleExpand'\n  }\n  return 'default'\n}\n\nconst options = [\n  {\n    label: 'Folder-1',\n    key: 'Folder-1',\n    children: [\n      {\n        label: 'File-1-1',\n        key: 'File-1-1'\n      },\n      {\n        label: 'Folder-1-2',\n        key: 'Folder-1-2',\n        children: [\n          {\n            label: 'File-1-2-1',\n            key: 'File-1-2-1'\n          },\n          {\n            label: 'File-1-2-2',\n            key: 'File-1-2-2'\n          }\n        ]\n      }\n    ]\n  },\n  {\n    label: 'Folder-2',\n    key: 'Folder-2',\n    children: [\n      {\n        label: 'File-2-1',\n        key: 'File-2-1'\n      },\n      {\n        label: 'File-2-2',\n        key: 'File-2-2'\n      }\n    ]\n  }\n]\n</script>\n\n<template>\n  <n-tree\n    block-line\n    :data=\"options\"\n    :override-default-node-click-behavior=\"override\"\n  />\n</template>\n"
  },
  {
    "path": "src/tree/demos/enUS/prefix-and-suffix.demo.vue",
    "content": "<markdown>\n# Prefix and suffix\n\nAdd some actions.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { TreeOption } from 'naive-ui'\nimport { NButton } from 'naive-ui'\nimport { repeat } from 'seemly'\nimport { h, ref } from 'vue'\n\nfunction createData(level = 4, baseKey = ''): TreeOption[] | undefined {\n  if (!level)\n    return undefined\n  return repeat(6 - level, undefined).map((_, index) => {\n    const key = `${baseKey}${level}${index}`\n    const label = createLabel(level)\n    return {\n      label,\n      key,\n      children: createData(level - 1, key),\n      suffix: () =>\n        h(\n          NButton,\n          { text: true, type: 'primary' },\n          { default: () => 'Suffix' }\n        ),\n      prefix: () =>\n        h(NButton, { text: true, type: 'primary' }, { default: () => 'Prefix' })\n    }\n  })\n}\n\nfunction createLabel(level: number): string {\n  if (level === 4)\n    return 'Out of Tao, One is born'\n  if (level === 3)\n    return 'Out of One, Two'\n  if (level === 2)\n    return 'Out of Two, Three'\n  if (level === 1)\n    return 'Out of Three, the created universe'\n  return ''\n}\n\nconst data = createData()\nconst defaultExpandedKeys = ref(['40', '41'])\n</script>\n\n<template>\n  <n-tree\n    block-line\n    :data=\"data\"\n    :default-expanded-keys=\"defaultExpandedKeys\"\n    :selectable=\"false\"\n  />\n</template>\n"
  },
  {
    "path": "src/tree/demos/enUS/show-line.demo.vue",
    "content": "<markdown>\n  # Show Line\n  </markdown>\n\n<script lang=\"ts\" setup>\nimport type { TreeOption } from 'naive-ui'\nimport { repeat } from 'seemly'\nimport { ref } from 'vue'\n\nfunction createData(level = 4, baseKey = ''): TreeOption[] | undefined {\n  if (!level)\n    return undefined\n  return repeat(6 - level, undefined).map((_, index) => {\n    const key = `${baseKey}${level}${index}`\n    return {\n      label: createLabel(level),\n      key,\n      children: createData(level - 1, key)\n    }\n  })\n}\n\nfunction createLabel(level: number): string {\n  if (level === 4)\n    return 'Out of Tao, One is born'\n  if (level === 3)\n    return 'Out of One, Two'\n  if (level === 2)\n    return 'Out of Two, Three'\n  if (level === 1)\n    return 'Out of Three, the created universe'\n  return ''\n}\n\nconst showLine = ref(false)\nconst data = createData()\nconst defaultExpandedKeys = ref(['40', '4030', '403020'])\n</script>\n\n<template>\n  <n-space vertical>\n    <n-switch v-model:value=\"showLine\" />\n    <n-tree\n      :show-line=\"showLine\"\n      :default-expanded-keys=\"defaultExpandedKeys\"\n      :data=\"data\"\n      checkable\n      expand-on-click\n      selectable\n    />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/tree/demos/enUS/switcher-icon.demo.vue",
    "content": "<markdown>\n# Switcher icon\n\nUse `render-switcher-icon` prop to customize switcher icon.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { TreeOption } from 'naive-ui'\nimport { ChevronForward, PlanetOutline, SunnyOutline } from '@vicons/ionicons5'\nimport { NIcon } from 'naive-ui'\nimport { repeat } from 'seemly'\nimport { h, ref } from 'vue'\n\nfunction createData(level = 4, baseKey = ''): TreeOption[] | undefined {\n  if (!level)\n    return undefined\n  return repeat(6 - level, undefined).map((_, index) => {\n    const key = `${baseKey}${level}${index}`\n    return {\n      label: createLabel(level),\n      key,\n      children: createData(level - 1, key)\n    }\n  })\n}\n\nfunction createLabel(level: number): string {\n  if (level === 4)\n    return 'Out of Tao, One is born'\n  if (level === 3)\n    return 'Out of One, Two'\n  if (level === 2)\n    return 'Out of Two, Three'\n  if (level === 1)\n    return 'Out of Three, the created universe'\n  return ''\n}\n\nconst data = createData()\nconst defaultExpandedKeys = ref(['40', '41'])\n\nfunction renderSwitcherIcon() {\n  return h(NIcon, null, { default: () => h(ChevronForward) })\n}\n\nfunction renderSwitcherIconWithExpaned({ expanded }: { expanded: boolean }) {\n  return h(NIcon, null, {\n    default: () => h(expanded ? SunnyOutline : PlanetOutline)\n  })\n}\n</script>\n\n<template>\n  <n-tree\n    block-line\n    :data=\"data\"\n    :default-expanded-keys=\"defaultExpandedKeys\"\n    :render-switcher-icon=\"renderSwitcherIcon\"\n    selectable\n  />\n  <n-tree\n    block-line\n    :data=\"data\"\n    :default-expanded-keys=\"defaultExpandedKeys\"\n    :render-switcher-icon=\"renderSwitcherIconWithExpaned\"\n    selectable\n  />\n</template>\n"
  },
  {
    "path": "src/tree/demos/enUS/virtual.demo.vue",
    "content": "<markdown>\n# Large data\n\nSet `virtual-scroll` to use virtual scroll. Note that you should set the height of the tree.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { TreeInst, TreeOption } from 'naive-ui'\nimport { repeat } from 'seemly'\nimport { ref } from 'vue'\n\nfunction createData(level = 4, baseKey = ''): TreeOption[] | undefined {\n  if (!level)\n    return undefined\n  return repeat(10 - level, undefined).map((_, index) => {\n    const key = `${baseKey}${level}${index}`\n    return {\n      label: createLabel(level),\n      key,\n      children: createData(level - 1, key)\n    }\n  })\n}\n\nfunction createLabel(level: number): string {\n  if (level === 4)\n    return 'Out of Tao, One is born'\n  if (level === 3)\n    return 'Out of One, Two'\n  if (level === 2)\n    return 'Out of Two, Three'\n  if (level === 1)\n    return 'Out of Three, the created universe'\n  return ''\n}\n\nconst treeInstRef = ref<TreeInst | null>(null)\nconst data = createData()\n\nfunction handleScrollToKey() {\n  treeInstRef.value?.scrollTo({ key: '45362710' })\n}\n\nfunction handleScrollToPosition() {\n  treeInstRef.value?.scrollTo({ position: 'bottom' })\n}\n\nfunction handleScrollToIndex() {\n  treeInstRef.value?.scrollTo({ index: 100 })\n}\n\nfunction handleScrollToDistance() {\n  treeInstRef.value?.scrollTo({ top: 400 })\n}\n</script>\n\n<template>\n  <n-space vertical>\n    <n-space>\n      <n-button @click=\"handleScrollToKey\">\n        Scroll\n      </n-button>\n      <n-button @click=\"handleScrollToPosition\">\n        Scroll to position\n      </n-button>\n      <n-button @click=\"handleScrollToIndex\">\n        Scroll to index\n      </n-button>\n      <n-button @click=\"handleScrollToDistance\">\n        Scroll to distance\n      </n-button>\n    </n-space>\n    <n-tree\n      ref=\"treeInstRef\"\n      block-line\n      :data=\"data\"\n      default-expand-all\n      virtual-scroll\n      style=\"height: 320px\"\n    />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/tree/demos/zhCN/async.demo.vue",
    "content": "<markdown>\n# 异步加载\n\n使用 `on-load` 回调来加载数据。异步加载时，所有 `isLeaf` 为 `false` 并且 `children` 不为数组的节点会被视为未加载的节点。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { TreeDropInfo, TreeOption } from 'naive-ui'\nimport { ref } from 'vue'\n\nfunction createData() {\n  return [\n    {\n      label: nextLabel(),\n      key: 1,\n      isLeaf: false\n    },\n    {\n      label: nextLabel(),\n      key: 2,\n      isLeaf: false\n    }\n  ]\n}\n\nfunction nextLabel(currentLabel?: string): string {\n  if (!currentLabel)\n    return 'Out of Tao, One is born'\n  if (currentLabel === 'Out of Tao, One is born')\n    return 'Out of One, Two'\n  if (currentLabel === 'Out of One, Two')\n    return 'Out of Two, Three'\n  if (currentLabel === 'Out of Two, Three') {\n    return 'Out of Three, the created universe'\n  }\n  if (currentLabel === 'Out of Three, the created universe') {\n    return 'Out of Tao, One is born'\n  }\n  return ''\n}\n\nfunction findSiblingsAndIndex(\n  node: TreeOption,\n  nodes?: TreeOption[]\n): [TreeOption[], number] | [null, null] {\n  if (!nodes)\n    return [null, null]\n  for (let i = 0; i < nodes.length; ++i) {\n    const siblingNode = nodes[i]\n    if (siblingNode.key === node.key)\n      return [nodes, i]\n    const [siblings, index] = findSiblingsAndIndex(node, siblingNode.children)\n    if (siblings && index !== null)\n      return [siblings, index]\n  }\n  return [null, null]\n}\n\nconst expandedKeysRef = ref<string[]>([])\nconst checkedKeysRef = ref<string[]>([])\nconst dataRef = ref(createData())\nconst checkStrategy = ref<'all' | 'parent' | 'child'>('all')\nconst cascade = ref(true)\n\nfunction handleExpandedKeysChange(expandedKeys: string[]) {\n  expandedKeysRef.value = expandedKeys\n}\n\nfunction handleCheckedKeysChange(checkedKeys: string[]) {\n  checkedKeysRef.value = checkedKeys\n}\n\nfunction handleDrop({ node, dragNode, dropPosition }: TreeDropInfo) {\n  const [dragNodeSiblings, dragNodeIndex] = findSiblingsAndIndex(\n    dragNode,\n    dataRef.value\n  )\n  if (dragNodeSiblings === null || dragNodeIndex === null)\n    return\n  dragNodeSiblings.splice(dragNodeIndex, 1)\n  if (dropPosition === 'inside') {\n    if (node.children) {\n      node.children.unshift(dragNode)\n    }\n    else {\n      node.children = [dragNode]\n    }\n  }\n  else if (dropPosition === 'before') {\n    const [nodeSiblings, nodeIndex] = findSiblingsAndIndex(node, dataRef.value)\n    if (nodeSiblings === null || nodeIndex === null)\n      return\n    nodeSiblings.splice(nodeIndex, 0, dragNode)\n  }\n  else if (dropPosition === 'after') {\n    const [nodeSiblings, nodeIndex] = findSiblingsAndIndex(node, dataRef.value)\n    if (nodeSiblings === null || nodeIndex === null)\n      return\n    nodeSiblings.splice(nodeIndex + 1, 0, dragNode)\n  }\n\n  dataRef.value = Array.from(dataRef.value)\n}\n\nfunction handleLoad(node: TreeOption) {\n  return new Promise<void>((resolve) => {\n    setTimeout(() => {\n      node.children = [\n        {\n          label: nextLabel(node.label),\n          key: node.key + nextLabel(node.label),\n          isLeaf: false\n        }\n      ]\n      resolve()\n    }, 1000)\n  })\n}\n</script>\n\n<template>\n  <n-space vertical>\n    <n-space align=\"center\">\n      <n-radio-group v-model:value=\"checkStrategy\">\n        <n-radio-button value=\"all\">\n          All\n        </n-radio-button>\n        <n-radio-button value=\"parent\">\n          Parent\n        </n-radio-button>\n        <n-radio-button value=\"child\">\n          Child\n        </n-radio-button>\n      </n-radio-group>\n      <n-space><n-switch v-model:value=\"cascade\" />Cascade</n-space>\n    </n-space>\n    <n-tree\n      block-line\n      checkable\n      draggable\n      :data=\"dataRef\"\n      :checked-keys=\"checkedKeysRef\"\n      :on-load=\"handleLoad\"\n      :expanded-keys=\"expandedKeysRef\"\n      :check-strategy=\"checkStrategy\"\n      :allow-checking-not-loaded=\"cascade\"\n      :cascade=\"cascade\"\n      expand-on-click\n      @drop=\"handleDrop\"\n      @update:checked-keys=\"handleCheckedKeysChange\"\n      @update:expanded-keys=\"handleExpandedKeysChange\"\n    />\n    {{ JSON.stringify(checkedKeysRef) }}\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/tree/demos/zhCN/basic.demo.vue",
    "content": "<markdown>\n# 基础用法\n\n好在这颗树不是活的，也不平衡。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { TreeOption } from 'naive-ui'\nimport { repeat } from 'seemly'\nimport { ref } from 'vue'\n\nfunction createData(level = 4, baseKey = ''): TreeOption[] | undefined {\n  if (!level)\n    return undefined\n  return repeat(6 - level, undefined).map((_, index) => {\n    const key = `${baseKey}${level}${index}`\n    return {\n      label: createLabel(level),\n      key,\n      children: createData(level - 1, key)\n    }\n  })\n}\n\nfunction createLabel(level: number): string {\n  if (level === 4)\n    return '道生一'\n  if (level === 3)\n    return '一生二'\n  if (level === 2)\n    return '二生三'\n  if (level === 1)\n    return '三生万物'\n  return ''\n}\n\nconst data = createData()\nconst defaultExpandedKeys = ref(['40', '41'])\n</script>\n\n<template>\n  <n-tree\n    block-line\n    :data=\"data\"\n    :default-expanded-keys=\"defaultExpandedKeys\"\n    expand-on-click\n    checkable\n  />\n</template>\n"
  },
  {
    "path": "src/tree/demos/zhCN/batch-render.demo.vue",
    "content": "<markdown>\n# 批量渲染\n\n如你所想，前缀、标签、后缀都可以批量渲染\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { TreeOption } from 'naive-ui'\nimport { NButton } from 'naive-ui'\nimport { repeat } from 'seemly'\nimport { h, ref } from 'vue'\n\nfunction createData(level = 4, baseKey = ''): TreeOption[] | undefined {\n  if (!level)\n    return undefined\n  return repeat(6 - level, undefined).map((_, index) => {\n    const key = `${baseKey}${level}${index}`\n    return {\n      label: createLabel(level),\n      key,\n      children: createData(level - 1, key),\n      level\n    }\n  })\n}\n\nfunction createLabel(level: number): string {\n  if (level === 4)\n    return '道生一'\n  if (level === 3)\n    return '一生二'\n  if (level === 2)\n    return '二生三'\n  if (level === 1)\n    return '三生万物'\n  return ''\n}\n\nfunction renderPrefix({ option }: { option: TreeOption }) {\n  return h(\n    NButton,\n    { text: true, type: 'primary' },\n    { default: () => `Prefix-${option.level}` }\n  )\n}\n\nfunction renderLabel({ option }: { option: TreeOption }) {\n  return `${option.label} :)`\n}\n\nfunction renderSuffix({ option }: { option: TreeOption }) {\n  return h(\n    NButton,\n    { text: true, type: 'primary' },\n    { default: () => `Suffix-${option.level}` }\n  )\n}\n\nconst data = createData()\nconst defaultExpandedKeys = ref(['40', '41'])\n</script>\n\n<template>\n  <n-tree\n    block-line\n    :data=\"data\"\n    :default-expanded-keys=\"defaultExpandedKeys\"\n    :render-prefix=\"renderPrefix\"\n    :render-label=\"renderLabel\"\n    :render-suffix=\"renderSuffix\"\n    :selectable=\"false\"\n  />\n</template>\n"
  },
  {
    "path": "src/tree/demos/zhCN/cascade.demo.vue",
    "content": "<markdown>\n# 级联选择\n\n设定 `cascade` 进行级联选择。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { TreeOption } from 'naive-ui'\nimport { repeat } from 'seemly'\nimport { ref } from 'vue'\n\nfunction createData(level = 4, baseKey = ''): TreeOption[] | undefined {\n  if (!level)\n    return undefined\n  return repeat(6 - level, undefined).map((_, index) => {\n    const key = `${baseKey}${level}${index}`\n    return {\n      label: createLabel(level),\n      key,\n      children: createData(level - 1, key)\n    }\n  })\n}\n\nfunction createLabel(level: number): string {\n  if (level === 4)\n    return '道生一'\n  if (level === 3)\n    return '一生二'\n  if (level === 2)\n    return '二生三'\n  if (level === 1)\n    return '三生万物'\n  return ''\n}\n\nconst data = createData()\nconst defaultExpandedKeys = ref(['40', '4030', '403020'])\nconst defaultCheckedKeys = ref(['40302010'])\n\nfunction updateCheckedKeys(\n  keys: Array<string | number>,\n  options: Array<TreeOption | null>,\n  meta: {\n    node: TreeOption | null\n    action: 'check' | 'uncheck'\n  }\n) {\n  console.log('updateCheckedKeys', keys, options, meta)\n}\n</script>\n\n<template>\n  <n-tree\n    block-line\n    cascade\n    checkable\n    :selectable=\"false\"\n    :data=\"data\"\n    :default-expanded-keys=\"defaultExpandedKeys\"\n    :default-checked-keys=\"defaultCheckedKeys\"\n    @update:checked-keys=\"updateCheckedKeys\"\n  />\n</template>\n"
  },
  {
    "path": "src/tree/demos/zhCN/change-debug.demo.vue",
    "content": "<markdown>\n# Change data debug\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { NButton, NTree } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst data = ref([\n  { key: '1', label: '1', children: [{ key: '1-1', label: '1-1' }] },\n  { key: '2', label: '2' }\n])\n\nfunction addChildrenToKey2() {\n  data.value = [\n    { key: '1', label: '1', children: [{ key: '1-1', label: '1-1' }] },\n    { key: '2', label: '2', children: [{ key: '2-1', label: '2-1' }] }\n  ]\n}\n\nfunction moveChildrenOutside() {\n  data.value = [\n    { key: '1', label: '1' },\n    { key: '1-1', label: '1-1' }\n  ]\n}\n</script>\n\n<template>\n  <NTree\n    default-expand-all\n    :data=\"data\"\n    :watch-props=\"['defaultExpandedKeys']\"\n  />\n  <NButton @click=\"addChildrenToKey2\">\n    add children to key 2\n  </NButton>\n  <NButton @click=\"moveChildrenOutside\">\n    move children to top\n  </NButton>\n</template>\n"
  },
  {
    "path": "src/tree/demos/zhCN/check-strategy-debug.demo.vue",
    "content": "<markdown>\n# Check Strategy Debug\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst disabled = ref(false)\nconst cascade = ref(false)\nconst multiple = ref(false)\nconst checkStrategy = ref<'all' | 'child' | 'parent'>('all')\nconst checkable = ref(false)\nconst selectable = ref(false)\nconst checkOnClick = ref(false)\nconst checkedKeys = ref(['Dig It', 'go'])\n\nconst options = [\n  {\n    label: 'Rubber Soul',\n    key: 'Rubber Soul',\n    children: [\n      {\n        label: 'Everybody\\'s Got Something to Hide Except Me and My Monkey',\n        key: 'Everybody\\'s Got Something to Hide Except Me and My Monkey'\n      },\n      {\n        label: 'Drive My Car',\n        key: 'Drive My Car',\n        disabled: true\n      },\n      {\n        label: 'Norwegian Wood',\n        key: 'Norwegian Wood'\n      },\n      {\n        label: 'You Won\\'t See',\n        key: 'You Won\\'t See',\n        disabled: true\n      },\n      {\n        label: 'Nowhere Man',\n        key: 'Nowhere Man',\n        checkboxDisabled: true\n      },\n      {\n        label: 'Think For Yourself',\n        key: 'Think For Yourself'\n      },\n      {\n        label: 'The Word',\n        key: 'The Word'\n      },\n      {\n        label: 'Michelle',\n        key: 'Michelle',\n        disabled: true\n      },\n      {\n        label: 'What goes on',\n        key: 'What goes on'\n      },\n      {\n        label: 'Girl',\n        key: 'Girl'\n      },\n      {\n        label: 'I\\'m looking through you',\n        key: 'I\\'m looking through you'\n      },\n      {\n        label: 'In My Life',\n        key: 'In My Life'\n      },\n      {\n        label: 'Wait',\n        key: 'Wait'\n      }\n    ]\n  },\n  {\n    label: 'Let It Be',\n    key: 'Let It Be Album',\n    children: [\n      {\n        label: 'Two Of Us',\n        key: 'Two Of Us'\n      },\n      {\n        label: 'Dig A Pony',\n        key: 'Dig A Pony'\n      },\n      {\n        label: 'Across The Universe',\n        key: 'Across The Universe',\n        children: [\n          {\n            label: 'Dig It',\n            key: 'Dig It'\n          },\n          {\n            label: 'go',\n            key: 'go'\n          }\n        ]\n      }\n    ]\n  }\n]\n</script>\n\n<template>\n  <n-space vertical>\n    <n-space>\n      <n-radio-group v-model:value=\"checkStrategy\">\n        <n-radio-button value=\"all\">\n          All\n        </n-radio-button>\n        <n-radio-button value=\"parent\">\n          Parent\n        </n-radio-button>\n        <n-radio-button value=\"child\">\n          Child\n        </n-radio-button>\n      </n-radio-group>\n      <n-switch v-model:value=\"checkable\">\n        <template #checked>\n          Checkable\n        </template>\n        <template #unchecked>\n          Unhheckable\n        </template>\n      </n-switch>\n      <n-switch v-model:value=\"selectable\">\n        <template #checked>\n          Selectable\n        </template>\n        <template #unchecked>\n          Unselectable\n        </template>\n      </n-switch>\n      <n-switch v-model:value=\"multiple\">\n        <template #checked>\n          Multiple\n        </template>\n        <template #unchecked>\n          Single\n        </template>\n      </n-switch>\n      <n-switch v-model:value=\"cascade\">\n        <template #checked>\n          Cascade\n        </template>\n        <template #unchecked>\n          Uncascade\n        </template>\n      </n-switch>\n      <n-switch v-model:value=\"disabled\">\n        <template #checked>\n          Disabled\n        </template>\n        <template #unchecked>\n          Enabled\n        </template>\n      </n-switch>\n      <n-switch v-model:value=\"checkOnClick\">\n        <template #checked>\n          CheckOnClick Enabled\n        </template>\n        <template #unchecked>\n          CheckOnClick Disabled\n        </template>\n      </n-switch>\n    </n-space>\n    <n-tree\n      v-model:checked-keys=\"checkedKeys\"\n      default-expand-all\n      :disabled=\"disabled\"\n      :selectable=\"selectable\"\n      :multiple=\"multiple\"\n      :cascade=\"cascade\"\n      :checkable=\"checkable\"\n      :check-on-click=\"checkOnClick\"\n      :check-strategy=\"checkStrategy\"\n      :data=\"options\"\n    />\n  </n-space>\n  {{ JSON.stringify(checkedKeys) }}\n</template>\n"
  },
  {
    "path": "src/tree/demos/zhCN/checkbox-placement.demo.vue",
    "content": "<markdown>\n# 复选框位置\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { TreeOption } from 'naive-ui'\nimport { repeat } from 'seemly'\nimport { ref } from 'vue'\n\nfunction createData(level = 4, baseKey = ''): TreeOption[] | undefined {\n  if (!level)\n    return undefined\n  return repeat(6 - level, undefined).map((_, index) => {\n    const key = `${baseKey}${level}${index}`\n    return {\n      label: createLabel(level),\n      key,\n      children: createData(level - 1, key)\n    }\n  })\n}\n\nfunction createLabel(level: number): string {\n  if (level === 4)\n    return '道生一'\n  if (level === 3)\n    return '一生二'\n  if (level === 2)\n    return '二生三'\n  if (level === 1)\n    return '三生万物'\n  return ''\n}\n\nconst data = createData()\nconst defaultExpandedKeys = ref(['40', '4030', '403020'])\nconst defaultCheckedKeys = ref(['40302010'])\n\nfunction updateCheckedKeys(v: string[]) {\n  console.log('updateCheckedKeys', v)\n}\n</script>\n\n<template>\n  <n-tree\n    checkable\n    block-node\n    checkbox-placement=\"right\"\n    :data=\"data\"\n    :default-expanded-keys=\"defaultExpandedKeys\"\n    :default-checked-keys=\"defaultCheckedKeys\"\n    @update:checked-keys=\"updateCheckedKeys\"\n  />\n</template>\n"
  },
  {
    "path": "src/tree/demos/zhCN/custom-field.demo.vue",
    "content": "<markdown>\n# 自定义 key 和 label 的字段\n\n后端会传来各种各样的数据。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { TreeOption } from 'naive-ui'\nimport { repeat } from 'seemly'\nimport { ref } from 'vue'\n\nfunction createData(level = 4, baseKey = ''): TreeOption[] | undefined {\n  if (!level)\n    return undefined\n  return repeat(6 - level, undefined).map((_, index) => {\n    const key = `${baseKey}${level}${index}`\n    return {\n      whateverLabel: createLabel(level),\n      whateverKey: key,\n      whateverChildren: createData(level - 1, key)\n    }\n  })\n}\n\nfunction createLabel(level: number): string {\n  if (level === 4)\n    return '道生一'\n  if (level === 3)\n    return '一生二'\n  if (level === 2)\n    return '二生三'\n  if (level === 1)\n    return '三生万物'\n  return ''\n}\n\nconst data = createData()\nconst defaultExpandedKeys = ref(['40', '41'])\n</script>\n\n<template>\n  <n-tree\n    block-line\n    :data=\"data\"\n    :default-expanded-keys=\"defaultExpandedKeys\"\n    key-field=\"whateverKey\"\n    label-field=\"whateverLabel\"\n    children-field=\"whateverChildren\"\n    selectable\n  />\n</template>\n"
  },
  {
    "path": "src/tree/demos/zhCN/disabled.demo.vue",
    "content": "<markdown>\n# 禁用节点\n</markdown>\n\n<script lang=\"ts\" setup>\nconst data = [\n  {\n    key: '0',\n    label: '0',\n    children: [\n      {\n        key: '0-0',\n        label: '0-0'\n      },\n      {\n        disabled: true,\n        key: '0-1',\n        label: '0-1',\n        children: [\n          {\n            label: '0-1-0',\n            key: '0-1-0'\n          },\n          {\n            label: '0-1-1',\n            key: '0-1-1'\n          }\n        ]\n      }\n    ]\n  },\n  {\n    key: '1',\n    label: '1',\n    children: [\n      {\n        key: '1-0',\n        label: '1-0'\n      },\n      {\n        checkboxDisabled: true,\n        key: '1-1',\n        label: '1-1',\n        children: [\n          {\n            label: '1-1-0',\n            key: '1-1-0'\n          },\n          {\n            label: '1-1-1',\n            key: '1-1-1'\n          }\n        ]\n      }\n    ]\n  }\n]\n</script>\n\n<template>\n  <n-tree\n    :data=\"data\"\n    block-line\n    checkable\n    default-expand-all\n    cascade\n    :default-checked-keys=\"['1-1']\"\n  />\n</template>\n"
  },
  {
    "path": "src/tree/demos/zhCN/drag-drop.demo.vue",
    "content": "<markdown>\n# 拖放节点\n\n设定 `draggable` 然后自己写一堆代码来支持节点的拖放。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { TreeDropInfo, TreeOption } from 'naive-ui'\nimport { repeat } from 'seemly'\nimport { ref } from 'vue'\n\nfunction createData(level = 4, baseKey = ''): TreeOption[] | undefined {\n  if (!level)\n    return undefined\n  return repeat(6 - level, undefined).map((_, index) => {\n    const key = `${baseKey}${level}${index}`\n    return {\n      label: createLabel(level),\n      key,\n      children: createData(level - 1, key)\n    }\n  })\n}\n\nfunction createLabel(level: number): string {\n  if (level === 4)\n    return '道生一'\n  if (level === 3)\n    return '一生二'\n  if (level === 2)\n    return '二生三'\n  if (level === 1)\n    return '三生万物'\n  return ''\n}\n\nfunction findSiblingsAndIndex(\n  node: TreeOption,\n  nodes?: TreeOption[]\n): [TreeOption[], number] | [null, null] {\n  if (!nodes)\n    return [null, null]\n  for (let i = 0; i < nodes.length; ++i) {\n    const siblingNode = nodes[i]\n    if (siblingNode.key === node.key)\n      return [nodes, i]\n    const [siblings, index] = findSiblingsAndIndex(node, siblingNode.children)\n    if (siblings && index !== null)\n      return [siblings, index]\n  }\n  return [null, null]\n}\n\n/**\n * 这个例子的时间复杂度确实可以优化 我实在是懒得改了\n */\nconst expandedKeysRef = ref<string[]>([])\nconst checkedKeysRef = ref<string[]>([])\nconst dataRef = ref(createData() || [])\n\nfunction handleExpandedKeysChange(expandedKeys: string[]) {\n  expandedKeysRef.value = expandedKeys\n}\n\nfunction handleCheckedKeysChange(checkedKeys: string[]) {\n  checkedKeysRef.value = checkedKeys\n}\n\nfunction handleDrop({ node, dragNode, dropPosition }: TreeDropInfo) {\n  const [dragNodeSiblings, dragNodeIndex] = findSiblingsAndIndex(\n    dragNode,\n    dataRef.value\n  )\n  if (dragNodeSiblings === null || dragNodeIndex === null)\n    return\n  dragNodeSiblings.splice(dragNodeIndex, 1)\n  if (dropPosition === 'inside') {\n    if (node.children) {\n      node.children.unshift(dragNode)\n    }\n    else {\n      node.children = [dragNode]\n    }\n  }\n  else if (dropPosition === 'before') {\n    const [nodeSiblings, nodeIndex] = findSiblingsAndIndex(node, dataRef.value)\n    if (nodeSiblings === null || nodeIndex === null)\n      return\n    nodeSiblings.splice(nodeIndex, 0, dragNode)\n  }\n  else if (dropPosition === 'after') {\n    const [nodeSiblings, nodeIndex] = findSiblingsAndIndex(node, dataRef.value)\n    if (nodeSiblings === null || nodeIndex === null)\n      return\n    nodeSiblings.splice(nodeIndex + 1, 0, dragNode)\n  }\n  dataRef.value = Array.from(dataRef.value)\n}\n</script>\n\n<template>\n  <n-tree\n    block-line\n    checkable\n    draggable\n    :data=\"dataRef\"\n    :checked-keys=\"checkedKeysRef\"\n    :expanded-keys=\"expandedKeysRef\"\n    @drop=\"handleDrop\"\n    @update:checked-keys=\"handleCheckedKeysChange\"\n    @update:expanded-keys=\"handleExpandedKeysChange\"\n  />\n</template>\n"
  },
  {
    "path": "src/tree/demos/zhCN/ellipsis.demo.vue",
    "content": "<markdown>\n# 省略\n\n有时候节点的文本会很长，可以使用 `ellipsis` 来省略文本。\n</markdown>\n\n<script lang=\"ts\">\nimport type { TreeOption } from 'naive-ui'\nimport { repeat } from 'seemly'\nimport { defineComponent, ref } from 'vue'\n\nfunction createData(level = 4, baseKey = ''): TreeOption[] | undefined {\n  if (!level)\n    return undefined\n  return repeat(6 - level, undefined).map((_, index) => {\n    const key = `${baseKey}${level}${index}`\n    const label = createLabel(level)\n    return {\n      label,\n      key,\n      children: createData(level - 1, key)\n    }\n  })\n}\n\nfunction createLabel(level: number): string {\n  if (level === 4)\n    return '站在能分割世界的桥 还是看不清 在那些时刻 遮蔽我们 黑暗的心 究竟是什么'\n  if (level === 3)\n    return '住在我心里孤独的 孤独的海怪 痛苦之王 开始厌倦 深海的光 停滞的海浪 你的心里 有没有一点点想念我'\n  if (level === 2)\n    return '站在能看到灯火的桥 还是看不清 在那些夜晚 照亮我们 黑暗的心 究竟是什么'\n  if (level === 1)\n    return '于是他默默追逐着 横渡海峡 年轻的人 看着他们 为了彼岸 骄傲的 骄傲的 灭亡'\n  return ''\n}\n\nexport default defineComponent({\n  setup() {\n    return {\n      data: createData(),\n      defaultExpandedKeys: ref(['40', '41'])\n    }\n  }\n})\n</script>\n\n<template>\n  <n-tree\n    ellipsis\n    :data=\"data\"\n    :default-expanded-keys=\"defaultExpandedKeys\"\n    :selectable=\"false\"\n  />\n</template>\n"
  },
  {
    "path": "src/tree/demos/zhCN/expand-debug.demo.vue",
    "content": "<markdown>\n# Expand debug\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst expandedKeys = ref<string[]>([])\n\nconst data = [\n  {\n    key: 'node-root',\n    label: '根节点',\n    children: [\n      { key: 'node-1', label: '节点1' },\n      { key: 'node-2', label: '节点2' }\n    ]\n  }\n]\n\nfunction onSelect(keys: string[]) {\n  expandedKeys.value.push(keys[0])\n}\n</script>\n\n<template>\n  <n-tree\n    v-model:expanded-keys=\"expandedKeys\"\n    block-line\n    :data=\"data\"\n    selectable\n    @update:selected-keys=\"onSelect\"\n  />\n</template>\n"
  },
  {
    "path": "src/tree/demos/zhCN/file-tree.demo.vue",
    "content": "<markdown>\n# 文件树\n\n使用 `on-update:expanded-keys` 来更改节点在不同状态下的前缀图标样式。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { TreeOption } from 'naive-ui'\nimport {\n  FileTrayFullOutline,\n  Folder,\n  FolderOpenOutline\n} from '@vicons/ionicons5'\nimport { NIcon, useMessage } from 'naive-ui'\nimport { h } from 'vue'\n\nconst message = useMessage()\n\nfunction updatePrefixWithExpaned(\n  _keys: Array<string | number>,\n  _option: Array<TreeOption | null>,\n  meta: {\n    node: TreeOption | null\n    action: 'expand' | 'collapse' | 'filter'\n  }\n) {\n  if (!meta.node)\n    return\n  switch (meta.action) {\n    case 'expand':\n      meta.node.prefix = () =>\n        h(NIcon, null, {\n          default: () => h(FolderOpenOutline)\n        })\n      break\n    case 'collapse':\n      meta.node.prefix = () =>\n        h(NIcon, null, {\n          default: () => h(Folder)\n        })\n      break\n  }\n}\n\nfunction nodeProps({ option }: { option: TreeOption }) {\n  return {\n    onClick() {\n      if (!option.children && !option.disabled) {\n        message.info(`[Click] ${option.label}`)\n      }\n    }\n  }\n}\n\nconst data = [\n  {\n    key: '文件夹',\n    label: '文件夹',\n    prefix: () =>\n      h(NIcon, null, {\n        default: () => h(Folder)\n      }),\n    children: [\n      {\n        key: '空的',\n        label: '空的',\n        disabled: true,\n        prefix: () =>\n          h(NIcon, null, {\n            default: () => h(Folder)\n          })\n      },\n      {\n        key: '我的文件',\n        label: '我的文件',\n        prefix: () =>\n          h(NIcon, null, {\n            default: () => h(Folder)\n          }),\n        children: [\n          {\n            label: 'template.txt',\n            key: 'template.txt',\n            prefix: () =>\n              h(NIcon, null, {\n                default: () => h(FileTrayFullOutline)\n              })\n          }\n        ]\n      }\n    ]\n  }\n]\n</script>\n\n<template>\n  <n-tree\n    block-line\n    expand-on-click\n    :data=\"data\"\n    :node-props=\"nodeProps\"\n    :on-update:expanded-keys=\"updatePrefixWithExpaned\"\n  />\n</template>\n"
  },
  {
    "path": "src/tree/demos/zhCN/filter.demo.vue",
    "content": "<markdown>\n# 搜索\n\n树接受 `pattern` 和 `filter` 来完成搜索。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { TreeOption } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst data: TreeOption[] = [\n  {\n    label: '0',\n    key: '0',\n    children: [\n      {\n        label: '0-0',\n        key: '0-0',\n        children: [\n          { label: '0-0-0', key: '0-0-0' },\n          { label: '0-0-1', key: '0-0-1' }\n        ]\n      },\n      {\n        label: '0-1',\n        key: '0-1',\n        children: [\n          { label: '0-1-0', key: '0-1-0' },\n          { label: '0-1-1', key: '0-1-1' }\n        ]\n      }\n    ]\n  },\n  {\n    label: '1',\n    key: '1',\n    children: [\n      {\n        label: '1-0',\n        key: '1-0',\n        children: [\n          { label: '1-0-0', key: '1-0-0' },\n          { label: '1-0-1', key: '1-0-1' }\n        ]\n      },\n      {\n        label: '1-1',\n        key: '1-1',\n        children: [\n          { label: '1-1-0', key: '1-1-0' },\n          { label: '1-1-1', key: '1-1-1' }\n        ]\n      }\n    ]\n  }\n]\n\nconst pattern = ref('')\nconst showIrrelevantNodes = ref(false)\n</script>\n\n<template>\n  <n-space vertical :size=\"12\">\n    <n-input v-model:value=\"pattern\" placeholder=\"搜索\" />\n    <n-switch v-model:value=\"showIrrelevantNodes\">\n      <template #checked>\n        展示搜索无关的节点\n      </template>\n      <template #unchecked>\n        隐藏搜索无关的节点\n      </template>\n    </n-switch>\n    <n-tree\n      :show-irrelevant-nodes=\"showIrrelevantNodes\"\n      :pattern=\"pattern\"\n      :data=\"data\"\n      block-line\n    />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/tree/demos/zhCN/index.demo-entry.md",
    "content": "# 树 Tree\n\n老实说我生物不好，认不出几种树来。\n\n以及，不光是生物不好，平衡树也是看了就忘。\n\n## 演示\n\n```demo\nbasic.vue\ncustom-field.vue\nmultiple.vue\ncascade.vue\nfilter.vue\ndrag-drop.vue\nvirtual.vue\nasync.vue\ndisabled.vue\nprefix-and-suffix.vue\nbatch-render.vue\nswitcher-icon.vue\nfile-tree.vue\nnode-props.vue\nshow-line.vue\ncheckbox-placement.vue\noverride-click-behavior.vue\ncheck-strategy-debug.vue\nchange-debug.vue\nscrollbar-debug.vue\nscroll-debug.vue\nrtl-debug.vue\nexpand-debug.vue\n```\n\n## API\n\n### Tree Props\n\n| 名称 | 类型 | 默认值 | 说明 | 版本 |\n| --- | --- | --- | --- | --- |\n| accordion | `boolean` | `false` | 是否使用手风琴展开模式 | 2.31.0 |\n| allow-checking-not-loaded | `boolean` | `false` | 是否允许级联勾选还没有完全加载的节点。如果你要用这个属性，请记住 `checked-keys` 可能是不完整的，并且请注意勾选行为和后端计算逻辑的一致性，尤其是有禁用节点的情况下 | 2.28.1 |\n| allow-drop | `(info: { dropPosition: DropPosition, node: TreeOption, phase: 'drag' \\| 'drop' }) => boolean` | 一个不允许 drop 在叶节点内部的函数 | 是否允许 drop |  |\n| animated | `boolean` | `true` | 是否有展开动画 | 2.33.4 |\n| block-line | `boolean` | `false` | 节点整行撑开 |  |\n| block-node | `boolean` | `false` | 节点名称整行撑开 |  |\n| cancelable | `boolean` | `true` | 选中之后是否允许取消 |  |\n| cascade | `boolean` | `false` | 是否关联选项 |  |\n| check-strategy | `string` | `'all'` | 设置勾选策略来指定勾选回调返回的值，`all` 表示回调函数值为全部选中节点；`parent` 表示回调函数值为父节点（当父节点下所有子节点都选中时）；`child` 表示回调函数值为子节点 |  |\n| checkable | `boolean` | `false` | 是否显示选择框 |  |\n| checkbox-placement | `'left' \\| 'right'` | `'left'` | 复选框的位置 | 2.28.3 |\n| children-field | `string` | `'children'` | 替代 `TreeOption` 中的 children 字段名 |  |\n| checked-keys | `Array<string \\| number>` | `undefined` | 如果设定则 `checked` 状态受控 |  |\n| check-on-click | `boolean \\| ((node: TreeOption) => boolean)` | `false` | 是否允许点击节点进行勾选，仅在 `checkable` 为 `true` 时生效 | 2.31.0 |\n| data | `Array<TreeOption>` | `[]` | 树的节点数据。重新设置 `data` 会将一些非受控状态清空，如果你需要在使用中改动 `data`，最好以受控的方式控制树 |  |\n| default-checked-keys | `Array<string \\| number>` | `[]` | 默认选中的多选项 |  |\n| default-expand-all | `boolean` | `false` | 展开全部选项 |  |\n| default-expanded-keys | `Array<string \\| number>` | `[]` | 默认展开项 |  |\n| default-selected-keys | `Array<string \\| number>` | `[]` | 默认选中的节点 |  |\n| draggable | `boolean` | `false` | 是否可拖拽 |  |\n| ellipsis | `boolean` | `false` | 是否省略超出宽度的文本 | 2.43.0 |\n| expand-on-dragenter | `boolean` | `true` | 是否在拖入后展开节点 |  |\n| expand-on-click | `boolean` | `false` | 是否在点击节点后展开或收缩节点 | 2.29.1 |\n| expanded-keys | `Array<string \\| number>` | `undefined` | 如果设定则展开受控 |  |\n| filter | `(pattern: string, node: TreeOption) => boolean` | 一个简单的字符串过滤算法 | 基于 pattern 指定过滤节点的函数 |  |\n| get-children | `(option: any) => unknown` | `undefined` | 获取当前选项的子选项 | 2.34.3 |\n| indent | `number` | `24` | 树的每一级缩进的大小 | 2.9.0 |\n| indeterminate-keys | `Array<string \\| number>` | `undefined` | 部分选中选项的 key |  |\n| keyboard | `boolean` | `true` | 是否支持键盘操作 | 2.32.2 |\n| key-field | `string` | `'key'` | 替代 `TreeOption` 中的 key 字段名 |  |\n| label-field | `string` | `'label'` | 替代 `TreeOption` 中的 label 字段名 |  |\n| disabled-field | `string` | `'disabled'` | 替代 `TreeOption` 中的 disabled 字段名 | 2.32.2 |\n| node-props | `(info: { option: TreeOption }) => HTMLAttributes` | `undefined` | 节点的 HTML 属性 | 2.25.0 |\n| multiple | `boolean` | `false` | 是否允许节点多选 |  |\n| on-load | `(node: TreeOption) => Promise<unknown>` | `undefined` | 异步加载数据的回调函数，如果没有加载到数据你应该让 Promise resolve `false` 或者 reject 这个 Promise，否则加载动画不会停止 | 非 void Promise 2.34.3 |\n| override-default-node-click-behavior | `(info: { option: TreeOption }) => 'toggleExpand' \\| 'toggleSelect' \\| 'toggleCheck' \\| 'default' \\| 'none'` | `undefined` | 覆盖默认的节点点击行为 | 2.37.0 |\n| pattern | `string` | `''` | 默认搜索的内容 |  |\n| render-label | `(info: { option: TreeOption, checked: boolean, selected: boolean }) => VNodeChild` | `undefined` | 节点内容的渲染函数 |  |\n| render-prefix | `(info: { option: TreeOption, checked: boolean, selected: boolean }) => VNodeChild` | `undefined` | 节点前缀的渲染函数 |  |\n| render-suffix | `(info: { option: TreeOption, checked: boolean, selected: boolean }) => VNodeChild` | `undefined` | 节点后缀的渲染函数 |  |\n| render-switcher-icon | `(props: { option: TreeOption, expanded: boolean, selected: boolean }) => VNodeChild` | `undefined` | 节点展开开关的渲染函数 | 2.24.0, `props` 2.34.0 |\n| scrollbar-props | `ScrollbarProps` | `undefined` | 属性参考 [Scrollbar props](scrollbar#Scrollbar-Props) |  |\n| selectable | `boolean` | `true` | 节点是否可以被选中 |  |\n| selected-keys | `Array<string \\| number>` | `undefined` | 如果设定则 `selected` 状态受控 |  |\n| show-irrelevant-nodes | `boolean` | `true` | 是否在搜索状态显示和搜索无关的节点 | 2.28.1 |\n| show-line | `boolean` | `false` | 是否显示连接线 | 2.35.0 |\n| spin-props | `{ strokeWidth?: number, stroke?: string, scale?: number, radius?: number }` | `undefined` | 加载图标的属性 | 2.44.0 |\n| virtual-scroll | `boolean` | `false` | 是否启用虚拟滚动，启用前你需要设定好树的高度样式 |  |\n| watch-props | `Array<'defaultCheckedKeys' \\| 'defaultSelectedKeys' \\|'defaultExpandedKeys'>` | `undefined` | 需要检测变更的默认属性，检测后组件状态会更新。注意：`watch-props` 本身不是响应式的 |  |\n| on-dragend | `(data: { node: TreeOption, event: DragEvent }) => void` | `undefined` | 节点完成拖拽动作后的回调函数 |  |\n| on-dragenter | `(data: { node: TreeOption, event: DragEvent }) => void` | `undefined` | 节点拖拽中的回调函数 |  |\n| on-dragleave | `(data: { node: TreeOption, event: DragEvent }) => void` | `undefined` | 拖拽一个节点，该节点离开其它节点后的回调函数 |  |\n| on-dragstart | `(data: { node: TreeOption, event: DragEvent }) => void` | `undefined` | 开始拖拽某一个节点的回调函数 |  |\n| on-drop | `(data: { node: TreeOption, dragNode: TreeOption, dropPosition: 'before' \\| 'inside' \\| 'after', event: DragEvent }) => void` | `undefined` | 节点完成拖拽动作后的回调函数 |  |\n| on-update:checked-keys | `(keys: Array<string \\| number>, option: Array<TreeOption \\| null>, meta: { node: TreeOption \\| null, action: 'check' \\| 'uncheck' }) => void` | `undefined` | 节点勾选项发生变化时的回调函数 | `meta` 2.34.0 |\n| on-update:indeterminate-keys | `(keys: Array<string \\| number>, option: Array<TreeOption \\| null>) => void` | `undefined` | 节点部分勾选项发生变化时的回调函数 |  |\n| on-update:expanded-keys | `(keys: Array<string \\| number>, option: Array<TreeOption \\| null>, meta: { node: TreeOption \\| null, action: 'expand' \\| 'collapse' \\| 'filter' }) => void` | `undefined` | 节点展开项发生变化时的回调函数 | `meta` 2.34.0 |\n| on-update:selected-keys | `(keys: Array<string \\| number>, option: Array<TreeOption \\| null>, meta: { node: TreeOption \\| null, action: 'select' \\| 'unselect' }) => void` | `undefined` | 节点选中项发生变化时的回调函数 | `meta` 2.34.0 |\n\n### TreeOption Properties\n\n| 名称 | 类型 | 说明 |\n| --- | --- | --- |\n| key | `string \\| number` | 节点的 `key`，需要唯一，可使用 `key-field` 修改字段名 |\n| label | `string` | 节点的内容，可使用 `label-field` 修改字段名 |\n| checkboxDisabled? | `boolean` | 是否禁用节点的 `checkbox` |\n| children? | `TreeOption[]` | 节点的子节点 |\n| disabled? | `boolean` | 是否禁用节点 |\n| isLeaf? | `boolean` | 节点是否是叶节点，在异步展开状态下是必须的 |\n| prefix? | `string \\| (() => VNodeChild)` | 节点的前缀 |\n| suffix? | `string \\| (() => VNodeChild)` | 节点的后缀 |\n\n### Tree Slots\n\n| 名称  | 参数 | 描述                  | 版本 |\n| ----- | ---- | --------------------- | ---- |\n| empty | `()` | 树组件无数据时的 slot |      |\n\n### Tree Methods\n\n| 名称 | 参数 | 说明 | 版本 |\n| --- | --- | --- | --- |\n| scrollTo | `ScrollTo` | 在虚拟滚动模式下滚动到某个节点 | 2.32.2 |\n| getCheckedData | `() => { keys: Array<string \\| number>, options: Array<TreeOption \\| null> }` | 获取选中的数据 | 2.34.1 |\n| getIndeterminateData | `() => { keys: Array<string \\| number>, options: Array<TreeOption \\| null> }` | 获取半选的数据 | 2.34.1 |\n\n#### ScrollTo Type\n\n```ts\ninterface ScrollTo {\n  (x: number, y: number): void\n  (options: { left?: number, top?: number, debounce?: boolean }): void\n  (options: { index: number, debounce?: boolean }): void\n  (options: { key: string | number, debounce?: boolean }): void\n  (options: { position: 'top' | 'bottom', debounce?: boolean }): void\n}\n```\n\n### Others\n\n1. `treeGetClickTarget: (e: MouseEvent) => ('checkbox' | 'switcher' | 'node')`：获取点击位置，可以用于 `nodeProps.onClick`。你可以直接从 `naive-ui` 这个包 import 此函数\n"
  },
  {
    "path": "src/tree/demos/zhCN/multiple.demo.vue",
    "content": "<markdown>\n# 多选节点\n\n设置 `multiple` 来允许多选节点。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { TreeOption } from 'naive-ui'\nimport { repeat } from 'seemly'\nimport { ref } from 'vue'\n\nfunction createData(level = 4, baseKey = ''): TreeOption[] | undefined {\n  if (!level)\n    return undefined\n  return repeat(6 - level, undefined).map((_, index) => {\n    const key = `${baseKey}${level}${index}`\n    return {\n      label: createLabel(level),\n      key,\n      children: createData(level - 1, key)\n    }\n  })\n}\n\nfunction createLabel(level: number): string {\n  if (level === 4)\n    return '道生一'\n  if (level === 3)\n    return '一生二'\n  if (level === 2)\n    return '二生三'\n  if (level === 1)\n    return '三生万物'\n  return ''\n}\n\nconst data = createData()\nconst value = ref([])\n</script>\n\n<template>\n  <n-tree multiple block-line :data=\"data\" />\n  <n-divider />\n  <n-tree v-model:selected-keys=\"value\" multiple block-line :data=\"data\" />\n</template>\n"
  },
  {
    "path": "src/tree/demos/zhCN/node-props.demo.vue",
    "content": "<markdown>\n# 为节点绑定事件\n\n使用 `node-props` 为节点绑定属性，比如点击事件或者右键菜单。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { DropdownOption, TreeOption } from 'naive-ui'\nimport { useMessage } from 'naive-ui'\nimport { repeat } from 'seemly'\nimport { ref } from 'vue'\n\nfunction createData(level = 4, baseKey = ''): TreeOption[] | undefined {\n  if (!level)\n    return undefined\n  return repeat(6 - level, undefined).map((_, index) => {\n    const key = `${baseKey}${level}${index}`\n    return {\n      label: createLabel(level),\n      key,\n      children: createData(level - 1, key)\n    }\n  })\n}\n\nfunction createLabel(level: number): string {\n  if (level === 4)\n    return '道生一'\n  if (level === 3)\n    return '一生二'\n  if (level === 2)\n    return '二生三'\n  if (level === 1)\n    return '三生万物'\n  return ''\n}\n\nconst message = useMessage()\nconst showDropdownRef = ref(false)\nconst optionsRef = ref<DropdownOption[]>([])\nconst xRef = ref(0)\nconst yRef = ref(0)\nconst data = createData()\nconst defaultExpandedKeys = ref(['40', '41'])\n\nfunction handleSelect() {\n  showDropdownRef.value = false\n}\n\nfunction handleClickoutside() {\n  showDropdownRef.value = false\n}\n\nfunction nodeProps({ option }: { option: TreeOption }) {\n  return {\n    onClick() {\n      message.info(`[Click] ${option.label}`)\n    },\n    onContextmenu(e: MouseEvent): void {\n      optionsRef.value = [option]\n      showDropdownRef.value = true\n      xRef.value = e.clientX\n      yRef.value = e.clientY\n      console.log(e.clientX, e.clientY)\n      e.preventDefault()\n    }\n  }\n}\n</script>\n\n<template>\n  <n-tree\n    block-line\n    :data=\"data\"\n    :default-expanded-keys=\"defaultExpandedKeys\"\n    :node-props=\"nodeProps\"\n  />\n  <n-dropdown\n    trigger=\"manual\"\n    placement=\"bottom-start\"\n    :show=\"showDropdownRef\"\n    :options=\"optionsRef as any\"\n    :x=\"xRef\"\n    :y=\"yRef\"\n    @select=\"handleSelect\"\n    @clickoutside=\"handleClickoutside\"\n  />\n</template>\n"
  },
  {
    "path": "src/tree/demos/zhCN/override-click-behavior.demo.vue",
    "content": "<markdown>\n# 自定义点击后的行为\n\n你可以利用 `override-default-node-click-behavior` 属性来覆盖默认的点击行为。\n\n例如下面的例子中，你可以使非根节点的点击行为变成展开，来模拟仅允许选中文件、而不允许选中文件夹的行为。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { TreeOverrideNodeClickBehavior } from 'naive-ui'\n\nconst override: TreeOverrideNodeClickBehavior = ({ option }) => {\n  if (option.children) {\n    return 'toggleExpand'\n  }\n  return 'default'\n}\n\nconst options = [\n  {\n    label: 'Folder-1',\n    key: 'Folder-1',\n    children: [\n      {\n        label: 'File-1-1',\n        key: 'File-1-1'\n      },\n      {\n        label: 'Folder-1-2',\n        key: 'Folder-1-2',\n        children: [\n          {\n            label: 'File-1-2-1',\n            key: 'File-1-2-1'\n          },\n          {\n            label: 'File-1-2-2',\n            key: 'File-1-2-2'\n          }\n        ]\n      }\n    ]\n  },\n  {\n    label: 'Folder-2',\n    key: 'Folder-2',\n    children: [\n      {\n        label: 'File-2-1',\n        key: 'File-2-1'\n      },\n      {\n        label: 'File-2-2',\n        key: 'File-2-2'\n      }\n    ]\n  }\n]\n</script>\n\n<template>\n  <n-tree\n    block-line\n    :data=\"options\"\n    :override-default-node-click-behavior=\"override\"\n  />\n</template>\n"
  },
  {
    "path": "src/tree/demos/zhCN/prefix-and-suffix.demo.vue",
    "content": "<markdown>\n# 前缀与后缀\n\n放一些操作。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { TreeOption } from 'naive-ui'\nimport { NButton } from 'naive-ui'\nimport { repeat } from 'seemly'\nimport { h, ref } from 'vue'\n\nfunction createData(level = 4, baseKey = ''): TreeOption[] | undefined {\n  if (!level)\n    return undefined\n  return repeat(6 - level, undefined).map((_, index) => {\n    const key = `${baseKey}${level}${index}`\n    const label = createLabel(level)\n    return {\n      label,\n      key,\n      children: createData(level - 1, key),\n      suffix: () =>\n        h(\n          NButton,\n          { text: true, type: 'primary' },\n          { default: () => 'Suffix' }\n        ),\n      prefix: () =>\n        h(NButton, { text: true, type: 'primary' }, { default: () => 'Prefix' })\n    }\n  })\n}\n\nfunction createLabel(level: number): string {\n  if (level === 4)\n    return '道生一'\n  if (level === 3)\n    return '一生二'\n  if (level === 2)\n    return '二生三'\n  if (level === 1)\n    return '三生万物'\n  return ''\n}\n\nconst data = createData()\nconst defaultExpandedKeys = ref(['40', '41'])\n</script>\n\n<template>\n  <n-tree\n    block-line\n    :data=\"data\"\n    :default-expanded-keys=\"defaultExpandedKeys\"\n    :selectable=\"false\"\n  />\n</template>\n"
  },
  {
    "path": "src/tree/demos/zhCN/rtl-debug.demo.vue",
    "content": "<markdown>\n# Rtl Debug\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { TreeOption } from 'naive-ui'\nimport { unstableTreeRtl } from 'naive-ui'\nimport { repeat } from 'seemly'\nimport { ref } from 'vue'\n\nfunction createData(level = 4, baseKey = ''): TreeOption[] | undefined {\n  if (!level)\n    return undefined\n  return repeat(6 - level, undefined).map((_, index) => {\n    const key = `${baseKey}${level}${index}`\n    return {\n      label: createLabel(level),\n      key,\n      children: createData(level - 1, key)\n    }\n  })\n}\n\nfunction createLabel(level: number): string {\n  if (level === 4)\n    return '道生一'\n  if (level === 3)\n    return '一生二'\n  if (level === 2)\n    return '二生三'\n  if (level === 1)\n    return '三生万物'\n  return ''\n}\n\nconst rtlEnabled = ref(false)\nconst rtlStyles = [unstableTreeRtl]\nconst data = createData()\nconst defaultExpandedKeys = ref(['40', '41'])\n</script>\n\n<template>\n  <n-space vertical>\n    <n-space><n-switch v-model:value=\"rtlEnabled\" />Rtl</n-space>\n    <n-config-provider :rtl=\"rtlEnabled ? rtlStyles : undefined\">\n      <n-tree\n        block-line\n        :data=\"data\"\n        :default-expanded-keys=\"defaultExpandedKeys\"\n        checkable\n        expand-on-click\n        selectable\n      />\n    </n-config-provider>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/tree/demos/zhCN/scroll-debug.demo.vue",
    "content": "<markdown>\n# Scroll debug\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { TreeOption } from 'naive-ui'\nimport { NScrollbar, NTree } from 'naive-ui'\n\nfunction createData(level = 10): TreeOption[] {\n  if (!level)\n    return []\n  return [\n    {\n      label: 'foooooooooooooooooo',\n      key: `node-${level}`,\n      children: createData(level - 1)\n    }\n  ]\n}\n\nconst data = createData()\n</script>\n\n<template>\n  <div>\n    <NScrollbar x-scrollable style=\"width: 100px; height: 150px\">\n      <NTree\n        default-expand-all\n        style=\"white-space: nowrap\"\n        block-line\n        :data=\"data\"\n      />\n    </NScrollbar>\n    <NScrollbar x-scrollable style=\"width: 300px; height: 150px\">\n      <NTree\n        default-expand-all\n        style=\"white-space: nowrap\"\n        block-line\n        :data=\"data\"\n      />\n    </NScrollbar>\n    <NTree default-expand-all style=\"\" block-line :data=\"data\" />\n  </div>\n</template>\n"
  },
  {
    "path": "src/tree/demos/zhCN/scrollbar-debug.demo.vue",
    "content": "<markdown>\n# Scrollbar debug\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { TreeOption } from 'naive-ui'\nimport { repeat } from 'seemly'\n\nfunction createData(level = 4, baseKey = ''): TreeOption[] | undefined {\n  if (!level)\n    return undefined\n  return repeat(5 - level, undefined).map((_, index) => {\n    const key = `${baseKey}${level}${index}`\n    return {\n      label: createLabel(level),\n      key,\n      children: createData(level - 1, key)\n    }\n  })\n}\n\nfunction createLabel(level: number): string {\n  if (level === 4)\n    return '道生一'\n  if (level === 3)\n    return '一生二'\n  if (level === 2)\n    return '二生三'\n  if (level === 1)\n    return '三生万物'\n  return ''\n}\n\nconst data = createData()\n</script>\n\n<template>\n  <n-tree\n    block-line\n    :data=\"data\"\n    default-expand-all\n    virtual-scroll\n    style=\"height: 320px; background-color: #cce3db\"\n  />\n</template>\n"
  },
  {
    "path": "src/tree/demos/zhCN/show-line.demo.vue",
    "content": "<markdown>\n  # 连接线\n  </markdown>\n\n<script lang=\"ts\" setup>\nimport type { TreeOption } from 'naive-ui'\nimport { repeat } from 'seemly'\nimport { ref } from 'vue'\n\nfunction createData(level = 4, baseKey = ''): TreeOption[] | undefined {\n  if (!level)\n    return undefined\n  return repeat(6 - level, undefined).map((_, index) => {\n    const key = `${baseKey}${level}${index}`\n    return {\n      label: createLabel(level),\n      key,\n      children: createData(level - 1, key)\n    }\n  })\n}\n\nfunction createLabel(level: number): string {\n  if (level === 4)\n    return '道生一'\n  if (level === 3)\n    return '一生二'\n  if (level === 2)\n    return '二生三'\n  if (level === 1)\n    return '三生万物'\n  return ''\n}\n\nconst showLine = ref(false)\nconst data = createData()\nconst defaultExpandedKeys = ref(['40', '4030', '403020'])\n</script>\n\n<template>\n  <n-space vertical>\n    <n-switch v-model:value=\"showLine\" />\n    <n-tree\n      :show-line=\"showLine\"\n      :default-expanded-keys=\"defaultExpandedKeys\"\n      :data=\"data\"\n      checkable\n      expand-on-click\n      selectable\n    />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/tree/demos/zhCN/switcher-icon.demo.vue",
    "content": "<markdown>\n# 展开开关的图标\n\n使用 `render-switcher-icon` 定制展开开关的图标。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { TreeOption } from 'naive-ui'\nimport { ChevronForward, PlanetOutline, SunnyOutline } from '@vicons/ionicons5'\nimport { NIcon } from 'naive-ui'\nimport { repeat } from 'seemly'\nimport { h, ref } from 'vue'\n\nfunction createData(level = 4, baseKey = ''): TreeOption[] | undefined {\n  if (!level)\n    return undefined\n  return repeat(6 - level, undefined).map((_, index) => {\n    const key = `${baseKey}${level}${index}`\n    return {\n      label: createLabel(level),\n      key,\n      children: createData(level - 1, key)\n    }\n  })\n}\n\nfunction createLabel(level: number): string {\n  if (level === 4)\n    return '道生一'\n  if (level === 3)\n    return '一生二'\n  if (level === 2)\n    return '二生三'\n  if (level === 1)\n    return '三生万物'\n  return ''\n}\n\nconst data = createData()\nconst defaultExpandedKeys = ref(['40', '41'])\nfunction renderSwitcherIcon() {\n  return h(NIcon, null, { default: () => h(ChevronForward) })\n}\nfunction renderSwitcherIconWithExpaned({ expanded }: { expanded: boolean }) {\n  return h(NIcon, null, {\n    default: () => h(expanded ? SunnyOutline : PlanetOutline)\n  })\n}\n</script>\n\n<template>\n  <n-tree\n    block-line\n    :data=\"data\"\n    :default-expanded-keys=\"defaultExpandedKeys\"\n    :render-switcher-icon=\"renderSwitcherIcon\"\n    selectable\n  />\n  <n-tree\n    block-line\n    :data=\"data\"\n    :default-expanded-keys=\"defaultExpandedKeys\"\n    :render-switcher-icon=\"renderSwitcherIconWithExpaned\"\n    selectable\n  />\n</template>\n"
  },
  {
    "path": "src/tree/demos/zhCN/virtual.demo.vue",
    "content": "<markdown>\n# 大量数据\n\n设定 `virtual-scroll` 使用虚拟滚动，注意要设定好树的高度。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { TreeInst, TreeOption } from 'naive-ui'\nimport { repeat } from 'seemly'\nimport { ref } from 'vue'\n\nfunction createData(level = 4, baseKey = ''): TreeOption[] | undefined {\n  if (!level)\n    return undefined\n  return repeat(10 - level, undefined).map((_, index) => {\n    const key = `${baseKey}${level}${index}`\n    return {\n      label: createLabel(level),\n      key,\n      children: createData(level - 1, key)\n    }\n  })\n}\n\nfunction createLabel(level: number): string {\n  if (level === 4)\n    return '道生一'\n  if (level === 3)\n    return '一生二'\n  if (level === 2)\n    return '二生三'\n  if (level === 1)\n    return '三生万物'\n  return ''\n}\n\nconst treeInstRef = ref<TreeInst | null>(null)\nconst data = createData()\n\nfunction handleScrollToKey() {\n  treeInstRef.value?.scrollTo({ key: '45362710' })\n}\n\nfunction handleScrollToPosition() {\n  treeInstRef.value?.scrollTo({ position: 'bottom' })\n}\n\nfunction handleScrollToIndex() {\n  treeInstRef.value?.scrollTo({ index: 100 })\n}\n\nfunction handleScrollToDistance() {\n  treeInstRef.value?.scrollTo({ top: 400 })\n}\n</script>\n\n<template>\n  <n-space vertical>\n    <n-space>\n      <n-button @click=\"handleScrollToKey\">\n        滚动\n      </n-button>\n      <n-button @click=\"handleScrollToPosition\">\n        滚动到指定位置\n      </n-button>\n      <n-button @click=\"handleScrollToIndex\">\n        滚动到指定 Index\n      </n-button>\n      <n-button @click=\"handleScrollToDistance\">\n        滚动到指定距离\n      </n-button>\n    </n-space>\n    <n-tree\n      ref=\"treeInstRef\"\n      block-line\n      :data=\"data\"\n      default-expand-all\n      virtual-scroll\n      style=\"height: 320px\"\n    />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/tree/index.ts",
    "content": "export type {\n  TreeDragInfo,\n  TreeDropInfo,\n  TreeInst,\n  TreeOption,\n  TreeOverrideNodeClickBehavior,\n  TreeOverrideNodeClickBehaviorReturn\n} from './src/interface'\nexport type * from './src/public-types'\nexport { default as NTree, treeProps } from './src/Tree'\nexport type { TreeProps, TreeSlots } from './src/Tree'\nexport { treeGetClickTarget } from './src/utils'\n"
  },
  {
    "path": "src/tree/src/MotionWrapper.tsx",
    "content": "import type { PropType } from 'vue'\nimport type { TmNode } from './interface'\nimport { pxfy } from 'seemly'\nimport { defineComponent, h } from 'vue'\nimport FadeInExpandTransition from '../../_internal/fade-in-expand-transition'\nimport TreeNode from './TreeNode'\n\nexport default defineComponent({\n  name: 'TreeMotionWrapper',\n  props: {\n    clsPrefix: {\n      type: String,\n      required: true\n    },\n    height: Number,\n    nodes: {\n      type: Array as PropType<TmNode[]>,\n      required: true\n    },\n    mode: {\n      type: String as PropType<'expand' | 'collapse'>,\n      required: true\n    },\n    onAfterEnter: {\n      type: Function as PropType<() => void>,\n      required: true\n    }\n  },\n  render() {\n    const { clsPrefix } = this\n    return (\n      <FadeInExpandTransition\n        onAfterEnter={this.onAfterEnter}\n        appear\n        reverse={this.mode === 'collapse'}\n      >\n        {{\n          default: () => (\n            <div\n              class={[\n                `${clsPrefix}-tree-motion-wrapper`,\n                `${clsPrefix}-tree-motion-wrapper--${this.mode}`\n              ]}\n              style={{\n                height: pxfy(this.height)\n              }}\n            >\n              {this.nodes.map(node => (\n                <TreeNode clsPrefix={clsPrefix} tmNode={node} />\n              ))}\n            </div>\n          )\n        }}\n      </FadeInExpandTransition>\n    )\n  }\n})\n"
  },
  {
    "path": "src/tree/src/Tree.tsx",
    "content": "import type { CheckStrategy, TreeMateOptions } from 'treemate'\nimport type { CSSProperties, PropType, SlotsType, VNode, VNodeChild } from 'vue'\nimport type { VirtualListInst, VirtualListScrollToOptions } from 'vueuc'\nimport type { ScrollbarInst } from '../../_internal'\nimport type { ThemeProps } from '../../_mixins'\nimport type { ExtractPublicPropTypes, MaybeArray } from '../../_utils'\nimport type { ScrollbarProps } from '../../scrollbar/src/Scrollbar'\nimport type { TreeTheme } from '../styles'\nimport type {\n  AllowDrop,\n  CheckOnClick,\n  DropPosition,\n  GetChildren,\n  InternalDragInfo,\n  InternalDropInfo,\n  InternalTreeInst,\n  Key,\n  MotionData,\n  OnLoad,\n  RenderLabel,\n  RenderPrefix,\n  RenderSuffix,\n  RenderSwitcherIcon,\n  TmNode,\n  TreeDragInfo,\n  TreeDropInfo,\n  TreeInst,\n  TreeNodeProps,\n  TreeOption,\n  TreeOptions,\n  TreeOverrideNodeClickBehavior\n} from './interface'\nimport type { TreeSpinProps } from './public-types'\nimport { depx, getPadding, pxfy } from 'seemly'\nimport { createIndexGetter, createTreeMate, flatten } from 'treemate'\nimport { useMergedState } from 'vooks'\nimport {\n  computed,\n  defineComponent,\n  h,\n  inject,\n  nextTick,\n  provide,\n  ref,\n  toRef,\n  watch,\n  watchEffect\n} from 'vue'\nimport { VVirtualList } from 'vueuc'\nimport { NxScrollbar } from '../../_internal'\nimport { useConfig, useRtl, useTheme, useThemeClass } from '../../_mixins'\nimport { call, createDataKey, resolveSlot, warn, warnOnce } from '../../_utils'\nimport { NEmpty } from '../../empty'\nimport { treeSelectInjectionKey } from '../../tree-select/src/interface'\nimport { treeLight } from '../styles'\nimport { defaultAllowDrop } from './dnd'\nimport { treeInjectionKey } from './interface'\nimport { useKeyboard } from './keyboard'\nimport MotionWrapper from './MotionWrapper'\nimport style from './styles/index.cssr'\nimport NTreeNode from './TreeNode'\nimport {\n  emptyImage,\n  filterTree,\n  isNodeDisabled,\n  keysWithFilter,\n  useMergedCheckStrategy\n} from './utils'\n\nexport function createTreeMateOptions<T>(\n  keyField: string,\n  childrenField: string,\n  disabledField: string,\n  getChildren: GetChildren | undefined\n): TreeMateOptions<T, T, T> {\n  const settledGetChildren: GetChildren\n    = getChildren\n      || ((node: T) => {\n        return (node as any)[childrenField]\n      })\n  return {\n    getIsGroup() {\n      return false\n    },\n    getKey(node: T) {\n      return (node as any)[keyField]\n    },\n    getChildren: settledGetChildren,\n    getDisabled(node: T) {\n      return !!((node as any)[disabledField] || (node as any).checkboxDisabled)\n    }\n  }\n}\n\nexport type OnUpdateCheckedKeys = (\n  value: Array<string & number>,\n  option: Array<TreeOption | null>,\n  meta: {\n    node: TreeOption | null\n    action: 'check' | 'uncheck'\n  }\n) => void\nexport type OnUpdateCheckedKeysImpl = (\n  value: Key[],\n  option: Array<TreeOption | null>,\n  meta: {\n    node: TreeOption | null\n    action: 'check' | 'uncheck'\n  }\n) => void\nexport type OnUpdateIndeterminateKeys = (\n  value: Array<string & number>,\n  option: Array<TreeOption | null>\n) => void\nexport type OnUpdateIndeterminateKeysImpl = (\n  value: Key[],\n  option: Array<TreeOption | null>\n) => void\nexport type OnUpdateSelectedKeys = (\n  value: Array<string & number>,\n  option: Array<TreeOption | null>,\n  meta: {\n    node: TreeOption | null\n    action: 'select' | 'unselect'\n  }\n) => void\nexport type OnUpdateSelectedKeysImpl = (\n  value: Key[],\n  option: Array<TreeOption | null>,\n  meta: {\n    node: TreeOption | null\n    action: 'select' | 'unselect'\n  }\n) => void\nexport type onUpdateExpandedKeys = (\n  value: Array<string & number>,\n  option: Array<TreeOption | null>,\n  meta:\n    | {\n      node: TreeOption\n      action: 'expand' | 'collapse'\n    }\n    | {\n      node: null\n      action: 'filter'\n    }\n) => void\nexport type OnUpdateExpandedKeysImpl = (\n  value: Key[],\n  option: Array<TreeOption | null>,\n  meta:\n    | {\n      node: TreeOption\n      action: 'expand' | 'collapse'\n    }\n    | {\n      node: null\n      action: 'filter'\n    }\n) => void\n\nexport const treeSharedProps = {\n  allowCheckingNotLoaded: Boolean,\n  filter: Function as PropType<(pattern: string, node: TreeOption) => boolean>,\n  defaultExpandAll: Boolean,\n  expandedKeys: Array as PropType<Key[]>,\n  keyField: {\n    type: String,\n    default: 'key'\n  },\n  labelField: {\n    type: String,\n    default: 'label'\n  },\n  childrenField: {\n    type: String,\n    default: 'children'\n  },\n  disabledField: {\n    type: String,\n    default: 'disabled'\n  },\n  defaultExpandedKeys: {\n    type: Array as PropType<Key[]>,\n    default: () => []\n  },\n  indent: {\n    type: Number,\n    default: 24\n  },\n  indeterminateKeys: Array as PropType<Key[]>,\n  renderSwitcherIcon: Function as PropType<RenderSwitcherIcon>,\n  onUpdateIndeterminateKeys: [Function, Array] as PropType<\n    MaybeArray<OnUpdateIndeterminateKeys>\n  >,\n  'onUpdate:indeterminateKeys': [Function, Array] as PropType<\n    MaybeArray<OnUpdateIndeterminateKeys>\n  >,\n  onUpdateExpandedKeys: [Function, Array] as PropType<\n    MaybeArray<onUpdateExpandedKeys>\n  >,\n  'onUpdate:expandedKeys': [Function, Array] as PropType<\n    MaybeArray<onUpdateExpandedKeys>\n  >,\n  overrideDefaultNodeClickBehavior:\n    Function as PropType<TreeOverrideNodeClickBehavior>\n} as const\n\nexport const treeProps = {\n  ...(useTheme.props as ThemeProps<TreeTheme>),\n  accordion: Boolean,\n  showIrrelevantNodes: { type: Boolean, default: true },\n  data: {\n    type: Array as PropType<TreeOptions>,\n    default: () => []\n  },\n  expandOnDragenter: {\n    type: Boolean,\n    default: true\n  },\n  expandOnClick: Boolean,\n  checkOnClick: {\n    type: [Boolean, Function] as PropType<boolean | CheckOnClick>,\n    default: false\n  },\n  cancelable: {\n    type: Boolean,\n    default: true\n  },\n  checkable: Boolean,\n  draggable: Boolean,\n  blockNode: Boolean,\n  blockLine: Boolean,\n  showLine: Boolean,\n  disabled: Boolean,\n  checkedKeys: Array as PropType<Key[]>,\n  defaultCheckedKeys: {\n    type: Array as PropType<Key[]>,\n    default: () => []\n  },\n  selectedKeys: Array as PropType<Key[]>,\n  defaultSelectedKeys: {\n    type: Array as PropType<Key[]>,\n    default: () => []\n  },\n  multiple: Boolean,\n  pattern: {\n    type: String,\n    default: ''\n  },\n  onLoad: Function as PropType<OnLoad>,\n  cascade: Boolean,\n  selectable: {\n    type: Boolean,\n    default: true\n  },\n  scrollbarProps: Object as PropType<ScrollbarProps>,\n  allowDrop: {\n    type: Function as PropType<AllowDrop>,\n    default: defaultAllowDrop\n  },\n  animated: {\n    type: Boolean,\n    default: true\n  },\n  ellipsis: Boolean,\n  checkboxPlacement: {\n    type: String as PropType<'left' | 'right'>,\n    default: 'left'\n  },\n  virtualScroll: Boolean,\n  watchProps: Array as PropType<\n    Array<'defaultCheckedKeys' | 'defaultSelectedKeys' | 'defaultExpandedKeys'>\n  >,\n  renderLabel: Function as PropType<RenderLabel>,\n  renderPrefix: Function as PropType<RenderPrefix>,\n  renderSuffix: Function as PropType<RenderSuffix>,\n  nodeProps: Function as PropType<TreeNodeProps>,\n  keyboard: {\n    type: Boolean,\n    default: true\n  },\n  getChildren: Function as PropType<GetChildren>,\n  onDragenter: [Function, Array] as PropType<\n    MaybeArray<(e: TreeDragInfo) => void>\n  >,\n  onDragleave: [Function, Array] as PropType<\n    MaybeArray<(e: TreeDragInfo) => void>\n  >,\n  onDragend: [Function, Array] as PropType<\n    MaybeArray<(e: TreeDragInfo) => void>\n  >,\n  onDragstart: [Function, Array] as PropType<\n    MaybeArray<(e: TreeDragInfo) => void>\n  >,\n  onDragover: [Function, Array] as PropType<\n    MaybeArray<(e: TreeDragInfo) => void>\n  >,\n  onDrop: [Function, Array] as PropType<MaybeArray<(e: TreeDropInfo) => void>>,\n  onUpdateCheckedKeys: [Function, Array] as PropType<\n    MaybeArray<OnUpdateCheckedKeys>\n  >,\n  'onUpdate:checkedKeys': [Function, Array] as PropType<\n    MaybeArray<OnUpdateCheckedKeys>\n  >,\n  onUpdateSelectedKeys: [Function, Array] as PropType<\n    MaybeArray<OnUpdateSelectedKeys>\n  >,\n  'onUpdate:selectedKeys': [Function, Array] as PropType<\n    MaybeArray<OnUpdateSelectedKeys>\n  >,\n  ...treeSharedProps,\n  // internal props for tree-select\n  internalTreeSelect: Boolean,\n  internalScrollable: Boolean,\n  internalScrollablePadding: String,\n  // use it to display\n  internalRenderEmpty: Function as PropType<() => VNodeChild>,\n  internalHighlightKeySet: Object as PropType<Set<Key> | null>,\n  internalUnifySelectCheck: Boolean,\n  internalCheckboxFocusable: {\n    type: Boolean,\n    default: true\n  },\n  internalFocusable: {\n    // Make tree-select take over keyboard operations\n    type: Boolean,\n    default: true\n  },\n  checkStrategy: {\n    type: String as PropType<CheckStrategy>,\n    default: 'all'\n  },\n  spinProps: Object as PropType<TreeSpinProps>,\n  /**\n   * @deprecated\n   */\n  leafOnly: Boolean\n} as const\n\nexport type TreeProps = ExtractPublicPropTypes<typeof treeProps>\n\nexport interface TreeSlots {\n  default?: () => VNode[]\n  empty?: () => VNode[]\n}\n\nexport default defineComponent({\n  name: 'Tree',\n  props: treeProps,\n  slots: Object as SlotsType<TreeSlots>,\n  setup(props) {\n    if (__DEV__) {\n      watchEffect(() => {\n        if (props.leafOnly) {\n          warnOnce(\n            'tree',\n            '`leaf-only` is deprecated, please use `check-strategy=\"child\"` instead'\n          )\n        }\n      })\n    }\n    const {\n      mergedClsPrefixRef,\n      inlineThemeDisabled,\n      mergedRtlRef,\n      mergedComponentPropsRef\n    } = useConfig(props)\n    const rtlEnabledRef = useRtl('Tree', mergedRtlRef, mergedClsPrefixRef)\n    const themeRef = useTheme(\n      'Tree',\n      '-tree',\n      style,\n      treeLight,\n      props,\n      mergedClsPrefixRef\n    )\n    const mergedRenderEmptyRef = computed(() => {\n      return mergedComponentPropsRef?.value?.Tree?.renderEmpty\n    })\n    const selfElRef = ref<HTMLDivElement | null>(null)\n    const scrollbarInstRef = ref<ScrollbarInst | null>(null)\n    const virtualListInstRef = ref<VirtualListInst | null>(null)\n    function getScrollContainer(): HTMLElement | null | undefined {\n      return virtualListInstRef.value?.listElRef\n    }\n    function getScrollContent(): HTMLElement | null | undefined {\n      return virtualListInstRef.value?.itemsElRef\n    }\n\n    const mergedFilterRef = computed(() => {\n      const { filter } = props\n      if (filter)\n        return filter\n      const { labelField } = props\n      return (pattern: string, node: TreeOption): boolean => {\n        if (!pattern.length)\n          return true\n        const label = node[labelField]\n        if (typeof label === 'string') {\n          return label.toLowerCase().includes(pattern.toLowerCase())\n        }\n        return false\n      }\n    })\n\n    const filteredTreeInfoRef = computed<{\n      filteredTree: TreeOption[]\n      highlightKeySet: Set<Key> | null\n      expandedKeys: Key[] | undefined\n    }>(() => {\n      const { pattern } = props\n      if (!pattern) {\n        return {\n          filteredTree: props.data,\n          highlightKeySet: null,\n          expandedKeys: undefined\n        }\n      }\n      if (!pattern.length || !mergedFilterRef.value) {\n        return {\n          filteredTree: props.data,\n          highlightKeySet: null,\n          expandedKeys: undefined\n        }\n      }\n      return filterTree(\n        props.data,\n        mergedFilterRef.value,\n        pattern,\n        props.keyField,\n        props.childrenField\n      )\n    })\n\n    // We don't expect data source to change so we just determine it once\n    const displayTreeMateRef = computed(() =>\n      createTreeMate<TreeOption>(\n        props.showIrrelevantNodes\n          ? props.data\n          : filteredTreeInfoRef.value.filteredTree,\n        createTreeMateOptions(\n          props.keyField,\n          props.childrenField,\n          props.disabledField,\n          props.getChildren\n        )\n      )\n    )\n    const treeSelectInjection = inject(treeSelectInjectionKey, null)\n    const dataTreeMateRef = props.internalTreeSelect\n      ? treeSelectInjection!.dataTreeMate\n      : computed(() =>\n          props.showIrrelevantNodes\n            ? displayTreeMateRef.value\n            : createTreeMate(\n                props.data,\n                createTreeMateOptions(\n                  props.keyField,\n                  props.childrenField,\n                  props.disabledField,\n                  props.getChildren\n                )\n              )\n        )\n    const { watchProps } = props\n    const uncontrolledCheckedKeysRef = ref<Key[]>([])\n    if (watchProps?.includes('defaultCheckedKeys')) {\n      watchEffect(() => {\n        uncontrolledCheckedKeysRef.value = props.defaultCheckedKeys\n      })\n    }\n    else {\n      uncontrolledCheckedKeysRef.value = props.defaultCheckedKeys\n    }\n    const controlledCheckedKeysRef = toRef(props, 'checkedKeys')\n    const mergedCheckedKeysRef = useMergedState(\n      controlledCheckedKeysRef,\n      uncontrolledCheckedKeysRef\n    )\n    const checkedStatusRef = computed(() => {\n      const value = dataTreeMateRef.value.getCheckedKeys(\n        mergedCheckedKeysRef.value,\n        {\n          cascade: props.cascade,\n          allowNotLoaded: props.allowCheckingNotLoaded\n        }\n      )\n      return value\n    })\n    const mergedCheckStrategyRef = useMergedCheckStrategy(props)\n    const displayedCheckedKeysRef = computed(() => {\n      return checkedStatusRef.value.checkedKeys\n    })\n    const displayedIndeterminateKeysRef = computed(() => {\n      const { indeterminateKeys } = props\n      if (indeterminateKeys !== undefined)\n        return indeterminateKeys\n      return checkedStatusRef.value.indeterminateKeys\n    })\n    const uncontrolledSelectedKeysRef = ref<Key[]>([])\n    if (watchProps?.includes('defaultSelectedKeys')) {\n      watchEffect(() => {\n        uncontrolledSelectedKeysRef.value = props.defaultSelectedKeys\n      })\n    }\n    else {\n      uncontrolledSelectedKeysRef.value = props.defaultSelectedKeys\n    }\n    const controlledSelectedKeysRef = toRef(props, 'selectedKeys')\n    const mergedSelectedKeysRef = useMergedState(\n      controlledSelectedKeysRef,\n      uncontrolledSelectedKeysRef\n    )\n    const uncontrolledExpandedKeysRef = ref<Key[]>([])\n\n    const initUncontrolledExpandedKeys = (keys: undefined | Key[]): void => {\n      uncontrolledExpandedKeysRef.value = props.defaultExpandAll\n        ? dataTreeMateRef.value.getNonLeafKeys()\n        : keys === undefined\n          ? props.defaultExpandedKeys\n          : keys\n    }\n    if (watchProps?.includes('defaultExpandedKeys')) {\n      // if watching defaultExpandedKeys, we use access props.defaultExpandedKeys inside initiator\n      watchEffect(() => {\n        initUncontrolledExpandedKeys(undefined)\n      })\n    }\n    else {\n      // We by default watchEffect since if defaultExpandAll is true, we should remain tree expand if data changes\n      watchEffect(() => {\n        initUncontrolledExpandedKeys(props.defaultExpandedKeys)\n      })\n    }\n\n    const controlledExpandedKeysRef = toRef(props, 'expandedKeys')\n    const mergedExpandedKeysRef = useMergedState(\n      controlledExpandedKeysRef,\n      uncontrolledExpandedKeysRef\n    )\n\n    const fNodesRef = computed(() =>\n      displayTreeMateRef.value.getFlattenedNodes(mergedExpandedKeysRef.value)\n    )\n\n    const { pendingNodeKeyRef, handleKeydown } = useKeyboard({\n      props,\n      mergedCheckedKeysRef,\n      mergedSelectedKeysRef,\n      fNodesRef,\n      mergedExpandedKeysRef,\n      handleCheck,\n      handleSelect,\n      handleSwitcherClick\n    })\n\n    let expandTimerId: number | null = null\n    let nodeKeyToBeExpanded: Key | null = null\n    const uncontrolledHighlightKeySetRef = ref(new Set<Key>())\n    const controlledHighlightKeySetRef = computed(() => {\n      return (\n        props.internalHighlightKeySet\n        || filteredTreeInfoRef.value.highlightKeySet\n      )\n    })\n    const mergedHighlightKeySetRef = useMergedState(\n      controlledHighlightKeySetRef,\n      uncontrolledHighlightKeySetRef\n    )\n    const loadingKeysRef = ref(new Set<Key>())\n    const expandedNonLoadingKeysRef = computed(() => {\n      return mergedExpandedKeysRef.value.filter(\n        key => !loadingKeysRef.value.has(key)\n      )\n    })\n\n    let dragStartX: number = 0\n    const draggingNodeRef = ref<TmNode | null>(null)\n    const droppingNodeRef = ref<TmNode | null>(null)\n    const droppingMouseNodeRef = ref<TmNode | null>(null)\n    const droppingPositionRef = ref<'before' | 'inside' | 'after' | null>(null)\n    const droppingOffsetLevelRef = ref<number>(0)\n    const droppingNodeParentRef = computed(() => {\n      const { value: droppingNode } = droppingNodeRef\n      if (!droppingNode)\n        return null\n      // May avoid overlap between line mark of first child & rect mark of parent\n      // if (droppingNode.isFirstChild && droppingPositionRef.value === 'before') {\n      //   return null\n      // }\n      return droppingNode.parent\n    })\n\n    // shallow watch data\n    let isDataReset = false\n    watch(\n      toRef(props, 'data'),\n      () => {\n        isDataReset = true\n        void nextTick(() => {\n          isDataReset = false\n        })\n        loadingKeysRef.value.clear()\n        pendingNodeKeyRef.value = null\n        resetDndState()\n      },\n      {\n        deep: false\n      }\n    )\n    let expandAnimationDisabled = false\n    const disableExpandAnimationForOneTick = (): void => {\n      expandAnimationDisabled = true\n      void nextTick(() => {\n        expandAnimationDisabled = false\n      })\n    }\n    let memoizedExpandedKeys: Key[] | undefined\n    watch(toRef(props, 'pattern'), (value, oldValue) => {\n      if (props.showIrrelevantNodes) {\n        memoizedExpandedKeys = undefined\n        if (value) {\n          const { expandedKeys: expandedKeysAfterChange, highlightKeySet }\n            = keysWithFilter(\n              props.data,\n              props.pattern,\n              props.keyField,\n              props.childrenField,\n              mergedFilterRef.value\n            )\n          uncontrolledHighlightKeySetRef.value = highlightKeySet\n          disableExpandAnimationForOneTick()\n          doUpdateExpandedKeys(\n            expandedKeysAfterChange,\n            getOptionsByKeys(expandedKeysAfterChange),\n            { node: null, action: 'filter' }\n          )\n        }\n        else {\n          uncontrolledHighlightKeySetRef.value = new Set()\n        }\n      }\n      else {\n        if (!value.length) {\n          if (memoizedExpandedKeys !== undefined) {\n            disableExpandAnimationForOneTick()\n            doUpdateExpandedKeys(\n              memoizedExpandedKeys,\n              getOptionsByKeys(memoizedExpandedKeys),\n              { node: null, action: 'filter' }\n            )\n          }\n        }\n        else {\n          if (!oldValue.length) {\n            memoizedExpandedKeys = mergedExpandedKeysRef.value\n          }\n          const { expandedKeys } = filteredTreeInfoRef.value\n          if (expandedKeys !== undefined) {\n            disableExpandAnimationForOneTick()\n            doUpdateExpandedKeys(expandedKeys, getOptionsByKeys(expandedKeys), {\n              node: null,\n              action: 'filter'\n            })\n          }\n        }\n      }\n    })\n    async function triggerLoading(node: TmNode): Promise<void> {\n      const { onLoad } = props\n      if (!onLoad) {\n        if (__DEV__) {\n          warn(\n            'tree',\n            'There is unloaded node in data but props.onLoad is not specified.'\n          )\n        }\n        await Promise.resolve()\n        return\n      }\n      const { value: loadingKeys } = loadingKeysRef\n      if (!loadingKeys.has(node.key)) {\n        loadingKeys.add(node.key)\n        try {\n          const loadResult = await onLoad(node.rawNode)\n          if (loadResult === false) {\n            resetDragExpandState()\n          }\n        }\n        catch (loadError) {\n          console.error(loadError)\n          resetDragExpandState()\n        }\n        loadingKeys.delete(node.key)\n      }\n    }\n    watchEffect(() => {\n      const { value: displayTreeMate } = displayTreeMateRef\n      if (!displayTreeMate)\n        return\n      const { getNode } = displayTreeMate\n      mergedExpandedKeysRef.value?.forEach((key) => {\n        const node = getNode(key)\n        if (node && !node.shallowLoaded) {\n          void triggerLoading(node)\n        }\n      })\n    })\n    // animation in progress\n    const aipRef = ref(false)\n    // animation flattened nodes\n    const afNodesRef = ref<Array<TmNode | MotionData>>([])\n    // Note: Since the virtual list depends on min height, if there's a node\n    // whose height starts from 0, the virtual list will have a wrong height\n    // during animation. This will seldom cause wired scrollbar status. It is\n    // fixable and need some changes in vueuc, I've no time so I just leave it\n    // here. Maybe the bug won't be fixed during the life time of the project.\n    watch(expandedNonLoadingKeysRef, (value, prevValue) => {\n      if (!props.animated || expandAnimationDisabled) {\n        void nextTick(syncScrollbar)\n        return\n      }\n      if (isDataReset) {\n        return\n      }\n      const nodeHeight = depx(themeRef.value.self.nodeHeight)\n      const prevVSet = new Set(prevValue)\n      let addedKey: Key | null = null\n      let removedKey: Key | null = null\n      for (const expandedKey of value) {\n        if (!prevVSet.has(expandedKey)) {\n          if (addedKey !== null)\n            return // multi expand, not triggered by click\n          addedKey = expandedKey\n        }\n      }\n      const currentVSet = new Set(value)\n      for (const expandedKey of prevValue) {\n        if (!currentVSet.has(expandedKey)) {\n          if (removedKey !== null)\n            return // multi collapse, not triggered by click\n          removedKey = expandedKey\n        }\n      }\n      if (addedKey === null && removedKey === null) {\n        // 1. multi action, not triggered by click\n        // 2. no action, don't know what happened\n        return\n      }\n      const { virtualScroll } = props\n      const viewportHeight = (\n        virtualScroll ? virtualListInstRef.value!.listElRef : selfElRef.value!\n      ).offsetHeight\n      const viewportItemCount = Math.ceil(viewportHeight / nodeHeight) + 1\n      // play add animation\n      let baseExpandedKeys: Key[] | undefined\n      if (addedKey !== null) {\n        baseExpandedKeys = prevValue\n      }\n      if (removedKey !== null) {\n        if (baseExpandedKeys === undefined) {\n          baseExpandedKeys = value\n        }\n        else {\n          baseExpandedKeys = baseExpandedKeys.filter(\n            key => key !== removedKey\n          )\n        }\n      }\n      aipRef.value = true\n      afNodesRef.value\n        = displayTreeMateRef.value.getFlattenedNodes(baseExpandedKeys)\n      if (addedKey !== null) {\n        const expandedNodeIndex = afNodesRef.value.findIndex(\n          node => (node as any).key === addedKey\n        )\n        if (~expandedNodeIndex) {\n          const children = (afNodesRef.value[expandedNodeIndex] as TmNode)\n            .children\n          // sometimes user will pass leaf keys in\n          if (children) {\n            const expandedChildren = flatten(children, value)\n            afNodesRef.value.splice(expandedNodeIndex + 1, 0, {\n              __motion: true,\n              mode: 'expand',\n              height: virtualScroll\n                ? expandedChildren.length * nodeHeight\n                : undefined,\n              nodes: virtualScroll\n                ? expandedChildren.slice(0, viewportItemCount)\n                : expandedChildren\n            })\n          }\n        }\n      }\n      if (removedKey !== null) {\n        const collapsedNodeIndex = afNodesRef.value.findIndex(\n          node => (node as any).key === removedKey\n        )\n        if (~collapsedNodeIndex) {\n          const collapsedNodeChildren = (\n            afNodesRef.value[collapsedNodeIndex] as TmNode\n          ).children\n          // Sometime the whole tree is change, remove a key doesn't mean it is collapsed,\n          // but maybe children removed\n          if (!collapsedNodeChildren)\n            return\n          // play remove animation\n          aipRef.value = true\n          const collapsedChildren = flatten(collapsedNodeChildren, value)\n          afNodesRef.value.splice(collapsedNodeIndex + 1, 0, {\n            __motion: true,\n            mode: 'collapse',\n            height: virtualScroll\n              ? collapsedChildren.length * nodeHeight\n              : undefined,\n            nodes: virtualScroll\n              ? collapsedChildren.slice(0, viewportItemCount)\n              : collapsedChildren\n          })\n        }\n      }\n    })\n\n    const getFIndexRef = computed(() => {\n      return createIndexGetter(fNodesRef.value)\n    })\n\n    const mergedFNodesRef = computed(() => {\n      if (aipRef.value)\n        return afNodesRef.value\n      else return fNodesRef.value\n    })\n\n    function syncScrollbar(): void {\n      const { value: scrollbarInst } = scrollbarInstRef\n      if (scrollbarInst)\n        scrollbarInst.sync()\n    }\n\n    function handleAfterEnter(): void {\n      aipRef.value = false\n      if (props.virtualScroll) {\n        // If virtual scroll, we won't listen to resize during animation, so\n        // resize callback of virtual list won't be called and as a result\n        // scrollbar won't sync. We need to sync scrollbar manually.\n        void nextTick(syncScrollbar)\n      }\n    }\n\n    function getOptionsByKeys(keys: Key[]): Array<TreeOption | null> {\n      const { getNode } = dataTreeMateRef.value\n      return keys.map(key => getNode(key)?.rawNode || null)\n    }\n\n    function doUpdateExpandedKeys(\n      value: Key[],\n      option: Array<TreeOption | null>,\n      meta:\n        | {\n          node: TreeOption\n          action: 'expand' | 'collapse'\n        }\n        | {\n          node: null\n          action: 'filter'\n        }\n    ): void {\n      const {\n        'onUpdate:expandedKeys': _onUpdateExpandedKeys,\n        onUpdateExpandedKeys\n      } = props\n      uncontrolledExpandedKeysRef.value = value\n      if (_onUpdateExpandedKeys) {\n        call(\n          _onUpdateExpandedKeys as OnUpdateExpandedKeysImpl,\n          value,\n          option,\n          meta\n        )\n      }\n      if (onUpdateExpandedKeys) {\n        call(\n          onUpdateExpandedKeys as OnUpdateExpandedKeysImpl,\n          value,\n          option,\n          meta\n        )\n      }\n    }\n    function doUpdateCheckedKeys(\n      value: Key[],\n      option: Array<TreeOption | null>,\n      meta: {\n        node: TreeOption | null\n        action: 'check' | 'uncheck'\n      }\n    ): void {\n      const {\n        'onUpdate:checkedKeys': _onUpdateCheckedKeys,\n        onUpdateCheckedKeys\n      } = props\n      uncontrolledCheckedKeysRef.value = value\n      if (onUpdateCheckedKeys) {\n        call(\n          onUpdateCheckedKeys as OnUpdateCheckedKeysImpl,\n          value,\n          option,\n          meta\n        )\n      }\n      if (_onUpdateCheckedKeys) {\n        call(\n          _onUpdateCheckedKeys as OnUpdateCheckedKeysImpl,\n          value,\n          option,\n          meta\n        )\n      }\n    }\n    function doUpdateIndeterminateKeys(\n      value: Key[],\n      option: Array<TreeOption | null>\n    ): void {\n      const {\n        'onUpdate:indeterminateKeys': _onUpdateIndeterminateKeys,\n        onUpdateIndeterminateKeys\n      } = props\n      if (_onUpdateIndeterminateKeys) {\n        call(\n          _onUpdateIndeterminateKeys as OnUpdateIndeterminateKeysImpl,\n          value,\n          option\n        )\n      }\n      if (onUpdateIndeterminateKeys) {\n        call(\n          onUpdateIndeterminateKeys as OnUpdateIndeterminateKeysImpl,\n          value,\n          option\n        )\n      }\n    }\n    function doUpdateSelectedKeys(\n      value: Key[],\n      option: Array<TreeOption | null>,\n      meta: {\n        node: TreeOption\n        action: 'select' | 'unselect'\n      }\n    ): void {\n      const {\n        'onUpdate:selectedKeys': _onUpdateSelectedKeys,\n        onUpdateSelectedKeys\n      } = props\n      uncontrolledSelectedKeysRef.value = value\n      if (onUpdateSelectedKeys) {\n        call(\n          onUpdateSelectedKeys as OnUpdateSelectedKeysImpl,\n          value,\n          option,\n          meta\n        )\n      }\n      if (_onUpdateSelectedKeys) {\n        call(\n          _onUpdateSelectedKeys as OnUpdateSelectedKeysImpl,\n          value,\n          option,\n          meta\n        )\n      }\n    }\n    // Drag & Drop\n    function doDragEnter(info: TreeDragInfo): void {\n      const { onDragenter } = props\n      if (onDragenter)\n        call(onDragenter, info)\n    }\n    function doDragLeave(info: TreeDragInfo): void {\n      const { onDragleave } = props\n      if (onDragleave)\n        call(onDragleave, info)\n    }\n    function doDragEnd(info: TreeDragInfo): void {\n      const { onDragend } = props\n      if (onDragend)\n        call(onDragend, info)\n    }\n    function doDragStart(info: TreeDragInfo): void {\n      const { onDragstart } = props\n      if (onDragstart)\n        call(onDragstart, info)\n    }\n    function doDragOver(info: TreeDragInfo): void {\n      const { onDragover } = props\n      if (onDragover)\n        call(onDragover, info)\n    }\n    function doDrop(info: TreeDropInfo): void {\n      const { onDrop } = props\n      if (onDrop)\n        call(onDrop, info)\n    }\n    function resetDndState(): void {\n      resetDragState()\n      resetDropState()\n    }\n    function resetDragState(): void {\n      draggingNodeRef.value = null\n    }\n    function resetDropState(): void {\n      droppingOffsetLevelRef.value = 0\n      droppingNodeRef.value = null\n      droppingMouseNodeRef.value = null\n      droppingPositionRef.value = null\n      resetDragExpandState()\n    }\n    function resetDragExpandState(): void {\n      if (expandTimerId) {\n        window.clearTimeout(expandTimerId)\n        expandTimerId = null\n      }\n      nodeKeyToBeExpanded = null\n    }\n    function handleCheck(node: TmNode, checked: boolean): void {\n      // We don't guard for leaf only since we have done it in view layer\n      if (props.disabled || isNodeDisabled(node, props.disabledField)) {\n        return\n      }\n      if (props.internalUnifySelectCheck && !props.multiple) {\n        handleSelect(node)\n        return\n      }\n      const checkedAction = checked ? 'check' : 'uncheck'\n      const { checkedKeys, indeterminateKeys } = dataTreeMateRef.value[\n        checkedAction\n      ](node.key, displayedCheckedKeysRef.value, {\n        cascade: props.cascade,\n        checkStrategy: mergedCheckStrategyRef.value,\n        allowNotLoaded: props.allowCheckingNotLoaded\n      })\n      doUpdateCheckedKeys(checkedKeys, getOptionsByKeys(checkedKeys), {\n        node: node.rawNode,\n        action: checkedAction\n      })\n      doUpdateIndeterminateKeys(\n        indeterminateKeys,\n        getOptionsByKeys(indeterminateKeys)\n      )\n    }\n    function toggleExpand(node: TmNode): void {\n      if (props.disabled)\n        return\n      const { key } = node\n      const { value: mergedExpandedKeys } = mergedExpandedKeysRef\n      const index = mergedExpandedKeys.findIndex(\n        expandNodeId => expandNodeId === key\n      )\n      if (~index) {\n        const expandedKeysAfterChange = Array.from(mergedExpandedKeys)\n        expandedKeysAfterChange.splice(index, 1)\n        doUpdateExpandedKeys(\n          expandedKeysAfterChange,\n          getOptionsByKeys(expandedKeysAfterChange),\n          {\n            node: node.rawNode,\n            action: 'collapse'\n          }\n        )\n      }\n      else {\n        const nodeToBeExpanded = displayTreeMateRef.value.getNode(key)\n        if (!nodeToBeExpanded || nodeToBeExpanded.isLeaf) {\n          return\n        }\n        let nextKeys: Key[]\n        if (props.accordion) {\n          const siblingKeySet = new Set<Key>(\n            node.siblings.map(({ key }) => key)\n          )\n          nextKeys = mergedExpandedKeys.filter((expandedKey) => {\n            return !siblingKeySet.has(expandedKey)\n          })\n          nextKeys.push(key)\n        }\n        else {\n          nextKeys = mergedExpandedKeys.concat(key)\n        }\n        doUpdateExpandedKeys(nextKeys, getOptionsByKeys(nextKeys), {\n          node: node.rawNode,\n          action: 'expand'\n        })\n      }\n    }\n    function handleSwitcherClick(node: TmNode): void {\n      if (props.disabled || aipRef.value)\n        return\n      toggleExpand(node)\n    }\n    function handleSelect(node: TmNode): void {\n      if (props.disabled || !props.selectable) {\n        return\n      }\n      pendingNodeKeyRef.value = node.key\n      if (props.internalUnifySelectCheck) {\n        const {\n          value: { checkedKeys, indeterminateKeys }\n        } = checkedStatusRef\n        if (props.multiple) {\n          handleCheck(\n            node,\n            !(\n              checkedKeys.includes(node.key)\n              || indeterminateKeys.includes(node.key)\n            )\n          )\n        }\n        else {\n          doUpdateCheckedKeys([node.key], getOptionsByKeys([node.key]), {\n            node: node.rawNode,\n            action: 'check'\n          })\n        }\n      }\n      if (props.multiple) {\n        const selectedKeys = Array.from(mergedSelectedKeysRef.value)\n        const index = selectedKeys.findIndex(key => key === node.key)\n        if (~index) {\n          if (props.cancelable) {\n            selectedKeys.splice(index, 1)\n          }\n        }\n        else if (!~index) {\n          selectedKeys.push(node.key)\n        }\n        doUpdateSelectedKeys(selectedKeys, getOptionsByKeys(selectedKeys), {\n          node: node.rawNode,\n          action: ~index ? 'unselect' : 'select'\n        })\n      }\n      else {\n        const selectedKeys = mergedSelectedKeysRef.value\n        if (selectedKeys.includes(node.key)) {\n          if (props.cancelable) {\n            doUpdateSelectedKeys([], [], {\n              node: node.rawNode,\n              action: 'unselect'\n            })\n          }\n        }\n        else {\n          doUpdateSelectedKeys([node.key], getOptionsByKeys([node.key]), {\n            node: node.rawNode,\n            action: 'select'\n          })\n        }\n      }\n    }\n\n    function expandDragEnterNode(node: TmNode): void {\n      if (expandTimerId) {\n        window.clearTimeout(expandTimerId)\n        expandTimerId = null\n      }\n      // Don't expand leaf node.\n      if (node.isLeaf)\n        return\n      nodeKeyToBeExpanded = node.key\n      const expand = (): void => {\n        if (nodeKeyToBeExpanded !== node.key)\n          return\n        const { value: droppingMouseNode } = droppingMouseNodeRef\n        if (\n          droppingMouseNode\n          && droppingMouseNode.key === node.key\n          && !mergedExpandedKeysRef.value.includes(node.key)\n        ) {\n          const nextKeys = mergedExpandedKeysRef.value.concat(node.key)\n          doUpdateExpandedKeys(nextKeys, getOptionsByKeys(nextKeys), {\n            node: node.rawNode,\n            action: 'expand'\n          })\n        }\n        expandTimerId = null\n        nodeKeyToBeExpanded = null\n      }\n      if (!node.shallowLoaded) {\n        expandTimerId = window.setTimeout(() => {\n          void triggerLoading(node).then(() => {\n            expand()\n          })\n        }, 1000)\n      }\n      else {\n        expandTimerId = window.setTimeout(() => {\n          expand()\n        }, 1000)\n      }\n    }\n\n    // Dnd\n    function handleDragEnter({ event, node }: InternalDragInfo): void {\n      // node should be a tmNode\n      if (\n        !props.draggable\n        || props.disabled\n        || isNodeDisabled(node, props.disabledField)\n      ) {\n        return\n      }\n      handleDragOver({ event, node }, false)\n      doDragEnter({ event, node: node.rawNode })\n    }\n    function handleDragLeave({ event, node }: InternalDragInfo): void {\n      if (\n        !props.draggable\n        || props.disabled\n        || isNodeDisabled(node, props.disabledField)\n      ) {\n        return\n      }\n      doDragLeave({ event, node: node.rawNode })\n    }\n    function handleDragLeaveTree(e: DragEvent): void {\n      if (e.target !== e.currentTarget)\n        return\n      resetDropState()\n    }\n    // Dragend is ok, we don't need to add global listener to reset drag status\n    function handleDragEnd({ event, node }: InternalDragInfo): void {\n      resetDndState()\n      if (\n        !props.draggable\n        || props.disabled\n        || isNodeDisabled(node, props.disabledField)\n      ) {\n        return\n      }\n      doDragEnd({ event, node: node.rawNode })\n    }\n    function handleDragStart({ event, node }: InternalDragInfo): void {\n      if (\n        !props.draggable\n        || props.disabled\n        || isNodeDisabled(node, props.disabledField)\n      ) {\n        return\n      }\n      // Most of time, the image will block user's view\n      if (emptyImage) {\n        event.dataTransfer?.setDragImage(emptyImage, 0, 0)\n      }\n      dragStartX = event.clientX\n      draggingNodeRef.value = node\n      doDragStart({ event, node: node.rawNode })\n    }\n    function handleDragOver(\n      { event, node }: InternalDragInfo,\n      emit: boolean = true\n    ): void {\n      if (\n        !props.draggable\n        || props.disabled\n        || isNodeDisabled(node, props.disabledField)\n      ) {\n        return\n      }\n      const { value: draggingNode } = draggingNodeRef\n      if (!draggingNode)\n        return\n      const { allowDrop, indent } = props\n      if (emit)\n        doDragOver({ event, node: node.rawNode })\n      // Update dropping node\n      const el = event.currentTarget as HTMLElement\n      const { height: elOffsetHeight, top: elClientTop }\n        = el.getBoundingClientRect()\n      const eventOffsetY = event.clientY - elClientTop\n      let mousePosition: DropPosition\n\n      const allowDropInside = allowDrop({\n        node: node.rawNode,\n        dropPosition: 'inside',\n        phase: 'drag'\n      })\n\n      if (allowDropInside) {\n        if (eventOffsetY <= 8) {\n          mousePosition = 'before'\n        }\n        else if (eventOffsetY >= elOffsetHeight - 8) {\n          mousePosition = 'after'\n        }\n        else {\n          mousePosition = 'inside'\n        }\n      }\n      else {\n        if (eventOffsetY <= elOffsetHeight / 2) {\n          mousePosition = 'before'\n        }\n        else {\n          mousePosition = 'after'\n        }\n      }\n\n      const { value: getFindex } = getFIndexRef\n\n      /** determine the drop position and drop node */\n      /** the dropping node needn't to be the mouse hovering node! */\n      /**\n       * if there is something i've learned from implementing a complex\n       * drag & drop. that is never write unit test before you really figure\n       * out what behavior is exactly you want.\n       */\n      let finalDropNode: TmNode\n      let finalDropPosition: DropPosition\n      const hoverNodeFIndex = getFindex(node.key)\n      if (hoverNodeFIndex === null) {\n        resetDropState()\n        return\n      }\n\n      let mouseAtExpandedNonLeafNode = false\n      if (mousePosition === 'inside') {\n        finalDropNode = node\n        finalDropPosition = 'inside'\n      }\n      else {\n        if (mousePosition === 'before') {\n          if (node.isFirstChild) {\n            finalDropNode = node\n            finalDropPosition = 'before'\n          }\n          else {\n            finalDropNode = fNodesRef.value[hoverNodeFIndex - 1]\n            finalDropPosition = 'after'\n          }\n        }\n        else {\n          finalDropNode = node\n          finalDropPosition = 'after'\n        }\n      }\n\n      // If the node is non-leaf and it is expanded, we don't allow it to\n      // drop after it and change it to drop before its next view sibling\n      if (\n        !finalDropNode.isLeaf\n        && mergedExpandedKeysRef.value.includes(finalDropNode.key)\n      ) {\n        mouseAtExpandedNonLeafNode = true\n        if (finalDropPosition === 'after') {\n          finalDropNode = fNodesRef.value[hoverNodeFIndex + 1]\n          if (!finalDropNode) {\n            // maybe there is no next view sibling when non-leaf node has no\n            // children and it is the last node in the tree\n            finalDropNode = node\n            finalDropPosition = 'inside'\n          }\n          else {\n            finalDropPosition = 'before'\n          }\n        }\n      }\n\n      const droppingMouseNode = finalDropNode\n\n      droppingMouseNodeRef.value = droppingMouseNode\n\n      // This is a speacial case, user is dragging a last child itself, so we\n      // only view it as they are trying to drop after it.\n      // There are some relevant codes in bailout 1's child branch.\n      // Also, the expand bailout should have a high priority. If it's non-leaf\n      // node and expanded, keep its origin drop position\n      if (\n        !mouseAtExpandedNonLeafNode\n        && draggingNode.isLastChild\n        && draggingNode.key === finalDropNode.key\n      ) {\n        finalDropPosition = 'after'\n      }\n\n      if (finalDropPosition === 'after') {\n        let offset = dragStartX - event.clientX // drag left => > 0\n        let offsetLevel = 0\n        while (\n          offset >= indent / 2 // divide by 2 to make it easier to trigger\n          && finalDropNode.parent !== null\n          && finalDropNode.isLastChild\n          && offsetLevel < 1\n        ) {\n          offset -= indent\n          offsetLevel += 1\n          finalDropNode = finalDropNode.parent\n        }\n        droppingOffsetLevelRef.value = offsetLevel\n      }\n      else {\n        droppingOffsetLevelRef.value = 0\n      }\n\n      // Bailout 1\n      // Drag self into self\n      // Drag it into direct parent\n      if (\n        draggingNode.contains(finalDropNode)\n        || (finalDropPosition === 'inside'\n          && draggingNode.parent?.key === finalDropNode.key)\n      ) {\n        if (\n          draggingNode.key === droppingMouseNode.key\n          && draggingNode.key === finalDropNode.key\n        ) {\n          // This is special case that we want ui to show a mark to guide user\n          // to start dragging. Nor they will think nothing happens.\n          // However this is an invalid drop, we need to guard it inside\n          // handleDrop\n        }\n        else {\n          resetDropState()\n          return\n        }\n      }\n\n      // Bailout 3\n      if (\n        !allowDrop({\n          node: finalDropNode.rawNode,\n          dropPosition: finalDropPosition,\n          phase: 'drag'\n        })\n      ) {\n        resetDropState()\n        return\n      }\n\n      if (draggingNode.key === finalDropNode.key) {\n        // don't expand when drag on itself\n        resetDragExpandState()\n      }\n      else {\n        if (nodeKeyToBeExpanded !== finalDropNode.key) {\n          if (finalDropPosition === 'inside') {\n            if (props.expandOnDragenter) {\n              expandDragEnterNode(finalDropNode)\n              // Bailout 4\n              // not try to loading\n              if (\n                !finalDropNode.shallowLoaded\n                && nodeKeyToBeExpanded !== finalDropNode.key\n              ) {\n                resetDndState()\n                return\n              }\n            }\n            else {\n              // Bailout 5\n              // never expands on drag\n              if (!finalDropNode.shallowLoaded) {\n                resetDndState()\n                return\n              }\n            }\n          }\n          else {\n            resetDragExpandState()\n          }\n        }\n        else {\n          if (finalDropPosition !== 'inside') {\n            resetDragExpandState()\n          }\n        }\n      }\n      droppingPositionRef.value = finalDropPosition\n      droppingNodeRef.value = finalDropNode\n    }\n    function handleDrop({ event, node, dropPosition }: InternalDropInfo): void {\n      if (\n        !props.draggable\n        || props.disabled\n        || isNodeDisabled(node, props.disabledField)\n      ) {\n        return\n      }\n      const { value: draggingNode } = draggingNodeRef\n      const { value: droppingNode } = droppingNodeRef\n      const { value: droppingPosition } = droppingPositionRef\n      if (!draggingNode || !droppingNode || !droppingPosition) {\n        return\n      }\n      // Bailout 1\n      if (\n        !props.allowDrop({\n          node: droppingNode.rawNode,\n          dropPosition: droppingPosition,\n          phase: 'drag'\n        })\n      ) {\n        return\n      }\n      // Bailout 2\n      // This is a special case to guard since we want ui to show the status\n      // but not to emit a event\n      if (draggingNode.key === droppingNode.key) {\n        return\n      }\n      // Bailout 3\n      // insert before its next node\n      // insert after its prev node\n      if (droppingPosition === 'before') {\n        const nextNode = draggingNode.getNext({ includeDisabled: true })\n        if (nextNode) {\n          if (nextNode.key === droppingNode.key) {\n            resetDropState()\n            return\n          }\n        }\n      }\n      if (droppingPosition === 'after') {\n        const prevNode = draggingNode.getPrev({ includeDisabled: true })\n        if (prevNode) {\n          if (prevNode.key === droppingNode.key) {\n            resetDropState()\n            return\n          }\n        }\n      }\n\n      doDrop({\n        event,\n        node: droppingNode.rawNode,\n        dragNode: draggingNode.rawNode,\n        dropPosition\n      })\n      resetDndState()\n    }\n    function handleScroll(): void {\n      syncScrollbar()\n    }\n    function handleResize(): void {\n      syncScrollbar()\n    }\n    function handleFocusout(e: FocusEvent): void {\n      if (props.virtualScroll || props.internalScrollable) {\n        const { value: scrollbarInst } = scrollbarInstRef\n        if (scrollbarInst?.containerRef?.contains(e.relatedTarget as Element)) {\n          return\n        }\n        pendingNodeKeyRef.value = null\n      }\n      else {\n        const { value: selfEl } = selfElRef\n        if (selfEl?.contains(e.relatedTarget as Element))\n          return\n        pendingNodeKeyRef.value = null\n      }\n    }\n    watch(pendingNodeKeyRef, (value) => {\n      if (value === null)\n        return\n      if (props.virtualScroll) {\n        virtualListInstRef.value?.scrollTo({ key: value })\n      }\n      else if (props.internalScrollable) {\n        const { value: scrollbarInst } = scrollbarInstRef\n        if (scrollbarInst === null)\n          return\n        const targetEl = scrollbarInst.contentRef?.querySelector(\n          `[data-key=\"${createDataKey(value)}\"]`\n        )\n        if (!targetEl)\n          return\n        scrollbarInst.scrollTo({\n          el: targetEl as any\n        })\n      }\n    })\n    provide(treeInjectionKey, {\n      loadingKeysRef,\n      highlightKeySetRef: mergedHighlightKeySetRef,\n      displayedCheckedKeysRef,\n      displayedIndeterminateKeysRef,\n      mergedSelectedKeysRef,\n      mergedExpandedKeysRef,\n      mergedThemeRef: themeRef,\n      mergedCheckStrategyRef,\n      nodePropsRef: toRef(props, 'nodeProps'),\n      disabledRef: toRef(props, 'disabled'),\n      checkableRef: toRef(props, 'checkable'),\n      selectableRef: toRef(props, 'selectable'),\n      expandOnClickRef: toRef(props, 'expandOnClick'),\n      onLoadRef: toRef(props, 'onLoad'),\n      draggableRef: toRef(props, 'draggable'),\n      blockLineRef: toRef(props, 'blockLine'),\n      indentRef: toRef(props, 'indent'),\n      cascadeRef: toRef(props, 'cascade'),\n      checkOnClickRef: toRef(props, 'checkOnClick'),\n      checkboxPlacementRef: props.checkboxPlacement,\n      droppingMouseNodeRef,\n      droppingNodeParentRef,\n      draggingNodeRef,\n      droppingPositionRef,\n      droppingOffsetLevelRef,\n      fNodesRef,\n      pendingNodeKeyRef,\n      showLineRef: toRef(props, 'showLine'),\n      disabledFieldRef: toRef(props, 'disabledField'),\n      internalScrollableRef: toRef(props, 'internalScrollable'),\n      internalCheckboxFocusableRef: toRef(props, 'internalCheckboxFocusable'),\n      internalTreeSelect: props.internalTreeSelect,\n      renderLabelRef: toRef(props, 'renderLabel'),\n      renderPrefixRef: toRef(props, 'renderPrefix'),\n      renderSuffixRef: toRef(props, 'renderSuffix'),\n      renderSwitcherIconRef: toRef(props, 'renderSwitcherIcon'),\n      labelFieldRef: toRef(props, 'labelField'),\n      multipleRef: toRef(props, 'multiple'),\n      overrideDefaultNodeClickBehaviorRef: toRef(\n        props,\n        'overrideDefaultNodeClickBehavior'\n      ),\n      spinPropsRef: toRef(props, 'spinProps'),\n      handleSwitcherClick,\n      handleDragEnd,\n      handleDragEnter,\n      handleDragLeave,\n      handleDragStart,\n      handleDrop,\n      handleDragOver,\n      handleSelect,\n      handleCheck\n    })\n    function scrollTo(\n      options: VirtualListScrollToOptions | number,\n      y?: number\n    ): void {\n      if (typeof options === 'number') {\n        virtualListInstRef.value?.scrollTo(options, y || 0)\n      }\n      else {\n        virtualListInstRef.value?.scrollTo(options)\n      }\n    }\n    const exposedMethods: InternalTreeInst & TreeInst = {\n      handleKeydown,\n      scrollTo,\n      getCheckedData: () => {\n        if (!props.checkable)\n          return { keys: [], options: [] }\n        const { checkedKeys } = checkedStatusRef.value\n        return {\n          keys: checkedKeys,\n          options: getOptionsByKeys(checkedKeys)\n        }\n      },\n      getIndeterminateData: () => {\n        if (!props.checkable)\n          return { keys: [], options: [] }\n        const { indeterminateKeys } = checkedStatusRef.value\n        return {\n          keys: indeterminateKeys,\n          options: getOptionsByKeys(indeterminateKeys)\n        }\n      }\n    }\n    const cssVarsRef = computed(() => {\n      const {\n        common: { cubicBezierEaseInOut },\n        self: {\n          fontSize,\n          nodeBorderRadius,\n          nodeColorHover,\n          nodeColorPressed,\n          nodeColorActive,\n          arrowColor,\n          loadingColor,\n          nodeTextColor,\n          nodeTextColorDisabled,\n          dropMarkColor,\n          nodeWrapperPadding,\n          nodeHeight,\n          lineHeight,\n          lineColor\n        }\n      } = themeRef.value\n      const lineOffsetTop = getPadding(nodeWrapperPadding, 'top')\n      const lineOffsetBottom = getPadding(nodeWrapperPadding, 'bottom')\n      const nodeContentHeight = pxfy(\n        depx(nodeHeight) - depx(lineOffsetTop) - depx(lineOffsetBottom)\n      )\n      return {\n        '--n-arrow-color': arrowColor,\n        '--n-loading-color': loadingColor,\n        '--n-bezier': cubicBezierEaseInOut,\n        '--n-font-size': fontSize,\n        '--n-node-border-radius': nodeBorderRadius,\n        '--n-node-color-active': nodeColorActive,\n        '--n-node-color-hover': nodeColorHover,\n        '--n-node-color-pressed': nodeColorPressed,\n        '--n-node-text-color': nodeTextColor,\n        '--n-node-text-color-disabled': nodeTextColorDisabled,\n        '--n-drop-mark-color': dropMarkColor,\n        '--n-node-wrapper-padding': nodeWrapperPadding,\n        '--n-line-offset-top': `-${lineOffsetTop}`,\n        '--n-line-offset-bottom': `-${lineOffsetBottom}`,\n        '--n-node-content-height': nodeContentHeight,\n        '--n-line-height': lineHeight,\n        '--n-line-color': lineColor\n      }\n    })\n    const themeClassHandle = inlineThemeDisabled\n      ? useThemeClass('tree', undefined, cssVarsRef, props)\n      : undefined\n    return {\n      ...exposedMethods,\n      mergedClsPrefix: mergedClsPrefixRef,\n      mergedTheme: themeRef,\n      mergedRenderEmpty: mergedRenderEmptyRef,\n      rtlEnabled: rtlEnabledRef,\n      fNodes: mergedFNodesRef,\n      aip: aipRef,\n      selfElRef,\n      virtualListInstRef,\n      scrollbarInstRef,\n      handleFocusout,\n      handleDragLeaveTree,\n      handleScroll,\n      getScrollContainer,\n      getScrollContent,\n      handleAfterEnter,\n      handleResize,\n      cssVars: inlineThemeDisabled ? undefined : cssVarsRef,\n      themeClass: themeClassHandle?.themeClass,\n      onRender: themeClassHandle?.onRender\n    }\n  },\n  render() {\n    const { fNodes, internalRenderEmpty } = this\n    if (!fNodes.length && internalRenderEmpty) {\n      return internalRenderEmpty()\n    }\n    const {\n      mergedClsPrefix,\n      blockNode,\n      blockLine,\n      draggable,\n      disabled,\n      ellipsis,\n      internalFocusable,\n      checkable,\n      handleKeydown,\n      rtlEnabled,\n      handleFocusout,\n      scrollbarProps\n    } = this\n    const mergedFocusable = internalFocusable && !disabled\n    const tabindex = mergedFocusable ? '0' : undefined\n    const treeClass: Array<string | boolean | undefined> = [\n      `${mergedClsPrefix}-tree`,\n      rtlEnabled && `${mergedClsPrefix}-tree--rtl`,\n      checkable && `${mergedClsPrefix}-tree--checkable`,\n      (blockLine || blockNode) && `${mergedClsPrefix}-tree--block-node`,\n      blockLine && `${mergedClsPrefix}-tree--block-line`,\n      ellipsis && `${mergedClsPrefix}-tree--ellipsis`\n    ]\n    const createNode = (tmNode: TmNode | MotionData): VNode => {\n      return '__motion' in tmNode ? (\n        <MotionWrapper\n          height={tmNode.height}\n          nodes={tmNode.nodes}\n          clsPrefix={mergedClsPrefix}\n          mode={tmNode.mode}\n          onAfterEnter={this.handleAfterEnter}\n        />\n      ) : (\n        <NTreeNode\n          key={tmNode.key}\n          tmNode={tmNode}\n          clsPrefix={mergedClsPrefix}\n        />\n      )\n    }\n    if (this.virtualScroll) {\n      const { mergedTheme, internalScrollablePadding } = this\n      const padding = getPadding(internalScrollablePadding || '0')\n      return (\n        <NxScrollbar\n          {...scrollbarProps}\n          ref=\"scrollbarInstRef\"\n          onDragleave={draggable ? this.handleDragLeaveTree : undefined}\n          container={this.getScrollContainer}\n          content={this.getScrollContent}\n          class={treeClass}\n          theme={mergedTheme.peers.Scrollbar}\n          themeOverrides={mergedTheme.peerOverrides.Scrollbar}\n          tabindex={tabindex}\n          onKeydown={mergedFocusable ? handleKeydown : undefined}\n          onFocusout={mergedFocusable ? handleFocusout : undefined}\n        >\n          {{\n            default: () => {\n              this.onRender?.()\n              return !fNodes.length ? (\n                resolveSlot(this.$slots.empty, () => {\n                  return [\n                    this.mergedRenderEmpty?.() || (\n                      <NEmpty\n                        class={`${mergedClsPrefix}-tree__empty`}\n                        theme={this.mergedTheme.peers.Empty}\n                        themeOverrides={this.mergedTheme.peerOverrides.Empty}\n                      />\n                    )\n                  ]\n                })\n              ) : (\n                <VVirtualList\n                  ref=\"virtualListInstRef\"\n                  items={this.fNodes}\n                  itemSize={depx(mergedTheme.self.nodeHeight)}\n                  ignoreItemResize={this.aip}\n                  paddingTop={padding.top}\n                  paddingBottom={padding.bottom}\n                  class={this.themeClass}\n                  style={[\n                    this.cssVars as CSSProperties,\n                    {\n                      paddingLeft: padding.left,\n                      paddingRight: padding.right\n                    }\n                  ]}\n                  onScroll={this.handleScroll}\n                  onResize={this.handleResize}\n                  showScrollbar={false}\n                  itemResizable\n                >\n                  {{\n                    default: ({ item }: { item: TmNode | MotionData }) =>\n                      createNode(item)\n                  }}\n                </VVirtualList>\n              )\n            }\n          }}\n        </NxScrollbar>\n      )\n    }\n    const { internalScrollable } = this\n    treeClass.push(this.themeClass)\n    this.onRender?.()\n    if (internalScrollable) {\n      return (\n        <NxScrollbar\n          {...scrollbarProps}\n          class={treeClass}\n          tabindex={tabindex}\n          onKeydown={mergedFocusable ? handleKeydown : undefined}\n          onFocusout={mergedFocusable ? handleFocusout : undefined}\n          style={this.cssVars as CSSProperties}\n          contentStyle={{ padding: this.internalScrollablePadding }}\n        >\n          {{\n            default: () => (\n              <div\n                onDragleave={draggable ? this.handleDragLeaveTree : undefined}\n                ref=\"selfElRef\"\n              >\n                {this.fNodes.map(createNode)}\n              </div>\n            )\n          }}\n        </NxScrollbar>\n      )\n    }\n    else {\n      return (\n        <div\n          class={treeClass}\n          tabindex={tabindex}\n          ref=\"selfElRef\"\n          style={this.cssVars as CSSProperties}\n          onKeydown={mergedFocusable ? handleKeydown : undefined}\n          onFocusout={mergedFocusable ? handleFocusout : undefined}\n          onDragleave={draggable ? this.handleDragLeaveTree : undefined}\n        >\n          {!fNodes.length\n            ? resolveSlot(this.$slots.empty, () => {\n                return [\n                  this.mergedRenderEmpty?.() || (\n                    <NEmpty\n                      class={`${mergedClsPrefix}-tree__empty`}\n                      theme={this.mergedTheme.peers.Empty}\n                      themeOverrides={this.mergedTheme.peerOverrides.Empty}\n                    />\n                  )\n                ]\n              })\n            : fNodes.map(createNode)}\n        </div>\n      )\n    }\n  }\n})\n"
  },
  {
    "path": "src/tree/src/TreeNode.tsx",
    "content": "import type { ComponentPublicInstance, PropType, VNode } from 'vue'\nimport type { TmNode } from './interface'\nimport { happensIn, repeat } from 'seemly'\nimport { useMemo } from 'vooks'\nimport { computed, defineComponent, h, inject, onMounted, ref } from 'vue'\nimport { createDataKey } from '../../_utils'\nimport { renderDropMark } from './dnd'\nimport { treeInjectionKey } from './interface'\nimport NTreeNodeCheckbox from './TreeNodeCheckbox'\nimport NTreeNodeContent from './TreeNodeContent'\nimport NTreeNodeSwitcher from './TreeNodeSwitcher'\nimport { isNodeDisabled } from './utils'\n\nconst TreeNode = defineComponent({\n  name: 'TreeNode',\n  props: {\n    clsPrefix: {\n      type: String,\n      required: true\n    },\n    tmNode: {\n      type: Object as PropType<TmNode>,\n      required: true\n    }\n  },\n  setup(props) {\n    const NTree = inject(treeInjectionKey)!\n    const {\n      droppingNodeParentRef,\n      droppingMouseNodeRef,\n      draggingNodeRef,\n      droppingPositionRef,\n      droppingOffsetLevelRef,\n      nodePropsRef,\n      indentRef,\n      blockLineRef,\n      checkboxPlacementRef,\n      checkOnClickRef,\n      disabledFieldRef,\n      showLineRef,\n      renderSwitcherIconRef,\n      overrideDefaultNodeClickBehaviorRef\n    } = NTree\n\n    const checkboxDisabledRef = useMemo(\n      () => !!props.tmNode.rawNode.checkboxDisabled\n    )\n\n    const nodeIsDisabledRef = useMemo(() => {\n      return isNodeDisabled(props.tmNode, disabledFieldRef.value)\n    })\n\n    const disabledRef = useMemo(\n      () => NTree.disabledRef.value || nodeIsDisabledRef.value\n    )\n\n    const resolvedNodePropsRef = computed(() => {\n      const { value: nodeProps } = nodePropsRef\n      if (!nodeProps)\n        return undefined\n      return nodeProps({\n        option: props.tmNode.rawNode\n      })\n    })\n\n    // used for drag and drop\n    const contentInstRef = ref<null | ComponentPublicInstance>(null)\n    // must be non-reactive\n    const contentElRef: { value: HTMLElement | null } = { value: null }\n\n    onMounted(() => {\n      contentElRef.value = contentInstRef.value!.$el as HTMLElement\n    })\n\n    function handleSwitcherClick(): void {\n      const callback = (): void => {\n        const { tmNode } = props\n        if (!tmNode.isLeaf && !tmNode.shallowLoaded) {\n          if (!NTree.loadingKeysRef.value.has(tmNode.key)) {\n            NTree.loadingKeysRef.value.add(tmNode.key)\n          }\n          else {\n            return\n          }\n          const {\n            onLoadRef: { value: onLoad }\n          } = NTree\n          if (onLoad) {\n            void onLoad(tmNode.rawNode)\n              .then((value) => {\n                if (value !== false) {\n                  NTree.handleSwitcherClick(tmNode)\n                }\n              })\n              .finally(() => {\n                NTree.loadingKeysRef.value.delete(tmNode.key)\n              })\n          }\n        }\n        else {\n          NTree.handleSwitcherClick(tmNode)\n        }\n      }\n      if (renderSwitcherIconRef.value) {\n        // if renderSwitcherIcon is set, icon dom may be altered before event\n        // bubbles to parent dom, so that target check fails. Call it in next\n        // event loop so that event bubble phase is finishes.\n        setTimeout(callback, 0)\n      }\n      else {\n        callback()\n      }\n    }\n\n    const selectableRef = useMemo(\n      () =>\n        !nodeIsDisabledRef.value\n        && NTree.selectableRef.value\n        && (NTree.internalTreeSelect\n          ? NTree.mergedCheckStrategyRef.value !== 'child'\n          || (NTree.multipleRef.value && NTree.cascadeRef.value)\n          || props.tmNode.isLeaf\n          : true)\n    )\n    const checkableRef = useMemo(\n      () =>\n        NTree.checkableRef.value\n        && (NTree.cascadeRef.value\n          || NTree.mergedCheckStrategyRef.value !== 'child'\n          || props.tmNode.isLeaf)\n    )\n\n    const checkedRef = useMemo(() =>\n      NTree.displayedCheckedKeysRef.value.includes(props.tmNode.key)\n    )\n\n    const mergedCheckOnClickRef = useMemo(() => {\n      const { value: checkable } = checkableRef\n      if (!checkable)\n        return false\n      const { value: checkOnClick } = checkOnClickRef\n      const { tmNode } = props\n      if (typeof checkOnClick === 'boolean') {\n        return !tmNode.disabled && checkOnClick\n      }\n      return checkOnClick(props.tmNode.rawNode)\n    })\n\n    function _handleClick(e: MouseEvent): void {\n      const { value: expandOnClick } = NTree.expandOnClickRef\n      const { value: selectable } = selectableRef\n      const { value: mergedCheckOnClick } = mergedCheckOnClickRef\n      if (!selectable && !expandOnClick && !mergedCheckOnClick)\n        return\n      if (happensIn(e, 'checkbox') || happensIn(e, 'switcher'))\n        return\n      const { tmNode } = props\n      if (selectable) {\n        NTree.handleSelect(tmNode)\n      }\n      if (expandOnClick && !tmNode.isLeaf) {\n        handleSwitcherClick()\n      }\n      if (mergedCheckOnClick) {\n        handleCheck(!checkedRef.value)\n      }\n    }\n\n    function handleNodeClick(e: PointerEvent): void {\n      if (happensIn(e, 'checkbox') || happensIn(e, 'switcher'))\n        return\n      if (!disabledRef.value) {\n        const overrideDefaultNodeClickBehavior\n          = overrideDefaultNodeClickBehaviorRef.value\n        let shouldOverride = false\n        if (overrideDefaultNodeClickBehavior) {\n          switch (\n            overrideDefaultNodeClickBehavior({ option: props.tmNode.rawNode })\n          ) {\n            case 'toggleCheck':\n              shouldOverride = true\n              handleCheck(!checkedRef.value)\n              break\n            case 'toggleSelect':\n              shouldOverride = true\n              NTree.handleSelect(props.tmNode)\n              break\n            case 'toggleExpand':\n              shouldOverride = true\n              handleSwitcherClick()\n              shouldOverride = true\n              break\n            case 'none':\n              shouldOverride = true\n              shouldOverride = true\n              return\n            case 'default':\n            default:\n              break\n          }\n        }\n        if (!shouldOverride) {\n          _handleClick(e)\n        }\n      }\n      resolvedNodePropsRef.value?.onClick?.(e)\n    }\n\n    function handleContentClick(e: PointerEvent): void {\n      if (blockLineRef.value)\n        return\n      handleNodeClick(e)\n    }\n\n    function handleLineClick(e: PointerEvent): void {\n      if (!blockLineRef.value)\n        return\n      handleNodeClick(e)\n    }\n\n    function handleCheck(checked: boolean): void {\n      NTree.handleCheck(props.tmNode, checked)\n    }\n    // Dnd\n    function handleDragStart(e: DragEvent): void {\n      NTree.handleDragStart({\n        event: e,\n        node: props.tmNode\n      })\n    }\n    function handleDragEnter(e: DragEvent): void {\n      if (e.currentTarget !== e.target) {\n        return\n      }\n      NTree.handleDragEnter({\n        event: e,\n        node: props.tmNode\n      })\n    }\n    function handleDragOver(e: DragEvent): void {\n      e.preventDefault() // if not prevent, drop event won't be fired...\n      NTree.handleDragOver({\n        event: e,\n        node: props.tmNode\n      })\n    }\n    function handleDragEnd(e: DragEvent): void {\n      NTree.handleDragEnd({\n        event: e,\n        node: props.tmNode\n      })\n    }\n    function handleDragLeave(e: DragEvent): void {\n      if (e.currentTarget !== e.target) {\n        return\n      }\n      NTree.handleDragLeave({\n        event: e,\n        node: props.tmNode\n      })\n    }\n    function handleDrop(e: DragEvent): void {\n      e.preventDefault()\n      if (droppingPositionRef.value !== null) {\n        NTree.handleDrop({\n          event: e,\n          node: props.tmNode,\n          dropPosition: droppingPositionRef.value\n        })\n      }\n    }\n    const indentNodes = computed(() => {\n      const { clsPrefix } = props\n      const { value: indent } = indentRef\n      if (showLineRef.value) {\n        const indentNodes: VNode[] = []\n        let cursor = props.tmNode.parent\n        while (cursor) {\n          if (cursor.isLastChild) {\n            indentNodes.push(\n              <div class={`${clsPrefix}-tree-node-indent`}>\n                <div style={{ width: `${indent}px` }} />\n              </div>\n            )\n          }\n          else {\n            indentNodes.push(\n              <div\n                class={[\n                  `${clsPrefix}-tree-node-indent`,\n                  `${clsPrefix}-tree-node-indent--show-line`\n                ]}\n              >\n                <div style={{ width: `${indent}px` }} />\n              </div>\n            )\n          }\n          cursor = cursor.parent\n        }\n        return indentNodes.reverse()\n      }\n      else {\n        return repeat(\n          props.tmNode.level,\n          <div class={`${props.clsPrefix}-tree-node-indent`}>\n            <div style={{ width: `${indent}px` }} />\n          </div>\n        )\n      }\n    })\n    return {\n      showDropMark: useMemo(() => {\n        const { value: draggingNode } = draggingNodeRef\n        if (!draggingNode)\n          return\n        const { value: droppingPosition } = droppingPositionRef\n        if (!droppingPosition)\n          return\n        const { value: droppingMouseNode } = droppingMouseNodeRef\n        if (!droppingMouseNode) {\n          return\n        }\n        const { tmNode } = props\n        if (tmNode.key === droppingMouseNode.key)\n          return true\n        return false\n      }),\n      showDropMarkAsParent: useMemo(() => {\n        const { value: droppingNodeParent } = droppingNodeParentRef\n        if (!droppingNodeParent)\n          return false\n        const { tmNode } = props\n        const { value: droppingPosition } = droppingPositionRef\n        if (droppingPosition === 'before' || droppingPosition === 'after') {\n          return droppingNodeParent.key === tmNode.key\n        }\n        return false\n      }),\n      pending: useMemo(\n        () => NTree.pendingNodeKeyRef.value === props.tmNode.key\n      ),\n      loading: useMemo(() => NTree.loadingKeysRef.value.has(props.tmNode.key)),\n      highlight: useMemo(() => {\n        return NTree.highlightKeySetRef.value?.has(props.tmNode.key)\n      }),\n      checked: checkedRef,\n      indeterminate: useMemo(() =>\n        NTree.displayedIndeterminateKeysRef.value.includes(props.tmNode.key)\n      ),\n      selected: useMemo(() =>\n        NTree.mergedSelectedKeysRef.value.includes(props.tmNode.key)\n      ),\n      expanded: useMemo(() =>\n        NTree.mergedExpandedKeysRef.value.includes(props.tmNode.key)\n      ),\n      disabled: disabledRef,\n      checkable: checkableRef,\n      mergedCheckOnClick: mergedCheckOnClickRef,\n      checkboxDisabled: checkboxDisabledRef,\n      selectable: selectableRef,\n      expandOnClick: NTree.expandOnClickRef,\n      internalScrollable: NTree.internalScrollableRef,\n      draggable: NTree.draggableRef,\n      blockLine: blockLineRef,\n      nodeProps: resolvedNodePropsRef,\n      checkboxFocusable: NTree.internalCheckboxFocusableRef,\n      droppingPosition: droppingPositionRef,\n      droppingOffsetLevel: droppingOffsetLevelRef,\n      indent: indentRef,\n      checkboxPlacement: checkboxPlacementRef,\n      showLine: showLineRef,\n      contentInstRef,\n      contentElRef,\n      indentNodes,\n      handleCheck,\n      handleDrop,\n      handleDragStart,\n      handleDragEnter,\n      handleDragOver,\n      handleDragEnd,\n      handleDragLeave,\n      handleLineClick,\n      handleContentClick,\n      handleSwitcherClick\n    }\n  },\n  render() {\n    const {\n      tmNode,\n      clsPrefix,\n      checkable,\n      expandOnClick,\n      selectable,\n      selected,\n      checked,\n      highlight,\n      draggable,\n      blockLine,\n      indent,\n      indentNodes,\n      disabled,\n      pending,\n      internalScrollable,\n      nodeProps,\n      checkboxPlacement\n    } = this\n    // drag start not inside\n    // it need to be append to node itself, not wrapper\n    const dragEventHandlers\n      = draggable && !disabled\n        ? {\n            onDragenter: this.handleDragEnter,\n            onDragleave: this.handleDragLeave,\n            onDragend: this.handleDragEnd,\n            onDrop: this.handleDrop,\n            onDragover: this.handleDragOver\n          }\n        : undefined\n    // In non virtual mode, there's no evidence that which element should be\n    // scrolled to, so we need data-key to query the target element.\n    const dataKey = internalScrollable ? createDataKey(tmNode.key) : undefined\n    const checkboxOnRight = checkboxPlacement === 'right'\n    const checkboxNode = checkable ? (\n      <NTreeNodeCheckbox\n        indent={indent}\n        right={checkboxOnRight}\n        focusable={this.checkboxFocusable}\n        disabled={disabled || this.checkboxDisabled}\n        clsPrefix={clsPrefix}\n        checked={this.checked}\n        indeterminate={this.indeterminate}\n        onCheck={this.handleCheck}\n      />\n    ) : null\n    return (\n      <div class={`${clsPrefix}-tree-node-wrapper`} {...dragEventHandlers}>\n        <div\n          {...(blockLine ? nodeProps : undefined)}\n          class={[\n            `${clsPrefix}-tree-node`,\n            {\n              [`${clsPrefix}-tree-node--selected`]: selected,\n              [`${clsPrefix}-tree-node--checkable`]: checkable,\n              [`${clsPrefix}-tree-node--highlight`]: highlight,\n              [`${clsPrefix}-tree-node--pending`]: pending,\n              [`${clsPrefix}-tree-node--disabled`]: disabled,\n              [`${clsPrefix}-tree-node--selectable`]: selectable,\n              [`${clsPrefix}-tree-node--clickable`]:\n                selectable || expandOnClick || this.mergedCheckOnClick\n            },\n            nodeProps?.class\n          ]}\n          data-key={dataKey}\n          draggable={draggable && blockLine}\n          onClick={this.handleLineClick}\n          onDragstart={\n            draggable && blockLine && !disabled\n              ? this.handleDragStart\n              : undefined\n          }\n        >\n          {indentNodes}\n          {tmNode.isLeaf && this.showLine ? (\n            <div\n              class={[\n                `${clsPrefix}-tree-node-indent`,\n                `${clsPrefix}-tree-node-indent--show-line`,\n                tmNode.isLeaf && `${clsPrefix}-tree-node-indent--is-leaf`,\n                tmNode.isLastChild\n                && `${clsPrefix}-tree-node-indent--last-child`\n              ]}\n            >\n              <div style={{ width: `${indent}px` }} />\n            </div>\n          ) : (\n            <NTreeNodeSwitcher\n              clsPrefix={clsPrefix}\n              expanded={this.expanded}\n              selected={selected}\n              loading={this.loading}\n              hide={tmNode.isLeaf}\n              tmNode={this.tmNode}\n              indent={indent}\n              onClick={this.handleSwitcherClick}\n            />\n          )}\n          {!checkboxOnRight ? checkboxNode : null}\n          <NTreeNodeContent\n            ref=\"contentInstRef\"\n            clsPrefix={clsPrefix}\n            checked={checked}\n            selected={selected}\n            onClick={this.handleContentClick}\n            nodeProps={blockLine ? undefined : nodeProps}\n            onDragstart={\n              draggable && !blockLine && !disabled\n                ? this.handleDragStart\n                : undefined\n            }\n            tmNode={tmNode}\n          />\n          {draggable\n            ? this.showDropMark\n              ? renderDropMark({\n                  el: this.contentElRef.value!,\n                  position: this.droppingPosition!,\n                  offsetLevel: this.droppingOffsetLevel,\n                  indent\n                })\n              : this.showDropMarkAsParent\n                ? renderDropMark({\n                    el: this.contentElRef.value!,\n                    position: 'inside',\n                    offsetLevel: this.droppingOffsetLevel,\n                    indent\n                  })\n                : null\n            : null}\n          {checkboxOnRight ? checkboxNode : null}\n        </div>\n      </div>\n    )\n  }\n})\n\nexport default TreeNode\n"
  },
  {
    "path": "src/tree/src/TreeNodeCheckbox.tsx",
    "content": "import type { PropType } from 'vue'\nimport { defineComponent, h, inject } from 'vue'\nimport { NCheckbox } from '../../checkbox'\nimport { treeInjectionKey } from './interface'\n\nexport default defineComponent({\n  name: 'NTreeNodeCheckbox',\n  props: {\n    clsPrefix: {\n      type: String,\n      required: true\n    },\n    indent: {\n      type: Number,\n      required: true\n    },\n    right: Boolean,\n    focusable: Boolean,\n    disabled: Boolean,\n    checked: Boolean,\n    indeterminate: Boolean,\n    onCheck: Function as PropType<(value: boolean) => void>\n  },\n  setup(props) {\n    const NTree = inject(treeInjectionKey)!\n    function doCheck(value: boolean): void {\n      const { onCheck } = props\n      if (onCheck) {\n        onCheck(value)\n      }\n    }\n    function handleUpdateValue(value: boolean): void {\n      doCheck(value)\n    }\n    return {\n      handleUpdateValue,\n      mergedTheme: NTree.mergedThemeRef\n    }\n  },\n  render() {\n    const {\n      clsPrefix,\n      mergedTheme,\n      checked,\n      indeterminate,\n      disabled,\n      focusable,\n      indent,\n      handleUpdateValue\n    } = this\n    return (\n      <span\n        class={[\n          `${clsPrefix}-tree-node-checkbox`,\n          this.right && `${clsPrefix}-tree-node-checkbox--right`\n        ]}\n        style={{\n          width: `${indent}px`\n        }}\n        data-checkbox\n      >\n        <NCheckbox\n          focusable={focusable}\n          disabled={disabled}\n          theme={mergedTheme.peers.Checkbox}\n          themeOverrides={mergedTheme.peerOverrides.Checkbox}\n          checked={checked}\n          indeterminate={indeterminate}\n          onUpdateChecked={handleUpdateValue}\n        />\n      </span>\n    )\n  }\n})\n"
  },
  {
    "path": "src/tree/src/TreeNodeContent.tsx",
    "content": "import type { HTMLAttributes, PropType } from 'vue'\nimport type { TmNode } from './interface'\nimport { defineComponent, h, inject, ref } from 'vue'\nimport { render } from '../../_utils'\nimport { treeInjectionKey } from './interface'\n\nexport default defineComponent({\n  name: 'TreeNodeContent',\n  props: {\n    clsPrefix: {\n      type: String,\n      required: true\n    },\n    disabled: Boolean,\n    checked: Boolean,\n    selected: Boolean,\n    onClick: Function as PropType<(e: PointerEvent) => void>,\n    onDragstart: Function as PropType<(e: DragEvent) => void>,\n    tmNode: {\n      type: Object as PropType<TmNode>,\n      required: true\n    },\n    nodeProps: Object as PropType<HTMLAttributes>\n  },\n  setup(props) {\n    const { renderLabelRef, renderPrefixRef, renderSuffixRef, labelFieldRef }\n      = inject(treeInjectionKey)!\n    const selfRef = ref<HTMLElement | null>(null)\n    function doClick(e: PointerEvent): void {\n      const { onClick } = props\n      if (onClick)\n        onClick(e)\n    }\n    function handleClick(e: PointerEvent): void {\n      doClick(e)\n    }\n    return {\n      selfRef,\n      renderLabel: renderLabelRef,\n      renderPrefix: renderPrefixRef,\n      renderSuffix: renderSuffixRef,\n      labelField: labelFieldRef,\n      handleClick\n    }\n  },\n  render() {\n    const {\n      clsPrefix,\n      labelField,\n      nodeProps,\n      checked = false,\n      selected = false,\n      renderLabel,\n      renderPrefix,\n      renderSuffix,\n      handleClick,\n      onDragstart,\n      tmNode: {\n        rawNode,\n        rawNode: { prefix, suffix, [labelField]: label }\n      }\n    } = this\n    return (\n      <span\n        {...nodeProps}\n        ref=\"selfRef\"\n        class={[`${clsPrefix}-tree-node-content`, nodeProps?.class]}\n        onClick={handleClick}\n        draggable={onDragstart === undefined ? undefined : true}\n        onDragstart={onDragstart}\n      >\n        {renderPrefix || prefix ? (\n          <div class={`${clsPrefix}-tree-node-content__prefix`}>\n            {renderPrefix\n              ? renderPrefix({\n                  option: rawNode,\n                  selected,\n                  checked\n                })\n              : render(prefix)}\n          </div>\n        ) : null}\n        <div class={`${clsPrefix}-tree-node-content__text`}>\n          {renderLabel\n            ? renderLabel({\n                option: rawNode,\n                selected,\n                checked\n              })\n            : render(label)}\n        </div>\n        {renderSuffix || suffix ? (\n          <div class={`${clsPrefix}-tree-node-content__suffix`}>\n            {renderSuffix\n              ? renderSuffix({\n                  option: rawNode,\n                  selected,\n                  checked\n                })\n              : render(suffix)}\n          </div>\n        ) : null}\n      </span>\n    )\n  }\n})\n"
  },
  {
    "path": "src/tree/src/TreeNodeSwitcher.tsx",
    "content": "import type { PropType } from 'vue'\nimport type { TmNode } from './interface'\nimport { defineComponent, h, inject } from 'vue'\nimport { NBaseIcon, NBaseLoading, NIconSwitchTransition } from '../../_internal'\nimport { SwitcherIcon } from '../../_internal/icons'\nimport { treeInjectionKey } from './interface'\n\nexport default defineComponent({\n  name: 'NTreeSwitcher',\n  props: {\n    clsPrefix: {\n      type: String,\n      required: true\n    },\n    indent: { type: Number, required: true },\n    expanded: Boolean,\n    selected: Boolean,\n    hide: Boolean,\n    loading: Boolean,\n    onClick: Function as PropType<(e: MouseEvent) => void>,\n    tmNode: {\n      type: Object as PropType<TmNode>,\n      required: true\n    }\n  },\n  setup(props) {\n    const { renderSwitcherIconRef, spinPropsRef } = inject(\n      treeInjectionKey,\n      null\n    )!\n    return () => {\n      const { clsPrefix, expanded, hide, indent, onClick } = props\n      return (\n        <span\n          data-switcher\n          class={[\n            `${clsPrefix}-tree-node-switcher`,\n            expanded && `${clsPrefix}-tree-node-switcher--expanded`,\n            hide && `${clsPrefix}-tree-node-switcher--hide`\n          ]}\n          style={{ width: `${indent}px` }}\n          onClick={onClick}\n        >\n          <div class={`${clsPrefix}-tree-node-switcher__icon`}>\n            <NIconSwitchTransition>\n              {{\n                default: () => {\n                  if (props.loading) {\n                    return (\n                      <NBaseLoading\n                        clsPrefix={clsPrefix}\n                        key=\"loading\"\n                        radius={85}\n                        strokeWidth={20}\n                        {...spinPropsRef?.value}\n                      />\n                    )\n                  }\n                  const { value: renderSwitcherIcon } = renderSwitcherIconRef\n                  return renderSwitcherIcon ? (\n                    renderSwitcherIcon({\n                      expanded: props.expanded,\n                      selected: props.selected,\n                      option: props.tmNode.rawNode\n                    })\n                  ) : (\n                    <NBaseIcon clsPrefix={clsPrefix} key=\"switcher\">\n                      {{ default: () => <SwitcherIcon /> }}\n                    </NBaseIcon>\n                  )\n                }\n              }}\n            </NIconSwitchTransition>\n          </div>\n        </span>\n      )\n    }\n  }\n})\n"
  },
  {
    "path": "src/tree/src/dnd.tsx",
    "content": "import type { CSSProperties, VNode } from 'vue'\nimport type { DropPosition, TreeOption } from './interface'\nimport { h } from 'vue'\n\nexport function renderDropMark({\n  position,\n  offsetLevel,\n  indent,\n  el\n}: {\n  position: 'before' | 'inside' | 'after'\n  offsetLevel: number\n  indent: number\n  el: HTMLElement\n}): VNode {\n  const style: CSSProperties = {\n    position: 'absolute',\n    boxSizing: 'border-box',\n    right: 0\n  }\n  if (position === 'inside') {\n    style.left = 0\n    style.top = 0\n    style.bottom = 0\n    style.borderRadius = 'inherit'\n    style.boxShadow = 'inset 0 0 0 2px var(--n-drop-mark-color)'\n  }\n  else {\n    const cssPosition = position === 'before' ? 'top' : 'bottom'\n    style[cssPosition] = 0\n    // The left prop should be modified when tree's style is changed\n    // Maybe it is possible to use content left\n    style.left = `${el.offsetLeft + 6 - offsetLevel * indent}px`\n    style.height = '2px'\n    style.backgroundColor = 'var(--n-drop-mark-color)'\n    style.transformOrigin = cssPosition\n    style.borderRadius = '1px'\n    style.transform\n      = position === 'before' ? 'translateY(-4px)' : 'translateY(4px)'\n  }\n  return <div style={style} />\n}\n\nexport function defaultAllowDrop({\n  dropPosition,\n  node\n}: {\n  dropPosition: DropPosition\n  node: TreeOption\n}): boolean {\n  if (node.isLeaf === false)\n    return true\n  if (node.children) {\n    return true\n  }\n  return dropPosition !== 'inside'\n}\n"
  },
  {
    "path": "src/tree/src/interface.ts",
    "content": "import type { CheckStrategy, TreeNode } from 'treemate'\nimport type { HTMLAttributes, Ref, VNodeChild } from 'vue'\nimport type { VirtualListScrollTo } from 'vueuc'\nimport type { MergedTheme } from '../../_mixins'\nimport type { TreeTheme } from '../styles'\nimport type { TreeSpinProps } from './public-types'\nimport { createInjectionKey } from '../../_utils'\n\nexport type Key = string | number\n\nexport type OnLoad = (node: TreeOption) => Promise<unknown>\n\nexport interface TreeOptionBase {\n  key?: Key\n  label?: string\n  checkboxDisabled?: boolean\n  disabled?: boolean\n  isLeaf?: boolean\n  children?: TreeOption[]\n  prefix?: () => VNodeChild\n  suffix?: () => VNodeChild\n}\n\nexport type TreeOption = TreeOptionBase & Record<string, unknown>\n\nexport type TreeOptions = TreeOption[]\n\nexport interface TreeRenderProps {\n  option: TreeOption\n  checked: boolean\n  selected: boolean\n}\n\ntype RenderTreePart = ({\n  option,\n  checked,\n  selected\n}: TreeRenderProps) => VNodeChild\n\nexport type RenderLabel = RenderTreePart\n\nexport type RenderPrefix = RenderTreePart\n\nexport type RenderSuffix = RenderTreePart\n\nexport type TreeOverrideNodeClickBehaviorReturn\n  = | 'toggleSelect'\n    | 'toggleExpand'\n    | 'toggleCheck'\n    | 'default'\n    | 'none'\n\nexport type TreeOverrideNodeClickBehavior = (info: {\n  option: TreeOption\n}) => TreeOverrideNodeClickBehaviorReturn\n\nexport type TreeNodeProps = (info: {\n  option: TreeOption\n}) => HTMLAttributes & Record<string, unknown>\n\nexport interface TreeDragInfo {\n  event: DragEvent\n  node: TreeOption\n}\n\nexport interface TreeDropInfo {\n  event: DragEvent\n  node: TreeOption\n  dragNode: TreeOption\n  dropPosition: 'before' | 'inside' | 'after'\n}\n\nexport interface InternalDragInfo {\n  event: DragEvent\n  node: TmNode\n}\n\nexport type DropPosition = 'before' | 'inside' | 'after'\n\nexport type AllowDrop = (info: {\n  dropPosition: DropPosition\n  node: TreeOption\n  phase: 'drag' | 'drop'\n}) => boolean\n\nexport interface InternalDropInfo {\n  event: DragEvent\n  node: TmNode\n  dropPosition: DropPosition\n}\n\nexport type RenderSwitcherIcon = (props: {\n  expanded: boolean\n  selected: boolean\n  option: TreeOption\n}) => VNodeChild\n\nexport type CheckOnClick = (option: TreeOption) => boolean\n\nexport interface TreeInjection {\n  loadingKeysRef: Ref<Set<Key>>\n  highlightKeySetRef: Ref<Set<Key> | null>\n  displayedCheckedKeysRef: Ref<Key[]>\n  displayedIndeterminateKeysRef: Ref<Key[]>\n  mergedSelectedKeysRef: Ref<Key[]>\n  mergedExpandedKeysRef: Ref<Key[]>\n  fNodesRef: Ref<Array<TreeNode<TreeOption>>>\n  draggableRef: Ref<boolean>\n  mergedThemeRef: Ref<MergedTheme<TreeTheme>>\n  onLoadRef: Ref<OnLoad | undefined>\n  blockLineRef: Ref<boolean>\n  indentRef: Ref<number>\n  draggingNodeRef: Ref<TmNode | null>\n  droppingMouseNodeRef: Ref<TmNode | null>\n  droppingNodeParentRef: Ref<TmNode | null>\n  droppingPositionRef: Ref<null | DropPosition>\n  droppingOffsetLevelRef: Ref<number>\n  disabledRef: Ref<boolean>\n  checkableRef: Ref<boolean>\n  cascadeRef: Ref<boolean>\n  mergedCheckStrategyRef: Ref<CheckStrategy>\n  selectableRef: Ref<boolean>\n  expandOnClickRef: Ref<boolean>\n  pendingNodeKeyRef: Ref<null | Key>\n  internalScrollableRef: Ref<boolean>\n  internalCheckboxFocusableRef: Ref<boolean>\n  renderLabelRef: Ref<RenderLabel | undefined>\n  renderPrefixRef: Ref<RenderPrefix | undefined>\n  renderSuffixRef: Ref<RenderSuffix | undefined>\n  renderSwitcherIconRef: Ref<RenderSwitcherIcon | undefined>\n  labelFieldRef: Ref<string>\n  nodePropsRef: Ref<TreeNodeProps | undefined>\n  multipleRef: Ref<boolean>\n  checkboxPlacementRef: 'left' | 'right'\n  internalTreeSelect: boolean\n  checkOnClickRef: Ref<boolean | CheckOnClick>\n  disabledFieldRef: Ref<string>\n  showLineRef: Ref<boolean>\n  overrideDefaultNodeClickBehaviorRef: Ref<\n    TreeOverrideNodeClickBehavior | undefined\n  >\n  spinPropsRef: Ref<TreeSpinProps | undefined>\n  handleSwitcherClick: (node: TreeNode<TreeOption>) => void\n  handleSelect: (node: TreeNode<TreeOption>) => void\n  handleCheck: (node: TreeNode<TreeOption>, checked: boolean) => void\n  handleDragStart: (info: InternalDragInfo) => void\n  handleDragEnter: (info: InternalDragInfo) => void\n  handleDragLeave: (info: InternalDragInfo) => void\n  handleDragEnd: (info: InternalDragInfo) => void\n  handleDragOver: (info: InternalDragInfo) => void\n  handleDrop: (info: InternalDropInfo) => void\n}\n\nexport const treeInjectionKey = createInjectionKey<TreeInjection>('n-tree')\n\nexport type TmNode = TreeNode<TreeOption>\n\nexport interface MotionData {\n  __motion: true\n  height: number | undefined\n  mode: 'expand' | 'collapse'\n  nodes: TmNode[]\n}\n\nexport interface InternalTreeInst {\n  handleKeydown: (e: KeyboardEvent) => {\n    enterBehavior: TreeOverrideNodeClickBehaviorReturn | null\n  }\n}\n\nexport interface TreeInst {\n  scrollTo: VirtualListScrollTo\n  getCheckedData: () => { keys: Key[], options: Array<TreeOption | null> }\n  getIndeterminateData: () => { keys: Key[], options: Array<TreeOption | null> }\n}\n\nexport type GetChildren = (option: any) => unknown\n"
  },
  {
    "path": "src/tree/src/keyboard.tsx",
    "content": "import type { TreeNode } from 'treemate'\nimport type { Ref } from 'vue'\nimport type {\n  Key,\n  TmNode,\n  TreeOption,\n  TreeOverrideNodeClickBehavior,\n  TreeOverrideNodeClickBehaviorReturn\n} from './interface'\nimport { inject, ref } from 'vue'\nimport { treeSelectInjectionKey } from '../../tree-select/src/interface'\n\nexport function useKeyboard({\n  props,\n  fNodesRef,\n  mergedExpandedKeysRef,\n  mergedSelectedKeysRef,\n  mergedCheckedKeysRef,\n  handleCheck,\n  handleSelect,\n  handleSwitcherClick\n}: {\n  props: {\n    keyboard: boolean\n    overrideDefaultNodeClickBehavior: TreeOverrideNodeClickBehavior | undefined\n  }\n  fNodesRef: Ref<Array<TreeNode<TreeOption>>>\n  mergedExpandedKeysRef: Ref<Key[]>\n  mergedSelectedKeysRef: Ref<Key[]>\n  mergedCheckedKeysRef: Ref<Key[]>\n  handleSelect: (node: TmNode) => void\n  handleSwitcherClick: (node: TmNode) => void\n  handleCheck: (node: TmNode, checked: boolean) => void\n}): {\n  pendingNodeKeyRef: Ref<null | Key>\n  handleKeydown: (e: KeyboardEvent) => {\n    enterBehavior: TreeOverrideNodeClickBehaviorReturn | null\n  }\n} {\n  const { value: mergedSelectedKeys } = mergedSelectedKeysRef\n\n  // If it's used in tree-select, make it take over pending state\n  const treeSelectInjection = inject(treeSelectInjectionKey, null)\n  const pendingNodeKeyRef = treeSelectInjection\n    ? treeSelectInjection.pendingNodeKeyRef\n    : ref<null | Key>(\n        mergedSelectedKeys.length\n          ? mergedSelectedKeys[mergedSelectedKeys.length - 1]\n          : null\n      )\n  function handleKeydown(e: KeyboardEvent): {\n    enterBehavior: TreeOverrideNodeClickBehaviorReturn | null\n  } {\n    if (!props.keyboard)\n      return { enterBehavior: null }\n    const { value: pendingNodeKey } = pendingNodeKeyRef\n    let enterBehavior: TreeOverrideNodeClickBehaviorReturn | null = null\n    if (pendingNodeKey === null) {\n      if (e.key === 'ArrowDown' || e.key === 'ArrowUp') {\n        e.preventDefault()\n      }\n      if (['ArrowDown', 'ArrowUp', 'ArrowLeft', 'ArrowRight'].includes(e.key)) {\n        if (pendingNodeKey === null) {\n          const { value: fNodes } = fNodesRef\n          let fIndex = 0\n          while (fIndex < fNodes.length) {\n            if (!fNodes[fIndex].disabled) {\n              pendingNodeKeyRef.value = fNodes[fIndex].key\n              break\n            }\n            fIndex += 1\n          }\n        }\n      }\n    }\n    else {\n      const { value: fNodes } = fNodesRef\n      let fIndex = fNodes.findIndex(tmNode => tmNode.key === pendingNodeKey)\n      if (!~fIndex)\n        return { enterBehavior: null }\n      if (e.key === 'Enter') {\n        const tmNode = fNodes[fIndex]\n        enterBehavior\n          = props.overrideDefaultNodeClickBehavior?.({\n            option: tmNode.rawNode\n          }) || null\n        switch (enterBehavior) {\n          case 'toggleCheck':\n            handleCheck(\n              tmNode,\n              !mergedCheckedKeysRef.value.includes(tmNode.key)\n            )\n            break\n          case 'toggleSelect':\n            handleSelect(tmNode)\n            break\n          case 'toggleExpand':\n            handleSwitcherClick(tmNode)\n            break\n          case 'none':\n            break\n          case 'default':\n          default:\n            enterBehavior = 'default'\n            handleSelect(tmNode)\n        }\n      }\n      else if (e.key === 'ArrowDown') {\n        e.preventDefault()\n        fIndex += 1\n        while (fIndex < fNodes.length) {\n          if (!fNodes[fIndex].disabled) {\n            pendingNodeKeyRef.value = fNodes[fIndex].key\n            break\n          }\n          fIndex += 1\n        }\n      }\n      else if (e.key === 'ArrowUp') {\n        e.preventDefault()\n        fIndex -= 1\n        while (fIndex >= 0) {\n          if (!fNodes[fIndex].disabled) {\n            pendingNodeKeyRef.value = fNodes[fIndex].key\n            break\n          }\n          fIndex -= 1\n        }\n      }\n      else if (e.key === 'ArrowLeft') {\n        const pendingNode = fNodes[fIndex]\n        if (\n          pendingNode.isLeaf\n          || !mergedExpandedKeysRef.value.includes(pendingNodeKey)\n        ) {\n          const parentTmNode = pendingNode.getParent()\n          if (parentTmNode) {\n            pendingNodeKeyRef.value = parentTmNode.key\n          }\n        }\n        else {\n          handleSwitcherClick(pendingNode)\n        }\n      }\n      else if (e.key === 'ArrowRight') {\n        const pendingNode = fNodes[fIndex]\n        if (pendingNode.isLeaf)\n          return { enterBehavior: null }\n        if (!mergedExpandedKeysRef.value.includes(pendingNodeKey)) {\n          handleSwitcherClick(pendingNode)\n        }\n        else {\n          // Tha same as ArrowDown\n          fIndex += 1\n          while (fIndex < fNodes.length) {\n            if (!fNodes[fIndex].disabled) {\n              pendingNodeKeyRef.value = fNodes[fIndex].key\n              break\n            }\n            fIndex += 1\n          }\n        }\n      }\n    }\n    return {\n      enterBehavior\n    }\n  }\n  return {\n    pendingNodeKeyRef,\n    handleKeydown\n  }\n}\n"
  },
  {
    "path": "src/tree/src/public-types.ts",
    "content": "import type { SharedSpinProps } from '../../_internal'\n\nexport type TreeSpinProps = SharedSpinProps\n"
  },
  {
    "path": "src/tree/src/styles/index.cssr.ts",
    "content": "import { fadeInHeightExpandTransition } from '../../../_styles/transitions/fade-in-height-expand.cssr'\nimport { iconSwitchTransition } from '../../../_styles/transitions/icon-switch.cssr'\nimport { c, cB, cE, cM, cNotM } from '../../../_utils/cssr'\n\nconst iconSwitchTransitionNode = iconSwitchTransition()\n\n// vars:\n// --n-arrow-color\n// --n-bezier\n// --n-font-size\n// --n-node-border-radius\n// --n-node-color-active\n// --n-node-color-hover\n// --n-node-color-pressed\n// --n-node-text-color\n// --n-node-text-color-disabled\n// --n-node-wrapper-padding\n// --n-line-offset-top\n// --n-line-offset-bottom\n// --n-node-content-height\n// --n-line-height\n// --n-line-color\nexport default cB('tree', `\n  font-size: var(--n-font-size);\n  outline: none;\n`, [\n  c('ul, li', `\n    margin: 0;\n    padding: 0;\n    list-style: none;\n  `),\n  c('>', [\n    cB('tree-node', [\n      c('&:first-child', 'margin-top: 0;')\n    ])\n  ]),\n  cB('tree-motion-wrapper', [\n    cM('expand', [\n      fadeInHeightExpandTransition({\n        duration: '0.2s'\n      })\n    ]),\n    cM('collapse', [\n      fadeInHeightExpandTransition({\n        duration: '0.2s',\n        reverse: true\n      })\n    ])\n  ]),\n  cB('tree-node-wrapper', `\n    box-sizing: border-box;\n    padding: var(--n-node-wrapper-padding);\n  `),\n  cB('tree-node', `\n    position: relative;\n    display: flex;\n    border-radius: var(--n-node-border-radius);\n    transition: background-color .3s var(--n-bezier);\n  `, [\n    cM('highlight', [\n      cB('tree-node-content', [\n        cE('text', 'border-bottom-color: var(--n-node-text-color-disabled);')\n      ])\n    ]),\n    cM('disabled', [\n      cB('tree-node-content', `\n        color: var(--n-node-text-color-disabled);\n        cursor: not-allowed;\n      `)\n    ]),\n    cNotM('disabled', [\n      cM('clickable', [\n        cB('tree-node-content', `\n          cursor: pointer;\n        `)\n      ])\n    ])\n  ]),\n  cM('block-node', [\n    cB('tree-node-content', `\n      flex: 1;\n      min-width: 0;\n    `)\n  ]),\n  cNotM('block-line', [\n    cB('tree-node', [\n      cNotM('disabled', [\n        cB('tree-node-content', [\n          c('&:hover', 'background: var(--n-node-color-hover);')\n        ]),\n        cM('selectable', [\n          cB('tree-node-content', [\n            c('&:active', 'background: var(--n-node-color-pressed);')\n          ])\n        ]),\n        cM('pending', [\n          cB('tree-node-content', `\n            background: var(--n-node-color-hover);\n          `)\n        ]),\n        cM('selected', [\n          cB('tree-node-content', 'background: var(--n-node-color-active);')\n        ])\n      ]),\n      cM('selected', [\n        cB('tree-node-content', 'background: var(--n-node-color-active);')\n      ])\n    ])\n  ]),\n  cM('block-line', [\n    cB('tree-node', [\n      cNotM('disabled', [\n        c('&:hover', 'background: var(--n-node-color-hover);'),\n        cM('pending', `\n          background: var(--n-node-color-hover);\n        `),\n        cM('selectable', [\n          cNotM('selected', [\n            c('&:active', 'background: var(--n-node-color-pressed);')\n          ])\n        ]),\n        cM('selected', 'background: var(--n-node-color-active);')\n      ]),\n      cM('selected', 'background: var(--n-node-color-active);'),\n      cM('disabled', `\n        cursor: not-allowed;\n      `)\n    ])\n  ]),\n  cM('ellipsis', [\n    cB('tree-node', [\n      cB('tree-node-content', `\n        overflow: hidden;\n      `, [\n        cE('text', `\n          text-overflow: ellipsis;\n          white-space: nowrap;\n          overflow: hidden;\n        `)\n      ])\n    ])\n  ]),\n  cB('tree-node-indent', `\n    flex-grow: 0;\n    flex-shrink: 0;\n  `, [\n    cM('show-line', 'position: relative', [\n      c('&::before', `\n        position: absolute;\n        left: 50%;\n        border-left: 1px solid var(--n-line-color);\n        transition: border-color .3s var(--n-bezier);\n        transform: translate(-50%);\n        content: \"\";\n        top: var(--n-line-offset-top);\n        bottom: var(--n-line-offset-bottom);\n      `),\n      cM('last-child', [\n        c('&::before', `\n          bottom: 50%;\n        `)\n      ]),\n      cM('is-leaf', [\n        c('&::after', `\n          position: absolute;\n          content: \"\";\n          left: calc(50% + 0.5px);\n          right: 0;\n          bottom: 50%;\n          transition: border-color .3s var(--n-bezier);\n          border-bottom: 1px solid var(--n-line-color);\n        `)\n      ])\n    ]),\n    cNotM('show-line', 'height: 0;')\n  ]),\n  cB('tree-node-switcher', `\n    cursor: pointer;\n    display: inline-flex;\n    flex-shrink: 0;\n    height: var(--n-node-content-height);\n    align-items: center;\n    justify-content: center;\n    transition: transform .15s var(--n-bezier);\n    vertical-align: bottom;\n  `, [\n    cE('icon', `\n      position: relative;\n      height: 14px;\n      width: 14px;\n      display: flex;\n      color: var(--n-arrow-color);\n      transition: color .3s var(--n-bezier);\n      font-size: 14px;\n    `, [\n      cB('icon', [\n        iconSwitchTransitionNode\n      ]),\n      cB('base-loading', `\n        color: var(--n-loading-color);\n        position: absolute;\n        left: 0;\n        top: 0;\n        right: 0;\n        bottom: 0;\n      `, [\n        iconSwitchTransitionNode\n      ]),\n      cB('base-icon', [\n        iconSwitchTransitionNode\n      ])\n    ]),\n    cM('hide', 'visibility: hidden;'),\n    cM('expanded', 'transform: rotate(90deg);')\n  ]),\n  cB('tree-node-checkbox', `\n    display: inline-flex;\n    height: var(--n-node-content-height);\n    vertical-align: bottom;\n    align-items: center;\n    justify-content: center;\n  `),\n  cB('tree-node-content', `\n    user-select: none;\n    position: relative;\n    display: inline-flex;\n    align-items: center;\n    min-height: var(--n-node-content-height);\n    box-sizing: border-box;\n    line-height: var(--n-line-height);\n    vertical-align: bottom;\n    padding: 0 6px 0 4px;\n    cursor: default;\n    border-radius: var(--n-node-border-radius);\n    color: var(--n-node-text-color);\n    transition:\n      color .3s var(--n-bezier),\n      background-color .3s var(--n-bezier),\n      border-color .3s var(--n-bezier);\n  `, [\n    c('&:last-child', 'margin-bottom: 0;'),\n    cE('prefix', `\n      display: inline-flex;\n      margin-right: 8px;\n    `),\n    cE('text', `\n      border-bottom: 1px solid #0000;\n      transition: border-color .3s var(--n-bezier);\n      flex-grow: 1;\n      max-width: 100%;\n    `),\n    cE('suffix', `\n      display: inline-flex;\n    `)\n  ]),\n  cE('empty', 'margin: auto;')\n])\n"
  },
  {
    "path": "src/tree/src/styles/rtl.cssr.ts",
    "content": "import { cB, cE, cM } from '../../../_utils/cssr'\n\nexport default cB('tree', [\n  cM('rtl', `\n    direction: rtl;\n    text-align: right;\n  `, [\n    cB('tree-node-switcher', `\n      transform: rotate(180deg);\n    `, [\n      cM('expanded', `\n        transform: rotate(90deg);\n      `)\n    ]),\n    cB('tree-node-checkbox', `\n      margin-right: 0;\n      margin-left: 4px;\n    `),\n    cB('tree-node-content', [\n      cE('prefix', `\n        margin-right: 0;\n        margin-left: 8px;\n      `)\n    ]),\n    cB('tree-node-checkbox', [\n      cM('right', `\n        margin-right: 4px;\n      `)\n    ])\n  ])\n])\n"
  },
  {
    "path": "src/tree/src/utils.ts",
    "content": "import type { CheckStrategy } from 'treemate'\nimport type { ComputedRef } from 'vue'\nimport type { Key, TmNode, TreeOption } from './interface'\nimport { happensIn } from 'seemly'\nimport { computed } from 'vue'\nimport { isBrowser } from '../../_utils'\n\nexport function useMergedCheckStrategy(props: {\n  leafOnly: boolean\n  checkStrategy: CheckStrategy\n}): ComputedRef<CheckStrategy> {\n  return computed(() => (props.leafOnly ? 'child' : props.checkStrategy))\n}\n\nexport function isNodeDisabled(node: TmNode, disabledField: string): boolean {\n  return !!node.rawNode[disabledField]\n}\n\nfunction traverse(\n  nodes: TreeOption[] | undefined,\n  childrenField: string,\n  callback: (node: TreeOption) => void,\n  callbackAfter: (node: TreeOption) => void\n): void {\n  nodes?.forEach((node) => {\n    callback(node)\n    traverse(\n      node[childrenField] as TreeOption[] | undefined,\n      childrenField,\n      callback,\n      callbackAfter\n    )\n    callbackAfter(node)\n  })\n}\n\nexport function keysWithFilter(\n  nodes: TreeOption[],\n  pattern: string,\n  keyField: string,\n  childrenField: string,\n  filter: (pattern: string, node: TreeOption) => boolean\n): {\n  expandedKeys: Key[]\n  highlightKeySet: Set<Key>\n} {\n  const keys = new Set<Key>()\n  const highlightKeySet = new Set<Key>()\n  const path: TreeOption[] = []\n  traverse(\n    nodes,\n    childrenField,\n    (node) => {\n      path.push(node)\n      if (filter(pattern, node)) {\n        highlightKeySet.add(node[keyField] as Key)\n        for (let i = path.length - 2; i >= 0; --i) {\n          if (!keys.has(path[i][keyField] as Key)) {\n            keys.add(path[i][keyField] as Key)\n          }\n          else {\n            return\n          }\n        }\n      }\n    },\n    () => {\n      path.pop()\n    }\n  )\n  return {\n    expandedKeys: Array.from(keys),\n    highlightKeySet\n  }\n}\n\nconst emptyImage: HTMLImageElement | null = null\nif (isBrowser && Image) {\n  const emptyImage = new Image()\n  emptyImage.src\n    = 'data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw=='\n}\n\nexport { emptyImage }\n\nexport function filterTree(\n  tree: TreeOption[],\n  filter: (pattern: string, v: TreeOption) => boolean,\n  pattern: string,\n  keyField: string,\n  childrenField: string\n): {\n  filteredTree: TreeOption[]\n  expandedKeys: Key[]\n  highlightKeySet: Set<Key>\n} {\n  const visitedTailKeys = new Set<Key>()\n  const visitedNonTailKeys = new Set<Key>()\n  const highlightKeySet = new Set<Key>()\n  const expandedKeys: Key[] = []\n  const filteredTree: TreeOption[] = []\n  const path: TreeOption[] = []\n  function visit(t: TreeOption[]): void {\n    t.forEach((n) => {\n      path.push(n)\n      if (filter(pattern, n)) {\n        visitedTailKeys.add(n[keyField] as Key)\n        highlightKeySet.add(n[keyField] as Key)\n        for (let i = path.length - 2; i >= 0; --i) {\n          const key = path[i][keyField] as Key\n          if (!visitedNonTailKeys.has(key)) {\n            visitedNonTailKeys.add(key)\n            if (visitedTailKeys.has(key)) {\n              visitedTailKeys.delete(key)\n            }\n          }\n          else {\n            break\n          }\n        }\n      }\n      const children = n[childrenField] as TreeOption[] | undefined\n      if (children) {\n        visit(children)\n      }\n      path.pop()\n    })\n  }\n  visit(tree)\n  function build(t: TreeOption[], sibs: TreeOption[]): void {\n    t.forEach((n) => {\n      const key = n[keyField] as Key\n      const isVisitedTail = visitedTailKeys.has(key)\n      const isVisitedNonTail = visitedNonTailKeys.has(key)\n      if (!isVisitedTail && !isVisitedNonTail)\n        return\n      const children = n[childrenField] as TreeOption[] | undefined\n      if (children) {\n        if (isVisitedTail) {\n          // If it is visited path tail, use origin node\n          sibs.push(n)\n        }\n        else {\n          // It it is not visited path tail, use cloned node\n          expandedKeys.push(key)\n          const clonedNode = { ...n, [childrenField]: [] }\n          sibs.push(clonedNode)\n          build(children, clonedNode[childrenField] as TreeOption[])\n        }\n      }\n      else {\n        sibs.push(n)\n      }\n    })\n  }\n  build(tree, filteredTree)\n  return {\n    filteredTree,\n    highlightKeySet,\n    expandedKeys\n  }\n}\n\nexport function treeGetClickTarget(\n  e: MouseEvent\n): 'checkbox' | 'switcher' | 'node' {\n  if (happensIn(e, 'checkbox')) {\n    return 'checkbox'\n  }\n  else if (happensIn(e, 'switcher')) {\n    return 'switcher'\n  }\n  else {\n    return 'node'\n  }\n}\n"
  },
  {
    "path": "src/tree/styles/dark.ts",
    "content": "import type { TreeTheme } from './light'\nimport { changeColor } from 'seemly'\nimport { scrollbarDark } from '../../_internal/scrollbar/styles'\nimport { commonDark } from '../../_styles/common'\nimport { checkboxDark } from '../../checkbox/styles'\nimport { emptyDark } from '../../empty/styles'\nimport { self } from './light'\n\nconst treeDark: TreeTheme = {\n  name: 'Tree',\n  common: commonDark,\n  peers: {\n    Checkbox: checkboxDark,\n    Scrollbar: scrollbarDark,\n    Empty: emptyDark\n  },\n  self(vars) {\n    const { primaryColor } = vars\n    const commonSelf = self(vars)\n    commonSelf.nodeColorActive = changeColor(primaryColor, { alpha: 0.15 })\n    return commonSelf\n  }\n}\n\nexport default treeDark\n"
  },
  {
    "path": "src/tree/styles/index.ts",
    "content": "export { default as treeDark } from './dark'\nexport { default as treeLight } from './light'\nexport type { TreeTheme, TreeThemeVars } from './light'\nexport { treeRtl } from './rtl'\n"
  },
  {
    "path": "src/tree/styles/light.ts",
    "content": "import type { ThemeCommonVars } from '../../_styles/common'\nimport { changeColor } from 'seemly'\nimport { scrollbarLight } from '../../_internal/scrollbar/styles'\nimport { createTheme } from '../../_mixins/use-theme'\nimport { commonLight } from '../../_styles/common'\nimport { checkboxLight } from '../../checkbox/styles'\nimport { emptyLight } from '../../empty/styles'\n\nexport function self(vars: ThemeCommonVars) {\n  const {\n    borderRadiusSmall,\n    dividerColor,\n    hoverColor,\n    pressedColor,\n    primaryColor,\n    textColor3,\n    textColor2,\n    textColorDisabled,\n    fontSize\n  } = vars\n  return {\n    fontSize,\n    lineHeight: '1.5',\n    nodeHeight: '30px',\n    nodeWrapperPadding: '3px 0',\n    nodeBorderRadius: borderRadiusSmall,\n    nodeColorHover: hoverColor,\n    nodeColorPressed: pressedColor,\n    nodeColorActive: changeColor(primaryColor, { alpha: 0.1 }),\n    arrowColor: textColor3,\n    nodeTextColor: textColor2,\n    nodeTextColorDisabled: textColorDisabled,\n    loadingColor: primaryColor,\n    dropMarkColor: primaryColor,\n    lineColor: dividerColor\n  }\n}\n\nexport type TreeThemeVars = ReturnType<typeof self>\n\nconst treeLight = createTheme({\n  name: 'Tree',\n  common: commonLight,\n  peers: {\n    Checkbox: checkboxLight,\n    Scrollbar: scrollbarLight,\n    Empty: emptyLight\n  },\n  self\n})\n\nexport default treeLight\nexport type TreeTheme = typeof treeLight\n"
  },
  {
    "path": "src/tree/styles/rtl.ts",
    "content": "import type { RtlItem } from '../../config-provider/src/internal-interface'\nimport rtlStyle from '../src/styles/rtl.cssr'\n\nexport const treeRtl: RtlItem = {\n  name: 'Tree',\n  style: rtlStyle\n}\n"
  },
  {
    "path": "src/tree/tests/Tree.spec.ts",
    "content": "import type { DOMWrapper, VueWrapper } from '@vue/test-utils'\nimport type { TreeOption } from '../index'\nimport { mount } from '@vue/test-utils'\nimport { nextTick } from 'vue'\nimport { NTree } from '../index'\n\nfunction getTreeNodes(wrapper: VueWrapper) {\n  return wrapper.findAll('.n-tree-node')\n}\n\nfunction isChecked(node: DOMWrapper<Element>): boolean {\n  return node\n    .findAll('.n-checkbox')\n    .some(cb => cb.classes().includes('n-checkbox--checked'))\n}\n\nfunction isIndeterminate(node: DOMWrapper<Element>): boolean {\n  return node\n    .findAll('.n-checkbox')\n    .some(cb => cb.classes().includes('n-checkbox--indeterminate'))\n}\n\ndescribe('n-tree', () => {\n  it('should work with import on demand', () => {\n    mount(NTree)\n  })\n\n  it('should accept proper options', () => {\n    mount(NTree, {\n      props: {\n        data: [\n          {\n            label: '123',\n            key: '123',\n            children: [\n              {\n                label: '123',\n                key: '123'\n              }\n            ]\n          }\n        ]\n      }\n    })\n    mount(NTree, {\n      props: {\n        data: [\n          {\n            label: '123',\n            key: '123',\n            unknown: 'unknown'\n          }\n        ]\n      }\n    })\n  })\n\n  it('should work with `prefix` and `suffix`', async () => {\n    const wrapper = mount(NTree, {\n      props: {\n        data: [\n          {\n            label: 'test',\n            key: '123',\n            prefix: () => 'prefix',\n            suffix: () => 'suffix',\n            children: [\n              {\n                label: '123',\n                key: '123'\n              }\n            ]\n          }\n        ]\n      }\n    })\n\n    expect(wrapper.find('.n-tree-node-content__prefix').exists()).toBe(true)\n    expect(wrapper.find('.n-tree-node-content__prefix').text()).toBe('prefix')\n    expect(wrapper.find('.n-tree-node-content__text').exists()).toBe(true)\n    expect(wrapper.find('.n-tree-node-content__text').text()).toBe('test')\n    expect(wrapper.find('.n-tree-node-content__suffix').exists()).toBe(true)\n    expect(wrapper.find('.n-tree-node-content__suffix').text()).toBe('suffix')\n  })\n\n  it('should work with `render-label`, `render-prefix` and `render-suffix`', async () => {\n    const wrapper = mount(NTree, {\n      props: {\n        data: [\n          {\n            label: 'test',\n            key: '123',\n            children: [\n              {\n                label: '123',\n                key: '123'\n              }\n            ]\n          }\n        ],\n        renderPrefix: () => 'prefix',\n        renderLabel: () => 'label',\n        renderSuffix: () => 'suffix'\n      }\n    })\n\n    expect(wrapper.find('.n-tree-node-content__prefix').exists()).toBe(true)\n    expect(wrapper.find('.n-tree-node-content__prefix').text()).toBe('prefix')\n    expect(wrapper.find('.n-tree-node-content__text').exists()).toBe(true)\n    expect(wrapper.find('.n-tree-node-content__text').text()).toBe('label')\n    expect(wrapper.find('.n-tree-node-content__suffix').exists()).toBe(true)\n    expect(wrapper.find('.n-tree-node-content__suffix').text()).toBe('suffix')\n  })\n\n  it('should work with `expand`', async () => {\n    const wrapper = mount(NTree, {\n      props: {\n        defaultExpandedKeys: ['1'],\n        data: [\n          {\n            type: 'group',\n            label: 'test1',\n            key: '1',\n            children: [\n              {\n                label: 'test1-1',\n                key: '1-1'\n              }\n            ]\n          },\n          {\n            type: 'group',\n            label: 'test2',\n            key: '2',\n            children: [\n              {\n                type: 'group',\n                label: 'test2-1',\n                key: '2-1'\n              }\n            ]\n          }\n        ]\n      }\n    })\n    expect(getTreeNodes(wrapper).length).toBe(3)\n    const switcher = getTreeNodes(wrapper)[2].find('.n-tree-node-switcher')\n\n    await switcher.trigger('click')\n\n    expect(getTreeNodes(wrapper).length).toBe(4)\n    const lastNodeText = getTreeNodes(wrapper)[3].text()\n    expect(lastNodeText).toContain('test2-1')\n  })\n\n  it('should work with `default-expand-all`', async () => {\n    const wrapper = mount(NTree, {\n      props: {\n        defaultExpandAll: true\n      }\n    })\n    await wrapper.setProps({\n      data: [\n        {\n          label: 'test1',\n          key: '1',\n          children: [\n            {\n              label: 'test1-1',\n              key: '1-1'\n            }\n          ]\n        },\n        {\n          label: 'test2',\n          key: '2',\n          children: [\n            {\n              label: 'test2-1',\n              key: '2-1'\n            }\n          ]\n        }\n      ]\n    })\n    expect(getTreeNodes(wrapper).length).toBe(4)\n    const texts = getTreeNodes(wrapper).map(n => n.text())\n    expect(texts.some(t => t.includes('test1-1'))).toBe(true)\n    expect(texts.some(t => t.includes('test2-1'))).toBe(true)\n  })\n\n  it('should work with `checkable` and `defaultCheckedKeys`', () => {\n    const wrapper = mount(NTree, {\n      props: {\n        data: [\n          {\n            label: 'test',\n            key: '123',\n            children: [\n              {\n                label: '1231',\n                key: '1231'\n              }\n            ]\n          }\n        ],\n        checkable: true,\n        defaultCheckedKeys: ['1231']\n      }\n    })\n\n    expect(wrapper.html()).toContain('n-tree-node--checkable')\n  })\n\n  it('should work with `draggable`', () => {\n    const wrapper = mount(NTree, {\n      props: {\n        data: [\n          {\n            label: 'test',\n            key: '123',\n            children: [\n              {\n                label: '1231',\n                key: '1231'\n              }\n            ]\n          }\n        ],\n        draggable: true\n      }\n    })\n\n    expect(wrapper.find('.n-tree-node-content').html()).toContain(\n      'draggable=\"true\"'\n    )\n  })\n\n  it('should work with `blockNode`', () => {\n    const wrapper = mount(NTree, {\n      props: {\n        data: [\n          {\n            label: 'test',\n            key: '123',\n            children: [\n              {\n                label: '1231',\n                key: '1231'\n              }\n            ]\n          }\n        ],\n        blockNode: true\n      }\n    })\n\n    expect(wrapper.find('.n-tree--block-node').exists()).toBe(true)\n  })\n\n  it('should work with `blockLine`', () => {\n    const wrapper = mount(NTree, {\n      props: {\n        data: [\n          {\n            label: 'test',\n            key: '123',\n            children: [\n              {\n                label: '1231',\n                key: '1231'\n              }\n            ]\n          }\n        ],\n        blockLine: true\n      }\n    })\n\n    expect(wrapper.find('.n-tree--block-line').exists()).toBe(true)\n  })\n\n  it('should work witch `selectable`', async () => {\n    const wrapper = mount(NTree, {\n      props: {\n        data: [\n          {\n            label: 'test',\n            key: '123',\n            children: [\n              {\n                label: '1231',\n                key: '1231'\n              }\n            ]\n          }\n        ]\n      }\n    })\n    expect(getTreeNodes(wrapper)[0].classes()).toContain(\n      'n-tree-node--selectable'\n    )\n    let node = getTreeNodes(wrapper)[0]\n    await node.find('.n-tree-node-content').trigger('click')\n    expect(node.classes()).toContain('n-tree-node--selected')\n\n    await wrapper.setProps({ selectable: false })\n    await vi.waitFor(() => {\n      expect(getTreeNodes(wrapper)[0].classes()).not.toContain(\n        'n-tree-node--selectable'\n      )\n    })\n    node = getTreeNodes(wrapper)[0]\n    await node.find('.n-tree-node-content').trigger('click')\n    expect(node.classes()).toContain('n-tree-node--selected')\n    expect(node.classes()).not.toContain('n-tree-node--selectable')\n  })\n\n  it('should work witch `cancelable`', async () => {\n    const wrapper = mount(NTree, {\n      props: {\n        data: [\n          {\n            label: 'test',\n            key: '123',\n            children: [\n              {\n                label: '1231',\n                key: '1231'\n              }\n            ]\n          }\n        ]\n      }\n    })\n\n    const nodeEl = getTreeNodes(wrapper)[0]\n    await nodeEl.find('.n-tree-node-content').trigger('click')\n    expect(nodeEl.classes()).toContain('n-tree-node--selected')\n    await nodeEl.find('.n-tree-node-content').trigger('click')\n    expect(nodeEl.classes()).not.toContain('n-tree-node--selected')\n\n    await wrapper.setProps({ cancelable: false })\n    await nodeEl.find('.n-tree-node-content').trigger('click')\n    expect(nodeEl.classes()).toContain('n-tree-node--selected')\n    await nodeEl.find('.n-tree-node-content').trigger('click')\n    expect(nodeEl.classes()).toContain('n-tree-node--selected')\n  })\n\n  it('should work with `disabled`', () => {\n    const wrapper = mount(NTree, {\n      props: {\n        data: [\n          {\n            label: 'test',\n            key: '123',\n            disabled: true,\n            children: [\n              {\n                label: '1231',\n                key: '1231'\n              }\n            ]\n          }\n        ]\n      }\n    })\n\n    expect(wrapper.find('.n-tree-node--disabled').exists()).toBe(true)\n  })\n\n  it('should work with `children-field`', () => {\n    const wrapper = mount(NTree, {\n      props: {\n        data: [\n          {\n            label: 'test',\n            key: '123',\n            disabled: true,\n            nodes: [\n              {\n                label: '1231',\n                key: '1231'\n              }\n            ]\n          }\n        ],\n        childrenField: 'nodes',\n        defaultExpandAll: true\n      }\n    })\n\n    expect(getTreeNodes(wrapper).length).toBe(2)\n    expect(getTreeNodes(wrapper)[1].text()).toContain('1231')\n  })\n\n  it('should work with `onLoad`', async () => {\n    const data = [\n      {\n        label: 'Parent 1',\n        key: 1,\n        isLeaf: false\n      },\n      {\n        label: 'Parent 2',\n        key: 2,\n        isLeaf: false\n      }\n    ]\n\n    const onLoad = vi.fn().mockImplementation((node) => {\n      return Promise.resolve().then(() => {\n        if (node.key === 1) {\n          node.children = [{ label: 'Child 1', key: 11 }]\n        }\n        else if (node.key === 2) {\n          node.children = [{ label: 'Child 2', key: 22 }]\n        }\n        return true\n      })\n    })\n\n    const wrapper = mount(NTree, {\n      props: {\n        data,\n        expandedKeys: [1],\n        onLoad\n      }\n    })\n\n    expect(onLoad).toHaveBeenCalledTimes(1)\n    expect(onLoad).toHaveBeenCalledWith(data[0])\n\n    await wrapper.setProps({ expandedKeys: [1, 2] })\n    expect(onLoad).toHaveBeenCalledTimes(2)\n    expect(onLoad).toHaveBeenCalledWith(data[1])\n  })\n\n  it('should work with `multiple`', async () => {\n    const wrapper = mount(NTree, {\n      props: {\n        data: [\n          {\n            label: '1',\n            key: '1'\n          },\n          {\n            label: '2',\n            key: '2'\n          },\n          {\n            label: '3',\n            key: '3'\n          }\n        ]\n      }\n    })\n\n    let nodes = getTreeNodes(wrapper)\n    await nodes[0].find('.n-tree-node-content').trigger('click')\n    await nextTick()\n    expect(getTreeNodes(wrapper)[0].classes()).toContain(\n      'n-tree-node--selected'\n    )\n    expect(getTreeNodes(wrapper)[1].classes()).not.toContain(\n      'n-tree-node--selected'\n    )\n\n    await nodes[1].find('.n-tree-node-content').trigger('click')\n    await nextTick()\n    expect(getTreeNodes(wrapper)[0].classes()).not.toContain(\n      'n-tree-node--selected'\n    )\n    expect(getTreeNodes(wrapper)[1].classes()).toContain(\n      'n-tree-node--selected'\n    )\n\n    await wrapper.setProps({ multiple: true })\n    nodes = getTreeNodes(wrapper)\n    await nodes[0].find('.n-tree-node-content').trigger('click')\n    expect(getTreeNodes(wrapper)[0].classes()).toContain(\n      'n-tree-node--selected'\n    )\n    expect(getTreeNodes(wrapper)[1].classes()).toContain(\n      'n-tree-node--selected'\n    )\n  })\n\n  it('should work with `click line to checked`', async () => {\n    const wrapper = mount(NTree, {\n      props: {\n        cascade: true,\n        checkable: true,\n        checkOnClick: true,\n        data: [\n          {\n            label: '1',\n            key: '1'\n          },\n          {\n            label: '2',\n            key: '2'\n          },\n          {\n            label: '3',\n            key: '3'\n          }\n        ]\n      }\n    })\n    const nodes = getTreeNodes(wrapper)\n    await nodes[0].find('.n-tree-node-content').trigger('click')\n    expect(isChecked(nodes[0])).toBe(true)\n    await nodes[0].find('.n-tree-node-content').trigger('click')\n    expect(isChecked(nodes[0])).toBe(false)\n    await nodes[0].find('.n-tree-node-content').trigger('click')\n    await nodes[1].find('.n-tree-node-content').trigger('click')\n    expect(isChecked(nodes[0])).toBe(true)\n    expect(isChecked(nodes[1])).toBe(true)\n\n    await wrapper.setProps({ checkOnClick: false })\n    await nodes[0].find('.n-tree-node-content').trigger('click')\n    expect(isChecked(nodes[0])).toBe(true)\n    await nodes[1].find('.n-tree-node-content').trigger('click')\n    expect(isChecked(nodes[1])).toBe(true)\n  })\n\n  it('should work with `click line to checked when checkOnClick is function`', async () => {\n    function checkOnClick(node: TreeOption): boolean {\n      return node.label === '1-1'\n    }\n\n    const wrapper = mount(NTree, {\n      props: {\n        expandOnClick: true,\n        checkOnClick,\n        cascade: true,\n        checkable: true,\n        data: [\n          {\n            label: '1',\n            key: '1',\n            children: [\n              {\n                label: '1-1',\n                key: '1-1'\n              },\n              {\n                label: '1-2',\n                key: '1-2'\n              }\n            ]\n          },\n          {\n            label: '2',\n            key: '2',\n            children: [\n              {\n                label: '2-1',\n                key: '2-1'\n              },\n              {\n                label: '2-2',\n                key: '2-2'\n              }\n            ]\n          },\n          {\n            label: '3',\n            key: '3'\n          }\n        ]\n      }\n    })\n    await getTreeNodes(wrapper)[0].find('.n-tree-node-content').trigger('click')\n    expect(isChecked(getTreeNodes(wrapper)[0])).toBe(false)\n    await getTreeNodes(wrapper)[1].find('.n-tree-node-content').trigger('click')\n    expect(isChecked(getTreeNodes(wrapper)[1])).toBe(true)\n    expect(isIndeterminate(getTreeNodes(wrapper)[0])).toBe(true)\n    await getTreeNodes(wrapper)[2].find('.n-tree-node-content').trigger('click')\n    expect(isChecked(getTreeNodes(wrapper)[1])).toBe(true)\n    expect(isIndeterminate(getTreeNodes(wrapper)[0])).toBe(true)\n  })\n\n  it('should work with `node-props` prop', async () => {\n    const testClass = 'menu-test'\n    const wrapper = mount(NTree, {\n      props: {\n        data: [\n          {\n            label: '1',\n            key: '1'\n          },\n          {\n            label: '2',\n            key: '2'\n          },\n          {\n            label: '3',\n            key: '3'\n          }\n        ],\n        nodeProps: () => ({ class: testClass })\n      }\n    })\n    expect(wrapper.find('.n-tree-node').classes()).toContain(testClass)\n  })\n\n  it('should work with `checkbox-placement` prop', async () => {\n    let wrapper = mount(NTree, {\n      props: {\n        data: [\n          {\n            label: '1',\n            key: '1'\n          },\n          {\n            label: '2',\n            key: '2'\n          },\n          {\n            label: '3',\n            key: '3'\n          }\n        ],\n        checkable: true\n      }\n    })\n    expect(wrapper.find('.n-tree-node-checkbox--right').exists()).toBe(false)\n\n    wrapper = mount(NTree, {\n      props: {\n        data: [\n          {\n            label: '1',\n            key: '1'\n          },\n          {\n            label: '2',\n            key: '2'\n          },\n          {\n            label: '3',\n            key: '3'\n          }\n        ],\n        checkable: true,\n        checkboxPlacement: 'right'\n      }\n    })\n    expect(wrapper.find('.n-tree-node-checkbox--right').exists()).toBe(true)\n\n    wrapper.unmount()\n  })\n})\n"
  },
  {
    "path": "src/tree/tests/server.spec.tsx",
    "content": "import { setup } from '@css-render/vue3-ssr'\nimport { renderToString } from '@vue/server-renderer'\n/**\n * @vitest-environment node\n */\nimport { createSSRApp, h } from 'vue'\nimport { NTree } from '../..'\n\ndescribe('server side rendering', () => {\n  it('works', async () => {\n    const app = createSSRApp(() => <NTree />)\n    setup(app)\n    try {\n      await renderToString(app)\n    }\n    catch (e) {\n      expect(e).not.toBeTruthy()\n    }\n  })\n})\n"
  },
  {
    "path": "src/tree-select/demos/enUS/action.demo.vue",
    "content": "<markdown>\n# Action slot\n\nMaybe you need to use this slot in the tree selection menu.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { TreeSelectOption } from 'naive-ui'\n\nfunction handleUpdateValue(\n  value: string | number | Array<string | number> | null,\n  option: TreeSelectOption | null | Array<TreeSelectOption | null>\n) {\n  console.log(value, option)\n}\n\nconst options = [\n  {\n    label: 'Rubber Soul',\n    key: 'Rubber Soul',\n    children: [\n      {\n        label: 'Everybody\\'s Got Something to Hide Except Me and My Monkey',\n        key: 'Everybody\\'s Got Something to Hide Except Me and My Monkey'\n      },\n      {\n        label: 'Drive My Car',\n        key: 'Drive My Car',\n        disabled: true\n      },\n      {\n        label: 'Norwegian Wood',\n        key: 'Norwegian Wood'\n      },\n      {\n        label: 'You Won\\'t See',\n        key: 'You Won\\'t See',\n        disabled: true\n      },\n      {\n        label: 'Nowhere Man',\n        key: 'Nowhere Man'\n      },\n      {\n        label: 'Think For Yourself',\n        key: 'Think For Yourself'\n      },\n      {\n        label: 'The Word',\n        key: 'The Word'\n      },\n      {\n        label: 'Michelle',\n        key: 'Michelle',\n        disabled: true\n      },\n      {\n        label: 'What goes on',\n        key: 'What goes on'\n      },\n      {\n        label: 'Girl',\n        key: 'Girl'\n      },\n      {\n        label: 'I\\'m looking through you',\n        key: 'I\\'m looking through you'\n      },\n      {\n        label: 'In My Life',\n        key: 'In My Life'\n      },\n      {\n        label: 'Wait',\n        key: 'Wait'\n      }\n    ]\n  }\n]\n</script>\n\n<template>\n  <n-tree-select\n    :options=\"options\"\n    default-value=\"Drive My Car\"\n    @update:value=\"handleUpdateValue\"\n  >\n    <template #header>\n      Don't know what to put\n    </template>\n    <template #action>\n      You can customize some operations here.\n    </template>\n  </n-tree-select>\n</template>\n"
  },
  {
    "path": "src/tree-select/demos/enUS/async.demo.vue",
    "content": "<markdown>\n# Async loading\n\nUse `on-load` callback to load data. When loading async, all nodes with `isLeaf` set to `false` and `chilren`'s type is not `Array` will be reckon as unloaded nodes.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { TreeSelectOption } from 'naive-ui'\nimport { ref } from 'vue'\n\nfunction getChildren(option: TreeSelectOption) {\n  const children = []\n  for (let i = 0; i <= (option as { depth: number }).depth; ++i) {\n    children.push({\n      label: `${option.label}-${i}`,\n      key: `${option.label}-${i}`,\n      depth: (option as { depth: number }).depth + 1,\n      isLeaf: option.depth === 3\n    })\n  }\n  return children\n}\n\nconst checkStrategy = ref<'all' | 'parent' | 'child'>('all')\nconst cascade = ref(false)\nconst showPath = ref(true)\nconst value = ref(null)\nconst options = ref([\n  {\n    label: 'l-0',\n    key: 'v-0',\n    depth: 1,\n    isLeaf: false\n  }\n])\n\nfunction handleLoad(option: TreeSelectOption) {\n  return new Promise<void>((resolve) => {\n    window.setTimeout(() => {\n      option.children = getChildren(option)\n      resolve()\n    }, 1000)\n  })\n}\n</script>\n\n<template>\n  <n-space vertical>\n    <n-space align=\"center\">\n      <n-radio-group v-model:value=\"checkStrategy\">\n        <n-radio-button value=\"all\">\n          All\n        </n-radio-button>\n        <n-radio-button value=\"parent\">\n          Parent\n        </n-radio-button>\n        <n-radio-button value=\"child\">\n          Child\n        </n-radio-button>\n      </n-radio-group>\n      <n-space><n-switch v-model:value=\"showPath\" />Show Path</n-space>\n      <n-space><n-switch v-model:value=\"cascade\" />Cascade </n-space>\n    </n-space>\n    <n-tree-select\n      v-model:value=\"value\"\n      multiple\n      checkable\n      :options=\"options\"\n      :cascade=\"cascade\"\n      :check-strategy=\"checkStrategy\"\n      :show-path=\"showPath\"\n      :allow-checking-not-loaded=\"cascade\"\n      :on-load=\"handleLoad\"\n    />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/tree-select/demos/enUS/basic.demo.vue",
    "content": "<markdown>\n# Basic\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { TreeSelectOption } from 'naive-ui'\n\nfunction handleUpdateValue(\n  value: string | number | Array<string | number> | null,\n  option: TreeSelectOption | null | Array<TreeSelectOption | null>\n) {\n  console.log(value, option)\n}\n\nconst options = [\n  {\n    label: 'Rubber Soul',\n    key: 'Rubber Soul',\n    children: [\n      {\n        label: 'Everybody\\'s Got Something to Hide Except Me and My Monkey',\n        key: 'Everybody\\'s Got Something to Hide Except Me and My Monkey'\n      },\n      {\n        label: 'Drive My Car',\n        key: 'Drive My Car',\n        disabled: true\n      },\n      {\n        label: 'Norwegian Wood',\n        key: 'Norwegian Wood'\n      },\n      {\n        label: 'You Won\\'t See',\n        key: 'You Won\\'t See',\n        disabled: true\n      },\n      {\n        label: 'Nowhere Man',\n        key: 'Nowhere Man'\n      },\n      {\n        label: 'Think For Yourself',\n        key: 'Think For Yourself'\n      },\n      {\n        label: 'The Word',\n        key: 'The Word'\n      },\n      {\n        label: 'Michelle',\n        key: 'Michelle',\n        disabled: true\n      },\n      {\n        label: 'What goes on',\n        key: 'What goes on'\n      },\n      {\n        label: 'Girl',\n        key: 'Girl'\n      },\n      {\n        label: 'I\\'m looking through you',\n        key: 'I\\'m looking through you'\n      },\n      {\n        label: 'In My Life',\n        key: 'In My Life'\n      },\n      {\n        label: 'Wait',\n        key: 'Wait'\n      }\n    ]\n  },\n  {\n    label: 'Let It Be',\n    key: 'Let It Be Album',\n    children: [\n      {\n        label: 'Two Of Us',\n        key: 'Two Of Us'\n      },\n      {\n        label: 'Dig A Pony',\n        key: 'Dig A Pony'\n      },\n      {\n        label: 'Across The Universe',\n        key: 'Across The Universe'\n      },\n      {\n        label: 'I Me Mine',\n        key: 'I Me Mine'\n      },\n      {\n        label: 'Dig It',\n        key: 'Dig It'\n      },\n      {\n        label: 'Let It Be',\n        key: 'Let It Be'\n      },\n      {\n        label: 'Maggie Mae',\n        key: 'Maggie Mae'\n      },\n      {\n        label: 'I\\'ve Got A Feeling',\n        key: 'I\\'ve Got A Feeling'\n      },\n      {\n        label: 'One After 909',\n        key: 'One After 909'\n      },\n      {\n        label: 'The Long And Winding Road',\n        key: 'The Long And Winding Road'\n      },\n      {\n        label: 'For You Blue',\n        key: 'For You Blue'\n      },\n      {\n        label: 'Get Back',\n        key: 'Get Back'\n      }\n    ]\n  }\n]\n</script>\n\n<template>\n  <n-tree-select\n    :options=\"options\"\n    default-value=\"Drive My Car\"\n    @update:value=\"handleUpdateValue\"\n  />\n</template>\n"
  },
  {
    "path": "src/tree-select/demos/enUS/check-strategy.demo.vue",
    "content": "<markdown>\n# Set check strategy\n\nSet the way to display selected nodes when parents and children are selected. `all` will display both the parent and the children when all the children are selected. `parent` will only show the parent option if all of the children are selected. `child` will only ever show leaf nodes (nodes with no children).\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { TreeSelectOption } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst checkStrategy = ref<'all' | 'child' | 'parent'>('all')\nconst options = [\n  {\n    label: 'Rubber Soul',\n    key: 'Rubber Soul',\n    children: [\n      {\n        label: 'Everybody\\'s Got Something to Hide Except Me and My Monkey',\n        key: 'Everybody\\'s Got Something to Hide Except Me and My Monkey'\n      },\n      {\n        label: 'Drive My Car',\n        key: 'Drive My Car',\n        disabled: true\n      },\n      {\n        label: 'Norwegian Wood',\n        key: 'Norwegian Wood'\n      },\n      {\n        label: 'You Won\\'t See',\n        key: 'You Won\\'t See',\n        disabled: true\n      },\n      {\n        label: 'Nowhere Man',\n        key: 'Nowhere Man'\n      },\n      {\n        label: 'Think For Yourself',\n        key: 'Think For Yourself'\n      },\n      {\n        label: 'The Word',\n        key: 'The Word'\n      },\n      {\n        label: 'Michelle',\n        key: 'Michelle',\n        disabled: true\n      },\n      {\n        label: 'What goes on',\n        key: 'What goes on'\n      },\n      {\n        label: 'Girl',\n        key: 'Girl'\n      },\n      {\n        label: 'I\\'m looking through you',\n        key: 'I\\'m looking through you'\n      },\n      {\n        label: 'In My Life',\n        key: 'In My Life'\n      },\n      {\n        label: 'Wait',\n        key: 'Wait'\n      }\n    ]\n  },\n  {\n    label: 'Let It Be',\n    key: 'Let It Be Album',\n    children: [\n      {\n        label: 'Two Of Us',\n        key: 'Two Of Us'\n      },\n      {\n        label: 'Dig A Pony',\n        key: 'Dig A Pony'\n      },\n      {\n        label: 'Across The Universe',\n        key: 'Across The Universe',\n        children: [\n          {\n            label: 'Dig It',\n            key: 'Dig It'\n          },\n          {\n            label: 'go',\n            key: 'go'\n          }\n        ]\n      }\n    ]\n  }\n]\n\nfunction handleUpdateValue(\n  value: string | number | Array<string | number> | null,\n  option: TreeSelectOption | null | Array<TreeSelectOption | null>\n) {\n  console.log(value, option)\n}\n</script>\n\n<template>\n  <n-space vertical>\n    <n-space>\n      <n-radio-group v-model:value=\"checkStrategy\">\n        <n-radio-button value=\"all\">\n          All\n        </n-radio-button>\n        <n-radio-button value=\"parent\">\n          Parent\n        </n-radio-button>\n        <n-radio-button value=\"child\">\n          Child\n        </n-radio-button>\n      </n-radio-group>\n    </n-space>\n    <n-tree-select\n      multiple\n      cascade\n      checkable\n      :check-strategy=\"checkStrategy\"\n      :options=\"options\"\n      :default-value=\"['Dig It', 'go']\"\n      @update:value=\"handleUpdateValue\"\n    />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/tree-select/demos/enUS/checkbox.demo.vue",
    "content": "<markdown>\n# Use checkbox\n\nIf you want to have the same effect of this demo, you will need `checkable`, `cascade` and `multiple` properties.\n</markdown>\n\n<script lang=\"ts\" setup>\nconst options = [\n  {\n    label: 'Rubber Soul',\n    key: 'Rubber Soul',\n    children: [\n      {\n        label: 'Everybody\\'s Got Something to Hide Except Me and My Monkey',\n        key: 'Everybody\\'s Got Something to Hide Except Me and My Monkey'\n      },\n      {\n        label: 'Drive My Car',\n        key: 'Drive My Car',\n        disabled: true\n      },\n      {\n        label: 'Norwegian Wood',\n        key: 'Norwegian Wood'\n      },\n      {\n        label: 'You Won\\'t See',\n        key: 'You Won\\'t See',\n        disabled: true\n      },\n      {\n        label: 'Nowhere Man',\n        key: 'Nowhere Man'\n      },\n      {\n        label: 'Think For Yourself',\n        key: 'Think For Yourself'\n      },\n      {\n        label: 'The Word',\n        key: 'The Word'\n      },\n      {\n        label: 'Michelle',\n        key: 'Michelle',\n        disabled: true\n      },\n      {\n        label: 'What goes on',\n        key: 'What goes on'\n      },\n      {\n        label: 'Girl',\n        key: 'Girl'\n      },\n      {\n        label: 'I\\'m looking through you',\n        key: 'I\\'m looking through you'\n      },\n      {\n        label: 'In My Life',\n        key: 'In My Life'\n      },\n      {\n        label: 'Wait',\n        key: 'Wait'\n      }\n    ]\n  },\n  {\n    label: 'Let It Be',\n    key: 'Let It Be Album',\n    children: [\n      {\n        label: 'Two Of Us',\n        key: 'Two Of Us'\n      },\n      {\n        label: 'Dig A Pony',\n        key: 'Dig A Pony'\n      },\n      {\n        label: 'Across The Universe',\n        key: 'Across The Universe'\n      },\n      {\n        label: 'I Me Mine',\n        key: 'I Me Mine'\n      },\n      {\n        label: 'Dig It',\n        key: 'Dig It'\n      },\n      {\n        label: 'Let It Be',\n        key: 'Let It Be'\n      },\n      {\n        label: 'Maggie Mae',\n        key: 'Maggie Mae'\n      },\n      {\n        label: 'I\\'ve Got A Feeling',\n        key: 'I\\'ve Got A Feeling'\n      },\n      {\n        label: 'One After 909',\n        key: 'One After 909'\n      },\n      {\n        label: 'The Long And Winding Road',\n        key: 'The Long And Winding Road'\n      },\n      {\n        label: 'For You Blue',\n        key: 'For You Blue'\n      },\n      {\n        label: 'Get Back',\n        key: 'Get Back'\n      }\n    ]\n  }\n]\n</script>\n\n<template>\n  <n-tree-select\n    multiple\n    cascade\n    checkable\n    :options=\"options\"\n    :default-value=\"['Norwegian Wood']\"\n  />\n</template>\n"
  },
  {
    "path": "src/tree-select/demos/enUS/custom-field.demo.vue",
    "content": "<markdown>\n# Customize fields\n\nYou can also target difference label and key properties of the objects you are using as nodes.\n</markdown>\n\n<script lang=\"ts\" setup>\nconst options = [\n  {\n    whateverLabel: 'Rubber Soul',\n    whateverKey: 'Rubber Soul',\n    whateverChildren: [\n      {\n        whateverLabel:\n          'Everybody\\'s Got Something to Hide Except Me and My Monkey',\n        whateverKey: 'Everybody\\'s Got Something to Hide Except Me and My Monkey'\n      },\n      {\n        whateverLabel: 'Drive My Car',\n        whateverKey: 'Drive My Car',\n        disabled: true\n      },\n      {\n        whateverLabel: 'Norwegian Wood',\n        whateverKey: 'Norwegian Wood'\n      },\n      {\n        whateverLabel: 'You Won\\'t See',\n        whateverKey: 'You Won\\'t See',\n        disabled: true\n      },\n      {\n        whateverLabel: 'Nowhere Man',\n        whateverKey: 'Nowhere Man'\n      },\n      {\n        whateverLabel: 'Think For Yourself',\n        whateverKey: 'Think For Yourself'\n      },\n      {\n        whateverLabel: 'The Word',\n        whateverKey: 'The Word'\n      },\n      {\n        whateverLabel: 'Michelle',\n        whateverKey: 'Michelle',\n        disabled: true\n      },\n      {\n        whateverLabel: 'What goes on',\n        whateverKey: 'What goes on'\n      },\n      {\n        whateverLabel: 'Girl',\n        whateverKey: 'Girl'\n      },\n      {\n        whateverLabel: 'I\\'m looking through you',\n        whateverKey: 'I\\'m looking through you'\n      },\n      {\n        whateverLabel: 'In My Life',\n        whateverKey: 'In My Life'\n      },\n      {\n        whateverLabel: 'Wait',\n        whateverKey: 'Wait'\n      }\n    ]\n  },\n  {\n    whateverLabel: 'Let It Be',\n    whateverKey: 'Let It Be Album',\n    whateverChildren: [\n      {\n        whateverLabel: 'Two Of Us',\n        whateverKey: 'Two Of Us'\n      },\n      {\n        whateverLabel: 'Dig A Pony',\n        whateverKey: 'Dig A Pony'\n      },\n      {\n        whateverLabel: 'Across The Universe',\n        whateverKey: 'Across The Universe'\n      },\n      {\n        whateverLabel: 'I Me Mine',\n        whateverKey: 'I Me Mine'\n      },\n      {\n        whateverLabel: 'Dig It',\n        whateverKey: 'Dig It'\n      },\n      {\n        whateverLabel: 'Let It Be',\n        whateverKey: 'Let It Be'\n      },\n      {\n        whateverLabel: 'Maggie Mae',\n        whateverKey: 'Maggie Mae'\n      },\n      {\n        whateverLabel: 'I\\'ve Got A Feeling',\n        whateverKey: 'I\\'ve Got A Feeling'\n      },\n      {\n        whateverLabel: 'One After 909',\n        whateverKey: 'One After 909'\n      },\n      {\n        whateverLabel: 'The Long And Winding Road',\n        whateverKey: 'The Long And Winding Road'\n      },\n      {\n        whateverLabel: 'For You Blue',\n        whateverKey: 'For You Blue'\n      },\n      {\n        whateverLabel: 'Get Back',\n        whateverKey: 'Get Back'\n      }\n    ]\n  }\n]\n</script>\n\n<template>\n  <n-tree-select\n    :options=\"options\"\n    default-value=\"Drive My Car\"\n    label-field=\"whateverLabel\"\n    key-field=\"whateverKey\"\n    children-field=\"whateverChildren\"\n  />\n</template>\n"
  },
  {
    "path": "src/tree-select/demos/enUS/debug.demo.vue",
    "content": "<markdown>\n# Debug\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { TreeSelectOption } from 'naive-ui'\nimport { ref } from 'vue'\n\nfunction createData(level = 4, baseKey = ''): TreeSelectOption[] | undefined {\n  if (!level)\n    return undefined\n  return Array.from({ length: 6 - level }).map((_, index) => {\n    const key = `${baseKey}${level}${index}`\n    return {\n      label: key,\n      key,\n      children: createData(level - 1, key)\n    }\n  })\n}\n\nconst multiple = ref(false)\nconst checkable = ref(false)\nconst cascade = ref(false)\nconst filterable = ref(false)\nconst options = createData()\n</script>\n\n<template>\n  <n-space vertical>\n    <n-space>\n      <n-switch v-model:value=\"multiple\" />Multiple\n      <n-switch v-model:value=\"checkable\" />Checkable\n      <n-switch v-model:value=\"cascade\" />Cascade\n      <n-switch v-model:value=\"filterable\" />Filterable\n    </n-space>\n    <n-tree-select\n      default-expand-all\n      :options=\"options\"\n      :multiple=\"multiple\"\n      :checkable=\"checkable\"\n      :cascade=\"cascade\"\n      :filterable=\"filterable\"\n    />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/tree-select/demos/enUS/file-picker.demo.vue",
    "content": "<markdown>\n# File picker\n\nUse `override-default-node-click-behavior` to simulate a file picker (folder is not selectable).\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { TreeSelectOverrideNodeClickBehavior } from 'naive-ui'\n\nconst override: TreeSelectOverrideNodeClickBehavior = ({ option }) => {\n  if (option.children) {\n    return 'toggleExpand'\n  }\n  return 'default'\n}\n\nconst options = [\n  {\n    label: 'Folder-1',\n    key: 'Folder-1',\n    children: [\n      {\n        label: 'File-1-1',\n        key: 'File-1-1'\n      },\n      {\n        label: 'Folder-1-2',\n        key: 'Folder-1-2',\n        children: [\n          {\n            label: 'File-1-2-1',\n            key: 'File-1-2-1'\n          },\n          {\n            label: 'File-1-2-2',\n            key: 'File-1-2-2'\n          }\n        ]\n      }\n    ]\n  },\n  {\n    label: 'Folder-2',\n    key: 'Folder-2',\n    children: [\n      {\n        label: 'File-2-1',\n        key: 'File-2-1'\n      },\n      {\n        label: 'File-2-2',\n        key: 'File-2-2'\n      }\n    ]\n  }\n]\n</script>\n\n<template>\n  <n-tree-select\n    block-line\n    :options=\"options\"\n    :override-default-node-click-behavior=\"override\"\n  />\n</template>\n"
  },
  {
    "path": "src/tree-select/demos/enUS/filterable.demo.vue",
    "content": "<markdown>\n# Filterable\n</markdown>\n\n<script lang=\"ts\" setup>\nconst options = [\n  {\n    label: 'Rubber Soul',\n    key: 'Rubber Soul',\n    children: [\n      {\n        label: 'Everybody\\'s Got Something to Hide Except Me and My Monkey',\n        key: 'Everybody\\'s Got Something to Hide Except Me and My Monkey'\n      },\n      {\n        label: 'Drive My Car',\n        key: 'Drive My Car',\n        disabled: true\n      },\n      {\n        label: 'Norwegian Wood',\n        key: 'Norwegian Wood'\n      },\n      {\n        label: 'You Won\\'t See',\n        key: 'You Won\\'t See',\n        disabled: true\n      },\n      {\n        label: 'Nowhere Man',\n        key: 'Nowhere Man'\n      },\n      {\n        label: 'Think For Yourself',\n        key: 'Think For Yourself'\n      },\n      {\n        label: 'The Word',\n        key: 'The Word'\n      },\n      {\n        label: 'Michelle',\n        key: 'Michelle',\n        disabled: true\n      },\n      {\n        label: 'What goes on',\n        key: 'What goes on'\n      },\n      {\n        label: 'Girl',\n        key: 'Girl'\n      },\n      {\n        label: 'I\\'m looking through you',\n        key: 'I\\'m looking through you'\n      },\n      {\n        label: 'In My Life',\n        key: 'In My Life'\n      },\n      {\n        label: 'Wait',\n        key: 'Wait'\n      }\n    ]\n  },\n  {\n    label: 'Let It Be',\n    key: 'Let It Be Album',\n    children: [\n      {\n        label: 'Two Of Us',\n        key: 'Two Of Us'\n      },\n      {\n        label: 'Dig A Pony',\n        key: 'Dig A Pony'\n      },\n      {\n        label: 'Across The Universe',\n        key: 'Across The Universe'\n      },\n      {\n        label: 'I Me Mine',\n        key: 'I Me Mine'\n      },\n      {\n        label: 'Dig It',\n        key: 'Dig It'\n      },\n      {\n        label: 'Let It Be',\n        key: 'Let It Be'\n      },\n      {\n        label: 'Maggie Mae',\n        key: 'Maggie Mae'\n      },\n      {\n        label: 'I\\'ve Got A Feeling',\n        key: 'I\\'ve Got A Feeling'\n      },\n      {\n        label: 'One After 909',\n        key: 'One After 909'\n      },\n      {\n        label: 'The Long And Winding Road',\n        key: 'The Long And Winding Road'\n      },\n      {\n        label: 'For You Blue',\n        key: 'For You Blue'\n      },\n      {\n        label: 'Get Back',\n        key: 'Get Back'\n      }\n    ]\n  }\n]\n</script>\n\n<template>\n  <n-space vertical>\n    <n-tree-select\n      filterable\n      :options=\"options\"\n      default-value=\"Drive My Car\"\n      clearable\n    />\n    <n-tree-select\n      multiple\n      checkable\n      filterable\n      :clear-filter-after-select=\"false\"\n      :options=\"options\"\n      :default-value=\"['Norwegian Wood']\"\n      clearable\n    />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/tree-select/demos/enUS/index.demo-entry.md",
    "content": "# Tree Select\n\nIt's said that 99% of the people can't distinguish the `TreeSelect` component from the `Cascader` component.\n\n## Demos\n\n```demo\nbasic.vue\ncustom-field.vue\nmultiple.vue\ncheckbox.vue\ncheck-strategy.vue\nshow-line.vue\nfilterable.vue\naction.vue\nasync.vue\nstatus.vue\nfile-picker.vue\ndebug.vue\n```\n\n## API\n\n### TreeSelect Props\n\n| Name | Type | Default | Description | Version |\n| --- | --- | --- | --- | --- |\n| allow-checking-not-loaded | `boolean` | `false` | Whether to allow cascade checking on not loaded nodes. If you want to use this, you should know the `value` may be incomplete. Also, you should aware about the consistency bewteen naive's checking logic and your backend's checking logic, especially when there are disabled nodes. | 2.28.1 |\n| cascade | `boolean` | `false` | Whether to link the selection of parent and child nodes. |  |\n| checkable | `boolean` | `false` | Whether to use a checkbox to select values. |  |\n| check-strategy | `string` | `'all'` | How to display selected nodes when parents and children are selected. |  |\n| children-field | `string` | `'children'` | The children property to use for `TreeSelectOption`'s. |  |\n| clearable | `boolean` | `false` | Whether the selection is clearable. |  |\n| clear-filter-after-select | `boolean` | `true` | When multiple and filter is true, whether to clear filter keyword after select an option. | 2.25.3 |\n| consistent-menu-width | `boolean` | `true` | Force the widths of selection input and menu to be equal. \\*This will disable virtual scrolling. |  |\n| default-value | `string \\| number \\| Array<string \\| number> \\| null` | `null` | Selected key (or keys when `multiple`) by default. |  |\n| default-expand-all | `boolean` | `false` | Expand all nodes by default. |  |\n| default-expanded-keys | `Array<string \\| number>` | `[]` | Expand specific keys by default. |  |\n| disabled | `boolean` | `false` | Disabled state. |  |\n| ellipsis-tag-popover-props | `PopoverProps` | `undefined` | `popover` props of the preview ellipsis tag. | 2.37.0 |\n| expanded-keys | `Array<string \\| number>` | `undefined` | Collection of expanded keys. |  |\n| indent | `number` | `24` | Indent of per level of the tree. | 2.41.1 |\n| indeterminate-keys | `Array<string \\| number>` | `undefined` | Indeterminate keys of the tree. |  |\n| filterable | `boolean` | `false` | Whether to show a filter. |  |\n| filter | `(pattern: string, option: TreeSelectOption) => boolean` | - | Filter function. |  |\n| get-children | `(option: any) => unknown` | `undefined` | Get children of the option. | 2.38.1 |\n| key-field | `string` | `'key'` | The key field used for `TreeSelectOption`. |  |\n| label-field | `string` | `'label'` | The label field used for `TreeSelectOption`. |  |\n| disabled-field | `string` | `'disabled'` | The disabled field used for `TreeSelectOption`. | 2.32.2 |\n| loading | `boolean` | `false` | Whether it's loading. | 2.28.3 |\n| max-tag-count | `number \\| 'responsive'` | `undefined` | Maximum number of selected options to show before the list is truncated. `'responsive'` will keep all of the selected options in one row. |  |\n| menu-props | `HTMLAttributes` | `undefined` | The menu's dom props. | 2.22.0 |\n| multiple | `boolean` | `false` | Allow selecting multiple options. |  |\n| node-props | `(info: { option: TreeSelectOption }) => HTMLAttributes` | `undefined` | HTML attributes of node. | 2.30.7 |\n| options | `TreeSelectOption[]` | `[]` | Options. |  |\n| override-default-node-click-behavior | `(info: { option: TreeSelectOption }) => 'toggleExpand' \\| 'toggleSelect' \\| 'toggleCheck' \\| 'default' \\| 'none'` | `undefined` | Override default node click behavior. | 2.37.0 |\n| placeholder | `string` | `'Please Select'` | Placeholder. |  |\n| placement | `'top-start' \\| 'top' \\| 'top-end' \\| 'right-start' \\| 'right' \\| 'right-end' \\| 'bottom-start' \\| 'bottom' \\| 'bottom-end' \\| 'left-start' \\| 'left' \\| 'left-end'` | `'bottom-start'` | Tree select menu's placement. | 2.25.0 |\n| render-label | `(info: { option: TreeSelectOption, checked: boolean, selected: boolean }) => VNodeChild` | `undefined` | Render function of all the options' label. | 2.30.7 |\n| render-prefix | `(info: { option: TreeSelectOption, checked: boolean, selected: boolean }) => VNodeChild` | `undefined` | Render function of all the options' prefix. | 2.30.7 |\n| render-suffix | `(info: { option: TreeSelectOption, checked: boolean, selected: boolean }) => VNodeChild` | `undefined` | Render function of all the options' suffix. | 2.30.7 |\n| render-switcher-icon | `() => VNodeChild` | `undefined` | Render function of option switcher icon. | 2.30.7 |\n| render-tag | `(props: { option: TreeSelectOption, handleClose: () => void }) => VNodeChild` | `undefined` | Render function for each option tag. | 2.30.7 |\n| separator | `string` | `' / '` | Option value separator. |  |\n| show-line | `boolean` | `false` | Whether to display tree connecting lines. | 2.44.0 |\n| show-path | `boolean` | `false` | Whether to also show the hierarchy of selected nodes in the label. |  |\n| size | `'small' \\| 'medium' \\| 'large'` | `'medium'` | Component size. |  |\n| status | `'success' \\| 'warning' \\| 'error'` | `undefined` | Validation status. | 2.27.0 |\n| to | `string \\| HTMLElement \\| false` | `body` | Container node of the menu. `false` will keep it not detached. |  |\n| value | `string \\| number \\| Array<string \\| number> \\| null>` | `undefined` | Selected key (or keys when multiple). |  |\n| virtual-scroll | `boolean` | `true` | Whether to enable virtual scrolling. |  |\n| watch-props | `Array<'defaultCheckedKeys' \\| 'defaultSelectedKeys' \\|'defaultExpandedKeys'>` | `undefined` | Default prop names that needed to be watched. Components will be updated after the prop is changed. Note: the `watch-props` itself is not reactive. | 2.36.0 |\n| on-blur | `(e: FocusEvent) => void` | `undefined` | Callback on blur. |  |\n| on-focus | `(e: FocusEvent) => void` | `undefined` | Callback on focus. |  |\n| on-load | `(node: TreeSelectOption) => Promise<void>` | `undefined` | Callback function for asynchronously loading data. | 2.27.0 |\n| on-update:expanded-keys | `(value: Array<string \\| number>, meta: { node: TreeOption \\| null, action: 'expand' \\| 'collapse' \\| 'filter' }) => void` | `undefined` | Callback on expanded keys updated. | `meta` 2.34.0 |\n| on-update:indeterminate-keys | `(keys: Array<string \\| number>) => void` | `undefined` | Callback function on indeterminate options changing. |  |\n| on-update:value | `(value: string \\| number \\| Array<string \\| number> \\| null, option: TreeSelectOption \\| null \\| Array<TreeSelectOption \\| null>, meta: { node: TreeOption \\| null, action: 'select' \\| 'unselect' \\| 'delete' \\| 'clear' }) => void) => void` | `undefined` | Callback on value updated. |  |\n\n### TreeSelectOption Properties\n\n| Name | Type | Description | Version |\n| --- | --- | --- | --- |\n| key | `string \\| number` | Unique option key. The field used can be set using `key-field`. |  |\n| label | `string` | Displayed content of the option. The field used can be set using `label-field`. |  |\n| children? | `TreeSelectOption[]` | Child options of the option. The field used can be set using `children-field` |  |\n| disabled? | `boolean` | Option disabled state. |  |\n| isLeaf? | `boolean` | Whether the node is leaf. Required in async mode. | 2.27.0 |\n\n### TreeSelect Slots\n\n| Name   | Parameters | Description                            | Version |\n| ------ | ---------- | -------------------------------------- | ------- |\n| header | `()`       | Header menu slot.                      | 2.40.0  |\n| action | `()`       | Options menu slot.                     | 2.22.0  |\n| arrow  | `()`       | Arrow icon of trigger.                 | 2.30.4  |\n| empty  | `()`       | Empty state slot for the options menu. | 2.22.0  |\n\n### TreeSelect Methods\n\n| Name | Type | Description | Version |\n| --- | --- | --- | --- |\n| blur | `() => void` | Blur. | 2.34.0 |\n| blurInput | `() => void` | Input blur. | 2.35.0 |\n| focus | `() => void` | Focus. | 2.34.0s |\n| focusInput | `() => void` | Input focus. | 2.35.0 |\n| getCheckedData | `() => { keys: Array<string \\| number>, options: Array<TreeOption \\| null> }` | Get checked data. | 2.34.0 |\n| getIndeterminateData | `() => { keys: Array<string \\| number>, options: Array<TreeOption \\| null> }` | Get indeterminate data. | 2.34.0 |\n"
  },
  {
    "path": "src/tree-select/demos/enUS/multiple.demo.vue",
    "content": "<markdown>\n# Multiple\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { TreeSelectOption } from 'naive-ui'\n\nfunction handleUpdateValue(\n  value: string | number | Array<string | number> | null,\n  option: TreeSelectOption | null | Array<TreeSelectOption | null>\n) {\n  console.log(value, option)\n}\n\nconst options = [\n  {\n    label: 'Rubber Soul',\n    key: 'Rubber Soul',\n    children: [\n      {\n        label: 'Everybody\\'s Got Something to Hide Except Me and My Monkey',\n        key: 'Everybody\\'s Got Something to Hide Except Me and My Monkey'\n      },\n      {\n        label: 'Drive My Car',\n        key: 'Drive My Car',\n        disabled: true\n      },\n      {\n        label: 'Norwegian Wood',\n        key: 'Norwegian Wood'\n      },\n      {\n        label: 'You Won\\'t See',\n        key: 'You Won\\'t See',\n        disabled: true\n      },\n      {\n        label: 'Nowhere Man',\n        key: 'Nowhere Man'\n      },\n      {\n        label: 'Think For Yourself',\n        key: 'Think For Yourself'\n      },\n      {\n        label: 'The Word',\n        key: 'The Word'\n      },\n      {\n        label: 'Michelle',\n        key: 'Michelle',\n        disabled: true\n      },\n      {\n        label: 'What goes on',\n        key: 'What goes on'\n      },\n      {\n        label: 'Girl',\n        key: 'Girl'\n      },\n      {\n        label: 'I\\'m looking through you',\n        key: 'I\\'m looking through you'\n      },\n      {\n        label: 'In My Life',\n        key: 'In My Life'\n      },\n      {\n        label: 'Wait',\n        key: 'Wait'\n      }\n    ]\n  },\n  {\n    label: 'Let It Be',\n    key: 'Let It Be Album',\n    children: [\n      {\n        label: 'Two Of Us',\n        key: 'Two Of Us'\n      },\n      {\n        label: 'Dig A Pony',\n        key: 'Dig A Pony'\n      },\n      {\n        label: 'Across The Universe',\n        key: 'Across The Universe'\n      },\n      {\n        label: 'I Me Mine',\n        key: 'I Me Mine'\n      },\n      {\n        label: 'Dig It',\n        key: 'Dig It'\n      },\n      {\n        label: 'Let It Be',\n        key: 'Let It Be'\n      },\n      {\n        label: 'Maggie Mae',\n        key: 'Maggie Mae'\n      },\n      {\n        label: 'I\\'ve Got A Feeling',\n        key: 'I\\'ve Got A Feeling'\n      },\n      {\n        label: 'One After 909',\n        key: 'One After 909'\n      },\n      {\n        label: 'The Long And Winding Road',\n        key: 'The Long And Winding Road'\n      },\n      {\n        label: 'For You Blue',\n        key: 'For You Blue'\n      },\n      {\n        label: 'Get Back',\n        key: 'Get Back'\n      }\n    ]\n  }\n]\n</script>\n\n<template>\n  <n-tree-select\n    multiple\n    :options=\"options\"\n    :default-value=\"['Norwegian Wood']\"\n    @update:value=\"handleUpdateValue\"\n  />\n</template>\n"
  },
  {
    "path": "src/tree-select/demos/enUS/show-line.demo.vue",
    "content": "<markdown>\n# Show Line\n\nUse `show-line` prop to display tree connecting lines.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { TreeSelectOption } from 'naive-ui'\n\nconst options: TreeSelectOption[] = [\n  {\n    label: 'Rubber Soul',\n    key: 'Rubber Soul',\n    children: [\n      {\n        label: 'Drive My Car',\n        key: 'Drive My Car'\n      },\n      {\n        label: 'Norwegian Wood',\n        key: 'Norwegian Wood'\n      },\n      {\n        label: 'You Won\\'t See',\n        key: 'You Won\\'t See'\n      },\n      {\n        label: 'Nowhere Man',\n        key: 'Nowhere Man'\n      },\n      {\n        label: 'Think For Yourself',\n        key: 'Think For Yourself'\n      }\n    ]\n  },\n  {\n    label: 'Let It Be',\n    key: 'Let It Be Album',\n    children: [\n      {\n        label: 'Two Of Us',\n        key: 'Two Of Us'\n      },\n      {\n        label: 'Dig A Pony',\n        key: 'Dig A Pony'\n      },\n      {\n        label: 'Across The Universe',\n        key: 'Across The Universe'\n      },\n      {\n        label: 'Let It Be',\n        key: 'Let It Be'\n      },\n      {\n        label: 'Get Back',\n        key: 'Get Back'\n      }\n    ]\n  }\n]\n</script>\n\n<template>\n  <n-tree-select\n    show-line\n    default-expand-all\n    :options=\"options\"\n    default-value=\"Drive My Car\"\n  />\n</template>\n"
  },
  {
    "path": "src/tree-select/demos/enUS/status.demo.vue",
    "content": "<markdown>\n# Validation status\n\nValidation status can be applied outside form.\n</markdown>\n\n<template>\n  <n-space vertical>\n    <n-tree-select status=\"warning\" placeholder=\"\" />\n    <n-tree-select status=\"error\" placeholder=\"\" />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/tree-select/demos/zhCN/action.demo.vue",
    "content": "<markdown>\n# 操作插槽\n\n可能你需要在树型选择菜单里用这个插槽。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { TreeSelectOption } from 'naive-ui'\n\nfunction handleUpdateValue(\n  value: string | number | Array<string | number> | null,\n  option: TreeSelectOption | null | Array<TreeSelectOption | null>\n) {\n  console.log(value, option)\n}\n\nconst options = [\n  {\n    label: 'Rubber Soul',\n    key: 'Rubber Soul',\n    children: [\n      {\n        label: 'Everybody\\'s Got Something to Hide Except Me and My Monkey',\n        key: 'Everybody\\'s Got Something to Hide Except Me and My Monkey'\n      },\n      {\n        label: 'Drive My Car',\n        key: 'Drive My Car',\n        disabled: true\n      },\n      {\n        label: 'Norwegian Wood',\n        key: 'Norwegian Wood'\n      },\n      {\n        label: 'You Won\\'t See',\n        key: 'You Won\\'t See',\n        disabled: true\n      },\n      {\n        label: 'Nowhere Man',\n        key: 'Nowhere Man'\n      },\n      {\n        label: 'Think For Yourself',\n        key: 'Think For Yourself'\n      },\n      {\n        label: 'The Word',\n        key: 'The Word'\n      },\n      {\n        label: 'Michelle',\n        key: 'Michelle',\n        disabled: true\n      },\n      {\n        label: 'What goes on',\n        key: 'What goes on'\n      },\n      {\n        label: 'Girl',\n        key: 'Girl'\n      },\n      {\n        label: 'I\\'m looking through you',\n        key: 'I\\'m looking through you'\n      },\n      {\n        label: 'In My Life',\n        key: 'In My Life'\n      },\n      {\n        label: 'Wait',\n        key: 'Wait'\n      }\n    ]\n  }\n]\n</script>\n\n<template>\n  <n-tree-select\n    :options=\"options\"\n    default-value=\"Drive My Car\"\n    @update:value=\"handleUpdateValue\"\n  >\n    <template #header>\n      不知道放些什么\n    </template>\n    <template #action>\n      你可以在这里自定义一些操作\n    </template>\n  </n-tree-select>\n</template>\n"
  },
  {
    "path": "src/tree-select/demos/zhCN/async.demo.vue",
    "content": "<markdown>\n# 异步加载\n\n使用 `on-load` 回调来加载数据。异步加载时，所有 `isLeaf` 为 `false` 并且 `children` 不为数组的节点会被视为未加载的节点。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { TreeSelectOption } from 'naive-ui'\nimport { ref } from 'vue'\n\nfunction getChildren(option: TreeSelectOption) {\n  const children = []\n  for (let i = 0; i <= (option as { depth: number }).depth; ++i) {\n    children.push({\n      label: `${option.label}-${i}`,\n      key: `${option.label}-${i}`,\n      depth: (option as { depth: number }).depth + 1,\n      isLeaf: option.depth === 3\n    })\n  }\n  return children\n}\n\nconst checkStrategy = ref<'all' | 'parent' | 'child'>('all')\nconst cascade = ref(false)\nconst showPath = ref(true)\nconst value = ref(null)\nconst options = ref([\n  {\n    label: 'l-0',\n    key: 'v-0',\n    depth: 1,\n    isLeaf: false\n  }\n])\n\nfunction handleLoad(option: TreeSelectOption) {\n  return new Promise<void>((resolve) => {\n    window.setTimeout(() => {\n      option.children = getChildren(option)\n      resolve()\n    }, 1000)\n  })\n}\n</script>\n\n<template>\n  <n-space vertical>\n    <n-space align=\"center\">\n      <n-radio-group v-model:value=\"checkStrategy\">\n        <n-radio-button value=\"all\">\n          All\n        </n-radio-button>\n        <n-radio-button value=\"parent\">\n          Parent\n        </n-radio-button>\n        <n-radio-button value=\"child\">\n          Child\n        </n-radio-button>\n      </n-radio-group>\n      <n-space><n-switch v-model:value=\"showPath\" />Show Path</n-space>\n      <n-space><n-switch v-model:value=\"cascade\" />Cascade </n-space>\n    </n-space>\n    <n-tree-select\n      v-model:value=\"value\"\n      multiple\n      checkable\n      :options=\"options\"\n      :cascade=\"cascade\"\n      :check-strategy=\"checkStrategy\"\n      :show-path=\"showPath\"\n      :allow-checking-not-loaded=\"cascade\"\n      :on-load=\"handleLoad\"\n    />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/tree-select/demos/zhCN/basic.demo.vue",
    "content": "<markdown>\n# 基础用法\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { TreeSelectOption } from 'naive-ui'\n\nfunction handleUpdateValue(\n  value: string | number | Array<string | number> | null,\n  option: TreeSelectOption | null | Array<TreeSelectOption | null>\n) {\n  console.log(value, option)\n}\n\nconst options = [\n  {\n    label: 'Rubber Soul',\n    key: 'Rubber Soul',\n    children: [\n      {\n        label: 'Everybody\\'s Got Something to Hide Except Me and My Monkey',\n        key: 'Everybody\\'s Got Something to Hide Except Me and My Monkey'\n      },\n      {\n        label: 'Drive My Car',\n        key: 'Drive My Car',\n        disabled: true\n      },\n      {\n        label: 'Norwegian Wood',\n        key: 'Norwegian Wood'\n      },\n      {\n        label: 'You Won\\'t See',\n        key: 'You Won\\'t See',\n        disabled: true\n      },\n      {\n        label: 'Nowhere Man',\n        key: 'Nowhere Man'\n      },\n      {\n        label: 'Think For Yourself',\n        key: 'Think For Yourself'\n      },\n      {\n        label: 'The Word',\n        key: 'The Word'\n      },\n      {\n        label: 'Michelle',\n        key: 'Michelle',\n        disabled: true\n      },\n      {\n        label: 'What goes on',\n        key: 'What goes on'\n      },\n      {\n        label: 'Girl',\n        key: 'Girl'\n      },\n      {\n        label: 'I\\'m looking through you',\n        key: 'I\\'m looking through you'\n      },\n      {\n        label: 'In My Life',\n        key: 'In My Life'\n      },\n      {\n        label: 'Wait',\n        key: 'Wait'\n      }\n    ]\n  },\n  {\n    label: 'Let It Be',\n    key: 'Let It Be Album',\n    children: [\n      {\n        label: 'Two Of Us',\n        key: 'Two Of Us'\n      },\n      {\n        label: 'Dig A Pony',\n        key: 'Dig A Pony'\n      },\n      {\n        label: 'Across The Universe',\n        key: 'Across The Universe'\n      },\n      {\n        label: 'I Me Mine',\n        key: 'I Me Mine'\n      },\n      {\n        label: 'Dig It',\n        key: 'Dig It'\n      },\n      {\n        label: 'Let It Be',\n        key: 'Let It Be'\n      },\n      {\n        label: 'Maggie Mae',\n        key: 'Maggie Mae'\n      },\n      {\n        label: 'I\\'ve Got A Feeling',\n        key: 'I\\'ve Got A Feeling'\n      },\n      {\n        label: 'One After 909',\n        key: 'One After 909'\n      },\n      {\n        label: 'The Long And Winding Road',\n        key: 'The Long And Winding Road'\n      },\n      {\n        label: 'For You Blue',\n        key: 'For You Blue'\n      },\n      {\n        label: 'Get Back',\n        key: 'Get Back'\n      }\n    ]\n  }\n]\n</script>\n\n<template>\n  <n-tree-select\n    :options=\"options\"\n    default-value=\"Drive My Car\"\n    @update:value=\"handleUpdateValue\"\n  />\n</template>\n"
  },
  {
    "path": "src/tree-select/demos/zhCN/check-strategy-debug.demo.vue",
    "content": "<markdown>\n# Check Strategy Debug\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { TreeSelectOption } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst cascade = ref(false)\nconst multiple = ref(false)\nconst checkStrategy = ref<'all' | 'parent' | 'child'>('all')\nconst checkable = ref(false)\nconst filterable = ref(false)\nconst options = [\n  {\n    label: 'Rubber Soul',\n    key: 'Rubber Soul',\n    children: [\n      {\n        label: 'Everybody\\'s Got Something to Hide Except Me and My Monkey',\n        key: 'Everybody\\'s Got Something to Hide Except Me and My Monkey'\n      },\n      {\n        label: 'Drive My Car',\n        key: 'Drive My Car',\n        disabled: true\n      },\n      {\n        label: 'Norwegian Wood',\n        key: 'Norwegian Wood'\n      },\n      {\n        label: 'You Won\\'t See',\n        key: 'You Won\\'t See',\n        disabled: true\n      },\n      {\n        label: 'Nowhere Man',\n        key: 'Nowhere Man'\n      },\n      {\n        label: 'Think For Yourself',\n        key: 'Think For Yourself'\n      },\n      {\n        label: 'The Word',\n        key: 'The Word'\n      },\n      {\n        label: 'Michelle',\n        key: 'Michelle',\n        disabled: true\n      },\n      {\n        label: 'What goes on',\n        key: 'What goes on'\n      },\n      {\n        label: 'Girl',\n        key: 'Girl'\n      },\n      {\n        label: 'I\\'m looking through you',\n        key: 'I\\'m looking through you'\n      },\n      {\n        label: 'In My Life',\n        key: 'In My Life'\n      },\n      {\n        label: 'Wait',\n        key: 'Wait'\n      }\n    ]\n  },\n  {\n    label: 'Let It Be',\n    key: 'Let It Be Album',\n    children: [\n      {\n        label: 'Two Of Us',\n        key: 'Two Of Us'\n      },\n      {\n        label: 'Dig A Pony',\n        key: 'Dig A Pony'\n      },\n      {\n        label: 'Across The Universe',\n        key: 'Across The Universe',\n        children: [\n          {\n            label: 'Dig It',\n            key: 'Dig It'\n          },\n          {\n            label: 'go',\n            key: 'go'\n          }\n        ]\n      }\n    ]\n  }\n]\n\nfunction handleUpdateValue(\n  value: string | number | Array<string | number> | null,\n  option: TreeSelectOption | null | Array<TreeSelectOption | null>\n) {\n  console.log(value, option)\n}\n</script>\n\n<template>\n  <n-space vertical>\n    <n-space>\n      <n-radio-group v-model:value=\"checkStrategy\">\n        <n-radio-button value=\"all\">\n          All\n        </n-radio-button>\n        <n-radio-button value=\"parent\">\n          Parent\n        </n-radio-button>\n        <n-radio-button value=\"child\">\n          Child\n        </n-radio-button>\n      </n-radio-group>\n      <n-switch v-model:value=\"checkable\">\n        <template #checked>\n          Checkable\n        </template>\n        <template #unchecked>\n          Unhheckable\n        </template>\n      </n-switch>\n      <n-switch v-model:value=\"multiple\">\n        <template #checked>\n          Multiple\n        </template>\n        <template #unchecked>\n          Single\n        </template>\n      </n-switch>\n      <n-switch v-model:value=\"cascade\">\n        <template #checked>\n          Cascade\n        </template>\n        <template #unchecked>\n          Uncascade\n        </template>\n      </n-switch>\n      <n-switch v-model:value=\"filterable\">\n        <template #checked>\n          Filterable\n        </template>\n        <template #unchecked>\n          Unfilterable\n        </template>\n      </n-switch>\n    </n-space>\n    <n-tree-select\n      default-expand-all\n      :multiple=\"multiple\"\n      :cascade=\"cascade\"\n      :checkable=\"checkable\"\n      :check-strategy=\"checkStrategy\"\n      :options=\"options\"\n      :default-value=\"['Rubber Soul']\"\n      @update:value=\"handleUpdateValue\"\n    />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/tree-select/demos/zhCN/check-strategy.demo.vue",
    "content": "<markdown>\n# 指定勾选策略\n\n设置勾选策略来指定显示的勾选节点，`all` 表示显示全部选中节点；`parent` 表示只显示父节点（当父节点下所有子节点都选中时）；`child` 表示只显示子节点。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { TreeSelectOption } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst checkStrategy = ref<'all' | 'child' | 'parent'>('all')\nconst options = [\n  {\n    label: 'Rubber Soul',\n    key: 'Rubber Soul',\n    children: [\n      {\n        label: 'Everybody\\'s Got Something to Hide Except Me and My Monkey',\n        key: 'Everybody\\'s Got Something to Hide Except Me and My Monkey'\n      },\n      {\n        label: 'Drive My Car',\n        key: 'Drive My Car',\n        disabled: true\n      },\n      {\n        label: 'Norwegian Wood',\n        key: 'Norwegian Wood'\n      },\n      {\n        label: 'You Won\\'t See',\n        key: 'You Won\\'t See',\n        disabled: true\n      },\n      {\n        label: 'Nowhere Man',\n        key: 'Nowhere Man'\n      },\n      {\n        label: 'Think For Yourself',\n        key: 'Think For Yourself'\n      },\n      {\n        label: 'The Word',\n        key: 'The Word'\n      },\n      {\n        label: 'Michelle',\n        key: 'Michelle',\n        disabled: true\n      },\n      {\n        label: 'What goes on',\n        key: 'What goes on'\n      },\n      {\n        label: 'Girl',\n        key: 'Girl'\n      },\n      {\n        label: 'I\\'m looking through you',\n        key: 'I\\'m looking through you'\n      },\n      {\n        label: 'In My Life',\n        key: 'In My Life'\n      },\n      {\n        label: 'Wait',\n        key: 'Wait'\n      }\n    ]\n  },\n  {\n    label: 'Let It Be',\n    key: 'Let It Be Album',\n    children: [\n      {\n        label: 'Two Of Us',\n        key: 'Two Of Us'\n      },\n      {\n        label: 'Dig A Pony',\n        key: 'Dig A Pony'\n      },\n      {\n        label: 'Across The Universe',\n        key: 'Across The Universe',\n        children: [\n          {\n            label: 'Dig It',\n            key: 'Dig It'\n          },\n          {\n            label: 'go',\n            key: 'go'\n          }\n        ]\n      }\n    ]\n  }\n]\n\nfunction handleUpdateValue(\n  value: string | number | Array<string | number> | null,\n  option: TreeSelectOption | null | Array<TreeSelectOption | null>\n) {\n  console.log(value, option)\n}\n</script>\n\n<template>\n  <n-space vertical>\n    <n-space>\n      <n-radio-group v-model:value=\"checkStrategy\">\n        <n-radio-button value=\"all\">\n          All\n        </n-radio-button>\n        <n-radio-button value=\"parent\">\n          Parent\n        </n-radio-button>\n        <n-radio-button value=\"child\">\n          Child\n        </n-radio-button>\n      </n-radio-group>\n    </n-space>\n    <n-tree-select\n      multiple\n      cascade\n      checkable\n      :check-strategy=\"checkStrategy\"\n      :options=\"options\"\n      :default-value=\"['Dig It', 'go']\"\n      @update:value=\"handleUpdateValue\"\n    />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/tree-select/demos/zhCN/checkbox.demo.vue",
    "content": "<markdown>\n# 使用 Checkbox 选择\n\n想达到 demo 的效果，`checkable`、`cascade`、`multiple` 需要同时设定。\n</markdown>\n\n<script lang=\"ts\" setup>\nconst options = [\n  {\n    label: 'Rubber Soul',\n    key: 'Rubber Soul',\n    children: [\n      {\n        label: 'Everybody\\'s Got Something to Hide Except Me and My Monkey',\n        key: 'Everybody\\'s Got Something to Hide Except Me and My Monkey'\n      },\n      {\n        label: 'Drive My Car',\n        key: 'Drive My Car',\n        disabled: true\n      },\n      {\n        label: 'Norwegian Wood',\n        key: 'Norwegian Wood'\n      },\n      {\n        label: 'You Won\\'t See',\n        key: 'You Won\\'t See',\n        disabled: true\n      },\n      {\n        label: 'Nowhere Man',\n        key: 'Nowhere Man'\n      },\n      {\n        label: 'Think For Yourself',\n        key: 'Think For Yourself'\n      },\n      {\n        label: 'The Word',\n        key: 'The Word'\n      },\n      {\n        label: 'Michelle',\n        key: 'Michelle',\n        disabled: true\n      },\n      {\n        label: 'What goes on',\n        key: 'What goes on'\n      },\n      {\n        label: 'Girl',\n        key: 'Girl'\n      },\n      {\n        label: 'I\\'m looking through you',\n        key: 'I\\'m looking through you'\n      },\n      {\n        label: 'In My Life',\n        key: 'In My Life'\n      },\n      {\n        label: 'Wait',\n        key: 'Wait'\n      }\n    ]\n  },\n  {\n    label: 'Let It Be',\n    key: 'Let It Be Album',\n    children: [\n      {\n        label: 'Two Of Us',\n        key: 'Two Of Us'\n      },\n      {\n        label: 'Dig A Pony',\n        key: 'Dig A Pony'\n      },\n      {\n        label: 'Across The Universe',\n        key: 'Across The Universe'\n      },\n      {\n        label: 'I Me Mine',\n        key: 'I Me Mine'\n      },\n      {\n        label: 'Dig It',\n        key: 'Dig It'\n      },\n      {\n        label: 'Let It Be',\n        key: 'Let It Be'\n      },\n      {\n        label: 'Maggie Mae',\n        key: 'Maggie Mae'\n      },\n      {\n        label: 'I\\'ve Got A Feeling',\n        key: 'I\\'ve Got A Feeling'\n      },\n      {\n        label: 'One After 909',\n        key: 'One After 909'\n      },\n      {\n        label: 'The Long And Winding Road',\n        key: 'The Long And Winding Road'\n      },\n      {\n        label: 'For You Blue',\n        key: 'For You Blue'\n      },\n      {\n        label: 'Get Back',\n        key: 'Get Back'\n      }\n    ]\n  }\n]\n</script>\n\n<template>\n  <n-tree-select\n    multiple\n    cascade\n    checkable\n    :options=\"options\"\n    :default-value=\"['Norwegian Wood']\"\n  />\n</template>\n"
  },
  {
    "path": "src/tree-select/demos/zhCN/custom-field.demo.vue",
    "content": "<markdown>\n# 自定义字段\n\n后端会传来各种各样的数据。\n</markdown>\n\n<script lang=\"ts\" setup>\nconst options = [\n  {\n    whateverLabel: 'Rubber Soul',\n    whateverKey: 'Rubber Soul',\n    whateverChildren: [\n      {\n        whateverLabel:\n          'Everybody\\'s Got Something to Hide Except Me and My Monkey',\n        whateverKey: 'Everybody\\'s Got Something to Hide Except Me and My Monkey'\n      },\n      {\n        whateverLabel: 'Drive My Car',\n        whateverKey: 'Drive My Car',\n        disabled: true\n      },\n      {\n        whateverLabel: 'Norwegian Wood',\n        whateverKey: 'Norwegian Wood'\n      },\n      {\n        whateverLabel: 'You Won\\'t See',\n        whateverKey: 'You Won\\'t See',\n        disabled: true\n      },\n      {\n        whateverLabel: 'Nowhere Man',\n        whateverKey: 'Nowhere Man'\n      },\n      {\n        whateverLabel: 'Think For Yourself',\n        whateverKey: 'Think For Yourself'\n      },\n      {\n        whateverLabel: 'The Word',\n        whateverKey: 'The Word'\n      },\n      {\n        whateverLabel: 'Michelle',\n        whateverKey: 'Michelle',\n        disabled: true\n      },\n      {\n        whateverLabel: 'What goes on',\n        whateverKey: 'What goes on'\n      },\n      {\n        whateverLabel: 'Girl',\n        whateverKey: 'Girl'\n      },\n      {\n        whateverLabel: 'I\\'m looking through you',\n        whateverKey: 'I\\'m looking through you'\n      },\n      {\n        whateverLabel: 'In My Life',\n        whateverKey: 'In My Life'\n      },\n      {\n        whateverLabel: 'Wait',\n        whateverKey: 'Wait'\n      }\n    ]\n  },\n  {\n    whateverLabel: 'Let It Be',\n    whateverKey: 'Let It Be Album',\n    whateverChildren: [\n      {\n        whateverLabel: 'Two Of Us',\n        whateverKey: 'Two Of Us'\n      },\n      {\n        whateverLabel: 'Dig A Pony',\n        whateverKey: 'Dig A Pony'\n      },\n      {\n        whateverLabel: 'Across The Universe',\n        whateverKey: 'Across The Universe'\n      },\n      {\n        whateverLabel: 'I Me Mine',\n        whateverKey: 'I Me Mine'\n      },\n      {\n        whateverLabel: 'Dig It',\n        whateverKey: 'Dig It'\n      },\n      {\n        whateverLabel: 'Let It Be',\n        whateverKey: 'Let It Be'\n      },\n      {\n        whateverLabel: 'Maggie Mae',\n        whateverKey: 'Maggie Mae'\n      },\n      {\n        whateverLabel: 'I\\'ve Got A Feeling',\n        whateverKey: 'I\\'ve Got A Feeling'\n      },\n      {\n        whateverLabel: 'One After 909',\n        whateverKey: 'One After 909'\n      },\n      {\n        whateverLabel: 'The Long And Winding Road',\n        whateverKey: 'The Long And Winding Road'\n      },\n      {\n        whateverLabel: 'For You Blue',\n        whateverKey: 'For You Blue'\n      },\n      {\n        whateverLabel: 'Get Back',\n        whateverKey: 'Get Back'\n      }\n    ]\n  }\n]\n</script>\n\n<template>\n  <n-tree-select\n    :options=\"options\"\n    default-value=\"Drive My Car\"\n    label-field=\"whateverLabel\"\n    key-field=\"whateverKey\"\n    children-field=\"whateverChildren\"\n  />\n</template>\n"
  },
  {
    "path": "src/tree-select/demos/zhCN/debug.demo.vue",
    "content": "<markdown>\n# Debug\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { TreeSelectOption } from 'naive-ui'\nimport { ref } from 'vue'\n\nfunction createData(level = 4, baseKey = ''): TreeSelectOption[] | undefined {\n  if (!level)\n    return undefined\n  return Array.from({ length: 6 - level }).map((_, index) => {\n    const key = `${baseKey}${level}${index}`\n    return {\n      label: key,\n      key,\n      children: createData(level - 1, key)\n    }\n  })\n}\n\nconst multiple = ref(false)\nconst checkable = ref(false)\nconst cascade = ref(false)\nconst filterable = ref(false)\nconst options = createData()\nconst showPath = ref(false)\nconst loading = ref(false)\n</script>\n\n<template>\n  <n-space vertical>\n    <n-space>\n      <n-switch v-model:value=\"multiple\" />Multiple\n      <n-switch v-model:value=\"checkable\" />Checkable\n      <n-switch v-model:value=\"cascade\" />Cascade\n      <n-switch v-model:value=\"filterable\" />Filterable\n      <n-switch v-model:value=\"showPath\" />ShowPath\n      <n-switch v-model:value=\"loading\" />Loading\n    </n-space>\n    <n-tree-select\n      default-expand-all\n      :options=\"options\"\n      :multiple=\"multiple\"\n      :checkable=\"checkable\"\n      :cascade=\"cascade\"\n      :filterable=\"filterable\"\n      :show-path=\"showPath\"\n      :loading=\"loading\"\n    />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/tree-select/demos/zhCN/field-search-debug.demo.vue",
    "content": "<markdown>\n# Field search debug\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { NTreeSelect } from 'naive-ui'\n\nconst options1 = [\n  {\n    name: 'label',\n    id: 'value',\n    subs: [{ name: 'child1', id: 'child1id' }]\n  }\n]\n\nconst options2 = [\n  {\n    label: 'label',\n    key: 'value',\n    children: [{ label: 'child1', key: 'child1id' }]\n  }\n]\n</script>\n\n<template>\n  <div>\n    有问题\n    <NTreeSelect\n      :options=\"options1\"\n      label-field=\"name\"\n      key-field=\"id\"\n      children-field=\"subs\"\n      filterable\n    />\n    没问题\n    <NTreeSelect :options=\"options2\" filterable />\n  </div>\n</template>\n"
  },
  {
    "path": "src/tree-select/demos/zhCN/file-picker.demo.vue",
    "content": "<markdown>\n# 文件选择器\n\n利用 `override-default-node-click-behavior` 属性模拟仅允许选中文件、而不允许选中文件夹的行为。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { TreeSelectOverrideNodeClickBehavior } from 'naive-ui'\n\nconst override: TreeSelectOverrideNodeClickBehavior = ({ option }) => {\n  if (option.children) {\n    return 'toggleExpand'\n  }\n  return 'default'\n}\n\nconst options = [\n  {\n    label: 'Folder-1',\n    key: 'Folder-1',\n    children: [\n      {\n        label: 'File-1-1',\n        key: 'File-1-1'\n      },\n      {\n        label: 'Folder-1-2',\n        key: 'Folder-1-2',\n        children: [\n          {\n            label: 'File-1-2-1',\n            key: 'File-1-2-1'\n          },\n          {\n            label: 'File-1-2-2',\n            key: 'File-1-2-2'\n          }\n        ]\n      }\n    ]\n  },\n  {\n    label: 'Folder-2',\n    key: 'Folder-2',\n    children: [\n      {\n        label: 'File-2-1',\n        key: 'File-2-1'\n      },\n      {\n        label: 'File-2-2',\n        key: 'File-2-2'\n      }\n    ]\n  }\n]\n</script>\n\n<template>\n  <n-tree-select\n    block-line\n    :options=\"options\"\n    :override-default-node-click-behavior=\"override\"\n  />\n</template>\n"
  },
  {
    "path": "src/tree-select/demos/zhCN/filterable.demo.vue",
    "content": "<markdown>\n# 可过滤\n</markdown>\n\n<script lang=\"ts\" setup>\nconst options = [\n  {\n    label: 'Rubber Soul',\n    key: 'Rubber Soul',\n    children: [\n      {\n        label: 'Everybody\\'s Got Something to Hide Except Me and My Monkey',\n        key: 'Everybody\\'s Got Something to Hide Except Me and My Monkey'\n      },\n      {\n        label: 'Drive My Car',\n        key: 'Drive My Car',\n        disabled: true\n      },\n      {\n        label: 'Norwegian Wood',\n        key: 'Norwegian Wood'\n      },\n      {\n        label: 'You Won\\'t See',\n        key: 'You Won\\'t See',\n        disabled: true\n      },\n      {\n        label: 'Nowhere Man',\n        key: 'Nowhere Man'\n      },\n      {\n        label: 'Think For Yourself',\n        key: 'Think For Yourself'\n      },\n      {\n        label: 'The Word',\n        key: 'The Word'\n      },\n      {\n        label: 'Michelle',\n        key: 'Michelle',\n        disabled: true\n      },\n      {\n        label: 'What goes on',\n        key: 'What goes on'\n      },\n      {\n        label: 'Girl',\n        key: 'Girl'\n      },\n      {\n        label: 'I\\'m looking through you',\n        key: 'I\\'m looking through you'\n      },\n      {\n        label: 'In My Life',\n        key: 'In My Life'\n      },\n      {\n        label: 'Wait',\n        key: 'Wait'\n      }\n    ]\n  },\n  {\n    label: 'Let It Be',\n    key: 'Let It Be Album',\n    children: [\n      {\n        label: 'Two Of Us',\n        key: 'Two Of Us'\n      },\n      {\n        label: 'Dig A Pony',\n        key: 'Dig A Pony'\n      },\n      {\n        label: 'Across The Universe',\n        key: 'Across The Universe'\n      },\n      {\n        label: 'I Me Mine',\n        key: 'I Me Mine'\n      },\n      {\n        label: 'Dig It',\n        key: 'Dig It'\n      },\n      {\n        label: 'Let It Be',\n        key: 'Let It Be'\n      },\n      {\n        label: 'Maggie Mae',\n        key: 'Maggie Mae'\n      },\n      {\n        label: 'I\\'ve Got A Feeling',\n        key: 'I\\'ve Got A Feeling'\n      },\n      {\n        label: 'One After 909',\n        key: 'One After 909'\n      },\n      {\n        label: 'The Long And Winding Road',\n        key: 'The Long And Winding Road'\n      },\n      {\n        label: 'For You Blue',\n        key: 'For You Blue'\n      },\n      {\n        label: 'Get Back',\n        key: 'Get Back'\n      }\n    ]\n  }\n]\n</script>\n\n<template>\n  <n-space vertical>\n    <n-tree-select\n      filterable\n      :options=\"options\"\n      default-value=\"Drive My Car\"\n      clearable\n    />\n    <n-tree-select\n      multiple\n      checkable\n      filterable\n      :clear-filter-after-select=\"false\"\n      :options=\"options\"\n      :default-value=\"['Norwegian Wood']\"\n      clearable\n    />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/tree-select/demos/zhCN/index.demo-entry.md",
    "content": "# 树型选择 Tree Select\n\n据说 99% 的人分不清它和 Cascader 的区别。\n\n## 演示\n\n```demo\nbasic.vue\ncustom-field.vue\nmultiple.vue\ncheckbox.vue\ncheck-strategy.vue\nshow-line.vue\nfilterable.vue\ncheck-strategy-debug.vue\naction.vue\nasync.vue\nstatus.vue\nfile-picker.vue\ndebug.vue\nfield-search-debug.vue\nrender-debug.vue\nrtl-debug.vue\n```\n\n## API\n\n### TreeSelect Props\n\n| 名称 | 类型 | 默认值 | 说明 | 版本 |\n| --- | --- | --- | --- | --- |\n| allow-checking-not-loaded | `boolean` | `false` | 是否允许级联勾选还没有完全加载的节点。如果你要用这个属性，请记住 `value` 可能是不完整的，并且请注意勾选行为和后端计算逻辑的一致性，尤其是有禁用节点的情况下 | 2.28.1 |\n| cascade | `boolean` | `false` | 使用 checkbox 进行多选时是否级联 |  |\n| checkable | `boolean` | `false` | 是否使用 checkbox 进行选择 |  |\n| check-strategy | `string` | `'all'` | 设置勾选策略来指定显示的勾选节点，`all` 表示显示全部选中节点；`parent` 表示只显示父节点（当父节点下所有子节点都选中时）；`child` 表示只显示子节点 |  |\n| children-field | `string` | `'children'` | 替代 `TreeSelectOption` 中的 children 字段名 |  |\n| clearable | `boolean` | `false` | 是否可清除 |  |\n| clear-filter-after-select | `boolean` | `true` | 是否在可过滤和多选的情况下选中一个选项后保留当前的搜索关键词 | 2.25.3 |\n| consistent-menu-width | `boolean` | `true` | 是否使菜单宽度和输入框一致，打开会禁用虚拟滚动 |  |\n| default-value | `string \\| number \\| Array<string \\| number> \\| null` | `null` | 默认选中的 key |  |\n| default-expand-all | `boolean` | `false` | 默认展开全部 |  |\n| default-expanded-keys | `Array<string \\| number>` | `[]` | 默认展开节点的 key |  |\n| disabled | `boolean` | `false` | 是否禁用 |  |\n| ellipsis-tag-popover-props | `PopoverProps` | `undefined` | 选中选项过多省略显示时，预览弹出 `popover` 的属性 | 2.37.0 |\n| expanded-keys | `Array<string \\| number>` | `undefined` | 展开节点的 key |  |\n| indent | `number` | `24` | 树的每一级缩进的大小 | 2.41.1 |\n| indeterminate-keys | `string \\| number` | `undefined` | 部分选中选项的 key |  |\n| filterable | `boolean` | `false` | 是否可过滤 |  |\n| filter | `(pattern: string, option: TreeSelectOption) => boolean` | - | 过滤器函数 |  |\n| get-children | `(option: any) => unknown` | `undefined` | 获取当前选项的子选项 | 2.38.1 |\n| key-field | `string` | `'key'` | 替代 `TreeSelectOption` 中的 key 字段名 |  |\n| label-field | `string` | `'label'` | 替代 `TreeSelectOption` 中的 label 字段名 |  |\n| disabled-field | `string` | `'disabled'` | 替代 `TreeSelectOption` 中的 disabled 字段名 | 2.32.2 |\n| loading | `boolean` | `false` | 是否加载中 | 2.28.3 |\n| max-tag-count | `number \\| 'responsive'` | `undefined` | 多选时最多直接显示多少选项，设为 `'responsive'` 会保证最多一行 |  |\n| menu-props | `HTMLAttributes` | `undefined` | 菜单的 DOM 属性 | 2.22.0 |\n| multiple | `boolean` | `false` | 是否支持多选 |  |\n| node-props | `(info: { option: TreeSelectOption }) => HTMLAttributes` | `undefined` | 节点的 HTML 属性 | 2.30.7 |\n| options | `TreeSelectOption[]` | `[]` | 选项 |  |\n| override-default-node-click-behavior | `(info: { option: TreeSelectOption }) => 'toggleExpand' \\| 'toggleSelect' \\| 'toggleCheck' \\| 'default' \\| 'none'` | `undefined` | 覆盖默认的节点点击行为 | 2.37.0 |\n| placeholder | `string` | `'请选择'` | 占位信息 |  |\n| placement | `'top-start' \\| 'top' \\| 'top-end' \\| 'right-start' \\| 'right' \\| 'right-end' \\| 'bottom-start' \\| 'bottom' \\| 'bottom-end' \\| 'left-start' \\| 'left' \\| 'left-end'` | `'bottom-start'` | 选择器的弹出位置. | 2.25.0 |\n| render-label | `(info: { option: TreeSelectOption, checked: boolean, selected: boolean }) => VNodeChild` | `undefined` | 节点内容的渲染函数 | 2.30.7 |\n| render-prefix | `(info: { option: TreeSelectOption, checked: boolean, selected: boolean }) => VNodeChild` | `undefined` | 节点前缀的渲染函数 | 2.30.7 |\n| render-suffix | `(info: { option: TreeSelectOption, checked: boolean, selected: boolean }) => VNodeChild` | `undefined` | 节点后缀的渲染函数 | 2.30.7 |\n| render-switcher-icon | `() => VNodeChild` | `undefined` | 节点展开开关的渲染函数 | 2.30.7 |\n| render-tag | `(props: { option: TreeSelectOption, handleClose: () => void }) => VNodeChild` | `undefined` | 控制标签的渲染 | 2.30.7 |\n| separator | `string` | `' / '` | 数据分隔符 |  |\n| show-line | `boolean` | `false` | 是否显示树的连接线 | 2.44.0 |\n| show-path | `boolean` | `false` | 是否在选择器中显示选项路径 |  |\n| size | `'small' \\| 'medium' \\| 'large'` | `'medium'` | 组件尺寸 |  |\n| status | `'success' \\| 'warning' \\| 'error'` | `undefined` | 验证状态 | 2.27.0 |\n| to | `string \\| HTMLElement \\| false` | `body` | 菜单的容器节点，`false` 会待在原地 |  |\n| value | `string \\| number \\| Array<string \\| number> \\| null>` | `undefined` | 选中的 key |  |\n| virtual-scroll | `boolean` | `true` | 是否开启虚拟滚动 |  |\n| watch-props | `Array<'defaultCheckedKeys' \\| 'defaultSelectedKeys' \\|'defaultExpandedKeys'>` | `undefined` | 需要检测变更的默认属性，检测后组件状态会更新。注意：`watch-props` 本身不是响应式的 | 2.36.0 |\n| on-blur | `(e: FocusEvent) => void` | `undefined` | Blur 时的回调 |  |\n| on-focus | `(e: FocusEvent) => void` | `undefined` | Focus 时的回调 |  |\n| on-load | `(node: TreeSelectOption) => Promise<void>` | `undefined` | 异步加载数据的回调函数 | 2.27.0 |\n| on-update:expanded-keys | `(value: Array<string \\| number>, meta: { node: TreeOption \\| null, action: 'expand' \\| 'collapse' \\| 'filter' }) => void` | `undefined` | 展开节点更新的回调 | `meta` 2.34.0 |\n| on-update:indeterminate-keys | `(keys: Array<string \\| number>) => void` | `undefined` | 节点部分勾选项发生变化时的回调函数 |  |\n| on-update:value | `(value: string \\| number \\| Array<string \\| number> \\| null, option: TreeSelectOption \\| null \\| Array<TreeSelectOption \\| null>, meta: { node: TreeOption \\| null, action: 'select' \\| 'unselect' \\| 'delete' \\| 'clear' }) => void` | `undefined` | 更新值的回调 | `meta` 2.34.0 |\n\n### TreeSelectOption Properties\n\n| 名称 | 类型 | 说明 | 版本 |\n| --- | --- | --- | --- |\n| key | `string \\| number` | 选项的 key，需要唯一，可使用 `key-field` 修改字段名 |  |\n| label | `string` | 选项的显示内容，可使用 `label-field` 修改字段名 |  |\n| children? | `TreeSelectOption[]` | 节点的子选项 |  |\n| disabled? | `boolean` | 是否禁用选项 |  |\n| isLeaf? | `boolean` | 节点是否是叶节点，在异步展开状态下是必须的 | 2.27.0 |\n\n### TreeSelect Slots\n\n| 名称   | 参数 | 说明                | 版本   |\n| ------ | ---- | ------------------- | ------ |\n| header | `()` | 菜单头部区域的 slot | 2.40.0 |\n| action | `()` | 菜单操作区域的 slot | 2.22.0 |\n| arrow  | `()` | 选择箭头 slot       | 2.30.4 |\n| empty  | `()` | 菜单无数据时的 slot | 2.22.0 |\n\n### TreeSelect Methods\n\n| 名称 | 类型 | 说明 | 版本 |\n| --- | --- | --- | --- |\n| blur | `() => void` | 失焦 | 2.34.0 |\n| blurInput | `() => void` | 输入失焦 | 2.35.0 |\n| focus | `() => void` | 聚焦 | 2.34.0 |\n| focusInput | `() => void` | 输入聚焦 | 2.35.0 |\n| getCheckedData | `() => { keys: Array<string \\| number>, options: Array<TreeOption \\| null> }` | 获取选中的数据 | 2.34.0 |\n| getIndeterminateData | `() => { keys: Array<string \\| number>, options: Array<TreeOption \\| null> }` | 获取半选的数据 | 2.34.0 |\n"
  },
  {
    "path": "src/tree-select/demos/zhCN/multiple.demo.vue",
    "content": "<markdown>\n# 多选\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { TreeSelectOption } from 'naive-ui'\n\nfunction handleUpdateValue(\n  value: string | number | Array<string | number> | null,\n  option: TreeSelectOption | null | Array<TreeSelectOption | null>\n) {\n  console.log(value, option)\n}\n\nconst options = [\n  {\n    label: 'Rubber Soul',\n    key: 'Rubber Soul',\n    children: [\n      {\n        label: 'Everybody\\'s Got Something to Hide Except Me and My Monkey',\n        key: 'Everybody\\'s Got Something to Hide Except Me and My Monkey'\n      },\n      {\n        label: 'Drive My Car',\n        key: 'Drive My Car',\n        disabled: true\n      },\n      {\n        label: 'Norwegian Wood',\n        key: 'Norwegian Wood'\n      },\n      {\n        label: 'You Won\\'t See',\n        key: 'You Won\\'t See',\n        disabled: true\n      },\n      {\n        label: 'Nowhere Man',\n        key: 'Nowhere Man'\n      },\n      {\n        label: 'Think For Yourself',\n        key: 'Think For Yourself'\n      },\n      {\n        label: 'The Word',\n        key: 'The Word'\n      },\n      {\n        label: 'Michelle',\n        key: 'Michelle',\n        disabled: true\n      },\n      {\n        label: 'What goes on',\n        key: 'What goes on'\n      },\n      {\n        label: 'Girl',\n        key: 'Girl'\n      },\n      {\n        label: 'I\\'m looking through you',\n        key: 'I\\'m looking through you'\n      },\n      {\n        label: 'In My Life',\n        key: 'In My Life'\n      },\n      {\n        label: 'Wait',\n        key: 'Wait'\n      }\n    ]\n  },\n  {\n    label: 'Let It Be',\n    key: 'Let It Be Album',\n    children: [\n      {\n        label: 'Two Of Us',\n        key: 'Two Of Us'\n      },\n      {\n        label: 'Dig A Pony',\n        key: 'Dig A Pony'\n      },\n      {\n        label: 'Across The Universe',\n        key: 'Across The Universe'\n      },\n      {\n        label: 'I Me Mine',\n        key: 'I Me Mine'\n      },\n      {\n        label: 'Dig It',\n        key: 'Dig It'\n      },\n      {\n        label: 'Let It Be',\n        key: 'Let It Be'\n      },\n      {\n        label: 'Maggie Mae',\n        key: 'Maggie Mae'\n      },\n      {\n        label: 'I\\'ve Got A Feeling',\n        key: 'I\\'ve Got A Feeling'\n      },\n      {\n        label: 'One After 909',\n        key: 'One After 909'\n      },\n      {\n        label: 'The Long And Winding Road',\n        key: 'The Long And Winding Road'\n      },\n      {\n        label: 'For You Blue',\n        key: 'For You Blue'\n      },\n      {\n        label: 'Get Back',\n        key: 'Get Back'\n      }\n    ]\n  }\n]\n</script>\n\n<template>\n  <n-tree-select\n    multiple\n    :options=\"options\"\n    :default-value=\"['Norwegian Wood']\"\n    @update:value=\"handleUpdateValue\"\n  />\n</template>\n"
  },
  {
    "path": "src/tree-select/demos/zhCN/render-debug.demo.vue",
    "content": "<markdown>\n# Render debug\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type {\n  TreeSelectNodeProps,\n  TreeSelectOption,\n  TreeSelectRenderLabel,\n  TreeSelectRenderTag\n} from 'naive-ui'\nimport { NTag } from 'naive-ui'\nimport { h } from 'vue'\n\nconst nodeProps: TreeSelectNodeProps = ({ option }) => {\n  return {\n    'data-xxx': option.label || ''\n  }\n}\n\nconst renderXxx: TreeSelectRenderLabel = ({ option }) => {\n  return option.label || ''\n}\n\nconst renderTag: TreeSelectRenderTag = ({ option, handleClose }) => {\n  console.log('renderTag', option)\n  return h(\n    NTag,\n    {\n      type: 'error',\n      closable: !option.disabled,\n      onMousedown: (e: FocusEvent) => {\n        e.preventDefault()\n      },\n      onClose: (e) => {\n        e.stopPropagation()\n        handleClose()\n      }\n    },\n    {\n      default: () => option.label || ''\n    }\n  )\n}\n\nconst renderSwitcherIcon = () => 'x'\n\nfunction handleUpdateValue(\n  value: string | number | Array<string | number> | null,\n  option: TreeSelectOption | null | Array<TreeSelectOption | null>\n) {\n  console.log(value, option)\n}\n\nconst options = [\n  {\n    label: 'Rubber Soul',\n    key: 'Rubber Soul',\n    children: [\n      {\n        label: 'Everybody\\'s Got Something to Hide Except Me and My Monkey',\n        key: 'Everybody\\'s Got Something to Hide Except Me and My Monkey'\n      },\n      {\n        label: 'Drive My Car',\n        key: 'Drive My Car',\n        disabled: true\n      },\n      {\n        label: 'Norwegian Wood',\n        key: 'Norwegian Wood'\n      },\n      {\n        label: 'You Won\\'t See',\n        key: 'You Won\\'t See',\n        disabled: true\n      },\n      {\n        label: 'Nowhere Man',\n        key: 'Nowhere Man'\n      },\n      {\n        label: 'Think For Yourself',\n        key: 'Think For Yourself'\n      },\n      {\n        label: 'The Word',\n        key: 'The Word'\n      },\n      {\n        label: 'Michelle',\n        key: 'Michelle',\n        disabled: true\n      },\n      {\n        label: 'What goes on',\n        key: 'What goes on'\n      },\n      {\n        label: 'Girl',\n        key: 'Girl'\n      },\n      {\n        label: 'I\\'m looking through you',\n        key: 'I\\'m looking through you'\n      },\n      {\n        label: 'In My Life',\n        key: 'In My Life'\n      },\n      {\n        label: 'Wait',\n        key: 'Wait'\n      }\n    ]\n  },\n  {\n    label: 'Let It Be',\n    key: 'Let It Be Album',\n    children: [\n      {\n        label: 'Two Of Us',\n        key: 'Two Of Us'\n      },\n      {\n        label: 'Dig A Pony',\n        key: 'Dig A Pony'\n      },\n      {\n        label: 'Across The Universe',\n        key: 'Across The Universe'\n      },\n      {\n        label: 'I Me Mine',\n        key: 'I Me Mine'\n      },\n      {\n        label: 'Dig It',\n        key: 'Dig It'\n      },\n      {\n        label: 'Let It Be',\n        key: 'Let It Be'\n      },\n      {\n        label: 'Maggie Mae',\n        key: 'Maggie Mae'\n      },\n      {\n        label: 'I\\'ve Got A Feeling',\n        key: 'I\\'ve Got A Feeling'\n      },\n      {\n        label: 'One After 909',\n        key: 'One After 909'\n      },\n      {\n        label: 'The Long And Winding Road',\n        key: 'The Long And Winding Road'\n      },\n      {\n        label: 'For You Blue',\n        key: 'For You Blue'\n      },\n      {\n        label: 'Get Back',\n        key: 'Get Back'\n      }\n    ]\n  }\n]\n</script>\n\n<template>\n  <n-tree-select\n    :options=\"options\"\n    default-value=\"Drive My Car\"\n    multiple\n    :node-props=\"nodeProps\"\n    :render-label=\"renderXxx\"\n    :render-prefix=\"renderXxx\"\n    :render-suffix=\"renderXxx\"\n    :render-switcher-icon=\"renderSwitcherIcon\"\n    :render-tag=\"renderTag\"\n    @update:value=\"handleUpdateValue\"\n  />\n</template>\n"
  },
  {
    "path": "src/tree-select/demos/zhCN/rtl-debug.demo.vue",
    "content": "<markdown>\n# Rtl Debug\n</markdown>\n\n<script lang=\"ts\">\nimport { unstableTreeSelectRtl } from 'naive-ui'\nimport { defineComponent, ref } from 'vue'\n\nexport default defineComponent({\n  setup() {\n    return {\n      rtlEnabled: ref(false),\n      rtlStyles: [unstableTreeSelectRtl],\n      options: [\n        {\n          label: 'Rubber Soul',\n          key: 'Rubber Soul',\n          children: [\n            {\n              label:\n                'Everybody\\'s Got Something to Hide Except Me and My Monkey',\n              key: 'Everybody\\'s Got Something to Hide Except Me and My Monkey'\n            },\n            {\n              label: 'Drive My Car',\n              key: 'Drive My Car',\n              disabled: true\n            },\n            {\n              label: 'Norwegian Wood',\n              key: 'Norwegian Wood'\n            },\n            {\n              label: 'You Won\\'t See',\n              key: 'You Won\\'t See',\n              disabled: true\n            },\n            {\n              label: 'Nowhere Man',\n              key: 'Nowhere Man'\n            },\n            {\n              label: 'Think For Yourself',\n              key: 'Think For Yourself'\n            },\n            {\n              label: 'The Word',\n              key: 'The Word'\n            },\n            {\n              label: 'Michelle',\n              key: 'Michelle',\n              disabled: true\n            },\n            {\n              label: 'What goes on',\n              key: 'What goes on'\n            },\n            {\n              label: 'Girl',\n              key: 'Girl'\n            },\n            {\n              label: 'I\\'m looking through you',\n              key: 'I\\'m looking through you'\n            },\n            {\n              label: 'In My Life',\n              key: 'In My Life'\n            },\n            {\n              label: 'Wait',\n              key: 'Wait'\n            }\n          ]\n        },\n        {\n          label: 'Let It Be',\n          key: 'Let It Be Album',\n          children: [\n            {\n              label: 'Two Of Us',\n              key: 'Two Of Us'\n            },\n            {\n              label: 'Dig A Pony',\n              key: 'Dig A Pony'\n            },\n            {\n              label: 'Across The Universe',\n              key: 'Across The Universe'\n            },\n            {\n              label: 'I Me Mine',\n              key: 'I Me Mine'\n            },\n            {\n              label: 'Dig It',\n              key: 'Dig It'\n            },\n            {\n              label: 'Let It Be',\n              key: 'Let It Be'\n            },\n            {\n              label: 'Maggie Mae',\n              key: 'Maggie Mae'\n            },\n            {\n              label: 'I\\'ve Got A Feeling',\n              key: 'I\\'ve Got A Feeling'\n            },\n            {\n              label: 'One After 909',\n              key: 'One After 909'\n            },\n            {\n              label: 'The Long And Winding Road',\n              key: 'The Long And Winding Road'\n            },\n            {\n              label: 'For You Blue',\n              key: 'For You Blue'\n            },\n            {\n              label: 'Get Back',\n              key: 'Get Back'\n            }\n          ]\n        }\n      ]\n    }\n  }\n})\n</script>\n\n<template>\n  <n-space vertical>\n    <n-space><n-switch v-model:value=\"rtlEnabled\" />Rtl</n-space>\n    <n-config-provider :rtl=\"rtlEnabled ? rtlStyles : undefined\">\n      <n-flex vertical>\n        <n-tree-select :options=\"options\" default-value=\"Drive My Car\" />\n      </n-flex>\n    </n-config-provider>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/tree-select/demos/zhCN/show-line.demo.vue",
    "content": "<markdown>\n# 连接线\n\n使用 `show-line` 属性显示树的连接线。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { TreeSelectOption } from 'naive-ui'\n\nconst options: TreeSelectOption[] = [\n  {\n    label: 'Rubber Soul',\n    key: 'Rubber Soul',\n    children: [\n      {\n        label: 'Drive My Car',\n        key: 'Drive My Car'\n      },\n      {\n        label: 'Norwegian Wood',\n        key: 'Norwegian Wood'\n      },\n      {\n        label: 'You Won\\'t See',\n        key: 'You Won\\'t See'\n      },\n      {\n        label: 'Nowhere Man',\n        key: 'Nowhere Man'\n      },\n      {\n        label: 'Think For Yourself',\n        key: 'Think For Yourself'\n      }\n    ]\n  },\n  {\n    label: 'Let It Be',\n    key: 'Let It Be Album',\n    children: [\n      {\n        label: 'Two Of Us',\n        key: 'Two Of Us'\n      },\n      {\n        label: 'Dig A Pony',\n        key: 'Dig A Pony'\n      },\n      {\n        label: 'Across The Universe',\n        key: 'Across The Universe'\n      },\n      {\n        label: 'Let It Be',\n        key: 'Let It Be'\n      },\n      {\n        label: 'Get Back',\n        key: 'Get Back'\n      }\n    ]\n  }\n]\n</script>\n\n<template>\n  <n-tree-select\n    show-line\n    default-expand-all\n    :options=\"options\"\n    default-value=\"Drive My Car\"\n  />\n</template>\n"
  },
  {
    "path": "src/tree-select/demos/zhCN/status.demo.vue",
    "content": "<markdown>\n# 验证状态\n\n输入的验证状态可以脱离表单使用。\n</markdown>\n\n<template>\n  <n-space vertical>\n    <n-tree-select status=\"warning\" placeholder=\"\" />\n    <n-tree-select status=\"error\" placeholder=\"\" />\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/tree-select/index.ts",
    "content": "export type {\n  TreeOverrideNodeClickBehavior as TreeSelectOverrideNodeClickBehavior,\n  TreeOverrideNodeClickBehaviorReturn as TreeSelectOverrideNodeClickBehaviorReturn\n} from '../tree'\nexport type {\n  TreeSelectInst,\n  TreeSelectNodeProps,\n  TreeSelectOption,\n  TreeSelectRenderLabel,\n  TreeSelectRenderPrefix,\n  TreeSelectRenderSuffix,\n  TreeSelectRenderTag\n} from './src/interface'\nexport type * from './src/public-types'\nexport { default as NTreeSelect, treeSelectProps } from './src/TreeSelect'\nexport type { TreeSelectProps, TreeSelectSlots } from './src/TreeSelect'\n"
  },
  {
    "path": "src/tree-select/src/TreeSelect.tsx",
    "content": "import type { CheckStrategy } from 'treemate'\nimport type {\n  CSSProperties,\n  HTMLAttributes,\n  PropType,\n  SlotsType,\n  VNode,\n  VNodeChild\n} from 'vue'\nimport type { FollowerInst, FollowerPlacement } from 'vueuc'\nimport type { InternalSelectionInst } from '../../_internal'\nimport type { ThemeProps } from '../../_mixins'\nimport type { ExtractPublicPropTypes, MaybeArray } from '../../_utils'\nimport type { FormValidationStatus } from '../../form/src/public-types'\nimport type { PopoverProps } from '../../popover'\nimport type { SelectBaseOption, SelectOption } from '../../select/src/interface'\nimport type {\n  GetChildren,\n  InternalTreeInst,\n  Key,\n  TreeOption,\n  TreeOverrideNodeClickBehaviorReturn\n} from '../../tree/src/interface'\nimport type { OnUpdateExpandedKeysImpl } from '../../tree/src/Tree'\nimport type { TreeSelectTheme } from '../styles'\nimport type {\n  OnUpdateIndeterminateKeysImpl,\n  OnUpdateValue,\n  OnUpdateValueImpl,\n  TreeSelectInst,\n  TreeSelectNodeProps,\n  TreeSelectOption,\n  TreeSelectRenderLabel,\n  TreeSelectRenderPrefix,\n  TreeSelectRenderSuffix,\n  TreeSelectRenderTag,\n  Value\n} from './interface'\nimport type { TreeSelectSize } from './public-types'\nimport { getPreciseEventTarget, happensIn } from 'seemly'\nimport { createTreeMate } from 'treemate'\nimport { clickoutside } from 'vdirs'\nimport { useIsMounted, useMergedState } from 'vooks'\nimport {\n  computed,\n  defineComponent,\n  h,\n  provide,\n  ref,\n  toRef,\n  Transition,\n  watchEffect,\n  withDirectives\n} from 'vue'\nimport { VBinder, VFollower, VTarget } from 'vueuc'\nimport { NBaseFocusDetector, NInternalSelection } from '../../_internal'\nimport {\n  useConfig,\n  useFormItem,\n  useLocale,\n  useTheme,\n  useThemeClass\n} from '../../_mixins'\nimport {\n  call,\n  markEventEffectPerformed,\n  resolveSlot,\n  resolveWrappedSlot,\n  useAdjustedTo,\n  useOnResize,\n  warnOnce\n} from '../../_utils'\nimport { NEmpty } from '../../empty'\nimport { NTree } from '../../tree'\nimport { createTreeMateOptions, treeSharedProps } from '../../tree/src/Tree'\nimport { useMergedCheckStrategy } from '../../tree/src/utils'\nimport { treeSelectLight } from '../styles'\nimport { treeSelectInjectionKey } from './interface'\nimport style from './styles/index.cssr'\nimport {\n  treeOption2SelectOption,\n  treeOption2SelectOptionWithPath\n} from './utils'\n\ntype OnLoad = (node: TreeSelectOption) => Promise<void>\n\nexport const treeSelectProps = {\n  ...(useTheme.props as ThemeProps<TreeSelectTheme>),\n  bordered: {\n    type: Boolean,\n    default: true\n  },\n  cascade: Boolean,\n  checkable: Boolean,\n  clearable: Boolean,\n  clearFilterAfterSelect: {\n    type: Boolean,\n    default: true\n  },\n  consistentMenuWidth: {\n    type: Boolean,\n    default: true\n  },\n  defaultShow: Boolean,\n  defaultValue: {\n    type: [String, Number, Array] as PropType<\n      string | number | Array<string | number> | null\n    >,\n    default: null\n  },\n  disabled: {\n    type: Boolean as PropType<boolean | undefined>,\n    default: undefined\n  },\n  filterable: Boolean,\n  checkStrategy: {\n    type: String as PropType<CheckStrategy>,\n    default: 'all'\n  },\n  loading: Boolean,\n  maxTagCount: [String, Number] as PropType<number | 'responsive'>,\n  multiple: Boolean,\n  showLine: Boolean,\n  showPath: Boolean,\n  separator: {\n    type: String,\n    default: ' / '\n  },\n  options: {\n    type: Array as PropType<TreeSelectOption[]>,\n    default: () => []\n  },\n  placeholder: String,\n  placement: {\n    type: String as PropType<FollowerPlacement>,\n    default: 'bottom-start'\n  },\n  show: {\n    type: Boolean as PropType<boolean | undefined>,\n    default: undefined\n  },\n  size: String as PropType<TreeSelectSize>,\n  value: [String, Number, Array] as PropType<\n    string | number | Array<string | number> | null\n  >,\n  to: useAdjustedTo.propTo,\n  menuProps: Object as PropType<HTMLAttributes>,\n  virtualScroll: {\n    type: Boolean,\n    default: true\n  },\n  status: String as PropType<FormValidationStatus>,\n  renderTag: Function as PropType<TreeSelectRenderTag>,\n  ellipsisTagPopoverProps: Object as PropType<PopoverProps>,\n  ...treeSharedProps,\n  renderLabel: Function as PropType<TreeSelectRenderLabel>,\n  renderPrefix: Function as PropType<TreeSelectRenderPrefix>,\n  renderSuffix: Function as PropType<TreeSelectRenderSuffix>,\n  nodeProps: Function as PropType<TreeSelectNodeProps>,\n  watchProps: Array as PropType<\n    Array<'defaultCheckedKeys' | 'defaultSelectedKeys' | 'defaultExpandedKeys'>\n  >,\n  getChildren: Function as PropType<GetChildren>,\n  onBlur: Function as PropType<(e: FocusEvent) => void>,\n  onFocus: Function as PropType<(e: FocusEvent) => void>,\n  onLoad: Function as PropType<OnLoad>,\n  onUpdateShow: [Function, Array] as PropType<\n    MaybeArray<(show: boolean) => void>\n  >,\n  onUpdateValue: [Function, Array] as PropType<MaybeArray<OnUpdateValue>>,\n  'onUpdate:value': [Function, Array] as PropType<MaybeArray<OnUpdateValue>>,\n  'onUpdate:show': [Function, Array] as PropType<\n    MaybeArray<(show: boolean) => void>\n  >,\n  /**\n   * @deprecated\n   */\n  leafOnly: Boolean\n} as const\n\nexport type TreeSelectProps = ExtractPublicPropTypes<typeof treeSelectProps>\n\nexport interface TreeSelectSlots {\n  header?: () => VNode[]\n  action?: () => VNode[]\n  arrow?: () => VNode[]\n  empty?: () => VNode[]\n}\n\nexport default defineComponent({\n  name: 'TreeSelect',\n  props: treeSelectProps,\n  slots: Object as SlotsType<TreeSelectSlots>,\n  setup(props) {\n    if (__DEV__) {\n      watchEffect(() => {\n        if (props.leafOnly) {\n          warnOnce(\n            'tree-select',\n            '`leaf-only` is deprecated, please use `check-strategy=\"child\"` instead.'\n          )\n        }\n      })\n    }\n    const followerInstRef = ref<FollowerInst | null>(null)\n    const triggerInstRef = ref<InternalSelectionInst | null>(null)\n    const treeInstRef = ref<InternalTreeInst | null>(null)\n    const menuElRef = ref<HTMLDivElement | null>(null)\n    const {\n      mergedClsPrefixRef,\n      namespaceRef,\n      inlineThemeDisabled,\n      mergedComponentPropsRef\n    } = useConfig(props)\n    const { localeRef } = useLocale('Select')\n    const {\n      mergedSizeRef,\n      mergedDisabledRef,\n      mergedStatusRef,\n      nTriggerFormBlur,\n      nTriggerFormChange,\n      nTriggerFormFocus,\n      nTriggerFormInput\n    } = useFormItem(props, {\n      mergedSize: (NFormItem) => {\n        const { size } = props\n        if (size)\n          return size\n        const { mergedSize: formItemSize } = NFormItem || {}\n        if (formItemSize?.value)\n          return formItemSize.value as TreeSelectSize\n        const configSize = mergedComponentPropsRef?.value?.TreeSelect?.size\n        if (configSize)\n          return configSize\n        return 'medium'\n      }\n    })\n    const uncontrolledValueRef = ref<Value>(props.defaultValue)\n    const controlledValueRef = toRef(props, 'value')\n    const mergedValueRef = useMergedState(\n      controlledValueRef,\n      uncontrolledValueRef\n    )\n    const uncontrolledShowRef = ref(props.defaultShow)\n    const controlledShowRef = toRef(props, 'show')\n    const mergedShowRef = useMergedState(controlledShowRef, uncontrolledShowRef)\n    const patternRef = ref('')\n    const mergedFilterRef = computed(() => {\n      const { filter } = props\n      if (filter)\n        return filter\n      const { labelField } = props\n      return (pattern: string, node: TreeSelectOption): boolean => {\n        if (!pattern.length)\n          return true\n        return (node[labelField] as string)\n          .toLowerCase()\n          .includes(pattern.toLowerCase())\n      }\n    })\n    // used to resolve selected options\n    const dataTreeMateRef = computed(() =>\n      createTreeMate<TreeSelectOption>(\n        props.options,\n        createTreeMateOptions(\n          props.keyField,\n          props.childrenField,\n          props.disabledField,\n          undefined\n        )\n      )\n    )\n    const { value: initMergedValue } = mergedValueRef\n    const pendingNodeKeyRef = ref(\n      props.checkable\n        ? null\n        : Array.isArray(initMergedValue) && initMergedValue.length\n          ? initMergedValue[initMergedValue.length - 1]\n          : null\n    )\n    const mergedCascadeRef = computed(() => {\n      return props.multiple && props.cascade && props.checkable\n    })\n    // The same logic as tree, now it's not that complex so I don't extract a\n    // function to reuse it.\n    const uncontrolledExpandedKeysRef = ref(\n      props.defaultExpandAll\n        ? undefined // leave it, n-tree will handle it\n        : props.defaultExpandedKeys || props.expandedKeys\n    )\n    const controlledExpandedKeysRef = toRef(props, 'expandedKeys')\n    const mergedExpandedKeysRef = useMergedState(\n      controlledExpandedKeysRef,\n      uncontrolledExpandedKeysRef\n    )\n    const focusedRef = ref(false)\n    const mergedPlaceholderRef = computed(() => {\n      const { placeholder } = props\n      if (placeholder !== undefined)\n        return placeholder\n      return localeRef.value.placeholder\n    })\n    const treeCheckedKeysRef = computed<Key[]>(() => {\n      const { value: mergedValue } = mergedValueRef\n      if (props.multiple) {\n        if (Array.isArray(mergedValue))\n          return mergedValue\n        else return []\n      }\n      else {\n        if (mergedValue === null || Array.isArray(mergedValue))\n          return []\n        else return [mergedValue]\n      }\n    })\n    const treeSelectedKeysRef = computed<Key[]>(() => {\n      if (props.checkable)\n        return []\n      return treeCheckedKeysRef.value\n    })\n    const selectedOptionRef = computed(() => {\n      const { multiple, showPath, separator, labelField } = props\n      if (multiple)\n        return null\n      const { value: mergedValue } = mergedValueRef\n      if (!Array.isArray(mergedValue) && mergedValue !== null) {\n        const { value: treeMate } = dataTreeMateRef\n        const tmNode = treeMate.getNode(mergedValue)\n        if (tmNode !== null) {\n          return showPath\n            ? treeOption2SelectOptionWithPath(\n                tmNode,\n                treeMate.getPath(mergedValue).treeNodePath,\n                separator,\n                labelField\n              )\n            : treeOption2SelectOption(tmNode, labelField)\n        }\n      }\n      return null\n    })\n    const selectedOptionsRef = computed(() => {\n      const { multiple, showPath, separator } = props\n      if (!multiple)\n        return null\n      const { value: mergedValue } = mergedValueRef\n      if (Array.isArray(mergedValue)) {\n        const res: SelectBaseOption[] = []\n        const { value: treeMate } = dataTreeMateRef\n        const { checkedKeys } = treeMate.getCheckedKeys(mergedValue, {\n          checkStrategy: props.checkStrategy,\n          cascade: mergedCascadeRef.value,\n          allowNotLoaded: props.allowCheckingNotLoaded\n        })\n        const { labelField } = props\n        checkedKeys.forEach((value) => {\n          const tmNode = treeMate.getNode(value)\n          if (tmNode !== null) {\n            res.push(\n              showPath\n                ? treeOption2SelectOptionWithPath(\n                    tmNode,\n                    treeMate.getPath(value).treeNodePath,\n                    separator,\n                    labelField\n                  )\n                : treeOption2SelectOption(tmNode, labelField)\n            )\n          }\n        })\n        return res\n      }\n      return []\n    })\n    function focusSelection(): void {\n      triggerInstRef.value?.focus()\n    }\n    function focusSelectionInput(): void {\n      triggerInstRef.value?.focusInput()\n    }\n    function doUpdateShow(value: boolean): void {\n      const { onUpdateShow, 'onUpdate:show': _onUpdateShow } = props\n      if (onUpdateShow)\n        call(onUpdateShow, value)\n      if (_onUpdateShow)\n        call(_onUpdateShow, value)\n      uncontrolledShowRef.value = value\n    }\n    function doUpdateValue(\n      value: string | number | Array<string | number> | null,\n      option: TreeSelectOption | null | Array<TreeSelectOption | null>,\n      meta:\n        | {\n          node: TreeSelectOption\n          action: 'select' | 'unselect'\n        }\n        | {\n          node: TreeSelectOption | null\n          action: 'delete'\n        }\n        | {\n          node: null\n          action: 'clear'\n        }\n    ): void {\n      const { onUpdateValue, 'onUpdate:value': _onUpdateValue } = props\n      if (onUpdateValue) {\n        call(onUpdateValue as OnUpdateValueImpl, value, option, meta)\n      }\n      if (_onUpdateValue) {\n        call(_onUpdateValue as OnUpdateValueImpl, value, option, meta)\n      }\n      uncontrolledValueRef.value = value\n      nTriggerFormInput()\n      nTriggerFormChange()\n    }\n    function doUpdateIndeterminateKeys(\n      value: string | number | Array<string | number> | null,\n      option: TreeSelectOption | null | Array<TreeSelectOption | null>\n    ): void {\n      const {\n        onUpdateIndeterminateKeys,\n        'onUpdate:indeterminateKeys': _onUpdateIndeterminateKeys\n      } = props\n      if (onUpdateIndeterminateKeys) {\n        call(\n          onUpdateIndeterminateKeys as OnUpdateIndeterminateKeysImpl,\n          value,\n          option\n        )\n      }\n      if (_onUpdateIndeterminateKeys) {\n        call(\n          _onUpdateIndeterminateKeys as OnUpdateIndeterminateKeysImpl,\n          value,\n          option\n        )\n      }\n    }\n    function doUpdateExpandedKeys(\n      keys: Key[],\n      option: Array<TreeSelectOption | null>,\n      meta:\n        | {\n          node: TreeSelectOption\n          action: 'expand' | 'collapse'\n        }\n        | {\n          node: null\n          action: 'filter'\n        }\n    ): void {\n      const {\n        onUpdateExpandedKeys,\n        'onUpdate:expandedKeys': _onUpdateExpandedKeys\n      } = props\n      if (onUpdateExpandedKeys) {\n        call(\n          onUpdateExpandedKeys as OnUpdateExpandedKeysImpl,\n          keys,\n          option,\n          meta\n        )\n      }\n      if (_onUpdateExpandedKeys) {\n        call(\n          _onUpdateExpandedKeys as OnUpdateExpandedKeysImpl,\n          keys,\n          option,\n          meta\n        )\n      }\n      uncontrolledExpandedKeysRef.value = keys\n    }\n    function doFocus(e: FocusEvent): void {\n      const { onFocus } = props\n      if (onFocus)\n        onFocus(e)\n      nTriggerFormFocus()\n    }\n    function doBlur(e: FocusEvent): void {\n      closeMenu()\n      const { onBlur } = props\n      if (onBlur)\n        onBlur(e)\n      nTriggerFormBlur()\n    }\n    function closeMenu(): void {\n      doUpdateShow(false)\n    }\n    function openMenu(): void {\n      if (!mergedDisabledRef.value) {\n        patternRef.value = ''\n        doUpdateShow(true)\n        if (props.filterable) {\n          focusSelectionInput()\n        }\n      }\n    }\n    function handleMenuLeave(): void {\n      patternRef.value = ''\n    }\n    function handleMenuClickoutside(e: MouseEvent): void {\n      if (mergedShowRef.value) {\n        if (\n          !triggerInstRef.value?.$el.contains(\n            getPreciseEventTarget(e) as Node | null\n          )\n        ) {\n          // outside select, don't need to return focus\n          closeMenu()\n        }\n      }\n    }\n    function handleTriggerClick(): void {\n      if (mergedDisabledRef.value)\n        return\n      if (!mergedShowRef.value) {\n        openMenu()\n      }\n      else {\n        if (!props.filterable) {\n          // already focused, don't need to return focus\n          closeMenu()\n        }\n      }\n    }\n    function getOptionsByKeys(keys: Key[]): Array<TreeSelectOption | null> {\n      const {\n        value: { getNode }\n      } = dataTreeMateRef\n      return keys.map(key => getNode(key)?.rawNode || null)\n    }\n    function handleUpdateCheckedKeys(\n      keys: Key[],\n      _: unknown,\n      meta: { node: TreeOption | null, action: 'check' | 'uncheck' }\n    ): void {\n      const options = getOptionsByKeys(keys)\n      const action = meta.action === 'check' ? 'select' : 'unselect'\n      const node = meta.node as TreeSelectOption\n      if (props.multiple) {\n        doUpdateValue(keys, options, { node, action })\n        if (props.filterable) {\n          focusSelectionInput()\n          if (props.clearFilterAfterSelect)\n            patternRef.value = ''\n        }\n      }\n      else {\n        if (keys.length) {\n          doUpdateValue(keys[0], options[0] || null, {\n            node,\n            action\n          })\n        }\n        else {\n          doUpdateValue(null, null, { node, action })\n        }\n        closeMenu()\n        // Currently it is not necessary. However if there is an action slot,\n        // it will be useful. So just leave it here.\n        focusSelection()\n      }\n    }\n    function handleUpdateIndeterminateKeys(keys: Key[]): void {\n      if (props.checkable) {\n        doUpdateIndeterminateKeys(keys, getOptionsByKeys(keys))\n      }\n    }\n    function handleTriggerFocus(e: FocusEvent): void {\n      if (menuElRef.value?.contains(e.relatedTarget as Element))\n        return\n      focusedRef.value = true\n      doFocus(e)\n    }\n    function handleTriggerBlur(e: FocusEvent): void {\n      if (menuElRef.value?.contains(e.relatedTarget as Element))\n        return\n      focusedRef.value = false\n      doBlur(e)\n    }\n    function handleMenuFocusin(e: FocusEvent): void {\n      if (\n        menuElRef.value?.contains(e.relatedTarget as Element)\n        || triggerInstRef.value?.$el?.contains(e.relatedTarget as Element)\n      ) {\n        return\n      }\n      focusedRef.value = true\n      doFocus(e)\n    }\n    function handleMenuFocusout(e: FocusEvent): void {\n      if (\n        menuElRef.value?.contains(e.relatedTarget as Element)\n        || triggerInstRef.value?.$el?.contains(e.relatedTarget as Element)\n      ) {\n        return\n      }\n      focusedRef.value = false\n      doBlur(e)\n    }\n    function handleClear(e: MouseEvent): void {\n      e.stopPropagation()\n      const { multiple } = props\n      if (!multiple && props.filterable) {\n        closeMenu()\n      }\n      if (multiple) {\n        doUpdateValue([], [], { node: null, action: 'clear' })\n      }\n      else {\n        doUpdateValue(null, null, { node: null, action: 'clear' })\n      }\n    }\n    function handleDeleteOption(option: SelectBaseOption): void {\n      // only work for multiple mode\n      const { value: mergedValue } = mergedValueRef\n      if (Array.isArray(mergedValue)) {\n        const { value: treeMate } = dataTreeMateRef\n        // all visible checked keys\n        const { checkedKeys: checkedKeysValue } = treeMate.getCheckedKeys(\n          mergedValue,\n          {\n            cascade: mergedCascadeRef.value,\n            allowNotLoaded: props.allowCheckingNotLoaded\n          }\n        )\n        const index = checkedKeysValue.findIndex(key => key === option.value)\n        if (~index) {\n          const checkedKeyToBeRemoved = checkedKeysValue[index]\n          const checkOptionToBeRemoved = getOptionsByKeys([\n            checkedKeyToBeRemoved\n          ])[0]\n          if (props.checkable) {\n            const { checkedKeys } = treeMate.uncheck(\n              option.value,\n              checkedKeysValue,\n              {\n                checkStrategy: props.checkStrategy,\n                cascade: mergedCascadeRef.value,\n                allowNotLoaded: props.allowCheckingNotLoaded\n              }\n            )\n            doUpdateValue(checkedKeys, getOptionsByKeys(checkedKeys), {\n              node: checkOptionToBeRemoved,\n              action: 'delete'\n            })\n          }\n          else {\n            const nextValue = Array.from(checkedKeysValue)\n            nextValue.splice(index, 1)\n            doUpdateValue(nextValue, getOptionsByKeys(nextValue), {\n              node: checkOptionToBeRemoved,\n              action: 'delete'\n            })\n          }\n        }\n      }\n    }\n    function handlePatternInput(e: InputEvent): void {\n      const { value } = e.target as unknown as HTMLInputElement\n      patternRef.value = value\n    }\n    function treeHandleKeydown(e: KeyboardEvent): {\n      enterBehavior: TreeOverrideNodeClickBehaviorReturn | null\n    } {\n      const { value: treeInst } = treeInstRef\n      if (treeInst) {\n        return treeInst.handleKeydown(e)\n      }\n      return {\n        enterBehavior: null\n      }\n    }\n    function handleKeydown(e: KeyboardEvent): void {\n      if (e.key === 'Enter') {\n        if (mergedShowRef.value) {\n          const { enterBehavior } = treeHandleKeydown(e)\n          if (!props.multiple) {\n            switch (enterBehavior) {\n              case 'default':\n              case 'toggleSelect':\n                closeMenu()\n                focusSelection()\n                break\n              default:\n                break\n            }\n          }\n        }\n        else {\n          openMenu()\n        }\n        e.preventDefault()\n      }\n      else if (e.key === 'Escape') {\n        if (mergedShowRef.value) {\n          markEventEffectPerformed(e)\n          closeMenu()\n          focusSelection()\n        }\n      }\n      else {\n        if (mergedShowRef.value) {\n          treeHandleKeydown(e)\n        }\n        else if (e.key === 'ArrowDown') {\n          openMenu()\n        }\n      }\n    }\n    function handleTabOut(): void {\n      closeMenu()\n      focusSelection()\n    }\n    function handleMenuMousedown(e: MouseEvent): void {\n      // If there's an action slot later, we need to check if mousedown happens\n      // in action panel\n      if (!happensIn(e, 'action') && !happensIn(e, 'header'))\n        e.preventDefault()\n    }\n    const selectionRenderTagRef = computed(() => {\n      const { renderTag } = props\n      if (!renderTag)\n        return undefined\n      return function selectionRenderTag({\n        option,\n        handleClose\n      }: {\n        option: SelectOption\n        handleClose: () => void\n      }): VNodeChild {\n        const { value } = option\n        if (value !== undefined) {\n          const treeOption = dataTreeMateRef.value.getNode(value)\n          if (treeOption) {\n            return renderTag({ option: treeOption.rawNode, handleClose })\n          }\n        }\n        return value\n      }\n    })\n\n    provide(treeSelectInjectionKey, {\n      pendingNodeKeyRef,\n      dataTreeMate: dataTreeMateRef\n    })\n\n    function handleTriggerOrMenuResize(): void {\n      if (!mergedShowRef.value)\n        return\n      followerInstRef.value?.syncPosition()\n    }\n\n    useOnResize(menuElRef, handleTriggerOrMenuResize)\n\n    const mergedCheckStrategyRef = useMergedCheckStrategy(props)\n    const exposedCheckedStatusRef = computed(() => {\n      if (props.checkable) {\n        const mergedValue = mergedValueRef.value\n        if (props.multiple && Array.isArray(mergedValue)) {\n          return dataTreeMateRef.value.getCheckedKeys(mergedValue, {\n            cascade: props.cascade,\n            checkStrategy: mergedCheckStrategyRef.value,\n            allowNotLoaded: props.allowCheckingNotLoaded\n          })\n        }\n        else {\n          return {\n            checkedKeys:\n              Array.isArray(mergedValue) || mergedValue === null\n                ? []\n                : [mergedValue],\n            indeterminateKeys: []\n          }\n        }\n      }\n      return {\n        checkedKeys: [],\n        indeterminateKeys: []\n      }\n    })\n\n    const exposedMethods: TreeSelectInst = {\n      getCheckedData: () => {\n        const { checkedKeys } = exposedCheckedStatusRef.value\n        return { keys: checkedKeys, options: getOptionsByKeys(checkedKeys) }\n      },\n      getIndeterminateData: () => {\n        const { indeterminateKeys } = exposedCheckedStatusRef.value\n        return {\n          keys: indeterminateKeys,\n          options: getOptionsByKeys(indeterminateKeys)\n        }\n      },\n      focus: () => triggerInstRef.value?.focus(),\n      focusInput: () => triggerInstRef.value?.focusInput(),\n      blur: () => triggerInstRef.value?.blur(),\n      blurInput: () => triggerInstRef.value?.blurInput()\n    }\n\n    const themeRef = useTheme(\n      'TreeSelect',\n      '-tree-select',\n      style,\n      treeSelectLight,\n      props,\n      mergedClsPrefixRef\n    )\n    const mergedRenderEmptyRef = computed(() => {\n      return mergedComponentPropsRef?.value?.TreeSelect?.renderEmpty\n    })\n\n    const cssVarsRef = computed(() => {\n      const {\n        common: { cubicBezierEaseInOut },\n        self: {\n          menuBoxShadow,\n          menuBorderRadius,\n          menuColor,\n          menuHeight,\n          actionPadding,\n          actionDividerColor,\n          actionTextColor,\n          headerDividerColor,\n          headerPadding,\n          headerTextColor\n        }\n      } = themeRef.value\n      return {\n        '--n-menu-box-shadow': menuBoxShadow,\n        '--n-menu-border-radius': menuBorderRadius,\n        '--n-menu-color': menuColor,\n        '--n-menu-height': menuHeight,\n        '--n-bezier': cubicBezierEaseInOut,\n        '--n-action-padding': actionPadding,\n        '--n-action-text-color': actionTextColor,\n        '--n-action-divider-color': actionDividerColor,\n        '--n-header-padding': headerPadding,\n        '--n-header-text-color': headerTextColor,\n        '--n-header-divider-color': headerDividerColor\n      }\n    })\n    const themeClassHandle = inlineThemeDisabled\n      ? useThemeClass('tree-select', undefined, cssVarsRef, props)\n      : undefined\n\n    const menuPaddingRef = computed(() => {\n      const {\n        self: { menuPadding }\n      } = themeRef.value\n      return menuPadding\n    })\n    return {\n      ...exposedMethods,\n      menuElRef,\n      mergedStatus: mergedStatusRef,\n      triggerInstRef,\n      followerInstRef,\n      treeInstRef,\n      mergedClsPrefix: mergedClsPrefixRef,\n      mergedValue: mergedValueRef,\n      mergedShow: mergedShowRef,\n      namespace: namespaceRef,\n      adjustedTo: useAdjustedTo(props),\n      isMounted: useIsMounted(),\n      focused: focusedRef,\n      menuPadding: menuPaddingRef,\n      mergedPlaceholder: mergedPlaceholderRef,\n      mergedExpandedKeys: mergedExpandedKeysRef,\n      treeSelectedKeys: treeSelectedKeysRef,\n      treeCheckedKeys: treeCheckedKeysRef,\n      mergedSize: mergedSizeRef,\n      mergedDisabled: mergedDisabledRef,\n      selectedOption: selectedOptionRef,\n      selectedOptions: selectedOptionsRef,\n      pattern: patternRef,\n      pendingNodeKey: pendingNodeKeyRef,\n      mergedCascade: mergedCascadeRef,\n      mergedFilter: mergedFilterRef,\n      selectionRenderTag: selectionRenderTagRef,\n      handleTriggerOrMenuResize,\n      doUpdateExpandedKeys,\n      handleMenuLeave,\n      handleTriggerClick,\n      handleMenuClickoutside,\n      handleUpdateCheckedKeys,\n      handleUpdateIndeterminateKeys,\n      handleTriggerFocus,\n      handleTriggerBlur,\n      handleMenuFocusin,\n      handleMenuFocusout,\n      handleClear,\n      handleDeleteOption,\n      handlePatternInput,\n      handleKeydown,\n      handleTabOut,\n      handleMenuMousedown,\n      mergedTheme: themeRef,\n      mergedRenderEmpty: mergedRenderEmptyRef,\n      cssVars: inlineThemeDisabled ? undefined : cssVarsRef,\n      themeClass: themeClassHandle?.themeClass,\n      onRender: themeClassHandle?.onRender\n    }\n  },\n  render() {\n    const { mergedTheme, mergedClsPrefix, $slots } = this\n    return (\n      <div class={`${mergedClsPrefix}-tree-select`}>\n        <VBinder>\n          {{\n            default: () => [\n              <VTarget>\n                {{\n                  default: () => (\n                    <NInternalSelection\n                      ref=\"triggerInstRef\"\n                      onResize={this.handleTriggerOrMenuResize}\n                      status={this.mergedStatus}\n                      focused={this.focused}\n                      clsPrefix={mergedClsPrefix}\n                      theme={mergedTheme.peers.InternalSelection}\n                      themeOverrides={\n                        mergedTheme.peerOverrides.InternalSelection\n                      }\n                      ellipsisTagPopoverProps={this.ellipsisTagPopoverProps}\n                      renderTag={this.selectionRenderTag}\n                      selectedOption={this.selectedOption}\n                      selectedOptions={this.selectedOptions}\n                      size={this.mergedSize}\n                      bordered={this.bordered}\n                      placeholder={this.mergedPlaceholder}\n                      disabled={this.mergedDisabled}\n                      active={this.mergedShow}\n                      loading={this.loading}\n                      multiple={this.multiple}\n                      maxTagCount={this.maxTagCount}\n                      showArrow={true}\n                      filterable={this.filterable}\n                      clearable={this.clearable}\n                      pattern={this.pattern}\n                      onPatternInput={this.handlePatternInput}\n                      onClear={this.handleClear}\n                      onClick={this.handleTriggerClick}\n                      onFocus={this.handleTriggerFocus}\n                      onBlur={this.handleTriggerBlur}\n                      onDeleteOption={this.handleDeleteOption}\n                      onKeydown={this.handleKeydown}\n                    >\n                      {{\n                        arrow: () => [this.$slots.arrow?.()]\n                      }}\n                    </NInternalSelection>\n                  )\n                }}\n              </VTarget>,\n              <VFollower\n                ref=\"followerInstRef\"\n                show={this.mergedShow}\n                placement={this.placement}\n                to={this.adjustedTo}\n                teleportDisabled={this.adjustedTo === useAdjustedTo.tdkey}\n                containerClass={this.namespace}\n                width={this.consistentMenuWidth ? 'target' : undefined}\n                minWidth=\"target\"\n              >\n                {{\n                  default: () => (\n                    <Transition\n                      name=\"fade-in-scale-up-transition\"\n                      appear={this.isMounted}\n                      onLeave={this.handleMenuLeave}\n                    >\n                      {{\n                        default: () => {\n                          if (!this.mergedShow)\n                            return null\n                          const {\n                            mergedClsPrefix,\n                            checkable,\n                            multiple,\n                            menuProps,\n                            options\n                          } = this\n                          this.onRender?.()\n                          return withDirectives(\n                            <div\n                              {...menuProps}\n                              class={[\n                                `${mergedClsPrefix}-tree-select-menu`,\n                                menuProps?.class,\n                                this.themeClass\n                              ]}\n                              ref=\"menuElRef\"\n                              style={[\n                                menuProps?.style || '',\n                                this.cssVars as CSSProperties\n                              ]}\n                              tabindex={0}\n                              onMousedown={this.handleMenuMousedown}\n                              onKeydown={this.handleKeydown}\n                              onFocusin={this.handleMenuFocusin}\n                              onFocusout={this.handleMenuFocusout}\n                            >\n                              {resolveWrappedSlot($slots.header, (children) => {\n                                return children ? (\n                                  <div\n                                    class={`${mergedClsPrefix}-tree-select-menu__header`}\n                                    data-header\n                                  >\n                                    {children}\n                                  </div>\n                                ) : null\n                              })}\n                              <NTree\n                                ref=\"treeInstRef\"\n                                blockLine\n                                allowCheckingNotLoaded={\n                                  this.allowCheckingNotLoaded\n                                }\n                                showIrrelevantNodes={false}\n                                animated={false}\n                                pattern={this.pattern}\n                                getChildren={this.getChildren}\n                                filter={this.mergedFilter}\n                                data={options}\n                                cancelable={multiple}\n                                labelField={this.labelField}\n                                keyField={this.keyField}\n                                disabledField={this.disabledField}\n                                childrenField={this.childrenField}\n                                theme={mergedTheme.peers.Tree}\n                                themeOverrides={mergedTheme.peerOverrides.Tree}\n                                defaultExpandAll={this.defaultExpandAll}\n                                defaultExpandedKeys={this.defaultExpandedKeys}\n                                indent={this.indent}\n                                expandedKeys={this.mergedExpandedKeys}\n                                checkedKeys={this.treeCheckedKeys}\n                                selectedKeys={this.treeSelectedKeys}\n                                checkable={checkable}\n                                checkStrategy={this.checkStrategy}\n                                cascade={this.mergedCascade}\n                                leafOnly={this.leafOnly}\n                                multiple={this.multiple}\n                                showLine={this.showLine}\n                                renderLabel={this.renderLabel}\n                                renderPrefix={this.renderPrefix}\n                                renderSuffix={this.renderSuffix}\n                                renderSwitcherIcon={this.renderSwitcherIcon}\n                                nodeProps={this.nodeProps}\n                                watchProps={this.watchProps}\n                                virtualScroll={\n                                  this.consistentMenuWidth && this.virtualScroll\n                                }\n                                overrideDefaultNodeClickBehavior={\n                                  this.overrideDefaultNodeClickBehavior\n                                }\n                                internalTreeSelect\n                                internalUnifySelectCheck\n                                internalScrollable\n                                internalScrollablePadding={this.menuPadding}\n                                internalFocusable={false}\n                                internalCheckboxFocusable={false}\n                                internalRenderEmpty={() => (\n                                  <div\n                                    class={`${mergedClsPrefix}-tree-select-menu__empty`}\n                                  >\n                                    {resolveSlot($slots.empty, () => {\n                                      return [\n                                        this.mergedRenderEmpty?.() || (\n                                          <NEmpty\n                                            theme={mergedTheme.peers.Empty}\n                                            themeOverrides={\n                                              mergedTheme.peerOverrides.Empty\n                                            }\n                                          />\n                                        )\n                                      ]\n                                    })}\n                                  </div>\n                                )}\n                                onLoad={this.onLoad}\n                                onUpdateCheckedKeys={\n                                  this.handleUpdateCheckedKeys\n                                }\n                                onUpdateIndeterminateKeys={\n                                  this.handleUpdateIndeterminateKeys\n                                }\n                                onUpdateExpandedKeys={this.doUpdateExpandedKeys}\n                              />\n                              {resolveWrappedSlot($slots.action, (children) => {\n                                return children ? (\n                                  <div\n                                    class={`${mergedClsPrefix}-tree-select-menu__action`}\n                                    data-action\n                                  >\n                                    {children}\n                                  </div>\n                                ) : null\n                              })}\n                              <NBaseFocusDetector onFocus={this.handleTabOut} />\n                            </div>,\n                            [\n                              [\n                                clickoutside,\n                                this.handleMenuClickoutside,\n                                undefined as unknown as string,\n                                { capture: true }\n                              ]\n                            ]\n                          )\n                        }\n                      }}\n                    </Transition>\n                  )\n                }}\n              </VFollower>\n            ]\n          }}\n        </VBinder>\n      </div>\n    )\n  }\n})\n"
  },
  {
    "path": "src/tree-select/src/interface.ts",
    "content": "import type { TreeMate, TreeNode } from 'treemate'\nimport type { HTMLAttributes, Ref, VNodeChild } from 'vue'\nimport type { TreeOption, TreeOptionBase } from '../../tree/src/interface'\nimport { createInjectionKey } from '../../_utils'\n\nexport type TreeSelectOption = Omit<\n  TreeOptionBase,\n  'checkboxDisabled' | 'isLeaf' | 'children'\n> & {\n  children?: TreeSelectOption[]\n  [k: string]: unknown\n}\n\nexport type TreeSelectTmNode = TreeNode<TreeSelectOption>\n\nexport type OnUpdateValue = (\n  value: string\n    & number\n    & (string | number)\n    & string[]\n    & number[]\n    & Array<string | number>\n    & null,\n  option: TreeSelectOption\n    & null\n    & TreeSelectOption[]\n    & Array<TreeSelectOption | null>,\n  meta:\n    | {\n      node: TreeSelectOption\n      action: 'select' | 'unselect'\n    }\n    | {\n      node: TreeSelectOption | null\n      action: 'delete'\n    }\n    | {\n      node: null\n      action: 'clear'\n    }\n) => void\n\nexport type OnUpdateValueImpl = (\n  value:\n    | string\n    | number\n    | (string | number)\n    | string[]\n    | number[]\n    | Array<string | number>\n    | null,\n  option: TreeSelectOption | null | Array<TreeSelectOption | null>,\n  meta:\n    | {\n      node: TreeSelectOption\n      action: 'select' | 'unselect'\n    }\n    | {\n      node: TreeSelectOption | null\n      action: 'delete'\n    }\n    | {\n      node: null\n      action: 'clear'\n    }\n) => void\n\nexport type OnUpdateIndeterminateKeysImpl = (\n  value:\n    | string\n    | number\n    | (string | number)\n    | string[]\n    | number[]\n    | Array<string | number>\n    | null,\n  option: TreeSelectOption | null | Array<TreeSelectOption | null>\n) => void\n\nexport type Value = string | number | Array<string | number> | null\n\nexport interface TreeSelectInjection {\n  pendingNodeKeyRef: Ref<string | number | null>\n  dataTreeMate: Ref<TreeMate<TreeOption>>\n}\n\nexport const treeSelectInjectionKey\n  = createInjectionKey<TreeSelectInjection>('n-tree-select')\n\nexport type TreeSelectRenderTag = (props: {\n  option: TreeSelectOption\n  handleClose: () => void\n}) => VNodeChild\n\nexport interface TreeSelectRenderProps {\n  option: TreeSelectOption\n  checked: boolean\n  selected: boolean\n}\n\nexport type TreeSelectRenderTreePart = ({\n  option,\n  checked,\n  selected\n}: TreeSelectRenderProps) => VNodeChild\n\nexport type TreeSelectRenderLabel = TreeSelectRenderTreePart\n\nexport type TreeSelectRenderPrefix = TreeSelectRenderTreePart\n\nexport type TreeSelectRenderSuffix = TreeSelectRenderTreePart\n\nexport type TreeSelectNodeProps = (info: {\n  option: TreeSelectOption\n}) => HTMLAttributes & Record<string, unknown>\n\nexport interface TreeSelectInst {\n  getCheckedData: () => {\n    keys: Array<string | number>\n    options: Array<TreeSelectOption | null>\n  }\n  getIndeterminateData: () => {\n    keys: Array<string | number>\n    options: Array<TreeSelectOption | null>\n  }\n  focus: () => void\n  focusInput: () => void\n  blur: () => void\n  blurInput: () => void\n}\n"
  },
  {
    "path": "src/tree-select/src/public-types.ts",
    "content": "export type TreeSelectSize = 'small' | 'medium' | 'large'\n"
  },
  {
    "path": "src/tree-select/src/styles/index.cssr.ts",
    "content": "import { fadeInScaleUpTransition } from '../../../_styles/transitions/fade-in-scale-up.cssr'\nimport { c, cB, cE } from '../../../_utils/cssr'\n\n// vars:\n// --n-bezier\n// --n-menu-height\n// --n-menu-border-radius\n// --n-menu-box-shadow\n// --n-menu-color\n// --n-header-padding\n// --n-header-text-color\n// --n-header-divider-color\n// --n-action-padding\n// --n-action-text-color\n// --n-action-divider-color\nexport default c([\n  cB('tree-select', `\n    z-index: auto;\n    outline: none;\n    width: 100%;\n    position: relative;\n  `),\n  cB('tree-select-menu', `\n    position: relative;\n    overflow: hidden;\n    margin: 4px 0;\n    transition: box-shadow .3s var(--n-bezier), background-color .3s var(--n-bezier);\n    border-radius: var(--n-menu-border-radius);\n    box-shadow: var(--n-menu-box-shadow);\n    background-color: var(--n-menu-color);\n    outline: none;\n  `, [\n    cB('tree', 'max-height: var(--n-menu-height);'),\n    cE('empty', `\n      display: flex;\n      padding: 12px 32px;\n      flex: 1;\n      justify-content: center;\n    `),\n    cE('header', `\n      padding: var(--n-header-padding);\n      transition: \n        color .3s var(--n-bezier);\n        border-color .3s var(--n-bezier);\n      border-bottom: 1px solid var(--n-header-divider-color);\n      color: var(--n-header-text-color);\n    `),\n    cE('action', `\n      padding: var(--n-action-padding);\n      transition: \n        color .3s var(--n-bezier);\n        border-color .3s var(--n-bezier);\n      border-top: 1px solid var(--n-action-divider-color);\n      color: var(--n-action-text-color);\n    `),\n    fadeInScaleUpTransition()\n  ])\n])\n"
  },
  {
    "path": "src/tree-select/src/utils.ts",
    "content": "import type { SelectBaseOption } from '../../select/src/interface'\nimport type { TreeSelectTmNode } from './interface'\n\nexport function treeOption2SelectOption(\n  tmNode: TreeSelectTmNode,\n  labelField: string\n): SelectBaseOption {\n  const { rawNode } = tmNode\n  return {\n    ...rawNode,\n    label: rawNode[labelField] as string,\n    value: tmNode.key\n  }\n}\n\nexport function treeOption2SelectOptionWithPath(\n  tmNode: TreeSelectTmNode,\n  path: TreeSelectTmNode[],\n  separator: string,\n  labelField: string\n): SelectBaseOption {\n  const { rawNode } = tmNode\n  return {\n    ...rawNode,\n    value: tmNode.key,\n    label: path.map(v => v.rawNode[labelField]).join(separator)\n  }\n}\n"
  },
  {
    "path": "src/tree-select/styles/dark.ts",
    "content": "import type { TreeSelectTheme } from './light'\nimport { internalSelectionDark } from '../../_internal/selection/styles'\nimport { commonDark } from '../../_styles/common'\nimport { emptyDark } from '../../empty/styles'\nimport { treeDark } from '../../tree/styles'\n\nconst treeSelectDark: TreeSelectTheme = {\n  name: 'TreeSelect',\n  common: commonDark,\n  peers: {\n    Tree: treeDark,\n    Empty: emptyDark,\n    InternalSelection: internalSelectionDark\n  }\n}\n\nexport default treeSelectDark\n"
  },
  {
    "path": "src/tree-select/styles/index.ts",
    "content": "export { default as treeSelectDark } from './dark'\nexport { default as treeSelectLight } from './light'\nexport type { TreeSelectTheme, TreeSelectThemeVars } from './light'\nexport { treeSelectRtl } from './rtl'\n"
  },
  {
    "path": "src/tree-select/styles/light.ts",
    "content": "import type { ThemeCommonVars } from '../../_styles/common'\nimport { internalSelectionLight } from '../../_internal/selection/styles'\nimport { createTheme } from '../../_mixins/use-theme'\nimport { commonLight } from '../../_styles/common'\nimport { emptyLight } from '../../empty/styles'\nimport { treeLight } from '../../tree/styles'\n\nexport function self(vars: ThemeCommonVars) {\n  const {\n    popoverColor,\n    boxShadow2,\n    borderRadius,\n    heightMedium,\n    dividerColor,\n    textColor2\n  } = vars\n  return {\n    menuPadding: '4px',\n    menuColor: popoverColor,\n    menuBoxShadow: boxShadow2,\n    menuBorderRadius: borderRadius,\n    menuHeight: `calc(${heightMedium} * 7.6)`,\n    actionDividerColor: dividerColor,\n    actionTextColor: textColor2,\n    actionPadding: '8px 12px',\n    headerDividerColor: dividerColor,\n    headerTextColor: textColor2,\n    headerPadding: '8px 12px'\n  }\n}\n\nexport type TreeSelectThemeVars = ReturnType<typeof self>\n\nconst treeSelectLight = createTheme({\n  name: 'TreeSelect',\n  common: commonLight,\n  peers: {\n    Tree: treeLight,\n    Empty: emptyLight,\n    InternalSelection: internalSelectionLight\n  },\n  self\n})\n\nexport default treeSelectLight\nexport type TreeSelectTheme = typeof treeSelectLight\n"
  },
  {
    "path": "src/tree-select/styles/rtl.ts",
    "content": "import type { RtlItem } from '../../config-provider/src/internal-interface'\nimport { scrollbarRtl } from '../../_internal/scrollbar/styles'\nimport { internalSelectMenuRtl } from '../../_internal/select-menu/styles'\nimport { internalSelectionRtl } from '../../_internal/selection/styles'\nimport { c } from '../../_utils/cssr'\nimport { tagRtl } from '../../tag/styles'\nimport { treeRtl } from '../../tree/styles'\n\nexport const treeSelectRtl: RtlItem = {\n  name: 'Select',\n  style: c([]),\n  peers: [\n    internalSelectionRtl,\n    internalSelectMenuRtl,\n    tagRtl,\n    scrollbarRtl,\n    treeRtl\n  ]\n}\n"
  },
  {
    "path": "src/tree-select/tests/TreeSelect.spec.ts",
    "content": "import type { TreeSelectOption } from '../index'\nimport { mount } from '@vue/test-utils'\nimport { NTreeSelect } from '../index'\n\ndescribe('n-tree-select', () => {\n  it('should work with import on demand', () => {\n    mount(NTreeSelect)\n  })\n  it('should accept proper options', () => {\n    mount(NTreeSelect, {\n      props: {\n        options: [\n          {\n            label: '1',\n            key: '1'\n          }\n        ]\n      }\n    })\n    const options: TreeSelectOption[] = [\n      {\n        label: '1',\n        key: '1',\n        gogogo: '12'\n      }\n    ]\n    mount(NTreeSelect, {\n      props: {\n        options\n      }\n    })\n  })\n  it('should show all path when set showPath', async () => {\n    const wrapper = mount(NTreeSelect, {\n      props: {\n        options: [\n          {\n            label: '1',\n            key: '1',\n            children: [\n              {\n                label: '1-1',\n                key: '1-1'\n              },\n              {\n                label: '1-2',\n                key: '1-2'\n              }\n            ]\n          }\n        ],\n        showPath: true,\n        defaultValue: '1-2'\n      }\n    })\n    expect(wrapper.find('.n-base-selection-input').exists()).toBe(true)\n    expect(wrapper.find('.n-base-selection-input').text()).toBe('1 / 1-2')\n\n    await wrapper.setProps({ showPath: false })\n    expect(wrapper.find('.n-base-selection-input').exists()).toBe(true)\n    expect(wrapper.find('.n-base-selection-input').text()).toBe('1-2')\n\n    await wrapper.setProps({\n      showPath: true,\n      defaultValue: '1-1',\n      separator: ' | '\n    })\n    expect(wrapper.find('.n-base-selection-input').exists()).toBe(true)\n    expect(wrapper.find('.n-base-selection-input').text()).toBe('1 | 1-2')\n  })\n\n  it('should work with `multiple` prop', () => {\n    const wrapper = mount(NTreeSelect, {\n      props: {\n        multiple: true,\n        options: [\n          {\n            label: '1',\n            key: '1'\n          }\n        ]\n      }\n    })\n    expect(wrapper.find('.n-base-selection').attributes('class')).toContain(\n      'n-base-selection--multiple'\n    )\n  })\n})\n"
  },
  {
    "path": "src/tree-select/tests/server.spec.tsx",
    "content": "import { setup } from '@css-render/vue3-ssr'\nimport { renderToString } from '@vue/server-renderer'\n/**\n * @vitest-environment node\n */\nimport { createSSRApp, h } from 'vue'\nimport { NTreeSelect } from '../..'\n\ndescribe('server side rendering', () => {\n  it('works', async () => {\n    const app = createSSRApp(() => <NTreeSelect />)\n    setup(app)\n    try {\n      await renderToString(app)\n    }\n    catch (e) {\n      expect(e).not.toBeTruthy()\n    }\n  })\n})\n"
  },
  {
    "path": "src/tsconfig.cjs.json",
    "content": "{\n  \"extends\": \"../tsconfig.json\",\n  \"compilerOptions\": {\n    \"target\": \"ES6\",\n    \"jsx\": \"react\",\n    \"rootDir\": \".\",\n    \"module\": \"CommonJS\",\n    \"moduleResolution\": \"node\",\n    \"outDir\": \"../lib\"\n  },\n  \"exclude\": [\"./**/*.spec.*\"]\n}\n"
  },
  {
    "path": "src/tsconfig.demo.json",
    "content": "{\n  \"extends\": \"../tsconfig.json\",\n  \"compilerOptions\": {\n    \"incremental\": false,\n    \"composite\": false,\n    \"target\": \"ES6\",\n    \"rootDirs\": [\".\", \"../generic\"],\n    \"module\": \"es6\",\n    \"noEmit\": true\n  },\n  \"include\": [\"./**/*.ts\", \"./**/*.tsx\", \"./**/*.vue\"],\n  \"exclude\": [\"./**/*.spec.*\"]\n}\n"
  },
  {
    "path": "src/tsconfig.esm.json",
    "content": "{\n  \"extends\": \"../tsconfig.json\",\n  \"compilerOptions\": {\n    \"target\": \"ES6\",\n    \"jsx\": \"react\",\n    \"rootDir\": \".\",\n    \"module\": \"ES6\",\n    \"outDir\": \"../es\"\n  },\n  \"exclude\": [\"./**/*.spec.*\"]\n}\n"
  },
  {
    "path": "src/typography/demos/enUS/header.demo.vue",
    "content": "<markdown>\n# Header\n\nMake your headers pop with a little bar to the left. Much less boring.\n</markdown>\n\n<template>\n  <div style=\"padding-left: 24px; position: relative\">\n    <div\n      style=\"\n        position: absolute;\n        left: 0;\n        top: 0;\n        bottom: 0;\n        width: 24px;\n        background-color: rgba(128, 128, 128, 0.5);\n      \"\n    />\n    <n-h1>\n      <n-text type=\"primary\">\n        sin(x)\n      </n-text>\n    </n-h1>\n    <n-h1 prefix=\"bar\">\n      <n-text type=\"primary\">\n        sin(x)\n      </n-text>\n    </n-h1>\n    <n-h1 prefix=\"bar\" align-text>\n      <n-text type=\"primary\">\n        sin(x)\n      </n-text>\n    </n-h1>\n    <n-h1 prefix=\"bar\" align-text type=\"success\">\n      <n-text type=\"success\">\n        sin(x)\n      </n-text>\n    </n-h1>\n    <n-h1 prefix=\"bar\" align-text type=\"info\">\n      <n-text type=\"info\">\n        sin(x)\n      </n-text>\n    </n-h1>\n    <n-h1 prefix=\"bar\" align-text type=\"warning\">\n      <n-text type=\"warning\">\n        sin(x)\n      </n-text>\n    </n-h1>\n    <n-h1 prefix=\"bar\" align-text type=\"error\">\n      <n-text type=\"error\">\n        sin(x)\n      </n-text>\n    </n-h1>\n    <n-h2>cos(x)</n-h2>\n    <n-h2 prefix=\"bar\">\n      cos(x)\n    </n-h2>\n    <n-h2 prefix=\"bar\" align-text>\n      cos(x)\n    </n-h2>\n    <n-h3>-sin(x)</n-h3>\n    <n-h3 prefix=\"bar\">\n      -sin(x)\n    </n-h3>\n    <n-h3 prefix=\"bar\" align-text>\n      -sin(x)\n    </n-h3>\n    <n-h4>-cos(x)</n-h4>\n    <n-h4 prefix=\"bar\">\n      -cos(x)\n    </n-h4>\n    <n-h4 prefix=\"bar\" align-text>\n      -cos(x)\n    </n-h4>\n    <n-h5>sin(x)</n-h5>\n    <n-h5 prefix=\"bar\">\n      sin(x)\n    </n-h5>\n    <n-h5 prefix=\"bar\" align-text>\n      sin(x)\n    </n-h5>\n    <n-h6>What a loop!</n-h6>\n    <n-h6 prefix=\"bar\">\n      What a loop!\n    </n-h6>\n    <n-h6 prefix=\"bar\" align-text>\n      What a loop!\n    </n-h6>\n  </div>\n</template>\n"
  },
  {
    "path": "src/typography/demos/enUS/index.demo-entry.md",
    "content": "# Typography\n\nNaive UI provides some HTML text styling.\n\nTypography is an art.\n\n## Demos\n\n```demo\nheader.vue\ntags.vue\ntext.vue\nrouter-link.vue\n```\n\n## API\n\n### Text Props\n\n| Name | Type | Default | Description |\n| --- | --- | --- | --- |\n| type | `'default' \\| 'success' \\| 'info' \\| 'warning' \\| 'error'` | `'default'` | Typography type. |\n| strong | `boolean` | `false` | Strong. |\n| italic | `boolean` | `false` | Italic. |\n| underline | `boolean` | `false` | Underline. |\n| delete | `boolean` | `false` | Use the `del` tag and strikethrough style. |\n| code | `boolean` | `false` | Use the `code` tag and style. |\n| depth | `1 \\| 2 \\| 3 \\| '1' \\| '2' \\| '3'` | `undefined` | Text depth (shade of text). |\n| tag | `string` | `undefined` | Tag to use. `code` or `delete` properties will override this. |\n\n### P Props\n\n| Name | Type | Default | Description |\n| --- | --- | --- | --- |\n| depth | `1 \\| 2 \\| 3 \\| '1' \\| '2' \\| '3'` | `undefined` | Text depth (shade of text). |\n\n### H1, H2, H3, H4, H5, H6 Props\n\n| Name | Type | Default | Description |\n| --- | --- | --- | --- |\n| align-text | `boolean` | `false` | Text alignment. |\n| type | `'default' \\| 'success' \\| 'info' \\| 'warning' \\| 'error'` | `'default'` | Text color style. |\n| prefix | `'bar'` | `undefined` | Show a bar in front of the heading. |\n\n### Ul, Ol Props\n\n| Name       | Type      | Default | Description     |\n| ---------- | --------- | ------- | --------------- |\n| align-text | `boolean` | `false` | Text alignment. |\n\n### Blockquote Props\n\n| Name       | Type      | Default | Description     |\n| ---------- | --------- | ------- | --------------- |\n| align-text | `boolean` | `false` | Text alignment. |\n\n### All Typography Components Slots\n\n| Name    | Parameters | Description                |\n| ------- | ---------- | -------------------------- |\n| default | `()`       | The content of typography. |\n"
  },
  {
    "path": "src/typography/demos/enUS/router-link.demo.vue",
    "content": "<markdown>\n# Use n-a with router link\n\nYou can use `<n-a />` for links and routes.\n\nIf you think the following method is a little verbose for routes, you can always make it a new component.\n</markdown>\n\n<template>\n  <router-link to=\"/\" #=\"{ navigate, href }\" custom>\n    <n-a :href=\"href\" @click=\"navigate\">\n      Back Home\n    </n-a>\n  </router-link>\n</template>\n"
  },
  {
    "path": "src/typography/demos/enUS/tags.demo.vue",
    "content": "<markdown>\n# Tags\n\nOther naive-ui built-in tags.\n</markdown>\n\n<template>\n  <n-a href=\"https://en.wikipedia.org/wiki/Hear_the_Wind_Sing\" target=\"_blank\">\n    Hear the Wind Sing\n  </n-a>\n  <n-h1>h1 tag</n-h1>\n  <n-p>\n    Hear the Wind Sing (風の歌を聴け Kaze no uta o kike) is the first novel by\n    Japanese writer Haruki Murakami. It first appeared in the June 1979 issue of\n    Gunzo (one of the most influential literary magazines in Japan), and in book\n    form the next month. The novel was adapted by Japanese director Kazuki Ōmori\n    in a 1981 film distributed by Art Theatre Guild. An English translation by\n    Alfred Birnbaum appeared in 1987.\n  </n-p>\n  <n-h2>h2 tag</n-h2>\n  <n-p>\n    Hear the Wind Sing (風の歌を聴け Kaze no uta o kike) is the first novel by\n    Japanese writer Haruki Murakami. It first appeared in the June 1979 issue of\n    Gunzo (one of the most influential literary magazines in Japan), and in book\n    form the next month. The novel was adapted by Japanese director Kazuki Ōmori\n    in a 1981 film distributed by Art Theatre Guild. An English translation by\n    Alfred Birnbaum appeared in 1987.\n  </n-p>\n  <n-h3>h3 tag</n-h3>\n  <n-p>\n    Hear the Wind Sing (風の歌を聴け Kaze no uta o kike) is the first novel by\n    Japanese writer Haruki Murakami. It first appeared in the June 1979 issue of\n    Gunzo (one of the most influential literary magazines in Japan), and in book\n    form the next month. The novel was adapted by Japanese director Kazuki Ōmori\n    in a 1981 film distributed by Art Theatre Guild. An English translation by\n    Alfred Birnbaum appeared in 1987.\n  </n-p>\n  <n-h4>h4 tag</n-h4>\n  <n-p>\n    Hear the Wind Sing (風の歌を聴け Kaze no uta o kike) is the first novel by\n    Japanese writer Haruki Murakami. It first appeared in the June 1979 issue of\n    Gunzo (one of the most influential literary magazines in Japan), and in book\n    form the next month. The novel was adapted by Japanese director Kazuki Ōmori\n    in a 1981 film distributed by Art Theatre Guild. An English translation by\n    Alfred Birnbaum appeared in 1987.\n  </n-p>\n  <n-h5>h5 tag</n-h5>\n  <n-p>\n    Hear the Wind Sing (風の歌を聴け Kaze no uta o kike) is the first novel by\n    Japanese writer Haruki Murakami. It first appeared in the June 1979 issue of\n    Gunzo (one of the most influential literary magazines in Japan), and in book\n    form the next month. The novel was adapted by Japanese director Kazuki Ōmori\n    in a 1981 film distributed by Art Theatre Guild. An English translation by\n    Alfred Birnbaum appeared in 1987.\n  </n-p>\n  <n-h6>h6 tag</n-h6>\n  <n-p>\n    Hear the Wind Sing (風の歌を聴け Kaze no uta o kike) is the first novel by\n    Japanese writer Haruki Murakami. It first appeared in the June 1979 issue of\n    Gunzo (one of the most influential literary magazines in Japan), and in book\n    form the next month. The novel was adapted by Japanese director Kazuki Ōmori\n    in a 1981 film distributed by Art Theatre Guild. An English translation by\n    Alfred Birnbaum appeared in 1987.\n  </n-p>\n  <n-ul>\n    <n-li>li tag</n-li>\n    <n-li>li tag</n-li>\n    <n-li>li tag</n-li>\n  </n-ul>\n  <n-hr />\n  <n-ol>\n    <n-li>li tag</n-li>\n    <n-li>li tag</n-li>\n    <n-li>li tag</n-li>\n  </n-ol>\n  <n-ul align-text>\n    <n-li>li tag</n-li>\n    <n-li>li tag</n-li>\n    <n-li>li tag</n-li>\n  </n-ul>\n  <n-hr />\n  <n-ol align-text>\n    <n-li>li tag</n-li>\n    <n-li>li tag</n-li>\n    <n-li>li tag</n-li>\n  </n-ol>\n  <n-blockquote>\n    Hear the Wind Sing (風の歌を聴け Kaze no uta o kike) is the first novel by\n    Japanese writer Haruki Murakami. It first appeared in the June 1979 issue of\n    Gunzo (one of the most influential literary magazines in Japan), and in book\n    form the next month. The novel was adapted by Japanese director Kazuki Ōmori\n    in a 1981 film distributed by Art Theatre Guild. An English translation by\n    Alfred Birnbaum appeared in 1987.\n  </n-blockquote>\n  <n-blockquote align-text>\n    Hear the Wind Sing (風の歌を聴け Kaze no uta o kike) is the first novel by\n    Japanese writer Haruki Murakami. It first appeared in the June 1979 issue of\n    Gunzo (one of the most influential literary magazines in Japan), and in book\n    form the next month. The novel was adapted by Japanese director Kazuki Ōmori\n    in a 1981 film distributed by Art Theatre Guild. An English translation by\n    Alfred Birnbaum appeared in 1987.\n  </n-blockquote>\n</template>\n"
  },
  {
    "path": "src/typography/demos/enUS/text.demo.vue",
    "content": "<markdown>\n# Text\n\nUse different `types` to add some variety to your styles.\n</markdown>\n\n<template>\n  <n-text type=\"info\">\n    Info\n  </n-text>\n  <n-text type=\"success\">\n    Success\n  </n-text>\n  <n-text type=\"warning\">\n    Warning\n  </n-text>\n  <n-text type=\"error\">\n    Error\n  </n-text> <n-text strong>\n    Strong\n  </n-text>\n  <n-text italic>\n    Italic\n  </n-text> <n-text underline>\n    Underline\n  </n-text>\n  <n-text delete>\n    Delete\n  </n-text> <n-text code>\n    Code\n  </n-text>\n  <n-text code delete>\n    Code\n  </n-text>\n  <n-text depth=\"1\">\n    Primary Depth\n  </n-text>\n  <n-text depth=\"2\">\n    Secondary Depth\n  </n-text>\n  <n-text depth=\"3\">\n    Tertiary Depth\n  </n-text>\n  <n-text tag=\"div\">\n    As Div\n  </n-text>\n</template>\n"
  },
  {
    "path": "src/typography/demos/zhCN/header.demo.vue",
    "content": "<markdown>\n# 标题\n\nHeader 不光是 Header。你知道 UI 一般很喜欢在 Header 旁边弄一个带颜色的竖条（确实，光有文字太单调了）。所以这它可以有个条。\n</markdown>\n\n<template>\n  <div style=\"padding-left: 24px; position: relative\">\n    <div\n      style=\"\n        position: absolute;\n        left: 0;\n        top: 0;\n        bottom: 0;\n        width: 24px;\n        background-color: rgba(128, 128, 128, 0.5);\n      \"\n    />\n    <n-h1>\n      <n-text type=\"primary\">\n        sin(x)\n      </n-text>\n    </n-h1>\n    <n-h1 prefix=\"bar\">\n      <n-text type=\"primary\">\n        sin(x)\n      </n-text>\n    </n-h1>\n    <n-h1 prefix=\"bar\" align-text>\n      <n-text type=\"primary\">\n        sin(x)\n      </n-text>\n    </n-h1>\n    <n-h1 prefix=\"bar\" align-text type=\"success\">\n      <n-text type=\"success\">\n        sin(x)\n      </n-text>\n    </n-h1>\n    <n-h1 prefix=\"bar\" align-text type=\"info\">\n      <n-text type=\"info\">\n        sin(x)\n      </n-text>\n    </n-h1>\n    <n-h1 prefix=\"bar\" align-text type=\"warning\">\n      <n-text type=\"warning\">\n        sin(x)\n      </n-text>\n    </n-h1>\n    <n-h1 prefix=\"bar\" align-text type=\"error\">\n      <n-text type=\"error\">\n        sin(x)\n      </n-text>\n    </n-h1>\n    <n-h2>cos(x)</n-h2>\n    <n-h2 prefix=\"bar\">\n      cos(x)\n    </n-h2>\n    <n-h2 prefix=\"bar\" align-text>\n      cos(x)\n    </n-h2>\n    <n-h3>-sin(x)</n-h3>\n    <n-h3 prefix=\"bar\">\n      -sin(x)\n    </n-h3>\n    <n-h3 prefix=\"bar\" align-text>\n      -sin(x)\n    </n-h3>\n    <n-h4>-cos(x)</n-h4>\n    <n-h4 prefix=\"bar\">\n      -cos(x)\n    </n-h4>\n    <n-h4 prefix=\"bar\" align-text>\n      -cos(x)\n    </n-h4>\n    <n-h5>sin(x)</n-h5>\n    <n-h5 prefix=\"bar\">\n      sin(x)\n    </n-h5>\n    <n-h5 prefix=\"bar\" align-text>\n      sin(x)\n    </n-h5>\n    <n-h6>循环啊！</n-h6>\n    <n-h6 prefix=\"bar\">\n      循环啊！\n    </n-h6>\n    <n-h6 prefix=\"bar\" align-text>\n      循环啊！\n    </n-h6>\n  </div>\n</template>\n"
  },
  {
    "path": "src/typography/demos/zhCN/index.demo-entry.md",
    "content": "# 排印 Typography\n\nNaive UI 提供了常用 HTML 标签的一些基本样式，以及对文本渲染提供帮助的组件。\n\n排印是一门艺术。\n\n## 演示\n\n```demo\nheader.vue\ntags.vue\ntext.vue\nrouter-link.vue\n```\n\n## API\n\n### Text Props\n\n| 名称 | 类型 | 默认值 | 说明 |\n| --- | --- | --- | --- |\n| type | `'default' \\| 'success' \\| 'info' \\| 'warning' \\| 'error'` | `'default'` | 排印类型 |\n| strong | `boolean` | `false` | 粗体 |\n| italic | `boolean` | `false` | 斜体 |\n| underline | `boolean` | `false` | 文字下划线 |\n| delete | `boolean` | `false` | 文字删除线 |\n| code | `boolean` | `false` | 代码模式 |\n| depth | `1 \\| 2 \\| 3 \\| '1' \\| '2' \\| '3'` | `undefined` | 文字深度 |\n| tag | `string` | `undefined` | 需要被渲染为什么标签，在 `code` 和 `del` 设定的情况下不生效 |\n\n### P Props\n\n| 名称  | 类型                               | 默认值      | 说明     |\n| ----- | ---------------------------------- | ----------- | -------- |\n| depth | `1 \\| 2 \\| 3 \\| '1' \\| '2' \\| '3'` | `undefined` | 文字深度 |\n\n### H1, H2, H3, H4, H5, H6 Props\n\n| 名称 | 类型 | 默认值 | 说明 |\n| --- | --- | --- | --- |\n| align-text | `boolean` | `false` | 文本对齐 |\n| type | `'default' \\| 'success' \\| 'info' \\| 'warning' \\| 'error'` | `'default'` | 排印类型 |\n| prefix | `'bar'` | `undefined` | 在字首显示条块 |\n\n### Ul, Ol Props\n\n| 名称       | 类型      | 默认值  | 说明     |\n| ---------- | --------- | ------- | -------- |\n| align-text | `boolean` | `false` | 文本对齐 |\n\n### Blockquote Props\n\n| 名称       | 类型      | 默认值  | 说明     |\n| ---------- | --------- | ------- | -------- |\n| align-text | `boolean` | `false` | 文本对齐 |\n\n### All Typography Components Slots\n\n| 名称    | 参数 | 说明       |\n| ------- | ---- | ---------- |\n| default | `()` | 排印的内容 |\n"
  },
  {
    "path": "src/typography/demos/zhCN/router-link.demo.vue",
    "content": "<markdown>\n# 配合 Router Link\n\n有的时候会需要让 `<n-a />` 具有 router-link 的功能。\n\n如果你觉得写起来很麻烦，可以再封装一个组件。\n</markdown>\n\n<template>\n  <router-link to=\"/\" #=\"{ navigate, href }\" custom>\n    <n-a :href=\"href\" @click=\"navigate\">\n      回到主页\n    </n-a>\n  </router-link>\n</template>\n"
  },
  {
    "path": "src/typography/demos/zhCN/tags.demo.vue",
    "content": "<markdown>\n# 标签\n\n其他的 Naive UI 内置标签。\n</markdown>\n\n<template>\n  <n-a\n    href=\"https://baike.baidu.com/item/%E4%B8%94%E5%90%AC%E9%A3%8E%E5%90%9F\"\n    target=\"_blank\"\n  >\n    且听风吟\n  </n-a>\n  <n-h1>h1 标签</n-h1>\n  <n-p>\n    《且听风吟》是日本作家村上春树的第一本小说。它首次出现在 1979 年 6\n    月的《群像》（日本最有影响力的文学杂志之一），并于次月出版成书。这部小说被日本导演\n    Kazuki Ōmori 改编成电影，并于 1981 年由艺术剧院协会发行。1987\n    年被阿尔弗雷德伯恩鲍姆译成英文。\n  </n-p>\n  <n-h2>h2 标签</n-h2>\n  <n-p>\n    《且听风吟》是日本作家村上春树的第一本小说。它首次出现在 1979 年 6\n    月的《群像》（日本最有影响力的文学杂志之一），并于次月出版成书。这部小说被日本导演\n    Kazuki Ōmori 改编成电影，并于 1981 年由艺术剧院协会发行。1987\n    年被阿尔弗雷德伯恩鲍姆译成英文。\n  </n-p>\n  <n-h3>h3 标签</n-h3>\n  <n-p>\n    《且听风吟》是日本作家村上春树的第一本小说。它首次出现在 1979 年 6\n    月的《群像》（日本最有影响力的文学杂志之一），并于次月出版成书。这部小说被日本导演\n    Kazuki Ōmori 改编成电影，并于 1981 年由艺术剧院协会发行。1987\n    年被阿尔弗雷德伯恩鲍姆译成英文。\n  </n-p>\n  <n-h4>h4 标签</n-h4>\n  <n-p>\n    《且听风吟》是日本作家村上春树的第一本小说。它首次出现在 1979 年 6\n    月的《群像》（日本最有影响力的文学杂志之一），并于次月出版成书。这部小说被日本导演\n    Kazuki Ōmori 改编成电影，并于 1981 年由艺术剧院协会发行。1987\n    年被阿尔弗雷德伯恩鲍姆译成英文。\n  </n-p>\n  <n-h5>h5 标签</n-h5>\n  <n-p>\n    《且听风吟》是日本作家村上春树的第一本小说。它首次出现在 1979 年 6\n    月的《群像》（日本最有影响力的文学杂志之一），并于次月出版成书。这部小说被日本导演\n    Kazuki Ōmori 改编成电影，并于 1981 年由艺术剧院协会发行。1987\n    年被阿尔弗雷德伯恩鲍姆译成英文。\n  </n-p>\n  <n-h6>h6 标签</n-h6>\n  <n-p>\n    《且听风吟》是日本作家村上春树的第一本小说。它首次出现在 1979 年 6\n    月的《群像》（日本最有影响力的文学杂志之一），并于次月出版成书。这部小说被日本导演\n    Kazuki Ōmori 改编成电影，并于 1981 年由艺术剧院协会发行。1987\n    年被阿尔弗雷德伯恩鲍姆译成英文。\n  </n-p>\n  <n-ul>\n    <n-li>li 标签</n-li>\n    <n-li>li 标签</n-li>\n    <n-li>li 标签</n-li>\n  </n-ul>\n  <n-hr />\n  <n-ol>\n    <n-li>li 标签</n-li>\n    <n-li>li 标签</n-li>\n    <n-li>li 标签</n-li>\n  </n-ol>\n  <n-ul align-text>\n    <n-li>li 标签</n-li>\n    <n-li>li 标签</n-li>\n    <n-li>li 标签</n-li>\n  </n-ul>\n  <n-hr />\n  <n-ol align-text>\n    <n-li>li 标签</n-li>\n    <n-li>li 标签</n-li>\n    <n-li>li 标签</n-li>\n  </n-ol>\n  <n-blockquote>\n    《且听风吟》是日本作家村上春树的第一本小说。它首次出现在 1979 年 6\n    月的《群像》（日本最有影响力的文学杂志之一），并于次月出版成书。这部小说被日本导演\n    Kazuki Ōmori 改编成电影，并于 1981 年由艺术剧院协会发行。1987\n    年被阿尔弗雷德伯恩鲍姆译成英文。\n  </n-blockquote>\n  <n-blockquote align-text>\n    《且听风吟》是日本作家村上春树的第一本小说。它首次出现在 1979 年 6\n    月的《群像》（日本最有影响力的文学杂志之一），并于次月出版成书。这部小说被日本导演\n    Kazuki Ōmori 改编成电影，并于 1981 年由艺术剧院协会发行。1987\n    年被阿尔弗雷德伯恩鲍姆译成英文。\n  </n-blockquote>\n</template>\n"
  },
  {
    "path": "src/typography/demos/zhCN/text.demo.vue",
    "content": "<markdown>\n# 文本\n\n用不同类型的文本展示各种信息。\n</markdown>\n\n<template>\n  <n-text type=\"info\">\n    Info\n  </n-text>\n  <n-text type=\"success\">\n    Success\n  </n-text>\n  <n-text type=\"warning\">\n    Warning\n  </n-text>\n  <n-text type=\"error\">\n    Error\n  </n-text> <n-text strong>\n    Strong\n  </n-text>\n  <n-text italic>\n    Italic\n  </n-text> <n-text underline>\n    Underline\n  </n-text>\n  <n-text delete>\n    Delete\n  </n-text> <n-text code>\n    Code\n  </n-text>\n  <n-text code delete>\n    Code\n  </n-text>\n  <n-text depth=\"1\">\n    Primary Depth\n  </n-text>\n  <n-text depth=\"2\">\n    Secondary Depth\n  </n-text>\n  <n-text depth=\"3\">\n    Tertiary Depth\n  </n-text>\n  <n-text tag=\"div\">\n    作为 Div\n  </n-text>\n</template>\n"
  },
  {
    "path": "src/typography/index.ts",
    "content": "export { aProps, default as NA } from './src/a'\nexport type { AProps } from './src/a'\nexport { blockquoteProps, default as NBlockquote } from './src/blockquote'\nexport type { BlockquoteProps } from './src/blockquote'\nexport {\n  headerProps as h1Props,\n  headerProps as h2Props,\n  headerProps as h3Props,\n  headerProps as h4Props,\n  headerProps as h5Props,\n  headerProps as h6Props\n} from './src/create-header'\nexport type { HeaderProps as H1Props } from './src/create-header'\nexport type { HeaderProps as H2Props } from './src/create-header'\nexport type { HeaderProps as H3Props } from './src/create-header'\nexport type { HeaderProps as H4Props } from './src/create-header'\nexport type { HeaderProps as H5Props } from './src/create-header'\nexport type { HeaderProps as H6Props } from './src/create-header'\nexport { NH1, NH2, NH3, NH4, NH5, NH6 } from './src/headers'\nexport { default as NHr } from './src/hr'\nexport { default as NLi } from './src/li'\nexport { default as NOl, olProps } from './src/ol'\nexport type { OlProps } from './src/ol'\nexport { default as NP, pProps } from './src/p'\nexport type { PProps } from './src/p'\nexport { default as NText, textProps } from './src/text'\nexport type { TextProps } from './src/text'\nexport { default as NUl, ulProps } from './src/ul'\nexport type { UlProps } from './src/ul'\n"
  },
  {
    "path": "src/typography/src/a.tsx",
    "content": "import type { CSSProperties } from 'vue'\nimport type { ThemeProps } from '../../_mixins'\nimport type { ExtractPublicPropTypes } from '../../_utils'\nimport type { TypographyTheme } from '../styles'\nimport { computed, defineComponent, h } from 'vue'\nimport { useConfig, useTheme, useThemeClass } from '../../_mixins'\nimport { typographyLight } from '../styles'\nimport style from './styles/a.cssr'\n\nexport const aProps = {\n  ...(useTheme.props as ThemeProps<TypographyTheme>)\n} as const\n\nexport type AProps = ExtractPublicPropTypes<typeof aProps>\n\nexport default defineComponent({\n  name: 'A',\n  props: aProps,\n  setup(props) {\n    const { mergedClsPrefixRef, inlineThemeDisabled } = useConfig(props)\n    const themeRef = useTheme(\n      'Typography',\n      '-a',\n      style,\n      typographyLight,\n      props,\n      mergedClsPrefixRef\n    )\n    const cssVarsRef = computed(() => {\n      const {\n        common: { cubicBezierEaseInOut },\n        self: { aTextColor }\n      } = themeRef.value\n      return {\n        '--n-text-color': aTextColor,\n        '--n-bezier': cubicBezierEaseInOut\n      }\n    })\n    const themeClassHandle = inlineThemeDisabled\n      ? useThemeClass('a', undefined, cssVarsRef, props)\n      : undefined\n    return {\n      mergedClsPrefix: mergedClsPrefixRef,\n      cssVars: inlineThemeDisabled ? undefined : cssVarsRef,\n      themeClass: themeClassHandle?.themeClass,\n      onRender: themeClassHandle?.onRender\n    }\n  },\n  render() {\n    this.onRender?.()\n    return (\n      <a\n        class={[`${this.mergedClsPrefix}-a`, this.themeClass]}\n        style={this.cssVars as CSSProperties}\n      >\n        {this.$slots}\n      </a>\n    )\n  }\n})\n"
  },
  {
    "path": "src/typography/src/blockquote.tsx",
    "content": "import type { CSSProperties } from 'vue'\nimport type { ThemeProps } from '../../_mixins'\nimport type { ExtractPublicPropTypes } from '../../_utils'\nimport type { TypographyTheme } from '../styles'\nimport { computed, defineComponent, h } from 'vue'\nimport { useConfig, useTheme, useThemeClass } from '../../_mixins'\nimport { typographyLight } from '../styles'\nimport style from './styles/blockquote.cssr'\n\nexport const blockquoteProps = {\n  ...(useTheme.props as ThemeProps<TypographyTheme>),\n  alignText: Boolean\n} as const\n\nexport type BlockquoteProps = ExtractPublicPropTypes<typeof blockquoteProps>\n\nexport default defineComponent({\n  name: 'Blockquote',\n  props: blockquoteProps,\n  setup(props) {\n    const { mergedClsPrefixRef, inlineThemeDisabled } = useConfig(props)\n    const themeRef = useTheme(\n      'Typography',\n      '-blockquote',\n      style,\n      typographyLight,\n      props,\n      mergedClsPrefixRef\n    )\n    const cssVarsRef = computed(() => {\n      const {\n        common: { cubicBezierEaseInOut },\n        self: {\n          blockquoteTextColor,\n          blockquotePrefixColor,\n          blockquoteLineHeight,\n          blockquoteFontSize\n        }\n      } = themeRef.value\n      return {\n        '--n-bezier': cubicBezierEaseInOut,\n        '--n-font-size': blockquoteFontSize,\n        '--n-line-height': blockquoteLineHeight,\n        '--n-prefix-color': blockquotePrefixColor,\n        '--n-text-color': blockquoteTextColor\n      }\n    })\n    const themeClassHandle = inlineThemeDisabled\n      ? useThemeClass('blockquote', undefined, cssVarsRef, props)\n      : undefined\n    return {\n      mergedClsPrefix: mergedClsPrefixRef,\n      cssVars: inlineThemeDisabled ? undefined : cssVarsRef,\n      themeClass: themeClassHandle?.themeClass,\n      onRender: themeClassHandle?.onRender\n    }\n  },\n  render() {\n    const { mergedClsPrefix } = this\n    this.onRender?.()\n    return (\n      <blockquote\n        class={[\n          `${mergedClsPrefix}-blockquote`,\n          this.themeClass,\n          this.alignText && `${mergedClsPrefix}-blockquote--align-text`\n        ]}\n        style={this.cssVars as CSSProperties}\n      >\n        {this.$slots}\n      </blockquote>\n    )\n  }\n})\n"
  },
  {
    "path": "src/typography/src/create-header.ts",
    "content": "import type { PropType } from 'vue'\nimport type { ThemeProps } from '../../_mixins'\nimport type { ExtractPublicPropTypes } from '../../_utils'\nimport type { TypographyTheme } from '../styles'\nimport { computed, defineComponent, h } from 'vue'\nimport { useConfig, useTheme, useThemeClass } from '../../_mixins'\nimport { createKey } from '../../_utils'\nimport { typographyLight } from '../styles'\nimport style from './styles/header.cssr'\n\nexport const headerProps = {\n  ...(useTheme.props as ThemeProps<TypographyTheme>),\n  type: {\n    type: String as PropType<\n      'info' | 'success' | 'warning' | 'error' | 'default'\n    >,\n    default: 'default'\n  },\n  prefix: String,\n  alignText: Boolean\n} as const\n\nexport type HeaderProps = ExtractPublicPropTypes<typeof headerProps>\n\nexport default (level: '1' | '2' | '3' | '4' | '5' | '6') =>\n  defineComponent({\n    name: `H${level}`,\n    props: headerProps,\n    setup(props) {\n      const { mergedClsPrefixRef, inlineThemeDisabled } = useConfig(props)\n      const themeRef = useTheme(\n        'Typography',\n        '-h',\n        style,\n        typographyLight,\n        props,\n        mergedClsPrefixRef\n      )\n      const cssVarsRef = computed(() => {\n        const { type } = props\n        const {\n          common: { cubicBezierEaseInOut },\n          self: {\n            headerFontWeight,\n            headerTextColor,\n            [createKey('headerPrefixWidth', level)]: prefixWidth,\n            [createKey('headerFontSize', level)]: fontSize,\n            [createKey('headerMargin', level)]: margin,\n            [createKey('headerBarWidth', level)]: barWidth,\n            [createKey('headerBarColor', type)]: barColor\n          }\n        } = themeRef.value\n        return {\n          '--n-bezier': cubicBezierEaseInOut,\n          '--n-font-size': fontSize,\n          '--n-margin': margin,\n          '--n-bar-color': barColor,\n          '--n-bar-width': barWidth,\n          '--n-font-weight': headerFontWeight,\n          '--n-text-color': headerTextColor,\n          '--n-prefix-width': prefixWidth\n        }\n      })\n      const themeClassHandle = inlineThemeDisabled\n        ? useThemeClass(\n            `h${level}`,\n            computed(() => props.type[0]),\n            cssVarsRef,\n            props\n          )\n        : undefined\n      return {\n        mergedClsPrefix: mergedClsPrefixRef,\n        cssVars: inlineThemeDisabled ? undefined : cssVarsRef,\n        themeClass: themeClassHandle?.themeClass,\n        onRender: themeClassHandle?.onRender\n      }\n    },\n    render() {\n      const { prefix, alignText, mergedClsPrefix, cssVars, $slots } = this\n      this.onRender?.()\n      return h(\n        `h${level}`,\n        {\n          class: [\n            `${mergedClsPrefix}-h`,\n            `${mergedClsPrefix}-h${level}`,\n            this.themeClass,\n            {\n              [`${mergedClsPrefix}-h--prefix-bar`]: prefix,\n              [`${mergedClsPrefix}-h--align-text`]: alignText\n            }\n          ],\n          style: cssVars\n        },\n        $slots\n      )\n    }\n  })\n"
  },
  {
    "path": "src/typography/src/headers.ts",
    "content": "import createHeader from './create-header'\n\nexport const NH1 = createHeader('1')\nexport const NH2 = createHeader('2')\nexport const NH3 = createHeader('3')\nexport const NH4 = createHeader('4')\nexport const NH5 = createHeader('5')\nexport const NH6 = createHeader('6')\n"
  },
  {
    "path": "src/typography/src/hr.tsx",
    "content": "import type { CSSProperties } from 'vue'\nimport type { ThemeProps } from '../../_mixins'\nimport type { TypographyTheme } from '../styles'\nimport { computed, defineComponent, h } from 'vue'\nimport { useConfig, useTheme, useThemeClass } from '../../_mixins'\nimport { typographyLight } from '../styles'\nimport style from './styles/hr.cssr'\n\nexport default defineComponent({\n  name: 'Hr',\n  props: {\n    ...(useTheme.props as ThemeProps<TypographyTheme>)\n  },\n  setup(props) {\n    const { mergedClsPrefixRef, inlineThemeDisabled } = useConfig(props)\n    const themeRef = useTheme(\n      'Typography',\n      '-hr',\n      style,\n      typographyLight,\n      props,\n      mergedClsPrefixRef\n    )\n    const cssVarsRef = computed(() => {\n      const {\n        common: { cubicBezierEaseInOut },\n        self: { hrColor }\n      } = themeRef.value\n      return {\n        '--n-bezier': cubicBezierEaseInOut,\n        '--n-color': hrColor\n      }\n    })\n    const themeClassHandle = inlineThemeDisabled\n      ? useThemeClass('hr', undefined, cssVarsRef, props)\n      : undefined\n    return {\n      mergedClsPrefix: mergedClsPrefixRef,\n      cssVars: inlineThemeDisabled ? undefined : cssVarsRef,\n      themeClass: themeClassHandle?.themeClass,\n      onRender: themeClassHandle?.onRender\n    }\n  },\n  render() {\n    this.onRender?.()\n    return (\n      <hr\n        class={[`${this.mergedClsPrefix}-hr`, this.themeClass]}\n        style={this.cssVars as CSSProperties}\n      />\n    )\n  }\n})\n"
  },
  {
    "path": "src/typography/src/li.tsx",
    "content": "import { defineComponent, h } from 'vue'\n\nexport default defineComponent({\n  name: 'Li',\n  render() {\n    return <li>{this.$slots}</li>\n  }\n})\n"
  },
  {
    "path": "src/typography/src/ol.tsx",
    "content": "import type { CSSProperties } from 'vue'\nimport type { ThemeProps } from '../../_mixins'\nimport type { ExtractPublicPropTypes } from '../../_utils'\nimport type { TypographyTheme } from '../styles'\nimport { computed, defineComponent, h } from 'vue'\nimport { useConfig, useTheme, useThemeClass } from '../../_mixins'\nimport { typographyLight } from '../styles'\nimport style from './styles/list.cssr'\n\nexport const olProps = {\n  ...(useTheme.props as ThemeProps<TypographyTheme>),\n  alignText: Boolean\n}\n\nexport type OlProps = ExtractPublicPropTypes<typeof olProps>\n\nexport default defineComponent({\n  name: 'Ol',\n  props: olProps,\n  setup(props) {\n    const { mergedClsPrefixRef, inlineThemeDisabled } = useConfig(props)\n    const themeRef = useTheme(\n      'Typography',\n      '-xl',\n      style,\n      typographyLight,\n      props,\n      mergedClsPrefixRef\n    )\n    const cssVarsRef = computed(() => {\n      const {\n        common: { cubicBezierEaseInOut },\n        self: {\n          olPadding,\n          ulPadding,\n          liMargin,\n          liTextColor,\n          liLineHeight,\n          liFontSize\n        }\n      } = themeRef.value\n      return {\n        '--n-bezier': cubicBezierEaseInOut,\n        '--n-font-size': liFontSize,\n        '--n-line-height': liLineHeight,\n        '--n-text-color': liTextColor,\n        '--n-li-margin': liMargin,\n        '--n-ol-padding': olPadding,\n        '--n-ul-padding': ulPadding\n      }\n    })\n    const themeClassHandle = inlineThemeDisabled\n      ? useThemeClass('ol', undefined, cssVarsRef, props)\n      : undefined\n    return {\n      mergedClsPrefix: mergedClsPrefixRef,\n      cssVars: inlineThemeDisabled ? undefined : cssVarsRef,\n      themeClass: themeClassHandle?.themeClass,\n      onRender: themeClassHandle?.onRender\n    }\n  },\n  render() {\n    const { mergedClsPrefix } = this\n    this.onRender?.()\n    return (\n      <ol\n        class={[\n          `${mergedClsPrefix}-ol`,\n          this.themeClass,\n          this.alignText && `${mergedClsPrefix}-ol--align-text`\n        ]}\n        style={this.cssVars as CSSProperties}\n      >\n        {this.$slots}\n      </ol>\n    )\n  }\n})\n"
  },
  {
    "path": "src/typography/src/p.tsx",
    "content": "import type { CSSProperties, PropType } from 'vue'\nimport type { ThemeProps } from '../../_mixins'\nimport type { ExtractPublicPropTypes } from '../../_utils'\nimport type { TypographyTheme } from '../styles'\nimport { computed, defineComponent, h } from 'vue'\nimport { useConfig, useTheme, useThemeClass } from '../../_mixins'\nimport { typographyLight } from '../styles'\nimport style from './styles/p.cssr'\n\nexport const pProps = {\n  ...(useTheme.props as ThemeProps<TypographyTheme>),\n  depth: [String, Number] as PropType<1 | 2 | 3 | '1' | '2' | '3'>\n}\n\nexport type PProps = ExtractPublicPropTypes<typeof pProps>\n\nexport default defineComponent({\n  name: 'P',\n  props: pProps,\n  setup(props) {\n    const { mergedClsPrefixRef, inlineThemeDisabled } = useConfig(props)\n    const themeRef = useTheme(\n      'Typography',\n      '-p',\n      style,\n      typographyLight,\n      props,\n      mergedClsPrefixRef\n    )\n    const cssVarsRef = computed(() => {\n      const { depth } = props\n      const typeSafeDepth = depth || '1'\n      const {\n        common: { cubicBezierEaseInOut },\n        self: {\n          pFontSize,\n          pLineHeight,\n          pMargin,\n          pTextColor,\n          [`pTextColor${typeSafeDepth}Depth` as const]: depthTextColor\n        }\n      } = themeRef.value\n      return {\n        '--n-bezier': cubicBezierEaseInOut,\n        '--n-font-size': pFontSize,\n        '--n-line-height': pLineHeight,\n        '--n-margin': pMargin,\n        '--n-text-color': depth === undefined ? pTextColor : depthTextColor\n      }\n    })\n    const themeClassHandle = inlineThemeDisabled\n      ? useThemeClass(\n          'p',\n          computed(() => `${props.depth || ''}`),\n          cssVarsRef,\n          props\n        )\n      : undefined\n    return {\n      mergedClsPrefix: mergedClsPrefixRef,\n      cssVars: inlineThemeDisabled ? undefined : cssVarsRef,\n      themeClass: themeClassHandle?.themeClass,\n      onRender: themeClassHandle?.onRender\n    }\n  },\n  render() {\n    this.onRender?.()\n    return (\n      <p\n        class={[`${this.mergedClsPrefix}-p`, this.themeClass]}\n        style={this.cssVars as CSSProperties}\n      >\n        {this.$slots}\n      </p>\n    )\n  }\n})\n"
  },
  {
    "path": "src/typography/src/styles/a.cssr.ts",
    "content": "import { cB } from '../../../_utils/cssr'\n\n// vars:\n// --n-text-color\n// --n-bezier\nexport default cB('a', `\n  cursor: pointer;\n  transition:\n    color .3s var(--n-bezier),\n    text-decoration-color .3s var(--n-bezier);\n  text-decoration-color: var(--n-text-color);\n  color: var(--n-text-color);\n`)\n"
  },
  {
    "path": "src/typography/src/styles/blockquote.cssr.ts",
    "content": "import { c, cB, cM } from '../../../_utils/cssr'\n\n// vars:\n// --n-bezier\n// --n-font-size\n// --n-line-height\n// --n-prefix-color\n// --n-text-color\nexport default cB('blockquote', `\n  font-size: var(--n-font-size);\n  line-height: var(--n-line-height);\n  margin: 0;\n  margin-top: 12px;\n  margin-bottom: 12px;\n  box-sizing: border-box;\n  padding-left: 12px;\n  border-left: 4px solid var(--n-prefix-color);\n  color: var(--n-text-color);\n  transition:\n    color .3s var(--n-bezier),\n    border-color .3s var(--n-bezier);\n`, [\n  c('&:first-child', {\n    marginTop: 0\n  }),\n  c('&:last-child', {\n    marginBottom: 0\n  }),\n  cM('align-text', {\n    marginLeft: '-16px'\n  })\n])\n"
  },
  {
    "path": "src/typography/src/styles/header.cssr.ts",
    "content": "import { c, cB, cM } from '../../../_utils/cssr'\n\n// vars:\n// --n-bezier\n// --n-font-size\n// --n-margin\n// --n-bar-color\n// --n-bar-width\n// --n-font-weight\n// --n-text-color\n// --n-prefix-width\nexport default cB('h', `\n  font-size: var(--n-font-size);\n  font-weight: var(--n-font-weight);\n  margin: var(--n-margin);\n  transition: color .3s var(--n-bezier);\n  color: var(--n-text-color);\n`, [\n  c('&:first-child', {\n    marginTop: 0\n  }),\n  cM('prefix-bar', {\n    position: 'relative',\n    paddingLeft: 'var(--n-prefix-width)'\n  }, [\n    cM('align-text', {\n      paddingLeft: 0\n    }, [\n      c('&::before', {\n        left: 'calc(-1 * var(--n-prefix-width))'\n      })\n    ]),\n    c('&::before', `\n      content: \"\";\n      width: var(--n-bar-width);\n      border-radius: calc(var(--n-bar-width) / 2);\n      transition: background-color .3s var(--n-bezier);\n      left: 0;\n      top: 0;\n      bottom: 0;\n      position: absolute;\n    `),\n    c('&::before', {\n      backgroundColor: 'var(--n-bar-color)'\n    })\n  ])\n])\n"
  },
  {
    "path": "src/typography/src/styles/hr.cssr.ts",
    "content": "import { cB } from '../../../_utils/cssr'\n\n// vars:\n// --n-color\nexport default cB('hr', `\n  margin: 12px 0;\n  transition: border-color .3s var(--n-bezier);\n  border-left: none;\n  border-right: none;\n  border-bottom: none;\n  border-top: 1px solid var(--n-color);\n`)\n"
  },
  {
    "path": "src/typography/src/styles/list.cssr.ts",
    "content": "import { c, cB, cM } from '../../../_utils/cssr'\n\nconst liStyle = c('li', {\n  transition: 'color .3s var(--n-bezier)',\n  lineHeight: 'var(--n-line-height)',\n  margin: 'var(--n-li-margin)',\n  marginBottom: 0,\n  color: 'var(--n-text-color)'\n})\n\nconst childStyle = [\n  c('&:first-child', `\n    margin-top: 0;\n  `),\n  c('&:last-child', `\n    margin-bottom: 0;\n  `)\n]\n\n// vars:\n// --n-bezier\n// --n-font-size\n// --n-line-height\n// --n-text-color\n// --n-li-margin\n// --n-ol-padding\n// --n-ul-padding\nexport default c([\n  cB('ol', {\n    fontSize: 'var(--n-font-size)',\n    padding: 'var(--n-ol-padding)'\n  }, [\n    cM('align-text', {\n      paddingLeft: 0\n    }),\n    liStyle,\n    childStyle\n  ]),\n  cB('ul', {\n    fontSize: 'var(--n-font-size)',\n    padding: 'var(--n-ul-padding)'\n  }, [\n    cM('align-text', {\n      paddingLeft: 0\n    }),\n    liStyle,\n    childStyle\n  ])\n])\n"
  },
  {
    "path": "src/typography/src/styles/p.cssr.ts",
    "content": "import { c, cB } from '../../../_utils/cssr'\n\n// vars:\n// --n-bezier\n// --n-font-size\n// --n-line-height\n// --n-margin\n// --n-text-color\nexport default cB('p', `\n  box-sizing: border-box;\n  transition: color .3s var(--n-bezier);\n  margin: var(--n-margin);\n  font-size:  var(--n-font-size);\n  line-height: var(--n-line-height);\n  color: var(--n-text-color);\n`, [\n  c('&:first-child', 'margin-top: 0;'),\n  c('&:last-child', 'margin-bottom: 0;')\n])\n"
  },
  {
    "path": "src/typography/src/styles/text.cssr.ts",
    "content": "import { cB, cM } from '../../../_utils/cssr'\n\n// vars:\n// --n-text-color\n// --n-font-weight-strong\n// --n-font-famliy-mono\n// --n-code-border-radius\n// --n-code-text-color\n// --n-code-color\n// --n-code-border\nexport default cB('text', `\n  transition: color .3s var(--n-bezier);\n  color: var(--n-text-color);\n`, [\n  cM('strong', `\n    font-weight: var(--n-font-weight-strong);\n  `),\n  cM('italic', {\n    fontStyle: 'italic'\n  }),\n  cM('underline', {\n    textDecoration: 'underline'\n  }),\n  cM('code', `\n    line-height: 1.4;\n    display: inline-block;\n    font-family: var(--n-font-famliy-mono);\n    transition: \n      color .3s var(--n-bezier),\n      border-color .3s var(--n-bezier),\n      background-color .3s var(--n-bezier);\n    box-sizing: border-box;\n    padding: .05em .35em 0 .35em;\n    border-radius: var(--n-code-border-radius);\n    font-size: .9em;\n    color: var(--n-code-text-color);\n    background-color: var(--n-code-color);\n    border: var(--n-code-border);\n  `)\n])\n"
  },
  {
    "path": "src/typography/src/text.tsx",
    "content": "import type { CSSProperties, PropType } from 'vue'\nimport type { ThemeProps } from '../../_mixins'\nimport type { ExtractPublicPropTypes } from '../../_utils'\nimport type { TypographyTheme } from '../styles'\nimport { useCompitable } from 'vooks'\nimport { computed, defineComponent, h } from 'vue'\nimport { useConfig, useTheme, useThemeClass } from '../../_mixins'\nimport { createKey, warn } from '../../_utils'\nimport { typographyLight } from '../styles'\nimport style from './styles/text.cssr'\n\nexport const textProps = {\n  ...(useTheme.props as ThemeProps<TypographyTheme>),\n  code: Boolean,\n  type: {\n    type: String,\n    default: 'default'\n  },\n  delete: Boolean,\n  strong: Boolean,\n  italic: Boolean,\n  underline: Boolean,\n  depth: [String, Number] as PropType<1 | 2 | 3 | '1' | '2' | '3'>,\n  tag: String,\n  // deprecated\n  as: {\n    type: String,\n    validator: () => {\n      if (__DEV__) {\n        warn('text', '`as` is deprecated, please use `tag` instead.')\n      }\n      return true\n    },\n    default: undefined\n  }\n} as const\n\nexport type TextProps = ExtractPublicPropTypes<typeof textProps>\n\nexport default defineComponent({\n  name: 'Text',\n  props: textProps,\n  setup(props) {\n    const { mergedClsPrefixRef, inlineThemeDisabled } = useConfig(props)\n    const themeRef = useTheme(\n      'Typography',\n      '-text',\n      style,\n      typographyLight,\n      props,\n      mergedClsPrefixRef\n    )\n    const cssVarsRef = computed(() => {\n      const { depth, type } = props\n      const textColorKey\n        = type === 'default'\n          ? depth === undefined\n            ? 'textColor'\n            : `textColor${depth}Depth`\n          : createKey('textColor', type)\n      const {\n        common: { fontWeightStrong, fontFamilyMono, cubicBezierEaseInOut },\n        self: {\n          codeTextColor,\n          codeBorderRadius,\n          codeColor,\n          codeBorder,\n          [textColorKey as 'textColor']: textColor\n        }\n      } = themeRef.value\n      return {\n        '--n-bezier': cubicBezierEaseInOut,\n        '--n-text-color': textColor,\n        '--n-font-weight-strong': fontWeightStrong,\n        '--n-font-famliy-mono': fontFamilyMono,\n        '--n-code-border-radius': codeBorderRadius,\n        '--n-code-text-color': codeTextColor,\n        '--n-code-color': codeColor,\n        '--n-code-border': codeBorder\n      }\n    })\n    const themeClassHandle = inlineThemeDisabled\n      ? useThemeClass(\n          'text',\n          computed(() => `${props.type[0]}${props.depth || ''}`),\n          cssVarsRef,\n          props\n        )\n      : undefined\n    return {\n      mergedClsPrefix: mergedClsPrefixRef,\n      compitableTag: useCompitable(props, ['as', 'tag']),\n      cssVars: inlineThemeDisabled ? undefined : cssVarsRef,\n      themeClass: themeClassHandle?.themeClass,\n      onRender: themeClassHandle?.onRender\n    }\n  },\n  render() {\n    const { mergedClsPrefix } = this\n    this.onRender?.()\n    const textClass = [\n      `${mergedClsPrefix}-text`,\n      this.themeClass,\n      {\n        [`${mergedClsPrefix}-text--code`]: this.code,\n        [`${mergedClsPrefix}-text--delete`]: this.delete,\n        [`${mergedClsPrefix}-text--strong`]: this.strong,\n        [`${mergedClsPrefix}-text--italic`]: this.italic,\n        [`${mergedClsPrefix}-text--underline`]: this.underline\n      }\n    ]\n    const children = this.$slots.default?.()\n    return this.code ? (\n      <code class={textClass} style={this.cssVars as CSSProperties}>\n        {this.delete ? <del>{children}</del> : children}\n      </code>\n    ) : this.delete ? (\n      <del class={textClass} style={this.cssVars as CSSProperties}>\n        {children}\n      </del>\n    ) : (\n      h(\n        this.compitableTag || 'span',\n        { class: textClass, style: this.cssVars },\n        children\n      )\n    )\n  }\n})\n"
  },
  {
    "path": "src/typography/src/ul.tsx",
    "content": "import type { CSSProperties } from 'vue'\nimport type { ThemeProps } from '../../_mixins'\nimport type { ExtractPublicPropTypes } from '../../_utils'\nimport type { TypographyTheme } from '../styles'\nimport { computed, defineComponent, h } from 'vue'\nimport { useConfig, useTheme, useThemeClass } from '../../_mixins'\nimport { typographyLight } from '../styles'\nimport style from './styles/list.cssr'\n\nexport const ulProps = {\n  ...(useTheme.props as ThemeProps<TypographyTheme>),\n  alignText: Boolean\n} as const\n\nexport type UlProps = ExtractPublicPropTypes<typeof ulProps>\n\nexport default defineComponent({\n  name: 'Ul',\n  props: ulProps,\n  setup(props) {\n    const { mergedClsPrefixRef, inlineThemeDisabled } = useConfig(props)\n    const themeRef = useTheme(\n      'Typography',\n      '-xl',\n      style,\n      typographyLight,\n      props,\n      mergedClsPrefixRef\n    )\n    const cssVarsRef = computed(() => {\n      const {\n        common: { cubicBezierEaseInOut },\n        self: {\n          olPadding,\n          ulPadding,\n          liMargin,\n          liTextColor,\n          liLineHeight,\n          liFontSize\n        }\n      } = themeRef.value\n      return {\n        '--n-bezier': cubicBezierEaseInOut,\n        '--n-font-size': liFontSize,\n        '--n-line-height': liLineHeight,\n        '--n-text-color': liTextColor,\n        '--n-li-margin': liMargin,\n        '--n-ol-padding': olPadding,\n        '--n-ul-padding': ulPadding\n      }\n    })\n    const themeClassHandle = inlineThemeDisabled\n      ? useThemeClass('ul', undefined, cssVarsRef, props)\n      : undefined\n    return {\n      mergedClsPrefix: mergedClsPrefixRef,\n      cssVars: inlineThemeDisabled ? undefined : cssVarsRef,\n      themeClass: themeClassHandle?.themeClass,\n      onRender: themeClassHandle?.onRender\n    }\n  },\n  render() {\n    const { mergedClsPrefix } = this\n    this.onRender?.()\n    return (\n      <ul\n        class={[\n          `${mergedClsPrefix}-ul`,\n          this.themeClass,\n          this.alignText && `${mergedClsPrefix}-ul--align-text`\n        ]}\n        style={this.cssVars as CSSProperties}\n      >\n        {this.$slots}\n      </ul>\n    )\n  }\n})\n"
  },
  {
    "path": "src/typography/styles/_common.ts",
    "content": "export default {\n  headerFontSize1: '30px',\n  headerFontSize2: '22px',\n  headerFontSize3: '18px',\n  headerFontSize4: '16px',\n  headerFontSize5: '16px',\n  headerFontSize6: '16px',\n  headerMargin1: '28px 0 20px 0',\n  headerMargin2: '28px 0 20px 0',\n  headerMargin3: '28px 0 20px 0',\n  headerMargin4: '28px 0 18px 0',\n  headerMargin5: '28px 0 18px 0',\n  headerMargin6: '28px 0 18px 0',\n  headerPrefixWidth1: '16px',\n  headerPrefixWidth2: '16px',\n  headerPrefixWidth3: '12px',\n  headerPrefixWidth4: '12px',\n  headerPrefixWidth5: '12px',\n  headerPrefixWidth6: '12px',\n  headerBarWidth1: '4px',\n  headerBarWidth2: '4px',\n  headerBarWidth3: '3px',\n  headerBarWidth4: '3px',\n  headerBarWidth5: '3px',\n  headerBarWidth6: '3px',\n  pMargin: '16px 0 16px 0',\n  liMargin: '.25em 0 0 0',\n  olPadding: '0 0 0 2em',\n  ulPadding: '0 0 0 2em'\n}\n"
  },
  {
    "path": "src/typography/styles/dark.ts",
    "content": "import type { TypographyTheme } from './light'\nimport { commonDark } from '../../_styles/common'\nimport { self } from './light'\n\nconst typographyDark: TypographyTheme = {\n  name: 'Typography',\n  common: commonDark,\n  self\n}\n\nexport default typographyDark\n"
  },
  {
    "path": "src/typography/styles/index.ts",
    "content": "export { default as typographyDark } from './dark'\nexport { default as typographyLight } from './light'\nexport type { TypographyTheme, TypographyThemeVars } from './light'\n"
  },
  {
    "path": "src/typography/styles/light.ts",
    "content": "import type { Theme } from '../../_mixins'\nimport type { ThemeCommonVars } from '../../_styles/common'\nimport { commonLight } from '../../_styles/common'\nimport commonVars from './_common'\n\nexport function self(vars: ThemeCommonVars) {\n  const {\n    primaryColor,\n    textColor2,\n    borderColor,\n    lineHeight,\n    fontSize,\n    borderRadiusSmall,\n    dividerColor,\n    fontWeightStrong,\n    textColor1,\n    textColor3,\n    infoColor,\n    warningColor,\n    errorColor,\n    successColor,\n    codeColor\n  } = vars\n  return {\n    ...commonVars,\n    aTextColor: primaryColor,\n    blockquoteTextColor: textColor2,\n    blockquotePrefixColor: borderColor,\n    blockquoteLineHeight: lineHeight,\n    blockquoteFontSize: fontSize,\n    codeBorderRadius: borderRadiusSmall,\n    liTextColor: textColor2,\n    liLineHeight: lineHeight,\n    liFontSize: fontSize,\n    hrColor: dividerColor,\n    headerFontWeight: fontWeightStrong,\n    headerTextColor: textColor1,\n    pTextColor: textColor2,\n    pTextColor1Depth: textColor1,\n    pTextColor2Depth: textColor2,\n    pTextColor3Depth: textColor3,\n    pLineHeight: lineHeight,\n    pFontSize: fontSize,\n    headerBarColor: primaryColor,\n    headerBarColorPrimary: primaryColor,\n    headerBarColorInfo: infoColor,\n    headerBarColorError: errorColor,\n    headerBarColorWarning: warningColor,\n    headerBarColorSuccess: successColor,\n    textColor: textColor2,\n    textColor1Depth: textColor1,\n    textColor2Depth: textColor2,\n    textColor3Depth: textColor3,\n    textColorPrimary: primaryColor,\n    textColorInfo: infoColor,\n    textColorSuccess: successColor,\n    textColorWarning: warningColor,\n    textColorError: errorColor,\n    codeTextColor: textColor2,\n    codeColor,\n    codeBorder: '1px solid #0000'\n  }\n}\n\nexport type TypographyThemeVars = ReturnType<typeof self>\n\nconst typographyLight: Theme<'Typography', TypographyThemeVars> = {\n  name: 'Typography',\n  common: commonLight,\n  self\n}\n\nexport default typographyLight\nexport type TypographyTheme = typeof typographyLight\n"
  },
  {
    "path": "src/typography/tests/Typography.spec.ts",
    "content": "import { mount } from '@vue/test-utils'\nimport { h } from 'vue'\nimport {\n  NA,\n  NBlockquote,\n  NH1,\n  NH2,\n  NH3,\n  NH4,\n  NH5,\n  NH6,\n  NLi,\n  NOl,\n  NP,\n  NText,\n  NUl\n} from '../index'\n\ndescribe('n-a', () => {\n  it('should work with import on demand', () => {\n    mount(NA)\n  })\n\n  it('should work with normal', () => {\n    const wrapper = mount(NA, { props: { href: '/test' } })\n\n    expect(wrapper.find('a').classes()).toContain('n-a')\n    expect(wrapper.find('a').attributes('href')).toBe('/test')\n  })\n})\n\ndescribe('n-text', () => {\n  it('should work with import on demand', () => {\n    mount(NText)\n  })\n\n  it('should work with `type` prop', async () => {\n    const wrapper = mount(NText, { slots: { default: () => 'test' } })\n\n    expect(wrapper.find('.n-text').attributes('style')).toMatchSnapshot()\n\n    await wrapper.setProps({ type: 'info' })\n    expect(wrapper.find('.n-text').attributes('style')).toMatchSnapshot()\n\n    await wrapper.setProps({ type: 'success' })\n    expect(wrapper.find('.n-text').attributes('style')).toMatchSnapshot()\n\n    await wrapper.setProps({ type: 'warning' })\n    expect(wrapper.find('.n-text').attributes('style')).toMatchSnapshot()\n\n    await wrapper.setProps({ type: 'error' })\n    expect(wrapper.find('.n-text').attributes('style')).toMatchSnapshot()\n  })\n\n  it('should work with Font style', () => {\n    let wrapper\n\n    wrapper = mount(NText, {\n      props: { strong: true },\n      slots: { default: () => 'test' }\n    })\n    expect(wrapper.find('.n-text').classes()).toContain('n-text--strong')\n\n    wrapper = mount(NText, {\n      props: { italic: true },\n      slots: { default: () => 'test' }\n    })\n    expect(wrapper.find('.n-text').classes()).toContain('n-text--italic')\n\n    wrapper = mount(NText, {\n      props: { underline: true },\n      slots: { default: () => 'test' }\n    })\n    expect(wrapper.find('.n-text').classes()).toContain('n-text--underline')\n\n    wrapper = mount(NText, {\n      props: { delete: true },\n      slots: { default: () => 'test' }\n    })\n    expect(wrapper.find('.n-text').classes()).toContain('n-text--delete')\n\n    wrapper = mount(NText, {\n      props: { code: true },\n      slots: { default: () => 'test' }\n    })\n    expect(wrapper.find('.n-text').classes()).toContain('n-text--code')\n  })\n\n  it('should work with `depth` prop', async () => {\n    const wrapper = mount(NText, { slots: { default: () => 'test' } })\n\n    expect(wrapper.find('.n-text').attributes('style')).toMatchSnapshot()\n\n    await wrapper.setProps({ depth: '1' })\n    expect(wrapper.find('.n-text').attributes('style')).toMatchSnapshot()\n\n    await wrapper.setProps({ depth: '2' })\n    expect(wrapper.find('.n-text').attributes('style')).toMatchSnapshot()\n\n    await wrapper.setProps({ depth: '3' })\n    expect(wrapper.find('.n-text').attributes('style')).toMatchSnapshot()\n  })\n\n  it('should work with `tag` prop', async () => {\n    const wrapper = mount(NText, {\n      props: { tag: 'div' },\n      slots: { default: () => 'test' }\n    })\n    expect(wrapper.find('.n-text').html()).toContain('test</div>')\n  })\n})\n\ndescribe('n-p', () => {\n  it('should work with import on demand', () => {\n    mount(NP)\n  })\n\n  it('should work with `depth` prop', async () => {\n    const wrapper = mount(NP, { slots: { default: () => 'test' } })\n\n    expect(wrapper.find('p').classes()).toContain('n-p')\n\n    await wrapper.setProps({ depth: '1' })\n    expect(wrapper.find('.n-p').attributes('style')).toMatchSnapshot()\n\n    await wrapper.setProps({ depth: '2' })\n    expect(wrapper.find('.n-p').attributes('style')).toMatchSnapshot()\n\n    await wrapper.setProps({ depth: '3' })\n    expect(wrapper.find('.n-p').attributes('style')).toMatchSnapshot()\n  })\n})\n\ndescribe('n-h1 n-h2 n-h3 n-h4 n-h5 n-h6', () => {\n  it('should work with import on demand', () => {\n    mount(NH1)\n    mount(NH2)\n    mount(NH3)\n    mount(NH4)\n    mount(NH5)\n    mount(NH6)\n  })\n\n  it('should work with normal', async () => {\n    let wrapper: any\n\n    wrapper = mount(NH1, {\n      props: { prefix: 'bar', alignText: true },\n      slots: { default: () => 'test' }\n    })\n    ;(['n-h1', 'n-h--prefix-bar', 'n-h--align-text'] as const).forEach(\n      (item) => {\n        expect(wrapper.find('.n-h').classes()).toContain(item)\n      }\n    )\n    expect(wrapper.find('.n-h').attributes('style')).toMatchSnapshot()\n\n    wrapper = mount(NH2, {\n      props: { prefix: 'bar', alignText: true, type: 'default' },\n      slots: { default: () => 'test' }\n    })\n    ;(['n-h2', 'n-h--prefix-bar', 'n-h--align-text'] as const).forEach(\n      (item) => {\n        expect(wrapper.find('.n-h').classes()).toContain(item)\n      }\n    )\n    expect(wrapper.find('.n-h').attributes('style')).toMatchSnapshot()\n\n    wrapper = mount(NH3, {\n      props: { prefix: 'bar', alignText: true, type: 'success' },\n      slots: { default: () => 'test' }\n    })\n    ;(['n-h3', 'n-h--prefix-bar', 'n-h--align-text'] as const).forEach(\n      (item) => {\n        expect(wrapper.find('.n-h').classes()).toContain(item)\n      }\n    )\n    expect(wrapper.find('.n-h').attributes('style')).toMatchSnapshot()\n\n    wrapper = mount(NH4, {\n      props: { prefix: 'bar', alignText: true, type: 'info' },\n      slots: { default: () => 'test' }\n    })\n    ;(['n-h4', 'n-h--prefix-bar', 'n-h--align-text'] as const).forEach(\n      (item) => {\n        expect(wrapper.find('.n-h').classes()).toContain(item)\n      }\n    )\n    expect(wrapper.find('.n-h').attributes('style')).toMatchSnapshot()\n\n    wrapper = mount(NH5, {\n      props: { prefix: 'bar', alignText: true, type: 'warning' },\n      slots: { default: () => 'test' }\n    })\n    ;(['n-h5', 'n-h--prefix-bar', 'n-h--align-text'] as const).forEach(\n      (item) => {\n        expect(wrapper.find('.n-h').classes()).toContain(item)\n      }\n    )\n    expect(wrapper.find('.n-h').attributes('style')).toMatchSnapshot()\n\n    wrapper = mount(NH6, {\n      props: { prefix: 'bar', alignText: true, type: 'error' },\n      slots: { default: () => 'test' }\n    })\n    ;(['n-h6', 'n-h--prefix-bar', 'n-h--align-text'] as const).forEach(\n      (item) => {\n        expect(wrapper.find('.n-h').classes()).toContain(item)\n      }\n    )\n    expect(wrapper.find('.n-h').attributes('style')).toMatchSnapshot()\n  })\n})\n\ndescribe('n-ul n-ol n-li', () => {\n  it('should work with import on demand', () => {\n    mount(NUl)\n    mount(NOl)\n    mount(NLi)\n  })\n\n  it('should work with normal', () => {\n    let wrapper = mount(NUl, {\n      props: { alignText: true },\n      slots: {\n        default: () =>\n          h(NLi, null, {\n            default: () => 'test'\n          })\n      }\n    })\n    ;(['n-ul', 'n-ul--align-text'] as const).forEach((item) => {\n      expect(wrapper.find('ul').classes()).toContain(item)\n    })\n    expect(wrapper.find('li').text()).toBe('test')\n    expect(wrapper.find('ul').attributes('style')).toMatchSnapshot()\n\n    wrapper = mount(NOl, {\n      props: { alignText: true },\n      slots: {\n        default: () =>\n          h(NLi, null, {\n            default: () => 'test'\n          })\n      }\n    })\n    ;(['n-ol', 'n-ol--align-text'] as const).forEach((item) => {\n      expect(wrapper.find('ol').classes()).toContain(item)\n    })\n    expect(wrapper.find('li').text()).toBe('test')\n    expect(wrapper.find('ol').attributes('style')).toMatchSnapshot()\n  })\n})\n\ndescribe('n-blockquote', () => {\n  it('should work with import on demand', () => {\n    mount(NBlockquote)\n  })\n\n  it('should work with normal', () => {\n    const wrapper = mount(NBlockquote, {\n      props: { alignText: true },\n      slots: { default: () => 'test' }\n    })\n\n    ;(['n-blockquote', 'n-blockquote--align-text'] as const).forEach((item) => {\n      expect(wrapper.find('blockquote').classes()).toContain(item)\n    })\n    expect(wrapper.find('blockquote').attributes('style')).toMatchSnapshot()\n  })\n})\n"
  },
  {
    "path": "src/typography/tests/__snapshots__/Typography.spec.ts.snap",
    "content": "// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html\n\nexports[`n-blockquote > should work with normal 1`] = `\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-font-size: 14px; --n-line-height: 1.6; --n-prefix-color: rgb(224, 224, 230); --n-text-color: rgb(51, 54, 57);\"`;\n\nexports[`n-h1 n-h2 n-h3 n-h4 n-h5 n-h6 > should work with normal 1`] = `\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-font-size: 30px; --n-margin: 28px 0 20px 0; --n-bar-color: #18a058; --n-bar-width: 4px; --n-font-weight: 500; --n-text-color: rgb(31, 34, 37); --n-prefix-width: 16px;\"`;\n\nexports[`n-h1 n-h2 n-h3 n-h4 n-h5 n-h6 > should work with normal 2`] = `\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-font-size: 22px; --n-margin: 28px 0 20px 0; --n-bar-color: #18a058; --n-bar-width: 4px; --n-font-weight: 500; --n-text-color: rgb(31, 34, 37); --n-prefix-width: 16px;\"`;\n\nexports[`n-h1 n-h2 n-h3 n-h4 n-h5 n-h6 > should work with normal 3`] = `\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-font-size: 18px; --n-margin: 28px 0 20px 0; --n-bar-color: #18a058; --n-bar-width: 3px; --n-font-weight: 500; --n-text-color: rgb(31, 34, 37); --n-prefix-width: 12px;\"`;\n\nexports[`n-h1 n-h2 n-h3 n-h4 n-h5 n-h6 > should work with normal 4`] = `\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-font-size: 16px; --n-margin: 28px 0 18px 0; --n-bar-color: #2080f0; --n-bar-width: 3px; --n-font-weight: 500; --n-text-color: rgb(31, 34, 37); --n-prefix-width: 12px;\"`;\n\nexports[`n-h1 n-h2 n-h3 n-h4 n-h5 n-h6 > should work with normal 5`] = `\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-font-size: 16px; --n-margin: 28px 0 18px 0; --n-bar-color: #f0a020; --n-bar-width: 3px; --n-font-weight: 500; --n-text-color: rgb(31, 34, 37); --n-prefix-width: 12px;\"`;\n\nexports[`n-h1 n-h2 n-h3 n-h4 n-h5 n-h6 > should work with normal 6`] = `\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-font-size: 16px; --n-margin: 28px 0 18px 0; --n-bar-color: #d03050; --n-bar-width: 3px; --n-font-weight: 500; --n-text-color: rgb(31, 34, 37); --n-prefix-width: 12px;\"`;\n\nexports[`n-p > should work with \\`depth\\` prop 1`] = `\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-font-size: 14px; --n-line-height: 1.6; --n-margin: 16px 0 16px 0; --n-text-color: rgb(31, 34, 37);\"`;\n\nexports[`n-p > should work with \\`depth\\` prop 2`] = `\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-font-size: 14px; --n-line-height: 1.6; --n-margin: 16px 0 16px 0; --n-text-color: rgb(51, 54, 57);\"`;\n\nexports[`n-p > should work with \\`depth\\` prop 3`] = `\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-font-size: 14px; --n-line-height: 1.6; --n-margin: 16px 0 16px 0; --n-text-color: rgb(118, 124, 130);\"`;\n\nexports[`n-text > should work with \\`depth\\` prop 1`] = `\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-text-color: rgb(51, 54, 57); --n-font-weight-strong: 500; --n-font-famliy-mono: v-mono, SFMono-Regular, Menlo, Consolas, Courier, monospace; --n-code-border-radius: 2px; --n-code-text-color: rgb(51, 54, 57); --n-code-color: rgb(244, 244, 248); --n-code-border: 1px solid #0000;\"`;\n\nexports[`n-text > should work with \\`depth\\` prop 2`] = `\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-text-color: rgb(31, 34, 37); --n-font-weight-strong: 500; --n-font-famliy-mono: v-mono, SFMono-Regular, Menlo, Consolas, Courier, monospace; --n-code-border-radius: 2px; --n-code-text-color: rgb(51, 54, 57); --n-code-color: rgb(244, 244, 248); --n-code-border: 1px solid #0000;\"`;\n\nexports[`n-text > should work with \\`depth\\` prop 3`] = `\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-text-color: rgb(51, 54, 57); --n-font-weight-strong: 500; --n-font-famliy-mono: v-mono, SFMono-Regular, Menlo, Consolas, Courier, monospace; --n-code-border-radius: 2px; --n-code-text-color: rgb(51, 54, 57); --n-code-color: rgb(244, 244, 248); --n-code-border: 1px solid #0000;\"`;\n\nexports[`n-text > should work with \\`depth\\` prop 4`] = `\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-text-color: rgb(118, 124, 130); --n-font-weight-strong: 500; --n-font-famliy-mono: v-mono, SFMono-Regular, Menlo, Consolas, Courier, monospace; --n-code-border-radius: 2px; --n-code-text-color: rgb(51, 54, 57); --n-code-color: rgb(244, 244, 248); --n-code-border: 1px solid #0000;\"`;\n\nexports[`n-text > should work with \\`type\\` prop 1`] = `\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-text-color: rgb(51, 54, 57); --n-font-weight-strong: 500; --n-font-famliy-mono: v-mono, SFMono-Regular, Menlo, Consolas, Courier, monospace; --n-code-border-radius: 2px; --n-code-text-color: rgb(51, 54, 57); --n-code-color: rgb(244, 244, 248); --n-code-border: 1px solid #0000;\"`;\n\nexports[`n-text > should work with \\`type\\` prop 2`] = `\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-text-color: #2080f0; --n-font-weight-strong: 500; --n-font-famliy-mono: v-mono, SFMono-Regular, Menlo, Consolas, Courier, monospace; --n-code-border-radius: 2px; --n-code-text-color: rgb(51, 54, 57); --n-code-color: rgb(244, 244, 248); --n-code-border: 1px solid #0000;\"`;\n\nexports[`n-text > should work with \\`type\\` prop 3`] = `\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-text-color: #18a058; --n-font-weight-strong: 500; --n-font-famliy-mono: v-mono, SFMono-Regular, Menlo, Consolas, Courier, monospace; --n-code-border-radius: 2px; --n-code-text-color: rgb(51, 54, 57); --n-code-color: rgb(244, 244, 248); --n-code-border: 1px solid #0000;\"`;\n\nexports[`n-text > should work with \\`type\\` prop 4`] = `\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-text-color: #f0a020; --n-font-weight-strong: 500; --n-font-famliy-mono: v-mono, SFMono-Regular, Menlo, Consolas, Courier, monospace; --n-code-border-radius: 2px; --n-code-text-color: rgb(51, 54, 57); --n-code-color: rgb(244, 244, 248); --n-code-border: 1px solid #0000;\"`;\n\nexports[`n-text > should work with \\`type\\` prop 5`] = `\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-text-color: #d03050; --n-font-weight-strong: 500; --n-font-famliy-mono: v-mono, SFMono-Regular, Menlo, Consolas, Courier, monospace; --n-code-border-radius: 2px; --n-code-text-color: rgb(51, 54, 57); --n-code-color: rgb(244, 244, 248); --n-code-border: 1px solid #0000;\"`;\n\nexports[`n-ul n-ol n-li > should work with normal 1`] = `\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-font-size: 14px; --n-line-height: 1.6; --n-text-color: rgb(51, 54, 57); --n-li-margin: .25em 0 0 0; --n-ol-padding: 0 0 0 2em; --n-ul-padding: 0 0 0 2em;\"`;\n\nexports[`n-ul n-ol n-li > should work with normal 2`] = `\"--n-bezier: cubic-bezier(.4, 0, .2, 1); --n-font-size: 14px; --n-line-height: 1.6; --n-text-color: rgb(51, 54, 57); --n-li-margin: .25em 0 0 0; --n-ol-padding: 0 0 0 2em; --n-ul-padding: 0 0 0 2em;\"`;\n"
  },
  {
    "path": "src/typography/tests/server.spec.tsx",
    "content": "import { setup } from '@css-render/vue3-ssr'\nimport { renderToString } from '@vue/server-renderer'\n/**\n * @vitest-environment node\n */\nimport { createSSRApp, h } from 'vue'\nimport { NText } from '../..'\n\ndescribe('server side rendering', () => {\n  it('works', async () => {\n    const app = createSSRApp(() => <NText />)\n    setup(app)\n    try {\n      await renderToString(app)\n    }\n    catch (e) {\n      expect(e).not.toBeTruthy()\n    }\n  })\n})\n"
  },
  {
    "path": "src/upload/demos/enUS/abstract.demo.vue",
    "content": "<markdown>\n# Split trigger and list\n\nNote: `n-upload-trigger` and `n-upload-file-list` must be children of `<n-upload />`.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { UploadFileInfo } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst fileListRef = ref<UploadFileInfo[]>([\n  {\n    id: 'b',\n    name: 'file.doc',\n    status: 'finished',\n    type: 'text/plain'\n  }\n])\n\nconst fileList = fileListRef\n</script>\n\n<template>\n  <n-upload\n    abstract\n    :default-file-list=\"fileList\"\n    action=\"__HTTP__://www.mocky.io/v2/5e4bafc63100007100d8b70f\"\n  >\n    <n-button-group>\n      <n-button>Useless</n-button>\n      <n-upload-trigger #=\"{ handleClick }\" abstract>\n        <n-button @click=\"handleClick\">\n          Upload\n        </n-button>\n      </n-upload-trigger>\n    </n-button-group>\n    <n-card style=\"margin-top: 12px\" title=\"File List\">\n      <n-upload-file-list />\n    </n-card>\n  </n-upload>\n</template>\n"
  },
  {
    "path": "src/upload/demos/enUS/basic.demo.vue",
    "content": "<markdown>\n# Basic\n</markdown>\n\n<template>\n  <n-upload\n    action=\"__HTTP__://www.mocky.io/v2/5e4bafc63100007100d8b70f\"\n    :headers=\"{\n      'naive-info': 'hello!',\n    }\"\n    :data=\"{\n      'naive-data': 'cool! naive!',\n    }\"\n  >\n    <n-button>Upload File</n-button>\n  </n-upload>\n</template>\n"
  },
  {
    "path": "src/upload/demos/enUS/before-upload.demo.vue",
    "content": "<markdown>\n# Before upload hook\n\nUse `before-upload` to perform a function before the upload starts (e.g. cancel the upload).\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { UploadFileInfo } from 'naive-ui'\nimport { useMessage } from 'naive-ui'\n\nconst message = useMessage()\n\nasync function beforeUpload(data: {\n  file: UploadFileInfo\n  fileList: UploadFileInfo[]\n}) {\n  if (data.file.file?.type !== 'image/png') {\n    message.error('Only upload picture files in png format, please re-upload.')\n    return false\n  }\n  return true\n}\n</script>\n\n<template>\n  <n-upload\n    action=\"__HTTP__://www.mocky.io/v2/5e4bafc63100007100d8b70f\"\n    @before-upload=\"beforeUpload\"\n  >\n    <n-button>Upload PNG</n-button>\n  </n-upload>\n</template>\n"
  },
  {
    "path": "src/upload/demos/enUS/controlled.demo.vue",
    "content": "<markdown>\n# Autogenerated file list\n\nThis example is just a joke.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { UploadFileInfo } from 'naive-ui'\nimport { useMessage } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst message = useMessage()\nconst fileListRef = ref<UploadFileInfo[]>([\n  {\n    id: 'url-test',\n    name: 'URL Test',\n    url: '__HTTP__://www.mocky.io/v2/5e4bafc63100007100d8b70f',\n    status: 'finished'\n  },\n  {\n    id: 'text-message',\n    name: 'Your text messages',\n    status: 'error'\n  },\n  {\n    id: 'notification',\n    name: 'You notifications',\n    status: 'finished'\n  },\n  {\n    id: 'contact',\n    name: 'You contact info',\n    status: 'finished'\n  }\n])\n\nconst fileList = fileListRef\n\nfunction handleUploadChange(data: { fileList: UploadFileInfo[] }) {\n  fileListRef.value = data.fileList\n}\n\nfunction handleRemove(data: {\n  file: UploadFileInfo\n  fileList: UploadFileInfo[]\n}) {\n  if (data.file.id === 'text-message') {\n    message.info('Oops... It\\'s now uploaded. Okay, delete it.')\n  }\n  else if (data.file.id === 'notification') {\n    message.error('No, this is useful for us. Removal not allowed.')\n    return false\n  }\n  else if (data.file.id === 'contact') {\n    message.loading(\n      'Don\\' know whether it is useful for us, let me ask the server',\n      {\n        duration: 4000\n      }\n    )\n    return new Promise((resolve) => {\n      setTimeout(() => {\n        message.error('Oh no, they said you can\\'t delete it too!')\n        resolve(false)\n      }, 4000)\n    })\n  }\n}\n\nfunction handleFileListChange() {\n  message.info('Yes, file-list changed.')\n}\n</script>\n\n<template>\n  <n-upload\n    v-model:file-list=\"fileList\"\n    action=\"__HTTP__://www.mocky.io/v2/5e4bafc63100007100d8b70f\"\n    @update:file-list=\"handleFileListChange\"\n    @change=\"handleUploadChange\"\n    @remove=\"handleRemove\"\n  >\n    <n-button>Upload File</n-button>\n  </n-upload>\n</template>\n"
  },
  {
    "path": "src/upload/demos/enUS/custom-download.demo.vue",
    "content": "<markdown>\n# Custom download\n\nUse `custom-download` to customize file downloading.\n\nBy default, naive-ui uses native download logic (which initiates downloading by perform a click on an `<a />` element with correspoding URL).\n\nHowever, you may want to preform custom download logic for example in a cross origin downloading process.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { UploadFileInfo } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst fileList = ref<UploadFileInfo[]>([\n  {\n    id: 'c',\n    name: 'custom-Download.png',\n    status: 'finished',\n    url: 'https://avatars.githubusercontent.com/u/20943608?s=60&v=4'\n  }\n])\n\nfunction handleCustomDownload(file: UploadFileInfo) {\n  const { url, name } = file\n  if (!url)\n    return\n  fetch(url)\n    .then(response => response.blob())\n    .then((blob) => {\n      const blobUrl = URL.createObjectURL(new Blob([blob]))\n      const link = document.createElement('a')\n      link.href = blobUrl\n      if (name) {\n        link.download = name\n      }\n      document.body.appendChild(link)\n      link.click()\n      URL.revokeObjectURL(blobUrl)\n      link.remove()\n    })\n}\n</script>\n\n<template>\n  <n-upload\n    action=\"http://www.mocky.io/v2/5e4bafc63100007100d8b70f\"\n    :default-file-list=\"fileList\"\n    list-type=\"image\"\n    show-download-button\n    :custom-download=\"handleCustomDownload\"\n  >\n    <n-button>Upload</n-button>\n  </n-upload>\n</template>\n"
  },
  {
    "path": "src/upload/demos/enUS/custom-request.demo.vue",
    "content": "<markdown>\n# Custom request\n\nUser `custom-request` to customize upload request.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { UploadCustomRequestOptions } from 'naive-ui'\nimport { lyla } from '@lylajs/web'\nimport { useMessage } from 'naive-ui'\n\nconst message = useMessage()\nfunction customRequest({\n  file,\n  data,\n  headers,\n  withCredentials,\n  action,\n  onFinish,\n  onError,\n  onProgress\n}: UploadCustomRequestOptions) {\n  const formData = new FormData()\n  if (data) {\n    Object.keys(data).forEach((key) => {\n      formData.append(\n        key,\n        data[key as keyof UploadCustomRequestOptions['data']]\n      )\n    })\n  }\n  formData.append(file.name, file.file as File)\n  lyla\n    .post(action as string, {\n      withCredentials,\n      headers: headers as Record<string, string>,\n      body: formData,\n      onUploadProgress: ({ percent }) => {\n        onProgress({ percent: Math.ceil(percent) })\n      }\n    })\n    .then(({ json }) => {\n      message.success(JSON.stringify(json))\n      onFinish()\n    })\n    .catch((error) => {\n      message.success(error.message)\n      onError()\n    })\n}\n</script>\n\n<template>\n  <n-upload\n    action=\"__HTTP__://naive-upload.free.beeceptor.com/\"\n    :headers=\"{\n      'naive-info': 'hello!',\n    }\"\n    :data=\"{\n      'naive-data': 'cool! naive!',\n    }\"\n    :custom-request=\"customRequest\"\n  >\n    <n-button>Upload</n-button>\n  </n-upload>\n</template>\n"
  },
  {
    "path": "src/upload/demos/enUS/default-files.demo.vue",
    "content": "<markdown>\n# Default file list\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { UploadFileInfo } from 'naive-ui'\n\nconst defaultFileList: UploadFileInfo[] = [\n  {\n    id: 'the',\n    name: 'The',\n    status: 'finished'\n  },\n  {\n    id: 'razars',\n    name: 'Razars\\'s',\n    status: 'finished'\n  },\n  {\n    id: 'edge',\n    name: 'Blade',\n    status: 'finished'\n  }\n]\n</script>\n\n<template>\n  <n-upload\n    action=\"__HTTP__://www.mocky.io/v2/5e4bafc63100007100d8b70f\"\n    :default-file-list=\"defaultFileList\"\n  >\n    <n-button>Upload File</n-button>\n  </n-upload>\n</template>\n"
  },
  {
    "path": "src/upload/demos/enUS/download.demo.vue",
    "content": "<markdown>\n# Download when finished\n\nset `show-download-button` to show download button. set `on-download` to provide a handler function when download button clicked.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { UploadFileInfo } from 'naive-ui'\nimport { useMessage } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst message = useMessage()\nconst fileListRef = ref<UploadFileInfo[]>([\n  {\n    id: 'a',\n    name: 'My Fault.png',\n    status: 'error'\n  },\n  {\n    id: 'c',\n    name: 'Finished you can dowload.png',\n    status: 'finished',\n    url: '__HTTP__://07akioni.oss-cn-beijing.aliyuncs.com/07akioni.jpeg'\n  },\n  {\n    id: 'd',\n    name: 'Waiting for the finish .doc',\n    status: 'uploading',\n    percentage: 50\n  }\n])\n\nconst fileList = fileListRef\n\nfunction handleDownload(file: UploadFileInfo) {\n  message.success(`success：${file.name}`)\n}\n</script>\n\n<template>\n  <n-upload\n    action=\"__HTTP__://www.mocky.io/v2/5e4bafc63100007100d8b70f\"\n    :default-file-list=\"fileList\"\n    list-type=\"image\"\n    show-download-button\n    @download=\"handleDownload\"\n  >\n    <n-button>Upload</n-button>\n  </n-upload>\n</template>\n"
  },
  {
    "path": "src/upload/demos/enUS/drag.demo.vue",
    "content": "<markdown>\n# Drag to upload\n\nYou can set `directory-dnd` to `true` to make directory drag and drop available.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ArchiveOutline as ArchiveIcon } from '@vicons/ionicons5'\n</script>\n\n<template>\n  <n-upload\n    multiple\n    directory-dnd\n    action=\"__HTTP__://www.mocky.io/v2/5e4bafc63100007100d8b70f\"\n    :max=\"5\"\n  >\n    <n-upload-dragger>\n      <div style=\"margin-bottom: 12px\">\n        <n-icon size=\"48\" :depth=\"3\">\n          <ArchiveIcon />\n        </n-icon>\n      </div>\n      <n-text style=\"font-size: 16px\">\n        Click or drag a file to this area to upload\n      </n-text>\n      <n-p depth=\"3\" style=\"margin: 8px 0 0 0\">\n        Strictly prohibit from uploading sensitive information. For example,\n        your bank card PIN or your credit card expiry date.\n      </n-p>\n    </n-upload-dragger>\n  </n-upload>\n</template>\n"
  },
  {
    "path": "src/upload/demos/enUS/image-card-style.demo.vue",
    "content": "<markdown>\n# Pictures wall\n\nBy default, this will use Naive UI's internal preview component. You can also use `on-preview` to customize what to do when previewing a file.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { UploadFileInfo } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst showModalRef = ref(false)\nconst previewImageUrlRef = ref('')\n\nfunction handlePreview(file: UploadFileInfo) {\n  const { url } = file\n  previewImageUrlRef.value = url as string\n  showModalRef.value = true\n}\n\nconst showModal = showModalRef\nconst previewImageUrl = previewImageUrlRef\n\nconst fileList = ref<UploadFileInfo[]>([\n  {\n    id: 'a',\n    name: '我是上传出错的普通文件.png',\n    status: 'error'\n  },\n  {\n    id: 'b',\n    name: '我是普通文本.doc',\n    status: 'finished',\n    type: 'text/plain'\n  },\n  {\n    id: 'c',\n    name: '我是自带url的图片.png',\n    status: 'finished',\n    url: '__HTTP__://07akioni.oss-cn-beijing.aliyuncs.com/07akioni.jpeg'\n  },\n  {\n    id: 'd',\n    name: '我是上传进度99%的文本.doc',\n    status: 'uploading',\n    percentage: 99\n  }\n])\n\nconst previewFileList = ref<UploadFileInfo[]>([\n  {\n    id: 'react',\n    name: '我是react.png',\n    status: 'finished',\n    url: '__HTTP__://07akioni.oss-cn-beijing.aliyuncs.com/07akioni.jpeg'\n  },\n  {\n    id: 'vue',\n    name: '我是vue.png',\n    status: 'finished',\n    url: '__HTTP__://07akioni.oss-cn-beijing.aliyuncs.com/07akioni.jpeg'\n  }\n])\n</script>\n\n<template>\n  <n-upload\n    action=\"__HTTP__://www.mocky.io/v2/5e4bafc63100007100d8b70f\"\n    :default-file-list=\"fileList\"\n    list-type=\"image-card\"\n  >\n    Click to Upload\n  </n-upload>\n  <n-divider />\n  <n-upload\n    action=\"__HTTP__://www.mocky.io/v2/5e4bafc63100007100d8b70f\"\n    :default-file-list=\"previewFileList\"\n    list-type=\"image-card\"\n    @preview=\"handlePreview\"\n  />\n  <n-modal\n    v-model:show=\"showModal\"\n    preset=\"card\"\n    style=\"width: 600px\"\n    title=\"A Cool Picture\"\n  >\n    <img :src=\"previewImageUrl\" style=\"width: 100%\">\n  </n-modal>\n</template>\n"
  },
  {
    "path": "src/upload/demos/enUS/image-style.demo.vue",
    "content": "<markdown>\n# Thumbnail file list\n\nThumbnails can be created using your own custom method via the `create-thumbnail-url` property.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { UploadFileInfo } from 'naive-ui'\nimport { useMessage } from 'naive-ui'\nimport { h, ref } from 'vue'\n\nconst message = useMessage()\nconst fileListRef = ref<UploadFileInfo[]>([\n  {\n    id: 'a',\n    name: 'My Fault.png',\n    status: 'error'\n  },\n  {\n    id: 'b',\n    name: 'regular text.doc',\n    status: 'finished',\n    type: 'text/plain'\n  },\n  {\n    id: 'c',\n    name: 'image.png',\n    status: 'finished',\n    url: '__HTTP__://07akioni.oss-cn-beijing.aliyuncs.com/07akioni.jpeg'\n  },\n  {\n    id: 'd',\n    name: 'Not Finished Yet.doc',\n    status: 'uploading',\n    percentage: 50\n  }\n])\n\nconst fileList = fileListRef\n\nfunction createThumbnailUrl(file: File | null): Promise<string> | undefined {\n  if (!file)\n    return undefined\n  message.info(() => [\n    '`createThumbnailUrl` changes the thumbnail image of the uploaded file.',\n    h('br'),\n    'It will be 07akioni whatever you upload.',\n    file.name\n  ])\n  message.info(`${file.name}`)\n  return new Promise((resolve) => {\n    setTimeout(() => {\n      resolve('__HTTP__://07akioni.oss-cn-beijing.aliyuncs.com/07akioni.jpeg')\n    }, 1000)\n  })\n}\n</script>\n\n<template>\n  <n-upload\n    action=\"__HTTP__://www.mocky.io/v2/5e4bafc63100007100d8b70f\"\n    :default-file-list=\"fileList\"\n    list-type=\"image\"\n    :create-thumbnail-url=\"createThumbnailUrl\"\n  >\n    <n-button>Upload</n-button>\n  </n-upload>\n</template>\n"
  },
  {
    "path": "src/upload/demos/enUS/index.demo-entry.md",
    "content": "# Upload\n\nIf latency didn't matter, I'd just fill trucks with hard disks.\n\n## Demos\n\n```demo\nbasic.vue\ndrag.vue\nsubmit-manually.vue\ncontrolled.vue\non-finish.vue\ndefault-files.vue\nbefore-upload.vue\nimage-style.vue\nimage-card-style.vue\ncustom-request.vue\ncustom-download.vue\nabstract.vue\ndownload.vue\n```\n\n## API\n\n### Upload Props\n\n| Name | Type | Default | Description | Version |\n| --- | --- | --- | --- | --- |\n| abstract | `boolean` | `false` | Whether or not DOM wrapping does not exist. Not supported for `image-card` type. |  |\n| accept | `string` | `undefined` | The accept type of upload. See <n-a href=\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/file#accept\" target=\"_blank\">accept</n-a>. |  |\n| action | `string` | `undefined` | The URL to submit data to. |  |\n| create-thumbnail-url | `(file: File \\| null, fileInfo: UploadSettledFileInfo) => (Promise<string> \\| string \\| undefined)` | `undefined` | Customize file thumbnails. If `undefined` is returned, the file would use default thumbnail display logic. | `fileInfo` 2.34.0 |\n| custom-request | `(options: UploadCustomRequestOptions) => void` | `undefined` | Customize upload request. For types, see <n-a href=\"#UploadCustomRequestOptions-Type\">UploadCustomRequestOptions</n-a> |  |\n| custom-download | `(file: FileInfo) => void` | `undefined` | Customize download request | 2.41.1 |\n| data | `Object \\| ({ file: UploadFileInfo }) => Object` | `undefined` | The additional fileds data of HTTP request's form data. |  |\n| default-file-list | `Array<UploadFileInfo>` | `[]` | The default file list in uncontrolled manner. |  |\n| default-upload | `boolean` | `true` | If file uploaded immediately after file is selected. |  |\n| directory | `boolean` | `false` | Whether to allow directory upload. (In open file dialog only directory can be selected) | 2.28.3 |\n| directory-dnd | `boolean` | `false` | Whether to allow directory drag and drop. (If it's not set, it will follow `directory` prop by default.) | 2.28.3 |\n| disabled | `boolean` | `false` | Whether to disable the upload. |  |\n| file-list-class | `string` | `undefined` | The class of file list area | 2.36.0 |\n| file-list-style | `Object` | `undefined` | The style of file list area |  |\n| file-list | `Array<UploadFileInfo>` | `undefined` | The file list of component. If set, the component will work in controlled manner. |  |\n| headers | `Object \\| ({ file: UploadFileInfo }) => Object` | `undefined` | The additional HTTP Headers of request. |  |\n| input-props | `InputHTMLAttributes` | `undefined` | Attributes of file input. | 2.24.2 |\n| image-group-props | `ImageGroupProps` | `undefined` | Props of `n-image` inside upload. See [ImageGroup Props](image#ImageGroup-Props). | 2.24.0 |\n| is-error-state | `(xhr: XMLHttpRequest) => boolean` | `undefined` | Check if response is error state. | 2.29.1 |\n| list-type | `string` | `'text'` | Built-in styles for file lists, `text`, `image` and `image-card`. |  |\n| max | `number` | `undefined` | Uploaded files limit. |  |\n| method | `string` | `'POST'` | The HTTP request method. |  |\n| multiple | `boolean` | `false` | Allow multiple files to be selected. |  |\n| name | `string` | `'file'` | The field name for the file(s) in the HTTP request's form data. |  |\n| render-icon | `(file: UploadSettledFileInfo) => VNodeChild` | `undefined` | Render function of file icon. It only works when `list-type=\"image\"` or `list-type=\"image-card\"`. | 2.34.0 |\n| response-type | `'' \\| 'arraybuffer' \\| 'blob' \\| 'document' \\| 'json' \\| 'text'` | `''` | Response type of `XMLHttpRequest` used by `n-upload` | 2.33.3 |\n| should-use-thumbnail-url | `(file: UploadSettledFileInfo) => boolean` | A function that only returns `true` for image typed file. | A function that determines whether to show thumbnail for the file. It only works when `list-type=\"image\"` or `list-type=\"image-card\"`. | 2.34.0 |\n| show-cancel-button | `boolean` | `true` | Show a cancel button (while uploading). Use the `on-remove` callback for this event. |  |\n| show-download-button | `boolean` | `false` | Show a download button (after upload is finished). |  |\n| show-file-list | `boolean` | `true` | Show a file list. |  |\n| show-preview-button | `boolean` | `true` | Show a preview button (when `list-type` is `image-card`). Use the `on-preview` callback for this event. |  |\n| show-remove-button | `boolean` | `true` | Show a remove button (after upload completed). Use the `on-remove` callback for this event. |  |\n| show-retry-button | `boolean` | `true` | Show a retry button (for a failed upload). |  |\n| show-trigger | `boolean` | `true` | Show upload trigger. | 2.21.5 |\n| trigger-class | `string` | `undefined` | Class of trigger area. | 2.36.0 |\n| trigger-style | `Object \\| string` | `undefined` | Style of trigger area. | 2.29.1 |\n| with-credentials | `boolean` | `false` | Any credentials to be sent with the request (e.g. cookie). |  |\n| on-change | `(options: { file: UploadFileInfo, fileList: Array<UploadFileInfo>, event?: Event }) => void` | `undefined` | Uploaded file(s) status change callback. |  |\n| on-error | `(options: { file: UploadFileInfo, event?: ProgressEvent }) => UploadFileInfo \\| void` | `undefined` | Upload failed callback. | 2.24.0 |\n| on-finish | `(options: { file: UploadFileInfo, event?: Event }) => UploadFileInfo \\| undefined` | `({ file }) => file` | Upload finished callback. You can intercept and even modify the uploaded `UploadFileInfo`. Note: file will be null in next event-loop |  |\n| on-before-upload | `(options: { file: UploadFileInfo, fileList: Array<UploadFileInfo> }) => (Promise<boolean \\| void> \\| boolean \\| void)` | `true` | Upload ready to start callback. Returning `false`, a promise resolved with `false`, or a rejected promise will cancel the upload. |  |\n| on-download | `(file: FileInfo) => Promise<boolean> \\| boolean \\| any` | `undefined` | Callback for clicking download buttons. Returning `false`, `Promise resolve false`, `Promise rejected` will cancel the download. |  |\n| on-preview | `(file: FileInfo, detail: { event: MouseEvent }) => void` | `undefined` | Callback for clicking file links or preview buttons. You can use `preventDefault` to prevent default anchor link open behavior. | `detail.event` 2.39.0 |\n| on-remove | `(options: { file: UploadFileInfo, fileList: Array<UploadFileInfo>, index: number }) => Promise<boolean> \\| boolean \\| any` | `() => true` | File removed callback. Returning `false`, a promise resolved with `false`, or a rejected promise will cancel this removal. | `index` 2.38.2 |\n| on-retry | `(options: { file: UploadFileInfo }) => (Promise<boolean \\| void> \\| boolean \\| void)` | `undefined` | Click retry callback function. Returning `false`, a promise resolved with `false`, or a rejected promise will cancel the retry. | 2.40.0 |\n| on-update:file-list | `(fileList: UploadFileInfo[]) => void` | `undefined` | Callback function triggered on file-list changes. |  |\n\n#### UploadFileInfo Type\n\n| Property | Type | Description | Version |\n| --- | --- | --- | --- |\n| id | `string \\| number` | Unique file ID. Please note that do not change it, if you need to save some corresponding data, you can use a Map object outside component. |  |\n| name | `string` | Filename. |  |\n| status | `'pending' \\| 'uploading' \\| 'error' \\| 'finished' \\| 'removed'` | The status of file. |  |\n| batchId? | `string \\| null` | Batch id of uploaded file. The files selected in a same upload batch will have same `batchId`. | 2.28.3 |\n| file? | `File \\| null` | The object of the file stored in the browser. |  |\n| fullPath? | `string \\| null` | Relative path of uploaded file. | 2.28.3 |\n| percentage? | `number` | The progress percentage of the file being uploaded. |  |\n| thumbnailUrl? | `string \\| null` | Thumbnail URL. |  |\n| type? | `string \\| null` | MIME type. |  |\n| url? | `string \\| null` | File URL. |  |\n\n### UploadTrigger Props\n\n| Name     | Type      | Default | Description                                |\n| -------- | --------- | ------- | ------------------------------------------ |\n| abstract | `boolean` | `false` | Whether or not to use the `abstract` mode. |\n\n#### UploadCustomRequestOptions Type\n\n```__ts\ninterface UploadCustomRequestOptions {\n  file: FileInfo\n  action?: string\n  data?:\n    | Record<string, string>\n    | (({ file }: { file: FileInfo }) => Record<string, string>)\n  withCredentials?: boolean\n  headers?:\n    | Record<string, string>\n    | (({ file }: { file: FileInfo }) => Record<string, string>)\n  onProgress: (e: { percent: number }) => void\n  onFinish: () => void\n  onError: () => void\n}\n```\n\n### Upload Methods\n\n| Name | Type | Description | Version |\n| --- | --- | --- | --- |\n| clear | `() => void` | Clear current upload list. | 2.24.2 |\n| openOpenFileDialog | `() => void` | Open the file dialog window. |  |\n| submit | `(options?: { fileId?: string, retry?: boolean })` | Submit all files with pending status. | `retry`: `2.44.0` |\n\n### Upload Slots\n\n| Name    | Parameters | Description                |\n| ------- | ---------- | -------------------------- |\n| default | `()`       | The content of the upload. |\n\n### UploadDragger Slots\n\n| Name | Parameters | Description |\n| --- | --- | --- |\n| default | `()` | The placeholder of the upload dragger; For an example see <n-a href=\"#drag.vue\">Drag to Upload Demo</n-a>. |\n\n### UploadTrigger Slots\n\n| Name | Parameters | Description |\n| --- | --- | --- |\n| default | `(options: { handleClick: () => void, handleDragOver: (e: DragEvent) => void, handleDragEnter: (e: DragEvent) => void, handleDragLeave: (e: DragEvent) => void, handleDrop: (e: DragEvent) => void})` | `handleClick` is the click upload function, `handleDrop` is the drag and drop upload function, `handleDragEnter`, `handleDragOver` and `handleDragLeave` are the drag and drop event functions. |\n\n### Others\n\n1. `uploadDownload`, with type of `(url: string, name: string | undefined): void`, you can import the method directly from naive-ui.\n"
  },
  {
    "path": "src/upload/demos/enUS/on-finish.demo.vue",
    "content": "<markdown>\n# Change file on finish\n\nYou can change a file's properties after its upload has finished.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { UploadFileInfo } from 'naive-ui'\nimport { useMessage } from 'naive-ui'\n\nconst message = useMessage()\n\nfunction handleFinish({\n  file,\n  event\n}: {\n  file: UploadFileInfo\n  event?: ProgressEvent\n}) {\n  message.success((event?.target as XMLHttpRequest).response)\n  const ext = file.name.split('.')[1]\n  file.name = `renamed.${ext}`\n  file.url = '__HTTP__://www.mocky.io/v2/5e4bafc63100007100d8b70f'\n  return file\n}\n</script>\n\n<template>\n  <n-upload\n    action=\"__HTTP__://www.mocky.io/v2/5e4bafc63100007100d8b70f\"\n    @finish=\"handleFinish\"\n  >\n    <n-button>Upload</n-button>\n  </n-upload>\n</template>\n"
  },
  {
    "path": "src/upload/demos/enUS/submit-manually.demo.vue",
    "content": "<markdown>\n# Uncontrolled manually submit\n\nYou can use a `ref` to get a handle on files uploaded, and the `submit` method to submit them when you're ready.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { UploadFileInfo, UploadInst } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst fileListLengthRef = ref(0)\nconst uploadRef = ref<UploadInst | null>(null)\n\nconst fileListLength = fileListLengthRef\n\nfunction handleChange(data: { fileList: UploadFileInfo[] }) {\n  fileListLengthRef.value = data.fileList.length\n}\n\nfunction handleClick() {\n  uploadRef.value?.submit()\n}\n</script>\n\n<template>\n  <n-button\n    :disabled=\"!fileListLength\"\n    style=\"margin-bottom: 12px\"\n    @click=\"handleClick\"\n  >\n    Upload File\n  </n-button>\n  <n-upload\n    ref=\"uploadRef\"\n    action=\"__HTTP__://www.mocky.io/v2/5e4bafc63100007100d8b70f\"\n    :default-upload=\"false\"\n    multiple\n    @change=\"handleChange\"\n  >\n    <n-button>Select File</n-button>\n  </n-upload>\n</template>\n"
  },
  {
    "path": "src/upload/demos/zhCN/abstract.demo.vue",
    "content": "<markdown>\n# 拆分触发器和列表\n\n`n-upload-trigger`和 `n-upload-file-list` 需在 `n-upload` 内调用。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { UploadFileInfo } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst fileListRef = ref<UploadFileInfo[]>([\n  {\n    id: 'b',\n    name: 'file.doc',\n    status: 'finished',\n    type: 'text/plain'\n  }\n])\n\nconst fileList = fileListRef\n</script>\n\n<template>\n  <n-upload\n    abstract\n    :default-file-list=\"fileList\"\n    action=\"__HTTP__://www.mocky.io/v2/5e4bafc63100007100d8b70f\"\n  >\n    <n-button-group>\n      <n-button>点我没用</n-button>\n      <n-upload-trigger #=\"{ handleClick }\" abstract>\n        <n-button @click=\"handleClick\">\n          上传\n        </n-button>\n      </n-upload-trigger>\n    </n-button-group>\n    <n-card style=\"margin-top: 12px\" title=\"文件列表\">\n      <n-upload-file-list />\n    </n-card>\n  </n-upload>\n</template>\n"
  },
  {
    "path": "src/upload/demos/zhCN/basic.demo.vue",
    "content": "<markdown>\n# 基础用法\n</markdown>\n\n<template>\n  <n-upload\n    action=\"__HTTP__://www.mocky.io/v2/5e4bafc63100007100d8b70f\"\n    :headers=\"{\n      'naive-info': 'hello!',\n    }\"\n    :data=\"{\n      'naive-data': 'cool! naive!',\n    }\"\n  >\n    <n-button>上传文件</n-button>\n  </n-upload>\n</template>\n"
  },
  {
    "path": "src/upload/demos/zhCN/before-upload.demo.vue",
    "content": "<markdown>\n# 限制上传文件\n\n使用 `before-upload` 限制上传。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { UploadFileInfo } from 'naive-ui'\nimport { useMessage } from 'naive-ui'\n\nconst message = useMessage()\n\nasync function beforeUpload(data: {\n  file: UploadFileInfo\n  fileList: UploadFileInfo[]\n}) {\n  if (data.file.file?.type !== 'image/png') {\n    message.error('只能上传png格式的图片文件，请重新上传')\n    return false\n  }\n  return true\n}\n</script>\n\n<template>\n  <n-upload\n    action=\"__HTTP__://www.mocky.io/v2/5e4bafc63100007100d8b70f\"\n    @before-upload=\"beforeUpload\"\n  >\n    <n-button>上传 PNG 文件</n-button>\n  </n-upload>\n</template>\n"
  },
  {
    "path": "src/upload/demos/zhCN/controlled.demo.vue",
    "content": "<markdown>\n# 受控的文件列表\n\n下面的例子纯属玩笑。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { UploadFileInfo } from 'naive-ui'\nimport { useMessage } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst message = useMessage()\nconst fileListRef = ref<UploadFileInfo[]>([\n  {\n    id: 'url-test',\n    name: 'URL 测试',\n    url: '__HTTP__://www.mocky.io/v2/5e4bafc63100007100d8b70f',\n    status: 'finished'\n  },\n  {\n    id: 'text-message',\n    name: '你的短信',\n    status: 'error'\n  },\n  {\n    id: 'notification',\n    name: '你的通知',\n    status: 'finished'\n  },\n  {\n    id: 'contact',\n    name: '你的联系人信息',\n    status: 'finished'\n  }\n])\n\nconst fileList = fileListRef\n\nfunction handleUploadChange(data: { fileList: UploadFileInfo[] }) {\n  fileListRef.value = data.fileList\n}\n\nfunction handleRemove(data: {\n  file: UploadFileInfo\n  fileList: UploadFileInfo[]\n}) {\n  if (data.file.id === 'text-message') {\n    message.info('居然没传上去，算了，删了吧')\n  }\n  else if (data.file.id === 'notification') {\n    message.error('不行，这个有用，不许删')\n    return false\n  }\n  else if (data.file.id === 'contact') {\n    message.loading('不知道这个有没有用，等我问问服务器能不能删', {\n      duration: 4000\n    })\n    return new Promise((resolve) => {\n      setTimeout(() => {\n        message.error('不行，他们也不许删这个')\n        resolve(false)\n      }, 4000)\n    })\n  }\n}\n\nfunction handleFileListChange() {\n  message.info('是的，file-list 的值变了')\n}\n</script>\n\n<template>\n  <n-upload\n    v-model:file-list=\"fileList\"\n    action=\"__HTTP__://www.mocky.io/v2/5e4bafc63100007100d8b70f\"\n    @change=\"handleUploadChange\"\n    @remove=\"handleRemove\"\n    @update:file-list=\"handleFileListChange\"\n  >\n    <n-button>上传文件</n-button>\n  </n-upload>\n</template>\n"
  },
  {
    "path": "src/upload/demos/zhCN/custom-download.demo.vue",
    "content": "<markdown>\n# 自定义下载\n\n通过设置 `custom-download` 来自定义下载文件的逻辑。\n\n默认下载方式为浏览器原生，通过对一个有对应 URL 的 `<a />` 元素的点击操作实现。但是在特定的场合下，例如跨域的文件下载，你可能会需要对文件的下载逻辑进行自定义。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { UploadFileInfo } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst fileList = ref<UploadFileInfo[]>([\n  {\n    id: 'c',\n    name: '自定义下载文件.png',\n    status: 'finished',\n    url: 'https://avatars.githubusercontent.com/u/20943608?s=60&v=4'\n  }\n])\n\nfunction handleCustomDownload(file: UploadFileInfo) {\n  const { url, name } = file\n  if (!url)\n    return\n  fetch(url)\n    .then(response => response.blob())\n    .then((blob) => {\n      const blobUrl = URL.createObjectURL(new Blob([blob]))\n      const link = document.createElement('a')\n      link.href = blobUrl\n      if (name) {\n        link.download = name\n      }\n      document.body.appendChild(link)\n      link.click()\n      URL.revokeObjectURL(blobUrl)\n      link.remove()\n    })\n}\n</script>\n\n<template>\n  <n-upload\n    action=\"http://www.mocky.io/v2/5e4bafc63100007100d8b70f\"\n    :default-file-list=\"fileList\"\n    list-type=\"image\"\n    show-download-button\n    :custom-download=\"handleCustomDownload\"\n  >\n    <n-button>上传文件</n-button>\n  </n-upload>\n</template>\n"
  },
  {
    "path": "src/upload/demos/zhCN/custom-request.demo.vue",
    "content": "<markdown>\n# 自定义上传\n\n使用 `custom-request` 属性来自定义上传请求。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { UploadCustomRequestOptions } from 'naive-ui'\nimport { lyla } from '@lylajs/web'\nimport { useMessage } from 'naive-ui'\n\nconst message = useMessage()\nfunction customRequest({\n  file,\n  data,\n  headers,\n  withCredentials,\n  action,\n  onFinish,\n  onError,\n  onProgress\n}: UploadCustomRequestOptions) {\n  const formData = new FormData()\n  if (data) {\n    Object.keys(data).forEach((key) => {\n      formData.append(\n        key,\n        data[key as keyof UploadCustomRequestOptions['data']]\n      )\n    })\n  }\n  formData.append(file.name, file.file as File)\n  lyla\n    .post(action as string, {\n      withCredentials,\n      headers: headers as Record<string, string>,\n      body: formData,\n      onUploadProgress: ({ percent }) => {\n        onProgress({ percent: Math.ceil(percent) })\n      }\n    })\n    .then(({ json }) => {\n      message.success(JSON.stringify(json))\n      onFinish()\n    })\n    .catch((error) => {\n      message.success(error.message)\n      onError()\n    })\n}\n</script>\n\n<template>\n  <n-upload\n    action=\"__HTTP__://naive-upload.free.beeceptor.com/\"\n    :headers=\"{\n      'naive-info': 'hello!',\n    }\"\n    :data=\"{\n      'naive-data': 'cool! naive!',\n    }\"\n    :custom-request=\"customRequest\"\n  >\n    <n-button>上传文件</n-button>\n  </n-upload>\n</template>\n"
  },
  {
    "path": "src/upload/demos/zhCN/debug.demo.vue",
    "content": "<markdown>\n# Debug\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ArchiveOutline as ArchiveIcon } from '@vicons/ionicons5'\nimport { ref } from 'vue'\n\nfunction handleUpdateList(...args: unknown[]) {\n  console.log(...args)\n}\n\nconst multiple = ref(false)\nconst directory = ref(false)\nconst directoryDnd = ref(false)\nconst directoryDndUndefined = ref(true)\n</script>\n\n<template>\n  Retry\n  <n-upload action=\"http://fake-api\">\n    <n-button>Upload</n-button>\n  </n-upload>\n  Multiple <n-switch v-model:value=\"multiple\" /><br>\n  Directory <n-switch v-model:value=\"directory\" /><br>\n  DirectoryDnd <n-switch v-model:value=\"directoryDnd\" /><br>\n  DirectoryDnd undefined <n-switch v-model:value=\"directoryDndUndefined\" />\n  <n-upload\n    action=\"__HTTP__://www.mocky.io/v2/5e4bafc63100007100d8b70f\"\n    :multiple=\"multiple\"\n    :directory=\"directory\"\n    :directory-dnd=\"directoryDndUndefined ? undefined : directoryDnd\"\n    @update:file-list=\"handleUpdateList\"\n  >\n    <n-button>Upload</n-button>\n  </n-upload>\n  <n-upload\n    action=\"__HTTP__://www.mocky.io/v2/5e4bafc63100007100d8b70f\"\n    :multiple=\"multiple\"\n    :directory=\"directory\"\n    :directory-dnd=\"directoryDndUndefined ? undefined : directoryDnd\"\n    @update:file-list=\"handleUpdateList\"\n  >\n    <n-upload-dragger>\n      <div style=\"margin-bottom: 12px\">\n        <n-icon size=\"48\" :depth=\"3\">\n          <ArchiveIcon />\n        </n-icon>\n      </div>\n      <n-text style=\"font-size: 16px\">\n        点击或者拖动文件到该区域来上传\n      </n-text>\n      <n-p depth=\"3\" style=\"margin: 8px 0 0 0\">\n        请不要上传敏感数据，比如你的银行卡号和密码，信用卡号有效期和安全码\n      </n-p>\n    </n-upload-dragger>\n  </n-upload>\n</template>\n"
  },
  {
    "path": "src/upload/demos/zhCN/default-files.demo.vue",
    "content": "<markdown>\n# 默认文件列表\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { UploadFileInfo } from 'naive-ui'\n\nconst defaultFileList: UploadFileInfo[] = [\n  {\n    id: 'razars',\n    name: '刀',\n    status: 'finished'\n  },\n  {\n    id: 'edge',\n    name: '锋',\n    status: 'finished'\n  }\n]\n</script>\n\n<template>\n  <n-upload\n    action=\"__HTTP__://www.mocky.io/v2/5e4bafc63100007100d8b70f\"\n    :default-file-list=\"defaultFileList\"\n  >\n    <n-button>上传文件</n-button>\n  </n-upload>\n</template>\n"
  },
  {
    "path": "src/upload/demos/zhCN/download.demo.vue",
    "content": "<markdown>\n# 下载文件\n\n通过设置 `show-download-button` 来显示下载按钮，通过 `on-download` 来设置下载按钮被点击的事件处理函数。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { UploadFileInfo } from 'naive-ui'\nimport { useMessage } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst message = useMessage()\nconst fileListRef = ref<UploadFileInfo[]>([\n  {\n    id: 'a',\n    name: '我错了，但我可以改.png',\n    status: 'error'\n  },\n  {\n    id: 'd',\n    name: '现在还不行呢.doc',\n    status: 'uploading',\n    percentage: 50\n  },\n  {\n    id: 'c',\n    name: '现在就可下载哟.png',\n    status: 'finished',\n    url: '__HTTP__://07akioni.oss-cn-beijing.aliyuncs.com/07akioni.jpeg'\n  }\n])\n\nconst fileList = fileListRef\n\nfunction handleDownload(file: UploadFileInfo) {\n  message.success(`下载成功：${file.name}`)\n}\n</script>\n\n<template>\n  <n-upload\n    action=\"__HTTP__://www.mocky.io/v2/5e4bafc63100007100d8b70f\"\n    :default-file-list=\"fileList\"\n    list-type=\"image\"\n    show-download-button\n    @download=\"handleDownload\"\n  >\n    <n-button>上传文件</n-button>\n  </n-upload>\n</template>\n"
  },
  {
    "path": "src/upload/demos/zhCN/drag.demo.vue",
    "content": "<markdown>\n# 拖拽上传\n\n你可以把 `directory-dnd` 设为 `true` 来允许拖拽上传文件夹。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ArchiveOutline as ArchiveIcon } from '@vicons/ionicons5'\n</script>\n\n<template>\n  <n-upload\n    multiple\n    directory-dnd\n    action=\"__HTTP__://www.mocky.io/v2/5e4bafc63100007100d8b70f\"\n    :max=\"5\"\n  >\n    <n-upload-dragger>\n      <div style=\"margin-bottom: 12px\">\n        <n-icon size=\"48\" :depth=\"3\">\n          <ArchiveIcon />\n        </n-icon>\n      </div>\n      <n-text style=\"font-size: 16px\">\n        点击或者拖动文件到该区域来上传\n      </n-text>\n      <n-p depth=\"3\" style=\"margin: 8px 0 0 0\">\n        请不要上传敏感数据，比如你的银行卡号和密码，信用卡号有效期和安全码\n      </n-p>\n    </n-upload-dragger>\n  </n-upload>\n</template>\n"
  },
  {
    "path": "src/upload/demos/zhCN/image-card-style.demo.vue",
    "content": "<markdown>\n# 照片墙\n\n照片墙中的预览会默认调用内部组件，你也可以使用 `on-preview` 自定义展示上传文件的方法。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { UploadFileInfo } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst showModalRef = ref(false)\nconst previewImageUrlRef = ref('')\n\nfunction handlePreview(file: UploadFileInfo) {\n  const { url } = file\n  previewImageUrlRef.value = url as string\n  showModalRef.value = true\n}\n\nconst showModal = showModalRef\nconst previewImageUrl = previewImageUrlRef\n\nconst fileList = ref<UploadFileInfo[]>([\n  {\n    id: 'a',\n    name: '我是上传出错的普通文件.png',\n    status: 'error'\n  },\n  {\n    id: 'b',\n    name: '我是普通文本.doc',\n    status: 'finished',\n    type: 'text/plain'\n  },\n  {\n    id: 'c',\n    name: '我是自带url的图片.png',\n    status: 'finished',\n    url: '__HTTP__://07akioni.oss-cn-beijing.aliyuncs.com/07akioni.jpeg'\n  },\n  {\n    id: 'd',\n    name: '我是上传进度99%的文本.doc',\n    status: 'uploading',\n    percentage: 99\n  }\n])\n\nconst previewFileList = ref<UploadFileInfo[]>([\n  {\n    id: 'react',\n    name: '我是react.png',\n    status: 'finished',\n    url: '__HTTP__://07akioni.oss-cn-beijing.aliyuncs.com/07akioni.jpeg'\n  },\n  {\n    id: 'vue',\n    name: '我是vue.png',\n    status: 'finished',\n    url: '__HTTP__://07akioni.oss-cn-beijing.aliyuncs.com/07akioni.jpeg'\n  }\n])\n</script>\n\n<template>\n  <n-upload\n    action=\"__HTTP__://www.mocky.io/v2/5e4bafc63100007100d8b70f\"\n    :default-file-list=\"fileList\"\n    list-type=\"image-card\"\n  >\n    点击上传\n  </n-upload>\n  <n-divider />\n  <n-upload\n    action=\"__HTTP__://www.mocky.io/v2/5e4bafc63100007100d8b70f\"\n    :default-file-list=\"previewFileList\"\n    list-type=\"image-card\"\n    @preview=\"handlePreview\"\n  />\n  <n-modal\n    v-model:show=\"showModal\"\n    preset=\"card\"\n    style=\"width: 600px\"\n    title=\"一张很酷的图片\"\n  >\n    <img :src=\"previewImageUrl\" style=\"width: 100%\">\n  </n-modal>\n</template>\n"
  },
  {
    "path": "src/upload/demos/zhCN/image-style.demo.vue",
    "content": "<markdown>\n# 缩略图文件列表\n\n你可以使用 `create-thumbnail-url` 自定义文件的缩略图。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { UploadFileInfo } from 'naive-ui'\nimport { useMessage } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst message = useMessage()\nconst fileListRef = ref<UploadFileInfo[]>([\n  {\n    id: 'a',\n    name: '我错了.png',\n    status: 'error'\n  },\n  {\n    id: 'b',\n    name: '普通文本.doc',\n    status: 'finished',\n    type: 'text/plain'\n  },\n  {\n    id: 'c',\n    name: '图片.png',\n    status: 'finished',\n    url: '__HTTP__://07akioni.oss-cn-beijing.aliyuncs.com/07akioni.jpeg'\n  },\n  {\n    id: 'd',\n    name: '没传完.doc',\n    status: 'uploading',\n    percentage: 50\n  }\n])\n\nconst fileList = fileListRef\n\nfunction createThumbnailUrl(file: File | null): Promise<string> | undefined {\n  if (!file)\n    return undefined\n  message.info('createThumbnailUrl 产生了图片的 URL，你传什么都会变成 07akioni')\n  message.info(`${file.name}`)\n  return new Promise((resolve) => {\n    setTimeout(() => {\n      resolve('__HTTP__://07akioni.oss-cn-beijing.aliyuncs.com/07akioni.jpeg')\n    }, 1000)\n  })\n}\n</script>\n\n<template>\n  <n-upload\n    action=\"__HTTP__://www.mocky.io/v2/5e4bafc63100007100d8b70f\"\n    :default-file-list=\"fileList\"\n    list-type=\"image\"\n    :create-thumbnail-url=\"createThumbnailUrl\"\n  >\n    <n-button>上传文件</n-button>\n  </n-upload>\n</template>\n"
  },
  {
    "path": "src/upload/demos/zhCN/index.demo-entry.md",
    "content": "# 上传 Upload\n\n如果不在意延迟，我更想用卡车和硬盘。\n\n## 演示\n\n```demo\nbasic.vue\ndrag.vue\nsubmit-manually.vue\ncontrolled.vue\non-finish.vue\ndownload.vue\ndefault-files.vue\nbefore-upload.vue\nimage-style.vue\nimage-card-style.vue\ncustom-request.vue\ncustom-download.vue\nabstract.vue\ndebug.vue\nrtl-debug.vue\n```\n\n## API\n\n### Upload Props\n\n| 名称 | 类型 | 默认值 | 说明 | 版本 |\n| --- | --- | --- | --- | --- |\n| abstract | `boolean` | `false` | 是否不存在 DOM 包裹，不支持 `image-card` 类型的 Upload |  |\n| accept | `string` | `undefined` | 接受的文件类型，参考 <n-a href=\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/file#accept\" target=\"_blank\">accept</n-a> |  |\n| action | `string` | `undefined` | 请求提交的地址 |  |\n| create-thumbnail-url | `(file: File \\| null, fileInfo: UploadSettledFileInfo) => (Promise<string> \\| string \\| undefined)` | `undefined` | 自定义文件缩略图，如果返回了 `undefined`，会使用默认的缩略图展示逻辑 | `fileInfo` 2.34.0 |\n| custom-request | `(options: UploadCustomRequestOptions) => void` | `undefined` | 自定义上传方法，类型参考 <n-a href=\"#UploadCustomRequestOptions-Type\">UploadCustomRequestOptions</n-a> |  |\n| custom-download | `(file: FileInfo) => void` | `undefined` | 自定义下载方法 | 2.41.1 |\n| data | `Object \\| ({ file: UploadFileInfo }) => Object` | `undefined` | 提交表单需要附加的数据 |  |\n| default-file-list | `Array<UploadFileInfo>` | `[]` | 非受控状态下默认的文件列表 |  |\n| default-upload | `boolean` | `true` | 选择文件时候是否默认上传 |  |\n| disabled | `boolean` | `false` | 是否禁用 |  |\n| directory | `boolean` | `false` | 是否支持目录上传（在文件选框中只能选择目录） | 2.28.3 |\n| directory-dnd | `boolean` | `false` | 是否支持目录拖拽上传（如果不设定会默认跟随 `directory`） | 2.28.3 |\n| file-list-class | `string` | `undefined` | 文件列表区域的类名 | 2.36.0 |\n| file-list-style | `Object` | `undefined` | 文件列表区域的样式 |  |\n| file-list | `Array<UploadFileInfo>` | `undefined` | 文件列表，如果传入组件会处于受控状态 |  |\n| headers | `Object \\| ({ file: UploadFileInfo }) => Object` | `undefined` | HTTP 请求需要附加的 Headers |  |\n| image-group-props | `ImageGroupProps` | `undefined` | Upload 中预览图片组件的属性，参考 [ImageGroup Props](image#ImageGroup-Props) | 2.24.0 |\n| input-props | `InputHTMLAttributes` | `undefined` | file input 元素的属性 | 2.24.2 |\n| is-error-state | `(xhr: XMLHttpRequest) => boolean` | `undefined` | 判断请求是否为异常状态 | 2.29.1 |\n| list-type | `string` | `'text'` | 文件列表的内建样式，`text`、`image` 和 `image-card` |  |\n| max | `number` | `undefined` | 限制上传文件数量 |  |\n| method | `string` | `'POST'` | HTTP 请求的方法 |  |\n| multiple | `boolean` | `false` | 是否支持多个文件 |  |\n| name | `string` | `'file'` | 文件在提交表单中的字段名 |  |\n| render-icon | `(file: UploadSettledFileInfo) => VNodeChild` | `undefined` | 文件图标的渲染函数，仅在 `list-type=\"image\"` 和 `list-type=\"image-card\"` 时生效 | 2.34.0 |\n| response-type | `'' \\| 'arraybuffer' \\| 'blob' \\| 'document' \\| 'json' \\| 'text'` | `''` | `n-upload` 使用的 `XMLHttpRequest` 的 `responseType` | 2.33.3 |\n| should-use-thumbnail-url | `(file: UploadSettledFileInfo) => boolean` | 只对图片类文件返回 `true` 的函数 | 是否要对文件使用预览图的判定函数，只在 `list-type=\"image\"` 或 `list-type=\"image-card\"` 时生效 | 2.34.0 |\n| show-cancel-button | `boolean` | `true` | 是否显示取消按钮（在 pending、uploading、error 的时候展示），点击取消按钮会触发 `on-remove` 回调 |  |\n| show-download-button | `boolean` | `false` | 是否显示下载按钮（在 finished 后展示） |  |\n| show-remove-button | `boolean` | `true` | 是否显示删除按钮（在 finished 后时候展示），点击删除按钮会触发 `on-remove` 回调 |  |\n| show-retry-button | `boolean` | `true` | 是否显示重新上传按钮（在 error 时展示） |  |\n| show-file-list | `boolean` | `true` | 是否显示文件列表 |  |\n| show-preview-button | `boolean` | `true` | 是否允许显示预览按钮（在 `list-type` 为 `image-card` 时生效） |  |\n| show-trigger | `boolean` | `true` | 是否显示触发元素 | 2.21.5 |\n| trigger-class | `string` | `undefined` | 触发器区域的类名 | 2.36.0 |\n| trigger-style | `Object \\| string` | `undefined` | 触发器区域的样式 | 2.29.1 |\n| with-credentials | `boolean` | `false` | 是否携带 Cookie |  |\n| on-change | `(options: { file: UploadFileInfo, fileList: Array<UploadFileInfo>, event?: Event }) => void` | `undefined` | 组件状态变化的回调，组件的任何文件状态变化都会触发回调 |  |\n| on-error | `(options: { file: UploadFileInfo, event?: ProgressEvent }) => UploadFileInfo \\| void` | `undefined` | 文件上传失败的回调 | 2.24.0 |\n| on-finish | `(options: { file: UploadFileInfo, event?: ProgressEvent }) => UploadFileInfo \\| undefined` | `({ file }) => file` | 文件上传结束的回调，可以修改传入的 UploadFileInfo 或者返回一个新的 UploadFileInfo。注意：file 将会下一次事件循环中被置为 null |  |\n| on-before-upload | `(options: { file: UploadFileInfo, fileList: UploadFileInfo[] }) => (Promise<boolean \\| void> \\| boolean \\| void)` | `undefined` | 文件上传之前的回调，返回 `false`、`Promise resolve false`、`Promise rejected` 时会取消本次上传 |  |\n| on-download | `(file: FileInfo) => Promise<boolean> \\| boolean \\| any` | `undefined` | 点击文件下载按钮的回调函数，返回 `false`、`Promise resolve false`、`Promise rejected` 时会取消本次下载 |  |\n| on-preview | `(file: FileInfo, detail: { event: MouseEvent }) => void` | `undefined` | 点击文件链接或预览按钮的回调函数，你可以通过 `preventDefault` 来取消默认的链接打开行为 | `detail.event` 2.39.0 |\n| on-remove | `(options: { file: UploadFileInfo, fileList: Array<UploadFileInfo>, index: number }) => Promise<boolean> \\| boolean \\| any` | `() => true` | 文件删除回调，返回 `false`、`Promise resolve false`、`Promise rejected` 时会取消本次删除 | `index` 2.38.2 |\n| on-retry | `(options: { file: UploadFileInfo }) => (Promise<boolean \\| void> \\| boolean \\| void)` | `undefined` | 点击重试的回调函数，返回 `false`、`Promise resolve false`、`Promise rejected` 时会取消本次重试 | 2.40.0 |\n| on-update:file-list | `(fileList: UploadFileInfo[]) => void` | `undefined` | 当 file-list 改变时触发的回调函数 |  |\n\n#### UploadFileInfo Type\n\n| 属性 | 类型 | 说明 | 版本 |\n| --- | --- | --- | --- |\n| id | `string` | 文件 id，需要唯一。请注意不要修改它，如果你需要保存一些对应的数据，可以建立一个 Map 对象来保存 |  |\n| name | `string` | 文件名 |  |\n| status | `'pending' \\| 'uploading' \\| 'error' \\| 'finished' \\| 'removed'` | 上传的状态 |  |\n| batchId? | `string \\| null` | 上传批次的 id，在同一次上传被选择的文件会拥有一样的 `batchId` | 2.28.3 |\n| file? | `File \\| null` | 文件对应的浏览器 File 对象 |  |\n| fullPath? | `string \\| null` | 上传文件的相对路径 | 2.28.3 |\n| percentage? | `number \\| null` | 文件上传进度百分比，在 uploading 状态下生效 |  |\n| thumbnailUrl? | `string \\| null` | 缩略图 URL |  |\n| type? | `string \\| null` | MIME 类型 |  |\n| url? | `string \\| null` | 文件下载 URL |  |\n\n### UploadTrigger Props\n\n| 名称     | 类型      | 默认值  | 说明                |\n| -------- | --------- | ------- | ------------------- |\n| abstract | `boolean` | `false` | 是否不存在 DOM 包裹 |\n\n#### UploadCustomRequestOptions Type\n\n```__ts\ninterface UploadCustomRequestOptions {\n  file: FileInfo\n  action?: string\n  data?:\n    | Record<string, string>\n    | (({ file }: { file: FileInfo }) => Record<string, string>)\n  withCredentials?: boolean\n  headers?:\n    | Record<string, string>\n    | (({ file }: { file: FileInfo }) => Record<string, string>)\n  onProgress: (e: { percent: number }) => void\n  onFinish: () => void\n  onError: () => void\n}\n```\n\n### Upload Methods\n\n| 名称 | 类型 | 说明 | 版本 |\n| --- | --- | --- | --- |\n| clear | `() => void` | 清空上传列表 | 2.24.2 |\n| openOpenFileDialog | `() => void` | 打开文件选择对话框 |  |\n| submit | `(options?: { fileId?: string, retry?: boolean })` | 提交当前所有处于 pending 状态的文件 | `retry`: `2.44.0` |\n\n### Upload Slots\n\n| 名称    | 参数 | 说明       |\n| ------- | ---- | ---------- |\n| default | `()` | 上传的内容 |\n\n### UploadDragger Slots\n\n| 名称 | 参数 | 说明 |\n| --- | --- | --- |\n| default | `()` | 上传拖动器的内容，使用可参考<n-a href=\"#drag\">拖拽上传</n-a> |\n\n### UploadTrigger Slots\n\n| 名称 | 参数 | 说明 |\n| --- | --- | --- |\n| default | `(options: { handleClick: () => void, handleDragOver: (e: DragEvent) => void, handleDragEnter: (e: DragEvent) => void, handleDragLeave: (e: DragEvent) => void, handleDrop: (e: DragEvent) => void})` | `handleClick` 为点击上传函数，`handleDrop` 为拖拽上传函数，`handleDragEnter`、`handleDragOver` 和 `handleDragLeave` 为拖拽事件函数 |\n\n### 其他\n\n1. `uploadDownload`，类型为 `(url: string, name: string | undefined): void`，你可以直接从 naive-ui import 此函数\n"
  },
  {
    "path": "src/upload/demos/zhCN/on-finish.demo.vue",
    "content": "<markdown>\n# 上传完成的回调\n\n你可以在回调中修改文件的属性。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { UploadFileInfo } from 'naive-ui'\nimport { useMessage } from 'naive-ui'\n\nconst message = useMessage()\n\nfunction handleFinish({\n  file,\n  event\n}: {\n  file: UploadFileInfo\n  event?: ProgressEvent\n}) {\n  console.log(event)\n  message.success((event?.target as XMLHttpRequest).response)\n  const ext = file.name.split('.')[1]\n  file.name = `更名.${ext}`\n  file.url = '__HTTPS__://www.mocky.io/v2/5e4bafc63100007100d8b70f'\n  return file\n}\n</script>\n\n<template>\n  <n-upload\n    action=\"__HTTP__://www.mocky.io/v2/5e4bafc63100007100d8b70f\"\n    @finish=\"handleFinish\"\n  >\n    <n-button>上传文件</n-button>\n  </n-upload>\n</template>\n"
  },
  {
    "path": "src/upload/demos/zhCN/rtl-debug.demo.vue",
    "content": "<markdown>\n# Rtl Debug\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { UploadFileInfo } from 'naive-ui'\nimport { unstableUploadsRtl } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst rtlEnabled = ref(false)\nconst rtlStyles = [unstableUploadsRtl]\n\nconst fileList = ref<UploadFileInfo[]>([\n  {\n    id: 'a',\n    name: '我是上传出错的普通文件.png',\n    status: 'error'\n  },\n  {\n    id: 'b',\n    name: '我是普通文本.doc',\n    status: 'finished',\n    type: 'text/plain'\n  },\n  {\n    id: 'c',\n    name: '我是自带url的图片.png',\n    status: 'finished',\n    url: '__HTTP__://07akioni.oss-cn-beijing.aliyuncs.com/07akioni.jpeg'\n  },\n  {\n    id: 'd',\n    name: '我是上传进度99%的文本.doc',\n    status: 'uploading',\n    percentage: 99\n  }\n])\n</script>\n\n<template>\n  <n-space vertical>\n    <n-space><n-switch v-model:value=\"rtlEnabled\" />Rtl</n-space>\n    <n-config-provider :rtl=\"rtlEnabled ? rtlStyles : undefined\">\n      <n-space vertical>\n        <n-upload\n          action=\"__HTTP__://www.mocky.io/v2/5e4bafc63100007100d8b70f\"\n          :default-file-list=\"fileList\"\n          list-type=\"image-card\"\n        >\n          点击上传\n        </n-upload>\n\n        <n-upload\n          action=\"http://www.mocky.io/v2/5e4bafc63100007100d8b70f\"\n          :default-file-list=\"fileList\"\n          list-type=\"image\"\n        >\n          <n-button>上传文件</n-button>\n        </n-upload>\n      </n-space>\n    </n-config-provider>\n  </n-space>\n</template>\n"
  },
  {
    "path": "src/upload/demos/zhCN/submit-manually.demo.vue",
    "content": "<markdown>\n# 非受控手动提交\n\n你可以使用 submit 方法来进行非受控状态下的手动提交。当然你也可以在受控模式下完全控制提交行为。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { UploadFileInfo, UploadInst } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst fileListLengthRef = ref(0)\nconst uploadRef = ref<UploadInst | null>(null)\n\nconst fileListLength = fileListLengthRef\n\nfunction handleChange(options: { fileList: UploadFileInfo[] }) {\n  fileListLengthRef.value = options.fileList.length\n}\n\nfunction handleClick() {\n  uploadRef.value?.submit()\n}\n</script>\n\n<template>\n  <n-button\n    :disabled=\"!fileListLength\"\n    style=\"margin-bottom: 12px\"\n    @click=\"handleClick\"\n  >\n    上传文件\n  </n-button>\n  <n-upload\n    ref=\"uploadRef\"\n    action=\"__HTTP__://www.mocky.io/v2/5e4bafc63100007100d8b70f\"\n    :default-upload=\"false\"\n    multiple\n    @change=\"handleChange\"\n  >\n    <n-button>选择文件</n-button>\n  </n-upload>\n</template>\n"
  },
  {
    "path": "src/upload/index.ts",
    "content": "export { publicDownload as uploadDownload } from '../_utils/dom/download'\nexport type * from './src/public-types'\nexport { default as NUpload, uploadProps } from './src/Upload'\nexport { default as NUploadDragger } from './src/UploadDragger'\nexport { default as NUploadFileList } from './src/UploadFileList'\nexport { default as NUploadTrigger } from './src/UploadTrigger'\nexport type { UploadTriggerSlots } from './src/UploadTrigger'\n"
  },
  {
    "path": "src/upload/src/Upload.tsx",
    "content": "import type { CSSProperties, InputHTMLAttributes, PropType } from 'vue'\nimport type { ThemeProps } from '../../_mixins'\nimport type { ExtractPublicPropTypes, MaybeArray } from '../../_utils'\nimport type { ImageGroupProps } from '../../image'\nimport type { UploadTheme } from '../styles'\nimport type {\n  CreateThumbnailUrl,\n  CustomRequest,\n  DoChange,\n  FileAndEntry,\n  FuncOrRecordOrUndef,\n  ListType,\n  OnBeforeUpload,\n  OnError,\n  OnPreview,\n  OnRetry,\n  OnUpdateFileList,\n  RenderIcon,\n  ShouldUseThumbnailUrl,\n  UploadInternalInst,\n  XhrHandlers\n} from './interface'\nimport type {\n  UploadFileInfo,\n  UploadInst,\n  UploadOnChange,\n  UploadOnDownload,\n  UploadOnFinish,\n  UploadOnRemove,\n  UploadSettledFileInfo\n} from './public-types'\nimport { createId } from 'seemly'\nimport { useMergedState } from 'vooks'\nimport {\n  computed,\n  defineComponent,\n  Fragment,\n  h,\n  nextTick,\n  provide,\n  ref,\n  Teleport,\n  toRef\n} from 'vue'\nimport {\n  useConfig,\n  useFormItem,\n  useRtl,\n  useTheme,\n  useThemeClass\n} from '../../_mixins'\nimport { call, throwError, warn } from '../../_utils'\nimport { uploadLight } from '../styles'\nimport { uploadInjectionKey } from './interface'\nimport style from './styles/index.cssr'\nimport { uploadDraggerKey } from './UploadDragger'\nimport NUploadFileList from './UploadFileList'\nimport NUploadTrigger from './UploadTrigger'\nimport {\n  createImageDataUrl,\n  createSettledFileInfo,\n  environmentSupportFile,\n  isImageFile,\n  matchType\n} from './utils'\n\n/**\n * fils status ['pending', 'uploading', 'finished', 'removed', 'error']\n */\nfunction createXhrHandlers(\n  inst: UploadInternalInst,\n  file: UploadSettledFileInfo,\n  xhr: XMLHttpRequest\n): XhrHandlers {\n  const { doChange, xhrMap } = inst\n  let percentage = 0\n  function handleXHRError(e: ProgressEvent<EventTarget>): void {\n    let fileAfterChange: UploadSettledFileInfo = Object.assign({}, file, {\n      status: 'error',\n      percentage\n    })\n    xhrMap.delete(file.id)\n    fileAfterChange = createSettledFileInfo(\n      inst.onError?.({ file: fileAfterChange, event: e }) || fileAfterChange\n    )\n    doChange(fileAfterChange, e)\n  }\n  function handleXHRLoad(e: ProgressEvent<EventTarget>): void {\n    if (inst.isErrorState) {\n      if (inst.isErrorState(xhr)) {\n        handleXHRError(e)\n        return\n      }\n    }\n    else {\n      if (xhr.status < 200 || xhr.status >= 300) {\n        handleXHRError(e)\n        return\n      }\n    }\n\n    let fileAfterChange: UploadSettledFileInfo = Object.assign<\n      Record<string, unknown>,\n      UploadSettledFileInfo,\n      Partial<UploadFileInfo>\n    >({}, file, {\n      status: 'finished',\n      percentage\n    })\n    xhrMap.delete(file.id)\n    fileAfterChange = createSettledFileInfo(\n      inst.onFinish?.({ file: fileAfterChange, event: e }) || fileAfterChange\n    )\n    doChange(fileAfterChange, e)\n  }\n  return {\n    handleXHRLoad,\n    handleXHRError,\n    handleXHRAbort(e) {\n      const fileAfterChange: UploadSettledFileInfo = Object.assign({}, file, {\n        status: 'removed',\n        file: null,\n        percentage\n      })\n\n      xhrMap.delete(file.id)\n      doChange(fileAfterChange, e)\n    },\n    handleXHRProgress(e) {\n      const fileAfterChange: UploadSettledFileInfo = Object.assign({}, file, {\n        status: 'uploading'\n      })\n\n      if (e.lengthComputable) {\n        const progress = Math.ceil((e.loaded / e.total) * 100)\n        fileAfterChange.percentage = progress\n        percentage = progress\n      }\n      doChange(fileAfterChange, e)\n    }\n  }\n}\n\nfunction customSubmitImpl(options: {\n  inst: Omit<UploadInternalInst, 'isErrorState'>\n  data?: FuncOrRecordOrUndef<string | Blob>\n  headers?: FuncOrRecordOrUndef\n  action?: string\n  withCredentials?: boolean\n  file: UploadSettledFileInfo\n  customRequest: CustomRequest\n}): void {\n  const { inst, file, data, headers, withCredentials, action, customRequest }\n    = options\n  const { doChange } = options.inst\n  let percentage = 0\n  customRequest({\n    file,\n    data,\n    headers,\n    withCredentials,\n    action,\n    onProgress(event) {\n      const fileAfterChange: UploadSettledFileInfo = Object.assign<\n        Record<string, unknown>,\n        UploadSettledFileInfo,\n        Partial<UploadFileInfo>\n      >({}, file, {\n        status: 'uploading'\n      })\n      const progress = event.percent\n      fileAfterChange.percentage = progress\n      percentage = progress\n      doChange(fileAfterChange)\n    },\n    onFinish() {\n      let fileAfterChange: UploadSettledFileInfo = Object.assign<\n        Record<string, unknown>,\n        UploadSettledFileInfo,\n        Partial<UploadFileInfo>\n      >({}, file, {\n        status: 'finished',\n        percentage\n      })\n      fileAfterChange = createSettledFileInfo(\n        inst.onFinish?.({ file: fileAfterChange }) || fileAfterChange\n      )\n      doChange(fileAfterChange)\n    },\n    onError() {\n      let fileAfterChange: UploadSettledFileInfo = Object.assign<\n        Record<string, unknown>,\n        UploadSettledFileInfo,\n        Partial<UploadFileInfo>\n      >({}, file, {\n        status: 'error',\n        percentage\n      })\n      fileAfterChange = createSettledFileInfo(\n        inst.onError?.({ file: fileAfterChange }) || fileAfterChange\n      )\n      doChange(fileAfterChange)\n    }\n  })\n}\n\nfunction registerHandler(\n  inst: UploadInternalInst,\n  file: UploadSettledFileInfo,\n  request: XMLHttpRequest\n): void {\n  const handlers = createXhrHandlers(inst, file, request)\n  request.onabort = handlers.handleXHRAbort\n  request.onerror = handlers.handleXHRError\n  request.onload = handlers.handleXHRLoad\n  if (request.upload) {\n    request.upload.onprogress = handlers.handleXHRProgress\n  }\n}\n\nfunction unwrapFunctionValue<T>(\n  data: FuncOrRecordOrUndef<T>,\n  file: UploadSettledFileInfo\n): Record<string, T> {\n  if (typeof data === 'function') {\n    return data({ file })\n  }\n  if (data)\n    return data\n  return {}\n}\n\nfunction setHeaders(\n  request: XMLHttpRequest,\n  headers: FuncOrRecordOrUndef,\n  file: UploadSettledFileInfo\n): void {\n  const headersObject = unwrapFunctionValue(headers, file)\n  if (!headersObject)\n    return\n  Object.keys(headersObject).forEach((key) => {\n    request.setRequestHeader(key, headersObject[key])\n  })\n}\n\nfunction appendData(\n  formData: FormData,\n  data: FuncOrRecordOrUndef<string | Blob>,\n  file: UploadSettledFileInfo\n): void {\n  const dataObject = unwrapFunctionValue(data, file)\n  if (!dataObject)\n    return\n  Object.keys(dataObject).forEach((key) => {\n    formData.append(key, dataObject[key])\n  })\n}\n\nfunction submitImpl(\n  inst: UploadInternalInst,\n  fieldName: string,\n  file: UploadSettledFileInfo,\n  {\n    method,\n    action,\n    withCredentials,\n    responseType,\n    headers,\n    data\n  }: {\n    method: string\n    action?: string\n    withCredentials: boolean\n    responseType: XMLHttpRequestResponseType\n    headers: FuncOrRecordOrUndef\n    data: FuncOrRecordOrUndef<string | Blob>\n  }\n): void {\n  const request = new XMLHttpRequest()\n  request.responseType = responseType\n  inst.xhrMap.set(file.id, request)\n  request.withCredentials = withCredentials\n  const formData = new FormData()\n  appendData(formData, data, file)\n  if (file.file !== null) {\n    formData.append(fieldName, file.file)\n  }\n  registerHandler(inst, file, request)\n  if (action !== undefined) {\n    request.open(method.toUpperCase(), action)\n    setHeaders(request, headers, file)\n    request.send(formData)\n    const fileAfterChange = Object.assign({}, file, {\n      status: 'uploading'\n    })\n    inst.doChange(fileAfterChange)\n  }\n}\n\nexport const uploadProps = {\n  ...(useTheme.props as ThemeProps<UploadTheme>),\n  name: {\n    type: String,\n    default: 'file'\n  },\n  accept: String,\n  action: String,\n  customRequest: Function as PropType<CustomRequest>,\n  directory: Boolean,\n  directoryDnd: { type: Boolean, default: undefined },\n  method: {\n    type: String,\n    default: 'POST'\n  },\n  multiple: Boolean,\n  showFileList: {\n    type: Boolean,\n    default: true\n  },\n  data: [Object, Function] as PropType<FuncOrRecordOrUndef<string | Blob>>,\n  headers: [Object, Function] as PropType<FuncOrRecordOrUndef>,\n  withCredentials: Boolean,\n  responseType: {\n    type: String as PropType<XMLHttpRequestResponseType>,\n    default: ''\n  },\n  disabled: {\n    type: Boolean as PropType<boolean | undefined>,\n    default: undefined\n  },\n  onChange: Function as PropType<UploadOnChange>,\n  onRemove: Function as PropType<UploadOnRemove>,\n  onFinish: Function as PropType<UploadOnFinish>,\n  onError: Function as PropType<OnError>,\n  onRetry: Function as PropType<OnRetry>,\n  onBeforeUpload: Function as PropType<OnBeforeUpload>,\n  isErrorState: Function as PropType<(xhr: XMLHttpRequest) => boolean>,\n  /** currently not used */\n  onDownload: Function as PropType<UploadOnDownload>,\n  customDownload: Function as PropType<UploadOnDownload>,\n  defaultUpload: {\n    type: Boolean,\n    default: true\n  },\n  fileList: Array as PropType<UploadFileInfo[]>,\n  'onUpdate:fileList': [Function, Array] as PropType<\n    MaybeArray<OnUpdateFileList>\n  >,\n  onUpdateFileList: [Function, Array] as PropType<MaybeArray<OnUpdateFileList>>,\n  fileListClass: String,\n  fileListStyle: [String, Object] as PropType<string | CSSProperties>,\n  defaultFileList: {\n    type: Array as PropType<UploadFileInfo[]>,\n    default: () => []\n  },\n  showCancelButton: {\n    type: Boolean,\n    default: true\n  },\n  showRemoveButton: {\n    type: Boolean,\n    default: true\n  },\n  showDownloadButton: Boolean,\n  showRetryButton: {\n    type: Boolean,\n    default: true\n  },\n  showPreviewButton: {\n    type: Boolean,\n    default: true\n  },\n  listType: {\n    type: String as PropType<ListType>,\n    default: 'text'\n  },\n  onPreview: Function as PropType<OnPreview>,\n  shouldUseThumbnailUrl: {\n    type: Function as PropType<ShouldUseThumbnailUrl>,\n    default: (file: UploadSettledFileInfo) => {\n      if (!environmentSupportFile)\n        return false\n      return isImageFile(file)\n    }\n  },\n  createThumbnailUrl: Function as PropType<CreateThumbnailUrl>,\n  abstract: Boolean,\n  max: Number,\n  showTrigger: {\n    type: Boolean,\n    default: true\n  },\n  imageGroupProps: Object as PropType<ImageGroupProps>,\n  inputProps: Object as PropType<InputHTMLAttributes>,\n  triggerClass: String,\n  triggerStyle: [String, Object] as PropType<CSSProperties | string>,\n  renderIcon: Function as PropType<RenderIcon>\n} as const\n\nexport type UploadProps = ExtractPublicPropTypes<typeof uploadProps>\n\nexport default defineComponent({\n  name: 'Upload',\n  props: uploadProps,\n  setup(props) {\n    if (props.abstract && props.listType === 'image-card') {\n      throwError(\n        'upload',\n        'when the list-type is image-card, abstract is not supported.'\n      )\n    }\n    const { mergedClsPrefixRef, inlineThemeDisabled, mergedRtlRef }\n      = useConfig(props)\n    const themeRef = useTheme(\n      'Upload',\n      '-upload',\n      style,\n      uploadLight,\n      props,\n      mergedClsPrefixRef\n    )\n\n    const rtlEnabledRef = useRtl('Upload', mergedRtlRef, mergedClsPrefixRef)\n\n    const formItem = useFormItem(props)\n    const uncontrolledFileListRef = ref(props.defaultFileList)\n    const controlledFileListRef = toRef(props, 'fileList')\n    const inputElRef = ref<HTMLInputElement | null>(null)\n    const draggerInsideRef = {\n      value: false\n    }\n    const dragOverRef = ref(false)\n    const xhrMap = new Map<string, XMLHttpRequest>()\n    const _mergedFileListRef = useMergedState(\n      controlledFileListRef,\n      uncontrolledFileListRef\n    )\n    const mergedFileListRef = computed(() =>\n      _mergedFileListRef.value.map(createSettledFileInfo)\n    )\n    const maxReachedRef = computed(() => {\n      const { max } = props\n      if (max !== undefined) {\n        return mergedFileListRef.value.length >= max\n      }\n      return false\n    })\n    function openOpenFileDialog(): void {\n      inputElRef.value?.click()\n    }\n    function handleFileInputChange(e: Event): void {\n      const target = e.target as HTMLInputElement\n      handleFileAddition(\n        target.files\n          ? Array.from(target.files).map(file => ({\n              file,\n              entry: null,\n              source: 'input'\n            }))\n          : null,\n        e\n      )\n      // May have bug! set to null?\n      target.value = ''\n    }\n    function doUpdateFileList(files: UploadSettledFileInfo[]): void {\n      const { 'onUpdate:fileList': _onUpdateFileList, onUpdateFileList } = props\n      if (_onUpdateFileList)\n        call(_onUpdateFileList, files)\n      if (onUpdateFileList)\n        call(onUpdateFileList, files)\n      uncontrolledFileListRef.value = files\n    }\n    const mergedMultipleRef = computed(() => props.multiple || props.directory)\n    const doChange: DoChange = (\n      fileAfterChange,\n      event,\n      options = {\n        append: false,\n        remove: false\n      }\n    ) => {\n      const { append, remove } = options\n      const fileListAfterChange = Array.from(mergedFileListRef.value)\n      const fileIndex = fileListAfterChange.findIndex(\n        file => file.id === fileAfterChange.id\n      )\n      if (append || remove || ~fileIndex) {\n        if (append) {\n          fileListAfterChange.push(fileAfterChange)\n        }\n        else if (remove) {\n          fileListAfterChange.splice(fileIndex, 1)\n        }\n        else {\n          fileListAfterChange.splice(fileIndex, 1, fileAfterChange)\n        }\n        const { onChange } = props\n        if (onChange) {\n          onChange({\n            file: fileAfterChange,\n            fileList: fileListAfterChange,\n            event\n          })\n        }\n        doUpdateFileList(fileListAfterChange)\n      }\n      else if (__DEV__) {\n        warn('upload', 'File has no corresponding id in current file list.')\n      }\n    }\n    function handleFileAddition(\n      fileAndEntries: FileAndEntry[] | null,\n      e?: Event\n    ): void {\n      if (!fileAndEntries || fileAndEntries.length === 0)\n        return\n      const { onBeforeUpload } = props\n      fileAndEntries = mergedMultipleRef.value\n        ? fileAndEntries\n        : [fileAndEntries[0]]\n      const { max, accept } = props\n      fileAndEntries = fileAndEntries.filter(({ file, source }) => {\n        if (source === 'dnd' && accept?.trim()) {\n          return matchType(file.name, file.type, accept)\n        }\n        else {\n          return true\n        }\n      })\n      if (max) {\n        fileAndEntries = fileAndEntries.slice(\n          0,\n          max - mergedFileListRef.value.length\n        )\n      }\n\n      const batchId = createId()\n\n      void Promise.all(\n        fileAndEntries.map(async ({ file, entry }) => {\n          const fileInfo: UploadSettledFileInfo = {\n            id: createId(),\n            batchId,\n            name: file.name,\n            status: 'pending',\n            percentage: 0,\n            file,\n            url: null,\n            type: file.type,\n            thumbnailUrl: null,\n            fullPath:\n              entry?.fullPath ?? `/${file.webkitRelativePath || file.name}`\n          }\n          if (\n            !onBeforeUpload\n            || (await onBeforeUpload({\n              file: fileInfo,\n              fileList: mergedFileListRef.value\n            })) !== false\n          ) {\n            return fileInfo\n          }\n          return null\n        })\n      )\n        .then(async (fileInfos) => {\n          let nextTickChain = Promise.resolve()\n\n          fileInfos.forEach((fileInfo) => {\n            nextTickChain = nextTickChain.then(nextTick as any).then(() => {\n              if (fileInfo) {\n                doChange(fileInfo, e, {\n                  append: true\n                })\n              }\n            })\n          })\n          await nextTickChain\n        })\n        .then(() => {\n          if (props.defaultUpload) {\n            submit()\n          }\n        })\n    }\n    function submit({\n      fileId,\n      retry = false\n    }: { fileId?: string, retry?: boolean } = {}): void {\n      const {\n        method,\n        action,\n        withCredentials,\n        headers,\n        data,\n        name: fieldName\n      } = props\n      const filesToUpload\n        = fileId !== undefined\n          ? mergedFileListRef.value.filter(file => file.id === fileId)\n          : mergedFileListRef.value\n      const shouldReupload = retry || fileId !== undefined\n      filesToUpload.forEach((file) => {\n        const { status } = file\n        if (status === 'pending' || (status === 'error' && shouldReupload)) {\n          if (props.customRequest) {\n            customSubmitImpl({\n              inst: {\n                doChange,\n                xhrMap,\n                onFinish: props.onFinish,\n                onError: props.onError\n              },\n              file,\n              action,\n              withCredentials,\n              headers,\n              data,\n              customRequest: props.customRequest\n            })\n          }\n          else {\n            submitImpl(\n              {\n                doChange,\n                xhrMap,\n                onFinish: props.onFinish,\n                onError: props.onError,\n                isErrorState: props.isErrorState\n              },\n              fieldName,\n              file,\n              {\n                method,\n                action,\n                withCredentials,\n                responseType: props.responseType,\n                headers,\n                data\n              }\n            )\n          }\n        }\n      })\n    }\n    function getFileThumbnailUrlResolver(\n      file: UploadSettledFileInfo\n    ): Promise<string> | string {\n      if (file.thumbnailUrl)\n        return file.thumbnailUrl\n      const { createThumbnailUrl } = props\n      if (createThumbnailUrl) {\n        return createThumbnailUrl(file.file, file) ?? (file.url || '')\n      }\n      if (file.url) {\n        return file.url\n      }\n      else if (file.file) {\n        return createImageDataUrl(file.file)\n      }\n      return ''\n    }\n    const cssVarsRef = computed(() => {\n      const {\n        common: { cubicBezierEaseInOut },\n        self: {\n          draggerColor,\n          draggerBorder,\n          draggerBorderHover,\n          itemColorHover,\n          itemColorHoverError,\n          itemTextColorError,\n          itemTextColorSuccess,\n          itemTextColor,\n          itemIconColor,\n          itemDisabledOpacity,\n          lineHeight,\n          borderRadius,\n          fontSize,\n          itemBorderImageCardError,\n          itemBorderImageCard\n        }\n      } = themeRef.value\n      return {\n        '--n-bezier': cubicBezierEaseInOut,\n        '--n-border-radius': borderRadius,\n        '--n-dragger-border': draggerBorder,\n        '--n-dragger-border-hover': draggerBorderHover,\n        '--n-dragger-color': draggerColor,\n        '--n-font-size': fontSize,\n        '--n-item-color-hover': itemColorHover,\n        '--n-item-color-hover-error': itemColorHoverError,\n        '--n-item-disabled-opacity': itemDisabledOpacity,\n        '--n-item-icon-color': itemIconColor,\n        '--n-item-text-color': itemTextColor,\n        '--n-item-text-color-error': itemTextColorError,\n        '--n-item-text-color-success': itemTextColorSuccess,\n        '--n-line-height': lineHeight,\n        '--n-item-border-image-card-error': itemBorderImageCardError,\n        '--n-item-border-image-card': itemBorderImageCard\n      } as any\n    })\n    const themeClassHandle = inlineThemeDisabled\n      ? useThemeClass('upload', undefined, cssVarsRef, props)\n      : undefined\n    provide(uploadInjectionKey, {\n      mergedClsPrefixRef,\n      mergedThemeRef: themeRef,\n      showCancelButtonRef: toRef(props, 'showCancelButton'),\n      showDownloadButtonRef: toRef(props, 'showDownloadButton'),\n      showRemoveButtonRef: toRef(props, 'showRemoveButton'),\n      showRetryButtonRef: toRef(props, 'showRetryButton'),\n      onRemoveRef: toRef(props, 'onRemove'),\n      onDownloadRef: toRef(props, 'onDownload'),\n      customDownloadRef: toRef(props, 'customDownload'),\n      mergedFileListRef,\n      triggerClassRef: toRef(props, 'triggerClass'),\n      triggerStyleRef: toRef(props, 'triggerStyle'),\n      shouldUseThumbnailUrlRef: toRef(props, 'shouldUseThumbnailUrl'),\n      renderIconRef: toRef(props, 'renderIcon'),\n      xhrMap,\n      submit,\n      doChange,\n      showPreviewButtonRef: toRef(props, 'showPreviewButton'),\n      onPreviewRef: toRef(props, 'onPreview'),\n      getFileThumbnailUrlResolver,\n      listTypeRef: toRef(props, 'listType'),\n      dragOverRef,\n      openOpenFileDialog,\n      draggerInsideRef,\n      handleFileAddition,\n      mergedDisabledRef: formItem.mergedDisabledRef,\n      maxReachedRef,\n      fileListClassRef: toRef(props, 'fileListClass'),\n      fileListStyleRef: toRef(props, 'fileListStyle'),\n      abstractRef: toRef(props, 'abstract'),\n      acceptRef: toRef(props, 'accept'),\n      cssVarsRef: inlineThemeDisabled ? undefined : cssVarsRef,\n      themeClassRef: themeClassHandle?.themeClass,\n      onRender: themeClassHandle?.onRender,\n      showTriggerRef: toRef(props, 'showTrigger'),\n      imageGroupPropsRef: toRef(props, 'imageGroupProps'),\n      mergedDirectoryDndRef: computed(() => {\n        return props.directoryDnd ?? props.directory\n      }),\n      onRetryRef: toRef(props, 'onRetry')\n    })\n\n    const exposedMethods: UploadInst = {\n      clear: () => {\n        uncontrolledFileListRef.value = []\n      },\n      submit,\n      openOpenFileDialog\n    }\n\n    return {\n      mergedClsPrefix: mergedClsPrefixRef,\n      draggerInsideRef,\n      rtlEnabled: rtlEnabledRef,\n      inputElRef,\n      mergedTheme: themeRef,\n      dragOver: dragOverRef,\n      mergedMultiple: mergedMultipleRef,\n      cssVars: inlineThemeDisabled ? undefined : cssVarsRef,\n      themeClass: themeClassHandle?.themeClass,\n      onRender: themeClassHandle?.onRender,\n      handleFileInputChange,\n      ...exposedMethods\n    }\n  },\n  render() {\n    const { draggerInsideRef, mergedClsPrefix, $slots, directory, onRender }\n      = this\n    if ($slots.default && !this.abstract) {\n      const firstChild = $slots.default()[0]\n      if ((firstChild as any)?.type?.[uploadDraggerKey]) {\n        draggerInsideRef.value = true\n      }\n    }\n\n    const inputNode = (\n      <input\n        {...this.inputProps}\n        ref=\"inputElRef\"\n        type=\"file\"\n        class={`${mergedClsPrefix}-upload-file-input`}\n        accept={this.accept}\n        multiple={this.mergedMultiple}\n        onChange={this.handleFileInputChange}\n        // @ts-expect-error // seems vue-tsc will add the prop, so we can't use expect-error\n        webkitdirectory={directory || undefined}\n        directory={directory || undefined}\n      />\n    )\n\n    if (this.abstract) {\n      return (\n        <>\n          {$slots.default?.()}\n          <Teleport to=\"body\">{inputNode}</Teleport>\n        </>\n      )\n    }\n\n    onRender?.()\n    return (\n      <div\n        class={[\n          `${mergedClsPrefix}-upload`,\n          this.rtlEnabled && `${mergedClsPrefix}-upload--rtl`,\n          draggerInsideRef.value && `${mergedClsPrefix}-upload--dragger-inside`,\n          this.dragOver && `${mergedClsPrefix}-upload--drag-over`,\n          this.themeClass\n        ]}\n        style={this.cssVars}\n      >\n        {inputNode}\n        {this.showTrigger && this.listType !== 'image-card' && (\n          <NUploadTrigger>{$slots}</NUploadTrigger>\n        )}\n        {this.showFileList && <NUploadFileList>{$slots}</NUploadFileList>}\n      </div>\n    )\n  }\n})\n"
  },
  {
    "path": "src/upload/src/UploadDragger.tsx",
    "content": "import { defineComponent, h, inject } from 'vue'\nimport { throwError } from '../../_utils'\nimport { uploadInjectionKey } from './interface'\n\nexport const uploadDraggerKey = '__UPLOAD_DRAGGER__'\n\nexport default defineComponent({\n  name: 'UploadDragger',\n  [uploadDraggerKey]: true,\n  setup(_, { slots }) {\n    const NUpload = inject(uploadInjectionKey, null)\n    if (!NUpload) {\n      throwError(\n        'upload-dragger',\n        '`n-upload-dragger` must be placed inside `n-upload`.'\n      )\n    }\n    return () => {\n      const {\n        mergedClsPrefixRef: { value: mergedClsPrefix },\n        mergedDisabledRef: { value: mergedDisabled },\n        maxReachedRef: { value: maxReached }\n      } = NUpload\n      return (\n        <div\n          class={[\n            `${mergedClsPrefix}-upload-dragger`,\n            (mergedDisabled || maxReached)\n            && `${mergedClsPrefix}-upload-dragger--disabled`\n          ]}\n        >\n          {slots}\n        </div>\n      )\n    }\n  }\n})\n"
  },
  {
    "path": "src/upload/src/UploadFile.tsx",
    "content": "import type { PropType, VNode } from 'vue'\nimport type { ExtractThemeOverrides } from '../../_mixins/use-theme'\nimport type { ButtonTheme } from '../../button/styles'\nimport type { ImageInst } from '../../image'\nimport type { ListType } from './interface'\nimport type { UploadSettledFileInfo } from './public-types'\nimport { useMemo } from 'vooks'\nimport { computed, defineComponent, h, inject, ref, watchEffect } from 'vue'\nimport { NBaseIcon, NIconSwitchTransition } from '../../_internal'\nimport {\n  AttachIcon,\n  CancelIcon,\n  DownloadIcon,\n  EyeIcon,\n  RetryIcon,\n  TrashIcon\n} from '../../_internal/icons'\nimport { download, warn } from '../../_utils'\nimport { NButton } from '../../button'\nimport { NImage } from '../../image'\nimport { renderDocumentIcon, renderImageIcon } from './icons'\nimport { uploadInjectionKey } from './interface'\nimport NUploadProgress from './UploadProgress'\nimport { isImageFile } from './utils'\n\nconst buttonThemeOverrides: ExtractThemeOverrides<ButtonTheme> = {\n  paddingMedium: '0 3px',\n  heightMedium: '24px',\n  iconSizeMedium: '18px'\n}\n\nexport default defineComponent({\n  name: 'UploadFile',\n  props: {\n    clsPrefix: {\n      type: String,\n      required: true\n    },\n    file: {\n      type: Object as PropType<UploadSettledFileInfo>,\n      required: true\n    },\n    listType: {\n      type: String as PropType<ListType>,\n      required: true\n    },\n    index: {\n      type: Number,\n      required: true\n    }\n  },\n  setup(props) {\n    const NUpload = inject(uploadInjectionKey)!\n\n    const imageRef = ref<ImageInst | null>(null)\n    const thumbnailUrlRef = ref<string>('')\n\n    const progressStatusRef = computed(() => {\n      const { file } = props\n      if (file.status === 'finished')\n        return 'success'\n      if (file.status === 'error')\n        return 'error'\n      return 'info'\n    })\n    const buttonTypeRef = computed(() => {\n      const { file } = props\n      if (file.status === 'error')\n        return 'error'\n      return undefined\n    })\n    const showProgressRef = computed(() => {\n      const { file } = props\n      return file.status === 'uploading'\n    })\n    const showCancelButtonRef = computed(() => {\n      if (!NUpload.showCancelButtonRef.value)\n        return false\n      const { file } = props\n      return ['uploading', 'pending', 'error'].includes(file.status)\n    })\n    const showRemoveButtonRef = computed(() => {\n      if (!NUpload.showRemoveButtonRef.value)\n        return false\n      const { file } = props\n      return ['finished'].includes(file.status)\n    })\n    const showDownloadButtonRef = computed(() => {\n      if (!NUpload.showDownloadButtonRef.value)\n        return false\n      const { file } = props\n      return ['finished'].includes(file.status)\n    })\n    const showRetryButtonRef = computed(() => {\n      if (!NUpload.showRetryButtonRef.value)\n        return false\n      const { file } = props\n      return ['error'].includes(file.status)\n    })\n    const mergedThumbnailUrlRef = useMemo(() => {\n      return thumbnailUrlRef.value || props.file.thumbnailUrl || props.file.url\n    })\n    const showPreviewButtonRef = computed(() => {\n      if (!NUpload.showPreviewButtonRef.value)\n        return false\n      const {\n        file: { status },\n        listType\n      } = props\n      return (\n        ['finished'].includes(status)\n        && mergedThumbnailUrlRef.value\n        && listType === 'image-card'\n      )\n    })\n    async function handleRetryClick(): Promise<void> {\n      const onRetry = NUpload.onRetryRef.value\n      if (onRetry) {\n        const onRetryReturn = await onRetry({ file: props.file })\n        if (onRetryReturn === false) {\n          return\n        }\n      }\n      NUpload.submit({ fileId: props.file.id })\n    }\n    function handleRemoveOrCancelClick(e: MouseEvent): void {\n      e.preventDefault()\n      const { file } = props\n      if (['finished', 'pending', 'error'].includes(file.status)) {\n        handleRemove(file)\n      }\n      else if (['uploading'].includes(file.status)) {\n        handleAbort(file)\n      }\n      else {\n        warn('upload', 'The button clicked type is unknown.')\n      }\n    }\n    function handleDownloadClick(e: MouseEvent): void {\n      e.preventDefault()\n      handleDownload(props.file)\n    }\n    function handleRemove(file: UploadSettledFileInfo): void {\n      const {\n        xhrMap,\n        doChange,\n        onRemoveRef: { value: onRemove },\n        mergedFileListRef: { value: mergedFileList }\n      } = NUpload\n      void Promise.resolve(\n        onRemove\n          ? onRemove({\n              file: Object.assign({}, file),\n              fileList: mergedFileList,\n              index: props.index\n            })\n          : true\n      ).then((result) => {\n        if (result === false)\n          return\n        const fileAfterChange = Object.assign({}, file, {\n          status: 'removed'\n        })\n        xhrMap.delete(file.id)\n        doChange(fileAfterChange, undefined, {\n          remove: true\n        })\n      })\n    }\n    function handleDownload(file: UploadSettledFileInfo): void {\n      const {\n        onDownloadRef: { value: onDownload },\n        customDownloadRef: { value: customDownload }\n      } = NUpload\n      void Promise.resolve(\n        onDownload ? onDownload(Object.assign({}, file)) : true\n      ).then((res) => {\n        if (res !== false) {\n          if (customDownload) {\n            customDownload(Object.assign({}, file))\n          }\n          else {\n            download(file.url, file.name)\n          }\n        }\n      })\n    }\n    function handleAbort(file: UploadSettledFileInfo): void {\n      const { xhrMap } = NUpload\n      const xhr = xhrMap.get(file.id)\n      xhr?.abort()\n      handleRemove(Object.assign({}, file))\n    }\n    function handlePreviewClick(e: MouseEvent): void {\n      const {\n        onPreviewRef: { value: onPreview }\n      } = NUpload\n\n      if (onPreview) {\n        onPreview(props.file, {\n          event: e\n        })\n      }\n      else if (props.listType === 'image-card') {\n        const { value } = imageRef\n        if (!value)\n          return\n        value.showPreview()\n      }\n    }\n\n    const deriveFileThumbnailUrl = async (): Promise<void> => {\n      const { listType } = props\n      if (listType !== 'image' && listType !== 'image-card') {\n        return\n      }\n      if (NUpload.shouldUseThumbnailUrlRef.value(props.file)) {\n        thumbnailUrlRef.value = await NUpload.getFileThumbnailUrlResolver(\n          props.file\n        )\n      }\n    }\n\n    watchEffect(() => {\n      void deriveFileThumbnailUrl()\n    })\n\n    return {\n      mergedTheme: NUpload.mergedThemeRef,\n      progressStatus: progressStatusRef,\n      buttonType: buttonTypeRef,\n      showProgress: showProgressRef,\n      disabled: NUpload.mergedDisabledRef,\n      showCancelButton: showCancelButtonRef,\n      showRemoveButton: showRemoveButtonRef,\n      showDownloadButton: showDownloadButtonRef,\n      showRetryButton: showRetryButtonRef,\n      showPreviewButton: showPreviewButtonRef,\n      mergedThumbnailUrl: mergedThumbnailUrlRef,\n      shouldUseThumbnailUrl: NUpload.shouldUseThumbnailUrlRef,\n      renderIcon: NUpload.renderIconRef,\n      imageRef,\n      handleRemoveOrCancelClick,\n      handleDownloadClick,\n      handleRetryClick,\n      handlePreviewClick\n    }\n  },\n  render() {\n    const { clsPrefix, mergedTheme, listType, file, renderIcon } = this\n\n    // if there is text list type, show file icon\n    let icon: VNode\n\n    const isImageType = listType === 'image'\n    const isImageCardType = listType === 'image-card'\n\n    if (isImageType || isImageCardType) {\n      icon\n        = !this.shouldUseThumbnailUrl(file) || !this.mergedThumbnailUrl ? (\n          <span class={`${clsPrefix}-upload-file-info__thumbnail`}>\n            {renderIcon ? (\n              renderIcon(file)\n            ) : isImageFile(file) ? (\n              <NBaseIcon clsPrefix={clsPrefix}>\n                {{ default: renderImageIcon }}\n              </NBaseIcon>\n            ) : (\n              <NBaseIcon clsPrefix={clsPrefix}>\n                {{ default: renderDocumentIcon }}\n              </NBaseIcon>\n            )}\n          </span>\n        ) : (\n          <a\n            rel=\"noopener noreferer\"\n            target=\"_blank\"\n            href={file.url || undefined}\n            class={`${clsPrefix}-upload-file-info__thumbnail`}\n            onClick={this.handlePreviewClick}\n          >\n            {listType === 'image-card' ? (\n              <NImage\n                src={this.mergedThumbnailUrl || undefined}\n                previewSrc={file.url || undefined}\n                alt={file.name}\n                ref=\"imageRef\"\n              />\n            ) : (\n              <img src={this.mergedThumbnailUrl || undefined} alt={file.name} />\n            )}\n          </a>\n        )\n    }\n    else {\n      icon = (\n        <span class={`${clsPrefix}-upload-file-info__thumbnail`}>\n          {renderIcon ? (\n            renderIcon(file)\n          ) : (\n            <NBaseIcon clsPrefix={clsPrefix}>\n              {{ default: () => <AttachIcon /> }}\n            </NBaseIcon>\n          )}\n        </span>\n      )\n    }\n\n    const progress = (\n      <NUploadProgress\n        show={this.showProgress}\n        percentage={file.percentage || 0}\n        status={this.progressStatus}\n      />\n    )\n\n    const showName = listType === 'text' || listType === 'image'\n\n    return (\n      <div\n        class={[\n          `${clsPrefix}-upload-file`,\n          `${clsPrefix}-upload-file--${this.progressStatus}-status`,\n          file.url\n          && file.status !== 'error'\n          && listType !== 'image-card'\n          && `${clsPrefix}-upload-file--with-url`,\n          `${clsPrefix}-upload-file--${listType}-type`\n        ]}\n      >\n        <div class={`${clsPrefix}-upload-file-info`}>\n          {icon}\n          <div class={`${clsPrefix}-upload-file-info__name`}>\n            {showName\n              && (file.url && file.status !== 'error' ? (\n                <a\n                  rel=\"noopener noreferer\"\n                  target=\"_blank\"\n                  href={file.url || undefined}\n                  onClick={this.handlePreviewClick}\n                >\n                  {file.name}\n                </a>\n              ) : (\n                <span onClick={this.handlePreviewClick}>{file.name}</span>\n              ))}\n            {isImageType && progress}\n          </div>\n          <div\n            class={[\n              `${clsPrefix}-upload-file-info__action`,\n              `${clsPrefix}-upload-file-info__action--${listType}-type`\n            ]}\n          >\n            {this.showPreviewButton ? (\n              <NButton\n                key=\"preview\"\n                quaternary\n                type={this.buttonType}\n                onClick={this.handlePreviewClick}\n                theme={mergedTheme.peers.Button}\n                themeOverrides={mergedTheme.peerOverrides.Button}\n                builtinThemeOverrides={buttonThemeOverrides}\n              >\n                {{\n                  icon: () => (\n                    <NBaseIcon clsPrefix={clsPrefix}>\n                      {{ default: () => <EyeIcon /> }}\n                    </NBaseIcon>\n                  )\n                }}\n              </NButton>\n            ) : null}\n            {(this.showRemoveButton || this.showCancelButton)\n              && !this.disabled && (\n              <NButton\n                key=\"cancelOrTrash\"\n                theme={mergedTheme.peers.Button}\n                themeOverrides={mergedTheme.peerOverrides.Button}\n                quaternary\n                builtinThemeOverrides={buttonThemeOverrides}\n                type={this.buttonType}\n                onClick={this.handleRemoveOrCancelClick}\n              >\n                {{\n                  icon: () => (\n                    <NIconSwitchTransition>\n                      {{\n                        default: () =>\n                          this.showRemoveButton ? (\n                            <NBaseIcon clsPrefix={clsPrefix} key=\"trash\">\n                              {{ default: () => <TrashIcon /> }}\n                            </NBaseIcon>\n                          ) : (\n                            <NBaseIcon clsPrefix={clsPrefix} key=\"cancel\">\n                              {{ default: () => <CancelIcon /> }}\n                            </NBaseIcon>\n                          )\n                      }}\n                    </NIconSwitchTransition>\n                  )\n                }}\n              </NButton>\n            )}\n            {this.showRetryButton && !this.disabled && (\n              <NButton\n                key=\"retry\"\n                quaternary\n                type={this.buttonType}\n                onClick={this.handleRetryClick}\n                theme={mergedTheme.peers.Button}\n                themeOverrides={mergedTheme.peerOverrides.Button}\n                builtinThemeOverrides={buttonThemeOverrides}\n              >\n                {{\n                  icon: () => (\n                    <NBaseIcon clsPrefix={clsPrefix}>\n                      {{ default: () => <RetryIcon /> }}\n                    </NBaseIcon>\n                  )\n                }}\n              </NButton>\n            )}\n            {this.showDownloadButton ? (\n              <NButton\n                key=\"download\"\n                quaternary\n                type={this.buttonType}\n                onClick={this.handleDownloadClick}\n                theme={mergedTheme.peers.Button}\n                themeOverrides={mergedTheme.peerOverrides.Button}\n                builtinThemeOverrides={buttonThemeOverrides}\n              >\n                {{\n                  icon: () => (\n                    <NBaseIcon clsPrefix={clsPrefix}>\n                      {{ default: () => <DownloadIcon /> }}\n                    </NBaseIcon>\n                  )\n                }}\n              </NButton>\n            ) : null}\n          </div>\n        </div>\n        {!isImageType && progress}\n      </div>\n    )\n  }\n})\n"
  },
  {
    "path": "src/upload/src/UploadFileList.tsx",
    "content": "import type { CSSProperties, VNode } from 'vue'\nimport { computed, defineComponent, h, inject } from 'vue'\nimport { NFadeInExpandTransition } from '../../_internal'\nimport { throwError } from '../../_utils'\nimport { NImageGroup } from '../../image'\nimport { uploadInjectionKey } from './interface'\nimport NUploadFile from './UploadFile'\nimport NUploadTrigger from './UploadTrigger'\n\nexport default defineComponent({\n  name: 'UploadFileList',\n  setup(_, { slots }) {\n    const NUpload = inject(uploadInjectionKey, null)\n    if (!NUpload) {\n      throwError(\n        'upload-file-list',\n        '`n-upload-file-list` must be placed inside `n-upload`.'\n      )\n    }\n\n    const {\n      abstractRef,\n      mergedClsPrefixRef,\n      listTypeRef,\n      mergedFileListRef,\n      fileListClassRef,\n      fileListStyleRef,\n      cssVarsRef,\n      themeClassRef,\n      maxReachedRef,\n      showTriggerRef,\n      imageGroupPropsRef\n    } = NUpload\n\n    const isImageCardTypeRef = computed(\n      () => listTypeRef.value === 'image-card'\n    )\n\n    const renderFileList = (): VNode[] =>\n      mergedFileListRef.value.map((file, index) => (\n        <NUploadFile\n          clsPrefix={mergedClsPrefixRef.value}\n          key={file.id}\n          file={file}\n          index={index}\n          listType={listTypeRef.value}\n        />\n      ))\n\n    const renderUploadFileList = (): VNode =>\n      isImageCardTypeRef.value ? (\n        <NImageGroup {...imageGroupPropsRef.value}>\n          {{ default: renderFileList }}\n        </NImageGroup>\n      ) : (\n        <NFadeInExpandTransition group>\n          {{\n            default: renderFileList\n          }}\n        </NFadeInExpandTransition>\n      )\n\n    return () => {\n      const { value: mergedClsPrefix } = mergedClsPrefixRef\n      const { value: abstract } = abstractRef\n      return (\n        <div\n          class={[\n            `${mergedClsPrefix}-upload-file-list`,\n            isImageCardTypeRef.value\n            && `${mergedClsPrefix}-upload-file-list--grid`,\n            abstract ? themeClassRef?.value : undefined,\n            fileListClassRef.value\n          ]}\n          style={[\n            abstract && cssVarsRef ? cssVarsRef.value : '',\n            fileListStyleRef.value as CSSProperties\n          ]}\n        >\n          {renderUploadFileList()}\n          {showTriggerRef.value\n            && !maxReachedRef.value\n            && isImageCardTypeRef.value && (\n            <NUploadTrigger>{slots}</NUploadTrigger>\n          )}\n        </div>\n      )\n    }\n  }\n})\n"
  },
  {
    "path": "src/upload/src/UploadProgress.tsx",
    "content": "import type { PropType } from 'vue'\nimport { defineComponent, h, inject } from 'vue'\nimport { NFadeInExpandTransition } from '../../_internal'\nimport { NProgress } from '../../progress'\nimport { uploadInjectionKey } from './interface'\n\nexport default defineComponent({\n  name: 'UploadProgress',\n  props: {\n    show: Boolean,\n    percentage: {\n      type: Number,\n      required: true\n    },\n    status: {\n      type: String as PropType<'info' | 'error' | 'success'>,\n      required: true\n    }\n  },\n  setup() {\n    const NUpload = inject(uploadInjectionKey)!\n    return {\n      mergedTheme: NUpload.mergedThemeRef\n    }\n  },\n  render() {\n    return (\n      <NFadeInExpandTransition>\n        {{\n          default: () =>\n            this.show ? (\n              <NProgress\n                type=\"line\"\n                showIndicator={false}\n                percentage={this.percentage}\n                status={this.status}\n                height={2}\n                theme={this.mergedTheme.peers.Progress}\n                themeOverrides={this.mergedTheme.peerOverrides.Progress}\n              />\n            ) : null\n        }}\n      </NFadeInExpandTransition>\n    )\n  }\n})\n"
  },
  {
    "path": "src/upload/src/UploadTrigger.tsx",
    "content": "import type { SlotsType, VNode } from 'vue'\nimport type { UploadTriggerDefaultSlotOptions } from './interface'\nimport { computed, defineComponent, h, inject } from 'vue'\nimport { NBaseIcon } from '../../_internal'\nimport { AddIcon } from '../../_internal/icons'\nimport { resolveSlot, throwError } from '../../_utils'\nimport { uploadInjectionKey } from './interface'\nimport NUploadDragger from './UploadDragger'\nimport { getFilesFromEntries } from './utils'\n\nexport interface UploadTriggerSlots {\n  default?: (options: UploadTriggerDefaultSlotOptions) => VNode[]\n}\n\nexport default defineComponent({\n  name: 'UploadTrigger',\n  props: {\n    abstract: Boolean\n  },\n  slots: Object as SlotsType<UploadTriggerSlots>,\n  setup(props, { slots }) {\n    const NUpload = inject(uploadInjectionKey, null)\n    if (!NUpload) {\n      throwError(\n        'upload-trigger',\n        '`n-upload-trigger` must be placed inside `n-upload`.'\n      )\n    }\n    const {\n      mergedClsPrefixRef,\n      mergedDisabledRef,\n      maxReachedRef,\n      listTypeRef,\n      dragOverRef,\n      openOpenFileDialog,\n      draggerInsideRef,\n      handleFileAddition,\n      mergedDirectoryDndRef,\n      triggerClassRef,\n      triggerStyleRef\n    } = NUpload\n\n    const isImageCardTypeRef = computed(\n      () => listTypeRef.value === 'image-card'\n    )\n\n    function handleTriggerClick(): void {\n      if (mergedDisabledRef.value || maxReachedRef.value)\n        return\n      openOpenFileDialog()\n    }\n    function handleTriggerDragOver(e: DragEvent): void {\n      e.preventDefault()\n      dragOverRef.value = true\n    }\n    function handleTriggerDragEnter(e: DragEvent): void {\n      e.preventDefault()\n      dragOverRef.value = true\n    }\n    function handleTriggerDragLeave(e: DragEvent): void {\n      e.preventDefault()\n      dragOverRef.value = false\n    }\n    function handleTriggerDrop(e: DragEvent): void {\n      e.preventDefault()\n      if (\n        !draggerInsideRef.value\n        || mergedDisabledRef.value\n        || maxReachedRef.value\n      ) {\n        dragOverRef.value = false\n        return\n      }\n      const dataTransferItems = e.dataTransfer?.items\n      if (dataTransferItems?.length) {\n        void getFilesFromEntries(\n          Array.from(dataTransferItems).map(item => item.webkitGetAsEntry()),\n          mergedDirectoryDndRef.value\n        )\n          .then((files) => {\n            handleFileAddition(files)\n          })\n          .finally(() => {\n            dragOverRef.value = false\n          })\n      }\n      else {\n        dragOverRef.value = false\n      }\n    }\n\n    return () => {\n      const { value: mergedClsPrefix } = mergedClsPrefixRef\n      return props.abstract ? (\n        slots.default?.({\n          handleClick: handleTriggerClick,\n          handleDrop: handleTriggerDrop,\n          handleDragOver: handleTriggerDragOver,\n          handleDragEnter: handleTriggerDragEnter,\n          handleDragLeave: handleTriggerDragLeave\n        })\n      ) : (\n        <div\n          class={[\n            `${mergedClsPrefix}-upload-trigger`,\n            (mergedDisabledRef.value || maxReachedRef.value)\n            && `${mergedClsPrefix}-upload-trigger--disabled`,\n            isImageCardTypeRef.value\n            && `${mergedClsPrefix}-upload-trigger--image-card`,\n            triggerClassRef.value\n          ]}\n          style={triggerStyleRef.value}\n          onClick={handleTriggerClick}\n          onDrop={handleTriggerDrop}\n          onDragover={handleTriggerDragOver}\n          onDragenter={handleTriggerDragEnter}\n          onDragleave={handleTriggerDragLeave}\n        >\n          {isImageCardTypeRef.value ? (\n            <NUploadDragger>\n              {{\n                default: () =>\n                  resolveSlot(slots.default, () => [\n                    <NBaseIcon clsPrefix={mergedClsPrefix}>\n                      {{ default: () => <AddIcon /> }}\n                    </NBaseIcon>\n                  ])\n              }}\n            </NUploadDragger>\n          ) : (\n            slots\n          )}\n        </div>\n      )\n    }\n  }\n})\n"
  },
  {
    "path": "src/upload/src/icons.tsx",
    "content": "import { h } from 'vue'\n\n/**\n * Since image is too large compared with normal icons, we keep it inside upload\n * now.\n */\n\nexport function renderImageIcon() {\n  return (\n    <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 28 28\">\n      <g fill=\"none\">\n        <path\n          d=\"M21.75 3A3.25 3.25 0 0 1 25 6.25v15.5A3.25 3.25 0 0 1 21.75 25H6.25A3.25 3.25 0 0 1 3 21.75V6.25A3.25 3.25 0 0 1 6.25 3h15.5zm.583 20.4l-7.807-7.68a.75.75 0 0 0-.968-.07l-.084.07l-7.808 7.68c.183.065.38.1.584.1h15.5c.204 0 .4-.035.583-.1l-7.807-7.68l7.807 7.68zM21.75 4.5H6.25A1.75 1.75 0 0 0 4.5 6.25v15.5c0 .208.036.408.103.593l7.82-7.692a2.25 2.25 0 0 1 3.026-.117l.129.117l7.82 7.692c.066-.185.102-.385.102-.593V6.25a1.75 1.75 0 0 0-1.75-1.75zm-3.25 3a2.5 2.5 0 1 1 0 5a2.5 2.5 0 0 1 0-5zm0 1.5a1 1 0 1 0 0 2a1 1 0 0 0 0-2z\"\n          fill=\"currentColor\"\n        >\n        </path>\n      </g>\n    </svg>\n  )\n}\n\nexport function renderDocumentIcon() {\n  return (\n    <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 28 28\">\n      <g fill=\"none\">\n        <path\n          d=\"M6.4 2A2.4 2.4 0 0 0 4 4.4v19.2A2.4 2.4 0 0 0 6.4 26h15.2a2.4 2.4 0 0 0 2.4-2.4V11.578c0-.729-.29-1.428-.805-1.944l-6.931-6.931A2.4 2.4 0 0 0 14.567 2H6.4zm-.9 2.4a.9.9 0 0 1 .9-.9H14V10a2 2 0 0 0 2 2h6.5v11.6a.9.9 0 0 1-.9.9H6.4a.9.9 0 0 1-.9-.9V4.4zm16.44 6.1H16a.5.5 0 0 1-.5-.5V4.06l6.44 6.44z\"\n          fill=\"currentColor\"\n        >\n        </path>\n      </g>\n    </svg>\n  )\n}\n"
  },
  {
    "path": "src/upload/src/interface.ts",
    "content": "import type { CSSProperties, Ref, VNodeChild } from 'vue'\nimport type { MergedTheme } from '../../_mixins'\nimport type { ImageGroupProps } from '../../image'\nimport type { UploadTheme } from '../styles'\nimport type {\n  UploadCustomRequestOptions,\n  UploadFileInfo,\n  UploadOnDownload,\n  UploadOnFinish,\n  UploadOnRemove,\n  UploadSettledFileInfo\n} from './public-types'\nimport { createInjectionKey } from '../../_utils'\n\nexport type ShouldUseThumbnailUrl = (file: UploadSettledFileInfo) => boolean\n\nexport type FuncOrRecordOrUndef<T = string>\n  = | Record<string, T>\n    | (({ file }: { file: UploadSettledFileInfo }) => Record<string, T>)\n    | undefined\n\nexport interface UploadInternalInst {\n  doChange: DoChange\n  xhrMap: Map<string, XMLHttpRequest>\n  isErrorState: ((xhr: XMLHttpRequest) => boolean) | undefined\n  onError: OnError | undefined\n  onFinish: UploadOnFinish | undefined\n}\n\nexport type DoChange = (\n  fileAfterChange: UploadSettledFileInfo,\n  event?: ProgressEvent | Event,\n  options?: {\n    append?: boolean\n    remove?: boolean\n  }\n) => void\n\nexport type OnUpdateFileList = (fileList: UploadSettledFileInfo[]) => void\n\nexport type RenderIcon = (file: UploadSettledFileInfo) => VNodeChild\n\nexport interface UploadInjection {\n  mergedClsPrefixRef: Ref<string>\n  mergedThemeRef: Ref<MergedTheme<UploadTheme>>\n  showCancelButtonRef: Ref<boolean>\n  showRemoveButtonRef: Ref<boolean>\n  showDownloadButtonRef: Ref<boolean>\n  showRetryButtonRef: Ref<boolean>\n  showTriggerRef: Ref<boolean>\n  mergedFileListRef: Ref<UploadSettledFileInfo[]>\n  onRemoveRef: Ref<UploadOnRemove | undefined>\n  onDownloadRef: Ref<UploadOnDownload | undefined>\n  customDownloadRef: Ref<UploadOnDownload | undefined>\n  xhrMap: Map<string, XMLHttpRequest>\n  showPreviewButtonRef: Ref<boolean>\n  onPreviewRef: Ref<OnPreview | undefined>\n  listTypeRef: Ref<ListType>\n  dragOverRef: Ref<boolean>\n  draggerInsideRef: { value: boolean }\n  fileListClassRef: Ref<string | undefined>\n  fileListStyleRef: Ref<string | CSSProperties | undefined>\n  mergedDisabledRef: Ref<boolean>\n  maxReachedRef: Ref<boolean>\n  abstractRef: Ref<boolean>\n  imageGroupPropsRef: Ref<ImageGroupProps | undefined>\n  cssVarsRef: undefined | Ref<CSSProperties>\n  themeClassRef: undefined | Ref<string>\n  mergedDirectoryDndRef: Ref<boolean>\n  acceptRef: Ref<string | undefined>\n  triggerClassRef: Ref<string | undefined>\n  triggerStyleRef: Ref<CSSProperties | string | undefined>\n  doChange: DoChange\n  onRender: undefined | (() => void)\n  submit: (options?: { fileId?: string, retry?: boolean }) => void\n  onRetryRef: Ref<undefined | OnRetry>\n  shouldUseThumbnailUrlRef: Ref<ShouldUseThumbnailUrl>\n  getFileThumbnailUrlResolver: (\n    file: UploadSettledFileInfo\n  ) => Promise<string> | string\n  renderIconRef: Ref<RenderIcon | undefined>\n  handleFileAddition: (files: FileAndEntry[] | null, e?: Event) => void\n  openOpenFileDialog: () => void\n}\n\nexport const uploadInjectionKey\n  = createInjectionKey<UploadInjection>('n-upload')\n\nexport interface XhrHandlers {\n  handleXHRLoad: (e: ProgressEvent) => void\n  handleXHRAbort: (e: ProgressEvent) => void\n  handleXHRProgress: (e: ProgressEvent) => void\n  handleXHRError: (e: ProgressEvent) => void\n}\n\nexport type OnBeforeUpload = (data: {\n  file: UploadSettledFileInfo\n  fileList: UploadSettledFileInfo[]\n}) => Promise<boolean | void> | boolean | void\n\nexport type ListType = 'text' | 'image' | 'image-card'\n\nexport type OnPreview = (\n  file: UploadSettledFileInfo,\n  detail: {\n    event: MouseEvent\n  }\n) => void\n\nexport type CreateThumbnailUrl = (\n  file: File | null,\n  fileInfo: UploadSettledFileInfo\n) => Promise<string> | string | undefined\n\nexport type CustomRequest = (options: UploadCustomRequestOptions) => void\n\nexport type OnError = ({\n  file,\n  event\n}: {\n  file: UploadSettledFileInfo\n  event?: ProgressEvent\n}) => UploadFileInfo | undefined | void\n\nexport type OnRetry = ({\n  file\n}: {\n  file: UploadSettledFileInfo\n}) => Promise<boolean | void> | boolean | void\n\nexport interface FileAndEntry {\n  file: File\n  entry: FileSystemFileEntry | null\n  source: 'dnd' | 'input'\n}\n\nexport interface UploadTriggerDefaultSlotOptions {\n  handleClick: () => void\n  handleDragOver: (e: DragEvent) => void\n  handleDragEnter: (e: DragEvent) => void\n  handleDragLeave: (e: DragEvent) => void\n  handleDrop: (e: DragEvent) => void\n}\n"
  },
  {
    "path": "src/upload/src/public-types.ts",
    "content": "import type { FuncOrRecordOrUndef } from './interface'\n\nexport type { UploadProps } from './Upload'\n\nexport interface UploadInst {\n  openOpenFileDialog: () => void\n  submit: (options?: { fileId?: string, retry?: boolean }) => void\n  clear: () => void\n}\n\nexport interface UploadFileInfo {\n  id: string\n  name: string\n  batchId?: string | null\n  percentage?: number | null\n  status: 'pending' | 'uploading' | 'finished' | 'removed' | 'error'\n  url?: string | null\n  file?: File | null\n  thumbnailUrl?: string | null\n  type?: string | null\n  fullPath?: string | null\n}\n\nexport interface UploadCustomRequestOptions {\n  file: UploadSettledFileInfo\n  action?: string\n  withCredentials?: boolean\n  data?: FuncOrRecordOrUndef<string | Blob>\n  headers?: FuncOrRecordOrUndef\n  onProgress: (e: { percent: number }) => void\n  onFinish: () => void\n  onError: () => void\n}\n\nexport type UploadSettledFileInfo = Required<UploadFileInfo>\n\nexport type UploadOnChange = (data: {\n  file: UploadSettledFileInfo\n  fileList: UploadSettledFileInfo[]\n  event: ProgressEvent | Event | undefined\n}) => void\n\nexport type UploadOnFinish = ({\n  file,\n  event\n}: {\n  file: UploadSettledFileInfo\n  event?: ProgressEvent\n}) => UploadFileInfo | undefined | void\n\nexport type UploadOnRemove = (data: {\n  file: UploadSettledFileInfo\n  fileList: UploadSettledFileInfo[]\n  index: number\n}) => Promise<boolean> | boolean | any\n\nexport type UploadOnDownload = (\n  file: UploadSettledFileInfo\n) => Promise<boolean> | boolean | any\n"
  },
  {
    "path": "src/upload/src/styles/index.cssr.ts",
    "content": "import { fadeInHeightExpandTransition } from '../../../_styles/transitions/fade-in-height-expand.cssr'\nimport { iconSwitchTransition } from '../../../_styles/transitions/icon-switch.cssr'\nimport { c, cB, cE, cM } from '../../../_utils/cssr'\n\nexport default c([\n  cB('upload', 'width: 100%;', [\n    cM('dragger-inside', [\n      cB('upload-trigger', `\n        display: block;\n      `)\n    ]),\n    cM('drag-over', [\n      cB('upload-dragger', `\n        border: var(--n-dragger-border-hover);\n      `)\n    ])\n  ]),\n  cB('upload-dragger', `\n    cursor: pointer;\n    box-sizing: border-box;\n    width: 100%;\n    text-align: center;\n    border-radius: var(--n-border-radius);\n    padding: 24px;\n    opacity: 1;\n    transition:\n      opacity .3s var(--n-bezier),\n      border-color .3s var(--n-bezier),\n      background-color .3s var(--n-bezier);\n    background-color: var(--n-dragger-color);\n    border: var(--n-dragger-border);\n  `, [\n    c('&:hover', `\n      border: var(--n-dragger-border-hover);\n    `),\n    cM('disabled', `\n      cursor: not-allowed;\n    `)\n  ]),\n  cB('upload-trigger', `\n    display: inline-block;\n    box-sizing: border-box;\n    opacity: 1;\n    transition: opacity .3s var(--n-bezier);\n  `, [\n    c('+', [\n      cB('upload-file-list', 'margin-top: 8px;')\n    ]),\n    cM('disabled', `\n      opacity: var(--n-item-disabled-opacity);\n      cursor: not-allowed;\n    `),\n    cM('image-card', `\n      width: 96px;\n      height: 96px;\n    `, [\n      cB('base-icon', `\n        font-size: 24px;\n      `),\n      cB('upload-dragger', `\n        padding: 0;\n        height: 100%;\n        width: 100%;\n        display: flex;\n        align-items: center;\n        justify-content: center;\n      `)\n    ])\n  ]),\n  cB('upload-file-list', `\n    line-height: var(--n-line-height);\n    opacity: 1;\n    transition: opacity .3s var(--n-bezier);\n  `, [\n    c('a, img', 'outline: none;'),\n    cM('disabled', `\n      opacity: var(--n-item-disabled-opacity);\n      cursor: not-allowed;\n    `, [\n      cB('upload-file', 'cursor: not-allowed;')\n    ]),\n    cM('grid', `\n      display: grid;\n      grid-template-columns: repeat(auto-fill, 96px);\n      grid-gap: 8px;\n      margin-top: 0;\n    `),\n    cB('upload-file', `\n      display: block;\n      box-sizing: border-box;\n      cursor: default;\n      padding: 0px 12px 0 6px;\n      transition: background-color .3s  var(--n-bezier);\n      border-radius: var(--n-border-radius);\n    `, [\n      fadeInHeightExpandTransition(),\n      cB('progress', [\n        fadeInHeightExpandTransition({\n          foldPadding: true\n        })\n      ]),\n      c('&:hover', `\n        background-color: var(--n-item-color-hover);\n      `, [\n        cB('upload-file-info', [\n          cE('action', `\n            opacity: 1;\n          `)\n        ])\n      ]),\n      cM('image-type', `\n        border-radius: var(--n-border-radius);\n        text-decoration: underline;\n        text-decoration-color: #0000;\n      `, [\n        cB('upload-file-info', `\n          padding-top: 0px;\n          padding-bottom: 0px;\n          width: 100%;\n          height: 100%;\n          display: flex;\n          justify-content: space-between;\n          align-items: center;\n          padding: 6px 0;\n        `, [\n          cB('progress', `\n            padding: 2px 0;\n            margin-bottom: 0;\n          `),\n          cE('name', `\n            padding: 0 8px;\n          `),\n          cE('thumbnail', `\n            width: 32px;\n            height: 32px;\n            font-size: 28px;\n            display: flex;\n            justify-content: center;\n            align-items: center;\n          `, [\n            c('img', `\n              width: 100%;\n            `)\n          ])\n        ])\n      ]),\n      cM('text-type', [\n        cB('progress', `\n          box-sizing: border-box;\n          padding-bottom: 6px;\n          margin-bottom: 6px;\n        `)\n      ]),\n      cM('image-card-type', `\n        position: relative;\n        width: 96px;\n        height: 96px;\n        border: var(--n-item-border-image-card);\n        border-radius: var(--n-border-radius);\n        padding: 0;\n        display: flex;\n        align-items: center;\n        justify-content: center;\n        transition: border-color .3s var(--n-bezier), background-color .3s var(--n-bezier);\n        border-radius: var(--n-border-radius);\n        overflow: hidden;\n      `, [\n        cB('progress', `\n          position: absolute;\n          left: 8px;\n          bottom: 8px;\n          right: 8px;\n          width: unset;\n        `),\n        cB('upload-file-info', `\n          padding: 0;\n          width: 100%;\n          height: 100%;\n        `, [\n          cE('thumbnail', `\n            width: 100%;\n            height: 100%;\n            display: flex;\n            flex-direction: column;\n            align-items: center;\n            justify-content: center;\n            font-size: 36px;\n          `, [\n            c('img', `\n              width: 100%;\n            `)\n          ])\n        ]),\n        c('&::before', `\n          position: absolute;\n          z-index: 1;\n          left: 0;\n          right: 0;\n          top: 0;\n          bottom: 0;\n          border-radius: inherit;\n          opacity: 0;\n          transition: opacity .2s var(--n-bezier);\n          content: \"\";\n        `),\n        c('&:hover', [\n          c('&::before', 'opacity: 1;'),\n          cB('upload-file-info', [\n            cE('thumbnail', 'opacity: .12;')\n          ])\n        ])\n      ]),\n      cM('error-status', [\n        c('&:hover', `\n          background-color: var(--n-item-color-hover-error);\n        `),\n        cB('upload-file-info', [\n          cE('name', 'color: var(--n-item-text-color-error);'),\n          cE('thumbnail', 'color: var(--n-item-text-color-error);')\n        ]),\n        cM('image-card-type', `\n          border: var(--n-item-border-image-card-error);\n        `)\n      ]),\n      cM('with-url', `\n        cursor: pointer;\n      `, [\n        cB('upload-file-info', [\n          cE('name', `\n            color: var(--n-item-text-color-success);\n            text-decoration-color: var(--n-item-text-color-success);\n          `, [\n            c('a', `\n              text-decoration: underline;\n            `)\n          ])\n        ])\n      ]),\n      cB('upload-file-info', `\n        position: relative;\n        padding-top: 6px;\n        padding-bottom: 6px;\n        display: flex;\n        flex-wrap: nowrap;\n      `, [\n        cE('thumbnail', `\n          font-size: 18px;\n          opacity: 1;\n          transition: opacity .2s var(--n-bezier);\n          color: var(--n-item-icon-color);\n        `, [\n          cB('base-icon', `\n            margin-right: 2px;\n            vertical-align: middle;\n            transition: color .3s var(--n-bezier);\n          `)\n        ]),\n        cE('action', `\n          padding-top: inherit;\n          padding-bottom: inherit;\n          position: absolute;\n          right: 0;\n          top: 0;\n          bottom: 0;\n          width: 80px;\n          display: flex;\n          align-items: center;\n          transition: opacity .2s var(--n-bezier);\n          justify-content: flex-end;\n          opacity: 0;\n        `, [\n          cB('button', [\n            c('&:not(:last-child)', {\n              marginRight: '4px'\n            }),\n            cB('base-icon', [\n              c('svg', [\n                iconSwitchTransition()\n              ])\n            ])\n          ]),\n          cM('image-type', `\n            position: relative;\n            max-width: 80px;\n            width: auto;\n          `),\n          cM('image-card-type', `\n            z-index: 2;\n            position: absolute;\n            width: 100%;\n            height: 100%;\n            left: 0;\n            right: 0;\n            bottom: 0;\n            top: 0;\n            display: flex;\n            justify-content: center;\n            align-items: center;\n          `)\n        ]),\n        cE('name', `\n          color: var(--n-item-text-color);\n          flex: 1;\n          display: flex;\n          justify-content: center;\n          text-overflow: ellipsis;\n          overflow: hidden;\n          flex-direction: column;\n          text-decoration-color: #0000;\n          font-size: var(--n-font-size);\n          transition:\n            color .3s var(--n-bezier),\n            text-decoration-color .3s var(--n-bezier); \n        `, [\n          c('a', `\n            color: inherit;\n            text-decoration: underline;\n          `)\n        ])\n      ])\n    ])\n  ]),\n  cB('upload-file-input', `\n    display: none;\n    width: 0;\n    height: 0;\n    opacity: 0;\n  `)\n])\n"
  },
  {
    "path": "src/upload/src/styles/rtl.cssr.ts",
    "content": "import { cB, cM } from '../../../_utils/cssr'\n\nexport default cB('upload', [\n  cM('rtl', `\n    direction: rtl;\n    text-align: right;\n  `)\n])\n"
  },
  {
    "path": "src/upload/src/utils.ts",
    "content": "import type { FileAndEntry, ShouldUseThumbnailUrl } from './interface'\nimport type { UploadFileInfo, UploadSettledFileInfo } from './public-types'\nimport { isBrowser } from '../../_utils'\nimport { error } from '../../_utils/naive/warn'\n\nexport function isImageFileType(type: string): boolean {\n  return type.includes('image/')\n}\n\nfunction getExtname(url: string = ''): string {\n  const temp = url.split('/')\n  const filename = temp[temp.length - 1]\n  const filenameWithoutSuffix = filename.split(/#|\\?/)[0]\n  return (/\\.[^./\\\\]*$/.exec(filenameWithoutSuffix) || [''])[0]\n}\n\nconst imageExtensionRegex = /(webp|svg|png|gif|jpg|jpeg|jfif|bmp|dpg|ico)$/i\n\n// Do not need File object\nexport const isImageFile: ShouldUseThumbnailUrl = (file) => {\n  if (file.type) {\n    return isImageFileType(file.type)\n  }\n  const fileNameExtension = getExtname(file.name || '')\n  if (imageExtensionRegex.test(fileNameExtension)) {\n    return true\n  }\n  const url: string = file.thumbnailUrl || file.url || ''\n  const urlExtension = getExtname(url)\n  if (/^data:image\\//.test(url) || imageExtensionRegex.test(urlExtension)) {\n    return true\n  }\n  return false\n}\n\nexport async function createImageDataUrl(file: File): Promise<string> {\n  return await new Promise((resolve) => {\n    if (!file.type || !isImageFileType(file.type)) {\n      resolve('')\n      return\n    }\n    resolve(window.URL.createObjectURL(file))\n  })\n}\n\nexport const environmentSupportFile\n  = isBrowser && window.FileReader && window.File\n\nexport function isFileSystemDirectoryEntry(\n  item: FileSystemEntry | FileSystemFileEntry | FileSystemDirectoryEntry\n): item is FileSystemDirectoryEntry {\n  return item.isDirectory\n}\n\nexport function isFileSystemFileEntry(\n  item: FileSystemEntry | FileSystemFileEntry | FileSystemDirectoryEntry\n): item is FileSystemFileEntry {\n  return item.isFile\n}\n\nexport async function getFilesFromEntries(\n  entries: readonly FileSystemEntry[] | Array<FileSystemEntry | null>,\n  directory: boolean\n): Promise<FileAndEntry[]> {\n  const fileAndEntries: FileAndEntry[] = []\n\n  async function _getFilesFromEntries(\n    entries: readonly FileSystemEntry[] | Array<FileSystemEntry | null>\n  ): Promise<void> {\n    for (const entry of entries) {\n      if (!entry)\n        continue\n      if (directory && isFileSystemDirectoryEntry(entry)) {\n        const directoryReader = entry.createReader()\n        let allEntries: FileSystemEntry[] = []\n        let readEntries: readonly FileSystemEntry[]\n        try {\n          do {\n            readEntries = await new Promise<readonly FileSystemEntry[]>(\n              (resolve, reject) => {\n                directoryReader.readEntries(resolve, reject)\n              }\n            )\n            allEntries = allEntries.concat(readEntries)\n          } while (readEntries.length > 0)\n        }\n        catch (e) {\n          error('upload', 'error happens when handling directory upload', e)\n        }\n        await _getFilesFromEntries(allEntries)\n      }\n      else if (isFileSystemFileEntry(entry)) {\n        try {\n          const file = await new Promise<File>((resolve, reject) => {\n            entry.file(resolve, reject)\n          })\n          fileAndEntries.push({ file, entry, source: 'dnd' })\n        }\n        catch (e) {\n          error('upload', 'error happens when handling file upload', e)\n        }\n      }\n    }\n  }\n\n  await _getFilesFromEntries(entries)\n\n  return fileAndEntries\n}\n\nexport function createSettledFileInfo(\n  fileInfo: UploadFileInfo\n): UploadSettledFileInfo {\n  const {\n    id,\n    name,\n    percentage,\n    status,\n    url,\n    file,\n    thumbnailUrl,\n    type,\n    fullPath,\n    batchId\n  } = fileInfo\n  return {\n    id,\n    name,\n    percentage: percentage ?? null,\n    status,\n    url: url ?? null,\n    file: file ?? null,\n    thumbnailUrl: thumbnailUrl ?? null,\n    type: type ?? null,\n    fullPath: fullPath ?? null,\n    batchId: batchId ?? null\n  }\n}\n\n/**\n * This is a rather simple version. I may fix it later to make it more accurate.\n * I've looked at https://github.com/broofa/mime, however it doesn't has a esm\n * version, so I can't simply use it.\n */\nexport function matchType(\n  name: string,\n  mimeType: string,\n  accept: string\n): boolean {\n  name = name.toLowerCase()\n  mimeType = mimeType.toLocaleLowerCase()\n  accept = accept.toLocaleLowerCase()\n  const acceptAtoms = accept\n    .split(',')\n    .map(acceptAtom => acceptAtom.trim())\n    .filter(Boolean)\n  return acceptAtoms.some((acceptAtom) => {\n    if (acceptAtom.startsWith('.')) {\n      // suffix\n      if (name.endsWith(acceptAtom))\n        return true\n    }\n    else if (acceptAtom.includes('/')) {\n      // mime type\n      const [type, subtype] = mimeType.split('/')\n      const [acceptType, acceptSubtype] = acceptAtom.split('/')\n      if (acceptType === '*' || (type && acceptType && acceptType === type)) {\n        if (\n          acceptSubtype === '*'\n          || (subtype && acceptSubtype && acceptSubtype === subtype)\n        ) {\n          return true\n        }\n      }\n    }\n    else {\n      // invalid type\n      return true\n    }\n    return false\n  })\n}\n"
  },
  {
    "path": "src/upload/styles/dark.ts",
    "content": "import type { UploadTheme } from './light'\nimport { changeColor } from 'seemly'\nimport { commonDark } from '../../_styles/common'\nimport { buttonDark } from '../../button/styles'\nimport { progressDark } from '../../progress/styles'\nimport { self } from './light'\n\nconst uploadDark: UploadTheme = {\n  name: 'Upload',\n  common: commonDark,\n  peers: {\n    Button: buttonDark,\n    Progress: progressDark\n  },\n  self(vars) {\n    const { errorColor } = vars\n    const commonSelf = self(vars)\n    commonSelf.itemColorHoverError = changeColor(errorColor, {\n      alpha: 0.09\n    })\n    return commonSelf\n  }\n}\n\nexport default uploadDark\n"
  },
  {
    "path": "src/upload/styles/index.ts",
    "content": "export { default as uploadDark } from './dark'\nexport { default as uploadLight } from './light'\nexport type { UploadTheme, UploadThemeVars } from './light'\nexport { uploadRtl } from './rtl'\n"
  },
  {
    "path": "src/upload/styles/light.ts",
    "content": "import type { ThemeCommonVars } from '../../_styles/common'\nimport { changeColor } from 'seemly'\nimport { createTheme } from '../../_mixins'\nimport { commonLight } from '../../_styles/common'\nimport { buttonLight } from '../../button/styles'\nimport { progressLight } from '../../progress/styles'\n\nexport function self(vars: ThemeCommonVars) {\n  const {\n    iconColor,\n    primaryColor,\n    errorColor,\n    textColor2,\n    successColor,\n    opacityDisabled,\n    actionColor,\n    borderColor,\n    hoverColor,\n    lineHeight,\n    borderRadius,\n    fontSize\n  } = vars\n  return {\n    fontSize,\n    lineHeight,\n    borderRadius,\n    draggerColor: actionColor,\n    draggerBorder: `1px dashed ${borderColor}`,\n    draggerBorderHover: `1px dashed ${primaryColor}`,\n    itemColorHover: hoverColor,\n    itemColorHoverError: changeColor(errorColor, {\n      alpha: 0.06\n    }),\n    itemTextColor: textColor2,\n    itemTextColorError: errorColor,\n    itemTextColorSuccess: successColor,\n    itemIconColor: iconColor,\n    itemDisabledOpacity: opacityDisabled,\n    itemBorderImageCardError: `1px solid ${errorColor}`,\n    itemBorderImageCard: `1px solid ${borderColor}`\n  }\n}\n\nexport type UploadThemeVars = ReturnType<typeof self>\n\nconst uploadLight = createTheme({\n  name: 'Upload',\n  common: commonLight,\n  peers: {\n    Button: buttonLight,\n    Progress: progressLight\n  },\n  self\n})\n\nexport default uploadLight\nexport type UploadTheme = typeof uploadLight\n"
  },
  {
    "path": "src/upload/styles/rtl.ts",
    "content": "import type { RtlItem } from '../../config-provider/src/internal-interface'\nimport rtlStyle from '../src/styles/rtl.cssr'\n\nexport const uploadRtl: RtlItem = {\n  name: 'Upload',\n  style: rtlStyle\n}\n"
  },
  {
    "path": "src/upload/tests/Upload.spec.tsx",
    "content": "import { mount } from '@vue/test-utils'\nimport { sleep } from 'seemly'\nimport { h } from 'vue'\nimport { NButton } from '../../button'\nimport { NButtonGroup } from '../../button-group'\nimport { NCard } from '../../card'\nimport { NImageGroup } from '../../image'\nimport {\n  NUpload,\n  NUploadDragger,\n  NUploadFileList,\n  NUploadTrigger\n} from '../index'\nimport { matchType } from '../src/utils'\n\nfunction getMockFile(element: Element, files: File[]): void {\n  Object.defineProperty(element, 'files', {\n    get() {\n      return files\n    }\n  })\n}\n\ndescribe('n-upload', () => {\n  it('should work with import on demand', () => {\n    mount(NUpload)\n  })\n\n  it('should work with `show-file-list` prop', async () => {\n    const wrapper = mount(NUpload)\n\n    await wrapper.setProps({ showFileList: true })\n    expect(wrapper.find('.n-upload-file-list').exists()).toBe(true)\n\n    await wrapper.setProps({ showFileList: false })\n    expect(wrapper.find('.n-upload-file-list').exists()).not.toBe(true)\n  })\n\n  it('should work with `disabled` prop', async () => {\n    const wrapper = mount(NUpload)\n    const disabledClasses = ['n-upload-trigger--disabled']\n    for (const disabledClass of disabledClasses) {\n      expect(wrapper.find(disabledClass).exists()).not.toBe(true)\n    }\n    await wrapper.setProps({ disabled: true })\n    for (const disabledClass of disabledClasses) {\n      expect(\n        wrapper.find(`.${disabledClass.split('--')[0]}`).classes()\n      ).toContain(disabledClass)\n    }\n  })\n\n  it('should work with `on-before-upload` prop', async () => {\n    const onBeforeUpload = vi.fn(async () => true)\n    const onChange = vi.fn()\n    const wrapper = mount(NUpload, {\n      props: {\n        onBeforeUpload,\n        onChange\n      }\n    })\n    const input = wrapper.find('input')\n    const fileList = [new File(['index'], 'file.txt')]\n\n    getMockFile(input.element, fileList)\n    await input.trigger('change')\n    await sleep(0)\n    expect(onBeforeUpload).toHaveBeenCalled()\n    expect(onChange).toHaveBeenCalled()\n  })\n\n  it('should work with `list-type` prop', async () => {\n    const wrapper = mount(NUpload, {\n      props: {\n        listType: 'text',\n        action: 'https://www.mocky.io/v2/5e4bafc63100007100d8b70f'\n      },\n      slots: {\n        default: () => 'test'\n      }\n    })\n    const input = wrapper.find('input')\n    const fileList = [new File(['index'], 'file.txt')]\n\n    getMockFile(input.element, fileList)\n    await input.trigger('change')\n\n    await sleep(0)\n    expect(wrapper.findAll('.n-upload-file--text-type').length).toBe(1)\n\n    await wrapper.setProps({\n      listType: 'image'\n    })\n    expect(wrapper.findAll('.n-upload-file--image-type').length).toBe(1)\n\n    await wrapper.setProps({\n      listType: 'image-card'\n    })\n    expect(wrapper.findAll('.n-upload-file--image-card-type').length).toBe(1)\n    expect(wrapper.findAll('.n-upload-trigger--image-card').length).toBe(1)\n    expect(wrapper.findAll('.n-upload-dragger').length).toBe(1)\n  })\n\n  it('should work with `create-thumbnail-url` prop', async () => {\n    const createThumbnailUrl = async (): Promise<string> => '/testThumbUrl.png'\n    const wrapper = mount(NUpload, {\n      props: {\n        listType: 'image',\n        createThumbnailUrl,\n        // It should be aligned with prop's default implementation\n        shouldUseThumbnailUrl: () => true\n      }\n    })\n    const input = wrapper.find('input')\n    const fileList = [new File(['index'], 'file.jpeg')]\n    getMockFile(input.element, fileList)\n    await input.trigger('change')\n    await sleep(0)\n    expect(\n      wrapper.find('.n-upload-file-info__thumbnail img').attributes('src')\n    ).toEqual('/testThumbUrl.png')\n  })\n\n  it('should work with `on-preview` prop', async () => {\n    const onPreview = vi.fn()\n    const wrapper = mount(NUpload, {\n      props: {\n        defaultFileList: [\n          {\n            name: 'test.png',\n            url: '/testUrl.png',\n            status: 'finished',\n            id: 'test',\n            percentage: 100,\n            file: null\n          }\n        ],\n        onPreview\n      }\n    })\n    const urlName = wrapper.findAll('.n-upload-file-info__name > a')[0]\n    await urlName.trigger('click')\n\n    expect(onPreview).toHaveBeenCalled()\n  })\n\n  it('should work with `show-remove-button` and `on-remove` prop', async () => {\n    const onRemove = vi.fn()\n    const wrapper = mount(NUpload, {\n      props: {\n        defaultFileList: [\n          {\n            name: 'test.png',\n            url: '/testUrl.png',\n            status: 'finished',\n            id: 'test',\n            percentage: 100,\n            file: null\n          }\n        ],\n        onRemove,\n        showRemoveButton: false\n      }\n    })\n    let button = wrapper.find('.n-button--default-type')\n    expect(button.exists()).not.toBe(true)\n\n    await wrapper.setProps({\n      showRemoveButton: true\n    })\n\n    button = wrapper.find('.n-button--default-type')\n    expect(button.exists()).toBe(true)\n\n    await button.trigger('click')\n    expect(onRemove).toHaveBeenCalled()\n  })\n\n  it('should work with `show-cancel-button` and `on-remove` prop', async () => {\n    const onRemove = vi.fn()\n    const wrapper = mount(NUpload, {\n      props: {\n        defaultFileList: [\n          {\n            name: 'test.png',\n            url: '/testUrl.png',\n            status: 'error',\n            id: 'test',\n            percentage: 0,\n            file: null\n          }\n        ],\n        onRemove,\n        showCancelButton: false\n      }\n    })\n    let button = wrapper.findAll('.n-button--error-type')\n    expect(button.length).toEqual(1)\n\n    await wrapper.setProps({\n      showCancelButton: true\n    })\n\n    button = wrapper.findAll('.n-button--error-type')\n    expect(button.length).toEqual(2)\n\n    await button[0].trigger('click')\n    expect(onRemove).toHaveBeenCalled()\n  })\n  it('should work with `abstract` prop', async () => {\n    const wrapper = mount(NUpload, {\n      props: { abstract: true },\n      slots: {\n        default: () => [\n          h(NButtonGroup, null, {\n            default: () => [\n              h(NButton, null, { default: () => 'button1' }),\n              h(\n                NUploadTrigger,\n                { abstract: true },\n                {\n                  default: () =>\n                    h(\n                      NButton,\n                      { class: 'upload-button' },\n                      { default: () => 'upload button' }\n                    )\n                }\n              )\n            ]\n          }),\n          h(NCard, null, { default: () => h(NUploadFileList, null) })\n        ]\n      }\n    })\n    const uploadWrapperDom = wrapper.find('.n-upload')\n    const uploadTriggerDom = wrapper.find('.upload-button')\n    const uploadFileLIstDom = wrapper.find('.n-upload-file-list')\n\n    expect(uploadWrapperDom.exists()).toBe(false)\n    expect(uploadTriggerDom.exists()).toBe(true)\n    expect(uploadFileLIstDom.exists()).toBe(true)\n  })\n\n  it('should work with `accept` prop', async () => {\n    const wrapper = mount(NUpload)\n    expect(wrapper.find('input').attributes('accept')).not.toBe('.doc')\n\n    await wrapper.setProps({\n      accept: '.doc'\n    })\n    expect(wrapper.find('input').attributes('accept')).toBe('.doc')\n  })\n\n  it('should work with `multiple` prop', async () => {\n    const wrapper = mount(NUpload)\n    expect(wrapper.find('input').attributes('multiple')).not.toBe('')\n\n    await wrapper.setProps({\n      multiple: true\n    })\n    expect(wrapper.find('input').attributes('multiple')).toBe('')\n  })\n  it('should work with `abstract`prop when `list-type` is not image-card', async () => {\n    try {\n      mount(NUpload, {\n        props: {\n          abstract: true,\n          listType: 'image-card'\n        }\n      })\n    }\n    catch (error) {\n      expect(String(error)).toBe(\n        'Error: [naive/upload]: when the list-type is image-card, abstract is not supported.'\n      )\n    }\n  })\n  it('should work with `max` prop', async () => {\n    const wrapper = mount(NUpload, {\n      props: {\n        defaultFileList: [\n          {\n            name: 'test.png',\n            url: '/testUrl.png',\n            status: 'finished',\n            id: 'test',\n            percentage: 100,\n            file: null\n          }\n        ],\n        max: 1\n      }\n    })\n    const triggerDisabledElement = wrapper.find('.n-upload-trigger--disabled')\n\n    expect(triggerDisabledElement.exists()).toBe(true)\n  })\n})\n\ndescribe('n-upload-file-list', () => {\n  it('should work', async () => {\n    const wrapper = mount(NUpload, {\n      props: {\n        abstract: true,\n        defaultFileList: [\n          {\n            name: 'test.png',\n            url: '/testUrl.png',\n            status: 'finished',\n            id: 'test',\n            percentage: 100,\n            file: null\n          }\n        ]\n      },\n      slots: {\n        default: () => [\n          h(NCard, null, { default: () => h(NUploadFileList, null) })\n        ]\n      }\n    })\n\n    const fileList = wrapper.findAll('.n-upload-file')\n    expect(fileList.length).toEqual(1)\n  })\n  it('should work with `list-type` prop', async () => {\n    const wrapper = mount(NUpload, {\n      props: {\n        listType: 'image-card',\n        defaultFileList: [\n          {\n            name: 'test.png',\n            url: '/testUrl.png',\n            status: 'finished',\n            id: 'test',\n            percentage: 100,\n            file: null\n          }\n        ]\n      }\n    })\n    expect(wrapper.findAll('.n-upload-file--image-card-type').length).toBe(1)\n    expect(wrapper.findComponent(NImageGroup).exists()).toBe(true)\n  })\n  it('should work inside `n-upload`', async () => {\n    try {\n      mount(NUploadFileList)\n    }\n    catch (error) {\n      expect(String(error)).toBe(\n        'Error: [naive/upload-file-list]: `n-upload-file-list` must be placed inside `n-upload`.'\n      )\n    }\n  })\n})\n\ndescribe('n-upload-trigger', () => {\n  it('should work', async () => {\n    const wrapper = mount(NUpload, {\n      props: { abstract: true },\n      slots: {\n        default: () => [\n          h(NButtonGroup, null, {\n            default: () => [\n              h(NButton, null, { default: () => 'button1' }),\n              h(\n                NUploadTrigger,\n                { abstract: true },\n                {\n                  default: () =>\n                    h(\n                      NButton,\n                      { class: 'upload-button' },\n                      { default: () => 'upload button' }\n                    )\n                }\n              )\n            ]\n          }),\n          h(NCard, null, { default: () => h(NUploadFileList, null) })\n        ]\n      }\n    })\n\n    const uploadButton = wrapper.findAll('.upload-button')\n    expect(uploadButton.length).toEqual(1)\n  })\n  it('should work inside `n-upload`', async () => {\n    try {\n      mount(NUploadTrigger)\n    }\n    catch (error) {\n      expect(String(error)).toBe(\n        'Error: [naive/upload-trigger]: `n-upload-trigger` must be placed inside `n-upload`.'\n      )\n    }\n  })\n\n  it('should work with drag and drop', async () => {\n    const wrapper = mount(NUpload, {\n      slots: {\n        default: () => h(NButton, null, { default: () => 'button1' })\n      }\n    })\n    const triggerItem = wrapper.find('.n-upload-trigger')\n    await triggerItem.trigger('click')\n    await triggerItem.trigger('drop')\n\n    expect(wrapper.vm.dragOver).toBe(false)\n\n    await triggerItem.trigger('dragenter')\n    expect(wrapper.vm.dragOver).toBe(true)\n\n    await triggerItem.trigger('dragleave')\n    expect(wrapper.vm.dragOver).toBe(false)\n\n    await triggerItem.trigger('dragover')\n    expect(wrapper.vm.dragOver).toBe(true)\n  })\n})\n\ndescribe('n-upload-dragger', () => {\n  it('should work', () => {\n    mount(NUpload, {\n      slots: {\n        default: () => h(NUploadDragger, null)\n      }\n    })\n  })\n  it('should work inside `n-upload`', async () => {\n    try {\n      mount(NUploadDragger)\n    }\n    catch (error) {\n      expect(String(error)).toBe(\n        'Error: [naive/upload-dragger]: `n-upload-dragger` must be placed inside `n-upload`.'\n      )\n    }\n  })\n})\n\ndescribe('match-type', () => {\n  it('works', () => {\n    expect(matchType('123', '', '*/*')).toEqual(true)\n    expect(matchType('123', '123/123', '*/*')).toEqual(true)\n    expect(matchType('123.gigig', '', '*/*')).toEqual(true)\n    expect(matchType('123.jpg', 'image/jpeg', 'image/*')).toEqual(true)\n    expect(matchType('123.jpg', 'image/jpeg', 'image/jpeg')).toEqual(true)\n    expect(matchType('123.jpg', 'image/jpeg', 'image/gif')).toEqual(false)\n    expect(matchType('123.jpeg', 'image/jpeg', 'image/*')).toEqual(true)\n    expect(matchType('123.jpeg', 'image/jpeg', 'image/jpeg')).toEqual(true)\n    expect(matchType('123.jpeg', 'image/jpeg', 'image/gif')).toEqual(false)\n    expect(matchType('123.vue', '', 'image/gif')).toEqual(false)\n    expect(matchType('123.vue', '', 'image/gif, .vue')).toEqual(true)\n    expect(matchType('123.vue', '', 'image/gif, .vUe')).toEqual(true)\n    expect(matchType('123.Vue', '', 'image/gif, .VUE')).toEqual(true)\n    expect(matchType('123.json', 'application/json', '.json')).toEqual(true)\n    expect(\n      matchType('123.json', 'application/json', 'application/json')\n    ).toEqual(true)\n    expect(\n      matchType('123.json', 'application/json', 'application/json , .json')\n    ).toEqual(true)\n    expect(\n      matchType('123.JSON', 'application/json', 'application/json , .json')\n    ).toEqual(true)\n  })\n})\n\ndescribe('test type', () => {\n  it('works', () => {\n    ;<NUpload onError={() => {}} onFinish={() => {}} />\n  })\n})\n"
  },
  {
    "path": "src/upload/tests/server.spec.tsx",
    "content": "import { setup } from '@css-render/vue3-ssr'\nimport { renderToString } from '@vue/server-renderer'\n/**\n * @vitest-environment node\n */\nimport { createSSRApp, h } from 'vue'\nimport { NUpload } from '../..'\n\ndescribe('server side rendering', () => {\n  it('works', async () => {\n    const app = createSSRApp(() => <NUpload />)\n    setup(app)\n    try {\n      await renderToString(app)\n    }\n    catch (e) {\n      expect(e).not.toBeTruthy()\n    }\n  })\n})\n"
  },
  {
    "path": "src/version.ts",
    "content": "export default '2.44.1'\n"
  },
  {
    "path": "src/virtual-list/demos/enUS/basic.demo.vue",
    "content": "<markdown>\n  # Basic size\n</markdown>\n\n<script lang=\"ts\" setup>\nconst avatars = [\n  'https://07akioni.oss-cn-beijing.aliyuncs.com/07akioni.jpeg',\n  'https://avatars.githubusercontent.com/u/20943608?s=60&v=4',\n  'https://avatars.githubusercontent.com/u/46394163?s=60&v=4',\n  'https://avatars.githubusercontent.com/u/39197136?s=60&v=4',\n  'https://avatars.githubusercontent.com/u/19239641?s=60&v=4'\n]\n\nconst items = Array.from({ length: 10000 }, (_, i) => ({\n  key: `${i}`,\n  value: i,\n  avatar: avatars[i % avatars.length]\n}))\n</script>\n\n<template>\n  <n-virtual-list style=\"max-height: 240px\" :item-size=\"42\" :items=\"items\">\n    <template #default=\"{ item }\">\n      <div :key=\"item.key\" class=\"item\" style=\"height: 42px\">\n        <img class=\"avatar\" :src=\"item.avatar\" alt=\"\">\n        <span> {{ item.value }}</span>\n      </div>\n    </template>\n  </n-virtual-list>\n</template>\n\n<style>\n.item {\n  display: flex;\n  align-items: center;\n}\n.avatar {\n  width: 28px;\n  border-radius: 50%;\n  margin-right: 10px;\n}\n</style>\n"
  },
  {
    "path": "src/virtual-list/demos/enUS/dynamic-size.demo.vue",
    "content": "<markdown>\n  # Dynamic size\n\n  Set 'item-resizable' which can render items of unknown size.\n</markdown>\n\n<script lang=\"ts\" setup>\nconst avatars = [\n  'https://07akioni.oss-cn-beijing.aliyuncs.com/07akioni.jpeg',\n  'https://avatars.githubusercontent.com/u/20943608?s=60&v=4',\n  'https://avatars.githubusercontent.com/u/46394163?s=60&v=4',\n  'https://avatars.githubusercontent.com/u/39197136?s=60&v=4',\n  'https://avatars.githubusercontent.com/u/19239641?s=60&v=4'\n]\n\nconst messages = [\n  'Life is like a grand magic show, we sometimes play the magician, and sometimes become the audience to be teased, and finally found that the biggest magic is actually time, it makes our youth and wallet have become lost',\n  'Complexity isn\\'t going away, it\\'s just going to shift, and when you hear people talking about elaborate conceptual models, stay awake',\n  'When it comes to virtual lists, it can make you feel like the list is infinite, but in reality it is just secretly hiding the invisible elements, like a lazy programmer with a blank note saying, You can\\'t see me, and I won\\'t load myself!',\n  'Sometimes the question itself is the answer, the process of pursuit is an answer, language has the ability to destroy, once a thing is said, it is destroyed, I say to silence, but I say silence is gone, I say to enjoy the moment, as soon as I enjoy the moment, the moment slips away',\n  'Freud read dreams and discovered a secret passage to the unconscious mind. Hemingway read the sea and found that life is a fish that takes a lifetime to catch. Van Gogh read the wheat fields and found that art hid behind the sun to cool itself. Rodin read the human body and discovered beautiful coastlines that Columbus had not. Camus reads Kafka and finds that half of the truth has been told'\n]\n\nconst items = Array.from({ length: 10000 }, (_, i) => ({\n  key: `${i}`,\n  value: i,\n  avatar: avatars[i % avatars.length],\n  message: messages[Math.floor(Math.random() * messages.length)]\n}))\n</script>\n\n<template>\n  <n-virtual-list\n    style=\"max-height: 240px\"\n    :item-size=\"42\"\n    :items=\"items\"\n    item-resizable\n  >\n    <template #default=\"{ item, index }\">\n      <div :key=\"item.key\" class=\"item\">\n        <img class=\"avatar\" :src=\"item.avatar\" alt=\"\">\n        <span> {{ index }} - {{ item.message }}</span>\n      </div>\n    </template>\n  </n-virtual-list>\n</template>\n\n<style>\n.item {\n  display: flex;\n}\n.avatar {\n  width: 28px;\n  height: 28px;\n  border-radius: 50%;\n  margin-right: 10px;\n}\n</style>\n"
  },
  {
    "path": "src/virtual-list/demos/enUS/index.demo-entry.md",
    "content": "# Virtual List\n\nWhen it comes to virtual lists, it can feel like a list is infinitely long, but in reality it is just secretly hiding the invisible elements.\n\nIt's like a lazy programmer holding up a blank note and saying, \"You can't see me, and I can't load myself!\"\n\nAvailable since `2.36.0`.\n\n## Demos\n\n```demo\nbasic.vue\ndynamic-size.vue\nscroll.vue\nkeep-alive.vue\n```\n\n## API\n\n### Virtual List Props\n\n| Name | Type | Default | Description | Version |\n| --- | --- | --- | --- | --- |\n| default-scroll-key | `string \\| number` | `undefined` | Default scroll key. | 2.36.0 |\n| default-scroll-index | `number` | `undefined` | Default scroll index. | 2.36.0 |\n| ignore-item-resize | `boolean` | `false` | Ignore item resize. It can make runtime slightly faster, although it's hard to feel. | 2.36.0 |\n| items | `Array<object>` | `[]` | Data to display. | 2.36.0 |\n| item-resizable | `boolean` | `false` | Whether dynamic sizing is enabled, you don't have to care about the size of the item, it will be calculated automatically. | 2.36.0 |\n| item-size | `number` | required | Displays the minimum height of the item in pixels to calculate scroll size and position. | 2.36.0 |\n| items-style | `string \\| CSSProperties` | `undefined` | Items container style. | 2.36.0 |\n| key-field | `string` | `'key'` | Field name of option key. | 2.36.0 |\n| padding-top | `string \\| number` | `undefined` | Distance from the top. | 2.36.0 |\n| padding-bottom | `string \\| number` | `undefined` | Distance from the bottom. | 2.36.0 |\n| scrollbar-props | `ScrollbarProps` | `undefined` | Attribute reference [Scrollbar props](scrollbar#Scrollbar-Props). | 2.36.0 |\n| visible-items-tag | `string` | `'div'` | Items container tag. | 2.36.0 |\n| visible-items-props | `object` | `undefined` | Items container prop. | 2.36.0 |\n| on-scroll | `(event: Event) => void` | `undefined` | Scrolling callback function. | 2.36.0 |\n| on-wheel | `(event: WheelEvent) => void` | `undefined` | Callback function for the wheel event. | 2.36.0 |\n| on-resize | `(event: ResizeObserverEntry) => void` | `undefined` | Element resizing callback function. | 2.36.0 |\n\n### Virtual List Methods\n\n| Name     | Type       | Description           | Version |\n| -------- | ---------- | --------------------- | ------- |\n| scrollTo | `ScrollTo` | Scroll to a position. | 2.36.0  |\n\n#### ScrollTo Type\n\n```ts\ninterface ScrollTo {\n  (x: number, y: number): void\n  (options: {\n    left?: number\n    top?: number\n    behavior?: ScrollBehavior\n    debounce?: boolean\n  }): void\n  (options: {\n    index: number\n    behavior?: ScrollBehavior\n    debounce?: boolean\n  }): void\n  (options: {\n    key: string | number\n    behavior?: ScrollBehavior\n    debounce?: boolean\n  }): void\n  (options: {\n    position: 'top' | 'bottom'\n    behavior?: ScrollBehavior\n    debounce?: boolean\n  }): void\n}\n```\n"
  },
  {
    "path": "src/virtual-list/demos/enUS/keep-alive.demo.vue",
    "content": "<markdown>\n  # Keep state\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst showVirtualList = ref(true)\n\nconst avatars = [\n  'https://07akioni.oss-cn-beijing.aliyuncs.com/07akioni.jpeg',\n  'https://avatars.githubusercontent.com/u/20943608?s=60&v=4',\n  'https://avatars.githubusercontent.com/u/46394163?s=60&v=4',\n  'https://avatars.githubusercontent.com/u/39197136?s=60&v=4',\n  'https://avatars.githubusercontent.com/u/19239641?s=60&v=4'\n]\n\nconst items = Array.from({ length: 10000 }, (_, i) => ({\n  key: `${i}`,\n  value: i,\n  avatar: avatars[i % avatars.length]\n}))\n</script>\n\n<template>\n  <n-space vertical>\n    <n-button @click=\"showVirtualList = !showVirtualList\">\n      Toggle visibility\n    </n-button>\n    <keep-alive>\n      <n-virtual-list\n        v-if=\"showVirtualList\"\n        style=\"max-height: 240px\"\n        :item-size=\"42\"\n        :items=\"items\"\n        item-resizable\n      >\n        <template #default=\"{ item, index }\">\n          <div :key=\"item.key\" class=\"item\" style=\"height: 42px\">\n            <img class=\"avatar\" :src=\"item.avatar\" alt=\"\">\n            <span> {{ index }}</span>\n          </div>\n        </template>\n      </n-virtual-list>\n    </keep-alive>\n  </n-space>\n</template>\n\n<style>\n.item {\n  display: flex;\n}\n.avatar {\n  width: 28px;\n  height: 28px;\n  border-radius: 50%;\n  margin-right: 10px;\n}\n</style>\n"
  },
  {
    "path": "src/virtual-list/demos/enUS/scroll.demo.vue",
    "content": "<markdown>\n  # Scroll\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { VirtualListInst } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst virtualListInst = ref<VirtualListInst>()\n\nconst avatars = [\n  'https://07akioni.oss-cn-beijing.aliyuncs.com/07akioni.jpeg',\n  'https://avatars.githubusercontent.com/u/20943608?s=60&v=4',\n  'https://avatars.githubusercontent.com/u/46394163?s=60&v=4',\n  'https://avatars.githubusercontent.com/u/39197136?s=60&v=4',\n  'https://avatars.githubusercontent.com/u/19239641?s=60&v=4'\n]\n\nconst items = Array.from({ length: 10000 }, (_, i) => ({\n  key: `${i}`,\n  value: i,\n  avatar: avatars[i % avatars.length]\n}))\n\nfunction handleScrollToKey() {\n  virtualListInst.value?.scrollTo({ key: '88' })\n}\n\nfunction handleScrollToPosition() {\n  virtualListInst.value?.scrollTo({ position: 'bottom' })\n}\n\nfunction handleScrollToIndex() {\n  virtualListInst.value?.scrollTo({ index: 200 })\n}\n\nfunction handleScrollToDistance() {\n  virtualListInst.value?.scrollTo({ top: 100 })\n}\n</script>\n\n<template>\n  <n-space vertical>\n    <n-space>\n      <n-button @click=\"handleScrollToKey\">\n        Scroll\n      </n-button>\n      <n-button @click=\"handleScrollToPosition\">\n        Scroll to position\n      </n-button>\n      <n-button @click=\"handleScrollToIndex\">\n        Scroll to index\n      </n-button>\n      <n-button @click=\"handleScrollToDistance\">\n        Scroll to distance\n      </n-button>\n    </n-space>\n    <n-virtual-list\n      ref=\"virtualListInst\"\n      style=\"max-height: 240px\"\n      :item-size=\"42\"\n      :items=\"items\"\n      item-resizable\n    >\n      <template #default=\"{ item, index }\">\n        <div :key=\"item.key\" class=\"item\" style=\"height: 42px\">\n          <img class=\"avatar\" :src=\"item.avatar\" alt=\"\">\n          <span> {{ index }}</span>\n        </div>\n      </template>\n    </n-virtual-list>\n  </n-space>\n</template>\n\n<style>\n.item {\n  display: flex;\n}\n.avatar {\n  width: 28px;\n  height: 28px;\n  border-radius: 50%;\n  margin-right: 10px;\n}\n</style>\n"
  },
  {
    "path": "src/virtual-list/demos/zhCN/basic.demo.vue",
    "content": "<markdown>\n  # 基础尺寸\n</markdown>\n\n<script lang=\"ts\" setup>\nconst avatars = [\n  'https://07akioni.oss-cn-beijing.aliyuncs.com/07akioni.jpeg',\n  'https://avatars.githubusercontent.com/u/20943608?s=60&v=4',\n  'https://avatars.githubusercontent.com/u/46394163?s=60&v=4',\n  'https://avatars.githubusercontent.com/u/39197136?s=60&v=4',\n  'https://avatars.githubusercontent.com/u/19239641?s=60&v=4'\n]\n\nconst items = Array.from({ length: 10000 }, (_, i) => ({\n  key: `${i}`,\n  value: i,\n  avatar: avatars[i % avatars.length]\n}))\n</script>\n\n<template>\n  <n-virtual-list style=\"max-height: 240px\" :item-size=\"42\" :items=\"items\">\n    <template #default=\"{ item }\">\n      <div :key=\"item.key\" class=\"item\" style=\"height: 42px\">\n        <img class=\"avatar\" :src=\"item.avatar\" alt=\"\">\n        <span> {{ item.value }}</span>\n      </div>\n    </template>\n  </n-virtual-list>\n</template>\n\n<style>\n.item {\n  display: flex;\n  align-items: center;\n}\n.avatar {\n  width: 28px;\n  border-radius: 50%;\n  margin-right: 10px;\n}\n</style>\n"
  },
  {
    "path": "src/virtual-list/demos/zhCN/dynamic-size.demo.vue",
    "content": "<markdown>\n  # 动态尺寸\n\n  设定 `item-resizable` 它可以渲染未知大小的项目。\n</markdown>\n\n<script lang=\"ts\" setup>\nconst avatars = [\n  'https://07akioni.oss-cn-beijing.aliyuncs.com/07akioni.jpeg',\n  'https://avatars.githubusercontent.com/u/20943608?s=60&v=4',\n  'https://avatars.githubusercontent.com/u/46394163?s=60&v=4',\n  'https://avatars.githubusercontent.com/u/39197136?s=60&v=4',\n  'https://avatars.githubusercontent.com/u/19239641?s=60&v=4'\n]\n\nconst messages = [\n  '生活就像一场盛大的魔术表演，我们时而扮演着魔术师，时而又成了被戏弄的观众，最后发现，最大的魔术其实是时间，它把我们的青春和钱包都变得不见了',\n  '复杂度不会消失，只会转移，当你听到一些人对于精致的概念模型侃侃而谈，请保持清醒',\n  '当谈到虚拟列表时，能让你感觉列表像是无限长的，但实际上它只是在偷偷隐藏那些不可见的元素，就像是个懒惰的程序员拿着一个空白纸条说：\"你看不见我，我也不会加载自己！\"',\n  '问题有时候本身就是答案，追寻的过程就是一种答案，语言具有破坏的能力，一旦一个东西说出口它就破坏了，我说要沉默，但我一说口沉默就没了，我说要享受当下，一说享受当下，当下就溜走了',\n  '弗洛伊德阅读梦，发现一条直达潜意识的秘密通道。海明威阅读海，发现生命是一条要花一辈子才会上钩的鱼。凡高阅读麦田，发现艺术躲在太阳的背后乘凉。罗丹阅读人体，发现哥伦布没有发现的美丽海岸线。加缪阅读卡夫卡，发现真理已经被讲完一半'\n]\n\nconst items = Array.from({ length: 10000 }, (_, i) => ({\n  key: `${i}`,\n  value: i,\n  avatar: avatars[i % avatars.length],\n  message: messages[Math.floor(Math.random() * messages.length)]\n}))\n</script>\n\n<template>\n  <n-virtual-list\n    style=\"max-height: 240px\"\n    :item-size=\"42\"\n    :items=\"items\"\n    item-resizable\n  >\n    <template #default=\"{ item, index }\">\n      <div :key=\"item.key\" class=\"item\">\n        <img class=\"avatar\" :src=\"item.avatar\" alt=\"\">\n        <span> {{ index }} - {{ item.message }}</span>\n      </div>\n    </template>\n  </n-virtual-list>\n</template>\n\n<style>\n.item {\n  display: flex;\n  align-items: flex-start;\n}\n.avatar {\n  width: 28px;\n  height: 28px;\n  border-radius: 50%;\n  margin-right: 10px;\n}\n</style>\n"
  },
  {
    "path": "src/virtual-list/demos/zhCN/index.demo-entry.md",
    "content": "# 虚拟列表 Virtual List\n\n当谈到虚拟列表时，能让你感觉列表像是无限长的，但实际上它只是在偷偷隐藏那些不可见的元素。\n\n就像是个懒惰的程序员拿着一个空白纸条说：“你看不见我，我也不会加载自己！”\n\n自 `2.36.0` 开始提供。\n\n## 演示\n\n```demo\nbasic.vue\ndynamic-size.vue\nscroll.vue\nkeep-alive.vue\n```\n\n## API\n\n### Virtual List Props\n\n| 名称 | 类型 | 默认值 | 说明 | 版本 |\n| --- | --- | --- | --- | --- |\n| default-scroll-key | `string \\| number` | `undefined` | 默认滚动的 Key | 2.36.0 |\n| default-scroll-index | `number` | `undefined` | 默认滚动的 Index | 2.36.0 |\n| ignore-item-resize | `boolean` | `false` | 忽略内容尺寸变化，可以让运行快一些（尽管应该很难感受到） | 2.36.0 |\n| items | `Array<object>` | `[]` | 需要展示的数据 | 2.36.0 |\n| item-resizable | `boolean` | `false` | 是否启用动态尺寸，你不必关心项目大小，它会自动计算 | 2.36.0 |\n| item-size | `number` | required | 以像素为单位显示项目的最小高度，用于计算滚动大小和位置 | 2.36.0 |\n| items-style | `string \\| CSSProperties` | `undefined` | 全部内容的容器样式 | 2.36.0 |\n| key-field | `string` | `'key'` | 选项 key 的字段名 | 2.36.0 |\n| padding-top | `string \\| number` | `undefined` | 距离上部的距离 | 2.36.0 |\n| padding-bottom | `string \\| number` | `undefined` | 距离底部的距离 | 2.36.0 |\n| scrollbar-props | `ScrollbarProps` | `undefined` | 属性参考 [Scrollbar props](scrollbar#Scrollbar-Props) | 2.36.0 |\n| visible-items-tag | `string` | `'div'` | 全部内容的容器标签 | 2.36.0 |\n| visible-items-props | `object` | `undefined` | 全部内容的容器属性 | 2.36.0 |\n| on-scroll | `(event: Event) => void` | `undefined` | 滚动的回调函数 | 2.36.0 |\n| on-wheel | `(event: WheelEvent) => void` | `undefined` | 滚轮事件的回调函数 | 2.36.0 |\n| on-resize | `(event: ResizeObserverEntry) => void` | `undefined` | 元素大小调整的回调函数 | 2.36.0 |\n\n### Virtual List Methods\n\n| 名称     | 参数       | 说明           | 版本   |\n| -------- | ---------- | -------------- | ------ |\n| scrollTo | `ScrollTo` | 滚动到某个位置 | 2.36.0 |\n\n#### ScrollTo Type\n\n```ts\ninterface ScrollTo {\n  (x: number, y: number): void\n  (options: {\n    left?: number\n    top?: number\n    behavior?: ScrollBehavior\n    debounce?: boolean\n  }): void\n  (options: {\n    index: number\n    behavior?: ScrollBehavior\n    debounce?: boolean\n  }): void\n  (options: {\n    key: string | number\n    behavior?: ScrollBehavior\n    debounce?: boolean\n  }): void\n  (options: {\n    position: 'top' | 'bottom'\n    behavior?: ScrollBehavior\n    debounce?: boolean\n  }): void\n}\n```\n"
  },
  {
    "path": "src/virtual-list/demos/zhCN/keep-alive.demo.vue",
    "content": "<markdown>\n  # 保持状态\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst showVirtualList = ref(true)\n\nconst avatars = [\n  'https://07akioni.oss-cn-beijing.aliyuncs.com/07akioni.jpeg',\n  'https://avatars.githubusercontent.com/u/20943608?s=60&v=4',\n  'https://avatars.githubusercontent.com/u/46394163?s=60&v=4',\n  'https://avatars.githubusercontent.com/u/39197136?s=60&v=4',\n  'https://avatars.githubusercontent.com/u/19239641?s=60&v=4'\n]\n\nconst items = Array.from({ length: 10000 }, (_, i) => ({\n  key: `${i}`,\n  value: i,\n  avatar: avatars[i % avatars.length]\n}))\n</script>\n\n<template>\n  <n-space vertical>\n    <n-button @click=\"showVirtualList = !showVirtualList\">\n      切换可见性\n    </n-button>\n    <keep-alive>\n      <n-virtual-list\n        v-if=\"showVirtualList\"\n        style=\"max-height: 240px\"\n        :item-size=\"42\"\n        :items=\"items\"\n      >\n        <template #default=\"{ item, index }\">\n          <div :key=\"item.key\" class=\"item\" style=\"height: 42px\">\n            <img class=\"avatar\" :src=\"item.avatar\" alt=\"\">\n            <span> {{ index }}</span>\n          </div>\n        </template>\n      </n-virtual-list>\n    </keep-alive>\n  </n-space>\n</template>\n\n<style>\n.item {\n  display: flex;\n}\n.avatar {\n  width: 28px;\n  height: 28px;\n  border-radius: 50%;\n  margin-right: 10px;\n}\n</style>\n"
  },
  {
    "path": "src/virtual-list/demos/zhCN/scroll.demo.vue",
    "content": "<markdown>\n  # 滚动\n</markdown>\n\n<script lang=\"ts\" setup>\nimport type { VirtualListInst } from 'naive-ui'\nimport { ref } from 'vue'\n\nconst virtualListInst = ref<VirtualListInst>()\n\nconst avatars = [\n  'https://07akioni.oss-cn-beijing.aliyuncs.com/07akioni.jpeg',\n  'https://avatars.githubusercontent.com/u/20943608?s=60&v=4',\n  'https://avatars.githubusercontent.com/u/46394163?s=60&v=4',\n  'https://avatars.githubusercontent.com/u/39197136?s=60&v=4',\n  'https://avatars.githubusercontent.com/u/19239641?s=60&v=4'\n]\n\nconst items = Array.from({ length: 10000 }, (_, i) => ({\n  key: `${i}`,\n  value: i,\n  avatar: avatars[i % avatars.length]\n}))\n\nfunction handleScrollToKey() {\n  virtualListInst.value?.scrollTo({ key: '88' })\n}\n\nfunction handleScrollToPosition() {\n  virtualListInst.value?.scrollTo({ position: 'bottom' })\n}\n\nfunction handleScrollToIndex() {\n  virtualListInst.value?.scrollTo({ index: 200 })\n}\n\nfunction handleScrollToDistance() {\n  virtualListInst.value?.scrollTo({ top: 100 })\n}\n</script>\n\n<template>\n  <n-space vertical>\n    <n-space>\n      <n-button @click=\"handleScrollToKey\">\n        滚动\n      </n-button>\n      <n-button @click=\"handleScrollToPosition\">\n        滚动到指定位置\n      </n-button>\n      <n-button @click=\"handleScrollToIndex\">\n        滚动到指定 Index\n      </n-button>\n      <n-button @click=\"handleScrollToDistance\">\n        滚动到指定距离\n      </n-button>\n    </n-space>\n    <n-virtual-list\n      ref=\"virtualListInst\"\n      style=\"max-height: 240px\"\n      :item-size=\"42\"\n      :items=\"items\"\n    >\n      <template #default=\"{ item, index }\">\n        <div :key=\"item.key\" class=\"item\" style=\"height: 42px\">\n          <img class=\"avatar\" :src=\"item.avatar\" alt=\"\">\n          <span> {{ index }}</span>\n        </div>\n      </template>\n    </n-virtual-list>\n  </n-space>\n</template>\n\n<style>\n.item {\n  display: flex;\n}\n.avatar {\n  width: 28px;\n  height: 28px;\n  border-radius: 50%;\n  margin-right: 10px;\n}\n</style>\n"
  },
  {
    "path": "src/virtual-list/index.ts",
    "content": "export { default as NVirtualList, virtualListProps } from './src/VirtualList'\nexport type { VirtualListInst, VirtualListProps } from './src/VirtualList'\n"
  },
  {
    "path": "src/virtual-list/src/VirtualList.tsx",
    "content": "import type { CSSProperties, PropType } from 'vue'\nimport type {\n  VirtualListInst,\n  VirtualListItemData,\n  VirtualListScrollToOptions\n} from 'vueuc'\nimport type { ScrollbarInst } from '../../_internal'\nimport type { ExtractPublicPropTypes } from '../../_utils'\nimport type { ScrollbarProps } from '../../scrollbar/src/Scrollbar'\nimport { defineComponent, h, ref } from 'vue'\nimport { VVirtualList } from 'vueuc'\nimport { NxScrollbar } from '../../_internal'\n\nexport { type VirtualListInst } from 'vueuc'\n\nexport const virtualListProps = {\n  scrollbarProps: Object as PropType<ScrollbarProps>,\n  items: {\n    type: Array as PropType<VirtualListItemData[]>,\n    default: () => []\n  },\n  itemSize: {\n    type: Number,\n    required: true\n  },\n  itemResizable: Boolean,\n  itemsStyle: [String, Object] as PropType<string | CSSProperties>,\n  visibleItemsTag: {\n    type: [String, Object] as PropType<string | object>,\n    default: 'div'\n  },\n  visibleItemsProps: Object,\n  ignoreItemResize: Boolean,\n  onScroll: Function as PropType<(event: Event) => void>,\n  onWheel: Function as PropType<(event: WheelEvent) => void>,\n  onResize: Function as PropType<(entry: ResizeObserverEntry) => void>,\n  defaultScrollKey: [Number, String] as PropType<number | string>,\n  defaultScrollIndex: Number,\n  keyField: {\n    type: String,\n    default: 'key'\n  },\n  paddingTop: {\n    type: [Number, String] as PropType<number | string>,\n    default: 0\n  },\n  paddingBottom: {\n    type: [Number, String] as PropType<number | string>,\n    default: 0\n  }\n} as const\n\nexport type VirtualListProps = ExtractPublicPropTypes<typeof virtualListProps>\n\nexport default defineComponent({\n  name: 'VirtualList',\n  props: virtualListProps,\n  setup(props) {\n    const scrollbarInstRef = ref<ScrollbarInst | null>(null)\n    const virtualListInstRef = ref<VirtualListInst | null>(null)\n\n    function syncScrollbar(): void {\n      const { value: scrollbarInst } = scrollbarInstRef\n      if (scrollbarInst)\n        scrollbarInst.sync()\n    }\n\n    function handleScroll(e: Event): void {\n      syncScrollbar()\n      props.onScroll?.(e)\n    }\n\n    function handleResize(e: ResizeObserverEntry): void {\n      syncScrollbar()\n      props.onResize?.(e)\n    }\n\n    function handleWheel(e: WheelEvent): void {\n      props.onWheel?.(e)\n    }\n\n    function scrollTo(\n      options: VirtualListScrollToOptions | number,\n      y?: number\n    ): void {\n      if (typeof options === 'number') {\n        virtualListInstRef.value?.scrollTo(options, y ?? 0)\n      }\n      else {\n        virtualListInstRef.value?.scrollTo(options)\n      }\n    }\n\n    function getScrollContainer(): HTMLElement | null | undefined {\n      return virtualListInstRef.value?.listElRef\n    }\n\n    function getScrollContent(): HTMLElement | null | undefined {\n      return virtualListInstRef.value?.itemsElRef\n    }\n\n    return {\n      scrollTo,\n      scrollbarInstRef,\n      virtualListInstRef,\n      getScrollContainer,\n      getScrollContent,\n      handleScroll,\n      handleResize,\n      handleWheel\n    }\n  },\n  render() {\n    return (\n      <NxScrollbar\n        {...this.scrollbarProps}\n        ref=\"scrollbarInstRef\"\n        container={this.getScrollContainer}\n        content={this.getScrollContent}\n      >\n        {{\n          default: () => {\n            return (\n              <VVirtualList\n                ref=\"virtualListInstRef\"\n                showScrollbar={false}\n                items={this.items}\n                itemSize={this.itemSize}\n                itemResizable={this.itemResizable}\n                itemsStyle={this.itemsStyle}\n                visibleItemsTag={this.visibleItemsTag}\n                visibleItemsProps={this.visibleItemsProps}\n                ignoreItemResize={this.ignoreItemResize}\n                keyField={this.keyField}\n                defaultScrollKey={this.defaultScrollKey}\n                defaultScrollIndex={this.defaultScrollIndex}\n                paddingTop={this.paddingTop}\n                paddingBottom={this.paddingBottom}\n                onScroll={this.handleScroll}\n                onResize={this.handleResize}\n                onWheel={this.handleWheel}\n              >\n                {{\n                  default: ({\n                    item,\n                    index\n                  }: {\n                    item: VirtualListItemData\n                    index: number\n                  }) => this.$slots.default?.({ item, index })\n                }}\n              </VVirtualList>\n            )\n          }\n        }}\n      </NxScrollbar>\n    )\n  }\n})\n"
  },
  {
    "path": "src/vitest-setup.ts",
    "content": "import { isBrowser, isJsdom } from './_utils'\n\n// Polyfill browser APIs\nclass _ResizeObserver {\n  observe(): void {}\n  unobserve(): void {}\n  disconnect(): void {}\n}\n\nfunction _matchMedia(query: string): MediaQueryList {\n  return {\n    matches: false,\n    media: query,\n    onchange: null,\n    addListener: () => {},\n    removeListener: () => {},\n    addEventListener: () => {},\n    removeEventListener: () => {},\n    dispatchEvent: () => false\n  }\n}\n\nif (isJsdom() && typeof window !== 'undefined') {\n  window.ResizeObserver = _ResizeObserver\n  window.matchMedia = _matchMedia\n}\n\n// https://github.com/jsdom/jsdom/issues/1422\nif (isBrowser) {\n  HTMLDivElement.prototype.scrollTo = () => {}\n}\n"
  },
  {
    "path": "src/watermark/demos/enUS/basic.demo.vue",
    "content": "<markdown>\n# Basic\n</markdown>\n\n<template>\n  <n-watermark\n    content=\"Watermark\"\n    cross\n    selectable\n    :font-size=\"16\"\n    :line-height=\"16\"\n    :width=\"192\"\n    :height=\"128\"\n    :x-offset=\"12\"\n    :y-offset=\"28\"\n    :rotate=\"-15\"\n  >\n    <n-table :bordered=\"false\" :single-line=\"false\">\n      <thead>\n        <tr>\n          <th>...</th>\n          <th>...</th>\n          <th>...</th>\n          <th>...</th>\n          <th>...</th>\n        </tr>\n      </thead>\n      <tbody>\n        <tr>\n          <td>...</td>\n          <td>...</td>\n          <td>...</td>\n          <td>...</td>\n          <td>...</td>\n        </tr>\n        <tr>\n          <td>...</td>\n          <td>...</td>\n          <td>...</td>\n          <td>...</td>\n          <td>...</td>\n        </tr>\n      </tbody>\n    </n-table>\n  </n-watermark>\n</template>\n"
  },
  {
    "path": "src/watermark/demos/enUS/custom.demo.vue",
    "content": "<markdown>\n# Custom Watermark\n\nPreview watermark effects by configuring custom parameters.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst content = ref('Watermark\\nCustom Watermark')\nconst fontSize = ref(16)\nconst rotate = ref(-15)\nconst fontColor = ref('rgba(128, 128, 128, .3)')\nconst cross = ref(true)\nconst fontStyle = ref<'normal' | 'italic' | 'oblique' | `oblique ${number}deg`>(\n  'normal'\n)\nconst fontWeight = ref(400)\nconst globalRotate = ref(0)\nconst lineHeight = ref(16)\nconst height = ref(128)\nconst width = ref(192)\nconst xGap = ref(0)\nconst yGap = ref(0)\nconst xOffset = ref(12)\nconst yOffset = ref(28)\nconst zIndex = ref(10)\nconst textAlign = ref<'left' | 'center' | 'right'>('left')\n</script>\n\n<template>\n  <n-flex :size=\"30\">\n    <n-watermark\n      style=\"flex: 1\"\n      :content=\"content\"\n      :cross=\"cross\"\n      selectable\n      :font-size=\"fontSize\"\n      :line-height=\"lineHeight\"\n      :width=\"width\"\n      :height=\"height\"\n      :x-offset=\"xOffset\"\n      :y-offset=\"yOffset\"\n      :rotate=\"rotate\"\n      :font-color=\"fontColor\"\n      :font-style=\"fontStyle\"\n      :font-weight=\"fontWeight\"\n      :global-rotate=\"globalRotate\"\n      :x-gap=\"xGap\"\n      :y-gap=\"yGap\"\n      :z-index=\"zIndex\"\n      :text-align=\"textAlign\"\n    >\n      <n-flex vertical>\n        <n-h4 prefix=\"bar\">\n          The underlying logic is to break through information barriers and\n          create a new industry ecosystem. The top-level design focuses on user\n          perception tracks, reaching a tipping point through differentiation\n          and granularity. Delivering value is to achieve lasting benefits by\n          reusing major developments in vertical fields.\n        </n-h4>\n        <n-table :bordered=\"false\" :single-line=\"false\">\n          <thead>\n            <tr>\n              <th>Review</th>\n              <th>Empower</th>\n              <th>Collaborate</th>\n              <th>...</th>\n              <th>Connect</th>\n            </tr>\n          </thead>\n          <tbody>\n            <tr>\n              <td>Align</td>\n              <td>Breakthrough</td>\n              <td>Establish</td>\n              <td>...</td>\n              <td>Fulfill</td>\n            </tr>\n            <tr>\n              <td>...</td>\n              <td>...</td>\n              <td>...</td>\n              <td>...</td>\n              <td>...</td>\n            </tr>\n          </tbody>\n        </n-table>\n        <img\n          width=\"100%\"\n          src=\"https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel4.jpeg\"\n        >\n      </n-flex>\n    </n-watermark>\n    <div style=\"width: 360px\">\n      <n-form-item label=\"Watermark Content\">\n        <n-input\n          v-model:value=\"content\"\n          placeholder=\"Please enter watermark content\"\n        />\n      </n-form-item>\n      <n-grid :cols=\"2\" :x-gap=\"12\">\n        <n-grid-item>\n          <n-form-item label=\"Font Size\">\n            <n-input-number v-model:value=\"fontSize\" :min=\"8\" :max=\"32\" />\n          </n-form-item>\n        </n-grid-item>\n        <n-grid-item>\n          <n-form-item label=\"Font Color\">\n            <n-color-picker v-model:value=\"fontColor\" />\n          </n-form-item>\n        </n-grid-item>\n        <n-grid-item>\n          <n-form-item label=\"Font Style\">\n            <n-select\n              v-model:value=\"fontStyle\"\n              :options=\"[\n                { label: 'Normal', value: 'normal' },\n                { label: 'Italic', value: 'italic' },\n                { label: 'Oblique', value: 'oblique' },\n              ]\"\n            />\n          </n-form-item>\n        </n-grid-item>\n        <n-grid-item>\n          <n-form-item label=\"Font Weight\">\n            <n-input-number\n              v-model:value=\"fontWeight\"\n              :min=\"100\"\n              :max=\"900\"\n              :step=\"100\"\n            />\n          </n-form-item>\n        </n-grid-item>\n        <n-grid-item>\n          <n-form-item label=\"Cross Boundary\">\n            <n-switch v-model:value=\"cross\" />\n          </n-form-item>\n        </n-grid-item>\n        <n-grid-item>\n          <n-form-item label=\"Rotation Angle\">\n            <n-slider v-model:value=\"rotate\" :min=\"-90\" :max=\"90\" />\n          </n-form-item>\n        </n-grid-item>\n        <n-grid-item>\n          <n-form-item label=\"Global Rotation\">\n            <n-slider v-model:value=\"globalRotate\" :min=\"-180\" :max=\"180\" />\n          </n-form-item>\n        </n-grid-item>\n        <n-grid-item>\n          <n-form-item label=\"Line Height\">\n            <n-input-number v-model:value=\"lineHeight\" :min=\"1\" />\n          </n-form-item>\n        </n-grid-item>\n        <n-grid-item>\n          <n-form-item label=\"Height\">\n            <n-input-number v-model:value=\"height\" :min=\"1\" />\n          </n-form-item>\n        </n-grid-item>\n        <n-grid-item>\n          <n-form-item label=\"Width\">\n            <n-input-number v-model:value=\"width\" :min=\"1\" />\n          </n-form-item>\n        </n-grid-item>\n        <n-grid-item>\n          <n-form-item label=\"X-axis Gap\">\n            <n-input-number v-model:value=\"xGap\" />\n          </n-form-item>\n        </n-grid-item>\n        <n-grid-item>\n          <n-form-item label=\"Y-axis Gap\">\n            <n-input-number v-model:value=\"yGap\" />\n          </n-form-item>\n        </n-grid-item>\n        <n-grid-item>\n          <n-form-item label=\"X-axis Offset\">\n            <n-input-number v-model:value=\"xOffset\" />\n          </n-form-item>\n        </n-grid-item>\n        <n-grid-item>\n          <n-form-item label=\"Y-axis Offset\">\n            <n-input-number v-model:value=\"yOffset\" />\n          </n-form-item>\n        </n-grid-item>\n        <n-grid-item>\n          <n-form-item label=\"Z-index\">\n            <n-input-number v-model:value=\"zIndex\" />\n          </n-form-item>\n        </n-grid-item>\n        <n-grid-item>\n          <n-form-item label=\"Text Align\">\n            <n-select\n              v-model:value=\"textAlign\"\n              :options=\"[\n                { label: 'Left', value: 'left' },\n                { label: 'Center', value: 'center' },\n                { label: 'Right', value: 'right' },\n              ]\"\n            />\n          </n-form-item>\n        </n-grid-item>\n      </n-grid>\n    </div>\n  </n-flex>\n</template>\n"
  },
  {
    "path": "src/watermark/demos/enUS/fullscreen.demo.vue",
    "content": "<markdown>\n# Fullscreen\n\nYou can make it displayed in fullscreen mode.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst show = ref(false)\n</script>\n\n<template>\n  <n-watermark\n    v-if=\"show\"\n    content=\"All the roads we have to walk are winding\"\n    cross\n    fullscreen\n    :font-size=\"16\"\n    :line-height=\"16\"\n    :width=\"384\"\n    :height=\"384\"\n    :x-offset=\"12\"\n    :y-offset=\"80\"\n    :rotate=\"-15\"\n  />\n  <n-switch v-model:value=\"show\" />\n</template>\n"
  },
  {
    "path": "src/watermark/demos/enUS/image.demo.vue",
    "content": "<markdown>\n# Image\n\nPut image here.\n\nPlease note about cross origin setting of the image URL. It will influence whether the image can be displayed.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst show = ref(false)\n</script>\n\n<template>\n  <n-watermark\n    v-if=\"show\"\n    image=\"https://07akioni.oss-cn-beijing.aliyuncs.com/07akioni.jpeg\"\n    cross\n    fullscreen\n    :font-size=\"16\"\n    :line-height=\"16\"\n    :width=\"384\"\n    :height=\"384\"\n    :x-offset=\"12\"\n    :y-offset=\"0\"\n    :image-width=\"64\"\n    :image-opacity=\"0.24\"\n  />\n  <n-switch v-model:value=\"show\" />\n</template>\n"
  },
  {
    "path": "src/watermark/demos/enUS/index.demo-entry.md",
    "content": "<!--single-column-->\n\n# Watermark\n\nWatermark.\n\n## Demos\n\n```demo\nbasic.vue\nfullscreen.vue\nimage.vue\nmultiline.vue\ncustom.vue\n```\n\n## API\n\n### Watermark Props\n\n| Name | Type | Default | Description | Version |\n| --- | --- | --- | --- | --- |\n| content | `string` | `undefined` | Content of watermark. | 2.25.3, supports multiple line text since 2.38.2 |\n| cross | `boolean` | `false` | Whether to show watermark at cross position. | 2.25.3 |\n| debug | `boolean` | `false` | Whether to show debug grid. | 2.25.3 |\n| font-size | `number` | `14` | Font size. | 2.25.3 |\n| font-family | `string` | `undefined` | Font family. | 2.25.3 |\n| font-style | ``'normal' \\| 'italic' \\| `oblique ${number}deg` `` | `normal` | Font style. | 2.25.3 |\n| font-variant | `string` | `''` | Font variant. | 2.25.3 |\n| font-weight | `number` | `400` | Font weight. | 2.25.3 |\n| font-color | `string` | `rgba(128, 128, 128, .3)` | Font color. | 2.25.3 |\n| fullscreen | `boolean` | `false` | Whether to show fullscreen watermark. | 2.25.3 |\n| global-rotate | `number` | `0` | Global rotate degree of the watermark. | 2.32.0 |\n| line-height | `number` | `14` | Line height. | 2.25.3 |\n| height | `number` | `32` | Height of watermark area. | 2.25.3 |\n| image | `string` | `undefined` | The URI of watermark image. | 2.25.3 |\n| image-height | `number` | `undefined` | Image height. | 2.25.3 |\n| image-opacity | `number` | `1` | Image opacity. | 2.25.3 |\n| image-width | `number` | `undefined` | Image width. | 2.25.3 |\n| rotate | `number` | `0` | Rotate degree | 2.25.3 |\n| selectable | `boolean` | `true` | Whether content covered by watermark is selectable. | 2.25.3 |\n| text-align | `'left' \\| 'center' \\| 'right'` | `'left'` | Text align method when there's multiple lines of text. | 2.38.2 |\n| width | `number` | `32` | Width of watermark area. | 2.25.3 |\n| x-gap | `number` | `0` | Horizontal gap. | 2.25.3 |\n| x-offset | `number` | `0` | Horizontal offset. | 2.25.3 |\n| y-gap | `number` | `0` | Vertical gap. | 2.25.3 |\n| y-offset | `number` | `0` | Vertical offset. | 2.25.3 |\n| z-index | `number` | `10` | Z index of watermark. | 2.25.3 |\n\n### Watermark Slots\n\n| Name    | Parameters | Description              | Version |\n| ------- | ---------- | ------------------------ | ------- |\n| default | `()`       | something with watermark | 2.25.3  |\n"
  },
  {
    "path": "src/watermark/demos/enUS/multiline.demo.vue",
    "content": "<markdown>\n# Multiline Text\n\nSupports multiple lines text separated by `\\n` since `2.38.2`.\n\nWatermark supports displaying multiline text content.\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst content = ref('Naive UI\\nQuite Interesting...')\n</script>\n\n<template>\n  <n-watermark\n    :content=\"content\"\n    cross\n    selectable\n    :font-size=\"16\"\n    :line-height=\"16\"\n    :width=\"192\"\n    :height=\"128\"\n    :x-offset=\"12\"\n    :y-offset=\"28\"\n    :rotate=\"-15\"\n  >\n    <n-table :bordered=\"false\" :single-line=\"false\">\n      <thead>\n        <tr>\n          <th>Review</th>\n          <th>Empower</th>\n          <th>Collaborate</th>\n          <th>...</th>\n          <th>Connect</th>\n        </tr>\n      </thead>\n      <tbody>\n        <tr>\n          <td>Align</td>\n          <td>Enable</td>\n          <td>Establish</td>\n          <td>...</td>\n          <td>Fulfill</td>\n        </tr>\n        <tr>\n          <td>...</td>\n          <td>...</td>\n          <td>...</td>\n          <td>...</td>\n          <td>...</td>\n        </tr>\n      </tbody>\n    </n-table>\n  </n-watermark>\n</template>\n"
  },
  {
    "path": "src/watermark/demos/zhCN/basic.demo.vue",
    "content": "<markdown>\n# 基本用法\n</markdown>\n\n<template>\n  <n-watermark\n    content=\"核心机密\"\n    cross\n    selectable\n    :font-size=\"16\"\n    :line-height=\"16\"\n    :width=\"192\"\n    :height=\"128\"\n    :x-offset=\"12\"\n    :y-offset=\"28\"\n    :rotate=\"-15\"\n  >\n    <n-table :bordered=\"false\" :single-line=\"false\">\n      <thead>\n        <tr>\n          <th>复盘</th>\n          <th>赋能</th>\n          <th>协同</th>\n          <th>...</th>\n          <th>串联</th>\n        </tr>\n      </thead>\n      <tbody>\n        <tr>\n          <td>拉通</td>\n          <td>打通</td>\n          <td>树立</td>\n          <td>...</td>\n          <td>履约</td>\n        </tr>\n        <tr>\n          <td>...</td>\n          <td>...</td>\n          <td>...</td>\n          <td>...</td>\n          <td>...</td>\n        </tr>\n      </tbody>\n    </n-table>\n  </n-watermark>\n</template>\n"
  },
  {
    "path": "src/watermark/demos/zhCN/custom.demo.vue",
    "content": "<markdown>\n# 自定义水印\n\n通过配置自定义参数来预览水印效果。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst content = ref('水印\\n自定义水印')\nconst fontSize = ref(16)\nconst rotate = ref(-15)\nconst fontColor = ref('rgba(128, 128, 128, .3)')\nconst cross = ref(true)\nconst fontStyle = ref<'normal' | 'italic' | 'oblique' | `oblique ${number}deg`>(\n  'normal'\n)\nconst fontWeight = ref(400)\nconst globalRotate = ref(0)\nconst lineHeight = ref(16)\nconst height = ref(128)\nconst width = ref(192)\nconst xGap = ref(0)\nconst yGap = ref(0)\nconst xOffset = ref(12)\nconst yOffset = ref(28)\nconst zIndex = ref(10)\nconst textAlign = ref<'left' | 'center' | 'right'>('left')\n</script>\n\n<template>\n  <n-flex :size=\"30\">\n    <n-watermark\n      style=\"flex: 1\"\n      :content=\"content\"\n      :cross=\"cross\"\n      selectable\n      :font-size=\"fontSize\"\n      :line-height=\"lineHeight\"\n      :width=\"width\"\n      :height=\"height\"\n      :x-offset=\"xOffset\"\n      :y-offset=\"yOffset\"\n      :rotate=\"rotate\"\n      :font-color=\"fontColor\"\n      :font-style=\"fontStyle\"\n      :font-weight=\"fontWeight\"\n      :global-rotate=\"globalRotate\"\n      :x-gap=\"xGap\"\n      :y-gap=\"yGap\"\n      :z-index=\"zIndex\"\n      :text-align=\"textAlign\"\n    >\n      <n-flex vertical>\n        <n-h4 prefix=\"bar\">\n          底层逻辑是打通信息屏障，创建行业新生态。顶层设计时聚焦用户感知赛道，通过差异化和颗粒度达到引爆点。交付价值是在垂直领域采取复用大发达成持久收益。抽离透传归因分析作为抓手为产品赋能，体验度量作为闭环的评判标准。亮点是载体，优势是链路。思考整个生命周期，完善逻辑考虑资源倾斜。方法论是组合拳达到平台化标准。\n        </n-h4>\n        <n-table :bordered=\"false\" :single-line=\"false\">\n          <thead>\n            <tr>\n              <th>复盘</th>\n              <th>赋能</th>\n              <th>协同</th>\n              <th>...</th>\n              <th>串联</th>\n            </tr>\n          </thead>\n          <tbody>\n            <tr>\n              <td>拉通</td>\n              <td>打通</td>\n              <td>树立</td>\n              <td>...</td>\n              <td>履约</td>\n            </tr>\n            <tr>\n              <td>...</td>\n              <td>...</td>\n              <td>...</td>\n              <td>...</td>\n              <td>...</td>\n            </tr>\n          </tbody>\n        </n-table>\n        <img\n          width=\"100%\"\n          src=\"https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel4.jpeg\"\n        >\n      </n-flex>\n    </n-watermark>\n    <div style=\"width: 360px\">\n      <n-form-item label=\"水印内容\">\n        <n-input v-model:value=\"content\" placeholder=\"请输入水印内容\" />\n      </n-form-item>\n      <n-grid :cols=\"2\" :x-gap=\"12\">\n        <n-grid-item>\n          <n-form-item label=\"字体大小\">\n            <n-input-number v-model:value=\"fontSize\" :min=\"8\" :max=\"32\" />\n          </n-form-item>\n        </n-grid-item>\n        <n-grid-item>\n          <n-form-item label=\"字体颜色\">\n            <n-color-picker v-model:value=\"fontColor\" />\n          </n-form-item>\n        </n-grid-item>\n        <n-grid-item>\n          <n-form-item label=\"字体风格\">\n            <n-select\n              v-model:value=\"fontStyle\"\n              :options=\"[\n                { label: '正常', value: 'normal' },\n                { label: '斜体', value: 'italic' },\n                { label: '倾斜', value: 'oblique' },\n              ]\"\n            />\n          </n-form-item>\n        </n-grid-item>\n        <n-grid-item>\n          <n-form-item label=\"字重\">\n            <n-input-number\n              v-model:value=\"fontWeight\"\n              :min=\"100\"\n              :max=\"900\"\n              :step=\"100\"\n            />\n          </n-form-item>\n        </n-grid-item>\n        <n-grid-item>\n          <n-form-item label=\"是否跨越边界\">\n            <n-switch v-model:value=\"cross\" />\n          </n-form-item>\n        </n-grid-item>\n        <n-grid-item>\n          <n-form-item label=\"旋转角度\">\n            <n-slider v-model:value=\"rotate\" :min=\"-90\" :max=\"90\" />\n          </n-form-item>\n        </n-grid-item>\n        <n-grid-item>\n          <n-form-item label=\"整体旋转\">\n            <n-slider v-model:value=\"globalRotate\" :min=\"-180\" :max=\"180\" />\n          </n-form-item>\n        </n-grid-item>\n        <n-grid-item>\n          <n-form-item label=\"行高\">\n            <n-input-number v-model:value=\"lineHeight\" :min=\"1\" />\n          </n-form-item>\n        </n-grid-item>\n        <n-grid-item>\n          <n-form-item label=\"高度\">\n            <n-input-number v-model:value=\"height\" :min=\"1\" />\n          </n-form-item>\n        </n-grid-item>\n        <n-grid-item>\n          <n-form-item label=\"宽度\">\n            <n-input-number v-model:value=\"width\" :min=\"1\" />\n          </n-form-item>\n        </n-grid-item>\n        <n-grid-item>\n          <n-form-item label=\"X轴间隔\">\n            <n-input-number v-model:value=\"xGap\" />\n          </n-form-item>\n        </n-grid-item>\n        <n-grid-item>\n          <n-form-item label=\"Y轴间隔\">\n            <n-input-number v-model:value=\"yGap\" />\n          </n-form-item>\n        </n-grid-item>\n        <n-grid-item>\n          <n-form-item label=\"X轴偏移\">\n            <n-input-number v-model:value=\"xOffset\" />\n          </n-form-item>\n        </n-grid-item>\n        <n-grid-item>\n          <n-form-item label=\"Y轴偏移\">\n            <n-input-number v-model:value=\"yOffset\" />\n          </n-form-item>\n        </n-grid-item>\n        <n-grid-item>\n          <n-form-item label=\"Z轴高度\">\n            <n-input-number v-model:value=\"zIndex\" />\n          </n-form-item>\n        </n-grid-item>\n        <n-grid-item>\n          <n-form-item label=\"文本对齐\">\n            <n-select\n              v-model:value=\"textAlign\"\n              :options=\"[\n                { label: '左对齐', value: 'left' },\n                { label: '居中', value: 'center' },\n                { label: '右对齐', value: 'right' },\n              ]\"\n            />\n          </n-form-item>\n        </n-grid-item>\n      </n-grid>\n    </div>\n  </n-flex>\n</template>\n"
  },
  {
    "path": "src/watermark/demos/zhCN/fullscreen.demo.vue",
    "content": "<markdown>\n# 全屏幕\n\n可以打开全屏，这样显得很专业。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst show = ref(false)\n</script>\n\n<template>\n  <n-watermark\n    v-if=\"show\"\n    content=\"大家艰苦一下，一切都会有的\"\n    cross\n    fullscreen\n    :font-size=\"16\"\n    :line-height=\"16\"\n    :width=\"384\"\n    :height=\"384\"\n    :x-offset=\"12\"\n    :y-offset=\"60\"\n    :rotate=\"-15\"\n  />\n  <n-switch v-model:value=\"show\" />\n</template>\n"
  },
  {
    "path": "src/watermark/demos/zhCN/image.demo.vue",
    "content": "<markdown>\n# 图片\n\n放点图。\n\n记得注意图像 URL 的跨域设置，这会影响图片是否能正常显示。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst show = ref(false)\n</script>\n\n<template>\n  <n-watermark\n    v-if=\"show\"\n    image=\"https://07akioni.oss-cn-beijing.aliyuncs.com/07akioni.jpeg\"\n    cross\n    fullscreen\n    :font-size=\"16\"\n    :line-height=\"16\"\n    :width=\"384\"\n    :height=\"384\"\n    :x-offset=\"12\"\n    :y-offset=\"0\"\n    :image-width=\"64\"\n    :image-opacity=\"0.24\"\n  />\n  <n-switch v-model:value=\"show\" />\n</template>\n"
  },
  {
    "path": "src/watermark/demos/zhCN/index.demo-entry.md",
    "content": "<!--single-column-->\n\n# 水印 Watermark\n\n出现在钱上的时候比较可爱。\n\n## 演示\n\n```demo\nbasic.vue\nfullscreen.vue\nimage.vue\nmultiline.vue\ncustom.vue\n```\n\n## API\n\n### Watermark Props\n\n| 名称 | 类型 | 默认值 | 说明 | 版本 |\n| --- | --- | --- | --- | --- |\n| content | `string` | `undefined` | 水印文本 | 2.25.3，自 2.38.2 支持多行文本 |\n| cross | `boolean` | `false` | 是否跨越边界显示 | 2.25.3 |\n| debug | `boolean` | `false` | 是否显示调试信息 | 2.25.3 |\n| font-size | `number` | `14` | 字体大小 | 2.25.3 |\n| font-family | `string` | `undefined` | 字体族 | 2.25.3 |\n| font-style | ``'normal' \\| 'italic' \\| `oblique ${number}deg` `` | `normal` | 字体风格 | 2.25.3 |\n| font-variant | `string` | `''` | 字型 | 2.25.3 |\n| font-weight | `number` | `400` | 字重 | 2.25.3 |\n| font-color | `string` | `rgba(128, 128, 128, .3)` | 字体颜色 | 2.25.3 |\n| fullscreen | `boolean` | `false` | 是否展示全屏 | 2.25.3 |\n| global-rotate | `number` | `0` | 水印整体的旋转 | 2.32.0 |\n| line-height | `number` | `14` | 行高 | 2.25.3 |\n| height | `number` | `32` | 高度 | 2.25.3 |\n| image | `string` | `undefined` | 图片路径 | 2.25.3 |\n| image-height | `number` | `undefined` | 图片高度 | 2.25.3 |\n| image-opacity | `number` | `1` | 图片不透明度 | 2.25.3 |\n| image-width | `number` | `undefined` | 图片宽度 | 2.25.3 |\n| rotate | `number` | `0` | 旋转角度 | 2.25.3 |\n| selectable | `boolean` | `true` | 被水印覆盖的内容是否可选中 | 2.25.3 |\n| text-align | `'left' \\| 'center' \\| 'right'` | `'left'` | 在文本有多行的情况下，多行文本的对齐方式 | 2.38.2 |\n| width | `number` | `32` | 宽度 | 2.25.3 |\n| x-gap | `number` | `0` | x 轴间隔 | 2.25.3 |\n| x-offset | `number` | `0` | x 轴偏移 | 2.25.3 |\n| y-gap | `number` | `0` | y 轴间隔 | 2.25.3 |\n| y-offset | `number` | `0` | y 轴偏移 | 2.25.3 |\n| z-index | `number` | `10` | z 轴高度 | 2.25.3 |\n\n### Watermark Slots\n\n| 名称    | 参数 | 说明           | 版本   |\n| ------- | ---- | -------------- | ------ |\n| default | `()` | 水印覆盖的内容 | 2.25.3 |\n"
  },
  {
    "path": "src/watermark/demos/zhCN/multiline.demo.vue",
    "content": "<markdown>\n# 多行文本\n\n自 `2.38.2` 起，支持由 `\\n` 分割的多行文本。\n\n水印支持显示多行文本内容。\n</markdown>\n\n<script lang=\"ts\" setup>\nimport { ref } from 'vue'\n\nconst content = ref('Naive UI\\n有点意思...')\n</script>\n\n<template>\n  <n-watermark\n    :content=\"content\"\n    cross\n    selectable\n    :font-size=\"16\"\n    :line-height=\"16\"\n    :width=\"192\"\n    :height=\"128\"\n    :x-offset=\"12\"\n    :y-offset=\"28\"\n    :rotate=\"-15\"\n  >\n    <n-table :bordered=\"false\" :single-line=\"false\">\n      <thead>\n        <tr>\n          <th>复盘</th>\n          <th>赋能</th>\n          <th>协同</th>\n          <th>...</th>\n          <th>串联</th>\n        </tr>\n      </thead>\n      <tbody>\n        <tr>\n          <td>拉通</td>\n          <td>打通</td>\n          <td>树立</td>\n          <td>...</td>\n          <td>履约</td>\n        </tr>\n        <tr>\n          <td>...</td>\n          <td>...</td>\n          <td>...</td>\n          <td>...</td>\n          <td>...</td>\n        </tr>\n      </tbody>\n    </n-table>\n  </n-watermark>\n</template>\n"
  },
  {
    "path": "src/watermark/index.ts",
    "content": "export { default as NWatermark, watermarkProps } from './src/Watermark'\nexport type { WatermarkProps } from './src/Watermark'\n"
  },
  {
    "path": "src/watermark/src/Watermark.tsx",
    "content": "import type { PropType } from 'vue'\nimport type { ThemeProps } from '../../_mixins'\nimport type { ExtractPublicPropTypes } from '../../_utils'\nimport type { WatermarkTheme } from '../styles'\nimport { onFontsReady } from 'vooks'\nimport { defineComponent, h, ref, watchEffect } from 'vue'\nimport { useConfig, useTheme } from '../../_mixins'\nimport { isBrowser, warnOnce } from '../../_utils'\nimport { watermarkLight } from '../styles'\nimport style from './styles/index.cssr'\n\nfunction getRatio(context: any): number {\n  if (!context) {\n    return 1\n  }\n  const backingStore\n    = context.backingStorePixelRatio\n      || context.webkitBackingStorePixelRatio\n      || context.mozBackingStorePixelRatio\n      || context.msBackingStorePixelRatio\n      || context.oBackingStorePixelRatio\n      || context.backingStorePixelRatio\n      || 1\n  return (window.devicePixelRatio || 1) / backingStore\n}\n\nexport const watermarkProps = {\n  ...(useTheme.props as ThemeProps<WatermarkTheme>),\n  debug: Boolean,\n  cross: Boolean,\n  fullscreen: Boolean,\n  width: {\n    type: Number,\n    default: 32\n  },\n  height: {\n    type: Number,\n    default: 32\n  },\n  zIndex: {\n    type: Number,\n    default: 10\n  },\n  xGap: {\n    type: Number,\n    default: 0\n  },\n  yGap: {\n    type: Number,\n    default: 0\n  },\n  yOffset: {\n    type: Number,\n    default: 0\n  },\n  xOffset: {\n    type: Number,\n    default: 0\n  },\n  rotate: {\n    type: Number,\n    default: 0\n  },\n  textAlign: {\n    type: String as PropType<'left' | 'center' | 'right'>,\n    default: 'left'\n  },\n  image: String,\n  imageOpacity: { type: Number, default: 1 },\n  imageHeight: Number,\n  imageWidth: Number,\n  content: String,\n  selectable: {\n    type: Boolean,\n    default: true\n  },\n  fontSize: {\n    type: Number,\n    default: 14\n  },\n  fontFamily: String,\n  fontStyle: {\n    type: String as PropType<\n      'normal' | 'italic' | 'oblique' | `oblique ${number}deg`\n    >,\n    default: 'normal'\n  },\n  fontVariant: {\n    type: String,\n    default: ''\n  },\n  fontWeight: {\n    type: Number,\n    default: 400\n  },\n  fontColor: {\n    type: String,\n    default: 'rgba(128, 128, 128, .3)'\n  },\n  fontStretch: {\n    type: String,\n    default: ''\n  },\n  lineHeight: {\n    type: Number,\n    default: 14\n  },\n  globalRotate: {\n    type: Number,\n    default: 0\n  }\n} as const\n\nexport type WatermarkProps = ExtractPublicPropTypes<typeof watermarkProps>\n\nexport default defineComponent({\n  name: 'Watermark',\n  props: watermarkProps,\n  setup(props, { slots }) {\n    const { mergedClsPrefixRef } = useConfig(props)\n    const themeRef = useTheme(\n      'Watermark',\n      '-watermark',\n      style,\n      watermarkLight,\n      props,\n      mergedClsPrefixRef\n    )\n    const base64UrlRef = ref('')\n    const canvas = isBrowser ? document.createElement('canvas') : null\n    const ctx = canvas ? canvas.getContext('2d') : null\n    const fontsReadyRef = ref(false)\n    onFontsReady(() => (fontsReadyRef.value = true))\n    watchEffect(() => {\n      if (!canvas)\n        return\n      void fontsReadyRef.value\n      const ratio = getRatio(ctx)\n      const {\n        xGap,\n        yGap,\n        width,\n        height,\n        yOffset,\n        xOffset,\n        rotate,\n        image,\n        content,\n        fontColor,\n        fontStyle,\n        fontVariant,\n        fontStretch,\n        fontWeight,\n        fontFamily,\n        fontSize,\n        lineHeight,\n        debug\n      } = props\n      const canvasWidth = (xGap + width) * ratio\n      const canvasHeight = (yGap + height) * ratio\n      const canvasOffsetLeft = xOffset * ratio\n      const canvasOffsetTop = yOffset * ratio\n      canvas.width = canvasWidth\n      canvas.height = canvasHeight\n      if (ctx) {\n        ctx.translate(0, 0)\n        const markWidth = width * ratio\n        const markHeight = height * ratio\n        if (debug) {\n          ctx.strokeStyle = 'grey'\n          ctx.strokeRect(0, 0, markWidth, markHeight)\n        }\n        ctx.rotate(rotate * (Math.PI / 180))\n        if (image) {\n          const img = new Image()\n          img.crossOrigin = 'anonymous'\n          img.referrerPolicy = 'no-referrer'\n          img.src = image\n          img.onload = () => {\n            ctx.globalAlpha = props.imageOpacity\n            const { imageWidth, imageHeight } = props\n            ctx.drawImage(\n              img,\n              canvasOffsetLeft,\n              canvasOffsetTop,\n              (props.imageWidth\n                || (imageHeight\n                  ? (img.width * imageHeight) / img.height\n                  : img.width)) * ratio,\n              (props.imageHeight\n                || (imageWidth\n                  ? (img.height * imageWidth) / img.width\n                  : img.height)) * ratio\n            )\n            base64UrlRef.value = canvas.toDataURL()\n          }\n        }\n        else if (content) {\n          if (debug) {\n            ctx.strokeStyle = 'green'\n            ctx.strokeRect(0, 0, markWidth, markHeight)\n          }\n          ctx.font = `${fontStyle} ${fontVariant} ${fontWeight} ${fontStretch} ${\n            fontSize * ratio\n          }px/${lineHeight * ratio}px ${\n            fontFamily || themeRef.value.self.fontFamily\n          }`\n          ctx.fillStyle = fontColor\n\n          let maxWidth = 0\n          const { textAlign } = props\n          content\n            .split('\\n')\n            .map((line) => {\n              const width = ctx.measureText(line).width\n              maxWidth = Math.max(maxWidth, width)\n              return {\n                width,\n                line\n              }\n            })\n            .forEach(({ line, width }, index) => {\n              const alignOffset\n                = textAlign === 'left'\n                  ? 0\n                  : textAlign === 'center'\n                    ? (maxWidth - width) / 2\n                    : maxWidth - width\n\n              ctx.fillText(\n                line,\n                canvasOffsetLeft + alignOffset,\n                canvasOffsetTop + lineHeight * ratio * (index + 1)\n              )\n            })\n          base64UrlRef.value = canvas.toDataURL()\n        }\n        else if (!content) {\n          // For example, you are using the input box to customize the watermark\n          // content, but after clearing the input box, the content is empty,\n          // and the canvas content is empty. Clear canvas when content is empty\n          ctx.clearRect(0, 0, canvas.width, canvas.height)\n          base64UrlRef.value = canvas.toDataURL()\n        }\n      }\n      else {\n        warnOnce('watermark', 'Canvas is not supported in the browser.')\n      }\n    })\n    return () => {\n      const { globalRotate, fullscreen, zIndex } = props\n      const mergedClsPrefix = mergedClsPrefixRef.value\n      const isFullScreenGlobalRotate = globalRotate !== 0 && fullscreen\n      const rotatedImageOffset = 'max(142vh, 142vw)'\n      const watermarkNode = (\n        <div\n          class={[\n            `${mergedClsPrefix}-watermark`,\n            globalRotate !== 0 && `${mergedClsPrefix}-watermark--global-rotate`,\n            fullscreen && `${mergedClsPrefix}-watermark--fullscreen`\n          ]}\n          style={{\n            transform: globalRotate\n              ? `translateX(-50%) translateY(-50%) rotate(${globalRotate}deg)`\n              : undefined,\n            zIndex: isFullScreenGlobalRotate ? undefined : zIndex,\n            backgroundSize: `${props.xGap + props.width}px`,\n            backgroundPosition:\n              globalRotate === 0\n                ? props.cross\n                  ? `${props.width / 2}px ${props.height / 2}px, 0 0`\n                  : ''\n                : props.cross\n                  ? `calc(${rotatedImageOffset} + ${\n                    props.width / 2\n                  }px) calc(${rotatedImageOffset} + ${\n                    props.height / 2\n                  }px), ${rotatedImageOffset} ${rotatedImageOffset}`\n                  : rotatedImageOffset,\n            backgroundImage: props.cross\n              ? `url(${base64UrlRef.value}), url(${base64UrlRef.value})`\n              : `url(${base64UrlRef.value})`\n          }}\n        />\n      )\n      if (props.fullscreen && !globalRotate)\n        return watermarkNode\n      return (\n        <div\n          class={[\n            `${mergedClsPrefix}-watermark-container`,\n            globalRotate !== 0\n            && `${mergedClsPrefix}-watermark-container--global-rotate`,\n            fullscreen && `${mergedClsPrefix}-watermark-container--fullscreen`,\n            props.selectable\n            && `${mergedClsPrefix}-watermark-container--selectable`\n          ]}\n          style={{\n            zIndex: isFullScreenGlobalRotate ? zIndex : undefined\n          }}\n        >\n          {slots.default?.()}\n          {watermarkNode}\n        </div>\n      )\n    }\n  }\n})\n"
  },
  {
    "path": "src/watermark/src/styles/index.cssr.ts",
    "content": "import { c, cB, cM, cNotM } from '../../../_utils/cssr'\n\nexport default c([\n  cB('watermark-container', `\n    position: relative;\n  `, [\n    cNotM('selectable', `\n      user-select: none;\n      -webkit-user-select: none;\n    `),\n    cM('global-rotate', `\n      overflow: hidden;\n    `),\n    cM('fullscreen', `\n      top: 0;\n      left: 0;\n      width: 100%;\n      height: 100%;\n      pointer-events: none;\n      position: fixed;\n    `)\n  ]),\n  cB('watermark', `\n    position: absolute;\n    top: 0;\n    left: 0;\n    width: 100%;\n    height: 100%;\n    pointer-events: none;\n    background-repeat: repeat;\n  `, [\n    cM('fullscreen', `\n      position: fixed;\n    `),\n    cM('global-rotate', `\n      position: absolute;\n      height: max(284vh, 284vw);\n      width: max(284vh, 284vw);\n    `)\n  ])\n])\n"
  },
  {
    "path": "src/watermark/styles/dark.ts",
    "content": "import type { WatermarkTheme } from './light'\nimport { commonDark } from '../../_styles/common'\n\nconst watermarkDark: WatermarkTheme = {\n  name: 'Watermark',\n  common: commonDark,\n  self(vars) {\n    const { fontFamily } = vars\n    return {\n      fontFamily\n    }\n  }\n}\n\nexport default watermarkDark\n"
  },
  {
    "path": "src/watermark/styles/index.ts",
    "content": "export { default as watermarkDark } from './dark'\nexport { default as watermarkLight } from './light'\nexport type { WatermarkTheme } from './light'\n"
  },
  {
    "path": "src/watermark/styles/light.ts",
    "content": "import { createTheme } from '../../_mixins'\nimport { commonLight } from '../../_styles/common'\n\nconst watermarkLight = createTheme({\n  name: 'Watermark',\n  common: commonLight,\n  self(vars) {\n    const { fontFamily } = vars\n    return {\n      fontFamily\n    }\n  }\n})\n\nexport default watermarkLight\nexport type WatermarkTheme = typeof watermarkLight\n"
  },
  {
    "path": "src/watermark/tests/Watermark.spec.ts",
    "content": "import { mount } from '@vue/test-utils'\nimport { NWatermark } from '../index'\n\ndescribe('nWatermark', () => {\n  it('should work with import on demand', () => {\n    mount(NWatermark)\n  })\n  it('should work with `z-index` prop', () => {\n    const wrapper = mount(NWatermark, {\n      props: {\n        zIndex: 9\n      }\n    })\n    expect(wrapper.find('.n-watermark').exists()).toBe(true)\n    expect(wrapper.find('.n-watermark').attributes('style')).toContain(\n      'z-index: 9'\n    )\n  })\n  it('should work with `x-gap` & `width` props', () => {\n    const wrapper = mount(NWatermark, {\n      props: {\n        xGap: 10,\n        width: 100\n      }\n    })\n    expect(wrapper.find('.n-watermark').attributes('style')).toContain(\n      'background-size: 110px'\n    )\n  })\n  it('should work with `selectable` prop', () => {\n    const wrapper = mount(NWatermark, {\n      props: {\n        selectable: true\n      }\n    })\n    expect(wrapper.find('.n-watermark-container--selectable').exists()).toBe(\n      true\n    )\n  })\n\n  it('should work with `fullscreen` prop', async () => {\n    const wrapper = mount(NWatermark)\n    expect(wrapper.find('.n-watermark').classes()).not.toContain(\n      'n-watermark--fullscreen'\n    )\n\n    await wrapper.setProps({ fullscreen: true })\n    expect(wrapper.find('.n-watermark').classes()).toContain(\n      'n-watermark--fullscreen'\n    )\n  })\n})\n"
  },
  {
    "path": "src/watermark/tests/server.spec.tsx",
    "content": "import { setup } from '@css-render/vue3-ssr'\nimport { renderToString } from '@vue/server-renderer'\nimport { createSSRApp, h } from 'vue'\nimport { NWatermark } from '../..'\n\ndescribe('server side rendering', () => {\n  it('works', async () => {\n    const app = createSSRApp(() => <NWatermark />)\n    setup(app)\n    try {\n      await renderToString(app)\n    }\n    catch (e) {\n      expect(e).not.toBeTruthy()\n    }\n  })\n})\n"
  },
  {
    "path": "test.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en-US\">\n    <head>\n        <title>Just a moment...</title>\n        <meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n        <meta http-equiv=\"X-UA-Compatible\" content=\"IE=Edge\">\n        <meta name=\"robots\" content=\"noindex,nofollow\">\n        <meta name=\"viewport\" content=\"width=device-width,initial-scale=1\">\n        <style>\n            * {\n                box-sizing: border-box;\n                margin: 0;\n                padding: 0\n            }\n\n            html {\n                line-height: 1.15;\n                -webkit-text-size-adjust: 100%;\n                color: #313131;\n                font-family: system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji\n            }\n\n            body {\n                display: flex;\n                flex-direction: column;\n                height: 100vh;\n                min-height: 100vh\n            }\n\n            .main-content {\n                margin: 8rem auto;\n                max-width: 60rem;\n                padding-left: 1.5rem\n            }\n\n            @media (width <= 720px) {\n                .main-content {\n                    margin-top: 4rem\n                }\n            }\n\n            .h2 {\n                font-size: 1.5rem;\n                font-weight: 500;\n                line-height: 2.25rem\n            }\n\n            @media (width <= 720px) {\n                .h2 {\n                    font-size: 1.25rem;\n                    line-height: 1.5rem\n                }\n            }\n\n            #challenge-error-text {\n                background-image: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIzMiIgaGVpZ2h0PSIzMiIgZmlsbD0ibm9uZSI+PHBhdGggZmlsbD0iI0IyMEYwMyIgZD0iTTE2IDNhMTMgMTMgMCAxIDAgMTMgMTNBMTMuMDE1IDEzLjAxNSAwIDAgMCAxNiAzbTAgMjRhMTEgMTEgMCAxIDEgMTEtMTEgMTEuMDEgMTEuMDEgMCAwIDEtMTEgMTEiLz48cGF0aCBmaWxsPSIjQjIwRjAzIiBkPSJNMTcuMDM4IDE4LjYxNUgxNC44N0wxNC41NjMgOS41aDIuNzgzem0tMS4wODQgMS40MjdxLjY2IDAgMS4wNTcuMzg4LjQwNy4zODkuNDA3Ljk5NCAwIC41OTYtLjQwNy45ODQtLjM5Ny4zOS0xLjA1Ny4zODktLjY1IDAtMS4wNTYtLjM4OS0uMzk4LS4zODktLjM5OC0uOTg0IDAtLjU5Ny4zOTgtLjk4NS40MDYtLjM5NyAxLjA1Ni0uMzk3Ii8+PC9zdmc+);\n                background-repeat: no-repeat;\n                background-size: contain;\n                padding-left: 34px\n            }\n\n            @media (prefers-color-scheme: dark) {\n                body {\n                    background-color:#222;\n                    color: #d9d9d9\n                }\n            }\n        </style>\n        <meta http-equiv=\"refresh\" content=\"390\">\n    </head>\n    <body class=\"no-js\">\n        <div class=\"main-wrapper\" role=\"main\">\n            <div class=\"main-content\">\n                <noscript>\n                    <div class=\"h2\">\n                        <span id=\"challenge-error-text\">Enable JavaScript and cookies to continue</span>\n                    </div>\n                </noscript>\n            </div>\n        </div>\n        <script>\n            (function() {\n                window._cf_chl_opt = {\n                    cvId: '3',\n                    cZone: \"platform-test.deepseek.com\",\n                    cType: 'interactive',\n                    cRay: '8ebb84cbfca5dd8c',\n                    cH: 'zQF49qXP.DjteD56ESRGlqxJMetjc9tgCEeE2dVOg2E-1733144623-1.2.1.1-R3rYRukqb6c.YmgqvA0nOlwD8fSpIAhsbhhb353HF_jrp2jWZKpz1qAiBTTeTqKH',\n                    cUPMDTk: \"\\/api\\/v0\\/users\\/get_api_keys?__cf_chl_tk=phrRzYiqROxVYDU6mUz4d8C2.rY9DEJNjIns77D.vfU-1733144623-1.0.1.1-M9u1czggbTBJWSFTa2hHMPbwU7CDExOUbvy9f1P4Oy0\",\n                    cFPWv: 'b',\n                    cITimeS: '1733144623',\n                    cTTimeMs: '1000',\n                    cMTimeMs: '390000',\n                    cTplC: 0,\n                    cTplV: 5,\n                    cTplB: 'cf',\n                    cK: \"\",\n                    fa: \"\\/api\\/v0\\/users\\/get_api_keys?__cf_chl_f_tk=phrRzYiqROxVYDU6mUz4d8C2.rY9DEJNjIns77D.vfU-1733144623-1.0.1.1-M9u1czggbTBJWSFTa2hHMPbwU7CDExOUbvy9f1P4Oy0\",\n                    md: \"i7yxB2eO7P4HY9uL0fZktVxhHOEGHUbmqYzr2pvn7dU-1733144623-1.2.1.1-soiylB39JKnUDYqfDcqo9vJlxmadBXWUjWn64WYoO.Z93kuBBJ2vLvN9i.pXiop4gc4okb3KQ6nkDVkUXqqWu9crpsrIxJZIW2eE8vj9pXsEJfq0hRGTv4HlCvfAyf5xvvBxSUbv.q.IuNm3mlcCe0UUFOIoxh8hM2NdcMfLceoso5IDDHWZM3weReqj4gg3aQ9Fb8Rm9siQ6sXDoPXfn6.UmVIDBP2uFJOpSBZuysQeOq6kR6g476XpCiWxdLzTtWxXlDbA3j_3NS1SzGE.Rw8RxdUuLEkfrj6p0470s6cYx3f3y6_C0gfwhU6mjXRpL71qFosnS_qocqnz0KQX12TOIqpnrHZUmVSv04JLdbuG4B.P1WJ8Y4WOOqilysEljxiPy.Zw8Ya3zWw.13oheNgV0gmzFXK4VIcqBaQpOyMDcQFG8EkJW.7XDw6C8ibXvv52Yw49UTOoMgJRmWbuMZWJBhyI9eoW.hmuoXCXKVH9XdXakIC5qgmCESJ.Y8qUjjlJ_utlEMUYepfUjfrw62BZFDcMWP5WI3r4kyObMkky3CuPz.Z.aoe7BZlxTd0isWDmsmumQNeB7Qp.T8TCgjIJRbLhJI_9jAdj1nPMGMIkQoWaN_S43rn3jMJL_VNjGPvvd5UG4_g2Tp3JP7QB87gDOg92Hp1326wvcNEW9vEwl8ZqvrFJOvCYUTE7ksIdgm64SkvfB64gV.VRPO0RHe4J_L2Fu7kA5Yam_6wwhJ8AWlrDwGno16g2Q.E9of4.ZlQt3gjOfyuP4ojOTcjah7e8SI1bjLkzq2V1GSa14PxHXTDckZ3oTGH3oj4wWgycSpIFdcRI_SXHh4RYY7Zehxpu.Y2BUN._fxsEvGsPqM5i6JyU.Cc5zqrpcqqQTssf1x8wvvmRl.OjSgwFLrsk.faEiiYqzA4IWFwjzKnVIQeyWydIqgik8qKv7miMpgrs7eZUOC8SrZmiZJVB.EOQFCR8tEGy3XKv0kdgG1HPslk9smO.iNLPAh2UJd0w5jHQGv7zN6WrqD6ZGaHui40YQWBsh2t4_jj0UxHnGPy0g3Ydb0bR4cbc1Lez430kk7RTF5Ov6mg_GcSpd4FZUKBsFRkVoXeVCjaF46l4t_QbMvDXcz.t0pmM1a_V9RzcJs6TUQFDF5F6TD18iS0Il2nfuz28ymlrKPSjZpHYNnROgpOXovDuIzzR.XLGWX0ELMn6m2Lr.emcAoXvfNZXDkk0SfHy1tclA4OtWozHcshZS0KGTqtbS43_Izo4nx07BvqWFODCsqkdEwRFAUKkpmM7XT3rlfB4UaQjdRiyRUKvtHEiIk7GbRi9vAf.wlehBFsa96Q16TJRUjBrVdg4Nh94TbCPBczWbcnsc1XlriGSsMcDj_45hHpMmz_DGG6zwRl_4hBjzAwHKtqzwVuRUjxgGFJArh4Ei8NE72fMT4w49DBWCTt.51TdrL9dPUqkGxjX5s1_ZHEHmV56CerBJk0.pv4VHGOsy67N5a6RMa1t0Cvt7TiivjBevpqOirXeqkGjzzZ6Wlox4ZKLFarz95gC8.TyZaZwSKKWhixMQ2C5Z4BVMMwNeCuLavfsCyz.Md9eK72BwlLd8MDynpbbMWhlM8DJRYZ_U6HT101hbqwqtFVhbuS08RdDjKhnXqO6T1FH96o77_.UkujtumdVkFK4GAYMmosz_tf0hILEDNfLBrtzD.GtC3NeVa8nG5uKbMl9xtE_8BTvKoKoGdmT37zofqaQf5QUKH84M.FlbQn1qKPSgHrUa7K91C1_83PMwZCybEAWPmyn8F5EYeo2iJBYOYLNUGqytHJXd7QavgwbXrOmnxHGeTxj7Pm25EQQfUyeG9RuZ8dMbE23swOezl_lxVpX0VgY00BaydniD7GHObfSRkMaSaFIAAHKbwEwso5IpcBKoThau6FuNF_cp9xnb.uCdikWRQjXnwnVDEZ3G6fYe9s_LoCY9l8i33cy2i9v70LpzWNB2QsVdc58KVcXSUpWOZW.rosdt7x8y0uzgedtnVjWhdiumhxKxCX.y1uh7IAMVZsfucHIOj5z2GmVJc64vym6dU_ShxsltcK7ULo\",\n                    mdrd: \"SPzqqPhWqd.9U6IdrpfRwVz.7mDNJdh4POLZmTOPqnM-1733144623-1.2.1.1-t8MBHxvSsSmvW5ieWBG_4fSxltqJq7tzLR7_nWdDmJTk14Yv7_rulE2pT.zsy0xNSmFqtFgvxF7uKd.EukYz_qE3x4SntEH1osycyivUrkWGHshnGB8owpX.uCJwA8ohMsE3VD4.IuZbsHpQ8XNZlRFithqWFn9jffWG04ueHVv7qaAP4JOsT2bLijz3uviQ2LMW7L.Xtf0dP8AlDDoKdA5tdRgmfcyLxrsfu.uWnjEEztbklCHgGKs0MlIDNWTLE6CC01O1gXW95jvyJG9iR9TO7c2T4U0L_fN6vYD4gtR.hyeOMAdBFR2cfjJX3B0UbtwgjoRM6XZQBW1YP8j1uFBWpJVKf7VzIcE9epNvxmbnZeHGVoAZrH7HUsa8L3VAOvnhLsyCdeL.1VGjRcY3CbFynwxqbDKsaesgzpvOVyJBE.Z3JkpuR.6H1a68PYPq6DgRdc84qW5WVf6ydWmE1jAqbRshKKBhpjK1mztcNk9vRodl3cfqj7DheINbVxFmkKs3aeRxYgntTxmb_dZ8T8Kc1_CSh8AJYJyP.7DgEq1z2S3yjxs6MhvOlgJVeUHjSAaxZ5fJdAmmO9gV7QneADvBxiOyW.TfOly9pGE0lyUuTSOiqOE8IsnB7Kb94qg17qYg9msupYz7ZLuNZupZU7IpB5qiT3wWg4fsmcexQpfYx9VSS1uEerlpM9ZCG7tyUsgl8McLES38392ve2Mf7Q.zWBNb.OvttNoojvEibxyAEezdO2cY2Ss1O3l5xOspJe.G_Nq8zGLCnQJyVy11kimA9gvacHwc3lt_4zPB0MWKdC_nxM0oxfj.SsQo2fLBLZ08dY.Tr1KYmrSDf8rZXdIHsvj2uYGb8qDixyievABBkMehnf_Tc1iBQs9T5LosWRPBiL6wBFc1ERirXfaaG5AvNw079Cg3AHz0loMS72KVqhfqOj8dVL8xLvsyPpvMC5KUPr9NGTW0efFJ2EQhwnroVBYi4VocJ9VJTu__1c1AVPSTtZeyELuXs8VtyM2sabKy.WaxKhFfbXiyFWx221VTC1edsmrIv65LsxEihTT9SfJ3mDAY7.coXCDL6swmlzcf68C1mAv1G2lFJBnLGqUZ8eAWzDX_vGUeImWHdsqEvLHkWZn5bJo.i3smzr4FnnYnWtEEXr4JyKoMFjUPYGq1O.DzFc4QssbzTr5LprslMeKYvvO._M5ja1VGC5SNliMMq.VD.pmE7MxADCgykhGqTZjNV2L0JULiFUuU1AznmuhlhiYc3mB0yeptETwqbYZgNIdLJvfTT0_MTFm1QjB3o7ppPTfMI12c9Ge5Uwcn1365NN1nkPUT2V.IgVEaOVhQ2AKna.HVlIzxeEA2cjeHO26GSRnm3EiRSY8nVH01s_q1MpKMN0XYD.7pja0t1BqPzo6PqMlUcSqOIxVpuqeue17fMQJML3ylqpshYKrDTweUZzTFR4Y2CSMo9c_H.eZkv1JMLXWnkqURj6J7HBuxq20bOWSSBbv_aU6SRdX9tI5bKnwbd.ImjOGpy4grDVsp7tyBbin4uTAVK5FSDbae8eQy6LDZkWvshbGNFJtgQ3o8Y4H8g1XpPAoAzvDuqin0MFPww8UaCaJ50dQyl_mUf3IdLBMI4MgXN94tSSpYr5k9NgoRRXroV64CPzbPLgYmYIRZHWadcqF6OrLbbQHEvi7SLdczjws13ELZCNEjtqkzPUvfPpW0VGE.XovkyNvzrRP6PtWqlsKEox663pAdaPJY2LKhTwUogPQ9tpAkA1DPpaMujOyurcyg6TMrXHvFAV5wHS8eDeojJwWmIYPmA1ijkFPEA6WWqvggJ.8b8Q4OyWDOZ.I7QDJgzhZ5GTzl3.FiyMkLcqL6cIKAvRDtTmcufZ02O2nkQ3qcqy8.NvV4gZwmtP9Mhoit6u584WXiaxvmiM_wGeHbwGz6iiqfKkXaE2w9HYjk5tF6v5zMBswEQAKslBiDdF4107ReiQZdZtsBrC5tH5kmXHEkISet6r6doFf4AUci9xg2N9avwCd2qxyI4udRdEJxWWHQNVqVB_hrguhXGgLCxGcv0SuyiTu2MSEOJolKzrbtkYT1TCpkTJHlszdXcxXwoEiWB6CsmSax6eJZZIxeFiBNbg1NBcROnlvaKgFpkbLYH5WGa149htVP0R.b_CHCbgoNEebwbHUxMQh6YLi2nY7iFGOhpgBer6HQSaGPbwXKMZawcS0BCr3EanKALJHe9Rc19Aeb531uQv_nIZWAiM4lSJTyVG1edXPPsj4qy1WeKHRMHREfhuzR9yjWj.1oJvx2IdAnFBmju6rKOmRFJIwqPsgJssmmSDml8QJ1Vqml1NqkS78JfIA.CXQ5BaoukYZgl8iIM8UcUaixG1qkZYzl0ZPXGojeHK1V3QkvgepEIyvD5Tp3DTPgcO39x9DUgglhCBQyl9vAA6Pp1RvVb_WeoBqFLVkY0Lgeui.RsPcttHNuZRBc3gy4AMdiQhOffXdzgjEQn4ynN_V_8Z9dakD_HuO8r5aSXWtCyMW7_ALuoDxItaoWVzDP3tImUdaGNdlbWfGOTT2S1xHfQ1pTpcexbSCOvSv6m9YuaKaBmi_lehppqcv0cWw_YVr2lY96nTVvBCcHzcGbgt7UJmgzq4K25cUwc8R7kaRsx6EKCnF5AThXZ27Y098.82YuxE5nT4yIzZh2iY.zcQR6mTH53Rn_QweLVwhSJUxzQD6iGmL5nRGwzE9Ha7xM.p.I1sAHG5FRocyzOKgW_bR7BpuUhWnXAphlkAFRr6NbRCeLd1t_3hKdVe1abVcx4EQPBc3qW8WbGFvRn3kTnG7UQj60J6BoOJMI_e2U1y4QvvWfZz1afdwoL9KusaaZc5669vOYGk9MUuLL29NjqIZbZ5CXNL9U4HRU5owL25JmFc6mWFZJqlinMXZ2rD96HF935w603AREXGN7Qn1PtbnHE5A6k3ekrDgrix0gLpd8orPAU8vDnAnM3mJWWXvCE6F92pmAGqtBu4rnXTmcqKMv4FMB1RdRymBBsZw1EyifoSap81YX2nVBVzJ4LUHu_Ej49JadybFjThmMFk5G7wtuGzlwQ7hNwUkIZ_5KWwQrexBda00rS6ZK7hVGepaVEQGyruqUAgsWrdReeA6.9YDzIbz17Yjy6kJN_CIijVfmjHLBRebJtbEZzQmHuKsHakgeuGxzqHX8AZy8zKp0UOgtme8gLZs5TZ3yT2CEhUWft0C_nNWio4RQ7.6rorID5o8KyoIhv43.eIjQ0zhHbzICGT8EMg9rDFneyDFehLrFxzI7JiZFmkYHiSm3ATy1pnzXhR5U0P5MDpUUu.9XZhH76pNUMLzF39i7.7Jt6MaUMAZrt98flbdz3Qq47RYa9bUme.Vo5Bn1pozwRqM7uG44.Do7qu2LVCnIiAses1lJRa9JS92N7LcmGqaqwWpPYegy5r8ZLRAZAvxEJSv9I1arZAEbhavn_BAMwIc9V2fpVjlZpuA8P1.lpDaBjsd6tsKQUq1D.jrztvoZnrquBzNFarvJg3bj9QFdUrKfi3mL9Q5FHakQp2k1MOS9uJv6DuzDTZESglEyrvPcbbSU_ZXDiZeVS3Fe6NHCyLEFYlo7pOgBNgh6KdnEZYE1MEs7RHqLGmj3oJ7UWE4pJZO_yZ5cYzwfqXAtO4CldozYCObPjU93aWnxZkYV2vakki_B5zm8AFzfsQHq6SQf0ivR_SVU38wSVBAWVLrg1dfaO6RMOyeBHbEfzOFYYNyp4vkrqXH8BhmLvsmNPvkmJ0CrUcBPanx3X9Lp03dP0kDg58cHSyZLoJpnhVCXyjTzOQ4NznTZMA1j8nLoyIBWF414nBA3FyN6nlJ7jnKcTKgpCW1i1Cp3yh2f62MdBH.KSBX60uaLZPX8IbRDnlY7._.7RtRmUERNWFr4B3QLcfkxIHgZFGr5690E4zb_HZB1WvztqRertGt2UZkgvwhPK6HSAKglnz2i_K7zjJJ.vAL6wEjBQ_kb9_nuIau9LC5nLO._XryTjxcnoJNWo41_LTFOWcpuWD6j7VWjszm5iQl1_HIlRBl6B9UIwS4gMv2xTmAp7d9u3mAnGq8nq5bvBG5YD3Jae9XuhEKM8F07xCBKZe7.wC5fTLpR5FbH6QnK5YmRL9jOdqb_HMKfWAGqVRola4FCRccd2.WoKvDjk61Mut1a5uydfXMtjplFaqQmTxpXqVI1_0AnV.IRMxaytWV.0mzfncvaJX7YSIe23nLEfS.YssRQGeygmCuDUqwlSfUPaOEC1fCJPyQuH.YoYo62Flwq8LBxtvnDmzKGipJKACzbfVN3pFiUS73.nG6GNGlFBLYT.U43wmooChBE0ur_oPbJjyBDpyVdmRbwOHIe7AVlIvBWlP8cLNBUceclBYQ756LyJhjWAk1OMPf101QA050b1ItU171MRhnLSK6Sp_IBP1xNtvEAlVcPrzE5tOoOm5.hI9ibPqPuehCO87oD2KyJD82A0h5W4G7GIzq8s.BVdZQedopnaUaT4zrRl.LKy7naymTMFbGQafIoUm6A5rS91V1Cs2RTaP80n89Tb0GB6G5WXP.iOu5pZoNNt3nfbwgL_auQwxoTfnUyRT9C1KFz.NnyZTmoOhjaSY4gCXR_QxA_cFpcpKOqHrlSLGxz4STxuO.a2oA_d_1LGu5SnXhfL08QuOXRsrwYHNqwLPvaHRPV9Ic3bvruL2hFLwU6Tg7RFGWQMjqNzAkYVHUZ5bQQ8cK0YoCQ6HWrk.NdN3xjZ676A2YCEDkPg_9ajvR_COxXADzqBFHxIscOLO_dMOkPD0GdjO1CGUopG3CaLDnzj0ifTixdbl8lOQ_QJBJwHssi6ADu8OpkLi3hT.rzqxsKkZ5cUXRepoT3yPK3hMzn4xrVilSJQckfi1VO3YOEfj.3D7lOtYEglrG6LB9dQ4NWpUga3_tYVaxvbRS_B4tZtd5SDVqnFG53pgSWpZR54zjgGeKJ_ZIGKjdbiXIQyyxgg_iENYyyX7sYIBM2_g4D2aSuBO5CZYQMqRtxiU07O_njKt8lf2btn0Ozgs10Mp11rzqPABxP869MnL9bf9d1osLGdziwIKTF2s7RoxDbc5KjuQElurwcNG3_.8q42P6WB.o80LTqFB5vYNW7N_rerDrEDDNTiKo9nbZeHvq5j2WxBvabMkE5qpsOOj1HsTKc1BiyLKH.BJ2N1GVftaWmiLbJ_FesoS72SnltqvXsPrzaM.XqkS4Ub3UuZSuW.c80isHaaPZQ.6wUblDV30YUxWGnlDom23gDf.vGKvDbjlPmnConp1NnCYcGh1_ltaDZAUEQokId9VRMAX_aegQT_TnhLXnci8OcszTuSaF_8CEYFSTrQHJz1GtdJBWpa0IGSwOg3S7JCuGs_2r5sVWSVeBl7tetpJT9ZwccHprnUCP9pyIixbkurZu6WJjV._xQbrCfMes3UX_160VOTViE.oTIhjSM9DwBghjopws3o9aI2jQ0i_6EarYUsQddSLVOcCd4j0S_RQZBxRt5h2dFtmpgI.JB_OMPe_1EkMkWv5gsPk_uo61N0yTvx9T_ZftY58CVbR4wR5glyh3S_o6khWmC.CkmHCU_cZ0XgWQ5MJ41Q_oy05c6GYAYdS7kSXVdsmGj22dpKfr7DpdtWdXY77GHHLGaLJ1vKADrTSxR71RJtQ_mH8Qd63KtP62t8hz.SAt80b_3a67DktmyXLn4TVq6hT_DSy_GJtFpSOarOVVY4CSed_4gKpbBkqpM38NGE87X1mwuGmctvgQY2ieg5lIQwmvyB_w241n3G5K.VBt6kiF3YSf.PargwPRZ4yVPizd8Mzqjwy.KnV5Qu3LMTvd9DnUITeNnZHCGuSGnr045Xw2mnuZMlITx5VK5pue4o0YGfSJckCxCfsAKwJmARPxL5J7wv_27.1EJPFb7d_x1G6.Hc9JoPl39RWFYbeWvcdACWhq35AY8n9_DEohDBbiw9r0q8QfPNwoYxVfFy1zAbu5xcgLJPeyZF08BB_RjPDgeIQyMjsCwG_IMd13CJpFBaYkxMS1hXxGWRFrIjkiDlwyzftXo.z5k.tl0LyER2NR4yQa6tbjRj7ZuFFIVcLKM6vFdNMqAqDl7ftkTqFhkkq4.2pFZgyejVDxQKTmy4xfiQ2kRL6a8LxY5V1Kz7aH6mUDCsdxlB1yLlcm3S34DIFyD1BI4\"\n                };\n                var cpo = document.createElement('script');\n                cpo.src = '/cdn-cgi/challenge-platform/h/b/orchestrate/chl_page/v1?ray=8ebb84cbfca5dd8c';\n                window._cf_chl_opt.cOgUHash = location.hash === '' && location.href.indexOf('#') !== -1 ? '#' : location.hash;\n                window._cf_chl_opt.cOgUQuery = location.search === '' && location.href.slice(0, location.href.length - window._cf_chl_opt.cOgUHash.length).indexOf('?') !== -1 ? '?' : location.search;\n                if (window.history && window.history.replaceState) {\n                    var ogU = location.pathname + window._cf_chl_opt.cOgUQuery + window._cf_chl_opt.cOgUHash;\n                    history.replaceState(null, null, \"\\/api\\/v0\\/users\\/get_api_keys?__cf_chl_rt_tk=phrRzYiqROxVYDU6mUz4d8C2.rY9DEJNjIns77D.vfU-1733144623-1.0.1.1-M9u1czggbTBJWSFTa2hHMPbwU7CDExOUbvy9f1P4Oy0\" + window._cf_chl_opt.cOgUHash);\n                    cpo.onload = function() {\n                        history.replaceState(null, null, ogU);\n                    }\n                }\n                document.getElementsByTagName('head')[0].appendChild(cpo);\n            }());\n        </script>\n    </body>\n</html>\n"
  },
  {
    "path": "themes/tusimple/.npmignore",
    "content": "~*\n*.tsbuildinfo"
  },
  {
    "path": "themes/tusimple/README.md",
    "content": "# @naive-ui/tusimple-theme\n\n## Versions\n\n| @naive-ui/tusimple-theme | naive-ui |\n| ------------------------ | -------- |\n| 0.1.8                    | 2.7.3    |\n| 0.1.9                    | 2.10.0   |\n| 0.1.10                   | 2.15.2   |\n| 0.1.11                   | 2.15.4   |\n| 0.2.0                    | 2.24.6   |\n"
  },
  {
    "path": "themes/tusimple/package.json",
    "content": "{\n  \"name\": \"@naive-ui/tusimple-theme\",\n  \"version\": \"0.2.0\",\n  \"author\": \"07akioni\",\n  \"license\": \"MIT\",\n  \"main\": \"lib/index.js\",\n  \"module\": \"es/index.js\",\n  \"files\": [\n    \"es\",\n    \"lib\"\n  ],\n  \"peerDependencies\": {\n    \"naive-ui\": \"^2.24.6\"\n  }\n}"
  },
  {
    "path": "themes/tusimple/src/TsConfigProvider.tsx",
    "content": "import {\n  type PropType,\n  defineComponent,\n  h,\n  onBeforeUnmount,\n  toRef,\n  watch\n} from 'vue'\nimport { NConfigProvider, configProviderProps } from 'naive-ui'\nimport { merge } from 'lodash-es'\nimport type { CNode } from 'css-render'\nimport { renderFilter, renderSorter } from './data-table'\nimport { mountSvgDefs, unconfigurableStyle } from './unconfigurable-style-light'\nimport {\n  mountSvgDefs as mountSvgDarkDefs,\n  unconfigurableStyle as unconfigurableDarkStyle\n} from './unconfigurable-style-dark'\n\nimport { themeOverridesLight } from './theme-overrides-light'\nimport { themeOverridesDark } from './theme-overrides-dark'\nimport { icons as tusimpleIcons } from './icons'\n\nconst tusimpleComponentOptions = {\n  Pagination: {\n    inputSize: 'medium'\n  },\n  DatePicker: {\n    timePickerSize: 'medium'\n  },\n  Dialog: {\n    iconPlacement: 'top'\n  },\n  DataTable: {\n    renderFilter,\n    renderSorter\n  },\n  DynamicInput: {\n    buttonSize: 'small'\n  }\n} as const\n\nexport default defineComponent({\n  name: 'TsConfigProvider',\n  props: {\n    themeName: {\n      type: String as PropType<'light' | 'dark'>,\n      default: 'light'\n    },\n    ...configProviderProps\n  },\n  setup(props) {\n    let currentUnconfigurableStyle: CNode | null = null\n    function mountLightTheme(): void {\n      mountSvgDefs()\n      currentUnconfigurableStyle = unconfigurableStyle\n      unconfigurableStyle.mount({\n        id: 'naive-ui/tusimple-theme'\n      })\n    }\n    function mountDarkTheme(): void {\n      mountSvgDarkDefs()\n      currentUnconfigurableStyle = unconfigurableDarkStyle\n      unconfigurableDarkStyle.mount({\n        id: 'naive-ui/tusimple-theme'\n      })\n    }\n    function unmountTheme(): void {\n      if (currentUnconfigurableStyle) {\n        currentUnconfigurableStyle.unmount()\n      }\n    }\n    watch(\n      toRef(props, 'themeName'),\n      (themeName) => {\n        if (themeName === 'light') {\n          unmountTheme()\n          mountLightTheme()\n        }\n        else {\n          unmountTheme()\n          mountDarkTheme()\n        }\n      },\n      {\n        immediate: true\n      }\n    )\n    onBeforeUnmount(() => {\n      unmountTheme()\n    })\n  },\n  render() {\n    const { $props } = this\n    const { themeOverrides, componentOptions, icons, themeName } = $props\n    const tusimpleThemeOverrides\n      = themeName === 'light' ? themeOverridesLight : themeOverridesDark\n    return (\n      <NConfigProvider\n        class={`ts-${themeName}-theme`}\n        {...$props}\n        themeOverrides={\n          themeOverrides\n            ? merge({}, tusimpleThemeOverrides, themeOverrides)\n            : tusimpleThemeOverrides\n        }\n        componentOptions={\n          componentOptions\n            ? merge({}, tusimpleComponentOptions, componentOptions)\n            : tusimpleComponentOptions\n        }\n        icons={icons ? merge({}, tusimpleIcons, icons) : tusimpleIcons}\n      >\n        {this.$slots}\n      </NConfigProvider>\n    )\n  }\n})\n"
  },
  {
    "path": "themes/tusimple/src/data-table.tsx",
    "content": "import { h } from 'vue'\nimport { CaretUpOutline, CaretDownOutline } from '@vicons/ionicons5'\nimport type { DataTableRenderFilter, DataTableRenderSorter } from 'naive-ui'\n\nexport const renderSorter: DataTableRenderSorter = ({ order }) => {\n  const chevronStyle = {\n    height: '16px',\n    width: '16px',\n    marginBottom: '-5px',\n    transition: 'fill .3s cubic-bezier(.4, 0, .2, 1)'\n  }\n  return h(\n    'div',\n    {\n      style: {\n        marginLeft: '8px',\n        display: 'inline-block',\n        lineHeight: '0',\n        width: '16px',\n        verticalAlign: '-0.15em'\n      }\n    },\n    [\n      h(CaretUpOutline, {\n        style: {\n          ...chevronStyle,\n          marginTop: '-4px',\n          color:\n            order === 'ascend'\n              ? 'var(--n-th-icon-color-active)'\n              : 'var(--n-th-icon-color)'\n        }\n      }),\n      h(CaretDownOutline, {\n        style: {\n          ...chevronStyle,\n          color:\n            order === 'descend'\n              ? 'var(--n-th-icon-color-active)'\n              : 'var(--n-th-icon-color)'\n        }\n      })\n    ]\n  )\n}\n\nexport const renderFilter: DataTableRenderFilter = ({ active, show }) => {\n  const fill =\n    active || show ? 'var(--n-th-icon-color-active)' : 'var(--n-th-icon-color)'\n  return (\n    <div\n      style={{\n        display: 'inline-block',\n        marginLeft: '8px',\n        height: '20px',\n        width: '20px',\n        lineHeight: '0',\n        verticalAlign: '-0.15em',\n        cursor: 'pointer'\n      }}\n    >\n      <svg\n        style={{\n          fill,\n          height: '20px',\n          width: '20px',\n          marginBottom: '-2px',\n          transition: 'fill .3s cubic-bezier(.4, 0, .2, 1)'\n        }}\n        viewBox=\"0 0 24 24\"\n        version=\"1.1\"\n        xmlns=\"http://www.w3.org/2000/svg\"\n      >\n        <g stroke=\"none\" stroke-width=\"1\" fill-rule=\"evenodd\">\n          <g transform=\"translate(-614.000000, -4051.000000)\">\n            <g transform=\"translate(71.000000, 3416.000000)\">\n              <g transform=\"translate(49.000000, 562.000000)\">\n                <g transform=\"translate(0.000000, 62.000000)\">\n                  <g transform=\"translate(433.000000, 11.000000)\">\n                    <path d=\"M78.9382739,3 C79.3793623,3 79.8080782,3.14581571 80.1576954,3.41475202 C80.9894283,4.05454654 81.1788319,5.21979947 80.6182784,6.08536419 L80.5235219,6.21942152 L74.9997261,13.4 L75,21.190983 C75,21.4671254 74.7761424,21.690983 74.5,21.690983 C74.4223775,21.690983 74.3458209,21.6729105 74.2763932,21.6381966 L71.5527864,20.2763932 C71.2140024,20.1070012 71,19.7607381 71,19.381966 L70.9997261,13.4 L65.4764781,6.21942152 C65.2459613,5.91974963 65.1059004,5.56196436 65.0705874,5.18808583 L65.0617261,5 C65.0617261,3.9456382 65.8776039,3.08183488 66.9124637,3.00548574 L67.0617261,3 L78.9382739,3 Z\" />\n                  </g>\n                </g>\n              </g>\n            </g>\n          </g>\n        </g>\n      </svg>\n    </div>\n  )\n}\n"
  },
  {
    "path": "themes/tusimple/src/icons.tsx",
    "content": "import { h, type VNode } from 'vue'\n\nconst clearIcon = (\n  <svg viewBox=\"0 0 24 24\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n    <g stroke=\"none\" stroke-width=\"1\" fill=\"none\" fill-rule=\"evenodd\">\n      <g transform=\"translate(-579.000000, -1679.000000)\" fill=\"currentColor\">\n        <g transform=\"translate(119.000000, 1482.000000)\">\n          <g transform=\"translate(0.000000, 104.000000)\">\n            <g transform=\"translate(0.000000, 93.000000)\">\n              <g transform=\"translate(460.000000, 0.000000)\">\n                <path d=\"M12,22 C17.5228475,22 22,17.5228475 22,12 C22,6.4771525 17.5228475,2 12,2 C6.4771525,2 2,6.4771525 2,12 C2,17.5228475 6.4771525,22 12,22 Z M15.5355339,8.46446609 C15.906532,8.83546417 15.906532,9.4369709 15.5355339,9.80796898 L13.34421,11.9992929 L15.5355339,14.192031 C15.906532,14.5630291 15.906532,15.1645358 15.5355339,15.5355339 C15.1645358,15.906532 14.5630291,15.906532 14.192031,15.5355339 L12,13.3420887 L9.80796898,15.5355339 C9.4369709,15.906532 8.83546417,15.906532 8.46446609,15.5355339 C8.09346802,15.1645358 8.09346802,14.5630291 8.46446609,14.192031 L10.6572042,11.9992929 L8.46446609,9.80796898 C8.09346802,9.4369709 8.09346802,8.83546417 8.46446609,8.46446609 C8.83546417,8.09346802 9.4369709,8.09346802 9.80796898,8.46446609 L12.0007071,10.65579 L14.192031,8.46446609 C14.5630291,8.09346802 15.1645358,8.09346802 15.5355339,8.46446609 Z\"></path>\n              </g>\n            </g>\n          </g>\n        </g>\n      </g>\n    </g>\n  </svg>\n)\n\nconst errorIcon = (\n  <svg viewBox=\"0 0 24 24\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n    <g stroke=\"none\" stroke-width=\"1\" fill-rule=\"evenodd\">\n      <g transform=\"translate(-132.000000, -3776.000000)\">\n        <g transform=\"translate(119.000000, 3344.000000)\">\n          <g transform=\"translate(1.000000, 420.000000)\">\n            <g transform=\"translate(12.000000, 12.000000)\">\n              <path d=\"M12,22 C17.5228475,22 22,17.5228475 22,12 C22,6.4771525 17.5228475,2 12,2 C6.4771525,2 2,6.4771525 2,12 C2,17.5228475 6.4771525,22 12,22 Z M15.5355339,8.46446609 C15.906532,8.83546417 15.906532,9.4369709 15.5355339,9.80796898 L13.34421,11.9992929 L15.5355339,14.192031 C15.906532,14.5630291 15.906532,15.1645358 15.5355339,15.5355339 C15.1645358,15.906532 14.5630291,15.906532 14.192031,15.5355339 L12,13.3420887 L9.80796898,15.5355339 C9.4369709,15.906532 8.83546417,15.906532 8.46446609,15.5355339 C8.09346802,15.1645358 8.09346802,14.5630291 8.46446609,14.192031 L10.6572042,11.9992929 L8.46446609,9.80796898 C8.09346802,9.4369709 8.09346802,8.83546417 8.46446609,8.46446609 C8.83546417,8.09346802 9.4369709,8.09346802 9.80796898,8.46446609 L12.0007071,10.65579 L14.192031,8.46446609 C14.5630291,8.09346802 15.1645358,8.09346802 15.5355339,8.46446609 Z\"></path>\n            </g>\n          </g>\n        </g>\n      </g>\n    </g>\n  </svg>\n)\n\nconst successIcon = (\n  <svg viewBox=\"0 0 24 24\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n    <g stroke=\"none\" stroke-width=\"1\" fill-rule=\"evenodd\">\n      <g transform=\"translate(-132.000000, -3572.000000)\">\n        <g transform=\"translate(119.000000, 3344.000000)\">\n          <g transform=\"translate(1.000000, 216.000000)\">\n            <g transform=\"translate(12.000000, 12.000000)\">\n              <path d=\"M12,2 C17.5228475,2 22,6.4771525 22,12 C22,17.5228475 17.5228475,22 12,22 C6.4771525,22 2,17.5228475 2,12 C2,6.4771525 6.4771525,2 12,2 Z M16.6315494,9.76758839 C16.2605513,9.39659031 15.6590446,9.39659031 15.2880465,9.76758839 L15.2880465,9.76758839 L10.9400469,14.115588 L8.71195347,11.8889087 C8.34095539,11.5179107 7.73944866,11.5179107 7.36845058,11.8889087 C6.99745251,12.2599068 6.99745251,12.8614135 7.36845058,13.2324116 L7.36845058,13.2324116 L10.2569818,16.1195286 L10.2675884,16.1315494 C10.6385865,16.5025475 11.2400932,16.5025475 11.6110913,16.1315494 L11.6110913,16.1315494 L16.6315494,11.1110913 C17.0025475,10.7400932 17.0025475,10.1385865 16.6315494,9.76758839 Z\"></path>\n            </g>\n          </g>\n        </g>\n      </g>\n    </g>\n  </svg>\n)\n\nconst warningIcon = (\n  <svg viewBox=\"0 0 24 24\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n    <g stroke=\"none\" stroke-width=\"1\" fill-rule=\"evenodd\">\n      <g transform=\"translate(-132.000000, -3708.000000)\">\n        <g transform=\"translate(119.000000, 3344.000000)\">\n          <g transform=\"translate(1.000000, 352.000000)\">\n            <g transform=\"translate(12.000000, 12.000000)\">\n              <path d=\"M12,2 C17.5228475,2 22,6.4771525 22,12 C22,17.5228475 17.5228475,22 12,22 C6.4771525,22 2,17.5228475 2,12 C2,6.4771525 6.4771525,2 12,2 Z M12,15 C11.4477153,15 11,15.4477153 11,16 C11,16.5522847 11.4477153,17 12,17 C12.5522847,17 13,16.5522847 13,16 C13,15.4477153 12.5522847,15 12,15 Z M12,7 C11.4871642,7 11.0644928,7.38604019 11.0067277,7.88337887 L11,8 L11,13 C11,13.5522847 11.4477153,14 12,14 C12.5128358,14 12.9355072,13.6139598 12.9932723,13.1166211 L13,13 L13,8 C13,7.44771525 12.5522847,7 12,7 Z\"></path>\n            </g>\n          </g>\n        </g>\n      </g>\n    </g>\n  </svg>\n)\n\nconst attachIcon = (\n  <svg viewBox=\"0 0 24 24\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n    <g stroke-width=\"1\" fill-rule=\"evenodd\">\n      <g\n        transform=\"translate(-119.000000, -1654.000000)\"\n        fill=\"currentColor\"\n        fill-rule=\"nonzero\"\n      >\n        <g transform=\"translate(119.000000, 1482.000000)\">\n          <g transform=\"translate(0.000000, 104.000000)\">\n            <g transform=\"translate(12.000000, 80.000000) rotate(-360.000000) translate(-12.000000, -80.000000) translate(0.000000, 68.000000)\">\n              <path d=\"M11.7720703,11.6476562 C12.2599609,11.1526758 12.2577734,10.3655664 11.7720703,9.87988281 C11.2872656,9.39505859 10.5014844,9.39242187 10.0042969,9.87988281 L6.0259375,13.8564453 C4.80662109,15.0863672 4.80972656,17.0596484 6.0259375,18.2758789 C7.24261719,19.4925391 9.21587891,19.495625 10.4453711,18.2758789 L17.9583789,10.7628516 C19.1781445,9.54310547 19.1781445,7.56320312 17.9583789,6.3434375 C16.739043,5.12412109 14.7587109,5.12367187 13.5389648,6.3434375 L13.3188672,6.5653125 C12.9529492,6.93123047 12.3589648,6.93123047 11.9930469,6.5653125 C11.6275586,6.19980469 11.6271094,5.60628906 11.9930469,5.23947266 L12.213125,5.01759766 C14.1735938,3.066875 17.3356836,3.06910156 19.2842188,5.01759766 C21.2327148,6.96613281 21.2358203,10.1273633 19.2842188,12.0886914 L11.7707422,19.60125 C9.81691406,21.5400586 6.6596875,21.535625 4.71292969,19.5888867 C2.76664063,17.6425586 2.76175781,14.4849023 4.70101563,12.5315039 L8.67847656,8.55402344 C9.9053125,7.33427734 11.8807813,7.33693359 13.0978906,8.55402344 C14.315,9.77113281 14.3176563,11.7466211 13.0978906,12.973457 L9.34140625,16.7299805 C8.97548828,17.0958984 8.38152344,17.0958984 8.01558594,16.7299805 C7.64966797,16.364043 7.64966797,15.7700781 8.01558594,15.4041602 L11.7720703,11.6476367 L11.7720703,11.6476562 Z\"></path>\n            </g>\n          </g>\n        </g>\n      </g>\n    </g>\n  </svg>\n)\n\nconst trashIcon = (\n  <svg viewBox=\"0 0 24 24\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n    <g stroke-width=\"1\" fill-rule=\"evenodd\">\n      <g transform=\"translate(-271.000000, -2058.000000)\">\n        <g transform=\"translate(119.000000, 1482.000000)\">\n          <g transform=\"translate(0.000000, 104.000000)\">\n            <g transform=\"translate(0.000000, 404.000000)\">\n              <g transform=\"translate(152.000000, 68.000000)\">\n                <g transform=\"translate(4.000000, 2.000000)\">\n                  <path\n                    d=\"M5.61803399,0 L10.381966,0 C10.7607381,1.71347806e-15 11.1070012,0.214002376 11.2763932,0.552786405 L12,2 L12,2 L15,2 C15.5522847,2 16,2.44771525 16,3 C16,3.55228475 15.5522847,4 15,4 L1,4 C0.44771525,4 6.76353751e-17,3.55228475 0,3 C-6.76353751e-17,2.44771525 0.44771525,2 1,2 L4,2 L4,2 L4.7236068,0.552786405 C4.89299881,0.214002376 5.23926193,2.91623903e-16 5.61803399,0 Z\"\n                    fill=\"currentColor\"\n                  />\n                  <path\n                    d=\"M3,5 L13,5 C13.5522847,5 14,5.44771525 14,6 L14,16 C14,18.209139 12.209139,20 10,20 L6,20 C3.790861,20 2,18.209139 2,16 L2,6 C2,5.44771525 2.44771525,5 3,5 Z\"\n                    fill=\"currentColor\"\n                  />\n                </g>\n              </g>\n            </g>\n          </g>\n        </g>\n      </g>\n    </g>\n  </svg>\n)\n\nconst cancelIcon = (\n  <svg viewBox=\"0 0 24 24\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n    <g stroke=\"none\" stroke-width=\"1\" fill=\"none\" fill-rule=\"evenodd\">\n      <g transform=\"translate(-579.000000, -1679.000000)\" fill=\"currentColor\">\n        <g transform=\"translate(119.000000, 1482.000000)\">\n          <g transform=\"translate(0.000000, 104.000000)\">\n            <g transform=\"translate(0.000000, 93.000000)\">\n              <g transform=\"translate(460.000000, 0.000000)\">\n                <path d=\"M12,22 C17.5228475,22 22,17.5228475 22,12 C22,6.4771525 17.5228475,2 12,2 C6.4771525,2 2,6.4771525 2,12 C2,17.5228475 6.4771525,22 12,22 Z M15.5355339,8.46446609 C15.906532,8.83546417 15.906532,9.4369709 15.5355339,9.80796898 L13.34421,11.9992929 L15.5355339,14.192031 C15.906532,14.5630291 15.906532,15.1645358 15.5355339,15.5355339 C15.1645358,15.906532 14.5630291,15.906532 14.192031,15.5355339 L12,13.3420887 L9.80796898,15.5355339 C9.4369709,15.906532 8.83546417,15.906532 8.46446609,15.5355339 C8.09346802,15.1645358 8.09346802,14.5630291 8.46446609,14.192031 L10.6572042,11.9992929 L8.46446609,9.80796898 C8.09346802,9.4369709 8.09346802,8.83546417 8.46446609,8.46446609 C8.83546417,8.09346802 9.4369709,8.09346802 9.80796898,8.46446609 L12.0007071,10.65579 L14.192031,8.46446609 C14.5630291,8.09346802 15.1645358,8.09346802 15.5355339,8.46446609 Z\"></path>\n              </g>\n            </g>\n          </g>\n        </g>\n      </g>\n    </g>\n  </svg>\n)\n\nconst retryIcon = (\n  <svg viewBox=\"0 0 24 24\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n    <g stroke=\"none\" stroke-width=\"1\" fill-rule=\"evenodd\">\n      <g transform=\"translate(-263.000000, -1861.000000)\" fill-rule=\"nonzero\">\n        <g transform=\"translate(119.000000, 1482.000000)\">\n          <g transform=\"translate(0.000000, 104.000000)\">\n            <g transform=\"translate(0.000000, 207.000000)\">\n              <g transform=\"translate(144.000000, 68.000000)\">\n                <path d=\"M12.0486674,4 C16.7612582,4 20.5789474,7.84236252 20.5789474,12.5789474 C20.5789474,17.3155322 16.7612582,21.1578947 12.0486674,21.1578947 C8.7674824,21.1578947 5.82198031,19.2776604 4.39577271,16.3724135 C4.15239625,15.876645 4.35700037,15.2774497 4.85276881,15.0340733 C5.34853725,14.7906968 5.94773258,14.9953009 6.19110904,15.4910693 C7.28483103,17.7190286 9.53890279,19.1578947 12.0486674,19.1578947 C15.6537942,19.1578947 18.5789474,16.2138366 18.5789474,12.5789474 C18.5789474,8.94405811 15.6537942,6 12.0486674,6 C9.9165536,6 7.95982642,7.036359 6.74256582,8.74298254 L8.14644661,10.1464466 C8.2402148,10.2402148 8.29289322,10.3673918 8.29289322,10.5 C8.29289322,10.7454599 8.11601806,10.9496084 7.88276885,10.9919443 L7.79289322,11 L3.5,11 C3.25454011,11 3.05039163,10.8231248 3.00805567,10.5898756 L3,10.5 L3,6.20710678 C3,6.07449854 3.05267842,5.94732158 3.14644661,5.85355339 C3.32001296,5.67998704 3.58943736,5.66070189 3.7843055,5.79569794 L3.85355339,5.85355339 L5.31281859,7.31434173 C6.91054253,5.24764778 9.37465889,4 12.0486674,4 Z\"></path>\n              </g>\n            </g>\n          </g>\n        </g>\n      </g>\n    </g>\n  </svg>\n)\n\nconst toIcon = (\n  <svg viewBox=\"0 0 24 24\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n    <g stroke=\"none\" stroke-width=\"1\" fill=\"none\" fill-rule=\"evenodd\">\n      <g\n        transform=\"translate(-339.000000, -1254.000000)\"\n        fill=\"currentColor\"\n        fill-rule=\"nonzero\"\n      >\n        <g transform=\"translate(119.000000, 288.000000)\">\n          <g transform=\"translate(0.000000, 900.000000)\">\n            <g transform=\"translate(0.000000, 62.000000)\">\n              <g transform=\"translate(100.000000, 0.000000)\">\n                <g transform=\"translate(120.000000, 4.000000)\">\n                  <path d=\"M14.2928932,7.29289322 C14.6533772,6.93240926 15.2206082,6.90467972 15.6128994,7.20970461 L15.7071068,7.29289322 L20.7071068,12.2928932 C21.3096819,12.8954683 20.9276677,13.9071808 20.1136309,13.9940167 L20,14 L4,14 C3.44771525,14 3,13.5522847 3,13 C3,12.4871642 3.38604019,12.0644928 3.88337887,12.0067277 L4,12 L17.585,12 L14.2928932,8.70710678 C13.9324093,8.34662282 13.9046797,7.77939176 14.2097046,7.38710056 L14.2928932,7.29289322 Z\"></path>\n                </g>\n              </g>\n            </g>\n          </g>\n        </g>\n      </g>\n    </g>\n  </svg>\n)\n\nfunction clear (): VNode {\n  return clearIcon\n}\n\nfunction success (): VNode {\n  return successIcon\n}\n\nfunction warning (): VNode {\n  return warningIcon\n}\n\nfunction error (): VNode {\n  return errorIcon\n}\n\nfunction attach (): VNode {\n  return attachIcon\n}\n\nfunction trash (): VNode {\n  return trashIcon\n}\n\nfunction cancel (): VNode {\n  return cancelIcon\n}\n\nfunction to (): VNode {\n  return toIcon\n}\n\nfunction retry (): VNode {\n  return retryIcon\n}\n\nexport const icons = {\n  clear,\n  success,\n  warning,\n  error,\n  attach,\n  trash,\n  cancel,\n  to,\n  retry\n}\n"
  },
  {
    "path": "themes/tusimple/src/index.ts",
    "content": "export { default as TsConfigProvider } from './TsConfigProvider'\nexport { useDialog } from './use-ts-dialog'\nexport { useMessage } from './use-ts-message'\n"
  },
  {
    "path": "themes/tusimple/src/theme-overrides-dark.ts",
    "content": "import { composite } from 'seemly'\nimport type { GlobalThemeOverrides } from 'naive-ui'\nimport { commonDark } from 'naive-ui'\nimport vars from './vars'\n\nfunction createHoverColor (color: string, overlayAlpha: number = 0.15): string {\n  return composite(color, [255, 255, 255, overlayAlpha])\n}\n\nfunction createPressedColor (\n  color: string,\n  overlayAlpha: number = 0.15\n): string {\n  return composite(color, [0, 0, 0, overlayAlpha])\n}\n\n// TODO\n// 2. input suffix & prefix text color\n// 3. input icon color?\n// 6. notification size customization\n// 7. upload style\n// 8. missing attrs\n//\n// Some demands are really not easy to implement,\n// particularly related to component layout.\n//\n// It's nearly impossible to expose all layout params (with a balanced count)\n\nexport const colors = {\n  primaryColor: '#4FB233',\n  primaryColorHover: createHoverColor('#4FB233'),\n  primaryColorPressed: createPressedColor('#4FB233'),\n  infoColor: '#4B70FA',\n  infoColorHover: createHoverColor('#4B70FA'),\n  infoColorPressed: createPressedColor('#4B70FA'),\n  successColor: '#4FB233',\n  successColorHover: createHoverColor('#4FB233'),\n  successColorPressed: createPressedColor('#4FB233'),\n  errorColor: '#EB3B61',\n  errorColorHover: createHoverColor('#EB3B61'),\n  errorColorPressed: createPressedColor('#EB3B61'),\n  warningColor: '#FAB23E',\n  warningColorHover: createHoverColor('#FAB23E', 0.2),\n  warningColorPressed: createPressedColor('#FAB23E', 0.05),\n  textColorDisabled: '#5B5B5B',\n  textColor1: '#FFFFFF',\n  textColor2: '#D6D6D6'\n}\n\nexport const themeOverridesDark: GlobalThemeOverrides = {\n  common: {\n    fontSize: '16px',\n    fontSizeMedium: '16px',\n    fontWeightStrong: '700',\n    borderRadius: '16px',\n    borderColor: '#5B5B5B',\n    opacity1: '0.8',\n    opacity2: '0.6',\n    opacity3: '0.4',\n    opacity4: '0.2',\n    opacity5: '0.2',\n    baseColor: '#FFFFFF',\n    dividerColor: '#5B5B5B',\n    popoverColor: '#333333',\n    inputColor: '#282828',\n    inputColorDisabled: '#333333',\n\n    textColor3: '#ADADAD',\n    placeholderColor: '#5B5B5B', // disabled, placeholder, icon\n    placeholderColorDisabled: '#848484',\n    tableHeaderColor: '#282828',\n\n    hoverColor: 'rgba(79, 178, 51, 0.15)',\n    closeIconColor: '#D6D6D6',\n\n    modalColor: '#282828',\n    clearColor: '#ADADAD',\n    boxShadow2: vars.NORMAL_BOX_SHADOW_DARK_THEME,\n    ...colors\n  },\n  Avatar: {\n    borderRadius: '50%'\n  },\n  Badge: {\n    color: '#EB3B61'\n  },\n  BackTop: {\n    width: '48px',\n    height: '48px',\n    iconSize: '24px',\n    borderRadius: '24px',\n    color: '#333',\n    iconColor: '#ADADAD',\n    iconColorHover: colors.primaryColor,\n    iconColorPressed: colors.primaryColorPressed,\n    boxShadow:\n      '0 40px 16px -24px rgba(0,0,0,0.04), 0 8px 16px -8px rgba(0,0,0,0.12), 0 16px 40px 16px rgba(0,0,0,0.04)',\n    boxShadowHover:\n      '0 40px 16px -24px rgba(0,0,0,0.04), 0 8px 16px -8px rgba(0,0,0,0.12), 0 16px 40px 16px rgba(0,0,0,0.04)',\n    boxShadowPressed:\n      '0 40px 16px -24px rgba(0,0,0,0.04), 0 8px 16px -8px rgba(0,0,0,0.12), 0 16px 40px 16px rgba(0,0,0,0.04)'\n  },\n  Breadcrumb: {\n    fontSize: '16px',\n    fontWeightActive: '500',\n    itemTextColorPressed: colors.primaryColor,\n    itemTextColor: '#ADADAD'\n  },\n  Button: {\n    fontWeightStrong: commonDark.fontWeightStrong,\n    textColor: '#FFFFFF',\n    textColorWarning: '#333',\n    textColorSuccess: '#333',\n    textColorPrimary: '#333',\n    iconSizeTiny: '14px',\n    iconSizeSmall: '20px',\n    iconSizeMedium: '20px',\n    iconSizeLarge: '28px',\n    borderRadiusTiny: '16px',\n    borderRadiusSmall: '16px',\n    borderRadiusMedium: '24px',\n    borderRadiusLarge: '40px',\n    heightTiny: '24px',\n    heightSmall: '32px',\n    heightMedium: '48px',\n    heightLarge: '80px',\n    fontSizeTiny: '14px',\n    fontSizeSmall: '16px',\n    fontSizeMedium: '16px',\n    fontSizeLarge: '24px',\n    paddingTiny: '0 16px',\n    paddingSmall: '0 24px',\n    paddingMedium: '0 40px',\n    paddingLarge: '0 72px',\n    paddingRoundTiny: '0 12px',\n    paddingRoundSmall: '0 24px',\n    paddingRoundMedium: '0 48px',\n    paddingRoundLarge: '0 80px',\n    opacityDisabled: '1',\n    colorDisabled: '#0000',\n    colorDisabledPrimary: '#333',\n    colorDisabledInfo: '#333',\n    colorDisabledSuccess: '#333',\n    colorDisabledWarning: '#333',\n    colorDisabledError: '#333',\n    border: '1px solid #ADADAD',\n    borderDisabled: '1px solid #5B5B5B',\n    borderDisabledPrimary: '1px solid #333',\n    borderDisabledInfo: '1px solid #333',\n    borderDisabledSuccess: '1px solid #333',\n    borderDisabledWarning: '1px solid #333',\n    borderDisabledError: '1px solid #333',\n    textColorGhost: '#FFFFFF',\n    textColorDisabled: '#5B5B5B',\n    textColorDisabledPrimary: '#5B5B5B',\n    textColorDisabledInfo: '#5B5B5B',\n    textColorDisabledSuccess: '#5B5B5B',\n    textColorDisabledWarning: '#5B5B5B',\n    textColorDisabledError: '#5B5B5B',\n    textColorGhostDisabled: '#5B5B5B',\n    textColorGhostDisabledPrimary: '#5B5B5B',\n    textColorGhostDisabledInfo: '#5B5B5B',\n    textColorGhostDisabledSuccess: '#5B5B5B',\n    textColorGhostDisabledWarning: '#5B5B5B',\n    textColorGhostDisabledError: '#5B5B5B',\n    textColorTextDisabled: '#5B5B5B',\n    textColorTextDisabledPrimary: '#5B5B5B',\n    textColorTextDisabledInfo: '#5B5B5B',\n    textColorTextDisabledSuccess: '#5B5B5B',\n    textColorTextDisabledWarning: '#5B5B5B',\n    textColorTextDisabledError: '#5B5B5B',\n    iconMarginSmall: '8px',\n    iconMarginMedium: '8px',\n    iconMarginLarge: '12px'\n  },\n  Checkbox: {\n    labelPadding: '0 8px 0 12px',\n    sizeMedium: '16px',\n    fontSizeMedium: '16px',\n    borderRadius: '4px',\n    borderDisabled: '1px solid #5B5B5B',\n    colorDisabled: '#0000',\n    colorDisabledChecked: '#D8D8D8',\n    textColor: '#FFFFFF'\n  },\n  Card: {\n    paddingSmall: '20px',\n    paddingMedium: '20px',\n    paddingLarge: '20px',\n    paddingHuge: '20px',\n    color: '#282828',\n    borderColor: '#5b5b5b',\n    closeIconColorHover: colors.primaryColor,\n    closeIconColorPressed: colors.primaryColorPressed\n  },\n  Cascader: {\n    menuHeight: '290px',\n    optionHeight: '38px'\n  },\n  DataTable: {\n    fontSizeMedium: '16px',\n    borderColor: '#404040',\n    thTextColor: '#FFFFFF',\n    tdColor: '#1E1E1E',\n    tdTextColor: '#FFFFFF',\n    thFontWeight: commonDark.fontWeight,\n    tdColorHover: '#222C1F',\n    thButtonColorHover: '#0000',\n    thColorModal: '#282828',\n    tdColorModal: '#1E1E1E',\n    tdColorHoverModal: '#222C1F',\n    thIconColor: '#848484',\n    thColorHover: '#0000',\n    thPaddingSmall: '10px 20px',\n    thPaddingMedium: '10px 20px',\n    thPaddingLarge: '10px 20px',\n    tdPaddingSmall: '10px 20px',\n    tdPaddingMedium: '10px 20px',\n    tdPaddingLarge: '10px 20px'\n  },\n  DatePicker: {\n    itemTextColor: '#FFF',\n    itemColorHover: 'rgba(79, 178, 51, 0.15)',\n    itemTextColorActive: '#333333',\n    iconColor: '#848484',\n    itemBorderRadius: '14px',\n    panelHeaderDividerColor: '#0000',\n    calendarDaysDividerColor: '#0000',\n    arrowColor: '#CCC',\n    arrowSize: '24px',\n    itemFontSize: '16px',\n    calendarDaysFontSize: '16px',\n    calendarTitleFontSize: '16px',\n    panelActionPadding: '12px 20px',\n    itemSize: '28px',\n    itemCellHeight: '34px',\n    itemCellWidth: '40px',\n    calendarTitlePadding: '0 8px 8px 8px',\n    calendarTitleHeight: '32px',\n    calendarLeftPaddingDate: '12px 16px 9px 16px',\n    calendarLeftPaddingDaterange: '12px 16px 9px 16px',\n    calendarLeftPaddingDatetime: '6px 16px 9px 16px',\n    calendarLeftPaddingDatetimerange: '6px 16px 9px 16px',\n    calendarRightPaddingDaterange: '12px 16px 9px 16px',\n    calendarRightPaddingDatetimerange: '6px 16px 9px 16px',\n    calendarDividerColor: '#0000',\n    panelHeaderPadding: '12px 20px 8px 20px'\n  },\n  Dialog: {\n    padding: '40px',\n    iconSize: '36px',\n    iconMarginIconTop: '0 0 20px 0',\n    closeMarginIconTop: '24px 24px 0 0',\n    titleFontSize: '24px',\n    fontSize: '16px',\n    actionSpace: '20px',\n    contentMargin: '12px 0 40px 0',\n    closeIconColorHover: colors.primaryColor,\n    closeIconColorPressed: colors.primaryColorPressed\n  },\n  Dropdown: {\n    optionHeightMedium: '38px'\n  },\n  Divider: {\n    color: '#5B5B5B'\n  },\n  Drawer: {\n    bodyPadding: '20px'\n  },\n  DynamicTags: {\n    peers: {\n      Tag: {\n        heightMedium: '24px'\n      },\n      Input: {\n        heightSmall: '24px'\n      }\n    }\n  },\n  Empty: {\n    iconColor: colors.textColorDisabled,\n    textColor: colors.textColorDisabled,\n    extraTextColor: colors.textColorDisabled\n  },\n  Input: {\n    heightSmall: '24px',\n    heightMedium: '32px',\n    fontSizeMedium: '16px',\n    paddingSmall: '0 12px',\n    paddingMedium: '0 12px',\n    paddingLarge: '0 12px',\n    iconSize: '24px',\n    border: '1px solid #5B5B5B',\n    borderWarning: '1px solid #FAB23E',\n    borderError: '1px solid EB3B61',\n    borderDisabled: '1px #333333 !important',\n    colorDisabled: '#333333',\n    borderHover: `1px solid ${colors.primaryColor}`,\n    borderFocus: `1px solid ${colors.primaryColor}`,\n    color: '#282828',\n    textColor: '#FFFFFF',\n    placeholderColor: '#848484',\n    lineHeight: '22px',\n    groupLabelColor: '#5B5B5B',\n    groupLabelTextColor: '#FFF'\n  },\n  InternalSelection: {\n    heightMedium: '32px',\n    fontSizeMedium: '16px',\n    paddingSingle: '0 36px 0 12px'\n  },\n  InternalSelectMenu: {\n    height: '290px',\n    optionTextColor: colors.textColor1,\n    optionFontSizeMedium: '16px',\n    optionPaddingMedium: '0 12px',\n    optionHeightMedium: '38px',\n    paddingSmall: '4px 0',\n    paddingMedium: '6px 0',\n    paddingLarge: '6px 0',\n    paddingHuge: '8px 0'\n  },\n  Form: {\n    blankHeightSmall: vars.CONTENT_SPACE,\n    blankHeightMedium: vars.CONTENT_SPACE,\n    blankHeightLarge: vars.CONTENT_SPACE,\n    feedbackHeightSmall: vars.CONTENT_SPACE,\n    feedbackHeightMedium: vars.CONTENT_SPACE,\n    feedbackHeightLarge: vars.CONTENT_SPACE,\n    feedbackFontSizeSmall: vars.SMALL_FRONT_SIZE,\n    feedbackFontSizeMedium: vars.SMALL_FRONT_SIZE,\n    feedbackFontSizeLarge: vars.SMALL_FRONT_SIZE,\n    labelFontSizeLeftSmall: vars.SMALL_FRONT_SIZE,\n    labelFontSizeLeftMedium: vars.SMALL_FRONT_SIZE,\n    labelFontSizeLeftLarge: vars.NORMAL_FRONT_SIZE,\n    labelFontSizeTopSmall: vars.SMALL_FRONT_SIZE,\n    labelFontSizeTopMedium: vars.SMALL_FRONT_SIZE,\n    labelFontSizeTopLarge: vars.NORMAL_FRONT_SIZE,\n    labelHeightSmall: '22px',\n    labelHeightMedium: '22px',\n    labelHeightLarge: '22px',\n    labelTextAlignHorizontal: 'left'\n  },\n  Icon: {\n    color: '#848484',\n    opacity1Depth: '1',\n    opacity2Depth: '1',\n    opacity3Depth: '1'\n  },\n  List: {\n    color: '#333',\n    borderColor: '#5B5B5B'\n  },\n  Menu: {\n    borderRadius: '100px',\n    itemIconColor: '#D6D6D6'\n  },\n  Message: {\n    padding: '12px 20px 12px 12px',\n    borderRadius: '32px',\n    maxWidth: '720px',\n    minWidth: '420px',\n    iconMargin: '0 20px 0 0',\n    closeMargin: '0 -8px 0 20px',\n    colorSuccess: colors.successColor,\n    colorInfo: colors.infoColor,\n    colorWarning: colors.warningColor,\n    colorError: colors.errorColor,\n    boxShadowInfo: vars.SPECIAL_BOX_SHADOW_DARK_THEME,\n    boxShadowSuccess: vars.SPECIAL_BOX_SHADOW_DARK_THEME,\n    boxShadowError: vars.SPECIAL_BOX_SHADOW_DARK_THEME,\n    boxShadowWarning: vars.SPECIAL_BOX_SHADOW_DARK_THEME,\n    textColorError: '#FFF',\n    textColorSuccess: '#333',\n    textColorInfo: '#FFF',\n    textColorWarning: '#333',\n    iconColorInfo: 'FFF',\n    iconColorSuccess: '#333333',\n    iconColorWarning: '#333333',\n    iconColorError: 'rgb(255, 255, 255)',\n    iconColorLoading: '#4FB233',\n    closeIconColorInfo: 'rgb(255, 255, 255)',\n    closeIconColorHoverInfo: 'rgb(255, 255, 255)',\n    closeIconColorPressedInfo: 'rgb(255, 255, 255)',\n    closeIconColorSuccess: '#333333',\n    closeIconColorHoverSuccess: '#333333',\n    closeIconColorPressedSuccess: '#333333',\n    closeIconColorError: 'rgb(255, 255, 255)',\n    closeIconColorHoverError: 'rgb(255, 255, 255)',\n    closeIconColorPressedError: 'rgb(255, 255, 255)',\n    closeIconColorWarning: '#333333',\n    closeIconColorHoverWarning: '#333333',\n    closeIconColorPressedWarning: '#333333',\n    closeIconColorLoading: 'rgb(255, 255, 255)',\n    closeIconColorHoverLoading: 'rgb(255, 255, 255)',\n    closeIconColorPressedLoading: 'rgb(255, 255, 255)',\n    closeSize: '24px',\n    iconSize: '20px'\n  },\n  Modal: {\n    textColor: '#FFF',\n    color: '#545454'\n  },\n  Notification: {\n    fontSize: '16px',\n    headerTextColor: '#FFF',\n    descriptionTextColor: '#ADADAD',\n    textColor: colors.textColor2,\n    closeIconColor: '#FFFFFF',\n    closeIconColorHover: colors.primaryColor,\n    closeIconColorPressed: colors.primaryColorPressed,\n    boxShadow: vars.SPECIAL_BOX_SHADOW_DARK_THEME\n  },\n  Pagination: {\n    itemSizeMedium: '32px',\n    itemPaddingMedium: '0',\n    // buttonFontSize: '24px',\n    itemFontSizeMedium: '16px',\n    inputWidthMedium: '80px',\n    selectWidthMedium: '100px',\n    inputMarginMedium: '0 20px',\n    itemMarginMedium: '0 0 0 20px',\n    itemBorder: '0 solid #0000',\n    itemBorderActive: '0 solid #0000',\n    itemBorderDisabled: '0 solid #0000',\n    itemColor: '#0000',\n    itemColorHover: 'rgba(79, 178, 51, 0.15)',\n    itemColorActive: '#0000',\n    itemColorDisabled: '#0000',\n    itemBorderRadius: '100px',\n    itemTextColor: colors.textColor1,\n    itemTextColorHover: colors.primaryColor,\n    itemTextColorDisabled: '#5B5B5B',\n    buttonIconColor: '#FFFFFF',\n    buttonBorder: '0 solid #0000',\n    buttonIconColorHover: commonDark.primaryColor\n  },\n  Popover: {\n    fontSize: '16px',\n    arrowOffset: '40px',\n    arrowOffsetVertical: '16px',\n    arrowHeight: '8px',\n    space: '4px',\n    spaceArrow: '14px',\n    textColor: '#FFF',\n    boxShadow: vars.NORMAL_BOX_SHADOW_DARK_THEME,\n    padding: '12px 20px'\n  },\n  Popconfirm: {\n    iconColor: '#FAB23E !important'\n  },\n  Progress: {\n    fontWeightCircle: '700',\n    railHeight: '4px',\n    fontSizeCircle: '24px',\n    iconSizeCircle: '30px',\n    iconSizeLine: '20px',\n    iconColor: colors.warningColor,\n    iconColorInfo: colors.warningColor,\n    iconColorSuccess: colors.successColor,\n    iconColorWarning: colors.errorColor,\n    iconColorError: colors.errorColor,\n    fillColor: colors.warningColor,\n    fillColorInfo: colors.warningColor,\n    fillColorSuccess: colors.successColor,\n    fillColorWarning: colors.warningColor,\n    fillColorError: colors.errorColor,\n    textColorCircle: '#ADADAD'\n  },\n  Steps: {\n    indicatorTextColorProcess: '#333'\n  },\n  Radio: {\n    labelPadding: '0 8px 0 12px',\n    fontSizeMedium: '16px',\n    radioSizeMedium: '16px',\n    dotColorDisabled: '#5B5B5B',\n    boxShadowDisabled: 'inset 0 0 0 1px #5B5B5B',\n    textColor: '#FFFFFF',\n    buttonTextColorActive: '#333'\n  },\n  Slider: {\n    railColor: '#5B5B5B',\n    fillColor: colors.primaryColor,\n    fillColorHover: colors.primaryColorHover,\n    railColorHover: '#5B5B5B',\n    handleBoxShadow: vars.NORMAL_BOX_SHADOW_DARK_THEME,\n    handleBoxShadowHover: vars.NORMAL_BOX_SHADOW_DARK_THEME,\n    handleBoxShadowActive: vars.NORMAL_BOX_SHADOW_DARK_THEME,\n    handleBoxShadowFocus: vars.NORMAL_BOX_SHADOW_DARK_THEME,\n    dotColor: '#333333',\n    dotBorder: '2px solid #5B5B5B',\n    dotBorderActive: `2px solid ${colors.primaryColor}`\n  },\n  Switch: {\n    railHeightMedium: '15px',\n    railHeightLarge: '20px',\n    railBorderRadiusMedium: '8px',\n    railBorderRadiusLarge: '10px',\n    railWidthMedium: '40px',\n    railWidthLarge: '50px',\n    buttonHeightMedium: '24px',\n    buttonHeightLarge: '32px',\n    buttonWidthMedium: '24px',\n    buttonWidthLarge: '32px',\n    buttonWidthPressedMedium: '30px',\n    buttonWidthPressedLarge: '38px',\n    buttonBorderRadiusMedium: '12px',\n    buttonBorderRadiusLarge: '16px',\n    opacityDisabled: '1',\n    railColor: '#5B5B5B',\n    railColorActive: '#5B5B5B',\n    buttonColor: '#5B5B5B',\n    buttonBoxShadow: '0 2px 3px 0 rgba(0,0,0,0.10)'\n  },\n  Table: {\n    thColor: '#282828',\n    thTextColor: '#FFFFFF',\n    tdColor: '#1E1E1E',\n    tdTextColor: '#FFFFFF',\n    thFontWeight: commonDark.fontWeight,\n    borderColor: '#404040',\n    thPaddingSmall: '10px 20px',\n    thPaddingMedium: '10px 20px',\n    thPaddingLarge: '10px 20px',\n    tdPaddingSmall: '10px 20px',\n    tdPaddingMedium: '10px 20px',\n    tdPaddingLarge: '10px 20px'\n  },\n  Tabs: {\n    tabTextColorLine: '#D6D6D6',\n    tabTextColorBar: '#D6D6D6'\n  },\n  Tag: {\n    borderRadius: '100px',\n    border: '1px solid #0000',\n    color: 'rgba(153,153,153,0.10)',\n    colorError: 'rgba(235,59,97,0.15)',\n    colorInfo: 'rgba(51,95,255,0.15)',\n    colorSuccess: 'rgba(79,178,51,0.15)',\n    closeIconColor: commonDark.closeIconColor,\n    closeIconColorHover: commonDark.closeIconColor,\n    closeIconColorPressed: commonDark.closeIconColor,\n    borderPrimary: '1px solid #0000',\n    closeIconColorPrimary: commonDark.closeIconColor,\n    closeIconColorHoverPrimary: commonDark.closeIconColor,\n    closeIconColorPressedPrimary: commonDark.closeIconColor,\n    closeIconColorError: colors.errorColor,\n    closeIconColorHoverError: colors.errorColorHover,\n    closeIconColorPressedError: colors.errorColorPressed,\n    closeIconColorInfo: colors.infoColor,\n    closeIconColorHoverInfo: colors.infoColorHover,\n    closeIconColorPressedInfo: colors.infoColorPressed,\n    closeIconColorSuccess: colors.successColor,\n    closeIconColorHoverSuccess: colors.successColorHover,\n    closeIconColorPressedSuccess: colors.successColorPressed,\n    closeIconColorWarning: colors.warningColor,\n    closeIconColorHoverWarning: colors.warningColorHover,\n    closeIconColorPressedWarning: colors.warningColorPressed,\n    borderInfo: '1px solid #0000',\n    borderSuccess: '1px solid #0000',\n    borderWarning: '1px solid #0000',\n    borderError: '1px solid #0000',\n    padding: '0 12px',\n    closeMargin: '0 0 0 8px',\n    heightMedium: '24px',\n    closeSizeSmall: '20px',\n    closeSizeMedium: '20px',\n    closeSizeLarge: '20px',\n    fontSizeSmall: '12px',\n    fontSizeMedium: '16px',\n    fontSizeLarge: '16px',\n    textColorCheckable: colors.textColor1,\n    textColorHoverCheckable: colors.primaryColor,\n    textColorChecked: '#000',\n    colorCheckable: 'rgba(173,173,173,0.20)',\n    colorHoverCheckable: 'rgba(79,178,51,0.15)',\n    colorPressedCheckable: 'rgba(79,178,51,0.15)',\n    colorChecked: colors.primaryColor,\n    colorCheckedHover: colors.primaryColorHover,\n    colorCheckedPressed: colors.primaryColorPressed\n  },\n  TimePicker: {\n    itemFontSize: '16px',\n    itemHeight: '38px',\n    itemWidth: '74px',\n    panelActionPadding: '12px 0',\n    itemTextColor: '#FFF'\n  },\n  Tooltip: {\n    peers: {\n      Popover: {\n        padding: '20px',\n        fontSize: '16px',\n        color: '#D6D6D6',\n        textColor: '#333333'\n      }\n    }\n  },\n  Transfer: {\n    borderColor: '#5B5B5B',\n    headerColor: '#363636',\n    extraTextColor: '#D6D6D6'\n  },\n  Typography: {\n    headerPrefixWidth3: '15px',\n    headerPrefixWidth4: '15px',\n    headerPrefixWidth5: '15px',\n    headerPrefixWidth6: '15px',\n    headerBarColor: '#ADADAD'\n  },\n  Upload: {\n    itemColorHover: 'rgba(255, 255, 255, 0.09)',\n    itemColorHoverError: 'rgba(232, 128, 128, 0.09)',\n    itemIconColor: '#FFFFFF',\n    fontSize: '16px'\n  }\n}\n"
  },
  {
    "path": "themes/tusimple/src/theme-overrides-light.ts",
    "content": "import { composite, changeColor } from 'seemly'\nimport type { GlobalThemeOverrides } from 'naive-ui'\nimport { commonLight } from 'naive-ui'\nimport vars from './vars'\n\nfunction createHoverColor (color: string, overlayAlpha: number = 0.15): string {\n  return composite(color, [255, 255, 255, overlayAlpha])\n}\n\nfunction createPressedColor (\n  color: string,\n  overlayAlpha: number = 0.15\n): string {\n  return composite(color, [0, 0, 0, overlayAlpha])\n}\n\nexport const colors = {\n  primaryColor: '#4FB233',\n  primaryColorHover: createHoverColor('#4FB233'),\n  primaryColorPressed: createPressedColor('#4FB233'),\n  infoColor: '#335FFF',\n  infoColorHover: createHoverColor('#335FFF'),\n  infoColorPressed: createPressedColor('#335FFF'),\n  successColor: '#4FB233',\n  successColorHover: createHoverColor('#4FB233'),\n  successColorPressed: createPressedColor('#4FB233'),\n  errorColor: '#D92149',\n  errorColorHover: createHoverColor('#D92149'),\n  errorColorPressed: createPressedColor('#D92149'),\n  warningColor: '#FFAC26',\n  warningColorHover: createHoverColor('#FFAC26', 0.2),\n  warningColorPressed: createPressedColor('#FFAC26', 0.05),\n  textColorDisabled: '#D7DAE0',\n  textColor1: '#333',\n  textColor2: '#333'\n}\n\nexport const themeOverridesLight: GlobalThemeOverrides = {\n  common: {\n    fontSize: '16px',\n    fontSizeMedium: '16px',\n    fontWeightStrong: '700',\n    borderRadius: '16px',\n    boxShadow2: vars.NORMAL_BOX_SHADOW,\n    borderColor: '#999',\n    dividerColor: '#EBEDF0',\n    tableHeaderColor: '#EBEDF0',\n    inputColorDisabled: '#EBEDF0',\n    actionColor: '#EBEDF0',\n    hoverColor: changeColor(colors.primaryColor, { alpha: 0.1 }),\n    clearColor: composite('#FFF', 'rgba(0, 0, 0, .4)'),\n    ...colors\n  },\n  Avatar: {\n    borderRadius: '50%'\n  },\n  BackTop: {\n    width: '48px',\n    height: '48px',\n    iconSize: '24px',\n    borderRadius: '24px',\n    iconColor: 'rgba(0, 0, 0, .8)',\n    iconColorHover: commonLight.primaryColor,\n    iconColorPressed: commonLight.primaryColorPressed,\n    boxShadow:\n      '0 40px 16px -24px rgba(0,0,0,0.04), 0 8px 16px -8px rgba(0,0,0,0.12), 0 16px 40px 16px rgba(0,0,0,0.04)',\n    boxShadowHover:\n      '0 40px 16px -24px rgba(0,0,0,0.04), 0 8px 16px -8px rgba(0,0,0,0.12), 0 16px 40px 16px rgba(0,0,0,0.04)',\n    boxShadowPressed:\n      '0 40px 16px -24px rgba(0,0,0,0.04), 0 8px 16px -8px rgba(0,0,0,0.12), 0 16px 40px 16px rgba(0,0,0,0.04)'\n  },\n  Breadcrumb: {\n    fontSize: '16px',\n    fontWeightActive: '500',\n    itemTextColor: '#999',\n    separatorColor: '#999'\n  },\n  Button: {\n    textColorWarning: '#333',\n    textColorHoverWarning: '#333',\n    textColorFocusWarning: '#333',\n    textColorPressedWarning: '#333',\n    iconSizeTiny: '14px',\n    iconSizeSmall: '20px',\n    iconSizeMedium: '20px',\n    iconSizeLarge: '28px',\n    borderRadiusTiny: '12px',\n    borderRadiusSmall: '16px',\n    borderRadiusMedium: '24px',\n    borderRadiusLarge: '40px',\n    heightTiny: '24px',\n    heightSmall: '32px',\n    heightMedium: '48px',\n    heightLarge: '80px',\n    fontSizeTiny: '14px',\n    fontSizeSmall: '16px',\n    fontSizeMedium: '16px',\n    fontSizeLarge: '24px',\n    paddingTiny: '0 16px',\n    paddingSmall: '0 24px',\n    paddingMedium: '0 40px',\n    paddingLarge: '0 72px',\n    paddingRoundTiny: '0 12px',\n    paddingRoundSmall: '0 24px',\n    paddingRoundMedium: '0 48px',\n    paddingRoundLarge: '0 80px',\n    opacityDisabled: '1',\n    colorDisabled: '#EBEDF0',\n    colorDisabledPrimary: '#EBEDF0',\n    colorDisabledInfo: '#EBEDF0',\n    colorDisabledSuccess: '#EBEDF0',\n    colorDisabledWarning: '#EBEDF0',\n    colorDisabledError: '#EBEDF0',\n    borderDisabled: '1px solid #EBEDF0',\n    borderDisabledPrimary: '1px solid #EBEDF0',\n    borderDisabledInfo: '1px solid #EBEDF0',\n    borderDisabledSuccess: '1px solid #EBEDF0',\n    borderDisabledWarning: '1px solid #EBEDF0',\n    borderDisabledError: '1px solid #EBEDF0',\n    textColorDisabled: '#CCCCCC',\n    textColorDisabledPrimary: '#CCCCCC',\n    textColorDisabledInfo: '#CCCCCC',\n    textColorDisabledSuccess: '#CCCCCC',\n    textColorDisabledWarning: '#CCCCCC',\n    textColorDisabledError: '#CCCCCC',\n    textColorGhostDisabled: '#D7DAE0',\n    textColorGhostDisabledPrimary: '#D7DAE0',\n    textColorGhostDisabledInfo: '#D7DAE0',\n    textColorGhostDisabledSuccess: '#D7DAE0',\n    textColorGhostDisabledWarning: '#D7DAE0',\n    textColorGhostDisabledError: '#D7DAE0',\n    textColorTextDisabled: '#D7DAE0',\n    textColorTextDisabledPrimary: '#D7DAE0',\n    textColorTextDisabledInfo: '#D7DAE0',\n    textColorTextDisabledSuccess: '#D7DAE0',\n    textColorTextDisabledWarning: '#D7DAE0',\n    textColorTextDisabledError: '#D7DAE0',\n    iconMarginSmall: '8px',\n    iconMarginMedium: '8px',\n    iconMarginLarge: '12px',\n    fontWeightStrong: '600'\n  },\n  Checkbox: {\n    sizeMedium: '16px',\n    fontSizeMedium: '16px',\n    borderRadius: '4px',\n    borderDisabled: `1px solid ${colors.textColorDisabled}`,\n    borderDisabledChecked: '1px solid #0000',\n    checkMarkColorDisabled: colors.textColorDisabled,\n    checkMarkColorDisabledChecked: '#FFF',\n    colorDisabled: '#0000',\n    colorDisabledChecked: '#F5F6F7 ',\n    textColor: colors.textColor1,\n    textColorDisabled: colors.textColorDisabled\n  },\n  Card: {\n    paddingSmall: '20px',\n    paddingMedium: '20px',\n    paddingLarge: '20px',\n    paddingHuge: '20px'\n  },\n  Cascader: {\n    menuHeight: '290px',\n    optionHeight: '38px'\n  },\n  DataTable: {\n    fontSizeMedium: '16px',\n    thColor: '#EBEDF0',\n    thIconColor: '#ccc',\n    thTextColor: commonLight.textColor2,\n    thFontWeight: commonLight.fontWeight,\n    tdColorHover: 'rgba(79, 178, 51, .1)',\n    thButtonColorHover: '#0000',\n    thColorModal: '#EBEDF0',\n    tdColorHoverModal: composite(\n      commonLight.primaryColor,\n      'rgba(255, 255, 255, .9)'\n    ),\n    thPaddingSmall: '10px 20px',\n    thPaddingMedium: '10px 20px',\n    thPaddingLarge: '10px 20px',\n    tdPaddingSmall: '10px 20px',\n    tdPaddingMedium: '10px 20px',\n    tdPaddingLarge: '10px 20px'\n  },\n  DatePicker: {\n    itemBorderRadius: '14px',\n    panelHeaderDividerColor: '#0000',\n    calendarDaysDividerColor: '#0000',\n    arrowColor: '#CCC',\n    arrowSize: '24px',\n    itemFontSize: '16px',\n    calendarDaysFontSize: '16px',\n    calendarTitleFontSize: '16px',\n    panelActionPadding: '12px 20px',\n    itemSize: '28px',\n    itemCellHeight: '34px',\n    itemCellWidth: '40px',\n    calendarTitlePadding: '0 8px 8px 8px',\n    calendarTitleHeight: '32px',\n    calendarLeftPaddingDate: '12px 16px 9px 16px',\n    calendarLeftPaddingDaterange: '12px 16px 9px 16px',\n    calendarLeftPaddingDatetime: '6px 16px 9px 16px',\n    calendarLeftPaddingDatetimerange: '6px 16px 9px 16px',\n    calendarRightPaddingDaterange: '12px 16px 9px 16px',\n    calendarRightPaddingDatetimerange: '6px 16px 9px 16px',\n    calendarDividerColor: '#0000',\n    panelHeaderPadding: '12px 20px 8px 20px'\n  },\n  Dialog: {\n    padding: '40px',\n    iconSize: '36px',\n    iconMarginIconTop: '0 0 12px 0',\n    closeMarginIconTop: '24px 24px 0 0',\n    titleFontSize: '24px',\n    fontSize: '16px',\n    actionSpace: '20px',\n    contentMargin: '12px 0 40px 0'\n  },\n  Dropdown: {\n    optionHeightMedium: '38px'\n  },\n  DynamicTags: {\n    peers: {\n      Tag: {\n        heightMedium: '24px'\n      },\n      Input: {\n        heightSmall: '24px'\n      }\n    }\n  },\n  Empty: {\n    iconColor: colors.textColorDisabled,\n    textColor: colors.textColorDisabled,\n    extraTextColor: colors.textColorDisabled\n  },\n  Input: {\n    heightMedium: '32px',\n    fontSizeMedium: '16px',\n    paddingMedium: '0 12px',\n    iconSize: '24px',\n    borderHover: `1px solid ${colors.primaryColor}`,\n    borderFocus: `1px solid ${colors.primaryColor}`\n  },\n  InternalSelection: {\n    heightMedium: '32px',\n    fontSizeMedium: '16px',\n    paddingSingle: '0 36px 0 12px'\n  },\n  InternalSelectMenu: {\n    height: '290px',\n    optionHeightMedium: '38px',\n    paddingSmall: '4px 0',\n    paddingMedium: '6px 0',\n    paddingLarge: '6px 0',\n    paddingHuge: '8px 0'\n  },\n  Form: {\n    blankHeightSmall: vars.CONTENT_SPACE,\n    blankHeightMedium: vars.CONTENT_SPACE,\n    blankHeightLarge: vars.CONTENT_SPACE,\n    feedbackHeightSmall: vars.CONTENT_SPACE,\n    feedbackHeightMedium: vars.CONTENT_SPACE,\n    feedbackHeightLarge: vars.CONTENT_SPACE,\n    feedbackFontSizeSmall: vars.SMALL_FRONT_SIZE,\n    feedbackFontSizeMedium: vars.SMALL_FRONT_SIZE,\n    feedbackFontSizeLarge: vars.SMALL_FRONT_SIZE,\n    labelFontSizeLeftSmall: vars.SMALL_FRONT_SIZE,\n    labelFontSizeLeftMedium: vars.SMALL_FRONT_SIZE,\n    labelFontSizeLeftLarge: vars.NORMAL_FRONT_SIZE,\n    labelFontSizeTopSmall: vars.SMALL_FRONT_SIZE,\n    labelFontSizeTopMedium: vars.SMALL_FRONT_SIZE,\n    labelFontSizeTopLarge: vars.NORMAL_FRONT_SIZE,\n    labelHeightSmall: '22px',\n    labelHeightMedium: '22px',\n    labelHeightLarge: '22px',\n    labelTextAlignHorizontal: 'left'\n  },\n  Menu: {\n    borderRadius: '100px',\n    itemIconColor: colors.textColor2\n  },\n  Message: {\n    padding: '12px 20px 12px 12px',\n    borderRadius: '24px',\n    maxWidth: '720px',\n    minWidth: '420px',\n    iconMargin: '0 20px 0 0',\n    closeMargin: '0 -8px 0 20px',\n    colorSuccess: colors.successColor,\n    colorInfo: colors.infoColor,\n    colorWarning: colors.warningColor,\n    colorError: colors.errorColor,\n    textColorError: '#FFF',\n    textColorSuccess: '#FFF',\n    textColorInfo: '#FFFFFF',\n    textColorWarning: '#333',\n    iconColorInfo: '#FFF',\n    iconColorSuccess: 'rgb(255, 255, 255)',\n    iconColorWarning: '#333',\n    iconColorError: 'rgb(255, 255, 255)',\n    closeIconColorInfo: 'rgb(0, 0, 0)',\n    closeIconColorHoverInfo: 'rgb(0, 0, 0)',\n    closeIconColorPressedInfo: 'rgb(0, 0, 0)',\n    closeIconColorSuccess: 'rgb(255, 255, 255)',\n    closeIconColorHoverSuccess: 'rgb(255, 255, 255)',\n    closeIconColorPressedSuccess: 'rgb(255, 255, 255)',\n    closeIconColorError: 'rgb(255, 255, 255)',\n    closeIconColorHoverError: 'rgb(255, 255, 255)',\n    closeIconColorPressedError: 'rgb(255, 255, 255)',\n    closeIconColorWarning: 'rgb(255, 255, 255)',\n    closeIconColorHoverWarning: 'rgb(255, 255, 255)',\n    closeIconColorPressedWarning: 'rgb(255, 255, 255)',\n    closeIconColorLoading: 'rgb(0, 0, 0)',\n    closeIconColorHoverLoading: 'rgb(0, 0, 0)',\n    closeIconColorPressedLoading: 'rgb(0, 0, 0)',\n    closeSize: '15px',\n    iconSize: '20px'\n  },\n  Pagination: {\n    itemSizeMedium: '32px',\n    itemPaddingMedium: '0',\n    // buttonFontSize: '24px',\n    itemFontSizeMedium: '16px',\n    inputWidthMedium: '80px',\n    selectWidthMedium: '100px',\n    inputMarginMedium: '0 20px',\n    itemMarginMedium: '0 0 0 20px',\n    itemBorder: '0 solid #0000',\n    itemBorderHover: '0 solid #0000',\n    itemBorderActive: '0 solid #0000',\n    itemBorderDisabled: '0 solid #0000',\n    itemColor: '#0000',\n    itemColorPressed: composite(\n      commonLight.primaryColor,\n      'rgba(255, 255, 255, 0.9)'\n    ),\n    itemColorHover: 'rgba(79,178,51,.1)',\n    itemColorActiveHover: composite(\n      commonLight.primaryColor,\n      'rgba(255, 255, 255, 0.9)'\n    ),\n    itemColorActive: '#0000',\n    itemColorDisabled: '#0000',\n    itemBorderRadius: '100px',\n    itemTextColorHover: commonLight.textColor2,\n    itemTextColorDisabled: '#D7DAE0',\n    buttonBorder: '0 solid #0000',\n    buttonBorderHover: '0 solid #0000',\n    buttonBorderPressed: '0 solid #0000',\n    buttonIconColorHover: commonLight.primaryColor\n  },\n  Popover: {\n    fontSize: '16px',\n    arrowOffset: '40px',\n    arrowOffsetVertical: '16px',\n    arrowHeight: '8px',\n    space: '4px',\n    spaceArrow: '14px',\n    padding: '12px 20px'\n  },\n  Progress: {\n    fontWeightCircle: '700',\n    railHeight: '4px',\n    fontSizeCircle: '24px',\n    iconSizeCircle: '30px',\n    iconSizeLine: '20px',\n    iconColor: colors.warningColor,\n    iconColorInfo: colors.warningColor,\n    iconColorSuccess: colors.successColor,\n    iconColorWarning: colors.errorColor,\n    iconColorError: colors.errorColor,\n    fillColor: colors.warningColor,\n    fillColorInfo: colors.warningColor,\n    fillColorSuccess: colors.successColor,\n    fillColorWarning: colors.warningColor,\n    fillColorError: colors.errorColor,\n    textColorCircle: '#666666'\n  },\n  Radio: {\n    dotColorDisabled: '#D7DAE0',\n    buttonColorActive: '#4FB233',\n    buttonTextColorActive: '#FFF'\n  },\n  Switch: {\n    railHeightMedium: '15px',\n    railHeightLarge: '20px',\n    railBorderRadiusMedium: '8px',\n    railBorderRadiusLarge: '10px',\n    railWidthMedium: '40px',\n    railWidthLarge: '50px',\n    buttonHeightMedium: '24px',\n    buttonHeightLarge: '32px',\n    buttonWidthMedium: '24px',\n    buttonWidthLarge: '32px',\n    buttonWidthPressedMedium: '30px',\n    buttonWidthPressedLarge: '38px',\n    buttonBorderRadiusMedium: '12px',\n    buttonBorderRadiusLarge: '16px',\n    opacityDisabled: '1',\n    railColor: '#D7DAE0',\n    railColorActive: '#D7DAE0',\n    buttonBoxShadow: '0 2px 3px 0 rgba(0,0,0,0.10)'\n  },\n  Table: {\n    thColor: '#EBEDF0',\n    thTextColor: commonLight.textColor2,\n    thFontWeight: commonLight.fontWeight,\n    thPaddingSmall: '10px 20px',\n    thPaddingMedium: '10px 20px',\n    thPaddingLarge: '10px 20px',\n    tdPaddingSmall: '10px 20px',\n    tdPaddingMedium: '10px 20px',\n    tdPaddingLarge: '10px 20px'\n  },\n  Tag: {\n    borderRadius: '100px',\n    border: '1px solid #0000',\n    color: 'rgba(153,153,153,0.10)',\n    closeIconColor: commonLight.closeIconColor,\n    closeIconColorHover: commonLight.closeIconColor,\n    closeIconColorPressed: commonLight.closeIconColor,\n    borderPrimary: '1px solid #0000',\n    closeIconColorPrimary: commonLight.closeIconColor,\n    closeIconColorHoverPrimary: commonLight.closeIconColor,\n    closeIconColorPressedPrimary: commonLight.closeIconColor,\n    borderInfo: '1px solid #0000',\n    borderSuccess: '1px solid #0000',\n    borderWarning: '1px solid #0000',\n    borderError: '1px solid #0000',\n    padding: '0 12px',\n    closeMargin: '0 0 0 8px',\n    heightMedium: '24px',\n    closeSizeSmall: '20px',\n    closeSizeMedium: '20px',\n    closeSizeLarge: '20px',\n    fontSizeSmall: '12px',\n    fontSizeMedium: '16px',\n    fontSizeLarge: '16px',\n    colorCheckable: 'rgba(102, 102, 102, .1)',\n    colorHoverCheckable: 'rgba(79, 178, 51, 0.1)'\n  },\n  TimePicker: {\n    itemFontSize: '16px',\n    itemHeight: '38px',\n    itemWidth: '74px',\n    panelActionPadding: '12px 0'\n  },\n  Tooltip: {\n    peers: {\n      Popover: {\n        padding: '20px',\n        fontSize: '16px'\n      }\n    }\n  },\n  Transfer: {\n    extraTextColor: '#666'\n  },\n  Typography: {\n    headerPrefixWidth3: '15px',\n    headerPrefixWidth4: '15px',\n    headerPrefixWidth5: '15px',\n    headerPrefixWidth6: '15px'\n  }\n}\n"
  },
  {
    "path": "themes/tusimple/src/unconfigurable-style-dark.ts",
    "content": "import { changeColor } from 'seemly'\nimport { c, cB, cE, cM, cNotM } from 'naive-ui'\n\nexport function mountSvgDefs (): void {\n  if (document.getElementById('naive-ui/tusimple/svg-defs')) return\n  const svgDefs = `<defs>\n    <linearGradient id=\"progress-info\">\n      <stop offset=\"0%\" stop-color=\"#80c6ff\" />\n      <stop offset=\"100%\" stop-color=\"#335fff\" />\n    </linearGradient>\n    <linearGradient id=\"progress-success\">\n      <stop offset=\"0%\" stop-color=\"#AFF25E\" />\n      <stop offset=\"100%\" stop-color=\"#4FB233\" />\n    </linearGradient>\n    <linearGradient id=\"progress-warning\">\n      <stop offset=\"0%\" stop-color=\"#F2E93D\" />\n      <stop offset=\"100%\" stop-color=\"#FFAC26\" />\n    </linearGradient>\n    <linearGradient id=\"progress-error\">\n      <stop offset=\"0%\" stop-color=\"#FF66BA\" />\n      <stop offset=\"100%\" stop-color=\"#D92149\" />\n    </linearGradient>\n  </defs>`\n  const svgEl = document.createElementNS('http://www.w3.org/2000/svg', 'svg')\n  svgEl.innerHTML = svgDefs\n  svgEl.id = 'naive-ui/tusimple/svg-defs'\n  document.body.appendChild(svgEl)\n}\n\nexport const unconfigurableStyle = c([\n  cB(\n    'base-select-menu',\n    {\n      overflow: 'hidden'\n    },\n    [\n      cB('base-select-menu-option-wrapper', {\n        paddingTop: '4px!important',\n        paddingBottom: '4px!important'\n      }),\n      cB('base-select-option', [\n        cM(\n          'selected',\n          {\n            backgroundColor: 'transparent'\n          },\n          [\n            c('&:hover', {\n              backgroundColor: 'var(--n-option-color-pending)'\n            })\n          ]\n        )\n      ])\n    ]\n  ),\n  cB('base-selection', [\n    cB('base-suffix', {\n      transition: 'all .3s'\n    }),\n    cM('active', [\n      cB(\n        'base-suffix',\n        {\n          transform: 'translateY(-50%) rotate(180deg)'\n        },\n        [\n          cB('base-suffix__arrow', {\n            color: '#4FB233'\n          })\n        ]\n      )\n    ])\n  ]),\n  cB('button', [\n    cNotM('disabled', [\n      c('&:hover', {\n        color: 'var(--n-text-color)'\n      })\n    ])\n  ]),\n  cB('cascader-menu', {\n    padding: '4px 0'\n  }),\n  cB('dropdown-menu', {\n    overflow: 'hidden'\n  }),\n  cB('date-panel', [\n    cB('date-panel-dates', [\n      cB('date-panel-date', [\n        cM(\n          'current',\n          {\n            color: '#4FB233'\n          },\n          [\n            cM('disabled', {\n              color: 'rgba(79, 178, 51, .5)'\n            }),\n            cB('date-panel-date__sup', {\n              display: 'none'\n            })\n          ]\n        ),\n        cM('start, end', [\n          c('&:nth-child(7n + 1)::before', {\n            left: '0'\n          }),\n          c('&:nth-child(7n + 7)::before', {\n            right: '0'\n          })\n        ]),\n        cM('covered, start, end', [\n          cNotM('excluded', [\n            c('&:nth-child(7n + 1)::before', {\n              left: '0'\n            }),\n            c('&:nth-child(7n + 7)::before', {\n              right: '0'\n            })\n          ])\n        ])\n      ])\n    ])\n  ]),\n  cB('data-table', [\n    cB('data-table-tr', [\n      cNotM('summary', [\n        c('&:hover', {\n          backgroundColor: 'transparent'\n        })\n      ])\n    ]),\n    cB('data-table-td', [\n      c('&.n-data-table-td--hover', {\n        backgroundColor: 'transparent'\n      })\n    ]),\n    cM('bottom-bordered', [\n      cB('data-table-wrapper', [\n        cB('data-table-base-table', [\n          cB('data-table-base-table-body', {\n            borderRadius: 'var(--n-border-radius);'\n          })\n        ])\n      ])\n    ]),\n    cB('data-table-empty', {\n      backgroundColor: '#1E1E1E'\n    })\n  ]),\n  cB('dialog', [\n    cE('title', {\n      marginTop: '20px',\n      lineHeight: '33px'\n    }),\n    cE('content', {\n      lineHeight: '22px'\n    })\n  ]),\n  cB('dynamic-tags', [\n    cB('button', {\n      height: '24px'\n    }),\n    cB('input', [\n      cM('autosize', {\n        minWidth: '68px'\n      })\n    ])\n  ]),\n  cB(\n    'table',\n    {\n      borderRadius: 'var(--n-border-radius)'\n    },\n    [\n      c('th', {\n        borderRight: '1px solid transparent'\n      })\n    ]\n  ),\n  cB('tabs', [\n    cB('tabs-bar', {\n      height: '4px !important',\n      borderRadius: '100px !important',\n      transform: 'scaleX(0.395)'\n    })\n  ]),\n  cB('input', [\n    cM('textarea', [\n      cM('resizable', [\n        cB('input-wrapper', {\n          margin: '0 5px 5px 0',\n          paddingRight: '7px'\n        })\n      ])\n    ])\n  ]),\n  cB('tag', [\n    cE(\n      'close',\n      {\n        borderRadius: '50%'\n      },\n      [\n        c('&:hover', {\n          backgroundColor: changeColor('#D7DAE0', { alpha: 0.5 })\n        }),\n        c('&:hover', {\n          backgroundColor: changeColor('#D7DAE0', { alpha: 0.25 })\n        })\n      ]\n    )\n  ]),\n  cB('time-picker-panel', [\n    cB('time-picker-col', [\n      cE('item', [\n        cM('active', [\n          c('&::before', {\n            backgroundColor: 'transparent'\n          })\n        ]),\n        c('&:before', {\n          right: '0'\n        })\n      ])\n    ]),\n    cB(\n      'time-picker-actions',\n      {\n        width: '100%',\n        display: 'inline-block',\n        textAlign: 'center'\n      },\n      [\n        cB('button', {\n          margin: '0 6px'\n        })\n      ]\n    )\n  ]),\n  cB('tooltip', {\n    padding: '8px 16px!important'\n  }),\n  cB('transfer', [\n    cB(\n      'transfer-gap',\n      {\n        width: '56px'\n      },\n      [\n        cB(\n          'button',\n          {\n            width: '32px',\n            height: '32px',\n            padding: '0'\n          },\n          [\n            c('&:hover', [\n              cNotM('disabled', [\n                cE('icon', {\n                  color: 'var(--n-text-color-hover)'\n                })\n              ])\n            ]),\n            cE('border', {\n              border: '1px solid #848484'\n            }),\n            cE('icon', {\n              color: '#848484'\n            }),\n            cM(\n              'disabled',\n              {\n                backgroundColor: 'transparent'\n              },\n              [\n                cE('border', {\n                  border: '1px solid #5B5B5B'\n                }),\n                cE('icon', {\n                  color: '#5B5B5B'\n                })\n              ]\n            )\n          ]\n        )\n      ]\n    ),\n    cB('transfer-list', [\n      cB('transfer-list-header', [\n        cB('transfer-list-header__checkbox', {\n          paddingLeft: '12px',\n          paddingRight: '13px'\n        }),\n        cB('transfer-list-header__extra', {\n          marginRight: '12px'\n        })\n      ]),\n      cB('transfer-list-body', [\n        cB('transfer-list-flex-container', [\n          cB('transfer-list-content', [\n            cB('transfer-list-item', [\n              cB('transfer-list-item__checkbox', {\n                paddingLeft: '12px',\n                paddingRight: '13px'\n              })\n            ])\n          ])\n        ])\n      ])\n    ])\n  ]),\n  cB('tree', [\n    cB('tree-node-wrapper', {\n      margin: '0 -4px'\n    })\n  ]),\n  cB('message', [\n    cE('close', [\n      c('&:hover', {\n        backgroundColor: changeColor('#D7DAE0', { alpha: 0.5 })\n      }),\n      c('&:active', {\n        backgroundColor: changeColor('#D7DAE0', { alpha: 0.25 })\n      })\n    ])\n  ]),\n  cB('progress', [\n    cB('progress-graph', [\n      cB('progress-graph-line', [\n        cB('progress-graph-line-rail', [\n          cB('progress-graph-line-fill', {\n            background: 'linear-gradient(270deg, #F2E93D 0%, #FFAC26 100%)'\n          })\n        ])\n      ]),\n      cB('progress-graph-circle', [\n        cB('progress-graph-circle-fill', {\n          stroke: 'url(#progress-warning)'\n        })\n      ])\n    ]),\n    cM('info', [\n      cB('progress-graph-line', [\n        cB('progress-graph-line-rail', [\n          cB('progress-graph-line-fill', {\n            background: 'linear-gradient(270deg, #F2E93D 0%, #FFAC26 100%)'\n          })\n        ])\n      ]),\n      cM('circle', [\n        cB('progress-graph-circle-fill', {\n          stroke: 'url(#progress-warning)'\n        })\n      ])\n    ]),\n    cM('success', [\n      cB('progress-graph-line', [\n        cB('progress-graph-line-rail', [\n          cB('progress-graph-line-fill', {\n            background: 'linear-gradient(270deg, #AFF25E 0%, #4FB233 100%)'\n          })\n        ])\n      ]),\n      cM('circle', [\n        cB('progress-graph-circle-fill', {\n          stroke: 'url(#progress-success)'\n        })\n      ])\n    ]),\n    cM('warning', [\n      cB('progress-graph-line', [\n        cB('progress-graph-line-rail', [\n          cB('progress-graph-line-fill', {\n            background: 'linear-gradient(270deg, #FF66BA 0%, #D92149 100%)'\n          })\n        ])\n      ]),\n      cM('circle', [\n        cB('progress-graph-circle-fill', {\n          stroke: 'url(#progress-error)'\n        })\n      ])\n    ]),\n    cM('error', [\n      cB('progress-graph-line', [\n        cB('progress-graph-line-rail', [\n          cB('progress-graph-line-fill', {\n            background: 'linear-gradient(270deg, #FF66BA 0%, #D92149 100%)'\n          })\n        ])\n      ]),\n      cM('circle', [\n        cB('progress-graph-circle-fill', {\n          stroke: 'url(#progress-error)'\n        })\n      ])\n    ])\n  ]),\n  cB('switch', [\n    cM('active', [\n      cE('rail', [\n        cE('button', {\n          backgroundImage: 'linear-gradient(45deg, #4EB233 0%, #AFF25E 100%)'\n        })\n      ])\n    ]),\n    cM('disabled', [\n      cE(\n        'rail',\n        {\n          opacity: '1',\n          backgroundColor: 'rgba(91, 91, 91, .5)'\n        },\n        [\n          cE('button', {\n            backgroundColor: '#5B5B5B',\n            backgroundImage: 'unset',\n            boxShadow: 'none'\n          })\n        ]\n      ),\n      cM('active', [\n        cE('rail', [\n          cE('button', {\n            backgroundColor: '#314A2A'\n          })\n        ])\n      ])\n    ]),\n    cE(\n      'rail',\n      {\n        overflow: 'visible'\n      },\n      [\n        cE('button', {\n          backgroundImage: 'linear-gradient(135deg, #E2E5E9 0%, #999999 100%)'\n        })\n      ]\n    )\n  ]),\n  cB('upload-file-list', [\n    cB('upload-file', [\n      cB('upload-file-info', [\n        cE('action', [\n          cB('button--default-type', {\n            color: '#ADADAD'\n          })\n        ])\n      ])\n    ])\n  ])\n])\n"
  },
  {
    "path": "themes/tusimple/src/unconfigurable-style-light.ts",
    "content": "import { changeColor } from 'seemly'\nimport { c, cB, cE, cM, cNotM } from 'naive-ui'\n\nexport function mountSvgDefs (): void {\n  if (document.getElementById('naive-ui/tusimple/svg-defs')) return\n  const svgDefs = `<defs>\n    <linearGradient id=\"progress-info\">\n      <stop offset=\"0%\" stop-color=\"#335fff\" />\n      <stop offset=\"100%\" stop-color=\"#80c6ff\" />\n    </linearGradient>\n    <linearGradient id=\"progress-success\">\n      <stop offset=\"0%\" stop-color=\"#4FB233\" />\n      <stop offset=\"100%\" stop-color=\"#AFF25E\" />\n    </linearGradient>\n    <linearGradient id=\"progress-warning\">\n      <stop offset=\"0%\" stop-color=\"#FFAC26\" />\n      <stop offset=\"100%\" stop-color=\"#F2E93D\" />\n    </linearGradient>\n    <linearGradient id=\"progress-error\">\n      <stop offset=\"0%\" stop-color=\"#D92149\" />\n      <stop offset=\"100%\" stop-color=\"#FF66BA\" />\n    </linearGradient>\n  </defs>`\n  const svgEl = document.createElementNS('http://www.w3.org/2000/svg', 'svg')\n  svgEl.innerHTML = svgDefs\n  svgEl.id = 'naive-ui/tusimple/svg-defs'\n  document.body.appendChild(svgEl)\n}\n\nexport const unconfigurableStyle = c([\n  cB(\n    'base-select-menu',\n    {\n      overflow: 'hidden'\n    },\n    [\n      cB('base-select-menu-option-wrapper', {\n        paddingTop: '4px!important',\n        paddingBottom: '4px!important'\n      }),\n      cB('base-select-option', [\n        cM(\n          'selected',\n          {\n            backgroundColor: 'transparent'\n          },\n          [\n            c('&:hover', {\n              backgroundColor: 'var(--n-option-color-pending)'\n            })\n          ]\n        )\n      ])\n    ]\n  ),\n  cB('base-selection', [\n    cB('base-suffix', {\n      transition: 'all .3s'\n    }),\n    cM('active', [\n      cB(\n        'base-suffix',\n        {\n          transform: 'translateY(-50%) rotate(180deg)'\n        },\n        [\n          cB('base-suffix__arrow', {\n            color: '#4FB233'\n          })\n        ]\n      )\n    ])\n  ]),\n  cB('cascader-menu', {\n    padding: '4px 0'\n  }),\n  cB('dropdown-menu', {\n    overflow: 'hidden'\n  }),\n  cB('date-panel', [\n    cB('date-panel-dates', [\n      cB('date-panel-date', [\n        cM(\n          'current',\n          {\n            color: '#4FB233'\n          },\n          [\n            cM('disabled', {\n              color: 'rgba(79, 178, 51, .5)'\n            }),\n            cB('date-panel-date__sup', {\n              display: 'none'\n            })\n          ]\n        ),\n        cM('selected', {\n          color: 'var(--n-item-text-color-active)'\n        }),\n        cM('start, end', [\n          c('&:nth-child(7n + 1)::before', {\n            left: '0'\n          }),\n          c('&:nth-child(7n + 7)::before', {\n            right: '0'\n          })\n        ]),\n        cM('covered, start, end', [\n          cNotM('excluded', [\n            c('&:nth-child(7n + 1)::before', {\n              left: '0'\n            }),\n            c('&:nth-child(7n + 7)::before', {\n              right: '0'\n            })\n          ])\n        ])\n      ])\n    ])\n  ]),\n  cB('data-table', [\n    cB('data-table-tr', [\n      cNotM('summary', [\n        c('&:hover', {\n          backgroundColor: 'transparent'\n        })\n      ])\n    ]),\n    cB('data-table-td', [\n      c('&.n-data-table-td--hover', {\n        backgroundColor: 'transparent'\n      })\n    ]),\n    cM('bottom-bordered', [\n      cB('data-table-wrapper', [\n        cB('data-table-base-table', [\n          cB('data-table-base-table-body', {\n            borderRadius: 'var(--n-border-radius);'\n          })\n        ])\n      ])\n    ])\n  ]),\n  cB('dialog', [\n    cE('title', {\n      marginTop: '20px',\n      lineHeight: '33px'\n    }),\n    cE('content', {\n      lineHeight: '22px'\n    })\n  ]),\n  cB('dynamic-tags', [\n    cB('button', {\n      height: '24px'\n    }),\n    cB('input', [\n      cM('autosize', {\n        minWidth: '68px'\n      })\n    ])\n  ]),\n  cB('input', [\n    cM('textarea', [\n      cM('resizable', [\n        cB('input-wrapper', {\n          margin: '0 5px 5px 0',\n          paddingRight: '7px'\n        })\n      ])\n    ])\n  ]),\n  cB(\n    'table',\n    {\n      borderRadius: 'var(--n-border-radius)'\n    },\n    [\n      c('th', {\n        borderRight: '1px solid transparent'\n      })\n    ]\n  ),\n  cB('tabs', [\n    cB('tabs-bar', {\n      height: '4px !important',\n      borderRadius: '100px !important',\n      transform: 'scaleX(0.395)'\n    })\n  ]),\n  cB('tag', [\n    cE(\n      'close',\n      {\n        borderRadius: '50%'\n      },\n      [\n        c('&:hover', {\n          backgroundColor: changeColor('#D7DAE0', { alpha: 0.5 })\n        }),\n        c('&:hover', {\n          backgroundColor: changeColor('#D7DAE0', { alpha: 0.25 })\n        })\n      ]\n    )\n  ]),\n  cB('time-picker-panel', [\n    cB('time-picker-col', [\n      cE('item', [\n        cM('active', [\n          c('&::before', {\n            backgroundColor: 'transparent'\n          })\n        ]),\n        c('&:before', {\n          right: '0'\n        })\n      ])\n    ]),\n    cB(\n      'time-picker-actions',\n      {\n        width: '100%',\n        display: 'inline-block',\n        textAlign: 'center'\n      },\n      [\n        cB('button', {\n          margin: '0 6px'\n        })\n      ]\n    )\n  ]),\n  cB('tooltip', {\n    padding: '8px 16px!important'\n  }),\n  cB('transfer', [\n    cB(\n      'transfer-gap',\n      {\n        width: '56px'\n      },\n      [\n        cB(\n          'button',\n          {\n            width: '32px',\n            height: '32px',\n            padding: '0'\n          },\n          [\n            c('&:hover', [\n              cNotM('disabled', [\n                cE('icon', {\n                  color: 'var(--n-text-color-hover)'\n                })\n              ])\n            ]),\n            cE('border', {\n              border: '1px solid #ccc'\n            }),\n            cE('icon', {\n              color: '#999'\n            }),\n            cM(\n              'disabled',\n              {\n                backgroundColor: 'transparent'\n              },\n              [\n                cE('border', {\n                  border: '1px solid #D7DAE0'\n                }),\n                cE('icon', {\n                  color: '#D7DAE0'\n                })\n              ]\n            )\n          ]\n        )\n      ]\n    ),\n    cB('transfer-list', [\n      cB('transfer-list-header', [\n        cB('transfer-list-header__checkbox', {\n          paddingLeft: '12px',\n          paddingRight: '13px'\n        }),\n        cB('transfer-list-header__extra', {\n          marginRight: '12px'\n        })\n      ]),\n      cB('transfer-list-body', [\n        cB('transfer-list-flex-container', [\n          cB('transfer-list-content', [\n            cB('transfer-list-item', [\n              cB('transfer-list-item__checkbox', {\n                paddingLeft: '12px',\n                paddingRight: '13px'\n              })\n            ])\n          ])\n        ])\n      ])\n    ])\n  ]),\n  cB('tree', [\n    cB('tree-node-wrapper', {\n      margin: '0 -4px'\n    })\n  ]),\n  cB('message', [\n    cE('close', [\n      c('&:hover', {\n        backgroundColor: changeColor('#D7DAE0', { alpha: 0.5 })\n      }),\n      c('&:active', {\n        backgroundColor: changeColor('#D7DAE0', { alpha: 0.25 })\n      })\n    ])\n  ]),\n  cB('progress', [\n    cB('progress-graph', [\n      cB('progress-graph-line', [\n        cB('progress-graph-line-rail', [\n          cB('progress-graph-line-fill', {\n            background: 'linear-gradient(270deg, #FFAC26 0%, #F2E93D 100%)'\n          })\n        ])\n      ]),\n      cB('progress-graph-circle', [\n        cB('progress-graph-circle-fill', {\n          stroke: 'url(#progress-warning)'\n        })\n      ])\n    ]),\n    cM('info', [\n      cB('progress-graph-line', [\n        cB('progress-graph-line-rail', [\n          cB('progress-graph-line-fill', {\n            background: 'linear-gradient(270deg, #FFAC26 0%, #F2E93D 100%)'\n          })\n        ])\n      ]),\n      cM('circle', [\n        cB('progress-graph-circle-fill', {\n          stroke: 'url(#progress-warning)'\n        })\n      ])\n    ]),\n    cM('success', [\n      cB('progress-graph-line', [\n        cB('progress-graph-line-rail', [\n          cB('progress-graph-line-fill', {\n            background: 'linear-gradient(270deg, #4FB233 0%, #AFF25E 100%)'\n          })\n        ])\n      ]),\n      cM('circle', [\n        cB('progress-graph-circle-fill', {\n          stroke: 'url(#progress-success)'\n        })\n      ])\n    ]),\n    cM('warning', [\n      cB('progress-graph-line', [\n        cB('progress-graph-line-rail', [\n          cB('progress-graph-line-fill', {\n            background: 'linear-gradient(270deg, #D92149 0%, #FF66BA 100%)'\n          })\n        ])\n      ]),\n      cM('circle', [\n        cB('progress-graph-circle-fill', {\n          stroke: 'url(#progress-error)'\n        })\n      ])\n    ]),\n    cM('error', [\n      cB('progress-graph-line', [\n        cB('progress-graph-line-rail', [\n          cB('progress-graph-line-fill', {\n            background: 'linear-gradient(270deg, #D92149 0%, #FF66BA 100%)'\n          })\n        ])\n      ]),\n      cM('circle', [\n        cB('progress-graph-circle-fill', {\n          stroke: 'url(#progress-error)'\n        })\n      ])\n    ])\n  ]),\n  cB('switch', [\n    cM('active', [\n      cE('rail', [\n        cE('button', {\n          backgroundImage: 'linear-gradient(45deg, #4EB233 0%, #AFF25E 100%)'\n        })\n      ])\n    ]),\n    cM('disabled', [\n      cE(\n        'rail',\n        {\n          opacity: '1',\n          backgroundColor: 'rgba(215, 218, 224, .5)'\n        },\n        [\n          cE('button', {\n            backgroundColor: '#D7DAE0',\n            backgroundImage: 'unset',\n            boxShadow: 'none'\n          })\n        ]\n      ),\n      cM('active', [\n        cE('rail', [\n          cE('button', {\n            backgroundColor: '#CBE5C6'\n          })\n        ])\n      ])\n    ]),\n    cE(\n      'rail',\n      {\n        overflow: 'visible'\n      },\n      [\n        cE('button', {\n          backgroundImage: 'linear-gradient(135deg, #E2E5E9 0%, #999999 100%)'\n        })\n      ]\n    )\n  ]),\n  cB('upload-file-list', [\n    cB('upload-file', [\n      cB('upload-file-info', [\n        cE('action', [\n          cB('button--default-type', {\n            color: '#999'\n          })\n        ])\n      ])\n    ])\n  ])\n])\n"
  },
  {
    "path": "themes/tusimple/src/use-ts-dialog.ts",
    "content": "import { useDialog as _useDialog } from 'naive-ui'\nimport type {\n  DialogOptions,\n  DialogReactive,\n  DialogApi\n} from 'naive-ui'\nimport { icons } from './icons'\n\nexport interface ExtendedApi {\n  danger: (options: DialogOptions) => DialogReactive\n}\n\nexport type TsDialogApi = DialogApi & ExtendedApi\n\nfunction useDialog (): TsDialogApi {\n  const dialog = _useDialog()\n  const extendedApi: ExtendedApi = {\n    danger: (options: DialogOptions) => {\n      return dialog.error({\n        ...options,\n        icon: icons.warning,\n        type: 'error'\n      })\n    }\n  }\n  return Object.assign(extendedApi, dialog)\n}\n\nexport { useDialog }\n"
  },
  {
    "path": "themes/tusimple/src/use-ts-message.ts",
    "content": "import { useMessage as _useMessage } from 'naive-ui'\nimport type {\n  MessageOptions,\n  MessageReactive,\n  MessageApi\n} from 'naive-ui'\nimport { icons } from './icons'\n\nexport interface ExtendedApi {\n  danger: (content: string, options: MessageOptions) => MessageReactive\n}\n\nexport type TsMessageApi = MessageApi & ExtendedApi\n\nfunction useMessage (): TsMessageApi {\n  const messageApi = _useMessage()\n  const extendedApi: ExtendedApi = {\n    danger: (content: string, options: MessageOptions) => {\n      return messageApi.error(content, {\n        ...options,\n        icon: icons.warning\n      })\n    }\n  }\n  return Object.assign(extendedApi, messageApi)\n}\n\nexport { useMessage }\n"
  },
  {
    "path": "themes/tusimple/src/vars.ts",
    "content": "export const BORDER_RADIUS = '20px'\n\nexport const NORMAL_BOX_SHADOW =\n  '0 2px 16px 0 rgba(0,0,0,0.1), 0 0 16px -2px rgba(0,0,0,0.06)'\n\nexport const NORMAL_BOX_SHADOW_DARK_THEME =\n  '0 2px 16px 0 rgba(0,0,0,0.16), 0 0 16px -2px rgba(0,0,0,0.12)'\n\nexport const SPECIAL_BOX_SHADOW =\n  '0 40px 16px -24px rgba(0,0,0, 0.04), 0 8px 16px -8px rgba(0,0,0, 0.12), 0 16px 40px 16px rgba(0,0,0,0.04)'\n\nexport const SPECIAL_BOX_SHADOW_DARK_THEME =\n  '0 40px 16px -24px rgba(0,0,0, 0.48), 0 8px 16px -8px rgba(0,0,0, 0.96), 0 16px 40px 16px rgba(0,0,0,0.48)'\n\nexport const SMALL_FRONT_SIZE = '12px'\n\nexport const NORMAL_FRONT_SIZE = '16px'\n\nexport const SPECIAL_FRONT_SIZE = '24px'\n\nexport const GRAY_COLOR_1 = '#333333'\n\nexport const GRAY_COLOR_2 = '#666666'\n\nexport const GRAY_COLOR_3 = '#999999'\n\nexport const GRAY_COLOR_4 = '#cccccc'\n\nexport const GRAY_COLOR_5 = '#D7DAE0'\n\nexport const GRAY_COLOR_6 = '#EBEDF0'\n\nexport const CONTENT_SPACE = '20px'\n\nexport default {\n  BORDER_RADIUS,\n  NORMAL_BOX_SHADOW,\n  NORMAL_BOX_SHADOW_DARK_THEME,\n  SPECIAL_BOX_SHADOW,\n  SPECIAL_BOX_SHADOW_DARK_THEME,\n  NORMAL_FRONT_SIZE,\n  SPECIAL_FRONT_SIZE,\n  SMALL_FRONT_SIZE,\n  CONTENT_SPACE,\n  GRAY_COLOR_1,\n  GRAY_COLOR_2,\n  GRAY_COLOR_3,\n  GRAY_COLOR_4,\n  GRAY_COLOR_5,\n  GRAY_COLOR_6\n}\n"
  },
  {
    "path": "themes/tusimple/tsconfig.cjs.json",
    "content": "{\n  \"extends\": \"../../tsconfig.json\",\n  \"compilerOptions\": {\n    \"target\": \"ES6\",\n    \"jsx\": \"react\",\n    \"rootDir\": \"./src\",\n    \"module\": \"CommonJS\",\n    \"moduleResolution\": \"node\",\n    \"outDir\": \"./lib\"\n  },\n  \"references\": [{ \"path\": \"../../src/tsconfig.cjs.json\" }]\n}\n"
  },
  {
    "path": "themes/tusimple/tsconfig.esm.json",
    "content": "{\n  \"extends\": \"../../tsconfig.json\",\n  \"compilerOptions\": {\n    \"target\": \"ES6\",\n    \"jsx\": \"react\",\n    \"rootDir\": \"./src\",\n    \"module\": \"ES6\",\n    \"outDir\": \"./es\"\n  },\n  \"references\": [{ \"path\": \"../../src/tsconfig.esm.json\" }]\n}\n"
  },
  {
    "path": "tsconfig.cjs.json",
    "content": "{\n  \"references\": [\n    {\n      \"path\": \"./src/tsconfig.cjs.json\"\n    },\n    {\n      \"path\": \"./themes/tusimple/tsconfig.cjs.json\"\n    }\n  ],\n  \"files\": []\n}\n"
  },
  {
    "path": "tsconfig.esbuild.json",
    "content": "{\n  \"extends\": \"./tsconfig.json\",\n  \"compilerOptions\": {\n    \"jsx\": \"react\",\n    \"jsxFactory\": \"h\",\n    \"jsxFragmentFactory\": \"Fragment\"\n  }\n}\n"
  },
  {
    "path": "tsconfig.esm.json",
    "content": "{\n  \"references\": [\n    {\n      \"path\": \"./src/tsconfig.esm.json\"\n    },\n    {\n      \"path\": \"./themes/tusimple/tsconfig.esm.json\"\n    }\n  ],\n  \"files\": []\n}\n"
  },
  {
    "path": "tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"composite\": true,\n    \"target\": \"ES6\",\n    \"jsx\": \"preserve\",\n    \"jsxFactory\": \"h\",\n    \"jsxFragmentFactory\": \"Fragment\",\n    \"lib\": [\"ESNext\", \"DOM\"],\n    \"module\": \"ESNext\",\n    \"moduleResolution\": \"bundler\",\n    \"paths\": {\n      \"naive-ui\": [\"./src\"],\n      \"naive-ui/generic\": [\"./generic\"]\n    },\n    \"resolveJsonModule\": true,\n    \"types\": [\"vue/jsx\", \"vitest/globals\"],\n    \"strict\": true,\n    \"strictNullChecks\": true,\n    \"noImplicitAny\": true,\n    \"noUnusedLocals\": true,\n    \"declaration\": true,\n    \"outDir\": \"./build/dist\",\n    \"esModuleInterop\": true,\n    \"forceConsistentCasingInFileNames\": true,\n    \"skipLibCheck\": true\n  }\n}\n"
  },
  {
    "path": "tsconfig.scripts.json",
    "content": "{\n  \"extends\": \"./tsconfig.json\",\n  \"compilerOptions\": {\n    \"target\": \"ESNext\",\n    \"module\": \"ESNext\",\n    \"moduleResolution\": \"nodenext\",\n    \"resolveJsonModule\": true,\n    \"types\": [\"node\"],\n    \"esModuleInterop\": true\n  },\n  \"references\": [{ \"path\": \"./src/tsconfig.esm.json\" }],\n  \"include\": [\"scripts/**/*.ts\", \"build/**/*.ts\", \"package.json\"]\n}\n"
  },
  {
    "path": "tsconfig.test.json",
    "content": "{\n  \"extends\": \"./tsconfig.json\",\n  \"compilerOptions\": {\n    \"jsx\": \"react\"\n  }\n}\n"
  },
  {
    "path": "umd-test/index.spec.js",
    "content": "import './setupVue.js'\nimport fs from 'fs'\nimport path from 'path'\n\n// eslint-disable-next-line n/no-exports-assign\nexports = undefined\n\n// eslint-disable-next-line no-eval\neval(\n  fs.readFileSync(path.resolve(__dirname, '..', 'dist', 'index.js')).toString()\n)\n\ndescribe('umd', () => {\n  it('works', () => {\n    const div = document.createElement('div')\n    document.body.appendChild(div)\n    window.Vue.createApp(window.naive.NDataTable).mount(div)\n    expect(div.innerHTML).toContain('n-data-table')\n  })\n})\n"
  },
  {
    "path": "umd-test/setupVue.js",
    "content": "import * as Vue from 'vue'\n\nwindow.Vue = Vue\n"
  },
  {
    "path": "vite.config.mts",
    "content": "import dns from 'node:dns'\nimport path from 'node:path'\nimport process from 'node:process'\nimport { babel } from '@rollup/plugin-babel'\nimport { configDefaults, defineConfig } from 'vitest/config'\nimport { createDemoPlugin } from './build/vite-plugin-demo'\n\ndns.setDefaultResultOrder('verbatim')\n\nconst isBuildTimeTest = process.argv.some(arg =>\n  /(?:^|[\\\\/])(umd-test|esm-test)/.test(arg)\n)\n\nconst testExclude = isBuildTimeTest\n  ? configDefaults.exclude\n  : [...configDefaults.exclude, 'umd-test/**/*', 'esm-test/**/*']\n\nexport default defineConfig({\n  root: __dirname,\n  plugins: createDemoPlugin(),\n  resolve: {\n    // In production site build, we want to import naive-ui from node_modules\n    alias:\n      process.env.NODE_ENV !== 'production'\n        ? [\n            {\n              find: 'naive-ui/generic',\n              replacement: path.resolve(__dirname, './generic')\n            },\n            {\n              find: 'naive-ui',\n              replacement: path.resolve(__dirname, './src')\n            }\n          ]\n        : undefined\n  },\n  define: {\n    'process.env.NODE_ENV': `'${process.env.NODE_ENV}'`,\n    'process.env.TUSIMPLE': !!process.env.TUSIMPLE,\n    __DEV__: process.env.NODE_ENV !== 'production'\n  },\n  optimizeDeps: {\n    include: [\n      '@css-render/plugin-bem',\n      'async-validator',\n      'css-render',\n      'date-fns',\n      'date-fns-tz/getTimezoneOffset',\n      'evtd',\n      'highlight.js',\n      'lodash-es',\n      'seemly',\n      'treemate',\n      'vdirs',\n      'vooks',\n      'vue',\n      'vue-router',\n      'vueuc',\n      '@css-render/vue3-ssr',\n      'date-fns-tz',\n      'codesandbox/lib/api/define',\n      'grapheme-splitter',\n      'highlight.js/lib/core',\n      'highlight.js/lib/languages/javascript',\n      'highlight.js/lib/languages/python',\n      'highlight.js/lib/languages/cpp',\n      'highlight.js/lib/languages/xml',\n      '@vicons/ionicons5',\n      '@vicons/ionicons4',\n      '@vicons/fluent/Compose16Regular.js'\n    ],\n    exclude: ['__INDEX__']\n  },\n  build: {\n    outDir: 'site',\n    rollupOptions: {\n      output: {\n        manualChunks: {\n          'grapheme-splitter': ['grapheme-splitter'],\n          katex: ['katex']\n        }\n      },\n      plugins: [\n        babel({\n          babelHelpers: 'bundled'\n        })\n      ]\n    }\n  },\n  esbuild: {\n    jsx: 'transform',\n    jsxFactory: 'h',\n    jsxFragment: 'Fragment'\n  },\n  test: {\n    globals: true,\n    environment: 'jsdom',\n    setupFiles: ['src/vitest-setup.ts'],\n    exclude: testExclude,\n    coverage: {\n      provider: 'v8',\n      reportsDirectory: path.resolve(__dirname, 'coverage'),\n      reporter: ['text', 'lcov', 'json', 'json-summary', 'html'],\n      include: ['src/**/*.{ts,tsx}'],\n      exclude: [\n        '**/*.d.ts',\n        'src/**/__tests__/**/*.[jt][sx]',\n        'src/**/tests/**/*.[jt][sx]'\n      ]\n    }\n  }\n})\n"
  },
  {
    "path": "volar.d.ts",
    "content": "// Auto generated component declarations\ndeclare module 'vue' {\n  export interface GlobalComponents {\n    NAffix: (typeof import('naive-ui'))['NAffix']\n    NAlert: (typeof import('naive-ui'))['NAlert']\n    NAnchor: (typeof import('naive-ui'))['NAnchor']\n    NAnchorLink: (typeof import('naive-ui'))['NAnchorLink']\n    NAutoComplete: (typeof import('naive-ui'))['NAutoComplete']\n    NAvatar: (typeof import('naive-ui'))['NAvatar']\n    NAvatarGroup: (typeof import('naive-ui'))['NAvatarGroup']\n    NBackTop: (typeof import('naive-ui'))['NBackTop']\n    NBadge: (typeof import('naive-ui'))['NBadge']\n    NBreadcrumb: (typeof import('naive-ui'))['NBreadcrumb']\n    NBreadcrumbItem: (typeof import('naive-ui'))['NBreadcrumbItem']\n    NButton: (typeof import('naive-ui'))['NButton']\n    NButtonGroup: (typeof import('naive-ui'))['NButtonGroup']\n    NCalendar: (typeof import('naive-ui'))['NCalendar']\n    NCard: (typeof import('naive-ui'))['NCard']\n    NCarousel: (typeof import('naive-ui'))['NCarousel']\n    NCarouselItem: (typeof import('naive-ui'))['NCarouselItem']\n    NCascader: (typeof import('naive-ui'))['NCascader']\n    NCheckbox: (typeof import('naive-ui'))['NCheckbox']\n    NCheckboxGroup: (typeof import('naive-ui'))['NCheckboxGroup']\n    NCode: (typeof import('naive-ui'))['NCode']\n    NCollapse: (typeof import('naive-ui'))['NCollapse']\n    NCollapseItem: (typeof import('naive-ui'))['NCollapseItem']\n    NCollapseTransition: (typeof import('naive-ui'))['NCollapseTransition']\n    NColorPicker: (typeof import('naive-ui'))['NColorPicker']\n    NConfigProvider: (typeof import('naive-ui'))['NConfigProvider']\n    NCountdown: (typeof import('naive-ui'))['NCountdown']\n    NDataTable: (typeof import('naive-ui'))['NDataTable']\n    NDatePicker: (typeof import('naive-ui'))['NDatePicker']\n    NDescriptions: (typeof import('naive-ui'))['NDescriptions']\n    NDescriptionsItem: (typeof import('naive-ui'))['NDescriptionsItem']\n    NDialog: (typeof import('naive-ui'))['NDialog']\n    NDialogProvider: (typeof import('naive-ui'))['NDialogProvider']\n    NDivider: (typeof import('naive-ui'))['NDivider']\n    NDrawer: (typeof import('naive-ui'))['NDrawer']\n    NDrawerContent: (typeof import('naive-ui'))['NDrawerContent']\n    NDropdown: (typeof import('naive-ui'))['NDropdown']\n    NDynamicInput: (typeof import('naive-ui'))['NDynamicInput']\n    NDynamicTags: (typeof import('naive-ui'))['NDynamicTags']\n    NEl: (typeof import('naive-ui'))['NEl']\n    NElement: (typeof import('naive-ui'))['NElement']\n    NEllipsis: (typeof import('naive-ui'))['NEllipsis']\n    NPerformantEllipsis: (typeof import('naive-ui'))['NPerformantEllipsis']\n    NEmpty: (typeof import('naive-ui'))['NEmpty']\n    NEquation: (typeof import('naive-ui'))['NEquation']\n    NFlex: (typeof import('naive-ui'))['NFlex']\n    NFloatButton: (typeof import('naive-ui'))['NFloatButton']\n    NFloatButtonGroup: (typeof import('naive-ui'))['NFloatButtonGroup']\n    NForm: (typeof import('naive-ui'))['NForm']\n    NFormItem: (typeof import('naive-ui'))['NFormItem']\n    NFormItemCol: (typeof import('naive-ui'))['NFormItemCol']\n    NFormItemGi: (typeof import('naive-ui'))['NFormItemGi']\n    NFormItemGridItem: (typeof import('naive-ui'))['NFormItemGridItem']\n    NFormItemRow: (typeof import('naive-ui'))['NFormItemRow']\n    NGlobalStyle: (typeof import('naive-ui'))['NGlobalStyle']\n    NGradientText: (typeof import('naive-ui'))['NGradientText']\n    NGi: (typeof import('naive-ui'))['NGi']\n    NGrid: (typeof import('naive-ui'))['NGrid']\n    NGridItem: (typeof import('naive-ui'))['NGridItem']\n    NHeatmap: (typeof import('naive-ui'))['NHeatmap']\n    NHighlight: (typeof import('naive-ui'))['NHighlight']\n    NIcon: (typeof import('naive-ui'))['NIcon']\n    NIconWrapper: (typeof import('naive-ui'))['NIconWrapper']\n    NImage: (typeof import('naive-ui'))['NImage']\n    NImageGroup: (typeof import('naive-ui'))['NImageGroup']\n    NImagePreview: (typeof import('naive-ui'))['NImagePreview']\n    NInfiniteScroll: (typeof import('naive-ui'))['NInfiniteScroll']\n    NInput: (typeof import('naive-ui'))['NInput']\n    NInputGroup: (typeof import('naive-ui'))['NInputGroup']\n    NInputGroupLabel: (typeof import('naive-ui'))['NInputGroupLabel']\n    NInputNumber: (typeof import('naive-ui'))['NInputNumber']\n    NInputOtp: (typeof import('naive-ui'))['NInputOtp']\n    NLayout: (typeof import('naive-ui'))['NLayout']\n    NLayoutContent: (typeof import('naive-ui'))['NLayoutContent']\n    NLayoutFooter: (typeof import('naive-ui'))['NLayoutFooter']\n    NLayoutHeader: (typeof import('naive-ui'))['NLayoutHeader']\n    NLayoutSider: (typeof import('naive-ui'))['NLayoutSider']\n    NCol: (typeof import('naive-ui'))['NCol']\n    NRow: (typeof import('naive-ui'))['NRow']\n    NLegacyTransfer: (typeof import('naive-ui'))['NLegacyTransfer']\n    NList: (typeof import('naive-ui'))['NList']\n    NListItem: (typeof import('naive-ui'))['NListItem']\n    NLoadingBarProvider: (typeof import('naive-ui'))['NLoadingBarProvider']\n    NLog: (typeof import('naive-ui'))['NLog']\n    NMarquee: (typeof import('naive-ui'))['NMarquee']\n    NMention: (typeof import('naive-ui'))['NMention']\n    NMenu: (typeof import('naive-ui'))['NMenu']\n    NMessageProvider: (typeof import('naive-ui'))['NMessageProvider']\n    NModal: (typeof import('naive-ui'))['NModal']\n    NModalProvider: (typeof import('naive-ui'))['NModalProvider']\n    NNotificationProvider: (typeof import('naive-ui'))['NNotificationProvider']\n    NNumberAnimation: (typeof import('naive-ui'))['NNumberAnimation']\n    NPageHeader: (typeof import('naive-ui'))['NPageHeader']\n    NPagination: (typeof import('naive-ui'))['NPagination']\n    NPopconfirm: (typeof import('naive-ui'))['NPopconfirm']\n    NPopover: (typeof import('naive-ui'))['NPopover']\n    NPopselect: (typeof import('naive-ui'))['NPopselect']\n    NProgress: (typeof import('naive-ui'))['NProgress']\n    NQrCode: (typeof import('naive-ui'))['NQrCode']\n    NRadio: (typeof import('naive-ui'))['NRadio']\n    NRadioButton: (typeof import('naive-ui'))['NRadioButton']\n    NRadioGroup: (typeof import('naive-ui'))['NRadioGroup']\n    NRate: (typeof import('naive-ui'))['NRate']\n    NResult: (typeof import('naive-ui'))['NResult']\n    NScrollbar: (typeof import('naive-ui'))['NScrollbar']\n    NSelect: (typeof import('naive-ui'))['NSelect']\n    NSkeleton: (typeof import('naive-ui'))['NSkeleton']\n    NSlider: (typeof import('naive-ui'))['NSlider']\n    NSpace: (typeof import('naive-ui'))['NSpace']\n    NSpin: (typeof import('naive-ui'))['NSpin']\n    NSplit: (typeof import('naive-ui'))['NSplit']\n    NStatistic: (typeof import('naive-ui'))['NStatistic']\n    NStep: (typeof import('naive-ui'))['NStep']\n    NSteps: (typeof import('naive-ui'))['NSteps']\n    NSwitch: (typeof import('naive-ui'))['NSwitch']\n    NTable: (typeof import('naive-ui'))['NTable']\n    NTbody: (typeof import('naive-ui'))['NTbody']\n    NTd: (typeof import('naive-ui'))['NTd']\n    NTh: (typeof import('naive-ui'))['NTh']\n    NThead: (typeof import('naive-ui'))['NThead']\n    NTr: (typeof import('naive-ui'))['NTr']\n    NTab: (typeof import('naive-ui'))['NTab']\n    NTabPane: (typeof import('naive-ui'))['NTabPane']\n    NTabs: (typeof import('naive-ui'))['NTabs']\n    NTag: (typeof import('naive-ui'))['NTag']\n    NThing: (typeof import('naive-ui'))['NThing']\n    NTime: (typeof import('naive-ui'))['NTime']\n    NTimePicker: (typeof import('naive-ui'))['NTimePicker']\n    NTimeline: (typeof import('naive-ui'))['NTimeline']\n    NTimelineItem: (typeof import('naive-ui'))['NTimelineItem']\n    NTooltip: (typeof import('naive-ui'))['NTooltip']\n    NTransfer: (typeof import('naive-ui'))['NTransfer']\n    NTree: (typeof import('naive-ui'))['NTree']\n    NTreeSelect: (typeof import('naive-ui'))['NTreeSelect']\n    NA: (typeof import('naive-ui'))['NA']\n    NBlockquote: (typeof import('naive-ui'))['NBlockquote']\n    NH1: (typeof import('naive-ui'))['NH1']\n    NH2: (typeof import('naive-ui'))['NH2']\n    NH3: (typeof import('naive-ui'))['NH3']\n    NH4: (typeof import('naive-ui'))['NH4']\n    NH5: (typeof import('naive-ui'))['NH5']\n    NH6: (typeof import('naive-ui'))['NH6']\n    NHr: (typeof import('naive-ui'))['NHr']\n    NLi: (typeof import('naive-ui'))['NLi']\n    NOl: (typeof import('naive-ui'))['NOl']\n    NP: (typeof import('naive-ui'))['NP']\n    NText: (typeof import('naive-ui'))['NText']\n    NUl: (typeof import('naive-ui'))['NUl']\n    NUpload: (typeof import('naive-ui'))['NUpload']\n    NUploadDragger: (typeof import('naive-ui'))['NUploadDragger']\n    NUploadFileList: (typeof import('naive-ui'))['NUploadFileList']\n    NUploadTrigger: (typeof import('naive-ui'))['NUploadTrigger']\n    NVirtualList: (typeof import('naive-ui'))['NVirtualList']\n    NWatermark: (typeof import('naive-ui'))['NWatermark']\n  }\n}\nexport {}\n"
  },
  {
    "path": "vue3.md",
    "content": "# Migrate from V1\n\n## General Breaking Changes\n\n- css\n  - css index `naive-ui/lib|es/styles/index.css` has been removed, do not import it any more!\n- fonts\n  - `naive-ui/lib|es/styles/fonts/*` has been removed, use [vfonts](https://www.npmjs.com/package/vfonts)\n- icons\n\n  - `naive-ui/lib|es/icons/*` is deprecated (vue-loader is required).\n  - `naive-ui/lib|es/icons/*` is removed since v2.10.0\n  - use [xicons](https://github.com/07akioni/xicons) instead.\n\n- `n-nimbus-icon` is moved to `naive-ui/compat/nimbus-icon` (vue-loader is required) `n-nimbus-icon` is removed since v2.10.0\n- `n-nimbus-form-card` is removed\n- locale & theme on `n-config-provider` doesn't accept string any more (not it accepts object).\n\n## Components\n\n- [x] form\n  - form-item\n    - new\n      - `show-feedback` prop\n- [x] affix\n  - deprecate\n    - `target` => `listen-to`\n- [x] alert\n- [x] anchor\n  - new\n    - `show-rail` props\n    - `show-background` props\n  - deprecate\n    - `target` => `listen-to`\n- [x] auto-complete\n  - break\n    - `v-model` => `v-model:value`\n  - deprecate\n    - `on-input` => `on-update:value`\n  - new\n    - `on-blur`\n    - `on-focus`\n- [x] avatar\n- [x] back-top\n  - new\n    - `show` controlled show\n    - `on-update:show`\n    - `to` teleport target\n  - deprecate\n    - `on-show` => `on-update:show`\n    - `on-hide` => `on-update:show`\n    - `target` => `listen-to`\n- [x] badge\n- [x] breadcrumb\n- [x] button\n- [x] button-group\n- [x] card\n- [x] cascader\n  - break\n    - `v-model` => `v-model:value`\n    - `on-load` has different usage\n    - `leaf-only` has different meaning\n  - new\n    - `cascade` prop\n    - `show-path` prop\n    - `default-value` prop\n  - deprecated\n    - `on-change` => `on-update:value`\n- [x] checkbox\n  - checkbox\n    - break\n      - `value` only supports `string`\n    - deprecate\n      - `on-change` => `on-update:checked`\n    - new\n      - `default-checked` prop\n  - checkbox-group\n    - break\n      - `value` only supports `string` or `null`\n    - deprecate\n      - `on-change` => `on-update:value`\n- [x] code\n- [x] collapse\n  - deprecate\n    - `on-expanded-names-change` => `on-update:expanded-names`\n  - removed\n    - `v-model` => `v-model:expanded-names`\n- [x] config-consumer (deprecated)\n- [x] config-provider\n  - break\n    - `theme` use new theme from naive export\n    - `$NOs.theme` => `useOsTheme`\n    - `theme` => `legacy-theme`\n  - deprecate\n    - `as` => `tag`\n    - `styleScheme` won't working in next version\n  - new\n    - `date-locale` prop\n    - `locale` prop\n    - provide `useOsTheme` hook\n- [x] confirm => `dialog`\n  - break\n    - rename `confirm` to `dialog`\n  - remove\n    - `$NConfirm`, `$NModal` => `useDialog`\n- [x] data-table\n  - deprecate\n    - `on-filters-change` => `on-update:filters`\n    - `on-sorter-change` => `on-update:sorter`\n    - `on-checked-row-keys-change` => `on-update:checked-row-keys`\n    - `on-page-change` => `on-update:page`\n    - `on-page-size-change` => `on-update:page-size`\n- [x] date-picker\n  - break\n    - `v-model` => `v-model:value`\n  - deprecate\n    - `on-change` => `on-update:value`\n  - new\n    - `default-value` prop\n- [x] descriptions\n- [x] divider\n- [x] drawer\n  - break\n    - `v-model`\n  - deprecate\n    - `on-show` => `on-update:show`\n    - `on-hide` => `on-update:show`\n    - `target` => `to`\n    - `drawer-class` => `class`\n    - `drawer-style` => `style`\n  - new\n    - `display-directive` prop\n- [x] dropdown\n  - break\n    - `option.value` => `option.key`\n    - item must have unique key\n    - submenu must have unique key\n  - remove\n    - `submenu-width`\n    - `submenu-min-width`\n    - `submenu-max-width`\n  - new\n    - `option.icon`\n- [x] dynamic-input\n  - break\n    - `v-model` => `v-model:value`\n    - `on-clear` is removed\n  - deprecate\n    - `on-input` => `on-update:value`\n  - new\n    - `item-style` prop\n    - `min` prop\n    - `default-value` prop\n- [x] dynamic-tags\n  - break\n    - `v-model` => `v-model:value`\n- [x] element\n- [x] empty\n- [x] gradient-text\n- [x] grid\n- [x] icon\n- [x] input\n  - break\n    - `v-model` => `v-model:value`\n  - new\n    - `on-update:value` prop\n    - `default-value` prop\n- [x] input-group\n- [x] input-group-label\n- [x] input-number\n  - deprecate\n    - `on-change` => `on-update:value`\n  - new\n    - `default-value` prop\n- [x] layout\n  - layout-content, layout\n    - breaking `use-native-scrollbar` => `native-scrollbar`\n  - layout-sider\n    - breaking `use-native-scrollbar` => `native-scrollbar`\n    - deprecate\n      - `on-expand` => `on-update:collapsed`\n      - `on-collapse` => `on-update:collapsed`\n- [x] list\n- [x] loading-bar\n  - remove\n    - `$NLoadingBar`\n  - new\n    - `useLoadingBar`\n    - `n-loading-bar-provider`\n- [x] log\n  - deprecate\n    - `scrollToTop` => `scrollTo`\n    - `scrollToBottom` => `scrollTo`\n- [x] menu\n  - deprecate\n    - `on-expanded-names-change` => `on-update:expanded-keys`\n    - `on-select` => `on-update:value`\n    - `expanded-names` => `expanded-keys`\n    - `default-expanded-names` => `default-expanded-keys`\n    - `item.name` => `item.key`\n  - remove\n    - `item.titleExtra`\n    - `overlay-width`\n    - `overlay-min-width`\n- [x] message\n  - rewrite message using `n-message-provider`\n  - new\n    - `useMessage`\n  - deprecate\n    - `onHide` => `onLeave`\n    - `onAfterHide` => `onAfterLeave`\n  - remove\n    - `message.hide` => `message.destroy`\n- [x] modal\n  - rewrite with teleport\n  - new\n    - `display-directive`\n  - deprecate\n    - `v-model`\n    - `on-show` => `on-update:show`\n    - `on-hide` => `on-update:show`\n    - `overlay-style` => `style`\n  - remove\n    - default hide behavior for preset\n- [x] notification\n  - new\n    - `useNotification`\n  - deprecate\n    - `open` => `create`\n    - `onHide` => `onLeave`\n    - `onAfterShow` => `onAfterEnter`\n    - `onAfterHide` => `onAfterHide`\n- [x] pagination\n  - deprecate\n    - `on-change` => `on-update:page`\n    - `on-page-size-change` => `on-update:page-size`\n- [x] popconfirm\n- [x] popover\n  - new\n    - `default-show`\n    - `overlap`\n  - deprecate\n    - `#activator` => `#trigger`\n    - `overlay-xxx` => `body-xxx`\n  - remove\n    - `controller`\n    - `max-width`\n    - `width`\n    - `min-width`\n    - `manual` trigger is removed, use `show` to controll the popover\n    - `body-class`, use `class` instead\n    - `body-style`, use `style` instead\n- [x] popselect\n  - break\n    - `v-model` => `v-model:value`\n  - deprecate\n    - `on-change` => `on-update:value`\n- [x] progress\n- [x] radio\n  - radio-group\n    - break\n      - default `size` `'small'` => `'medium'`\n      - value only supports `string` or `null`\n    - deprecate\n      - `on-change` => `on-update:value`\n  - radio & radio-button\n    - break\n      - value only supports `string`\n      - `checked-value` => `checked`\n        - It is change to conform html standard usage\n      - `on-change` => `on-update:checked`\n        - `on-change` is now a native event\n- [x] result\n- [x] scrollbar\n- [x] select\n  - break\n    - `v-model` => `v-model:value`\n    - `on-scroll(event, container, content)` => `on-scroll(event)`\n    - `option.render(h, data)` => `option.render(data)`\n  - deprecated\n    - `on-change` => `on-update:value`\n- [x] slider\n  - deprecated\n    - `on-change` => `on-update:value`\n  - new\n    - `default-value` prop\n  - bug\n    - vue refs https://github.com/vuejs/vue-next/issues/2283\n    - drag logic\n- [x] space\n- [x] spin\n  - breaking\n    - `'in-small'`, `'in-medium'` and `'in-large'` size are removed\n  - deprecate\n    - `spinning` => `show`\n- [x] statistic\n- [x] steps\n- [x] switch\n  - remove\n    - `value` => `value`\n    - `change` => `on-update:value`\n- [x] table\n- [x] tabs\n  - deprecate\n    - `active-name` => `value`\n    - `on-active-name-change` => `on-update:value`\n- [x] tag\n  - break\n    - `v-model` => `v-model:value`\n  - deprecate\n    - `on-checked-change` => `on-update:checked`\n- [x] thing\n- [x] time\n  - break\n    - `type` default from `'relative'` to `'date-time'`\n- [x] time-picker\n  - break\n    - `v-model` => `v-model:value`\n- [x] timeline\n- [x] tooltip\n  - deprecate\n    - `#activator` => `#trigger`\n- [x] transfer\n  - break\n    - `v-model` => `v-model:value`\n  - deprecate\n    - `on-change` => `on-update:value`\n  - new\n    - `default-value` prop\n- [x] tree\n  - break\n    - `v-model` => `v-model:selected-keys`\n  - deprecate\n    - `on-selected-keys-change` => `on-update:selected-keys`\n    - `on-checked-keys-change` => `on-update:checked-keys`\n    - `on-expanded-keys-change` => `on-update:expanded-keys`\n- [x] typography\n  - breaking\n    - text, p\n      - `depth` from `primary` ... `tertiary` => `1`, `2`, `3`\n  - deprecate\n    - text\n      - `as` => `tag`\n- [x] upload\n- [x] nimbus-service-layout\n\n  - breaking\n    - `v-model` => `v-model:value`\n\n- TODO\n  - [x] vooks\n  - [x] icons from `vicons`\n  - [x] fonts from `vfonts`\n  - [x] vite-build\n  - [x] rollup-build\n    - [x] wait for new version of rollup-plugin-vue, https://github.com/vuejs/rollup-plugin-vue/issues/408\n  - tusimple theme\n  - [x] clean delegate\n  - [x] site production tag (bug)\n  - [x] demo scrollbar 的问题\n  - [x] table x scroll 右侧阴影不消失\n  - [x] log scrollTo 有点问题\n  - [x] remove hollowoutable\n  - [x] styleScheme, css variables 组件\n    - 文档之后再说\n  - [x] use-global-style ? 感觉效果不会特别好而且还是很无谓的性能开销这个问题可以之后再思考，现阶段 vue 的写法还是全局 install\n  - [x] dynamic-input, no value\n  - [x] button, input 的 css 变量名需要修改一下\n  - [x] test rollup treeshaking\n  - [x] test webpack treeshaking\n  - [x] menu utils render\n  - [x] dialog bug\n  - [x] data-table css vars\n  - [x] typography css vars\n  - [x] spin css vars\n  - [x] radio css vars\n  - [x] checkbox css vars\n  - [x] avatar css vars\n  - [x] landing page icon\n  - [x] switch styles\n  - [x] slider styles\n  - [x] drawer api\n  - [x] chrome date-picker overflow (focus({ preventScroll }))\n  - [x] slider 键盘好像会激活不该激活的 tooltip...\n  - [x] transfer 打包之后有问题\n  - [x] side effects = false 好像会影响 rollup 的打包（这让我很不安，要是生效 css 怎么办？要是不生效 JS 怎么办？）（事实上确实会影响网站对于 fonts 的打包，只能先靠脚本凑活一下） https://github.com/rollup/plugins/issues/692\n  - [x] vue 在 $attrs 的处理上 dev 和 prod 还是有差别 https://github.com/vuejs/vue-next/issues/2741\n  - [x] date-picker input 的 clear 有时候不会清除，看起来是 vue 的 bug\n    - https://github.com/vuejs/vue-next/issues/2768\n  - [x] radio-group 影响主题切换，看起来是 vue 的 bug\n    - https://github.com/vuejs/vue-next/issues/2829\n  - [x] cascader demo async 切换未重置数据，demo 写的有问题\n  - [x] gradient-text transition 又没了\n  - [x] md-loader code\n  - [x] input + form-item style\n  - [x] loadingbar theme\n  - [x] dropdown group + menu use dropdown\n  - [x] 多行 message\n  - [x] progress height\n  - [x] close 重构\n  - [x] data-table, radio style 重构\n  - [x] message icon style\n  - [x] transfer search icon style\n  - [x] base selection icon style\n  - [x] date picker not working\n  - [x] avatar font size bug\n  - [x] handle global style\n    - 暂时放在 useTheme + useStyle 中... 似乎没啥太好的办法，最终还是要想办法让样式不要溢出\n  - [x] select menu padding top & bottom\n  - [x] time-picker invalid\n  - [x] date-picker invalid\n  - [x] vooks `useNow`\n  - [x] treemate activePath includeGroup: false\n  - [x] 拆分 dateFns locale => dateLocale\n  - [x] 试图把组件的 demo 放到 src 里面\n  - [x] 去掉仅存的 mixin\n  - [x] form item default type explain\n  - [x] selection focus style\n  - [x] refactor site use store!!! singleton\n  - [x] 文档网站主题切换\n  - [x] 文档网站 demo 样式\n  - [x] anchor bug！\n  - [x] getKey select & autocomplete type safe & input event interface? onInput value | null or value\n  - [x] vshow (maybe create a vue pr)\n  - [x] jsx focusin out (waiting for vue update)\n  - [x] inject key & value in type (I should use InjectionKey...)\n  - [x] form item no label css\n  - [x] unify treemate ignored\n  - [x] fix menu extra\n  - [x] build icon\n  - [x] compat\n  - [x] fix upload dragger\n  - [x] fix table sorter\n  - [x] tree 多选节点第二个 demo\n  - [x] table treemate!!!\n  - [x] createTheme\n  - [x] build site\n  - [x] table fixed col\n  - [ ] prefixCls，暂时不需要\n  - [x] 更新一波文档 props\n  - [x] 更新样式的文档\n  - [ ] on update value api\n  - [x] anchor in modal page, maybe a bug of vue...\n  - [ ] menu + dropdown collapsed 时候 menu item 不更新（selected 从使用 useMemo 切换成 computed（性能下降）, Vue 在这种时候一定存在 bug，但是暂时没空找了...）\n  - [ ] select menu multiple, when show=true, checkmark transiton not working（推测是 vue 的 bug）\n  - [ ] demo hmr （或许是 vite-plugin-vue 或 vite 的 bug，修改内容不更新）\n  - [x] 不再提前编译 demo 的 highlight code，应该可以缩小很多打包体积\n  - [x] fix input textarea clear...\n  - [x] input auto size\n  - [x] data table custom render sorter\n  - [x] upload retry\n  - [x] table bottom-bordered\n  - [x] data table filter menu\n  - [x] popover default trigger\n  - [x] select option type\n  - [x] <del>popover after enter 之后关闭再生效</del> 把 duration 和 delay 弄小点，而且里面事件处理器其实写的有问题\n  - [x] popover width\n  - [ ] selection popover 滚动\n  - [x] card 设定高度\n  - [x] dropdown 手动定位有 bug，mousemoveoutside\n  - [x] select menu loading\n  - [x] refactor layout to make position work on first shot\n  - [x] <del>mention mention pending option not correct, sometimes it is not the first option</del> In fact it's caused by mouse hover on item...\n  - [x] code Deprecated as of 10.7.0. highlight(lang, code, ...args) has been deprecated.\n  - [x] vdirs zindexable https://github.com/vuejs/vue-next/issues/3497\n  - [x] collapse-item overflow\n  - [x] anchor ignore gap 有 bug\n  - [x] popover click 移动端不生效\n  - [ ] menu path 对应的问题\n  - [x] debug anchor 删除无用 link\n  - [x] popover inst methods\n  - [x] ios 浏览器 demo code font size 不对\n  - [x] <del>table overflow bordered</del>\n  - [x] table ellipisis vertical align\n  - [x] form item grid item\n  - [x] select filter composite...\n  - [x] 清理导出的 select 类型\n  - [ ] make eslint work with markdown ts\n\n## Build\n\npackage: tsx => es|lib => terse cssr => replace global vars => release\n\nsite: build package => move to node_modules => setup side effects => vite build => release\n\n## Info\n\nhttps://github.com/vuejs/vue-next/issues/2549 last cherry-picked commit: 6560ae34d71b81d584af79f810cb9dfa87119d1a\n"
  }
]