[
  {
    "path": ".eslintrc",
    "content": "{\n  \"root\": false,\n\n  \"env\": {\n    \"browser\": true\n  },\n\n  \"parserOptions\": {\n    \"parser\": \"babel-eslint\",\n    \"sourceType\": \"module\"\n  },\n\n  \"extends\": [\n    \"eslint:recommended\",\n    \"airbnb-base\",\n    \"plugin:vue/recommended\",\n    \"prettier\",\n    \"prettier/vue\"\n  ],\n\n  \"rules\": {\n    \"func-names\": 0,\n    \"no-unused-expressions\": [\n      \"error\",\n      {\n        \"allowShortCircuit\": true,\n        \"allowTernary\": false,\n        \"allowTaggedTemplates\": false\n      }\n    ],\n    \"prefer-destructuring\": [\n      \"error\",\n      {\n        \"array\": false\n      }\n    ],\n\n    \"import/extensions\": \"off\",\n    \"import/no-unresolved\": \"off\",\n\n    \"vue/component-name-in-template-casing\": [\"error\", \"kebab-case\"],\n    \"vue/max-attributes-per-line\": \"warn\",\n    \"vue/no-v-html\": 0,\n    \"vue/html-closing-bracket-newline\": \"warn\",\n    \"vue/html-indent\": \"warn\",\n\n    \"no-console\": 0,\n    \"no-debugger\": 0\n  },\n\n  \"overrides\": [\n    {\n      \"files\": [\"**/*.test.js\"],\n      \"env\": { \"jest\": true },\n      \"globals\": {\n        \"mount\": \"readonly\",\n        \"shallowMount\": \"readonly\"\n      }\n    }\n  ]\n}\n"
  },
  {
    "path": ".github/workflows/codeql-analysis.yml",
    "content": "# For most projects, this workflow file will not need changing; you simply need\n# to commit it to your repository.\n#\n# You may wish to alter this file to override the set of languages analyzed,\n# or to provide custom queries or build logic.\n#\n# ******** NOTE ********\n# We have attempted to detect the languages in your repository. Please check\n# the `language` matrix defined below to confirm you have the correct set of\n# supported CodeQL languages.\n#\nname: 'CodeQL'\n\non:\n  push:\n    branches: [master]\n  pull_request:\n    # The branches below must be a subset of the branches above\n    branches: [master]\n  schedule:\n    - cron: '21 8 * * 4'\n\njobs:\n  analyze:\n    name: Analyze\n    runs-on: ubuntu-latest\n\n    strategy:\n      fail-fast: false\n      matrix:\n        language: ['javascript']\n        # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ]\n        # Learn more:\n        # https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#changing-the-languages-that-are-analyzed\n\n    steps:\n      - name: Checkout repository\n        uses: actions/checkout@v2\n\n      # Initializes the CodeQL tools for scanning.\n      - name: Initialize CodeQL\n        uses: github/codeql-action/init@v1\n        with:\n          languages: ${{ matrix.language }}\n          # If you wish to specify custom queries, you can do so here or in a config file.\n          # By default, queries listed here will override any specified in a config file.\n          # Prefix the list here with \"+\" to use these queries and those in the config file.\n          # queries: ./path/to/local/query, your-org/your-repo/queries@main\n\n      # Autobuild attempts to build any compiled languages  (C/C++, C#, or Java).\n      # If this step fails, then you should remove it and run the build manually (see below)\n      - name: Autobuild\n        uses: github/codeql-action/autobuild@v1\n\n      # ℹ️ Command-line programs to run using the OS shell.\n      # 📚 https://git.io/JvXDl\n\n      # ✏️ If the Autobuild fails above, remove it and uncomment the following three lines\n      #    and modify them (or add more) to build your code if your project\n      #    uses a compiled language\n\n      #- run: |\n      #   make bootstrap\n      #   make release\n\n      - name: Perform CodeQL Analysis\n        uses: github/codeql-action/analyze@v1\n"
  },
  {
    "path": ".github/workflows/deploy.yml",
    "content": "name: github pages\n\non:\n  push:\n    branches:\n      - master\n\njobs:\n  deploy:\n    runs-on: ubuntu-18.04\n    steps:\n      - uses: actions/checkout@v2\n\n      - name: Setup Node\n        uses: actions/setup-node@v1\n        with:\n          node-version: '12.x'\n\n      - name: Cache dependencies\n        uses: actions/cache@v2\n        with:\n          path: ~/.npm\n          key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}\n          restore-keys: |\n            ${{ runner.os }}-node-\n\n      - run: yarn --frozen-lockfile\n      - run: yarn build-storybook\n      - run: yarn deploy-storybook -- --ci\n        env:\n          GH_TOKEN: Qvant-lab:${{ secrets.GITHUB_TOKEN }}\n"
  },
  {
    "path": ".gitignore",
    "content": ".DS_Store\nnode_modules\ncoverage\n/dist\n.out\n\n\n# local env files\n.env.local\n.env.*.local\n\n# Log files\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\npnpm-debug.log*\n\n# Editor directories and files\n.idea\n.vscode\n*.suo\n*.ntvs*\n*.njsproj\n*.sln\n*.sw?\n"
  },
  {
    "path": ".lintstagedrc",
    "content": "{\n  \"*.js\": [\"prettier --write\", \"git add\"],\n  \"*.scss\": [\"stylelint --fix\", \"prettier --write\", \"git add\"],\n  \"*.vue\": [\n    \"stylelint --fix\",\n    \"prettier --parser vue --write\",\n    \"eslint --fix --no-ignore\",\n    \"git add\"\n  ],\n  \"{*.json,.*rc}\": [\"prettier --parser json --write\", \"git add\"],\n  \"*.{yaml,yml}\": [\"prettier --parser yaml --write\", \"git add\"]\n}\n"
  },
  {
    "path": ".npmignore",
    "content": "yarn-error.log\n/.storybook\n/.github\n/.readme-assets\n"
  },
  {
    "path": ".nvmrc",
    "content": "12.22.6\n"
  },
  {
    "path": ".prettierignore",
    "content": ".nvmrc\n/dist\n"
  },
  {
    "path": ".prettierrc",
    "content": "{\n  \"printWidth\": 80,\n  \"tabWidth\": 2,\n  \"useTabs\": false,\n  \"semi\": true,\n  \"singleQuote\": true,\n  \"quoteProps\": \"as-needed\",\n  \"trailingComma\": \"none\",\n  \"bracketSpacing\": true,\n  \"arrowParens\": \"avoid\",\n  \"endOfLine\": \"lf\"\n}\n"
  },
  {
    "path": ".storybook/locales/en.js",
    "content": "export default {\n  qBreadcrumbsStories: {\n    routeA: 'Route A',\n    routeB: 'Route B',\n    routeC: 'Route C',\n    routeD: 'Route D'\n  }\n};\n"
  },
  {
    "path": ".storybook/locales/index.js",
    "content": "import en from './en';\nimport ru from './ru';\nimport {\n  en as qMessagesEn,\n  ru as qMessagesRu\n} from '../../src/qComponents/constants/locales';\n\nexport default {\n  en: {\n    ...en,\n    ...qMessagesEn\n  },\n  ru: {\n    ...ru,\n    ...qMessagesRu\n  }\n};\n"
  },
  {
    "path": ".storybook/locales/ru.js",
    "content": "export default {\n  qBreadcrumbsStories: {\n    routeA: 'Роут А',\n    routeB: 'Очень длинный маршрут Б',\n    routeC: 'Роут С',\n    routeD: 'Роут D'\n  }\n};\n"
  },
  {
    "path": ".storybook/main.js",
    "content": "module.exports = {\n  stories: ['../stories/**/**/*.stories.@(ts|js|mdx)'],\n  logLevel: 'debug',\n  addons: [\n    '@storybook/addon-docs',\n    '@storybook/addon-controls',\n    '@storybook/addon-storysource',\n    '@storybook/preset-scss',\n    '@storybook/addon-toolbars'\n  ]\n};\n"
  },
  {
    "path": ".storybook/manager.js",
    "content": "import addons from '@storybook/addons';\nimport theme from './theme';\n\naddons.setConfig({\n  theme\n});\n"
  },
  {
    "path": ".storybook/preview.js",
    "content": "import Vue from 'vue';\nimport Qui from '../src/qComponents';\nimport VueI18n from 'vue-i18n';\nimport messages from './locales';\n\nVue.use(VueI18n);\nVue.use(Qui, {\n  localization: {\n    locale: 'en'\n  }\n});\n\nexport const parameters = {\n  layout: 'centered',\n  controls: { expanded: true },\n  docs: {\n    inlineStories: true\n  }\n};\n\nexport const globalTypes = {\n  locale: {\n    name: 'Locale',\n    description: 'Internationalization locale',\n    defaultValue: 'en',\n    toolbar: {\n      icon: 'globe',\n      items: [\n        { value: 'en', right: '🇺🇸', title: 'English' },\n        { value: 'ru', right: '🇷🇺', title: 'Русский' }\n      ]\n    }\n  }\n};\n\nconst i18n = new VueI18n({\n  locale: 'en',\n  messages,\n  silentTranslationWarn: true,\n  silentFallbackWarn: true,\n  fallbackRoot: true\n});\n\nexport const decorators = [\n  (args, { globals: { locale } }) => ({\n    i18n,\n    beforeCreate: function() {\n      this.$Q.locale = locale;\n      i18n.locale = locale;\n      this.$root._i18n = i18n;\n    },\n    template: '<story />'\n  })\n];\n"
  },
  {
    "path": ".storybook/theme.js",
    "content": "import { create } from '@storybook/theming/create';\nimport logo from '../.readme-assets/qui-logo.svg';\n\nexport default create({\n  name: 'Theme',\n  base: 'light',\n\n  brandTitle: 'QUI',\n  brandUrl: 'https://qvant-lab.github.io/qui/',\n  brandImage: logo\n});\n"
  },
  {
    "path": ".stylelintignore",
    "content": "/src/normalize.scss\n"
  },
  {
    "path": ".stylelintrc",
    "content": "{\n  \"extends\": [\"stylelint-config-prettier\"],\n  \"plugins\": [\"stylelint-order\"],\n  \"rules\": {\n    \"color-hex-length\": \"short\",\n    \"color-named\": \"never\",\n    \"font-weight-notation\": \"numeric\",\n    \"function-url-quotes\": [\"always\", { \"except\": [\"empty\"] }],\n    \"length-zero-no-unit\": true,\n    \"rule-empty-line-before\": [\n      \"always-multi-line\",\n      { \"ignore\": [\"after-comment\", \"first-nested\"] }\n    ],\n    \"selector-pseudo-element-colon-notation\": \"double\",\n    \"order/properties-order\": [\n      \"content\",\n      \"position\",\n      \"top\",\n      \"right\",\n      \"bottom\",\n      \"left\",\n      \"z-index\",\n      \"display\",\n      \"flex\",\n      \"flex-grow\",\n      \"flex-shrink\",\n      \"flex-basis\",\n      \"flex-flow\",\n      \"flex-direction\",\n      \"flex-wrap\",\n      \"justify-content\",\n      \"align-content\",\n      \"align-items\",\n      \"order\",\n      \"align-self\",\n      \"float\",\n      \"clear\",\n      \"box-sizing\",\n      \"width\",\n      \"min-width\",\n      \"max-width\",\n      \"height\",\n      \"min-height\",\n      \"max-height\",\n      \"margin\",\n      \"margin-top\",\n      \"margin-right\",\n      \"margin-bottom\",\n      \"margin-left\",\n      \"padding\",\n      \"padding-top\",\n      \"padding-right\",\n      \"padding-bottom\",\n      \"padding-left\",\n      \"overflow\",\n      \"overflow-x\",\n      \"overflow-y\",\n      \"list-style\",\n      \"list-style-position\",\n      \"list-style-type\",\n      \"list-style-image\",\n      \"border-collapse\",\n      \"border-spacing\",\n      \"table-layout\",\n      \"empty-cells\",\n      \"caption-side\",\n      \"font\",\n      \"font-style\",\n      \"font-variant\",\n      \"font-weight\",\n      \"font-size\",\n      \"line-height\",\n      \"font-family\",\n      \"vertical-align\",\n      \"text-align\",\n      \"direction\",\n      \"color\",\n      \"text-transform\",\n      \"text-decoration\",\n      \"font-size-adjust\",\n      \"font-stretch\",\n      \"font-effect\",\n      \"font-emphasize\",\n      \"font-emphasize-position\",\n      \"font-emphasize-style\",\n      \"font-smooth\",\n      \"text-align-last\",\n      \"letter-spacing\",\n      \"word-spacing\",\n      \"white-space\",\n      \"text-emphasis\",\n      \"text-emphasis-color\",\n      \"text-emphasis-style\",\n      \"text-emphasis-position\",\n      \"text-indent\",\n      \"text-justify\",\n      \"-ms-writing-mode\",\n      \"text-outline\",\n      \"text-wrap\",\n      \"text-overflow\",\n      \"text-overflow-ellipsis\",\n      \"text-overflow-mode\",\n      \"text-orientation\",\n      \"word-wrap\",\n      \"word-break\",\n      \"tab-size\",\n      \"hyphens\",\n      \"unicode-bidi\",\n      \"columns\",\n      \"column-count\",\n      \"column-fill\",\n      \"column-gap\",\n      \"column-rule\",\n      \"column-rule-color\",\n      \"column-rule-style\",\n      \"column-rule-width\",\n      \"column-span\",\n      \"column-width\",\n      \"text-shadow\",\n      \"page-break-after\",\n      \"page-break-before\",\n      \"page-break-inside\",\n      \"background\",\n      \"background-color\",\n      \"background-image\",\n      \"linear-gradient\",\n      \"background-repeat\",\n      \"background-position\",\n      \"background-position-x\",\n      \"background-position-y\",\n      \"background-size\",\n      \"background-clip\",\n      \"background-origin\",\n      \"background-attachment\",\n      \"box-decoration-break\",\n      \"background-blend-mode\",\n      \"border\",\n      \"border-width\",\n      \"border-style\",\n      \"border-color\",\n      \"border-top\",\n      \"border-top-width\",\n      \"border-top-style\",\n      \"border-top-color\",\n      \"border-right\",\n      \"border-right-width\",\n      \"border-right-style\",\n      \"border-right-color\",\n      \"border-bottom\",\n      \"border-bottom-width\",\n      \"border-bottom-style\",\n      \"border-bottom-color\",\n      \"border-left\",\n      \"border-left-width\",\n      \"border-left-style\",\n      \"border-left-color\",\n      \"border-radius\",\n      \"border-top-left-radius\",\n      \"border-top-right-radius\",\n      \"border-bottom-right-radius\",\n      \"border-bottom-left-radius\",\n      \"border-image\",\n      \"border-image-source\",\n      \"border-image-slice\",\n      \"border-image-width\",\n      \"border-image-outset\",\n      \"border-image-repeat\",\n      \"outline\",\n      \"outline-width\",\n      \"outline-style\",\n      \"outline-color\",\n      \"outline-offset\",\n      \"box-shadow\",\n      \"transform\",\n      \"transform-origin\",\n      \"backface-visibility\",\n      \"perspective\",\n      \"perspective-origin\",\n      \"transform-style\",\n      \"visibility\",\n      \"cursor\",\n      \"opacity\",\n      \"filter\",\n      \"transition\",\n      \"transition-delay\",\n      \"transition-timing-function\",\n      \"transition-duration\",\n      \"transition-property\",\n      \"animation\",\n      \"animation-name\",\n      \"animation-duration\",\n      \"animation-play-state\",\n      \"animation-timing-function\",\n      \"animation-delay\",\n      \"animation-iteration-count\",\n      \"animation-direction\",\n      \"quotes\",\n      \"counter-reset\",\n      \"counter-increment\",\n      \"resize\",\n      \"user-select\",\n      \"nav-index\",\n      \"nav-up\",\n      \"nav-right\",\n      \"nav-down\",\n      \"nav-left\",\n      \"pointer-events\",\n      \"will-change\",\n      \"clip\",\n      \"clip-path\",\n      \"zoom\"\n    ]\n  }\n}\n"
  },
  {
    "path": "CODE_OF_CONDUCT.md",
    "content": "# Contributor Covenant Code of Conduct\n\n## Our Pledge\n\nIn the interest of fostering an open and welcoming environment, we as\ncontributors and maintainers pledge to making participation in our project and\nour community a harassment-free experience for everyone, regardless of age, body\nsize, disability, ethnicity, sex characteristics, gender identity and expression,\nlevel of experience, education, socio-economic status, nationality, personal\nappearance, race, religion, or sexual identity and orientation.\n\n## Our Standards\n\nExamples of behavior that contributes to creating a positive environment\ninclude:\n\n* Using welcoming and inclusive language\n* Being respectful of differing viewpoints and experiences\n* Gracefully accepting constructive criticism\n* Focusing on what is best for the community\n* Showing empathy towards other community members\n\nExamples of unacceptable behavior by participants include:\n\n* The use of sexualized language or imagery and unwelcome sexual attention or\n advances\n* Trolling, insulting/derogatory comments, and personal or political attacks\n* Public or private harassment\n* Publishing others' private information, such as a physical or electronic\n address, without explicit permission\n* Other conduct which could reasonably be considered inappropriate in a\n professional setting\n\n## Our Responsibilities\n\nProject maintainers are responsible for clarifying the standards of acceptable\nbehavior and are expected to take appropriate and fair corrective action in\nresponse to any instances of unacceptable behavior.\n\nProject maintainers have the right and responsibility to remove, edit, or\nreject comments, commits, code, wiki edits, issues, and other contributions\nthat are not aligned to this Code of Conduct, or to ban temporarily or\npermanently any contributor for other behaviors that they deem inappropriate,\nthreatening, offensive, or harmful.\n\n## Scope\n\nThis Code of Conduct applies both within project spaces and in public spaces\nwhen an individual is representing the project or its community. Examples of\nrepresenting a project or community include using an official project e-mail\naddress, posting via an official social media account, or acting as an appointed\nrepresentative at an online or offline event. Representation of a project may be\nfurther defined and clarified by project maintainers.\n\n## Enforcement\n\nInstances of abusive, harassing, or otherwise unacceptable behavior may be\nreported by contacting the project team at . All\ncomplaints will be reviewed and investigated and will result in a response that\nis deemed necessary and appropriate to the circumstances. The project team is\nobligated to maintain confidentiality with regard to the reporter of an incident.\nFurther details of specific enforcement policies may be posted separately.\n\nProject maintainers who do not follow or enforce the Code of Conduct in good\nfaith may face temporary or permanent repercussions as determined by other\nmembers of the project's leadership.\n\n## Attribution\n\nThis Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,\navailable at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html\n\n[homepage]: https://www.contributor-covenant.org\n\nFor answers to common questions about this code of conduct, see\nhttps://www.contributor-covenant.org/faq\n"
  },
  {
    "path": "LICENSE",
    "content": "MIT License\n\nCopyright (c) 2020 Qvant\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 src=\"/.readme-assets/qui-logo.svg?raw=true\" />\n</p>\n\n<p align=\"center\" class=\"unchanged rich-diff-level-one\">\n<!--BADGES-->\n<span class=\"badge-shields\"><a href=\"https://qvant-lab.github.io/qui\" title=\"storybook\"><img src=\"https://img.shields.io/badge/storybook-yes-green.svg\" alt=\"storybook\" /></a></span> <span class=\"badge-shields\"><img src=\"https://img.shields.io/badge/responsive-yes-green.svg\" /></span> <span class=\"badge-npmversion\"><a href=\"https://npmjs.org/package/@qvant/qui\" title=\"View this project on NPM\"><img src=\"https://img.shields.io/npm/v/@qvant/qui.svg\" alt=\"NPM version\" /></a></span> <span class=\"badge-npmdownloads\"><a href=\"https://npmjs.org/package/@qvant/qui\" title=\"View this project on NPM\"><img src=\"https://img.shields.io/npm/dm/@qvant/qui.svg\" alt=\"NPM downloads\" /></a></span></span><!--/BADGES--></p>\n\n# A Vue.js Neumorphism Design System for Web\n\nResponsive, user-friendly and lightweight library helping us build great products for our customers. This library for Vue 2.x\n\n‼️ Currently we are working on [Qui Max](https://github.com/Qvant-lab/qui-max) for Vue 3.x, it is more complex and modern version of Qui - we recommend use it instead of this package. Qui remains for Vue 2.x, but we can't claim it will be supported well.\n\n[Storybook (live demo)](https://qvant-lab.github.io/qui/)\n\nWhat is it?\n\n- 🔩 30+ Vue components\n- 📦 icons pack\n- 🏳️‍🌈 colors & grid\n- 🥷 neumorphism styles\n- 📚 storybook sandbox\n\nSome examples below:\n\n![buttons](/.readme-assets/buttons.jpg?raw=true)\n![inputs](/.readme-assets/inputs.gif?raw=true)\n![icons](/.readme-assets/icons.gif?raw=true)\n![tables](/.readme-assets/tables.jpg?raw=true)\n![datepicker](/.readme-assets/datepicker.jpg?raw=true)\n![other](/.readme-assets/other.jpg?raw=true)\n\n## Install\n\nCDN:\n\n```html\n<!-- import CSS -->\n<link rel=\"stylesheet\" href=\"https://unpkg.com/@qvant/qui/dist/qui.css\" />\n<!-- import JavaScript -->\n<script src=\"https://unpkg.com/@qvant/qui/dist/qui.umd.min.js\"></script>\n```\nNpm | Yarn:\n\n```bash\nnpm install @qvant/qui -S\nyarn add @qvant/qui\n```\n\nYou can import Qui entirely, or just import what you need. Let's start with fully import.\n\n## Quick setup\n\nIn main.js:\n\n```js\nimport Vue from 'vue';\nimport Qui from '@qvant/qui';\nimport '@qvant/qui/dist/qui.css';\n\n// Setup all components\nVue.use(Qui);\n// that's it! All components will be imported with styles\n```\n\nin YourComponent.vue: (Example)\n\n```vue\n<template>\n  <q-input v-model=\"value\" />\n</template>\n<script>\nexport default {\n  data() {\n    return {\n      value: ''\n    };\n  },\n  mounted() {\n    // the modals have shortcuts in your components:\n    this.$notify({ ... }) // calls QNotification\n    this.$message({ ... }) // calls QMessageBox\n    this.$dialog({ ... }) // calls QDialog\n  }\n};\n</script>\n```\n\n...or configure quick setup\n\nIn main.js:\n\n```js\nimport Vue from 'vue';\nimport Qui from '@qvant/qui';\nimport '@qvant/qui/dist/qui.css';\n\nVue.use(Qui, {\n  localization: {\n    locale: 'en', // Russian language by default, you can set `en` for English\n    customI18nMessages: {\n      // rewrite default texts, see the source: src/qComponents/constants/locales\n      en: {\n        QDatepicker: {\n          placeholder: 'Pick your birthday!'\n        }\n      }\n    },\n    zIndexCounter: 3000, // zIndexCounter is being used by some components, (e.g QPopover, QSelect, QDialog ...etc), 2000 by default\n    prefix: 'yo' // you can change component's prefix, e.g. must be used <yo-input /> instead of <q-input />\n  }\n});\n```\n\nin YourComponent.vue: (Example)\n\n```vue\n<template>\n  <!-- placeholder is changed on 'Pick your birthday!' -->\n  <yo-datepicker v-model=\"value\" type=\"date\" />\n</template>\n<script>\nexport default {\n  data() {\n    return {\n      value: null\n    };\n  }\n};\n</script>\n```\n\nNow you have implemented Vue and Qui to your project, and it's time to write your code.\nPlease refer to each component's [Stories](https://qvant-lab.github.io/qui/) to learn how to use them.\n\n## Not quick setup\n\nIf you have a module bundler (e.g webpack), you can import components separately and take care about your bundle size\n\nIn main.js:\n\n```js\n// import the main plugin from another place (it ensures Qui will be installed without any components, but instance will set required properties and directives)\nimport Qui from '@qvant/qui/src/onDemand';\n\n// import the component you want\nimport QButton from '@qvant/qui/src/qComponents/QButton';\n// ...or in async way\nVue.component('q-button', () =>\n  import(/* webpackChunkName: \"qui\" */ '@qvant/qui/src/qComponents/QButton')\n);\n\n// init\nVue.use(Qui);\nVue.use(QButton);\n```\n\nIn main.scss:\n\n```scss\n// need to set the path for files with statics\n$--base-path: '~@qvant/qui/src';\n// set main styles\n@import '~@qvant/qui/src/main.scss';\n// notice that you must use `fonts` and `icons` styles for some of components:\n@import '~@qvant/qui/src/fonts/index.scss';\n@import '~@qvant/qui/src/icons/index.scss';\n```\n\nimport all styles:\n\n```scss\n@import '~@qvant/qui/src/components.scss';\n```\n\n...or components separately:\n\n```scss\n@import '~@qvant/qui/src/qComponents/QBreadcrumbs/src/q-breadcrumbs.scss';\n@import '~@qvant/qui/src/qComponents/QButton/src/q-button.scss';\n// ...etc\n```\n\n## Optional\n\n- if you want use modals inside your components as property of 'this':\n\n```js\nimport { QMessageBox, QDialog, QNotification } from '@qvant/qui';\n// or import separately\nimport QMessageBox from '@qvant/qui/src/qComponents/QMessageBox';\nimport QDialog from '@qvant/qui/src/qComponents/QDialog';\nimport QNotification from '@qvant/qui/src/qComponents/QNotification';\n\nVue.prototype.$message = QMessageBox;\nVue.prototype.$dialog = QDialog;\nVue.prototype.$notify = options =>\n  QNotification({\n    duration: 3000, // - ms\n    ...options\n  });\n```\n\n- if you use VueI18n, you need to merge messages:\n\n```js\nimport VueI18n from 'vue-i18n';\nimport { en, ru } from '@qvant/qui/src/qComponents/constants/locales';\n\nVue.use(VueI18n);\n\nconst messages = {\n  en: {\n    message: {\n      hello: 'hello world'\n    },\n    ...en\n  },\n  ru: {\n    message: {\n      hello: 'привет, мир'\n    },\n    ...ru\n  }\n};\n\nconst i18n = new VueI18n({\n  locale: 'en',\n  messages\n});\n\nnew Vue({\n  i18n\n}).$mount('#your-app');\n```\n\n## Supported languages\n\n- Russian ✅\n- English ✅\n- Also you can use any language by setting texts for components via 'customI18nMessages' property in the Qui instance. See the example above.\n\n## Browser Support\n\nModern browsers are recomended\n\n- safari: >11\n- chrome: >=61\n- firefox: >=58\n- opera: >=62\n- edge: >=16\n- yandex: >=18\n- ie: ? (we don't know :) and will not support it)\n\n## Development\n\nClone repository and run storybook\n\n```bash\nyarn storybook\nnpm run storybook\n```\n\n## LICENSE\n\nMIT\n"
  },
  {
    "path": "babel.config.js",
    "content": "module.exports = {\n  presets: ['@vue/cli-plugin-babel/preset']\n};\n"
  },
  {
    "path": "jest.config.js",
    "content": "module.exports = {\n  moduleFileExtensions: ['js', 'vue', 'json'],\n  transform: {\n    '^.+\\\\.vue$': 'vue-jest',\n    '^.+\\\\.js$': 'babel-jest',\n    '.+\\\\.(css|styl|less|sass|scss|svg|png|jpg|ttf|woff|woff2)$':\n      'jest-transform-stub'\n  },\n  transformIgnorePatterns: ['[/\\\\\\\\]node_modules[/\\\\\\\\](?!lodash-es/).+\\\\.js$'],\n  setupFiles: ['<rootDir>/tests/unit/setup.js'],\n  testMatch: ['<rootDir>/src/**/*.test.(ts|tsx|js)'],\n  testURL: 'http://localhost/',\n  coverageReporters: ['text-summary', 'html', 'lcov', 'clover'],\n  coverageDirectory: '<rootDir>/tests/unit/coverage',\n  coverageThreshold: {\n    global: {\n      branches: 7,\n      functions: 14,\n      lines: 17\n    }\n  }\n};\n"
  },
  {
    "path": "package.json",
    "content": "{\n  \"name\": \"@qvant/qui\",\n  \"version\": \"1.4.5\",\n  \"private\": false,\n  \"description\": \"A Vue.js Design system for Web.\",\n  \"author\": {\n    \"name\": \"Qvant Frontend team\"\n  },\n  \"scripts\": {\n    \"build\": \"npx vue-cli-service build --target lib --name qui --entry ./src/qComponents/index.js\",\n    \"build-storybook\": \"build-storybook -c .storybook -o .out\",\n    \"create-badges\": \"node scripts/badges.js\",\n    \"deploy-storybook\": \"storybook-to-ghpages\",\n    \"eslint\": \"eslint --fix --no-ignore .storybook/**/**/*.{vue,js}\",\n    \"prettier\": \"prettier --write '**/*.{js,vue,scss,json,yml}'\",\n    \"storybook\": \"start-storybook -s ./public -p 6006\",\n    \"stylelint:fix\": \"stylelint --fix '**/*.{scss,vue}'\",\n    \"test:unit\": \"jest\"\n  },\n  \"main\": \"./dist/qui.common.js\",\n  \"dependencies\": {\n    \"@popperjs/core\": \"^2.4.4\",\n    \"async-validator\": \"^3.4.0\",\n    \"color\": \"^3.1.2\",\n    \"date-fns\": \"^2.15.0\",\n    \"focus-visible\": \"^5.2.0\",\n    \"jest-transform-stub\": \"^2.0.0\",\n    \"lodash-es\": \"^4.17.15\",\n    \"resize-observer-polyfill\": \"^1.5.0\",\n    \"v-click-outside\": \"^3.1.2\",\n    \"vue\": \"^2.6.11\",\n    \"vue-i18n\": \"^8.22.2\"\n  },\n  \"devDependencies\": {\n    \"@babel/core\": \"^7.10.4\",\n    \"@storybook/addon-controls\": \"^6.1.10\",\n    \"@storybook/addon-docs\": \"^6.1.10\",\n    \"@storybook/addon-storysource\": \"^6.1.10\",\n    \"@storybook/addon-toolbars\": \"^6.1.11\",\n    \"@storybook/preset-scss\": \"^1.0.3\",\n    \"@storybook/storybook-deployer\": \"^2.8.7\",\n    \"@storybook/theming\": \"^6.1.10\",\n    \"@storybook/vue\": \"^6.1.10\",\n    \"@vue/cli-plugin-babel\": \"~4.5.0\",\n    \"@vue/cli-plugin-eslint\": \"~4.5.0\",\n    \"@vue/cli-service\": \"~4.5.0\",\n    \"@vue/eslint-config-prettier\": \"^6.0.0\",\n    \"@vue/test-utils\": \"^1.1.1\",\n    \"babel-eslint\": \"^10.1.0\",\n    \"babel-jest\": \"^26.6.3\",\n    \"babel-loader\": \"^8.1.0\",\n    \"babel-preset-vue\": \"^2.0.2\",\n    \"badges\": \"^4.24.0\",\n    \"css-loader\": \"^4.3.0\",\n    \"eslint\": \"^7.9.0\",\n    \"eslint-config-airbnb-base\": \"^14.1.0\",\n    \"eslint-config-prettier\": \"^6.7.0\",\n    \"eslint-plugin-import\": \"^2.20.2\",\n    \"eslint-plugin-prettier\": \"^3.1.1\",\n    \"eslint-plugin-vue\": \"^6.0.1\",\n    \"husky\": \"^4.2.5\",\n    \"jest\": \"^26.6.3\",\n    \"lint-staged\": \"^10.1.7\",\n    \"node-sass\": \"^4.13.0\",\n    \"sass-loader\": \"^10.0.2\",\n    \"style-loader\": \"^1.2.1\",\n    \"stylelint\": \"^13.7.1\",\n    \"stylelint-config-prettier\": \"^8.0.1\",\n    \"stylelint-order\": \"^4.0.0\",\n    \"vue-jest\": \"^3.0.7\",\n    \"vue-loader\": \"^15.9.3\",\n    \"vue-template-compiler\": \"^2.6.11\"\n  },\n  \"_id\": \"@qvant/qui@1.4.5\",\n  \"bugs\": {\n    \"url\": \"https://github.com/Qvant-lab/qui/issues\"\n  },\n  \"contributors\": [\n    {\n      \"name\": \"Viktor Zheleztsov\",\n      \"url\": \"https://github.com/ViZhe\"\n    },\n    {\n      \"name\": \"Maksim Novikov\",\n      \"url\": \"https://github.com/Esvalirion\"\n    },\n    {\n      \"name\": \"Shamil Alisultanov\",\n      \"url\": \"https://github.com/shamilfrontend\"\n    }\n  ],\n  \"demo\": \"https://qvant-lab.github.io/qui/\",\n  \"homepage\": \"https://github.com/Qvant-lab/qui#readme\",\n  \"husky\": {\n    \"hooks\": {\n      \"pre-commit\": \"lint-staged && yarn test:unit --coverage\"\n    }\n  },\n  \"keywords\": [\n    \"design-system\",\n    \"components\",\n    \"library\",\n    \"ui\",\n    \"vue\",\n    \"sass\",\n    \"neumorphism\"\n  ],\n  \"license\": \"MIT\",\n  \"maintainers\": [\n    {\n      \"name\": \"Tim Bochkarev\",\n      \"url\": \"https://github.com/Tim152\"\n    }\n  ],\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/Qvant-lab/qui.git\"\n  }\n}\n"
  },
  {
    "path": "scripts/badges.js",
    "content": "// edit `list` & run `node scripts/badges.js` for creating new badges\n\nconst { renderBadges } = require('badges');\nconst fs = require('fs');\n\n// Listing of badges to output\nconst list = [\n  [\n    'shields',\n    {\n      left: 'storybook',\n      right: 'yes',\n      color: 'green',\n      alt: 'storybook',\n      url: 'https://qvant-lab.github.io/qui',\n      title: 'storybook'\n    }\n  ],\n  [\n    'shields',\n    {\n      left: 'responsive',\n      right: 'yes',\n      color: 'green',\n      title: 'responsive'\n    }\n  ],\n  'npmversion',\n  'npmdownloads',\n  'daviddm',\n  'daviddmdev'\n];\n\n// Configuration for the badges\nconst config = {\n  npmPackageName: '@qvant/qui',\n\n  saucelabsUsername: 'Qui',\n  githubSlug: 'Qvant-lab/qui',\n  nodeicoQueryString: { downloads: true, compact: true, height: 2 },\n  homepage: 'https://qvant-lab.github.io/qui/'\n};\n\n// Options for rendering the badges\nconst options = {\n  // Filter Category\n  // When set to a string, will only render badges from the list that of the specified category\n  // Values can be 'development', 'testing', 'funding', or 'social'\n  // E.g. to render only funding badges, set to 'funding'\n  filterCategory: false,\n\n  // Filter Scripts\n  // When true, do not render any badges from the list that are scripts\n  filterScripts: false\n};\n\n// Render the badges to a string\nconst badges = renderBadges(list, config, options);\n\nfs.readFile('README.md', 'utf8', function(err, data) {\n  if (err) {\n    return console.log(err);\n  }\n\n  const result = data.replace(\n    /<!--BADGES-->((.|\\n)*)<!--\\/BADGES-->/g,\n    `<!--BADGES-->${badges}<!--/BADGES-->`\n  );\n\n  fs.writeFile('README.md', result, 'utf8', function(error) {\n    if (error) return console.log(error);\n  });\n});\n"
  },
  {
    "path": "src/components.scss",
    "content": "@import '../qComponents/QBreadcrumbs/src/q-breadcrumbs.scss';\n@import '../qComponents/QButton/src/q-button.scss';\n@import '../qComponents/QCascader/src/q-cascader.scss';\n@import '../qComponents/QCheckbox/src/q-checkbox.scss';\n@import '../qComponents/QCheckboxGroup/src/q-checkbox-group.scss';\n@import '../qComponents/QCol/src/q-col.scss';\n@import '../qComponents/QCollapseItem/src/q-collapse-item.scss';\n@import '../qComponents/QColorPicker/src/q-color-picker.scss';\n@import '../qComponents/QContextMenu/src/q-context-menu.scss'; //\n@import '../qComponents/QDatePicker/src/q-date-picker.scss';\n@import '../qComponents/QDialog/src/q-dialog.scss';\n@import '../qComponents/QDrawer/src/q-drawer.scss';\n@import '../qComponents/QFormItem/src/q-form-item.scss';\n@import '../qComponents/QInput/src/q-input.scss';\n@import '../qComponents/QInputNumber/src/q-input-number.scss';\n@import '../qComponents/QMessageBox/src/q-message-box.scss';\n@import '../qComponents/QNotification/src/q-notification.scss';\n@import '../qComponents/QOption/src/q-option.scss';\n@import '../qComponents/QPagination/src/q-pagination.scss';\n@import '../qComponents/QPopover/src/q-popover.scss';\n@import '../qComponents/QRadio/src/q-radio.scss';\n@import '../qComponents/QRadioGroup/src/q-radio-group.scss';\n@import '../qComponents/QRow/src/q-row.scss';\n@import '../qComponents/QScrollbar/src/q-scrollbar.scss';\n@import '../qComponents/QSelect/src/q-select.scss';\n@import '../qComponents/QSlider/src/q-slider.scss';\n@import '../qComponents/QTable/src/q-table.scss';\n@import '../qComponents/QTabPane/src/q-tab-pane.scss';\n@import '../qComponents/QTabs/src/q-tabs.scss';\n@import '../qComponents/QTag/src/q-tag.scss';\n@import '../qComponents/QTextarea/src/q-textarea.scss';\n@import '../qComponents/QTimePicker/src/q-time-picker.scss';\n@import '../qComponents/QUpload/src/q-upload.scss';\n"
  },
  {
    "path": "src/fonts/index.scss",
    "content": "$--base-path: '..' !default;\n\n@font-face {\n  font-display: swap;\n  font-style: normal;\n  font-weight: 800;\n  font-family: 'Gilroy';\n  src: local('Gilroy ExtraBold'), local('Gilroy-ExtraBold'),\n    url('#{$--base-path}/fonts/Gilroy-ExtraBold.woff?29042020') format('woff');\n}\n\n@font-face {\n  font-display: swap;\n  font-style: normal;\n  font-weight: 600;\n  font-family: 'Gilroy';\n  src: local('Gilroy Bold'), local('Gilroy-Bold'),\n    url('#{$--base-path}/fonts/Gilroy-Bold.woff?29042020') format('woff');\n}\n\n@font-face {\n  font-display: swap;\n  font-style: normal;\n  font-weight: 500;\n  font-family: 'Gilroy';\n  src: local('Gilroy Medium'), local('Gilroy-Medium'),\n    url('#{$--base-path}/fonts/Gilroy-Medium.woff?29042020') format('woff');\n}\n\n@font-face {\n  font-display: swap;\n  font-style: normal;\n  font-weight: 400;\n  font-family: 'Gilroy';\n  src: local('Gilroy Regular'), local('Gilroy-Regular'),\n    url('#{$--base-path}/fonts/Gilroy-Regular.woff?29042020') format('woff');\n}\n"
  },
  {
    "path": "src/icons/index.scss",
    "content": "$--base-path: '..' !default;\n\n@font-face {\n  font-style: normal;\n  font-weight: 400;\n  font-family: 'qicon';\n  src: url('#{$--base-path}/icons/qicon.woff?07092021') format('woff');\n  font-display: block;\n}\n\n[class^='q-icon-'],\n[class*=' q-icon-'] {\n  display: inline-block;\n  font-style: normal;\n  font-variant: normal;\n  font-weight: 400;\n  line-height: 1;\n  // use !important to prevent issues with browser extensions that change fonts\n  // stylelint-disable-next-line font-family-no-missing-generic-family-keyword\n  font-family: 'qicon' !important;\n  vertical-align: baseline;\n  text-transform: none;\n  letter-spacing: 0;\n  speak: none;\n\n  /* Better Font Rendering =========== */\n  -webkit-font-smoothing: antialiased;\n  -moz-osx-font-smoothing: grayscale;\n}\n\n.q-icon-y-4::before {\n  content: '\\e900';\n}\n\n.q-icon-y-3::before {\n  content: '\\e901';\n}\n\n.q-icon-y-2::before {\n  content: '\\e902';\n}\n\n.q-icon-y-1::before {\n  content: '\\e903';\n}\n\n.q-icon-withdraw-fill::before {\n  content: '\\e904';\n}\n\n.q-icon-wifi::before {\n  content: '\\e905';\n}\n\n.q-icon-wallet::before {\n  content: '\\e906';\n}\n\n.q-icon-wallet-stroke::before {\n  content: '\\e907';\n}\n\n.q-icon-view-list::before {\n  content: '\\e908';\n}\n\n.q-icon-triangle-up::before {\n  content: '\\e909';\n}\n\n.q-icon-triangle-right::before {\n  content: '\\e90a';\n}\n\n.q-icon-triangle-left::before {\n  content: '\\e90b';\n}\n\n.q-icon-triangle-down::before {\n  content: '\\e90c';\n}\n\n.q-icon-trash-bin::before {\n  content: '\\e90d';\n}\n\n.q-icon-trash-bin-stroke::before {\n  content: '\\e90e';\n}\n\n.q-icon-target::before {\n  content: '\\e90f';\n}\n\n.q-icon-stop-2::before {\n  content: '\\e910';\n}\n\n.q-icon-stop-1::before {\n  content: '\\e911';\n}\n\n.q-icon-star::before {\n  content: '\\e912';\n}\n\n.q-icon-star-fill::before {\n  content: '\\e913';\n}\n\n.q-icon-settings-vertical::before {\n  content: '\\e914';\n}\n\n.q-icon-settings-horizontal::before {\n  content: '\\e915';\n}\n\n.q-icon-search::before {\n  content: '\\e916';\n}\n\n.q-icon-save::before {\n  content: '\\e917';\n}\n\n.q-icon-rubles::before {\n  content: '\\e918';\n}\n\n.q-icon-rubles-circle::before {\n  content: '\\e919';\n}\n\n.q-icon-router::before {\n  content: '\\e91a';\n}\n\n.q-icon-router-arrow-down::before {\n  content: '\\e91b';\n}\n\n.q-icon-reverse::before {\n  content: '\\e91c';\n}\n\n.q-icon-question::before {\n  content: '\\e91d';\n}\n\n.q-icon-question-mark::before {\n  content: '\\e91e';\n}\n\n.q-icon-proceed-2::before {\n  content: '\\e91f';\n}\n\n.q-icon-proceed-1::before {\n  content: '\\e920';\n}\n\n.q-icon-plus::before {\n  content: '\\e921';\n}\n\n.q-icon-play::before {\n  content: '\\e922';\n}\n\n.q-icon-piggy-bank-fill::before {\n  content: '\\e923';\n}\n\n.q-icon-pic::before {\n  content: '\\e924';\n}\n\n.q-icon-phone-settings-stroke::before {\n  content: '\\e925';\n}\n\n.q-icon-percent::before {\n  content: '\\e926';\n}\n\n.q-icon-pencil-square-stroke::before {\n  content: '\\e927';\n}\n\n.q-icon-pencil-list::before {\n  content: '\\e928';\n}\n\n.q-icon-pause::before {\n  content: '\\e929';\n}\n\n.q-icon-multiply-fill::before {\n  content: '\\e92a';\n}\n\n.q-icon-minus::before {\n  content: '\\e92b';\n}\n\n.q-icon-menu::before {\n  content: '\\e92c';\n}\n\n.q-icon-menu-2-fill::before {\n  content: '\\e92d';\n}\n\n.q-icon-logout::before {\n  content: '\\e92e';\n}\n\n.q-icon-login::before {\n  content: '\\e92f';\n}\n\n.q-icon-lock::before {\n  content: '\\e930';\n}\n\n.q-icon-lock-fill::before {\n  content: '\\e931';\n}\n\n.q-icon-key::before {\n  content: '\\e932';\n}\n\n.q-icon-info::before {\n  content: '\\e933';\n}\n\n.q-icon-info-stroke::before {\n  content: '\\e934';\n}\n\n.q-icon-info-fill::before {\n  content: '\\e935';\n}\n\n.q-icon-house-stroke::before {\n  content: '\\e936';\n}\n\n.q-icon-graph-gisto::before {\n  content: '\\e937';\n}\n\n.q-icon-finish-fill::before {\n  content: '\\e938';\n}\n\n.q-icon-filter-stroke::before {\n  content: '\\e939';\n}\n\n.q-icon-filter-fill::before {\n  content: '\\e93a';\n}\n\n.q-icon-file::before {\n  content: '\\e93b';\n}\n\n.q-icon-eye::before {\n  content: '\\e93c';\n}\n\n.q-icon-eye-fill::before {\n  content: '\\e93d';\n}\n\n.q-icon-eye-close::before {\n  content: '\\e93e';\n}\n\n.q-icon-envelope-edit::before {\n  content: '\\e93f';\n}\n\n.q-icon-earth::before {\n  content: '\\e940';\n}\n\n.q-icon-drag-linear::before {\n  content: '\\e941';\n}\n\n.q-icon-drag-vertical-fill::before {\n  content: '\\e942';\n}\n\n.q-icon-double-triangle-right::before {\n  content: '\\e943';\n}\n\n.q-icon-double-triangle-left::before {\n  content: '\\e944';\n}\n\n.q-icon-dots-3-horizontal::before {\n  content: '\\e945';\n}\n\n.q-icon-diagram-round::before {\n  content: '\\e946';\n}\n\n.q-icon-diagram-round-stroke::before {\n  content: '\\e947';\n}\n\n.q-icon-database-arrow-down::before {\n  content: '\\e948';\n}\n\n.q-icon-credit-card::before {\n  content: '\\e949';\n}\n\n.q-icon-comment::before {\n  content: '\\e94a';\n}\n\n.q-icon-cog-stroke::before {\n  content: '\\e94b';\n}\n\n.q-icon-cloud-upload::before {\n  content: '\\e94c';\n}\n\n.q-icon-cog-fill::before {\n  content: '\\e94d';\n}\n\n.q-icon-close::before {\n  content: '\\e94e';\n}\n\n.q-icon-clock-stroke::before {\n  content: '\\e94f';\n}\n\n.q-icon-checkbox-square-multiply-non::before {\n  content: '\\e950';\n}\n\n.q-icon-check::before {\n  content: '\\e951';\n}\n\n.q-icon-change-list::before {\n  content: '\\e952';\n}\n\n.q-icon-chain::before {\n  content: '\\e953';\n}\n\n.q-icon-cart::before {\n  content: '\\e954';\n}\n\n.q-icon-calendar::before {\n  content: '\\e955';\n}\n\n.q-icon-calendar-refresh::before {\n  content: '\\e956';\n}\n\n.q-icon-calendar-clock::before {\n  content: '\\e957';\n}\n\n.q-icon-bell::before {\n  content: '\\e958';\n}\n\n.q-icon-bell-ring::before {\n  content: '\\e959';\n}\n\n.q-icon-attention-mark::before {\n  content: '\\e95a';\n}\n\n.q-icon-attach-fill::before {\n  content: '\\e95b';\n}\n\n.q-icon-arrow-up::before {\n  content: '\\e95c';\n}\n\n.q-icon-arrow-right::before {\n  content: '\\e95d';\n}\n\n.q-icon-arrow-left::before {\n  content: '\\e95e';\n}\n\n.q-icon-arrow-down::before {\n  content: '\\e95f';\n}\n\n.q-icon-alert-stroke::before {\n  content: '\\e960';\n}\n\n.q-icon-archive-arrow-down::before {\n  content: '\\e961';\n}\n\n.q-icon-alert-fill::before {\n  content: '\\e962';\n}\n\n.q-icon-account::before {\n  content: '\\e963';\n}\n\n.q-icon-account-settings::before {\n  content: '\\e964';\n}\n\n.q-icon-account-group::before {\n  content: '\\e965';\n}\n\n.q-icon-account-group-web::before {\n  content: '\\e966';\n}\n\n.q-icon-account-couple-fill::before {\n  content: '\\e967';\n}\n\n.q-icon-account-check-fill::before {\n  content: '\\e968';\n}\n"
  },
  {
    "path": "src/main.scss",
    "content": "@import './normalize.scss';\n@import './vars.scss';\n@import './transition.scss';\n\n*,\n*::before,\n*::after {\n  box-sizing: border-box;\n}\n\nhtml,\nbody,\n#app {\n  height: 100%;\n}\n\nbody {\n  margin: 0;\n  font-weight: var(--font-weight-base);\n  font-size: var(--font-size-base);\n  line-height: var(--line-height-base);\n  font-family: 'Gilroy', sans-serif;\n  color: rgba(var(--color-rgb-gray), 0.64);\n  letter-spacing: var(--letter-spacing-base);\n  background-color: var(--color-tertiary-gray-lighter);\n}\n\nsvg {\n  vertical-align: middle;\n}\n\nbutton {\n  cursor: pointer;\n\n  &:focus {\n    outline: none;\n  }\n}\n\na {\n  color: var(--color-primary-blue);\n  text-decoration: none;\n\n  &:focus {\n    outline: none;\n  }\n}\n\n/*\n  :focus-visible polyfill.\n  This will hide the focus indicator if the element receives focus via the mouse,\n  but it will still show up on keyboard focus.\n*/\n\n.js-focus-visible :focus:not(.focus-visible) {\n  outline: none;\n}\n"
  },
  {
    "path": "src/normalize.scss",
    "content": "/*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */\n\n/* Document\n   ========================================================================== */\n\n/**\n * 1. Correct the line height in all browsers.\n * 2. Prevent adjustments of font size after orientation changes in iOS.\n */\n\nhtml {\n  line-height: 1.15; /* 1 */\n  -webkit-text-size-adjust: 100%; /* 2 */\n}\n\n/* Sections\n   ========================================================================== */\n\n/**\n * Remove the margin in all browsers.\n */\n\nbody {\n  margin: 0;\n}\n\n/**\n * Render the `main` element consistently in IE.\n */\n\nmain {\n  display: block;\n}\n\n/**\n * Correct the font size and margin on `h1` elements within `section` and\n * `article` contexts in Chrome, Firefox, and Safari.\n */\n\nh1 {\n  margin: 0.67em 0;\n  font-size: 2em;\n}\n\n/* Grouping content\n   ========================================================================== */\n\n/**\n * 1. Add the correct box sizing in Firefox.\n * 2. Show the overflow in Edge and IE.\n */\n\nhr {\n  box-sizing: content-box; /* 1 */\n  height: 0; /* 1 */\n  overflow: visible; /* 2 */\n}\n\n/**\n * 1. Correct the inheritance and scaling of font size in all browsers.\n * 2. Correct the odd `em` font sizing in all browsers.\n */\n\npre {\n  font-size: 1em; /* 2 */\n  font-family: monospace, monospace; /* 1 */\n}\n\n/* Text-level semantics\n   ========================================================================== */\n\n/**\n * Remove the gray background on active links in IE 10.\n */\n\na {\n  background-color: transparent;\n}\n\n/**\n * 1. Remove the bottom border in Chrome 57-\n * 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari.\n */\n\nabbr[title] {\n  text-decoration: underline; /* 2 */\n  text-decoration: underline dotted; /* 2 */\n  border-bottom: none; /* 1 */\n}\n\n/**\n * Add the correct font weight in Chrome, Edge, and Safari.\n */\n\nb,\nstrong {\n  font-weight: bolder;\n}\n\n/**\n * 1. Correct the inheritance and scaling of font size in all browsers.\n * 2. Correct the odd `em` font sizing in all browsers.\n */\n\ncode,\nkbd,\nsamp {\n  font-size: 1em; /* 2 */\n  font-family: monospace, monospace; /* 1 */\n}\n\n/**\n * Add the correct font size in all browsers.\n */\n\nsmall {\n  font-size: 80%;\n}\n\n/**\n * Prevent `sub` and `sup` elements from affecting the line height in\n * all browsers.\n */\n\nsub,\nsup {\n  position: relative;\n  font-size: 75%;\n  line-height: 0;\n  vertical-align: baseline;\n}\n\nsub {\n  bottom: -0.25em;\n}\n\nsup {\n  top: -0.5em;\n}\n\n/* Embedded content\n   ========================================================================== */\n\n/**\n * Remove the border on images inside links in IE 10.\n */\n\nimg {\n  border-style: none;\n}\n\n/* Forms\n   ========================================================================== */\n\n/**\n * 1. Change the font styles in all browsers.\n * 2. Remove the margin in Firefox and Safari.\n */\n\nbutton,\ninput,\noptgroup,\nselect,\ntextarea {\n  margin: 0; /* 2 */\n  font-size: 100%; /* 1 */\n  line-height: 1.15; /* 1 */\n  font-family: inherit; /* 1 */\n}\n\n/**\n * Show the overflow in IE.\n * 1. Show the overflow in Edge.\n */\n\nbutton,\ninput {\n  /* 1 */\n  overflow: visible;\n}\n\n/**\n * Remove the inheritance of text transform in Edge, Firefox, and IE.\n * 1. Remove the inheritance of text transform in Firefox.\n */\n\nbutton,\nselect {\n  /* 1 */\n  text-transform: none;\n}\n\n/**\n * Correct the inability to style clickable types in iOS and Safari.\n */\n\nbutton,\n[type='button'],\n[type='reset'],\n[type='submit'] {\n  -webkit-appearance: button;\n}\n\n/**\n * Remove the inner border and padding in Firefox.\n */\n\nbutton::-moz-focus-inner,\n[type='button']::-moz-focus-inner,\n[type='reset']::-moz-focus-inner,\n[type='submit']::-moz-focus-inner {\n  padding: 0;\n  border-style: none;\n}\n\n/**\n * Correct the padding in Firefox.\n */\n\nfieldset {\n  padding: 0.35em 0.75em 0.625em;\n}\n\n/**\n * 1. Correct the text wrapping in Edge and IE.\n * 2. Correct the color inheritance from `fieldset` elements in IE.\n * 3. Remove the padding so developers are not caught out when they zero out\n *    `fieldset` elements in all browsers.\n */\n\nlegend {\n  display: table; /* 1 */\n  box-sizing: border-box; /* 1 */\n  max-width: 100%; /* 1 */\n  padding: 0; /* 3 */\n  color: inherit; /* 2 */\n  white-space: normal; /* 1 */\n}\n\n/**\n * Add the correct vertical alignment in Chrome, Firefox, and Opera.\n */\n\nprogress {\n  vertical-align: baseline;\n}\n\n/**\n * Remove the default vertical scrollbar in IE 10+.\n */\n\ntextarea {\n  overflow: auto;\n}\n\n/**\n * 1. Add the correct box sizing in IE 10.\n * 2. Remove the padding in IE 10.\n */\n\n[type='checkbox'],\n[type='radio'] {\n  box-sizing: border-box; /* 1 */\n  padding: 0; /* 2 */\n}\n\n/**\n * Correct the cursor style of increment and decrement buttons in Chrome.\n */\n\n[type='number']::-webkit-inner-spin-button,\n[type='number']::-webkit-outer-spin-button {\n  height: auto;\n}\n\n/**\n * 1. Correct the odd appearance in Chrome and Safari.\n * 2. Correct the outline style in Safari.\n */\n\n[type='search'] {\n  -webkit-appearance: textfield; /* 1 */\n  outline-offset: -2px; /* 2 */\n}\n\n/**\n * Remove the inner padding in Chrome and Safari on macOS.\n */\n\n[type='search']::-webkit-search-decoration {\n  -webkit-appearance: none;\n}\n\n/**\n * 1. Correct the inability to style clickable types in iOS and Safari.\n * 2. Change font properties to `inherit` in Safari.\n */\n\n::-webkit-file-upload-button {\n  -webkit-appearance: button; /* 1 */\n  font: inherit; /* 2 */\n}\n\n/* Interactive\n   ========================================================================== */\n\n/*\n * Add the correct display in Edge, IE 10+, and Firefox.\n */\n\ndetails {\n  display: block;\n}\n\n/*\n * Add the correct display in all browsers.\n */\n\nsummary {\n  display: list-item;\n}\n\n/* Misc\n   ========================================================================== */\n\n/**\n * Add the correct display in IE 10+.\n */\n\ntemplate {\n  display: none;\n}\n\n/**\n * Add the correct display in IE 10.\n */\n\n[hidden] {\n  display: none;\n}\n"
  },
  {
    "path": "src/onDemand.js",
    "content": "/* eslint-disable global-require */\n/* eslint-disable no-param-reassign */\nimport vClickOutside from 'v-click-outside';\nimport 'focus-visible';\nimport { version } from '../package.json';\nimport { installI18n } from './qComponents/constants/locales';\n\nconst install = (\n  Vue,\n  {\n    localization: { locale = 'ru', customI18nMessages = {} } = {},\n    zIndexCounter = 2000\n  } = {}\n) => {\n  Vue.prototype.$Q = {};\n  // define plugins\n  Object.defineProperties(Vue.prototype.$Q, {\n    zIndex: {\n      get() {\n        zIndexCounter += 1;\n        return zIndexCounter;\n      }\n    },\n    locale: {\n      value: locale\n    }\n  });\n\n  Vue.use(vClickOutside);\n  installI18n({ locale, customI18nMessages });\n};\n\nconst Qui = {\n  version,\n  install\n};\n\nexport default Qui;\n"
  },
  {
    "path": "src/qComponents/QBreadcrumbs/QBreadcrumbs.test.js",
    "content": "import Component from './src/QBreadcrumbs';\n\ndescribe('QBreadcrumbs', () => {\n  let instance;\n  let options;\n\n  beforeEach(() => {\n    options = {\n      mocks: {\n        $route: { matched: [{ meta: 'one' }] }\n      }\n    };\n\n    instance = shallowMount(Component, options);\n  });\n\n  it('should match snapshot', () => {\n    expect(instance.element).toMatchSnapshot();\n  });\n\n  describe('computed', () => {\n    it('lastCrumb should return custom last crumb if it has been passed', () => {\n      const expected = 'one';\n      instance.setProps({\n        last: expected\n      });\n\n      expect(instance.vm.lastCrumb).toEqual(expected);\n    });\n  });\n\n  describe('pushTo', () => {\n    it(`should return the router's 'name' if it has been passed`, () => {\n      const route = { name: 'R_MAIN', path: '/main' };\n      const expected = { name: route.name };\n      expect(instance.vm.pushTo(route)).toEqual(expected);\n    });\n\n    it(`should return the router's 'path' if the 'name' hasn't been passed`, () => {\n      const route = { path: '/main' };\n      const expected = route.path;\n      expect(instance.vm.pushTo(route)).toEqual(expected);\n    });\n  });\n});\n"
  },
  {
    "path": "src/qComponents/QBreadcrumbs/__snapshots__/QBreadcrumbs.test.js.snap",
    "content": "// Jest Snapshot v1, https://goo.gl/fbAQLP\n\nexports[`QBreadcrumbs should match snapshot 1`] = `\n<div\n  class=\"q-breadcrumbs\"\n>\n   \n  <div\n    class=\"q-breadcrumbs__crumb q-breadcrumbs__crumb_last\"\n  >\n    \n    \n  \n  </div>\n</div>\n`;\n"
  },
  {
    "path": "src/qComponents/QBreadcrumbs/index.js",
    "content": "import QBreadcrumbs from './src/QBreadcrumbs.vue';\n\n/* istanbul ignore next */\nQBreadcrumbs.install = function(Vue) {\n  Vue.component(QBreadcrumbs.name, QBreadcrumbs);\n};\n\nexport default QBreadcrumbs;\n"
  },
  {
    "path": "src/qComponents/QBreadcrumbs/src/QBreadcrumbs.vue",
    "content": "<template>\n  <div class=\"q-breadcrumbs\">\n    <template v-for=\"crumb in breadcrumbs\">\n      <router-link\n        :key=\"crumb.name || crumb.path\"\n        :to=\"pushTo(crumb)\"\n        active-class=\"q-breadcrumbs__crumb_active\"\n        exact-active-class=\"q-breadcrumbs__crumb_exact-active\"\n        class=\"q-breadcrumbs__crumb\"\n      >\n        {{ crumb.meta.breadcrumb }}\n      </router-link>\n\n      <span\n        :key=\"`${crumb.name || crumb.path}divider`\"\n        class=\"q-breadcrumbs__divider q-icon-arrow-right\"\n      />\n    </template>\n\n    <div class=\"q-breadcrumbs__crumb q-breadcrumbs__crumb_last\">\n      {{ lastCrumb }}\n    </div>\n  </div>\n</template>\n\n<script>\nexport default {\n  name: 'QBreadcrumbs',\n  componentName: 'QBreadcrumbs',\n\n  /**\n   * if you have vue router, QBreadcrumbs will get crumbs from this.$route.matched\n   */\n  props: {\n    /**\n     * custom last crumb\n     */\n    last: {\n      type: String,\n      default: null\n    },\n    /**\n     * Array of Objects, object must contain required fields: `path` - uses as route path, `name` - route name, `meta` - must contain `breadcrumb` - visible title\n     */\n    customRoutes: {\n      type: Array,\n      default: null\n    }\n  },\n\n  computed: {\n    crumbs() {\n      const routes = this.customRoutes ?? this.$route.matched;\n\n      return routes.filter(route => route.meta?.breadcrumb);\n    },\n\n    breadcrumbs() {\n      const breadcrumbs = [...this.crumbs];\n      breadcrumbs.pop();\n      return breadcrumbs;\n    },\n\n    lastCrumb() {\n      if (this.last) return this.last;\n\n      return this.crumbs[this.crumbs.length - 1]?.meta.breadcrumb ?? '';\n    }\n  },\n\n  methods: {\n    pushTo({ name, path }) {\n      return name ? { name } : path;\n    }\n  }\n};\n</script>\n"
  },
  {
    "path": "src/qComponents/QBreadcrumbs/src/q-breadcrumbs.scss",
    "content": ".q-breadcrumbs {\n  display: inline-grid;\n  grid-auto-flow: column;\n  align-items: baseline;\n  max-width: 100%;\n\n  &__divider {\n    position: relative;\n    top: 5px;\n    margin-right: 8px;\n    margin-left: 8px;\n    font-size: 24px;\n    color: rgba(var(--color-rgb-gray), 0.32);\n  }\n\n  &__crumb {\n    overflow: hidden;\n    font-weight: 800;\n    font-size: 24px;\n    line-height: 31px;\n    color: var(--color-primary-blue);\n    white-space: nowrap;\n    text-overflow: ellipsis;\n\n    &:focus {\n      text-decoration: underline;\n    }\n\n    &_last:first-child {\n      color: var(--color-primary-black);\n    }\n\n    &_exact-active:not(:first-child),\n    &_last:not(:first-child) {\n      font-weight: var(--font-weight-bold);\n      font-size: 16px;\n      line-height: var(--line-height-base);\n      color: var(--color-primary-black);\n      cursor: default;\n    }\n  }\n}\n"
  },
  {
    "path": "src/qComponents/QButton/QButton.test.js",
    "content": "import Component from './src/QButton';\n\ndescribe('QButton', () => {\n  it('should match snapshot', () => {\n    const { element } = shallowMount(Component);\n    expect(element).toMatchSnapshot();\n  });\n\n  it(`should have class 'q-button_type_icon' if type is icon`, () => {\n    const instance = shallowMount(Component);\n    const expected = 'q-button_type_icon';\n    instance.setProps({\n      type: 'icon'\n    });\n    expect(instance.vm.classes).toContain(expected);\n  });\n\n  it(`should have class 'q-button_theme_link' if theme is link`, () => {\n    const instance = shallowMount(Component);\n    const expected = 'q-button_theme_link';\n    instance.setProps({\n      theme: 'link'\n    });\n    expect(instance.vm.classes).toContain(expected);\n  });\n\n  describe('handleClick', () => {\n    it('should emit click', () => {\n      const instance = shallowMount(Component);\n      instance.vm.handleClick();\n      expect(instance.emitted().click).toBeTruthy();\n    });\n  });\n});\n"
  },
  {
    "path": "src/qComponents/QButton/__snapshots__/QButton.test.js.snap",
    "content": "// Jest Snapshot v1, https://goo.gl/fbAQLP\n\nexports[`QButton should match snapshot 1`] = `\n<button\n  class=\"q-button q-button_theme_primary q-button_type_default q-button_size_medium\"\n  type=\"button\"\n>\n  <!---->\n   \n  <!---->\n   \n  <!---->\n</button>\n`;\n"
  },
  {
    "path": "src/qComponents/QButton/index.js",
    "content": "import QButton from './src/QButton.vue';\n\n/* istanbul ignore next */\nQButton.install = function(Vue) {\n  Vue.component(QButton.name, QButton);\n};\n\nexport default QButton;\n"
  },
  {
    "path": "src/qComponents/QButton/src/QButton.vue",
    "content": "<template>\n  <button\n    class=\"q-button\"\n    :disabled=\"disabled || loading\"\n    :autofocus=\"autofocus\"\n    :type=\"nativeType\"\n    :class=\"classes\"\n    @click=\"handleClick\"\n  >\n    <span\n      v-if=\"loading\"\n      class=\"q-icon-reverse\"\n    />\n    <span\n      v-if=\"icon && !loading\"\n      :class=\"icon\"\n    />\n    <span\n      v-if=\"$slots.default\"\n      class=\"q-button__inner\"\n    >\n      <slot />\n    </span>\n  </button>\n</template>\n\n<script>\nexport default {\n  name: 'QButton',\n  componentName: 'QButton',\n\n  inject: {\n    qForm: {\n      default: null\n    }\n  },\n\n  props: {\n    type: {\n      type: String,\n      default: 'default',\n      validator: value => ['default', 'icon'].includes(value)\n    },\n    theme: {\n      type: String,\n      default: 'primary',\n      validator: value => ['primary', 'secondary', 'link'].includes(value)\n    },\n    size: {\n      type: String,\n      default: 'medium',\n      validator: value => ['small', 'medium'].includes(value)\n    },\n    /**\n     * any q-icon\n     */\n    icon: {\n      type: String,\n      default: ''\n    },\n    /**\n     * as native button type\n     */\n    nativeType: {\n      type: String,\n      default: 'button'\n    },\n    /**\n     * whether to show loader inside button\n     */\n    loading: {\n      type: Boolean,\n      default: false\n    },\n    /**\n     * whether the button is disabled\n     */\n    disabled: {\n      type: Boolean,\n      default: false\n    },\n    /**\n     * as native button autofocus\n     */\n    autofocus: {\n      type: Boolean,\n      default: false\n    },\n    /**\n     * change button's shape to circle (use with type icon)\n     */\n    circle: {\n      type: Boolean,\n      default: false\n    },\n    /**\n     * sets button width to 100%\n     */\n    fullWidth: {\n      type: Boolean,\n      default: false\n    }\n  },\n\n  computed: {\n    classes() {\n      const classes = Object.entries({\n        theme: this.theme,\n        type: this.type,\n        size: this.size\n      })\n        .filter(([, value]) => Boolean(value))\n        .map(([key, value]) => `q-button_${key}_${value}`);\n\n      classes.push({\n        'q-button_disabled': this.disabled || (this.qForm?.disabled ?? false),\n        'q-button_loading': this.loading,\n        'q-button_circle': this.circle,\n        'q-button_full-width': this.fullWidth\n      });\n\n      return classes;\n    }\n  },\n\n  methods: {\n    handleClick(evt) {\n      this.$emit('click', evt);\n    }\n  }\n};\n</script>\n"
  },
  {
    "path": "src/qComponents/QButton/src/q-button.scss",
    "content": ".q-button {\n  display: inline-block;\n  box-sizing: border-box;\n  max-height: 40px;\n  padding: 12px 40px;\n  font-weight: var(--font-weight-bold);\n  font-size: 12px;\n  line-height: var(--line-height-button);\n  vertical-align: middle;\n  text-align: center;\n  color: var(--color-tertiary-white);\n  text-transform: uppercase;\n  letter-spacing: var(--letter-spacing-base);\n  white-space: nowrap;\n  background-color: var(--color-primary);\n  background-image: var(--gradient-primary);\n  border: none;\n  border-radius: var(--border-radius-base);\n  outline: none;\n  box-shadow: -1px -1px 3px rgba(var(--color-rgb-white), 0.25),\n    1px 1px 3px rgba(var(--color-rgb-blue), 0.4),\n    4px 4px 8px rgba(var(--color-rgb-blue), 0.4),\n    -4px -4px 12px var(--color-tertiary-white);\n  cursor: pointer;\n  transition: background-color 0.1s;\n  appearance: none;\n\n  & + & {\n    margin-left: 16px;\n  }\n\n  &:focus {\n    outline: none;\n  }\n\n  &:hover {\n    background-color: var(--color-primary);\n    background-image: none;\n    box-shadow: -1px -1px 4px rgba(var(--color-rgb-white), 0.25),\n      1px 1px 4px rgba(var(--color-rgb-blue), 0.4),\n      4px 4px 8px rgba(var(--color-rgb-blue), 0.4),\n      -4px -4px 8px rgba(var(--color-rgb-white), 0.8);\n  }\n\n  &:active {\n    background-image: none;\n    box-shadow: var(--box-shadow-pressed);\n  }\n\n  &:visited {\n    background-image: var(--gradient-primary);\n    box-shadow: var(--box-shadow-primary);\n  }\n\n  &::-moz-focus-inner {\n    border: 0;\n  }\n\n  &_type {\n    &_icon {\n      display: inline-flex;\n      justify-content: center;\n      align-items: center;\n      width: 40px;\n      height: 40px;\n      padding: 0;\n      font-size: 26px;\n    }\n  }\n\n  &_theme {\n    &_primary {\n      &.focus-visible {\n        background-color: var(--color-primary-darker);\n        background-image: none;\n      }\n    }\n\n    &_secondary {\n      color: var(--color-primary-blue);\n      background-color: var(--color-tertiary-gray);\n      background-image: none;\n      box-shadow: var(--box-shadow-primary);\n\n      &:hover {\n        color: var(--color-tertiary-white);\n        background-color: var(--color-primary);\n        box-shadow: var(--box-shadow-hover);\n      }\n\n      &:active {\n        outline: none;\n        box-shadow: var(--box-shadow-pressed);\n      }\n\n      &.focus-visible {\n        color: var(--color-tertiary-white);\n        background-color: var(--color-primary-darker);\n      }\n    }\n\n    &_link {\n      padding: 0;\n      font-weight: var(--font-weight-base);\n      font-size: var(--font-size-base);\n      color: var(--color-primary-blue);\n      text-transform: initial;\n      background-color: transparent;\n      background-image: none;\n      box-shadow: none;\n\n      &.focus-visible {\n        text-decoration: underline;\n      }\n\n      &:hover {\n        color: var(--color-primary-black);\n        background-color: transparent;\n        box-shadow: none;\n      }\n\n      &:active {\n        outline: none;\n        box-shadow: none;\n      }\n    }\n  }\n\n  &_size {\n    &_small {\n      &.q-button_type_icon {\n        width: 24px;\n        height: 24px;\n        padding: 0;\n        font-size: 16px;\n        line-height: 1;\n      }\n\n      &.q-button_theme_link {\n        font-size: 12px;\n      }\n    }\n  }\n\n  &_full-width {\n    width: 100%;\n  }\n\n  &_disabled {\n    --color: rgba(var(--color-rgb-gray), 0.64);\n    --background-color: var(--color-tertiary-gray);\n    --box-shadow: 1px 1px 3px rgba(var(--color-rgb-blue), 0.4),\n      -1px -1px 3px rgba(var(--color-rgb-white), 0.25);\n\n    color: var(--color);\n    background-color: var(--background-color);\n    background-image: none;\n    box-shadow: var(--box-shadow);\n    cursor: not-allowed;\n\n    &:hover,\n    &:active {\n      color: var(--color);\n      background-color: var(--background-color);\n      box-shadow: var(--box-shadow);\n    }\n\n    &.q-button_theme_link {\n      --box-shadow: none;\n      --background-color: transparent;\n    }\n  }\n\n  &_loading {\n    position: relative;\n    pointer-events: none;\n\n    .q-button__inner {\n      margin-left: 0;\n      visibility: hidden;\n    }\n\n    .q-icon-reverse {\n      --icon-size: 24px;\n\n      position: absolute;\n      top: calc(50% - var(--icon-size) / 2);\n      left: calc(50% - var(--icon-size) / 2);\n      font-size: var(--icon-size);\n      transform-origin: calc(var(--icon-size) / 2);\n      animation: rotating 2s linear infinite;\n    }\n\n    &.q-button_size_small {\n      .q-icon-reverse {\n        --icon-size: 16px;\n      }\n    }\n\n    &::before {\n      content: '';\n      position: absolute;\n      top: 0;\n      right: 0;\n      bottom: 0;\n      left: 0;\n      border-radius: inherit;\n      pointer-events: none;\n    }\n  }\n\n  &_circle {\n    border-radius: 50%;\n  }\n}\n\n@keyframes rotating {\n  0% {\n    transform: rotateZ(0deg);\n  }\n\n  100% {\n    transform: rotateZ(360deg);\n  }\n}\n"
  },
  {
    "path": "src/qComponents/QCascader/QCascader.test.js",
    "content": "import Component from './src/QCascader';\n\nconst module = require('../helpers');\n\nmodule.randId = jest.fn();\n\ndescribe('QCascader', () => {\n  let instance;\n  let options;\n\n  beforeEach(() => {\n    options = {\n      mocks: { $t: () => {} },\n      propsData: {\n        value: 'resource',\n        placeholder: 'placeholder',\n        options: [\n          {\n            value: 'guide',\n            label: 'Guide',\n            children: [\n              {\n                value: 'child',\n                label: 'Child',\n                children: [{ value: 'next child', label: 'Next child' }]\n              }\n            ]\n          },\n          { value: 'resource', label: 'Resource' }\n        ]\n      }\n    };\n\n    instance = mount(Component, options);\n  });\n\n  it('should match snapshot', () => {\n    const spy = prefix => `${prefix}000`;\n    module.randId.mockImplementation(spy);\n    instance = mount(Component, options);\n    expect(instance.element).toMatchSnapshot();\n  });\n\n  it('data should match snapshot', () => {\n    expect(Component.data()).toMatchSnapshot();\n  });\n\n  describe('computed', () => {\n    describe('model', () => {\n      it('should set inputValue if has been changed', () => {\n        const expected = 'guide';\n        instance.vm.model = expected;\n\n        expect(instance.vm.inputValue).toEqual(expected);\n      });\n    });\n\n    describe('isClearBtnVisible', () => {\n      it('should return false if showClose is false', async () => {\n        await instance.setData({ showClose: false });\n        expect(instance.vm.isClearBtnVisible).toBeFalsy();\n      });\n\n      it('should return true if showClose is true', async () => {\n        await instance.setData({ showClose: true });\n        expect(instance.vm.isClearBtnVisible).toBeTruthy();\n      });\n    });\n  });\n\n  describe('watch', () => {\n    describe('value', () => {\n      it('should set checkedValues if value is array', async () => {\n        const expected = ['guide', 'child'];\n        await instance.setProps({ value: expected });\n        expect(instance.vm.checkedValues).toEqual(expected);\n      });\n    });\n  });\n});\n"
  },
  {
    "path": "src/qComponents/QCascader/__snapshots__/QCascader.test.js.snap",
    "content": "// Jest Snapshot v1, https://goo.gl/fbAQLP\n\nexports[`QCascader data should match snapshot 1`] = `\nObject {\n  \"areTagsHovered\": false,\n  \"checkedNodes\": Array [],\n  \"checkedValues\": Array [],\n  \"focus\": false,\n  \"id\": \"q-cascader-000\",\n  \"inputInitialHeight\": 0,\n  \"inputValue\": null,\n  \"popper\": null,\n  \"presentText\": null,\n  \"showClose\": false,\n}\n`;\n\nexports[`QCascader should match snapshot 1`] = `\n<div\n  class=\"q-cascader\"\n>\n  <div\n    class=\"q-input q-input_suffix\"\n  >\n    <!---->\n     \n    <input\n      aria-controls=\"q-cascader-000\"\n      aria-haspopup=\"true\"\n      aria-label=\"\"\n      autocomplete=\"off\"\n      class=\"q-input__inner\"\n      placeholder=\"placeholder\"\n      readonly=\"readonly\"\n      role=\"button\"\n      tabindex=\"\"\n      type=\"text\"\n    />\n     \n    <span\n      class=\"q-input__suffix\"\n    >\n      <span\n        class=\"q-input__suffix-inner\"\n      >\n        <span\n          class=\"q-input__icon q-icon-triangle-down\"\n        />\n         \n        <!---->\n         \n        <!---->\n      </span>\n    </span>\n  </div>\n   \n  <!---->\n   \n  <div\n    class=\"q-cascader-panel\"\n  >\n    <div\n      aria-labelledby=\"q-cascader-000\"\n      class=\"q-cascader-menu\"\n      role=\"menu\"\n    >\n      <div\n        class=\"q-cascader-menu__wrap\"\n      >\n        <div\n          class=\"q-scrollbar q-scrollbar_has-horizontal-bar q-scrollbar_has-vertical-bar\"\n        >\n          <div\n            class=\"q-scrollbar__wrap q-cascader-menu__scrollbar q-scrollbar__wrap_hidden-default\"\n          >\n            <div\n              class=\"q-scrollbar__view\"\n            >\n              <div\n                class=\"q-cascader-node\"\n                id=\"q-cascader-000-node-0-0\"\n                role=\"menuitem\"\n                tabindex=\"-1\"\n              >\n                <!---->\n                 \n                <span\n                  class=\"q-cascader-node__label\"\n                >\n                  Guide\n                </span>\n                 \n                <span\n                  class=\"q-cascader-node__postfix q-icon-triangle-right\"\n                />\n              </div>\n              <div\n                class=\"q-cascader-node\"\n                id=\"q-cascader-000-node-0-1\"\n                role=\"menuitem\"\n                tabindex=\"-1\"\n              >\n                <!---->\n                 \n                <span\n                  class=\"q-cascader-node__label\"\n                >\n                  Resource\n                </span>\n                 \n                <!---->\n              </div>\n            </div>\n          </div>\n           \n          <div\n            class=\"q-scrollbar__bar q-scrollbar__bar_horizontal\"\n          >\n            <div\n              class=\"q-scrollbar__thumb\"\n              style=\"width: 0px; transform: translateX(0%); webkit-transform: translateX(0%);\"\n            />\n          </div>\n           \n          <div\n            class=\"q-scrollbar__bar q-scrollbar__bar_vertical\"\n          >\n            <div\n              class=\"q-scrollbar__thumb\"\n              style=\"height: 0px; transform: translateY(0%); webkit-transform: translateY(0%);\"\n            />\n          </div>\n        </div>\n      </div>\n    </div>\n  </div>\n</div>\n`;\n"
  },
  {
    "path": "src/qComponents/QCascader/index.js",
    "content": "import QCascader from './src/QCascader';\n\n/* istanbul ignore next */\nQCascader.install = function(Vue) {\n  Vue.component(QCascader.name, QCascader);\n};\n\nexport default QCascader;\n"
  },
  {
    "path": "src/qComponents/QCascader/src/QCascader.vue",
    "content": "<template>\n  <div\n    ref=\"reference\"\n    v-click-outside=\"hidePopper\"\n    :class=\"['q-cascader', { 'q-cascader_disabled': isDisabled }]\"\n  >\n    <q-input\n      ref=\"input\"\n      v-model=\"model\"\n      readonly\n      :placeholder=\"calcPlaceholder\"\n      :disabled=\"isDisabled\"\n      :validate-event=\"false\"\n      aria-haspopup=\"true\"\n      role=\"button\"\n      :aria-controls=\"id\"\n      :aria-expanded=\"popper\"\n      :class=\"{\n        'q-input_focus': Boolean(popper),\n        'q-input_hover': areTagsHovered\n      }\"\n      @mouseenter.native=\"handleMouseEnter\"\n      @mouseleave.native=\"showClose = false\"\n      @focus=\"handleInputFocus\"\n      @click=\"togglePopper\"\n    >\n      <template slot=\"suffix\">\n        <span\n          v-if=\"isClearBtnVisible\"\n          key=\"clear\"\n          class=\"q-input__icon q-icon-close\"\n          @click.stop=\"handleClear\"\n        />\n        <span\n          v-else\n          key=\"arrow-down\"\n          :class=\"[\n            'q-input__icon',\n            'q-icon-triangle-down',\n            Boolean(popper) && 'q-icon-triangle-down_reverse'\n          ]\"\n        />\n      </template>\n    </q-input>\n\n    <div\n      v-if=\"multiple\"\n      class=\"q-cascader__tags\"\n      @click=\"togglePopper\"\n      @mouseenter=\"handleTagsHover\"\n      @mouseleave=\"handleTagsLeave\"\n    >\n      <template v-if=\"collapseTags\">\n        <q-tag\n          v-for=\"(tag, index) in checkedNodes.slice(0, 1)\"\n          :key=\"index\"\n          closable\n          @close=\"deleteTag(tag)\"\n        >\n          <span\n            v-if=\"allLevelsShown\"\n            class=\"q-cascader__tag-text\"\n          >{{\n            tag.fullPathLabel\n          }}</span>\n          <span\n            v-else\n            class=\"q-cascader__tag-text\"\n          >{{ tag.label }}</span>\n        </q-tag>\n        <q-tag v-if=\"checkedNodes.length > 1\">\n          <span\n            class=\"q-cascader__tag-text\"\n          >+{{ checkedNodes.length - 1 }}</span>\n        </q-tag>\n      </template>\n      <template v-else>\n        <q-tag\n          v-for=\"(tag, index) in checkedNodes\"\n          :key=\"index\"\n          closable\n          @close=\"deleteTag(tag)\"\n        >\n          <span\n            v-if=\"allLevelsShown\"\n            class=\"q-cascader__tag-text\"\n          >{{\n            tag.fullPathLabel\n          }}</span>\n          <span\n            v-else\n            class=\"q-cascader__tag-text\"\n          >{{ tag.label }}</span>\n        </q-tag>\n      </template>\n    </div>\n\n    <q-cascader-panel\n      ref=\"panel\"\n      v-model=\"checkedValues\"\n      :options=\"options\"\n    />\n  </div>\n</template>\n\n<script>\nimport { createPopper } from '@popperjs/core';\nimport Emitter from '../../mixins/emitter';\nimport { addResizeListener, removeResizeListener, randId } from '../../helpers';\n\nimport QCascaderPanel from './QCascaderPanel';\n\nconst DEFAULT_INPUT_HEIGHT = 40;\n\nconst findFullPath = (branches, find) => {\n  let level = null;\n  for (let i = 0; i < branches.length; i += 1) {\n    if (branches[i].value === find) {\n      level = [branches[i].label];\n      break;\n    }\n    if (branches[i].children) {\n      const nextLevel = findFullPath(branches[i].children, find);\n      if (nextLevel !== null) {\n        level = [branches[i].label, nextLevel].flat(Infinity);\n      }\n    }\n  }\n\n  return level;\n};\n\nconst getCheckedNodes = (options, checkedValues, separator) => {\n  return options.reduce((acc, firstLevelOption) => {\n    const getChecked = option => {\n      if (checkedValues.includes(option.value)) {\n        const transformedOption = {\n          ...option,\n          fullPathLabel: findFullPath(options, option.value).join(separator)\n        };\n\n        acc.push(transformedOption);\n      }\n\n      if (option.children) {\n        option.children.forEach(getChecked);\n      }\n    };\n\n    getChecked(firstLevelOption);\n    return acc;\n  }, []);\n};\n\nexport default {\n  name: 'QCascader',\n  componentName: 'QCascader',\n\n  components: {\n    QCascaderPanel\n  },\n\n  mixins: [Emitter],\n\n  inject: {\n    qForm: {\n      default: null\n    },\n    qFormItem: {\n      default: null\n    }\n  },\n\n  props: {\n    /**\n     * Array for multiple value, String for single\n     */\n    value: { type: [String, Array], default: null },\n    /**\n     * array of objects with required fields, example:\n     * ```{\n      value: 'guide',\n      label: 'Guide',\n      children: [{ ... }]\n      }```\n     */\n    options: { type: Array, default: null },\n    /**\n     * as native placeholder\n     */\n    placeholder: {\n      type: String,\n      default: null\n    },\n    /**\n     * whether QCascader is disabled\n     */\n    disabled: {\n      type: Boolean,\n      default: false\n    },\n    /**\n     * whether QCascader is clearable\n     */\n    clearable: {\n      type: Boolean,\n      default: true\n    },\n    /**\n     * pick several values\n     */\n    multiple: {\n      type: Boolean,\n      default: false\n    },\n    /**\n     * check each value as independent\n     */\n    checkStrictly: {\n      type: Boolean,\n      default: false\n    },\n    /**\n     * separator in tags\n     */\n    separator: {\n      type: String,\n      default: ' / '\n    },\n    /**\n     * whether all path to value in tags is shown\n     */\n    allLevelsShown: {\n      type: Boolean,\n      default: true\n    },\n    /**\n     * hide tags in counter\n     */\n    collapseTags: { type: Boolean, default: true }\n  },\n\n  provide() {\n    return {\n      cascader: this\n    };\n  },\n\n  data() {\n    return {\n      checkedValues: [],\n      inputValue: null,\n      presentText: null,\n      checkedNodes: [],\n      inputInitialHeight: 0,\n      popper: null,\n      showClose: false,\n      areTagsHovered: false,\n      focus: false,\n      id: randId('q-cascader-')\n    };\n  },\n\n  computed: {\n    model: {\n      get() {\n        return this.presentText;\n      },\n      set(value) {\n        this.inputValue = value;\n      }\n    },\n\n    calcPlaceholder() {\n      return this.checkedNodes.length\n        ? ''\n        : this.placeholder ?? this.$t('QCascader.placeholder');\n    },\n\n    isDisabled() {\n      return this.disabled || (this.qForm?.disabled ?? false);\n    },\n\n    isClearBtnVisible() {\n      return Boolean(this.value?.length) && this.showClose;\n    },\n\n    panel() {\n      return this.$refs.panel;\n    }\n  },\n\n  watch: {\n    value: {\n      immediate: true,\n      handler(value) {\n        if (Array.isArray(value) || (this.multiple && value === null)) {\n          this.checkedValues = value;\n        } else {\n          this.inputValue = value;\n        }\n      }\n    },\n\n    checkedValues(val) {\n      this.calcTags(val);\n    },\n\n    inputValue: {\n      immediate: true,\n      handler(val) {\n        if (val) {\n          const fullPath = findFullPath(this.options, val);\n          if (this.allLevelsShown) {\n            this.presentText = fullPath.join(this.separator);\n          } else {\n            this.presentText = fullPath[fullPath.length - 1];\n          }\n        } else {\n          this.presentText = null;\n          if (this.$refs.panel) {\n            this.$refs.panel.activePath = [];\n            this.$refs.panel.menus = [this.options];\n          }\n        }\n      }\n    },\n\n    checkedNodes() {\n      if (this.multiple) {\n        this.$nextTick(this.updateStyle);\n      }\n    }\n  },\n\n  mounted() {\n    const { input } = this.$refs;\n    this.inputInitialHeight = input?.$el?.offsetHeight ?? DEFAULT_INPUT_HEIGHT;\n\n    addResizeListener(this.$el, this.updateStyle);\n    document.addEventListener('keyup', this.handleKeyUp, true);\n  },\n\n  beforeDestroy() {\n    removeResizeListener(this.$el, this.updateStyle);\n    document.removeEventListener('keyup', this.handleKeyUp, true);\n  },\n\n  methods: {\n    handleKeyUp(e) {\n      if (!this.focus) return;\n      if (e.target.classList.contains('q-input__inner') && e.key === 'Enter') {\n        this.togglePopper();\n      }\n\n      switch (e.key) {\n        case 'Escape': {\n          this.$refs.input.blur();\n          this.hidePopper();\n          break;\n        }\n\n        case 'Backspace': {\n          this.deleteTag();\n          break;\n        }\n\n        case 'Tab': {\n          if (!this.$refs.reference.contains(document.activeElement)) {\n            this.hidePopper();\n            this.focus = false;\n          }\n          break;\n        }\n\n        case 'ArrowRight':\n        case 'ArrowUp':\n        case 'ArrowLeft':\n        case 'ArrowDown': {\n          this.$refs.panel.navigateFocus(e);\n          break;\n        }\n\n        default:\n          break;\n      }\n    },\n\n    handleTagsHover() {\n      this.areTagsHovered = true;\n      this.showClose = true;\n    },\n\n    handleTagsLeave() {\n      this.areTagsHovered = false;\n      this.showClose = false;\n    },\n\n    handleMouseEnter() {\n      if (this.disabled) return;\n      if (this.clearable && this.value) {\n        this.showClose = true;\n      }\n    },\n\n    deleteTag({ value } = {}) {\n      if (!this.checkedValues) return;\n\n      const result = new Set(this.checkedValues);\n      if (value) {\n        result.delete(value);\n      } else {\n        result.delete(this.checkedValues[this.checkedValues.length - 1]);\n      }\n\n      const payload = Array.from(result);\n      this.emit(payload.length ? payload : null);\n    },\n\n    emit(val) {\n      this.$emit('change', val);\n      this.qFormItem?.validateField('change');\n    },\n\n    handleClear() {\n      this.emit(null);\n      this.showClose = false;\n    },\n\n    calcTags(checkedValues) {\n      if (!checkedValues) {\n        this.checkedNodes = [];\n        return;\n      }\n\n      this.checkedNodes = getCheckedNodes(\n        this.options,\n        this.checkedValues,\n        this.separator\n      );\n    },\n\n    togglePopper() {\n      if (this.popper) {\n        this.hidePopper();\n      } else {\n        this.showPopper();\n      }\n    },\n\n    showPopper() {\n      if (this.isDisabled) return;\n      this.$refs.panel?.$el.setAttribute('data-show', '');\n      this.popper = createPopper(this.$refs.reference, this.$refs.panel?.$el, {\n        placement: 'bottom-start',\n        modifiers: [\n          {\n            name: 'offset',\n            options: {\n              offset: [0, 8]\n            }\n          }\n        ]\n      });\n\n      this.$refs.panel.$el.style.zIndex = this.$Q?.zIndex ?? 2000;\n    },\n\n    hidePopper() {\n      if (this.popper) {\n        this.$refs.panel?.$el.removeAttribute('data-show');\n        this.popper.destroy();\n        this.popper = null;\n      }\n    },\n\n    handleInputFocus(e) {\n      this.$emit('focus', e);\n      this.focus = true;\n    },\n\n    updateStyle() {\n      const { $el, inputInitialHeight } = this;\n      if (!$el) return;\n\n      const inputInner = $el.querySelector('.q-input__inner');\n\n      if (!inputInner) return;\n\n      const tags = $el.querySelector('.q-cascader__tags');\n\n      if (tags) {\n        const { offsetHeight } = tags;\n        const height = `${Math.max(offsetHeight + 6, inputInitialHeight)}px`;\n        inputInner.style.height = height;\n      }\n\n      this.popper?.update();\n    }\n  }\n};\n</script>\n"
  },
  {
    "path": "src/qComponents/QCascader/src/QCascaderMenu.vue",
    "content": "<template>\n  <div class=\"q-cascader-menu\">\n    <div :class=\"classes\">\n      <q-scrollbar wrap-class=\"q-cascader-menu__scrollbar\">\n        <div\n          v-if=\"isEmpty\"\n          class=\"q-cascader-menu__empty-text\"\n        >\n          {{ noDataText }}\n        </div>\n        <div\n          v-for=\"(node, key) in nodes\"\n          v-else\n          :id=\"`${cascader.id}-node-${index}-${key}`\"\n          :key=\"key\"\n          :class=\"getNodeClass(node)\"\n          role=\"menuitem\"\n          tabindex=\"-1\"\n          @click=\"e => expandMenuItem(e, node)\"\n          @keyup.enter=\"e => handleEnterKeyUp(e, node, index, key)\"\n          @keyup.right=\"e => expandMenuItem(e, node)\"\n        >\n          <q-checkbox\n            v-if=\"cascader.multiple\"\n            :ref=\"`QCheckbox${index}${key}`\"\n            input-tab-index=\"-1\"\n            :value=\"getChecked(node)\"\n            :indeterminate=\"getIndeterminate(node)\"\n            @change=\"isChecked => handleValueChange(node, isChecked)\"\n          />\n          <span class=\"q-cascader-node__label\">{{ node.label }}</span>\n          <span\n            v-if=\"node.children\"\n            :class=\"postfixClasses\"\n          />\n        </div>\n      </q-scrollbar>\n    </div>\n  </div>\n</template>\n\n<script>\nconst getCheckedChildren = (option, checkedValues) => {\n  const checkedArray = [];\n  const goToTheLast = childOption => {\n    if (childOption.children) {\n      childOption.children.forEach(goToTheLast);\n    } else {\n      checkedArray.push(checkedValues.includes(childOption.value));\n    }\n  };\n\n  goToTheLast(option);\n\n  return checkedArray;\n};\n\nexport default {\n  name: 'QCascaderMenu',\n  componentName: 'QCascaderMenu',\n\n  inject: ['panel', 'cascader'],\n\n  props: {\n    nodes: {\n      type: Array,\n      required: true\n    },\n    index: { type: Number, default: 0 }\n  },\n\n  computed: {\n    postfixClasses() {\n      return {\n        'q-cascader-node__postfix': true,\n        'q-icon-lock': this.disabled,\n        'q-icon-triangle-right': !this.disabled\n      };\n    },\n    classes() {\n      const classes = ['q-cascader-menu__wrap'];\n      const currentNodesCount = this.panel.menus[this.index]?.length;\n      const nextNodesCount = this.panel.menus[this.index + 1]?.length;\n      const prevNodesCount = this.panel.menus[this.index - 1]?.length;\n      if (this.panel.menus?.length > 1) {\n        if (this.index === 0 || nextNodesCount >= currentNodesCount) {\n          classes.push('q-cascader-menu__wrap_no-right-borders');\n        }\n\n        if (this.index > 0 && prevNodesCount >= currentNodesCount) {\n          classes.push('q-cascader-menu__wrap_no-left-bottom-border');\n        }\n\n        if (prevNodesCount) {\n          classes.push('q-cascader-menu__wrap_no-left-top-border');\n        }\n\n        if (nextNodesCount) {\n          classes.push('q-cascader-menu__wrap_no-right-top-border');\n        }\n\n        if (currentNodesCount > nextNodesCount) {\n          classes.push('q-cascader-menu__wrap_with-right-borders');\n        }\n      }\n\n      return classes;\n    },\n\n    isEmpty() {\n      return !this.nodes.length;\n    },\n\n    noDataText() {\n      return this.panel?.noDataText ?? this.$t('QCascader.noDataText');\n    }\n  },\n\n  methods: {\n    handleEnterKeyUp(e, node, index, key) {\n      if (this.cascader.multiple) {\n        const QCheckboxInstance = this.$refs[`QCheckbox${index}${key}`]?.[0];\n        if (QCheckboxInstance) {\n          QCheckboxInstance.nativeClick();\n        }\n        return;\n      }\n\n      this.expandMenuItem(e, node);\n    },\n    getIndeterminate(node) {\n      if (\n        !this.cascader.checkedValues ||\n        this.cascader.checkedValues.includes(node.value) ||\n        this.cascader.checkStrictly\n      )\n        return false;\n\n      const checkedArray = getCheckedChildren(\n        node,\n        this.cascader.checkedValues\n      );\n\n      if (checkedArray.every(Boolean)) return false;\n      if (checkedArray.some(Boolean)) return true;\n\n      return false;\n    },\n\n    checkStrictly(value) {\n      const result = new Set(this.cascader.checkedValues);\n      if (result.has(value)) {\n        result.delete(value);\n      } else {\n        result.add(value);\n      }\n      this.cascader.emit(Array.from(result));\n    },\n\n    check(value, isChecked) {\n      const result = new Set(this.cascader.checkedValues);\n      if (result.has(value)) {\n        result.delete(value);\n      } else {\n        const findAndCheckChildren = ({ option = {}, checkMode = false }) => {\n          // try to find checked value and run check mode to all children if success\n          if (checkMode || option.value === value) {\n            if (option.children) {\n              // it's not the last level, go to next\n              option.children.forEach(childOption => {\n                findAndCheckChildren({ option: childOption, checkMode: true });\n              });\n              // it is the last level, check if value have already added\n            } else if (this.cascader.checkStrictly) {\n              if (result.has(option.value)) {\n                result.delete(option.value);\n              } else {\n                result.add(option.value);\n              }\n              // if no stricltly, check all or delete all\n            } else if (isChecked) {\n              result.add(option.value);\n            } else {\n              result.delete(option.value);\n            }\n          } else if (option.children) {\n            // just go to the next level\n            option.children.forEach(childOption => {\n              findAndCheckChildren({ option: childOption });\n            });\n          }\n        };\n\n        this.cascader.options.forEach(option => {\n          // go throw the children to the last level\n          findAndCheckChildren({ option });\n        });\n      }\n\n      this.cascader.emit(Array.from(result));\n    },\n\n    handleValueChange({ value }, isChecked) {\n      if (this.cascader.checkStrictly) {\n        this.checkStrictly(value);\n      } else {\n        this.check(value, isChecked);\n      }\n    },\n\n    getChecked(node) {\n      if (!this.cascader.checkedValues) return false;\n      if (this.cascader.checkStrictly) {\n        if (Array.isArray(this.cascader.checkedValues)) {\n          return Boolean(\n            this.cascader.checkedValues.find(value => value === node.value)\n          );\n        }\n\n        return false;\n      }\n\n      const checkedArray = getCheckedChildren(\n        node,\n        this.cascader.checkedValues\n      );\n\n      return checkedArray.every(Boolean);\n    },\n\n    getNodeClass(node) {\n      const isActive = this.panel.activePath.find(\n        value => value === node.label\n      );\n      return {\n        'q-cascader-node': true,\n        'q-cascader-node_active': isActive\n      };\n    },\n\n    expandMenuItem(e, value) {\n      if (e.key === 'ArrowRight' && !value.children) return;\n      if (!value.children && !this.cascader.multiple) {\n        this.cascader.emit(value.value);\n      }\n      this.$emit('expand', this.index, value);\n    }\n  }\n};\n</script>\n"
  },
  {
    "path": "src/qComponents/QCascader/src/QCascaderPanel.vue",
    "content": "<template>\n  <div class=\"q-cascader-panel\">\n    <q-cascader-menu\n      v-for=\"(menu, index) in menus\"\n      :key=\"index\"\n      role=\"menu\"\n      :aria-labelledby=\"cascader.id\"\n      :index=\"index\"\n      :nodes=\"menu\"\n      @expand=\"handleExpand\"\n    />\n  </div>\n</template>\n\n<script>\nimport QCascaderMenu from './QCascaderMenu';\n\nexport default {\n  name: 'QCascaderPanel',\n  componentName: 'QCascaderPanel',\n\n  components: {\n    QCascaderMenu\n  },\n\n  props: {\n    /**\n     * see QCascader value\n     */\n    value: { type: [Array, Object], default: null },\n    /**\n     * see QCascader options\n     */\n    options: { type: Array, default: null },\n    /**\n     * noDataText\n     */\n    noDataText: {\n      type: String,\n      default: null\n    }\n  },\n\n  inject: ['cascader'],\n\n  provide() {\n    return {\n      panel: this\n    };\n  },\n\n  data() {\n    return {\n      activePath: [],\n      menus: []\n    };\n  },\n\n  watch: {\n    options: {\n      immediate: true,\n      handler() {\n        this.menus = [this.options];\n      }\n    }\n  },\n\n  methods: {\n    navigateFocus(e) {\n      if (\n        ['ArrowDown', 'ArrowUp'].includes(e.key) &&\n        e.target instanceof HTMLInputElement\n      ) {\n        const firstNode = this.$el.querySelector(\n          `#${this.cascader.id}-node-0-0`\n        );\n        if (firstNode) {\n          firstNode.focus();\n        }\n      }\n\n      if (!e.target.classList.contains('q-cascader-node')) return;\n      const nodeText = e.target.innerText;\n      let nodeIndex;\n      let currentNodePosition;\n      this.menus.forEach((menu, menuIndex) => {\n        nodeIndex = menu.findIndex(node => node.label === nodeText);\n        if (nodeIndex > -1) {\n          currentNodePosition = [menuIndex, nodeIndex];\n        }\n      });\n\n      let nextNodePosition;\n\n      switch (e.key) {\n        case 'ArrowRight':\n          nextNodePosition = [\n            currentNodePosition[0] + 1,\n            currentNodePosition[1]\n          ];\n          break;\n        case 'ArrowLeft':\n          nextNodePosition = [\n            currentNodePosition[0] === 0 ? 0 : currentNodePosition[0] - 1,\n            currentNodePosition[1]\n          ];\n\n          break;\n\n        case 'ArrowUp':\n          nextNodePosition = [\n            currentNodePosition[0],\n            currentNodePosition[1] === 0 ? 0 : currentNodePosition[1] - 1\n          ];\n          break;\n\n        case 'ArrowDown':\n          nextNodePosition = [\n            currentNodePosition[0],\n            currentNodePosition[1] + 1\n          ];\n          break;\n        default:\n          break;\n      }\n\n      const node = this.$el.querySelector(\n        `#${this.cascader.id}-node-${nextNodePosition[0]}-${nextNodePosition[1]}`\n      );\n\n      if (node) {\n        node.focus();\n      }\n    },\n    handleExpand(index, activeValue) {\n      if (this.cascader.multiple && !activeValue.children) return;\n      let nextLevel;\n      // current level has already opened\n      if (this.menus[index]) {\n        if (this.activePath.length) {\n          this.activePath = this.activePath.slice(0, index);\n        }\n        this.activePath.push(activeValue.label);\n\n        this.menus = this.menus.slice(0, index + 1);\n        nextLevel = activeValue.children;\n      }\n\n      if (nextLevel) {\n        this.menus.push(nextLevel);\n      }\n    }\n  }\n};\n</script>\n"
  },
  {
    "path": "src/qComponents/QCascader/src/q-cascader-menu.scss",
    "content": ".q-cascader-menu {\n  min-width: 200px;\n  height: auto;\n  max-height: 304px;\n  margin-left: 1px;\n\n  &__wrap {\n    overflow: hidden;\n    color: var(--color-primary-blue);\n    background-color: var(--color-tertiary-gray-light);\n    border-radius: var(--border-radius-base);\n    box-shadow: -1px -1px 3px rgba(var(--color-rgb-white), 0.25),\n      -1px 1px 3px rgba(var(--color-rgb-blue), 0.4),\n      4px 4px 8px rgba(var(--color-rgb-blue), 0.4),\n      -4px -4px 12px var(--color-tertiary-white);\n\n    &_no-right-borders {\n      border-top-right-radius: 0;\n      border-bottom-right-radius: 0;\n    }\n\n    &_no-left-bottom-border {\n      border-bottom-left-radius: 0;\n    }\n\n    &_no-left-top-border {\n      border-top-left-radius: 0;\n    }\n\n    &_no-right-top-border {\n      border-top-right-radius: 0;\n    }\n\n    &_with-right-borders {\n      border-bottom-right-radius: var(--border-radius-base);\n    }\n  }\n\n  &__scrollbar {\n    max-height: 300px;\n  }\n\n  &__empty-text {\n    margin: 9px 0;\n    text-align: center;\n    color: var(--color-controls-black);\n  }\n\n  &:last-child {\n    border-right: none;\n\n    .q-cascader-node {\n      padding-right: 20px;\n    }\n  }\n\n  &__list {\n    min-height: 100%;\n    margin: 0;\n    padding: 0;\n    list-style: none;\n  }\n\n  &__hover-zone {\n    position: absolute;\n    top: 0;\n    left: 0;\n    width: 100%;\n    height: 100%;\n    pointer-events: none;\n  }\n\n  .q-cascader-node {\n    position: relative;\n    z-index: 1;\n    display: flex;\n    align-items: center;\n    height: 40px;\n    margin-top: 1px;\n    padding: 4px 8px;\n    background-color: var(--color-tertiary-gray-light);\n    outline: none;\n    box-shadow: var(--box-shadow-pressed);\n\n    &::before {\n      content: '';\n      position: absolute;\n      top: 0;\n      left: 0;\n      width: 100%;\n      height: 100%;\n      overflow: hidden;\n    }\n\n    &:first-child {\n      margin-top: 0;\n    }\n\n    &:last-child {\n      margin-bottom: 0;\n    }\n\n    &:not(.q-cascader-node_disabled) {\n      cursor: pointer;\n\n      &:hover {\n        position: relative;\n        z-index: 1;\n        color: var(--color-primary-black);\n        background: var(--color-tertiary-gray);\n      }\n    }\n\n    &:focus,\n    &_active {\n      position: relative;\n      color: var(--color-primary-black);\n      box-shadow: -1px -1px 3px rgba(var(--color-rgb-white), 0.25),\n        1px 1px 3px rgba(var(--color-rgb-blue), 0.4);\n\n      .q-cascader-node__postfix::before {\n        color: var(--color-primary-blue);\n      }\n    }\n\n    &_active {\n      background-color: var(--color-tertiary-gray-ultra-light);\n    }\n\n    &:focus {\n      background-color: var(--color-tertiary-gray);\n    }\n\n    &_disabled {\n      color: var(--color-opacity-gray-dark);\n      cursor: not-allowed;\n\n      .q-cascader-node__postfix {\n        &::before {\n          font-size: 24px;\n        }\n      }\n    }\n\n    &__prefix {\n      display: none;\n    }\n\n    &__postfix {\n      position: absolute;\n      right: 10px;\n\n      &::before {\n        font-size: 22px;\n        color: rgba(var(--color-rgb-gray), 0.64);\n      }\n    }\n\n    &__label {\n      flex: 1;\n      padding: 0 25px 0 10px;\n      overflow: hidden;\n      text-align: left;\n      white-space: nowrap;\n      text-overflow: ellipsis;\n    }\n  }\n}\n"
  },
  {
    "path": "src/qComponents/QCascader/src/q-cascader.scss",
    "content": ".q-cascader {\n  position: relative;\n  display: inline-block;\n  width: 100%;\n  font-size: var(--font-size-base);\n\n  &:not(.q-cascader_disabled):hover {\n    .q-input__inner {\n      cursor: pointer;\n    }\n  }\n\n  .q-input {\n    cursor: pointer;\n\n    &__inner {\n      text-overflow: ellipsis;\n    }\n\n    &__icon {\n      &::before {\n        font-size: 24px;\n      }\n\n      &:hover {\n        color: var(--color-primary-blue);\n        background-color: unset;\n      }\n    }\n\n    .q-icon-triangle-down {\n      transition: transform 0.3s;\n\n      &_reverse {\n        transform: rotateZ(180deg);\n      }\n    }\n\n    &_hover {\n      .q-input__inner {\n        background-color: var(--field-background-color-hover);\n      }\n    }\n\n    &_focus {\n      .q-input__inner {\n        background-color: var(--color-tertiary-gray-ultra-light);\n        box-shadow: var(--box-shadow-focus);\n      }\n    }\n  }\n\n  &__dropdown {\n    position: relative;\n    z-index: 100;\n  }\n\n  &__tags {\n    position: absolute;\n    top: 50%;\n    right: 30px;\n    left: 8px;\n    display: flex;\n    flex-wrap: wrap;\n    box-sizing: border-box;\n    line-height: normal;\n    text-align: left;\n    transform: translateY(-50%);\n\n    .q-tag {\n      max-width: calc(100% - 15px);\n      margin: 2px 0 2px 8px;\n      line-height: var(--line-height-base);\n      color: var(--color-opacity-gray-dark);\n      text-overflow: ellipsis;\n      background: var(--color-tertiary-gray-darker);\n      border: none;\n      border-radius: 2px;\n\n      .q-cascader__tag-text {\n        flex: 1;\n        overflow: hidden;\n        text-overflow: ellipsis;\n      }\n\n      .q-icon-close {\n        position: relative;\n        top: 0;\n        flex: none;\n        border-radius: unset;\n\n        &:hover {\n          color: var(--color-primary-blue);\n          background-color: unset;\n        }\n\n        &::before {\n          font-size: 16px;\n        }\n      }\n    }\n  }\n\n  &__search-input {\n    flex: 1;\n    box-sizing: border-box;\n    min-width: 60px;\n    height: 24px;\n    margin: 2px 0 2px 15px;\n    padding: 0;\n    border: none;\n    outline: none;\n  }\n}\n\n.q-cascader-panel {\n  display: none;\n\n  &[data-show] {\n    display: flex;\n    border-radius: var(--border-radius-base);\n  }\n}\n\n@import './q-cascader-menu.scss';\n"
  },
  {
    "path": "src/qComponents/QCheckbox/index.js",
    "content": "import QCheckbox from './src/QCheckbox.vue';\n\n/* istanbul ignore next */\nQCheckbox.install = function(Vue) {\n  Vue.component(QCheckbox.name, QCheckbox);\n};\n\nexport default QCheckbox;\n"
  },
  {
    "path": "src/qComponents/QCheckbox/src/QCheckbox.vue",
    "content": "<template>\n  <component\n    :is=\"rootTag\"\n    class=\"q-checkbox\"\n    :class=\"{\n      'q-checkbox_disabled': isDisabled,\n      'q-checkbox_checked': isChecked\n    }\"\n  >\n    <span\n      class=\"q-checkbox__input\"\n      :class=\"{\n        'q-checkbox__input_disabled': isDisabled,\n        'q-checkbox__input_checked': isChecked,\n        'q-checkbox__input_focus': focus\n      }\"\n      :tabindex=\"indeterminate ? 0 : false\"\n      :role=\"indeterminate ? 'checkbox' : false\"\n      :aria-checked=\"indeterminate ? 'mixed' : false\"\n    >\n      <span class=\"q-checkbox__inner\">\n        <span\n          class=\"q-checkbox__inner-icon\"\n          :class=\"{\n            'q-icon-minus': indeterminate,\n            'q-icon-check': isChecked\n          }\"\n        />\n      </span>\n      <input\n        ref=\"checkboxInput\"\n        v-model=\"model\"\n        class=\"q-checkbox__original\"\n        type=\"checkbox\"\n        :aria-hidden=\"indeterminate ? 'true' : 'false'\"\n        :disabled=\"isDisabled\"\n        :value=\"label\"\n        :name=\"name\"\n        :tabindex=\"inputTabIndex\"\n        @change=\"handleChange\"\n        @focus=\"focus = true\"\n        @blur=\"focus = false\"\n      />\n    </span>\n    <span\n      v-if=\"$slots.default || label\"\n      class=\"q-checkbox__label\"\n    >\n      <slot>{{ label }}</slot>\n    </span>\n  </component>\n</template>\n\n<script>\nimport { isBoolean } from 'lodash-es';\nimport Emitter from '../../mixins/emitter';\n\nexport default {\n  name: 'QCheckbox',\n  componentName: 'QCheckbox',\n\n  mixins: [Emitter],\n\n  inject: {\n    qForm: {\n      default: null\n    },\n    qFormItem: {\n      default: null\n    }\n  },\n\n  props: {\n    /**\n     * Array for group, Boolean for single\n     */\n    value: {\n      type: [Array, Boolean],\n      default: null\n    },\n    /**\n     * Checkbox label\n     */\n    label: { type: String, default: '' },\n    /**\n     * wheteher Checkbox is indeterminate\n     */\n    indeterminate: { type: Boolean, default: false },\n    /**\n     * wheteher Checkbox is disabled\n     */\n    disabled: { type: Boolean, default: false },\n    /**\n     * wheteher Checkbox is checked\n     */\n    checked: { type: Boolean, default: false },\n    /**\n     * as native name\n     */\n    name: { type: String, default: '' },\n    rootTag: { type: String, default: 'label' },\n    /**\n     * as native tabIndex\n     */\n    inputTabIndex: {\n      type: [Number, String],\n      default: null\n    }\n  },\n\n  data() {\n    return {\n      selfModel: false,\n      focus: false,\n      isLimitExceeded: false,\n      isGroup: false\n    };\n  },\n\n  computed: {\n    model: {\n      get() {\n        const result = this.value !== undefined ? this.value : this.selfModel;\n        return this.isGroup ? this.store : result;\n      },\n      set(val) {\n        if (this.isGroup) {\n          this.isLimitExceeded = false;\n          if (\n            val.length < this.checkboxGroup.min ||\n            val.length > this.checkboxGroup.max\n          ) {\n            this.isLimitExceeded = true;\n          }\n          if (!this.isLimitExceeded)\n            this.dispatch('QCheckboxGroup', 'input', [val]);\n        } else {\n          this.$emit('input', val);\n          this.selfModel = val;\n        }\n      }\n    },\n\n    isChecked() {\n      if (isBoolean(this.model)) return this.model;\n      if (Array.isArray(this.model)) return this.model.includes(this.label);\n      return false;\n    },\n\n    store() {\n      return this.checkboxGroup ? this.checkboxGroup.value : this.value;\n    },\n\n    /* used to make the isDisabled judgment under max/min props */\n    isLimitDisabled() {\n      const { max, min } = this.checkboxGroup;\n      return (\n        (Boolean(max || min) && this.model.length >= max && !this.isChecked) ||\n        (this.model.length <= min && this.isChecked)\n      );\n    },\n\n    isDisabled() {\n      return this.isGroup\n        ? this.checkboxGroup.disabled ||\n            this.disabled ||\n            (this.qForm?.disabled ?? false) ||\n            this.isLimitDisabled\n        : this.disabled || (this.qForm?.disabled ?? false);\n    }\n  },\n\n  watch: {\n    value() {\n      this.qFormItem?.validateField('change');\n    }\n  },\n\n  created() {\n    if (this.checked) this.addToStore();\n  },\n\n  mounted() {\n    let parent = this.$parent;\n    while (parent) {\n      if (parent.$options.componentName !== 'QCheckboxGroup') {\n        parent = parent.$parent;\n        this.isGroup = false;\n      } else {\n        this.checkboxGroup = parent;\n        this.isGroup = true;\n        break;\n      }\n    }\n  },\n\n  methods: {\n    /**\n     * @public\n     */\n    nativeClick() {\n      this.$refs.checkboxInput.click();\n    },\n\n    addToStore() {\n      if (Array.isArray(this.model) && this.model.includes(this.label)) {\n        this.model.push(this.label);\n        return;\n      }\n\n      this.model = false;\n    },\n\n    handleChange(event) {\n      if (this.isLimitExceeded) return;\n      const value = event.target.checked;\n      this.$emit('change', value, event);\n\n      if (this.isGroup) {\n        this.$nextTick(() => {\n          this.dispatch('QCheckboxGroup', 'change', [this.checkboxGroup.value]);\n        });\n      }\n    }\n  }\n};\n</script>\n"
  },
  {
    "path": "src/qComponents/QCheckbox/src/q-checkbox.scss",
    "content": ".q-checkbox {\n  --checkbox-color-base: var(--color-primary-black);\n  --checkbox-color-disabled: rgba(var(--color-rgb-gray), 0.64);\n\n  --checkbox-background-color-base: var(--color-tertiary-gray-ultra-light);\n  --checkbox-background-color-hover: var(--color-tertiary-gray);\n  --checkbox-background-color-focus: var(--color-tertiary-gray-ultra-light);\n  --checkbox-background-color-checked: var(--color-tertiary-gray-ultra-light);\n  --checkbox-background-color-disabled: var(--color-tertiary-gray);\n\n  --checkbox-mark-color-base: var(--color-primary-blue);\n  --checkbox-mark-color-disabled: rgba(var(--color-rgb-gray), 0.64);\n\n  --checkbox-box-shadow-base: -1px -1px 3px rgba(var(--color-rgb-white), 0.25),\n    1px 1px 3px rgba(var(--color-rgb-blue), 0.4),\n    inset -1px -1px 1px rgba(var(--color-rgb-white), 0.7),\n    inset 1px 1px 2px rgba(var(--color-rgb-blue), 0.2);\n  --checkbox-box-shadow-focus: -1px -1px 3px rgba(var(--color-rgb-white), 0.25),\n    1px 1px 3px rgba(var(--color-rgb-blue), 0.4),\n    4px 4px 10px rgba(var(--color-rgb-blue), 0.4),\n    -4px -4px 10px rgba(var(--color-rgb-white), 0.25),\n    inset -1px -1px 1px rgba(var(--color-rgb-white), 0.7),\n    inset 1px 1px 2px rgba(var(--color-rgb-blue), 0.2);\n\n  position: relative;\n  display: inline-flex;\n  font-weight: var(--font-weight-base);\n  font-size: var(--font-size-base);\n  line-height: 1;\n  vertical-align: middle;\n  color: var(--checkbox-color-base);\n  white-space: nowrap;\n  outline: none;\n  cursor: pointer;\n  user-select: none;\n\n  &__label {\n    margin-top: 3px;\n    padding-left: 16px;\n    font-size: var(--font-size-base);\n    line-height: 18px;\n    white-space: normal;\n    word-break: break-word;\n\n    .q-checkbox_disabled & {\n      color: var(--checkbox-color-disabled);\n      cursor: not-allowed;\n    }\n  }\n\n  &__input {\n    position: relative;\n    line-height: 0;\n    white-space: nowrap;\n    border: none;\n    outline: none;\n    cursor: pointer;\n  }\n\n  &__inner {\n    position: relative;\n    z-index: 1;\n    display: inline-block;\n    box-sizing: border-box;\n    width: 24px;\n    height: 24px;\n    overflow: hidden;\n    background-color: var(--checkbox-background-color-base);\n    border: none;\n    border-radius: var(--border-radius-base);\n    box-shadow: var(--checkbox-box-shadow-base);\n\n    &-icon {\n      position: absolute;\n      top: 4px;\n      left: 4px;\n      box-sizing: content-box;\n      width: 16px;\n      font-size: 16px;\n      text-align: center;\n      color: var(--checkbox-mark-color-base);\n    }\n\n    .q-checkbox_checked &,\n    .q-checkbox__input_indeterminate & {\n      background-color: var(--checkbox-background-color-checked);\n\n      &::after {\n        opacity: 1;\n      }\n    }\n\n    .q-checkbox__input_focus & {\n      background-color: var(--checkbox-background-color-focus);\n      box-shadow: var(--checkbox-box-shadow-focus);\n    }\n\n    &,\n    .q-checkbox__input_focus &,\n    .q-checkbox_checked &,\n    .q-checkbox__input_indeterminate & {\n      &:hover {\n        background-color: var(--checkbox-background-color-hover);\n      }\n    }\n\n    .q-checkbox_disabled & {\n      background-color: var(--checkbox-background-color-disabled);\n      cursor: not-allowed;\n\n      &-icon {\n        color: var(--checkbox-mark-color-disabled);\n        cursor: not-allowed;\n      }\n    }\n  }\n\n  &__original {\n    position: absolute;\n    top: 0;\n    right: 0;\n    bottom: 0;\n    left: 0;\n    z-index: -1;\n    margin: 0;\n    outline: none;\n    opacity: 0;\n  }\n}\n"
  },
  {
    "path": "src/qComponents/QCheckboxGroup/index.js",
    "content": "import QCheckboxGroup from './src/QCheckboxGroup.vue';\n\n/* istanbul ignore next */\nQCheckboxGroup.install = function(Vue) {\n  Vue.component(QCheckboxGroup.name, QCheckboxGroup);\n};\n\nexport default QCheckboxGroup;\n"
  },
  {
    "path": "src/qComponents/QCheckboxGroup/src/QCheckboxGroup.vue",
    "content": "<template>\n  <component\n    :is=\"tag\"\n    :class=\"['q-checkbox-group', `q-checkbox-group_${direction}`]\"\n    role=\"group\"\n    aria-label=\"checkbox-group\"\n  >\n    <slot />\n  </component>\n</template>\n\n<script>\nimport Emitter from '../../mixins/emitter';\n\nexport default {\n  name: 'QCheckboxGroup',\n  componentName: 'QCheckboxGroup',\n\n  mixins: [Emitter],\n\n  inject: {\n    qFormItem: {\n      default: null\n    }\n  },\n\n  props: {\n    value: {\n      type: Array,\n      default: () => []\n    },\n    /**\n     * disable all inner QCheckbox'es\n     */\n    disabled: { type: Boolean, default: false },\n    /**\n     * minimum checked values\n     */\n    min: { type: Number, default: 0 },\n    /**\n     * maximum checked values\n     */\n    max: { type: Number, default: Infinity },\n    /**\n     * root tag\n     */\n    tag: { type: String, default: 'div' },\n    /**\n     * vertical renders to column, horizontal to row\n     */\n    direction: {\n      type: String,\n      default: 'vertical',\n      validator: value => ['vertical', 'horizontal'].includes(value)\n    }\n  },\n\n  watch: {\n    value() {\n      this.qFormItem?.validateField('change');\n    }\n  }\n};\n</script>\n"
  },
  {
    "path": "src/qComponents/QCheckboxGroup/src/q-checkbox-group.scss",
    "content": ".q-checkbox-group {\n  display: flex;\n  align-items: flex-start;\n  font-size: 0;\n  line-height: 1;\n\n  &_vertical {\n    flex-direction: column;\n\n    .q-checkbox:not(:last-child) {\n      margin-bottom: 16px;\n    }\n  }\n\n  &_horizontal {\n    .q-checkbox:not(:last-child) {\n      margin-right: 32px;\n    }\n  }\n}\n"
  },
  {
    "path": "src/qComponents/QCol/QCol.test.js",
    "content": "import Component from './src/QCol';\n\ndescribe('QCol', () => {\n  it('should match snapshot', async () => {\n    const { element } = shallowMount(Component);\n\n    expect(element).toMatchSnapshot();\n  });\n});\n"
  },
  {
    "path": "src/qComponents/QCol/__snapshots__/QCol.test.js.snap",
    "content": "// Jest Snapshot v1, https://goo.gl/fbAQLP\n\nexports[`QCol should match snapshot 1`] = `\n<div\n  class=\"q-col\"\n/>\n`;\n"
  },
  {
    "path": "src/qComponents/QCol/index.js",
    "content": "import QCol from './src/QCol';\n\nQCol.install = Vue => {\n  Vue.component(QCol.name, QCol);\n};\n\nexport default QCol;\n"
  },
  {
    "path": "src/qComponents/QCol/src/QCol.vue",
    "content": "<template>\n  <component\n    :is=\"tag\"\n    class=\"q-col\"\n    :class=\"classes\"\n  >\n    <slot />\n  </component>\n</template>\n\n<script>\nexport default {\n  name: 'QCol',\n  componentName: 'QCol',\n\n  props: {\n    /**\n     * custom element tag\n     */\n    tag: {\n      type: String,\n      default: 'div'\n    },\n    /**\n     * number of column the grid cols.\n     * `auto || [1-12]`\n     */\n    cols: {\n      type: [String, Number],\n      default: null,\n      validator: value => value === 'auto' || (value > 0 && value <= 12)\n    },\n    /**\n     * number of spacing on the left side of the grid.\n     * `[0-11]`\n     */\n    offset: {\n      type: [String, Number],\n      default: null,\n      validator: value => value >= 0 && value <= 11\n    }\n  },\n\n  computed: {\n    classes() {\n      return {\n        [`q-col_size_${this.cols}`]: Boolean(this.cols),\n        [`q-col_offset_${this.offset}`]: Number.isInteger(\n          Number(this.offset ?? 'hide')\n        )\n      };\n    }\n  }\n};\n</script>\n"
  },
  {
    "path": "src/qComponents/QCol/src/q-col.scss",
    "content": ".q-col {\n  position: relative;\n  flex: 1 0 0;\n  width: 100%;\n  max-width: 100%;\n  padding-right: calc(var(--layout-gutter) / 2);\n  padding-left: calc(var(--layout-gutter) / 2);\n\n  &_size_auto {\n    flex: 0 0 auto;\n    width: auto;\n    max-width: 100%;\n  }\n\n  @for $i from 1 through 12 {\n    &_size_#{$i} {\n      flex: 0 0 percentage($i / 12);\n      max-width: percentage($i / 12);\n    }\n  }\n\n  @for $i from 0 through 11 {\n    &_offset_#{$i} {\n      margin-left: percentage($i / 12);\n    }\n  }\n}\n"
  },
  {
    "path": "src/qComponents/QCollapse/QCollapse.test.js",
    "content": "import Component from './src/QCollapse';\n\ndescribe('QCollapse', () => {\n  it('should match snapshot', () => {\n    const { element } = mount(Component);\n    expect(element).toMatchSnapshot();\n  });\n\n  it('data should match snapshot', () => {\n    expect(Component.data()).toMatchSnapshot();\n  });\n});\n"
  },
  {
    "path": "src/qComponents/QCollapse/__snapshots__/QCollapse.test.js.snap",
    "content": "// Jest Snapshot v1, https://goo.gl/fbAQLP\n\nexports[`QCollapse data should match snapshot 1`] = `\nObject {\n  \"activeNames\": Array [],\n  \"uniqueId\": [Function],\n}\n`;\n\nexports[`QCollapse should match snapshot 1`] = `\n<div\n  class=\"q-collapse\"\n/>\n`;\n"
  },
  {
    "path": "src/qComponents/QCollapse/index.js",
    "content": "import QCollapse from './src/QCollapse.vue';\n\n/* istanbul ignore next */\nQCollapse.install = function(Vue) {\n  Vue.component(QCollapse.name, QCollapse);\n};\n\nexport default QCollapse;\n"
  },
  {
    "path": "src/qComponents/QCollapse/src/QCollapse.vue",
    "content": "<template>\n  <div class=\"q-collapse\">\n    <slot />\n  </div>\n</template>\n\n<script>\nimport { uniqueId } from 'lodash-es';\n\nexport default {\n  name: 'QCollapse',\n  componentName: 'QCollapse',\n\n  provide() {\n    return {\n      qCollapse: this\n    };\n  },\n\n  model: {\n    prop: 'value',\n    event: 'change'\n  },\n\n  props: {\n    /**\n     * shrink all panels, except the last selected\n     */\n    accordion: {\n      type: Boolean,\n      default: false\n    },\n    value: {\n      type: [Array, String, Number],\n      default: () => []\n    }\n  },\n\n  data() {\n    return {\n      activeNames: [],\n      uniqueId\n    };\n  },\n\n  watch: {\n    value: {\n      immediate: true,\n      handler(value) {\n        this.activeNames = [].concat(value);\n      }\n    }\n  },\n\n  methods: {\n    updateValue(name) {\n      if (this.accordion) {\n        this.activeNames = this.activeNames === name ? [] : [name];\n      } else {\n        const index = this.activeNames.indexOf(name);\n\n        if (index > -1) {\n          this.activeNames.splice(index, 1);\n        } else {\n          this.activeNames.push(name);\n        }\n      }\n\n      this.$emit('change', this.activeNames);\n    }\n  }\n};\n</script>\n"
  },
  {
    "path": "src/qComponents/QCollapse/src/q-collapse.scss",
    "content": ""
  },
  {
    "path": "src/qComponents/QCollapseItem/QCollapseItem.test.js",
    "content": "import Component from './src/QCollapseItem';\n\ndescribe('QCollapseItem', () => {\n  it('should match snapshot', () => {\n    const { element } = mount(Component);\n    expect(element).toMatchSnapshot();\n  });\n\n  it('data should match snapshot', () => {\n    expect(Component.data()).toMatchSnapshot();\n  });\n});\n"
  },
  {
    "path": "src/qComponents/QCollapseItem/__snapshots__/QCollapseItem.test.js.snap",
    "content": "// Jest Snapshot v1, https://goo.gl/fbAQLP\n\nexports[`QCollapseItem data should match snapshot 1`] = `\nObject {\n  \"activeNames\": Array [],\n}\n`;\n\nexports[`QCollapseItem should match snapshot 1`] = `\n<div\n  class=\"q-collapse-item\"\n>\n  <button\n    class=\"q-collapse-item__header\"\n  >\n    <div\n      class=\"q-collapse-item__title\"\n    >\n      \n    </div>\n     \n    <div\n      class=\"q-collapse-item__icon q-icon-plus\"\n    />\n  </button>\n   \n  <transition-stub>\n    <div\n      class=\"q-collapse-item__body\"\n      style=\"display: none;\"\n    >\n      <div\n        class=\"q-collapse-item__content\"\n      />\n    </div>\n  </transition-stub>\n</div>\n`;\n"
  },
  {
    "path": "src/qComponents/QCollapseItem/index.js",
    "content": "import QCollapseItem from './src/QCollapseItem.vue';\n\n/* istanbul ignore next */\nQCollapseItem.install = function(Vue) {\n  Vue.component(QCollapseItem.name, QCollapseItem);\n};\n\nexport default QCollapseItem;\n"
  },
  {
    "path": "src/qComponents/QCollapseItem/src/QCollapseItem.vue",
    "content": "<template>\n  <div\n    class=\"q-collapse-item\"\n    :class=\"{\n      'q-collapse-item_active': isActive\n    }\"\n  >\n    <button\n      class=\"q-collapse-item__header\"\n      @click=\"handleTabClick\"\n    >\n      <slot name=\"title\">\n        <div class=\"q-collapse-item__title\">{{ title }}</div>\n      </slot>\n      <div\n        class=\"q-collapse-item__icon\"\n        :class=\"icon\"\n      />\n    </button>\n\n    <q-collapse-transition>\n      <div\n        v-show=\"isActive\"\n        class=\"q-collapse-item__body\"\n      >\n        <div class=\"q-collapse-item__content\">\n          <slot />\n        </div>\n      </div>\n    </q-collapse-transition>\n  </div>\n</template>\n\n<script>\nimport QCollapseTransition from '../../helpers/collapse-transition';\n\nexport default {\n  name: 'QCollapseItem',\n  componentName: 'QCollapseItem',\n\n  components: { QCollapseTransition },\n\n  inject: {\n    qCollapse: {\n      default: null\n    }\n  },\n\n  props: {\n    title: {\n      type: String,\n      default: ''\n    },\n    name: {\n      type: [String, Number],\n      default: null\n    }\n  },\n\n  data() {\n    return {\n      activeNames: []\n    };\n  },\n\n  computed: {\n    preparedName() {\n      return this.name ?? this.qCollapse?.uniqueId('default-collapse-name-');\n    },\n\n    isActive() {\n      return this.qCollapse?.activeNames?.includes(this.preparedName) ?? false;\n    },\n\n    icon() {\n      return this.isActive ? 'q-icon-minus' : 'q-icon-plus';\n    }\n  },\n\n  methods: {\n    handleTabClick() {\n      this.qCollapse?.updateValue(this.preparedName);\n    }\n  }\n};\n</script>\n"
  },
  {
    "path": "src/qComponents/QCollapseItem/src/q-collapse-item.scss",
    "content": ".q-collapse-item {\n  &:not(:last-child) {\n    margin-bottom: 16px;\n  }\n\n  &__header {\n    display: flex;\n    align-items: center;\n    width: 100%;\n    text-align: left;\n    background-color: var(--color-tertiary-gray-light);\n    border: none;\n    border-radius: var(--border-radius-base);\n    outline: none;\n    box-shadow: -1px -1px 3px rgba(var(--color-rgb-white), 0.25),\n      1px 1px 3px rgba(var(--color-rgb-blue), 0.4);\n    cursor: pointer;\n    transition: background-color 0.1s;\n\n    .q-collapse-item_active & {\n      background-color: var(--color-tertiary-gray-ultra-light);\n      border-radius: var(--border-radius-base) var(--border-radius-base) 0 0;\n    }\n\n    &:focus,\n    &:hover {\n      background-color: var(--color-tertiary-gray);\n    }\n  }\n\n  &__title {\n    flex: 1;\n    padding: 12px 0 12px 24px;\n    font-weight: 600;\n    font-size: 16px;\n    line-height: 20px;\n    color: rgba(var(--color-rgb-gray), 0.64);\n\n    .q-collapse-item_active > .q-collapse-item__header:not(:hover) &,\n    .q-collapse-item_active > .q-collapse-item__header:not(:focus) & {\n      color: var(--color-primary-black);\n    }\n  }\n\n  &__icon {\n    flex: 0 64px;\n    padding: 20px 16px 20px 24px;\n    font-size: 24px;\n    color: var(--color-primary-blue);\n  }\n\n  &__body {\n    margin-top: 1px;\n    background-color: var(--color-tertiary-gray-light);\n    border-radius: 0 0 var(--border-radius-base) var(--border-radius-base);\n    box-shadow: -1px -1px 3px rgba(var(--color-rgb-white), 0.25),\n      1px 1px 3px rgba(var(--color-rgb-blue), 0.4);\n  }\n\n  &__content {\n    padding: 24px;\n  }\n}\n"
  },
  {
    "path": "src/qComponents/QColorPicker/QColorAlphaSlider.test.js",
    "content": "import Component from './src/QColorAlphaSlider';\n\ndescribe('QColorAlphaSlider', () => {\n  it('should match snapshot', async () => {\n    const instance = shallowMount(Component, {\n      propsData: {\n        color: 'rgba(255,155,155,.5)',\n        alpha: 55\n      }\n    });\n\n    expect(instance.element).toMatchSnapshot();\n  });\n\n  it('data should match snapshot', () => {\n    expect(Component.data()).toMatchSnapshot();\n  });\n});\n"
  },
  {
    "path": "src/qComponents/QColorPicker/QColorHueSlider.test.js",
    "content": "import Component from './src/QColorHueSlider';\n\ndescribe('QColorHueSlider', () => {\n  it('should match snapshot', async () => {\n    const instance = shallowMount(Component, {\n      propsData: {\n        hue: 155\n      }\n    });\n\n    expect(instance.element).toMatchSnapshot();\n  });\n\n  it('data should match snapshot', () => {\n    expect(Component.data()).toMatchSnapshot();\n  });\n});\n"
  },
  {
    "path": "src/qComponents/QColorPicker/QColorPicker.test.js",
    "content": "import Component from './src/QColorPicker';\n\ndescribe('QColorPicker', () => {\n  it('should match snapshot', async () => {\n    const instance = shallowMount(Component);\n\n    expect(instance.element).toMatchSnapshot();\n  });\n\n  it('data should match snapshot', () => {\n    expect(Component.data()).toMatchSnapshot();\n  });\n});\n"
  },
  {
    "path": "src/qComponents/QColorPicker/QColorSvpanel.test.js",
    "content": "import Component from './src/QColorSvpanel';\n\ndescribe('QColorSvpanel', () => {\n  it('should match snapshot', async () => {\n    const instance = shallowMount(Component, {\n      propsData: {\n        hue: 100,\n        saturation: 50,\n        value: 25\n      }\n    });\n\n    expect(instance.element).toMatchSnapshot();\n  });\n\n  it('data should match snapshot', () => {\n    expect(Component.data()).toMatchSnapshot();\n  });\n});\n"
  },
  {
    "path": "src/qComponents/QColorPicker/QPickerDropdown.test.js",
    "content": "import Component from './src/QPickerDropdown';\n\ndescribe('QPickerDropdown', () => {\n  it('should match snapshot', async () => {\n    const instance = shallowMount(Component);\n\n    expect(instance.element).toMatchSnapshot();\n  });\n\n  it('data should match snapshot', () => {\n    expect(Component.data()).toMatchSnapshot();\n  });\n});\n"
  },
  {
    "path": "src/qComponents/QColorPicker/__snapshots__/QColorAlphaSlider.test.js.snap",
    "content": "// Jest Snapshot v1, https://goo.gl/fbAQLP\n\nexports[`QColorAlphaSlider data should match snapshot 1`] = `\nObject {\n  \"thumbLeft\": 0,\n}\n`;\n\nexports[`QColorAlphaSlider should match snapshot 1`] = `\n<div\n  class=\"q-color-alpha-slider\"\n>\n  <div\n    class=\"q-color-alpha-slider__bar\"\n  />\n   \n  <div\n    class=\"q-color-alpha-slider__thumb\"\n    style=\"left: 0px;\"\n  />\n</div>\n`;\n"
  },
  {
    "path": "src/qComponents/QColorPicker/__snapshots__/QColorHueSlider.test.js.snap",
    "content": "// Jest Snapshot v1, https://goo.gl/fbAQLP\n\nexports[`QColorHueSlider data should match snapshot 1`] = `\nObject {\n  \"thumbTop\": 0,\n}\n`;\n\nexports[`QColorHueSlider should match snapshot 1`] = `\n<div\n  class=\"q-color-hue-slider\"\n>\n  <div\n    class=\"q-color-hue-slider__bar\"\n  />\n   \n  <div\n    class=\"q-color-hue-slider__thumb\"\n    style=\"top: 0px;\"\n  />\n</div>\n`;\n"
  },
  {
    "path": "src/qComponents/QColorPicker/__snapshots__/QColorPicker.test.js.snap",
    "content": "// Jest Snapshot v1, https://goo.gl/fbAQLP\n\nexports[`QColorPicker data should match snapshot 1`] = `\nObject {\n  \"isClickIgnored\": false,\n  \"isPickerShown\": false,\n  \"popperJS\": null,\n  \"zIndex\": null,\n}\n`;\n\nexports[`QColorPicker should match snapshot 1`] = `\n<div\n  class=\"q-color-picker\"\n>\n  <div\n    class=\"q-color-picker-trigger\"\n  >\n    <button\n      class=\"q-color-picker-trigger__default\"\n    >\n      <div\n        class=\"q-color-picker-trigger__color\"\n      />\n       \n      <span\n        class=\"q-color-picker-trigger__icon q-icon-triangle-down\"\n      />\n    </button>\n  </div>\n   \n  <q-picker-dropdown-stub\n    colorformat=\"hex\"\n    isclearbtnshown=\"true\"\n  />\n</div>\n`;\n"
  },
  {
    "path": "src/qComponents/QColorPicker/__snapshots__/QColorSvpanel.test.js.snap",
    "content": "// Jest Snapshot v1, https://goo.gl/fbAQLP\n\nexports[`QColorSvpanel data should match snapshot 1`] = `\nObject {\n  \"cursorLeft\": 0,\n  \"cursorTop\": 0,\n}\n`;\n\nexports[`QColorSvpanel should match snapshot 1`] = `\n<div\n  class=\"q-color-svpanel\"\n  style=\"background-color: rgb(0, 0, 0);\"\n>\n  <div\n    class=\"q-color-svpanel__cursor\"\n    style=\"top: 0px; left: 0px;\"\n  />\n</div>\n`;\n"
  },
  {
    "path": "src/qComponents/QColorPicker/__snapshots__/QPickerDropdown.test.js.snap",
    "content": "// Jest Snapshot v1, https://goo.gl/fbAQLP\n\nexports[`QPickerDropdown data should match snapshot 1`] = `\nObject {\n  \"alpha\": 100,\n  \"elementToFocusAfterClosing\": null,\n  \"hue\": 0,\n  \"saturation\": 100,\n  \"tempColor\": \"\",\n  \"value\": 100,\n}\n`;\n\nexports[`QPickerDropdown should match snapshot 1`] = `\n<transition-stub\n  name=\"fade\"\n>\n  <div\n    class=\"q-picker-dropdown\"\n    style=\"display: none;\"\n    tabindex=\"-1\"\n  >\n    <div\n      class=\"q-picker-dropdown__base\"\n    >\n      <q-color-svpanel-stub\n        hue=\"0\"\n        saturation=\"0\"\n        value=\"0\"\n      />\n       \n      <q-color-hue-slider-stub\n        hue=\"0\"\n      />\n    </div>\n     \n    <!---->\n     \n    <div\n      class=\"q-picker-dropdown__footer\"\n    >\n      <div\n        class=\"q-picker-dropdown__input\"\n      >\n        <q-input-stub\n          autocomplete=\"off\"\n          label=\"\"\n          suffixicon=\"\"\n          tabindex=\"\"\n          type=\"text\"\n          value=\"#000000\"\n        />\n      </div>\n       \n      <!---->\n       \n      <q-button-stub\n        icon=\"\"\n        nativetype=\"button\"\n        size=\"medium\"\n        theme=\"primary\"\n        type=\"default\"\n      >\n        \n        Применить\n      \n      </q-button-stub>\n    </div>\n  </div>\n</transition-stub>\n`;\n"
  },
  {
    "path": "src/qComponents/QColorPicker/index.js",
    "content": "import QColorPicker from './src/QColorPicker';\n\nQColorPicker.install = Vue => {\n  Vue.component(QColorPicker.name, QColorPicker);\n};\n\nexport default QColorPicker;\n"
  },
  {
    "path": "src/qComponents/QColorPicker/src/QColorAlphaSlider.vue",
    "content": "<template>\n  <div class=\"q-color-alpha-slider\">\n    <div\n      ref=\"bar\"\n      class=\"q-color-alpha-slider__bar\"\n      :style=\"barStyles\"\n      @click=\"handleBarClick\"\n    />\n    <div\n      ref=\"thumb\"\n      class=\"q-color-alpha-slider__thumb\"\n      :style=\"thumbStyles\"\n    />\n  </div>\n</template>\n\n<script>\nimport draggable from './draggable';\n\nexport default {\n  name: 'QColorAlphaSlider',\n  componentName: 'QColorAlphaSlider',\n\n  props: {\n    color: {\n      type: String,\n      required: true\n    },\n    alpha: {\n      type: Number,\n      required: true\n    }\n  },\n\n  data() {\n    return {\n      thumbLeft: 0\n    };\n  },\n\n  computed: {\n    barStyles() {\n      return {\n        backgroundImage: `linear-gradient(90deg, rgba(0, 0, 0, 0) 0%, ${this.color})`\n      };\n    },\n\n    thumbStyles() {\n      return {\n        left: `${this.thumbLeft}px`\n      };\n    }\n  },\n\n  watch: {\n    alpha() {\n      this.update();\n    }\n  },\n\n  mounted() {\n    const { bar, thumb } = this.$refs;\n    const dragConfig = {\n      drag: this.handleDrag,\n      end: this.handleDrag\n    };\n    draggable(bar, dragConfig);\n    draggable(thumb, dragConfig);\n\n    this.update();\n  },\n\n  methods: {\n    handleDrag(event) {\n      const rect = this.$el.getBoundingClientRect();\n      const { thumb } = this.$refs;\n\n      let left = event.clientX - rect.left;\n      left = Math.max(thumb.offsetWidth / 2, left);\n      left = Math.min(left, rect.width - thumb.offsetWidth / 2);\n      const alpha = Math.round(\n        ((left - thumb.offsetWidth / 2) / (rect.width - thumb.offsetWidth)) *\n          100\n      );\n\n      this.$emit('update:alpha', alpha);\n    },\n\n    handleBarClick(event) {\n      if (event.target !== this.$refs.thumb) {\n        this.handleDrag(event);\n      }\n    },\n\n    getThumbLeft() {\n      const el = this.$el;\n      if (!el) return 0;\n\n      return Math.round(\n        (this.alpha * (el.offsetWidth - this.$refs.thumb.offsetWidth * 1.5)) /\n          100\n      );\n    },\n\n    update() {\n      this.thumbLeft = this.getThumbLeft();\n    }\n  }\n};\n</script>\n"
  },
  {
    "path": "src/qComponents/QColorPicker/src/QColorHueSlider.vue",
    "content": "<template>\n  <div class=\"q-color-hue-slider\">\n    <div\n      ref=\"bar\"\n      class=\"q-color-hue-slider__bar\"\n      @click=\"handleBarClick\"\n    />\n    <div\n      ref=\"thumb\"\n      class=\"q-color-hue-slider__thumb\"\n      :style=\"thumbStyles\"\n    />\n  </div>\n</template>\n\n<script>\nimport draggable from './draggable';\n\nexport default {\n  name: 'QColorHueSlider',\n  componentName: 'QColorHueSlider',\n\n  props: {\n    hue: {\n      type: Number,\n      required: true\n    }\n  },\n\n  data() {\n    return {\n      thumbTop: 0\n    };\n  },\n\n  computed: {\n    thumbStyles() {\n      return {\n        top: `${this.thumbTop}px`\n      };\n    }\n  },\n\n  watch: {\n    hue() {\n      this.update();\n    }\n  },\n\n  mounted() {\n    const { bar, thumb } = this.$refs;\n    const dragConfig = {\n      drag: this.handleDrag,\n      end: this.handleDrag\n    };\n    draggable(bar, dragConfig);\n    draggable(thumb, dragConfig);\n\n    this.update();\n  },\n\n  methods: {\n    handleDrag(event) {\n      const rect = this.$el.getBoundingClientRect();\n      const { thumb } = this.$refs;\n\n      let top = event.clientY - rect.top;\n      top = Math.min(top, rect.height - thumb.offsetHeight / 2);\n      top = Math.max(thumb.offsetHeight / 2, top);\n      const hue = Math.round(\n        ((top - thumb.offsetHeight / 2) / (rect.height - thumb.offsetHeight)) *\n          360\n      );\n\n      this.$emit('update:hue', hue);\n    },\n\n    handleBarClick(event) {\n      if (event.target !== this.$refs.thumb) {\n        this.handleDrag(event);\n      }\n    },\n\n    getThumbTop() {\n      const el = this.$el;\n      if (!el) return 0;\n\n      return Math.round(\n        (this.hue * (el.offsetHeight - this.$refs.thumb.offsetHeight * 1.5)) /\n          360\n      );\n    },\n\n    update() {\n      this.thumbTop = this.getThumbTop();\n    }\n  }\n};\n</script>\n"
  },
  {
    "path": "src/qComponents/QColorPicker/src/QColorPicker.vue",
    "content": "<template>\n  <div class=\"q-color-picker\">\n    <div\n      ref=\"trigger\"\n      class=\"q-color-picker-trigger\"\n      :class=\"{\n        'q-color-picker-trigger_is-disabled': isDisabled,\n        'q-color-picker-trigger_is-opened': isPickerShown\n      }\"\n      @click.prevent=\"handleTriggerClick\"\n    >\n      <!-- @slot _Optional_. HTML element that triggers dropdown -->\n      <slot\n        v-if=\"$slots.trigger\"\n        name=\"trigger\"\n      />\n      <button\n        v-else\n        :disabled=\"isDisabled\"\n        class=\"q-color-picker-trigger__default\"\n      >\n        <div\n          class=\"q-color-picker-trigger__color\"\n          :style=\"{\n            backgroundColor: value\n          }\"\n        />\n        <span :class=\"iconClasses\" />\n      </button>\n    </div>\n\n    <q-picker-dropdown\n      ref=\"dropdown\"\n      :is-shown=\"isPickerShown\"\n      :is-clear-btn-shown=\"clearable\"\n      :color=\"value\"\n      :color-format=\"colorFormat\"\n      :alpha-shown=\"alphaShown\"\n      :style=\"{ zIndex }\"\n      @click.stop\n      @close=\"handleClose\"\n      @clear=\"handleClear\"\n      @pick=\"handlePick\"\n    />\n  </div>\n</template>\n\n<script>\nimport { createPopper } from '@popperjs/core';\nimport Color from 'color';\n\nimport Emitter from '../../mixins/emitter';\nimport PLACEMENTS from '../../constants/popperPlacements';\nimport QPickerDropdown from './QPickerDropdown';\n\nexport default {\n  name: 'QColorPicker',\n  componentName: 'QColorPicker',\n\n  components: {\n    QPickerDropdown\n  },\n\n  mixins: [Emitter],\n\n  model: {\n    prop: 'value',\n    event: 'change'\n  },\n\n  inject: {\n    qForm: {\n      default: null\n    },\n    qFormItem: {\n      default: null\n    }\n  },\n\n  props: {\n    /**\n     * binding value\n     */\n    value: {\n      type: String,\n      default: null\n    },\n    /**\n     * whether to disable the ColorPicker\n     */\n    disabled: {\n      type: Boolean,\n      default: false\n    },\n    /**\n     * whether to show clear button\n     */\n    clearable: {\n      type: Boolean,\n      default: true\n    },\n    /**\n     * whether to display the alpha slider\n     */\n    alphaShown: {\n      type: Boolean,\n      default: false\n    },\n    /**\n     * output color format\n     */\n    colorFormat: {\n      type: String,\n      default: 'hex',\n      validator: value => ['hex', 'rgb'].includes(value)\n    },\n    placement: {\n      type: String,\n      default: 'right-start',\n      validator: value => PLACEMENTS.includes(value)\n    },\n    /**\n     * whether to append the popper menu to body. If the positioning of the popper is wrong, you can try to set this prop to false\n     */\n    appendToBody: {\n      type: Boolean,\n      default: true\n    },\n    popperOptions: {\n      type: Object,\n      default: () => ({})\n    }\n  },\n\n  data() {\n    return {\n      zIndex: null,\n      isClickIgnored: false,\n      isPickerShown: false,\n      popperJS: null\n    };\n  },\n\n  computed: {\n    isDisabled() {\n      return this.disabled || (this.qForm?.disabled ?? false);\n    },\n\n    isColorDark() {\n      if (!this.value) return false;\n\n      return Color(this.value).isDark();\n    },\n\n    iconClasses() {\n      return {\n        'q-color-picker-trigger__icon': true,\n        'q-color-picker-trigger__icon_light': this.isColorDark,\n        'q-icon-triangle-down': !this.isDisabled,\n        'q-icon-lock': this.isDisabled\n      };\n    },\n\n    options() {\n      return {\n        placement: this.placement,\n        computeStyle: {\n          boundariesElement: 'body',\n          gpuAcceleration: false\n        },\n        modifiers: [\n          {\n            name: 'offset',\n            options: {\n              offset: [0, 16]\n            }\n          }\n        ],\n        ...this.popperOptions\n      };\n    }\n  },\n\n  watch: {\n    isPickerShown(value) {\n      if (this.isDisabled || !value) return;\n\n      this.zIndex = this.$Q?.zIndex ?? 2000;\n      this.createPopper();\n    }\n  },\n\n  beforeDestroy() {\n    const dropdown = this.$refs?.dropdown?.$el;\n    if (dropdown?.parentNode === document.body) {\n      document.body.removeChild(dropdown);\n    }\n  },\n\n  methods: {\n    handleClose() {\n      if (this.isClickIgnored) {\n        this.isClickIgnored = false;\n        return;\n      }\n\n      this.isPickerShown = false;\n    },\n\n    handleTriggerClick() {\n      if (this.isDisabled) return;\n\n      this.isClickIgnored = true;\n      this.isPickerShown = !this.isPickerShown;\n    },\n\n    handleClear() {\n      this.$emit('change', null);\n\n      if (this.value !== null) {\n        this.qFormItem?.validateField('change');\n      }\n\n      this.isPickerShown = false;\n    },\n\n    handlePick(value) {\n      this.$emit('change', value);\n\n      if (this.value !== value) {\n        this.qFormItem?.validateField('change');\n      }\n\n      this.isPickerShown = false;\n    },\n\n    createPopper() {\n      if (this.popperJS?.destroy) {\n        this.popperJS.destroy();\n        this.popperJS = null;\n      }\n\n      if (this.appendToBody) document.body.appendChild(this.$refs.dropdown.$el);\n\n      this.popperJS = createPopper(\n        this.$refs.trigger,\n        this.$refs.dropdown.$el,\n        this.options\n      );\n    }\n  }\n};\n</script>\n"
  },
  {
    "path": "src/qComponents/QColorPicker/src/QColorSvpanel.vue",
    "content": "<template>\n  <div\n    class=\"q-color-svpanel\"\n    :style=\"rootStyles\"\n  >\n    <div\n      class=\"q-color-svpanel__cursor\"\n      :style=\"cursorStyles\"\n    />\n  </div>\n</template>\n\n<script>\nimport draggable from './draggable';\n\nexport default {\n  name: 'QColorSvpanel',\n  componentName: 'QColorSvpanel',\n\n  props: {\n    hue: {\n      type: Number,\n      required: true\n    },\n    saturation: {\n      type: Number,\n      required: true\n    },\n    value: {\n      type: Number,\n      required: true\n    }\n  },\n\n  data() {\n    return {\n      cursorTop: 0,\n      cursorLeft: 0\n    };\n  },\n\n  computed: {\n    rootStyles() {\n      return {\n        backgroundColor: `hsl(${this.hue}, 100%, 50%)`\n      };\n    },\n\n    cursorStyles() {\n      return {\n        top: `${this.cursorTop}px`,\n        left: `${this.cursorLeft}px`\n      };\n    }\n  },\n\n  watch: {\n    saturation() {\n      this.update();\n    },\n    value() {\n      this.update();\n    }\n  },\n\n  mounted() {\n    draggable(this.$el, {\n      drag: this.handleDrag,\n      end: this.handleDrag\n    });\n\n    this.update();\n  },\n\n  methods: {\n    update() {\n      const { clientWidth: width, clientHeight: height } = this.$el;\n      this.cursorLeft = (this.saturation * width) / 100;\n      this.cursorTop = ((100 - this.value) * height) / 100;\n    },\n\n    handleDrag(event) {\n      const rect = this.$el.getBoundingClientRect();\n\n      let left = event.clientX - rect.left;\n      let top = event.clientY - rect.top;\n      left = Math.min(Math.max(0, left), rect.width);\n      top = Math.min(Math.max(0, top), rect.height);\n\n      this.cursorLeft = left;\n      this.cursorTop = top;\n\n      this.$emit('update:saturation', (left / rect.width) * 100);\n      this.$emit('update:value', 100 - (top / rect.height) * 100);\n    }\n  }\n};\n</script>\n"
  },
  {
    "path": "src/qComponents/QColorPicker/src/QPickerDropdown.vue",
    "content": "<template>\n  <transition name=\"fade\">\n    <div\n      v-show=\"isShown\"\n      ref=\"dropdown\"\n      v-click-outside=\"closeDropdown\"\n      class=\"q-picker-dropdown\"\n      tabindex=\"-1\"\n      @keyup.esc=\"closeDropdown\"\n    >\n      <div class=\"q-picker-dropdown__base\">\n        <q-color-svpanel\n          ref=\"sv\"\n          :hue=\"hue\"\n          :saturation.sync=\"saturation\"\n          :value.sync=\"value\"\n        />\n\n        <q-color-hue-slider\n          ref=\"hue\"\n          :hue.sync=\"hue\"\n        />\n      </div>\n\n      <q-color-alpha-slider\n        v-if=\"alphaShown\"\n        ref=\"alpha\"\n        :color=\"rgbString\"\n        :alpha.sync=\"alpha\"\n      />\n\n      <div class=\"q-picker-dropdown__footer\">\n        <div class=\"q-picker-dropdown__input\">\n          <q-input\n            v-model=\"tempColor\"\n            :validate-event=\"false\"\n            @keyup.native.enter=\"updateHSVA(tempColor)\"\n            @blur=\"updateHSVA(tempColor)\"\n          />\n        </div>\n\n        <q-button\n          v-if=\"isClearBtnShown\"\n          theme=\"link\"\n          @click=\"handleClearBtnClick\"\n        >\n          {{ $t('QColorPicker.clear') }}\n        </q-button>\n\n        <q-button @click=\"handleConfirmBtnClick\">\n          {{ $t('QColorPicker.confirm') }}\n        </q-button>\n      </div>\n    </div>\n  </transition>\n</template>\n\n<script>\nimport Color from 'color';\n\nimport QButton from '../../QButton';\nimport QColorSvpanel from './QColorSvpanel';\nimport QColorAlphaSlider from './QColorAlphaSlider';\nimport QColorHueSlider from './QColorHueSlider';\n\nexport default {\n  name: 'QPickerDropdown',\n  componentName: 'QPickerDropdown',\n\n  components: {\n    QButton,\n    QColorSvpanel,\n    QColorHueSlider,\n    QColorAlphaSlider\n  },\n\n  props: {\n    isShown: {\n      type: Boolean,\n      default: false\n    },\n    isClearBtnShown: {\n      type: Boolean,\n      default: false\n    },\n    color: {\n      type: String,\n      default: null\n    },\n    colorFormat: {\n      type: String,\n      default: 'hex',\n      validator: value => ['hex', 'rgb'].includes(value)\n    },\n    alphaShown: {\n      type: Boolean,\n      default: false\n    }\n  },\n\n  data() {\n    return {\n      elementToFocusAfterClosing: null,\n      tempColor: '',\n      hue: 0,\n      saturation: 100,\n      value: 100,\n      alpha: 100\n    };\n  },\n\n  computed: {\n    colorModel() {\n      return Color({\n        h: this.hue,\n        s: this.saturation,\n        v: this.value\n      });\n    },\n\n    rgbString() {\n      return this.colorModel.rgb().string();\n    },\n\n    colorString() {\n      if (this.alphaShown || this.colorFormat === 'rgb') {\n        return this.colorModel\n          .alpha(this.alpha / 100)\n          .rgb()\n          .string();\n      }\n      return this.colorModel.hex();\n    }\n  },\n\n  watch: {\n    async isShown(value) {\n      if (!value) {\n        document.removeEventListener('focus', this.handleDocumentFocus, true);\n        await this.$nextTick();\n        this.elementToFocusAfterClosing?.focus();\n        return;\n      }\n\n      document.addEventListener('focus', this.handleDocumentFocus, true);\n      this.updateHSVA(this.color);\n      this.tempColor = this.colorString;\n      this.elementToFocusAfterClosing = document.activeElement;\n\n      await this.$nextTick();\n\n      this.$refs.dropdown.focus();\n\n      const { sv, hue, alpha } = this.$refs;\n      sv?.update();\n      hue?.update();\n      alpha?.update();\n    },\n\n    color: {\n      immediate: true,\n      handler(value) {\n        this.updateHSVA(value);\n      }\n    },\n\n    colorString: {\n      immediate: true,\n      handler(value) {\n        this.tempColor = value;\n      }\n    }\n  },\n\n  methods: {\n    closeDropdown() {\n      this.$emit('close');\n    },\n\n    handleDocumentFocus(event) {\n      if (!this.$refs.dropdown.contains(event.target)) {\n        this.$refs.dropdown.focus();\n      }\n    },\n\n    updateHSVA(value) {\n      try {\n        const { valpha, color } = Color(value).hsv();\n\n        this.hue = color[0];\n        this.saturation = color[1];\n        this.value = color[2];\n        this.alpha = valpha * 100;\n      } catch (error) {\n        // do nothing\n      }\n    },\n\n    handleClearBtnClick() {\n      this.$emit('clear');\n    },\n\n    handleConfirmBtnClick() {\n      this.$emit('pick', this.colorString);\n    }\n  }\n};\n</script>\n"
  },
  {
    "path": "src/qComponents/QColorPicker/src/draggable.js",
    "content": "let isDragging = false;\n\nexport default function(element, options) {\n  const moveFn = event => {\n    if (options.drag) options.drag(event);\n  };\n\n  const upFn = event => {\n    document.removeEventListener('mousemove', moveFn);\n    document.removeEventListener('mouseup', upFn);\n    document.onselectstart = null;\n    document.ondragstart = null;\n\n    isDragging = false;\n\n    if (options.end) options.end(event);\n  };\n\n  element.addEventListener('mousedown', event => {\n    if (isDragging) return;\n    document.onselectstart = () => false;\n    document.ondragstart = () => false;\n\n    document.addEventListener('mousemove', moveFn);\n    document.addEventListener('mouseup', upFn);\n    isDragging = true;\n\n    if (options.start) options.start(event);\n  });\n}\n"
  },
  {
    "path": "src/qComponents/QColorPicker/src/q-color-alpha-slider.scss",
    "content": ".q-color-alpha-slider {\n  position: relative;\n  width: 464px;\n  height: 16px;\n  margin-top: 8px;\n  overflow: hidden;\n  background-image: linear-gradient(\n      45deg,\n      var(--color-tertiary-gray-ultra-dark) 25%,\n      transparent 25%\n    ),\n    linear-gradient(\n      -45deg,\n      var(--color-tertiary-gray-ultra-dark) 25%,\n      transparent 25%\n    ),\n    linear-gradient(\n      45deg,\n      transparent 75%,\n      var(--color-tertiary-gray-ultra-dark) 75%\n    ),\n    linear-gradient(\n      -45deg,\n      transparent 75%,\n      var(--color-tertiary-gray-ultra-dark) 75%\n    );\n  background-position: 8px 16px, -8px 8px, 16px 8px, -16px 0;\n  background-size: 16px 16px;\n  border-radius: var(--border-radius-base);\n  box-shadow: inset 2px 2px 4px rgba(var(--color-rgb-gray), 0.32);\n  cursor: pointer;\n\n  &__bar {\n    width: 100%;\n    height: 100%;\n  }\n\n  &__thumb {\n    position: absolute;\n    top: 0;\n    left: 0;\n    z-index: 1;\n    width: 8px;\n    height: 12px;\n    margin: 2px;\n    background-color: var(--color-tertiary-white);\n    border-radius: 2px;\n    box-shadow: -1px -1px 3px rgba(var(--color-rgb-white), 0.25),\n      1px 1px 3px rgba(var(--color-rgb-blue), 0.4);\n  }\n}\n"
  },
  {
    "path": "src/qComponents/QColorPicker/src/q-color-hue-slider.scss",
    "content": ".q-color-hue-slider {\n  position: relative;\n  width: 16px;\n  height: 208px;\n  margin-left: 16px;\n  cursor: pointer;\n\n  &__bar {\n    width: 100%;\n    height: 100%;\n    background-image: linear-gradient(\n      180deg,\n      #f00 0,\n      #ff0 17%,\n      #0f0 33%,\n      #0ff 50%,\n      #00f 67%,\n      #f0f 83%,\n      #f00\n    );\n    border-radius: var(--border-radius-base);\n    box-shadow: inset 2px 2px 4px rgba(var(--color-rgb-gray), 0.32);\n  }\n\n  &__thumb {\n    position: absolute;\n    top: 0;\n    left: 0;\n    z-index: 1;\n    width: 12px;\n    height: 8px;\n    margin: 2px;\n    background-color: var(--color-tertiary-white);\n    border-radius: 2px;\n    box-shadow: -1px -1px 3px rgba(var(--color-rgb-white), 0.25),\n      1px 1px 3px rgba(var(--color-rgb-blue), 0.4);\n  }\n}\n"
  },
  {
    "path": "src/qComponents/QColorPicker/src/q-color-picker.scss",
    "content": "@import './q-picker-dropdown';\n@import './q-color-svpanel';\n@import './q-color-hue-slider';\n@import './q-color-alpha-slider';\n\n.q-color-picker {\n  &-trigger {\n    display: inline-block;\n    cursor: pointer;\n\n    &__default {\n      position: relative;\n      display: block;\n      width: 40px;\n      height: 40px;\n      padding: 0;\n      font-size: 24px;\n      border: none;\n      border-radius: var(--border-radius-base);\n\n      box-shadow: -1px -1px 3px rgba(var(--color-rgb-white), 0.25),\n        1px 1px 3px rgba(var(--color-rgb-blue), 0.4),\n        4px 4px 8px rgba(var(--color-rgb-blue), 0.4),\n        -4px -4px 12px var(--color-tertiary-white);\n      cursor: inherit;\n\n      &:hover {\n        box-shadow: -1px -1px 4px rgba(var(--color-rgb-white), 0.25),\n          1px 1px 4px rgba(var(--color-rgb-blue), 0.4),\n          4px 4px 8px rgba(var(--color-rgb-blue), 0.4),\n          -4px -4px 8px rgba(var(--color-rgb-white), 0.8);\n      }\n\n      &:focus {\n        outline: none;\n        box-shadow: -1px -1px 3px rgba(var(--color-rgb-white), 0.25),\n          1px 1px 3px rgba(var(--color-rgb-blue), 0.4);\n      }\n\n      &::before {\n        content: '';\n        position: absolute;\n        top: 0;\n        left: 0;\n        display: block;\n        width: 100%;\n        height: 100%;\n        background-image: linear-gradient(\n            45deg,\n            var(--color-tertiary-gray-ultra-dark) 25%,\n            transparent 25%\n          ),\n          linear-gradient(\n            -45deg,\n            var(--color-tertiary-gray-ultra-dark) 25%,\n            transparent 25%\n          ),\n          linear-gradient(\n            45deg,\n            transparent 75%,\n            var(--color-tertiary-gray-ultra-dark) 75%\n          ),\n          linear-gradient(\n            -45deg,\n            transparent 75%,\n            var(--color-tertiary-gray-ultra-dark) 75%\n          );\n        background-position: 8px 16px, -8px 8px, 16px 8px, -16px 0;\n        background-size: 16px 16px;\n        border-radius: var(--border-radius-base);\n      }\n\n      .q-color-picker-trigger_is-disabled & {\n        background-color: var(--color-tertiary-gray);\n        box-shadow: -1px -1px 3px rgba(var(--color-rgb-white), 0.25),\n          1px 1px 3px rgba(var(--color-rgb-blue), 0.4);\n        cursor: not-allowed;\n\n        &::before {\n          display: none;\n        }\n      }\n    }\n\n    &__color {\n      position: absolute;\n      top: 0;\n      left: 0;\n      display: block;\n      width: 100%;\n      height: 100%;\n      overflow: hidden;\n      background-color: var(--color-tertiary-gray-light);\n      border-radius: var(--border-radius-base);\n\n      &::before {\n        content: '';\n        position: absolute;\n        top: 0;\n        left: 0;\n        width: 100%;\n        height: 100%;\n        opacity: 0;\n        transition: opacity ease 0.25s;\n      }\n\n      .q-color-picker-trigger__default:hover & {\n        &::before {\n          background-color: rgba(var(--color-rgb-gray), 0.1);\n          opacity: 1;\n        }\n\n        .q-color-picker-trigger_is-disabled & {\n          &::before {\n            opacity: 0;\n          }\n        }\n      }\n\n      .q-color-picker-trigger__default:focus & {\n        &::before {\n          background-color: rgba(var(--color-rgb-white), 0.1);\n          opacity: 1;\n        }\n      }\n    }\n\n    &__icon {\n      position: relative;\n      z-index: 1;\n      line-height: 40px;\n      color: var(--color-primary-black);\n      transition: transform 0.25s ease, color 0.25s ease;\n\n      .q-color-picker-trigger_is-opened & {\n        transform: rotate(-180deg);\n      }\n\n      .q-color-picker-trigger_is-disabled & {\n        color: rgba(var(--color-rgb-gray), 0.64);\n      }\n\n      &_light {\n        color: var(--color-tertiary-white);\n\n        .q-color-picker-trigger_is-disabled & {\n          color: rgba(var(--color-rgb-white), 0.64);\n        }\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "src/qComponents/QColorPicker/src/q-color-svpanel.scss",
    "content": ".q-color-svpanel {\n  position: relative;\n  width: 464px;\n  height: 208px;\n  cursor: pointer;\n\n  &::before,\n  &::after {\n    content: '';\n    position: absolute;\n    top: 0;\n    left: 0;\n    width: 100%;\n    height: 100%;\n  }\n\n  &::before {\n    background-image: linear-gradient(\n      90deg,\n      var(--color-tertiary-white),\n      transparent\n    );\n  }\n\n  &::after {\n    background-image: linear-gradient(0, #000, transparent);\n  }\n\n  &__cursor {\n    position: absolute;\n    z-index: 1;\n    width: 8px;\n    height: 8px;\n    background-color: var(--color-tertiary-gray-lighter);\n    border-radius: 50%;\n    box-shadow: -1px -1px 3px rgba(var(--color-rgb-white), 0.25),\n      1px 1px 3px rgba(var(--color-rgb-blue), 0.4),\n      4px 4px 8px rgba(var(--color-rgb-blue), 0.4),\n      -4px -4px 12px var(--color-tertiary-white);\n    transform: translate(-4px, -4px);\n    cursor: grab;\n  }\n}\n"
  },
  {
    "path": "src/qComponents/QColorPicker/src/q-picker-dropdown.scss",
    "content": ".q-picker-dropdown {\n  padding: 16px;\n  background-color: var(--color-tertiary-gray-ultra-light);\n  border-radius: var(--border-radius-base);\n  outline: none;\n  box-shadow: -1px -1px 3px rgba(var(--color-rgb-white), 0.25),\n    1px 1px 3px rgba(var(--color-rgb-blue), 0.4);\n\n  &__base {\n    display: flex;\n  }\n\n  &__footer {\n    display: flex;\n    margin-top: 16px;\n  }\n\n  &__input {\n    width: 223px;\n    margin-right: auto;\n  }\n}\n"
  },
  {
    "path": "src/qComponents/QContextMenu/index.js",
    "content": "import QContextMenu from './src/QContextMenu.vue';\n\n/* istanbul ignore next */\nQContextMenu.install = function(Vue) {\n  Vue.component(QContextMenu.name, QContextMenu);\n};\n\nexport default QContextMenu;\n"
  },
  {
    "path": "src/qComponents/QContextMenu/src/QContextMenu.vue",
    "content": "<template>\n  <div class=\"q-context-wrapper\">\n    <div\n      ref=\"reference\"\n      class=\"q-context-trigger\"\n      @click=\"handleTriggerClick\"\n    >\n      <slot v-if=\"$slots.default\" />\n      <button\n        v-else\n        class=\"q-context-trigger__button q-icon-dots-3-horizontal\"\n      />\n    </div>\n\n    <div\n      v-show=\"isContextMenuShown\"\n      ref=\"qContextMenu\"\n      class=\"q-context-menu\"\n    >\n      <button\n        v-for=\"(item, index) in menuItems\"\n        :key=\"index\"\n        tabindex=\"-1\"\n        class=\"q-context-menu__item\"\n        :class=\"{ 'q-context-menu__item_with-icon': item.icon }\"\n        @click.prevent=\"handleItemClick(item.action)\"\n      >\n        <span\n          v-if=\"item.icon\"\n          class=\"q-context-menu__icon\"\n          :class=\"item.icon\"\n        />\n        {{ item.name }}\n      </button>\n    </div>\n  </div>\n</template>\n\n<script>\nimport { createPopper } from '@popperjs/core';\n\nexport default {\n  name: 'QContextMenu',\n  componentName: 'QContextMenu',\n\n  props: {\n    position: {\n      type: String,\n      default: 'left',\n      validator: value => ['left', 'right'].includes(value)\n    },\n    menuItems: {\n      type: Array,\n      required: true\n    },\n    appendToBody: {\n      type: Boolean,\n      default: true\n    }\n  },\n\n  data() {\n    return {\n      isContextMenuShown: false,\n      menuItemElements: null\n    };\n  },\n\n  computed: {\n    placement() {\n      return this.position === 'right' ? 'bottom-start' : 'bottom-end';\n    }\n  },\n\n  beforeDestroy() {\n    document.removeEventListener('click', this.handleDocumentClick);\n\n    const { qContextMenu } = this.$refs;\n\n    if (qContextMenu?.parentNode === document.body)\n      document.body.removeChild(qContextMenu);\n  },\n\n  methods: {\n    handleDocumentClick({ target }) {\n      if (\n        this.$refs.reference?.contains(target) ||\n        this.$refs.qContextMenu.contains(target)\n      ) {\n        return;\n      }\n\n      this.closePopper();\n    },\n\n    createPopper() {\n      document.addEventListener('click', this.handleDocumentClick);\n      document.addEventListener('keyup', this.handleKeyUp);\n      this.isContextMenuShown = true;\n\n      if (this.appendToBody) document.body.appendChild(this.$refs.qContextMenu);\n\n      const options = {\n        placement: this.placement,\n        computeStyle: {\n          boundariesElement: 'body',\n          gpuAcceleration: false\n        },\n        modifiers: [\n          {\n            name: 'offset',\n            options: {\n              offset: [0, -40]\n            }\n          }\n        ]\n      };\n\n      this.popperJS = createPopper(\n        this.$refs.reference,\n        this.$refs.qContextMenu,\n        options\n      );\n\n      this.$refs.qContextMenu.style.zIndex = this.$Q?.zIndex ?? 2000;\n      this.menuItemElements = this.$refs.qContextMenu.querySelectorAll(\n        '.q-context-menu__item'\n      );\n    },\n\n    handleTriggerClick() {\n      if (this.isContextMenuShown) {\n        this.closePopper();\n        return;\n      }\n\n      this.createPopper();\n    },\n\n    handleItemClick(actionName) {\n      this.$emit('action', actionName, this.entity);\n      this.closePopper();\n    },\n\n    handleKeyUp(e) {\n      if (!this.isContextMenuShown) return;\n      if (e.key === 'Escape') this.closePopper();\n      if (!['ArrowUp', 'ArrowDown'].includes(e.key)) return;\n      if (document.activeElement.classList.contains('q-context-menu__item')) {\n        let currentNodeIndex;\n        let nextNodeIndex;\n        Array.from(this.menuItemElements).some((element, index) => {\n          const isItActiveElement = document.activeElement === element;\n\n          if (isItActiveElement) currentNodeIndex = index;\n\n          return isItActiveElement;\n        });\n\n        switch (e.key) {\n          case 'ArrowUp': {\n            nextNodeIndex = currentNodeIndex - 1;\n            break;\n          }\n\n          case 'ArrowDown': {\n            nextNodeIndex = currentNodeIndex + 1;\n            break;\n          }\n\n          default:\n            break;\n        }\n        this.menuItemElements[nextNodeIndex]?.focus();\n      } else {\n        this.menuItemElements[0]?.focus();\n      }\n    },\n\n    closePopper() {\n      document.removeEventListener('click', this.handleDocumentClick);\n      document.removeEventListener('keyup', this.handleKeyUp);\n\n      if (this.appendToBody) document.body.removeChild(this.$refs.qContextMenu);\n\n      this.isContextMenuShown = false;\n      this.menuItemElements = null;\n    }\n  }\n};\n</script>\n"
  },
  {
    "path": "src/qComponents/QContextMenu/src/q-context-menu.scss",
    "content": ".q-context {\n  &-menu {\n    min-width: 150px;\n    overflow: hidden;\n    background-color: var(--color-tertiary-gray-light);\n    border-radius: var(--border-radius-base);\n    box-shadow: var(--box-shadow-primary);\n\n    &__icon {\n      margin-right: 16px;\n      font-size: 24px;\n    }\n\n    &__item {\n      position: relative;\n      display: flex;\n      width: 100%;\n      padding: 12px 24px;\n      font-weight: var(--font-weight-base);\n      font-size: var(--font-size-base);\n      line-height: 24px;\n      color: var(--color-primary-blue);\n      text-decoration: none;\n      white-space: nowrap;\n      background-color: var(--color-tertiary-gray-light);\n      border: none;\n      cursor: pointer;\n\n      &_with-icon {\n        padding-right: 50px;\n        padding-left: 24px;\n      }\n\n      &:not(:first-child) {\n        margin-top: 1px;\n      }\n\n      &:hover,\n      &:focus {\n        position: relative;\n        z-index: 1;\n        color: var(--color-primary-black);\n        background-color: var(--color-tertiary-gray);\n        outline: none;\n      }\n\n      &::before {\n        content: '';\n        position: absolute;\n        top: 0;\n        left: 0;\n        width: 100%;\n        height: 100%;\n        box-shadow: -1px -1px 3px rgba(var(--color-rgb-white), 0.25),\n          1px 1px 3px rgba(var(--color-rgb-blue), 0.4);\n      }\n    }\n  }\n\n  &-trigger {\n    display: inline-block;\n    cursor: pointer;\n\n    &__button {\n      display: block;\n      width: 40px;\n      height: 40px;\n      padding: 0;\n      font-size: 24px;\n      color: var(--color-primary-blue);\n      background-color: transparent;\n      border: none;\n      outline: none;\n\n      &:hover,\n      &[data-focus-visible-added] {\n        color: var(--color-primary-black);\n        background-color: rgba(var(--color-rgb-gray), 0.16);\n        border-radius: 100%;\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "src/qComponents/QDatePicker/index.js",
    "content": "import QDatePicker from './src/QDatePicker.vue';\n\n/* istanbul ignore next */\nQDatePicker.install = function install(Vue) {\n  Vue.component(QDatePicker.name, QDatePicker);\n};\n\nexport default QDatePicker;\n"
  },
  {
    "path": "src/qComponents/QDatePicker/src/QDatePicker.vue",
    "content": "<template>\n  <div v-click-outside=\"handleClose\">\n    <q-input\n      v-if=\"!isRanged\"\n      ref=\"reference\"\n      :class=\"['q-date-editor', { 'q-input_focus': pickerVisible }]\"\n      :readonly=\"!editable\"\n      :disabled=\"pickerDisabled\"\n      :name=\"name\"\n      :placeholder=\"placeholder || $t('QDatePicker.placeholder')\"\n      :value=\"displayValue\"\n      @focus=\"handleFocus\"\n      @keyup.native=\"handleKeyUp\"\n      @input=\"handleInput\"\n      @change=\"handleChange\"\n      @mouseenter.native=\"handleMouseEnter\"\n      @mouseleave.native=\"showClose = false\"\n    >\n      <span\n        slot=\"suffix\"\n        class=\"q-input__icon\"\n        :class=\"iconClass\"\n        @click=\"handleIconClick\"\n      />\n    </q-input>\n    <div\n      v-else\n      ref=\"reference\"\n      :class=\"rangeClasses\"\n      tabindex=\"0\"\n      @click=\"handleRangeClick\"\n      @mouseenter=\"handleMouseEnter\"\n      @mouseleave=\"showClose = false\"\n      @keyup=\"handleKeyUp\"\n      @focus=\"handleFocus\"\n    >\n      <input\n        autocomplete=\"off\"\n        class=\"q-range-input\"\n        :placeholder=\"startPlaceholder || $t('QDatePicker.startPlaceholder')\"\n        :value=\"displayValue && displayValue[0]\"\n        :disabled=\"pickerDisabled\"\n        :name=\"name && name[0]\"\n        readonly\n        tabindex=\"-1\"\n      />\n      <slot name=\"range-separator\">\n        <span class=\"q-range-separator\">{{ rangeSeparator }}</span>\n      </slot>\n      <input\n        autocomplete=\"off\"\n        :placeholder=\"endPlaceholder || $t('QDatePicker.endPlaceholder')\"\n        :value=\"displayValue && displayValue[1]\"\n        :disabled=\"pickerDisabled\"\n        :name=\"name && name[1]\"\n        class=\"q-range-input\"\n        readonly\n        tabindex=\"-1\"\n      />\n      <span\n        :class=\"iconClass\"\n        class=\"q-input__icon\"\n        @click=\"handleIconClick\"\n      />\n    </div>\n    <component\n      :is=\"panelComponent\"\n      ref=\"panel\"\n      :class=\"{ 'q-picker-panel_shown': Boolean(popper) }\"\n      :visible=\"Boolean(popper)\"\n      :type=\"type\"\n      :shortcuts=\"shortcuts\"\n      :disabled-values=\"disabledValues\"\n      :first-day-of-week=\"calcFirstDayOfWeek\"\n      :value=\"transformedValue\"\n      :show-time=\"timepicker\"\n      @pick=\"handlePickClick\"\n    >\n      <slot\n        v-if=\"$slots.sidebar\"\n        :slot=\"$slots.sidebar\"\n        name=\"sidebar\"\n      />\n    </component>\n  </div>\n</template>\n\n<script>\nimport { createPopper } from '@popperjs/core';\nimport { isNil, isString } from 'lodash-es';\nimport {\n  formatISO,\n  isDate,\n  isValid,\n  parse,\n  startOfMonth,\n  startOfWeek,\n  startOfYear,\n  parseISO\n} from 'date-fns';\nimport { formatLocalDate } from './helpers';\nimport Emitter from '../../mixins/emitter';\nimport Pickers from '../../mixins/pickers';\n\nimport DatePanel from './panel/date';\nimport DateRangePanel from './panel/date-range';\nimport MonthRangePanel from './panel/month-range';\nimport YearRangePanel from './panel/year-range';\n\nconst validator = function(val) {\n  // either: String, Array of String, null / undefined\n  return (\n    val === null ||\n    val === undefined ||\n    isString(val) ||\n    (Array.isArray(val) && val.length === 2 && val.every(isString))\n  );\n};\n\nconst dateValidator = function(val) {\n  return (\n    null ||\n    isDate(val) ||\n    isDate(parseISO(val)) ||\n    (Array.isArray(val) &&\n      val.length === 2 &&\n      (val.every(isDate) || val.every(isDate(parseISO))))\n  );\n};\n\nconst convertDate = value => {\n  if (value && !isDate(value)) {\n    return parseISO(value);\n  }\n\n  return value;\n};\n\nexport default {\n  name: 'QDatePicker',\n  componentName: 'QDatePicker',\n  mixins: [Emitter, Pickers],\n\n  inject: {\n    qForm: {\n      default: null\n    },\n    qFormItem: {\n      default: null\n    }\n  },\n\n  model: {\n    prop: 'value',\n    event: 'change'\n  },\n\n  props: {\n    /**\n     * one of sugested types\n     */\n    type: {\n      type: String,\n      default: 'date',\n      validator: value =>\n        [\n          'date',\n          'datetime',\n          'week',\n          'month',\n          'year',\n          'daterange',\n          'datetimerange',\n          'monthrange',\n          'yearrange'\n        ].includes(value)\n    },\n    /**\n     * any format from date-fns https://date-fns.org/v2.16.1/docs/format\n     */\n    format: { type: String, default: 'dd MMMM yyyy' },\n    /**\n     * two options of returned value: 'date' - type Date format, 'iso' - ISO string format\n     */\n    outputFormat: {\n      type: String,\n      default: 'date',\n      validator: val => ['date', 'iso'].includes(val)\n    },\n    placeholder: { type: String, default: null },\n    /**\n     * only for ranged types\n     */\n    startPlaceholder: {\n      type: String,\n      default: null\n    },\n    /**\n     * only for ranged types\n     */\n    endPlaceholder: { type: String, default: null },\n    /**\n     * start with monday by default\n     */\n    firstDayOfWeek: {\n      default: null,\n      type: Number,\n      validator: val => val === null || (val >= 0 && val <= 6)\n    },\n    /**\n     * as native name for input\n     */\n    name: {\n      default: '',\n      validator\n    },\n    /**\n     * whether QDatePicker is disabled\n     */\n    disabled: { type: Boolean, default: false },\n    /**\n     * whether DatePicker is clearable\n     */\n    clearable: {\n      type: Boolean,\n      default: true\n    },\n    /**\n     * whether DatePicker is editable, for type is `date` only\n     */\n    editable: {\n      type: Boolean,\n      default: true\n    },\n    /**\n     * type Date, type String (ISO), array for ranges\n     */\n    value: {\n      type: [String, Array, Date],\n      default: '',\n      validator: dateValidator\n    },\n    /**\n     * separator in the middle of the range\n     */\n    rangeSeparator: {\n      type: String,\n      default: '-'\n    },\n    /**\n     * type of each Object is { text: 'example', onClick(picker) }\n     */\n    shortcuts: { type: Array, default: () => [] },\n    /**\n     * any field is optional:\n     * `to` - disable all before this date,\n     * `from` - disable after this date,\n     * `ranges` - array of dateranges, each daterange is object and must has `start` and `end` field\n     */\n    disabledValues: {\n      type: Object,\n      default: () => ({})\n    },\n    /**\n     * whether to trigger form validation\n     */\n    validateEvent: {\n      type: Boolean,\n      default: true\n    },\n    /**\n     * whether to append the popper to body\n     */\n    appendToBody: {\n      type: Boolean,\n      default: false\n    }\n  },\n\n  data() {\n    return {\n      pickerVisible: false,\n      showClose: false,\n      userInput: null,\n      unwatchPickerOptions: null,\n      popper: null\n    };\n  },\n\n  provide() {\n    return {\n      picker: this\n    };\n  },\n\n  computed: {\n    calcFirstDayOfWeek() {\n      if (isNil(this.firstDayOfWeek)) return this.$Q.locale === 'ru' ? 1 : 0;\n\n      return this.firstDayOfWeek;\n    },\n    transformedValue() {\n      if (Array.isArray(this.value) && this.value.length) {\n        return [convertDate(this.value[0]), convertDate(this.value[1])];\n      }\n\n      if (isString(this.value)) return convertDate(this.value);\n\n      return this.value;\n    },\n    rangeClasses() {\n      return {\n        'q-date-editor': true,\n        'q-range-editor': true,\n        'q-range-editor_disabled': this.pickerDisabled,\n        'q-range-editor_focused': this.pickerVisible\n      };\n    },\n    iconClass() {\n      if (this.disabled) return 'q-icon-lock';\n      const calendarIcon = this.timepicker\n        ? 'q-icon-calendar-clock'\n        : 'q-icon-calendar';\n      return this.showClose ? 'q-icon-close' : calendarIcon;\n    },\n\n    panelComponent() {\n      switch (this.type) {\n        case 'daterange':\n        case 'datetimerange':\n          return DateRangePanel;\n        case 'monthrange':\n          return MonthRangePanel;\n        case 'yearrange':\n          return YearRangePanel;\n        default:\n          return DatePanel;\n      }\n    },\n\n    isRanged() {\n      return this.type.includes('range');\n    },\n\n    timepicker() {\n      return this.type.includes('time');\n    },\n\n    isValueEmpty() {\n      if (Array.isArray(this.transformedValue)) {\n        return !this.transformedValue.length;\n      }\n\n      return !this.transformedValue;\n    },\n\n    displayValue() {\n      let formattedValue = '';\n\n      if (Array.isArray(this.transformedValue)) {\n        formattedValue = this.transformedValue.map(dateFromArray =>\n          formatLocalDate(dateFromArray, this.format, this.$Q.locale)\n        );\n      } else if (\n        isDate(this.transformedValue) &&\n        isValid(this.transformedValue)\n      ) {\n        formattedValue = formatLocalDate(\n          this.transformedValue,\n          this.format,\n          this.$Q.locale\n        );\n      }\n\n      if (Array.isArray(this.userInput)) {\n        return [\n          this.userInput[0] ?? formattedValue?.[0] ?? '',\n          this.userInput[1] ?? formattedValue?.[1] ?? ''\n        ];\n      }\n      if (this.userInput !== null) {\n        return this.userInput;\n      }\n      if (formattedValue) {\n        return formattedValue;\n      }\n\n      return '';\n    },\n\n    pickerDisabled() {\n      return this.disabled || this.qForm?.disabled;\n    }\n  },\n\n  watch: {\n    pickerVisible(val) {\n      if (this.pickerDisabled) return;\n      if (val) {\n        this.createPopper();\n      } else {\n        this.destroyPopper();\n        this.userInput = null;\n        if (this.validateEvent) {\n          this.qFormItem?.validateField('blur');\n        }\n      }\n    },\n\n    value() {\n      if (!this.pickerVisible && this.validateEvent) {\n        this.qFormItem?.validateField('change');\n      }\n    }\n  },\n\n  beforeDestroy() {\n    this.destroyPopper();\n  },\n\n  methods: {\n    handlePickClick(val, { hidePicker = true } = {}) {\n      this.pickerVisible = !hidePicker;\n      this.emitChange(val);\n    },\n\n    createPopper() {\n      if (this.appendToBody) {\n        document.body.appendChild(this.$refs.panel.$el);\n      }\n\n      const reference =\n        this.$refs.reference instanceof Element\n          ? this.$refs.reference\n          : this.$refs.reference.$el;\n      const panel = this.$refs.panel.$el;\n\n      this.popper = createPopper(reference, panel, {\n        modifiers: [\n          {\n            name: 'offset',\n            options: {\n              offset: [0, 8]\n            }\n          },\n          {\n            name: 'flip',\n            options: {\n              fallbackPlacements: ['top', 'bottom']\n            }\n          }\n        ]\n      });\n\n      panel.style.zIndex = this.$Q?.zIndex ?? 2000;\n      document.addEventListener('keyup', this.handleKeyUp, true);\n    },\n\n    destroyPopper() {\n      if (this.popper) {\n        this.popper.destroy();\n        this.popper = null;\n      }\n\n      const dropdown = this.$refs?.panel?.$el;\n      if (dropdown?.parentNode === document.body) {\n        document.body.removeChild(dropdown);\n      }\n\n      document.removeEventListener('keyup', this.handleKeyUp, true);\n    },\n\n    focus() {\n      if (!this.isRanged) {\n        this.$refs.reference.focus();\n      } else {\n        this.handleFocus();\n      }\n    },\n\n    formatToISO(date) {\n      if (Array.isArray(date)) {\n        return [formatISO(date[0]), formatISO(date[1])];\n      }\n\n      return formatISO(date);\n    },\n\n    handleMouseEnter() {\n      if (this.pickerDisabled) return;\n      if (!this.isValueEmpty && this.clearable) {\n        this.showClose = true;\n      }\n    },\n\n    handleKeyUp(e) {\n      // if user is typing, do not let picker handle key input\n      if (this.userInput) {\n        e.stopPropagation();\n      }\n\n      switch (e.key) {\n        case 'ArrowRight':\n        case 'ArrowUp':\n        case 'ArrowLeft':\n        case 'ArrowDown': {\n          this.$refs.panel.navigateDropdown(e);\n          break;\n        }\n        case 'Escape': {\n          this.pickerVisible = false;\n          e.stopPropagation();\n          break;\n        }\n        case 'Tab': {\n          if (this.$el.contains(document.activeElement)) {\n            this.$refs.panel.navigateDropdown(e);\n            return;\n          }\n\n          if (!this.isRanged) {\n            this.handleChange();\n          }\n\n          this.pickerVisible = false;\n          e.stopPropagation();\n          break;\n        }\n        default:\n          break;\n      }\n    },\n\n    handleChange() {\n      let value;\n      let format;\n      const date = this.userInput;\n      if (date) {\n        format = date.length === 10 ? 'dd.MM.yyyy' : 'dd.MM.yy';\n        if (this.timepicker && date.length > 10) {\n          format = \"dd.MM.yyyy', 'HH:mm:ss\";\n        }\n        value = parse(date, format, new Date());\n\n        if (!Number.isNaN(Number(value))) {\n          let resultValue = value;\n          switch (this.type) {\n            case 'week':\n              resultValue = startOfWeek(value, { weekStartsOn: 1 });\n              break;\n            case 'month':\n              resultValue = startOfMonth(value);\n              break;\n            case 'year':\n              resultValue = startOfYear(value);\n              break;\n            default:\n              resultValue = value;\n              break;\n          }\n          this.emitChange(resultValue);\n        }\n      } else {\n        this.emitChange(null);\n      }\n      this.userInput = null;\n    },\n\n    handleIconClick(event) {\n      if (this.pickerDisabled) return;\n      if (this.showClose) {\n        event.stopPropagation();\n        this.emitChange(null);\n        this.userInput = null;\n        this.showClose = false;\n      } else {\n        this.pickerVisible = !this.pickerVisible;\n      }\n    },\n\n    handleClose(e) {\n      if (!this.pickerVisible) return;\n      if (this.appendToBody) {\n        const path = e.path || (e.composedPath && e.composedPath());\n        const isClickToPanel = path.find(\n          element => element === this.$refs.panel.$el\n        );\n        if (!isClickToPanel) {\n          this.pickerVisible = false;\n        }\n      } else {\n        this.pickerVisible = false;\n      }\n    },\n\n    handleFocus() {\n      this.pickerVisible = true;\n      this.$emit('focus', this);\n      if (\n        !isDate(this.transformedValue) ||\n        Array.isArray(this.transformedValue)\n      )\n        return;\n      const format = this.timepicker ? 'dd.MM.yyyy, HH:mm:ss' : 'dd.MM.yy';\n      this.userInput = formatLocalDate(\n        this.transformedValue,\n        format,\n        this.$Q.locale\n      );\n    },\n\n    handleRangeClick() {\n      this.pickerVisible = true;\n      this.$emit('focus', this);\n    },\n\n    emitChange(val) {\n      let formatted = val;\n      if (this.outputFormat === 'iso' && val) {\n        formatted = this.formatToISO(val);\n      }\n\n      if (formatted !== this.value) {\n        this.$emit('change', formatted);\n        if (this.validateEvent) {\n          this.qFormItem?.validateField('change');\n        }\n      }\n    }\n  }\n};\n</script>\n"
  },
  {
    "path": "src/qComponents/QDatePicker/src/basic/date-table.vue",
    "content": "<template>\n  <table\n    cellspacing=\"10\"\n    cellpadding=\"2\"\n    class=\"q-date-table\"\n    @mousemove=\"handleMouseMove\"\n  >\n    <thead>\n      <tr>\n        <th\n          v-for=\"day in days\"\n          :key=\"day\"\n          class=\"q-date-table_days\"\n        >\n          {{ day }}\n        </th>\n      </tr>\n    </thead>\n    <tbody>\n      <tr\n        v-for=\"(row, key) in rows\"\n        :key=\"key\"\n        class=\"q-date-table__row\"\n      >\n        <td\n          v-for=\"(cell, index) in row\"\n          :key=\"index\"\n          class=\"q-date-table__cell-wrapper\"\n        >\n          <button\n            :class=\"getCellClasses(cell)\"\n            type=\"button\"\n            tabindex=\"-1\"\n            @click=\"handleClick(cell)\"\n          >\n            {{ cell.text }}\n          </button>\n        </td>\n      </tr>\n    </tbody>\n  </table>\n</template>\n\n<script>\nimport {\n  getDaysInMonth,\n  startOfMonth,\n  endOfMonth,\n  isSameDay,\n  isBefore,\n  isAfter,\n  isWithinInterval,\n  startOfWeek,\n  endOfWeek,\n  isToday,\n  isDate\n} from 'date-fns';\nimport { ru, enGB as en } from 'date-fns/locale';\n\nconst locales = { ru, en };\n\nconst checkDisabled = ({ date }, disabledValues) => {\n  if (!disabledValues) return false;\n  const disabled = [];\n  if (Array.isArray(disabledValues.ranges)) {\n    disabledValues.ranges.forEach(({ start, end }) => {\n      disabled.push(\n        isWithinInterval(date, {\n          start,\n          end\n        })\n      );\n    });\n  }\n\n  if (isDate(disabledValues.to) && disabledValues.to) {\n    disabled.push(isBefore(date, disabledValues.to));\n  }\n\n  if (isDate(disabledValues.from) && disabledValues.from) {\n    disabled.push(isAfter(date, disabledValues.from));\n  }\n\n  return disabled.some(Boolean);\n};\n\nexport default {\n  props: {\n    firstDayOfWeek: {\n      default: 1,\n      type: Number\n    },\n\n    disabledValues: {\n      type: Object,\n      default: null\n    },\n\n    year: {\n      type: [String, Number],\n      default: new Date().getFullYear()\n    },\n    month: {\n      type: [String, Number],\n      default: new Date().getMonth()\n    },\n\n    value: { type: [Array, String, Date], default: null },\n\n    selectionMode: {\n      type: String,\n      default: 'date'\n    },\n\n    minDate: { type: [Date, String], default: null },\n\n    maxDate: { type: [Date, String], default: null },\n\n    rangeState: {\n      type: Object,\n      default() {\n        return {\n          endDate: null,\n          selecting: false\n        };\n      }\n    }\n  },\n\n  data() {\n    return {\n      lastRow: null,\n      lastColumn: null,\n      tableRows: [[], [], [], [], [], []]\n    };\n  },\n\n  computed: {\n    offsetDay() {\n      const week = this.firstDayOfWeek;\n      return week > 3 ? 7 - week : -week;\n    },\n\n    days() {\n      const DAYS_OF_WEEK = [...Array(7).keys()].map(i => {\n        return locales[this.$Q.locale].localize.day(i, { width: 'short' });\n      });\n\n      const day = this.firstDayOfWeek;\n      return [...DAYS_OF_WEEK, ...DAYS_OF_WEEK].slice(day, day + 7);\n    },\n\n    startMonthDate() {\n      return startOfMonth(new Date(this.year, this.month, 1));\n    },\n\n    endMonthDate() {\n      return endOfMonth(new Date(this.year, this.month, 1));\n    },\n\n    rows() {\n      const date = new Date(this.year, this.month, 1);\n      const firstDay = this.startMonthDate.getDay();\n      const dateCountOfMonth = getDaysInMonth(date);\n      const dateCountOfLastMonth = getDaysInMonth(\n        new Date(this.year, this.month === 0 ? 11 : this.month - 1)\n      );\n\n      const offset = this.offsetDay;\n      let count = 1;\n\n      return this.tableRows.map((row, i) => {\n        const newRow = [];\n        for (let j = 0; j < 7; j += 1) {\n          const cell = {\n            row: i,\n            column: j,\n            type: 'normal',\n            inRange: false,\n            start: false,\n            end: false\n          };\n\n          if (i === 0 || i === 1) {\n            const numberOfDaysFromPreviousMonth =\n              firstDay + offset < 0 ? 7 + firstDay + offset : firstDay + offset;\n\n            if (j + i * 7 >= numberOfDaysFromPreviousMonth) {\n              cell.text = count;\n              count += 1;\n              cell.date = new Date(this.year, this.month, cell.text);\n            } else {\n              cell.text =\n                dateCountOfLastMonth -\n                (numberOfDaysFromPreviousMonth - (j % 7)) +\n                1 +\n                i * 7;\n              cell.type = 'prev-month';\n              cell.date = new Date(this.year, this.month - 1, cell.text);\n            }\n          } else if (count <= dateCountOfMonth) {\n            cell.text = count;\n            count += 1;\n            cell.date = new Date(this.year, this.month, cell.text);\n          } else {\n            cell.text = count - dateCountOfMonth;\n            count += 1;\n            cell.type = 'next-month';\n            cell.date = new Date(this.year, this.month + 1, cell.text);\n          }\n\n          let maxDate = this.maxDate;\n          let minDate = this.minDate;\n          if (this.rangeState.selecting) {\n            maxDate = this.rangeState.endDate;\n          }\n\n          minDate = minDate?.getTime() ?? null;\n          maxDate = maxDate?.getTime() ?? minDate;\n          [minDate, maxDate] = [\n            Math.min(minDate, maxDate),\n            Math.max(minDate, maxDate)\n          ];\n\n          cell.inRange =\n            minDate &&\n            cell.date.getTime() >= minDate &&\n            cell.date.getTime() <= maxDate;\n\n          if (isToday(cell.date)) {\n            if (!['prev-month', 'next-month'].includes(cell.type)) {\n              cell.type = 'today';\n            }\n          }\n\n          cell.disabled = checkDisabled(cell, this.disabledValues);\n          newRow.push(cell);\n        }\n\n        return newRow;\n      });\n    }\n  },\n\n  methods: {\n    getCellClasses(cell) {\n      const classes = ['cell', 'cell_date'];\n      if (['today', 'prev-month', 'next-month'].includes(cell.type)) {\n        classes.push(`cell_${cell.type}`);\n      }\n\n      if (\n        ['normal', 'today'].includes(cell.type) &&\n        this.value &&\n        isSameDay(cell.date, this.value)\n      ) {\n        classes.push('cell_current');\n      }\n\n      if (\n        cell.inRange ||\n        (this.minDate && isSameDay(cell.date, this.minDate)) ||\n        (this.maxDate && isSameDay(cell.date, this.maxDate)) ||\n        (this.selectionMode === 'week' &&\n          this.value &&\n          isWithinInterval(cell.date, {\n            start: startOfWeek(this.value, { weekStartsOn: 1 }),\n            end: endOfWeek(this.value, { weekStartsOn: 1 })\n          }))\n      ) {\n        classes.push('cell_in-range');\n      }\n\n      if (cell.disabled) {\n        classes.push('cell_disabled');\n      }\n\n      return classes;\n    },\n\n    handleMouseMove(event) {\n      if (!this.rangeState.selecting) return;\n      let target = event.target;\n      if (target.tagName === 'BUTTON') {\n        target = target.parentNode;\n      }\n\n      if (target.tagName !== 'TD') return;\n\n      const row = target.parentNode.rowIndex - 1;\n      const column = target.cellIndex;\n      // can not select disabled date\n      if (this.rows[row]?.[column].disabled) return;\n\n      // only update rangeState when mouse moves to a new cell\n      // this avoids frequent Date object creation and improves performance\n      if (row !== this.lastRow || column !== this.lastColumn) {\n        this.lastRow = row;\n        this.lastColumn = column;\n        this.$emit('changerange', {\n          minDate: this.minDate,\n          maxDate: this.maxDate,\n          rangeState: {\n            selecting: true,\n            endDate: this.rows[row][column].date\n          }\n        });\n      }\n    },\n\n    handleClick(cell) {\n      if (cell.disabled || cell.type === 'week') return;\n      const newDate = cell.date;\n\n      if (this.selectionMode === 'range') {\n        if (!this.rangeState.selecting) {\n          this.$emit('pick', { minDate: newDate, maxDate: null });\n          this.rangeState.selecting = true;\n        } else {\n          if (newDate >= this.minDate) {\n            this.$emit('pick', { minDate: this.minDate, maxDate: newDate });\n          } else {\n            this.$emit('pick', { minDate: newDate, maxDate: this.minDate });\n          }\n          this.rangeState.selecting = false;\n        }\n      } else if (this.selectionMode === 'day') {\n        this.$emit('pick', newDate);\n      } else if (this.selectionMode === 'datetime') {\n        this.$emit('pick', newDate, { hidePicker: false });\n      } else if (this.selectionMode === 'week') {\n        const value = startOfWeek(newDate, { weekStartsOn: 1 });\n        this.$emit('pick', value);\n      } else if (this.selectionMode === 'dates') {\n        const value = this.value || [];\n        const newValue = [...value, newDate];\n        this.$emit('pick', newValue);\n      } else {\n        this.$emit('pick', newDate);\n      }\n    }\n  }\n};\n</script>\n"
  },
  {
    "path": "src/qComponents/QDatePicker/src/basic/month-table.vue",
    "content": "<template>\n  <table\n    cellspacing=\"4\"\n    cellpadding=\"5\"\n    class=\"q-month-table\"\n    @mousemove=\"handleMouseMove\"\n  >\n    <tr\n      v-for=\"(row, index) in rows\"\n      :key=\"index\"\n    >\n      <td\n        v-for=\"(cell, key) in row\"\n        :key=\"key\"\n        class=\"q-month-table__cell-wrapper\"\n      >\n        <button\n          :class=\"getCellClasses(cell)\"\n          :disabled=\"cell.disabled\"\n          type=\"button\"\n          tabindex=\"-1\"\n          @click=\"handleMonthTableClick(cell)\"\n        >\n          {{ getMonthName(cell.text) }}\n        </button>\n      </td>\n    </tr>\n  </table>\n</template>\n\n<script>\nimport { startOfMonth, isSameMonth, isBefore, isAfter } from 'date-fns';\nimport { formatLocalDate } from '../helpers';\n\nconst checkDisabled = ({ date }, disabledValues) => {\n  if (!disabledValues) return false;\n  const disabled = [];\n  if (Array.isArray(disabledValues.ranges)) {\n    disabledValues.ranges.forEach(range => {\n      disabled.push(\n        (isSameMonth(date, range.start) || isBefore(range.start, date)) &&\n          (isAfter(range.end, date) || isSameMonth(range.end, date))\n      );\n    });\n  }\n\n  if (disabledValues.to) {\n    disabled.push(isBefore(date, disabledValues.to));\n  }\n\n  if (disabledValues.from) {\n    disabled.push(isAfter(date, disabledValues.from));\n  }\n\n  return disabled.some(Boolean);\n};\n\nexport default {\n  props: {\n    disabledValues: {\n      type: Object,\n      default: null\n    },\n    value: { type: [Date, String], default: null },\n    selectionMode: {\n      type: String,\n      default: 'month'\n    },\n    minDate: { type: [Date, String], default: null },\n    maxDate: { type: [Date, String], default: null },\n    year: {\n      type: [String, Number],\n      default: new Date().getFullYear()\n    },\n    month: {\n      type: [String, Number],\n      default: new Date().getMonth()\n    },\n    rangeState: {\n      type: Object,\n      default() {\n        return {\n          endDate: null,\n          selecting: false\n        };\n      }\n    }\n  },\n\n  data() {\n    return {\n      tableRows: [[], [], []],\n      lastRow: null,\n      lastColumn: null\n    };\n  },\n\n  computed: {\n    rows() {\n      // TODO: refactory rows / getCellClasses\n      const rows = this.tableRows;\n\n      return rows.map((row, i) => {\n        const newRow = [];\n        for (let j = 0; j < 4; j += 1) {\n          const cell = {\n            row: i,\n            column: j,\n            type: 'normal',\n            inRange: false,\n            start: false,\n            end: false\n          };\n          cell.type = 'normal';\n\n          const index = i * 4 + j;\n\n          cell.text = index;\n          cell.month = startOfMonth(new Date(this.year, index));\n          cell.disabled = checkDisabled(\n            { date: cell.month },\n            this.disabledValues\n          );\n\n          let maxDate = this.maxDate;\n          let minDate = this.minDate;\n\n          if (this.rangeState.selecting) {\n            maxDate = this.rangeState.endDate;\n          }\n\n          minDate = startOfMonth(minDate);\n          maxDate = maxDate ? startOfMonth(maxDate) : minDate;\n\n          [minDate, maxDate] = [\n            Math.min(minDate, maxDate),\n            Math.max(minDate, maxDate)\n          ];\n\n          cell.inRange =\n            minDate &&\n            cell.month.getTime() >= minDate &&\n            cell.month.getTime() <= maxDate;\n\n          if (isSameMonth(cell.month, new Date())) {\n            cell.type = 'today';\n          }\n\n          newRow.push(cell);\n        }\n\n        return newRow;\n      });\n    }\n  },\n\n  methods: {\n    getMonthName(monthIndex) {\n      return formatLocalDate(\n        new Date(this.year, monthIndex, 1),\n        'MMM',\n        this.$Q.locale\n      );\n    },\n\n    getCellClasses(cell) {\n      const classes = ['cell', 'cell_month'];\n      if (this.value && isSameMonth(this.value, cell.month))\n        classes.push('cell_current');\n      if (cell.type === 'today') classes.push('cell_today');\n\n      if (cell.inRange) {\n        classes.push('cell_in-range');\n      }\n      return classes;\n    },\n\n    handleMouseMove(event) {\n      if (!this.rangeState.selecting) return;\n\n      let target = event.target;\n      if (target.tagName === 'BUTTON') {\n        target = target.parentNode;\n      }\n\n      if (target.tagName !== 'TD') return;\n\n      const row = target.parentNode.rowIndex;\n      const column = target.cellIndex;\n      // can not select disabled date\n      if (this.rows[row][column].disabled) return;\n\n      // only update rangeState when mouse moves to a new cell\n      // this avoids frequent Date object creation and improves performance\n      if (row !== this.lastRow || column !== this.lastColumn) {\n        this.lastRow = row;\n        this.lastColumn = column;\n        this.$emit('changerange', {\n          minDate: this.minDate,\n          maxDate: this.maxDate,\n          rangeState: {\n            selecting: true,\n            endDate: new Date(this.year, row * 4 + column, 1)\n          }\n        });\n      }\n    },\n\n    handleMonthTableClick(cell) {\n      if (cell.disabled) return;\n      const month = cell.month.getMonth();\n      const newDate = cell.month;\n      if (this.selectionMode === 'range') {\n        if (!this.rangeState.selecting) {\n          this.$emit('pick', {\n            minDate: newDate,\n            maxDate: null,\n            rangeState: { ...this.rangeState, selecting: true }\n          });\n        } else if (newDate >= this.minDate) {\n          this.$emit('pick', {\n            minDate: this.minDate,\n            maxDate: newDate,\n            rangeState: { ...this.rangeState, selecting: false }\n          });\n        } else {\n          this.$emit('pick', {\n            minDate: newDate,\n            maxDate: this.minDate,\n            rangeState: { ...this.rangeState, selecting: false }\n          });\n        }\n      } else {\n        this.$emit('pick', month, this.year);\n      }\n    }\n  }\n};\n</script>\n"
  },
  {
    "path": "src/qComponents/QDatePicker/src/basic/year-table.vue",
    "content": "<template>\n  <table\n    cellspacing=\"4\"\n    cellpadding=\"5\"\n    class=\"q-year-table\"\n  >\n    <tr\n      v-for=\"(row, key) in rows\"\n      :key=\"key\"\n    >\n      <td\n        v-for=\"(cell, index) in row\"\n        :key=\"index\"\n        class=\"q-year-table__cell-wrapper\"\n        @mousemove=\"event => handleMouseMove(event, cell)\"\n        @click=\"event => handleYearTableClick(event, cell)\"\n      >\n        <button\n          :class=\"getCellClasses(cell)\"\n          :disabled=\"cell.disabled\"\n          type=\"button\"\n          tabindex=\"-1\"\n        >\n          {{ cell.year.getFullYear() }}\n        </button>\n      </td>\n    </tr>\n  </table>\n</template>\n\n<script>\nimport {\n  isSameYear,\n  addYears,\n  isDate,\n  startOfMonth,\n  startOfDecade,\n  isBefore,\n  isAfter\n} from 'date-fns';\n\nconst checkDisabled = (year, disabledValues) => {\n  if (!disabledValues) return false;\n  const disabled = [];\n  if (Array.isArray(disabledValues.ranges)) {\n    disabledValues.ranges.forEach(range => {\n      disabled.push(\n        (isSameYear(year, range.start) || isBefore(range.start, year)) &&\n          (isAfter(range.end, year) || isSameYear(range.end, year))\n      );\n    });\n  }\n\n  if (disabledValues.to) {\n    disabled.push(isBefore(year, disabledValues.to));\n  }\n\n  if (disabledValues.from) {\n    disabled.push(isAfter(year, disabledValues.from));\n  }\n\n  return disabled.some(Boolean);\n};\n\nexport default {\n  props: {\n    disabledValues: {\n      type: Object,\n      default: null\n    },\n    value: { type: [Date, String], default: null },\n    year: { type: [String, Number], default: '' },\n    selectionMode: {\n      type: String,\n      default: 'year'\n    },\n    minDate: { type: [Date, String], default: null },\n    maxDate: { type: [Date, String], default: null },\n    rangeState: {\n      type: Object,\n      default() {\n        return {\n          endDate: null,\n          selecting: false\n        };\n      }\n    }\n  },\n\n  data() {\n    return {\n      tableRows: [[], [], []],\n      lastHoveredCell: null\n    };\n  },\n\n  computed: {\n    startYear() {\n      if (this.year) {\n        return startOfDecade(new Date(this.year, 0, 1));\n      }\n\n      return startOfDecade(new Date());\n    },\n    rows() {\n      let startYear = this.startYear;\n      return this.tableRows.map((row, i) => {\n        const newRow = [];\n        const cellCount = i < 2 ? 4 : 2;\n        for (let j = 0; j < cellCount; j += 1) {\n          let maxDate = this.maxDate;\n          let minDate = this.minDate;\n          if (this.rangeState.selecting) {\n            maxDate = this.rangeState.endDate;\n          }\n\n          minDate = startOfMonth(minDate);\n          maxDate = maxDate ? startOfMonth(maxDate) : minDate;\n          [minDate, maxDate] = [\n            Math.min(minDate, maxDate),\n            Math.max(minDate, maxDate)\n          ];\n          newRow.push({\n            year: startYear,\n            disabled: checkDisabled(startYear, this.disabledValues),\n            inRange:\n              minDate &&\n              startYear.getTime() >= minDate &&\n              startYear.getTime() <= maxDate\n          });\n\n          startYear = addYears(startYear, 1);\n        }\n\n        return newRow;\n      });\n    }\n  },\n\n  methods: {\n    handleMouseMove(event, { year }) {\n      // update data only different cell's hover\n      if (event.target === this.lastHoveredCell) return;\n      this.lastHoveredCell = event.target;\n      if (!this.rangeState.selecting) return;\n      this.$emit('changerange', {\n        minDate: this.minDate,\n        maxDate: this.maxDate,\n        rangeState: {\n          selecting: true,\n          endDate: year\n        }\n      });\n    },\n\n    getCellClasses(cell) {\n      const style = ['cell', 'cell_year'];\n      if (this.selectionMode === 'year') {\n        if (\n          isDate(this.value) &&\n          this.value.getFullYear() === cell.year.getFullYear()\n        )\n          style.push('cell_current');\n        if (new Date().getFullYear() === cell.year.getFullYear())\n          style.push('cell_today');\n      } else {\n        if (cell.inRange) style.push('cell_in-range');\n\n        if (isSameYear(cell.year, new Date())) {\n          style.push('cell_today');\n        }\n      }\n\n      return style;\n    },\n\n    handleYearTableClick(event, { year }) {\n      if (this.selectionMode === 'range') {\n        if (!this.rangeState.selecting) {\n          this.$emit('pick', {\n            minDate: year,\n            maxDate: null,\n            rangeState: { selecting: true, end: null }\n          });\n        } else if (year.getTime() >= this.minDate.getTime()) {\n          this.$emit('pick', {\n            minDate: this.minDate,\n            maxDate: year,\n            rangeState: { selecting: false, end: null }\n          });\n        } else {\n          this.$emit('pick', {\n            minDate: year,\n            maxDate: this.minDate,\n            rangeState: { selecting: false, end: null }\n          });\n        }\n      } else {\n        this.$emit('pick', year);\n      }\n    }\n  }\n};\n</script>\n"
  },
  {
    "path": "src/qComponents/QDatePicker/src/helpers.js",
    "content": "import { format, isDate, parseISO } from 'date-fns';\nimport { ru, enGB as en } from 'date-fns/locale';\n\nconst locales = { ru, en };\n\nconst formatLocalDate = (value, dateFnsFormat, dateFnsLocale = 'ru') => {\n  let parsedValue = value;\n  if (!isDate(parsedValue)) {\n    parsedValue = parseISO(parsedValue);\n  }\n\n  if (isDate(parsedValue)) {\n    return format(parsedValue, dateFnsFormat ?? 'dd MMM yyyy', {\n      locale: locales[dateFnsLocale]\n    });\n  }\n\n  return parsedValue;\n};\n\nconst setTimeToDate = (date, type, value) => {\n  let newDate = date;\n  if (isDate(date)) {\n    newDate = new Date(date);\n    switch (type) {\n      case 'hours':\n        newDate.setHours(Number(value));\n        break;\n      case 'minutes':\n        newDate.setMinutes(Number(value));\n        break;\n      case 'seconds':\n        newDate.setSeconds(Number(value));\n        break;\n      default:\n        break;\n    }\n  }\n\n  return newDate;\n};\n\nconst clearTime = function(date) {\n  return new Date(date.getFullYear(), date.getMonth(), date.getDate());\n};\n\nconst clearMilliseconds = function(date) {\n  return new Date(\n    date.getFullYear(),\n    date.getMonth(),\n    date.getDate(),\n    date.getHours(),\n    date.getMinutes(),\n    date.getSeconds(),\n    0\n  );\n};\n\nexport { clearTime, clearMilliseconds, formatLocalDate, setTimeToDate };\n"
  },
  {
    "path": "src/qComponents/QDatePicker/src/panel/date-range.vue",
    "content": "<template>\n  <div class=\"q-picker-panel\">\n    <div class=\"q-picker-panel__body-wrapper\">\n      <div class=\"q-picker-panel__body\">\n        <slot\n          name=\"sidebar\"\n          class=\"q-picker-panel__sidebar\"\n        >\n          <div\n            v-if=\"shortcuts.length\"\n            class=\"q-picker-panel__sidebar\"\n          >\n            <button\n              v-for=\"(shortcut, key) in shortcuts\"\n              :key=\"key\"\n              type=\"button\"\n              class=\"q-picker-panel__shortcut\"\n              @click=\"handleShortcutClick(shortcut)\"\n            >\n              {{ shortcut.text }}\n            </button>\n          </div>\n        </slot>\n        <div\n          ref=\"leftPanel\"\n          :class=\"leftPanelClasses\"\n        >\n          <div class=\"q-picker-panel__header\">\n            <button\n              type=\"button\"\n              class=\"q-picker-panel__icon-btn q-icon-double-triangle-left\"\n              @click=\"handleLeftPrevYearClick\"\n            />\n            <button\n              type=\"button\"\n              class=\"q-picker-panel__icon-btn q-icon-triangle-left\"\n              @click=\"handleLeftPrevMonthClick\"\n            />\n            <div class=\"q-picker-panel__header-sign\">{{ leftLabel }}</div>\n            <button\n              type=\"button\"\n              :disabled=\"!enableMonthArrow\"\n              :class=\"{\n                'q-picker-panel__icon-btn_disabled': !enableMonthArrow\n              }\"\n              class=\"q-picker-panel__icon-btn q-icon-triangle-right\"\n              @click=\"handleLeftNextMonthClick\"\n            />\n            <button\n              type=\"button\"\n              :disabled=\"!enableYearArrow\"\n              :class=\"{ 'q-picker-panel__icon-btn_disabled': !enableYearArrow }\"\n              class=\"q-picker-panel__icon-btn q-icon-double-triangle-right\"\n              @click=\"handleLeftNextYearClick\"\n            />\n          </div>\n          <date-table\n            selection-mode=\"range\"\n            :min-date=\"minDate\"\n            :max-date=\"maxDate\"\n            :month=\"leftMonth\"\n            :year=\"leftYear\"\n            :range-state=\"rangeState\"\n            :disabled-values=\"disabledValues\"\n            :first-day-of-week=\"firstDayOfWeek\"\n            @changerange=\"handleChangeRange\"\n            @pick=\"handleRangePick\"\n          />\n        </div>\n        <div\n          ref=\"rightPanel\"\n          :class=\"rightPanelClasses\"\n        >\n          <div class=\"q-picker-panel__header\">\n            <button\n              type=\"button\"\n              :disabled=\"!enableYearArrow\"\n              :class=\"{ 'q-picker-panel__icon-btn_disabled': !enableYearArrow }\"\n              class=\"q-picker-panel__icon-btn q-icon-double-triangle-left\"\n              @click=\"handleRightPrevYearClick\"\n            />\n            <button\n              type=\"button\"\n              :disabled=\"!enableMonthArrow\"\n              :class=\"{\n                'q-picker-panel__icon-btn_disabled': !enableMonthArrow\n              }\"\n              class=\"q-picker-panel__icon-btn q-icon-triangle-left\"\n              @click=\"handleRightPrevMonthClick\"\n            />\n            <div class=\"q-picker-panel__header-sign\">\n              {{ rightLabel }}\n            </div>\n            <button\n              type=\"button\"\n              class=\"q-picker-panel__icon-btn q-icon-triangle-right\"\n              @click=\"handleRightNextMonthClick\"\n            />\n            <button\n              type=\"button\"\n              class=\"q-picker-panel__icon-btn q-icon-double-triangle-right\"\n              @click=\"handleRightNextYearClick\"\n            />\n          </div>\n          <date-table\n            selection-mode=\"range\"\n            :min-date=\"minDate\"\n            :max-date=\"maxDate\"\n            :month=\"rightMonth\"\n            :year=\"rightYear\"\n            :range-state=\"rangeState\"\n            :disabled-values=\"disabledValues\"\n            :first-day-of-week=\"firstDayOfWeek\"\n            @changerange=\"handleChangeRange\"\n            @pick=\"handleRangePick\"\n          />\n        </div>\n        <div\n          v-show=\"showTime\"\n          class=\"q-picker-panel__timepickers\"\n        >\n          <div class=\"q-picker-panel__timepicker\">\n            <time-panel\n              ref=\"leftTimePanel\"\n              class=\"time-panel time-panel_no-left-borders time-panel_no-right-borders\"\n              :value=\"parsedLeftTime\"\n              :panel-in-focus=\"panelInFocus === 'timeLeft'\"\n              :disabled=\"isLeftTimeDisabled\"\n              :disabled-values=\"disabledValues.time\"\n              :prefix-to-time=\"$t('QDatePicker.timeFrom')\"\n              @change=\"handleLeftTimeChange\"\n            />\n          </div>\n          <div class=\"q-picker-panel__timepicker\">\n            <time-panel\n              ref=\"rightTimePanel\"\n              :panel-in-focus=\"panelInFocus === 'timeRight'\"\n              :disabled=\"isLeftTimeDisabled\"\n              class=\"time-panel time-panel_no-left-borders\"\n              :value=\"parsedRightTime\"\n              :disabled-values=\"disabledRightTimeValues\"\n              :prefix-to-time=\"$t('QDatePicker.timeTo')\"\n              @change=\"handleRightTimeChange\"\n            />\n          </div>\n        </div>\n      </div>\n    </div>\n  </div>\n</template>\n\n<script>\nimport { addMonths, isDate, isSameDay, isSameMonth, subMonths } from 'date-fns';\nimport DateTable from '../basic/date-table';\nimport rangeMixin from './range-mixin';\nimport focusMixin from './focus-mixin';\nimport focusTimeMixin from './focus-time-mixin';\nimport { setTimeToDate } from '../helpers';\nimport { addZero } from '../../../helpers/dateHelpers';\nimport TimePanel from '../../../QTimePicker/src/components/panel';\n\nconst MONTHS_COUNT = 12;\n\nexport default {\n  name: 'QDatePickerPanelDateRange',\n  components: { DateTable, TimePanel },\n  mixins: [rangeMixin, focusMixin, focusTimeMixin],\n  props: {\n    firstDayOfWeek: {\n      type: Number,\n      default: 1\n    },\n    visible: {\n      type: Boolean,\n      default: false\n    },\n\n    value: {\n      type: Array,\n      default: () => []\n    },\n\n    disabledValues: {\n      type: Object,\n      default: null\n    },\n\n    shortcuts: {\n      type: Array,\n      default: () => []\n    },\n\n    showTime: {\n      type: Boolean,\n      default: false\n    }\n  },\n\n  data() {\n    return {\n      minDate: '',\n      maxDate: '',\n      leftDate: new Date(),\n      rightDate: addMonths(new Date(), 1),\n      rangeState: {\n        endDate: null,\n        selecting: false\n      },\n      isRanged: true\n    };\n  },\n\n  computed: {\n    transformedValue() {\n      if (Array.isArray(this.value)) {\n        return this.value;\n      }\n\n      return [];\n    },\n    disabledRightTimeValues() {\n      const values = { ...this.disabledValues.time };\n      if (\n        isSameDay(this.transformedValue[0], this.transformedValue[1]) &&\n        this.parsedLeftTime\n      ) {\n        values.to = Object.values(this.parsedLeftTime).join(':');\n      }\n      return values;\n    },\n\n    isLeftTimeDisabled() {\n      return !this.transformedValue[0];\n    },\n    parsedLeftTime() {\n      const value = this.transformedValue[0];\n      if (isDate(value)) {\n        return {\n          hours: addZero(value.getHours()),\n          minutes: addZero(value.getMinutes()),\n          seconds: addZero(value.getSeconds())\n        };\n      }\n\n      return value;\n    },\n\n    parsedRightTime() {\n      const value = this.transformedValue[1] ?? null;\n      if (isDate(value)) {\n        return {\n          hours: addZero(value.getHours()),\n          minutes: addZero(value.getMinutes()),\n          seconds: addZero(value.getSeconds())\n        };\n      }\n\n      return value ?? null;\n    },\n\n    rightPanelClasses() {\n      return {\n        'q-picker-panel__content': true,\n        'q-picker-panel__content_no-left-borders': true,\n        'q-picker-panel__content_no-right-borders': this.showTime,\n        'q-picker-panel__content_focused': this.panelInFocus === 'right'\n      };\n    },\n    leftPanelClasses() {\n      return {\n        'q-picker-panel__content': true,\n        'q-picker-panel__content_no-left-borders':\n          this.$slots.sidebar || this.shortcuts.length,\n        'q-picker-panel__content_no-right-borders': true,\n        'q-picker-panel__content_focused': this.panelInFocus === 'left'\n      };\n    },\n\n    rightYear() {\n      return this.rightDate.getFullYear();\n    },\n\n    enableMonthArrow() {\n      const nextMonth = (this.leftMonth + 1) % 12;\n      const yearOffset = this.leftMonth + 1 >= 12 ? 1 : 0;\n      return (\n        new Date(this.leftYear + yearOffset, nextMonth) <\n        new Date(this.rightYear, this.rightMonth)\n      );\n    },\n\n    enableYearArrow() {\n      return (\n        this.rightYear * MONTHS_COUNT +\n          this.rightMonth -\n          (this.leftYear * MONTHS_COUNT + this.leftMonth + 1) >=\n        MONTHS_COUNT\n      );\n    }\n  },\n\n  watch: {\n    visible() {\n      if (this.transformedValue.length) {\n        if (isDate(this.transformedValue[0])) {\n          this.leftDate = this.transformedValue[0];\n        }\n\n        if (isDate(this.transformedValue[1])) {\n          this.rightDate = this.transformedValue[1];\n        }\n      }\n\n      if (isSameMonth(this.leftDate, this.rightDate)) {\n        this.rightDate = addMonths(this.leftDate, 1);\n      }\n    }\n  },\n\n  methods: {\n    handleLeftTimeChange({ value, type }) {\n      let rightTime = this.transformedValue[1] || new Date();\n      const newDate = setTimeToDate(\n        this.transformedValue[0] || new Date(),\n        type,\n        value\n      );\n\n      if (newDate.getTime() > rightTime.getTime()) {\n        rightTime = newDate;\n      }\n\n      this.$emit('pick', [newDate, rightTime], { hidePicker: false });\n    },\n\n    handleRightTimeChange({ value, type }) {\n      const leftTime = this.transformedValue[0] || new Date();\n      const newDate = setTimeToDate(\n        this.transformedValue[1] || new Date(),\n        type,\n        value\n      );\n\n      this.$emit('pick', [leftTime, newDate], { hidePicker: false });\n    },\n\n    handleClear() {\n      this.minDate = null;\n      this.maxDate = null;\n      this.leftDate = new Date();\n      this.rightDate = addMonths(new Date(), 1);\n      this.$emit('pick', null);\n    },\n\n    handleLeftPrevMonthClick() {\n      this.leftDate = subMonths(this.leftDate, 1);\n    },\n\n    handleRightNextMonthClick() {\n      this.rightDate = addMonths(this.rightDate, 1);\n    },\n\n    handleLeftNextMonthClick() {\n      this.leftDate = addMonths(this.leftDate, 1);\n    },\n\n    handleRightPrevMonthClick() {\n      this.rightDate = subMonths(this.rightDate, 1);\n    }\n  }\n};\n</script>\n"
  },
  {
    "path": "src/qComponents/QDatePicker/src/panel/date.vue",
    "content": "<template>\n  <div class=\"q-picker-panel\">\n    <div class=\"q-picker-panel__body\">\n      <slot\n        name=\"sidebar\"\n        class=\"q-picker-panel__sidebar\"\n      >\n        <div\n          v-if=\"shortcuts.length\"\n          class=\"q-picker-panel__sidebar\"\n        >\n          <button\n            v-for=\"(shortcut, key) in shortcuts\"\n            :key=\"key\"\n            type=\"button\"\n            class=\"q-picker-panel__shortcut\"\n            @click=\"handleShortcutClick(shortcut)\"\n          >\n            {{ shortcut.text }}\n          </button>\n        </div>\n      </slot>\n      <div\n        ref=\"datePanel\"\n        :class=\"panelContentClasses\"\n      >\n        <div class=\"q-picker-panel__header\">\n          <button\n            type=\"button\"\n            :title=\"$t('QDatePicker.prevYear')\"\n            class=\"q-picker-panel__icon-btn q-icon-double-triangle-left\"\n            @click=\"handlePrevYearClick\"\n          />\n          <button\n            v-show=\"currentView === 'date'\"\n            type=\"button\"\n            :title=\"$t('QDatePicker.prevMonth')\"\n            class=\"q-picker-panel__icon-btn q-icon-triangle-left\"\n            @click=\"handlePrevMonthClick\"\n          />\n          <div class=\"q-picker-panel__header-sign\">\n            <span\n              v-show=\"currentView === 'date'\"\n              role=\"button\"\n              class=\"q-picker-panel__header-label\"\n              :class=\"{ active: currentView === 'month' }\"\n              @click=\"showMonthPicker\"\n            >\n              {{ currentMonth }}\n            </span>\n            <span\n              role=\"button\"\n              class=\"q-picker-panel__header-label\"\n              @click=\"showYearPicker\"\n            >\n              {{ yearLabel }}\n            </span>\n          </div>\n          <button\n            v-show=\"currentView === 'date'\"\n            type=\"button\"\n            :title=\"$t('QDatePicker.nextMonth')\"\n            class=\"q-picker-panel__icon-btn q-icon-triangle-right\"\n            @click=\"handleNextMonthClick\"\n          />\n          <button\n            type=\"button\"\n            :title=\"$t('QDatePicker.nextYear')\"\n            class=\"q-picker-panel__icon-btn q-icon-double-triangle-right\"\n            @click=\"handleNextYearClick\"\n          />\n        </div>\n\n        <date-table\n          v-if=\"currentView === 'date'\"\n          :selection-mode=\"selectionMode\"\n          :first-day-of-week=\"firstDayOfWeek\"\n          :value=\"value\"\n          :year=\"year\"\n          :month=\"month\"\n          :disabled-values=\"disabledValues\"\n          @pick=\"handleDatePick\"\n        />\n        <year-table\n          v-if=\"currentView === 'year'\"\n          :value=\"value\"\n          :year=\"year\"\n          :disabled-values=\"disabledValues\"\n          @pick=\"handleYearPick\"\n        />\n        <month-table\n          v-if=\"currentView === 'month'\"\n          :value=\"value\"\n          :month=\"month\"\n          :year=\"year\"\n          :disabled-values=\"disabledValues\"\n          @pick=\"handleMonthPick\"\n        />\n      </div>\n      <div\n        v-if=\"showTime && currentView === 'date'\"\n        class=\"q-picker-panel__timepickers\"\n      >\n        <time-panel\n          ref=\"timePanel\"\n          class=\"time-panel_no-left-borders\"\n          :value=\"parsedTime\"\n          :disabled-values=\"disabledValues\"\n          :panel-in-focus=\"panelInFocus === 'time'\"\n          @change=\"handleTimeChange\"\n        />\n      </div>\n    </div>\n  </div>\n</template>\n\n<script>\nimport { isDate, subMonths, addMonths, subYears, addYears } from 'date-fns';\nimport { clearTime, clearMilliseconds, setTimeToDate } from '../helpers';\nimport { addZero } from '../../../helpers/dateHelpers';\nimport TimePanel from '../../../QTimePicker/src/components/panel';\nimport YearTable from '../basic/year-table';\nimport MonthTable from '../basic/month-table';\nimport DateTable from '../basic/date-table';\nimport focusMixin from './focus-mixin';\nimport focusTimeMixin from './focus-time-mixin';\n\nexport default {\n  name: 'QDatePickerPanelDate',\n  components: {\n    TimePanel,\n    YearTable,\n    MonthTable,\n    DateTable\n  },\n  mixins: [focusMixin, focusTimeMixin],\n  props: {\n    firstDayOfWeek: {\n      type: Number,\n      default: 1\n    },\n\n    type: {\n      type: String,\n      default: 'date'\n    },\n\n    shortcuts: {\n      type: Array,\n      default: () => []\n    },\n\n    disabledValues: {\n      type: Object,\n      default: null\n    },\n\n    showTime: {\n      type: Boolean,\n      default: false\n    },\n\n    value: {\n      type: [Object, Array, Date, String],\n      default: null\n    }\n  },\n\n  data() {\n    return {\n      year: new Date().getFullYear(),\n      month: new Date().getMonth(),\n      currentView: 'date',\n      isRanged: false\n    };\n  },\n\n  computed: {\n    panelContentClasses() {\n      return {\n        'q-picker-panel__content': true,\n        'q-picker-panel__content_no-right-borders': this.showTime,\n        'q-picker-panel__content_focused': this.panelInFocus === 'date'\n      };\n    },\n    parsedTime() {\n      if (isDate(this.value)) {\n        return {\n          hours: addZero(this.value.getHours()),\n          minutes: addZero(this.value.getMinutes()),\n          seconds: addZero(this.value.getSeconds())\n        };\n      }\n\n      return null;\n    },\n\n    selectionMode() {\n      return this.type ?? 'day';\n    },\n\n    currentMonth() {\n      const formatter = new Intl.DateTimeFormat(this.$Q.locale, {\n        month: 'short'\n      });\n      return formatter.format(new Date(this.year, this.month));\n    },\n\n    yearLabel() {\n      if (this.currentView === 'year') {\n        const startYear = Math.floor(this.year / 10) * 10;\n        return `${startYear} - ${startYear + 9}`;\n      }\n      return this.year;\n    }\n  },\n\n  watch: {\n    type: {\n      handler(value) {\n        let currentView;\n        switch (value) {\n          case 'week':\n          case 'date':\n          case 'datetime':\n            currentView = 'date';\n            break;\n          default:\n            currentView = value;\n        }\n        this.currentView = currentView;\n      },\n      immediate: true\n    },\n\n    value(date) {\n      if (isDate(date)) {\n        this.year = date.getFullYear();\n        this.month = date.getMonth();\n      } else {\n        this.year = new Date().getFullYear();\n        this.month = new Date().getMonth();\n      }\n    }\n  },\n\n  created() {\n    if (isDate(this.value)) {\n      this.year = this.value.getFullYear();\n      this.month = this.value.getMonth();\n    }\n  },\n\n  methods: {\n    handleTimeChange({ type, value }) {\n      const newDate = setTimeToDate(this.value || new Date(), type, value);\n\n      this.emit(newDate, { hidePicker: false });\n    },\n\n    emit(value, ...args) {\n      if (Array.isArray(value)) {\n        const dates = value.map(date =>\n          this.showTime ? clearMilliseconds(date) : clearTime(date)\n        );\n        this.$emit('pick', dates, ...args);\n      } else {\n        this.$emit('pick', value, ...args);\n      }\n    },\n\n    showMonthPicker() {\n      this.currentView = 'month';\n    },\n\n    showYearPicker() {\n      this.currentView = 'year';\n    },\n\n    showDatePicker() {\n      this.currentView = 'date';\n    },\n\n    handlePrevMonthClick() {\n      const year = this.year;\n      if (this.month === 0) {\n        this.year -= 1;\n      }\n      this.month = subMonths(new Date(year, this.month), 1).getMonth();\n    },\n\n    handleNextMonthClick() {\n      const year = this.year;\n      if (this.month === 11) {\n        this.year += 1;\n      }\n      this.month = addMonths(new Date(year, this.month), 1).getMonth();\n    },\n\n    handlePrevYearClick() {\n      if (this.currentView === 'year') {\n        this.year = subYears(new Date(this.year, this.month), 10).getFullYear();\n      } else {\n        this.year = subYears(new Date(this.year, this.month), 1).getFullYear();\n      }\n    },\n\n    handleNextYearClick() {\n      if (this.currentView === 'year') {\n        this.year = addYears(new Date(this.year, 1), 10).getFullYear();\n      } else {\n        this.year = addYears(new Date(this.year, 1), 1).getFullYear();\n      }\n    },\n\n    handleShortcutClick(shortcut) {\n      if (shortcut.onClick) {\n        shortcut.onClick(this);\n      }\n    },\n\n    handleMonthPick(month, year) {\n      if (this.selectionMode === 'month') {\n        this.emit(new Date(year, month, 1));\n      } else if (isDate(this.value) && !Array.isArray(this.value)) {\n        this.emit(new Date(year, month, this.value.getDate()));\n        this.showDatePicker();\n      } else {\n        this.month = month;\n        this.year = year;\n        this.showDatePicker();\n      }\n    },\n\n    handleDatePick(value) {\n      this.emit(value, { hidePicker: !this.showTime }); // set false to keep panel open\n    },\n\n    handleYearPick(year) {\n      if (this.selectionMode === 'year') {\n        this.emit(year);\n      } else if (isDate(this.value) && !Array.isArray(this.value)) {\n        this.emit(\n          new Date(\n            year.getFullYear(),\n            this.value.getMonth(),\n            this.value.getDate()\n          )\n        );\n        this.showDatePicker();\n      } else {\n        this.year = year.getFullYear();\n        this.showMonthPicker();\n      }\n    }\n  }\n};\n</script>\n"
  },
  {
    "path": "src/qComponents/QDatePicker/src/panel/focus-mixin.js",
    "content": "const DATE_CELLS_COUNT = 42;\nconst DATE_CELLS_IN_ROW_COUNT = 7;\n\nconst PERIOD_CELLS_IN_ROW_COUNT = 4;\n\nconst LEFT_MONTH_PANEL_START_INDEX = 0;\nconst RIGHT_MONTH_PANEL_START_INDEX = 12;\nconst RIGHT_YEAR_PANEL_START_INDEX = 10;\n\nexport default {\n  data() {\n    return {\n      panelInFocus: null,\n      lastFocusedCellIndex: null\n    };\n  },\n  mounted() {\n    this.dateCells = this.$el.querySelectorAll('.q-date-table .cell');\n    this.monthCells = this.$el.querySelectorAll('.q-month-table .cell');\n    this.yearCells = this.$el.querySelectorAll('.q-year-table .cell');\n  },\n\n  methods: {\n    setPanelFocus() {\n      if (this.isRanged) {\n        if (this.$refs.leftPanel?.contains(document.activeElement)) {\n          this.panelInFocus = 'left';\n        } else if (this.$refs.rightPanel?.contains(document.activeElement)) {\n          this.panelInFocus = 'right';\n        } else if (\n          this.$refs.leftTimePanel?.$el.contains(document.activeElement)\n        ) {\n          this.panelInFocus = 'timeLeft';\n        } else if (\n          this.$refs.rightTimePanel?.$el.contains(document.activeElement)\n        ) {\n          this.panelInFocus = 'timeRight';\n        }\n      } else if (this.$refs.datePanel?.contains(document.activeElement)) {\n        this.panelInFocus = 'date';\n      } else if (this.$refs.timePanel?.$el.contains(document.activeElement)) {\n        this.panelInFocus = 'time';\n      } else {\n        this.panelInFocus = null;\n      }\n    },\n\n    navigateDropdown(e) {\n      if (e.key !== 'Tab') {\n        if (e.target.classList.contains('cell_time')) {\n          this.moveWithinTime(e);\n        } else if (e.target.classList.contains('cell_date')) {\n          this.moveWithinDates(e);\n        } else if (e.target.classList.contains('cell_month')) {\n          this.moveWithinPeriod({ period: 'month', e });\n        } else if (e.target.classList.contains('cell_year')) {\n          this.moveWithinPeriod({ period: 'year', e });\n        } else if (['monthrange', 'month'].includes(this.currentView)) {\n          this.monthCells[0]?.focus();\n        } else if (['yearrange', 'year'].includes(this.currentView)) {\n          this.yearCells[0]?.focus();\n        } else {\n          this.dateCells[0]?.focus();\n        }\n      }\n\n      this.setPanelFocus();\n    },\n\n    moveWithinPeriod({ period, e }) {\n      let currentNodeIndex;\n      let nextNodeIndex;\n      const periodCells = period === 'month' ? this.monthCells : this.yearCells;\n      const rightPanelStartIndex =\n        period === 'month'\n          ? RIGHT_MONTH_PANEL_START_INDEX\n          : RIGHT_YEAR_PANEL_START_INDEX;\n      Array.from(periodCells).some((element, index) => {\n        if (document.activeElement === element) {\n          currentNodeIndex = index;\n          return true;\n        }\n\n        return false;\n      });\n\n      switch (e.key) {\n        case 'ArrowUp': {\n          nextNodeIndex = currentNodeIndex - PERIOD_CELLS_IN_ROW_COUNT;\n          break;\n        }\n\n        case 'ArrowRight':\n          if (\n            this.isRanged &&\n            this.panelInFocus === 'left' &&\n            (currentNodeIndex + 1) % PERIOD_CELLS_IN_ROW_COUNT === 0\n          ) {\n            nextNodeIndex = rightPanelStartIndex;\n          } else {\n            nextNodeIndex = currentNodeIndex + 1;\n          }\n\n          break;\n\n        case 'ArrowLeft':\n          if (\n            this.isRanged &&\n            this.panelInFocus === 'right' &&\n            currentNodeIndex % PERIOD_CELLS_IN_ROW_COUNT === 0\n          ) {\n            nextNodeIndex = LEFT_MONTH_PANEL_START_INDEX + 3;\n          } else {\n            nextNodeIndex = currentNodeIndex - 1;\n          }\n\n          break;\n\n        case 'ArrowDown': {\n          nextNodeIndex = currentNodeIndex + PERIOD_CELLS_IN_ROW_COUNT;\n          break;\n        }\n        default:\n          break;\n      }\n\n      const node = periodCells[nextNodeIndex];\n      const newIndex = nextNodeIndex % PERIOD_CELLS_IN_ROW_COUNT;\n      if (node) {\n        node.focus();\n        this.lastFocusedCellIndex = nextNodeIndex;\n      } else if (nextNodeIndex > this.lastFocusedCellIndex) {\n        if (this.isRanged) {\n          this.handleRightNextYearClick();\n          this.handleLeftNextYearClick();\n        } else {\n          this.handleNextYearClick();\n        }\n        periodCells[newIndex]?.focus();\n      } else if (nextNodeIndex < this.lastFocusedCellIndex) {\n        if (this.isRanged) {\n          this.handleLeftPrevYearClick();\n          this.handleRightPrevYearClick();\n        } else {\n          this.handlePrevYearClick();\n        }\n      }\n    },\n\n    moveWithinDates(e) {\n      this.timePanelInFocus = 'left';\n      let currentNodeIndex;\n      let nextNodeIndex;\n      Array.from(this.dateCells).some((element, index) => {\n        const isItActiveElement = document.activeElement === element;\n        if (isItActiveElement) currentNodeIndex = index;\n        return isItActiveElement;\n      });\n\n      switch (e.key) {\n        case 'ArrowUp': {\n          nextNodeIndex = currentNodeIndex - DATE_CELLS_IN_ROW_COUNT;\n          break;\n        }\n\n        case 'ArrowRight':\n          if (this.isRanged) {\n            if (\n              this.panelInFocus === 'left' &&\n              (currentNodeIndex + 1) % DATE_CELLS_IN_ROW_COUNT === 0\n            ) {\n              nextNodeIndex = DATE_CELLS_COUNT;\n              this.setPanelFocus();\n              break;\n            } else if (\n              this.showTime &&\n              this.panelInFocus === 'right' &&\n              (currentNodeIndex + 1) % DATE_CELLS_IN_ROW_COUNT === 0\n            ) {\n              this.moveWithinTime();\n              return;\n            }\n\n            nextNodeIndex = currentNodeIndex + 1;\n          } else if (\n            this.showTime &&\n            (currentNodeIndex + 1) % DATE_CELLS_IN_ROW_COUNT === 0\n          ) {\n            this.moveWithinTime();\n          } else {\n            nextNodeIndex = currentNodeIndex + 1;\n          }\n\n          break;\n\n        case 'ArrowLeft':\n          if (\n            this.panelInFocus === 'right' &&\n            (currentNodeIndex - DATE_CELLS_IN_ROW_COUNT) %\n              DATE_CELLS_IN_ROW_COUNT ===\n              0\n          ) {\n            nextNodeIndex = DATE_CELLS_IN_ROW_COUNT - 1;\n            this.setPanelFocus();\n          } else {\n            nextNodeIndex = currentNodeIndex - 1;\n          }\n\n          break;\n\n        case 'ArrowDown': {\n          nextNodeIndex = currentNodeIndex + DATE_CELLS_IN_ROW_COUNT;\n          break;\n        }\n        default:\n          break;\n      }\n\n      const node = this.dateCells[nextNodeIndex];\n      const newIndex = nextNodeIndex % DATE_CELLS_IN_ROW_COUNT;\n      if (node) {\n        node.focus();\n        this.lastFocusedCellIndex = nextNodeIndex;\n      } else if (nextNodeIndex > this.lastFocusedCellIndex) {\n        if (this.isRanged) {\n          this.handleRightNextMonthClick();\n          this.handleLeftNextMonthClick();\n        } else {\n          this.handleNextMonthClick();\n        }\n        this.dateCells[newIndex]?.focus();\n      } else if (nextNodeIndex < this.lastFocusedCellIndex) {\n        if (this.isRanged) {\n          this.handleLeftPrevMonthClick();\n          this.handleRightPrevMonthClick();\n        } else {\n          this.handlePrevMonthClick();\n        }\n        this.dateCells[DATE_CELLS_COUNT + newIndex]?.focus();\n      }\n    }\n  }\n};\n"
  },
  {
    "path": "src/qComponents/QDatePicker/src/panel/focus-time-mixin.js",
    "content": "const DATE_CELLS_IN_ROW_COUNT = 7;\n\nconst RIGHT_DATE_PANEL_START_INDEX = 42;\n\nconst LEFT_TIME_PANEL_HOURS_INDEX = 0;\nconst LEFT_TIME_PANEL_MINUTES_INDEX = 24;\nconst LEFT_TIME_PANEL_SECONDS_INDEX = 84;\n\nconst RIGHT_TIME_PANEL_HOURS_INDEX = 144;\nconst RIGHT_TIME_PANEL_MINUTES_INDEX = 168;\nconst RIGHT_TIME_PANEL_SECONDS_INDEX = 228;\n\nexport default {\n  mounted() {\n    this.timeCells = this.$el.querySelectorAll('.time-panel__pickers .cell');\n  },\n\n  methods: {\n    moveWithinTime(e) {\n      // switch from date\n      if (!e) {\n        if (this.timeCells[0]?.disabled) return;\n        this.timeCells[0].focus();\n        this.setPanelFocus();\n        // true keyup\n      } else {\n        let currentNodeIndex;\n        let nextNodeIndex;\n        this.timeCells.forEach((element, index) => {\n          if (document.activeElement === element) {\n            currentNodeIndex = index;\n          }\n        });\n\n        const classList = e.target.classList;\n\n        switch (e.key) {\n          case 'ArrowUp': {\n            nextNodeIndex = currentNodeIndex - 1;\n            break;\n          }\n\n          case 'ArrowRight':\n            if (this.isRanged) {\n              if (this.panelInFocus === 'timeLeft') {\n                switch (true) {\n                  case classList.contains('cell_hours'):\n                    nextNodeIndex = LEFT_TIME_PANEL_MINUTES_INDEX;\n                    break;\n                  case classList.contains('cell_minutes'):\n                    nextNodeIndex = LEFT_TIME_PANEL_SECONDS_INDEX;\n                    break;\n                  case classList.contains('cell_seconds'):\n                    nextNodeIndex = RIGHT_TIME_PANEL_HOURS_INDEX;\n                    break;\n                  default:\n                    break;\n                }\n              } else if (this.panelInFocus === 'timeRight') {\n                switch (true) {\n                  case classList.contains('cell_hours'):\n                    nextNodeIndex = RIGHT_TIME_PANEL_MINUTES_INDEX;\n                    break;\n                  case classList.contains('cell_minutes'):\n                    nextNodeIndex = RIGHT_TIME_PANEL_SECONDS_INDEX;\n                    break;\n                  default:\n                    break;\n                }\n              }\n              break;\n            }\n\n            if (classList.contains('cell_hours')) {\n              nextNodeIndex = LEFT_TIME_PANEL_MINUTES_INDEX;\n            } else if (classList.contains('cell_minutes')) {\n              nextNodeIndex = LEFT_TIME_PANEL_SECONDS_INDEX;\n            }\n            break;\n\n          case 'ArrowLeft':\n            if (this.isRanged) {\n              if (this.panelInFocus === 'timeRight') {\n                switch (true) {\n                  case classList.contains('cell_seconds'):\n                    nextNodeIndex = RIGHT_TIME_PANEL_MINUTES_INDEX;\n                    break;\n                  case classList.contains('cell_minutes'):\n                    nextNodeIndex = RIGHT_TIME_PANEL_HOURS_INDEX;\n                    break;\n                  case classList.contains('cell_hours'):\n                    nextNodeIndex = LEFT_TIME_PANEL_SECONDS_INDEX;\n                    break;\n                  default:\n                    break;\n                }\n              } else if (this.panelInFocus === 'timeLeft') {\n                switch (true) {\n                  case classList.contains('cell_seconds'):\n                    nextNodeIndex = LEFT_TIME_PANEL_MINUTES_INDEX;\n                    break;\n                  case classList.contains('cell_minutes'):\n                    nextNodeIndex = LEFT_TIME_PANEL_HOURS_INDEX;\n                    break;\n                  case classList.contains('cell_hours'):\n                    this.dateCells[RIGHT_DATE_PANEL_START_INDEX + 6]?.focus();\n                    break;\n                  default:\n                    break;\n                }\n\n                break;\n              }\n\n              if (\n                this.panelInFocus === 'timeRight' &&\n                classList.contains('cell_seconds')\n              ) {\n                nextNodeIndex = RIGHT_TIME_PANEL_MINUTES_INDEX;\n              } else if (\n                this.panelInFocus === 'timeRight' &&\n                classList.contains('cell_minutes')\n              ) {\n                nextNodeIndex = RIGHT_TIME_PANEL_HOURS_INDEX;\n              } else if (\n                this.panelInFocus === 'timeRight' &&\n                classList.contains('cell_hours')\n              ) {\n                nextNodeIndex = LEFT_TIME_PANEL_SECONDS_INDEX;\n              }\n            } else if (classList.contains('cell_seconds')) {\n              nextNodeIndex = LEFT_TIME_PANEL_MINUTES_INDEX;\n            } else if (classList.contains('cell_minutes')) {\n              nextNodeIndex = LEFT_TIME_PANEL_HOURS_INDEX;\n            } else {\n              // switch to dates\n              this.dateCells[DATE_CELLS_IN_ROW_COUNT - 1]?.focus();\n            }\n\n            break;\n\n          case 'ArrowDown': {\n            nextNodeIndex = currentNodeIndex + 1;\n            break;\n          }\n          default:\n            break;\n        }\n\n        this.timeCells[nextNodeIndex]?.focus();\n        this.setPanelFocus();\n      }\n    }\n  }\n};\n"
  },
  {
    "path": "src/qComponents/QDatePicker/src/panel/month-range.vue",
    "content": "<template>\n  <div class=\"q-picker-panel\">\n    <div class=\"q-picker-panel__body-wrapper\">\n      <div class=\"q-picker-panel__body\">\n        <slot\n          name=\"sidebar\"\n          class=\"q-picker-panel__sidebar\"\n        />\n        <div\n          v-if=\"$slots.sidebar && shortcuts.length\"\n          class=\"q-picker-panel__sidebar\"\n        >\n          <button\n            v-for=\"(shortcut, key) in shortcuts\"\n            :key=\"key\"\n            type=\"button\"\n            class=\"q-picker-panel__shortcut\"\n            @click=\"handleShortcutClick(shortcut)\"\n          >\n            {{ shortcut.text }}\n          </button>\n        </div>\n        <div\n          ref=\"leftPanel\"\n          :class=\"leftPanelClasses\"\n        >\n          <div class=\"q-picker-panel__header\">\n            <button\n              type=\"button\"\n              class=\"q-picker-panel__icon-btn q-icon-double-triangle-left\"\n              @click=\"handleLeftPrevYearClick\"\n            />\n            <div class=\"q-picker-panel__header-sign\">{{ leftYear }}</div>\n            <button\n              type=\"button\"\n              :disabled=\"!enableYearArrow\"\n              :class=\"{ 'q-picker-panel__icon-btn_disabled': !enableYearArrow }\"\n              class=\"q-picker-panel__icon-btn q-icon-double-triangle-right\"\n              @click=\"handleLeftNextYearClick\"\n            />\n          </div>\n          <month-table\n            selection-mode=\"range\"\n            :min-date=\"minDate\"\n            :max-date=\"maxDate\"\n            :month=\"leftMonth\"\n            :year=\"leftYear\"\n            :range-state=\"rangeState\"\n            :disabled-values=\"disabledValues\"\n            @changerange=\"handleChangeRange\"\n            @pick=\"handleRangePick\"\n          />\n        </div>\n        <div\n          ref=\"rightPanel\"\n          :class=\"rightPanelClasses\"\n        >\n          <div class=\"q-picker-panel__header\">\n            <button\n              type=\"button\"\n              :disabled=\"!enableYearArrow\"\n              :class=\"{ 'q-picker-panel__icon-btn_disabled': !enableYearArrow }\"\n              class=\"q-picker-panel__icon-btn q-icon-double-triangle-left\"\n              @click=\"handleRightPrevYearClick\"\n            />\n            <div class=\"q-picker-panel__header-sign\">{{ rightYear }}</div>\n            <button\n              type=\"button\"\n              class=\"q-picker-panel__icon-btn q-icon-double-triangle-right\"\n              @click=\"handleRightNextYearClick\"\n            />\n          </div>\n          <month-table\n            selection-mode=\"range\"\n            :month=\"rightMonth\"\n            :year=\"rightYear\"\n            :min-date=\"minDate\"\n            :max-date=\"maxDate\"\n            :range-state=\"rangeState\"\n            :disabled-values=\"disabledValues\"\n            @changerange=\"handleChangeRange\"\n            @pick=\"handleRangePick\"\n          />\n        </div>\n      </div>\n    </div>\n  </div>\n</template>\n\n<script>\nimport { isDate, addYears } from 'date-fns';\nimport MonthTable from '../basic/month-table';\nimport rangeMixin from './range-mixin';\nimport focusMixin from './focus-mixin';\n\nexport default {\n  components: { MonthTable },\n  mixins: [rangeMixin, focusMixin],\n  props: {\n    value: {\n      type: Array,\n      default: () => []\n    },\n    disabledValues: {\n      type: Object,\n      default: null\n    }\n  },\n  data() {\n    return {\n      minDate: '',\n      maxDate: '',\n      leftDate: new Date(),\n      rightDate: addYears(new Date(), 1),\n      rangeState: {\n        endDate: null,\n        selecting: false\n      },\n      shortcuts: '',\n      isRanged: true,\n      currentView: 'monthrange'\n    };\n  },\n\n  computed: {\n    leftPanelClasses() {\n      return {\n        'q-picker-panel__content': true,\n        'q-picker-panel__content_no-right-borders': true,\n        'q-picker-panel__content_focused': this.panelInFocus === 'left'\n      };\n    },\n    rightPanelClasses() {\n      return {\n        'q-picker-panel__content': true,\n        'q-picker-panel__content_no-left-borders': true,\n        'q-picker-panel__content_focused': this.panelInFocus === 'right'\n      };\n    },\n    rightYear() {\n      if (isDate(this.rightDate) && isDate(this.leftDate)) {\n        return this.rightDate.getFullYear() === this.leftDate.getFullYear()\n          ? this.leftDate.getFullYear() + 1\n          : this.rightDate.getFullYear();\n      }\n\n      return new Date().getFullYear() + 1;\n    },\n\n    enableYearArrow() {\n      return this.rightYear > this.leftYear + 1;\n    }\n  },\n\n  methods: {\n    handleClear() {\n      this.minDate = null;\n      this.maxDate = null;\n      this.leftDate = new Date();\n      this.rightDate = addYears(new Date(), 1);\n      this.$emit('pick', null);\n    }\n  }\n};\n</script>\n"
  },
  {
    "path": "src/qComponents/QDatePicker/src/panel/range-mixin.js",
    "content": "import {\n  subYears,\n  addYears,\n  isDate,\n  startOfDecade,\n  endOfDecade,\n  isSameMonth,\n  addMonths,\n  getDecade,\n  endOfDay\n} from 'date-fns';\n\nimport { isTimeValueValid } from '../../../helpers/dateHelpers';\n\nexport default {\n  inject: {\n    picker: {\n      default: null\n    }\n  },\n  computed: {\n    btnDisabled() {\n      return !(\n        this.minDate &&\n        this.maxDate &&\n        !this.selecting &&\n        this.isValidValue([this.minDate, this.maxDate])\n      );\n    },\n\n    leftLabel() {\n      if (this.$parent.type === 'yearrange') {\n        return `${startOfDecade(this.leftDate).getFullYear()} - ${endOfDecade(\n          this.leftDate\n        ).getFullYear()}`;\n      }\n      const formatter = new Intl.DateTimeFormat(this.$Q.locale, {\n        month: 'short'\n      });\n\n      return `${formatter.format(\n        this.leftDate\n      )} ${this.leftDate.getFullYear()}`;\n    },\n\n    rightLabel() {\n      if (this.$parent.type === 'yearrange') {\n        return `${startOfDecade(this.rightDate).getFullYear()} - ${endOfDecade(\n          this.rightDate\n        ).getFullYear()}`;\n      }\n\n      const formatter = new Intl.DateTimeFormat(this.$Q.locale, {\n        month: 'short'\n      });\n\n      return `${formatter.format(\n        this.rightDate\n      )} ${this.rightDate.getFullYear()}`;\n    },\n\n    leftYear() {\n      if (isDate(this.leftDate)) {\n        return this.leftDate.getFullYear();\n      }\n      return new Date().getFullYear();\n    },\n\n    leftMonth() {\n      if (isDate(this.leftDate)) {\n        return this.leftDate.getMonth();\n      }\n      return new Date().getMonth();\n    },\n\n    rightMonth() {\n      if (isDate(this.rightDate)) {\n        return this.rightDate.getMonth();\n      }\n      return new Date().getMonth() + 1;\n    }\n  },\n  watch: {\n    value: {\n      handler(newVal) {\n        if (!newVal || !newVal?.length) {\n          this.handleClear();\n        } else {\n          this.minDate = newVal[0];\n          this.maxDate = newVal[1];\n          switch (this.$parent.type) {\n            case 'yearrange': {\n              if (getDecade(this.minDate) === getDecade(this.maxDate)) {\n                this.leftDate = this.minDate;\n                this.rightDate = addYears(this.minDate, 10);\n              }\n              break;\n            }\n            default: {\n              if (isSameMonth(this.minDate, this.maxDate)) {\n                this.leftDate = this.minDate;\n                this.rightDate = addMonths(this.minDate, 1);\n              } else {\n                this.leftDate = this.minDate;\n                this.rightDate = this.maxDate;\n              }\n            }\n          }\n        }\n      },\n      immediate: true\n    }\n  },\n  methods: {\n    handleLeftPrevYearClick() {\n      this.leftDate = subYears(this.leftDate, 1);\n    },\n\n    handleRightNextYearClick() {\n      this.rightDate = addYears(this.rightDate, 1);\n    },\n\n    handleLeftNextYearClick() {\n      this.leftDate = addYears(this.leftDate, 1);\n    },\n\n    handleRightPrevYearClick() {\n      this.rightDate = subYears(this.rightDate, 1);\n    },\n\n    handleShortcutClick(shortcut) {\n      if (shortcut.onClick) {\n        shortcut.onClick(this);\n      }\n    },\n\n    handleRangePick(val, close = true) {\n      if (this.maxDate === val.maxDate && this.minDate === val.minDate) {\n        return;\n      }\n\n      if (isDate(val.maxDate)) {\n        // eslint-disable-next-line no-param-reassign\n        val.maxDate = endOfDay(val.maxDate);\n      }\n\n      if (val.rangeState) {\n        this.rangeState = val.rangeState;\n      }\n\n      this.maxDate = val.maxDate;\n      this.minDate = val.minDate;\n      const to = this.disabledValues?.time?.to;\n\n      if (this.maxDate && to && isTimeValueValid(to)) {\n        const [hours, minutes, seconds] = to.split(':');\n        this.minDate.setHours(Number(hours));\n        this.minDate.setMinutes(Number(minutes));\n        this.minDate.setSeconds(Number(seconds));\n        this.maxDate.setHours(Number(hours));\n        this.maxDate.setMinutes(Number(minutes));\n        this.maxDate.setSeconds(Number(seconds));\n      }\n\n      // emit QDatepicker intermediate value\n      this.picker?.$emit('rangepick', val);\n\n      if (!close) return;\n      if (this.isValidValue([this.minDate, this.maxDate])) {\n        this.$emit('pick', [this.minDate, this.maxDate], {\n          hidePicker: !this.showTime\n        });\n      }\n    },\n\n    handleChangeRange(val) {\n      this.minDate = val.minDate;\n      this.maxDate = val.maxDate;\n      this.rangeState = val.rangeState;\n    },\n\n    isValidValue(value) {\n      return (\n        Array.isArray(value) &&\n        value &&\n        value[0] &&\n        value[1] &&\n        isDate(value[0]) &&\n        isDate(value[1]) &&\n        value[0].getTime() <= value[1].getTime()\n      );\n    }\n  }\n};\n"
  },
  {
    "path": "src/qComponents/QDatePicker/src/panel/year-range.vue",
    "content": "<template>\n  <div class=\"q-picker-panel\">\n    <div class=\"q-picker-panel__body-wrapper\">\n      <slot\n        name=\"sidebar\"\n        class=\"q-picker-panel__sidebar\"\n      />\n      <div\n        v-if=\"!$slots.sidebar && shortcuts.length\"\n        class=\"q-picker-panel__sidebar\"\n      >\n        <button\n          v-for=\"(shortcut, key) in shortcuts\"\n          :key=\"key\"\n          type=\"button\"\n          class=\"q-picker-panel__shortcut\"\n          @click=\"handleShortcutClick(shortcut)\"\n        >\n          {{ shortcut.text }}\n        </button>\n      </div>\n      <div class=\"q-picker-panel__body\">\n        <div\n          ref=\"leftPanel\"\n          :class=\"leftPanelClasses\"\n        >\n          <div class=\"q-picker-panel__header\">\n            <button\n              type=\"button\"\n              class=\"q-picker-panel__icon-btn q-icon-double-triangle-left\"\n              @click=\"leftPrevYear\"\n            />\n            <div class=\"q-picker-panel__header-sign\">{{ leftLabel }}</div>\n            <button\n              type=\"button\"\n              :disabled=\"!enableYearArrow\"\n              :class=\"{\n                'q-picker-panel__icon-btn_disabled': !enableYearArrow\n              }\"\n              class=\"q-picker-panel__icon-btn q-icon-double-triangle-right\"\n              @click=\"leftNextYear\"\n            />\n          </div>\n          <year-table\n            :year=\"leftYear\"\n            :min-date=\"minDate\"\n            :max-date=\"maxDate\"\n            :disabled-values=\"disabledValues\"\n            :range-state=\"rangeState\"\n            selection-mode=\"range\"\n            @pick=\"handleRangePick\"\n            @changerange=\"handleChangeRange\"\n          />\n        </div>\n        <div\n          ref=\"rightPanel\"\n          :class=\"rightPanelClasses\"\n        >\n          <div class=\"q-picker-panel__header\">\n            <button\n              type=\"button\"\n              :disabled=\"!enableYearArrow\"\n              :class=\"{\n                'q-picker-panel__icon-btn_disabled': !enableYearArrow\n              }\"\n              class=\"q-picker-panel__icon-btn q-icon-double-triangle-left\"\n              @click=\"rightPrevYear\"\n            />\n            <div class=\"q-picker-panel__header-sign\">\n              {{ rightLabel }}\n            </div>\n            <button\n              type=\"button\"\n              class=\"q-picker-panel__icon-btn q-icon-double-triangle-right\"\n              @click=\"rightNextYear\"\n            />\n          </div>\n          <year-table\n            :year=\"rightYear\"\n            :min-date=\"minDate\"\n            :max-date=\"maxDate\"\n            :disabled-values=\"disabledValues\"\n            selection-mode=\"range\"\n            :range-state=\"rangeState\"\n            @pick=\"handleRangePick\"\n            @changerange=\"handleChangeRange\"\n          />\n        </div>\n      </div>\n    </div>\n  </div>\n</template>\n\n<script>\nimport { addYears, getDecade, isDate, subYears } from 'date-fns';\nimport YearTable from '../basic/year-table';\nimport rangeMixin from './range-mixin';\nimport focusMixin from './focus-mixin';\n\nconst YEARS_IN_DECADE = 10;\n\nexport default {\n  components: { YearTable },\n  mixins: [rangeMixin, focusMixin],\n  props: {\n    value: {\n      type: Array,\n      default: () => []\n    },\n    disabledValues: {\n      type: Object,\n      default: null\n    }\n  },\n  data() {\n    return {\n      minDate: '',\n      maxDate: '',\n      leftDate: new Date(),\n      rightDate: addYears(new Date(), YEARS_IN_DECADE),\n      rangeState: {\n        endDate: null,\n        selecting: false\n      },\n      shortcuts: '',\n      isRanged: true,\n      currentView: 'yearrange'\n    };\n  },\n\n  computed: {\n    rightYear() {\n      if (isDate(this.rightDate) && isDate(this.leftDate)) {\n        return getDecade(this.rightDate) === getDecade(this.leftDate)\n          ? this.leftDate.getFullYear() + YEARS_IN_DECADE\n          : this.rightDate.getFullYear();\n      }\n\n      return new Date().getFullYear() + YEARS_IN_DECADE;\n    },\n\n    enableYearArrow() {\n      return this.rightYear > this.leftYear + YEARS_IN_DECADE;\n    },\n    leftPanelClasses() {\n      return {\n        'q-picker-panel__content': true,\n        'q-picker-panel__content_no-right-borders': true,\n        'q-picker-panel__content_focused': this.panelInFocus === 'left'\n      };\n    },\n    rightPanelClasses() {\n      return {\n        'q-picker-panel__content': true,\n        'q-picker-panel__content_no-left-borders': true,\n        'q-picker-panel__content_focused': this.panelInFocus === 'right'\n      };\n    }\n  },\n\n  methods: {\n    leftNextYear() {\n      this.leftDate = addYears(this.leftDate, YEARS_IN_DECADE);\n    },\n    leftPrevYear() {\n      this.leftDate = subYears(this.leftDate, YEARS_IN_DECADE);\n    },\n    rightNextYear() {\n      this.rightDate = addYears(this.rightDate, YEARS_IN_DECADE);\n    },\n    rightPrevYear() {\n      this.rightDate = subYears(this.rightDate, YEARS_IN_DECADE);\n    },\n    handleClear() {\n      this.minDate = null;\n      this.maxDate = null;\n      this.leftDate = new Date();\n      this.rightDate = addYears(new Date(), YEARS_IN_DECADE);\n      this.$emit('pick', null);\n    }\n  }\n};\n</script>\n"
  },
  {
    "path": "src/qComponents/QDatePicker/src/q-date-picker.scss",
    "content": "@import './styles/date-table.scss';\n@import './styles/month-table.scss';\n@import './styles/year-table.scss';\n@import './styles/picker.scss';\n@import './styles/picker-panel.scss';\n@import '../../QTimePicker/src/components/time-panel.scss';\n"
  },
  {
    "path": "src/qComponents/QDatePicker/src/styles/date-table.scss",
    "content": ".q-date-table {\n  width: 100%;\n  table-layout: fixed;\n  font-size: 10px;\n  user-select: none;\n\n  &_days {\n    line-height: 1;\n  }\n\n  &__cell-wrapper {\n    position: relative;\n    width: 20px;\n    height: 20px;\n    padding: 0;\n    text-align: center;\n    cursor: pointer;\n\n    .cell {\n      position: relative;\n      box-sizing: border-box;\n      width: 20px;\n      height: 20px;\n      margin: 0 auto;\n      padding: 0;\n      font-weight: var(--font-weight-base);\n      color: var(--color-primary-blue);\n      background-color: var(--color-tertiary-gray-light);\n      border: none;\n      border-radius: var(--border-radius-base);\n      box-shadow: var(--box-shadow-secondary);\n\n      &:hover {\n        &:not(.cell_disabled):not(.cell_current):not(.cell_in-range) {\n          color: var(--color-primary-black);\n          background-color: var(--color-tertiary-gray);\n        }\n      }\n\n      &[data-focus-visible-added] {\n        &:not(.cell_disabled) {\n          color: var(--color-tertiary-white);\n          background-color: var(--color-primary-blue);\n          box-shadow: var(--box-shadow-pressed);\n          transform: scale(1.2);\n          transition: transform 0.2s;\n        }\n      }\n\n      &_disabled {\n        color: rgba(var(--color-primary-black), 0.64);\n        background-color: var(--color-tertiary-gray);\n        cursor: not-allowed;\n        opacity: 1;\n      }\n\n      &_selected {\n        color: var(--color-tertiary-white);\n        background-color: var(--color-primary-blue);\n        box-shadow: var(--box-shadow-primary);\n      }\n\n      &_today:not(.cell_disabled) {\n        color: var(--color-primary);\n      }\n\n      &_today {\n        &::before {\n          content: '';\n          position: absolute;\n          top: -4px;\n          left: 9px;\n          display: block;\n          width: 2px;\n          height: 2px;\n          background-color: var(--color-primary);\n          border-radius: 50%;\n        }\n      }\n\n      &_current,\n      &_in-range {\n        color: var(--color-tertiary-white);\n        background-color: var(--color-primary-blue);\n\n        &::after {\n          content: '';\n          position: absolute;\n          top: 0;\n          right: 0;\n          left: 0;\n          z-index: -1;\n          width: 20px;\n          height: 20px;\n          margin: auto;\n          border-radius: 4px;\n          box-shadow: var(--box-shadow-primary);\n        }\n\n        &:hover {\n          color: #fff;\n        }\n      }\n\n      &_today {\n        &.cell_current,\n        &.cell_in-range:not(.cell_prev-month),\n        &.cell_in-range:not(.cell_next-month) {\n          color: #fff;\n        }\n      }\n\n      &_next-month,\n      &_prev-month {\n        color: rgba(var(--color-rgb-gray), 0.32);\n\n        &.cell_in-range {\n          color: var(--color-primary-black);\n          background-color: var(--color-tertiary-gray);\n        }\n      }\n    }\n  }\n\n  th {\n    font-weight: var(--font-weight-base);\n    color: rgba(var(--color-rgb-gray), 0.64);\n  }\n}\n"
  },
  {
    "path": "src/qComponents/QDatePicker/src/styles/month-table.scss",
    "content": ".q-month-table {\n  width: 100%;\n  padding: 10px 0 20px;\n  table-layout: fixed;\n  font-size: 12px;\n\n  &__cell-wrapper {\n    text-align: center;\n    cursor: pointer;\n\n    .cell {\n      position: relative;\n      display: block;\n      width: 40px;\n      height: 40px;\n      font-weight: var(--font-weight-base);\n      color: var(--color-primary-blue);\n      border: none;\n      border-radius: var(--border-radius-base);\n      box-shadow: var(--box-shadow-secondary);\n\n      &:hover:not([disabled]):not(.cell_in-range):not(.cell_current) {\n        color: var(--color-primary-black);\n        background-color: var(--color-tertiary-gray);\n      }\n\n      &[data-focus-visible-added] {\n        &:not(.cell_disabled) {\n          color: var(--color-tertiary-white);\n          background-color: var(--color-primary-blue);\n          box-shadow: var(--box-shadow-pressed);\n          transform: scale(1.1);\n          transition: transform 0.2s;\n        }\n      }\n\n      &_today {\n        color: var(--color-primary);\n\n        &.cell_current {\n          color: var(--color-tertiary-white);\n        }\n\n        &::before {\n          content: '';\n          position: absolute;\n          top: -5px;\n          left: 19px;\n          display: block;\n          width: 2px;\n          height: 2px;\n          background-color: var(--color-primary);\n          border-radius: 50%;\n        }\n      }\n\n      &[disabled] {\n        color: var(--color-tertiary-gray-ultra-dark);\n        background-color: var(--color-tertiary-gray-lighter);\n        cursor: not-allowed;\n\n        &:hover {\n          color: var(--color-tertiary-gray-ultra-dark);\n        }\n      }\n\n      &_in-range {\n        color: #fff;\n        background-color: var(--color-primary-blue);\n        box-shadow: var(--box-shadow-pressed);\n      }\n\n      &_current:not(.disabled) {\n        color: #fff;\n        background-color: var(--color-primary-blue);\n        box-shadow: var(--box-shadow-pressed);\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "src/qComponents/QDatePicker/src/styles/picker-panel.scss",
    "content": ".q-picker-panel {\n  z-index: 1;\n  display: none;\n  border-radius: 4px;\n\n  &_shown {\n    display: block;\n  }\n\n  &__sidebar {\n    flex-shrink: 0;\n    width: 114px;\n    padding: 16px 8px;\n    overflow: auto;\n    background: var(--color-tertiary-gray-light);\n    border-top-left-radius: 4px;\n    border-bottom-left-radius: 4px;\n    box-shadow: var(--box-shadow-pressed);\n\n    & + .q-picker-panel__content {\n      margin-left: 1px;\n      border-top-left-radius: 0;\n      border-bottom-left-radius: 0;\n    }\n  }\n\n  &__body,\n  &__body-wrapper {\n    display: flex;\n    flex-shrink: 0;\n    height: 100%;\n    background: var(--color-tertiary-gray-light);\n    border-radius: 4px;\n    box-shadow: var(--box-shadow-secondary);\n\n    &::after {\n      content: '';\n      display: table;\n      clear: both;\n    }\n  }\n\n  &__header {\n    position: relative;\n    display: flex;\n    justify-content: space-between;\n    align-items: center;\n    padding: 10px 8px 0;\n    text-align: center;\n    text-transform: uppercase;\n\n    &-sign {\n      display: flex;\n      flex-basis: 72px;\n      justify-content: center;\n      margin-right: 12px;\n      margin-left: 12px;\n      font-weight: 600;\n      font-size: 12px;\n      line-height: 15px;\n      color: var(--color-primary-black);\n      white-space: nowrap;\n    }\n  }\n\n  &__header-label {\n    cursor: pointer;\n    user-select: none;\n\n    &:nth-child(2) {\n      margin-left: 5px;\n    }\n\n    &:hover {\n      color: var(--color-primary-blue);\n    }\n  }\n\n  &__content {\n    position: relative;\n    flex-shrink: 0;\n    box-sizing: border-box;\n    width: 220px;\n    background: var(--color-tertiary-gray-light);\n    border-radius: 4px;\n    box-shadow: var(--box-shadow-pressed);\n\n    &_no-right-borders {\n      border-top-right-radius: 0;\n      border-bottom-right-radius: 0;\n    }\n\n    &_no-left-borders {\n      margin-left: 1px;\n      border-top-left-radius: 0;\n      border-bottom-left-radius: 0;\n    }\n\n    &_focused {\n      z-index: 2;\n      border-radius: 4px;\n      outline: none;\n      box-shadow: var(--box-shadow-secondary);\n      transform: scale(1.03);\n      transition: transform 0.2s;\n    }\n  }\n\n  &__shortcut {\n    display: block;\n    width: 100%;\n    padding-bottom: 8px;\n    font-size: 10px;\n    line-height: 12px;\n    text-align: left;\n    color: rgba(var(--color-rgb-gray), 0.64);\n    background-color: transparent;\n    border: 0;\n    outline: none;\n    cursor: pointer;\n\n    &:hover {\n      color: var(--color-primary-blue);\n    }\n\n    &[data-focus-visible-added] {\n      color: var(--color-primary-blue);\n      text-decoration: underline;\n    }\n  }\n\n  &__icon-btn {\n    width: 20px;\n    min-width: 20px;\n    height: 20px;\n    padding: 0;\n    font-size: 20px;\n    line-height: 21px;\n    color: var(--color-primary-blue);\n    background: var(--color-tertiary-gray-light);\n    border: 0;\n    border-radius: 20px;\n    outline: none;\n    box-shadow: var(--box-shadow-primary);\n    cursor: pointer;\n\n    &:hover {\n      color: var(--color-primary-black);\n    }\n\n    &[data-focus-visible-added] {\n      color: var(--color-primary-black);\n      background-color: var(--color-tertiary-gray);\n    }\n\n    &_disabled {\n      color: var(--color-tertiary-gray-ultra-darker);\n\n      &:hover {\n        color: var(--color-tertiary-gray-ultra-darker);\n        cursor: not-allowed;\n      }\n    }\n  }\n\n  &__link-btn {\n    vertical-align: middle;\n  }\n\n  &__timepickers {\n    display: inline-flex;\n\n    .time-panel {\n      display: block;\n      height: 100%;\n      box-shadow: var(--box-shadow-pressed);\n\n      &_focused {\n        box-shadow: var(--box-shadow-secondary);\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "src/qComponents/QDatePicker/src/styles/picker.scss",
    "content": ".q-date-editor {\n  --field-box-shadow-focus: -1px -1px 3px rgba(var(--color-rgb-white), 0.25),\n    1px 1px 3px rgba(var(--color-rgb-blue), 0.4),\n    inset -1px -1px 1px rgba(var(--color-rgb-white), 0.7),\n    inset 1px 1px 2px rgba(var(--color-rgb-blue), 0.2);\n\n  position: relative;\n  display: inline-block;\n  text-align: left;\n\n  .q-input__icon.q-icon-close {\n    color: var(--color-primary-blue);\n    cursor: pointer;\n\n    &:hover {\n      color: var(--color-primary-black);\n    }\n  }\n\n  .q-range-input {\n    display: inline-block;\n    width: 42%;\n    height: 100%;\n    margin: 0;\n    padding: 0;\n    font-weight: var(--font-weight-base);\n    font-size: inherit;\n    line-height: 40px;\n    color: var(--color-primary-black);\n    white-space: nowrap;\n    text-overflow: ellipsis;\n    border: none;\n    outline: none;\n    appearance: none;\n\n    &::placeholder {\n      color: rgba(var(--color-rgb-gray), 0.32);\n      opacity: 1;\n    }\n  }\n\n  .q-range-separator {\n    display: inline-block;\n    width: 5%;\n    height: 100%;\n    margin: 0;\n    padding: 0 2px;\n    font-size: 14px;\n    line-height: 32px;\n    text-align: center;\n    color: var(--color-primary-black);\n  }\n}\n\n.q-range-editor {\n  display: inline-flex;\n  align-items: center;\n  width: 100%;\n  padding-left: 5px;\n  background-color: var(--color-tertiary-gray-light);\n  border: none;\n  border-radius: var(--border-radius-base);\n  box-shadow: var(--box-shadow-primary);\n  cursor: pointer;\n\n  &:hover:not(.q-range-editor_disabled) {\n    background-color: var(--color-tertiary-gray);\n    box-shadow: var(--box-shadow-hover);\n  }\n\n  .q-range-input {\n    line-height: 1;\n    text-align: center;\n    background: none;\n  }\n\n  &_focused {\n    background-color: var(--color-tertiary-gray-ultra-light);\n    outline: none;\n    box-shadow: var(--field-box-shadow-focus);\n  }\n\n  &_disabled {\n    background-color: var(--color-tertiary-gray);\n    box-shadow: var(--box-shadow-pressed);\n    cursor: not-allowed;\n\n    .q-range-separator,\n    .q-range-input {\n      color: var(--field-color-disabled);\n      cursor: not-allowed;\n    }\n  }\n\n  .q-form-item_is-error & {\n    border: var(--border-error);\n  }\n}\n"
  },
  {
    "path": "src/qComponents/QDatePicker/src/styles/year-table.scss",
    "content": ".q-year-table {\n  width: 100%;\n  padding: 10px 0 20px;\n  table-layout: fixed;\n  font-size: 12px;\n\n  &__cell-wrapper {\n    text-align: center;\n    cursor: pointer;\n\n    .cell {\n      position: relative;\n      display: block;\n      width: 40px;\n      height: 40px;\n      margin: 0 auto;\n      font-weight: 500;\n      line-height: 40px;\n      color: var(--color-primary-blue);\n      border: none;\n      border-radius: var(--border-radius-base);\n      box-shadow: var(--box-shadow-secondary);\n\n      &:hover:not([disabled]):hover:not(.cell_in-range):not(.cell_current) {\n        color: var(--color-primary-black);\n        background-color: var(--color-tertiary-gray);\n      }\n\n      &[data-focus-visible-added] {\n        &:not(.cell_disabled) {\n          color: var(--color-tertiary-white);\n          background-color: var(--color-primary-blue);\n          box-shadow: var(--box-shadow-pressed);\n          transform: scale(1.1);\n          transition: transform 0.2s;\n        }\n      }\n\n      &_current:not(.cell_disabled) {\n        color: var(--color-tertiary-white);\n        background-color: var(--color-primary-blue);\n        box-shadow: var(--box-shadow-pressed);\n      }\n\n      &_today {\n        color: var(--color-primary);\n\n        &::before {\n          content: '';\n          position: absolute;\n          top: -5px;\n          left: 19px;\n          display: block;\n          width: 2px;\n          height: 2px;\n          background-color: var(--color-primary);\n          border-radius: 50%;\n        }\n      }\n\n      &[disabled] {\n        color: var(--color-tertiary-gray-ultra-dark);\n        background-color: var(--color-tertiary-gray-lighter);\n        cursor: not-allowed;\n\n        &:hover {\n          color: var(--color-tertiary-gray-ultra-dark);\n        }\n      }\n\n      &_in-range {\n        color: var(--color-tertiary-white);\n        background-color: var(--color-primary-blue);\n        box-shadow: var(--box-shadow-pressed);\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "src/qComponents/QDialog/QDialog.test.js",
    "content": "import Component from './src/QDialog.vue';\n\ndescribe('QDialog', () => {\n  it('should match snapshot', async () => {\n    const instance = shallowMount(Component, {\n      stubs: ['dialog-content']\n    });\n\n    await instance.setData({\n      isShown: true\n    });\n\n    expect(instance.element).toMatchSnapshot();\n  });\n\n  it('data should match snapshot', () => {\n    expect(Component.data()).toMatchSnapshot();\n  });\n});\n"
  },
  {
    "path": "src/qComponents/QDialog/__snapshots__/QDialog.test.js.snap",
    "content": "// Jest Snapshot v1, https://goo.gl/fbAQLP\n\nexports[`QDialog data should match snapshot 1`] = `\nObject {\n  \"callback\": null,\n  \"elementToFocusAfterClosing\": null,\n  \"isShown\": false,\n  \"top\": null,\n}\n`;\n\nexports[`QDialog should match snapshot 1`] = `\n<transition-stub\n  name=\"q-dialog-fade\"\n>\n  <div\n    class=\"q-dialog\"\n    tabindex=\"-1\"\n  >\n    <div\n      class=\"q-dialog__container\"\n    >\n      <q-scrollbar-stub\n        theme=\"secondary\"\n        viewclass=\"q-dialog__view\"\n        viewtag=\"div\"\n        wrapclass=\"\"\n      >\n        <div\n          class=\"q-dialog__inner\"\n        >\n          <div\n            class=\"q-dialog__title\"\n          >\n            \n            \n          \n          </div>\n           \n          <q-button-stub\n            circle=\"true\"\n            class=\"q-dialog__close\"\n            icon=\"q-icon-close\"\n            nativetype=\"button\"\n            size=\"medium\"\n            theme=\"secondary\"\n            type=\"icon\"\n          />\n           \n          <div\n            class=\"q-dialog__content\"\n          >\n            <dialog-content-stub />\n          </div>\n        </div>\n      </q-scrollbar-stub>\n    </div>\n  </div>\n</transition-stub>\n`;\n"
  },
  {
    "path": "src/qComponents/QDialog/index.js",
    "content": "import QDialog from './src/QDialog.js';\n\nexport default QDialog;\n"
  },
  {
    "path": "src/qComponents/QDialog/src/QDialog.js",
    "content": "import Vue from 'vue';\n\nimport QDialog from './QDialog.vue';\n\nlet currentPromise;\n\nconst defaultCallback = ({ payload }) => {\n  currentPromise.resolve({ payload });\n};\n\nconst Dialog = function(config = {}) {\n  const DialogComponent = Vue.extend({\n    components: {\n      DialogContent: config.component\n    },\n    ...QDialog\n  });\n\n  const instance = new DialogComponent();\n\n  Object.entries(config).forEach(([key, value]) => {\n    instance[key] = value;\n  });\n\n  if (!instance.zIndex) {\n    instance.zIndex = Vue.prototype.$Q?.zIndex ?? 2000;\n  }\n\n  instance.callback = defaultCallback;\n\n  let parent = document.body;\n  if (config.rootSelector) {\n    parent = document.querySelector(config.rootSelector);\n  }\n  parent.appendChild(instance.$mount().$el);\n\n  Vue.nextTick(() => {\n    instance.isShown = true;\n  });\n\n  return {\n    instance,\n    answer: new Promise((resolve, reject) => {\n      currentPromise = {\n        resolve,\n        reject\n      };\n    })\n  };\n};\n\nexport default Dialog;\n"
  },
  {
    "path": "src/qComponents/QDialog/src/QDialog.vue",
    "content": "<template>\n  <transition\n    name=\"q-dialog-fade\"\n    @after-enter=\"handleHookAfterEnter\"\n    @after-leave=\"handleHookAfterLeave\"\n  >\n    <div\n      v-if=\"isShown\"\n      ref=\"dialog\"\n      class=\"q-dialog\"\n      :style=\"dialogStyles\"\n      tabindex=\"-1\"\n      @keyup.esc=\"closeBox\"\n    >\n      <div class=\"q-dialog__container\">\n        <q-scrollbar\n          theme=\"secondary\"\n          view-class=\"q-dialog__view\"\n        >\n          <div class=\"q-dialog__inner\">\n            <div class=\"q-dialog__title\">\n              {{ title }}\n            </div>\n\n            <q-button\n              class=\"q-dialog__close\"\n              circle\n              theme=\"secondary\"\n              type=\"icon\"\n              icon=\"q-icon-close\"\n              @click=\"closeBox\"\n            />\n\n            <div class=\"q-dialog__content\">\n              <dialog-content\n                v-bind=\"componentProps\"\n                @close=\"closeBox\"\n              />\n            </div>\n          </div>\n        </q-scrollbar>\n      </div>\n    </div>\n  </transition>\n</template>\n\n<script>\nexport default {\n  name: 'QDialog',\n  componentName: 'QDialog',\n\n  props: {\n    /**\n     * z-index of the QDialog\n     */\n    zIndex: {\n      type: Number,\n      default: null\n    },\n    /**\n     * offset from top border of parent relative element\n     */\n    offsetTop: {\n      type: Number,\n      default: null\n    },\n    /**\n     * title of the QDialog\n     */\n    title: {\n      type: String,\n      default: ''\n    },\n    /**\n     * callback before QDialog closes, and it will prevent QDialog from closing\n     */\n    beforeClose: {\n      type: Function,\n      default: null\n    },\n    /**\n     * pass props to child component\n     */\n    componentProps: {\n      type: Object,\n      default: () => ({})\n    }\n  },\n\n  data() {\n    return {\n      isShown: false,\n      callback: null,\n      top: null,\n      elementToFocusAfterClosing: null\n    };\n  },\n\n  computed: {\n    dialogStyles() {\n      return {\n        zIndex: this.zIndex,\n        top: this.offsetTop ? `${this.offsetTop}px` : null\n      };\n    }\n  },\n\n  watch: {\n    isShown(value) {\n      if (value) {\n        this.elementToFocusAfterClosing = document.activeElement;\n        this.$nextTick(() => {\n          this.$refs.dialog.focus();\n        });\n      }\n\n      this.$emit(value ? 'open' : 'close');\n    }\n  },\n\n  mounted() {\n    document.documentElement.style.overflowY = 'hidden';\n    document.addEventListener('focus', this.handleDocumentFocus, true);\n  },\n\n  beforeDestroy() {\n    document.documentElement.style.overflowY = '';\n\n    const el = this.$el;\n    if (el?.parentNode) {\n      el.parentNode.removeChild(el);\n    }\n  },\n\n  methods: {\n    handleDocumentFocus(event) {\n      const { dialog } = this.$refs;\n      if (dialog && !dialog.contains(event.target)) {\n        dialog.focus();\n      }\n    },\n\n    handleHookAfterEnter() {\n      this.$emit('opened');\n    },\n\n    handleHookAfterLeave() {\n      this.$emit('closed');\n      this.$destroy();\n    },\n\n    async closeBox({ payload = null } = {}) {\n      let isReadyToClose = true;\n\n      if (typeof this.beforeClose === 'function') {\n        isReadyToClose = await this.beforeClose({ payload, ctx: this });\n      }\n\n      if (isReadyToClose) {\n        this.callback({ payload });\n\n        this.isShown = false;\n\n        document.removeEventListener('focus', this.handleDocumentFocus, true);\n        this.$nextTick(() => {\n          this.elementToFocusAfterClosing?.focus();\n        });\n      }\n    }\n  }\n};\n</script>\n"
  },
  {
    "path": "src/qComponents/QDialog/src/q-dialog.scss",
    "content": ".q-dialog {\n  position: fixed;\n  top: 0;\n  right: 0;\n  left: 0;\n  display: flex;\n  justify-content: center;\n  align-items: center;\n  height: 100vh;\n\n  &__container {\n    width: 100%;\n    height: 100%;\n    overflow: auto;\n    background-color: var(--color-tertiary-gray-ultra-light);\n  }\n\n  &__view {\n    display: flex;\n  }\n\n  &__inner {\n    position: relative;\n    display: flex;\n    flex-direction: column;\n    width: 100%;\n    padding: 36px 32px 32px;\n  }\n\n  &__close {\n    position: absolute;\n    top: 24px;\n    right: 32px;\n  }\n\n  &__title {\n    padding-right: 104px;\n    font-weight: 800;\n    font-size: 24px;\n    line-height: 31px;\n    color: var(--color-primary-black);\n    word-break: break-word;\n  }\n\n  &__content {\n    flex: 1;\n    margin-top: 32px;\n  }\n}\n\n.q-dialog-fade-enter-active {\n  animation: q-dialog-fade-in 0.3s;\n}\n\n.q-dialog-fade-leave-active {\n  animation: q-dialog-fade-out 0.3s;\n}\n\n@keyframes q-dialog-fade-in {\n  0% {\n    transform: translate3d(0, -20px, 0);\n    opacity: 0;\n  }\n\n  100% {\n    transform: translate3d(0, 0, 0);\n    opacity: 1;\n  }\n}\n\n@keyframes q-dialog-fade-out {\n  0% {\n    transform: translate3d(0, 0, 0);\n    opacity: 1;\n  }\n\n  100% {\n    transform: translate3d(0, -20px, 0);\n    opacity: 0;\n  }\n}\n"
  },
  {
    "path": "src/qComponents/QDrawer/QDrawer.test.js",
    "content": "import Component from './src/QDrawer';\n\ndescribe('QDrawer', () => {\n  it('should match snapshot', async () => {\n    const instance = shallowMount(Component);\n\n    await instance.setProps({\n      visible: true\n    });\n\n    expect(instance.element).toMatchSnapshot();\n  });\n\n  it('data should match snapshot', () => {\n    expect(Component.data()).toMatchSnapshot();\n  });\n});\n"
  },
  {
    "path": "src/qComponents/QDrawer/__snapshots__/QDrawer.test.js.snap",
    "content": "// Jest Snapshot v1, https://goo.gl/fbAQLP\n\nexports[`QDrawer data should match snapshot 1`] = `\nObject {\n  \"elementToFocusAfterClosing\": null,\n  \"isRendered\": false,\n  \"zIndex\": null,\n}\n`;\n\nexports[`QDrawer should match snapshot 1`] = `\n<transition-stub\n  name=\"q-drawer-fade\"\n>\n  <div\n    class=\"q-drawer\"\n    style=\"z-index: 2001;\"\n  >\n    <div\n      class=\"q-drawer-wrapper q-drawer-wrapper_right focus-visible\"\n      data-focus-visible-added=\"\"\n      tabindex=\"-1\"\n    >\n      <div\n        class=\"q-drawer__header\"\n      >\n        <!---->\n         \n        <button\n          class=\"q-drawer__close q-icon-close\"\n        />\n      </div>\n       \n      <q-scrollbar-stub\n        theme=\"primary\"\n        viewclass=\"\"\n        viewtag=\"div\"\n        wrapclass=\"\"\n      >\n        <div\n          class=\"q-drawer__content\"\n        />\n      </q-scrollbar-stub>\n    </div>\n  </div>\n</transition-stub>\n`;\n"
  },
  {
    "path": "src/qComponents/QDrawer/index.js",
    "content": "import QDrawer from './src/QDrawer';\n\nQDrawer.install = Vue => {\n  Vue.component(QDrawer.name, QDrawer);\n};\n\nexport default QDrawer;\n"
  },
  {
    "path": "src/qComponents/QDrawer/src/QDrawer.vue",
    "content": "<template>\n  <transition\n    name=\"q-drawer-fade\"\n    @after-enter=\"afterEnter\"\n    @after-leave=\"afterLeave\"\n  >\n    <div\n      v-if=\"isRendered\"\n      v-show=\"visible\"\n      class=\"q-drawer\"\n      :style=\"{ zIndex }\"\n      @click.self=\"handleWrapperClick\"\n    >\n      <div\n        ref=\"drawer\"\n        tabindex=\"-1\"\n        class=\"q-drawer-wrapper\"\n        :style=\"drawerStyle\"\n        :class=\"[drawerClass, customClass]\"\n        @keyup.esc=\"closeDrawer\"\n      >\n        <div class=\"q-drawer__header\">\n          <div\n            v-if=\"title\"\n            class=\"q-drawer__title\"\n          >{{ title }}</div>\n          <button\n            class=\"q-drawer__close q-icon-close\"\n            @click=\"closeDrawer\"\n          />\n        </div>\n        <q-scrollbar>\n          <div class=\"q-drawer__content\">\n            <slot />\n          </div>\n        </q-scrollbar>\n      </div>\n    </div>\n  </transition>\n</template>\n\n<script>\nexport default {\n  name: 'QDrawer',\n  componentName: 'QDrawer',\n\n  props: {\n    width: {\n      type: [String, Number],\n      default: ''\n    },\n    /**\n     * Drawer's title\n     */\n    title: {\n      type: String,\n      default: ''\n    },\n    /**\n     * whether Drawer is visible\n     */\n    visible: {\n      type: Boolean,\n      default: false\n    },\n    /**\n     * whether the component will be deleted from layout\n     */\n    destroyOnClose: {\n      type: Boolean,\n      default: false\n    },\n    /**\n     * closes Drawer by click on shadow layer\n     */\n    wrapperClosable: {\n      type: Boolean,\n      default: true\n    },\n    /**\n     * callback before close\n     */\n    beforeClose: {\n      type: Function,\n      default: null\n    },\n    /**\n     * Drawer's position\n     */\n    position: {\n      type: String,\n      default: 'right',\n      validator(dir) {\n        return ['left', 'right'].includes(dir);\n      }\n    },\n    /**\n     * Extra class names for Drawer's wrapper\n     */\n    customClass: {\n      type: String,\n      default: ''\n    },\n    /**\n     * whether to append the popper to body\n     */\n    appendToBody: {\n      type: Boolean,\n      default: true\n    },\n    renderOnMount: {\n      type: Boolean,\n      default: false\n    }\n  },\n\n  data() {\n    return {\n      zIndex: null,\n      isRendered: false,\n      elementToFocusAfterClosing: null\n    };\n  },\n\n  computed: {\n    drawerStyle() {\n      return {\n        width: Number(this.width) ? `${Number(this.width)}px` : this.width\n      };\n    },\n    drawerClass() {\n      return `q-drawer-wrapper_${this.position}`;\n    }\n  },\n\n  watch: {\n    visible: {\n      handler(isVisible) {\n        if (!isVisible) {\n          document.body.style.overflow = '';\n\n          document.removeEventListener('focus', this.handleDocumentFocus, true);\n          if (this.destroyOnClose) {\n            this.isRendered = false;\n          }\n\n          this.$nextTick(() => {\n            this.elementToFocusAfterClosing?.focus();\n          });\n          return;\n        }\n\n        this.elementToFocusAfterClosing = document.activeElement;\n        this.$nextTick(() => {\n          this.$refs.drawer.focus();\n        });\n        this.$emit('open');\n        this.zIndex = this.$Q?.zIndex ?? 2000;\n        document.body.style.overflow = 'hidden';\n        document.addEventListener('focus', this.handleDocumentFocus, true);\n\n        if (this.appendToBody && !this.isRendered)\n          document.body.appendChild(this.$el);\n\n        this.isRendered = true;\n      },\n      immediate: true\n    }\n  },\n\n  mounted() {\n    if (!this.renderOnMount) return;\n\n    this.isRendered = true;\n    if (this.appendToBody) document.body.appendChild(this.$el);\n  },\n\n  beforeDestroy() {\n    document.body.style.overflow = '';\n\n    if (this.$el?.parentNode === document.body) {\n      this.$el.parentNode.removeChild(this.$el);\n    }\n  },\n\n  methods: {\n    handleDocumentFocus(event) {\n      if (!this.$refs.drawer.contains(event.target)) {\n        this.$refs.drawer.focus();\n      }\n    },\n\n    afterEnter() {\n      this.$emit('opened');\n    },\n\n    afterLeave() {\n      this.$emit('closed');\n    },\n\n    handleWrapperClick() {\n      if (!this.wrapperClosable) return;\n\n      this.closeDrawer();\n    },\n\n    hide() {\n      this.$emit('close');\n      this.$emit('update:visible', false);\n    },\n\n    closeDrawer() {\n      if (this.beforeClose) {\n        this.beforeClose(this.hide);\n      } else {\n        this.hide();\n      }\n    }\n  }\n};\n</script>\n"
  },
  {
    "path": "src/qComponents/QDrawer/src/q-drawer.scss",
    "content": "@keyframes left-drawer-in {\n  0% {\n    transform: translate(-100%, 0);\n  }\n\n  100% {\n    transform: translate(0, 0);\n  }\n}\n\n@keyframes left-drawer-out {\n  0% {\n    transform: translate(0, 0);\n  }\n\n  100% {\n    transform: translate(-100%, 0);\n  }\n}\n\n@keyframes right-drawer-in {\n  0% {\n    transform: translate(100%, 0);\n  }\n\n  100% {\n    transform: translate(0, 0);\n  }\n}\n\n@keyframes right-drawer-out {\n  0% {\n    transform: translate(0, 0);\n  }\n\n  100% {\n    transform: translate(100%, 0);\n  }\n}\n\n@mixin animation-in($position) {\n  .q-drawer-wrapper_#{$position} {\n    animation: #{$position}-drawer-in 0.3s 1ms;\n  }\n}\n\n@mixin animation-out($position) {\n  .q-drawer-wrapper_#{$position} {\n    animation: #{$position}-drawer-out 0.3s;\n  }\n}\n\n$positions: right, left;\n\n@keyframes q-drawer-fade-in {\n  0% {\n    opacity: 0;\n  }\n\n  100% {\n    opacity: 1;\n  }\n}\n\n@keyframes q-drawer-slide-in {\n  0% {\n    transform: translate(-100%, 0);\n  }\n\n  100% {\n    transform: translate(0, 0);\n  }\n}\n\n.q-drawer {\n  position: fixed;\n  top: 0;\n  right: 0;\n  bottom: 0;\n  left: 0;\n  z-index: 1;\n  width: 100%;\n  height: 100%;\n  background-color: rgba(var(--color-rgb-white), 0.72);\n\n  &-fade-enter-active {\n    animation: q-drawer-fade-in 0.3s;\n  }\n\n  &-fade-leave-active {\n    animation: q-drawer-fade-in 0.3s reverse;\n  }\n\n  @each $position in $positions {\n    @include animation-out($position);\n    @include animation-in($position);\n  }\n\n  &-wrapper {\n    position: absolute;\n    top: 0;\n    z-index: 1;\n    display: flex;\n    flex-direction: column;\n    min-width: 100px;\n    height: 100%;\n    padding: 24px;\n    padding-right: 0;\n    text-align: left;\n    background-color: var(--color-tertiary-gray-ultra-light);\n    outline: none;\n    box-shadow: -1px -1px 3px rgba(var(--color-rgb-blue), 0.4),\n      1px 1px 3px rgba(var(--color-rgb-white), 0.25);\n\n    &_left {\n      left: 0;\n      box-shadow: 1px 1px 3px rgba(var(--color-rgb-blue), 0.4),\n        -1px -1px 3px rgba(var(--color-rgb-white), 0.25);\n    }\n\n    &_right {\n      right: 0;\n    }\n  }\n\n  &__header {\n    padding-right: 56px;\n    padding-bottom: 32px;\n  }\n\n  &__close {\n    position: absolute;\n    top: 16px;\n    right: 16px;\n    padding: 0;\n    font-size: 32px;\n    color: var(--color-primary-blue);\n    background-color: transparent;\n    border: none;\n\n    &:hover,\n    &:focus {\n      color: var(--color-primary-black);\n      outline: none;\n    }\n  }\n\n  &__title {\n    font-weight: 800;\n    font-size: 20px;\n    line-height: 25px;\n    color: var(--color-primary-black);\n  }\n\n  &__content {\n    padding-right: 24px;\n  }\n}\n"
  },
  {
    "path": "src/qComponents/QForm/index.js",
    "content": "import QForm from './src/QForm';\n\nQForm.install = Vue => {\n  Vue.component(QForm.name, QForm);\n};\n\nexport default QForm;\n"
  },
  {
    "path": "src/qComponents/QForm/src/QForm.vue",
    "content": "<template>\n  <form class=\"q-form\">\n    <slot />\n  </form>\n</template>\n\n<script>\nimport { concat } from 'lodash-es';\n\n/**\n * Form consists of `input`, `radio`, `select`, `checkbox` and so on.\n * With form, you can collect, verify and submit data. You must use QFormItem inside QForm\n */\nexport default {\n  name: 'QForm',\n  componentName: 'QForm',\n\n  provide() {\n    return {\n      qForm: this\n    };\n  },\n\n  props: {\n    /**\n     * data of form component\n     */\n    model: {\n      type: Object,\n      default: () => ({})\n    },\n    /**\n     * validation rules of form.\n     * https://github.com/yiminghe/async-validator#rules\n     */\n    rules: {\n      type: Object,\n      default: () => ({})\n    },\n    /**\n     * whether to disabled all components in this form. If set to true,\n     * it cannot be overridden by its inner components `disabled` prop\n     */\n    disabled: {\n      type: Boolean,\n      default: false\n    },\n    /**\n     * whether required fields should have a red asterisk (star) beside their labels\n     */\n    hideRequiredAsterisk: {\n      type: Boolean,\n      default: false\n    },\n    /**\n     * whether to show the error message\n     */\n    showErrorMessage: {\n      type: Boolean,\n      default: true\n    },\n    /**\n     * whether to trigger validation when the `rules` prop is changed\n     */\n    validateOnRuleChange: {\n      type: Boolean,\n      default: true\n    }\n  },\n\n  data() {\n    return {\n      fields: []\n    };\n  },\n\n  watch: {\n    rules() {\n      if (this.validateOnRuleChange) this.validate();\n    }\n  },\n\n  methods: {\n    /**\n     * @param {?string[]|string} props List of fields props.\n     */\n    filterFields(props) {\n      const preparedProps = concat(props || []);\n\n      return preparedProps.length\n        ? this.fields.filter(({ prop }) => preparedProps.includes(prop))\n        : this.fields;\n    },\n\n    /**\n     * @public\n     * @param {?string[]|string} props List of fields props.\n     */\n    resetFields(props) {\n      if (!this.model) {\n        if (process.env.NODE_ENV !== 'production') {\n          console.warn(\n            '[Warn][QForm] model is required for resetFields to work.'\n          );\n        }\n        return;\n      }\n      const filteredFields = this.filterFields(props);\n\n      filteredFields.forEach(field => {\n        field.resetField();\n      });\n    },\n\n    /**\n     * @public\n     * @param {?string[]|string} props List of fields props.\n     */\n    clearValidate(props) {\n      const filteredFields = this.filterFields(props);\n\n      filteredFields.forEach(field => {\n        field.clearValidate();\n      });\n    },\n\n    /**\n     * @public\n     * @async\n     * @param {?string[]|string} props List of fields props.\n     * @return {Promise<?object>}\n     */\n    async validate(props) {\n      if (!this.model) {\n        if (process.env.NODE_ENV !== 'production') {\n          console.warn('[Warn][QForm] model is required for validate to work!');\n        }\n        return null;\n      }\n\n      const filteredFields = this.filterFields(props);\n\n      let isValid = true;\n      let invalidFields = {};\n\n      await Promise.all(\n        filteredFields.map(async field => {\n          const { errors, fields } = (await field.validateField()) ?? {};\n          if (!errors) return;\n\n          isValid = false;\n          invalidFields = { ...invalidFields, ...fields };\n        })\n      );\n\n      return {\n        isValid,\n        invalidFields\n      };\n    }\n  }\n};\n</script>\n"
  },
  {
    "path": "src/qComponents/QForm/src/q-form.scss",
    "content": ""
  },
  {
    "path": "src/qComponents/QFormItem/index.js",
    "content": "import QFormItem from './src/QFormItem';\n\nQFormItem.install = Vue => {\n  Vue.component(QFormItem.name, QFormItem);\n};\n\nexport default QFormItem;\n"
  },
  {
    "path": "src/qComponents/QFormItem/src/QFormItem.vue",
    "content": "<template>\n  <div\n    class=\"q-form-item\"\n    :class=\"rootClasses\"\n  >\n    <div\n      v-if=\"isHeaderShown\"\n      class=\"q-form-item__header\"\n    >\n      <label\n        v-if=\"label || $slots.label\"\n        :for=\"labelFor\"\n        class=\"q-form-item__label\"\n      >\n        <slot name=\"label\">{{ label }}</slot>\n      </label>\n\n      <div\n        v-if=\"sublabel || $slots.sublabel\"\n        class=\"q-form-item__sublabel\"\n      >\n        <slot name=\"sublabel\">{{ sublabel }}</slot>\n      </div>\n    </div>\n\n    <div class=\"q-form-item__body\">\n      <slot />\n\n      <transition name=\"q-fade-in\">\n        <slot\n          v-if=\"isErrorSlotShown\"\n          name=\"error\"\n          :error=\"errorMessage\"\n        >\n          <div class=\"q-form-item__error\">\n            {{ errorMessage }}\n          </div>\n        </slot>\n      </transition>\n    </div>\n  </div>\n</template>\n\n<script>\nimport AsyncValidator from 'async-validator';\nimport { get, set } from 'lodash-es';\n\nexport default {\n  name: 'QFormItem',\n  componentName: 'QFormItem',\n\n  inject: ['qForm'],\n\n  provide() {\n    return {\n      qFormItem: {\n        validateField: this.validateField\n      }\n    };\n  },\n\n  props: {\n    for: {\n      type: String,\n      default: null\n    },\n    /**\n     * a key of model.In the use of validate and resetFields method,\n     * the attribute is required\n     */\n    prop: {\n      type: String,\n      default: null\n    },\n    /**\n     * label\n     */\n    label: {\n      type: String,\n      default: null\n    },\n    sublabel: {\n      type: String,\n      default: null\n    },\n    /**\n     * field error message, set its value and the field will validate error\n     * and show this message immediately\n     */\n    error: {\n      type: String,\n      default: null\n    },\n    /**\n     * validation rules of form.\n     * https://github.com/yiminghe/async-validator#rules\n     */\n    rules: {\n      type: [Object, Array],\n      default: null\n    },\n    /**\n     * whether to show the error message\n     */\n    showErrorMessage: {\n      type: Boolean,\n      default: true\n    }\n  },\n\n  data() {\n    return {\n      initialValue: null,\n      errorMessage: null\n    };\n  },\n\n  computed: {\n    rootClasses() {\n      return {\n        'q-form-item_is-required': this.isRequired,\n        'q-form-item_is-error': Boolean(this.errorMessage),\n        'q-form-item_is-no-asterisk': this.qForm.hideRequiredAsterisk\n      };\n    },\n\n    isHeaderShown() {\n      return Boolean(\n        this.label || this.$slots.label || this.sublabel || this.$slots.sublabel\n      );\n    },\n\n    isRequired() {\n      const propRules = this.rules || get(this.qForm.rules, this.prop);\n      if (!propRules) return false;\n\n      const preparedPropRules = Array.isArray(propRules)\n        ? propRules\n        : [propRules];\n      return preparedPropRules.some(({ required }) => required);\n    },\n\n    labelFor() {\n      return this.for ?? this.prop;\n    },\n\n    isErrorSlotShown() {\n      return (\n        (this.errorMessage || this.$slots.error) &&\n        this.showErrorMessage &&\n        this.qForm.showErrorMessage\n      );\n    }\n  },\n\n  watch: {\n    error: {\n      immediate: true,\n      handler(value) {\n        this.errorMessage = value;\n      }\n    }\n  },\n\n  mounted() {\n    if (!this.prop) return;\n\n    this.initialValue = get(this.qForm.model, this.prop, null);\n    this.qForm.fields.push(this);\n  },\n\n  beforeDestroy() {\n    const qFormFields = this.qForm.fields;\n    qFormFields.splice(qFormFields.indexOf(this), 1);\n  },\n\n  methods: {\n    /**\n     * @public\n     */\n    resetField() {\n      set(this.qForm.model, this.prop, this.initialValue);\n      this.errorMessage = null;\n    },\n\n    /**\n     * @public\n     */\n    clearValidate() {\n      this.errorMessage = null;\n    },\n\n    getFilteredRules(trigger) {\n      const formRules = this.qForm.rules?.[this.prop] ?? [];\n      const propRules = this.rules || formRules;\n      if (!propRules) return null;\n\n      const preparedPropRules = Array.isArray(propRules)\n        ? propRules\n        : [propRules];\n\n      if (!trigger) {\n        return preparedPropRules.map(({ trigger: _, ...rule }) => rule);\n      }\n\n      return preparedPropRules\n        .filter(rule => {\n          if (!rule?.trigger) return true;\n\n          return [].concat(rule.trigger).includes(trigger);\n        })\n        .map(({ trigger: _, ...rule }) => rule);\n    },\n\n    /**\n     * @public\n     * @async\n     * @param {?string} trigger\n     * @return {Promise}\n     */\n    validateField(trigger = null) {\n      const triggeredRules = this.getFilteredRules(trigger);\n\n      if (!triggeredRules?.length) return null;\n\n      const validator = new AsyncValidator({\n        [this.prop]: triggeredRules\n      });\n\n      return new Promise(resolve => {\n        validator.validate(\n          {\n            [this.prop]: get(this.qForm.model, this.prop)\n          },\n          { firstFields: true },\n          (errors, fields) => {\n            if (!errors) resolve({});\n\n            this.errorMessage = errors?.[0]?.message ?? null;\n            resolve({ errors, fields });\n          }\n        );\n      });\n    }\n  }\n};\n</script>\n"
  },
  {
    "path": "src/qComponents/QFormItem/src/q-form-item.scss",
    "content": ".q-form-item {\n  position: relative;\n\n  &__header {\n    position: relative;\n    z-index: 1;\n    display: flex;\n    align-items: baseline;\n    margin-bottom: 8px;\n  }\n\n  &__label {\n    font-weight: var(--font-weight-base);\n    font-size: var(--font-size-base);\n    line-height: 18px;\n    color: var(--color-primary-black);\n\n    .q-form-item_is-required:not(.q-form-item_is-no-asterisk) &::after {\n      content: '*';\n      margin-left: 4px;\n      color: var(--color-secondary-orange);\n    }\n  }\n\n  &__sublabel {\n    margin-left: auto;\n    font-size: 10px;\n    line-height: 12px;\n    color: rgba(var(--color-rgb-gray), 0.64);\n  }\n\n  &__body {\n    position: relative;\n    padding-bottom: 24px;\n  }\n\n  &__error {\n    position: absolute;\n    top: calc(100% - 16px);\n    right: 0;\n    left: 0;\n    font-size: 10px;\n    line-height: 12px;\n    color: var(--color-secondary-orange);\n  }\n}\n"
  },
  {
    "path": "src/qComponents/QInput/index.js",
    "content": "import QInput from './src/QInput.vue';\n\n/* istanbul ignore next */\nQInput.install = function(Vue) {\n  Vue.component(QInput.name, QInput);\n};\n\nexport default QInput;\n"
  },
  {
    "path": "src/qComponents/QInput/src/QInput.vue",
    "content": "<template>\n  <div\n    :class=\"classes\"\n    @mouseenter=\"hovering = true\"\n    @mouseleave=\"hovering = false\"\n    @click=\"$emit('click')\"\n  >\n    <div\n      v-if=\"isSymbolLimitShown\"\n      class=\"q-input__count\"\n    >\n      <span class=\"q-input__count-inner\">\n        {{ $t('QInput.charNumber') }}: {{ textLength }}/{{ upperLimit }}\n      </span>\n    </div>\n    <input\n      ref=\"input\"\n      :tabindex=\"tabindex\"\n      class=\"q-input__inner\"\n      v-bind=\"$attrs\"\n      :type=\"nativeInputType\"\n      :disabled=\"inputDisabled\"\n      :readonly=\"readonly\"\n      :autocomplete=\"autocomplete\"\n      :aria-label=\"label\"\n      @compositionstart=\"handleCompositionStart\"\n      @compositionend=\"handleCompositionEnd\"\n      @input=\"handleInput\"\n      @focus=\"handleFocus\"\n      @blur=\"handleBlur\"\n      @change=\"handleChange\"\n    />\n    <span\n      v-if=\"isSuffixVisible\"\n      class=\"q-input__suffix\"\n    >\n      <span class=\"q-input__suffix-inner\">\n        <template v-if=\"!isClearButtonShown || !isPasswordShown\">\n          <span\n            v-if=\"suffixIcon\"\n            class=\"q-input__icon\"\n            :class=\"suffixIcon\"\n          />\n          <slot\n            v-else\n            name=\"suffix\"\n          />\n        </template>\n        <span\n          v-if=\"isClearButtonShown\"\n          class=\"q-input__icon q-icon-close\"\n          @click=\"handleClearClick\"\n        />\n        <span\n          v-if=\"isPasswordShown\"\n          class=\"q-input__icon\"\n          :class=\"passwordVisible ? 'q-icon-eye' : 'q-icon-eye-close'\"\n          @click=\"handlePasswordVisible\"\n        />\n      </span>\n    </span>\n  </div>\n</template>\n\n<script>\nimport emitter from '../../mixins/emitter';\nimport inputs from '../../mixins/inputs';\n\nexport default {\n  name: 'QInput',\n  componentName: 'QInput',\n\n  mixins: [emitter, inputs],\n\n  props: {\n    /**\n     * as native input type\n     */\n    type: {\n      type: String,\n      default: 'text',\n      validator: value =>\n        [\n          'text',\n          'password',\n          'number',\n          'email',\n          'hidden',\n          'tel',\n          'url'\n        ].includes(value)\n    },\n\n    /**\n     * as native input autocomplete\n     */\n    autocomplete: {\n      type: String,\n      default: 'off'\n    },\n\n    /**\n     * suffix icon class\n     */\n    suffixIcon: {\n      type: String,\n      default: ''\n    },\n\n    /**\n     * whether to show clear button\n     */\n    clearable: {\n      type: Boolean,\n      default: false\n    },\n\n    /**\n     * whether to show password\n     */\n    showPassword: {\n      type: Boolean,\n      default: false\n    }\n  },\n\n  data() {\n    return {\n      passwordVisible: false\n    };\n  },\n\n  computed: {\n    classes() {\n      const mainClass = 'q-input';\n\n      return [\n        mainClass,\n        {\n          [`${mainClass}_disabled`]: this.inputDisabled,\n          [`${mainClass}_suffix`]: this.isSuffixVisible\n        }\n      ];\n    },\n\n    isPasswordShown() {\n      return (\n        this.showPassword &&\n        !this.inputDisabled &&\n        !this.readonly &&\n        (Boolean(this.nativeInputValue) || this.focused || this.hovering)\n      );\n    },\n\n    nativeInputType() {\n      let type = this.type;\n      if (this.showPassword) {\n        type = this.passwordVisible ? 'text' : 'password';\n      }\n      return type;\n    },\n\n    componentRef() {\n      return this.$refs.input;\n    },\n\n    isSuffixVisible() {\n      return Boolean(\n        this.$slots.suffix ||\n          this.suffixIcon ||\n          this.isClearButtonShown ||\n          this.showPassword\n      );\n    }\n  },\n\n  watch: {\n    value() {\n      if (this.validateEvent) this.qFormItem?.validateField('change');\n    },\n\n    type() {\n      this.$nextTick(() => {\n        this.setNativeInputValue();\n      });\n    }\n  },\n\n  mounted() {\n    this.setNativeInputValue();\n  },\n\n  methods: {\n    handlePasswordVisible() {\n      this.passwordVisible = !this.passwordVisible;\n      this.focus();\n    },\n\n    handleClearClick(event) {\n      this.$emit('input', '');\n      this.$emit('change', '');\n      this.$emit('clear', event);\n    }\n  }\n};\n</script>\n"
  },
  {
    "path": "src/qComponents/QInput/src/q-input.scss",
    "content": ".q-input {\n  --field-color-base: var(--color-primary-black);\n  --field-color-placeholder: rgba(var(--color-rgb-gray), 0.32);\n  --field-color-disabled: rgba(var(--color-rgb-gray), 0.64);\n\n  --field-icon-color-base: var(--color-primary-blue);\n  --field-icon-color-hover: var(--color-primary-black);\n  --field-icon-color-inactive: rgba(var(--color-rgb-gray), 0.64);\n\n  --field-background-color-base: var(--color-tertiary-gray-light);\n  --field-background-color-hover: var(--color-tertiary-gray);\n  --field-background-color-focus: var(--color-tertiary-gray-ultra-light);\n  --field-background-color-disabled: var(--color-tertiary-gray);\n\n  --field-box-shadow-base: -1px -1px 3px rgba(var(--color-rgb-white), 0.25),\n    1px 1px 3px rgba(var(--color-rgb-blue), 0.4),\n    4px 4px 8px rgba(var(--color-rgb-blue), 0.4),\n    -4px -4px 12px var(--color-tertiary-white);\n  --field-box-shadow-hover: -1px -1px 4px rgba(var(--color-rgb-white), 0.25),\n    1px 1px 4px rgba(var(--color-rgb-blue), 0.4),\n    4px 4px 8px rgba(var(--color-rgb-blue), 0.4),\n    -4px -4px 8px rgba(var(--color-rgb-white), 0.8);\n  --field-box-shadow-focus: -1px -1px 3px rgba(var(--color-rgb-white), 0.25),\n    1px 1px 3px rgba(var(--color-rgb-blue), 0.4),\n    inset -1px -1px 1px rgba(var(--color-rgb-white), 0.7),\n    inset 1px 1px 2px rgba(var(--color-rgb-blue), 0.2);\n  --field-box-shadow-disabled: -1px -1px 3px rgba(var(--color-rgb-white), 0.25),\n    1px 1px 3px rgba(var(--color-rgb-blue), 0.4);\n\n  position: relative;\n  display: inline-block;\n  width: 100%;\n\n  &__inner {\n    display: inline-block;\n    width: 100%;\n    height: 40px;\n    padding: 0 16px;\n    font-weight: var(--font-weight-base);\n    font-size: var(--font-size-base);\n    line-height: var(--line-height-base);\n    color: var(--field-color-base);\n    background-color: var(--field-background-color-base);\n    border: none;\n    border-radius: var(--border-radius-base);\n    box-shadow: var(--field-box-shadow-base);\n    appearance: textfield;\n\n    &::-webkit-outer-spin-button,\n    &::-webkit-inner-spin-button {\n      appearance: none;\n      margin: 0;\n    }\n\n    &::placeholder,\n    &:placeholder-shown {\n      color: var(--field-color-placeholder);\n      text-overflow: ellipsis;\n      opacity: 1;\n    }\n\n    /** disable default clear on IE */\n    &::-ms-reveal,\n    &::-ms-clear {\n      display: none;\n      width: 0;\n      height: 0;\n    }\n\n    &:focus {\n      background-color: var(--field-background-color-focus);\n      outline: none;\n      box-shadow: var(--field-box-shadow-focus);\n    }\n\n    &:hover {\n      background-color: var(--field-background-color-hover);\n      box-shadow: var(--field-box-shadow-hover);\n    }\n\n    .q-form-item_is-error & {\n      &,\n      &:focus {\n        padding-left: 15px;\n        border: var(--border-error);\n      }\n    }\n  }\n\n  &_focus {\n    .q-input__inner {\n      background-color: var(--field-background-color-focus);\n      outline: none;\n      box-shadow: var(--field-box-shadow-focus);\n    }\n  }\n\n  &_disabled {\n    &::after {\n      content: '\\e930';\n      position: absolute;\n      top: 0;\n      right: 8px;\n      font-size: 24px;\n      line-height: 40px;\n      font-family: 'qicon';\n      cursor: not-allowed;\n    }\n\n    .q-input__inner {\n      padding-right: 40px;\n      color: var(--field-color-disabled);\n      background-color: var(--field-background-color-disabled);\n      box-shadow: var(--field-box-shadow-disabled);\n      cursor: not-allowed;\n    }\n  }\n\n  &_suffix {\n    .q-input__inner {\n      padding-right: 40px;\n    }\n  }\n\n  &__suffix {\n    position: absolute;\n    top: 0;\n    right: 0;\n    width: 40px;\n    height: 100%;\n    text-align: center;\n    transition: all 0.3s;\n    pointer-events: none;\n\n    .q-input.q-input_disabled & {\n      display: none;\n    }\n  }\n\n  &__suffix-inner {\n    display: block;\n    pointer-events: all;\n  }\n\n  &__icon {\n    width: 40px;\n    text-align: center;\n    color: var(--field-icon-color-inactive);\n\n    &_reverse {\n      color: var(--field-icon-color-base);\n    }\n\n    &:not(:last-child) {\n      display: none;\n    }\n\n    &::before {\n      font-size: 24px;\n      line-height: 40px;\n    }\n\n    &.q-icon-close,\n    &.q-icon-eye-close,\n    &.q-icon-eye {\n      color: var(--field-icon-color-base);\n    }\n\n    &.q-icon-close,\n    &.q-icon-eye,\n    &.q-icon-eye-close {\n      cursor: pointer;\n\n      &::before {\n        font-family: 'qicon';\n      }\n\n      &:focus,\n      &:hover {\n        color: var(--field-icon-color-hover);\n      }\n    }\n  }\n\n  &__count {\n    position: absolute;\n    top: -24px;\n    right: 0;\n    margin-bottom: 2px;\n    font-size: 10px;\n    text-align: right;\n  }\n}\n"
  },
  {
    "path": "src/qComponents/QInputNumber/QInputNumber.test.js",
    "content": "import Component from './src/QInputNumber';\n\ndescribe('QInputNumber', () => {\n  it('should match snapshot', () => {\n    const { element } = shallowMount(Component);\n\n    expect(element).toMatchSnapshot();\n  });\n\n  it('should match snapshot without controls', () => {\n    const { element } = shallowMount(Component, {\n      propsData: {\n        controls: false\n      }\n    });\n\n    expect(element).toMatchSnapshot();\n  });\n\n  it('data should match snapshot', () => {\n    expect(Component.data()).toMatchSnapshot();\n  });\n});\n"
  },
  {
    "path": "src/qComponents/QInputNumber/__snapshots__/QInputNumber.test.js.snap",
    "content": "// Jest Snapshot v1, https://goo.gl/fbAQLP\n\nexports[`QInputNumber data should match snapshot 1`] = `\nObject {\n  \"number\": null,\n  \"prevNumber\": null,\n  \"userNumber\": null,\n}\n`;\n\nexports[`QInputNumber should match snapshot 1`] = `\n<div\n  class=\"q-input-number q-input-number_with-controls\"\n>\n  <button\n    class=\"q-input-number__button_decrease q-input-number__button q-icon-minus\"\n  />\n   \n  <q-input-stub\n    autocomplete=\"off\"\n    class=\"q-input-number__input\"\n    label=\"\"\n    suffixicon=\"\"\n    tabindex=\"\"\n    type=\"number\"\n    value=\"\"\n  />\n   \n  <button\n    class=\"q-input-number__button_increase q-input-number__button q-icon-plus\"\n  />\n</div>\n`;\n\nexports[`QInputNumber should match snapshot without controls 1`] = `\n<div\n  class=\"q-input-number\"\n>\n  <!---->\n   \n  <q-input-stub\n    autocomplete=\"off\"\n    class=\"q-input-number__input\"\n    label=\"\"\n    suffixicon=\"\"\n    tabindex=\"\"\n    type=\"number\"\n    value=\"\"\n  />\n   \n  <!---->\n</div>\n`;\n"
  },
  {
    "path": "src/qComponents/QInputNumber/index.js",
    "content": "import QInputNumber from './src/QInputNumber.vue';\n\n/* istanbul ignore next */\nQInputNumber.install = function(Vue) {\n  Vue.component(QInputNumber.name, QInputNumber);\n};\n\nexport default QInputNumber;\n"
  },
  {
    "path": "src/qComponents/QInputNumber/src/QInputNumber.vue",
    "content": "<template>\n  <div\n    class=\"q-input-number\"\n    :class=\"withControlsClass\"\n  >\n    <button\n      v-if=\"controls\"\n      class=\"q-input-number__button_decrease q-input-number__button q-icon-minus\"\n      :disabled=\"isDisabled\"\n      :class=\"decreaseClass\"\n      @click.prevent=\"handleDecreaseClick\"\n    />\n\n    <q-input\n      :value=\"currentValue\"\n      class=\"q-input-number__input\"\n      :disabled=\"isDisabled\"\n      :placeholder=\"placeholder\"\n      :validate-event=\"false\"\n      type=\"number\"\n      @blur=\"handleBlur\"\n      @focus=\"handleFocus\"\n      @input=\"handleChangeInput($event, 'input')\"\n      @change=\"handleChangeInput($event, 'change')\"\n    />\n\n    <button\n      v-if=\"controls\"\n      class=\"q-input-number__button_increase q-input-number__button q-icon-plus\"\n      :disabled=\"isDisabled\"\n      :class=\"increaseClass\"\n      @click.prevent=\"handleIncreaseClick\"\n    />\n  </div>\n</template>\n\n<script>\nexport default {\n  name: 'QInputNumber',\n  componentName: 'QInputNumber',\n\n  inject: {\n    qForm: {\n      default: null\n    },\n    qFormItem: {\n      default: null\n    }\n  },\n\n  props: {\n    /**\n     * the minimum allowed value\n     */\n    min: {\n      type: Number,\n      default: Number.MIN_SAFE_INTEGER\n    },\n\n    /**\n     * the maximum allowed value\n     */\n    max: {\n      type: Number,\n      default: Number.MAX_SAFE_INTEGER\n    },\n\n    /**\n     * incremental step\n     */\n    step: {\n      type: Number,\n      default: 1\n    },\n\n    /**\n     * precision of input value\n     */\n    precision: {\n      type: Number,\n      default: 0\n    },\n    /**\n     * whether the component is disabled\n     */\n    disabled: {\n      type: Boolean,\n      default: false\n    },\n    /**\n     * whether to enable the control buttons\n     */\n    controls: {\n      type: Boolean,\n      default: true\n    },\n    placeholder: {\n      type: String,\n      default: null\n    },\n    value: {\n      type: [Number, String],\n      default: null,\n      validator: value => {\n        if (!Number.isNaN(Number(value)) || value === null) return true;\n\n        return false;\n      }\n    },\n    validateEvent: {\n      type: Boolean,\n      default: true\n    }\n  },\n\n  data() {\n    return {\n      number: null,\n      userNumber: null,\n      prevNumber: null\n    };\n  },\n\n  computed: {\n    isDisabled() {\n      return this.disabled || (this.qForm?.disabled ?? false);\n    },\n\n    withControlsClass() {\n      return { 'q-input-number_with-controls': this.controls };\n    },\n\n    increaseClass() {\n      if (this.number >= this.max) {\n        return 'q-input-number__button_is-disabled';\n      }\n\n      return '';\n    },\n\n    decreaseClass() {\n      if (this.number <= this.min) {\n        return 'q-input-number__button_is-disabled';\n      }\n\n      return '';\n    },\n\n    currentValue() {\n      return (this.userNumber ?? this.number ?? '').toString();\n    }\n  },\n\n  watch: {\n    value: {\n      handler(value) {\n        this.number = value === null ? null : Number(value);\n      },\n      immediate: true\n    }\n  },\n\n  methods: {\n    handleIncreaseClick() {\n      const updatedNumber = Math.round((this.number + this.step) * 100) / 100;\n\n      if (updatedNumber > this.max) return;\n\n      this.userNumber = updatedNumber;\n      this.changesEmmiter(updatedNumber, 'change');\n    },\n\n    handleDecreaseClick() {\n      const updatedNumber = Math.round((this.number - this.step) * 100) / 100;\n\n      if (updatedNumber < this.min) return;\n\n      this.userNumber = updatedNumber;\n      this.changesEmmiter(updatedNumber, 'change');\n    },\n\n    handleBlur(event) {\n      this.$emit('blur', event);\n      if (this.validateEvent) this.qFormItem?.validateField('blur');\n    },\n\n    handleFocus(event) {\n      this.$emit('focus', event);\n    },\n\n    handleChangeInput(value, type) {\n      if (!value) {\n        this.userNumber = value;\n        this.changesEmmiter(null, type);\n        return;\n      }\n\n      this.processUserValue(value, type);\n    },\n\n    processUserValue(value, type) {\n      const userValue = Number(value);\n      this.userNumber = null;\n\n      if (Number.isNaN(userValue) || value > this.max || value < this.min) {\n        return;\n      }\n\n      this.prevNumber = userValue;\n\n      if (type === 'change') {\n        this.changesEmmiter(userValue, type);\n        return;\n      }\n\n      this.$emit('input', Number(userValue.toFixed(this.precision)));\n      if (this.validateEvent) this.qFormItem?.validateField('input');\n    },\n\n    changesEmmiter(value, type) {\n      let passedData = null;\n\n      if (value) {\n        this.number = Number(value.toFixed(this.precision));\n        passedData = this.number;\n      }\n\n      this.prevNumber = passedData;\n\n      if (type === 'change') {\n        this.$emit('input', passedData);\n        this.$emit('change', passedData);\n        if (this.validateEvent) this.qFormItem?.validateField('change');\n        return;\n      }\n\n      this.$emit('input', passedData);\n      if (this.validateEvent) this.qFormItem?.validateField('input');\n    }\n  }\n};\n</script>\n"
  },
  {
    "path": "src/qComponents/QInputNumber/src/q-input-number.scss",
    "content": ".q-input-number {\n  position: relative;\n  display: inline-block;\n  width: 100%;\n  line-height: 40px;\n\n  &_with-controls {\n    width: 160px;\n\n    & .q-input__inner {\n      box-sizing: border-box;\n      padding: 0 34px;\n      text-align: center;\n    }\n  }\n\n  &__button {\n    position: absolute;\n    top: 0;\n    right: 0;\n    z-index: 1;\n    width: 32px;\n    height: 40px;\n    font-size: 16px;\n    color: rgba(var(--color-rgb-gray), 0.64);\n    background-color: transparent;\n    border: none;\n    border-radius: var(--border-radius-base);\n    outline: none;\n    cursor: pointer;\n\n    &_decrease {\n      right: auto;\n      left: 0;\n    }\n\n    &:enabled:not(.q-input-number__button_is-disabled) {\n      &:hover::before,\n      &:focus::before {\n        background-color: rgba(var(--color-rgb-gray), 0.16);\n        border-radius: 16px;\n        outline: none;\n      }\n\n      &:focus::before {\n        color: var(--color-primary-black);\n      }\n    }\n\n    &[disabled]:hover {\n      cursor: not-allowed;\n    }\n\n    &_is-disabled {\n      color: rgba(var(--color-rgb-gray), 0.16);\n      cursor: not-allowed;\n    }\n  }\n\n  &__input {\n    &.q-input_disabled::after {\n      display: none;\n    }\n  }\n}\n"
  },
  {
    "path": "src/qComponents/QMessageBox/QMessageBox.test.js",
    "content": "import Component from './src/QMessageBox.vue';\n\ndescribe('QMessageBox', () => {\n  it('should match snapshot', async () => {\n    const instance = shallowMount(Component, {\n      stubs: ['message-box-content']\n    });\n\n    await instance.setData({\n      isShown: true\n    });\n\n    expect(instance.element).toMatchSnapshot();\n  });\n\n  it('data should match snapshot', () => {\n    expect(Component.data()).toMatchSnapshot();\n  });\n});\n"
  },
  {
    "path": "src/qComponents/QMessageBox/__snapshots__/QMessageBox.test.js.snap",
    "content": "// Jest Snapshot v1, https://goo.gl/fbAQLP\n\nexports[`QMessageBox data should match snapshot 1`] = `\nObject {\n  \"callback\": null,\n  \"elementToFocusAfterClosing\": null,\n  \"isCancelBtnLoading\": false,\n  \"isComponentUsed\": false,\n  \"isConfirmBtnLoading\": false,\n  \"isShown\": false,\n}\n`;\n\nexports[`QMessageBox should match snapshot 1`] = `\n<transition-stub\n  name=\"q-msgbox-fade\"\n>\n  <div\n    class=\"q-message-box\"\n    tabindex=\"-1\"\n  >\n    <div\n      class=\"q-message-box__shadow\"\n    />\n     \n    <q-scrollbar-stub\n      class=\"q-message-box__scrollbar\"\n      theme=\"secondary\"\n      viewclass=\"q-message-box__view\"\n      viewtag=\"div\"\n      visible=\"true\"\n      wrapclass=\"\"\n    >\n      <div\n        class=\"q-message-box__clickable-shadow\"\n      />\n       \n      <div\n        class=\"q-message-box__container\"\n      >\n        <div\n          class=\"q-message-box__title\"\n        >\n          \n          \n        \n        </div>\n         \n        <button\n          class=\"q-message-box__close q-icon-close\"\n        />\n         \n        <div\n          class=\"q-message-box__content\"\n        >\n          <!---->\n           \n          <!---->\n        </div>\n         \n        <!---->\n      </div>\n    </q-scrollbar-stub>\n  </div>\n</transition-stub>\n`;\n"
  },
  {
    "path": "src/qComponents/QMessageBox/index.js",
    "content": "import QMessageBox from './src/QMessageBox.js';\n\nexport default QMessageBox;\n"
  },
  {
    "path": "src/qComponents/QMessageBox/src/QMessageBox.js",
    "content": "import Vue from 'vue';\n\nimport QMessageBox from './QMessageBox.vue';\n\nlet currentPromise;\n\nconst defaultCallback = ({ action, payload }) => {\n  if (action === 'confirm') {\n    currentPromise.resolve({ action, payload });\n  } else if (action === 'cancel' || action === 'close') {\n    currentPromise.reject({ action });\n  }\n};\n\nconst Message = function(config = {}) {\n  const MessageBox = Vue.extend({\n    components: {\n      MessageBoxContent: config.component\n    },\n    ...QMessageBox\n  });\n\n  const instance = new MessageBox();\n\n  Object.entries(config).forEach(([key, value]) => {\n    instance[key] = value;\n  });\n\n  if (!instance.zIndex) {\n    instance.zIndex = Vue.prototype.$Q?.zIndex ?? 2000;\n  }\n\n  instance.callback = defaultCallback;\n\n  instance.isComponentUsed = Boolean(config.component);\n\n  if (\n    config.message &&\n    !instance.isComponentUsed &&\n    Object.prototype.hasOwnProperty.call(config.message, 'componentOptions')\n  ) {\n    instance.$slots.default = [config.message];\n    instance.message = null;\n  } else {\n    delete instance.$slots.default;\n  }\n\n  document.body.appendChild(instance.$mount().$el);\n\n  Vue.nextTick(() => {\n    instance.isShown = true;\n  });\n\n  return new Promise((resolve, reject) => {\n    currentPromise = {\n      resolve,\n      reject\n    };\n  });\n};\n\nexport default Message;\n"
  },
  {
    "path": "src/qComponents/QMessageBox/src/QMessageBox.vue",
    "content": "<template>\n  <transition\n    name=\"q-msgbox-fade\"\n    @after-leave=\"handleHookAfterLeave\"\n  >\n    <div\n      v-if=\"isShown\"\n      ref=\"messageBox\"\n      class=\"q-message-box\"\n      :class=\"wrapClass\"\n      :style=\"[wrapStyle, { zIndex }]\"\n      tabindex=\"-1\"\n      @keyup.esc=\"closeBox\"\n    >\n      <div class=\"q-message-box__shadow\" />\n      <q-scrollbar\n        theme=\"secondary\"\n        class=\"q-message-box__scrollbar\"\n        view-class=\"q-message-box__view\"\n        visible\n      >\n        <div\n          v-if=\"closeOnClickShadow\"\n          class=\"q-message-box__clickable-shadow\"\n          @click=\"emitCloseEvent\"\n        />\n\n        <div class=\"q-message-box__container\">\n          <div class=\"q-message-box__title\">\n            {{ title }}\n          </div>\n\n          <button\n            class=\"q-message-box__close q-icon-close\"\n            @click=\"emitCloseEvent\"\n          />\n\n          <message-box-content\n            v-if=\"isComponentUsed\"\n            v-bind=\"componentProps\"\n            @close=\"closeBox\"\n          />\n          <template v-else>\n            <div class=\"q-message-box__content\">\n              <slot>\n                <template v-if=\"message\">\n                  <div\n                    v-if=\"!dangerouslyUseHTMLString\"\n                    class=\"q-message-box__message\"\n                  >\n                    {{ message }}\n                  </div>\n                  <div\n                    v-else\n                    class=\"q-message-box__message\"\n                    v-html=\"message\"\n                  />\n                </template>\n              </slot>\n\n              <div\n                v-if=\"submessage\"\n                class=\"q-message-box__submessage\"\n              >\n                {{ submessage }}\n              </div>\n            </div>\n\n            <div\n              v-if=\"isActionsSectionShown\"\n              class=\"q-message-box__actions\"\n            >\n              <q-button\n                v-if=\"confirmButtonText\"\n                :loading=\"isConfirmBtnLoading\"\n                :disabled=\"isCancelBtnLoading\"\n                @click=\"handleConfirmBtnClick\"\n              >\n                {{ confirmButtonText }}\n              </q-button>\n\n              <q-button\n                v-if=\"cancelButtonText\"\n                theme=\"secondary\"\n                :loading=\"isCancelBtnLoading\"\n                :disabled=\"isConfirmBtnLoading\"\n                @click=\"handleCancelBtnClick\"\n              >\n                {{ cancelButtonText }}\n              </q-button>\n            </div>\n          </template>\n        </div>\n      </q-scrollbar>\n    </div>\n  </transition>\n</template>\n\n<script>\nexport default {\n  name: 'QMessageBox',\n  componentName: 'QMessageBox',\n\n  props: {\n    /**\n     * z-index of the QMessageBox\n     */\n    zIndex: {\n      type: Number,\n      default: null\n    },\n    /**\n     * title of the QMessageBox\n     */\n    title: {\n      type: String,\n      default: ''\n    },\n    /**\n     * content of the QMessageBox\n     */\n    message: {\n      type: String,\n      default: ''\n    },\n    /**\n     * subcontent of the QMessageBox\n     */\n    submessage: {\n      type: String,\n      default: ''\n    },\n    /**\n     * whether message is treated as HTML string\n     */\n    dangerouslyUseHTMLString: {\n      type: Boolean,\n      default: false\n    },\n    /**\n     * text content of confirm button\n     */\n    confirmButtonText: {\n      type: String,\n      default: null\n    },\n    /**\n     * text content of cancel button\n     */\n    cancelButtonText: {\n      type: String,\n      default: null\n    },\n    /**\n     * whether QMessageBox can be closed by clicking the mask\n     */\n    closeOnClickShadow: {\n      type: Boolean,\n      default: true\n    },\n    /**\n     * whether to distinguish canceling and closing the QMessageBox\n     */\n    distinguishCancelAndClose: {\n      type: Boolean,\n      default: false\n    },\n    /**\n     * callback before QMessageBox closes, and it will prevent QMessageBox from closing\n     */\n    beforeClose: {\n      type: Function,\n      default: null\n    },\n    /**\n     * pass props to child component\n     */\n    componentProps: {\n      type: Object,\n      default: () => ({})\n    },\n    /**\n     * class list of the QMessageBox\n     */\n    wrapClass: {\n      type: [String, Object, Array],\n      default: null\n    },\n    /**\n     * style list of the QMessageBox\n     */\n    wrapStyle: {\n      type: [String, Object, Array],\n      default: null\n    }\n  },\n\n  data() {\n    return {\n      isComponentUsed: false,\n      isShown: false,\n      isConfirmBtnLoading: false,\n      isCancelBtnLoading: false,\n      callback: null,\n      elementToFocusAfterClosing: null\n    };\n  },\n\n  computed: {\n    isActionsSectionShown() {\n      return Boolean(this.confirmButtonText) || Boolean(this.cancelButtonText);\n    }\n  },\n\n  watch: {\n    isShown(value) {\n      if (!value) return;\n\n      this.elementToFocusAfterClosing = document.activeElement;\n      this.$nextTick(() => {\n        this.$refs.messageBox.focus();\n      });\n    }\n  },\n\n  mounted() {\n    document.documentElement.style.overflow = 'hidden';\n    document.addEventListener('focus', this.handleDocumentFocus, true);\n  },\n\n  beforeDestroy() {\n    document.documentElement.style.overflow = '';\n\n    const el = this.$el;\n    if (el?.parentNode === document.body) {\n      document.body.removeChild(el);\n    }\n  },\n\n  methods: {\n    handleDocumentFocus(event) {\n      if (!this.$refs.messageBox.contains(event.target)) {\n        this.$refs.messageBox.focus();\n      }\n    },\n\n    handleHookAfterLeave() {\n      this.$destroy();\n    },\n\n    async closeBox({ action, payload = null }) {\n      let isReadyToClose = true;\n\n      if (typeof this.beforeClose === 'function') {\n        isReadyToClose = await this.beforeClose({ action, payload, ctx: this });\n      }\n\n      if (isReadyToClose) {\n        this.callback({ action, payload });\n        this.isShown = false;\n\n        document.removeEventListener('focus', this.handleDocumentFocus, true);\n        this.$nextTick(() => {\n          this.elementToFocusAfterClosing?.focus();\n        });\n      }\n    },\n\n    handleConfirmBtnClick() {\n      this.closeBox({ action: 'confirm' });\n    },\n\n    handleCancelBtnClick() {\n      this.closeBox({ action: 'cancel' });\n    },\n\n    emitCloseEvent() {\n      this.closeBox({\n        action: this.distinguishCancelAndClose ? 'close' : 'cancel'\n      });\n    }\n  }\n};\n</script>\n"
  },
  {
    "path": "src/qComponents/QMessageBox/src/q-message-box.scss",
    "content": ".q-message-box {\n  --message-box-indent: 32px;\n  --message-box-container-width: 488px;\n\n  position: fixed;\n  top: 0;\n  right: 0;\n  bottom: 0;\n  left: 0;\n\n  &__scrollbar {\n    width: 100%;\n  }\n\n  &__view {\n    position: relative;\n    display: flex;\n    justify-content: center;\n    align-items: center;\n\n    .q-message-box__scrollbar:not(.q-scrollbar_has-vertical-bar) & {\n      align-items: center;\n    }\n  }\n\n  &__shadow,\n  &__clickable-shadow {\n    position: absolute;\n    top: 0;\n    left: 0;\n  }\n\n  &__shadow {\n    width: calc(100% + 20px);\n    height: calc(100% + 20px);\n    background-color: rgba(var(--color-rgb-white), 0.7);\n  }\n\n  &__clickable-shadow {\n    width: 100%;\n    height: 100%;\n  }\n\n  &__container {\n    position: relative;\n    display: flex;\n    flex-direction: column;\n    width: var(--message-box-container-width);\n    margin-top: 80px;\n    margin-bottom: 80px;\n    background-color: var(--color-tertiary-gray-ultra-light);\n    border-radius: var(--border-radius-base);\n    box-shadow: 0 100px 384px rgba(var(--color-rgb-gray), 0.07),\n      0 41px 162px rgba(var(--color-rgb-gray), 0.05),\n      0 22px 85px rgba(var(--color-rgb-gray), 0.04),\n      0 12px 48px rgba(var(--color-rgb-gray), 0.03),\n      0 7px 25px rgba(var(--color-rgb-gray), 0.03),\n      0 3px 10px rgba(var(--color-rgb-gray), 0.02);\n  }\n\n  &__close {\n    position: absolute;\n    top: 16px;\n    right: 16px;\n    padding: 0;\n    font-size: 32px;\n    color: var(--color-primary-blue);\n    background-color: transparent;\n    border: none;\n\n    &:hover,\n    &:focus {\n      color: var(--color-primary-black);\n      outline: none;\n    }\n  }\n\n  &__title {\n    margin: var(--message-box-indent) calc(var(--message-box-indent) * 2)\n      calc(var(--message-box-indent) / 2) var(--message-box-indent);\n    font-weight: var(--font-weight-bold);\n    font-size: 16px;\n    line-height: var(--line-height-base);\n    color: var(--color-primary-black);\n    word-break: break-word;\n  }\n\n  &__content {\n    padding-right: var(--message-box-indent);\n    padding-left: var(--message-box-indent);\n\n    &:last-child {\n      margin-bottom: 32px;\n    }\n  }\n\n  &__message,\n  &__submessage {\n    font-weight: var(--font-weight-base);\n    font-size: var(--font-size-base);\n    line-height: var(--line-height-base);\n    word-break: break-word;\n  }\n\n  &__message {\n    color: var(--color-primary-black);\n  }\n\n  &__submessage {\n    margin-top: 24px;\n    color: rgba(var(--color-rgb-gray), 0.64);\n  }\n\n  &__actions {\n    display: flex;\n    margin-top: 32px;\n    margin-bottom: 24px;\n    padding-left: var(--message-box-indent);\n  }\n}\n\n.q-msgbox-fade-enter-active {\n  animation: q-msgbox-fade-in 0.3s;\n}\n\n.q-msgbox-fade-leave-active {\n  animation: q-msgbox-fade-out 0.3s;\n}\n\n@keyframes q-msgbox-fade-in {\n  0% {\n    transform: translate3d(0, -20px, 0);\n    opacity: 0;\n  }\n\n  100% {\n    transform: translate3d(0, 0, 0);\n    opacity: 1;\n  }\n}\n\n@keyframes q-msgbox-fade-out {\n  0% {\n    transform: translate3d(0, 0, 0);\n    opacity: 1;\n  }\n\n  100% {\n    transform: translate3d(0, -20px, 0);\n    opacity: 0;\n  }\n}\n"
  },
  {
    "path": "src/qComponents/QNotification/index.js",
    "content": "import QNotification from './src/QNotification.js';\n\nexport default QNotification;\n"
  },
  {
    "path": "src/qComponents/QNotification/src/QNotification.js",
    "content": "import Vue from 'vue';\n\nimport QNotification from './QNotification.vue';\n\nconst instances = [];\nlet instancesCounter = 1;\n\nconst parent = document.createElement('div');\nparent.className = 'q-notification-box';\n\nconst Notification = (config = {}) => {\n  instancesCounter += 1;\n  const id = `notification_${instancesCounter}`;\n\n  const NotificationConstructor = Vue.extend(QNotification);\n  const instance = new NotificationConstructor();\n\n  Object.entries(config).forEach(([key, value]) => {\n    instance[key] = value;\n  });\n\n  instance.id = id;\n  instance.onClose = () => {\n    Notification.close(id, config.onClose);\n  };\n\n  if (\n    config.message &&\n    Object.prototype.hasOwnProperty.call(config.message, 'componentOptions')\n  ) {\n    instance.$slots.default = [config.message];\n    instance.message = null;\n  } else {\n    delete instance.$slots.default;\n  }\n\n  parent.style.zIndex = Vue.prototype.$Q?.zIndex + 1 ?? 2000;\n  document.body.appendChild(parent);\n  parent.appendChild(instance.$mount().$el);\n\n  Vue.nextTick(() => {\n    instance.isShown = true;\n  });\n\n  instances.push(instance);\n  return instance;\n};\n\nNotification.close = (instanceId, onClose) => {\n  if (typeof onClose === 'function') onClose();\n\n  const foundInstanceIndex = instances.findIndex(({ id }) => id === instanceId);\n  instances.splice(foundInstanceIndex, 1);\n};\n\nNotification.closeAll = () => {\n  for (let i = instances.length - 1; i >= 0; i -= 1) {\n    instances[i].close();\n  }\n};\n\nexport default Notification;\n"
  },
  {
    "path": "src/qComponents/QNotification/src/QNotification.vue",
    "content": "<template>\n  <transition\n    name=\"q-notification-fade\"\n    @after-leave=\"handleHookAfterLeave\"\n  >\n    <div\n      v-if=\"isShown\"\n      class=\"q-notification\"\n      :class=\"notificationClasses\"\n      @mouseenter=\"clearTimer\"\n      @mouseleave=\"startTimer\"\n    >\n      <div\n        class=\"q-notification__icon\"\n        :class=\"[iconClass]\"\n      />\n\n      <div class=\"q-notification__content\">\n        <slot>\n          <template v-if=\"message\">\n            <template v-if=\"!dangerouslyUseHTMLString\">\n              {{ message }}\n            </template>\n            <div\n              v-else\n              v-html=\"message\"\n            />\n          </template>\n        </slot>\n      </div>\n\n      <button\n        type=\"button\"\n        class=\"q-notification__close q-icon-close\"\n        @click=\"close\"\n      />\n    </div>\n  </transition>\n</template>\n\n<script>\nexport default {\n  name: 'QNotification',\n  componentName: 'QNotification',\n\n  props: {\n    /**\n     * description text\n     */\n    message: {\n      type: String,\n      default: ''\n    },\n    /**\n     * notification type\n     */\n    type: {\n      type: String,\n      default: null,\n      validator: value =>\n        ['success', 'warning', 'info', 'error'].includes(value)\n    },\n    /**\n     * whether message is treated as HTML string\n     */\n    dangerouslyUseHTMLString: {\n      type: Boolean,\n      default: false\n    },\n    /**\n     * icon class\n     */\n    icon: {\n      type: String,\n      default: null\n    },\n    /**\n     * duration before close\n     */\n    duration: {\n      type: Number,\n      default: 4500\n    },\n    /**\n     * callback function when closed\n     */\n    onClose: {\n      type: Function,\n      default: null\n    }\n  },\n\n  data() {\n    return {\n      isShown: false,\n      timer: null\n    };\n  },\n\n  computed: {\n    notificationClasses() {\n      return {\n        [`q-notification_type_${this.type}`]: Boolean(this.type)\n      };\n    },\n\n    iconClass() {\n      if (this.icon) return this.icon;\n\n      switch (this.type) {\n        case 'success':\n          return 'q-icon-check';\n\n        case 'warning':\n        case 'error':\n          return 'q-icon-attention-mark';\n\n        default:\n        case 'info':\n          return 'q-icon-info';\n      }\n    }\n  },\n\n  mounted() {\n    this.startTimer();\n  },\n\n  beforeDestroy() {\n    const el = this.$el;\n    if (el?.parentNode) {\n      el.parentNode.removeChild(el);\n    }\n\n    this.clearTimer();\n  },\n\n  methods: {\n    clearTimer() {\n      if (this.timer) clearTimeout(this.timer);\n    },\n\n    startTimer() {\n      if (this.duration > 0) {\n        this.timer = setTimeout(this.close, this.duration);\n      }\n    },\n\n    handleHookAfterLeave() {\n      this.$destroy();\n    },\n\n    /**\n     * @public\n     */\n    close() {\n      if (typeof this.onClose === 'function') this.onClose();\n\n      this.isShown = false;\n    }\n  }\n};\n</script>\n"
  },
  {
    "path": "src/qComponents/QNotification/src/q-notification.scss",
    "content": ".q-notification-box {\n  position: fixed;\n  top: 16px;\n  right: 16px;\n}\n\n.q-notification {\n  position: relative;\n  display: flex;\n  align-items: center;\n  width: 552px;\n  min-height: 88px;\n  padding-top: 24px;\n  padding-bottom: 24px;\n  overflow: hidden;\n  background-color: var(--color-tertiary-gray-ultra-light);\n  border-radius: var(--border-radius-base);\n  box-shadow: var(--box-shadow-pressed);\n  transition: opacity 0.3s, transform 0.3s;\n\n  &:not(:first-child) {\n    margin-top: 16px;\n  }\n\n  &__icon {\n    position: absolute;\n    top: 28px;\n    left: 24px;\n    font-size: 32px;\n\n    .q-notification_type_success & {\n      color: var(--color-secondary-green);\n    }\n\n    .q-notification_type_warning & {\n      color: var(--color-secondary-yellow);\n    }\n\n    .q-notification_type_info & {\n      color: rgba(var(--color-rgb-gray), 32);\n    }\n\n    .q-notification_type_error & {\n      color: var(--color-secondary-orange);\n    }\n  }\n\n  &__content {\n    padding-right: 56px;\n    padding-left: 80px;\n    font-weight: var(--font-weight-base);\n    font-size: var(--font-size-base);\n    line-height: var(--line-height-base);\n    color: var(--color-primary-black);\n    letter-spacing: var(--letter-spacing-base);\n  }\n\n  &__close {\n    position: absolute;\n    top: 32px;\n    right: 16px;\n    padding: 0;\n    font-size: 24px;\n    color: var(--color-primary-blue);\n    background-color: transparent;\n    border: none;\n\n    &:hover,\n    &:focus {\n      color: var(--color-primary-black);\n      outline: none;\n    }\n  }\n}\n\n.q-notification-fade-enter {\n  transform: translateX(100%);\n  opacity: 0;\n}\n\n.q-notification-fade-leave-active {\n  animation: q-notification-fade-out 0.3s;\n}\n\n@keyframes q-notification-fade-out {\n  0% {\n    transform: translateX(0);\n    opacity: 1;\n  }\n\n  100% {\n    transform: translateX(100%);\n\n    opacity: 0;\n  }\n}\n"
  },
  {
    "path": "src/qComponents/QOption/index.js",
    "content": "import QOption from './src/QOption';\n\nQOption.install = function(Vue) {\n  Vue.component(QOption.name, QOption);\n};\n\nexport default QOption;\n"
  },
  {
    "path": "src/qComponents/QOption/src/QOption.vue",
    "content": "<template>\n  <div\n    v-show=\"isVisible\"\n    class=\"q-option\"\n    :class=\"{\n      'q-option_selected': isSelected,\n      'q-option_disabled': isDisabled,\n      'q-option_with-checkbox': qSelect.multiple\n    }\"\n    :tabindex=\"isDisabled ? null : '-1'\"\n    @mouseenter=\"handleMouseEnter\"\n    @click.stop=\"handleOptionClick\"\n  >\n    <q-checkbox\n      v-if=\"qSelect.multiple\"\n      root-tag=\"div\"\n      input-tab-index=\"-1\"\n      :value=\"isSelected\"\n      :disabled=\"isDisabled\"\n    />\n\n    <slot>\n      <div class=\"q-option__label\">{{ preparedLabel }}</div>\n    </slot>\n\n    <span\n      v-if=\"isDisabled\"\n      class=\"q-icon-lock q-option__lock\"\n    />\n  </div>\n</template>\n\n<script>\nimport { isObject, isEqual, get } from 'lodash-es';\n\nexport default {\n  name: 'QOption',\n  componentName: 'QOption',\n\n  inject: ['qSelect'],\n\n  props: {\n    value: {\n      type: [Object, String, Number],\n      required: true\n    },\n    label: {\n      type: [String, Number],\n      default: ''\n    },\n    created: {\n      type: Boolean,\n      default: false\n    },\n    disabled: {\n      type: Boolean,\n      default: false\n    }\n  },\n\n  computed: {\n    key() {\n      return isObject(this.value)\n        ? get(this.value, this.qSelect.valueKey)\n        : this.value;\n    },\n\n    preparedLabel() {\n      return String(this.label ?? this.key);\n    },\n\n    isVisible() {\n      const { remote, query } = this.qSelect;\n      if (remote || !query) return true;\n\n      return (\n        this.preparedLabel.toLowerCase().includes(query.toLowerCase()) ||\n        this.created\n      );\n    },\n\n    isSelected() {\n      const { value, multiple, valueKey } = this.qSelect;\n      if (!value) return false;\n\n      const { key } = this;\n\n      if (!multiple) {\n        if (!isObject(this.value)) return value === key;\n\n        return isEqual(get(value, valueKey), key);\n      }\n\n      const prepareValue = val => (isObject(val) ? get(val, valueKey) : val);\n      return value.some(val => prepareValue(val) === key);\n    },\n\n    isLimitReached() {\n      if (!this.qSelect.multiple) return false;\n\n      const { multipleLimit, value } = this.qSelect;\n\n      return (\n        !this.isSelected &&\n        Array.isArray(value) &&\n        multipleLimit > 0 &&\n        value.length >= multipleLimit\n      );\n    },\n\n    isDisabled() {\n      return this.disabled || this.isLimitReached;\n    }\n  },\n\n  watch: {\n    preparedLabel() {\n      if (!this.created && !this.qSelect.remote) this.qSelect.setSelected();\n    },\n\n    value(val, oldVal) {\n      const { remote } = this.qSelect;\n\n      if (!this.created && !remote) {\n        const { valueKey } = this.qSelect;\n\n        if (\n          valueKey &&\n          isObject(val) &&\n          isObject(oldVal) &&\n          get(val, valueKey) === get(oldVal, valueKey)\n        )\n          return;\n\n        this.qSelect.setSelected();\n      }\n    }\n  },\n\n  created() {\n    this.qSelect.options.push(this);\n  },\n\n  beforeDestroy() {\n    const currentOptionIndex = this.qSelect.options.indexOf(this);\n    if (currentOptionIndex > -1) {\n      this.qSelect.options.splice(currentOptionIndex, 1);\n    }\n  },\n\n  methods: {\n    handleMouseEnter() {\n      if (this.disabled) return;\n\n      this.qSelect.hoverIndex = this.qSelect.options.indexOf(this);\n    },\n\n    handleOptionClick() {\n      if (this.disabled) return;\n\n      this.qSelect.toggleOptionSelection(this);\n    }\n  }\n};\n</script>\n"
  },
  {
    "path": "src/qComponents/QOption/src/q-option.scss",
    "content": ".q-option {\n  --option-background-color-base: var(--color-tertiary-gray-light);\n  --option-background-color-hover: var(--color-tertiary-gray);\n  --option-background-color-focus: var(--color-tertiary-gray);\n  --option-background-color-selected: var(--color-tertiary-gray-ultra-light);\n  --option-background-color-disabled: var(--color-tertiary-gray-light);\n\n  --option-color-base: var(--color-primary-blue);\n  --option-color-hover: var(--color-primary-black);\n  --option-color-selected: var(--color-primary-black);\n  --option-color-disabled: rgba(var(--color-rgb-gray), 0.64);\n\n  position: relative;\n  display: flex;\n  align-items: flex-end;\n  height: 40px;\n  padding: 8px 16px;\n  background-color: var(--option-background-color-base);\n  outline: none;\n  box-shadow: -1px -1px 3px rgba(var(--color-rgb-white), 0.25),\n    1px 1px 3px rgba(var(--color-rgb-blue), 0.4);\n  cursor: pointer;\n  user-select: none;\n\n  &:not(:first-child) {\n    margin-top: 1px;\n  }\n\n  &_selected {\n    background-color: var(--option-background-color-selected);\n  }\n\n  &:hover:not(.q-option_disabled) {\n    background-color: var(--option-background-color-hover);\n  }\n\n  &:focus {\n    outline: none;\n  }\n\n  &.focus-visible {\n    background-color: var(--option-background-color-focus);\n  }\n\n  &_all ~ .q-option {\n    padding-left: 24px;\n  }\n\n  &_disabled {\n    padding-right: 40px;\n    background-color: var(--option-background-color-disabled);\n    cursor: not-allowed;\n  }\n\n  &_with-checkbox {\n    padding-left: 8px;\n\n    .q-option__label {\n      margin-left: 8px;\n    }\n  }\n\n  &__label {\n    overflow: hidden;\n    font-size: var(--font-size-base);\n    line-height: var(--line-height-base);\n    text-align: left;\n    color: var(--option-color-base);\n    white-space: nowrap;\n    text-overflow: ellipsis;\n\n    .q-option_selected & {\n      color: var(--option-color-selected);\n    }\n\n    .q-option:hover:not(.q-option_disabled) & {\n      color: var(--option-color-hover);\n    }\n\n    .q-option_disabled & {\n      color: var(--option-color-disabled);\n    }\n  }\n\n  &__lock {\n    position: absolute;\n    top: 0;\n    right: 0;\n    width: 40px;\n    font-size: 24px;\n    line-height: 40px;\n    text-align: center;\n  }\n}\n"
  },
  {
    "path": "src/qComponents/QPagination/index.js",
    "content": "import QPagination from './src/QPagination.vue';\n\nQPagination.install = Vue => {\n  Vue.component(QPagination.name, QPagination);\n};\n\nexport default QPagination;\n"
  },
  {
    "path": "src/qComponents/QPagination/src/QPagination.vue",
    "content": "<template>\n  <div\n    class=\"q-pagination\"\n    :class=\"{\n      'q-pagination_disabled': disabled\n    }\"\n  >\n    <button\n      type=\"button\"\n      class=\"q-pagination__btn q-pagination__btn_icon q-icon-arrow-left\"\n      :class=\"{\n        'q-pagination__btn_disabled': isPrevBtnDisabled\n      }\"\n      :disabled=\"isPrevBtnDisabled\"\n      @click.prevent=\"handlePrevBtnClick\"\n    />\n\n    <button\n      type=\"button\"\n      class=\"q-pagination__btn\"\n      :class=\"{\n        'q-pagination__btn_active': currentPage === 1\n      }\"\n      :disabled=\"disabled\"\n      @click.prevent=\"handlePageBtnClick(1)\"\n    >\n      1\n    </button>\n\n    <button\n      v-if=\"isPrevQuickBtnShown\"\n      type=\"button\"\n      class=\"q-pagination__btn q-pagination__btn_quick q-icon-triangle-left\"\n      :disabled=\"disabled\"\n      @click.prevent=\"handlePrevQuickBtnClick\"\n    />\n\n    <button\n      v-for=\"page in pagers\"\n      :key=\"page\"\n      type=\"button\"\n      class=\"q-pagination__btn\"\n      :class=\"{\n        'q-pagination__btn_active': page === currentPage\n      }\"\n      :disabled=\"disabled\"\n      @click.prevent=\"handlePageBtnClick(page)\"\n    >\n      {{ page }}\n    </button>\n\n    <button\n      v-if=\"isNextQuickBtnShown\"\n      type=\"button\"\n      class=\"q-pagination__btn q-pagination__btn_quick q-icon-triangle-right\"\n      :disabled=\"disabled\"\n      @click.prevent=\"handleNextQuickBtnClick\"\n    />\n\n    <button\n      v-if=\"preparedPageCount > 1\"\n      type=\"button\"\n      class=\"q-pagination__btn\"\n      :class=\"{\n        'q-pagination__btn_active': preparedPageCount === currentPage\n      }\"\n      :disabled=\"disabled\"\n      @click.prevent=\"handlePageBtnClick(preparedPageCount)\"\n    >\n      {{ preparedPageCount }}\n    </button>\n\n    <button\n      type=\"button\"\n      class=\"q-pagination__btn q-pagination__btn_icon q-icon-arrow-right\"\n      :class=\"{\n        'q-pagination__btn_disabled': isNextBtnDisabled\n      }\"\n      :disabled=\"isNextBtnDisabled\"\n      @click.prevent=\"handleNextBtnClick\"\n    />\n  </div>\n</template>\n\n<script>\nimport { range } from 'lodash-es';\n\nexport default {\n  name: 'QPagination',\n  componentName: 'QPagination',\n\n  props: {\n    /**\n     * total page count\n     */\n    pageCount: { type: Number, default: null },\n    /**\n     * total item count\n     */\n    total: { type: Number, default: null },\n    /**\n     * item count of each page\n     */\n    pageSize: { type: Number, default: null },\n    /**\n     * current page number\n     */\n    currentPage: { type: Number, default: null },\n    /**\n     * whether Pagination is disabled\n     */\n    disabled: { type: Boolean, default: false },\n    /**\n     * number of visible page's buttons\n     */\n    pagerCount: {\n      type: Number,\n      default: 7,\n      validator: value => value >= 3\n    }\n  },\n\n  computed: {\n    preparedPageCount() {\n      const pageCount = this.pageCount ?? Math.ceil(this.total / this.pageSize);\n\n      return pageCount && Number.isFinite(pageCount) ? pageCount : 1;\n    },\n\n    isPrevBtnDisabled() {\n      return this.disabled || this.currentPage <= 1;\n    },\n\n    isNextBtnDisabled() {\n      return this.disabled || this.currentPage >= this.preparedPageCount;\n    },\n\n    isPrevQuickBtnShown() {\n      if (this.preparedPageCount <= this.pagerCount) return false;\n\n      const halfPagerCount = (this.pagerCount - 1) / 2;\n      return this.currentPage > this.pagerCount - halfPagerCount;\n    },\n\n    isNextQuickBtnShown() {\n      if (this.preparedPageCount <= this.pagerCount) return false;\n\n      const halfPagerCount = (this.pagerCount - 1) / 2;\n      return this.currentPage < this.preparedPageCount - halfPagerCount;\n    },\n\n    pagers() {\n      if (this.preparedPageCount <= 1) return [];\n\n      let rangeStart = 2;\n      let rangeEnd = this.preparedPageCount;\n\n      if (this.isPrevQuickBtnShown && this.isNextQuickBtnShown) {\n        const offset = Math.floor(this.pagerCount / 2) - 1;\n\n        rangeStart = this.currentPage - offset;\n        rangeEnd = this.currentPage + offset + 1;\n      } else if (this.isPrevQuickBtnShown) {\n        rangeStart = this.preparedPageCount - (this.pagerCount - 2);\n      } else if (this.isNextQuickBtnShown) {\n        rangeEnd = this.pagerCount;\n      }\n\n      return range(rangeStart, rangeEnd);\n    }\n  },\n\n  methods: {\n    handlePrevBtnClick() {\n      let newPage = this.currentPage - 1;\n      if (newPage > this.preparedPageCount) newPage = this.preparedPageCount;\n\n      /**\n       * triggers when the prev button is clicked\n       */\n      this.$emit('prev-click', newPage);\n      /**\n       * triggers when the current page changes\n       */\n      this.$emit('current-change', newPage);\n    },\n\n    handlePageBtnClick(newPage) {\n      if (this.currentPage === newPage) return;\n      this.$emit('current-change', newPage);\n    },\n\n    handleNextBtnClick() {\n      const newPage = this.currentPage + 1;\n\n      /**\n       * triggers when the next button is clicked\n       */\n      this.$emit('next-click', newPage);\n      this.$emit('current-change', newPage);\n    },\n\n    handlePrevQuickBtnClick() {\n      let newPage = this.currentPage - this.pagerCount - 2;\n      if (newPage > this.preparedPageCount) newPage = this.preparedPageCount;\n      else if (newPage < 1) newPage = 1;\n\n      this.$emit('quick-prev-click', newPage);\n      this.$emit('current-change', newPage);\n    },\n\n    handleNextQuickBtnClick() {\n      let newPage = this.currentPage + this.pagerCount - 2;\n      if (newPage > this.preparedPageCount) newPage = this.preparedPageCount;\n      else if (newPage < 1) newPage = 1;\n\n      this.$emit('quick-next-click', newPage);\n      this.$emit('current-change', newPage);\n    }\n  }\n};\n</script>\n"
  },
  {
    "path": "src/qComponents/QPagination/src/q-pagination.scss",
    "content": ".q-pagination {\n  --pagination-color-base: var(--color-primary-blue);\n  --pagination-color-hover: var(--color-primary-black);\n  --pagination-color-selected: var(--color-primary-black);\n  --pagination-color-disabled: rgba(var(--color-rgb-gray), 0.64);\n\n  --pagination-background-color-base: var(--color-tertiary-gray-light);\n  --pagination-background-color-hover: var(--color-tertiary-gray);\n  --pagination-background-color-selected: var(\n    --color-tertiary-gray-ultra-light\n  );\n  --pagination-background-color-disabled: var(--color-tertiary-gray);\n\n  --pagination-box-shadow-primary: -1px -1px 4px var(--color-tertiary-white),\n    1px 1px 4px rgba(var(--color-rgb-blue), 0.4),\n    4px 4px 8px rgba(var(--color-rgb-blue), 0.4),\n    -4px -4px 8px rgba(var(--color-rgb-white), 0.25);\n  --pagination-box-shadow-secondary: -1px -1px 3px rgba(var(--color-rgb-white), 0.25),\n    1px 1px 3px rgba(var(--color-rgb-blue), 0.4);\n\n  display: inline-grid;\n  margin-top: 24px;\n  white-space: nowrap;\n  grid-gap: 8px;\n\n  &__btn {\n    box-sizing: border-box;\n    min-width: 40px;\n    height: 40px;\n    margin: 0;\n    padding: 0;\n    font-weight: var(--font-weight-base);\n    font-size: var(--font-size-base);\n    line-height: 40px;\n    vertical-align: top;\n    text-align: center;\n    color: var(--pagination-color-base);\n    background-color: var(--pagination-background-color-base);\n    border: none;\n    border-radius: var(--border-radius-base);\n    box-shadow: var(--pagination-box-shadow-primary);\n    cursor: pointer;\n    grid-row: 1;\n\n    &:hover,\n    &:focus {\n      color: var(--pagination-color-hover);\n      background-color: var(--pagination-background-color-hover);\n      outline: none;\n    }\n\n    &_quick {\n      font-size: 24px;\n\n      &::before {\n        line-height: 40px;\n      }\n\n      .q-pagination_disabled &,\n      &:not(:focus):not(:hover) {\n        &::before {\n          content: '...';\n          font-size: var(--font-size-base);\n        }\n      }\n    }\n\n    &_icon {\n      font-size: 24px;\n    }\n\n    &_active:not(:hover),\n    &_active:not(:focus) {\n      color: var(--pagination-color-selected);\n      background-color: var(--pagination-background-color-selected);\n      box-shadow: var(--pagination-box-shadow-secondary);\n      cursor: default;\n    }\n\n    &.q-pagination__btn_disabled,\n    .q-pagination_disabled & {\n      color: var(--pagination-color-disabled);\n      background-color: var(--pagination-background-color-disabled);\n      box-shadow: var(--pagination-box-shadow-secondary);\n      cursor: not-allowed;\n    }\n  }\n}\n"
  },
  {
    "path": "src/qComponents/QPopover/QPopover.test.js",
    "content": "import Component from './index';\n\ndescribe('QPopover', () => {\n  const options = {\n    slots: {\n      reference: '<button>Open</button>'\n    }\n  };\n\n  it('should match snapshot', () => {\n    const { element } = shallowMount(Component, options);\n    expect(element).toMatchSnapshot();\n  });\n\n  it('data should match snapshot', () => {\n    expect(Component.data()).toMatchSnapshot();\n  });\n\n  describe('computed', () => {\n    describe('popoverClasses', () => {\n      it('should return expected value if icon does not exist', () => {\n        const instance = shallowMount(Component, options);\n        instance.setProps({\n          icon: ''\n        });\n        const expected = {\n          'q-popover_without-icon': true\n        };\n        expect(instance.vm.popoverClasses).toEqual(expected);\n      });\n\n      it('should return expected value if icon exists', () => {\n        const instance = shallowMount(Component, options);\n        instance.setProps({\n          icon: 'icon-name'\n        });\n        const expected = {\n          'q-popover_without-icon': false\n        };\n        expect(instance.vm.popoverClasses).toEqual(expected);\n      });\n    });\n  });\n\n  describe('methods', () => {\n    describe('togglePopover', () => {\n      it('should set isPopoverShown to false', () => {\n        const instance = shallowMount(Component, options);\n        instance.setData({\n          isPopoverShown: true\n        });\n        instance.vm.togglePopover();\n        expect(instance.vm.isPopoverShown).toBeFalsy();\n      });\n\n      it('should set isPopoverShown to true', () => {\n        const instance = shallowMount(Component, options);\n        instance.setData({\n          isPopoverShown: false\n        });\n        instance.vm.togglePopover();\n        expect(instance.vm.isPopoverShown).toBeTruthy();\n      });\n    });\n\n    describe('destroy', () => {\n      it('should set isPopoverShown to false', () => {\n        const instance = shallowMount(Component, options);\n        instance.setData({\n          isPopoverShown: true\n        });\n        instance.vm.destroy();\n        expect(instance.vm.isPopoverShown).toBeFalsy();\n      });\n\n      it('should call destroy', () => {\n        const instance = shallowMount(Component, options);\n        const spy = jest.fn(() => {});\n        instance.setData({\n          popperJS: {\n            destroy: spy\n          }\n        });\n        instance.vm.destroy();\n        expect(spy).toBeCalled();\n      });\n\n      it('should set popperJS to null', () => {\n        const instance = shallowMount(Component, options);\n        instance.setData({\n          popperJS: {\n            destroy: () => {}\n          }\n        });\n        instance.vm.destroy();\n        expect(instance.vm.popperJS).toBeNull();\n      });\n    });\n  });\n});\n"
  },
  {
    "path": "src/qComponents/QPopover/__snapshots__/QPopover.test.js.snap",
    "content": "// Jest Snapshot v1, https://goo.gl/fbAQLP\n\nexports[`QPopover data should match snapshot 1`] = `\nObject {\n  \"isPopoverShown\": false,\n  \"popperJS\": null,\n  \"referenceElement\": null,\n  \"zIndex\": null,\n}\n`;\n\nexports[`QPopover should match snapshot 1`] = `\n<span>\n  <transition-stub\n    name=\"fade-in-linear\"\n  >\n    <div\n      class=\"q-popover q-popover_without-icon\"\n      style=\"display: none;\"\n    >\n      <!---->\n       \n      <q-scrollbar-stub\n        theme=\"primary\"\n        viewclass=\"scrollbar__list\"\n        viewtag=\"div\"\n        wrapclass=\"q-popover__inner\"\n      >\n        <!---->\n         \n        <!---->\n      </q-scrollbar-stub>\n    </div>\n  </transition-stub>\n   \n  <button>\n    Open\n  </button>\n</span>\n`;\n"
  },
  {
    "path": "src/qComponents/QPopover/index.js",
    "content": "import QPopover from './src/QPopover.vue';\n\n/* istanbul ignore next */\nQPopover.install = function(Vue) {\n  Vue.component(QPopover.name, QPopover);\n};\n\nexport default QPopover;\n"
  },
  {
    "path": "src/qComponents/QPopover/src/QPopover.vue",
    "content": "<template>\n  <component :is=\"tagName\">\n    <transition\n      :name=\"transition\"\n      @after-leave=\"destroy\"\n    >\n      <div\n        v-show=\"isPopoverShown\"\n        ref=\"qPopover\"\n        class=\"q-popover\"\n        :class=\"popoverClasses\"\n        :style=\"popoverStyles\"\n      >\n        <div\n          v-if=\"icon\"\n          class=\"q-popover__icon\"\n          :class=\"icon\"\n          :style=\"popoverIconStyles\"\n        />\n        <q-scrollbar\n          wrap-class=\"q-popover__inner\"\n          view-class=\"scrollbar__list\"\n        >\n          <div\n            v-if=\"title\"\n            class=\"q-popover__title\"\n          >\n            {{ title }}\n          </div>\n          <div\n            v-if=\"$slots.default\"\n            class=\"q-popover__content\"\n          >\n            <slot />\n          </div>\n        </q-scrollbar>\n      </div>\n    </transition>\n\n    <slot name=\"reference\" />\n  </component>\n</template>\n\n<script>\nimport { createPopper } from '@popperjs/core';\nimport PLACEMENTS from '../../constants/popperPlacements';\n\nfunction eventOn(element, event, handler) {\n  if (element && event && handler) {\n    element.addEventListener(event, handler, false);\n  }\n}\n\nfunction eventOff(element, event, handler) {\n  if (element && event) {\n    element.removeEventListener(event, handler, false);\n  }\n}\n\nconst TRIGGERS = ['click', 'hover'];\n\nexport default {\n  name: 'QPopover',\n  componentName: 'QPopover',\n\n  props: {\n    /**\n     * Popover content title\n     */\n    title: {\n      type: String,\n      default: ''\n    },\n    /**\n     * custom element tag\n     */\n    tagName: {\n      type: String,\n      default: 'span'\n    },\n    /**\n     * opening event trigger\n     */\n    trigger: {\n      type: String,\n      default: 'click',\n      validator: value => TRIGGERS.includes(value)\n    },\n    /**\n     * see: https://popper.js.org/docs/v2/constructors/#options\n     */\n    placement: {\n      type: String,\n      default: 'top-start',\n      validator: value => PLACEMENTS.includes(value)\n    },\n    /**\n     * icon class name\n     */\n    icon: {\n      type: String,\n      default: ''\n    },\n    /**\n     * content icon color\n     */\n    iconColor: {\n      type: String,\n      default: 'var(--gradient-secondary)'\n    },\n    /**\n     * custom transition's animation\n     */\n    transition: {\n      type: String,\n      default: 'fade-in-linear'\n    },\n    /**\n     * delay before appearing, in milliseconds\n     * (works only when trigger is hover)\n     */\n    openDelay: {\n      type: Number,\n      default: 10\n    },\n    /**\n     * delay before disappearing, in milliseconds\n     * (works only when trigger is hover)\n     */\n    closeDelay: {\n      type: Number,\n      default: 10\n    },\n    /**\n     * popover min-width\n     */\n    minWidth: {\n      type: [String, Number],\n      default: ''\n    },\n    /**\n     * popover max-width\n     */\n    maxWidth: {\n      type: [String, Number],\n      default: ''\n    },\n    /**\n     * see: https://popper.js.org/docs/v2/constructors/#options\n     */\n    popperOptions: {\n      type: Object,\n      default: () => ({})\n    },\n    /**\n     * whether to append the popover to body\n     */\n    appendToBody: {\n      type: Boolean,\n      default: true\n    }\n  },\n\n  data() {\n    return {\n      zIndex: null,\n      popperJS: null,\n      referenceElement: null,\n      isPopoverShown: false\n    };\n  },\n\n  computed: {\n    popoverClasses() {\n      return {\n        'q-popover_without-icon': !this.icon\n      };\n    },\n\n    popoverStyles() {\n      return {\n        zIndex: this.zIndex,\n        minWidth: Number(this.minWidth)\n          ? `${Number(this.minWidth)}px`\n          : this.minWidth,\n        maxWidth: Number(this.maxWidth)\n          ? `${Number(this.maxWidth)}px`\n          : this.maxWidth\n      };\n    },\n\n    popoverIconStyles() {\n      const backgroundProperty = this.iconColor.includes('-gradient')\n        ? 'backgroundImage'\n        : 'backgroundColor';\n\n      return {\n        [backgroundProperty]: this.iconColor\n      };\n    }\n  },\n\n  watch: {\n    isPopoverShown(value) {\n      if (value && !this.popperJS) {\n        this.zIndex = this.$Q?.zIndex ?? 2000;\n        this.$emit('show');\n        this.createPopper();\n      } else {\n        this.$emit('hide');\n      }\n    }\n  },\n\n  created() {\n    if (!this.$slots.reference && process.env.NODE_ENV !== 'production') {\n      console.error('QPopover requires reference be provided in the slot.');\n    }\n  },\n\n  mounted() {\n    this.referenceElement = this.$slots?.reference?.[0]?.elm;\n\n    if (!this.referenceElement) return;\n\n    switch (this.trigger) {\n      default:\n      case 'click':\n        eventOn(this.referenceElement, 'click', this.togglePopover);\n        eventOn(document, 'click', this.handleDocumentClick);\n        break;\n\n      case 'hover':\n        eventOn(this.referenceElement, 'mouseover', this.handleMouseOver);\n        eventOn(this.referenceElement, 'mouseout', this.onMouseOut);\n        eventOn(this.$refs.qPopover, 'mouseover', this.handleMouseOver);\n        eventOn(this.$refs.qPopover, 'mouseout', this.onMouseOut);\n        break;\n    }\n  },\n\n  beforeDestroy() {\n    eventOff(this.referenceElement, 'click', this.togglePopover);\n    eventOff(this.referenceElement, 'mouseout', this.onMouseOut);\n    eventOff(this.referenceElement, 'mouseover', this.handleMouseOver);\n    eventOff(document, 'click', this.handleDocumentClick);\n\n    this.isPopoverShown = false;\n    this.destroy();\n\n    if (this.appendToBody) {\n      const { qPopover } = this.$refs;\n      qPopover.parentNode.removeChild(qPopover);\n    }\n  },\n\n  methods: {\n    async createPopper() {\n      await this.$nextTick();\n\n      if (this.appendToBody) {\n        document.body.appendChild(this.$refs.qPopover);\n      }\n\n      const options = {\n        placement: this.placement,\n        computeStyle: {\n          boundariesElement: 'body',\n          gpuAcceleration: false\n        },\n        modifiers: [\n          {\n            name: 'offset',\n            options: {\n              offset: [0, 16]\n            }\n          }\n        ],\n        ...this.popperOptions\n      };\n\n      this.popperJS = createPopper(\n        this.referenceElement,\n        this.$refs.qPopover,\n        options\n      );\n    },\n\n    togglePopover() {\n      this.isPopoverShown = !this.isPopoverShown;\n    },\n\n    destroy() {\n      this.isPopoverShown = false;\n\n      if (this.popperJS) {\n        this.popperJS.destroy();\n        this.popperJS = null;\n      }\n    },\n\n    handleMouseOver() {\n      clearTimeout(this.timer);\n\n      this.timer = setTimeout(() => {\n        this.isPopoverShown = true;\n      }, this.openDelay);\n    },\n\n    onMouseOut() {\n      clearTimeout(this.timer);\n\n      this.timer = setTimeout(() => {\n        this.isPopoverShown = false;\n      }, this.closeDelay);\n    },\n\n    handleDocumentClick({ target }) {\n      if (\n        this.$el.contains(target) ||\n        this.referenceElement.contains(target) ||\n        this.$refs.qPopover.contains(target)\n      ) {\n        return;\n      }\n\n      this.isPopoverShown = false;\n    }\n  }\n};\n</script>\n"
  },
  {
    "path": "src/qComponents/QPopover/src/q-popover.scss",
    "content": ".q-popover {\n  display: flex;\n  align-items: flex-start;\n  min-width: 320px;\n  max-width: 552px;\n  padding: 24px;\n  text-align: left;\n  color: var(--color-primary-black);\n  letter-spacing: 0.2px;\n  background-color: var(--color-tertiary-white);\n  border-radius: var(--border-radius-base);\n  box-shadow: var(--box-shadow-primary);\n\n  &__icon {\n    margin-right: 16px;\n    text-align: center;\n    color: var(--color-tertiary-white);\n    -webkit-text-fill-color: transparent;\n    -webkit-background-clip: text;\n\n    &::before {\n      font-size: 40px;\n      line-height: 40px;\n    }\n  }\n\n  &__inner {\n    max-height: 646px;\n    padding-top: 8px;\n  }\n\n  &__title {\n    min-width: 216px;\n    font-weight: 600;\n    font-size: 16px;\n    line-height: 22px;\n\n    & + .q-popover__content {\n      margin-top: 16px;\n    }\n  }\n\n  &__content {\n    font-style: normal;\n    font-weight: var(--font-weight-base);\n    font-size: var(--font-size-base);\n    line-height: 20px;\n    color: var(--color-primary-black);\n  }\n\n  &_without-icon {\n    padding: 16px;\n  }\n}\n"
  },
  {
    "path": "src/qComponents/QRadio/QRadio.test.js",
    "content": "import Component from './src/QRadio';\n\ndescribe('QRadio', () => {\n  it('should match snapshot', () => {\n    const { element } = shallowMount(Component);\n\n    expect(element).toMatchSnapshot();\n  });\n});\n"
  },
  {
    "path": "src/qComponents/QRadio/__snapshots__/QRadio.test.js.snap",
    "content": "// Jest Snapshot v1, https://goo.gl/fbAQLP\n\nexports[`QRadio should match snapshot 1`] = `\n<label\n  class=\"q-radio\"\n  role=\"radio\"\n  tabindex=\"0\"\n>\n  <span\n    class=\"q-radio__input\"\n  >\n    <span\n      class=\"q-radio__inner\"\n    />\n     \n    <input\n      aria-hidden=\"true\"\n      class=\"q-radio__original\"\n      tabindex=\"-1\"\n      type=\"radio\"\n      value=\"\"\n    />\n  </span>\n   \n  <span\n    class=\"q-radio__label\"\n  >\n    \n  </span>\n</label>\n`;\n"
  },
  {
    "path": "src/qComponents/QRadio/index.js",
    "content": "import QRadio from './src/QRadio';\n\nQRadio.install = Vue => {\n  Vue.component(QRadio.name, QRadio);\n};\n\nexport default QRadio;\n"
  },
  {
    "path": "src/qComponents/QRadio/src/QRadio.vue",
    "content": "<template>\n  <label\n    class=\"q-radio\"\n    :class=\"wrapClass\"\n    role=\"radio\"\n    :aria-checked=\"isChecked\"\n    :aria-disabled=\"isDisabled\"\n    :tabindex=\"tabIndex\"\n    @keyup.space=\"handleSpaceKeyUp\"\n  >\n    <span class=\"q-radio__input\">\n      <span class=\"q-radio__inner\" />\n      <input\n        class=\"q-radio__original\"\n        type=\"radio\"\n        aria-hidden=\"true\"\n        tabindex=\"-1\"\n        :name=\"name\"\n        :value=\"value\"\n        :checked=\"isChecked\"\n        :disabled=\"isDisabled\"\n        @change=\"handleChange\"\n      />\n    </span>\n    <span\n      class=\"q-radio__label\"\n      @keydown.stop\n    >\n      <slot>{{ label }}</slot>\n    </span>\n  </label>\n</template>\n\n<script>\nimport Emitter from '../../mixins/emitter';\n\nexport default {\n  name: 'QRadio',\n  componentName: 'QRadio',\n\n  mixins: [Emitter],\n\n  inject: {\n    qForm: {\n      default: null\n    },\n    qFormItem: {\n      default: null\n    },\n    qRadioGroup: {\n      default: null\n    }\n  },\n\n  model: {\n    prop: 'checked',\n    event: 'change'\n  },\n\n  props: {\n    /**\n     * the value of Radio label\n     */\n    label: { type: String, default: '' },\n    /**\n     * binding value\n     */\n    value: { type: [String, Number, Boolean], default: '' },\n    checked: { type: [String, Number, Boolean], default: false },\n    /**\n     * whether Radio is disabled\n     */\n    disabled: { type: Boolean, default: false },\n    /**\n     * as native name\n     */\n    name: { type: String, default: null }\n  },\n\n  computed: {\n    isGroup() {\n      return Boolean(this.qRadioGroup);\n    },\n\n    isChecked() {\n      if (this.isGroup) return this.qRadioGroup?.value === this.value;\n\n      if (typeof this.checked === typeof this.value) {\n        return this.checked === this.value;\n      }\n\n      return Boolean(this.checked);\n    },\n\n    isDisabled() {\n      return (\n        this.disabled ||\n        (this.qForm?.disabled ?? false) ||\n        (this.qRadioGroup?.disabled ?? false)\n      );\n    },\n\n    wrapClass() {\n      return {\n        'q-radio_disabled': this.isDisabled,\n        'q-radio_checked': this.isChecked\n      };\n    },\n\n    tabIndex() {\n      return this.isDisabled || (this.isGroup && !this.isChecked) ? -1 : 0;\n    }\n  },\n\n  methods: {\n    handleSpaceKeyUp() {\n      if (this.isGroup) return;\n\n      this.$emit('change', this.value);\n    },\n\n    handleChange() {\n      /**\n       * triggers when the value changes\n       */\n      this.$emit('change', this.value);\n\n      if (this.isGroup) {\n        this.dispatch('QRadioGroup', 'change', this.value);\n      }\n    }\n  }\n};\n</script>\n"
  },
  {
    "path": "src/qComponents/QRadio/src/q-radio.scss",
    "content": ".q-radio {\n  --radio-color-base: var(--color-primary-black);\n  --radio-color-disabled: rgba(var(--color-rgb-gray), 0.64);\n\n  --radio-background-color-base: var(--color-tertiary-gray-ultra-light);\n  --radio-background-color-hover: var(--color-tertiary-gray);\n  --radio-background-color-focus: var(--color-tertiary-gray-ultra-light);\n  --radio-background-color-checked: var(--color-tertiary-gray-ultra-light);\n  --radio-background-color-disabled: var(--color-tertiary-gray);\n\n  --radio-dot-color-base: var(--color-primary-blue);\n  --radio-dot-color-disabled: rgba(var(--color-rgb-gray), 0.64);\n\n  --radio-box-shadow-base: -1px -1px 3px rgba(var(--color-rgb-white), 0.25),\n    1px 1px 3px rgba(var(--color-rgb-blue), 0.4),\n    inset -1px -1px 1px rgba(var(--color-rgb-white), 0.7),\n    inset 1px 1px 2px rgba(var(--color-rgb-blue), 0.2);\n  --radio-box-shadow-focus: -1px -1px 3px rgba(var(--color-rgb-white), 0.25),\n    1px 1px 3px rgba(var(--color-rgb-blue), 0.4),\n    4px 4px 10px rgba(var(--color-rgb-blue), 0.4),\n    -4px -4px 10px rgba(var(--color-rgb-white), 0.25),\n    inset -1px -1px 1px rgba(var(--color-rgb-white), 0.7),\n    inset 1px 1px 2px rgba(var(--color-rgb-blue), 0.2);\n\n  position: relative;\n  display: inline-flex;\n  font-weight: var(--font-weight-base);\n  font-size: var(--font-size-base);\n  line-height: 1;\n  color: var(--radio-color-base);\n  white-space: nowrap;\n  outline: none;\n  cursor: pointer;\n  user-select: none;\n\n  &_disabled {\n    cursor: not-allowed;\n  }\n\n  &__label {\n    margin-top: 3px;\n    padding-left: 16px;\n    font-size: var(--font-size-base);\n    line-height: 18px;\n    white-space: normal;\n    word-break: break-word;\n\n    .q-radio_disabled & {\n      color: var(--radio-color-disabled);\n    }\n  }\n\n  &__input {\n    position: relative;\n    line-height: 0;\n    white-space: nowrap;\n    border: none;\n    outline: none;\n  }\n\n  &__inner {\n    position: relative;\n    display: inline-block;\n    box-sizing: border-box;\n    width: 24px;\n    height: 24px;\n    background-color: var(--radio-background-color-base);\n    border-radius: 100%;\n    outline: none;\n    box-shadow: var(--radio-box-shadow-base);\n\n    &::after {\n      content: '';\n      position: absolute;\n      top: 50%;\n      left: 50%;\n      width: 12px;\n      height: 12px;\n      background-color: var(--radio-dot-color-base);\n      border-radius: 100%;\n      transform: translate(-50%, -50%) scale(0);\n      transition: transform 0.15s ease-in;\n    }\n\n    .q-radio_checked & {\n      background-color: var(--radio-background-color-checked);\n\n      &::after {\n        transform: translate(-50%, -50%) scale(1);\n      }\n    }\n\n    .q-radio:not(.q-radio_disabled):focus & {\n      background-color: var(--radio-background-color-focus);\n      box-shadow: var(--radio-box-shadow-focus);\n    }\n\n    &,\n    .q-radio:not(.q-radio_disabled):focus &,\n    .q-radio_checked & {\n      &:hover {\n        background-color: var(--radio-background-color-hover);\n      }\n    }\n\n    .q-radio_disabled & {\n      background-color: var(--radio-background-color-disabled);\n\n      &::after {\n        background-color: var(--radio-dot-color-disabled);\n      }\n    }\n  }\n\n  &__original {\n    position: absolute;\n    top: 0;\n    right: 0;\n    bottom: 0;\n    left: 0;\n    z-index: -1;\n    margin: 0;\n    outline: none;\n    opacity: 0;\n  }\n}\n"
  },
  {
    "path": "src/qComponents/QRadioGroup/QRadioGroup.test.js",
    "content": "import Component from './src/QRadioGroup';\n\ndescribe('QRadioGroup', () => {\n  it('should match snapshot', () => {\n    const { element } = shallowMount(Component);\n\n    expect(element).toMatchSnapshot();\n  });\n});\n"
  },
  {
    "path": "src/qComponents/QRadioGroup/__snapshots__/QRadioGroup.test.js.snap",
    "content": "// Jest Snapshot v1, https://goo.gl/fbAQLP\n\nexports[`QRadioGroup should match snapshot 1`] = `\n<div\n  class=\"q-radio-group q-radio-group_vertical\"\n  role=\"radiogroup\"\n/>\n`;\n"
  },
  {
    "path": "src/qComponents/QRadioGroup/index.js",
    "content": "import QRadioGroup from './src/QRadioGroup';\n\nQRadioGroup.install = Vue => {\n  Vue.component(QRadioGroup.name, QRadioGroup);\n};\n\nexport default QRadioGroup;\n"
  },
  {
    "path": "src/qComponents/QRadioGroup/src/QRadioGroup.vue",
    "content": "<template>\n  <component\n    :is=\"tag\"\n    class=\"q-radio-group\"\n    :class=\"`q-radio-group_${direction}`\"\n    role=\"radiogroup\"\n    @keydown=\"handleKeydown\"\n  >\n    <slot />\n  </component>\n</template>\n\n<script>\nimport Emitter from '../../mixins/emitter';\n\nconst keyCode = {\n  LEFT: 37,\n  UP: 38,\n  RIGHT: 39,\n  DOWN: 40\n};\n\nexport default {\n  name: 'QRadioGroup',\n  componentName: 'QRadioGroup',\n\n  mixins: [Emitter],\n\n  inject: {\n    qFormItem: {\n      default: null\n    }\n  },\n\n  provide() {\n    return {\n      qRadioGroup: this\n    };\n  },\n\n  model: {\n    prop: 'value',\n    event: 'change'\n  },\n\n  props: {\n    value: { type: [String, Number, Boolean], default: '' },\n    /**\n     * whether Radio is disabled\n     */\n    disabled: { type: Boolean, default: false },\n    /**\n     * custom element tag\n     */\n    tag: { type: String, default: 'div' },\n    direction: {\n      type: String,\n      default: 'vertical',\n      validator: value => ['vertical', 'horizontal'].includes(value)\n    }\n  },\n\n  watch: {\n    value() {\n      this.qFormItem?.validateField('change');\n    }\n  },\n\n  mounted() {\n    const radios = this.$el.querySelectorAll('[type=radio]');\n    const firstLabel = this.$el.querySelector('[role=radio]');\n\n    if (![...radios].some(({ checked }) => checked) && firstLabel) {\n      firstLabel.tabIndex = 0;\n    }\n  },\n\n  methods: {\n    handleKeydown(e) {\n      const target = e.target;\n      const selector =\n        target.nodeName === 'INPUT' ? '[type=radio]' : '[role=radio]';\n      const radios = this.$el.querySelectorAll(selector);\n      const length = radios.length;\n      const index = [...radios].indexOf(target);\n      const roleRadios = this.$el.querySelectorAll('[role=radio]');\n\n      switch (e.keyCode) {\n        case keyCode.LEFT:\n        case keyCode.UP:\n          e.stopPropagation();\n          e.preventDefault();\n          if (index === 0) {\n            roleRadios[length - 1].click();\n            roleRadios[length - 1].focus();\n          } else {\n            roleRadios[index - 1].click();\n            roleRadios[index - 1].focus();\n          }\n          break;\n\n        case keyCode.RIGHT:\n        case keyCode.DOWN:\n          if (index === length - 1) {\n            e.stopPropagation();\n            e.preventDefault();\n            roleRadios[0].click();\n            roleRadios[0].focus();\n          } else {\n            roleRadios[index + 1].click();\n            roleRadios[index + 1].focus();\n          }\n          break;\n\n        default:\n          break;\n      }\n    }\n  }\n};\n</script>\n"
  },
  {
    "path": "src/qComponents/QRadioGroup/src/q-radio-group.scss",
    "content": ".q-radio-group {\n  display: flex;\n  align-items: flex-start;\n  font-size: 0;\n  line-height: 1;\n\n  &_vertical {\n    flex-direction: column;\n\n    .q-radio:not(:last-child) {\n      margin-bottom: 16px;\n    }\n  }\n\n  &_horizontal {\n    .q-radio:not(:last-child) {\n      margin-right: 32px;\n    }\n  }\n}\n"
  },
  {
    "path": "src/qComponents/QRow/QRow.test.js",
    "content": "import Component from './src/QRow';\n\ndescribe('QRow', () => {\n  it('should match snapshot', async () => {\n    const { element } = shallowMount(Component);\n\n    expect(element).toMatchSnapshot();\n  });\n});\n"
  },
  {
    "path": "src/qComponents/QRow/__snapshots__/QRow.test.js.snap",
    "content": "// Jest Snapshot v1, https://goo.gl/fbAQLP\n\nexports[`QRow should match snapshot 1`] = `\n<div\n  class=\"q-row\"\n/>\n`;\n"
  },
  {
    "path": "src/qComponents/QRow/index.js",
    "content": "import QRow from './src/QRow';\n\nQRow.install = Vue => {\n  Vue.component(QRow.name, QRow);\n};\n\nexport default QRow;\n"
  },
  {
    "path": "src/qComponents/QRow/src/QRow.vue",
    "content": "<template>\n  <component\n    :is=\"tag\"\n    class=\"q-row\"\n    :class=\"classes\"\n  >\n    <slot />\n  </component>\n</template>\n\n<script>\nexport default {\n  name: 'QRow',\n  componentName: 'QRow',\n\n  props: {\n    /**\n     * custom element tag\n     */\n    tag: {\n      type: String,\n      default: 'div'\n    },\n    /**\n     * vertical alignment of flex layout.\n     * `['start', 'end', 'center', 'baseline', 'stretch']`\n     */\n    alignV: {\n      type: String,\n      default: null,\n      validator: value =>\n        ['start', 'end', 'center', 'baseline', 'stretch'].includes(value)\n    },\n    /**\n     * horizontal alignment of flex layout.\n     * `['start', 'end', 'center', 'between', 'around']`\n     */\n    alignH: {\n      type: String,\n      default: null,\n      validator: value =>\n        ['start', 'end', 'center', 'between', 'around'].includes(value)\n    }\n  },\n\n  computed: {\n    classes() {\n      return {\n        [`q-row_align-h_${this.alignH}`]: Boolean(this.alignH),\n        [`q-row_align-v_${this.alignV}`]: Boolean(this.alignV)\n      };\n    }\n  }\n};\n</script>\n"
  },
  {
    "path": "src/qComponents/QRow/src/q-row.scss",
    "content": "$align-h: (\n  start: flex-start,\n  end: flex-end,\n  center: center,\n  between: space-between,\n  around: space-around\n);\n\n$align-v: (\n  start: flex-start,\n  end: flex-end,\n  center: center,\n  baseline: baseline,\n  stretch: stretch\n);\n\n.q-row {\n  display: flex;\n  flex-wrap: wrap;\n  margin-right: calc(var(--layout-gutter) / -2);\n  margin-left: calc(var(--layout-gutter) / -2);\n\n  @each $key, $value in $align-h {\n    &_align-h_#{$key} {\n      justify-content: $value;\n    }\n  }\n\n  @each $key, $value in $align-v {\n    &_align-v_#{$key} {\n      align-items: $value;\n    }\n  }\n}\n"
  },
  {
    "path": "src/qComponents/QScrollbar/index.js",
    "content": "import QScrollbar from './src/QScrollbar';\n\n/* istanbul ignore next */\nQScrollbar.install = function(Vue) {\n  Vue.component(QScrollbar.name, QScrollbar);\n};\n\nexport default QScrollbar;\n"
  },
  {
    "path": "src/qComponents/QScrollbar/src/QBar.vue",
    "content": "<template>\n  <div\n    class=\"q-scrollbar__bar\"\n    :class=\"classes\"\n    @mousedown=\"handleTrackerClick\"\n  >\n    <div\n      ref=\"thumb\"\n      :class=\"thumbClasses\"\n      :style=\"renderThumbStyle({ size, move, bar })\"\n      @mousedown=\"handleThumbClick\"\n    />\n  </div>\n</template>\n\n<script>\nimport { renderThumbStyle, BAR_MAP } from './util';\nimport { on, off } from '../../helpers';\n\nexport default {\n  name: 'QBar',\n  componentName: 'QBar',\n\n  props: {\n    type: {\n      type: String,\n      default: 'horizontal',\n      validator: value => ['horizontal', 'vertical'].includes(value)\n    },\n    size: { type: String, default: '0' },\n    move: { type: Number, default: 0 }\n  },\n\n  data() {\n    return {\n      renderThumbStyle\n    };\n  },\n\n  computed: {\n    classes() {\n      return [\n        `q-scrollbar__bar_${this.bar.key}`,\n        this.$parent.theme === 'secondary' && 'q-scrollbar__bar_secondary'\n      ];\n    },\n\n    thumbClasses() {\n      return [\n        'q-scrollbar__thumb',\n        this.$parent.theme === 'secondary' && 'q-scrollbar__thumb_secondary'\n      ];\n    },\n\n    bar() {\n      return BAR_MAP[this.type];\n    },\n\n    wrap() {\n      return this.$parent.wrap;\n    }\n  },\n\n  destroyed() {\n    off(document, 'mouseup', this.mouseUpDocumentHandler);\n  },\n\n  methods: {\n    handleThumbClick(e) {\n      // prevent click event of right button\n      if (e.ctrlKey || e.button === 2) {\n        return;\n      }\n      this.startDrag(e);\n      this[this.bar.axis] =\n        e.currentTarget[this.bar.offset] -\n        (e[this.bar.client] -\n          e.currentTarget.getBoundingClientRect()[this.bar.direction]);\n    },\n\n    handleTrackerClick(e) {\n      const offset = Math.abs(\n        e.target.getBoundingClientRect()[this.bar.direction] -\n          e[this.bar.client]\n      );\n      const thumbHalf = this.$refs.thumb[this.bar.offset] / 2;\n      const thumbPositionPercentage =\n        ((offset - thumbHalf) * 100) / this.$el[this.bar.offset];\n\n      this.wrap[this.bar.scroll] =\n        (thumbPositionPercentage * this.wrap[this.bar.scrollSize]) / 100;\n    },\n\n    startDrag(e) {\n      e.stopImmediatePropagation();\n      this.cursorDown = true;\n\n      on(document, 'mousemove', this.mouseMoveDocumentHandler);\n      on(document, 'mouseup', this.mouseUpDocumentHandler);\n      document.onselectstart = () => false;\n    },\n\n    mouseMoveDocumentHandler(e) {\n      if (this.cursorDown === false) return;\n      const prevPage = this[this.bar.axis];\n\n      if (!prevPage) return;\n\n      const offset =\n        (this.$el.getBoundingClientRect()[this.bar.direction] -\n          e[this.bar.client]) *\n        -1;\n      const thumbClickPosition = this.$refs.thumb[this.bar.offset] - prevPage;\n      const thumbPositionPercentage =\n        ((offset - thumbClickPosition) * 100) / this.$el[this.bar.offset];\n\n      this.scrollToPx(\n        (thumbPositionPercentage * this.wrap[this.bar.scrollSize]) / 100\n      );\n    },\n\n    scrollToPx(px) {\n      this.wrap[this.bar.scroll] = px;\n    },\n\n    mouseUpDocumentHandler() {\n      this.cursorDown = false;\n      this[this.bar.axis] = 0;\n      off(document, 'mousemove', this.mouseMoveDocumentHandler);\n      document.onselectstart = null;\n    }\n  }\n};\n</script>\n"
  },
  {
    "path": "src/qComponents/QScrollbar/src/QScrollbar.vue",
    "content": "<template>\n  <div :class=\"classes\">\n    <div\n      ref=\"wrap\"\n      class=\"q-scrollbar__wrap\"\n      :class=\"wrapClasses\"\n      @scroll=\"handleScroll\"\n    >\n      <component\n        :is=\"viewTag\"\n        ref=\"resize\"\n        class=\"q-scrollbar__view\"\n        :class=\"viewClass\"\n        :style=\"viewStyle\"\n      >\n        <slot />\n      </component>\n    </div>\n    <q-bar\n      v-show=\"sizeWidth !== ''\"\n      ref=\"xbar\"\n      type=\"horizontal\"\n      :move=\"moveX\"\n      :size=\"sizeWidth\"\n    />\n    <q-bar\n      v-show=\"sizeHeight !== ''\"\n      ref=\"ybar\"\n      type=\"vertical\"\n      :move=\"moveY\"\n      :size=\"sizeHeight\"\n    />\n  </div>\n</template>\n\n<script>\nimport { addResizeListener, removeResizeListener } from '../../helpers';\nimport QBar from './QBar';\n\nconst OFFSET = -10;\n\nexport default {\n  name: 'QScrollbar',\n  componentName: 'QScrollbar',\n\n  components: { QBar },\n\n  props: {\n    /**\n     * passing DOM element will scroll content to it (works dynamically)\n     */\n    scrollTo: {\n      type: HTMLElement,\n      default: null\n    },\n    /**\n     * whether scrollbar is always visible\n     */\n    visible: { type: Boolean, default: false },\n    /**\n     * changes style\n     */\n    theme: {\n      type: String,\n      default: 'primary',\n      validator: value => ['primary', 'secondary'].includes(value)\n    },\n    /**\n     * custom wrapper content class (it helps you to style content)\n     */\n    wrapClass: { type: [Object, String, Array], default: '' },\n    /**\n     * custom inner content tag\n     */\n    viewTag: {\n      type: String,\n      default: 'div'\n    },\n    /**\n     * custom inner content class\n     */\n    viewClass: { type: [Object, String, Array], default: '' },\n    /**\n     * custom inner content class\n     */\n    viewStyle: { type: Object, default: null },\n    /**\n     * whether is resizeListener will watch for parent\n     */\n    noresize: { type: Boolean, default: false }\n  },\n\n  data() {\n    return {\n      sizeWidth: '0',\n      sizeHeight: '0',\n      moveX: 0,\n      moveY: 0\n    };\n  },\n\n  computed: {\n    wrap() {\n      return this.$refs.wrap;\n    },\n\n    classes() {\n      return [\n        'q-scrollbar',\n        this.visible && 'q-scrollbar_visible',\n        this.sizeWidth !== '' && 'q-scrollbar_has-horizontal-bar',\n        this.sizeHeight !== '' && 'q-scrollbar_has-vertical-bar'\n      ];\n    },\n\n    wrapClasses() {\n      return [this.wrapClass, { 'q-scrollbar__wrap_hidden-default': true }];\n    }\n  },\n\n  watch: {\n    scrollTo(element) {\n      if (element) {\n        this.$refs.ybar.scrollToPx(element.offsetTop + OFFSET);\n      }\n    },\n    visible(value) {\n      if (value) {\n        const offset = this.scrollTo?.offsetTop ?? 0 + OFFSET;\n        this.$refs.ybar.scrollToPx(offset);\n      }\n    }\n  },\n\n  mounted() {\n    this.$nextTick(this.update);\n\n    if (!this.noresize) {\n      addResizeListener(this.$refs.resize, this.update);\n      addResizeListener(this.$el.parentNode, this.update);\n    }\n  },\n\n  beforeDestroy() {\n    if (!this.noresize) {\n      removeResizeListener(this.$refs.resize, this.update);\n      removeResizeListener(this.$el.parentNode, this.update);\n    }\n  },\n\n  methods: {\n    /**\n     * @public\n     */\n    handleScroll() {\n      const { wrap } = this;\n\n      this.moveY = (wrap.scrollTop * 100) / wrap.clientHeight;\n      this.moveX = (wrap.scrollLeft * 100) / wrap.clientWidth;\n    },\n\n    /**\n     * @public\n     */\n    update() {\n      const { wrap } = this;\n      if (!wrap) return;\n\n      const heightPercentage = (wrap.clientHeight * 100) / wrap.scrollHeight;\n      const widthPercentage = (wrap.clientWidth * 100) / wrap.scrollWidth;\n\n      this.sizeHeight = heightPercentage < 100 ? `${heightPercentage}%` : '';\n      this.sizeWidth = widthPercentage < 100 ? `${widthPercentage}%` : '';\n    }\n  }\n};\n</script>\n"
  },
  {
    "path": "src/qComponents/QScrollbar/src/q-scrollbar.scss",
    "content": ".q-scrollbar {\n  position: relative;\n  height: 100%;\n  overflow: hidden;\n\n  &_visible,\n  &:hover,\n  &:active,\n  &:focus {\n    > .q-scrollbar__bar {\n      opacity: 1;\n      transition: opacity 340ms ease-out;\n    }\n  }\n\n  &__wrap {\n    height: 100%;\n    overflow: scroll;\n\n    &_hidden-default {\n      scrollbar-width: none;\n\n      &::-webkit-scrollbar {\n        width: 0;\n        height: 0;\n      }\n    }\n  }\n\n  &__view {\n    min-height: 100%;\n  }\n\n  &__thumb {\n    position: relative;\n    display: block;\n    width: 0;\n    height: 0;\n    background-color: var(--color-primary-blue);\n    border-radius: var(--border-radius-base);\n    cursor: pointer;\n    transition: 0.3s background-color;\n\n    &:hover {\n      background-color: var(--color-primary-blue);\n    }\n\n    &_secondary {\n      background-color: rgba(var(--color-rgb-gray), 0.16);\n\n      &:hover,\n      &:active {\n        background-color: rgba(var(--color-rgb-gray), 0.32);\n      }\n    }\n  }\n\n  &__bar {\n    position: absolute;\n    right: 4px;\n    bottom: 4px;\n    z-index: 1;\n    border-radius: var(--border-radius-base);\n    opacity: 0;\n    transition: opacity 120ms ease-out;\n\n    &_vertical {\n      top: 6px;\n      width: 2px;\n\n      > .q-scrollbar__thumb {\n        width: 100%;\n      }\n    }\n\n    &_horizontal {\n      left: 6px;\n      height: 2px;\n\n      > .q-scrollbar__thumb {\n        height: 100%;\n      }\n    }\n\n    &_secondary.q-scrollbar__bar_vertical {\n      width: 8px;\n      background-color: var(--color-tertiary-gray);\n    }\n\n    &_secondary.q-scrollbar__bar_horizontal {\n      height: 8px;\n      background-color: var(--color-tertiary-gray);\n    }\n  }\n}\n"
  },
  {
    "path": "src/qComponents/QScrollbar/src/util.js",
    "content": "export const BAR_MAP = {\n  vertical: {\n    offset: 'offsetHeight',\n    scroll: 'scrollTop',\n    scrollSize: 'scrollHeight',\n    size: 'height',\n    key: 'vertical',\n    axis: 'Y',\n    client: 'clientY',\n    direction: 'top'\n  },\n  horizontal: {\n    offset: 'offsetWidth',\n    scroll: 'scrollLeft',\n    scrollSize: 'scrollWidth',\n    size: 'width',\n    key: 'horizontal',\n    axis: 'X',\n    client: 'clientX',\n    direction: 'left'\n  }\n};\n\nexport function renderThumbStyle({ move, size, bar }) {\n  const style = {};\n  const translate = `translate${bar.axis}(${move}%)`;\n\n  style[bar.size] = size;\n  style.transform = translate;\n  style.msTransform = translate;\n  style.webkitTransform = translate;\n\n  return style;\n}\n"
  },
  {
    "path": "src/qComponents/QSelect/index.js",
    "content": "import QSelect from './src/QSelect.vue';\n\nQSelect.install = function(Vue) {\n  Vue.component(QSelect.name, QSelect);\n};\n\nexport default QSelect;\n"
  },
  {
    "path": "src/qComponents/QSelect/src/QSelect.vue",
    "content": "<template>\n  <div\n    ref=\"reference\"\n    v-click-outside=\"handleOutsideClick\"\n    class=\"q-select\"\n    @click=\"toggleMenu\"\n  >\n    <q-input\n      ref=\"input\"\n      v-model=\"selectedLabel\"\n      type=\"text\"\n      class=\"q-select__input\"\n      :placeholder=\"preparedPlaceholder\"\n      :autocomplete=\"autocomplete\"\n      :disabled=\"isDisabled\"\n      :readonly=\"readonly\"\n      :validate-event=\"false\"\n      :class=\"{ 'q-input_focus': visible }\"\n      :tabindex=\"multiple && filterable ? '-1' : null\"\n      @focus=\"handleFocus\"\n      @blur=\"handleBlur\"\n      @keyup.native=\"onInputChange\"\n      @keyup.native.enter.prevent=\"handleEnterKeyUp\"\n      @keyup.native.esc.stop.prevent=\"visible = false\"\n      @keyup.native.tab=\"visible = false\"\n      @keyup.native.backspace=\"clearSelected\"\n      @paste.native=\"onInputChange\"\n      @mouseenter.native=\"inputHovering = true\"\n      @mouseleave.native=\"inputHovering = false\"\n    >\n      <template #suffix>\n        <span\n          v-show=\"!isClearBtnShown\"\n          class=\"q-select__caret q-input__icon\"\n          :class=\"iconClass\"\n        />\n        <span\n          v-if=\"isClearBtnShown\"\n          class=\"q-select__caret q-input__icon q-icon-close\"\n          @click.stop=\"clearSelected\"\n        />\n      </template>\n    </q-input>\n\n    <q-select-tags\n      v-if=\"multiple && selected\"\n      ref=\"tags\"\n      :collapse-tags=\"collapseTags\"\n      :autocomplete=\"autocomplete\"\n      :selected=\"selected\"\n      :filterable=\"filterable\"\n      :is-disabled=\"isDisabled\"\n      :query.sync=\"query\"\n      @keyup-enter=\"handleEnterKeyUp\"\n      @focus=\"handleFocus\"\n      @remove-tag=\"deleteTag\"\n      @exit=\"visible = false\"\n    />\n\n    <q-select-dropdown\n      ref=\"dropdown\"\n      :multiple=\"multiple\"\n      :shown=\"isDropdownShown\"\n      :width=\"inputWidth\"\n      :options=\"options\"\n      :value=\"value\"\n      :value-key=\"valueKey\"\n      :select-all-shown=\"selectAllShown\"\n      :select-all-text=\"selectAllText || $t('QSelect.selectAll')\"\n      :show-empty-content=\"showEmptyContent\"\n      :empty-text=\"emptyText\"\n      :is-can-load-more-shown=\"isCanLoadMoreShown\"\n      :load-more-text=\"loadMoreText || $t('QSelect.more')\"\n      :query=\"query\"\n      :is-new-option-shown=\"isNewOptionShown\"\n      @select-all=\"emitValueUpdate\"\n    >\n      <slot v-if=\"!loading\" />\n\n      <template\n        v-if=\"$slots.empty\"\n        #empty\n      >\n        <slot name=\"empty\" />\n      </template>\n    </q-select-dropdown>\n  </div>\n</template>\n\n<script>\nimport { isObject, isPlainObject, isNil, isEqual, get } from 'lodash-es';\nimport { createPopper } from '@popperjs/core';\n\nimport QSelectDropdown from './QSelectDropdown';\nimport QSelectTags from './QSelectTags';\nimport { addResizeListener, removeResizeListener } from '../../helpers';\nimport Emitter from '../../mixins/emitter';\n\nexport default {\n  name: 'QSelect',\n  componentName: 'QSelect',\n\n  components: {\n    QSelectTags,\n    QSelectDropdown\n  },\n\n  mixins: [Emitter],\n\n  inject: {\n    qForm: {\n      default: null\n    },\n    qFormItem: {\n      default: null\n    }\n  },\n\n  provide() {\n    return {\n      qSelect: this\n    };\n  },\n\n  props: {\n    /**\n     * binding value\n     */\n    value: {\n      type: [String, Number, Object, Array],\n      default: null\n    },\n    /**\n     * the autocomplete attribute of select input\n     */\n    autocomplete: {\n      type: String,\n      default: 'off'\n    },\n    /**\n     * whether loadMoreText is shown\n     */\n    canLoadMore: {\n      type: Boolean,\n      default: false\n    },\n    /**\n     * whether Select is disabled\n     */\n    disabled: { type: Boolean, default: false },\n    /**\n     * whether select can be cleared\n     */\n    clearable: { type: Boolean, default: false },\n    /**\n     * whether Select is filterable\n     */\n    filterable: { type: Boolean, default: false },\n    /**\n     * whether creating new items is allowed. To use this, `filterable` must be true\n     */\n    allowCreate: { type: Boolean, default: false },\n    /**\n     * whether Select is loading data from server\n     */\n    loading: { type: Boolean, default: false },\n    /**\n     * whether options are loaded from server\n     */\n    remote: { type: Boolean, default: false },\n    /**\n     * text that is shown when `loading` is true\n     */\n    loadingText: {\n      type: String,\n      default: null\n    },\n    /**\n     * text that is shown when `canLoadMore` is true\n     */\n    loadMoreText: {\n      type: String,\n      default: null\n    },\n    /**\n     * text of no match state\n     */\n    noMatchText: {\n      type: String,\n      default: null\n    },\n    /**\n     * text of no data state\n     */\n    noDataText: {\n      type: String,\n      default: null\n    },\n    /**\n     * whether multiple-select is activated\n     */\n    multiple: { type: Boolean, default: false },\n    /**\n     * maximum number of options user can select when `multiple` is true. No `limit` when set to 0\n     */\n    multipleLimit: {\n      type: Number,\n      default: 0\n    },\n    /**\n     * placeholder\n     */\n    placeholder: {\n      type: String,\n      default: ''\n    },\n    /**\n     * whether select all button is shown\n     */\n    selectAllShown: { type: Boolean, default: false },\n    /**\n     * text of select all button\n     */\n    selectAllText: { type: String, default: null },\n    /**\n     * unique identity key name for value, required when value is an object\n     */\n    valueKey: {\n      type: String,\n      default: 'value'\n    },\n    /**\n     * whether to collapse tags to a text when multiple selecting\n     */\n    collapseTags: { type: Boolean, default: false },\n    /**\n     * whether to append the popper menu to body. If the positioning of the popper is wrong, you can try to set this prop to false\n     */\n    appendToBody: { type: Boolean, default: true }\n  },\n\n  data() {\n    return {\n      options: [],\n      selected: this.multiple ? [] : null,\n      inputWidth: 0,\n      visible: false,\n      selectedLabel: '',\n      hoverIndex: 0,\n      query: '',\n      inputHovering: false,\n      menuVisibleOnFocus: false,\n      popper: null,\n      isDropdownShown: false\n    };\n  },\n\n  computed: {\n    preparedPlaceholder() {\n      if (this.query || (this.multiple && this.value?.length)) {\n        return '';\n      }\n\n      if (this.visible && !this.multiple && this.selected) {\n        return this.selected.preparedLabel;\n      }\n\n      return this.placeholder;\n    },\n\n    visibleOptionsCount() {\n      return this.options.filter(({ isVisible }) => isVisible).length;\n    },\n\n    isCanLoadMoreShown() {\n      return this.canLoadMore && !this.loading && this.visibleOptionsCount > 0;\n    },\n\n    showEmptyContent() {\n      return Boolean(\n        this.emptyText &&\n          (!this.allowCreate ||\n            this.loading ||\n            (this.allowCreate && this.options.length === 0))\n      );\n    },\n\n    readonly() {\n      return !this.filterable || this.multiple;\n    },\n\n    isClearBtnShown() {\n      const hasValue = this.multiple\n        ? Array.isArray(this.value) && this.value.length > 0\n        : ![undefined, null, ''].includes(this.value);\n\n      return (\n        this.clearable && !this.isDisabled && this.inputHovering && hasValue\n      );\n    },\n\n    iconClass() {\n      if (this.remote && this.filterable) return 'q-icon-search';\n\n      return this.visible\n        ? 'q-icon-triangle-up q-input__icon_reverse'\n        : 'q-icon-triangle-down';\n    },\n\n    emptyText() {\n      const loadingText = this.loadingText ?? this.$t('QSelect.loading');\n      if (this.loading) return loadingText;\n\n      if (\n        this.filterable &&\n        this.query &&\n        this.options.length > 0 &&\n        this.visibleOptionsCount === 0\n      ) {\n        return this.noMatchText ?? this.$t('QSelect.noMatch');\n      }\n\n      if (this.options.length === 0)\n        return this.noDataText ?? this.$t('QSelect.noData');\n\n      return '';\n    },\n\n    isNewOptionShown() {\n      const hasExistingOption = this.options\n        .filter(({ created }) => !created)\n        .some(({ preparedLabel }) => preparedLabel === this.query);\n\n      return (\n        this.filterable &&\n        this.allowCreate &&\n        this.query !== '' &&\n        !hasExistingOption\n      );\n    },\n\n    isDisabled() {\n      return this.disabled || (this.qForm?.disabled ?? false);\n    }\n  },\n\n  watch: {\n    options() {\n      this.setSelected();\n    },\n\n    value(val, oldVal) {\n      this.setSelected();\n\n      if (!isEqual(val, oldVal)) {\n        this.qFormItem?.validateField('change');\n      }\n    },\n\n    multiple(value) {\n      if (value) this.selectedLabel = '';\n    },\n\n    query(value) {\n      this.hoverIndex = 0;\n\n      /**\n       * use `search` event instead\n       * @deprecated Use `search` event instead.\n       */\n      this.$emit('remote-method', value);\n      /**\n       * use `search` event instead\n       * @deprecated Use `search` event instead.\n       */\n      this.$emit('filter-method', value);\n      /**\n       * triggers when the query changes\n       */\n      this.$emit('search', value);\n    },\n\n    visible(val) {\n      if (!val) {\n        this.$refs.tags?.$refs.input?.blur();\n        this.menuVisibleOnFocus = false;\n        this.hoverIndex = 0;\n\n        if (!this.multiple && this.selected) {\n          this.selectedLabel = this.selected.preparedLabel;\n        } else {\n          this.selectedLabel = '';\n        }\n\n        this.hidePopper();\n      } else {\n        this.query = '';\n        this.showPopper();\n        if (this.filterable) {\n          if (this.multiple) {\n            this.$refs.tags.$refs.input.focus();\n          } else if (this.selectedLabel) {\n            this.selectedLabel = '';\n          }\n        }\n\n        this.$nextTick(this.$refs.dropdown?.$refs.scrollbar?.update);\n      }\n\n      this.$emit('visible-change', val);\n    }\n  },\n\n  created() {\n    if (this.multiple) {\n      if (!Array.isArray(this.value)) this.$emit('input', []);\n    } else if (Array.isArray(this.value)) this.$emit('input', '');\n  },\n\n  mounted() {\n    addResizeListener(this.$el, this.handleResize);\n\n    this.$nextTick(() => {\n      this.inputWidth = this.$el.getBoundingClientRect().width;\n    });\n\n    this.setSelected();\n  },\n\n  beforeDestroy() {\n    if (this.$el) removeResizeListener(this.$el, this.handleResize);\n\n    const dropdown = this.$refs.dropdown?.$el;\n    if (dropdown?.parentNode === document.body) {\n      document.body.removeChild(dropdown);\n    }\n\n    document.removeEventListener('keyup', this.handleKeyUp, true);\n  },\n\n  methods: {\n    handleKeyUp(e) {\n      if (\n        this.$refs.input.$el.querySelector('input') === e.target &&\n        e.key === 'Enter'\n      ) {\n        this.toggleMenu();\n      }\n\n      switch (e.key) {\n        case 'Escape': {\n          this.visible = false;\n          break;\n        }\n        case 'Tab': {\n          if (!this.$refs.reference.contains(document.activeElement)) {\n            this.visible = false;\n          }\n          break;\n        }\n        case 'ArrowRight':\n        case 'ArrowUp':\n        case 'ArrowLeft':\n        case 'ArrowDown':\n        case 'Enter': {\n          this.$refs.dropdown.navigateDropdown(e);\n          break;\n        }\n        default:\n          break;\n      }\n    },\n\n    handleOutsideClick() {\n      this.visible = false;\n    },\n\n    async handleResize() {\n      this.inputWidth = this.$el.getBoundingClientRect().width;\n\n      if (!this.multiple || (this.collapseTags && !this.filterable)) return;\n      await this.$nextTick();\n      this.popper && this.popper.update();\n    },\n\n    createPopper() {\n      const { input, dropdown } = this.$refs;\n\n      if (this.appendToBody) {\n        document.body.appendChild(dropdown.$el);\n      }\n\n      this.popper = createPopper(input.$el, dropdown.$el, {\n        modifiers: [\n          {\n            name: 'offset',\n            options: {\n              offset: [0, 8]\n            }\n          }\n        ]\n      });\n    },\n\n    showPopper() {\n      this.isDropdownShown = true;\n      this.createPopper();\n      document.addEventListener('keyup', this.handleKeyUp, true);\n    },\n\n    hidePopper() {\n      this.isDropdownShown = false;\n      this.query = '';\n\n      if (!this.popper) return;\n\n      this.popper.destroy();\n      this.popper = null;\n      document.removeEventListener('keyup', this.handleKeyUp, true);\n    },\n\n    getKey(value) {\n      return isPlainObject(value) ? get(value, this.valueKey) : value;\n    },\n\n    getOption(value) {\n      if (isNil(value)) return null;\n\n      const keyByValueKey = this.getKey(value);\n      const option = this.options.find(({ key }) => key === keyByValueKey);\n\n      if (option) return option;\n      if (!this.allowCreate) return null;\n\n      const newOption = {\n        value,\n        preparedLabel: isObject(value) ? '' : value ?? ''\n      };\n\n      return newOption;\n    },\n\n    /**\n     * @public\n     */\n    setSelected() {\n      if (this.multiple) {\n        const result = [];\n        if (Array.isArray(this.value)) {\n          this.value.forEach(value => {\n            const option = this.getOption(value);\n\n            if (option) {\n              result.push(option);\n              return;\n            }\n\n            const keyByValueKey = this.getKey(value);\n            const cachedOption = this.selected.find(\n              ({ key }) => key === keyByValueKey\n            );\n            if (cachedOption) result.push(cachedOption);\n          });\n        }\n\n        this.selected = result;\n        return;\n      }\n\n      const option = this.getOption(this.value);\n      if (option) {\n        if (!this.isDropdownShown) this.selectedLabel = option.preparedLabel;\n        this.selected = option;\n        return;\n      }\n\n      const keyByValueKey = this.getKey(this.value);\n      if (this.selected?.key === keyByValueKey) return;\n      if (!this.isDropdownShown) this.selectedLabel = '';\n      this.selected = null;\n    },\n\n    handleFocus(event) {\n      if (this.filterable) {\n        this.visible = true;\n\n        if (this.filterable) {\n          this.menuVisibleOnFocus = true;\n        }\n      }\n\n      this.$emit('focus', event);\n    },\n\n    blur() {\n      this.visible = false;\n      this.$refs.input.blur();\n    },\n\n    handleBlur(event) {\n      setTimeout(() => {\n        this.$emit('blur', event);\n      }, 50);\n    },\n\n    clearSelected() {\n      const value = this.multiple ? [] : null;\n      this.emitValueUpdate(value);\n\n      this.visible = false;\n      this.$emit('clear');\n    },\n\n    getValueIndex(arr = [], value) {\n      const isValueObject = isObject(value);\n      if (!isValueObject) return arr.indexOf(value);\n\n      const valueKey = this.valueKey;\n      const valueByValuekey = get(value, valueKey);\n      return arr.findIndex(item => get(item, valueKey) === valueByValuekey);\n    },\n\n    /**\n     * @public\n     */\n    toggleOptionSelection(option) {\n      if (this.multiple) {\n        const value = [...(this.value ?? [])];\n        const optionIndex = this.getValueIndex(value, option.value);\n        if (optionIndex > -1) {\n          value.splice(optionIndex, 1);\n        } else if (\n          this.multipleLimit <= 0 ||\n          value.length < this.multipleLimit\n        ) {\n          value.push(option.value);\n        }\n\n        this.emitValueUpdate(value);\n        if (option.created) {\n          this.query = '';\n        }\n        if (this.filterable) this.$refs.tags.$refs.input.focus();\n      } else {\n        this.emitValueUpdate(option.value);\n        this.visible = false;\n      }\n    },\n\n    toggleMenu() {\n      if (this.isDisabled) return;\n\n      if (this.menuVisibleOnFocus) {\n        this.menuVisibleOnFocus = false;\n      } else {\n        this.visible = !this.visible;\n      }\n\n      if (this.visible) {\n        (this.$refs.tags?.$refs.input ?? this.$refs.input).focus();\n      }\n    },\n\n    handleEnterKeyUp() {\n      if (!this.visible) {\n        this.toggleMenu();\n        return;\n      }\n\n      let option = null;\n      if (this.isNewOptionShown) {\n        option = this.options.find(({ created }) => created);\n      } else {\n        option = this.options[this.hoverIndex];\n      }\n\n      if (option?.isVisible) {\n        this.toggleOptionSelection(option);\n      }\n    },\n\n    deleteTag(tag) {\n      if (this.isDisabled) return;\n\n      const index = this.selected.findIndex(({ key }) => key === tag.key);\n      if (index === -1) return;\n\n      const value = [...this.value];\n      value.splice(index, 1);\n\n      this.emitValueUpdate(value);\n      this.$emit('remove-tag', tag.value);\n    },\n\n    onInputChange() {\n      if (this.filterable && this.query !== this.selectedLabel) {\n        this.query = this.selectedLabel;\n      }\n    },\n\n    emitValueUpdate(value) {\n      this.$emit('input', value);\n      if (!isEqual(this.value, value)) this.$emit('change', value);\n    }\n  }\n};\n</script>\n"
  },
  {
    "path": "src/qComponents/QSelect/src/QSelectDropdown.vue",
    "content": "<template>\n  <div\n    class=\"q-select-dropdown\"\n    :class=\"{\n      'q-select-dropdown_multiple': multiple,\n      'q-select-dropdown_shown': shown\n    }\"\n    :style=\"styles\"\n  >\n    <q-scrollbar\n      ref=\"scrollbar\"\n      wrap-class=\"q-select-dropdown__wrap\"\n    >\n      <div\n        v-if=\"selectAllShown && isVisibleOptionExist && multiple\"\n        tabindex=\"-1\"\n        class=\"q-option q-option_with-checkbox q-option_all\"\n        @click.stop=\"handleSelectAllClick\"\n      >\n        <q-checkbox\n          root-tag=\"div\"\n          input-tab-index=\"-1\"\n          :value=\"areAllSelected\"\n          :indeterminate=\"isIndeterminate\"\n        />\n\n        <div class=\"q-option__label\">{{ selectAllText }}</div>\n      </div>\n\n      <q-option\n        v-if=\"isNewOptionShown\"\n        :value=\"query\"\n        :label=\"query\"\n        created\n      />\n\n      <slot />\n    </q-scrollbar>\n\n    <template v-if=\"showEmptyContent\">\n      <slot\n        v-if=\"$slots.empty\"\n        name=\"empty\"\n      />\n      <div\n        v-else\n        class=\"q-select-dropdown__empty\"\n      >{{ emptyText }}</div>\n    </template>\n\n    <div\n      v-else-if=\"isCanLoadMoreShown\"\n      class=\"q-select-dropdown__empty\"\n    >\n      {{ loadMoreText }}\n    </div>\n  </div>\n</template>\n\n<script>\nimport { get, isPlainObject } from 'lodash-es';\n\nexport default {\n  name: 'QSelectDropdown',\n  componentName: 'QSelectDropdown',\n\n  inject: ['qSelect'],\n\n  props: {\n    shown: { type: Boolean, required: true },\n    multiple: { type: Boolean, required: true },\n    selectAllShown: { type: Boolean, required: true },\n    selectAllText: { type: String, required: true },\n    showEmptyContent: { type: Boolean, required: true },\n    emptyText: { type: String, required: true },\n    isCanLoadMoreShown: { type: Boolean, required: true },\n    loadMoreText: { type: String, required: true },\n    query: { type: String, required: true },\n    isNewOptionShown: { type: Boolean, required: true },\n    options: { type: Array, required: true },\n    value: { type: [String, Number, Object, Array], default: null },\n    valueKey: { type: String, required: true },\n    width: {\n      type: Number,\n      default: null\n    }\n  },\n\n  data() {\n    return {\n      zIndex: this.$Q?.zIndex ?? 2000\n    };\n  },\n\n  computed: {\n    styles() {\n      return {\n        zIndex: this.zIndex,\n        width: this.width ? `${this.width}px` : null\n      };\n    },\n\n    isVisibleOptionExist() {\n      return this.options.some(({ isVisible }) => isVisible);\n    },\n\n    areAllSelected() {\n      return (\n        this.multiple &&\n        this.isVisibleOptionExist &&\n        this.options\n          .filter(({ isDisabled, isVisible }) => !isDisabled && isVisible)\n          .every(({ isSelected }) => isSelected)\n      );\n    },\n\n    isIndeterminate() {\n      return (\n        this.multiple &&\n        this.isVisibleOptionExist &&\n        !this.areAllSelected &&\n        this.options.some(\n          ({ isVisible, isSelected }) => isVisible && isSelected\n        )\n      );\n    }\n  },\n\n  watch: {\n    shown(value) {\n      if (!value) return;\n\n      const zIndex = this.$Q?.zIndex;\n      if (zIndex) this.zIndex = zIndex;\n    }\n  },\n\n  methods: {\n    navigateDropdown(e) {\n      if (\n        ['ArrowDown', 'ArrowUp'].includes(e.key) &&\n        e.target instanceof HTMLInputElement\n      ) {\n        const firstNode = this.$el.querySelector(`.q-option`);\n        firstNode?.focus();\n      }\n\n      if (!e.target.classList.contains('q-option')) return;\n      const availableOptions = this.options.filter(\n        ({ isDisabled, isVisible }) => !isDisabled && isVisible\n      );\n      const availableElements = availableOptions.map(option => option.$el);\n      let currentNodeIndex;\n      let nextNodeIndex;\n      availableElements.forEach((element, index) => {\n        if (document.activeElement === element) {\n          currentNodeIndex = index;\n        }\n      });\n\n      switch (e.key) {\n        case 'ArrowUp':\n        case 'ArrowLeft':\n          nextNodeIndex = currentNodeIndex - 1;\n          break;\n\n        case 'Tab':\n          this.qSelect.visible = false;\n          break;\n\n        case 'ArrowDown':\n        case 'ArrowRight':\n          nextNodeIndex = currentNodeIndex + 1;\n          break;\n\n        case 'Enter': {\n          this.qSelect.toggleOptionSelection(\n            availableOptions[currentNodeIndex]\n          );\n          break;\n        }\n        default:\n          break;\n      }\n\n      const node = availableElements[nextNodeIndex];\n\n      node?.focus();\n    },\n    handleSelectAllClick() {\n      if (this.areAllSelected) {\n        const keysToRemove = this.options\n          .filter(({ isVisible, disabled }) => !disabled && isVisible)\n          .map(({ key }) => key);\n\n        const getKey = value => {\n          return isPlainObject(value) ? get(value, this.valueKey) : value;\n        };\n\n        this.$emit(\n          'select-all',\n          this.value.filter(value => !keysToRemove.includes(getKey(value)))\n        );\n        return;\n      }\n\n      let newValue = this.options\n        .filter(({ isSelected, disabled }) => !disabled && !isSelected)\n        .map(({ value }) => value);\n\n      const currentFieldValue = this.value;\n      const { multipleLimit } = this.qSelect;\n\n      if (multipleLimit) {\n        const availableQuantity = multipleLimit - currentFieldValue.length;\n\n        if (availableQuantity < newValue.length) {\n          newValue = newValue.splice(0, availableQuantity);\n        }\n      }\n\n      this.$emit('select-all', [...currentFieldValue, ...newValue]);\n    }\n  }\n};\n</script>\n"
  },
  {
    "path": "src/qComponents/QSelect/src/QSelectTags.vue",
    "content": "<template>\n  <div\n    class=\"q-select-tags\"\n    :class=\"{\n      'q-select-tags_filterable': filterable,\n      'q-select-tags_collapse-tags': collapseTags\n    }\"\n  >\n    <template v-if=\"collapseTags && selected.length\">\n      <q-tag\n        :closable=\"!isDisabled\"\n        @close=\"handleTagClose(selected[0])\"\n      >\n        {{ selected[0].preparedLabel }}\n      </q-tag>\n      <q-tag\n        v-if=\"selected.length > 1\"\n        :closable=\"false\"\n      >\n        + {{ selected.length - 1 }}\n      </q-tag>\n    </template>\n\n    <template v-if=\"!collapseTags\">\n      <q-tag\n        v-for=\"option in selected\"\n        :key=\"option.key\"\n        :closable=\"!isDisabled\"\n        @close=\"handleTagClose(option)\"\n      >\n        {{ option.preparedLabel }}\n      </q-tag>\n    </template>\n\n    <input\n      v-if=\"filterable && !isDisabled\"\n      ref=\"input\"\n      :value=\"query\"\n      type=\"text\"\n      class=\"q-select-tags__input\"\n      :autocomplete=\"autocomplete\"\n      @focus=\"$emit('focus')\"\n      @keyup.esc.stop.prevent=\"emitExit\"\n      @keyup.enter.prevent=\"$emit('keyup-enter')\"\n      @keydown.backspace.capture=\"handleBackspaceKeyDown\"\n      @input=\"handleInput\"\n    />\n  </div>\n</template>\n\n<script>\nexport default {\n  name: 'QSelectTags',\n  componentName: 'QSelectTags',\n\n  inject: ['qSelect'],\n\n  props: {\n    collapseTags: { type: Boolean, required: true },\n    filterable: { type: Boolean, required: true },\n    isDisabled: { type: Boolean, required: true },\n    autocomplete: { type: String, required: true },\n    query: { type: String, required: true },\n    selected: { type: [Array, Object], required: true }\n  },\n\n  methods: {\n    handleBackspaceKeyDown() {\n      if (!this.query) {\n        this.$emit('remove-tag', this.selected[this.selected.length - 1]);\n      }\n    },\n\n    handleTagClose(option) {\n      this.$emit('remove-tag', option);\n    },\n\n    emitExit() {\n      this.$emit('exit');\n    },\n\n    handleInput({ target }) {\n      this.$emit('update:query', target.value);\n    }\n  }\n};\n</script>\n"
  },
  {
    "path": "src/qComponents/QSelect/src/q-select-dropdown.scss",
    "content": ".q-select-dropdown {\n  --dropdown-max-height: 204px;\n  --dropdown-box-shadow-base: var(--box-shadow-primary);\n  --dropdown-background-color-base: var(--color-tertiary-gray-light);\n\n  position: absolute;\n  z-index: 1001;\n  display: none;\n  width: 100%;\n  overflow: hidden;\n  background-color: var(--dropdown-background-color-base);\n  border-radius: var(--border-radius-base);\n  box-shadow: var(--dropdown-box-shadow-base);\n\n  &_shown {\n    display: block;\n  }\n\n  &__empty {\n    margin: 0;\n    padding: 10px 16px 8px;\n    color: rgba(var(--color-rgb-gray), 0.64);\n  }\n\n  &__wrap {\n    max-height: var(--dropdown-max-height);\n  }\n}\n"
  },
  {
    "path": "src/qComponents/QSelect/src/q-select-tags.scss",
    "content": ".q-select-tags {\n  --field-color-base: var(--color-primary-black);\n\n  display: flex;\n  flex-wrap: wrap;\n  align-items: center;\n  width: calc(100% - 40px);\n\n  padding: 8px 0 8px 8px;\n  white-space: normal;\n  pointer-events: none;\n\n  &_filterable {\n    &:not(.q-select-tags_collapse-tags) {\n      .q-tag:last-of-type {\n        max-width: 65%;\n      }\n    }\n  }\n\n  &.q-select-tags_collapse-tags {\n    flex-wrap: nowrap;\n\n    .q-tag + .q-tag {\n      flex-shrink: 0;\n    }\n  }\n\n  &__input {\n    z-index: 1;\n    flex: 1;\n    min-width: 24px;\n    height: 20px;\n    padding: 0;\n    font-weight: var(--font-weight-base);\n    font-size: var(--font-size-base);\n    line-height: var(--line-height-base);\n    color: var(--field-color-base);\n    background-color: transparent;\n    border: none;\n    outline: none;\n    appearance: none;\n\n    &:first-child {\n      margin-left: 8px;\n    }\n  }\n}\n"
  },
  {
    "path": "src/qComponents/QSelect/src/q-select.scss",
    "content": "@import './q-select-tags';\n@import './q-select-dropdown';\n\n.q-select {\n  position: relative;\n  display: inline-flex;\n  width: 100%;\n  min-height: 40px;\n  vertical-align: middle;\n\n  &__input {\n    position: absolute;\n    top: 0;\n    left: 0;\n    width: 100%;\n    height: 100%;\n\n    .q-input__inner {\n      height: 100%;\n      user-select: none;\n    }\n  }\n}\n"
  },
  {
    "path": "src/qComponents/QSlider/index.js",
    "content": "import QSlider from './src/QSlider.vue';\n\nQSlider.install = function(Vue) {\n  Vue.component(QSlider.name, QSlider);\n};\n\nexport default QSlider;\n"
  },
  {
    "path": "src/qComponents/QSlider/src/QSlider.vue",
    "content": "<template>\n  <div\n    class=\"q-slider\"\n    :class=\"wrapperClasses\"\n    :style=\"wrapperStyles\"\n  >\n    <div\n      ref=\"path\"\n      class=\"q-slider__path\"\n      @click=\"handlePathClick\"\n    >\n      <q-slider-button\n        ref=\"startBtn\"\n        v-model=\"startValue\"\n        :show-tooltip=\"showTooltip\"\n        :min=\"min\"\n        :max=\"max\"\n        :step=\"step\"\n        :format-tooltip=\"formatTooltip\"\n        :vertical=\"vertical\"\n        :disabled=\"isDisabled\"\n        @dragging=\"handleButtonDragging\"\n        @change=\"emitChange\"\n      />\n\n      <q-slider-bar\n        :range=\"range\"\n        :vertical=\"vertical\"\n        :min=\"min\"\n        :max=\"max\"\n        :min-value=\"minValue\"\n        :max-value=\"maxValue\"\n        :start-value=\"startValue\"\n      />\n\n      <q-slider-button\n        v-if=\"range\"\n        ref=\"endBtn\"\n        v-model=\"endValue\"\n        :show-tooltip=\"showTooltip\"\n        :min=\"min\"\n        :max=\"max\"\n        :step=\"step\"\n        :format-tooltip=\"formatTooltip\"\n        :vertical=\"vertical\"\n        :disabled=\"isDisabled\"\n        @dragging=\"handleButtonDragging\"\n        @change=\"emitChange\"\n      />\n\n      <q-slider-steps\n        v-if=\"showSteps\"\n        :vertical=\"vertical\"\n        :min=\"min\"\n        :max=\"max\"\n        :step=\"step\"\n      />\n    </div>\n\n    <q-slider-captions\n      v-if=\"captions\"\n      :vertical=\"vertical\"\n      :captions=\"captions\"\n      :min=\"min\"\n      :max=\"max\"\n      :start-value=\"startValue\"\n      :end-value=\"endValue\"\n      @change=\"handleCaptionChange\"\n    />\n  </div>\n</template>\n\n<script>\nimport QSliderBar from './components/QSliderBar';\nimport QSliderButton from './components/QSliderButton';\nimport QSliderSteps from './components/QSliderSteps';\nimport QSliderCaptions from './components/QSliderCaptions';\n\nexport default {\n  name: 'QSlider',\n\n  components: {\n    QSliderBar,\n    QSliderButton,\n    QSliderSteps,\n    QSliderCaptions\n  },\n\n  inject: {\n    qForm: {\n      default: null\n    },\n\n    qFormItem: {\n      default: null\n    }\n  },\n\n  props: {\n    /**\n     * binding value\n     */\n    value: {\n      type: [Number, Array],\n      default: null\n    },\n\n    /**\n     * minimum value\n     */\n    min: {\n      type: Number,\n      default: 0\n    },\n\n    /**\n     * maximum value\n     */\n    max: {\n      type: Number,\n      default: 100\n    },\n\n    /**\n     * step size\n     */\n    step: {\n      type: Number,\n      default: 1\n    },\n\n    /**\n     * whether to display breakpoints\n     */\n    showSteps: {\n      type: Boolean,\n      default: false\n    },\n\n    /**\n     * whether to display tooltip value\n     */\n    showTooltip: {\n      type: Boolean,\n      default: true\n    },\n\n    /**\n     * format to display tooltip value\n     */\n    formatTooltip: {\n      type: Function,\n      default: null\n    },\n\n    /**\n     * object consisting of a key and a value for quick selection\n     */\n    captions: {\n      type: Object,\n      default: null\n    },\n\n    /**\n     * whether Slider is disabled\n     */\n    disabled: {\n      type: Boolean,\n      default: false\n    },\n\n    /**\n     * whether to select a range\n     */\n    range: {\n      type: Boolean,\n      default: false\n    },\n\n    /**\n     * vertical mode\n     */\n    vertical: {\n      type: Boolean,\n      default: false\n    },\n\n    /**\n     * Slider height, required in vertical mode\n     */\n    height: {\n      type: String,\n      default: null\n    }\n  },\n\n  data() {\n    return {\n      startValue: null,\n      endValue: null,\n      oldValue: null,\n      isDragging: false\n    };\n  },\n\n  computed: {\n    isDisabled() {\n      return this.disabled || (this.qForm?.disabled ?? false);\n    },\n\n    wrapperClasses() {\n      return {\n        'q-slider_is-vertical': this.vertical,\n        'q-slider_is-disabled': this.isDisabled\n      };\n    },\n\n    minValue() {\n      return Math.min(this.startValue, this.endValue);\n    },\n\n    maxValue() {\n      return Math.max(this.startValue, this.endValue);\n    },\n\n    wrapperStyles() {\n      return this.vertical ? { height: this.height } : {};\n    },\n\n    isValueChanged() {\n      if (this.range) {\n        return ![this.minValue, this.maxValue].every(\n          (value, index) => value === this.oldValue[index]\n        );\n      }\n      return this.value !== this.oldValue;\n    }\n  },\n\n  watch: {\n    value(val, oldVal) {\n      if (\n        this.isDragging ||\n        (Array.isArray(val) &&\n          Array.isArray(oldVal) &&\n          val.every((item, i) => item === oldVal[i]))\n      ) {\n        return;\n      }\n\n      this.setValues();\n    },\n\n    isDragging(val) {\n      if (val) return;\n      this.setValues();\n    },\n\n    startValue(val) {\n      const values = this.range ? [this.minValue, this.maxValue] : val;\n      this.$emit('input', values);\n    },\n\n    endValue() {\n      if (!this.range) return;\n      this.$emit('input', [this.minValue, this.maxValue]);\n    },\n\n    range(value) {\n      if (!value) return;\n      this.endValue = this.max;\n    },\n\n    min() {\n      this.setValues();\n    },\n\n    max() {\n      this.setValues();\n    }\n  },\n\n  mounted() {\n    this.setupValues();\n  },\n\n  methods: {\n    setupValues() {\n      if (this.range) {\n        if (Array.isArray(this.value)) {\n          this.startValue = Math.max(this.min, this.value[0]);\n          this.endValue = Math.min(this.max, this.value[1]);\n        } else {\n          this.startValue = this.min;\n          this.endValue = this.max;\n        }\n\n        this.oldValue = [this.startValue, this.endValue];\n      } else {\n        if (typeof this.value !== 'number' || Number.isNaN(this.value)) {\n          this.startValue = this.min;\n        } else {\n          this.startValue = Math.min(this.max, Math.max(this.min, this.value));\n        }\n\n        this.oldValue = this.startValue;\n      }\n    },\n\n    setValues() {\n      if (this.min > this.max) return;\n\n      let emitValue;\n\n      if (this.range && Array.isArray(this.value)) {\n        if (this.value[1] < this.min) {\n          emitValue = [this.min, this.min];\n        } else if (this.value[0] > this.max) {\n          emitValue = [this.max, this.max];\n        } else if (this.value[0] < this.min) {\n          emitValue = [this.min, this.value[1]];\n        } else if (this.value[1] > this.max) {\n          emitValue = [this.value[0], this.max];\n        } else {\n          this.startValue = this.value[0];\n          this.endValue = this.value[1];\n\n          if (this.isValueChanged) {\n            this.qFormItem?.validateField('change', [\n              this.minValue,\n              this.maxValue\n            ]);\n            this.oldValue = this.value.slice();\n          }\n        }\n      } else if (typeof this.value === 'number' && !Number.isNaN(this.value)) {\n        if (this.value < this.min) {\n          emitValue = this.min;\n        } else if (this.value > this.max) {\n          emitValue = this.max;\n        } else {\n          this.startValue = this.value;\n\n          if (this.isValueChanged) {\n            this.qFormItem?.validateField('change', this.value);\n            this.oldValue = this.value;\n          }\n        }\n      }\n\n      this.$emit('input', emitValue);\n    },\n\n    getPathSize() {\n      return this.$refs.path.getBoundingClientRect();\n    },\n\n    getNearestButton(value) {\n      if (Math.abs(this.minValue - value) < Math.abs(this.maxValue - value)) {\n        return this.startValue < this.endValue ? 'startBtn' : 'endBtn';\n      }\n\n      return this.startValue > this.endValue ? 'startBtn' : 'endBtn';\n    },\n\n    setPosition(percent) {\n      const targetValue = this.min + (percent * (this.max - this.min)) / 100;\n\n      if (!this.range) {\n        this.$refs.startBtn.setPosition(percent);\n        return;\n      }\n\n      const currentBtn = this.getNearestButton(targetValue);\n      this.$refs[currentBtn].setPosition(percent);\n    },\n\n    emitChange() {\n      this.$nextTick(() => {\n        this.$emit(\n          'change',\n          this.range ? [this.minValue, this.maxValue] : this.value\n        );\n        this.qFormItem?.validateField('change');\n      });\n    },\n\n    handlePathClick({ clientX, clientY }) {\n      if (this.isDisabled || this.isDragging) return;\n\n      const { width, height, bottom, left } = this.getPathSize();\n\n      if (this.vertical) {\n        this.setPosition(((bottom - clientY) / height) * 100);\n      } else {\n        this.setPosition(((clientX - left) / width) * 100);\n      }\n\n      this.emitChange();\n    },\n\n    handleCaptionChange(value) {\n      if (this.isDisabled) return;\n\n      if (!this.range) {\n        this.startValue = value;\n        return;\n      }\n\n      if (this.getNearestButton(value) === 'startBtn') {\n        this.startValue = value;\n      } else {\n        this.endValue = value;\n      }\n    },\n\n    handleButtonDragging(value) {\n      this.isDragging = value;\n    }\n  }\n};\n</script>\n"
  },
  {
    "path": "src/qComponents/QSlider/src/components/QSliderBar/index.vue",
    "content": "<template>\n  <div\n    class=\"q-slider-bar\"\n    :style=\"barStyle\"\n  />\n</template>\n\n<script>\nexport default {\n  name: 'QSliderBar',\n\n  props: {\n    range: {\n      type: Boolean,\n      default: false\n    },\n\n    vertical: {\n      type: Boolean,\n      default: false\n    },\n\n    min: {\n      type: Number,\n      default: 0\n    },\n\n    max: {\n      type: Number,\n      default: 100\n    },\n\n    minValue: {\n      type: Number,\n      default: null\n    },\n\n    maxValue: {\n      type: Number,\n      default: null\n    },\n\n    startValue: {\n      type: Number,\n      default: null\n    }\n  },\n\n  computed: {\n    barSize() {\n      return this.range\n        ? `${(100 * (this.maxValue - this.minValue)) / (this.max - this.min)}%`\n        : `${(100 * (this.startValue - this.min)) / (this.max - this.min)}%`;\n    },\n\n    barStart() {\n      return this.range\n        ? `${(100 * (this.minValue - this.min)) / (this.max - this.min)}%`\n        : '0%';\n    },\n\n    barStyle() {\n      if (this.vertical) {\n        return {\n          height: this.barSize,\n          bottom: this.barStart\n        };\n      }\n\n      return {\n        width: this.barSize,\n        left: this.barStart\n      };\n    }\n  }\n};\n</script>\n"
  },
  {
    "path": "src/qComponents/QSlider/src/components/QSliderButton/index.vue",
    "content": "<template>\n  <button\n    type=\"button\"\n    :tabindex=\"tabIndex\"\n    class=\"q-slider-button\"\n    :class=\"btnClasses\"\n    :style=\"wrapperStyle\"\n    @keydown.left.prevent=\"handleKeyDown\"\n    @keydown.right.prevent=\"handleKeyDown\"\n    @keydown.down.prevent=\"handleKeyDown\"\n    @keydown.up.prevent=\"handleKeyDown\"\n    @mousedown=\"handleButtonDown\"\n  >\n    <div class=\"q-slider-button__target\" />\n    <div\n      v-if=\"showTooltip\"\n      class=\"q-slider-button__tooltip\"\n    >\n      {{ formattedValue }}\n    </div>\n  </button>\n</template>\n\n<script>\nexport default {\n  name: 'QSliderButton',\n\n  props: {\n    tabIndex: {\n      type: Number,\n      default: 0\n    },\n\n    showTooltip: {\n      type: Boolean,\n      default: true\n    },\n\n    min: {\n      type: Number,\n      default: 0\n    },\n\n    max: {\n      type: Number,\n      default: 100\n    },\n\n    step: {\n      type: Number,\n      default: 1\n    },\n\n    formatTooltip: {\n      type: Function,\n      default: null\n    },\n\n    vertical: {\n      type: Boolean,\n      default: false\n    },\n\n    disabled: {\n      type: Boolean,\n      default: false\n    },\n\n    value: {\n      type: Number,\n      default: 0\n    }\n  },\n\n  data() {\n    return {\n      isDragging: false,\n      isClick: false,\n      clientX: 0,\n      currentX: 0,\n      clientY: 0,\n      currentY: 0,\n      startPosition: 0,\n      newPosition: null,\n      oldValue: this.value\n    };\n  },\n\n  computed: {\n    btnClasses() {\n      return {\n        'q-slider-button_show-tooltip': this.isDragging\n      };\n    },\n\n    currentPosition() {\n      return `${((this.value - this.min) / (this.max - this.min)) * 100}%`;\n    },\n\n    formattedValue() {\n      return (\n        (this.formatTooltip && this.formatTooltip(this.value)) || this.value\n      );\n    },\n\n    wrapperStyle() {\n      return this.vertical\n        ? { bottom: this.currentPosition }\n        : { left: this.currentPosition };\n    },\n\n    precision() {\n      const precisionsList = [this.min, this.max, this.step].map(value => {\n        const decimal = String(value).split('.')[1];\n        return decimal ? decimal.length : 0;\n      });\n\n      return Math.max.apply(null, precisionsList);\n    }\n  },\n\n  watch: {\n    isDragging(value) {\n      this.$emit('dragging', value);\n    }\n  },\n\n  beforeDestroy() {\n    document.removeEventListener('mousemove', this.handleDragging);\n    document.removeEventListener('mouseup', this.handleDragEnd);\n    document.removeEventListener('contextmenu', this.handleDragEnd);\n  },\n\n  methods: {\n    setPosition(value) {\n      if (value === null || Number.isNaN(value)) return;\n\n      let newPosition = value;\n      if (newPosition < 0) {\n        newPosition = 0;\n      } else if (newPosition > 100) {\n        newPosition = 100;\n      }\n\n      const lengthPerStep = 100 / ((this.max - this.min) / this.step);\n      const steps = Math.round(newPosition / lengthPerStep);\n\n      let result =\n        steps * lengthPerStep * (this.max - this.min) * 0.01 + this.min;\n      result = parseFloat(result.toFixed(this.precision));\n      this.$emit('input', result);\n\n      if (!this.isDragging && this.value !== this.oldValue) {\n        this.oldValue = this.value;\n      }\n    },\n\n    handleButtonDown(event) {\n      if (this.disabled) return;\n\n      event.preventDefault();\n\n      this.handleDragStart(event);\n\n      document.addEventListener('mousemove', this.handleDragging);\n      document.addEventListener('mouseup', this.handleDragEnd);\n      document.addEventListener('contextmenu', this.handleDragEnd);\n    },\n\n    handleDragging({ clientX, clientY }) {\n      if (!this.isDragging) return;\n\n      this.isClick = false;\n\n      const { width, height } = this.$parent.getPathSize();\n\n      let diff = 0;\n      if (this.vertical) {\n        this.currentY = clientY;\n        diff = ((this.clientY - this.currentY) / height) * 100;\n      } else {\n        this.currentX = clientX;\n        diff = ((this.currentX - this.clientX) / width) * 100;\n      }\n\n      this.newPosition = this.startPosition + diff;\n      this.setPosition(this.newPosition);\n    },\n\n    handleKeyDown({ key }) {\n      if (this.disabled) return;\n\n      if (key === 'ArrowLeft' || key === 'ArrowDown') {\n        this.newPosition =\n          parseFloat(this.currentPosition) -\n          (this.step / (this.max - this.min)) * 100;\n      } else {\n        this.newPosition =\n          parseFloat(this.currentPosition) +\n          (this.step / (this.max - this.min)) * 100;\n      }\n\n      this.setPosition(this.newPosition);\n      this.$emit('change');\n    },\n\n    handleDragStart({ clientX, clientY }) {\n      this.isDragging = true;\n      this.isClick = true;\n\n      if (this.vertical) {\n        this.clientY = clientY;\n      } else {\n        this.clientX = clientX;\n      }\n\n      this.startPosition = parseFloat(this.currentPosition);\n      this.newPosition = this.startPosition;\n    },\n\n    handleDragEnd() {\n      if (!this.isDragging) return;\n\n      this.$nextTick(() => {\n        this.isDragging = false;\n\n        if (!this.isClick) {\n          this.setPosition(this.newPosition);\n          this.$emit('change');\n        }\n      });\n\n      document.removeEventListener('mousemove', this.handleDragging);\n      document.removeEventListener('mouseup', this.handleDragEnd);\n      document.removeEventListener('contextmenu', this.handleDragEnd);\n    }\n  }\n};\n</script>\n"
  },
  {
    "path": "src/qComponents/QSlider/src/components/QSliderCaptions/index.vue",
    "content": "<template>\n  <div class=\"q-slider-captions\">\n    <button\n      v-for=\"(caption, index) in captionsList\"\n      :key=\"index\"\n      type=\"button\"\n      class=\"q-slider-captions__btn\"\n      :class=\"getBtnClasses(caption.value)\"\n      :style=\"getBtnStyles(caption.position)\"\n      @click=\"handleCaptionLabelClick(caption.value)\"\n    >\n      {{ caption.label }}\n    </button>\n  </div>\n</template>\n\n<script>\nexport default {\n  name: 'QSliderCaptions',\n\n  props: {\n    vertical: {\n      type: Boolean,\n      default: false\n    },\n\n    captions: {\n      type: Object,\n      default: null\n    },\n\n    min: {\n      type: Number,\n      default: 0\n    },\n\n    max: {\n      type: Number,\n      default: 100\n    },\n\n    startValue: {\n      type: Number,\n      default: null\n    },\n\n    endValue: {\n      type: Number,\n      default: null\n    }\n  },\n\n  computed: {\n    captionsList() {\n      if (!this.captions) return [];\n\n      return Object.keys(this.captions)\n        .map(parseFloat)\n        .filter(value => value <= this.max && value >= this.min)\n        .map(value => ({\n          value,\n          position: ((value - this.min) * 100) / (this.max - this.min),\n          label: this.captions[value]\n        }));\n    }\n  },\n\n  methods: {\n    getBtnStyles(position) {\n      return this.vertical\n        ? { bottom: `${position}%` }\n        : { left: `${position}%` };\n    },\n\n    getBtnClasses(value) {\n      return value === this.startValue || value === this.endValue\n        ? 'q-slider-captions__btn_selected'\n        : null;\n    },\n\n    handleCaptionLabelClick(value) {\n      this.$emit('change', value);\n    }\n  }\n};\n</script>\n"
  },
  {
    "path": "src/qComponents/QSlider/src/components/QSliderSteps/index.vue",
    "content": "<template>\n  <div class=\"q-slider-steps\">\n    <div\n      v-for=\"(stepItem, key) in stepsList\"\n      :key=\"key\"\n      class=\"q-slider-steps__step\"\n      :style=\"getStopStyle(stepItem)\"\n    />\n  </div>\n</template>\n\n<script>\nexport default {\n  name: 'QSliderSteps',\n\n  props: {\n    vertical: {\n      type: Boolean,\n      default: false\n    },\n\n    min: {\n      type: Number,\n      default: 0\n    },\n\n    max: {\n      type: Number,\n      default: 100\n    },\n\n    step: {\n      type: Number,\n      default: 1\n    }\n  },\n\n  computed: {\n    stepsCount() {\n      return (this.max - this.min) / this.step;\n    },\n\n    stepsWidth() {\n      return (100 * this.step) / (this.max - this.min);\n    },\n\n    stepsList() {\n      if (this.min > this.max) return [];\n\n      return Array.from(\n        { length: this.stepsCount + 1 },\n        (_, item) => item * this.stepsWidth\n      );\n    }\n  },\n\n  methods: {\n    getStopStyle(position) {\n      return this.vertical\n        ? { bottom: `${position}%` }\n        : { left: `${position}%` };\n    }\n  }\n};\n</script>\n"
  },
  {
    "path": "src/qComponents/QSlider/src/q-slider.scss",
    "content": "@import './styles/q-slider.scss';\n@import './styles/q-slider-bar.scss';\n@import './styles/q-slider-button.scss';\n@import './styles/q-slider-steps.scss';\n@import './styles/q-slider-captions.scss';\n"
  },
  {
    "path": "src/qComponents/QSlider/src/styles/q-slider-bar.scss",
    "content": ".q-slider-bar {\n  position: absolute;\n  z-index: 1;\n  height: 8px;\n  background-color: rgba(var(--color-rgb-red), 0.32);\n  border-radius: 3px;\n}\n"
  },
  {
    "path": "src/qComponents/QSlider/src/styles/q-slider-button.scss",
    "content": ".q-slider-button {\n  position: absolute;\n  top: 50%;\n  z-index: 2;\n  display: flex;\n  justify-content: center;\n  align-items: center;\n  padding: 0;\n  line-height: normal;\n  text-align: center;\n  background-color: transparent;\n  border: none;\n  transform: translate(-50%, -50%);\n  user-select: none;\n\n  &__target {\n    width: 16px;\n    height: 16px;\n    background-color: var(--color-tertiary-gray-light);\n    border-radius: 50%;\n    box-shadow: -4px -4px 12px var(--color-tertiary-white),\n      4px 4px 8px rgba(var(--color-rgb-blue), 0.4),\n      1px 1px 3px rgba(var(--color-rgb-blue), 0.4),\n      -1px -1px 3px rgba(var(--color-rgb-white), 0.25);\n    user-select: none;\n  }\n\n  &__tooltip {\n    position: absolute;\n    bottom: calc(100% + 8px);\n    display: none;\n    min-width: 24px;\n    padding: 5px 4px;\n    font-weight: var(--font-weight-base);\n    text-align: center;\n    color: var(--color-primary-black);\n    white-space: nowrap;\n    background-color: var(--color-tertiary-gray-lighter);\n    border-radius: var(--border-radius-base);\n    box-shadow: var(--box-shadow-secondary);\n  }\n\n  &:hover,\n  &:focus,\n  &_show-tooltip {\n    z-index: 3;\n    outline: none;\n\n    .q-slider-button__target {\n      background-color: var(--color-primary);\n      box-shadow: none;\n    }\n\n    .q-slider-button__tooltip {\n      z-index: 3;\n      display: block;\n    }\n  }\n}\n"
  },
  {
    "path": "src/qComponents/QSlider/src/styles/q-slider-captions.scss",
    "content": ".q-slider-captions {\n  position: relative;\n  width: 100%;\n  height: 20px;\n  margin-top: 8px;\n\n  &__btn {\n    position: absolute;\n    top: 0;\n    font-weight: var(--font-weight-base);\n    font-size: var(--font-size-base);\n    line-height: var(--line-height-base);\n    color: rgba(var(--color-rgb-gray), 0.32);\n    background-color: transparent;\n    border: none;\n    transform: translateX(-50%);\n\n    &:hover,\n    &:focus,\n    &_selected {\n      color: var(--color-primary-black);\n    }\n  }\n}\n"
  },
  {
    "path": "src/qComponents/QSlider/src/styles/q-slider-steps.scss",
    "content": ".q-slider-steps {\n  position: relative;\n  z-index: 1;\n  width: 100%;\n  height: 100%;\n  overflow: hidden;\n\n  &__step {\n    position: absolute;\n    top: 0;\n    width: 4px;\n    height: 8px;\n    background-color: var(--color-tertiary-gray-light);\n    box-shadow: 1px 0 1px rgba(174, 174, 192, 0.2),\n      -1px 0 1px rgba(255, 255, 255, 0.7);\n    transform: translateX(-50%);\n\n    &:first-child,\n    &:last-child {\n      display: none;\n    }\n  }\n}\n"
  },
  {
    "path": "src/qComponents/QSlider/src/styles/q-slider.scss",
    "content": ".q-slider {\n  --box-shadow-line: inset 1px 1px 2px rgba(var(--color-rgb-blue), 0.2),\n    inset -1px -1px 1px rgba(var(--color-rgb-white), 0.7);\n\n  position: relative;\n  width: 100%;\n\n  &__path {\n    position: relative;\n    width: 100%;\n    height: 8px;\n    background-color: var(--color-tertiary-gray);\n    border-radius: 4px;\n    box-shadow: var(--box-shadow-line);\n    cursor: pointer;\n  }\n\n  &_is-disabled {\n    .q-slider {\n      &__path {\n        cursor: default;\n      }\n    }\n\n    .q-slider-button {\n      &__target {\n        background-color: var(--color-tertiary-gray-light);\n\n        &:hover {\n          background-color: var(--color-tertiary-gray-light);\n        }\n      }\n\n      &:focus {\n        .q-slider-button__target {\n          background-color: var(--color-tertiary-gray-light);\n          box-shadow: var(--box-shadow-hover);\n        }\n      }\n\n      &:hover {\n        cursor: not-allowed;\n\n        .q-slider-button__target {\n          background-color: var(--color-tertiary-gray-light);\n          box-shadow: var(--box-shadow-hover);\n        }\n      }\n    }\n\n    .q-slider-bar {\n      background-color: rgba(var(--color-rgb-gray), 0.32);\n    }\n\n    .q-slider-captions {\n      &__btn {\n        cursor: default;\n      }\n    }\n  }\n\n  &_is-vertical {\n    width: auto;\n    height: 196px;\n\n    .q-slider {\n      &__path {\n        width: 8px;\n        height: 100%;\n      }\n    }\n\n    .q-slider-button {\n      top: auto;\n      left: 50%;\n      transform: translate(-50%, 50%);\n    }\n\n    .q-slider-bar {\n      width: 8px;\n      height: auto;\n    }\n\n    .q-slider-steps {\n      &__step {\n        top: auto;\n        width: 8px;\n        height: 4px;\n        transform: translateY(50%);\n      }\n    }\n\n    .q-slider-captions {\n      position: absolute;\n      top: 0;\n      left: 12px;\n      width: 20px;\n      height: 100%;\n\n      &__btn {\n        top: auto;\n        left: 0;\n        transform: translateY(50%);\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "src/qComponents/QTabPane/QTabPane.test.js",
    "content": "import Component from './src/QTabPane';\n\ndescribe('QTabPane', () => {\n  it('should match snapshot', async () => {\n    const instance = shallowMount(Component, {\n      propsData: {\n        name: 'pane_name',\n        title: 'Pane Title'\n      }\n    });\n\n    expect(instance.element).toMatchSnapshot();\n  });\n});\n"
  },
  {
    "path": "src/qComponents/QTabPane/__snapshots__/QTabPane.test.js.snap",
    "content": "// Jest Snapshot v1, https://goo.gl/fbAQLP\n\nexports[`QTabPane should match snapshot 1`] = `\n<div\n  class=\"q-tab-pane\"\n>\n  <div\n    class=\"q-tab-pane__inner\"\n  >\n    <button\n      class=\"q-tab-pane__btn\"\n      type=\"button\"\n    >\n      \n      Pane Title\n    \n    </button>\n     \n  </div>\n   \n  <!---->\n</div>\n`;\n"
  },
  {
    "path": "src/qComponents/QTabPane/index.js",
    "content": "import QTabPane from './src/QTabPane';\n\nQTabPane.install = Vue => {\n  Vue.component(QTabPane.name, QTabPane);\n};\n\nexport default QTabPane;\n"
  },
  {
    "path": "src/qComponents/QTabPane/src/QTabPane.vue",
    "content": "<template>\n  <div\n    class=\"q-tab-pane\"\n    :style=\"tabWidthStyle\"\n  >\n    <div class=\"q-tab-pane__inner\">\n      <button\n        type=\"button\"\n        class=\"q-tab-pane__btn\"\n        :class=\"tabBtnClasses\"\n        :disabled=\"isDisabled\"\n        @click=\"handleTabClick\"\n      >\n        {{ title }}\n      </button>\n\n      <slot name=\"content\" />\n    </div>\n    <div\n      v-if=\"description\"\n      class=\"q-tab-pane__description\"\n    >\n      {{ description }}\n    </div>\n  </div>\n</template>\n\n<script>\nexport default {\n  name: 'QTabPane',\n  componentName: 'QTabPane',\n\n  inject: {\n    qTabs: {\n      default: null\n    }\n  },\n\n  props: {\n    /**\n     * key of QTabPane\n     */\n    name: {\n      type: String,\n      required: true\n    },\n    /**\n     * title of QTabPane\n     */\n    title: {\n      type: String,\n      required: true\n    },\n    /**\n     * description of QTabPane\n     */\n    description: {\n      type: String,\n      default: null\n    },\n    /**\n     * width of QTabPane\n     */\n    width: {\n      type: [String, Number],\n      default: null\n    },\n    /**\n     * whether QTabPane is disabled\n     */\n    disabled: {\n      type: Boolean,\n      default: false\n    }\n  },\n\n  computed: {\n    isDisabled() {\n      return this.disabled || this.qTabs?.disabled;\n    },\n\n    tabWidthStyle() {\n      const width = this.width ?? this.qTabs?.tabWidth;\n\n      return {\n        '--tab-pane-width': Number(width) ? `${Number(width)}px` : width\n      };\n    },\n\n    tabBtnClasses() {\n      return {\n        'q-tab-pane__btn_active': this.qTabs?.currentName === this.name,\n        'q-tab-pane__btn_disabled': this.isDisabled\n      };\n    }\n  },\n\n  methods: {\n    handleTabClick() {\n      this.qTabs?.updateValue(this.name);\n    }\n  }\n};\n</script>\n"
  },
  {
    "path": "src/qComponents/QTabPane/src/q-tab-pane.scss",
    "content": ".q-tab-pane {\n  --tab-pane-width: 200px;\n\n  &:not(:last-child) {\n    margin-right: 8px;\n  }\n\n  &__inner {\n    display: flex;\n    align-items: center;\n  }\n\n  &__btn {\n    width: var(--tab-pane-width);\n    padding: 11px 0;\n    font-weight: var(--font-weight-base);\n    font-size: var(--font-size-base);\n    line-height: 18px;\n    text-align: center;\n    color: var(--color-primary-blue);\n    letter-spacing: 0.2px;\n    background-color: var(--color-tertiary-gray-light);\n    border: none;\n    border-radius: var(--border-radius-base);\n    outline: none;\n    box-shadow: var(--box-shadow-primary);\n    cursor: pointer;\n\n    &:hover {\n      color: var(--color-primary-black);\n      background-color: var(--color-tertiary-gray);\n    }\n\n    &:focus {\n      color: var(--color-primary-black);\n      background-color: var(--color-tertiary-gray-dark);\n      outline: none;\n    }\n\n    &_active {\n      color: var(--color-primary-black);\n      background-color: var(--color-tertiary-gray-ultra-light);\n    }\n\n    &_active {\n      &:hover {\n        color: var(--color-primary-black);\n        background-color: var(--color-tertiary-gray-ultra-light);\n      }\n    }\n\n    &_disabled {\n      color: rgba(var(--color-rgb-gray), 0.64);\n      background-color: var(--color-tertiary-gray);\n      cursor: not-allowed;\n\n      &:focus,\n      &:hover {\n        color: rgba(var(--color-rgb-gray), 0.64);\n        background-color: var(--color-tertiary-gray);\n      }\n    }\n  }\n\n  &__description {\n    width: var(--tab-pane-width);\n    margin-top: 8px;\n    font-weight: var(--font-weight-base);\n    font-size: 10px;\n    line-height: 12px;\n    color: rgba(var(--color-rgb-gray), 0.32);\n  }\n}\n"
  },
  {
    "path": "src/qComponents/QTable/QTable.test.js",
    "content": "import Component from './index';\n\ndescribe('QTable', () => {\n  const options = {\n    propsData: {\n      groupsOfColumns: [\n        {\n          columns: [\n            {\n              key: 'col1',\n              value: 'Column 1'\n            }\n          ]\n        }\n      ],\n      rows: [\n        {\n          col1: 'Columns row 1'\n        }\n      ]\n    }\n  };\n\n  it('QTable should match snapshot', () => {\n    const { element } = shallowMount(Component, options);\n\n    expect(element).toMatchSnapshot();\n  });\n});\n"
  },
  {
    "path": "src/qComponents/QTable/__snapshots__/QTable.test.js.snap",
    "content": "// Jest Snapshot v1, https://goo.gl/fbAQLP\n\nexports[`QTable QTable should match snapshot 1`] = `\n<div\n  class=\"q-table\"\n>\n  <div\n    class=\"q-table__loading-wrapper\"\n  >\n    <q-scrollbar-stub\n      theme=\"secondary\"\n      viewclass=\"\"\n      viewtag=\"div\"\n      wrapclass=\"q-table__scroll-wrapper\"\n    >\n      <!---->\n       \n      <div\n        class=\"q-table__wrapper\"\n        style=\"transition: all 0.2s;\"\n      >\n        <!---->\n         \n        <table\n          cellpadding=\"0\"\n          cellspacing=\"0\"\n          class=\"q-table__table q-table__fixed\"\n        >\n          <colgroup>\n            <!---->\n             \n            <col\n              style=\"width: 200px;\"\n            />\n          </colgroup>\n           \n          <thead>\n            <tr>\n              <!---->\n               \n              <th\n                class=\"q-table__header-cell\"\n              >\n                <div\n                  class=\"q-table__header-cell-wrapper\"\n                >\n                  <div\n                    class=\"q-table__header-cell-content q-table__header-cell-content_original\"\n                    title=\"Column 1\"\n                  >\n                    \n                        Column 1\n                      \n                  </div>\n                   \n                  <!---->\n                   \n                  <!---->\n                </div>\n              </th>\n            </tr>\n          </thead>\n           \n          <tbody>\n            <!---->\n             \n            <row-hoc-stub\n              checked-rows=\"\"\n              checkedrows=\"\"\n              children-key=\"children\"\n              childrenkey=\"children\"\n              class=\"\"\n              columns=\"[object Object]\"\n              indent-size=\"16\"\n              indentsize=\"16\"\n              row=\"[object Object]\"\n              row-index=\"0\"\n              rowindex=\"0\"\n            />\n          </tbody>\n        </table>\n      </div>\n    </q-scrollbar-stub>\n  </div>\n</div>\n`;\n"
  },
  {
    "path": "src/qComponents/QTable/index.js",
    "content": "import QTable from './src/QTable.vue';\n\nQTable.install = function(Vue) {\n  Vue.component(QTable.name, QTable);\n};\n\nexport default QTable;\n"
  },
  {
    "path": "src/qComponents/QTable/src/QTable.vue",
    "content": "<template>\n  <div\n    ref=\"root\"\n    class=\"q-table\"\n  >\n    <div\n      ref=\"loaderWrapper\"\n      class=\"q-table__loading-wrapper\"\n    >\n      <q-scrollbar\n        ref=\"scrollbar\"\n        wrap-class=\"q-table__scroll-wrapper\"\n        theme=\"secondary\"\n      >\n        <div\n          v-if=\"isLoading || !isLoadingAnimationComplete\"\n          class=\"q-table__loader\"\n          :class=\"{ 'q-table__loader_is-loading': isLoading }\"\n        >\n          <div class=\"q-table__loader-circle\">\n            <div class=\"q-table__loader-circle_quarter\" />\n            <div class=\"q-table__loader-circle_quarter\" />\n            <div class=\"q-table__loader-circle_quarter\" />\n            <div class=\"q-table__loader-circle_quarter\" />\n          </div>\n        </div>\n        <div\n          ref=\"tableWrapper\"\n          class=\"q-table__wrapper\"\n          :class=\"wrapperClass\"\n          :style=\"loadingWrapperClass\"\n        >\n          <template v-if=\"isDraggable\">\n            <div class=\"dnd-handler\" />\n            <div class=\"dnd-separator\" />\n          </template>\n\n          <table\n            v-if=\"rows.length\"\n            ref=\"QTable\"\n            class=\"q-table__table\"\n            :class=\"tableClasses\"\n            cellspacing=\"0\"\n            cellpadding=\"0\"\n          >\n            <colgroup>\n              <col\n                v-if=\"isSelectable\"\n                :style=\"checkboxColWidth\"\n              />\n              <template v-for=\"(group, groupIndex) in groupsOfColumns\">\n                <col\n                  v-for=\"(column, index) in group.columns\"\n                  :key=\"`fixCol${groupIndex}${index}`\"\n                  :style=\"getColWidth(column)\"\n                />\n              </template>\n            </colgroup>\n\n            <thead v-if=\"doesHeaderExist\">\n              <tr>\n                <th\n                  v-if=\"isSelectable\"\n                  :observer-key=\"\n                    isSelectableColumnSticked && 'q-table-checkboxes'\n                  \"\n                  class=\"q-table__header-cell q-table__header-cell__checkbox\"\n                >\n                  <q-checkbox\n                    v-if=\"selectableColumn.totalCheckboxPosition === 'header'\"\n                    v-model=\"areAllChecked\"\n                    :indeterminate=\"isIndeterminate\"\n                  />\n                </th>\n                <template v-for=\"(group, groupIndex) in groupsOfColumns\">\n                  <th\n                    v-for=\"(column, index) in group.columns\"\n                    :key=\"`group${groupIndex}${index}`\"\n                    :class=\"getCellClasses(column, group)\"\n                    :style=\"getHeaderCellStyles(group, column)\"\n                    :observer-key=\"column.sticky ? column.key : null\"\n                    class=\"q-table__header-cell\"\n                  >\n                    <div class=\"q-table__header-cell-wrapper\">\n                      <div\n                        class=\"q-table__header-cell-content\"\n                        :class=\"getHeaderContentClass(column)\"\n                        :title=\"getHeaderTitle(column)\"\n                        @click=\"handleHeaderClick(column)\"\n                      >\n                        <slot\n                          v-if=\"$scopedSlots.header\"\n                          name=\"header\"\n                          :data=\"column\"\n                          v-bind=\"updateColumnItem(column, index, column.key)\"\n                        />\n\n                        <slot\n                          v-else-if=\"column.slots && column.slots.header\"\n                          :name=\"column.slots.header\"\n                          :data=\"column\"\n                          v-bind=\"updateColumnItem(column, index, column.key)\"\n                        />\n\n                        <template v-else>\n                          {{ column.value }}\n                        </template>\n                      </div>\n\n                      <span\n                        v-if=\"column.sortable\"\n                        class=\"q-table__sort-arrow\"\n                        :class=\"{\n                          'q-icon-arrow-up': sort.direction !== 'descending',\n                          'q-icon-arrow-down': sort.direction === 'descending'\n                        }\"\n                        @click=\"handleHeaderClick(column)\"\n                      />\n\n                      <template v-if=\"group.draggable\">\n                        <div\n                          class=\"drop-handler dnd-before\"\n                          :class=\"getHandlerClass(group.key)\"\n                          :dndidx=\"index\"\n                        />\n\n                        <drag-elements\n                          :col-index=\"index\"\n                          parent-selector=\".q-table__scroll-wrapper\"\n                          dummy-selector=\".dnd-handler\"\n                          separator-selector=\".dnd-separator\"\n                          target-selector=\".q-table__header-cell\"\n                          limit-box-selector=\".q-table__table\"\n                          :drop-zone-selector=\"`.${getHandlerClass(group.key)}`\"\n                          :is-first-blocked=\"isSelectable\"\n                          @change-order=\"\n                            data => changeColumnsOrder(data, group.key)\n                          \"\n                        >\n                          <div class=\"drag-n-drop-icon\">\n                            <span\n                              v-if=\"group.draggable\"\n                              class=\"q-icon-drag-linear\"\n                            />\n                          </div>\n                        </drag-elements>\n\n                        <div\n                          class=\"drop-handler dnd-after\"\n                          :class=\"getHandlerClass(group.key)\"\n                          :dndidx=\"index + 1\"\n                        />\n                      </template>\n                    </div>\n                  </th>\n                </template>\n              </tr>\n            </thead>\n\n            <tbody>\n              <tr v-if=\"isTotalExist\">\n                <td\n                  v-if=\"isSelectable\"\n                  class=\"q-table__total-cell\"\n                  :observer-key=\"\n                    isSelectableColumnSticked && 'q-table-checkboxes'\n                  \"\n                  :class=\"{\n                    'q-table__total-cell_selectable':\n                      selectableColumn.totalCheckboxPosition === 'total'\n                  }\"\n                >\n                  <q-checkbox\n                    v-if=\"selectableColumn.totalCheckboxPosition === 'total'\"\n                    v-model=\"areAllChecked\"\n                    :indeterminate=\"isIndeterminate\"\n                  />\n                </td>\n                <template v-for=\"(group, groupIndex) in groupsOfColumns\">\n                  <td\n                    v-for=\"(column, index) in group.columns\"\n                    :key=\"`col${groupIndex}${index}`\"\n                    :class=\"getCellClasses(column, group)\"\n                    :observer-key=\"column.sticky ? column.key : null\"\n                    class=\"q-table__cell q-table__total-cell\"\n                  >\n                    <slot\n                      v-if=\"$scopedSlots.total\"\n                      name=\"total\"\n                      :data=\"total\"\n                      v-bind=\"updateTotalItem(total, index, column.key)\"\n                    />\n\n                    <slot\n                      v-else-if=\"column.slots && column.slots.total\"\n                      :name=\"column.slots.total\"\n                      :data=\"total\"\n                      v-bind=\"updateTotalItem(total, index, column.key)\"\n                    />\n\n                    <template v-else-if=\"total[column.key]\">\n                      {{ total[column.key] }}\n                    </template>\n                  </td>\n                </template>\n              </tr>\n\n              <row-hoc\n                v-for=\"(row, rowIndex) in computedRows\"\n                :ref=\"rowIndex === 0 && 'QFirstRow'\"\n                :key=\"rowIndex\"\n                :row=\"row\"\n                :row-index=\"rowIndex\"\n                :columns=\"allColumns\"\n                :class=\"levelClass(row.indent)\"\n                :expandable=\"expandable\"\n                :indent-size=\"indentSize\"\n                :indent=\"row.indent\"\n                :children-key=\"childrenKey\"\n                :pages-in-expand=\"pagesInExpand\"\n                :custom-row-class=\"customRowClass\"\n                :custom-row-style=\"customRowStyle\"\n                :checked-rows=\"checkedRows\"\n                :is-selectable=\"isSelectable\"\n                :is-selectable-column-sticked=\"isSelectableColumnSticked\"\n                :row-click=\"$listeners['row-click'] && handleRowClick\"\n                @expand-click=\"handleExpandClick\"\n                @check=\"handleRowCheck\"\n              >\n                <template #row=\"{ rowData }\">\n                  <slot\n                    v-if=\"$scopedSlots.row\"\n                    name=\"row\"\n                    :row=\"rowData\"\n                  />\n\n                  <slot\n                    v-else-if=\"findSlotForRow(rowData.key)\"\n                    :name=\"findSlotForRow(rowData.key)\"\n                    :row=\"rowData.data\"\n                    :row-key=\"rowData.key\"\n                    :index=\"rowData.index\"\n                    :value=\"rowData.value\"\n                    :indent=\"rowData.indent\"\n                    :column=\"rowData.column\"\n                  />\n\n                  <template v-else>\n                    {{ rowData.value }}\n                  </template>\n                </template>\n              </row-hoc>\n            </tbody>\n          </table>\n\n          <div\n            v-else\n            class=\"q-table__empty\"\n          >\n            <div class=\"q-table__empty-image\" />\n            <div class=\"q-table__empty-text\">\n              {{ emptyText || $t('QTable.noData') }}\n            </div>\n          </div>\n        </div>\n      </q-scrollbar>\n    </div>\n  </div>\n</template>\n\n<script>\nimport { cloneDeep, throttle } from 'lodash-es';\nimport QTableRow from './components/QTableRow';\nimport DragElements from './components/DragElements';\n\nimport withQTableRow from './hocs/withQTableRow';\n\nconst RowHoc = withQTableRow(QTableRow);\nconst shadowDropOffset = 3;\nconst MIN_BLANK_TABLE_HEIGHT = 228;\nconst CHECKBOX_COL_WIDTH = 64;\n\nexport default {\n  name: 'QTable',\n\n  components: {\n    RowHoc,\n    DragElements\n  },\n\n  props: {\n    /**\n     * do not shrink column's width as native table does (change `defaultColWidth` or pass the `width` to each column object for managing the width)\n     */\n    fixedLayout: {\n      type: Boolean,\n      default: true\n    },\n    /**\n     * Default columns width, required `fixedLayout: true`\n     */\n    defaultColWidth: {\n      type: String,\n      default: '200px'\n    },\n    isLoading: {\n      type: Boolean,\n      default: false\n    },\n    /**\n     * `groupsOfColumns` MUST contain one or more groups of columns,\n     * Each group MUST contain `key` and `columns` - array of objects.\n     * Each group MAY contain:\n     *  `color` (hex string) - column's header color.\n     *  `draggabble` (boolean) - whether to drag and drop columns inside the group.\n     *  `align` (left/right) - content's align.\n     * Each column MUST contain `key` and `value`.\n     * Each column MAY contain:\n     *  `sortable`,\n     *  `slots`,\n     *  `width` (works with `fixedLayout: true`),\n     *  `minWidth` (works with `fixedLayout: false`),\n     *  `customCellClass`,\n     *  `formatter` (fn)\n     */\n    groupsOfColumns: {\n      type: Array,\n      required: true\n    },\n    /**\n     * Array of objects, each object must contain `[column.key]: value` pair\n     */\n    rows: {\n      type: Array,\n      required: true\n    },\n    /**\n     * Show/hide grid view\n     */\n    grid: {\n      type: Boolean,\n      default: false\n    },\n    /**\n     * Object, `[column.key]: value` pair, not all are required\n     */\n    total: {\n      type: Object,\n      default: () => ({})\n    },\n    childrenKey: {\n      type: String,\n      default: 'children'\n    },\n    expandable: {\n      type: Boolean,\n      default: false\n    },\n    indentSize: {\n      type: Number,\n      default: 16\n    },\n    uniqueKey: {\n      type: String,\n      default: ''\n    },\n    pagesInExpand: {\n      type: [Boolean, String],\n      default: false\n    },\n    /**\n     * Get row as argument, must return style `String`,\n     * you can also return one:\n     * `green-row`\n     * `red-row`\n     * `grey-row`\n     * `dark-row`\n     * `yellow-row`\n     */\n    customRowClass: {\n      type: Function,\n      default: null\n    },\n    /**\n     * Get row as argument, must return style `String`\n     */\n    customRowStyle: {\n      type: Function,\n      default: null\n    },\n    /**\n     * Checkboxes column.\n     * `sticky` - whether column should stick.\n     * `totalCheckboxPosition` - where total checkbox need to place, `header` or `total`.\n     */\n    selectableColumn: {\n      type: Object,\n      default: () => ({}),\n      required: false,\n      validator: props => {\n        if (!Object.keys(props).length) return true;\n\n        return (\n          props.totalCheckboxPosition &&\n          ['header', 'total'].includes(props.totalCheckboxPosition)\n        );\n      }\n    },\n    defaultSort: {\n      type: Object,\n      default: () => ({\n        key: null,\n        direction: 'ascending'\n      })\n    },\n    /**\n     * Text for empty table\n     */\n    emptyText: {\n      type: String,\n      default: null\n    }\n  },\n\n  data() {\n    return {\n      timer: 2,\n      isLoadingAnimationComplete: true,\n      loaderWrapperHeight: 0,\n      scrolled: 0,\n      wrapperWidth: 0,\n      tableWrapper: null,\n      treeRows: [],\n      loaderRow: null,\n      wrapperClass: '',\n      checkedRows: [],\n      sort: this.defaultSort,\n      stickedOffsets: {\n        left: {},\n        right: {}\n      },\n      observers: {},\n      isRendered: false,\n      QFirstRowEl: null\n    };\n  },\n\n  computed: {\n    allColumns() {\n      return this.groupsOfColumns.reduce((acc, group) => {\n        const eachGroup = group.columns.map(col => {\n          const newCol = {\n            ...col,\n            align: col.align ?? group.align ?? 'left'\n          };\n          return newCol;\n        });\n        return acc.concat(eachGroup);\n      }, []);\n    },\n\n    doesHeaderExist() {\n      return this.groupsOfColumns.some(({ columns }) =>\n        columns.some(({ value, slots }) => value?.toString() ?? slots?.header)\n      );\n    },\n\n    isDraggable() {\n      return this.groupsOfColumns.find(group => group.draggable);\n    },\n\n    isSeparated() {\n      return this.groupsOfColumns.length > 1;\n    },\n\n    areAllChecked: {\n      get() {\n        return this.checkedRows.length === this.rows.length;\n      },\n      set(isChecked) {\n        this.checkedRows = isChecked\n          ? Array.from(Array(this.computedRows.length).keys())\n          : [];\n      }\n    },\n\n    isSelectable() {\n      return Boolean(Object.keys(this.selectableColumn).length);\n    },\n\n    isSelectableColumnSticked() {\n      return (this.isSelectable && this.selectableColumn?.sticky) ?? false;\n    },\n\n    tableClasses() {\n      return {\n        'q-table__draggable': this.isDraggable,\n        'q-table__selectable': this.isSelectable,\n        'q-table__separated': this.isSeparated,\n        'q-table__grid': this.grid,\n        'q-table__fixed': this.fixedLayout\n      };\n    },\n\n    isIndeterminate() {\n      return Boolean(\n        this.checkedRows.length && this.checkedRows.length !== this.rows.length\n      );\n    },\n\n    isTotalExist() {\n      return Boolean(Object.keys(this.total).length);\n    },\n\n    loadingWrapperClass() {\n      return {\n        height: this.loaderWrapperHeight ? `${this.loaderWrapperHeight}px` : '',\n        transition: `all 0.${this.timer}s`\n      };\n    },\n\n    tableClass() {\n      if (this.scrolled === 0) return 'scrolled-left';\n\n      const QTableWidth = this.$refs.QTable.offsetWidth;\n\n      return this.scrolled === QTableWidth - this.wrapperWidth\n        ? 'scrolled-right'\n        : 'scrolled-center';\n    },\n\n    computedRows() {\n      const rows = this.treeRows.length ? this.treeRows : this.rows;\n\n      return rows.map((row, index) => ({\n        ...row,\n        treeIndex: index\n      }));\n    },\n\n    checkboxColWidth() {\n      return { width: `${CHECKBOX_COL_WIDTH}px` };\n    }\n  },\n\n  watch: {\n    isLoading() {\n      this.isLoadingAnimationComplete = false;\n\n      setTimeout(() => {\n        this.loaderWrapperHeight = this.$refs.QTable\n          ? this.$refs.QTable.clientHeight + shadowDropOffset\n          : MIN_BLANK_TABLE_HEIGHT;\n\n        setTimeout(() => {\n          this.isLoadingAnimationComplete = true;\n        }, 200);\n      }, this.timer * 300);\n    },\n    rows: {\n      handler(rows) {\n        this.treeRows = rows.map((row, index) => {\n          const updatedRow = {\n            data: row,\n            treeIndex: index\n          };\n\n          const childs = updatedRow.data[this.childrenKey];\n\n          if (childs) {\n            updatedRow.data[this.childrenKey] = this.updateChildrenRows(\n              childs,\n              row,\n              updatedRow\n            );\n          }\n\n          return updatedRow;\n        });\n      },\n      immediate: true\n    },\n    checkedRows(rowsIndexes) {\n      const rows = this.computedRows.filter((_, index) =>\n        rowsIndexes.includes(index)\n      );\n\n      this.$emit('rows-check', rows);\n    }\n  },\n\n  updated() {\n    this.changeWrapperHeight();\n  },\n\n  beforeUpdate() {\n    this.QFirstRowEl = this.$refs.QFirstRow?.[0]?.$el;\n\n    if (!this.QFirstRowEl) return;\n\n    this.getStickedOffsets();\n    this.createObservers();\n\n    if (!this.isRendered) this.detectIntersections(0);\n  },\n\n  created() {\n    window.addEventListener('resize', this.changeWrapperHeight, {\n      passive: true\n    });\n  },\n\n  destroyed() {\n    window.removeEventListener('resize', this.changeWrapperHeight);\n  },\n\n  mounted() {\n    if (this.$refs.QTable) {\n      this.loaderWrapperHeight =\n        this.$refs.QTable.clientHeight + shadowDropOffset;\n    }\n\n    const wrapper = this.$refs?.tableWrapper ?? null;\n\n    if (wrapper && this.$refs.QTable) {\n      if (wrapper.offsetWidth < this.$refs.QTable.offsetWidth) {\n        this.wrapperClass = 'q-table__wrapper_scrollable';\n      }\n\n      wrapper.addEventListener('scroll', this.onScroll, {\n        passive: true\n      });\n\n      this.wrapperWidth = wrapper.offsetWidth;\n    }\n\n    if (!this.$refs.scrollbar) return;\n\n    this.$watch(\n      () => this.$refs.scrollbar.moveX,\n      throttle(this.detectIntersections, 100)\n    );\n  },\n\n  beforeDestroy() {\n    if (!this.$refs.tableWrapper) return;\n\n    this.$refs.tableWrapper.removeEventListener('scroll', this.onScroll);\n  },\n\n  methods: {\n    createObservers() {\n      if (!this.$refs.QTable) return;\n\n      this.observers = {};\n\n      let totalWidth = parseFloat(\n        window.getComputedStyle(this.$refs.tableWrapper).paddingLeft\n      );\n\n      if (this.isSelectable) {\n        if (this.isSelectableColumnSticked) {\n          this.observers['q-table-checkboxes'] = {\n            position: 'left',\n            triggerLeft: totalWidth,\n            triggerRight: totalWidth + CHECKBOX_COL_WIDTH,\n            offset: 0,\n            isSticked: false\n          };\n        }\n\n        totalWidth += CHECKBOX_COL_WIDTH;\n      }\n\n      this.allColumns.forEach(({ sticky, key }, index) => {\n        const elementWidth = this.QFirstRowEl.querySelector(\n          `td:nth-child(${index + (this.isSelectable ? 2 : 1)})`\n        ).offsetWidth;\n\n        if (!sticky) {\n          totalWidth += elementWidth;\n          return;\n        }\n\n        this.observers[key] = {\n          position: sticky.position,\n          triggerLeft: totalWidth,\n          triggerRight: totalWidth + elementWidth,\n          offset: this.getStickyOffset(sticky.position, key),\n          isSticked: false\n        };\n\n        totalWidth += elementWidth;\n      });\n\n      totalWidth += parseFloat(\n        window.getComputedStyle(this.$refs.tableWrapper).paddingRight\n      );\n    },\n\n    detectIntersections(moveX) {\n      const rootWidth = this.$refs.root.offsetWidth;\n      const moveXPixels = (rootWidth * moveX) / 100;\n\n      if (!this.$refs.QTable) return;\n\n      const observers = { ...this.observers };\n\n      Object.entries(observers).forEach(\n        (\n          [key, { position, triggerLeft, triggerRight, offset, isSticked }],\n          index\n        ) => {\n          const intersectableElements = this.$refs.QTable.querySelectorAll(\n            `[observer-key=${key}]`\n          );\n\n          const scroll = moveXPixels + offset;\n\n          let triggerWithinRoot = triggerLeft < scroll;\n          let triggerOutsideRoot = triggerLeft >= scroll;\n\n          if (position === 'right') {\n            const reversedOffset = triggerRight + offset * 2;\n            triggerWithinRoot = reversedOffset > scroll + rootWidth;\n            triggerOutsideRoot = reversedOffset < scroll + rootWidth;\n          }\n\n          const isTriggerConditionChanged =\n            (!isSticked && triggerWithinRoot) ||\n            (isSticked && triggerOutsideRoot);\n\n          if (!isTriggerConditionChanged) return;\n\n          observers[key].isSticked = !isSticked && triggerWithinRoot;\n          intersectableElements.forEach(elem =>\n            this.changeStickyStyles({\n              elem,\n              index,\n              position,\n              offset,\n              isOff: isSticked && triggerOutsideRoot\n            })\n          );\n        }\n      );\n\n      this.observers = observers;\n      this.isRendered = true;\n    },\n\n    changeStickyStyles({ elem, index, position, isOff, offset }) {\n      if (isOff) {\n        elem.classList.remove('q-table__sticked-cell');\n\n        if (position === 'right') {\n          elem.classList.remove('q-table__sticked-cell_is-reversed');\n          /* eslint-disable-next-line no-param-reassign */\n          elem.style.zIndex = null;\n        }\n\n        /* eslint-disable-next-line no-param-reassign */\n        elem.style[position] = null;\n\n        return;\n      }\n\n      elem.classList.add('q-table__sticked-cell');\n\n      let correction = this.grid ? index : 0;\n\n      if (position === 'right') {\n        const reversedIndex =\n          Object.keys(this.stickedOffsets.right).length + 2 - index;\n\n        elem.classList.add('q-table__sticked-cell_is-reversed');\n        /* eslint-disable-next-line no-param-reassign */\n        elem.style.zIndex = reversedIndex;\n\n        correction = this.grid ? reversedIndex : 0;\n      }\n\n      /* eslint-disable-next-line no-param-reassign */\n      elem.style[position] = `${offset + correction}px`;\n    },\n\n    getStickyOffset(position, key) {\n      if (!Object.keys(this.stickedOffsets[position]).length) return 0;\n\n      return this.stickedOffsets[position]?.[key] ?? 0;\n    },\n\n    getStickedOffsets() {\n      if (!this.$refs.QTable) return;\n\n      this.stickedOffsets = {\n        left: {},\n        right: {}\n      };\n\n      let tds = this.QFirstRowEl.querySelectorAll('td');\n\n      if (!tds.length) return;\n\n      let totalLeftWidth = 0;\n      let totalRightWidth = 0;\n\n      if (this.isSelectable && this.isSelectableColumnSticked) {\n        this.stickedOffsets.left['q-table-checkboxes'] = CHECKBOX_COL_WIDTH;\n        totalLeftWidth += CHECKBOX_COL_WIDTH;\n      }\n\n      this.allColumns.forEach((col, index) => {\n        if (col.sticky?.position === 'left') {\n          this.stickedOffsets.left[col.key] = totalLeftWidth;\n          totalLeftWidth += tds[index].offsetWidth;\n        }\n      });\n\n      tds = Array.from(tds).reverse();\n      [...this.allColumns].reverse().forEach((col, index) => {\n        if (col.sticky?.position === 'right') {\n          this.stickedOffsets.right[col.key] = totalRightWidth;\n          totalRightWidth += tds[index].offsetWidth;\n        }\n      });\n    },\n\n    getHeaderContentClass({ slots }) {\n      const hasSlot = Boolean(slots?.header || this.$scopedSlots.header);\n      return hasSlot ? null : 'q-table__header-cell-content_original';\n    },\n\n    getHeaderTitle({ value, slots }) {\n      const hasSlot = Boolean(slots?.header || this.$scopedSlots.header);\n      return hasSlot ? null : value;\n    },\n\n    changeWrapperHeight() {\n      if (this.isLoading || !this.isLoadingAnimationComplete) return;\n\n      this.loaderWrapperHeight = this.$refs.QTable\n        ? this.$refs.QTable.clientHeight + shadowDropOffset\n        : MIN_BLANK_TABLE_HEIGHT;\n    },\n\n    updateChildrenRows(childs, row, updatedRow) {\n      return childs.map(child => {\n        const childlessRow = { ...row };\n        this.$delete(childlessRow, [this.childrenKey]);\n\n        const updatedChildRow = {\n          data: child,\n          parentRow: childlessRow,\n          indent: updatedRow.indent + this.indentSize || this.indentSize,\n          treeIndex: updatedRow.treeIndex\n        };\n\n        const rowChilds = updatedChildRow.data[this.childrenKey];\n\n        if (rowChilds) {\n          updatedChildRow.data[this.childrenKey] = this.updateChildrenRows(\n            rowChilds,\n            child,\n            updatedChildRow\n          );\n        }\n\n        return updatedChildRow;\n      });\n    },\n\n    handleHeaderClick({ key, sortable }) {\n      if (!sortable) return;\n      this.setSort(key);\n    },\n\n    getHandlerClass(group) {\n      return `${this.isSeparated ? group : 'column'}-handler`;\n    },\n\n    findSlotForRow(columnKey) {\n      const currentCol = this.allColumns.find(({ key }) => key === columnKey);\n\n      return currentCol?.slots?.row ?? null;\n    },\n\n    handleRowClick(row) {\n      this.$emit('row-click', row);\n    },\n\n    handleRowCheck({ isChecked, rowIndex }) {\n      const checkedRows = new Set(this.checkedRows);\n\n      if (isChecked) {\n        checkedRows.add(rowIndex);\n      } else {\n        checkedRows.delete(rowIndex);\n      }\n\n      this.checkedRows = Array.from(checkedRows);\n    },\n\n    setSort(key, direction) {\n      if (direction) {\n        this.sort = {\n          key,\n          direction\n        };\n\n        this.$emit('change-sort', this.sort);\n\n        return;\n      }\n\n      if (this.sort.key !== key) {\n        this.sort = {\n          key,\n          direction: this.sort.direction ?? 'ascending'\n        };\n\n        this.$emit('change-sort', this.sort);\n\n        return;\n      }\n\n      switch (this.sort.direction) {\n        case null:\n          this.sort.direction = 'ascending';\n          break;\n        case 'ascending':\n          this.sort.direction = 'descending';\n          break;\n        default:\n        case 'descending':\n          this.sort.direction = null;\n          break;\n      }\n\n      this.$emit('change-sort', this.sort);\n    },\n\n    levelClass(indent) {\n      if (!indent) return '';\n      return `q-table__row-level-${indent / this.indentSize}`;\n    },\n\n    handleExpandClick(row) {\n      const currentRow = this.treeRows[row.treeIndex];\n\n      if (!row.isTreeOpened) {\n        const updatedRow = {\n          ...currentRow,\n          isTreeOpened: true\n        };\n\n        this.treeRows.splice(currentRow, 1, updatedRow);\n        return;\n      }\n\n      this.$delete(currentRow, 'isTreeOpened');\n    },\n\n    findScopedRow(row, key, value) {\n      let foundRow = null;\n\n      if (row[key] === value) {\n        foundRow = row;\n      }\n\n      if (!foundRow && row[this.childrenKey]) {\n        row[this.childrenKey].forEach(childRow => {\n          if (!foundRow) foundRow = this.findScopedRow(childRow, key, value);\n        });\n      }\n\n      return foundRow;\n    },\n\n    resolve(row, newChilds, isAdditional) {\n      this.treeRows = this.computedRows;\n\n      const parentRow = this.findScopedRow(\n        this.treeRows[row.treeIndex],\n        this.uniqueKey,\n        row[this.uniqueKey]\n      );\n\n      let loaderRow = null;\n\n      let updatedChilds = newChilds.map(child => {\n        const childlessRow = { ...row };\n        this.$delete(childlessRow, [this.childrenKey]);\n\n        if (child[this.pagesInExpand]) {\n          loaderRow = { ...child, parentRow: childlessRow };\n        }\n        return {\n          ...child,\n          parentRow: childlessRow,\n          indent: row.indent + this.indentSize || this.indentSize,\n          treeIndex: row.treeIndex\n        };\n      });\n\n      if (this.pagesInExpand && loaderRow) {\n        updatedChilds = updatedChilds.filter(\n          child => !child[this.pagesInExpand]\n        );\n        updatedChilds.push(loaderRow);\n      }\n\n      if (isAdditional && parentRow[this.childrenKey]) {\n        const childs = parentRow[this.childrenKey].filter(\n          child => !child[this.pagesInExpand]\n        );\n\n        this.$set(parentRow, [this.childrenKey], [...childs, ...updatedChilds]);\n      } else {\n        this.$set(parentRow, [this.childrenKey], updatedChilds);\n      }\n\n      parentRow.isTreeOpened = true;\n\n      return this.treeRows;\n    },\n\n    onScroll({ target }) {\n      this.scrolled = target.scrollLeft;\n    },\n\n    getHeaderCellStyles(group, column) {\n      const style = {};\n\n      if (column?.minWidth) style.minWidth = column.minWidth;\n      if (!this.isSeparated || !group) return style;\n\n      return {\n        ...style,\n        borderColor: group.color ?? ''\n      };\n    },\n\n    getCellClasses(column = {}, group) {\n      const classes = [this.getSortableClass(column)];\n\n      if (this.isSeparated) {\n        classes.push(`q-table__header-cell_${group.key}`);\n      }\n\n      if (group.align || column.align) {\n        classes.push(\n          `q-table__header-cell_align-${column.align ?? group.align}`\n        );\n      }\n\n      return classes;\n    },\n\n    getSortableClass(column) {\n      const isColumnSortable = column?.sortable ?? null;\n\n      const sortableClass =\n        this.sort.key === column.key && this.sort.direction\n          ? `q-table__cell-sortable_${this.sort.direction}`\n          : 'q-table__cell-sortable';\n\n      if (!isColumnSortable) return '';\n\n      if (this.sort.key === column?.key) {\n        return `${sortableClass} ${sortableClass}`;\n      }\n\n      return sortableClass;\n    },\n\n    getColWidth(column) {\n      return {\n        width: column.width ?? this.defaultColWidth\n      };\n    },\n\n    updateColumnItem(item, index, key) {\n      return {\n        columnKey: key || null,\n        index,\n        value: item.value ?? null\n      };\n    },\n\n    updateTotalItem(item, index, key) {\n      return {\n        columnKey: key || null,\n        index,\n        value: item[key] ?? null\n      };\n    },\n\n    changeColumnsOrder({ newPositionIndex, oldPositionIndex }, groupKey) {\n      const columns = cloneDeep(this.groupsOfColumns);\n      const group = columns.find(({ key }) => key === groupKey);\n      if (group?.columns) {\n        group.columns.splice(\n          newPositionIndex,\n          0,\n          group.columns.splice(oldPositionIndex, 1)[0]\n        );\n      }\n\n      this.$emit('change-order', columns);\n    }\n  }\n};\n</script>\n"
  },
  {
    "path": "src/qComponents/QTable/src/components/DragElements/index.vue",
    "content": "<template>\n  <div\n    class=\"q-table__drag-elements\"\n    @mousedown.stop=\"handleColDrag\"\n  >\n    <slot />\n  </div>\n</template>\n\n<script>\nimport { throttle } from 'lodash-es';\n\nconst shadowDropOffset = 3;\n\nexport default {\n  name: 'DragElements',\n\n  props: {\n    parentSelector: {\n      type: String,\n      required: true\n    },\n    limitBoxSelector: {\n      type: String,\n      required: true\n    },\n    dummySelector: {\n      type: String,\n      required: true\n    },\n    separatorSelector: {\n      type: String,\n      required: true\n    },\n    targetSelector: {\n      type: String,\n      required: true\n    },\n    dropZoneSelector: {\n      type: String,\n      required: true\n    },\n    colIndex: {\n      type: Number,\n      required: true\n    },\n    isFirstBlocked: {\n      type: Boolean,\n      default: false\n    }\n  },\n\n  data() {\n    return {\n      diff: 0,\n      colEl: null,\n      dummyEl: null,\n      separatorDummyEl: null,\n      parent: null,\n      parentBox: null,\n      draggendIndex: null\n    };\n  },\n\n  created() {\n    this.trottledSeparatorDummyMove = throttle(this.separatorDummyMove, 100);\n  },\n\n  methods: {\n    separatorDummyMove(e) {\n      this.separatorDummyEl.style.display = 'block';\n\n      const elem = document\n        .elementFromPoint(e.pageX, e.pageY - window.pageYOffset)\n        ?.closest(this.dropZoneSelector);\n\n      if (!elem) return;\n\n      if (elem.classList.contains('dnd-before')) {\n        this.separatorDummyEl.style.left = `${elem.getBoundingClientRect()\n          .left -\n          this.parentBox.left +\n          this.parent.scrollLeft}px`;\n      } else {\n        this.separatorDummyEl.style.left = `${elem.getBoundingClientRect()\n          .right -\n          this.parentBox.left +\n          this.parent.scrollLeft}px`;\n      }\n\n      this.draggendIndex = elem.attributes.dndidx.value;\n    },\n    handleColDrag(e) {\n      this.colEl = this.$el.parentElement.parentElement;\n      this.parent = document.querySelector(this.parentSelector);\n      this.dummyEl = document.querySelector(this.dummySelector);\n      this.separatorDummyEl = document.querySelector(this.separatorSelector);\n      this.parentBox = this.parent.getBoundingClientRect();\n\n      this.diff = e.pageX - this.colEl.getBoundingClientRect().left;\n\n      const dummyStyles = [\n        'display:block',\n        `width:${this.colEl.offsetWidth}px`,\n        `height:${this.parent.offsetHeight - shadowDropOffset}px`,\n        `left:${e.pageX -\n          this.diff -\n          this.parentBox.left +\n          this.parent.scrollLeft}px`\n      ];\n\n      const separatorDummyStyles = [\n        `height:${this.parent.offsetHeight - shadowDropOffset}px`\n      ];\n\n      this.dummyEl.style.cssText = dummyStyles.join(';');\n      this.separatorDummyEl.style.cssText = separatorDummyStyles.join(';');\n\n      document.querySelectorAll(this.targetSelector).forEach(item => {\n        item.classList.add('dragInit');\n      });\n\n      document.addEventListener('mousemove', this.handleDummyMoving);\n      document.addEventListener('mouseup', this.handleDummyMovingEnd);\n    },\n    handleDummyMoving(e) {\n      const limitBox = document\n        .querySelector(this.limitBoxSelector)\n        .getBoundingClientRect();\n\n      const dummy = this.dummyEl;\n\n      if (e.pageX - this.diff < limitBox.left) {\n        dummy.style.left = 0;\n        return;\n      }\n\n      if (e.pageX > this.parentBox.right) {\n        this.parent.scrollLeft += e.pageX - this.parentBox.right;\n\n        this.dummyEl.style.left = `${e.pageX - dummy.outerWidth - this.diff}px`;\n\n        return;\n      }\n\n      if (e.pageX < this.parentBox.left) {\n        this.parent.scrollLeft -= e.pageX;\n\n        this.dummyEl.style.left = `${e.pageX - this.diff}px`;\n\n        return;\n      }\n\n      if (e.pageX - this.diff + dummy.offsetWidth > limitBox.right) {\n        dummy.style.left = `${limitBox.right - dummy.outerWidth}px`;\n        return;\n      }\n\n      if (e.clientY < limitBox.top || e.clientY > limitBox.bottom) {\n        dummy.style.left = `${e.pageX - this.diff - limitBox.left}px`;\n        return;\n      }\n\n      this.dummyEl.style.left = `${e.pageX - this.diff - limitBox.left}px`;\n\n      this.trottledSeparatorDummyMove(e);\n    },\n    handleDummyMovingEnd() {\n      document.removeEventListener('mousemove', this.handleDummyMoving);\n      document.removeEventListener('mouseup', this.handleDummyMovingEnd);\n\n      this.dummyEl.style.cssText = '';\n      this.separatorDummyEl.style.cssText = '';\n\n      document.querySelectorAll('.dragInit').forEach(({ classList }) => {\n        classList.remove('dragInit');\n      });\n\n      this.draggendIndex = parseInt(this.draggendIndex, 10);\n\n      const isCurrentColBlocked = this.isFirstBlocked\n        ? Boolean(this.draggendIndex)\n        : this.draggendIndex > -1;\n\n      if (\n        isCurrentColBlocked &&\n        this.colIndex !== this.draggendIndex &&\n        this.colIndex !== this.draggendIndex - 1\n      ) {\n        const newPositionIndex =\n          this.colIndex < this.draggendIndex\n            ? this.draggendIndex - 1\n            : this.draggendIndex;\n\n        this.$emit('change-order', {\n          oldPositionIndex: this.colIndex,\n          newPositionIndex\n        });\n      }\n\n      this.draggendIndex = null;\n\n      this.colEl = null;\n    }\n  }\n};\n</script>\n"
  },
  {
    "path": "src/qComponents/QTable/src/components/QTableRow/index.vue",
    "content": "<template>\n  <tr\n    :class=\"rowClass\"\n    :style=\"getRowStyle\"\n    @click=\"rowClick && rowClick(row)\"\n  >\n    <td\n      v-if=\"isSelectable\"\n      class=\"q-table__cell q-table__cell_selectable\"\n      :observer-key=\"isSelectableColumnSticked && 'q-table-checkboxes'\"\n      :style=\"firstTdStyle\"\n    >\n      <div\n        v-if=\"canRowExpand(0)\"\n        class=\"q-table__expand-arrow\"\n        :class=\"openedTreeClass\"\n        @click=\"handleExpandClick\"\n      >\n        <span class=\"q-icon-triangle-right\" />\n      </div>\n      <q-checkbox v-model=\"isChecked\" />\n    </td>\n    <td\n      v-for=\"(column, columnIndex) in columns\"\n      :key=\"column.key\"\n      :style=\"getCellStyle(columnIndex)\"\n      :align=\"column.align || 'left'\"\n      :observer-key=\"column.sticky ? column.key : null\"\n      class=\"q-table__cell\"\n    >\n      <div\n        v-if=\"!isSelectable && canRowExpand(columnIndex)\"\n        class=\"q-table__expand-arrow\"\n        :class=\"openedTreeClass\"\n        @click=\"handleExpandClick\"\n      >\n        <span class=\"q-icon-triangle-right\" />\n      </div>\n\n      <div\n        v-if=\"column.customCellClass\"\n        :class=\"column.customCellClass\"\n      >\n        <slot\n          :row-data=\"updateRow(row.data, columnIndex, column.key, column)\"\n          name=\"row\"\n        />\n\n        <slot\n          v-if=\"checkLoader(columnIndex)\"\n          :row-data=\"row\"\n          name=\"loader\"\n        />\n      </div>\n\n      <template v-else>\n        <slot\n          :row-data=\"updateRow(row.data, columnIndex, column.key, column)\"\n          name=\"row\"\n        />\n\n        <slot\n          v-if=\"checkLoader(columnIndex)\"\n          :row-data=\"row\"\n          name=\"loader\"\n        />\n      </template>\n    </td>\n  </tr>\n</template>\n\n<script>\nimport { get } from 'lodash-es';\n\nexport default {\n  name: 'QTableRow',\n\n  props: {\n    row: {\n      type: Object,\n      required: true\n    },\n    rowIndex: {\n      type: Number,\n      required: true\n    },\n    columns: {\n      type: Array,\n      required: true\n    },\n    childrenKey: {\n      type: String,\n      default: 'children'\n    },\n    expandable: {\n      type: Boolean,\n      default: false\n    },\n    indent: {\n      type: Number,\n      default: 0\n    },\n    indentSize: {\n      type: Number,\n      default: 16\n    },\n    pagesInExpand: {\n      type: [Boolean, String],\n      default: false\n    },\n    customRowClass: {\n      type: Function,\n      default: null\n    },\n    customRowStyle: {\n      type: Function,\n      default: null\n    },\n    rowClick: {\n      type: Function,\n      default: null\n    },\n    isSelectable: {\n      type: Boolean,\n      default: false\n    },\n    isSelectableColumnSticked: {\n      type: Boolean,\n      default: false\n    },\n    checkedRows: {\n      type: Array,\n      default: () => []\n    }\n  },\n\n  data() {\n    return {\n      firstTdStyle: ''\n    };\n  },\n\n  computed: {\n    isChecked: {\n      get() {\n        return this.checkedRows.includes(this.rowIndex);\n      },\n      set(isChecked) {\n        this.$emit('check', {\n          isChecked,\n          row: this.row,\n          rowIndex: this.rowIndex\n        });\n      }\n    },\n    rowClass() {\n      const rowClass = {};\n\n      if (this.customRowClass) {\n        const newClass = this.customRowClass({\n          row: this.row,\n          rowIndex: this.rowIndex\n        });\n\n        rowClass[newClass] = true;\n      }\n\n      if (this.getRowStyle) {\n        rowClass['custom-border'] = Boolean(this.customRowStyle);\n      }\n\n      if (this.rowClick) {\n        const newClass = 'q-table__row_is-interactive';\n\n        rowClass[newClass] = true;\n      }\n\n      if (!this.indent) return rowClass;\n\n      rowClass[`q-table__row-level-${this.indent / this.indentSize}`] = true;\n\n      return rowClass;\n    },\n    openedTreeClass() {\n      return this.row.isTreeOpened ? 'q-table__expand-arrow_opened' : '';\n    },\n    getRowStyle() {\n      return (\n        this.customRowStyle &&\n        this.customRowStyle({\n          row: this.row,\n          rowIndex: this.rowIndex\n        })\n      );\n    }\n  },\n\n  mounted() {\n    this.getFirstTdStyle();\n  },\n\n  methods: {\n    checkLoader(columnIndex) {\n      return this.row[this.pagesInExpand] && !columnIndex;\n    },\n    canRowExpand(columnIndex) {\n      return (\n        this.expandable &&\n        columnIndex === 0 &&\n        Boolean(this.row.data[this.childrenKey]?.length)\n      );\n    },\n    handleExpandClick() {\n      this.$emit('expand-click', this.row);\n    },\n    getFirstTdStyle() {\n      if (!this.isSelectable || !this.row.data[this.childrenKey]?.length)\n        return;\n\n      const elm = this.$el?.querySelector('td:first-child');\n\n      if (!elm || !this.indent) return;\n\n      const paddingLeft = window\n        .getComputedStyle(elm)\n        .paddingLeft.replace(/\\D/g, '');\n\n      this.firstTdStyle = {\n        paddingLeft: `${Number(paddingLeft) + this.indent}px`\n      };\n    },\n    getCellStyle(index) {\n      const style = {};\n\n      if (!this.indent) return style;\n\n      if (index === 0 && !this.isSelectable && this.$el) {\n        const elm = this.$el.querySelector('td:first-child');\n\n        if (elm) {\n          const paddingLeft = window\n            .getComputedStyle(elm)\n            .paddingLeft.replace(/\\D/g, '');\n\n          style.paddingLeft = `${Number(paddingLeft) + this.indentSize}px`;\n        }\n      }\n\n      return style;\n    },\n    updateRow(row, index, key, column) {\n      let value = get(row.data || row, key);\n\n      if (column.formatter) {\n        value = column.formatter(value, row, column);\n      }\n\n      return {\n        key,\n        index,\n        value,\n        indent: this.indent,\n        column,\n        data: row\n      };\n    }\n  }\n};\n</script>\n"
  },
  {
    "path": "src/qComponents/QTable/src/hocs/withQTableRow/index.js",
    "content": "const renderedChilds = ({\n  renderContext,\n  childrenKey,\n  listeners,\n  component,\n  children,\n  props,\n  scopedSlots\n}) => {\n  return children.reduce((acc, row) => {\n    const renderingArray = [];\n\n    renderingArray.push(\n      renderContext(component, {\n        props: {\n          ...props,\n          indent: row.indent,\n          row\n        },\n        on: { ...listeners },\n        scopedSlots\n      })\n    );\n\n    if (row[childrenKey]) {\n      const renderedData = {\n        renderContext,\n        childrenKey,\n        component,\n        listeners,\n        props,\n        scopedSlots,\n        children: row.data[childrenKey]\n      };\n\n      renderingArray.push(renderedChilds(renderedData));\n    }\n\n    return [...acc, ...renderingArray];\n  }, []);\n};\n\nconst withQTableRow = QTableRow => ({\n  functional: true,\n\n  name: 'withQTableRow',\n\n  render(renderContext, context) {\n    const { props, listeners, scopedSlots, data } = context;\n    const { childrenKey, row } = props;\n\n    const renderingArray = [];\n\n    if (row.data[childrenKey]) {\n      const renderedData = {\n        renderContext,\n        childrenKey,\n        component: QTableRow,\n        listeners,\n        children: row.data[childrenKey],\n        props,\n        scopedSlots\n      };\n\n      if (row.isTreeOpened) renderingArray.push(renderedChilds(renderedData));\n    }\n\n    return [renderContext(QTableRow, { ...data }), ...renderingArray];\n  }\n});\n\nexport default withQTableRow;\n"
  },
  {
    "path": "src/qComponents/QTable/src/q-table.scss",
    "content": "@keyframes spin {\n  from {\n    transform: rotate(0deg);\n  }\n\n  to {\n    transform: rotate(360deg);\n  }\n}\n\n.q-table {\n  --row-custom-border-color: transparent;\n  --custom-box-shadow: -1px -1px 3px rgba(var(--color-rgb-white), 0.25),\n    2px 1px 3px rgba(var(--color-rgb-blue), 0.4);\n\n  --custom-box-shadow-reversed: 1px -1px 3px rgba(var(--color-rgb-white), 0.25),\n    -2px 1px 3px rgba(var(--color-rgb-blue), 0.4);\n\n  &__fixed {\n    table-layout: fixed;\n  }\n\n  &__expand-arrow {\n    display: inline-block;\n    font-size: 23px;\n    vertical-align: middle;\n\n    &_opened {\n      transform: rotate(90deg);\n    }\n  }\n\n  &__drag-elements {\n    display: inline-block;\n    width: auto;\n    cursor: grab;\n  }\n\n  .dnd-separator,\n  .dnd-handler {\n    position: absolute;\n    display: none;\n    pointer-events: none;\n  }\n\n  .dnd-separator {\n    left: -100%;\n    z-index: 9;\n    width: 1px;\n    height: 100%;\n    background-color: var(--color-primary-blue);\n    box-shadow: 0 0 8px rgba(65, 98, 240, 0.24);\n  }\n\n  .dnd-handler {\n    z-index: 999;\n    height: 100%;\n    background-color: rgba(var(--color-rgb-gray), 0.16);\n  }\n\n  .drop-handler {\n    position: absolute;\n    top: 0;\n    left: -1px;\n    z-index: -1;\n    width: 50%;\n    height: 100%;\n\n    &.dnd-after {\n      right: 0;\n      left: auto;\n    }\n  }\n\n  .dragInit {\n    cursor: grabbing;\n    user-select: none;\n\n    .drop-handler {\n      z-index: 99;\n    }\n  }\n\n  &__wrapper {\n    position: relative;\n    height: 100%;\n    padding-right: 3px;\n\n    &_scrollable {\n      .q-table__table {\n        padding-bottom: 11px;\n      }\n    }\n\n    & .q-checkbox__inner {\n      z-index: 0;\n    }\n  }\n\n  &__loading-wrapper {\n    height: 100%;\n    overflow: hidden;\n  }\n\n  &__loader {\n    position: absolute;\n    top: 0;\n    left: 0;\n    z-index: 10;\n    display: flex;\n    justify-content: center;\n    width: 100%;\n    height: 100%;\n    min-height: 115px;\n    padding-top: 120px;\n    background-color: var(--color-tertiary-gray-light);\n    opacity: 0;\n    transition: height 0.2s, background-color 0.5s, opacity 0.2s 0.6s;\n\n    &-circle {\n      width: 64px;\n      height: 64px;\n      border-radius: 100%;\n      animation: spin 4s linear infinite;\n\n      &_quarter {\n        position: absolute;\n        display: block;\n        box-sizing: border-box;\n        width: 64px;\n        height: 64px;\n        border: 8px solid #fff;\n        border-color: var(--color-tertiary-gray-darker) transparent transparent\n          transparent;\n        border-radius: 50%;\n        animation: spin 1s cubic-bezier(0.5, 0, 0.5, 1) infinite;\n\n        &:nth-child(1) {\n          animation-delay: -0.3s;\n        }\n\n        &:nth-child(2) {\n          animation-delay: -0.2s;\n        }\n\n        &:nth-child(3) {\n          animation-delay: -0.1s;\n        }\n      }\n    }\n\n    &_is-loading {\n      z-index: 10;\n      opacity: 1;\n      transition: opacity 0.2s 0.1s;\n    }\n  }\n\n  &__table {\n    width: 100%;\n    margin-right: 3px;\n    border-spacing: 0 1px;\n    font-size: var(--font-size-base);\n    text-align: left;\n  }\n\n  &__grid {\n    border-spacing: 1px;\n  }\n\n  &__header-cell {\n    position: relative;\n    padding: 12px 24px;\n    overflow: hidden;\n    font-weight: var(--font-weight-bold);\n    line-height: var(--line-height-base);\n    vertical-align: bottom;\n    color: var(--color-primary-black);\n\n    &:not(.q-table__header-cell__checkbox) [class*='q-icon'] {\n      font-size: 24px;\n      vertical-align: middle;\n    }\n\n    &-wrapper {\n      display: flex;\n      align-items: flex-end;\n    }\n\n    &_align-right .q-table__header-cell-wrapper {\n      flex-direction: row-reverse;\n    }\n\n    &-content {\n      display: flex;\n      white-space: nowrap;\n\n      .q-table__cell-sortable & {\n        cursor: pointer;\n      }\n\n      &_original {\n        display: -webkit-box;\n        align-items: flex-end;\n        width: auto;\n        overflow: hidden;\n        white-space: initial;\n        word-break: break-word;\n        -webkit-line-clamp: 2;\n        -webkit-box-orient: vertical;\n      }\n    }\n\n    .q-context-wrapper {\n      margin: -12px 0;\n    }\n\n    .drag-n-drop-icon {\n      color: var(--color-tertiary-gray-ultra-dark);\n    }\n\n    .q-table__separated & {\n      background-color: var(--color-tertiary-gray-light);\n      border-top-width: 4px;\n      border-top-style: solid;\n      box-shadow: var(--custom-box-shadow);\n\n      &.q-table__header-cell__checkbox {\n        border-top: none;\n      }\n\n      &:first-child {\n        border-top-left-radius: var(--border-radius-base);\n      }\n\n      &:last-child {\n        border-top-right-radius: var(--border-radius-base);\n      }\n    }\n\n    &:first-child {\n      padding-left: 16px;\n    }\n\n    &.q-table__sticked-cell {\n      background-color: var(--color-tertiary-gray-light);\n    }\n\n    &.q-table__cell-sortable {\n      & .q-table__sort-arrow {\n        vertical-align: middle;\n        color: inherit;\n        visibility: hidden;\n        cursor: pointer;\n      }\n\n      &_ascending,\n      &_descending {\n        cursor: pointer;\n\n        .q-table__sort-arrow {\n          color: var(--color-primary-blue);\n          visibility: visible;\n        }\n      }\n\n      &:hover .q-table__sort-arrow {\n        visibility: visible;\n      }\n    }\n  }\n\n  &__cell {\n    height: 64px;\n    padding: 12px 24px;\n    overflow: hidden;\n    font-weight: var(--font-weight-base);\n    line-height: 20px;\n    background-color: var(--color-tertiary-gray-light);\n    box-shadow: var(--custom-box-shadow);\n\n    &:first-child {\n      padding-left: 16px;\n    }\n\n    tr:first-child & {\n      &:first-child {\n        border-top-left-radius: var(--border-radius-base);\n      }\n\n      &:last-child {\n        border-top-right-radius: var(--border-radius-base);\n      }\n    }\n\n    tr:last-child & {\n      &:first-child {\n        border-bottom-left-radius: var(--border-radius-base);\n      }\n\n      &:last-child {\n        border-bottom-right-radius: var(--border-radius-base);\n      }\n    }\n  }\n\n  &__total-cell {\n    position: relative;\n    padding: 16px 24px;\n    overflow: hidden;\n    font-weight: 400;\n    text-align: left;\n    color: rgba(var(--color-rgb-gray), 0.64);\n    background-color: var(--color-tertiary-gray-ultra-light);\n    box-shadow: var(--custom-box-shadow);\n\n    &_selectable {\n      padding-left: 16px;\n    }\n  }\n\n  &__cell {\n    position: relative;\n  }\n\n  &__sticked-cell {\n    position: sticky;\n    left: 0;\n    z-index: 2;\n    box-shadow: var(--custom-box-shadow);\n\n    &_is-reversed {\n      box-shadow: var(--custom-box-shadow-reversed);\n    }\n  }\n\n  &__row {\n    &_is-interactive {\n      cursor: pointer;\n\n      &:hover .q-table__cell {\n        background-color: var(--color-tertiary-gray);\n      }\n    }\n  }\n\n  tr {\n    &.green-row,\n    &.red-row,\n    &.grey-row,\n    &.dark-row,\n    &.yellow-row,\n    &.custom-border {\n      & td:first-child {\n        padding-left: 12px;\n        border-left: 4px solid;\n      }\n    }\n\n    &.green-row td:first-child {\n      border-left-color: var(--color-secondary-green);\n    }\n\n    &.red-row td:first-child {\n      border-left-color: var(--color-secondary-orange);\n    }\n\n    &.grey-row td:first-child {\n      border-left-color: rgba(var(--color-rgb-gray), 0.32);\n    }\n\n    &.dark-row td:first-child {\n      border-left-color: rgba(var(--color-rgb-gray), 0.64);\n    }\n\n    &.yellow-row td:first-child {\n      border-left-color: var(--color-secondary-yellow);\n    }\n\n    &.custom-border td:first-child {\n      border-left-color: var(--row-custom-border-color);\n    }\n  }\n\n  &__empty {\n    display: flex;\n    flex-direction: column;\n    justify-content: center;\n    align-items: center;\n    width: 100%;\n    height: 228px;\n    background-color: var(--color-tertiary-gray-light);\n    border-radius: var(--border-radius-base);\n    box-shadow: var(--custom-box-shadow);\n\n    &-image {\n      width: 148px;\n      height: 148px;\n      margin-bottom: 8px;\n      background-color: var(--color-tertiary-gray-ultra-light);\n      border-radius: 50%;\n\n      $--base-path: '../../..' !default;\n\n      &::before {\n        content: '';\n        display: block;\n        width: 160px;\n        height: 160px;\n        margin-top: -6px;\n        margin-left: -6px;\n        background-image: url('#{$--base-path}/assets/empty-table-v2.svg');\n        background-size: 100%;\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "src/qComponents/QTabs/QTabs.test.js",
    "content": "import Component from './src/QTabs';\n\ndescribe('QTabs', () => {\n  it('should match snapshot', () => {\n    const instance = shallowMount(Component);\n\n    expect(instance.element).toMatchSnapshot();\n  });\n\n  it('data should match snapshot', () => {\n    expect(Component.data()).toMatchSnapshot();\n  });\n});\n"
  },
  {
    "path": "src/qComponents/QTabs/__snapshots__/QTabs.test.js.snap",
    "content": "// Jest Snapshot v1, https://goo.gl/fbAQLP\n\nexports[`QTabs data should match snapshot 1`] = `\nObject {\n  \"currentName\": \"\",\n}\n`;\n\nexports[`QTabs should match snapshot 1`] = `\n<div\n  class=\"q-tabs\"\n/>\n`;\n"
  },
  {
    "path": "src/qComponents/QTabs/index.js",
    "content": "import QTabs from './src/QTabs';\n\nQTabs.install = Vue => {\n  Vue.component(QTabs.name, QTabs);\n};\n\nexport default QTabs;\n"
  },
  {
    "path": "src/qComponents/QTabs/src/QTabs.vue",
    "content": "<template>\n  <div class=\"q-tabs\">\n    <slot />\n  </div>\n</template>\n\n<script>\nexport default {\n  name: 'QTabs',\n  componentName: 'QTabs',\n\n  model: {\n    prop: 'value',\n    event: 'change'\n  },\n\n  provide() {\n    return {\n      qTabs: this\n    };\n  },\n\n  props: {\n    /**\n     * width of QTabPanes\n     */\n    tabWidth: {\n      type: [String, Number],\n      default: null\n    },\n    value: {\n      type: String,\n      default: null\n    },\n    /**\n     * whether QTabs is disabled\n     */\n    disabled: {\n      type: Boolean,\n      default: false\n    }\n  },\n\n  data() {\n    return {\n      currentName: ''\n    };\n  },\n\n  watch: {\n    value: {\n      immediate: true,\n      handler(name) {\n        this.updateValue(name);\n      }\n    }\n  },\n\n  methods: {\n    updateValue(name) {\n      /**\n       * triggers when the tab changes\n       */\n      this.$emit('change', name);\n      this.currentName = name;\n    }\n  }\n};\n</script>\n"
  },
  {
    "path": "src/qComponents/QTabs/src/q-tabs.scss",
    "content": ".q-tabs {\n  display: flex;\n}\n"
  },
  {
    "path": "src/qComponents/QTag/QTag.test.js",
    "content": "import Component from './src/QTag';\n\ndescribe('QTag', () => {\n  it('should match snapshot', async () => {\n    const { element } = shallowMount(Component);\n    expect(element).toMatchSnapshot();\n  });\n\n  describe('methods', () => {\n    describe('handleClose', () => {\n      it('should emit close', () => {\n        const instance = shallowMount(Component);\n\n        instance.vm.handleClose();\n\n        expect(instance.emitted().close).toBeTruthy();\n      });\n    });\n  });\n});\n"
  },
  {
    "path": "src/qComponents/QTag/__snapshots__/QTag.test.js.snap",
    "content": "// Jest Snapshot v1, https://goo.gl/fbAQLP\n\nexports[`QTag should match snapshot 1`] = `\n<div\n  class=\"q-tag\"\n>\n  <div\n    class=\"q-tag__text\"\n  />\n   \n  <!---->\n</div>\n`;\n"
  },
  {
    "path": "src/qComponents/QTag/index.js",
    "content": "import QTag from './src/QTag';\n\nQTag.install = Vue => {\n  Vue.component(QTag.name, QTag);\n};\n\nexport default QTag;\n"
  },
  {
    "path": "src/qComponents/QTag/src/QTag.vue",
    "content": "<template>\n  <div\n    class=\"q-tag\"\n    :class=\"{\n      'q-tag_closable': closable\n    }\"\n  >\n    <div class=\"q-tag__text\">\n      <!-- @slot text of QTag -->\n      <slot />\n    </div>\n    <button\n      v-if=\"closable\"\n      type=\"button\"\n      class=\"q-tag__close q-icon-close\"\n      @click.stop=\"handleClose\"\n    />\n  </div>\n</template>\n\n<script>\nexport default {\n  name: 'QTag',\n  componentName: 'QTag',\n\n  props: {\n    /**\n     * whether is close button shown\n     */\n    closable: {\n      type: Boolean,\n      default: false\n    }\n  },\n\n  methods: {\n    handleClose(event) {\n      /**\n       * triggers when the close button is clicked\n       */\n      this.$emit('close', event);\n    }\n  }\n};\n</script>\n"
  },
  {
    "path": "src/qComponents/QTag/src/q-tag.scss",
    "content": ".q-tag {\n  position: relative;\n  display: inline-flex;\n  align-items: center;\n  box-sizing: border-box;\n  max-width: 100%;\n  margin-top: 2px;\n  margin-right: 4px;\n  margin-bottom: 2px;\n  padding-right: 8px;\n  padding-left: 8px;\n  line-height: 20px;\n  color: rgba(var(--color-rgb-gray), 0.64);\n  background-color: var(--color-tertiary-gray-darker);\n  border-radius: 2px;\n\n  &_closable {\n    padding-right: 2px;\n  }\n\n  .q-cascader &:first-child {\n    max-width: 65%;\n  }\n\n  &__text {\n    display: -webkit-box;\n    -webkit-line-clamp: 1;\n    -webkit-box-orient: vertical;\n    overflow: hidden;\n    word-break: break-all;\n  }\n\n  &__close {\n    width: 16px;\n    height: 16px;\n    margin-left: 4px;\n    padding: 0;\n    font-size: 16px;\n    line-height: 1;\n    text-align: center;\n    color: rgba(var(--color-rgb-gray), 0.64);\n    background-color: transparent;\n    border: none;\n    cursor: pointer;\n    pointer-events: auto;\n\n    &:focus,\n    &:hover {\n      color: var(--color-primary-black);\n    }\n  }\n}\n"
  },
  {
    "path": "src/qComponents/QTextarea/index.js",
    "content": "import QTextarea from './src/QTextarea.vue';\n\n/* istanbul ignore next */\nQTextarea.install = function(Vue) {\n  Vue.component(QTextarea.name, QTextarea);\n};\n\nexport default QTextarea;\n"
  },
  {
    "path": "src/qComponents/QTextarea/src/QTextarea.vue",
    "content": "<template>\n  <div\n    :class=\"classes\"\n    @mouseenter=\"hovering = true\"\n    @mouseleave=\"hovering = false\"\n  >\n    <div\n      v-if=\"isSymbolLimitShown\"\n      class=\"q-textarea__count\"\n    >\n      {{ $t('QTextarea.charNumber') }}: {{ textLength }}/{{ upperLimit }}\n    </div>\n    <textarea\n      ref=\"textarea\"\n      :tabindex=\"tabindex\"\n      class=\"q-textarea__inner\"\n      v-bind=\"$attrs\"\n      :disabled=\"inputDisabled\"\n      :readonly=\"readonly\"\n      :autocomplete=\"autocomplete\"\n      :style=\"textareaStyle\"\n      :aria-label=\"label\"\n      @compositionstart=\"handleCompositionStart\"\n      @compositionend=\"handleCompositionEnd\"\n      @input=\"handleInput\"\n      @focus=\"handleFocus\"\n      @blur=\"handleBlur\"\n      @change=\"handleChange\"\n    />\n  </div>\n</template>\n<script>\nimport emitter from '../../mixins/emitter';\nimport inputs from '../../mixins/inputs';\nimport calcTextareaHeight from './calcTextareaHeight';\n\nexport default {\n  name: 'QTextarea',\n  componentName: 'QTextarea',\n\n  mixins: [emitter, inputs],\n\n  props: {\n    /**\n     * control the resizability\n     */\n    resize: {\n      type: String,\n      default: 'vertical',\n      validator: value =>\n        ['vertical', 'horizontal', 'both', 'none'].includes(value)\n    },\n    /**\n     * whether textarea has an adaptive height. Can accept an object, e.g. { minRows: 2, maxRows: 6 }\n     */\n    autosize: {\n      type: [Boolean, Object],\n      default: false\n    },\n    autocomplete: {\n      type: String,\n      default: 'off'\n    }\n  },\n\n  data() {\n    return {\n      textareaCalcStyle: {}\n    };\n  },\n\n  computed: {\n    classes() {\n      const mainClass = 'q-textarea';\n\n      return [\n        mainClass,\n        {\n          [`${mainClass}_disabled`]: this.inputDisabled\n        }\n      ];\n    },\n    textareaStyle() {\n      return { ...this.textareaCalcStyle, resize: this.resize };\n    },\n\n    componentRef() {\n      return this.$refs.textarea;\n    }\n  },\n\n  watch: {\n    value() {\n      this.$nextTick(this.resizeTextarea);\n\n      if (this.validateEvent) this.qFormItem?.validateField('change');\n    }\n  },\n\n  mounted() {\n    this.setNativeInputValue();\n    this.resizeTextarea();\n  },\n\n  methods: {\n    resizeTextarea() {\n      const { autosize } = this;\n      if (!autosize) {\n        this.textareaCalcStyle = {\n          minHeight: calcTextareaHeight(this.$refs.textarea).minHeight\n        };\n        return;\n      }\n      const minRows = autosize.minRows;\n      const maxRows = autosize.maxRows;\n\n      this.textareaCalcStyle = calcTextareaHeight(\n        this.$refs.textarea,\n        minRows,\n        maxRows\n      );\n    }\n  }\n};\n</script>\n"
  },
  {
    "path": "src/qComponents/QTextarea/src/calcTextareaHeight.js",
    "content": "let hiddenTextarea;\n\nconst HIDDEN_STYLE = `\n  height:0 !important;\n  visibility:hidden !important;\n  overflow:hidden !important;\n  position:absolute !important;\n  z-index:-1000 !important;\n  top:0 !important;\n  right:0 !important\n`;\n\nconst CONTEXT_STYLE = [\n  'letter-spacing',\n  'line-height',\n  'padding-top',\n  'padding-bottom',\n  'font-family',\n  'font-weight',\n  'font-size',\n  'text-rendering',\n  'text-transform',\n  'width',\n  'text-indent',\n  'padding-left',\n  'padding-right',\n  'border-width',\n  'box-sizing'\n];\n\nfunction calculateNodeStyling(targetElement) {\n  const style = window.getComputedStyle(targetElement);\n\n  const boxSizing = style.getPropertyValue('box-sizing');\n\n  const paddingSize =\n    parseFloat(style.getPropertyValue('padding-bottom')) +\n    parseFloat(style.getPropertyValue('padding-top'));\n\n  const borderSize =\n    parseFloat(style.getPropertyValue('border-bottom-width')) +\n    parseFloat(style.getPropertyValue('border-top-width'));\n\n  const contextStyle = CONTEXT_STYLE.map(\n    name => `${name}:${style.getPropertyValue(name)}`\n  ).join(';');\n\n  return { contextStyle, paddingSize, borderSize, boxSizing };\n}\n\nexport default function calcTextareaHeight(\n  targetElement,\n  minRows = 1,\n  maxRows = null\n) {\n  if (!hiddenTextarea) {\n    hiddenTextarea = document.createElement('textarea');\n    document.body.appendChild(hiddenTextarea);\n  }\n\n  const {\n    paddingSize,\n    borderSize,\n    boxSizing,\n    contextStyle\n  } = calculateNodeStyling(targetElement);\n\n  hiddenTextarea.setAttribute('style', `${contextStyle};${HIDDEN_STYLE}`);\n  hiddenTextarea.value = targetElement.value || targetElement.placeholder || '';\n\n  let height = hiddenTextarea.scrollHeight;\n  const result = {};\n\n  if (boxSizing === 'border-box') {\n    height += borderSize;\n  } else if (boxSizing === 'content-box') {\n    height -= paddingSize;\n  }\n\n  hiddenTextarea.value = '';\n  const singleRowHeight = hiddenTextarea.scrollHeight - paddingSize;\n\n  if (minRows !== null) {\n    let minHeight = singleRowHeight * minRows;\n    if (boxSizing === 'border-box') {\n      minHeight = minHeight + paddingSize + borderSize;\n    }\n    height = Math.max(minHeight, height);\n    result.minHeight = `${minHeight}px`;\n  }\n  if (maxRows !== null) {\n    let maxHeight = singleRowHeight * maxRows;\n    if (boxSizing === 'border-box') {\n      maxHeight = maxHeight + paddingSize + borderSize;\n    }\n    height = Math.min(maxHeight, height);\n  }\n  result.height = `${height}px`;\n  hiddenTextarea.parentNode &&\n    hiddenTextarea.parentNode.removeChild(hiddenTextarea);\n  hiddenTextarea = null;\n  return result;\n}\n"
  },
  {
    "path": "src/qComponents/QTextarea/src/q-textarea.scss",
    "content": ".q-textarea {\n  --field-color-base: var(--color-primary-black);\n  --field-color-placeholder: rgba(var(--color-rgb-gray), 0.32);\n  --field-color-disabled: rgba(var(--color-rgb-gray), 0.64);\n\n  --field-icon-color-base: var(--color-primary-blue);\n  --field-icon-color-hover: var(--color-primary-black);\n  --field-icon-color-inactive: rgba(var(--color-rgb-gray), 0.64);\n\n  --field-background-color-base: var(--color-tertiary-gray-light);\n  --field-background-color-hover: var(--color-tertiary-gray);\n  --field-background-color-focus: var(--color-tertiary-gray-ultra-light);\n  --field-background-color-disabled: var(--color-tertiary-gray);\n\n  --field-box-shadow-base: -1px -1px 3px rgba(var(--color-rgb-white), 0.25),\n    1px 1px 3px rgba(var(--color-rgb-blue), 0.4),\n    4px 4px 8px rgba(var(--color-rgb-blue), 0.4),\n    -4px -4px 12px var(--color-tertiary-white);\n  --field-box-shadow-hover: -1px -1px 4px rgba(var(--color-rgb-white), 0.25),\n    1px 1px 4px rgba(var(--color-rgb-blue), 0.4),\n    4px 4px 8px rgba(var(--color-rgb-blue), 0.4),\n    -4px -4px 8px rgba(var(--color-rgb-white), 0.8);\n  --field-box-shadow-focus: -1px -1px 3px rgba(var(--color-rgb-white), 0.25),\n    1px 1px 3px rgba(var(--color-rgb-blue), 0.4),\n    inset -1px -1px 1px rgba(var(--color-rgb-white), 0.7),\n    inset 1px 1px 2px rgba(var(--color-rgb-blue), 0.2);\n  --field-box-shadow-disabled: -1px -1px 3px rgba(var(--color-rgb-white), 0.25),\n    1px 1px 3px rgba(var(--color-rgb-blue), 0.4);\n\n  position: relative;\n  display: inline-block;\n  width: 100%;\n  vertical-align: middle;\n\n  &__inner {\n    display: block;\n    width: 100%;\n    height: 40px;\n    padding: 10px 16px;\n    font-weight: var(--font-weight-base);\n    font-size: var(--font-size-base);\n    line-height: var(--line-height-base);\n    color: var(--field-color-base);\n    text-overflow: ellipsis;\n    background-color: var(--field-background-color-base);\n    border: none;\n    border-radius: var(--border-radius-base);\n    box-shadow: var(--field-box-shadow-base);\n    resize: vertical;\n\n    &::placeholder {\n      color: var(--field-color-placeholder);\n      text-overflow: ellipsis;\n      opacity: 1;\n    }\n\n    &:hover {\n      background-color: var(--field-background-color-hover);\n      box-shadow: var(--field-box-shadow-hover);\n    }\n\n    &:focus {\n      background-color: var(--field-background-color-focus);\n      outline: none;\n      box-shadow: var(--field-box-shadow-focus);\n    }\n\n    &::-webkit-scrollbar {\n      width: 2px;\n    }\n\n    &::-webkit-scrollbar:hover {\n      width: 6px;\n      cursor: default;\n    }\n\n    &::-webkit-scrollbar-thumb {\n      background-color: var(--color-primary-blue);\n      border-radius: var(--border-radius-base);\n    }\n\n    .q-form-item_is-error & {\n      padding: 9px 15px;\n      border: var(--border-error);\n    }\n  }\n\n  &_disabled {\n    &::after {\n      content: '\\e930';\n      position: absolute;\n      top: 0;\n      right: 0;\n      width: 40px;\n      font-size: 24px;\n      line-height: 40px;\n      font-family: 'qicon';\n      cursor: not-allowed;\n      pointer-events: none;\n    }\n\n    .q-textarea__inner {\n      padding-right: 40px;\n      color: var(--field-color-disabled);\n      background-color: var(--field-background-color-disabled);\n      box-shadow: var(--field-box-shadow-disabled);\n      cursor: not-allowed;\n    }\n  }\n\n  &__count {\n    margin-bottom: 2px;\n    font-size: 10px;\n    text-align: right;\n  }\n}\n"
  },
  {
    "path": "src/qComponents/QTimePicker/index.js",
    "content": "import QTimePicker from './src/QTimePicker';\n\nQTimePicker.install = Vue => {\n  Vue.component(QTimePicker.name, QTimePicker);\n};\n\nexport default QTimePicker;\n"
  },
  {
    "path": "src/qComponents/QTimePicker/src/QTimePicker.vue",
    "content": "<template>\n  <div\n    v-click-outside=\"hidePopper\"\n    class=\"q-time-picker\"\n  >\n    <q-input\n      ref=\"reference\"\n      :value=\"displayValue\"\n      class=\"q-time-picker__input\"\n      :disabled=\"isTimePickerDisabled\"\n      @focus=\"showPopper\"\n      @input=\"handleInput\"\n      @change=\"handleChange\"\n      @mouseenter.native=\"handleMouseEnter\"\n      @mouseleave.native=\"showClose = false\"\n    >\n      <span\n        slot=\"suffix\"\n        class=\"q-input__icon\"\n        :class=\"iconClass\"\n        @click=\"handleClickIcon\"\n      />\n    </q-input>\n    <time-panel\n      ref=\"panel\"\n      :value=\"parsedTime\"\n      :disabled-values=\"disabledValues\"\n      :visible=\"Boolean(popper)\"\n      :minutes-gap=\"minutesGap\"\n      :seconds-gap=\"secondsGap\"\n      @change=\"handleTimeChange\"\n    />\n  </div>\n</template>\n\n<script>\nimport { isDate } from 'date-fns';\nimport { createPopper } from '@popperjs/core';\nimport Pickers from '../../mixins/pickers';\nimport TimePanel from './components/panel';\nimport { addZero, isTimeValueValid } from '../../helpers/dateHelpers';\n\nexport default {\n  name: 'QTimePicker',\n  componentName: 'QTimePicker',\n  components: {\n    TimePanel\n  },\n  inject: {\n    qForm: {\n      default: null\n    },\n    qFormItem: {\n      default: null\n    }\n  },\n  mixins: [Pickers],\n  props: {\n    /**\n     * date or string '00:00:00'\n     */\n    value: {\n      type: [Date, String],\n      default: null,\n      validator: isTimeValueValid\n    },\n    /**\n     * whether QTimePicker is disabled\n     */\n    disabled: {\n      type: Boolean,\n      default: false\n    },\n    /**\n     * whether QTimePicker is clearable\n     */\n    clearable: {\n      type: Boolean,\n      default: true\n    },\n    /**\n     * any field is optional:\n     * `to` - example string '10:10:10', disable all before this value',\n     * `from` - example string '10:10:10', disable after this value,\n     */\n    disabledValues: {\n      type: Object,\n      default: null\n    },\n    minutesGap: {\n      type: [String, Number],\n      default: 1\n    },\n    secondsGap: {\n      type: [String, Number],\n      default: 1\n    }\n  },\n  data() {\n    return {\n      popper: null,\n      showClose: false,\n      userInput: null\n    };\n  },\n\n  computed: {\n    isTimePickerDisabled() {\n      return this.disabled || this.qForm?.disabled;\n    },\n\n    iconClass() {\n      const defaultClass = this.isTimePickerDisabled\n        ? 'q-icon-lock'\n        : 'q-icon-clock-stroke';\n      return this.showClose ? 'q-icon-close' : defaultClass;\n    },\n\n    parsedTime() {\n      if (isDate(this.value)) {\n        return {\n          hours: addZero(this.value.getHours()),\n          minutes: addZero(this.value.getMinutes()),\n          seconds: addZero(this.value.getSeconds())\n        };\n      }\n\n      const timeString = isTimeValueValid(this.value) ? this.value : '';\n      if (!timeString) return '';\n      const time = timeString.split(':');\n      return {\n        hours: addZero(time[0]),\n        minutes: addZero(time[1]),\n        seconds: addZero(time[2])\n      };\n    },\n    displayValue() {\n      if (this.userInput !== null) {\n        return this.userInput;\n      }\n\n      if (this.parsedTime) {\n        const { hours, minutes, seconds } = this.parsedTime;\n        return `${hours}:${minutes}:${seconds}`;\n      }\n\n      return '';\n    }\n  },\n\n  beforeDestroy() {\n    this.destroyPopper();\n  },\n\n  methods: {\n    handleMouseEnter() {\n      if (this.disabled) return;\n      if (this.clearable && (this.userInput || this.value)) {\n        this.showClose = true;\n      }\n    },\n    handleClickIcon() {\n      this.showClose = false;\n      this.$emit('change', null);\n    },\n\n    handleChange() {\n      if (this.userInput) {\n        if (isTimeValueValid(this.userInput)) {\n          this.$emit('change', this.userInput);\n        }\n      } else {\n        this.$emit('change', null);\n      }\n      this.userInput = null;\n    },\n\n    handleTimeChange({ type, value }) {\n      const newValue = {\n        ...(this.parsedTime\n          ? this.parsedTime\n          : {\n              hours: '00',\n              minutes: '00',\n              seconds: '00'\n            })\n      };\n      newValue[type] = value;\n      const result = `${newValue.hours}:${newValue.minutes}:${newValue.seconds}`;\n      this.$emit('change', result);\n      this.qFormItem?.validateField('change');\n    },\n\n    createPopper() {\n      const reference = this.$refs.reference.$el;\n      const panel = this.$refs.panel.$el;\n\n      this.popper = createPopper(reference, panel, {\n        modifiers: [\n          {\n            name: 'offset',\n            options: {\n              offset: [0, 8]\n            }\n          },\n          {\n            name: 'flip',\n            options: {\n              fallbackPlacements: ['top', 'bottom']\n            }\n          }\n        ]\n      });\n    },\n\n    destroyPopper() {\n      if (this.popper) {\n        this.popper.destroy();\n        this.popper = null;\n      }\n\n      const dropdown = this.$refs?.panel?.$el;\n      if (dropdown?.parentNode === document.body) {\n        document.body.removeChild(dropdown);\n      }\n    },\n\n    showPopper() {\n      this.$refs.panel.$el.setAttribute('data-show', '');\n      this.createPopper();\n    },\n\n    hidePopper() {\n      this.$refs.panel.$el.removeAttribute('data-show');\n      this.destroyPopper();\n    }\n  }\n};\n</script>\n"
  },
  {
    "path": "src/qComponents/QTimePicker/src/components/panel.vue",
    "content": "<template>\n  <div :class=\"timePanelClasses\">\n    <div class=\"time-panel__common\">\n      {{ fullTime }}\n    </div>\n    <div class=\"time-panel__pickers\">\n      <div class=\"time-panel__hours\">\n        <div class=\"time-panel__sign\">{{ $t('QTimePicker.hour') }}</div>\n        <div class=\"time-panel__scrollbar\">\n          <q-scrollbar :scroll-to=\"hoursElement\">\n            <button\n              v-for=\"hour in hours\"\n              :key=\"hour\"\n              class=\"cell cell_time cell_hours\"\n              type=\"button\"\n              tabindex=\"-1\"\n              :disabled=\"getDisabled({ type: 'hours', value: hour })\"\n              :class=\"getClasses({ type: 'hours', value: hour })\"\n              @click=\"$emit('change', { type: 'hours', value: hour })\"\n            >\n              {{ hour }}\n            </button>\n          </q-scrollbar>\n        </div>\n      </div>\n      <div class=\"time-panel__minutes\">\n        <div class=\"time-panel__scrollbar\">\n          <div class=\"time-panel__sign\">{{ $t('QTimePicker.minute') }}</div>\n          <q-scrollbar :scroll-to=\"minutesElement\">\n            <button\n              v-for=\"minute in minutes\"\n              :key=\"minute\"\n              class=\"cell cell_time cell_minutes\"\n              type=\"button\"\n              tabindex=\"-1\"\n              :disabled=\"getDisabled({ type: 'minutes', value: minute })\"\n              :class=\"getClasses({ type: 'minutes', value: minute })\"\n              @click=\"$emit('change', { type: 'minutes', value: minute })\"\n            >\n              {{ minute }}\n            </button>\n          </q-scrollbar>\n        </div>\n      </div>\n      <div class=\"time-panel__seconds\">\n        <div class=\"time-panel__scrollbar\">\n          <div class=\"time-panel__sign\">{{ $t('QTimePicker.second') }}</div>\n          <q-scrollbar :scroll-to=\"secondsElement\">\n            <button\n              v-for=\"second in seconds\"\n              :key=\"second\"\n              class=\"cell cell_time cell_seconds\"\n              type=\"button\"\n              tabindex=\"-1\"\n              :class=\"getClasses({ type: 'seconds', value: second })\"\n              :disabled=\"getDisabled({ type: 'seconds', value: second })\"\n              @click=\"$emit('change', { type: 'seconds', value: second })\"\n            >\n              {{ second }}\n            </button>\n          </q-scrollbar>\n        </div>\n      </div>\n    </div>\n  </div>\n</template>\n\n<script>\nimport { isString } from 'lodash-es';\nimport { isDate, format } from 'date-fns';\nimport { addZero, isTimeValueValid } from '../../../helpers/dateHelpers';\n\nconst calcValuesWithGap = gap => {\n  const values = [];\n  [...Array(60).keys()].forEach(value => {\n    if (value % gap === 0) {\n      values.push(addZero(value));\n    }\n  });\n\n  return values;\n};\n\nconst findElement = (target, querySelector, value) => {\n  const elements = target.querySelectorAll(querySelector);\n  const elementsArray = Array.prototype.slice.call(elements);\n  const element = elementsArray.find(cell => cell.innerText === value);\n\n  return element;\n};\n\nexport default {\n  name: 'TimePanel',\n  props: {\n    disabledValues: {\n      type: Object,\n      default: () => ({ to: null, from: null, ranges: null })\n    },\n    visible: {\n      type: Boolean,\n      default: false\n    },\n    prefixToTime: {\n      type: String,\n      default: null\n    },\n    minutesGap: {\n      type: [String, Number],\n      default: 1\n    },\n    secondsGap: {\n      type: [String, Number],\n      default: 1\n    },\n    value: {\n      type: [Object, String],\n      default: () => ({\n        hours: '00',\n        minutes: '00',\n        seconds: '00'\n      })\n    },\n    disabled: {\n      type: Boolean,\n      default: false\n    },\n    panelInFocus: {\n      type: Boolean,\n      default: false\n    }\n  },\n\n  data() {\n    return {\n      hoursElement: null,\n      minutesElement: null,\n      secondsElement: null\n    };\n  },\n\n  computed: {\n    timePanelClasses() {\n      return {\n        'time-panel': true,\n        'time-panel_focused': this.panelInFocus\n      };\n    },\n    hours() {\n      return [...Array(24).keys()].map(hour => addZero(hour));\n    },\n    minutes() {\n      return calcValuesWithGap(this.minutesGap);\n    },\n    seconds() {\n      return calcValuesWithGap(this.secondsGap);\n    },\n    fullTime() {\n      const time = this.value\n        ? `${this.value.hours}:${this.value.minutes}:${this.value.seconds}`\n        : '__:__:__';\n\n      return this.prefixToTime ? `${this.prefixToTime} ${time}` : time;\n    }\n  },\n\n  watch: {\n    value(value) {\n      this.scrollToPickedElements(value);\n    },\n    visible(isVisible) {\n      if (isVisible) this.scrollToPickedElements(this.value);\n    }\n  },\n\n  methods: {\n    scrollToPickedElements(value) {\n      if (!value) return;\n      this.hoursElement = findElement(this.$el, '.cell_hours', value.hours);\n      this.minutesElement = findElement(\n        this.$el,\n        '.cell_minutes',\n        value.minutes\n      );\n      this.secondsElement = findElement(\n        this.$el,\n        '.cell_seconds',\n        value.seconds\n      );\n    },\n    getDisabled({ type, value }) {\n      if (this.disabled) return true;\n      let disabled = false;\n      let to = this.disabledValues?.to;\n      if (isDate(to)) {\n        to = format(to, 'HH:mm:ss');\n      }\n\n      let from = this.disabledValues?.from;\n      if (isDate(from)) {\n        from = format(from, 'HH:mm:ss');\n      }\n\n      if (to || from) {\n        const [toHours, toMinutes, toSeconds] =\n          isString(to) && isTimeValueValid(to) ? to.split(':') : [];\n        const [fromHours, fromMinutes, fromSeconds] =\n          isString(from) && isTimeValueValid(from) ? from.split(':') : [];\n        switch (type) {\n          default:\n            disabled = false;\n            break;\n          case 'hours':\n            disabled =\n              (toHours && Number(value) < toHours) ||\n              (fromHours && Number(value) > fromHours);\n            break;\n          case 'minutes':\n            disabled =\n              (toMinutes && Number(value) < toMinutes) ||\n              (fromMinutes && Number(value) > fromMinutes);\n            break;\n          case 'seconds':\n            disabled =\n              (toSeconds && Number(value) < toSeconds) ||\n              (fromSeconds && Number(value) > fromSeconds);\n            break;\n        }\n      }\n\n      return disabled;\n    },\n    getClasses({ type, value }) {\n      return { cell_current: this.value?.[type] === value };\n    }\n  }\n};\n</script>\n"
  },
  {
    "path": "src/qComponents/QTimePicker/src/components/time-panel.scss",
    "content": ".time-panel {\n  position: relative;\n  z-index: 1;\n  display: none;\n  width: 124px;\n  height: 256px;\n  padding: 5px 0;\n  font-size: 10px;\n  background: var(--color-tertiary-gray-light);\n  border-radius: var(--border-radius-base);\n  box-shadow: var(--box-shadow-secondary);\n\n  &[data-show] {\n    display: block;\n  }\n\n  &_no-right-borders {\n    border-top-right-radius: 0;\n    border-bottom-right-radius: 0;\n  }\n\n  &_no-left-borders {\n    margin-left: 1px;\n    border-top-left-radius: 0;\n    border-bottom-left-radius: 0;\n  }\n\n  &_focused {\n    z-index: 2;\n    border-radius: 4px;\n    outline: none;\n    box-shadow: var(--box-shadow-secondary);\n    transform: scale(1.03);\n    transition: transform 0.2s;\n  }\n\n  &__sign {\n    height: 19px;\n    font-weight: 500;\n    text-align: center;\n\n    &::after {\n      content: '';\n      position: relative;\n      top: -4px;\n      z-index: 1;\n      display: block;\n      height: 6px;\n      background: linear-gradient(to bottom, #f0f0f3, transparent);\n    }\n  }\n\n  &__common {\n    padding: 10px 0 11px;\n    font-weight: 400;\n    line-height: 10px;\n    text-align: center;\n    color: var(--color-primary-black);\n  }\n\n  &__pickers {\n    display: flex;\n    justify-content: center;\n    height: 201px;\n  }\n\n  &__scrollbar {\n    width: 35px;\n    height: 201px;\n  }\n\n  .cell {\n    position: relative;\n    display: block;\n    box-sizing: border-box;\n    width: 20px;\n    height: 20px;\n    margin: 12px auto;\n    padding: 0;\n    font-weight: var(--font-weight-base);\n    line-height: 20px;\n    color: var(--color-primary-blue);\n    background-color: var(--color-tertiary-gray-light);\n    border: none;\n    border-radius: var(--border-radius-base);\n    box-shadow: 36px 2px 45px #fff, 4px 4px 8px rgba(var(--color-rgb-blue), 0.4),\n      1px 1px 3px rgba(var(--color-rgb-blue), 0.4),\n      -1px -1px 3px rgba(var(--color-rgb-white), 0.25);\n    cursor: pointer;\n\n    &:first-child {\n      margin-top: 10px;\n    }\n\n    &:last-child {\n      margin-bottom: 5px;\n    }\n\n    &[data-focus-visible-added] {\n      &:not(.cell_disabled) {\n        color: var(--color-tertiary-white);\n        background-color: var(--color-primary-blue);\n        box-shadow: var(--box-shadow-pressed);\n        transform: scale(1.2);\n        transition: transform 0.2s;\n      }\n    }\n\n    &:hover {\n      &:not(.cell_current) {\n        color: var(--color-primary-black);\n        background-color: var(--color-tertiary-gray);\n      }\n    }\n\n    &[disabled] {\n      color: rgba(var(--color-primary-black), 0.64);\n      background-color: var(--color-tertiary-gray);\n      cursor: not-allowed;\n      opacity: 1;\n\n      &:hover {\n        color: rgba(var(--color-primary-black), 0.64);\n      }\n    }\n\n    &_current {\n      color: #fff;\n      background-color: var(--color-primary-blue);\n\n      &:hover {\n        color: #fff;\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "src/qComponents/QTimePicker/src/q-time-picker.scss",
    "content": "@import '../src/components/time-panel.scss';\n\n.q-time-picker {\n  &__input {\n    position: relative;\n  }\n}\n"
  },
  {
    "path": "src/qComponents/QUpload/index.js",
    "content": "import QUpload from './src/QUpload.vue';\n\nQUpload.install = function(Vue) {\n  Vue.component(QUpload.name, QUpload);\n};\n\nexport default QUpload;\n"
  },
  {
    "path": "src/qComponents/QUpload/src/QUpload.vue",
    "content": "<template>\n  <div\n    class=\"q-upload\"\n    :class=\"classes\"\n  >\n    <q-upload-drop-zone\n      :is-disabled=\"isDisabled\"\n      :is-loading=\"isLoading\"\n      :text-upload-file=\"textUploadFile\"\n      :text-replace-file=\"textReplaceFile\"\n      :text-loading-file=\"textLoadingFile\"\n      @click.native=\"handleUploadClick\"\n      @keyup.enter.native=\"handleUploadClick\"\n    />\n\n    <input\n      ref=\"fileInput\"\n      class=\"q-upload__input\"\n      type=\"file\"\n      tabindex=\"-1\"\n      :accept=\"accept.toString()\"\n      :multiple=\"multiple\"\n      @change=\"processFile\"\n    />\n\n    <q-upload-file-multiple\n      v-if=\"multiple\"\n      :value=\"value\"\n      :is-disabled=\"isDisabled\"\n      :is-clearable=\"clearable\"\n      @clear-all=\"handleClearAll\"\n      @clear=\"handleClear\"\n      @abort=\"handleAbort\"\n    />\n    <template v-else>\n      <q-upload-file-single\n        v-if=\"value\"\n        :value=\"value\"\n        :is-loading=\"isLoading\"\n        :is-disabled=\"isDisabled\"\n        :is-clearable=\"clearable\"\n        :text-uploaded-files=\"textUploadedFiles\"\n        @clear=\"handleClear\"\n        @abort=\"handleAbort\"\n      />\n    </template>\n  </div>\n</template>\n\n<script>\nimport { isNil } from 'lodash-es';\n\nimport { randId } from '../../helpers';\n\nimport QUploadDropZone from './QUploadDropZone';\nimport QUploadFileSingle from './QUploadFileSingle';\nimport QUploadFileMultiple from './QUploadFileMultiple';\n\nexport default {\n  name: 'QUpload',\n  componentName: 'QUpload',\n\n  components: {\n    QUploadDropZone,\n    QUploadFileSingle,\n    QUploadFileMultiple\n  },\n\n  model: {\n    prop: 'value',\n    event: 'change'\n  },\n\n  inject: {\n    qForm: {\n      default: null\n    },\n    qFormItem: {\n      default: null\n    }\n  },\n\n  props: {\n    value: {\n      type: [Object, Array],\n      default: null\n    },\n    /**\n     * whether uploading multiple files is permitted\n     */\n    multiple: {\n      type: Boolean,\n      default: false\n    },\n    /**\n     * direction to show the file list\n     */\n    direction: {\n      type: String,\n      default: 'right',\n      validator: value => ['right', 'bottom'].includes(value)\n    },\n    /**\n     * maximum number of uploads allowed\n     */\n    limit: {\n      type: Number,\n      default: null\n    },\n    /**\n     * the accept attribute value is a string or an array that defines the file types the file input should accept.\n     * https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/file#Unique_file_type_specifiers\n     */\n    accept: {\n      type: [String, Array],\n      default: () => []\n    },\n    /**\n     * whether to disable upload\n     */\n    disabled: {\n      type: Boolean,\n      default: false\n    },\n    /**\n     * whether to show clear button\n     */\n    clearable: {\n      type: Boolean,\n      default: true\n    },\n    /**\n     * whether to trigger form validation\n     */\n    validateEvent: {\n      type: Boolean,\n      default: true\n    },\n    /**\n     * text of text upload file\n     */\n    textUploadFile: {\n      type: String,\n      default: null\n    },\n    /**\n     * text of text replace file\n     */\n    textReplaceFile: {\n      type: String,\n      default: null\n    },\n    /**\n     * text of text loading file\n     */\n    textLoadingFile: {\n      type: String,\n      default: null\n    },\n\n    /**\n     * text of text uploaded files\n     */\n    textUploadedFiles: {\n      type: String,\n      default: null\n    }\n  },\n\n  computed: {\n    classes() {\n      if (!this.multiple) return {};\n\n      return {\n        'q-upload_multiple': true,\n        [`q-upload_multiple_open-${this.direction}`]: Boolean(\n          this.value?.length\n        )\n      };\n    },\n\n    isDisabled() {\n      return this.disabled || (this.qForm?.disabled ?? false);\n    },\n\n    isLoading() {\n      return !this.multiple && !isNil(this.value?.loading);\n    }\n  },\n\n  watch: {\n    value() {\n      if (this.validateEvent) this.qFormItem?.validateField('change');\n    }\n  },\n\n  methods: {\n    handleUploadClick() {\n      if (this.isDisabled || this.isLoading) return;\n\n      const { fileInput } = this.$refs;\n      fileInput.value = null;\n      fileInput.click();\n    },\n\n    processFile({ dataTransfer, target }) {\n      if (this.isDisabled) return;\n\n      const fileList = (dataTransfer ?? target)?.files;\n\n      if (!this.multiple) {\n        /**\n         * triggers when a file is selected\n         */\n        this.$emit('select', fileList?.[0], randId());\n        return;\n      }\n\n      if (this.limit && this.value.length + fileList.length > this.limit) {\n        /**\n         * triggers when limit is exceeded\n         */\n        this.$emit('exceed');\n        return;\n      }\n\n      const preparedFileList = Array.from(fileList).map(sourceFile => {\n        const fileId = randId();\n        /**\n         * triggers when a file is selected\n         */\n        this.$emit('select', sourceFile, fileId);\n\n        return { id: fileId, sourceFile };\n      });\n\n      /**\n       * triggers when multiple files are selected\n       */\n      this.$emit('select-all', preparedFileList);\n    },\n\n    resetNativeInput() {\n      this.$refs.fileInput.value = null;\n    },\n\n    handleClearAll() {\n      this.resetNativeInput();\n      /**\n       * triggers when clear all files button clicked\n       */\n      this.$emit('clear-all');\n    },\n\n    handleClear(fileId) {\n      this.resetNativeInput();\n      /**\n       * triggers when the file clear button clicked\n       */\n      this.$emit('clear', fileId);\n    },\n\n    handleAbort(fileId) {\n      this.resetNativeInput();\n      /**\n       * triggers when the file abort button clicked\n       */\n      this.$emit('abort', fileId);\n    }\n  }\n};\n</script>\n"
  },
  {
    "path": "src/qComponents/QUpload/src/QUploadDropZone.vue",
    "content": "<template>\n  <div\n    class=\"q-upload-drop-zone\"\n    :class=\"classes\"\n    tabindex=\"0\"\n    @dragenter.prevent\n    @drop.prevent=\"handleDrop\"\n    @dragover.prevent=\"handleDragover\"\n    @dragleave.prevent=\"handleDragleave\"\n  >\n    <span\n      class=\"q-upload-drop-zone__icon\"\n      :class=\"icon\"\n    />\n    <div class=\"q-upload-drop-zone__text\">{{ text }}</div>\n  </div>\n</template>\n\n<script>\nexport default {\n  name: 'QUploadDropZone',\n  componentName: 'QUploadDropZone',\n\n  props: {\n    isDisabled: {\n      type: Boolean,\n      default: false\n    },\n    isLoading: {\n      type: Boolean,\n      default: false\n    },\n    textUploadFile: {\n      type: String,\n      default: null\n    },\n    textReplaceFile: {\n      type: String,\n      default: null\n    },\n    textLoadingFile: {\n      type: String,\n      default: null\n    }\n  },\n\n  data() {\n    return {\n      isDragover: false\n    };\n  },\n\n  computed: {\n    classes() {\n      return {\n        'q-upload-drop-zone_is-dragover': this.isDragover,\n        'q-upload-drop-zone_is-disabled': this.isDisabled,\n        'q-upload-drop-zone_is-loading': this.isLoading\n      };\n    },\n\n    icon() {\n      if (this.isLoading) return 'q-icon-reverse';\n\n      return this.isDisabled ? 'q-icon-lock' : 'q-icon-cloud-upload';\n    },\n\n    text() {\n      if (this.isLoading)\n        return this.textLoadingFile ?? this.$t('QUpload.loading');\n\n      return this.value\n        ? this.textReplaceFile ?? this.$t('QUpload.replaceFile')\n        : this.textUploadFile ?? this.$t('QUpload.uploadFile');\n    }\n  },\n\n  methods: {\n    handleDrop({ dataTransfer, target }) {\n      if (this.isDisabled) return;\n      if (this.isDragover) this.isDragover = false;\n\n      const sourceFile = (dataTransfer ?? target)?.files?.[0];\n\n      this.$emit('drop', sourceFile);\n    },\n\n    handleDragover() {\n      if (!this.isDisabled) this.isDragover = true;\n    },\n\n    handleDragleave() {\n      this.isDragover = false;\n    }\n  }\n};\n</script>\n"
  },
  {
    "path": "src/qComponents/QUpload/src/QUploadFileMultiple.vue",
    "content": "<template>\n  <div\n    class=\"q-upload-file-multiple\"\n    :class=\"classes\"\n  >\n    <div class=\"q-upload-file-multiple__title\">\n      {{ title }}\n\n      <q-button\n        v-if=\"isClearable\"\n        class=\"q-upload-file-multiple__clear-all\"\n        circle\n        type=\"icon\"\n        icon=\"q-icon-trash-bin\"\n        size=\"small\"\n        theme=\"secondary\"\n        :disabled=\"isDisabled\"\n        @click=\"handleRemoveAllFilesBtnClick\"\n      />\n    </div>\n\n    <q-scrollbar\n      visible\n      view-class=\"q-dialog__view\"\n    >\n      <div class=\"q-upload-file-multiple__inner\">\n        <div\n          v-for=\"line in fileList\"\n          :key=\"line.file.id\"\n          class=\"q-upload-file-multiple__line\"\n          :title=\"line.file.name\"\n        >\n          <div\n            class=\"q-upload-file-multiple__icon\"\n            :class=\"{\n              'q-icon-reverse': line.isLoading,\n              'q-icon-file': !line.isLoading\n            }\"\n          />\n          <div class=\"q-upload-file-multiple__name\">\n            {{ line.file.name }}\n\n            <div\n              v-if=\"line.isLoading\"\n              class=\"q-upload-file-multiple__loader\"\n            >\n              <div\n                class=\"q-upload-file-multiple__bar\"\n                :style=\"line.barStyle\"\n              ></div>\n            </div>\n          </div>\n\n          <div\n            v-if=\"isDisabled\"\n            class=\"q-upload-file-multiple__action q-icon-lock\"\n          ></div>\n          <button\n            v-else-if=\"line.isLoading\"\n            type=\"button\"\n            class=\"q-upload-file-multiple__action q-icon-close\"\n            @click=\"handleAbortUploadingBtnClick(line.file.id)\"\n          />\n          <button\n            v-else-if=\"isClearable\"\n            type=\"button\"\n            class=\"q-upload-file-multiple__action q-icon-trash-bin\"\n            @click=\"handleRemoveFileBtnClick(line.file.id)\"\n          />\n        </div>\n      </div>\n    </q-scrollbar>\n  </div>\n</template>\n\n<script>\nimport { isNil } from 'lodash-es';\n\nconst calcBarStyle = loading => {\n  let progress = loading ?? null;\n\n  if (progress === null) return {};\n\n  if (progress < 0) progress = 0;\n  if (progress > 100) progress = 100;\n\n  return {\n    width: `${progress}%`\n  };\n};\n\nexport default {\n  name: 'QUploadFileMultiple',\n  componentName: 'QUploadFileMultiple',\n\n  props: {\n    value: {\n      type: Array,\n      default: null\n    },\n    isDisabled: {\n      type: Boolean,\n      default: false\n    },\n    isClearable: {\n      type: Boolean,\n      default: true\n    },\n    textUploadedFiles: {\n      type: String,\n      default: null\n    }\n  },\n\n  computed: {\n    title() {\n      return this.textUploadedFiles ?? this.$t('QUpload.uploadedFiles');\n    },\n\n    fileList() {\n      if (!this.value) return [];\n\n      return this.value.filter(Boolean).map(file => ({\n        file,\n        isLoading: !isNil(file.loading),\n        barStyle: calcBarStyle(file?.loading)\n      }));\n    },\n\n    classes() {\n      return {\n        'q-upload-file-multiple_shown': Boolean(this.fileList.length)\n      };\n    }\n  },\n\n  methods: {\n    handleRemoveAllFilesBtnClick() {\n      this.$emit('clear-all');\n    },\n\n    handleRemoveFileBtnClick(fileId) {\n      this.$emit('clear', fileId);\n    },\n\n    handleAbortUploadingBtnClick(fileId) {\n      this.$emit('abort', fileId);\n    }\n  }\n};\n</script>\n"
  },
  {
    "path": "src/qComponents/QUpload/src/QUploadFileSingle.vue",
    "content": "<template>\n  <div\n    class=\"q-upload-file-single\"\n    :title=\"fileTitle\"\n  >\n    <div class=\"q-upload-file-single__icon q-icon-file\" />\n    <div class=\"q-upload-file-single__name\">{{ preparedFileName }}</div>\n\n    <button\n      v-if=\"isClearable && !isDisabled && !isLoading\"\n      type=\"button\"\n      class=\"q-upload-file-single__btn q-icon-trash-bin\"\n      @click=\"handleRemoveFileBtnClick\"\n    />\n\n    <template v-if=\"isLoading\">\n      <button\n        type=\"button\"\n        class=\"q-upload-file-single__btn q-icon-close\"\n        @click=\"handleAbortUploadingBtnClick\"\n      />\n\n      <div class=\"q-upload-file-single__loader\">\n        <div\n          class=\"q-upload-file-single__bar\"\n          :style=\"barStyle\"\n        ></div>\n      </div>\n    </template>\n  </div>\n</template>\n\n<script>\nconst MAX_VISIBLE_FILE_NAME_LENGTH = 23;\n\nexport default {\n  name: 'QUploadFileSingle',\n  componentName: 'QUploadFileSingle',\n\n  props: {\n    value: {\n      type: Object,\n      default: null\n    },\n    isLoading: {\n      type: Boolean,\n      default: false\n    },\n    isDisabled: {\n      type: Boolean,\n      default: false\n    },\n    isClearable: {\n      type: Boolean,\n      default: true\n    }\n  },\n\n  computed: {\n    fileName() {\n      return this.value?.name ?? '';\n    },\n\n    barStyle() {\n      let loading = this.value?.loading ?? null;\n\n      if (loading === null) return {};\n\n      if (loading < 0) loading = 0;\n      if (loading > 100) loading = 100;\n      return {\n        width: `${loading}%`\n      };\n    },\n\n    isTitleShown() {\n      return this.fileName?.length > MAX_VISIBLE_FILE_NAME_LENGTH;\n    },\n\n    preparedFileName() {\n      if (!this.fileName) return '';\n\n      const name = this.fileName;\n      return this.isTitleShown\n        ? `${name.slice(0, 10)}...${name.slice(-10)}`\n        : name;\n    },\n\n    fileTitle() {\n      return this.isTitleShown ? this.fileName : '';\n    }\n  },\n\n  methods: {\n    handleRemoveFileBtnClick() {\n      this.$emit('clear');\n    },\n\n    handleAbortUploadingBtnClick() {\n      this.$emit('abort');\n    }\n  }\n};\n</script>\n"
  },
  {
    "path": "src/qComponents/QUpload/src/q-upload-drop-zone.scss",
    "content": ".q-upload-drop-zone {\n  --background-color: var(--color-tertiary-gray-light);\n  --border-color: rgba(var(--color-rgb-gray), 0.16);\n  --text-color: var(--color-primary-blue);\n  --box-shadow: var(--box-shadow-primary);\n\n  position: relative;\n  z-index: 10;\n  display: flex;\n  flex-direction: column;\n  justify-content: center;\n  align-items: center;\n  width: var(--q-upload-size);\n  height: var(--q-upload-size);\n  overflow: hidden;\n  text-align: center;\n  background-color: var(--background-color);\n  border-radius: 6px;\n  outline: none;\n  box-shadow: var(--box-shadow);\n  cursor: pointer;\n\n  &:hover,\n  &[data-focus-visible-added] {\n    --background-color: var(--color-tertiary-gray);\n    --box-shadow: var(--box-shadow-hover);\n  }\n\n  &::before {\n    content: '';\n    position: absolute;\n    top: 8px;\n    right: 8px;\n    bottom: 8px;\n    left: 8px;\n    border: 1px dashed var(--border-color);\n  }\n\n  &__icon {\n    font-size: 40px;\n    line-height: 1;\n    color: var(--text-color);\n  }\n\n  &__text {\n    margin-top: 8px;\n    font-weight: var(--font-weight-bold);\n    font-size: 12px;\n    line-height: 15px;\n    color: var(--text-color);\n    text-transform: uppercase;\n  }\n\n  &_is-dragover {\n    --border-color: var(--color-primary-blue);\n    --background-color: var(--color-tertiary-gray);\n  }\n\n  &_is-loading {\n    --background-color: var(--color-tertiary-gray-ultra-light);\n    --text-color: rgba(var(--color-rgb-gray), 0.64);\n    --box-shadow: var(--box-shadow-pressed);\n\n    &:hover {\n      --background-color: var(--color-tertiary-gray-ultra-light);\n      --box-shadow: var(--box-shadow-pressed);\n    }\n\n    .q-upload-drop-zone__icon {\n      animation: rotating 2s linear infinite;\n    }\n  }\n\n  &_is-disabled {\n    --border-color: rgba(var(--color-rgb-gray), 0.64);\n    --text-color: rgba(var(--color-rgb-gray), 0.64);\n    --background-color: var(--color-tertiary-gray);\n    --box-shadow: var(--box-shadow-pressed);\n\n    cursor: not-allowed;\n\n    &:hover {\n      --box-shadow: var(--box-shadow-pressed);\n    }\n  }\n\n  .q-form-item_is-error & {\n    --border-color: var(--color-secondary-orange);\n  }\n}\n"
  },
  {
    "path": "src/qComponents/QUpload/src/q-upload-file-multiple.scss",
    "content": ".q-upload-file-multiple {\n  --text-color: rgba(var(--color-rgb-gray), 0.64);\n\n  position: absolute;\n  right: 0;\n  bottom: 0;\n  z-index: 5;\n  display: flex;\n  flex-direction: column;\n  width: var(--q-upload-size);\n  height: var(--q-upload-size);\n  background-color: var(--color-tertiary-gray-light);\n  border-radius: var(--border-radius-base);\n  box-shadow: var(--box-shadow-secondary);\n  visibility: hidden;\n  opacity: 0;\n  transition: visibility ease 0.5s, opacity ease 0.25s;\n\n  &_shown {\n    visibility: visible;\n    opacity: 1;\n    transition: visibility ease 0.5s, opacity ease 0.25s 0.25s;\n  }\n\n  &__title {\n    display: flex;\n    align-items: center;\n    margin-top: 16px;\n    margin-bottom: 16px;\n    margin-left: 16px;\n    font-weight: var(--font-weight-bold);\n    font-size: 12px;\n    line-height: 24px;\n    color: var(--color-primary-black);\n    text-transform: uppercase;\n    letter-spacing: var(--letter-spacing-base);\n  }\n\n  &__clear-all {\n    margin-left: 8px;\n  }\n\n  &__inner {\n    width: 100%;\n    padding: 0 16px 16px;\n  }\n\n  &__line {\n    display: flex;\n    justify-content: space-between;\n    align-items: center;\n\n    & + & {\n      margin-top: 11px;\n    }\n  }\n\n  &__icon {\n    width: 24px;\n    margin-right: 8px;\n    font-size: 24px;\n    color: var(--text-color);\n\n    &.q-icon-reverse {\n      animation: rotating 2s linear infinite;\n    }\n  }\n\n  &__name {\n    position: relative;\n    display: block;\n    width: 168px;\n    margin-right: auto;\n    overflow: hidden;\n    font-weight: var(--font-weight-base);\n    font-size: 14px;\n    line-height: 22px;\n    text-align: left;\n    color: var(--text-color);\n    white-space: nowrap;\n    text-overflow: ellipsis;\n  }\n\n  &__action {\n    width: 24px;\n    margin-left: 8px;\n    padding: 0;\n    font-size: 24px;\n    color: var(--color-primary-blue);\n    background-color: transparent;\n    border: none;\n    outline: none;\n    cursor: pointer;\n\n    &:hover,\n    &.focus-visible {\n      color: var(--color-primary-black);\n    }\n\n    &.q-icon-lock {\n      color: var(--text-color);\n    }\n  }\n\n  &__loader {\n    position: absolute;\n    bottom: 0;\n    left: 0;\n    width: 100%;\n    height: 2px;\n    background-color: rgba(var(--color-rgb-gray), 0.16);\n  }\n\n  &__bar {\n    width: 0;\n    height: 100%;\n    background-color: var(--color-primary-blue);\n    transition: width 0.1s ease;\n  }\n}\n"
  },
  {
    "path": "src/qComponents/QUpload/src/q-upload-file-single.scss",
    "content": ".q-upload-file-single {\n  --text-color: rgba(var(--color-rgb-gray), 0.64);\n\n  position: absolute;\n  right: 24px;\n  bottom: 24px;\n  left: 24px;\n  z-index: 15;\n  display: flex;\n  justify-content: space-between;\n  align-items: center;\n  padding: 8px;\n  overflow: hidden;\n  background-color: var(--color-tertiary-gray);\n  border-radius: var(--border-radius-base);\n  box-shadow: var(--box-shadow-pressed);\n\n  &__icon {\n    width: 24px;\n    margin-right: 8px;\n    font-size: 24px;\n    color: var(--text-color);\n  }\n\n  &__name {\n    width: 136px;\n    margin-right: auto;\n    font-weight: var(--font-weight-base);\n    font-size: 10px;\n    line-height: 12px;\n    text-align: left;\n    color: var(--text-color);\n  }\n\n  &__btn {\n    width: 24px;\n    margin-left: 8px;\n    padding: 0;\n    font-size: 24px;\n    color: var(--color-primary-blue);\n    background-color: transparent;\n    border: none;\n    outline: none;\n    cursor: pointer;\n\n    &:hover,\n    &.focus-visible {\n      color: var(--color-primary-black);\n    }\n  }\n\n  &__loader {\n    position: absolute;\n    bottom: 0;\n    left: 0;\n    width: 100%;\n    height: 2px;\n    background-color: rgba(var(--color-rgb-gray), 0.16);\n  }\n\n  &__bar {\n    width: 0;\n    height: 100%;\n    background-color: var(--color-primary-blue);\n    transition: width 0.1s ease;\n  }\n}\n"
  },
  {
    "path": "src/qComponents/QUpload/src/q-upload.scss",
    "content": "@import './q-upload-drop-zone.scss';\n@import './q-upload-file-single.scss';\n@import './q-upload-file-multiple.scss';\n\n.q-upload {\n  --q-upload-size: 264px;\n\n  position: relative;\n  display: inline-block;\n\n  &_multiple {\n    width: var(--q-upload-size);\n    height: var(--q-upload-size);\n    transition: width ease 0.5s, height ease 0.5s;\n\n    &_open {\n      &-right {\n        width: 544px;\n      }\n\n      &-bottom {\n        height: 544px;\n      }\n    }\n  }\n\n  &__input {\n    position: absolute;\n    top: 0;\n    right: 0;\n    bottom: 0;\n    left: 0;\n    z-index: -1;\n    margin: 0;\n    outline: none;\n    opacity: 0;\n  }\n}\n\n@keyframes rotating {\n  0% {\n    transform: rotateZ(0deg);\n  }\n\n  100% {\n    transform: rotateZ(360deg);\n  }\n}\n"
  },
  {
    "path": "src/qComponents/constants/locales/en.js",
    "content": "export default {\n  QInput: {\n    charNumber: 'Number of characters'\n  },\n  QSelect: {\n    loading: 'Loading...',\n    more: 'Not all results are shown, refine your query',\n    noMatch: 'No matching data',\n    noData: 'No data',\n    selectAll: 'Select all'\n  },\n  QTextarea: {\n    charNumber: 'Number of characters'\n  },\n  QDatePicker: {\n    placeholder: 'Pick a date',\n    startPlaceholder: 'Start',\n    endPlaceholder: 'End',\n    prevYear: 'Previous Year',\n    nextYear: 'Next Year',\n    prevMonth: 'Previous Month',\n    nextMonth: 'Next Month',\n    timeFrom: 'from',\n    timeTo: 'to'\n  },\n  QCascader: {\n    placeholder: 'Pick',\n    noDataText: 'No data'\n  },\n  QColorPicker: {\n    clear: 'Clear',\n    confirm: 'Apply'\n  },\n  QTable: {\n    noData: 'No data'\n  },\n  QTimePicker: {\n    hour: 'hour',\n    minute: 'min',\n    second: 'sec'\n  },\n  QUpload: {\n    uploadFile: 'upload file',\n    replaceFile: 'replace file',\n    loading: 'loading',\n    uploadedFiles: 'Uploaded files'\n  }\n};\n"
  },
  {
    "path": "src/qComponents/constants/locales/index.js",
    "content": "/* eslint-disable no-underscore-dangle */\nimport Vue from 'vue';\nimport VueI18n from 'vue-i18n';\nimport { merge } from 'lodash-es';\n\nimport ru from './ru';\nimport en from './en';\n\nconst installI18n = ({ locale, customI18nMessages }) => {\n  const isI18nExist = Boolean(Vue.prototype._i18n);\n  if (isI18nExist) {\n    console.warn(\n      `Error: Qui can't setup VueI18n, it has detected in the app, please merge i18n messages, see the docs`\n    );\n    return;\n  }\n  Vue.use(VueI18n);\n  const i18n = new VueI18n({\n    locale,\n    messages: merge({ en, ru }, customI18nMessages)\n  });\n  Vue.prototype._i18n = i18n;\n};\n\nexport default {\n  en,\n  ru\n};\n\nexport { ru, en, installI18n };\n"
  },
  {
    "path": "src/qComponents/constants/locales/ru.js",
    "content": "export default {\n  QInput: {\n    charNumber: 'Количество символов'\n  },\n  QSelect: {\n    loading: 'Загрузка...',\n    more: 'Показаны не все результаты, уточните поиск',\n    noMatch: 'Нет совпадений',\n    noData: 'Нет данных',\n    selectAll: 'Выбрать всё'\n  },\n  QTextarea: {\n    charNumber: 'Количество символов'\n  },\n  QDatePicker: {\n    placeholder: 'Выберите дату',\n    startPlaceholder: 'Дата начала',\n    endPlaceholder: 'Дата окончания',\n    prevYear: 'Предыдущий год',\n    nextYear: 'Следующий год',\n    prevMonth: 'Предыдущий месяц',\n    nextMonth: 'Следующий месяц',\n    timeFrom: 'с',\n    timeTo: 'по'\n  },\n  QCascader: {\n    placeholder: 'Выберите',\n    noDataText: 'Нет данных'\n  },\n  QColorPicker: {\n    clear: 'Очистить',\n    confirm: 'Применить'\n  },\n  QTable: {\n    noData: 'Нет данных'\n  },\n  QTimePicker: {\n    hour: 'час',\n    minute: 'мин',\n    second: 'сек'\n  },\n  QUpload: {\n    uploadFile: 'загрузить файл',\n    replaceFile: 'заменить файл',\n    loading: 'загрузка',\n    uploadedFiles: 'Загруженные файлы'\n  }\n};\n"
  },
  {
    "path": "src/qComponents/constants/popperPlacements.js",
    "content": "export default [\n  'top',\n  'top-start',\n  'top-end',\n  'right',\n  'right-start',\n  'right-end',\n  'bottom',\n  'bottom-start',\n  'bottom-end',\n  'left',\n  'left-start',\n  'left-end'\n];\n"
  },
  {
    "path": "src/qComponents/helpers/collapse-transition.js",
    "content": "/* eslint-disable no-param-reassign */\n\nexport default {\n  name: 'QCollapseTransition',\n\n  functional: true,\n\n  render(h, { children }) {\n    const data = {\n      on: {\n        beforeEnter(el) {\n          el.classList.add('collapse-transition');\n\n          if (!el.dataset) el.dataset = {};\n\n          el.dataset.oldPaddingTop = el.style.paddingTop;\n          el.dataset.oldPaddingBottom = el.style.paddingBottom;\n\n          el.style.height = '0';\n          el.style.paddingTop = 0;\n          el.style.paddingBottom = 0;\n        },\n\n        enter(el) {\n          el.dataset.oldOverflow = el.style.overflow;\n          if (el.scrollHeight !== 0) {\n            el.style.height = `${el.scrollHeight}px`;\n            el.style.paddingTop = el.dataset.oldPaddingTop;\n            el.style.paddingBottom = el.dataset.oldPaddingBottom;\n          } else {\n            el.style.height = '';\n            el.style.paddingTop = el.dataset.oldPaddingTop;\n            el.style.paddingBottom = el.dataset.oldPaddingBottom;\n          }\n\n          el.style.overflow = 'hidden';\n        },\n\n        afterEnter(el) {\n          el.classList.remove('collapse-transition');\n\n          // for safari: remove class then reset height is necessary\n          el.style.height = '';\n          el.style.overflow = el.dataset.oldOverflow;\n        },\n\n        beforeLeave(el) {\n          if (!el.dataset) el.dataset = {};\n          el.dataset.oldPaddingTop = el.style.paddingTop;\n          el.dataset.oldPaddingBottom = el.style.paddingBottom;\n          el.dataset.oldOverflow = el.style.overflow;\n\n          el.style.height = `${el.scrollHeight}px`;\n          el.style.overflow = 'hidden';\n        },\n\n        leave(el) {\n          if (el.scrollHeight !== 0) {\n            el.classList.add('collapse-transition');\n            // for safari: add class after set height, or it will jump to zero height suddenly, weired\n            el.style.height = 0;\n            el.style.paddingTop = 0;\n            el.style.paddingBottom = 0;\n          }\n        },\n\n        afterLeave(el) {\n          el.classList.remove('collapse-transition');\n          el.style.height = '';\n          el.style.overflow = el.dataset.oldOverflow;\n          el.style.paddingTop = el.dataset.oldPaddingTop;\n          el.style.paddingBottom = el.dataset.oldPaddingBottom;\n        }\n      }\n    };\n\n    return h('transition', data, children);\n  }\n};\n"
  },
  {
    "path": "src/qComponents/helpers/dateHelpers.js",
    "content": "import { isDate } from 'date-fns';\n\nconst addZero = value => {\n  return String(value).padStart(2, '0');\n};\n\nconst isTimeValueValid = value => {\n  let isValid = false;\n  if (typeof value === 'string') {\n    const array = value.split(':');\n    isValid =\n      array.every((datePart, index) => {\n        let condition = false;\n        if (index === 0) {\n          // hours\n          condition = Number(datePart) >= 0 && Number(datePart) < 24;\n        } else if ([1, 2].includes(index)) {\n          // minutes / seconds\n          condition = Number(datePart) >= 0 && Number(datePart) < 60;\n        }\n        return condition && datePart.length === 2;\n      }) && array.length === 3;\n  } else if (isDate(value) || value === null) {\n    isValid = true;\n  }\n\n  return isValid;\n};\n\nexport { addZero, isTimeValueValid };\n"
  },
  {
    "path": "src/qComponents/helpers/index.js",
    "content": "/* eslint-disable no-underscore-dangle */\nimport ResizeObserver from 'resize-observer-polyfill';\n\nexport const on = (function() {\n  if (document.addEventListener) {\n    return function(element, event, handler) {\n      if (element && event && handler) {\n        element.addEventListener(event, handler, false);\n      }\n    };\n  }\n  return function(element, event, handler) {\n    if (element && event && handler) {\n      element.attachEvent(`on${event}`, handler);\n    }\n  };\n})();\n\n/* istanbul ignore next */\nexport const off = (function() {\n  if (document.removeEventListener) {\n    return function(element, event, handler) {\n      if (element && event) {\n        element.removeEventListener(event, handler, false);\n      }\n    };\n  }\n  return function(element, event, handler) {\n    if (element && event) {\n      element.detachEvent(`on${event}`, handler);\n    }\n  };\n})();\n\nconst resizeHandler = entries => {\n  Object.values(entries).forEach(entry => {\n    const listeners = entry.target.__resizeListeners__ ?? [];\n    if (listeners.length) {\n      listeners.forEach(fn => {\n        fn();\n      });\n    }\n  });\n};\n\nexport const addResizeListener = (element, fn) => {\n  if (!element) return;\n  if (!element.__resizeListeners__) {\n    // eslint-disable-next-line no-param-reassign\n    element.__resizeListeners__ = [];\n    // eslint-disable-next-line no-param-reassign\n    element.__ro__ = new ResizeObserver(resizeHandler);\n    element.__ro__.observe(element);\n  }\n  element.__resizeListeners__.push(fn);\n};\n\nexport const removeResizeListener = (element, fn) => {\n  if (!element || !element.__resizeListeners__) return;\n  element.__resizeListeners__.splice(\n    element.__resizeListeners__.indexOf(fn),\n    1\n  );\n  if (!element.__resizeListeners__.length) {\n    element.__ro__.disconnect();\n  }\n};\n\nexport const randId = prefix =>\n  Math.random()\n    .toString(36)\n    .replace('0.', prefix ?? '');\n"
  },
  {
    "path": "src/qComponents/index.js",
    "content": "/* eslint-disable no-underscore-dangle, global-require, no-param-reassign */\nimport 'focus-visible';\nimport { kebabCase, isString } from 'lodash-es';\nimport vClickOutside from 'v-click-outside';\nimport { version } from '../../package.json';\nimport { installI18n } from './constants/locales';\n\nimport QButton from './QButton';\nimport QBreadcrumbs from './QBreadcrumbs';\nimport QCascader from './QCascader';\nimport QDatePicker from './QDatePicker';\nimport QTimePicker from './QTimePicker';\nimport QCheckbox from './QCheckbox';\nimport QCheckboxGroup from './QCheckboxGroup';\nimport QRadio from './QRadio';\nimport QRadioGroup from './QRadioGroup';\nimport QRow from './QRow';\nimport QCol from './QCol';\nimport QCollapse from './QCollapse';\nimport QCollapseItem from './QCollapseItem';\nimport QColorPicker from './QColorPicker';\nimport QContextMenu from './QContextMenu';\nimport QForm from './QForm';\nimport QFormItem from './QFormItem';\nimport QInput from './QInput';\nimport QInputNumber from './QInputNumber';\nimport QPagination from './QPagination';\nimport QPopover from './QPopover';\nimport QScrollbar from './QScrollbar';\nimport QSelect from './QSelect';\nimport QSlider from './QSlider';\nimport QOption from './QOption';\nimport QTextarea from './QTextarea';\nimport QTabs from './QTabs';\nimport QTabPane from './QTabPane';\nimport QTag from './QTag';\nimport QDrawer from './QDrawer';\nimport QTable from './QTable';\nimport QUpload from './QUpload';\n// modals\nimport QNotification from './QNotification';\nimport QDialog from './QDialog';\nimport QMessageBox from './QMessageBox';\n\nconst Components = {\n  QBreadcrumbs,\n  QButton,\n  QCascader,\n  QCheckbox,\n  QCheckboxGroup,\n  QCol,\n  QCollapse,\n  QCollapseItem,\n  QColorPicker,\n  QContextMenu,\n  QDatePicker,\n  QDialog,\n  QDrawer,\n  QForm,\n  QFormItem,\n  QInput,\n  QInputNumber,\n  QMessageBox,\n  QNotification,\n  QOption,\n  QPagination,\n  QPopover,\n  QRadio,\n  QRadioGroup,\n  QRow,\n  QScrollbar,\n  QSelect,\n  QSlider,\n  QTabPane,\n  QTable,\n  QTabs,\n  QTag,\n  QTextarea,\n  QTimePicker,\n  QUpload\n};\n\nconst allComponents = Object.keys(Components);\nconst allComponentsExceptModals = allComponents.filter(\n  name => !['QNotification', 'QMessageBox', 'QDialog'].includes(name)\n);\n\n// import styles\nrequire('../fonts/index.scss');\nrequire('../icons/index.scss');\nrequire('../main.scss');\n\nallComponents.forEach(component => {\n  const kebabCaseComponent = kebabCase(component);\n  try {\n    // eslint-disable-next-line import/no-dynamic-require\n    require(`../qComponents/${component}/src/${kebabCaseComponent}.scss`);\n  } catch (err) {\n    console.warn(err);\n  }\n});\n\n// install\nconst install = (\n  Vue,\n  {\n    localization: { locale = 'ru', customI18nMessages = {} } = {},\n    zIndexCounter = 2000,\n    prefix = ''\n  } = {}\n) => {\n  Vue.prototype.$Q = {};\n  // define plugins\n  Object.defineProperties(Vue.prototype.$Q, {\n    zIndex: {\n      get() {\n        zIndexCounter += 1;\n        return zIndexCounter;\n      }\n    },\n    locale: {\n      get: () => locale,\n      set(newLocale) {\n        locale = newLocale;\n      }\n    }\n  });\n\n  Vue.use(vClickOutside);\n  installI18n({ locale, customI18nMessages });\n\n  // setup modals\n  if (!Vue.prototype.$notify) {\n    Vue.prototype.$notify = options =>\n      QNotification({\n        duration: 3000, // - ms\n        ...options\n      });\n  } else if (process.env.NODE_ENV !== 'production') {\n    console.warn(`$notify hasn't been registered, it has existed before`);\n  }\n\n  if (!Vue.prototype.$message) {\n    Vue.prototype.$message = QMessageBox;\n  } else if (process.env.NODE_ENV !== 'production') {\n    console.warn(`$message hasn't been registered, it has existed before`);\n  }\n\n  if (!Vue.prototype.$dialog) {\n    Vue.prototype.$dialog = QDialog;\n  } else if (process.env.NODE_ENV !== 'production') {\n    console.warn(`$dialog hasn't been registered, it has existed before`);\n  }\n\n  allComponentsExceptModals.forEach(name => {\n    const newName =\n      prefix && isString(prefix) ? name.replace(/^Q/, prefix) : name;\n    Vue.component(newName, Components[name]);\n  });\n};\n\nconst Qui = {\n  version,\n  install\n};\n\n// Auto-install when vue is found (eg. in browser via <script> tag)\nlet GlobalVue = null;\nif (typeof window !== 'undefined') {\n  GlobalVue = window.Vue;\n} else if (typeof global !== 'undefined') {\n  GlobalVue = global.Vue;\n}\n\nif (GlobalVue) {\n  GlobalVue.use(Qui);\n}\n\nexport default Qui;\nexport {\n  QBreadcrumbs,\n  QButton,\n  QCascader,\n  QCheckbox,\n  QCheckboxGroup,\n  QCol,\n  QCollapse,\n  QCollapseItem,\n  QColorPicker,\n  QContextMenu,\n  QDatePicker,\n  QDialog,\n  QDrawer,\n  QForm,\n  QFormItem,\n  QInput,\n  QInputNumber,\n  QMessageBox,\n  QNotification,\n  QOption,\n  QPagination,\n  QPopover,\n  QRadio,\n  QRadioGroup,\n  QRow,\n  QScrollbar,\n  QSelect,\n  QSlider,\n  QTabPane,\n  QTable,\n  QTabs,\n  QTag,\n  QTextarea,\n  QTimePicker,\n  QUpload\n};\n"
  },
  {
    "path": "src/qComponents/mixins/emitter.js",
    "content": "function broadcast(componentName, eventName, params) {\n  this.$children.forEach(child => {\n    const name = child.$options.componentName;\n\n    if (name === componentName) {\n      child.$emit(...[eventName].concat(params));\n    } else {\n      broadcast.apply(child, [componentName, eventName].concat([params]));\n    }\n  });\n}\n\nexport default {\n  methods: {\n    dispatch(componentName, eventName, params) {\n      let parent = this.$parent || this.$root;\n      let name = parent.$options.componentName;\n\n      while (parent && (!name || name !== componentName)) {\n        parent = parent.$parent;\n\n        if (parent) {\n          name = parent.$options.componentName;\n        }\n      }\n      if (parent) {\n        parent.$emit(...[eventName].concat(params));\n      }\n    },\n\n    broadcast(componentName, eventName, params) {\n      broadcast.call(this, componentName, eventName, params);\n    }\n  }\n};\n"
  },
  {
    "path": "src/qComponents/mixins/inputs.js",
    "content": "export default {\n  inheritAttrs: false,\n\n  inject: {\n    qForm: {\n      default: null\n    },\n    qFormItem: {\n      default: null\n    }\n  },\n\n  props: {\n    value: {\n      type: [String, Number],\n      default: ''\n    },\n    disabled: {\n      type: Boolean,\n      default: false\n    },\n    readonly: {\n      type: Boolean,\n      default: false\n    },\n    showSymbolLimit: {\n      type: Boolean,\n      default: false\n    },\n    counterLimit: {\n      type: Number,\n      default: null\n    },\n    validateEvent: {\n      type: Boolean,\n      default: true\n    },\n    label: { type: String, default: '' },\n    tabindex: { type: String, default: '' }\n  },\n\n  data() {\n    return {\n      hovering: false,\n      focused: false,\n      isComposing: false\n    };\n  },\n\n  computed: {\n    inputDisabled() {\n      return this.disabled || (this.qForm?.disabled ?? false);\n    },\n\n    nativeInputValue() {\n      return String(this.value ?? '');\n    },\n\n    isClearButtonShown() {\n      return Boolean(\n        this.clearable &&\n          !this.inputDisabled &&\n          !this.readonly &&\n          this.nativeInputValue &&\n          (this.focused || this.hovering)\n      );\n    },\n\n    isSymbolLimitShown() {\n      return (\n        this.showSymbolLimit &&\n        (this.$attrs.maxlength || this.counterLimit) &&\n        !this.inputDisabled &&\n        !this.readonly &&\n        !this.showPassword\n      );\n    },\n\n    upperLimit() {\n      return this.$attrs.maxlength ?? this.counterLimit;\n    },\n\n    textLength() {\n      return this.value?.length ?? 0;\n    }\n  },\n\n  watch: {\n    nativeInputValue() {\n      this.setNativeInputValue();\n    }\n  },\n\n  created() {\n    this.$on('inputSelect', this.select);\n  },\n\n  methods: {\n    focus() {\n      this.componentRef.focus();\n    },\n\n    blur() {\n      this.componentRef.blur();\n    },\n\n    handleBlur(event) {\n      this.focused = false;\n      this.$emit('blur', event);\n      if (this.validateEvent) this.qFormItem?.validateField('blur');\n    },\n\n    select() {\n      this.componentRef.select();\n    },\n\n    setNativeInputValue() {\n      const input = this.componentRef;\n      if (!input || input.value === this.nativeInputValue) return;\n      input.value = this.nativeInputValue;\n    },\n\n    handleFocus(event) {\n      this.focused = true;\n      this.$emit('focus', event);\n    },\n\n    handleCompositionStart() {\n      this.isComposing = true;\n    },\n\n    handleCompositionEnd(event) {\n      if (this.isComposing) {\n        this.isComposing = false;\n        this.handleInput(event);\n      }\n    },\n\n    handleInput(event) {\n      // should not emit input during composition\n      if (this.isComposing) return;\n      this.$emit('input', event.target.value, event);\n      // ensure native input value is controlled\n      this.$nextTick(this.setNativeInputValue);\n    },\n\n    handleChange(event) {\n      this.$emit('change', event.target.value);\n    }\n  }\n};\n"
  },
  {
    "path": "src/qComponents/mixins/pickers.js",
    "content": "export default {\n  methods: {\n    handleInput(val, { inputType }) {\n      const timeLength = this.timepicker ? 6 : 0;\n      const options =\n        this.$options.name === 'QTimePicker'\n          ? { separator: ':', maxLength: 8 + timeLength }\n          : { separator: '.', maxLength: 10 + timeLength };\n      if (inputType === 'deleteContentBackward' && !this.userInput) {\n        this.userInput = '';\n        return;\n      }\n\n      const clearVal = val.replace(/ |,|:|\\./g, '');\n      const array = clearVal.split('');\n\n      if (\n        inputType === 'insertText' &&\n        !array[array.length - 1]?.match(/[0-9]+/)\n      )\n        return;\n\n      if (array.length > 1) array.splice(2, 0, options.separator);\n      if (array.length > 3 && array.length !== 4)\n        array.splice(5, 0, options.separator);\n      if (array.length > options.maxLength) return;\n\n      if (timeLength) {\n        if (array.length > 10) array.splice(10, 0, ', ');\n        if (array.length > 13) array.splice(13, 0, ':');\n        if (array.length > 15) array.splice(16, 0, ':');\n      }\n\n      if (\n        inputType === 'deleteContentBackward' &&\n        ['.', ':'].includes(array[array.length - 1])\n      ) {\n        array.pop();\n      }\n\n      const parsedInputValue = array.join('');\n      this.userInput = parsedInputValue;\n      this.$emit('input', parsedInputValue);\n    }\n  }\n};\n"
  },
  {
    "path": "src/transition.scss",
    "content": ".fade-in-linear-enter-active,\n.fade-in-linear-leave-active {\n  transition: opacity 200ms linear;\n}\n\n.fade-in-linear-enter,\n.fade-in-linear-leave,\n.fade-in-linear-leave-active {\n  opacity: 0;\n}\n\n.q-fade-in-linear-enter-active,\n.q-fade-in-linear-leave-active {\n  transition: opacity 200ms linear;\n}\n\n.q-fade-in-linear-enter,\n.q-fade-in-linear-leave,\n.q-fade-in-linear-leave-active {\n  opacity: 0;\n}\n\n.q-fade-in-enter-active,\n.q-fade-in-leave-active {\n  transition: all 0.3s cubic-bezier(0.55, 0, 0.1, 1);\n}\n\n.q-fade-in-enter,\n.q-fade-in-leave-active {\n  opacity: 0;\n}\n\n.q-zoom-in-center-enter-active,\n.q-zoom-in-center-leave-active {\n  transition: all 0.3s cubic-bezier(0.55, 0, 0.1, 1);\n}\n\n.q-zoom-in-center-enter,\n.q-zoom-in-center-leave-active {\n  transform: scaleX(0);\n  opacity: 0;\n}\n\n.q-zoom-in-top-enter-active,\n.q-zoom-in-top-leave-active,\n.q-zoom-in-bottom-enter-active,\n.q-zoom-in-bottom-leave-active,\n.q-zoom-in-left-enter-active,\n.q-zoom-in-left-leave-active {\n  opacity: 1;\n  transition: transform 300ms cubic-bezier(0.23, 1, 0.32, 1),\n    opacity 300ms cubic-bezier(0.23, 1, 0.32, 1);\n}\n\n.q-zoom-in-top-enter-active,\n.q-zoom-in-top-leave-active {\n  transform: scaleY(1);\n  transform-origin: center top;\n}\n\n.q-zoom-in-top-enter,\n.q-zoom-in-top-leave-active {\n  transform: scaleY(0);\n  opacity: 0;\n}\n\n.q-zoom-in-bottom-enter-active,\n.q-zoom-in-bottom-leave-active {\n  transform: scaleY(1);\n  transform-origin: center bottom;\n}\n\n.q-zoom-in-bottom-enter,\n.q-zoom-in-bottom-leave-active {\n  transform: scaleY(0);\n  opacity: 0;\n}\n\n.q-zoom-in-left-enter-active,\n.q-zoom-in-left-leave-active {\n  transform: scale(1, 1);\n  transform-origin: top left;\n}\n\n.q-zoom-in-left-enter,\n.q-zoom-in-left-leave-active {\n  transform: scale(0.45, 0.45);\n  opacity: 0;\n}\n\n.collapse-transition {\n  transition: 0.3s height ease-in-out, 0.3s padding-top ease-in-out,\n    0.3s padding-bottom ease-in-out;\n}\n\n.horizontal-collapse-transition {\n  transition: 0.3s width ease-in-out, 0.3s padding-left ease-in-out,\n    0.3s padding-right ease-in-out;\n}\n\n.q-list-enter-active,\n.q-list-leave-active {\n  transition: all 1s;\n}\n\n.q-list-enter,\n.q-list-leave-active {\n  transform: translateY(-30px);\n  opacity: 0;\n}\n\n.q-opacity-transition {\n  transition: opacity 0.3s cubic-bezier(0.55, 0, 0.1, 1);\n}\n"
  },
  {
    "path": "src/vars.scss",
    "content": ":root {\n  --color-primary: #de4b7a;\n  --color-primary-purple: #d048b4;\n  --color-primary-blue: #4162f0;\n  --color-primary-blue-light: #74aff8;\n  --color-primary-blue-aqua: #5ecae7;\n  --color-primary-darker: #b83e65;\n  --color-primary-black: #1d1c1a;\n\n  --color-secondary-orange: #f95e2d;\n  --color-secondary-green: #40ba3e;\n  --color-secondary-yellow: #f2d22b;\n\n  --color-tertiary-white: #fff;\n  --color-tertiary-gray-ultra-light: #fafafa;\n  --color-tertiary-gray-lighter: #f4f4f6;\n  --color-tertiary-gray-light: #f0f0f3;\n  --color-tertiary-gray: #eaeaea;\n  --color-tertiary-gray-dark: #e2e2e2;\n  --color-tertiary-gray-darker: #dadada;\n  --color-tertiary-gray-ultra-dark: #c4c4c4;\n  --color-tertiary-gray-ultra-darker: #adacae;\n\n  --color-rgb-white: 255, 255, 255;\n  --color-rgb-blue: 174, 174, 192;\n  --color-rgb-gray: 29, 28, 26;\n  --color-rgb-red: 222, 75, 122;\n\n  --gradient-primary: linear-gradient(\n    101.12deg,\n    var(--color-primary) 0.76%,\n    var(--color-primary-purple) 100%\n  );\n\n  --gradient-secondary: linear-gradient(\n    180deg,\n    var(--color-primary) -27.44%,\n    var(--color-primary-blue) 100.54%\n  );\n\n  --box-shadow-primary: -1px -1px 3px rgba(var(--color-rgb-white), 0.25),\n    1px 1px 3px rgba(var(--color-rgb-blue), 0.4),\n    4px 4px 8px rgba(var(--color-rgb-blue), 0.4),\n    -4px -4px 12px var(--color-tertiary-white);\n  --box-shadow-secondary: -4px -4px 12px #fff,\n    4px 4px 8px rgba(var(--color-rgb-blue), 0.4),\n    1px 1px 3px rgba(var(--color-rgb-blue), 0.4),\n    -1px -1px 3px rgba(var(--color-rgb-white), 0.25);\n  --box-shadow-hover: -1px -1px 4px rgba(var(--color-rgb-white), 0.25),\n    1px 1px 4px rgba(var(--color-rgb-blue), 0.4),\n    4px 4px 8px rgba(var(--color-rgb-blue), 0.4),\n    -4px -4px 8px rgba(var(--color-rgb-white), 0.8);\n  --box-shadow-pressed: -1px -1px 3px rgba(var(--color-rgb-white), 0.25),\n    1px 1px 3px rgba(var(--color-rgb-blue), 0.4);\n  --box-shadow-focus: inset 2px 2px 3px rgba(var(--color-rgb-blue), 0.2),\n    inset -2px -2px 3px rgba(var(--color-rgb-white), 0.7);\n\n  --border-error: 1px solid var(--color-secondary-orange);\n\n  --border-radius-base: 4px;\n\n  //font\n  --line-height-base: 22px;\n  --font-size-base: 14px;\n  --font-weight-base: 500;\n  --font-weight-bold: 600;\n  --letter-spacing-base: 0.03em;\n\n  // layout\n  --layout-gutter: 32px;\n\n  //button\n  --line-height-button: 16px;\n\n  --all-transition: all 0.3s cubic-bezier(0.645, 0.045, 0.355, 1);\n}\n"
  },
  {
    "path": "stories/components/Layout/Layout.stories.js",
    "content": "import QCol from '../../../src/qComponents/QCol';\nimport QRow from '../../../src/qComponents/QRow';\nimport './layout.scss';\n\nexport default {\n  title: 'Components/Layout',\n  subcomponents: { QRow, QCol },\n  argTypes: {\n    gutter: {\n      name: 'gutter',\n      control: 'text',\n      type: { name: 'string', required: false },\n      description: 'grid spacing (in CSS units)',\n      table: {\n        type: {\n          summary: ['string']\n        }\n      }\n    }\n  }\n};\n\nexport const QRowStory = (_, { argTypes }) => ({\n  props: Object.keys(argTypes),\n  computed: {\n    demoStyles() {\n      return {\n        '--layout-gutter': (this.gutter ?? '').trim()\n      };\n    }\n  },\n  template: `\n    <div class=\"demo\" :style=\"demoStyles\">\n      <q-row class=\"demo__row\">\n        <q-col class=\"demo__col\" cols=\"8\">\n          <div class=\"demo__content\">8</div>\n        </q-col>\n\n        <q-col class=\"demo__col\" cols=\"4\">\n          <div class=\"demo__content\">4</div>\n        </q-col>\n\n        <q-col class=\"demo__col\" cols=\"4\">\n          <div class=\"demo__content\">4</div>\n        </q-col>\n\n        <q-col class=\"demo__col\" cols=\"4\">\n          <div class=\"demo__content\">4</div>\n        </q-col>\n\n        <q-col class=\"demo__col\" cols=\"2\">\n          <div class=\"demo__content\">2</div>\n        </q-col>\n\n        <q-col class=\"demo__col\" cols=\"2\">\n          <div class=\"demo__content\">2</div>\n        </q-col>\n      </q-row>\n\n      <q-row class=\"demo__row\">\n        <q-col class=\"demo__col\" cols=\"2\">\n          <div class=\"demo__content\">2</div>\n        </q-col>\n\n        <q-col class=\"demo__col\" cols=\"8\">\n          <div class=\"demo__content\">8</div>\n        </q-col>\n\n        <q-col class=\"demo__col\" cols=\"2\">\n          <div class=\"demo__content\">2</div>\n        </q-col>\n      </q-row>\n\n      <q-row class=\"demo__row\">\n        <q-col class=\"demo__col\" cols=\"2\">\n          <div class=\"demo__content\">2</div>\n        </q-col>\n\n        <q-col class=\"demo__col\" cols=\"5\">\n          <div class=\"demo__content\">5</div>\n        </q-col>\n\n        <q-col class=\"demo__col\" cols=\"2\">\n          <div class=\"demo__content\">2</div>\n        </q-col>\n\n        <q-col class=\"demo__col\" cols=\"3\">\n          <div class=\"demo__content\">3</div>\n        </q-col>\n      </q-row>\n\n      <q-row class=\"demo__row\">\n        <q-col class=\"demo__col\" cols=\"5\">\n          <div class=\"demo__content\">5</div>\n        </q-col>\n\n        <q-col class=\"demo__col\" cols=\"7\">\n          <div class=\"demo__content\">7</div>\n        </q-col>\n      </q-row>\n\n      <q-row class=\"demo__row\">\n        <q-col class=\"demo__col\" cols=\"10\">\n          <div class=\"demo__content\">10</div>\n        </q-col>\n\n        <q-col class=\"demo__col\" cols=\"2\">\n          <div class=\"demo__content\">2</div>\n        </q-col>\n      </q-row>\n    </div>\n  `\n});\n\nQRowStory.storyName = 'Default';\n"
  },
  {
    "path": "stories/components/Layout/QCol.stories.js",
    "content": "import QRow from '../../../src/qComponents/QRow';\nimport QCol from '../../../src/qComponents/QCol';\nimport './layout.scss';\n\nexport default {\n  title: 'Components/Layout/QCol',\n  component: QCol,\n  subcomponents: { QRow },\n  argTypes: {\n    cols: {\n      control: {\n        type: 'select',\n        options: [null, 'auto', 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]\n      }\n    },\n    offset: {\n      control: {\n        type: 'select',\n        options: [null, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]\n      }\n    }\n  }\n};\n\nexport const QColStory = (_, { argTypes }) => ({\n  props: Object.keys(argTypes),\n  template: `\n    <div class=\"demo\">\n      <q-row class=\"demo__row\">\n        <q-col class=\"demo__col\" cols=\"2\">\n          <div class=\"demo__content\">2</div>\n        </q-col>\n\n        <q-col class=\"demo__col\" v-bind=\"$props\">\n          <div class=\"demo__content\">dyn</div>\n        </q-col>\n\n        <q-col class=\"demo__col\" cols=\"2\">\n          <div class=\"demo__content\">2</div>\n        </q-col>\n      </q-row>\n    </div>\n  `\n});\n\nQColStory.storyName = 'Default';\nQColStory.args = {\n  cols: 5,\n  offset: 3\n};\n"
  },
  {
    "path": "stories/components/Layout/QRow.stories.js",
    "content": "import QCol from '../../../src/qComponents/QCol';\nimport QRow from '../../../src/qComponents/QRow';\nimport './layout.scss';\n\nexport default {\n  title: 'Components/Layout/QRow',\n  component: QRow,\n  subcomponents: { QCol },\n  argTypes: {\n    alignV: {\n      control: {\n        type: 'select',\n        options: [null, 'start', 'end', 'center', 'baseline', 'stretch']\n      }\n    },\n    alignH: {\n      control: {\n        type: 'select',\n        options: [null, 'start', 'end', 'center', 'between', 'around']\n      }\n    }\n  }\n};\n\nexport const QRowStory = (_, { argTypes }) => ({\n  props: Object.keys(argTypes),\n  template: `\n    <div class=\"demo\">\n      <q-row class=\"demo__row\" v-bind=\"$props\">\n        <q-col class=\"demo-col\" cols=\"2\">\n          <div class=\"demo__content\">2</div>\n        </q-col>\n\n        <q-col class=\"demo__col\" cols=\"4\">\n          <div class=\"demo__content\" style=\"height: 25px;\">4</div>\n        </q-col>\n\n        <q-col class=\"demo__col\" cols=\"2\">\n          <div class=\"demo__content\">2</div>\n        </q-col>\n      </q-row>\n    </div>\n  `\n});\n\nQRowStory.storyName = 'Default';\n"
  },
  {
    "path": "stories/components/Layout/layout.scss",
    "content": ".demo {\n  display: flex;\n  flex-direction: column;\n  align-items: center;\n  width: 1000px;\n  max-width: 100%;\n\n  &__row {\n    width: 100%;\n\n    &:nth-child(odd) {\n      .demo__content {\n        background-color: var(--color-primary-blue-light);\n      }\n    }\n  }\n\n  &__content {\n    display: flex;\n    justify-content: center;\n    align-items: center;\n    width: 100%;\n    height: 50px;\n    margin-bottom: var(--layout-gutter);\n    background-color: var(--color-primary-blue-aqua);\n    border-radius: var(--border-radius-base);\n  }\n}\n"
  },
  {
    "path": "stories/components/QBreadcrumbs.stories.js",
    "content": "import Vue from 'vue';\n\nimport QBreadcrumbs from '../../src/qComponents/QBreadcrumbs';\n\nexport default {\n  title: 'Components/QBreadcrumbs',\n  component: QBreadcrumbs\n};\n\nVue.component('router-link', {\n  props: {\n    to: {\n      type: [String, Object],\n      default: null\n    }\n  },\n  template: '<a href=\"#\" @click.prevent.stop><slot/></a>'\n});\n\nObject.defineProperty(Vue.prototype, '$route', {\n  get() {\n    return {\n      matched: [\n        {\n          path: 'path-a',\n          name: 'ROUTE_A',\n          meta: {\n            breadcrumb: this.$t('qBreadcrumbsStories.routeA')\n          }\n        },\n        {\n          path: 'path-b',\n          name: 'ROUTE_B',\n          meta: {\n            breadcrumb: this.$t('qBreadcrumbsStories.routeB')\n          }\n        },\n        {\n          path: 'path-c',\n          name: 'ROUTE_C',\n          meta: {\n            breadcrumb: this.$t('qBreadcrumbsStories.routeC')\n          }\n        },\n        {\n          path: 'path-d',\n          name: 'ROUTE_D',\n          meta: {\n            breadcrumb: this.$t('qBreadcrumbsStories.routeD')\n          }\n        }\n      ]\n    };\n  }\n});\n\nexport const QBreadcrumbsStory = (_, { argTypes }) => ({\n  props: Object.keys(argTypes),\n  template: `\n    <q-breadcrumbs v-bind=\"$props\" />\n  `\n});\n\nQBreadcrumbsStory.storyName = 'Default';\n\nexport const QBreadcrumbsRouteStory = (_, { argTypes }) => ({\n  props: Object.keys(argTypes).filter(val => val !== 'customRoutes'),\n  data() {\n    return {\n      customRoutes: [\n        {\n          path: 'path-a',\n          name: 'ROUTE_A',\n          meta: {\n            breadcrumb: this.$t('qBreadcrumbsStories.routeA')\n          }\n        },\n        {\n          path: 'path-b',\n          name: 'ROUTE_b',\n          meta: {\n            breadcrumb: this.$t('qBreadcrumbsStories.routeB')\n          }\n        }\n      ]\n    };\n  },\n  template: `\n    <q-breadcrumbs v-bind=\"$props\" :custom-routes=\"customRoutes\" />\n  `\n});\n\nQBreadcrumbsRouteStory.storyName = 'Custom route';\n"
  },
  {
    "path": "stories/components/QButton.stories.mdx",
    "content": "import { Meta, Canvas, Story, ArgsTable } from '@storybook/addon-docs/blocks';\n\nimport QButton from '../../src/qComponents/QButton';\n\n<Meta\n  title=\"Components/QButton\"\n  component={QButton}\n  argTypes={{\n    type: {\n      control: { type: 'select', options: ['default', 'icon'] }\n    },\n    theme: {\n      control: { type: 'select', options: ['primary', 'secondary', 'link'] }\n    },\n    size: {\n      control: { type: 'select', options: ['small', 'medium'] }\n    }\n  }}\n/>\n\nexport const Template = (args, { argTypes }) => ({\n  props: Object.keys(argTypes),\n  components: { QButton },\n  template: `\n    <q-button\n      :type=\"type\"\n      :icon=\"icon\"\n      :size=\"size\"\n      :theme=\"theme\"\n      :loading=\"loading\"\n      :disabled=\"disabled\"\n      :circle=\"circle\"\n      :fullWidth=\"fullWidth\"\n    >{{label}}</q-button>\n  `\n});\n\n# QButton\n\n<Canvas>\n  <Story\n    name=\"Type Default\"\n    args={{\n      label: 'A Button with default theme'\n    }}\n  >\n    {Template.bind({})}\n  </Story>\n  <Story\n    name=\"Type Default Secondary\"\n    args={{\n      label: 'A Button with secondary theme',\n      theme: 'secondary'\n    }}\n  >\n    {Template.bind({})}\n  </Story>\n  <Story\n    name=\"Type Default Link\"\n    args={{\n      label: 'A Button with link theme',\n      theme: 'link'\n    }}\n  >\n    {Template.bind({})}\n  </Story>\n</Canvas>\n\n## Icons\n\n<Canvas>\n  <Story\n    name=\"Type Icon Default\"\n    args={{\n      label: '',\n      type: 'icon',\n      icon: 'q-icon-bell'\n    }}\n  >\n    {Template.bind({})}\n  </Story>\n  <Story\n    name=\"Type Icon Secondary\"\n    args={{\n      label: '',\n      type: 'icon',\n      icon: 'q-icon-bell',\n      theme: 'secondary'\n    }}\n  >\n    {Template.bind({})}\n  </Story>\n  <Story\n    name=\"Type Icon Link\"\n    args={{\n      label: '',\n      type: 'icon',\n      icon: 'q-icon-bell',\n      theme: 'link'\n    }}\n  >\n    {Template.bind({})}\n  </Story>\n</Canvas>\n\n## Playground\n\n<Canvas>\n  <Story\n    name=\"Playground\"\n    args={{\n      label: 'Click me'\n    }}\n  >\n    {Template.bind({})}\n  </Story>\n</Canvas>\n\n<ArgsTable story=\"Playground\" />\n"
  },
  {
    "path": "stories/components/QCascader.stories.js",
    "content": "import QCascader from '../../src/qComponents/QCascader';\n\nconst args = {\n  options: [\n    {\n      value: 'guide',\n      label: 'Guide',\n      children: [\n        {\n          value: 'disciplines',\n          label: 'Disciplines',\n          children: [\n            {\n              value: 'consistency',\n              label: 'Consistency',\n              children: [\n                {\n                  value: 'four level',\n                  label: 'Four level'\n                }\n              ]\n            },\n            {\n              value: 'feedback',\n              label: 'Feedback'\n            }\n          ]\n        },\n        {\n          value: 'navigation',\n          label: 'Navigation',\n          children: [\n            {\n              value: 'side nav',\n              label: 'Side Navigation'\n            },\n            {\n              value: 'top nav',\n              label: 'Top Navigation'\n            }\n          ]\n        },\n        {\n          value: 'alone',\n          label: 'Alone'\n        }\n      ]\n    },\n    {\n      value: 'resource',\n      label: 'Resource'\n    }\n  ]\n};\n\nexport default {\n  title: 'Components/QCascader',\n  component: QCascader,\n  argTypes: {\n    value: { control: { type: 'none' } }\n  }\n};\n\nexport const Default = (_, { argTypes }) => ({\n  props: Object.keys(argTypes).filter(arg => !['value'].includes(arg)),\n  data() {\n    return { value: null };\n  },\n  methods: {\n    handleValueChange(value) {\n      this.value = value;\n    }\n  },\n  template: `\n    <q-cascader\n      v-model=\"value\"\n      @change=\"handleValueChange\"\n      :check-strictly=\"checkStrictly\"\n      :options=\"options\"\n      :placeholder=\"placeholder\"\n      :disabled=\"disabled\"\n      :clearable=\"clearable\"\n      :multiple=\"multiple\"\n      :separator=\"separator\"\n      :all-levels-shown=\"allLevelsShown\"\n      :collapse-tags=\"collapseTags\"\n    />\n  `\n});\n\nDefault.args = args;\n\nexport const Multiple = Default.bind({});\nMultiple.args = {\n  ...args,\n  multiple: true\n};\n"
  },
  {
    "path": "stories/components/QCheckbox.stories.js",
    "content": "import QCheckbox from '../../src/qComponents/QCheckbox';\n\nexport default {\n  title: 'Components/QCheckbox/QCheckbox',\n  component: QCheckbox,\n  argTypes: {\n    'v-model': { control: { type: 'none' } },\n    value: { control: { type: 'none' } }\n  }\n};\n\nexport const QCheckboxStory = (_, { argTypes }) => ({\n  props: Object.keys(argTypes),\n  data() {\n    return {\n      checked1: true,\n      checked2: false,\n      checked3: false,\n      checked4: false,\n      checked5: true\n    };\n  },\n  template: `\n    <div>\n      <q-checkbox v-model=\"checked1\" v-bind=\"$props\" />\n      <br /><br />\n      <q-checkbox v-model=\"checked2\" label=\"Option B\" />\n      <br /><br />\n      <q-checkbox v-model=\"checked3\" label=\"Option C\" />\n      <br /><br />\n      <q-checkbox\n        v-model=\"checked4\"\n        label=\"Disabled\"\n        disabled\n      />\n      <br /><br />\n      <q-checkbox\n        v-model=\"checked5\"\n        label=\"Checked & Disabled\"\n        disabled\n      />\n    </div>\n  `\n});\n\nQCheckboxStory.storyName = 'Default';\nQCheckboxStory.args = {\n  label: 'Option A'\n};\n"
  },
  {
    "path": "stories/components/QCheckboxGroup.stories.js",
    "content": "import QCheckboxGroup from '../../src/qComponents/QCheckboxGroup';\nimport QCheckbox from '../../src/qComponents/QCheckbox';\n\nconst args = {\n  min: 0,\n  max: 3\n};\n\nexport default {\n  title: 'Components/QCheckbox/QCheckboxGroup',\n  component: QCheckboxGroup,\n  subcomponents: { QCheckbox },\n  argTypes: {\n    value: { control: { type: 'none' } },\n    min: { control: { type: 'none' } },\n    max: { control: { type: 'none' } },\n    direction: {\n      control: { type: 'inline-radio', options: ['vertical', 'horizontal'] }\n    }\n  }\n};\n\nexport const Default = (_, { argTypes }) => ({\n  props: Object.keys(argTypes),\n  data() {\n    return {\n      checkedCities: ['Shanghai', 'Beijing'],\n      cities: ['Shanghai', 'Beijing', 'Guangzhou', 'Shenzhen']\n    };\n  },\n  template: `\n    <q-checkbox-group\n      v-model=\"checkedCities\"\n      v-bind=\"$props\"\n    >\n      <q-checkbox\n        v-for=\"city in cities\"\n        :key=\"city\"\n        :label=\"city\"\n      >{{\n        city\n      }}</q-checkbox>\n    </q-checkbox-group>\n  `\n});\n\nDefault.args = args;\n\nexport const Indeterminate = (_, { argTypes }) => ({\n  props: Object.keys(argTypes),\n  components: { QCheckbox, QCheckboxGroup },\n  data() {\n    return {\n      checkAll: false,\n      checkedCities: ['Option A', 'Option C'],\n      cities: ['Option A', 'Option B', 'Option C', 'Option D'],\n      isIndeterminate: true\n    };\n  },\n  methods: {\n    handleCheckAllChange(val) {\n      this.checkedCities = val ? this.cities : [];\n      this.isIndeterminate = false;\n    },\n    handleCheckedCitiesChange(value) {\n      const checkedCount = value.length;\n      this.checkAll = checkedCount === this.cities.length;\n      this.isIndeterminate =\n        checkedCount > 0 && checkedCount < this.cities.length;\n    }\n  },\n  template: `\n    <div>\n      <q-checkbox\n        v-model=\"checkAll\"\n        :indeterminate=\"isIndeterminate\"\n        style=\"margin-bottom: 16px\"\n        @change=\"handleCheckAllChange\"\n        :disabled=\"disabled\"\n      >\n        Check all\n      </q-checkbox>\n\n      <q-checkbox-group\n        v-model=\"checkedCities\"\n        @change=\"handleCheckedCitiesChange\"\n        v-bind=\"$props\"\n      >\n        <q-checkbox\n          v-for=\"city in cities\"\n          :key=\"city\"\n          :label=\"city\"\n        >\n          {{ city }}\n        </q-checkbox>\n      </q-checkbox-group>\n    </div>\n  `\n});\n\nIndeterminate.args = args;\n"
  },
  {
    "path": "stories/components/QCollapse.stories.js",
    "content": "import QCollapse from '../../src/qComponents/QCollapse';\nimport QCollapseItem from '../../src/qComponents/QCollapseItem';\n\nexport default {\n  title: 'Components/QCollapse',\n  component: QCollapse,\n  subcomponents: { QCollapseItem },\n  argTypes: {\n    'v-model': { control: { type: 'none' } }\n  }\n};\n\nexport const QCollapseStory = (_, { argTypes }) => ({\n  props: Object.keys(argTypes),\n  data() {\n    return {\n      activeNames: ['1']\n    };\n  },\n  methods: {\n    handleChange(value) {\n      console.log(value);\n    }\n  },\n  template: `\n    <q-collapse\n      v-model=\"activeNames\"\n      :accordion=\"accordion\"\n      style=\"max-width:732px\"\n      @change=\"handleChange\"\n    >\n      <q-collapse-item\n        title=\"Consistency\"\n        name=\"1\"\n      >\n        <div>\n          Consistent with real life: in line with the process and logic of real\n          life, and comply with languages and habits that the users are used to;\n        </div>\n        <div>\n          Consistent within interface: all elements should be consistent, such as:\n          design style, icons and texts, position of elements, etc.\n        </div>\n      </q-collapse-item>\n      <q-collapse-item\n        title=\"Controlled consequences: users should be granted the freedom to operate, including canceling, aborting or  reflect current state by updat\"\n      >\n        <div>\n          Operation feedback: enable the users to clearly perceive their\n          operations by style updates and interactive effects;\n        </div>\n        <div>\n          Visual feedback: reflect current state by updating or rearranging\n          elements of the page.\n        </div>\n      </q-collapse-item>\n      <q-collapse-item title=\"Efficiency\">\n        <div>\n          Simplify the process: keep operating process simple and intuitive;\n        </div>\n        <div>\n          Definite and clear: enunciate your intentions clearly so that the users\n          can quickly understand and make decisions;\n        </div>\n        <div>\n          Easy to identify: the interface should be straightforward, which helps\n          the users to identify and frees them from memorizing and recalling.\n        </div>\n      </q-collapse-item>\n      <q-collapse-item\n        title=\"Controllability\"\n        name=\"4\"\n      >\n        <div>\n          Decision making: giving advices about operations is acceptable, but do\n          not make decisions for the users;\n        </div>\n        <div>\n          Controlled consequences: users should be granted the freedom to operate,\n          including canceling, aborting or terminating current operation.\n        </div>\n      </q-collapse-item>\n    </q-collapse>\n  `\n});\n\nQCollapseStory.storyName = 'Default';\n"
  },
  {
    "path": "stories/components/QColorPicker.stories.js",
    "content": "import QColorPicker from '../../src/qComponents/QColorPicker';\n\nimport PLACEMENTS from '../../src/qComponents/constants/popperPlacements';\n\nexport default {\n  title: 'Components/QColorPicker',\n  component: QColorPicker,\n  argTypes: {\n    'v-model': { control: { type: 'none' } },\n    placement: {\n      control: { type: 'select', options: PLACEMENTS }\n    },\n    colorFormat: {\n      control: { type: 'select', options: ['hex', 'rgb'] }\n    }\n  }\n};\n\nexport const QColorPickerStory = (_, { argTypes }) => ({\n  props: Object.keys(argTypes),\n  data() {\n    return {\n      color: '#f25'\n    };\n  },\n  template: `\n    <q-color-picker\n      v-model=\"color\"\n      v-bind=\"$props\"\n    />\n  `\n});\n\nQColorPickerStory.storyName = 'Default';\n"
  },
  {
    "path": "stories/components/QContextMenu.stories.js",
    "content": "import QContextMenu from '../../src/qComponents/QContextMenu';\n\nexport default {\n  title: 'Components/QContextMenu',\n  component: QContextMenu,\n  argTypes: {\n    position: {\n      control: { type: 'inline-radio', options: ['left', 'right'] }\n    }\n  }\n};\n\nexport const QContextMenuStory = (_, { argTypes }) => ({\n  props: Object.keys(argTypes),\n  methods: {\n    handleAction(action) {\n      console.log(action);\n    }\n  },\n  template: `\n    <q-context-menu\n      v-bind=\"$props\"\n      @action=\"handleAction\"\n    />\n  `\n});\n\nQContextMenuStory.storyName = 'Default';\nQContextMenuStory.args = {\n  menuItems: [\n    {\n      action: 'action1',\n      name: 'Menu item 1',\n      icon: 'q-icon-account'\n    },\n    {\n      action: 'action2',\n      name: 'Menu item 2',\n      icon: 'q-icon-bell'\n    },\n    {\n      action: 'action3',\n      name: 'Menu item 3',\n      icon: 'q-icon-pic'\n    }\n  ]\n};\n"
  },
  {
    "path": "stories/components/QDatePicker/DateRange.js",
    "content": "import Template from './Default';\n\nconst DateRange = Template.bind({});\n\nDateRange.args = {\n  type: 'daterange'\n};\n\nexport default DateRange;\n"
  },
  {
    "path": "stories/components/QDatePicker/DateTime.js",
    "content": "import Template from './Default';\n\nconst DateTime = Template.bind({});\n\nDateTime.args = {\n  type: 'datetime'\n};\n\nexport default DateTime;\n"
  },
  {
    "path": "stories/components/QDatePicker/DateTimeRange.js",
    "content": "import Template from './Default';\n\nconst DateTimeRange = Template.bind({});\n\nDateTimeRange.args = {\n  type: 'datetimerange'\n};\n\nexport default DateTimeRange;\n"
  },
  {
    "path": "stories/components/QDatePicker/Default.js",
    "content": "export default (_, { argTypes }) => ({\n  props: Object.keys(argTypes).filter(\n    arg => !['value', 'format'].includes(arg)\n  ),\n  data() {\n    return {\n      value: null,\n      format: 'dd MMMM yyyy'\n    };\n  },\n  methods: {\n    handleRangePickClick(val) {\n      console.log('handleRangePickClick', val);\n    },\n    handleChange(value) {\n      console.log('handleChange', value);\n    },\n    handleInput(value) {\n      console.log('handleInput', value);\n    }\n  },\n  watch: {\n    type(value) {\n      switch (value) {\n        case 'datetime':\n          this.format = 'dd MMM yy, HH:mm:ss';\n          this.value = null;\n          break;\n        case 'daterange':\n          this.format = 'dd MMM yyyy';\n          this.value = null;\n          break;\n        case 'datetimerange':\n          this.format = 'dd MMM yy, HH:mm:ss';\n          this.value = null;\n          break;\n        case 'week':\n          this.format = 'wo';\n          this.value = null;\n          break;\n        case 'month':\n          this.format = 'LLLL yyyy';\n          this.value = null;\n          break;\n        case 'monthrange':\n          this.format = 'LLLL yyyy';\n          this.value = null;\n          break;\n        case 'year':\n          this.format = 'yyyy';\n          this.value = null;\n          break;\n        case 'yearrange':\n          this.format = 'yyyy';\n          this.value = null;\n          break;\n        default:\n          this.format = 'dd MMMM yyyy';\n          this.value = null;\n          break;\n      }\n    }\n  },\n  template: `\n      <q-date-picker\n        v-model=\"value\"\n        :clearable=\"clearable\"\n        :editable=\"editable\"\n        :placeholder=\"placeholder\"\n        :type=\"type\"\n        :format=\"format\"\n        :output-format=\"outputFormat\"\n        :name=\"name\"\n        :disabled=\"disabled\"\n        :disabled-values=\"disabledValues\"\n        :shortcuts=\"shortcuts\"\n        :start-placeholder=\"startPlaceholder\"\n        :end-placeholder=\"endPlaceholder\"\n        :first-day-of-week=\"firstDayOfWeek\"\n        :range-separator=\"rangeSeparator\"\n        :validate-event=\"validateEvent\"\n        @rangepick=\"handleRangePickClick\"\n        @input=\"handleInput\"\n        @change=\"handleChange\"\n        :append-to-body=\"appendToBody\"\n      />`\n});\n"
  },
  {
    "path": "stories/components/QDatePicker/Month.js",
    "content": "import Template from './Default';\n\nconst Month = Template.bind({});\n\nMonth.args = {\n  type: 'month'\n};\n\nexport default Month;\n"
  },
  {
    "path": "stories/components/QDatePicker/MonthRange.js",
    "content": "import Template from './Default';\n\nconst MonthRange = Template.bind({});\n\nMonthRange.args = {\n  type: 'monthrange'\n};\n\nexport default MonthRange;\n"
  },
  {
    "path": "stories/components/QDatePicker/QDatePicker.stories.js",
    "content": "import { addMonths, subMonths } from 'date-fns';\nimport QDatePicker from '../../../src/qComponents/QDatePicker';\nimport Default from './Default';\nimport DateTime from './DateTime';\nimport Month from './Month';\nimport Year from './Year';\nimport DateRange from './DateRange';\nimport DateTimeRange from './DateTimeRange';\nimport MonthRange from './MonthRange';\nimport YearRange from './YearRange';\n\nexport default {\n  title: 'Components/QDatePicker',\n  component: QDatePicker,\n  argTypes: {\n    'v-model': { control: { type: 'none' } },\n    disabledValues: {\n      control: {\n        type: 'select',\n        options: [\n          null,\n          {\n            to: subMonths(new Date(), 2),\n            ranges: [\n              { start: new Date(), end: new Date(addMonths(new Date(), 1)) }\n            ]\n          }\n        ]\n      }\n    },\n    outputFormat: {\n      control: {\n        type: 'select',\n        options: ['date', 'iso']\n      }\n    },\n    shortcuts: {\n      control: {\n        type: 'select',\n        options: [\n          [],\n          [\n            {\n              text: 'Сегодня',\n              onClick(picker) {\n                picker.$emit('pick', new Date());\n              }\n            },\n            {\n              text: 'Вчера',\n              onClick(picker) {\n                const date = new Date();\n                date.setTime(date.getTime() - 3600 * 1000 * 24);\n                picker.$emit('pick', date);\n              }\n            },\n            {\n              text: 'Неделю назад',\n              onClick(picker) {\n                const date = new Date();\n                date.setTime(date.getTime() - 3600 * 1000 * 24 * 7);\n                picker.$emit('pick', date);\n              }\n            }\n          ]\n        ]\n      }\n    },\n    placeholder: {\n      type: { name: 'string', required: false }\n    },\n    format: {\n      name: 'format',\n      type: { name: 'string', required: false }\n    },\n    type: {\n      control: {\n        type: 'select',\n        options: [\n          'date',\n          'datetime',\n          'week',\n          'month',\n          'year',\n          'daterange',\n          'datetimerange',\n          'monthrange',\n          'yearrange'\n        ]\n      },\n      datetime: { disable: true }\n    },\n    firstDayOfWeek: {\n      control: {\n        type: 'select',\n        options: [0, 1, 2, 3, 4, 5, 6]\n      }\n    }\n  }\n};\n\nexport {\n  Default,\n  DateTime,\n  Month,\n  Year,\n  DateRange,\n  DateTimeRange,\n  MonthRange,\n  YearRange\n};\n"
  },
  {
    "path": "stories/components/QDatePicker/Year.js",
    "content": "import Template from './Default';\n\nconst Year = Template.bind({});\n\nYear.args = {\n  type: 'year'\n};\n\nexport default Year;\n"
  },
  {
    "path": "stories/components/QDatePicker/YearRange.js",
    "content": "import Template from './Default';\n\nconst YearRange = Template.bind({});\n\nYearRange.args = {\n  type: 'yearrange'\n};\n\nexport default YearRange;\n"
  },
  {
    "path": "stories/components/QDialog/DialogFormTest.vue",
    "content": "<template>\n  <q-form\n    ref=\"form\"\n    :model=\"formModel\"\n    :rules=\"rules\"\n  >\n    <q-form-item\n      prop=\"name\"\n      label=\"Name\"\n      required\n    >\n      <q-input v-model=\"formModel.name\" />\n    </q-form-item>\n\n    <q-button\n      :loading=\"isSending\"\n      @click=\"handleSendClick\"\n    >\n      Send\n    </q-button>\n\n    <q-button\n      theme=\"secondary\"\n      @click=\"handleCancelClick\"\n    >\n      Cancel\n    </q-button>\n  </q-form>\n</template>\n\n<script>\nexport default {\n  data() {\n    return {\n      isSending: false,\n      formModel: {\n        name: 'Testname'\n      },\n      rules: {\n        name: {\n          required: true,\n          message: 'Please input name',\n          trigger: 'blur'\n        }\n      }\n    };\n  },\n\n  methods: {\n    handleCancelClick() {\n      this.$emit('close', { action: 'cancel' });\n    },\n\n    async handleSendClick() {\n      this.isSending = true;\n\n      const promise = () =>\n        new Promise(resolve => {\n          setTimeout(() => resolve('done'), 1000);\n        });\n\n      try {\n        const payload = await promise();\n\n        this.$emit('close', { action: 'confirm', payload });\n      } catch (error) {\n        console.log(error);\n      }\n\n      this.isSending = false;\n    }\n  }\n};\n</script>\n"
  },
  {
    "path": "stories/components/QDialog/QDialog.stories.js",
    "content": "import Vue from 'vue';\n\nimport QDialog from '../../../src/qComponents/QDialog';\nimport QDialogComponent from '../../../src/qComponents/QDialog/src/QDialog.vue';\n\nexport default {\n  title: 'Components/QDialog',\n  component: QDialogComponent\n};\n\nexport const QDialogStory = (_, { argTypes }) => ({\n  props: Object.keys(argTypes),\n  data() {\n    return { dialogInstance: null };\n  },\n  beforeDestroy() {\n    // Use it to destroy dialog in handmode from outside\n    if (this.dialogInstance) this.dialogInstance.$destroy();\n  },\n  methods: {\n    async handleClick() {\n      console.log(Object.keys(argTypes));\n      const { answer, instance } = QDialog.bind(Vue)({\n        component: () => import('./DialogFormTest'),\n        ...this.$props\n      });\n\n      this.dialogInstance = instance;\n\n      console.log('instance', instance);\n      console.log('answer', await answer);\n    }\n  },\n  template: '<q-button @click=\"handleClick\">Click to open</q-button>'\n});\n\nQDialogStory.storyName = 'Default';\nQDialogStory.args = {\n  title: 'Morbi massa libero, vehicula nec consequat sed, porta a sem.'\n};\n"
  },
  {
    "path": "stories/components/QDrawer.stories.js",
    "content": "import QDrawer from '../../src/qComponents/QDrawer';\n\nexport default {\n  title: 'Components/QDrawer',\n  component: QDrawer,\n  argTypes: {\n    visible: { control: { type: 'none' } },\n    width: { control: { type: 'number' } },\n    position: {\n      control: { type: 'inline-radio', options: ['left', 'right'] }\n    }\n  }\n};\n\nexport const QNotificationStory = (_, { argTypes }) => ({\n  props: Object.keys(argTypes),\n  data() {\n    return {\n      drawer: false\n    };\n  },\n  template: `\n    <div>\n      <q-button @click=\"drawer = true\">\n        open\n      </q-button>\n      <q-drawer v-bind=\"$props\" :visible.sync=\"drawer\" >I'm drawer's slot</q-drawer>\n    </div>\n  `\n});\n\nQNotificationStory.storyName = 'Default';\nQNotificationStory.args = {\n  visible: false,\n  appendToBody: false,\n  title: 'What is Lorem Ipsum?',\n  width: 350\n};\n"
  },
  {
    "path": "stories/components/QForm.stories.js",
    "content": "import QForm from '../../src/qComponents/QForm';\nimport QFormItem from '../../src/qComponents/QFormItem';\n\nexport default {\n  title: 'Components/QForm',\n  component: QForm,\n  subcomponents: { QFormItem },\n  argTypes: {\n    rules: { control: { type: 'object' } },\n    model: { control: { type: 'none' } }\n  }\n};\n\nexport const QFormStory = (_, { argTypes }) => ({\n  props: Object.keys(argTypes).filter(arg => arg !== 'model'),\n  data() {\n    return {\n      formModel: {\n        name: '',\n        intro: '',\n        date: null\n      }\n    };\n  },\n  methods: {\n    async handleSubmitClick() {\n      const { isValid, invalidFields } = await this.$refs.form.validate();\n      console.log('QForm | validate', isValid, invalidFields);\n      if (isValid) {\n        // eslint-disable-next-line no-alert\n        alert('Success');\n      }\n    },\n\n    handleResetClick() {\n      this.$refs.form.resetFields();\n    }\n  },\n  template: `\n    <q-form\n      ref=\"form\"\n      :model=\"formModel\"\n      :rules=\"rules\"\n      :disabled=\"disabled\"\n      :hideRequiredAsterisk=\"hideRequiredAsterisk\"\n      :showErrorMessage=\"showErrorMessage\"\n      :validateOnRuleChange=\"validateOnRuleChange\"\n    >\n      <q-form-item\n        label=\"Name\"\n        prop=\"name\"\n      >\n        <q-input\n          v-model=\"formModel.name\"\n          type=\"text\"\n        />\n      </q-form-item>\n      <q-form-item\n        label=\"Introtext\"\n        prop=\"intro\"\n      >\n        <q-textarea\n          v-model=\"formModel.intro\"\n        />\n      </q-form-item>\n\n      <q-form-item\n        label=\"Date\"\n        prop=\"date\"\n      >\n        <q-date-picker\n          v-model=\"formModel.date\"\n          type=\"daterange\"\n        />\n      </q-form-item>    \n\n      <q-button @click=\"handleSubmitClick\">Create</q-button>\n      <q-button @click=\"handleResetClick\">Reset</q-button>\n    </q-form>\n  `\n});\n\nQFormStory.storyName = 'Default';\nQFormStory.args = {\n  rules: {\n    name: [\n      {\n        required: true,\n        message: 'Please input name',\n        trigger: 'blur'\n      },\n      {\n        min: 3,\n        max: 5,\n        message: 'Length should be 3 to 10',\n        trigger: 'blur'\n      }\n    ],\n    intro: {\n      required: true,\n      message: 'Please input introtext',\n      trigger: 'change'\n    },\n    date: {\n      required: true\n    }\n  }\n};\n"
  },
  {
    "path": "stories/components/QInput.stories.js",
    "content": "import QInput from '../../src/qComponents/QInput';\n\nimport { iconsList } from '../core/icons.stories.mdx';\n\nexport default {\n  title: 'Components/QInput',\n\n  component: QInput,\n\n  argTypes: {\n    placeholder: {\n      control: {\n        type: 'text'\n      }\n    },\n\n    maxlength: {\n      control: {\n        type: 'number'\n      }\n    },\n\n    value: {\n      control: {\n        type: 'text'\n      }\n    },\n\n    type: {\n      control: {\n        type: 'select',\n        options: ['text', 'password', 'number', 'email', 'hidden', 'tel', 'url']\n      }\n    },\n\n    suffixIcon: {\n      control: {\n        type: 'select',\n        options: iconsList\n      }\n    },\n\n    autocomplete: {\n      control: {\n        type: 'select',\n        options: ['on', 'off']\n      }\n    }\n  }\n};\n\nexport const QInputStory = (_, { argTypes }) => ({\n  props: Object.keys(argTypes).filter(arg => arg !== 'value'),\n\n  data() {\n    return {\n      value: ''\n    };\n  },\n\n  template: '<q-input v-bind=\"$props\" v-model=\"value\" />'\n});\n\nQInputStory.storyName = 'Default';\n"
  },
  {
    "path": "stories/components/QInputNumber.stories.js",
    "content": "import QInputNumber from '../../src/qComponents/QInputNumber';\n\nexport default {\n  title: 'Components/QInputNumber',\n  component: QInputNumber,\n  argTypes: {\n    value: {\n      control: {\n        type: 'none'\n      }\n    }\n  }\n};\n\nexport const Default = (_, { argTypes }) => ({\n  props: Object.keys(argTypes).filter(val => val !== 'value'),\n  data() {\n    return {\n      value: 2\n    };\n  },\n  methods: {\n    handleEmit(value, type) {\n      console.log(value, type);\n    }\n  },\n  template: `\n    <q-input-number \n      v-bind=\"$props\" \n      v-model=\"value\"\n      @input=\"handleEmit($event, 'input')\"\n      @change=\"handleEmit($event, 'change')\"\n    />\n  `\n});\n\nDefault.storyName = 'Default';\n"
  },
  {
    "path": "stories/components/QMessageBox/MessageBoxFormTest.vue",
    "content": "<template>\n  <q-form\n    ref=\"form\"\n    :model=\"formModel\"\n    :rules=\"rules\"\n  >\n    <div class=\"q-message-box__content\">\n      <q-form-item\n        prop=\"name\"\n        label=\"Name\"\n        required\n      >\n        <q-input v-model=\"formModel.name\" />\n      </q-form-item>\n    </div>\n    <div class=\"q-message-box__actions\">\n      <q-button\n        :loading=\"isSending\"\n        @click=\"handleSendClick\"\n      >\n        Send\n      </q-button>\n\n      <q-button\n        theme=\"secondary\"\n        @click=\"handleCancelClick\"\n      >\n        Cancel\n      </q-button>\n    </div>\n  </q-form>\n</template>\n\n<script>\nexport default {\n  data() {\n    return {\n      isSending: false,\n      formModel: {\n        name: 'Testname'\n      },\n      rules: {\n        name: {\n          required: true,\n          message: 'Please input name',\n          trigger: 'blur'\n        }\n      }\n    };\n  },\n\n  methods: {\n    handleCancelClick() {\n      this.$emit('close', { action: 'cancel' });\n    },\n\n    async handleSendClick() {\n      this.isSending = true;\n\n      const promise = () =>\n        new Promise(resolve => {\n          setTimeout(() => resolve('done'), 1000);\n        });\n\n      try {\n        const payload = await promise();\n\n        this.$emit('close', { action: 'confirm', payload });\n      } catch (error) {\n        console.log(error);\n      }\n\n      this.isSending = false;\n    }\n  }\n};\n</script>\n"
  },
  {
    "path": "stories/components/QMessageBox/QMessageBox.stories.js",
    "content": "import Vue from 'vue';\n\nimport QMessageBox from '../../../src/qComponents/QMessageBox';\nimport QMessageBoxComponent from '../../../src/qComponents/QMessageBox/src/QMessageBox.vue';\n\nexport default {\n  title: 'Components/QMessageBox',\n  component: QMessageBoxComponent\n};\n\nexport const QMessageBoxStory = (_, { argTypes }) => ({\n  props: Object.keys(argTypes).filter(val => val !== 'beforeClose'),\n  methods: {\n    async beforeClose({ action, ctx }) {\n      if (action !== 'confirm') return true;\n\n      ctx.isConfirmBtnLoading = true;\n\n      const promise = () =>\n        new Promise(resolve => {\n          setTimeout(() => resolve('готово!'), 1000);\n        });\n\n      try {\n        await promise();\n        ctx.isConfirmBtnLoading = false;\n\n        return true;\n      } catch (error) {\n        ctx.isConfirmBtnLoading = false;\n\n        return false;\n      }\n    },\n\n    async handleClick() {\n      try {\n        const response = await QMessageBox.bind(Vue)({\n          ...this.$props,\n          beforeClose: this.beforeClose\n        });\n        console.log(response);\n      } catch (error) {\n        console.log(error);\n      }\n    }\n  },\n  template: '<q-button @click=\"handleClick\">Click to open</q-button>'\n});\n\nQMessageBoxStory.storyName = 'Default';\nQMessageBoxStory.args = {\n  title: 'Morbi massa libero, vehicula nec consequat sed, porta a sem.',\n  message:\n    'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec vehicula volutpat nulla et egestas. Mauris mollis, lorem vel aliquam gravida.',\n  submessage:\n    'Sed sit amet nibh consequat, pellentesque arcu ut, congue lorem.',\n  confirmButtonText: 'Fusce blandit',\n  cancelButtonText: 'Integer non'\n};\n\nexport const QMessageBoxComponentStory = (_, { argTypes }) => ({\n  props: Object.keys(argTypes),\n  methods: {\n    async handleClick() {\n      try {\n        const response = await QMessageBox.bind(Vue)({\n          component: () => import('./MessageBoxFormTest')\n        });\n        console.log(response);\n      } catch (error) {\n        console.log(error);\n      }\n    }\n  },\n  template: '<q-button @click=\"handleClick\">Click to open</q-button>'\n});\n\nQMessageBoxComponentStory.storyName = 'Component';\nQMessageBoxComponentStory.args = {\n  title: 'Morbi massa libero, vehicula nec consequat sed, porta a sem.'\n};\n\nexport const QMessageBoxHTMLStory = (_, { argTypes }) => ({\n  props: Object.keys(argTypes),\n  methods: {\n    async handleClick() {\n      try {\n        const response = await QMessageBox.bind(Vue)({\n          ...this.$props\n        });\n        console.log(response);\n      } catch (error) {\n        console.log(error);\n      }\n    }\n  },\n  template: '<q-button @click=\"handleClick\">Click to open</q-button>'\n});\n\nQMessageBoxHTMLStory.storyName = 'HTML';\nQMessageBoxHTMLStory.args = {\n  title: 'Morbi massa libero, vehicula nec consequat sed, porta a sem.',\n  message:\n    '<strong>This</strong> is <i>HTML</i> <span style=\"color:red;\">string</span>',\n  dangerouslyUseHTMLString: true,\n  submessage:\n    'Sed sit amet nibh consequat, pellentesque arcu ut, congue lorem.',\n  confirmButtonText: 'Fusce blandit'\n};\n\nexport const QMessageBoxVNodeStory = (_, { argTypes }) => ({\n  props: Object.keys(argTypes),\n  methods: {\n    async handleClick() {\n      try {\n        const h = this.$createElement;\n        const response = await QMessageBox.bind(Vue)({\n          ...this.$props,\n          message: h('p', null, [\n            h('span', null, 'Message can be '),\n            h('i', { style: 'color: teal' }, 'VNode')\n          ])\n        });\n        console.log(response);\n      } catch (error) {\n        console.log(error);\n      }\n    }\n  },\n  template: '<q-button @click=\"handleClick\">Click to open</q-button>'\n});\n\nQMessageBoxVNodeStory.storyName = 'VNode';\nQMessageBoxVNodeStory.agrs = {\n  title: 'Morbi massa libero, vehicula nec consequat sed, porta a sem.',\n  confirmButtonText: 'Fusce blandit'\n};\n"
  },
  {
    "path": "stories/components/QNotification.stories.js",
    "content": "import QNotification from '../../src/qComponents/QNotification';\nimport QNotificationComponent from '../../src/qComponents/QNotification/src/QNotification.vue';\nimport { iconsList } from '../core/icons.stories.mdx';\n\nexport default {\n  title: 'Components/QNotification',\n  component: QNotificationComponent,\n  argTypes: {\n    type: {\n      control: {\n        type: 'select',\n        options: [null, 'success', 'warning', 'info', 'error']\n      }\n    },\n    icon: {\n      control: {\n        type: 'select',\n        options: iconsList\n      }\n    }\n  }\n};\n\nexport const QNotificationStory = (_, { argTypes }) => ({\n  props: Object.keys(argTypes),\n  methods: {\n    handleClick() {\n      QNotification({\n        message: this.message,\n        type: this.type,\n        dangerouslyUseHTMLString: this.dangerouslyUseHTMLString,\n        duration: this.duration,\n        icon: this.icon\n      });\n    },\n\n    handleCloseAllClick() {\n      QNotification.closeAll();\n    }\n  },\n  template: `\n    <div>\n      <q-button @click=\"handleClick\">Click to open</q-button>\n      <q-button @click=\"handleCloseAllClick\" theme=\"secondary\">\n        close all\n      </q-button>\n    </div>\n    `\n});\n\nQNotificationStory.storyName = 'Default';\nQNotificationStory.args = {\n  message: 'Morbi massa libero, vehicula nec consequat sed, porta a sem.'\n};\n"
  },
  {
    "path": "stories/components/QPagination.stories.js",
    "content": "import QPagination from '../../src/qComponents/QPagination';\n\nexport default {\n  title: 'Components/QPagination',\n  component: QPagination\n};\n\nexport const QPaginationStory = (_, { argTypes }) => ({\n  props: Object.keys(argTypes),\n  methods: {\n    handleCurrentChange(val) {\n      this.currentPage = val;\n    }\n  },\n  template: `\n    <q-pagination\n      :pageCount=\"pageCount\"\n      :total=\"total\"\n      :pageSize=\"pageSize\"\n      :currentPage=\"currentPage\"\n      :disabled=\"disabled\"\n      :pagerCount=\"pagerCount\"\n      @current-change=\"handleCurrentChange\"\n    />\n  `\n});\n\nQPaginationStory.storyName = 'Default';\nQPaginationStory.args = {\n  pageCount: 30,\n  currentPage: 1,\n  total: 300,\n  pageSize: 10\n};\n"
  },
  {
    "path": "stories/components/QPopover.stories.js",
    "content": "import QPopover from '../../src/qComponents/QPopover';\nimport { iconsList } from '../core/icons.stories.mdx';\nimport PLACEMENTS from '../../src/qComponents/constants/popperPlacements';\n\nexport default {\n  title: 'Components/QPopover',\n  component: QPopover,\n  argTypes: {\n    trigger: {\n      control: {\n        type: 'inline-radio',\n        options: ['click', 'hover']\n      }\n    },\n    placement: {\n      control: {\n        type: 'select',\n        options: PLACEMENTS\n      }\n    },\n    icon: {\n      control: {\n        type: 'select',\n        options: iconsList\n      }\n    }\n  }\n};\n\nexport const Default = (_, { argTypes }) => ({\n  props: Object.keys(argTypes),\n  data() {\n    return {\n      componentKey: 0\n    };\n  },\n  watch: {\n    trigger() {\n      // trigger is being setting up in mounted, we need to update render\n      this.componentKey += 1;\n    }\n  },\n  template: `\n    <q-popover v-bind=\"$props\" :key=\"componentKey\">\n      <q-button\n        slot=\"reference\"\n        circle\n        type=\"icon\"\n        theme=\"secondary\"\n        size=\"small\"\n        icon=\"q-icon-question-mark\"\n      />\n\n      Lorem Ipsum is simply dummy text of the printing and typesetting industry.\n    </q-popover>\n  `\n});\n\nDefault.storyName = 'Default';\nDefault.args = {\n  title: 'What is Lorem Ipsum?',\n  icon: 'q-icon-question'\n};\n"
  },
  {
    "path": "stories/components/QRadio.stories.js",
    "content": "import QRadio from '../../src/qComponents/QRadio';\n\nexport default {\n  title: 'Components/QRadio/QRadio',\n  component: QRadio,\n  argTypes: {\n    'v-model': { control: { type: 'none' } },\n    value: { control: { type: 'none' } },\n    label: { control: 'text' }\n  }\n};\n\nexport const QRadioStory = (_, { argTypes }) => ({\n  props: Object.keys(argTypes),\n  data() {\n    return {\n      radio1: '1',\n      radio2: '1'\n    };\n  },\n  template: `\n    <div>\n      <q-radio\n        v-model=\"radio1\"\n        value=\"1\"\n        v-bind=\"$props\"\n      />\n      <br /><br />\n      <q-radio\n        v-model=\"radio1\"\n        value=\"2\"\n        label=\"Option B\"\n      />\n      <br /><br />\n      <q-radio\n        v-model=\"radio1\"\n        value=\"3\"\n        label=\"Option C\"\n      />\n      <br /><br />\n      <q-radio\n        v-model=\"radio1\"\n        disabled\n        value=\"4\"\n        label=\"Disabled\"\n      />\n      <br /><br />\n      <q-radio\n        v-model=\"radio2\"\n        disabled\n        value=\"1\"\n        label=\"Checked & disabled\"\n      />\n    </div>\n  `\n});\n\nQRadioStory.storyName = 'Default';\nQRadioStory.args = {\n  label: 'Option A'\n};\n"
  },
  {
    "path": "stories/components/QRadioGroup.stories.js",
    "content": "import QRadioGroup from '../../src/qComponents/QRadioGroup';\nimport QRadio from '../../src/qComponents/QRadio';\n\nexport default {\n  title: 'Components/QRadio/QRadioGroup',\n  component: QRadioGroup,\n  subcomponents: { QRadio },\n  argTypes: {\n    'v-model': { control: { type: 'none' } },\n    direction: {\n      control: { type: 'inline-radio', options: ['vertical', 'horizontal'] }\n    }\n  }\n};\n\nexport const QRadioGroupStory = (_, { argTypes }) => ({\n  props: Object.keys(argTypes),\n  data() {\n    return { value: 3 };\n  },\n  template: `\n    <q-radio-group\n      v-model=\"value\"\n      v-bind=\"$props\"\n    >\n      <q-radio :value=\"3\" label=\"Option A\" />\n      <q-radio :value=\"6\" label=\"Option B\" />\n      <q-radio :value=\"9\" label=\"Option C\" />\n    </q-radio-group>\n  `\n});\n\nQRadioGroupStory.storyName = 'Default';\n"
  },
  {
    "path": "stories/components/QScrollbar/QScrollbar.stories.js",
    "content": "import QScrollbar from '../../../src/qComponents/QScrollbar';\n\nimport './q-scrollbar.scss';\n\nexport default {\n  title: 'Components/QScrollbar',\n  component: QScrollbar,\n  argTypes: {\n    theme: {\n      control: { type: 'inline-radio', options: ['primary', 'secondary'] }\n    }\n  }\n};\n\nexport const QScrollbarStory = (_, { argTypes }) => ({\n  props: Object.keys(argTypes),\n  template: `\n    <q-scrollbar v-bind=\"$props\">\n      <div class=\"french-bread\">\n        <p>\"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p>\n        <p>Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p>\n        <p>Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.</p>\n        <p>Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.\"</p>\n        <p>\"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p>\n        <p>Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p>\n        <p>Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.</p>\n        <p>Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.\"</p>\n      </div>\n    </q-scrollbar>\n  `\n});\n\nQScrollbarStory.storyName = 'Default';\nQScrollbarStory.args = {\n  wrapClass: 'scrollbar__wrap'\n};\n"
  },
  {
    "path": "stories/components/QScrollbar/q-scrollbar.scss",
    "content": ".scrollbar__wrap {\n  width: 500px;\n  height: 200px;\n  background: #fff;\n}\n\n.french-bread {\n  padding: 0 20px;\n\n  p:first-child {\n    margin-top: 0;\n  }\n}\n"
  },
  {
    "path": "stories/components/QSelect/Default.js",
    "content": "const options = [\n  {\n    value: { value: 'value1' },\n    label: 'Option 1'\n  },\n  {\n    value: { value: 'value2' },\n    label: 'Option 2'\n  },\n  {\n    value: { value: 'value3' },\n    label:\n      'Lorem Ipsum is simply dummy text of the printing and typesetting industry.'\n  },\n  {\n    value: { value: 'value4' },\n    label: 'Option 4',\n    disabled: true\n  },\n  {\n    value: { value: 'value5' },\n    label: 'Sed sit amet nibh consequat, pellentesque arcu ut, congue lorem.',\n    disabled: true\n  },\n  {\n    value: { value: 'value6' },\n    label: 'Option 6'\n  }\n];\n\nexport default (_, { argTypes }) => ({\n  props: Object.keys(argTypes).filter(arg => arg !== 'value'),\n\n  data() {\n    return {\n      remoteLoading: false,\n      value: null,\n      options\n    };\n  },\n\n  watch: {\n    multiple() {\n      this.value = null;\n    },\n\n    remote(value) {\n      if (!value) this.options = options;\n    }\n  },\n\n  methods: {\n    handleSearch(query) {\n      if (!this.remote) return;\n\n      this.remoteLoading = true;\n\n      setTimeout(() => {\n        this.remoteLoading = false;\n\n        if (query !== '') {\n          this.options = options.filter(item => {\n            return item.label.toLowerCase().includes(query.toLowerCase());\n          });\n        } else {\n          this.options = options;\n        }\n      }, 2000);\n    }\n  },\n\n  template: `\n      <div style=\"width: 304px;\">\n        <q-select\n          v-model=\"value\"\n          v-bind=\"$props\"\n          :loading=\"loading || remoteLoading\"\n          @search=\"handleSearch\"\n          placeholder=\"Pick an option\"\n        >\n          <q-option\n            v-for=\"item in options\"\n            :key=\"item.value.id\"\n            :label=\"item.label\"\n            :value=\"item.value\"\n            :disabled=\"item.disabled\"\n          />\n        </q-select>\n      </div>\n    `\n});\n"
  },
  {
    "path": "stories/components/QSelect/Multiple.js",
    "content": "import Template from './Default';\n\nconst Multiple = Template.bind({});\n\nMultiple.args = {\n  appendToBody: false,\n  multiple: true,\n  filterable: true,\n  allowCreate: false,\n  collapseTags: false,\n  clearable: true\n};\n\nexport default Multiple;\n"
  },
  {
    "path": "stories/components/QSelect/QSelect.stories.js",
    "content": "import QSelect from '../../../src/qComponents/QSelect';\nimport QOption from '../../../src/qComponents/QOption';\n\nimport Default from './Default';\nimport Multiple from './Multiple';\n\nexport default {\n  title: 'Components/QSelect',\n  component: QSelect,\n  subcomponents: { QOption },\n  argTypes: {\n    value: { control: { type: 'none' } }\n  }\n};\n\nexport { Default, Multiple };\n"
  },
  {
    "path": "stories/components/QSlider/Breakpoints.js",
    "content": "const BreakpointsStory = (_, { argTypes }) => ({\n  props: Object.keys(argTypes).filter(val => val !== 'value'),\n\n  data() {\n    return {\n      value: null\n    };\n  },\n\n  template: `\n    <q-slider \n      v-bind=\"$props\" \n      v-model=\"value\"\n    />\n  `\n});\n\nBreakpointsStory.args = {\n  showSteps: true,\n  step: 10\n};\n\nexport default BreakpointsStory;\n"
  },
  {
    "path": "stories/components/QSlider/Captions.js",
    "content": "const CaptionsStory = (_, { argTypes }) => ({\n  props: Object.keys(argTypes).filter(val => val !== 'value'),\n\n  data() {\n    return {\n      value: 20\n    };\n  },\n\n  template: `\n    <q-slider \n      v-bind=\"$props\" \n      v-model=\"value\"\n    />\n  `\n});\n\nCaptionsStory.args = {\n  showSteps: true,\n  step: 20,\n  captions: {\n    0: '0',\n    20: '20%',\n    40: '40%',\n    60: '60%',\n    80: '80%',\n    100: '100%'\n  }\n};\n\nexport default CaptionsStory;\n"
  },
  {
    "path": "stories/components/QSlider/Default.js",
    "content": "export default (_, { argTypes }) => ({\n  props: Object.keys(argTypes).filter(val => val !== 'value'),\n\n  data() {\n    return {\n      value: null\n    };\n  },\n\n  template: `\n    <q-slider \n      v-bind=\"$props\" \n      v-model=\"value\"\n    />\n  `\n});\n"
  },
  {
    "path": "stories/components/QSlider/Disabled.js",
    "content": "const DisabledStory = (_, { argTypes }) => ({\n  props: Object.keys(argTypes).filter(val => val !== 'value'),\n\n  data() {\n    return {\n      value: 50\n    };\n  },\n\n  template: `\n    <q-slider \n      v-bind=\"$props\" \n      v-model=\"value\"\n    />\n  `\n});\n\nDisabledStory.args = {\n  disabled: true\n};\n\nexport default DisabledStory;\n"
  },
  {
    "path": "stories/components/QSlider/QSlider.stories.js",
    "content": "import QSlider from '../../../src/qComponents/QSlider';\n\nimport Default from './Default';\nimport WithoutTooltip from './WithoutTooltip';\nimport Breakpoints from './Breakpoints';\nimport Captions from './Captions';\nimport Range from './Range';\nimport Disabled from './Disabled';\nimport Vertical from './Vertical';\n\nexport default {\n  title: 'Components/QSlider',\n  component: QSlider,\n  decorators: [\n    () => ({\n      template: '<div style=\"width: 80vw;\"><story /></div>'\n    })\n  ]\n};\n\nexport {\n  Default,\n  WithoutTooltip,\n  Breakpoints,\n  Captions,\n  Range,\n  Disabled,\n  Vertical\n};\n"
  },
  {
    "path": "stories/components/QSlider/Range.js",
    "content": "const RangeStory = (_, { argTypes }) => ({\n  props: Object.keys(argTypes).filter(val => val !== 'value'),\n\n  data() {\n    return {\n      value: [20, 80]\n    };\n  },\n\n  template: `\n    <q-slider \n      v-bind=\"$props\" \n      v-model=\"value\"\n    />\n  `\n});\n\nRangeStory.args = {\n  range: true\n};\n\nexport default RangeStory;\n"
  },
  {
    "path": "stories/components/QSlider/Vertical.js",
    "content": "const VerticalStory = (_, { argTypes }) => ({\n  props: Object.keys(argTypes).filter(val => val !== 'value'),\n\n  data() {\n    return {\n      value: 30\n    };\n  },\n\n  template: `\n    <q-slider \n      v-bind=\"$props\" \n      v-model=\"value\"\n    />\n  `\n});\n\nVerticalStory.args = {\n  vertical: true\n};\n\nexport default VerticalStory;\n"
  },
  {
    "path": "stories/components/QSlider/WithoutTooltip.js",
    "content": "const WithoutTooltipStory = (_, { argTypes }) => ({\n  props: Object.keys(argTypes).filter(val => val !== 'value'),\n\n  data() {\n    return {\n      value: null\n    };\n  },\n\n  template: `\n    <q-slider \n      v-bind=\"$props\" \n      v-model=\"value\"\n    />\n  `\n});\n\nWithoutTooltipStory.args = {\n  showTooltip: false\n};\n\nexport default WithoutTooltipStory;\n"
  },
  {
    "path": "stories/components/QTabPane.stories.js",
    "content": "import QTabPane from '../../src/qComponents/QTabPane';\nimport QTabs from '../../src/qComponents/QTabs';\n\nexport default {\n  title: 'Components/QTabs/QTabPane',\n  component: QTabPane,\n  subcomponents: { QTabs },\n  argTypes: { width: { control: { type: 'number' } } }\n};\n\nexport const QTabPaneStory = (_, { argTypes }) => ({\n  props: Object.keys(argTypes),\n  data() {\n    return {\n      activeTab: 'first_tab'\n    };\n  },\n  template: `\n    <q-tabs v-model=\"activeTab\">\n      <q-tab-pane v-bind=\"$props\" />\n      <q-tab-pane\n        name=\"second_tab\"\n        title=\"Second tab\"\n      />\n      <q-tab-pane\n        name=\"third_tab\"\n        title=\"Third tab\"\n      />\n    </q-tabs>\n  `\n});\n\nQTabPaneStory.storyName = 'Default';\nQTabPaneStory.args = {\n  name: 'first_tab',\n  title: 'First tab',\n  description:\n    'Lorem Ipsum is simply dummy text of the printing and typesetting industry.'\n};\n"
  },
  {
    "path": "stories/components/QTable/CustomRows.js",
    "content": "import Template from './Default';\n\nconst CustomRows = Template.bind({});\n\nCustomRows.args = {\n  customRowClass: ({ rowIndex }) => {\n    if (rowIndex === 0) {\n      return 'red-row';\n    }\n\n    if (rowIndex === 1) {\n      return 'green-row';\n    }\n\n    return '';\n  },\n  customRowStyle: ({ rowIndex }) => {\n    if (rowIndex === 2) {\n      return { '--row-custom-border-color': '#ff0' };\n    }\n\n    return '';\n  }\n};\n\nexport default CustomRows;\n"
  },
  {
    "path": "stories/components/QTable/CustomWidth.js",
    "content": "import Template from './Default';\n\nconst CustomWidth = Template.bind({});\n\nCustomWidth.args = {\n  fixedLayout: true\n};\n\nexport default CustomWidth;\n"
  },
  {
    "path": "stories/components/QTable/Default.js",
    "content": "export default (_, { argTypes }) => ({\n  props: Object.keys(argTypes),\n  methods: {\n    handleRowClick(row) {\n      console.log(row);\n    },\n    changeColumnsOrder(groupsOfColumns) {\n      this.groupsOfColumns = groupsOfColumns;\n    }\n  },\n  template: `\n    <q-table\n      ref=\"table\"\n      :groups-of-columns=\"groupsOfColumns\"\n      @change-order=\"changeColumnsOrder\"\n      @change-sort=\"changeSort\"\n      @row-click=\"handleRowClick\"\n      v-bind=\"$props\"\n    >\n      <template #customHeader=\"{ value }\">\n        {{ value }} custom\n      </template>\n\n      <template #customRow=\"{ value }\">\n        {{ value }} custom\n      </template>\n    </q-table>\n  `\n});\n"
  },
  {
    "path": "stories/components/QTable/Draggable.js",
    "content": "import Template from './Default';\n\nconst Draggable = Template.bind({});\n\nDraggable.args = {\n  fixedLayout: true,\n  groupsOfColumns: [\n    {\n      key: 'one',\n      color: '#de4b7a',\n      draggable: true,\n      columns: [\n        {\n          key: 'col1',\n          value: 'Column 1',\n          formatter: val => `formatted_${val}`\n        },\n        {\n          key: 'col2',\n          value: 'Column 2'\n        },\n        {\n          key: 'col3',\n          value: 'Column 3',\n          sortable: true\n        },\n        {\n          key: 'col4',\n          value: 'Column 4',\n          sortable: true,\n          slots: {\n            header: 'customHeader',\n            row: 'customRow'\n          }\n        },\n        {\n          key: 'col5',\n          value: 'Column 5'\n        },\n        {\n          key: 'col6',\n          value: 'Column 6'\n        }\n      ]\n    }\n  ]\n};\n\nexport default Draggable;\n"
  },
  {
    "path": "stories/components/QTable/Groups.js",
    "content": "import Template from './Default';\n\nconst Groups = Template.bind({});\n\nGroups.args = {\n  fixedLayout: true,\n  groupsOfColumns: [\n    {\n      key: 'one',\n      color: '#de4b7a',\n      columns: [\n        {\n          key: 'col1',\n          value: 'Column 1',\n          formatter: val => `formatted_${val}`\n        },\n        {\n          key: 'col2',\n          value: 'Column 2'\n        },\n        {\n          key: 'col3',\n          value: 'Column 3',\n          sortable: true\n        }\n      ]\n    },\n    {\n      color: '#74aff8',\n      align: 'right',\n      key: 'two',\n      columns: [\n        {\n          key: 'col4',\n          value: 'Column 4',\n          sortable: true,\n          slots: {\n            header: 'customHeader',\n            row: 'customRow'\n          }\n        },\n        {\n          key: 'col5',\n          value: 'Column 6'\n        },\n        {\n          key: 'col6',\n          value: 'Column 6'\n        }\n      ]\n    }\n  ]\n};\n\nexport default Groups;\n"
  },
  {
    "path": "stories/components/QTable/QTable.stories.js",
    "content": "import QTable from '../../../src/qComponents/QTable';\n\nimport Default from './Default';\nimport CustomWidth from './CustomWidth';\nimport Selectable from './Selectable';\nimport Total from './Total';\nimport StickyColumn from './StickyColumn';\nimport CustomRows from './CustomRows';\nimport Groups from './Groups';\nimport Draggable from './Draggable';\n\nexport default {\n  title: 'Components/QTable',\n  component: QTable,\n  decorators: [\n    () => ({ template: '<div style=\"width: 90vw;\"><story /></div>' })\n  ],\n  argTypes: {\n    total: {\n      control: { type1: 'object' }\n    },\n\n    childrenKey: {\n      table: { disable: true }\n    },\n    expandable: {\n      table: { disable: true }\n    },\n    indentSize: {\n      table: { disable: true }\n    },\n    uniqueKey: {\n      table: { disable: true }\n    },\n    pagesInExpand: {\n      table: { disable: true }\n    }\n  },\n  args: {\n    defaultSort: {\n      key: 'col1',\n      direction: 'descending'\n    },\n    fixedLayout: false,\n    groupsOfColumns: [\n      {\n        key: 'one',\n        columns: [\n          {\n            key: 'col1',\n            value: 'Column 1',\n            formatter: val => `formatted_${val}`\n          },\n          {\n            key: 'col2',\n            value: 'Column 2'\n          },\n          {\n            key: 'col3',\n            value: 'Column 3'\n          },\n          {\n            key: 'col4',\n            value: 'Column 4',\n            sortable: true,\n            slots: {\n              header: 'customHeader',\n              row: 'customRow'\n            }\n          },\n          {\n            key: 'col5',\n            value: 'Column with very long title'\n          },\n          {\n            key: 'col6',\n            value: 'Column 6'\n          }\n        ]\n      }\n    ],\n    rows: [\n      {\n        col1: 'Lorem ipsum dolor sit amet',\n        col2: 'consectetur adipiscing elit',\n        col3: 'sed do eiusmod tempor incididunt',\n        col4: 'ut labore et dolore magna aliqua.',\n        col5: 'Ut enim ad minim veniam',\n        col6: 'quis nostrud exercitation ullamco laboris',\n        col8: 'quis nostrud exercitation ullamco laboris',\n        col7: 'quis nostrud exercitation ullamco laboris'\n      },\n      {\n        col1: 'nisi ut aliquip ex ea commodo consequat',\n        col2: 'Duis aute irure dolor in reprehenderit',\n        col3: 'in voluptate velit esse cillum dolore eu fugiat nulla pariatur',\n        col4: 'Excepteur sint occaecat cupidatat non proident',\n        col5: 'sunt in culpa qui officia deserunt mollit anim id est laborum',\n        col6: 'sunt in culpa qui officia deserunt mollit anim id est laborum',\n        col7: 'sunt in culpa qui officia deserunt mollit anim id est laborum',\n        col8: 'sunt in culpa qui officia deserunt mollit anim id est laborum'\n      },\n      {\n        col1:\n          'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua',\n        col2:\n          'Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.',\n        col3:\n          'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua',\n        col4:\n          'Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.',\n        col5:\n          'Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.',\n        col6:\n          'Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.',\n        col7:\n          'Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.',\n        col8:\n          'Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.'\n      }\n    ],\n    changeSort(sort) {\n      console.log('sort', sort);\n    }\n  }\n};\n\nexport {\n  Default,\n  CustomWidth,\n  Selectable,\n  Total,\n  StickyColumn,\n  CustomRows,\n  Groups,\n  Draggable\n};\n"
  },
  {
    "path": "stories/components/QTable/Selectable.js",
    "content": "import Template from './Default';\n\nconst Selectable = Template.bind({});\n\nSelectable.args = {\n  selectableColumn: {\n    totalCheckboxPosition: 'header'\n  }\n};\n\nexport default Selectable;\n"
  },
  {
    "path": "stories/components/QTable/StickyColumn.js",
    "content": "import Template from './Default';\n\nconst StickyColumn = Template.bind({});\n\nStickyColumn.args = {\n  groupsOfColumns: [\n    {\n      key: 'one',\n      columns: [\n        {\n          key: 'col1',\n          value: 'Column 1',\n          formatter: val => `formatted_${val}`,\n          width: '300px'\n        },\n        {\n          key: 'col2',\n          value: 'Column 2 sticky',\n          sticky: {\n            position: 'left'\n          }\n        },\n        {\n          key: 'col3',\n          value: 'Column 3',\n          width: '150px',\n          sortable: true\n        },\n        {\n          key: 'col4',\n          value: 'Column 4',\n          sortable: true,\n          slots: {\n            header: 'customHeader',\n            row: 'customRow'\n          }\n        },\n        {\n          key: 'col5',\n          value: 'Column 5 sticky',\n          sticky: {\n            position: 'right'\n          }\n        },\n        {\n          key: 'col6',\n          value: 'Column 6'\n        },\n        {\n          key: 'col7',\n          value: 'Column 7 sticky',\n          width: '157px',\n          sticky: {\n            position: 'right'\n          }\n        },\n        {\n          key: 'col8',\n          value: 'Column 8',\n          width: '1000px'\n        }\n      ]\n    }\n  ],\n  selectableColumn: {\n    sticky: true,\n    totalCheckboxPosition: 'total'\n  },\n  fixedLayout: true,\n  grid: true,\n  total: {\n    col1: 'Total 100',\n    col2: 'Total 200',\n    col3: 'Total 300',\n    col4: 'Total 400',\n    col5: 'Total 500',\n    col6: 'Total 600',\n    col7: 'Total 700',\n    col8: 'Total 800'\n  }\n};\n\nexport default StickyColumn;\n"
  },
  {
    "path": "stories/components/QTable/Total.js",
    "content": "import Template from './Default';\n\nconst Total = Template.bind({});\n\nTotal.args = {\n  total: {\n    col1: 'Total 100',\n    col2: 'Total 200',\n    col3: 'Total 300',\n    col4: 'Total 400',\n    col5: 'Total 500',\n    col6: 'Total 600'\n  }\n};\n\nexport default Total;\n"
  },
  {
    "path": "stories/components/QTabs.stories.js",
    "content": "import QTabs from '../../src/qComponents/QTabs';\nimport QTabPane from '../../src/qComponents/QTabPane';\n\nexport default {\n  title: 'Components/QTabs/QTabs',\n  component: QTabs,\n  subcomponents: { QTabPane },\n  argTypes: {\n    'v-model': { control: { type: 'none' } },\n    tabWidth: { control: { type: 'number' } }\n  }\n};\n\nexport const QTabsStory = (_, { argTypes }) => ({\n  props: Object.keys(argTypes),\n  data() {\n    return {\n      activeTab: 'first_tab'\n    };\n  },\n  template: `\n    <q-tabs\n      v-model=\"activeTab\"\n      v-bind=\"$props\"\n    >\n      <q-tab-pane\n        name=\"first_tab\"\n        title=\"First tab\"\n      />\n      <q-tab-pane\n        name=\"second_tab\"\n        title=\"Second tab\"\n      />\n      <q-tab-pane\n        name=\"third_tab\"\n        title=\"Third tab\"\n      />\n    </q-tabs>\n  `\n});\n\nQTabsStory.storyName = 'Default';\n"
  },
  {
    "path": "stories/components/QTag.stories.js",
    "content": "import QTag from '../../src/qComponents/QTag';\n\nexport default {\n  title: 'Components/QTag',\n  component: QTag\n};\n\nexport const QTagStory = (_, { argTypes }) => ({\n  props: Object.keys(argTypes),\n  data() {\n    return {\n      tags: ['Tag 1', 'Tag 2', 'Tag 3', 'Tag 4', 'Tag 5']\n    };\n  },\n  methods: {\n    handleCloseClick(clickedTag) {\n      console.log('Close tag clicked');\n      this.tags = this.tags.filter(tag => tag !== clickedTag);\n    }\n  },\n  template: `\n    <div>\n      <q-tag\n        v-for=\"tag in tags\"\n        :key=\"tag\"\n        :closable=\"closable\"\n        @close=\"handleCloseClick(tag)\"\n      >\n        {{ tag }}\n      </q-tag>\n    </div>\n  `\n});\n\nQTagStory.storyName = 'Default';\n"
  },
  {
    "path": "stories/components/QTextarea.stories.js",
    "content": "import QTextarea from '../../src/qComponents/QTextarea';\n\nexport default {\n  title: 'Components/QTextarea',\n  component: QTextarea,\n  argTypes: {\n    placeholder: {\n      control: { type: 'text' }\n    },\n    maxlength: {\n      control: {\n        type: 'number'\n      }\n    },\n    value: {\n      control: {\n        type: 'none'\n      }\n    },\n    resize: {\n      control: {\n        type: 'select',\n        options: ['vertical', 'horizontal', 'both', 'none']\n      }\n    }\n  }\n};\n\nexport const Default = (_, { argTypes }) => ({\n  props: Object.keys(argTypes).filter(arg => arg !== 'input'),\n  data() {\n    return {\n      input: ''\n    };\n  },\n  template: `\n    <q-textarea\n      v-model=\"input\"\n      :disabled=\"disabled\"\n      :resize=\"resize\"\n      :autosize=\"autosize\"\n      :placeholder=\"placeholder\"\n    />\n  `\n});\n\nDefault.storyName = 'Default';\n"
  },
  {
    "path": "stories/components/QTimePicker.stories.js",
    "content": "import QTimePicker from '../../src/qComponents/QTimePicker';\n\nexport default {\n  title: 'Components/QTimePicker',\n  component: QTimePicker,\n  argTypes: {\n    value: { control: { type: 'none' } },\n    disabledValues: {\n      control: {\n        type: 'select',\n        options: [\n          null,\n          {\n            to: '03:03:03'\n          }\n        ]\n      }\n    }\n  }\n};\n\nexport const Default = (_, { argTypes }) => ({\n  props: Object.keys(argTypes).filter(arg => arg !== 'value'),\n  components: { QTimePicker },\n  data() {\n    return {\n      value: null\n    };\n  },\n  methods: {\n    handleTimeChange(val) {\n      this.value = val;\n    }\n  },\n  template: `\n      <q-time-picker :clearable=\"clearable\" :disabled=\"disabled\" :disabled-values=\"disabledValues\" @change=\"handleTimeChange\" :value=\"value\" :minutes-gap=\"minutesGap\" :seconds-gap=\"secondsGap\" />\n  `\n});\n\nDefault.storyName = 'Default';\n"
  },
  {
    "path": "stories/components/QUpload/Default.js",
    "content": "const QUploadStory = (_, { argTypes }) => ({\n  props: Object.keys(argTypes),\n  data() {\n    return {\n      formModel: {\n        file: null\n      }\n    };\n  },\n  methods: {\n    async handleFileSelect(sourceFile) {\n      this.formModel.file = {\n        sourceFile,\n        name: sourceFile.name,\n        loading: 0\n      };\n\n      const promise = () =>\n        new Promise(resolve => {\n          const interval = setInterval(() => {\n            this.formModel.file.loading += 10;\n          }, 100);\n\n          setTimeout(() => {\n            clearInterval(interval);\n            this.formModel.file.loading = null;\n            resolve();\n          }, 1000);\n        });\n\n      await promise();\n    },\n\n    handleAbort() {\n      console.log('abort uploading');\n    },\n\n    handleClear() {\n      this.formModel.file = null;\n    }\n  },\n  template: `\n    <q-upload\n      v-bind=\"$props\"\n      :value=\"formModel.file\"\n      @select=\"handleFileSelect\"\n      @abort=\"handleAbort\"\n      @clear=\"handleClear\"\n    />\n  `\n});\n\nQUploadStory.storyName = 'Default';\nQUploadStory.args = {\n  accept: ['image/*', '.pdf']\n};\n\nexport default QUploadStory;\n"
  },
  {
    "path": "stories/components/QUpload/Multiple.js",
    "content": "const QUploadStoryMultiple = (_, { argTypes }) => ({\n  props: Object.keys(argTypes),\n  data() {\n    return {\n      formModel: {\n        files: []\n      }\n    };\n  },\n  methods: {\n    async handleFileSelect(sourceFile, fileId) {\n      this.formModel.files.push({\n        id: fileId,\n        sourceFile,\n        name: sourceFile.name,\n        loading: 0\n      });\n\n      const currentFile = this.formModel.files.find(({ id }) => id === fileId);\n\n      const promise = () =>\n        new Promise(resolve => {\n          const interval = setInterval(() => {\n            currentFile.loading += 10;\n          }, 100);\n\n          setTimeout(() => {\n            clearInterval(interval);\n            currentFile.loading = null;\n            resolve();\n          }, 1000);\n        });\n\n      await promise();\n    },\n\n    handleAbort(fileId) {\n      console.log('abort uploading for: ', fileId);\n    },\n\n    handleClear(fileId) {\n      this.formModel.files = this.formModel.files.filter(\n        ({ id }) => id !== fileId\n      );\n    },\n\n    handleClearAll() {\n      this.formModel.files = [];\n    }\n  },\n  template: `\n    <q-upload\n      v-bind=\"$props\"\n      multiple\n      :value=\"formModel.files\"\n      @select=\"handleFileSelect\"\n      @abort=\"handleAbort\"\n      @clear=\"handleClear\"\n      @clear-all=\"handleClearAll\"\n    />\n  `\n});\n\nQUploadStoryMultiple.storyName = 'Multiple';\nQUploadStoryMultiple.args = {\n  accept: ['image/*', '.pdf']\n};\n\nexport default QUploadStoryMultiple;\n"
  },
  {
    "path": "stories/components/QUpload/QUpload.stories.js",
    "content": "import QUpload from '../../../src/qComponents/QUpload';\n\nimport Default from './Default';\nimport Multiple from './Multiple';\n\nexport default {\n  title: 'Components/QUpload',\n  component: QUpload,\n  argTypes: {\n    'v-model': { control: { type: 'none' } },\n    multiple: { control: { type: 'none' } },\n    direction: {\n      control: { type: 'select', options: ['right', 'bottom'] }\n    }\n  }\n};\n\nexport { Default, Multiple };\n"
  },
  {
    "path": "stories/core/colors.js",
    "content": "export const primaryColors = {\n  '--color-primary': '#de4b7a',\n  '--color-primary-purple': '#d048b4',\n  '--color-primary-blue': '#4162f0',\n  '--color-primary-blue-light': '#74aff8',\n  '--color-primary-blue-aqua': '#5ecae7',\n  '--color-primary-black': '#1d1c1a',\n  '--color-primary-darker': '#b83e65'\n};\n\nexport const secondaryColors = {\n  '--color-secondary-orange': '#f95e2d',\n  '--color-secondary-green': '#40ba3e',\n  '--color-secondary-yellow': '#f2d22b'\n};\n\nexport const tertiaryColors = {\n  '--color-tertiary-white': '#fff',\n  '--color-tertiary-gray-ultra-light': '#fafafa',\n  '--color-tertiary-gray-lighter': '#f4f4f6',\n  '--color-tertiary-gray-light': '#f0f0f3',\n  '--color-tertiary-gray': '#eaeaea',\n  '--color-tertiary-gray-dark': '#e2e2e2',\n  '--color-tertiary-gray-darker': '#dadada',\n  '--color-tertiary-gray-ultra-dark': '#c4c4c4',\n  '--color-tertiary-gray-ultra-darker': '#adacae'\n};\n\nexport const gradients = {\n  '--gradient-primary':\n    'linear-gradient(101.12deg, var(--color-primary) 0.76%, var(--color-primary-purple) 100%)',\n  '--gradient-secondary':\n    'linear-gradient(180deg, var(--color-primary) -27.44%, var(--color-primary-blue) 100.54%)'\n};\n"
  },
  {
    "path": "stories/core/colors.stories.mdx",
    "content": "import { Meta, ColorPalette, ColorItem } from '@storybook/addon-docs/blocks';\n\nimport '../../src/vars.scss';\nimport {\n  primaryColors,\n  secondaryColors,\n  tertiaryColors,\n  gradients\n} from './colors';\n\n<Meta title=\"Core/Colors\" />\n\n<ColorPalette>\n  <ColorItem\n    title=\"--color-primary\"\n    subtitle=\"primary colors\"\n    colors={primaryColors}\n  />\n  <ColorItem\n    title=\"--color-secondary\"\n    subtitle=\"secondary colors\"\n    colors={secondaryColors}\n  />\n  <ColorItem\n    title=\"--color-tertiary\"\n    subtitle=\"tertiary colors\"\n    colors={tertiaryColors}\n  />\n  <ColorItem title=\"gradient\" colors={gradients} />\n</ColorPalette>\n"
  },
  {
    "path": "stories/core/icons.stories.mdx",
    "content": "import {\n  Meta,\n  Preview,\n  Story,\n  ArgsTable,\n  IconGallery,\n  IconItem\n} from '@storybook/addon-docs/blocks';\n\nimport '../../src/icons/index.scss';\n\nexport const iconsList = [\n  'q-icon-bell',\n  'q-icon-bell-ring',\n  'q-icon-triangle-down',\n  'q-icon-triangle-up',\n  'q-icon-triangle-left',\n  'q-icon-triangle-right',\n  'q-icon-double-triangle-left',\n  'q-icon-double-triangle-right',\n  'q-icon-account',\n  'q-icon-account-settings',\n  'q-icon-account-couple-fill',\n  'q-icon-settings-vertical',\n  'q-icon-arrow-down',\n  'q-icon-arrow-up',\n  'q-icon-arrow-right',\n  'q-icon-arrow-left',\n  'q-icon-attention-mark',\n  'q-icon-alert-stroke',\n  'q-icon-alert-fill',\n  'q-icon-info',\n  'q-icon-question-mark',\n  'q-icon-question',\n  'q-icon-rubles-circle',\n  'q-icon-proceed-1',\n  'q-icon-proceed-2',\n  'q-icon-close',\n  'q-icon-check',\n  'q-icon-minus',\n  'q-icon-pause',\n  'q-icon-reverse',\n  'q-icon-plus',\n  'q-icon-router',\n  'q-icon-router-arrow-down',\n  'q-icon-calendar',\n  'q-icon-calendar-refresh',\n  'q-icon-pic',\n  'q-icon-checkbox-square-multiply-non',\n  'q-icon-file',\n  'q-icon-menu',\n  'q-icon-stop-1',\n  'q-icon-stop-2',\n  'q-icon-view-list',\n  'q-icon-graph-gisto',\n  'q-icon-eye',\n  'q-icon-eye-close',\n  'q-icon-search',\n  'q-icon-trash-bin',\n  'q-icon-envelope-edit',\n  'q-icon-cloud-upload',\n  'q-icon-diagram-round',\n  'q-icon-wallet',\n  'q-icon-lock-fill',\n  'q-icon-target',\n  'q-icon-database-arrow-down',\n  'q-icon-dots-3-horizontal',\n  'q-icon-wifi',\n  'q-icon-logout',\n  'q-icon-lock',\n  'q-icon-comment',\n  'q-icon-credit-card',\n  'q-icon-login',\n  'q-icon-piggy-bank-fill',\n  'q-icon-rubles',\n  'q-icon-multiply-fill',\n  'q-icon-account-group',\n  'q-icon-menu-2-fill',\n  'q-icon-eye-fill',\n  'q-icon-cog-stroke',\n  'q-icon-pencil-square-stroke',\n  'q-icon-play',\n  'q-icon-finish-fill',\n  'q-icon-archive-arrow-down',\n  'q-icon-wallet-stroke',\n  'q-icon-change-list',\n  'q-icon-withdraw-fill',\n  'q-icon-info-stroke',\n  'q-icon-trash-bin-stroke',\n  'q-icon-star',\n  'q-icon-save',\n  'q-icon-percent',\n  'q-icon-drag-vertical-fill',\n  'q-icon-diagram-round-stroke',\n  'q-icon-attach-fill',\n  'q-icon-account-check-fill',\n  'q-icon-calendar-clock',\n  'q-icon-chain',\n  'q-icon-clock-stroke',\n  'q-icon-cog-fill',\n  'q-icon-earth',\n  'q-icon-filter-fill',\n  'q-icon-filter-stroke',\n  'q-icon-pencil-list',\n  'q-icon-settings-horizontal',\n  'q-icon-star-fill',\n  'q-icon-account-group-web',\n  'q-icon-drag-linear',\n  'q-icon-y-1',\n  'q-icon-y-2',\n  'q-icon-y-3',\n  'q-icon-y-4',\n  'q-icon-key',\n  'q-icon-cart',\n  'q-icon-house-stroke',\n  'q-icon-info-fill',\n  'q-icon-phone-settings-stroke'\n];\n\n<Meta\n  title=\"Core/Icons\"\n  argTypes={{\n    icon: {\n      control: { type: 'select', options: iconsList }\n    },\n    size: {\n      control: { type: 'range', min: 8, max: 320 }\n    },\n    color: {\n      control: { type: 'color' }\n    }\n  }}\n/>\n\n# Icon\n\nUse a class to apply an icon to an element\n\n<IconGallery>\n  {iconsList.map((iconName, index) => (\n    <IconItem key={iconName} name={iconName}>\n      <span\n        class={iconName}\n        style={{ fontSize: '32px', color: 'var(--color-primary-black)' }}\n      />\n    </IconItem>\n  ))}\n</IconGallery>\n\n## Playground\n\nexport const Template = (args, { argTypes }) => ({\n  props: Object.keys(argTypes),\n  template: `\n    <span\n      :class=\"icon\"\n      :style=\"{\n        fontSize: size + 'px',\n        color: color,\n      }\"\n    />\n  `\n});\n\n<Preview>\n  <Story\n    name=\"Playground\"\n    args={{\n      icon: 'q-icon-bell',\n      size: '56',\n      color: '#1d1c1a'\n    }}\n  >\n    {Template.bind({})}\n  </Story>\n</Preview>\n\n<ArgsTable story=\"Playground\" />\n"
  },
  {
    "path": "stories/intro.stories.mdx",
    "content": "import { Meta, Story } from '@storybook/addon-docs/blocks';\n\n<Meta title=\"Intro\" />\n\n<div\n  style={{\n    margin: '0 auto 40px',\n    maxWidth: '600px',\n    textAlign: 'center'\n  }}\n>\n  <img src=\"https://github.com/Qvant-lab/qui/raw/master/.readme-assets/qui-logo.svg\" />\n\n<div style={{ marginTop: '16px' }}>\n  <span class=\"badge-shields\">\n    <a href=\"https://qvant-lab.github.io/qui\" title=\"storybook\">\n      <img\n        src=\"https://img.shields.io/badge/storybook-yes-green.svg\"\n        alt=\"storybook\"\n      />\n    </a>\n  </span>\n  <span class=\"badge-shields\">\n    <img src=\"https://img.shields.io/badge/responsive-yes-green.svg\" />\n  </span>\n  <span class=\"badge-npmversion\">\n    <a\n      href=\"https://npmjs.org/package/@qvant/qui\"\n      title=\"View this project on NPM\"\n    >\n      <img\n        src=\"https://img.shields.io/npm/v/@qvant/qui.svg\"\n        alt=\"NPM version\"\n      />\n    </a>\n  </span>\n  <span class=\"badge-npmdownloads\">\n    <a\n      href=\"https://npmjs.org/package/@qvant/qui\"\n      title=\"View this project on NPM\"\n    >\n      <img\n        src=\"https://img.shields.io/npm/dm/@qvant/qui.svg\"\n        alt=\"NPM downloads\"\n      />\n    </a>\n  </span>\n</div>\n\n<span class=\"badge-daviddm\">\n  <a\n    href=\"https://david-dm.org/Qvant-lab/qui\"\n    title=\"View the status of this project's dependencies on DavidDM\"\n  >\n    <img\n      src=\"https://img.shields.io/david/Qvant-lab/qui.svg\"\n      alt=\"Dependency Status\"\n    />\n  </a>\n</span>\n<span class=\"badge-daviddmdev\">\n  <a\n    href=\"https://david-dm.org/Qvant-lab/qui#info=devDependencies\"\n    title=\"View the status of this project's development dependencies on DavidDM\"\n  >\n    <img\n      src=\"https://img.shields.io/david/dev/Qvant-lab/qui.svg\"\n      alt=\"Dev Dependency Status\"\n    />\n  </a>\n</span>\n\n</div>\n\n# A Vue.js Design System for Web\n\nResponsive, user-friendly and lightweight library helping us build great products for our customers.\nThis library for Vue 2.x, Qui for Vue 3 in our roadmap.\n\nWhat is it?\n\n- 🔩 30+ Vue components\n- 📦 icons pack\n- 🏳️‍🌈 colors & grid\n- 🥷 neumorphism styles\n- 📚 storybook sandbox\n\nSome examples below:\n\n![buttons](https://github.com/Qvant-lab/qui/raw/master/.readme-assets/buttons.jpg)\n![buttons](https://github.com/Qvant-lab/qui/raw/master/.readme-assets/buttons.jpg)\n![inputs](https://github.com/Qvant-lab/qui/raw/master/.readme-assets/inputs.gif)\n![icons](https://github.com/Qvant-lab/qui/raw/master/.readme-assets/icons.gif)\n![tables](https://github.com/Qvant-lab/qui/raw/master/.readme-assets/tables.jpg)\n![datepicker](https://github.com/Qvant-lab/qui/raw/master/.readme-assets/datepicker.jpg)\n![other](https://github.com/Qvant-lab/qui/raw/master/.readme-assets/other.jpg)\n\n## Install\n\n```bash\nnpm install @qvant/qui -S\nyarn add @qvant/qui\n```\n\nYou can import Qui entirely, or just import what you need. Let's start with fully import.\n\n## Quick setup\n\nIn main.js:\n\n```js\nimport Vue from 'vue';\nimport Qui from '@qvant/qui';\nimport '@qvant/qui/dist/qui.css';\n\n// Setup all components\nVue.use(Qui);\n// that's it! All components will be imported with styles\n```\n\nin YourComponent.vue: (Example)\n\n```vue\n<template>\n  <q-input v-model=\"value\" />\n</template>\n<script>\nexport default {\n  data() {\n    return {\n      value: ''\n    };\n  },\n  mounted() {\n    // the modals have shortcuts in your components:\n    this.$notify({ ... }) // calls QNotification\n    this.$message({ ... }) // calls QMessageBox\n    this.$dialog({ ... }) // calls QDialog\n  }\n};\n</script>\n```\n\n...or configure quick setup\n\nIn main.js:\n\n```js\nimport Vue from 'vue';\nimport Qui from '@qvant/qui';\nimport '@qvant/qui/dist/qui.css';\n\nVue.use(Qui, {\n  localization: {\n    locale: 'en', // Russian language by default, you can set `en` for English\n    customI18nMessages: {\n      // rewrite default texts, see the source: src/qComponents/constants/locales\n      en: {\n        QDatepicker: {\n          placeholder: 'Pick your birthday!'\n        }\n      }\n    },\n    zIndexCounter: 3000, // zIndexCounter is being used by some components, (e.g QPopover, QSelect, QDialog ...etc), 2000 by default\n    prefix: 'yo' // you can change component's prefix, e.g. must be used <yo-input /> instead of <q-input />\n  }\n});\n```\n\nin YourComponent.vue: (Example)\n\n```vue\n<template>\n  <!-- placeholder is changed on 'Pick your birthday!' -->\n  <yo-datepicker v-model=\"value\" type=\"date\" />\n</template>\n<script>\nexport default {\n  data() {\n    return {\n      value: null\n    };\n  }\n};\n</script>\n```\n\nNow you have implemented Vue and Qui to your project, and it's time to write your code.\nPlease refer to each component's [Stories](https://qvant-lab.github.io/qui/) to learn how to use them.\n\n## Not quick setup\n\nIf you have a module bundler (e.g webpack), you can import components separately and take care about your bundle size\n\nIn main.js:\n\n```js\n// import the main plugin from another place (it ensures Qui will be installed without any components, but instance will set required properties and directives)\nimport Qui from '@qvant/qui/src/onDemand';\n\n// import the component you want\nimport QButton from '@qvant/qui/src/qComponents/QButton';\n// ...or in async way\nVue.component('q-button', () =>\n  import(/* webpackChunkName: \"qui\" */ '@qvant/qui/src/qComponents/QButton')\n);\n\n// init\nVue.use(Qui);\nVue.use(QButton);\n```\n\nIn main.scss:\n\n```scss\n// need to set the path for files with statics\n$--base-path: '~@qvant/qui/src';\n// set main styles\n@import '~@qvant/qui/src/main.scss';\n// notice that you must use `fonts` and `icons` styles for some of components:\n@import '~@qvant/qui/src/fonts/index.scss';\n@import '~@qvant/qui/src/icons/index.scss';\n```\n\nImport all styles:\n\n```scss\n@import '~@qvant/qui/src/components.scss';\n```\n\n...or components separately:\n\n```scss\n@import '~@qvant/qui/src/qComponents/QBreadcrumbs/src/q-breadcrumbs.scss';\n@import '~@qvant/qui/src/qComponents/QButton/src/q-button.scss';\n// ...etc\n```\n\n## Optional\n\n- if you want use modals inside your components as property of 'this':\n\n```js\nimport { QMessageBox, QDialog, QNotification } from '@qvant/qui';\n// or import separately\nimport QMessageBox from '@qvant/qui/src/qComponents/QMessageBox';\nimport QDialog from '@qvant/qui/src/qComponents/QDialog';\nimport QNotification from '@qvant/qui/src/qComponents/QNotification';\n\nVue.prototype.$message = QMessageBox;\nVue.prototype.$dialog = QDialog;\nVue.prototype.$notify = options =>\n  QNotification({\n    duration: 3000, // - ms\n    ...options\n  });\n```\n\n- if you use VueI18n, you need to merge messages:\n\n```js\nimport VueI18n from 'vue-i18n';\nimport { en, ru } from '@qvant/qui/src/qComponents/constants/locales';\n\nVue.use(VueI18n);\n\nconst messages = {\n  en: {\n    message: {\n      hello: 'hello world'\n    },\n    ...en\n  },\n  ru: {\n    message: {\n      hello: 'привет, мир'\n    },\n    ...ru\n  }\n};\n\nconst i18n = new VueI18n({\n  locale: 'en',\n  messages\n});\n\nnew Vue({\n  i18n\n}).$mount('#your-app');\n```\n\n## Supported languages\n\n- Russian ✅\n- English ✅\n- Also you can use any language by setting texts for components via 'customI18nMessages' property in the Qui instance. See the example above.\n\n## Browser Support\n\nModern browsers are recomended\n\n- safari: >11\n- chrome: >=61\n- firefox: >=58\n- opera: >=62\n- edge: >=16\n- yandex: >=18\n- ie: ? (we don't know :) and will not support it)\n\n## Development\n\nClone repository and run storybook\n\n```bash\nyarn storybook\nnpm run storybook\n```\n\n## LICENSE\n\nMIT\n"
  },
  {
    "path": "tests/unit/setup.js",
    "content": "import Vue from 'vue';\nimport { mount, shallowMount } from '@vue/test-utils';\nimport Qui from '../../src/qComponents';\n\nVue.use(Qui);\n\nglobal.mount = mount;\nglobal.shallowMount = shallowMount;\n"
  }
]