[
  {
    "path": ".dumirc.ts",
    "content": "// more config: https://d.umijs.org/config\nimport { defineConfig } from 'dumi';\nimport path from 'path';\n\nconst basePath = process.env.GITHUB_ACTIONS ? '/collapse/' : '/';\nconst publicPath = process.env.GITHUB_ACTIONS ? '/collapse/' : '/';\n\nexport default defineConfig({\n  alias: {\n    'rc-collapse$': path.resolve('src'),\n    'rc-collapse/es': path.resolve('src'),\n  },\n  mfsu: false,\n  favicons: ['https://avatars0.githubusercontent.com/u/9441414?s=200&v=4'],\n  themeConfig: {\n    name: 'Collapse',\n    logo: 'https://avatars0.githubusercontent.com/u/9441414?s=200&v=4',\n  },\n  base: basePath,\n  publicPath,\n});\n"
  },
  {
    "path": ".editorconfig",
    "content": "# top-most EditorConfig file\nroot = true\n\n# Unix-style newlines with a newline ending every file\n[*.{js,css}]\nend_of_line = lf\ninsert_final_newline = true\nindent_style = space\nindent_size = 2\n"
  },
  {
    "path": ".eslintrc.js",
    "content": "const base = require('@umijs/fabric/dist/eslint');\n\nmodule.exports = {\n  ...base,\n  rules: {\n    ...base.rules,\n    'no-template-curly-in-string': 0,\n    'prefer-promise-reject-errors': 0,\n    'react/no-array-index-key': 0,\n    'react/sort-comp': 0,\n    '@typescript-eslint/no-explicit-any': 0,\n    'jsx-a11y/role-supports-aria-props': 0,\n    'jsx-a11y/label-has-associated-control': 0,\n    'jsx-a11y/label-has-for': 0,\n    'jsx-a11y/no-noninteractive-tabindex': 0,\n    'import/no-extraneous-dependencies': 0,\n    '@typescript-eslint/consistent-type-exports': 2,\n  },\n};\n"
  },
  {
    "path": ".fatherrc.ts",
    "content": "import { defineConfig } from 'father';\n\nexport default defineConfig({\n  plugins: ['@rc-component/father-plugin'],\n});\n"
  },
  {
    "path": ".github/dependabot.yml",
    "content": "version: 2\nupdates:\n- package-ecosystem: npm\n  directory: \"/\"\n  schedule:\n    interval: daily\n    time: \"21:00\"\n  open-pull-requests-limit: 10\n  ignore:\n  - dependency-name: \"@types/react-dom\"\n    versions:\n    - 17.0.0\n    - 17.0.1\n    - 17.0.2\n  - dependency-name: \"@types/react\"\n    versions:\n    - 17.0.0\n    - 17.0.1\n    - 17.0.2\n    - 17.0.3\n  - dependency-name: np\n    versions:\n    - 7.2.0\n    - 7.3.0\n    - 7.4.0\n  - dependency-name: less\n    versions:\n    - 4.1.0\n"
  },
  {
    "path": ".github/workflows/react-component-ci.yml",
    "content": "name: ✅ test\non: [push, pull_request]\njobs:\n  test:\n    uses: react-component/rc-test/.github/workflows/test.yml@main\n    secrets: inherit"
  },
  {
    "path": ".github/workflows/site-deploy.yml",
    "content": "name: Deploy website\non:\n  push:\n    tags:\n      - '*'\n  workflow_dispatch:\n\npermissions:\n  contents: write\n\njobs:\n  build-and-deploy:\n    runs-on: ubuntu-latest\n    steps:\n      - name: checkout\n        uses: actions/checkout@v3\n\n      - name: setup node\n        uses: actions/setup-node@v1\n        with:\n          node-version: 14\n\n      - name: create package-lock.json\n        run: npm i --package-lock-only --ignore-scripts\n\n      - name: Install dependencies\n        run: npm ci\n\n      - name: build Docs\n        run: npm run build\n\n      - name: Deploy to GitHub Pages\n        uses: peaceiris/actions-gh-pages@v3\n        with:\n          github_token: ${{ secrets.GITHUB_TOKEN }}\n          publish_dir: ./dist\n          force_orphan: true\n          user_name: 'github-actions[bot]'\n          user_email: 'github-actions[bot]@users.noreply.github.com'\n"
  },
  {
    "path": ".gitignore",
    "content": "*.iml\n*.log\n.idea/\n.ipr\n.iws\n*~\n~*\n*.diff\n*.patch\n*.bak\n.DS_Store\nThumbs.db\n.project\n.*proj\n.svn/\n*.swp\n*.swo\n*.pyc\n*.pyo\n.build\nnode_modules\n.cache\ndist\nassets/**/*.css\nbuild\nlib\ncoverage\nes\nyarn.lock\npackage-lock.json\npnpm-lock.yaml\n.storybook\n.doc\n\n# dumi\n.dumi/tmp\n.dumi/tmp-production\n.dumi/tmp-test\n.env.local\nsrc/.umi\n\nbun.lockb"
  },
  {
    "path": ".husky/pre-commit",
    "content": "lint-staged\n"
  },
  {
    "path": ".prettierrc",
    "content": "{\n  \"singleQuote\": true,\n  \"trailingComma\": \"all\",\n  \"proseWrap\": \"never\",\n  \"printWidth\": 100\n}\n"
  },
  {
    "path": "HISTORY.md",
    "content": "# History\n\n---\n\n## 2.0.0 `2020-05-08`\n\n- Remove `react-lifecycles-compat` and `prop-types`.\n- Upgrade `rc-animate` to `3.x`.\n- Use `@ant-design/css-animation`.\n\n## 1.11.0\n\n- Add `extra`.\n\n## 1.10.0 2018-08-13\n\n- Add `expandIcon`.\n\n## 1.9.1 2018-05-10\n\n- Fix invalid aria-expanded prop in preact\n\n## 1.9.0 2018-04-02\n\n- Add keyboard support [#84](https://github.com/react-component/collapse/pull/84)\n\n## 1.8.0 2018-01-30\n\n- Add prop forceRender to Panel [#82](https://github.com/react-component/collapse/pull/82)\n\n## 1.7.6 2017-06-06\n\n- Add prop id for Panel [#69](https://github.com/react-component/collapse/issues/69)\n\n## 1.7.4 2017-05-16\n\n- Add prop disabled [!71](https://github.com/react-component/collapse/pull/71)\n- Add es module export [!70](https://github.com/react-component/collapse/pull/70)\n\n## 1.7.2 2017-04-25\n\n- Allow user to add custom header classe [!66](https://github.com/react-component/collapse/pull/66)\n\n## 1.7.1 2017-04-19\n\n- Add prop destroyInactivePanel [!61](https://github.com/react-component/collapse/pull/61)\n\n## 1.7.0\n\n- Change createClass to React.Component [!58](https://github.com/react-component/collapse/pull/58)\n\n## 1.6.12\n\n- Fix `style` support for Panel\n\n## 1.6.11\n\n- Add 'showArrow' prop to Panel to toggle arrow visibility [!48](https://github.com/react-component/collapse/pull/48)\n\n## 1.6.10\n\n- Child item support null [!45](https://github.com/react-component/collapse/pull/45)\n\n## 1.6.6\n\n- add className props to Panel\n\n## 1.6.5\n\n- fix missing rc-collapse-item-active classname on active panel header\n\n## 1.6.0\n\n- lazy render/controllable\n\n## 1.5.0\n\n- use css animation instead of velocity.js\n\n## 1.4.0\n\n- only support react 0.14+\n\n## 1.2.0 2015-07-10\n\n- 'chore' Change name to Collapse\n- 'feat' Support Collapse and Accordion\n\n## 1.1.0 2015-07-09\n\n- `test` Add test\n- `refactor` add Panel Api\n"
  },
  {
    "path": "LICENSE.md",
    "content": "The MIT License (MIT)\n\nCopyright (c) 2014-present yiminghe\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n"
  },
  {
    "path": "README.md",
    "content": "# rc-collapse\n\nrc-collapse ui component for react\n\n[![NPM version][npm-image]][npm-url] [![build status][github-actions-image]][github-actions-url] [![Test coverage][codecov-image]][codecov-url] [![npm download][download-image]][download-url]\n\n[npm-image]: http://img.shields.io/npm/v/rc-collapse.svg?style=flat-square\n[npm-url]: http://npmjs.org/package/rc-collapse\n[github-actions-image]: https://github.com/react-component/collapse/workflows/CI/badge.svg\n[github-actions-url]: https://github.com/react-component/collapse/actions\n[codecov-image]: https://img.shields.io/codecov/c/github/react-component/collapse/master.svg?style=flat-square\n[codecov-url]: https://app.codecov.io/gh/react-component/collapse\n[download-image]: https://img.shields.io/npm/dm/rc-collapse.svg?style=flat-square\n[download-url]: https://npmjs.org/package/rc-collapse\n\n## Live Demo\n\nhttps://collapse-react-component.vercel.app\n\n## Install\n\n[![rc-collapse](https://nodei.co/npm/rc-collapse.png)](https://npmjs.org/package/rc-collapse)\n\n## Usage\n\n```js\nvar Collapse = require('rc-collapse');\nvar Panel = Collapse.Panel;\nvar React = require('react');\nvar ReactDOM = require('react-dom');\nrequire('rc-collapse/assets/index.css');\n\nvar App = (\n  <Collapse accordion={true}>\n    <Panel header=\"hello\" headerClass=\"my-header-class\">\n      this is panel content\n    </Panel>\n    <Panel header=\"title2\">this is panel content2 or other</Panel>\n  </Collapse>\n);\nReactDOM.render(App, container);\n```\n\n## Features\n\n- support ie8,ie8+,chrome,firefox,safari\n\n## API\n\n### Collapse props\n\n<table class=\"table table-bordered table-striped\">\n    <thead>\n    <tr>\n        <th style=\"width: 100px;\">name</th>\n        <th style=\"width: 50px;\">type</th>\n        <th>default</th>\n        <th>description</th>\n    </tr>\n    </thead>\n    <tbody>\n      <tr>\n          <td>activeKey</td>\n          <td>String|Array<String></td>\n          <th>The first panel key</th>\n          <td>current active Panel key</td>\n      </tr>\n      <tr>\n        <td>className</td>\n        <td>String or object</td>\n        <th></th>\n        <td>custom className to apply</td>\n      </tr>\n      <tr>\n          <td>defaultActiveKey</td>\n          <td>String|Array<String></td>\n          <th>null</th>\n          <td>default active key</td>\n      </tr>\n      <tr>\n          <td>destroyOnHidden</td>\n          <td>Boolean</td>\n          <th>false</th>\n          <td>If destroy the panel which not active, default false. </td>\n      </tr>\n      <tr>\n          <td>accordion</td>\n          <td>Boolean</td>\n          <th>false</th>\n          <td>accordion mode, default is null, is collapse mode</td>\n      </tr>\n      <tr>\n          <td>onChange</td>\n          <td>Function(key)</td>\n          <th>noop</th>\n          <td>called when collapse Panel is changed</td>\n      </tr>\n      <tr>\n          <td>expandIcon</td>\n          <td>(props: PanelProps) => ReactNode</td>\n          <th></th>\n          <td>specific the custom expand icon.</td>\n      </tr>\n      <tr>\n          <td>collapsible</td>\n          <td>'header' | 'icon' | 'disabled'</td>\n          <th>-</th>\n          <td>specify whether the panel of children is collapsible or the area of collapsible.</td>\n      </tr>\n      <tr>\n          <td>items</td>\n          <td>\n            <a href=\"./src/interface.ts#ItemType\">interface.ts#ItemType</a>\n          </td>\n          <th>-</th>\n          <td>collapse items content</td>\n      </tr>\n    </tbody>\n</table>\n\nIf `accordion` is null or false, every panel can open. Opening another panel will not close any of the other panels. `activeKey` should be an string, if passing an array (the first item in the array will be used).\n\nIf `accordion` is true, only one panel can be open. Opening another panel will cause the previously opened panel to close. `activeKey` should be an string, if passing an array (the first item in the array will be used).\n\n### Collapse.Panel props\n\n> **deprecated** use `items` instead, will be removed in `v4.0.0`\n\n<table class=\"table table-bordered table-striped\">\n    <thead>\n    <tr>\n        <th style=\"width: 100px;\">name</th>\n        <th style=\"width: 200px;\">type</th>\n        <th>default</th>\n        <th>description</th>\n    </tr>\n    </thead>\n    <tbody>\n      <tr>\n          <td>header</td>\n          <td>String or node</td>\n          <th></th>\n          <td>header content of Panel</td>\n      </tr>\n      <tr>\n          <td>headerClass</td>\n          <td>String</td>\n          <th>' '</th>\n          <td>custom className to apply to header</td>\n      </tr>\n      <tr>\n          <td>showArrow</td>\n          <td>boolean</td>\n          <th>true</th>\n          <td>show arrow beside header</td>\n      </tr>\n      <tr>\n        <td>className</td>\n        <td>String or object</td>\n        <th></th>\n        <td>custom className to apply</td>\n      </tr>\n      <tr>\n        <td>classNames</td>\n        <td>{ header?: string, body?: string }</td>\n        <th></th>\n        <td>Semantic structure className</td>\n      </tr>\n      <tr>\n        <td>style</td>\n        <td>object</td>\n        <th></th>\n        <td>custom style</td>\n      </tr>\n      <tr>\n        <td>styles</td>\n        <td>{ header?: React.CSSProperties, body?: React.CSSProperties }</td>\n        <th></th>\n        <td>Semantic structure styles</td>\n      </tr>\n      <tr>\n        <td>openMotion</td>\n        <td>object</td>\n        <th></th>\n        <td>set the animation of open behavior, [more](https://github.com/react-component/motion). Different with v2, closed pane use a `rc-collapse-content-hidden` class to set `display: none` for hidden.</td>\n      </tr>\n      <tr>\n        <td>forceRender</td>\n        <td>boolean</td>\n        <th>false</th>\n        <td>forced render of content in panel, not lazy render after clicking on header</td>\n      </tr>\n      <tr>\n          <td>extra</td>\n          <td>String | ReactNode</td>\n          <th></th>\n          <td>Content to render in the right of the panel header</td>\n      </tr>\n      <tr>\n          <td>collapsible</td>\n          <td>'header' | 'icon' | 'disabled'</td>\n          <th>-</th>\n          <td>specify whether the panel be collapsible or the area of collapsible.</td>\n      </tr>\n    </tbody>\n</table>\n\n> `disabled` is removed since 3.0.0, please use `collapsible=disabled` replace it.\n\n#### key\n\nIf `key` is not provided, the panel's index will be used instead.\n\n#### KeyBoard Event\n\nBy default, Collapse will listen `onKeyDown`(<3.7.0 `onKeyPress`) event with `enter` key to toggle panel's active state when `collapsible` is not `disabled`. If you want to disable this behavior, you can prevent the event from bubbling like this:\n\n```tsx | pure\nconst App = () => {\n  const items: CollapseProps['items'] = [\n    {\n      label: <input onKeyDown={(e) => e.stopPropagation()} />,\n      children: 'content',\n    },\n    {\n      label: (\n        <div onKeyDown={(e) => e.stopPropagation()}>\n          <CustomComponent />\n        </div>\n      ),\n      children: 'content',\n    },\n    {\n      label: 'title 2',\n      children: 'content 2',\n      collapsible: 'disabled',\n    },\n    {\n      label: 'title 3',\n      children: 'content 3',\n      onItemClick: console.log,\n    },\n  ];\n\n  return <Collapse items={items} />;\n};\n```\n\n## Development\n\n```bash\nnpm install\nnpm start\n```\n\n## Test Case\n\n```bash\nnpm test\n```\n\n## Coverage\n\n```bash\nnpm test -- --coverage\n```\n\n## License\n\nrc-collapse is released under the MIT license.\n"
  },
  {
    "path": "assets/index.less",
    "content": "@prefixCls: rc-collapse;\n@text-color: #666;\n@borderStyle: 1px solid #d9d9d9;\n\n@import './motion.less';\n\n#arrow {\n  .common() {\n    width: 0;\n    height: 0;\n    font-size: 0;\n    line-height: 0;\n  }\n  .right(@w, @h, @color) {\n    border-top: @w solid transparent;\n    border-bottom: @w solid transparent;\n    border-left: @h solid @color;\n  }\n\n  .bottom(@w, @h, @color) {\n    border-left: @w solid transparent;\n    border-right: @w solid transparent;\n    border-top: @h solid @color;\n  }\n}\n\n.@{prefixCls} {\n  background-color: #f7f7f7;\n  border-radius: 3px;\n  border: @borderStyle;\n\n  // &-anim-active {\n  //   transition: height 0.2s ease-out;\n  // }\n\n  & > &-item {\n    border-top: @borderStyle;\n    &:first-child {\n      border-top: none;\n    }\n\n    > .@{prefixCls}-header {\n      display: flex;\n      align-items: center;\n      line-height: 22px;\n      padding: 10px 16px;\n      color: #666;\n      cursor: pointer;\n      .arrow {\n        display: inline-block;\n        content: '\\20';\n        #arrow > .common();\n        #arrow > .right(3px, 4px, #666);\n        vertical-align: middle;\n        margin-right: 8px;\n      }\n\n      .@{prefixCls}-extra {\n        margin: 0 16px 0 auto;\n      }\n    }\n    .@{prefixCls}-collapsible-header {\n      cursor: default;\n      .@{prefixCls}-title {\n        cursor: pointer;\n      }\n      .@{prefixCls}-expand-icon {\n        cursor: pointer;\n      }\n    }\n    .@{prefixCls}-collapsible-icon {\n      cursor: default;\n      .@{prefixCls}-expand-icon {\n        cursor: pointer;\n      }\n    }\n  }\n\n  & > &-item-disabled > .@{prefixCls}-header {\n    cursor: not-allowed;\n    color: #999;\n    background-color: #f3f3f3;\n  }\n\n  &-panel {\n    overflow: hidden;\n    color: @text-color;\n    padding: 0 16px;\n    background-color: #fff;\n\n    & > &-box {\n      margin-top: 16px;\n      margin-bottom: 16px;\n    }\n\n    // &-inactive {\n    //   display: none;\n    // }\n  }\n\n  &-item:last-child {\n    > .@{prefixCls}-panel {\n      border-radius: 0 0 3px 3px;\n    }\n  }\n\n  & > &-item-active {\n    > .@{prefixCls}-header {\n      .arrow {\n        position: relative;\n        top: 2px;\n        #arrow > .bottom(3px, 4px, #666);\n        margin-right: 6px;\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "assets/motion.less",
    "content": "@prefixCls: rc-collapse;\n\n.@{prefixCls} {\n  &-motion {\n    transition: height 0.3s, opacity 0.3s;\n  }\n\n  &-panel-hidden {\n    display: none;\n  }\n}\n"
  },
  {
    "path": "bunfig.toml",
    "content": "[install]\npeer = false"
  },
  {
    "path": "docs/demo/basic.md",
    "content": "---\ntitle: Basic\nnav:\n  title: Demo\n  path: /demo\n---\n\n<code src=\"../examples/basic.tsx\"></code>\n"
  },
  {
    "path": "docs/demo/custom-icon.md",
    "content": "---\ntitle: custom-icon\nnav:\n  title: Demo\n  path: /demo\n---\n\n<code src=\"../examples/custom-icon.tsx\"></code>\n"
  },
  {
    "path": "docs/demo/fragment.md",
    "content": "---\ntitle: fragment\nnav:\n  title: Demo\n  path: /demo\n---\n\n<code src=\"../examples/fragment.tsx\"></code>\n"
  },
  {
    "path": "docs/demo/simple.md",
    "content": "---\ntitle: simple\nnav:\n  title: Demo\n  path: /demo\n---\n\n<code src=\"../examples/simple.tsx\"></code>\n"
  },
  {
    "path": "docs/examples/_util/motionUtil.ts",
    "content": "import type {\n  CSSMotionProps,\n  MotionEndEventHandler,\n  MotionEventHandler,\n} from '@rc-component/motion';\n\nconst getCollapsedHeight: MotionEventHandler = () => ({ height: 0, opacity: 0 });\nconst getRealHeight: MotionEventHandler = (node) => ({ height: node.scrollHeight, opacity: 1 });\nconst getCurrentHeight: MotionEventHandler = (node) => ({ height: node.offsetHeight });\nconst skipOpacityTransition: MotionEndEventHandler = (_, event) =>\n  (event as TransitionEvent).propertyName === 'height';\n\nconst collapseMotion: CSSMotionProps = {\n  motionName: 'rc-collapse-motion',\n  onEnterStart: getCollapsedHeight,\n  onEnterActive: getRealHeight,\n  onLeaveStart: getCurrentHeight,\n  onLeaveActive: getCollapsedHeight,\n  onEnterEnd: skipOpacityTransition,\n  onLeaveEnd: skipOpacityTransition,\n  motionDeadline: 500,\n  leavedClassName: 'rc-collapse-panel-hidden',\n};\n\nexport default collapseMotion;\n"
  },
  {
    "path": "docs/examples/basic.tsx",
    "content": "import type { CollapseProps } from 'rc-collapse';\nimport Collapse from 'rc-collapse';\nimport * as React from 'react';\nimport '../../assets/index.less';\n\nconst App = () => {\n  const items: CollapseProps['items'] = [\n    {\n      label: <input onKeyDown={(e) => e.stopPropagation()} />,\n      children: 'content',\n    },\n    {\n      label: 'title 2',\n      children: 'content 2',\n      collapsible: 'disabled',\n    },\n    {\n      label: 'title 3',\n      children: 'content 3',\n      onItemClick: console.log,\n    },\n  ];\n\n  return <Collapse items={items} />;\n};\n\nexport default App;\n"
  },
  {
    "path": "docs/examples/custom-icon.tsx",
    "content": "import Collapse, { Panel } from 'rc-collapse';\nimport * as React from 'react';\nimport '../../assets/index.less';\nimport motion from './_util/motionUtil';\n\nconst initLength = 3;\n\nconst text = `\n  A dog is a type of domesticated animal.\n  Known for its loyalty and faithfulness,\n  it can be found as a welcome guest in many households across the world.\n`;\n\nfunction random() {\n  return parseInt((Math.random() * 10).toString(), 10) + 1;\n}\n\nconst arrowPath =\n  'M869 487.8L491.2 159.9c-2.9-2.5-6.6-3.9-10.5-3.9h-88' +\n  '.5c-7.4 0-10.8 9.2-5.2 14l350.2 304H152c-4.4 0-8 3.6-8 8v60c0 4.4 3.' +\n  '6 8 8 8h585.1L386.9 854c-5.6 4.9-2.2 14 5.2 14h91.5c1.9 0 3.8-0.7 5.' +\n  '2-2L869 536.2c14.7-12.8 14.7-35.6 0-48.4z';\n\nfunction expandIcon({ isActive }) {\n  return (\n    <i style={{ marginRight: '.5rem' }}>\n      <svg\n        viewBox=\"0 0 1024 1024\"\n        width=\"1em\"\n        height=\"1em\"\n        fill=\"currentColor\"\n        style={{\n          verticalAlign: '-.125em',\n          transition: 'transform .2s',\n          transform: `rotate(${isActive ? 90 : 0}deg)`,\n        }}\n      >\n        <path d={arrowPath} />\n      </svg>\n    </i>\n  );\n}\n\nconst App: React.FC = () => {\n  const [, reRender] = React.useState({});\n  const [accordion, setAccordion] = React.useState(false);\n  const [activeKey, setActiveKey] = React.useState<React.Key | React.Key[]>(['4']);\n\n  const time = random();\n\n  const panelItems = Array.from<object, React.ReactNode>({ length: initLength }, (_, i) => {\n    const key = i + 1;\n    return (\n      <Panel header={`This is panel header ${key}`} key={key}>\n        <p>{text.repeat(time)}</p>\n      </Panel>\n    );\n  }).concat(\n    <Panel header={`This is panel header ${initLength + 1}`} key={initLength + 1}>\n      <Collapse defaultActiveKey=\"1\" expandIcon={expandIcon}>\n        <Panel header=\"This is panel nest panel\" key=\"1\" id=\"header-test\">\n          <p>{text}</p>\n        </Panel>\n      </Collapse>\n    </Panel>,\n    <Panel header={`This is panel header ${initLength + 2}`} key={initLength + 2}>\n      <Collapse defaultActiveKey=\"1\">\n        <Panel header=\"This is panel nest panel\" key=\"1\" id=\"another-test\">\n          <form>\n            <label htmlFor=\"test\">Name:&nbsp;</label>\n            <input type=\"text\" id=\"test\" />\n          </form>\n        </Panel>\n      </Collapse>\n    </Panel>,\n  );\n\n  const tools = (\n    <>\n      <button type=\"button\" onClick={() => reRender({})}>\n        reRender\n      </button>\n      <br />\n      <br />\n      <button type=\"button\" onClick={() => setAccordion((prev) => !prev)}>\n        {accordion ? 'Mode: accordion' : 'Mode: collapse'}\n      </button>\n      <br />\n      <br />\n      <button type=\"button\" onClick={() => setActiveKey(['2'])}>\n        active header 2\n      </button>\n      <br />\n      <br />\n    </>\n  );\n\n  return (\n    <>\n      {tools}\n      <Collapse\n        accordion={accordion}\n        onChange={setActiveKey}\n        activeKey={activeKey}\n        expandIcon={expandIcon}\n        openMotion={motion}\n      >\n        {panelItems}\n      </Collapse>\n    </>\n  );\n};\n\nexport default App;\n"
  },
  {
    "path": "docs/examples/fragment.tsx",
    "content": "import Collapse, { Panel } from 'rc-collapse';\nimport * as React from 'react';\nimport { Fragment } from 'react';\nimport '../../assets/index.less';\n\nconst App = () => (\n  <Collapse>\n    <Panel header=\"title\">content</Panel>\n    <Panel header=\"title\">content</Panel>\n    <Fragment>\n      <Panel header=\"title\">content</Panel>\n      <Panel header=\"title\">content</Panel>\n    </Fragment>\n    <Fragment>\n      <Fragment>\n        <Panel header=\"title\">content</Panel>\n        <Panel header=\"title\">content</Panel>\n      </Fragment>\n    </Fragment>\n  </Collapse>\n);\n\nexport default App;\n"
  },
  {
    "path": "docs/examples/simple.tsx",
    "content": "import type { CollapseProps } from 'rc-collapse';\nimport Collapse, { Panel } from 'rc-collapse';\nimport * as React from 'react';\nimport '../../assets/index.less';\nimport motion from './_util/motionUtil';\n\nconst initLength = 3;\n\nconst text = `\n  A dog is a type of domesticated animal.\n  Known for its loyalty and faithfulness,\n  it can be found as a welcome guest in many households across the world.\n`;\n\nfunction random() {\n  return parseInt((Math.random() * 10).toString(), 10) + 1;\n}\n\nconst arrowPath =\n  'M869 487.8L491.2 159.9c-2.9-2.5-6.6-3.9-10.5-3.9h-88' +\n  '.5c-7.4 0-10.8 9.2-5.2 14l350.2 304H152c-4.4 0-8 3.6-8 8v60c0 4.4 3.' +\n  '6 8 8 8h585.1L386.9 854c-5.6 4.9-2.2 14 5.2 14h91.5c1.9 0 3.8-0.7 5.' +\n  '2-2L869 536.2c14.7-12.8 14.7-35.6 0-48.4z';\n\nfunction expandIcon({ isActive }) {\n  return (\n    <i style={{ marginRight: '.5rem' }}>\n      <svg\n        viewBox=\"0 0 1024 1024\"\n        width=\"1em\"\n        height=\"1em\"\n        fill=\"currentColor\"\n        style={{\n          verticalAlign: '-.125em',\n          transition: 'transform .2s',\n          transform: `rotate(${isActive ? 90 : 0}deg)`,\n        }}\n      >\n        <path d={arrowPath} />\n      </svg>\n    </i>\n  );\n}\n\nconst App: React.FC = () => {\n  const [, reRender] = React.useState({});\n  const [accordion, setAccordion] = React.useState(false);\n  const [activeKey, setActiveKey] = React.useState<React.Key | React.Key[]>(['4']);\n  const [collapsible, setCollapsible] = React.useState<CollapseProps['collapsible']>();\n\n  const time = random();\n\n  const panelItems = Array.from<object, React.ReactNode>({ length: initLength }, (_, i) => {\n    const key = i + 1;\n    return (\n      <Panel header={`This is panel header ${key}`} key={key}>\n        <p>{text.repeat(time)}</p>\n      </Panel>\n    );\n  }).concat(\n    <Panel header={`This is panel header ${initLength + 1}`} key={initLength + 1}>\n      <Collapse defaultActiveKey=\"1\" expandIcon={expandIcon}>\n        <Panel header=\"This is panel nest panel\" key=\"1\" id=\"header-test\">\n          <p>{text}</p>\n        </Panel>\n      </Collapse>\n    </Panel>,\n    <Panel header={`This is panel header ${initLength + 2}`} key={initLength + 2}>\n      <Collapse defaultActiveKey=\"1\">\n        <Panel header=\"This is panel nest panel\" key=\"1\" id=\"another-test\">\n          <form>\n            <label htmlFor=\"test\">Name:&nbsp;</label>\n            <input type=\"text\" id=\"test\" />\n          </form>\n        </Panel>\n      </Collapse>\n    </Panel>,\n    <Panel\n      header={`This is panel header ${initLength + 3}`}\n      key={initLength + 3}\n      extra={<span>Extra Node</span>}\n    >\n      <p>Panel with extra</p>\n    </Panel>,\n  );\n\n  const handleCollapsibleChange = (e: React.ChangeEvent<HTMLSelectElement>) => {\n    const values = [undefined, 'header', 'icon', 'disabled'];\n    setCollapsible(values[e.target.value]);\n  };\n\n  const tools = (\n    <>\n      <button type=\"button\" onClick={() => reRender({})}>\n        reRender\n      </button>\n      <br />\n      <br />\n      <button type=\"button\" onClick={() => setAccordion((prev) => !prev)}>\n        {accordion ? 'Mode: accordion' : 'Mode: collapse'}\n      </button>\n      <br />\n      <br />\n      <div>\n        collapsible:\n        <select onChange={handleCollapsibleChange}>\n          <option value={0}>default</option>\n          <option value={1}>header</option>\n          <option value={2}>icon</option>\n          <option value={3}>disabled</option>\n        </select>\n      </div>\n      <br />\n      <button type=\"button\" onClick={() => setActiveKey(['2'])}>\n        active header 2\n      </button>\n      <br />\n      <br />\n    </>\n  );\n\n  return (\n    <>\n      {tools}\n      <Collapse\n        accordion={accordion}\n        onChange={setActiveKey}\n        activeKey={activeKey}\n        expandIcon={expandIcon}\n        openMotion={motion}\n        collapsible={collapsible}\n      >\n        {panelItems}\n      </Collapse>\n    </>\n  );\n};\n\nexport default App;\n"
  },
  {
    "path": "docs/index.md",
    "content": "---\nhero:\n  title: rc-collapse\n  description: rc-collapse ui component for react\n---\n\n<embed src=\"../README.md\"></embed>\n"
  },
  {
    "path": "jest.config.js",
    "content": "module.exports = {\n  setupFilesAfterEnv: ['<rootDir>/tests/setupAfterEnv.ts'],\n};\n"
  },
  {
    "path": "package.json",
    "content": "{\n  \"name\": \"@rc-component/collapse\",\n  \"version\": \"1.2.0\",\n  \"description\": \"rc-collapse ui component for react\",\n  \"keywords\": [\n    \"react\",\n    \"react-component\",\n    \"react-rc-collapse\",\n    \"rc-collapse\",\n    \"collapse\",\n    \"accordion\"\n  ],\n  \"homepage\": \"http://github.com/react-component/collapse\",\n  \"bugs\": {\n    \"url\": \"http://github.com/react-component/collapse/issues\"\n  },\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git@github.com:react-component/collapse.git\"\n  },\n  \"license\": \"MIT\",\n  \"main\": \"./lib/index\",\n  \"module\": \"./es/index\",\n  \"typings\": \"es/index.d.ts\",\n  \"files\": [\n    \"lib\",\n    \"es\",\n    \"assets/*.css\"\n  ],\n  \"scripts\": {\n    \"compile\": \"father build && lessc assets/index.less assets/index.css\",\n    \"coverage\": \"rc-test --coverage\",\n    \"docs:build\": \"dumi build\",\n    \"docs:deploy\": \"npm run docs:build && gh-pages -d dist\",\n    \"lint\": \"eslint src/ --ext .ts,.tsx,.jsx,.js,.md\",\n    \"prepare\": \"husky\",\n    \"now-build\": \"npm run docs:build\",\n    \"prepublishOnly\": \"npm run compile && rc-np\",\n    \"prettier\": \"prettier --write \\\"**/*.{ts,tsx,js,jsx,json,md}\\\"\",\n    \"postpublish\": \"npm run docs:deploy\",\n    \"start\": \"dumi dev\",\n    \"test\": \"rc-test\"\n  },\n  \"lint-staged\": {\n    \"**/*.{ts,tsx,js,jsx,json,md}\": \"npm run prettier\"\n  },\n  \"dependencies\": {\n    \"@babel/runtime\": \"^7.10.1\",\n    \"@rc-component/motion\": \"^1.1.4\",\n    \"@rc-component/util\": \"^1.3.0\",\n    \"clsx\": \"^2.1.1\"\n  },\n  \"devDependencies\": {\n    \"@rc-component/father-plugin\": \"^2.0.1\",\n    \"@rc-component/np\": \"^1.0.4\",\n    \"@testing-library/jest-dom\": \"^6.1.4\",\n    \"@testing-library/react\": \"^16.3.0\",\n    \"@types/jest\": \"^29.4.0\",\n    \"@types/node\": \"^24.2.0\",\n    \"@types/react\": \"^19.1.4\",\n    \"@types/react-dom\": \"^19.1.5\",\n    \"@umijs/fabric\": \"^4.0.0\",\n    \"dumi\": \"^2.1.1\",\n    \"eslint\": \"^8.55.0\",\n    \"eslint-plugin-jest\": \"^29.0.1\",\n    \"eslint-plugin-unicorn\": \"^49.0.0\",\n    \"father\": \"^4.1.3\",\n    \"gh-pages\": \"^6.2.0\",\n    \"husky\": \"^9.0.0\",\n    \"jest\": \"^30.0.3\",\n    \"less\": \"^4.2.0\",\n    \"lint-staged\": \"^16.0.0\",\n    \"prettier\": \"^3.0.3\",\n    \"rc-test\": \"^7.0.14\",\n    \"react\": \"^19.1.0\",\n    \"react-dom\": \"^19.1.0\",\n    \"typescript\": \"^5.0.0\"\n  },\n  \"peerDependencies\": {\n    \"react\": \">=18.0.0\",\n    \"react-dom\": \">=18.0.0\"\n  }\n}\n"
  },
  {
    "path": "src/Collapse.tsx",
    "content": "import { clsx } from 'clsx';\nimport { useControlledState, useEvent } from '@rc-component/util';\nimport warning from '@rc-component/util/lib/warning';\nimport React from 'react';\nimport useItems from './hooks/useItems';\nimport type { CollapseProps } from './interface';\nimport CollapsePanel from './Panel';\nimport pickAttrs from '@rc-component/util/lib/pickAttrs';\n\nfunction getActiveKeysArray(activeKey: React.Key | React.Key[]): React.Key[] {\n  let currentActiveKey = activeKey;\n  if (!Array.isArray(currentActiveKey)) {\n    const activeKeyType = typeof currentActiveKey;\n    currentActiveKey =\n      activeKeyType === 'number' || activeKeyType === 'string' ? [currentActiveKey] : [];\n  }\n  return currentActiveKey.map((key) => String(key));\n}\n\nconst Collapse = React.forwardRef<HTMLDivElement, CollapseProps>((props, ref) => {\n  const {\n    prefixCls = 'rc-collapse',\n    destroyOnHidden = false,\n    style,\n    accordion,\n    className,\n    children,\n    collapsible,\n    openMotion,\n    expandIcon,\n    activeKey: rawActiveKey,\n    defaultActiveKey,\n    onChange,\n    items,\n    classNames: customizeClassNames,\n    styles,\n  } = props;\n\n  const collapseClassName = clsx(prefixCls, className);\n\n  const [internalActiveKey, setActiveKey] = useControlledState<React.Key[] | React.Key>(\n    defaultActiveKey,\n    rawActiveKey,\n  );\n\n  const activeKey = getActiveKeysArray(internalActiveKey);\n\n  const triggerActiveKey = useEvent((next) => {\n    const nextKeys = getActiveKeysArray(next);\n    setActiveKey(nextKeys);\n    onChange?.(nextKeys);\n  });\n\n  const onItemClick = (key: React.Key) => {\n    if (accordion) {\n      triggerActiveKey(activeKey[0] === key ? [] : [key]);\n    } else {\n      triggerActiveKey(\n        activeKey.includes(key) ? activeKey.filter((item) => item !== key) : [...activeKey, key],\n      );\n    }\n  };\n\n  // ======================== Children ========================\n  warning(\n    !children,\n    '[rc-collapse] `children` will be removed in next major version. Please use `items` instead.',\n  );\n\n  const mergedChildren = useItems(items, children, {\n    prefixCls,\n    accordion,\n    openMotion,\n    expandIcon,\n    collapsible,\n    destroyOnHidden,\n    onItemClick,\n    activeKey,\n    classNames: customizeClassNames,\n    styles,\n  });\n\n  // ======================== Render ========================\n  return (\n    <div\n      ref={ref}\n      className={collapseClassName}\n      style={style}\n      role={accordion ? 'tablist' : undefined}\n      {...pickAttrs(props, { aria: true, data: true })}\n    >\n      {mergedChildren}\n    </div>\n  );\n});\n\nexport default Object.assign(Collapse, {\n  /**\n   * @deprecated use `items` instead, will be removed in `v4.0.0`\n   */\n  Panel: CollapsePanel,\n});\n"
  },
  {
    "path": "src/Panel.tsx",
    "content": "import { clsx } from 'clsx';\nimport CSSMotion from '@rc-component/motion';\nimport KeyCode from '@rc-component/util/lib/KeyCode';\nimport React from 'react';\nimport type { CollapsePanelProps } from './interface';\nimport PanelContent from './PanelContent';\n\nconst CollapsePanel = React.forwardRef<HTMLDivElement, CollapsePanelProps>((props, ref) => {\n  const {\n    showArrow = true,\n    headerClass,\n    isActive,\n    onItemClick,\n    forceRender,\n    className,\n    classNames: customizeClassNames = {},\n    styles = {},\n    prefixCls,\n    collapsible,\n    accordion,\n    panelKey,\n    extra,\n    header,\n    expandIcon,\n    openMotion,\n    destroyOnHidden,\n    children,\n    ...resetProps\n  } = props;\n\n  const disabled = collapsible === 'disabled';\n\n  const ifExtraExist = extra !== null && extra !== undefined && typeof extra !== 'boolean';\n\n  const collapsibleProps = {\n    onClick: () => {\n      onItemClick?.(panelKey);\n    },\n    onKeyDown: (e: React.KeyboardEvent) => {\n      if (e.key === 'Enter' || e.keyCode === KeyCode.ENTER || e.which === KeyCode.ENTER) {\n        onItemClick?.(panelKey);\n      }\n    },\n    role: accordion ? 'tab' : 'button',\n    ['aria-expanded']: isActive,\n    ['aria-disabled']: disabled,\n    tabIndex: disabled ? -1 : 0,\n  };\n\n  // ======================== Icon ========================\n  const iconNodeInner =\n    typeof expandIcon === 'function' ? expandIcon(props) : <i className=\"arrow\" />;\n  const iconNode = iconNodeInner && (\n    <div\n      className={clsx(`${prefixCls}-expand-icon`, customizeClassNames?.icon)}\n      style={styles?.icon}\n      {...(['header', 'icon'].includes(collapsible) ? collapsibleProps : {})}\n    >\n      {iconNodeInner}\n    </div>\n  );\n\n  const collapsePanelClassNames = clsx(\n    `${prefixCls}-item`,\n    {\n      [`${prefixCls}-item-active`]: isActive,\n      [`${prefixCls}-item-disabled`]: disabled,\n    },\n    className,\n  );\n\n  const headerClassName = clsx(\n    headerClass,\n    `${prefixCls}-header`,\n    {\n      [`${prefixCls}-collapsible-${collapsible}`]: !!collapsible,\n    },\n    customizeClassNames?.header,\n  );\n\n  // ======================== HeaderProps ========================\n  const headerProps: React.HTMLAttributes<HTMLDivElement> = {\n    className: headerClassName,\n    style: styles?.header,\n    ...(['header', 'icon'].includes(collapsible) ? {} : collapsibleProps),\n  };\n\n  // ======================== Render ========================\n  return (\n    <div {...resetProps} ref={ref} className={collapsePanelClassNames}>\n      <div {...headerProps}>\n        {showArrow && iconNode}\n        <span\n          className={clsx(`${prefixCls}-title`, customizeClassNames?.title)}\n          style={styles?.title}\n          {...(collapsible === 'header' ? collapsibleProps : {})}\n        >\n          {header}\n        </span>\n        {ifExtraExist && <div className={`${prefixCls}-extra`}>{extra}</div>}\n      </div>\n      <CSSMotion\n        visible={isActive}\n        leavedClassName={`${prefixCls}-panel-hidden`}\n        {...openMotion}\n        forceRender={forceRender}\n        removeOnLeave={destroyOnHidden}\n      >\n        {({ className: motionClassName, style: motionStyle }, motionRef) => {\n          return (\n            <PanelContent\n              ref={motionRef}\n              prefixCls={prefixCls}\n              className={motionClassName}\n              classNames={customizeClassNames}\n              style={motionStyle}\n              styles={styles}\n              isActive={isActive}\n              forceRender={forceRender}\n              role={accordion ? 'tabpanel' : undefined}\n            >\n              {children}\n            </PanelContent>\n          );\n        }}\n      </CSSMotion>\n    </div>\n  );\n});\n\nexport default CollapsePanel;\n"
  },
  {
    "path": "src/PanelContent.tsx",
    "content": "import { clsx } from 'clsx';\nimport React from 'react';\nimport type { CollapsePanelProps } from './interface';\n\nconst PanelContent = React.forwardRef<\n  HTMLDivElement,\n  React.PropsWithChildren<Readonly<CollapsePanelProps>>\n>((props, ref) => {\n  const {\n    prefixCls,\n    forceRender,\n    className,\n    style,\n    children,\n    isActive,\n    role,\n    classNames: customizeClassNames,\n    styles,\n  } = props;\n\n  const [rendered, setRendered] = React.useState(isActive || forceRender);\n\n  React.useEffect(() => {\n    if (forceRender || isActive) {\n      setRendered(true);\n    }\n  }, [forceRender, isActive]);\n\n  if (!rendered) {\n    return null;\n  }\n\n  return (\n    <div\n      ref={ref}\n      className={clsx(\n        `${prefixCls}-panel`,\n        {\n          [`${prefixCls}-panel-active`]: isActive,\n          [`${prefixCls}-panel-inactive`]: !isActive,\n        },\n        className,\n      )}\n      style={style}\n      role={role}\n    >\n      <div className={clsx(`${prefixCls}-body`, customizeClassNames?.body)} style={styles?.body}>\n        {children}\n      </div>\n    </div>\n  );\n});\n\nif (process.env.NODE_ENV !== 'production') {\n  PanelContent.displayName = 'PanelContent';\n}\n\nexport default PanelContent;\n"
  },
  {
    "path": "src/hooks/useItems.tsx",
    "content": "import toArray from '@rc-component/util/lib/Children/toArray';\nimport React from 'react';\nimport type { CollapsePanelProps, CollapseProps, ItemType } from '../interface';\nimport CollapsePanel from '../Panel';\nimport clsx from 'clsx';\n\ntype Props = Pick<\n  CollapsePanelProps,\n  'prefixCls' | 'onItemClick' | 'openMotion' | 'expandIcon' | 'classNames' | 'styles'\n> &\n  Pick<CollapseProps, 'accordion' | 'collapsible' | 'destroyOnHidden'> & {\n    activeKey: React.Key[];\n  };\n\nfunction mergeSemantic<T>(src: T, tgt: T, mergeFn: (a: any, b: any) => any) {\n  if (!src || !tgt) {\n    return src || tgt;\n  }\n\n  const keys = Array.from(new Set([...Object.keys(src), ...Object.keys(tgt)]));\n  const result = {};\n  keys.forEach((key) => {\n    result[key] = mergeFn(src[key], tgt[key]);\n  });\n  return result;\n}\n\nfunction mergeSemanticClassNames<T>(src: T, tgt: T) {\n  return mergeSemantic(src, tgt, (a: string, b: string) => clsx(a, b));\n}\n\nfunction mergeSemanticStyles<T>(src: T, tgt: T) {\n  return mergeSemantic(src, tgt, (a: React.CSSProperties, b: React.CSSProperties) => ({\n    ...a,\n    ...b,\n  }));\n}\n\nconst convertItemsToNodes = (items: ItemType[], props: Props) => {\n  const {\n    prefixCls,\n    accordion,\n    collapsible,\n    destroyOnHidden,\n    onItemClick,\n    activeKey,\n    openMotion,\n    expandIcon,\n    classNames: collapseClassNames,\n    styles: collapseStyles,\n  } = props;\n\n  return items.map((item, index) => {\n    const {\n      children,\n      label,\n      key: rawKey,\n      collapsible: rawCollapsible,\n      onItemClick: rawOnItemClick,\n      destroyOnHidden: rawDestroyOnHidden,\n      classNames,\n      styles,\n      ...restProps\n    } = item;\n\n    // You may be puzzled why you want to convert them all into strings, me too.\n    // Maybe: https://github.com/react-component/collapse/blob/aac303a8b6ff30e35060b4f8fecde6f4556fcbe2/src/Collapse.tsx#L15\n    const key = String(rawKey ?? index);\n    const mergeCollapsible = rawCollapsible ?? collapsible;\n    const mergedDestroyOnHidden = rawDestroyOnHidden ?? destroyOnHidden;\n\n    const handleItemClick = (value: React.Key) => {\n      if (mergeCollapsible === 'disabled') {\n        return;\n      }\n      onItemClick(value);\n      rawOnItemClick?.(value);\n    };\n\n    let isActive = false;\n    if (accordion) {\n      isActive = activeKey[0] === key;\n    } else {\n      isActive = activeKey.indexOf(key) > -1;\n    }\n\n    return (\n      <CollapsePanel\n        {...restProps}\n        classNames={mergeSemanticClassNames(collapseClassNames, classNames)}\n        styles={mergeSemanticStyles(collapseStyles, styles)}\n        prefixCls={prefixCls}\n        key={key}\n        panelKey={key}\n        isActive={isActive}\n        accordion={accordion}\n        openMotion={openMotion}\n        expandIcon={expandIcon}\n        header={label}\n        collapsible={mergeCollapsible}\n        onItemClick={handleItemClick}\n        destroyOnHidden={mergedDestroyOnHidden}\n      >\n        {children}\n      </CollapsePanel>\n    );\n  });\n};\n\n/**\n * @deprecated The next major version will be removed\n */\nconst getNewChild = (\n  child: React.ReactElement<CollapsePanelProps>,\n  index: number,\n  props: Props,\n) => {\n  if (!child) {\n    return null;\n  }\n\n  const {\n    prefixCls,\n    accordion,\n    collapsible,\n    destroyOnHidden,\n    onItemClick,\n    activeKey,\n    openMotion,\n    expandIcon,\n    classNames: collapseClassNames,\n    styles,\n  } = props;\n\n  const key = child.key || String(index);\n\n  const {\n    header,\n    headerClass,\n    destroyOnHidden: childDestroyOnHidden,\n    collapsible: childCollapsible,\n    onItemClick: childOnItemClick,\n  } = child.props;\n\n  let isActive = false;\n  if (accordion) {\n    isActive = activeKey[0] === key;\n  } else {\n    isActive = activeKey.indexOf(key) > -1;\n  }\n\n  const mergeCollapsible = childCollapsible ?? collapsible;\n\n  const handleItemClick = (value: React.Key) => {\n    if (mergeCollapsible === 'disabled') {\n      return;\n    }\n    onItemClick(value);\n    childOnItemClick?.(value);\n  };\n\n  const childProps = {\n    key,\n    panelKey: key,\n    header,\n    headerClass,\n    classNames: collapseClassNames,\n    styles,\n    isActive,\n    prefixCls,\n    destroyOnHidden: childDestroyOnHidden ?? destroyOnHidden,\n    openMotion,\n    accordion,\n    children: child.props.children,\n    onItemClick: handleItemClick,\n    expandIcon,\n    collapsible: mergeCollapsible,\n  };\n\n  // https://github.com/ant-design/ant-design/issues/20479\n  if (typeof child.type === 'string') {\n    return child;\n  }\n\n  Object.keys(childProps).forEach((propName) => {\n    if (typeof childProps[propName] === 'undefined') {\n      delete childProps[propName];\n    }\n  });\n\n  return React.cloneElement<CollapsePanelProps>(child, childProps);\n};\n\nfunction useItems(\n  items?: ItemType[],\n  rawChildren?: React.ReactNode,\n  props?: Props,\n): React.ReactElement<CollapsePanelProps>[] {\n  if (Array.isArray(items)) {\n    return convertItemsToNodes(items, props);\n  }\n  return toArray(rawChildren).map((child, index) =>\n    getNewChild(child as React.ReactElement<CollapsePanelProps>, index, props),\n  );\n}\n\nexport default useItems;\n"
  },
  {
    "path": "src/index.tsx",
    "content": "import Collapse from './Collapse';\n\nexport type { CollapsePanelProps, CollapseProps } from './interface';\n\nexport default Collapse;\n\n/**\n * @deprecated use `items` instead, will be removed in `v4.0.0`\n */\nexport const { Panel } = Collapse;\n"
  },
  {
    "path": "src/interface.ts",
    "content": "import type { CSSMotionProps } from '@rc-component/motion';\nimport type * as React from 'react';\n\nexport type CollapsibleType = 'header' | 'icon' | 'disabled';\n\nexport interface ItemType\n  extends Omit<\n    CollapsePanelProps,\n    | 'header' // alias of label\n    | 'prefixCls'\n    | 'panelKey' // alias of key\n    | 'isActive'\n    | 'accordion'\n    | 'openMotion'\n    | 'expandIcon'\n  > {\n  key?: CollapsePanelProps['panelKey'];\n  label?: CollapsePanelProps['header'];\n  ref?: React.RefObject<HTMLDivElement>;\n}\n\nexport interface CollapseProps {\n  prefixCls?: string;\n  activeKey?: React.Key | React.Key[];\n  defaultActiveKey?: React.Key | React.Key[];\n  openMotion?: CSSMotionProps;\n  onChange?: (key: React.Key[]) => void;\n  accordion?: boolean;\n  className?: string;\n  style?: object;\n  destroyOnHidden?: boolean;\n  expandIcon?: (props: object) => React.ReactNode;\n  collapsible?: CollapsibleType;\n  children?: React.ReactNode;\n  /**\n   * Collapse items content\n   * @since 3.6.0\n   */\n  items?: ItemType[];\n  classNames?: Partial<Record<SemanticName, string>>;\n  styles?: Partial<Record<SemanticName, React.CSSProperties>>;\n}\n\nexport type SemanticName = 'header' | 'title' | 'body' | 'icon';\n\nexport interface CollapsePanelProps extends React.DOMAttributes<HTMLDivElement> {\n  id?: string;\n  header?: React.ReactNode;\n  prefixCls?: string;\n  headerClass?: string;\n  showArrow?: boolean;\n  className?: string;\n  classNames?: Partial<Record<SemanticName, string>>;\n  style?: object;\n  styles?: Partial<Record<SemanticName, React.CSSProperties>>;\n  isActive?: boolean;\n  openMotion?: CSSMotionProps;\n  destroyOnHidden?: boolean;\n  accordion?: boolean;\n  forceRender?: boolean;\n  extra?: React.ReactNode;\n  onItemClick?: (panelKey: React.Key) => void;\n  expandIcon?: (props: object) => React.ReactNode;\n  panelKey?: React.Key;\n  role?: string;\n  collapsible?: CollapsibleType;\n  children?: React.ReactNode;\n}\n"
  },
  {
    "path": "tests/__snapshots__/index.spec.tsx.snap",
    "content": "// Jest Snapshot v1, https://goo.gl/fbAQLP\n\nexports[`collapse props items should work with nested 1`] = `\n<div\n  class=\"rc-collapse\"\n>\n  <div\n    class=\"rc-collapse-item rc-collapse-item-disabled\"\n  >\n    <div\n      aria-disabled=\"true\"\n      aria-expanded=\"false\"\n      class=\"rc-collapse-header rc-collapse-collapsible-disabled\"\n      role=\"button\"\n      tabindex=\"-1\"\n    >\n      <div\n        class=\"rc-collapse-expand-icon\"\n      >\n        <i\n          class=\"arrow\"\n        />\n      </div>\n      <span\n        class=\"rc-collapse-title\"\n      >\n        collapse 1\n      </span>\n    </div>\n  </div>\n  <div\n    class=\"rc-collapse-item\"\n  >\n    <div\n      aria-disabled=\"false\"\n      aria-expanded=\"false\"\n      class=\"rc-collapse-header\"\n      role=\"button\"\n      tabindex=\"0\"\n    >\n      <div\n        class=\"rc-collapse-expand-icon\"\n      >\n        <i\n          class=\"arrow\"\n        />\n      </div>\n      <span\n        class=\"rc-collapse-title\"\n      >\n        collapse 2\n      </span>\n      <div\n        class=\"rc-collapse-extra\"\n      >\n        <span>\n          ExtraSpan\n        </span>\n      </div>\n    </div>\n  </div>\n  <div\n    class=\"rc-collapse-item important\"\n  >\n    <div\n      aria-disabled=\"false\"\n      aria-expanded=\"false\"\n      class=\"rc-collapse-header\"\n      role=\"button\"\n      tabindex=\"0\"\n    >\n      <div\n        class=\"rc-collapse-expand-icon\"\n      >\n        <i\n          class=\"arrow\"\n        />\n      </div>\n      <span\n        class=\"rc-collapse-title\"\n      >\n        collapse 3\n      </span>\n    </div>\n  </div>\n  <div\n    class=\"rc-collapse-item\"\n  >\n    <div\n      aria-disabled=\"false\"\n      aria-expanded=\"false\"\n      class=\"rc-collapse-header\"\n      role=\"button\"\n      tabindex=\"0\"\n    >\n      <div\n        class=\"rc-collapse-expand-icon\"\n      >\n        <i\n          class=\"arrow\"\n        />\n      </div>\n      <span\n        class=\"rc-collapse-title\"\n      >\n        title 3\n      </span>\n    </div>\n  </div>\n</div>\n`;\n"
  },
  {
    "path": "tests/index.spec.tsx",
    "content": "import type { RenderResult } from '@testing-library/react';\nimport { fireEvent, render } from '@testing-library/react';\nimport KeyCode from '@rc-component/util/lib/KeyCode';\nimport React, { Fragment } from 'react';\nimport Collapse, { Panel } from '../src/index';\nimport type { CollapseProps, ItemType } from '../src/interface';\n\ndescribe('collapse', () => {\n  let changeHook: jest.Mock<any, any> | null;\n\n  beforeEach(() => {\n    jest.useFakeTimers();\n  });\n\n  afterEach(() => {\n    jest.useRealTimers();\n    changeHook = null;\n  });\n\n  function onChange(...args: any[]) {\n    if (changeHook) {\n      // eslint-disable-next-line @typescript-eslint/no-invalid-this\n      changeHook.apply(this, args);\n    }\n  }\n\n  function runNormalTest(element: any) {\n    let collapse: RenderResult;\n\n    beforeEach(() => {\n      collapse = render(element);\n    });\n\n    afterEach(() => {\n      collapse.unmount();\n    });\n\n    it('add className', () => {\n      const expectedClassName = 'rc-collapse-item important';\n      expect(collapse.container.querySelectorAll('.rc-collapse-item')?.[2]).toHaveClass(\n        expectedClassName,\n      );\n    });\n\n    it('create works', () => {\n      expect(collapse.container.querySelectorAll('.rc-collapse')).toHaveLength(1);\n    });\n\n    it('header works', () => {\n      expect(collapse.container.querySelectorAll('.rc-collapse-header')).toHaveLength(3);\n    });\n\n    it('panel works', () => {\n      expect(collapse.container.querySelectorAll('.rc-collapse-item')).toHaveLength(3);\n      expect(collapse.container.querySelectorAll('.rc-collapse-panel')).toHaveLength(0);\n    });\n\n    it('should render custom arrow icon correctly', () => {\n      expect(collapse.container.querySelector('.rc-collapse-header')?.textContent).toContain(\n        'test>',\n      );\n    });\n\n    it('default active works', () => {\n      expect(collapse.container.querySelectorAll('.rc-collapse-item-active').length).toBeFalsy();\n    });\n\n    it('extra works', () => {\n      const extraNodes = collapse.container.querySelectorAll('.rc-collapse-extra');\n      expect(extraNodes).toHaveLength(1);\n      expect(extraNodes?.[0]?.innerHTML).toBe('<span>ExtraSpan</span>');\n    });\n\n    it('onChange works', () => {\n      changeHook = jest.fn();\n      const header = collapse.container.querySelectorAll('.rc-collapse-header')?.[1];\n      fireEvent.click(header);\n      expect(changeHook.mock.calls[0][0]).toEqual(['2']);\n    });\n\n    it('click should toggle panel state', () => {\n      const header = collapse.container.querySelectorAll('.rc-collapse-header')?.[1];\n      fireEvent.click(header);\n      jest.runAllTimers();\n      expect(collapse.container.querySelectorAll('.rc-collapse-panel-active')).toHaveLength(1);\n      fireEvent.click(header);\n      jest.runAllTimers();\n      expect(collapse.container.querySelector('.rc-collapse-panel-inactive')?.innerHTML).toBe(\n        '<div class=\"rc-collapse-body\">second</div>',\n      );\n      expect(collapse.container.querySelectorAll('.rc-collapse-panel-active').length).toBeFalsy();\n    });\n\n    it('click should not toggle disabled panel state', () => {\n      const header = collapse.container.querySelector('.rc-collapse-header');\n      expect(header).toBeTruthy();\n      fireEvent.click(header!);\n      jest.runAllTimers();\n      expect(collapse.container.querySelectorAll('.rc-collapse-panel-active').length).toBeFalsy();\n    });\n\n    it('should not have role', () => {\n      const item = collapse.container.querySelector('.rc-collapse');\n      expect(item).toBeTruthy();\n      expect(item!.getAttribute('role')).toBe(null);\n    });\n\n    it('should set button role on panel title', () => {\n      const item = collapse.container.querySelector('.rc-collapse-header');\n      expect(item).toBeTruthy();\n      expect(item!.getAttribute('role')).toBe('button');\n    });\n  }\n\n  describe('collapse', () => {\n    const expandIcon = () => <span>test{'>'}</span>;\n\n    const element = (\n      <Collapse onChange={onChange} expandIcon={expandIcon}>\n        <Panel header=\"collapse 1\" key=\"1\" collapsible=\"disabled\">\n          first\n        </Panel>\n        <Panel header=\"collapse 2\" key=\"2\" extra={<span>ExtraSpan</span>}>\n          second\n        </Panel>\n        <Panel header=\"collapse 3\" key=\"3\" className=\"important\">\n          third\n        </Panel>\n      </Collapse>\n    );\n\n    runNormalTest(element);\n\n    it('controlled', () => {\n      const onChangeSpy = jest.fn();\n\n      const ControlledCollapse = () => {\n        const [activeKey, updateActiveKey] = React.useState<React.Key[] | React.Key>(['2']);\n\n        const handleChange: CollapseProps['onChange'] = (key) => {\n          updateActiveKey(key);\n          onChangeSpy(key);\n        };\n\n        return (\n          <Collapse onChange={handleChange} activeKey={activeKey}>\n            <Panel header=\"collapse 1\" key=\"1\">\n              first\n            </Panel>\n            <Panel header=\"collapse 2\" key=\"2\">\n              second\n            </Panel>\n            <Panel header=\"collapse 3\" key=\"3\">\n              third\n            </Panel>\n          </Collapse>\n        );\n      };\n\n      const { container } = render(<ControlledCollapse />);\n\n      expect(container.querySelectorAll('.rc-collapse-panel-active')).toHaveLength(1);\n      const header = container.querySelector('.rc-collapse-header');\n      expect(header).toBeTruthy();\n      fireEvent.click(header!);\n      jest.runAllTimers();\n      expect(container.querySelectorAll('.rc-collapse-panel-active')).toHaveLength(2);\n      expect(onChangeSpy).toBeCalledWith(['2', '1']);\n    });\n  });\n\n  describe('it should support number key', () => {\n    const expandIcon = () => <span>test{'>'}</span>;\n    const element = (\n      <Collapse onChange={onChange} expandIcon={expandIcon}>\n        <Panel header=\"collapse 1\" key={1} collapsible=\"disabled\">\n          first\n        </Panel>\n        <Panel header=\"collapse 2\" key={2} extra={<span>ExtraSpan</span>}>\n          second\n        </Panel>\n        <Panel header=\"collapse 3\" key={3} className=\"important\">\n          third\n        </Panel>\n      </Collapse>\n    );\n\n    runNormalTest(element);\n  });\n\n  describe('prop: headerClass', () => {\n    it('applies the passed headerClass to the header', () => {\n      const element = (\n        <Collapse onChange={onChange}>\n          <Panel header=\"collapse 1\" key=\"1\" headerClass=\"custom-class\">\n            first\n          </Panel>\n        </Collapse>\n      );\n\n      const { container } = render(element);\n      const header = container.querySelector('.rc-collapse-header');\n\n      expect(header?.classList.contains('custom-class')).toBeTruthy();\n    });\n  });\n\n  it('should support extra whit number 0', () => {\n    const { container } = render(\n      <Collapse onChange={onChange} activeKey={0}>\n        <Panel header=\"collapse 0\" key={0} extra={0}>\n          zero\n        </Panel>\n      </Collapse>,\n    );\n\n    const extraNodes = container.querySelectorAll('.rc-collapse-extra');\n    expect(extraNodes).toHaveLength(1);\n    expect(extraNodes[0].innerHTML).toBe('0');\n  });\n\n  it('should support activeKey number 0', () => {\n    const { container } = render(\n      <Collapse onChange={onChange} activeKey={0}>\n        <Panel header=\"collapse 0\" key={0}>\n          zero\n        </Panel>\n        <Panel header=\"collapse 1\" key={1}>\n          first\n        </Panel>\n        <Panel header=\"collapse 2\" key={2}>\n          second\n        </Panel>\n      </Collapse>,\n    );\n\n    // activeKey number 0, should open one item\n    expect(container.querySelectorAll('.rc-collapse-panel-active')).toHaveLength(1);\n  });\n\n  it('click should toggle panel state', () => {\n    const { container } = render(\n      <Collapse onChange={onChange} destroyOnHidden>\n        <Panel header=\"collapse 1\" key=\"1\">\n          first\n        </Panel>\n        <Panel header=\"collapse 2\" key=\"2\">\n          second\n        </Panel>\n        <Panel header=\"collapse 3\" key=\"3\" className=\"important\">\n          third\n        </Panel>\n      </Collapse>,\n    );\n\n    const header = container.querySelectorAll('.rc-collapse-header')?.[1];\n    fireEvent.click(header);\n    expect(container.querySelectorAll('.rc-collapse-panel-active')).toHaveLength(1);\n    fireEvent.click(header);\n    expect(container.querySelectorAll('.rc-collapse-panel-inactive').length).toBeFalsy();\n  });\n\n  function runAccordionTest(element: React.ReactElement) {\n    let collapse: RenderResult;\n\n    beforeEach(() => {\n      collapse = render(element);\n    });\n\n    afterEach(() => {\n      collapse.unmount();\n    });\n\n    it('accordion content, should default open zero item', () => {\n      expect(collapse.container.querySelectorAll('.rc-collapse-panel-active')).toHaveLength(0);\n    });\n\n    it('accordion item, should default open zero item', () => {\n      expect(collapse.container.querySelectorAll('.rc-collapse-item-active')).toHaveLength(0);\n    });\n\n    it('should toggle show on panel', () => {\n      let header = collapse.container.querySelectorAll('.rc-collapse-header')?.[1];\n      fireEvent.click(header);\n      jest.runAllTimers();\n      expect(collapse.container.querySelectorAll('.rc-collapse-panel-active')).toHaveLength(1);\n      expect(collapse.container.querySelectorAll('.rc-collapse-item-active')).toHaveLength(1);\n      header = collapse.container.querySelectorAll('.rc-collapse-header')?.[1];\n      fireEvent.click(header);\n      jest.runAllTimers();\n      expect(collapse.container.querySelectorAll('.rc-collapse-panel-active')).toHaveLength(0);\n      expect(collapse.container.querySelectorAll('.rc-collapse-item-active')).toHaveLength(0);\n    });\n\n    it('should only show on panel', () => {\n      let header = collapse.container.querySelector('.rc-collapse-header');\n      expect(header).toBeTruthy();\n      fireEvent.click(header!);\n      jest.runAllTimers();\n      expect(collapse.container.querySelectorAll('.rc-collapse-panel-active')).toHaveLength(1);\n      expect(collapse.container.querySelectorAll('.rc-collapse-item-active')).toHaveLength(1);\n      header = collapse.container.querySelectorAll('.rc-collapse-header')?.[2];\n      fireEvent.click(header);\n      jest.runAllTimers();\n      expect(collapse.container.querySelectorAll('.rc-collapse-panel-active')).toHaveLength(1);\n      expect(collapse.container.querySelectorAll('.rc-collapse-item-active')).toHaveLength(1);\n    });\n\n    it('should add tab role on panel title', () => {\n      const item = collapse.container.querySelector('.rc-collapse-header');\n      expect(item).toBeTruthy();\n      expect(item!.getAttribute('role')).toBe('tab');\n    });\n\n    it('should add tablist role on accordion', () => {\n      const item = collapse.container.querySelector('.rc-collapse');\n      expect(item).toBeTruthy();\n      expect(item!.getAttribute('role')).toBe('tablist');\n    });\n\n    it('should add tablist role on PanelContent', () => {\n      const header = collapse.container.querySelector('.rc-collapse-header');\n      expect(header).toBeTruthy();\n      fireEvent.click(header!);\n      const item = collapse.container.querySelector('.rc-collapse-panel');\n      expect(item).toBeTruthy();\n      expect(item!.getAttribute('role')).toBe('tabpanel');\n    });\n  }\n\n  describe('prop: accordion', () => {\n    runAccordionTest(\n      <Collapse onChange={onChange} accordion>\n        <Panel header=\"collapse 1\" key=\"1\">\n          first\n        </Panel>\n        <Panel header=\"collapse 2\" key=\"2\">\n          second\n        </Panel>\n        <Panel header=\"collapse 3\" key=\"3\">\n          third\n        </Panel>\n      </Collapse>,\n    );\n  });\n\n  describe('forceRender', () => {\n    it('when forceRender is not supplied it should lazy render the panel content', () => {\n      const { container } = render(\n        <Collapse>\n          <Panel header=\"collapse 1\" key=\"1\" collapsible=\"disabled\">\n            first\n          </Panel>\n          <Panel header=\"collapse 2\" key=\"2\">\n            second\n          </Panel>\n        </Collapse>,\n      );\n      expect(container.querySelectorAll('.rc-collapse-panel')).toHaveLength(0);\n    });\n\n    it('when forceRender is FALSE it should lazy render the panel content', () => {\n      const { container } = render(\n        <Collapse>\n          <Panel header=\"collapse 1\" key=\"1\" forceRender={false} collapsible=\"disabled\">\n            first\n          </Panel>\n          <Panel header=\"collapse 2\" key=\"2\">\n            second\n          </Panel>\n        </Collapse>,\n      );\n      expect(container.querySelectorAll('.rc-collapse-panel')).toHaveLength(0);\n    });\n\n    it('when forceRender is TRUE then it should render all the panel content to the DOM', () => {\n      const { container } = render(\n        <Collapse>\n          <Panel header=\"collapse 1\" key=\"1\" forceRender collapsible=\"disabled\">\n            first\n          </Panel>\n          <Panel header=\"collapse 2\" key=\"2\">\n            second\n          </Panel>\n        </Collapse>,\n      );\n\n      jest.runAllTimers();\n\n      expect(container.querySelectorAll('.rc-collapse-panel')).toHaveLength(1);\n      expect(container.querySelectorAll('.rc-collapse-panel-active')).toHaveLength(0);\n      const inactiveDom = container.querySelector('div.rc-collapse-panel-inactive');\n      expect(inactiveDom).not.toBeFalsy();\n      expect(getComputedStyle(inactiveDom!)).toHaveProperty('display', 'none');\n    });\n  });\n\n  it('should toggle panel when press enter', () => {\n    const myKeyEvent = {\n      key: 'Enter',\n      keyCode: KeyCode.ENTER,\n      which: KeyCode.ENTER,\n      // https://github.com/testing-library/react-testing-library/issues/269#issuecomment-455854112\n      charCode: KeyCode.ENTER,\n    };\n\n    const { container } = render(\n      <Collapse>\n        <Panel header=\"collapse 1\" key=\"1\">\n          first\n        </Panel>\n        <Panel header=\"collapse 2\" key=\"2\">\n          second\n        </Panel>\n        <Panel header=\"collapse 3\" key=\"3\" collapsible=\"disabled\">\n          third\n        </Panel>\n      </Collapse>,\n    );\n\n    fireEvent.keyDown(container.querySelectorAll('.rc-collapse-header')?.[2], myKeyEvent);\n    jest.runAllTimers();\n    expect(container.querySelectorAll('.rc-collapse-panel-active')).toHaveLength(0);\n\n    fireEvent.keyDown(container.querySelector('.rc-collapse-header')!, myKeyEvent);\n    jest.runAllTimers();\n\n    expect(container.querySelectorAll('.rc-collapse-panel-active')).toHaveLength(1);\n\n    expect(container.querySelector('.rc-collapse-panel')).toHaveClass('rc-collapse-panel-active');\n\n    fireEvent.keyDown(container.querySelector('.rc-collapse-header')!, myKeyEvent);\n    jest.runAllTimers();\n\n    expect(container.querySelectorAll('.rc-collapse-panel-active')).toHaveLength(0);\n    expect(container.querySelector('.rc-collapse-panel')!.className).not.toContain(\n      'rc-collapse-panel-active',\n    );\n  });\n\n  describe('wrapped in Fragment', () => {\n    const expandIcon = () => <span>test{'>'}</span>;\n    const element = (\n      <Collapse onChange={onChange} expandIcon={expandIcon}>\n        <Fragment>\n          <Panel header=\"collapse 1\" key=\"1\" collapsible=\"disabled\">\n            first\n          </Panel>\n          <Panel header=\"collapse 2\" key=\"2\" extra={<span>ExtraSpan</span>}>\n            second\n          </Panel>\n          <Fragment>\n            <Panel header=\"collapse 3\" key=\"3\" className=\"important\">\n              third\n            </Panel>\n          </Fragment>\n        </Fragment>\n      </Collapse>\n    );\n\n    runNormalTest(element);\n  });\n\n  it('should support return null icon', () => {\n    const { container } = render(\n      <Collapse expandIcon={() => null}>\n        <Panel header=\"title\" key=\"1\">\n          first\n        </Panel>\n      </Collapse>,\n    );\n    expect(container.querySelector('.rc-collapse-header')?.childNodes).toHaveLength(1);\n  });\n\n  it('should support custom child', () => {\n    const { container } = render(\n      <Collapse>\n        <Panel header=\"collapse 1\" key=\"1\">\n          first\n        </Panel>\n        <a className=\"custom-child\">custom-child</a>\n      </Collapse>,\n    );\n    expect(container.querySelector('.custom-child')?.innerHTML).toBe('custom-child');\n  });\n\n  // https://github.com/ant-design/ant-design/issues/36327\n  // https://github.com/ant-design/ant-design/issues/6179\n  // https://github.com/react-component/collapse/issues/73#issuecomment-323626120\n  it('should support custom component', () => {\n    const PanelElement = (props) => (\n      <Panel header=\"collapse 1\" {...props}>\n        <p>test</p>\n      </Panel>\n    );\n    const { container } = render(\n      <Collapse defaultActiveKey=\"1\">\n        <PanelElement key=\"1\" />\n        <Panel header=\"collapse 2\" key=\"2\">\n          second\n        </Panel>\n      </Collapse>,\n    );\n\n    expect(container.querySelectorAll('.rc-collapse-panel-active')).toHaveLength(1);\n    expect(container.querySelector('.rc-collapse-panel')).toHaveClass('rc-collapse-panel-active');\n    expect(container.querySelector('.rc-collapse-header')?.textContent).toBe('collapse 1');\n    expect(container.querySelector('.rc-collapse-header')?.querySelectorAll('.arrow')).toHaveLength(\n      1,\n    );\n    fireEvent.click(container.querySelector('.rc-collapse-header')!);\n    expect(container.querySelectorAll('.rc-collapse-panel-active')).toHaveLength(0);\n    expect(container.querySelector('.rc-collapse-panel')).toHaveClass('rc-collapse-panel-inactive');\n  });\n\n  describe('prop: collapsible', () => {\n    it('default', () => {\n      const { container } = render(\n        <Collapse>\n          <Panel header=\"collapse 1\" key=\"1\">\n            first\n          </Panel>\n        </Collapse>,\n      );\n      expect(container.querySelector('.rc-collapse-title')).toBeTruthy();\n      fireEvent.click(container.querySelector('.rc-collapse-header')!);\n      expect(container.querySelectorAll('.rc-collapse-item-active')).toHaveLength(1);\n    });\n    it('should work when value is header', () => {\n      const { container } = render(\n        <Collapse collapsible=\"header\">\n          <Panel header=\"collapse 1\" key=\"1\">\n            first\n          </Panel>\n        </Collapse>,\n      );\n      expect(container.querySelector('.rc-collapse-title')).toBeTruthy();\n      fireEvent.click(container.querySelector('.rc-collapse-header')!);\n      expect(container.querySelectorAll('.rc-collapse-item-active')).toHaveLength(0);\n      fireEvent.click(container.querySelector('.rc-collapse-title')!);\n      expect(container.querySelectorAll('.rc-collapse-item-active')).toHaveLength(1);\n    });\n    it('should work when value is icon', () => {\n      const { container } = render(\n        <Collapse collapsible=\"icon\">\n          <Panel header=\"collapse 1\" key=\"1\">\n            first\n          </Panel>\n        </Collapse>,\n      );\n      expect(container.querySelector('.rc-collapse-expand-icon')).toBeTruthy();\n      fireEvent.click(container.querySelector('.rc-collapse-header')!);\n      expect(container.querySelectorAll('.rc-collapse-item-active')).toHaveLength(0);\n      fireEvent.click(container.querySelector('.rc-collapse-expand-icon')!);\n      expect(container.querySelectorAll('.rc-collapse-item-active')).toHaveLength(1);\n    });\n\n    it('should disabled when value is disabled', () => {\n      const { container } = render(\n        <Collapse collapsible=\"disabled\">\n          <Panel header=\"collapse 1\" key=\"1\">\n            first\n          </Panel>\n        </Collapse>,\n      );\n      expect(container.querySelector('.rc-collapse-title')).toBeTruthy();\n      expect(container.querySelectorAll('.rc-collapse-item-disabled')).toHaveLength(1);\n      fireEvent.click(container.querySelector('.rc-collapse-header')!);\n      expect(container.querySelectorAll('.rc-collapse-item-active')).toHaveLength(0);\n    });\n\n    it('the value of panel should be read first', () => {\n      const { container } = render(\n        <Collapse collapsible=\"header\">\n          <Panel collapsible=\"disabled\" header=\"collapse 1\" key=\"1\">\n            first\n          </Panel>\n        </Collapse>,\n      );\n      expect(container.querySelector('.rc-collapse-title')).toBeTruthy();\n\n      expect(container.querySelectorAll('.rc-collapse-item-disabled')).toHaveLength(1);\n\n      fireEvent.click(container.querySelector('.rc-collapse-header')!);\n      expect(container.querySelectorAll('.rc-collapse-item-active')).toHaveLength(0);\n    });\n\n    it('icon trigger when collapsible equal header', () => {\n      const { container } = render(\n        <Collapse collapsible=\"header\">\n          <Panel header=\"collapse 1\" key=\"1\">\n            first\n          </Panel>\n        </Collapse>,\n      );\n\n      fireEvent.click(container.querySelector('.rc-collapse-header .arrow')!);\n      expect(container.querySelectorAll('.rc-collapse-item-active')).toHaveLength(1);\n    });\n\n    it('header not trigger when collapsible equal icon', () => {\n      const { container } = render(\n        <Collapse collapsible=\"icon\">\n          <Panel header=\"collapse 1\" key=\"1\">\n            first\n          </Panel>\n        </Collapse>,\n      );\n\n      fireEvent.click(container.querySelector('.rc-collapse-title')!);\n      expect(container.querySelectorAll('.rc-collapse-item-active')).toHaveLength(0);\n    });\n  });\n\n  it('!showArrow', () => {\n    const { container } = render(\n      <Collapse>\n        <Panel header=\"collapse 1\" key=\"1\" showArrow={false}>\n          first\n        </Panel>\n      </Collapse>,\n    );\n\n    expect(container.querySelectorAll('.rc-collapse-expand-icon')).toHaveLength(0);\n  });\n\n  it('Panel container dom can set event handler', () => {\n    const clickHandler = jest.fn();\n    const { container } = render(\n      <Collapse defaultActiveKey=\"1\">\n        <Panel header=\"collapse 1\" key=\"1\" onClick={clickHandler}>\n          <div className=\"target\">Click this</div>\n        </Panel>\n      </Collapse>,\n    );\n\n    fireEvent.click(container.querySelector('.target')!);\n    expect(clickHandler).toHaveBeenCalled();\n  });\n\n  it('falsy Panel', () => {\n    const { container } = render(\n      <Collapse>\n        {null}\n        <Panel header=\"collapse 1\" key=\"1\">\n          <p>Panel 1 content</p>\n        </Panel>\n        {0}\n        <Panel header=\"collapse 2\" key=\"2\">\n          <p>Panel 2 content</p>\n        </Panel>\n        {undefined}\n        {false}\n        {true}\n      </Collapse>,\n    );\n\n    expect(container.querySelectorAll('.rc-collapse-item')).toHaveLength(2);\n  });\n\n  it('ref should work', () => {\n    const ref = React.createRef<any>();\n    const panelRef = React.createRef<any>();\n    const { container } = render(\n      <Collapse ref={ref}>\n        <Panel header=\"collapse 1\" key=\"1\" ref={panelRef}>\n          first\n        </Panel>\n      </Collapse>,\n    );\n    expect(ref.current).toBe(container.firstChild);\n    expect(panelRef.current).toBe(container.querySelector('.rc-collapse-item'));\n  });\n\n  // https://github.com/react-component/collapse/issues/235\n  it('onItemClick should work', () => {\n    const onItemClick = jest.fn();\n    const { container } = render(\n      <Collapse>\n        <Panel header=\"collapse 1\" key=\"1\" onItemClick={onItemClick}>\n          first\n        </Panel>\n      </Collapse>,\n    );\n    fireEvent.click(container.querySelector('.rc-collapse-header')!);\n    expect(onItemClick).toHaveBeenCalled();\n  });\n\n  it('onItemClick should not work when collapsible is disabled', () => {\n    const onItemClick = jest.fn();\n    const { container } = render(\n      <Collapse collapsible=\"disabled\">\n        <Panel header=\"collapse 1\" key=\"1\" onItemClick={onItemClick}>\n          first\n        </Panel>\n      </Collapse>,\n    );\n    fireEvent.click(container.querySelector('.rc-collapse-header')!);\n    expect(onItemClick).not.toHaveBeenCalled();\n  });\n\n  it('panel style should work', () => {\n    const { container } = render(\n      <Collapse>\n        <Panel header=\"collapse 1\" key=\"1\" style={{ color: 'red' }}>\n          first\n        </Panel>\n      </Collapse>,\n    );\n    expect(container.querySelector('.rc-collapse-item')).toHaveStyle({ color: 'red' });\n  });\n\n  describe('props items', () => {\n    const items: ItemType[] = [\n      {\n        key: '1',\n        label: 'collapse 1',\n        children: 'first',\n        collapsible: 'disabled',\n      },\n      {\n        key: '2',\n        label: 'collapse 2',\n        children: 'second',\n        extra: <span>ExtraSpan</span>,\n      },\n      {\n        key: '3',\n        label: 'collapse 3',\n        className: 'important',\n        children: 'third',\n      },\n    ];\n\n    runNormalTest(\n      <Collapse onChange={onChange} expandIcon={() => <span>test{'>'}</span>} items={items} />,\n    );\n\n    runAccordionTest(\n      <Collapse\n        onChange={onChange}\n        accordion\n        items={[\n          {\n            key: '1',\n            label: 'collapse 1',\n            children: 'first',\n          },\n          {\n            key: '2',\n            label: 'collapse 2',\n            children: 'second',\n          },\n          {\n            key: '3',\n            label: 'collapse 3',\n            children: 'third',\n          },\n        ]}\n      />,\n    );\n\n    it('should work with onItemClick', () => {\n      const onItemClick = jest.fn();\n      const { container } = render(\n        <Collapse\n          items={[\n            {\n              label: 'title 3',\n              onItemClick,\n            },\n          ]}\n        />,\n      );\n      fireEvent.click(container.querySelector('.rc-collapse-header')!);\n      expect(onItemClick).toHaveBeenCalled();\n      expect(onItemClick).lastCalledWith('0');\n    });\n\n    it('should work with collapsible', () => {\n      const onItemClick = jest.fn();\n      const onChangeFn = jest.fn();\n      const { container } = render(\n        <Collapse\n          onChange={onChangeFn}\n          items={[\n            ...items.slice(0, 1),\n            {\n              label: 'title 3',\n              onItemClick,\n              collapsible: 'icon',\n            },\n          ]}\n        />,\n      );\n\n      fireEvent.click(container.querySelector('.rc-collapse-header')!);\n      expect(onItemClick).not.toHaveBeenCalled();\n\n      fireEvent.click(\n        container.querySelector('.rc-collapse-item:nth-child(2) .rc-collapse-expand-icon')!,\n      );\n      expect(onItemClick).toHaveBeenCalled();\n      expect(onChangeFn).toBeCalledTimes(1);\n      expect(onChangeFn).lastCalledWith(['1']);\n    });\n\n    it('should work with nested', () => {\n      const { container } = render(\n        <Collapse\n          items={[\n            ...items,\n            {\n              label: 'title 3',\n              children: <Collapse items={items} />,\n            },\n          ]}\n        />,\n      );\n      expect(container.firstChild).toMatchSnapshot();\n    });\n\n    it('should not support expandIcon', () => {\n      const { container } = render(\n        <Collapse\n          expandIcon={() => <i className=\"custom-icon\">p</i>}\n          items={[\n            {\n              label: 'title',\n              expandIcon: () => <i className=\"custom-icon\">c</i>,\n            } as any,\n          ]}\n        />,\n      );\n\n      expect(container.querySelectorAll('.custom-icon')).toHaveLength(1);\n      expect(container.querySelector('.custom-icon')?.innerHTML).toBe('p');\n    });\n\n    it('should support data- and aria- attributes', () => {\n      const { container } = render(\n        <Collapse\n          data-testid=\"1234\"\n          aria-label=\"test\"\n          items={[\n            {\n              label: 'title',\n            } as any,\n          ]}\n        />,\n      );\n\n      expect(container.querySelector('.rc-collapse')?.getAttribute('data-testid')).toBe('1234');\n      expect(container.querySelector('.rc-collapse')?.getAttribute('aria-label')).toBe('test');\n    });\n\n    it('should support styles and classNames', () => {\n      const customStyles = {\n        header: { color: 'red' },\n        body: { color: 'blue' },\n        title: { color: 'green' },\n        icon: { color: 'yellow' },\n      };\n      const customClassnames = {\n        header: 'custom-header',\n        body: 'custom-body',\n        title: 'custom-title',\n        icon: 'custom-icon',\n      };\n\n      const { container } = render(\n        <Collapse\n          activeKey={['1']}\n          styles={customStyles}\n          classNames={customClassnames}\n          items={[\n            {\n              key: '1',\n              label: 'title',\n            },\n          ]}\n        />,\n      );\n      const headerElement = container.querySelector('.rc-collapse-header') as HTMLElement;\n      const bodyElement = container.querySelector('.rc-collapse-body') as HTMLElement;\n      const titleElement = container.querySelector('.rc-collapse-title') as HTMLElement;\n      const iconElement = container.querySelector('.rc-collapse-expand-icon') as HTMLElement;\n\n      // check classNames\n      expect(headerElement.classList).toContain('custom-header');\n      expect(bodyElement.classList).toContain('custom-body');\n      expect(titleElement.classList).toContain('custom-title');\n      expect(iconElement.classList).toContain('custom-icon');\n\n      // check styles\n      expect(headerElement.style.color).toBe('red');\n      expect(bodyElement.style.color).toBe('blue');\n      expect(titleElement.style.color).toBe('green');\n      expect(iconElement.style.color).toBe('yellow');\n    });\n\n    it('should support styles and classNames in panel', () => {\n      const customStyles = {\n        header: { color: 'red' },\n        body: { color: 'blue' },\n        title: { color: 'green' },\n        icon: { color: 'yellow' },\n      };\n      const customClassnames = {\n        header: 'custom-header',\n        body: 'custom-body',\n      };\n\n      const { container } = render(\n        <Collapse\n          activeKey={['1']}\n          styles={customStyles}\n          classNames={customClassnames}\n          items={[\n            {\n              key: '1',\n              styles: {\n                header: {\n                  color: 'blue',\n                  fontSize: 20,\n                },\n                body: {\n                  fontSize: 20,\n                },\n                title: {\n                  color: 'red',\n                },\n                icon: {\n                  color: 'blue',\n                },\n              },\n              classNames: {\n                header: 'custom-header-panel',\n                body: 'custom-body-panel',\n              },\n              label: 'title',\n            },\n          ]}\n        />,\n      );\n      const headerElement = container.querySelector('.rc-collapse-header') as HTMLElement;\n      const bodyElement = container.querySelector('.rc-collapse-body') as HTMLElement;\n      const titleElement = container.querySelector('.rc-collapse-title') as HTMLElement;\n      const iconElement = container.querySelector('.rc-collapse-expand-icon') as HTMLElement;\n\n      // check classNames\n      expect(headerElement.classList).toContain('custom-header');\n      expect(headerElement.classList).toContain('custom-header-panel');\n      expect(bodyElement.classList).toContain('custom-body');\n      expect(bodyElement.classList).toContain('custom-body-panel');\n\n      // check styles\n      expect(headerElement).toHaveStyle({ color: 'blue', fontSize: '20px' });\n      expect(bodyElement).toHaveStyle({ color: 'blue', fontSize: '20px' });\n      expect(titleElement).toHaveStyle({ color: 'red' });\n      expect(iconElement).toHaveStyle({ color: 'blue' });\n    });\n  });\n});\n"
  },
  {
    "path": "tests/setupAfterEnv.ts",
    "content": "import '@testing-library/jest-dom';\n"
  },
  {
    "path": "tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"target\": \"esnext\",\n    \"moduleResolution\": \"node\",\n    \"baseUrl\": \"./\",\n    \"jsx\": \"react\",\n    \"declaration\": true,\n    \"skipLibCheck\": true,\n    \"esModuleInterop\": true,\n    \"paths\": {\n      \"@/*\": [\"src/*\"],\n      \"@@/*\": [\"src/.dumi/*\"],\n      \"rc-collapse\": [\"src/index.tsx\"]\n    }\n  },\n  \"include\": [\n    \".dumirc.ts\",\n    \"./src/**/*.ts\",\n    \"./src/**/*.tsx\",\n    \"./tests/**/*.ts\",\n    \"./tests/**/*.tsx\",\n    \"./docs/**/*.tsx\"\n  ]\n}\n"
  },
  {
    "path": "vercel.json",
    "content": "{\n  \"framework\": \"umijs\"\n}\n"
  }
]